[LLVMdev] MachO non-external X86_64_RELOC_UNSIGNED

Nick Kledzik
Mon, 09 Jun 2014 23:19:44 -0000

On Jun 8, 2014, at 8:59 PM, Keno Fischer <kfischer at college.harvard.edu>
wrote:

> Hello everybody,
>
> I would like some insights on the semantics of the X86_64_RELOC_UNSIGNED
relocation type. When r_extern=1, the semantics seem pretty clear:
>
> Let x be a pointer to r_offset of appropriate size given by r_size, then
> *x += addr_of_symbol(r_symbolnum)
>
> However, when r_extern=0 the correct behavior is not clear. By analogy with
the above, I would have expected
>
> *x += addr_of_section(r_symbolnum)
>
> but what LLVM implements is different. In RTDyld it implements
>
> *x = (*x-addr_of_section(r_symbolnum)) + addr_of_section(r_symbolnum)
>
> or equivalently
>
> *x = *x
In ld64 relocations are parsed into “Fixups”.  A Fixup is a location to fix up
and a value/expression of what to set it to.  All sections are parsed up into
“atoms”.  A location is an atom and an offset (within the atom).  The expression
for a fixup is a target atom and optional addend (e.g. &foo + 10).

For X86_64_RELOC_UNSIGNED when r_extern=1, the location is the atom containing
the r_address (offset in the section), and the expression is the atom
corresponding to r_symbolnum plus the added that is the current content of the
location.  In the JIT case where you are trying to prepare a object file for
execution, that boils down to adding the final address of the r_symbolnum atom
to the current content (addend) in the fixup location.

For X86_64_RELOC_UNSIGNED when r_extern=0, the fixup location is the atom
containing the r_address (offset in the section), and the expression is whatever
atom+offset the current contents of location points to in that object file.  In
the JIT case, the boils down to adjusting the location by the amount the target
atom slid from its address in the object file to its final address for
execution.  For instance, if the location contains 0x00000218 which points into
section __DATA,__data (0x200 thru 0x280) and the __data section winds up at
address 0x100001000 at runtime, then the location needs to have 0x100000E00
added to it (0x100001000 - 0x200).

-Nick


>
> i.e. a noop. This works because llvm codegen also emits the absolute value
of the address. I am unsure what is intended and would appreciate some
clarification. A couple of points to consider:
>
> 1. I checked ld64 and as far as I can tell it doesn't consider
non-external X86_64_RELOC_UNSIGNED but does *x += addr_of_symbol(r_symbolnum)
regardless. That seems like a bug in ld64 to me because other relocations in the
same switch statement do check r_extern.
>
> 2. I implemented *x += addr_of_section(r_symbolnum) in LLVM and all tests
pass just fine
>
> 3. If the current implementation is correct r_symbolnum (and potentially
the entire relocation) basically meaningless, which could of course be correct,
but which is what originally caused me to look at this. If so I'd appreciate
an explanation as to why we need to have the relocation in the first place.
>
> That's all I could find on the subject. I hope somebody else knows more
than I.
>
> Thanks,
> Keno
>
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev