librasan: Simplify assembly patches (#3192)

Co-authored-by: Dongjia "toka" Zhang <tokazerkje@outlook.com>
This commit is contained in:
Wim de With 2025-05-12 16:17:56 +02:00 committed by GitHub
parent df9b5b7e3d
commit 0d962bc561
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -19,7 +19,7 @@ impl Patch for RawPatch {
if target == destination { if target == destination {
Err(RawPatchError::IdentityPatch(target))?; Err(RawPatchError::IdentityPatch(target))?;
} }
let patch = Self::get_patch(target, destination)?; let patch = Self::get_patch(target, destination);
// Mask the thumb mode indicator bit // Mask the thumb mode indicator bit
#[cfg(target_arch = "arm")] #[cfg(target_arch = "arm")]
@ -34,108 +34,88 @@ impl Patch for RawPatch {
impl RawPatch { impl RawPatch {
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fn get_patch(_target: GuestAddr, destination: GuestAddr) -> Result<Vec<u8>, RawPatchError> { fn get_patch(_target: GuestAddr, destination: GuestAddr) -> Vec<u8> {
// mov rax, 0xdeadfacef00dd00d // mov rax, 0xdeadfacef00dd00d
// jmp rax // jmp rax
let insns = [ let addr = destination.to_ne_bytes();
[0x48, 0xb8, 0x0d, 0xd0, 0x0d, 0xf0, 0xce, 0xfa, 0xad, 0xde].to_vec(), #[rustfmt::skip]
[0xff, 0xe0].to_vec(), let insns: &[&[u8]] = &[
&[0x48, 0xb8], &addr,
&[0xff, 0xe0],
]; ];
let addr = destination.to_le_bytes(); insns.concat()
let insn0_mod = [
insns[0][0],
insns[0][1],
addr[0],
addr[1],
addr[2],
addr[3],
addr[4],
addr[5],
addr[6],
addr[7],
]
.to_vec();
let insns_mod = [&insn0_mod, &insns[1]];
Ok(insns_mod.into_iter().flatten().cloned().collect())
} }
#[cfg(target_arch = "x86")] #[cfg(target_arch = "x86")]
fn get_patch(_target: GuestAddr, destination: GuestAddr) -> Result<Vec<u8>, RawPatchError> { fn get_patch(_target: GuestAddr, destination: GuestAddr) -> Vec<u8> {
// mov eax, 0xdeadface // mov eax, 0xdeadface
// jmp eax // jmp eax
let insns = [ let addr = destination.to_ne_bytes();
[0xb8, 0xce, 0xfa, 0xad, 0xde].to_vec(), #[rustfmt::skip]
[0xff, 0xe0].to_vec(), let insns: &[&[u8]] = &[
&[0xb8], &addr,
&[0xff, 0xe0],
]; ];
let addr = destination.to_le_bytes(); insns.concat()
let insn0_mod = [insns[0][0], addr[0], addr[1], addr[2], addr[3]].to_vec();
let insns_mod = [&insn0_mod, &insns[1]];
Ok(insns_mod.into_iter().flatten().cloned().collect())
} }
#[cfg(target_arch = "arm")] #[cfg(target_arch = "arm")]
fn get_patch(target: GuestAddr, destination: GuestAddr) -> Result<Vec<u8>, RawPatchError> { fn get_patch(target: GuestAddr, destination: GuestAddr) -> Vec<u8> {
let addr = destination.to_ne_bytes();
// If our target is in thumb mode // If our target is in thumb mode
if target & 1 == 1 { #[rustfmt::skip]
let insns: &[&[u8]] = if target & 1 == 1 {
// ldr ip, [pc, #2] // ldr ip, [pc, #2]
// bx ip // bx ip
// .long 0xdeadface // .long 0xdeadface
let insns = [ &[
[0xdf, 0xf8, 0x02, 0xc0].to_vec(), &[0xdf, 0xf8, 0x02, 0xc0],
[0x60, 0x47].to_vec(), &[0x60, 0x47],
[0xce, 0xfa, 0xad, 0xde].to_vec(), &addr,
]; ]
let addr = destination.to_ne_bytes().to_vec();
let insns_mod = [&insns[0], &insns[1], &addr];
Ok(insns_mod.into_iter().flatten().cloned().collect())
} else { } else {
// ldr ip, [pc] // ldr ip, [pc]
// bx ip // bx ip
// .long 0xdeadface // .long 0xdeadface
let insns = [ &[
[0x00, 0xc0, 0x9f, 0xe5].to_vec(), &[0x00, 0xc0, 0x9f, 0xe5],
[0x1c, 0xff, 0x2f, 0xe1].to_vec(), &[0x1c, 0xff, 0x2f, 0xe1],
[0xce, 0xfa, 0xad, 0xde].to_vec(), &addr,
]; ]
let addr = destination.to_ne_bytes().to_vec(); };
let insns_mod = [&insns[0], &insns[1], &addr]; insns.concat()
Ok(insns_mod.into_iter().flatten().cloned().collect())
}
} }
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
fn get_patch(_target: GuestAddr, destination: GuestAddr) -> Result<Vec<u8>, RawPatchError> { fn get_patch(_target: GuestAddr, destination: GuestAddr) -> Vec<u8> {
// ldr x16, #8 // ldr x16, #8
// br x16 // br x16
// .quad 0xdeadfacef00dd00d // .quad 0xdeadfacef00dd00d
let insns = [ let addr = destination.to_ne_bytes();
[0x50, 0x00, 0x00, 0x58].to_vec(), #[rustfmt::skip]
[0x00, 0x02, 0x1f, 0xd6].to_vec(), let insns: &[&[u8]] = &[
[0x0d, 0xd0, 0x0d, 0xf0].to_vec(), &[0x50, 0x00, 0x00, 0x58],
[0xce, 0xfa, 0xad, 0xde].to_vec(), &[0x00, 0x02, 0x1f, 0xd6],
&addr
]; ];
let addr = destination.to_ne_bytes().to_vec(); insns.concat()
let insns_mod = [&insns[0], &insns[1], &addr];
Ok(insns_mod.into_iter().flatten().cloned().collect())
} }
#[cfg(target_arch = "powerpc")] #[cfg(target_arch = "powerpc")]
fn get_patch(_target: GuestAddr, destination: GuestAddr) -> Result<Vec<u8>, RawPatchError> { fn get_patch(_target: GuestAddr, destination: GuestAddr) -> Vec<u8> {
// lis 12, 0xdead // lis 12, 0xdead
// ori 12, 12, 0xface // ori 12, 12, 0xface
// mtctr 12 // mtctr 12
// bctr // bctr
let insns = [ let addr = destination.to_ne_bytes();
[0x3d, 0x80, 0xde, 0xad].to_vec(), #[rustfmt::skip]
[0x61, 0x8c, 0xfa, 0xce].to_vec(), let insns: &[&[u8]] = &[
[0x7d, 0x89, 0x03, 0xa6].to_vec(), &[0x3d, 0x80], &addr[..2],
[0x4e, 0x80, 0x04, 0x20].to_vec(), &[0x61, 0x8c], &addr[2..],
&[0x7d, 0x89, 0x03, 0xa6],
&[0x4e, 0x80, 0x04, 0x20],
]; ];
let addr = destination.to_be_bytes().to_vec(); insns.concat()
let insn0_mod = [insns[0][0], insns[0][1], addr[0], addr[1]].to_vec();
let insn1_mod = [insns[1][0], insns[1][1], addr[2], addr[3]].to_vec();
let insns_mod = [&insn0_mod, &insn1_mod, &insns[2], &insns[3]];
Ok(insns_mod.into_iter().flatten().cloned().collect())
} }
} }