patch static invocation

This commit is contained in:
Jean-Marie 'Histausse' Mineau 2025-03-04 17:51:36 +01:00
parent 91fd0137d8
commit b33807edde
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2

View file

@ -114,7 +114,8 @@ pub struct ReflectionInvokeData {
pub caller_method: IdMethod,
/// Address where the call to `java.lang.reflect.Method.invoke()` was made in `caller_method`.
pub addr: usize,
// TODO: variable number of args?
/// If the method is static (static method don't take 'this' as argument)
pub is_static: bool,
// TODO: type of invoke?
}
@ -924,14 +925,10 @@ fn get_invoke_block(
(a, b, c)
} else {
bail!(
"Method;->invoke arg should have exactrly 3 arguments, found {}",
"Method;->invoke arg should have exactly 3 arguments, found {}",
invoke_arg.len()
);
};
if arg_arr > u8::MAX as u16 {
// TODO
bail!("Cannot transform invoke calls to a method using 16 bits register for its argument");
}
let nb_args: usize = ref_data
.method
.proto
@ -939,14 +936,14 @@ fn get_invoke_block(
.iter()
.map(|ty| if ty.is_double() || ty.is_long() { 2 } else { 1 })
.sum();
if reg_inf.nb_arg_reg < nb_args as u16 + 1 {
reg_inf.nb_arg_reg = nb_args as u16 + 1;
if reg_inf.nb_arg_reg < nb_args as u16 + if ref_data.is_static { 0 } else { 1 } {
reg_inf.nb_arg_reg = nb_args as u16 + if ref_data.is_static { 0 } else { 1 };
}
let abort_label = format!(
"end_static_call_to_{}_at_{}",
"end_static_call_to_{}_at_{:08X}",
ref_data.method.try_to_smali()?,
"TODO_ADDR"
ref_data.addr
);
let mut insns = test_method(
method_obj,
@ -955,6 +952,7 @@ fn get_invoke_block(
reg_inf,
);
if !ref_data.is_static {
// Move 'this' to fist arg
// We do a small detour to `reg_inf.array_val` because we need a u8 reg to down cast the
// Object reference to the right Class
@ -970,16 +968,24 @@ fn get_invoke_block(
from: reg_inf.array_val as u16,
to: reg_inf.first_arg,
});
}
insns.append(&mut get_args_from_obj_arr(
&ref_data.method.proto.get_parameters(),
arg_arr,
reg_inf.first_arg + 1,
reg_inf.first_arg + if ref_data.is_static { 0 } else { 1 },
reg_inf,
));
if ref_data.is_static {
insns.push(Instruction::InvokeStatic {
method: ref_data.method.clone(),
args: (reg_inf.first_arg..reg_inf.first_arg + nb_args as u16).collect(),
});
} else {
insns.push(Instruction::InvokeVirtual {
method: ref_data.method.clone(),
args: (reg_inf.first_arg..reg_inf.first_arg + 1 + nb_args as u16).collect(),
});
}
if let Some(move_result) = move_result {
let ret_ty = ref_data.method.proto.get_return_type();
let res_reg = if let Instruction::MoveResultObject { to } = &move_result {