I've been attempting to compile position-independent code for i686-pc-windows-gnu
(although I am using a custom target due to Compiling `no_std` for `i686-pc-windows-gnu` ignores `panic=abort` · Issue #133826 · rust-lang/rust · GitHub ). However, references to the .bss
and .data
sections generate absolute addresses despite my best combinations of -fPIC
, --disable-large-memory-addresses
etc.
For example, the following rust code to use an external linker-generated symbol will result in the use of an absolute address.
extern "C" {
static mut _data_offset: usize;
}
pub fn data_offset() -> usize {
#[allow(unused_unsafe)]
unsafe {
let offset_addr = &raw mut _data_offset;
offset_addr as usize
}
}
Calling data_offset()
results in the generation of the following assembly:
add esi,DWORD PTR ds:0x928
ds:0x928
is the location of .refptr.__data_offset
which can be view in the symbol map:
.rdata$.refptr.__data_offset
0x00000928 0x4 /home/irate-walrus/Source/stardust-rs/target/i686-custom-windows-gnu/release/deps/stardust-2c9480055904d2d5.stardust.594aeda9d04a4488-cgu.0.rcgu.o
0x00000928 .refptr.__data_offset
Global static variables will also result in absolute addresses.
pub static INSTANCE: AtomicPtr<Instance> = AtomicPtr::new(ptr::null_mut());
mov DWORD PTR ds:0x1000,ebx
mov esi,DWORD PTR ds:0x1000
ds:0x1000
is the location of the .bss
section where INSTANCE
is stored.
.bss 0x00001000 0x5
When targeting i686-unknown-linux-gnu
, x86_64-unknown-linux-gnu
, and x86_64_pc-windows-gnu
relative addressing works as expected. i686-unknown-linux-gnu
produces the following assembly when accessing the same INSTANCE
global.
lea ecx,[ebx-0x144f]
I don't know if what I am attempting to do is even possible, but it must be in theory as it is working on the i686 linux target. The project this is for is GitHub - Irate-Walrus/stardust-rs: An i686 & x86_64 position independent implant template for Rust 🦀 . Your help is much appreciated and if this fails I guess I'm going to have get deep into some mingw
forums.