How to avoid generation of stub references for global variables (ex. "rdata$.refptr") ?"

Hello.

When using PIC relocation model and compiling for windows target, all accesses to extern variables (defined by the linker) occur through a stub reference - a section ".rdata$.refptr.SYMBOL" that contains a single pointer to the real referenced symbol.

For example, the following code:

#![no_main]
#![no_std]

#[panic_handler]
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
    loop {}
}

extern "C" {
    static SYMBOL: usize;
}

#[no_mangle]
#[link_section = ".entry"]
unsafe extern "C" fn _start() {
    // Just do something with the symbol so that the compiler does not optimize it await.
    let symbol = core::ptr::read_volatile(&SYMBOL);
    *(0x1000 as *mut usize) = symbol;
}

Compiled with the following flags:

rustflags = [
    "-C",
    "link-arg=-nostdlib",
    "-C",
    "link-arg=-static",
    "-C",
    "link-arg=-Wl,-M,-Tlink.ld,--build-id=none",
    "-C",
    "relocation-model=pic",
]

The linker part of a linker script defining the SYMBOL:

	.text :
	{
		*(.entry)
		SYMBOL = .;
		*(.text)
		*(.data)
		*(.rdata)
	}

Produces the following code:

0000000200000000 <.text>:
   200000000:   48 8b 05 11 00 00 00    mov    rax,QWORD PTR [rip+0x11]        # 0x200000018
   200000007:   48 8b 00                mov    rax,QWORD PTR [rax]
   20000000a:   48 89 04 25 00 10 00    mov    QWORD PTR ds:0x1000,rax
   200000011:   00 
   200000012:   c3                      ret

Where 0x200000018 is the address of a "refptr" section. From verbose linker output:

.rdata$.refptr.SYMBOL
                          0x0000000000000018        0x8 *.rcgu.o
                          0x0000000000000018                .refptr.SYMBOL
           .reloc         0x0000000000000020        0xc dll stuff

The resulting binary requires resolving relocations of the refptr, which is what I want to avoid.

How can I make the compiler reference symbols directly (using pc relative instructions, like lea in x86), and not produce any code requiring resolving relocations?

You can't. Windows accesses globals in certain way and if you want to implement some other way of doing that then it's no longer x86_64-pc-windows-msvc or x86_64-pc-windows-gnullvm, but some other target.

And since that's a different target you would need to add changes to LLVM and then use changed LLVM in updated version of rustc.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.