pub(crate) fn generate_plt0_code() -> Vec<u8> {
let mut code = vec![0; 20];
code[0..4].copy_from_slice(&[0x04, 0xe0, 0x2d, 0xe5]);
code[4..8].copy_from_slice(&[0x04, 0xe0, 0x9f, 0xe5]);
code[8..12].copy_from_slice(&[0x0e, 0xe0, 0x8f, 0xe0]);
code[12..16].copy_from_slice(&[0x08, 0xf0, 0xbe, 0xe5]);
code
}
pub(crate) fn patch_plt0(
plt_data: &mut [u8],
plt0_off: usize,
plt0_vaddr: u64,
got_plt_vaddr: u64,
) {
let pc_val = plt0_vaddr + 16;
let offset = (got_plt_vaddr as i64 - pc_val as i64) as u32;
plt_data[plt0_off + 16..plt0_off + 20].copy_from_slice(&offset.to_le_bytes());
}
pub(crate) fn generate_plt_entry_code() -> Vec<u8> {
let mut code = vec![0; 12];
code[0..4].copy_from_slice(&[0x00, 0xc0, 0x8f, 0xe2]);
code[4..8].copy_from_slice(&[0x00, 0xc0, 0x8c, 0xe2]);
code[8..12].copy_from_slice(&[0x00, 0xf0, 0xbc, 0xe5]);
code
}
pub(crate) fn patch_plt_entry(
plt_data: &mut [u8],
plt_entry_off: usize,
plt_entry_vaddr: u64,
target_got_vaddr: u64,
) {
let pc = plt_entry_vaddr + 8;
let offset = (target_got_vaddr as i64 - pc as i64) as u32;
let low_12 = offset & 0xfff;
let residual = offset - low_12;
let (imm_high, imm_mid) = if let Some(enc) = encode_arm_imm(residual) {
(0, enc) } else {
let high_part = residual & 0xFFF00000; let mid_part = residual - high_part;
let enc_h = encode_arm_imm(high_part).expect("Failed to encode high part of PLT offset");
let enc_m = encode_arm_imm(mid_part).expect("Failed to encode mid part of PLT offset");
(enc_h, enc_m)
};
let insn1 = 0xe28fc000 | imm_high;
plt_data[plt_entry_off..plt_entry_off + 4].copy_from_slice(&insn1.to_le_bytes());
let insn2 = 0xe28cc000 | imm_mid;
plt_data[plt_entry_off + 4..plt_entry_off + 8].copy_from_slice(&insn2.to_le_bytes());
let insn3 = 0xe5bcf000 | low_12;
plt_data[plt_entry_off + 8..plt_entry_off + 12].copy_from_slice(&insn3.to_le_bytes());
}
fn encode_arm_imm(mut n: u32) -> Option<u32> {
if n == 0 {
return Some(0);
}
for r in 0..16 {
if n <= 0xFF {
let rot_code = r;
return Some(n | (rot_code << 8));
}
n = n.rotate_left(2);
}
None
}
pub(crate) fn generate_helper_code() -> Vec<u8> {
let mut code = vec![0; 4];
code[0..4].copy_from_slice(&[0x00, 0x00, 0x00, 0xea]);
code
}
pub(crate) fn patch_helper(
text_data: &mut [u8],
helper_text_off: usize,
helper_vaddr: u64,
target_plt_vaddr: u64,
) {
let off = (target_plt_vaddr as i64 - (helper_vaddr + 8) as i64) / 4;
let insn = 0xea000000 | ((off & 0x00ffffff) as u32);
text_data[helper_text_off..helper_text_off + 4].copy_from_slice(&insn.to_le_bytes());
}
pub(crate) fn get_ifunc_resolver_code() -> Vec<u8> {
let mut code = vec![0; 16];
code[0..4].copy_from_slice(&[0x04, 0x00, 0x9f, 0xe5]);
code[4..8].copy_from_slice(&[0x00, 0x00, 0x8f, 0xe0]);
code[8..12].copy_from_slice(&[0x1e, 0xff, 0x2f, 0xe1]);
code
}
pub(crate) fn patch_ifunc_resolver(
text_data: &mut [u8],
offset: usize,
resolver_vaddr: u64,
target_vaddr: u64,
) {
let pc = resolver_vaddr + 12;
let off = (target_vaddr as i64 - pc as i64) as i32;
text_data[offset + 12..offset + 16].copy_from_slice(&off.to_le_bytes());
}
pub(crate) fn generate_tls_helper_code() -> Vec<u8> {
let mut code = vec![0; 32];
for i in (0..32).step_by(4) {
code[i..i + 4].copy_from_slice(&[0x00, 0x00, 0xa0, 0xe1]);
}
code[0..4].copy_from_slice(&[0x10, 0x40, 0x2d, 0xe9]);
code[16..20].copy_from_slice(&[0x10, 0x80, 0xbd, 0xe8]);
code
}
pub(crate) fn patch_tls_tester(
text_data: &mut [u8],
offset: usize,
helper_vaddr: u64,
reloc_vaddr: u64,
tls_get_addr_vaddr: u64,
) {
text_data[offset + 4..offset + 8].copy_from_slice(&[0x0c, 0x00, 0x9f, 0xe5]);
text_data[offset + 8..offset + 12].copy_from_slice(&[0x00, 0x00, 0x8f, 0xe0]);
let bl_off = (tls_get_addr_vaddr as i64 - (helper_vaddr as i64 + 20)) >> 2;
let bl = 0xeb000000u32 | (bl_off as u32 & 0x00ffffff);
text_data[offset + 12..offset + 16].copy_from_slice(&bl.to_le_bytes());
let data_val = (reloc_vaddr as i64 - (helper_vaddr as i64 + 16)) as i32;
text_data[offset + 24..offset + 28].copy_from_slice(&data_val.to_le_bytes());
}