R_X86_64_GOTOFF64: S + A - GOT
R_X86_64_GOTPC{32,64}: GOT + A - P (R_GOTONLY_PC_FROM_END)
R_X86_64_GOTOFF64 should use R_GOTREL_FROM_END so that in junction with
R_X86_64_GOTPC{32,64}, the GOT term is neutralized.
Differential D48095
[ELF][X86_64] Use R_GOTREL_FROM_END instead of R_GOTREL for R_X86_64_GOTOFF64 MaskRay on Jun 12 2018, 2:11 PM. Authored by
Details
R_X86_64_GOTOFF64: S + A - GOT R_X86_64_GOTOFF64 should use R_GOTREL_FROM_END so that in junction with
Diff Detail
Event TimelineComment Actions Test is not only important to not break the feature in the future, but it helps readers a lot by demonstrating the issue in action, so even for a change that's not ready for submission, adding test is greatly appreciated. Comment Actions Can you take another look? I have removed one function. R_X86_64_GOTPC32 and R_X86_64_GOTPC64 are related and use the same assumption. Comment Actions First of all, please do not remove x86-64-reloc-gotoff64.s. I'd write your new test to that file instead. It is easier to maintain two separate test files than having one larger test file. Second of all, I got a different compilation result for the code that you gave to me: https://godbolt.org/g/qA1K9y. Is this expected? Comment Actions OK moved the test to x86-64-reloc-gotoff64.s, and renamed x86-64-reloc-got.s to x86-64-reloc-gotpc64.s.
Sorry, the code was produced by gcc, not clang gcc -O2 -S -mcmodel=medium -fPIC a.c emits the expected two instructions whose sum computes the pc-relative address (runtime address of _DYNAMIC) The dynamic loader needs a runtime-address (_DYNAMIC here), subtracting the link-time address (static _DYNAMIC) from it to compute its image base. Comment Actions Thank you for the explanation. This is perhaps a bit of topic, but does this mean it's a clang's bug? It seems to me that the code clang emits is not position independent. Comment Actions
The movabsq encodes the link-time address of a symbol, then in runtime the address is added by an offset R_X86_64_RELATIVE. The clang way: one movabsq plus a R_X86_64_RELATIVE relocation that is supposed to be resolved by the dynamic loader. The clang way is still position-independent. Comment Actions
Is that true? Clang's output needs text relocations which in many cases prohibited. As a result, clang's output won't work in many environments. Comment Actions Yes, clang emits R_X86_64_RELATIVE in .text, which is text relocation and generates DT_TEXTREL and DF_TEXTREL in the linked executable. When DT_TEXTREL is used in conjunction with R_X86_64_IRELATIVE (ifunc calls, which can even be left in statically linked executables), glibc ld.so will segfault when resolving the relocations. https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=elf/dl-reloc.c /* DT_TEXTREL is now in level 2 and might phase out at some time. But we rewrite the DT_FLAGS entry to a DT_TEXTREL entry to make testing easier and therefore it will be available at all time. */ if (__builtin_expect (l->l_info[DT_TEXTREL] != NULL, 0)) { ... /////////// the program text segment is remapped as read+write but not executable /////// if (__mprotect (newp->start, newp->len, PROT_READ|PROT_WRITE) < 0) ... ////// IFUNC (R_X86_64_IRELATIVE) is resolved in this call /////// ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc); ... /////// recover ////////// /* Undo the segment protection changes. */ while (__builtin_expect (textrels != NULL, 0)) { if (__mprotect (textrels->start, textrels->len, textrels->prot) < 0) |