Page 3 of 3
Re: Debugging UEFI Issues on real hardware (POSIX-UEFI)
Posted: Wed Jul 28, 2021 5:33 pm
by davmac314
Octocontrabass wrote:davmac314 wrote:Note that If compiling with GCC and linking with GNU ld (to `pei-XXX` format eg pei-x86-64) you can use `--emit-reloc-section` at link time (possibly requires `-mi386pep` linker emulation setting) rather than `-fpie` at compile time, if you want to preserve relocations (rather than eliminate the need for them, which is what `-fpie` achieves).
Hold on, there's a difference between "-fpie" and "-pie".
You're right, I conflated the two options.
Octocontrabass wrote:Mingw-w64 GCC ignores options like "-fpie"; it unconditionally generates relocatable code.
"-fpie" causes GCC to emit position-independent code, which is not strictly the same thing as relocatable code (i.e. code with relocations). With "-fpie", loads are emitted as PC-relative, which means load-time relocations are generally not necessary (in the ELF world, it turns out that references to variables in shared libraries will use a special COPY relocation record, which literally copies the variable into the executable's own chosen location; a PLT is still used for calls to functions from shared libraries).
Regular GCC also unconditionally generates relocatable code - it's the link stage which strips the relocations. They can be kept, via "--emit-relocs"; most ELF loaders will probably just load a non-PIE ELF image at its nominal address, however, even if relocations are present.
Re: Debugging UEFI Issues on real hardware (POSIX-UEFI)
Posted: Wed Jul 28, 2021 8:32 pm
by Octocontrabass
davmac314 wrote:"-fpie" causes GCC to emit position-independent code,
This is true on ELF targets, but Mingw-w64 GCC ignores that option.
davmac314 wrote:which is not strictly the same thing as relocatable code (i.e. code with relocations).
It's almost the same. PIC just consolidates relocations to the GOT instead of applying them all over the binary. There's no GOT in PE, so it doesn't make sense for Mingw-w64 GCC to support PIC.
davmac314 wrote:With "-fpie", loads are emitted as PC-relative, which means load-time relocations are generally not necessary
GCC already does this for x64 even without "-fpie".
Re: Debugging UEFI Issues on real hardware (POSIX-UEFI)
Posted: Thu Jul 29, 2021 4:08 am
by davmac314
Octocontrabass wrote:davmac314 wrote:which is not strictly the same thing as relocatable code (i.e. code with relocations).
It's almost the same. PIC just consolidates relocations to the GOT instead of applying them all over the binary. There's no GOT in PE, so it doesn't make sense for Mingw-w64 GCC to support PIC.
"almost the same"
is not strictly the same, though. I think we're just mincing terms. I was trying to say that "relocatable code" can be both non-PIC and non-PIE, it's just code that can be relocated (possibly by performing relocations). (and I was otherwise talking about PIE, not PIC. Certainly it makes sense that Mingw-w64 doesn't support PIC).
An EFI image should be "relocatable" but that does not mean it needs to be either PIE nor PIC code. It can be PIE (with no relocations necessary) or it can be non-PIE (with relocations).
Octocontrabass wrote:davmac314 wrote:With "-fpie", loads are emitted as PC-relative, which means load-time relocations are generally not necessary
GCC already does this for x64 even without "-fpie".
It does for x64 with the default memory model, but not for all memory models (and it doesn't for 32-bit i686).
Re: Debugging UEFI Issues on real hardware (POSIX-UEFI)
Posted: Thu Jul 29, 2021 10:02 am
by Octocontrabass
davmac314 wrote:It can be PIE (with no relocations necessary)
I'm pretty sure PIE can still require relocations, just not in the .text section. (But PE doesn't have PIC or PIE, those are part of ELF.)
davmac314 wrote:It does for x64 with the default memory model, but not for all memory models (and it doesn't for 32-bit i686).
Actually, on further investigation, this might be target-dependent. Mingw-w64 GCC always uses RIP-relative addressing for x64, but Linux GCC only uses RIP-relative addressing for position-independent code (PIC or PIE). I'm not entirely certain why Mingw-w64 GCC works this way. Clang does the same thing, so it might be something to do with the Windows ABI.
Mingw-w64 never uses EIP-relative addressing for i686, but the reasoning is much easier to understand: PE doesn't have PIC or PIE, and EIP-relative addressing is significantly bigger and slower than ordinary position-dependent addressing.
Re: Debugging UEFI Issues on real hardware (POSIX-UEFI)
Posted: Thu Jul 29, 2021 3:40 pm
by davmac314
Octocontrabass wrote:I'm pretty sure PIE can still require relocations, just not in the .text section. (But PE doesn't have PIC or PIE, those are part of ELF.)
True, it can require relocations in the .data section for instance if you initialise something with the address of something else. But it will not require a GOT. Remember the original context was:
zaval wrote:I am not sure what effect the gcc's -pie flag would have on PE targets, if any. in the ELF context, it's a total opposite to the PE approach, and it hardly would work for the latter, because PE loader does apply base relocations, that is fixes up addresses in the code and data itself, while -pie would require fixing up the contents of a special indirection table (GOT)
Regarding:
Octocontrabass wrote:Actually, on further investigation, this might be target-dependent. Mingw-w64 GCC always uses RIP-relative addressing for x64, but Linux GCC only uses RIP-relative addressing for position-independent code (PIC or PIE).
Linux GCC will at least sometimes use RIP-relative addressing for non-PIC & non-PIE code:
https://godbolt.org/z/3jWTorbTq
Again it will depend on the memory model, at least. Adding "-mcmodel=large" to the command line will cause the above example to no longer use RIP-relative addressing.
Octocontrabass wrote:Mingw-w64 never uses EIP-relative addressing for i686, but the reasoning is much easier to understand: PE doesn't have PIC or PIE, and EIP-relative addressing is significantly bigger and slower than ordinary position-dependent addressing.
That makes sense. The same is true on Linux unless you use -fpie (or your GCC is configured to generate PIE code by default).