Macro r3_portkit::sym::sym_static
source · pub macro sym_static { ( // A trait item #[sym($sym_name:ident)] $(#[$meta:meta])* $vis:vis fn $fn_name:ident() -> &$ty:ty ) => { ... }, ( // A concrete definition #[sym($sym_name:ident)] $(#[$meta:meta])* $vis:vis fn $fn_name:ident() -> &$ty:ty { &$static:path } ) => { ... }, }
Expand description
Define two fn
items representing the specified static
variable.
-
$fn_name
is a normal function just returning a'static
reference to that variable. -
$sym_name
is not really a function but an immutable variable holding the address of that variable. Inline assembly code can refer to this by asym
operand, but when doing this, it must append_
(an underscore) to the symbol name (see the following example).
Examples
#![feature(naked_functions)]
#![feature(asm_const)]
use r3_portkit::sym::sym_static;
use std::{arch::asm, cell::Cell};
struct InteriorMutable(Cell<usize>);
unsafe impl Sync for InteriorMutable {}
trait Tr {
sym_static!(#[sym(p_var)] fn var() -> &InteriorMutable);
}
static S: InteriorMutable = InteriorMutable(Cell::new(0));
impl Tr for u8 {
sym_static!(#[sym(p_var)] fn var() -> &InteriorMutable { &S });
}
// TODO: Replace with the following when const arguments become
// inferrable:
//
// let sr1: SymStatic<InteriorMutable, _> = u8::VAR;
let sr = u8::var();
sr.0.set(42);
assert_eq!(sr.0.get(), 42);
// Since it appears as a `fn` item, it can be passed to `asm!` by a
// `sym` input.
let got_value: usize;
#[cfg(target_arch = "x86_64")]
#[cfg(target_os = "linux")]
unsafe {
asm!("
mov {0}, qword ptr [rip + {1}_@GOTPCREL]
mov {0}, qword ptr [{0}]
mov {0}, qword ptr [{0}]",
out(reg) got_value, sym u8::p_var,
);
}
#[cfg(target_arch = "x86_64")]
#[cfg(not(target_os = "linux"))]
unsafe {
asm!("
mov {0}, qword ptr [rip + {1}_]
mov {0}, qword ptr [{0}]",
out(reg) got_value, sym u8::p_var,
)
};
#[cfg(target_arch = "aarch64")]
#[cfg(target_os = "macos")]
unsafe {
asm!("
adrp {0}, {1}_@PAGE
ldr {0}, [{0}, {1}_@PAGEOFF]
ldr {0}, [{0}]
",
out(reg) got_value, sym u8::p_var
);
}
#[cfg(target_arch = "aarch64")]
#[cfg(not(target_os = "macos"))]
unsafe {
asm!("
adrp {0}, :got:{1}_
ldr {0}, [{0}, #:got_lo12:{1}_]
ldr {0}, [{0}]
ldr {0}, [{0}]
",
out(reg) got_value, sym u8::p_var
)
};
assert_eq!(got_value, 42);