diff --git a/src/arch/aarch64.rs b/src/arch/aarch64.rs new file mode 100644 index 0000000..0bfd8ed --- /dev/null +++ b/src/arch/aarch64.rs @@ -0,0 +1,68 @@ +//! AArch64 arch-sepcific implementations + +use crate::{JumpEntry, JumpLabelType}; + +/// Length of jump instruction to be replaced +pub const ARCH_JUMP_INS_LENGTH: usize = 4; + +/// New instruction generated according to jump label type and jump entry +#[inline(always)] +pub fn arch_jump_entry_instruction( + jump_label_type: JumpLabelType, + jump_entry: &JumpEntry, +) -> [u8; ARCH_JUMP_INS_LENGTH] { + match jump_label_type { + JumpLabelType::Jmp => { + // Note that aarch64 only supports relative address within +/-128MB. + // In current implementation, this assumption is always hold. + let relative_addr = + (jump_entry.target_addr() - (jump_entry.code_addr() + ARCH_JUMP_INS_LENGTH)) as u32; + let [a, b, c, d] = (relative_addr / 4).to_ne_bytes(); + [a, b, c, d | 0b00010100] + } + JumpLabelType::Nop => [0x1f, 0x20, 0x03, 0xd5], + } +} + +#[doc(hidden)] +#[macro_export] +macro_rules! arch_static_key_init_nop_asm_template { + () => { + ::core::concat!( + r#" + 2: + nop + .pushsection "#, + $crate::os_static_key_sec_name_attr!(), + r#" + .balign 8 + .quad 2b - . + .quad {0} - . + .quad {1} + {2} - . + .popsection + "# + ) + }; +} + +// The `0x90,0x90,0x90` are three NOPs, which is to make sure the `jmp {0}` is at least 5 bytes long. +#[doc(hidden)] +#[macro_export] +macro_rules! arch_static_key_init_jmp_asm_template { + () => { + ::core::concat!( + r#" + 2: + b {0} + .pushsection "#, + $crate::os_static_key_sec_name_attr!(), + r#" + .balign 8 + .quad 2b - . + .quad {0} - . + .quad {1} + {2} - . + .popsection + "# + ) + }; +} diff --git a/src/arch/mod.rs b/src/arch/mod.rs index 3f6e232..c056393 100644 --- a/src/arch/mod.rs +++ b/src/arch/mod.rs @@ -9,3 +9,8 @@ pub use x86_64::*; mod x86; #[cfg(target_arch = "x86")] pub use x86::*; + +#[cfg(target_arch = "aarch64")] +mod aarch64; +#[cfg(target_arch = "aarch64")] +pub use aarch64::*; diff --git a/src/arch/x86.rs b/src/arch/x86.rs index f50b06c..16bc9ae 100644 --- a/src/arch/x86.rs +++ b/src/arch/x86.rs @@ -31,8 +31,8 @@ macro_rules! arch_static_key_init_nop_asm_template { 2: .byte 0x3e,0x8d,0x74,0x26,0x00 .pushsection "#, - $crate::os_static_key_sec_name!(), - r#", "awR" + $crate::os_static_key_sec_name_attr!(), + r#" .balign 4 .long 2b - . .long {0} - . @@ -54,8 +54,8 @@ macro_rules! arch_static_key_init_jmp_asm_template { jmp {0} .byte 0x90,0x90,0x90 .pushsection "#, - $crate::os_static_key_sec_name!(), - r#", "awR" + $crate::os_static_key_sec_name_attr!(), + r#" .balign 4 .long 2b - . .long {0} - . diff --git a/src/arch/x86_64.rs b/src/arch/x86_64.rs index 2adcadd..5f9f47e 100644 --- a/src/arch/x86_64.rs +++ b/src/arch/x86_64.rs @@ -31,8 +31,8 @@ macro_rules! arch_static_key_init_nop_asm_template { 2: .byte 0x0f,0x1f,0x44,0x00,0x00 .pushsection "#, - $crate::os_static_key_sec_name!(), - r#", "awR" + $crate::os_static_key_sec_name_attr!(), + r#" .balign 8 .quad 2b - . .quad {0} - . @@ -54,8 +54,8 @@ macro_rules! arch_static_key_init_jmp_asm_template { jmp {0} .byte 0x90,0x90,0x90 .pushsection "#, - $crate::os_static_key_sec_name!(), - r#", "awR" + $crate::os_static_key_sec_name_attr!(), + r#" .balign 8 .quad 2b - . .quad {0} - . diff --git a/src/os/linux.rs b/src/os/linux.rs index 4a5f70d..39e6719 100644 --- a/src/os/linux.rs +++ b/src/os/linux.rs @@ -2,12 +2,13 @@ use crate::JumpEntry; -/// Section name of +// See https://sourceware.org/binutils/docs/as/Section.html +/// Name and attribute of section storing jump entries #[doc(hidden)] #[macro_export] -macro_rules! os_static_key_sec_name { +macro_rules! os_static_key_sec_name_attr { () => { - "__static_keys" + "__static_keys, \"awR\"" }; } diff --git a/src/os/macos.rs b/src/os/macos.rs new file mode 100644 index 0000000..29eaac6 --- /dev/null +++ b/src/os/macos.rs @@ -0,0 +1,23 @@ +//! macOS-specific implementations + +use crate::JumpEntry; + +// See https://developer.apple.com/library/archive/documentation/DeveloperTools/Reference/Assembler/040-Assembler_Directives/asm_directives.html#//apple_ref/doc/uid/TP30000823-CJBIFBJG +/// Name and attribute of section storing jump entries +#[doc(hidden)] +#[macro_export] +macro_rules! os_static_key_sec_name_attr { + () => { + "__DATA,__static_keys,regular,no_dead_strip" + }; +} + +// See https://stackoverflow.com/q/17669593/10005095 and https://github.com/apple-opensource-mirror/ld64/blob/master/unit-tests/test-cases/section-labels/main.c +extern "Rust" { + /// Address of this static is the start address of __static_keys section + #[link_name = "\x01section$start$__DATA$__static_keys"] + pub static mut JUMP_ENTRY_START: JumpEntry; + /// Address of this static is the end address of __static_keys section (excluded) + #[link_name = "\x01section$end$__DATA$__static_keys"] + pub static mut JUMP_ENTRY_STOP: JumpEntry; +} diff --git a/src/os/mod.rs b/src/os/mod.rs index 0e4a390..278d070 100644 --- a/src/os/mod.rs +++ b/src/os/mod.rs @@ -4,3 +4,8 @@ mod linux; #[cfg(target_os = "linux")] pub use linux::*; + +#[cfg(target_os = "macos")] +mod macos; +#[cfg(target_os = "macos")] +pub use macos::*;