I'm trying to create LLVM IR which outputs Relative Virtual Addresses. However, after compiling and linking, I see that it outputs addresses based on the preferred image base address of the executable, rather than relative addresses.
For instance, if I use code like:
@.myconstant = private constant [12 x i8] c"My constant\00"
@.myglobal = global {i8*} {i8* bitcast([12 x i8]* @.myconstant to i8*)}
In the matching executable section, I see a hex value like:
44 30 40 00
Or simply 0x403044, which is much larger than my entire executable size, even after section alignment.
If I manually subtract 0x400000, Like so:
@.myconstant = private constant [12 x i8] c"My constant\00"
@.myglobal = global {i8*} {i8* inttoptr (i32 sub(i32 ptrtoint([12 x i8]* @.myconstant to i32), i32 u0x400000) to i8*)}
I get the correct address in the executable. But this solution is not maintainable, because the image base address isn't guaranteed to be 0x400000.
At the same time, I have to use a pointer to a global, because I don't know where that global would end up inside the relevant section (since that depends on other globals in the same section), or what relative memory address would be assigned for that section (since that depends on alignment with previous sections).
So my question is, how do I either get the base address as a constant, or get an address relative to the loading address of the program?
Update: Apparently, the developers of lld already encountered this problem, and added an extention to the AT&T assembly language to account for this:
.regular_global:
.long .L.myconstant # Outputs 0x403044
.rva_global:
.long .L.myconstant@imgrel # Outputs 0x3044
So my question becomes: How do I cause this assembly to be produced through the IR?