Merge branch 'main' of git.mineau.eu:histausse/androscalpel
This commit is contained in:
commit
4c4940e6b1
5 changed files with 58 additions and 30 deletions
|
|
@ -2769,8 +2769,6 @@ impl Apk {
|
||||||
}
|
}
|
||||||
Ok(Code {
|
Ok(Code {
|
||||||
registers_size: code_item.registers_size,
|
registers_size: code_item.registers_size,
|
||||||
ins_size: code_item.ins_size,
|
|
||||||
outs_size: code_item.outs_size,
|
|
||||||
parameter_names,
|
parameter_names,
|
||||||
insns,
|
insns,
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ use std::collections::{HashMap, HashSet};
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ins::Instruction, DexString, IdField, IdMethod, IdMethodType, IdType, MethodHandle, Result,
|
ins::Instruction, DexString, IdField, IdMethod, IdMethodType, IdType, Method, MethodHandle,
|
||||||
Visitable, VisitableMut, Visitor, VisitorMut,
|
Result, Visitable, VisitableMut, Visitor, VisitorMut,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: make this easy to edit/manipulate, maybe move to Method
|
// TODO: make this easy to edit/manipulate, maybe move to Method
|
||||||
|
|
@ -25,14 +25,6 @@ pub struct Code {
|
||||||
/// The number of registers used by the code
|
/// The number of registers used by the code
|
||||||
#[cfg_attr(feature = "python", pyo3(get))]
|
#[cfg_attr(feature = "python", pyo3(get))]
|
||||||
pub registers_size: u16,
|
pub registers_size: u16,
|
||||||
// TODO: what does it means? is it computable?
|
|
||||||
/// The number of words of incoming arguments to the method
|
|
||||||
#[cfg_attr(feature = "python", pyo3(get))]
|
|
||||||
pub ins_size: u16,
|
|
||||||
// TODO: what does it means? is it computable?
|
|
||||||
/// The number of words of outgoing argument space
|
|
||||||
#[cfg_attr(feature = "python", pyo3(get))]
|
|
||||||
pub outs_size: u16,
|
|
||||||
/// The names of the parameters if given
|
/// The names of the parameters if given
|
||||||
#[cfg_attr(feature = "python", pyo3(get))]
|
#[cfg_attr(feature = "python", pyo3(get))]
|
||||||
pub parameter_names: Option<Vec<Option<DexString>>>,
|
pub parameter_names: Option<Vec<Option<DexString>>>,
|
||||||
|
|
@ -47,8 +39,6 @@ impl PartialEq for Code {
|
||||||
let comparable_self = self.semantic_comparable().unwrap();
|
let comparable_self = self.semantic_comparable().unwrap();
|
||||||
let comparable_other = other.semantic_comparable().unwrap();
|
let comparable_other = other.semantic_comparable().unwrap();
|
||||||
(comparable_self.registers_size == comparable_other.registers_size)
|
(comparable_self.registers_size == comparable_other.registers_size)
|
||||||
&& (comparable_self.ins_size == comparable_other.ins_size)
|
|
||||||
&& (comparable_self.outs_size == comparable_other.outs_size)
|
|
||||||
&& (comparable_self.insns == comparable_other.insns)
|
&& (comparable_self.insns == comparable_other.insns)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -68,20 +58,46 @@ impl Code {
|
||||||
#[cfg_attr(feature = "python", pyo3(signature = (registers_size, ins_size, outs_size, insns, parameter_names=None)))]
|
#[cfg_attr(feature = "python", pyo3(signature = (registers_size, ins_size, outs_size, insns, parameter_names=None)))]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
registers_size: u16,
|
registers_size: u16,
|
||||||
ins_size: u16,
|
|
||||||
outs_size: u16,
|
|
||||||
insns: Vec<Instruction>,
|
insns: Vec<Instruction>,
|
||||||
parameter_names: Option<Vec<Option<DexString>>>,
|
parameter_names: Option<Vec<Option<DexString>>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
registers_size,
|
registers_size,
|
||||||
ins_size,
|
|
||||||
outs_size,
|
|
||||||
insns,
|
insns,
|
||||||
parameter_names,
|
parameter_names,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Compute the `ins_size` field. This is the number of register parameters, including the
|
||||||
|
/// `this` parameter for non-static methods.
|
||||||
|
/// This information is stored in the code item in dex files, but is not computable from the code
|
||||||
|
/// (as opposed to `outs_size`). The [`Method`] struct is needed to compute it.
|
||||||
|
pub fn ins_size(&self, method: &Method) -> u16 {
|
||||||
|
method.ins_size()
|
||||||
|
}
|
||||||
|
/// Compute the `outs_size` field. This is the number of registers needed to call other
|
||||||
|
/// function.
|
||||||
|
pub fn outs_size(&self) -> u16 {
|
||||||
|
let mut outs = 0;
|
||||||
|
for ins in &self.insns {
|
||||||
|
match ins {
|
||||||
|
Instruction::InvokeVirtual { args, .. }
|
||||||
|
| Instruction::InvokeSuper { args, .. }
|
||||||
|
| Instruction::InvokeDirect { args, .. }
|
||||||
|
| Instruction::InvokeStatic { args, .. }
|
||||||
|
| Instruction::InvokeInterface { args, .. }
|
||||||
|
| Instruction::InvokePolymorphic { args, .. }
|
||||||
|
| Instruction::InvokeCustom { args, .. } => {
|
||||||
|
if args.len() > outs {
|
||||||
|
outs = args.len();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outs as u16
|
||||||
|
}
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
pub fn __str__(&self) -> String {
|
||||||
self.__repr__()
|
self.__repr__()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ impl MethodCFG<'_> {
|
||||||
return HashMap::new();
|
return HashMap::new();
|
||||||
}
|
}
|
||||||
// Initialize the entry block from function signature:
|
// Initialize the entry block from function signature:
|
||||||
let mut i = (code.registers_size - code.ins_size) as usize;
|
let mut i = (code.registers_size - code.ins_size(&self.method)) as usize;
|
||||||
if !self.method.is_static {
|
if !self.method.is_static {
|
||||||
end_block_reg_tys[0][i] = RegType::Object; // 'this'
|
end_block_reg_tys[0][i] = RegType::Object; // 'this'
|
||||||
i += 1;
|
i += 1;
|
||||||
|
|
|
||||||
|
|
@ -406,7 +406,7 @@ impl DexWriter {
|
||||||
///
|
///
|
||||||
/// This is currently a stub that probably serialize invalid references to data.
|
/// This is currently a stub that probably serialize invalid references to data.
|
||||||
fn insert_code_item(&mut self, method_id: IdMethod, direct_methods: bool) -> Result<()> {
|
fn insert_code_item(&mut self, method_id: IdMethod, direct_methods: bool) -> Result<()> {
|
||||||
let code = if direct_methods {
|
let method = if direct_methods {
|
||||||
self.class_defs
|
self.class_defs
|
||||||
.get(&method_id.class_)
|
.get(&method_id.class_)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
@ -414,10 +414,6 @@ impl DexWriter {
|
||||||
.direct_methods
|
.direct_methods
|
||||||
.get(&method_id)
|
.get(&method_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.code
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
} else {
|
} else {
|
||||||
self.class_defs
|
self.class_defs
|
||||||
.get(&method_id.class_)
|
.get(&method_id.class_)
|
||||||
|
|
@ -426,11 +422,10 @@ impl DexWriter {
|
||||||
.virtual_methods
|
.virtual_methods
|
||||||
.get(&method_id)
|
.get(&method_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.code
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.clone()
|
|
||||||
};
|
};
|
||||||
|
let code = method.code.as_ref().unwrap().clone();
|
||||||
|
let ins_size = code.ins_size(&method);
|
||||||
|
let outs_size = code.outs_size();
|
||||||
// Estimate instructions addresses
|
// Estimate instructions addresses
|
||||||
let mut min_addr = 0;
|
let mut min_addr = 0;
|
||||||
let mut max_addr = 0;
|
let mut max_addr = 0;
|
||||||
|
|
@ -864,9 +859,9 @@ impl DexWriter {
|
||||||
};
|
};
|
||||||
let item = CodeItem {
|
let item = CodeItem {
|
||||||
registers_size: code.registers_size,
|
registers_size: code.registers_size,
|
||||||
ins_size: code.ins_size,
|
|
||||||
outs_size: code.outs_size,
|
|
||||||
debug_info_off, // linked in link_debug_info()
|
debug_info_off, // linked in link_debug_info()
|
||||||
|
ins_size,
|
||||||
|
outs_size,
|
||||||
insns,
|
insns,
|
||||||
tries,
|
tries,
|
||||||
handlers,
|
handlers,
|
||||||
|
|
|
||||||
|
|
@ -294,6 +294,25 @@ impl Method {
|
||||||
.iter()
|
.iter()
|
||||||
.any(|list| !list.is_empty())
|
.any(|list| !list.is_empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Compute the `ins_size` field. This is the number of register parameters, including the
|
||||||
|
/// `this` parameter for non-static methods.
|
||||||
|
/// This information is stored in the code item in dex files, but is not computable from the code
|
||||||
|
/// (as opposed to `outs_size`). The [`Method`] struct is needed to compute it.
|
||||||
|
pub fn ins_size(&self) -> u16 {
|
||||||
|
let mut ins = 0;
|
||||||
|
if !self.is_static {
|
||||||
|
ins += 1; // this
|
||||||
|
}
|
||||||
|
for param in &self.descriptor.proto.parameters {
|
||||||
|
if param.is_long() || param.is_double() {
|
||||||
|
ins += 2;
|
||||||
|
} else {
|
||||||
|
ins += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ins
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: Visitor> Visitable<V> for Method {
|
impl<V: Visitor> Visitable<V> for Method {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue