On 1 August 2016 at 08:13, Shi, Steven <steven....@intel.com> wrote: >> >> >> >> I am also concerned about the GOTPCRELX/REX_GOTPCRELX relocations. >> >> Reading the x86_64 ABI docs, it appears that these may refer to >> >> instructions that have been modified by the linker. In that case, how >> >> do we deal with the relocation? Also, according to the doc, mov >> >> instructions may be emitted by the linker in some cases that are only >> >> valid in the lowest 2 GB of the address space. >> >> >> > [Steven]: Frankly to say, the x86_64 ABI docs is only good for compiler >> domain developer and not very good for other domain developers to >> understand it. >> > My overall understanding for these different relocation type is like this: >> compiler generate PIC code with different "level of indirection to all global >> data and function references in the code." And these different level of >> indirection is implemented through GOT and PLT structure with different >> addressing calculation pattern. The different calculation patterns are the >> different relocation types which are defined by x86_64 ABI Table 4.9. We >> don't need worry about how compiler correctly generate code to work with >> these relocation types, we just need correctly understand their addressing >> calculation pattern. >> > >> > The GOTPCRELX/REX_GOTPCRELX has the same calculation definition in >> x86_64 ABI Table 4.9 as "G + GOT + A - P". So, I assume their difference is >> not >> in the relocation calculation pattern, but how to co-work with specific >> instructions to finish these calculation in a hardware optimized way. >> > >> >> No, that is not what these are for. The special types mark >> instructions that can be converted by the linker into simpler >> sequences if the symbol turns out to be in the same module. From the >> doc: >> >> mov foo@GOTPCREL(%rip), %reg >> >> could be converted by the linker into >> >> lea foo(%rip), %reg >> >> if the reference to 'foo' is satisfied by a non-preemptible local >> definition. This is a useful optimization, since it eliminates a >> memory load. The problem is that we cannot recalculate such >> relocations in GenFw without checking whether the linker has applied >> this optimization or not. >> > [Steven]: Do you mean the linker will apply above optimization but not remove > the original GOTPCREL item? It sounds like a severe linker bug. >
I checked quickly, and it appears the linker does the right thing here, i.e., it performs the optimization and also modifies the relocation emitted into the .rela.text section So this: .globl bar .type bar, @function bar: mov foo@GOTPCREL(%rip), %eax ret .globl foo foo: .quad 0 compiles into /tmp/pie.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <bar>: 0: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 6 <bar+0x6> 2: R_X86_64_GOTPCRELX foo-0x4 6: c3 retq 0000000000000007 <foo>: ... but after linking (ld -o /tmp/pie -e bar -q /tmp/pie.o) /tmp/pie: file format elf64-x86-64 Disassembly of section .text: 00000000004000b0 <bar>: 4000b0: 8d 05 01 00 00 00 lea 0x1(%rip),%eax # 4000b7 <foo> 4000b2: R_X86_64_PC32 foo-0x4 4000b6: c3 retq 00000000004000b7 <foo>: ... >> >> The fact that it works does not make it safe. Having multiple fixups >> for the same symbol in the .reloc section is a problem, and so is >> reapplying GOTPCRELX to places where the original instruction has been >> replaced by the linker. >> > [Steven]: I still don't understand why there will be multiple fixups for the > same symbol in the .reloc section? > Remember this example >> > int n; >> > int f () { return n; } >> > int g () { return n; } >> > int h () { return n; } If every 'return n' results in a GOTPCREL relocation, how are you going to make sure that the GOT entry for 'n' is only fixed up a single time? _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel