#![cfg(target_arch = "arm")]
use injectorpp::interface::injector::*;
const T32_ALIGNED_32_FUNCTION_OPCODES: [u16; 7] = [
0xB480, 0xAF00, 0x232A, 0x4618, 0x46BD, 0xBC80, 0x4770, ];
const A32_ALIGNED_32_FUNCTION_OPCODES: [u32; 7] = [
0xE52DB004, 0xE28DB000, 0xE3A0302A, 0xE1A00003, 0xE28BD000, 0xE49DB004, 0xE12FFF1E, ];
#[test]
fn test_arm_t32_32_bit_aligned_patch() {
unsafe {
let allocated_memory: [u8; T32_ALIGNED_32_FUNCTION_OPCODES.len() * 2 + 4] =
[0; T32_ALIGNED_32_FUNCTION_OPCODES.len() * 2 + 4];
let allocated_memory_ptr = allocated_memory.as_ptr() as *mut u8;
let aligned_memory = ((allocated_memory_ptr as usize)
+ (4 - (allocated_memory_ptr as usize % 4)) % 4)
as *mut u8;
assert!(
aligned_memory as usize % 4 == 0,
"Aligned memory should be 4-byte aligned"
);
for (i, &opcode) in T32_ALIGNED_32_FUNCTION_OPCODES.iter().enumerate() {
for (j, b) in opcode.to_le_bytes().iter().enumerate() {
aligned_memory.add(i * 2 + j + 2).write(*b);
}
}
let mut injector = InjectorPP::new();
injector
.when_called(FuncPtr::new(
aligned_memory.add(1) as *const (), "fn() -> u32",
))
.will_execute_raw(injectorpp::closure!(|| { 99 }, fn() -> u32));
let result =
std::mem::transmute::<*const (), fn() -> u32>(aligned_memory.add(1) as *const ())();
assert_eq!(result, 99, "T32 function should return 99");
}
}
#[test]
fn test_arm_t32_16_bit_aligned_patch() {
unsafe {
let allocated_memory: [u8; T32_ALIGNED_32_FUNCTION_OPCODES.len() * 2 + 4] =
[0; T32_ALIGNED_32_FUNCTION_OPCODES.len() * 2 + 4];
let allocated_memory_ptr = allocated_memory.as_ptr() as *mut u8;
let mut aligned_memory = ((allocated_memory_ptr as usize)
+ (2 - (allocated_memory_ptr as usize % 2)) % 2)
as *mut u8;
if aligned_memory as usize % 4 == 0 {
aligned_memory = aligned_memory.add(2); }
assert!(
aligned_memory as usize % 2 == 0,
"Aligned memory should be 2-byte aligned"
);
assert!(
aligned_memory as usize % 4 != 0,
"Aligned memory should not be 4-byte aligned"
);
for (i, &opcode) in T32_ALIGNED_32_FUNCTION_OPCODES.iter().enumerate() {
for (j, b) in opcode.to_le_bytes().iter().enumerate() {
aligned_memory.add(i * 2 + j).write(*b);
}
}
let mut injector = InjectorPP::new();
injector
.when_called(FuncPtr::new(
aligned_memory.add(1) as *const (), "fn() -> u32",
))
.will_execute_raw(injectorpp::closure!(|| { 99 }, fn() -> u32));
let result =
std::mem::transmute::<*const (), fn() -> u32>(aligned_memory.add(1) as *const ())();
assert_eq!(result, 99, "T32 function should return 99");
}
}
#[test]
fn test_arm_a32_32_bit_aligned_patch() {
unsafe {
let allocated_memory: [u8; A32_ALIGNED_32_FUNCTION_OPCODES.len() * 4 + 4] =
[0; A32_ALIGNED_32_FUNCTION_OPCODES.len() * 4 + 4];
let allocated_memory_ptr = allocated_memory.as_ptr() as *mut u8;
let aligned_memory = ((allocated_memory_ptr as usize)
+ (4 - (allocated_memory_ptr as usize % 4)) % 4)
as *mut u8;
assert!(
aligned_memory as usize % 4 == 0,
"Aligned memory should be 4-byte aligned"
);
for (i, &opcode) in A32_ALIGNED_32_FUNCTION_OPCODES.iter().enumerate() {
for (j, b) in opcode.to_le_bytes().iter().enumerate() {
aligned_memory.add(i * 4 + j).write(*b);
}
}
let mut injector = InjectorPP::new();
injector
.when_called(FuncPtr::new(aligned_memory as *const (), "fn() -> u32"))
.will_execute_raw(injectorpp::closure!(|| { 99 }, fn() -> u32));
let result = std::mem::transmute::<*const (), fn() -> u32>(aligned_memory as *const ())();
assert_eq!(result, 99, "A32 function should return 99");
}
}