Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#12430 closed bug (fixed)

gcc 4 won't build a non-position-independent executable

Reported by: simonsouth Owned by: korli
Priority: normal Milestone: Unscheduled
Component: System Version: R1/Development
Keywords: Cc:
Blocked By: Blocking:
Has a Patch: yes Platform: All

Description

(This is the compile-side counterpart to #12427.)

On Haiku, executables are position-independent by default. However asking gcc (4.8.5) to build a non-position-independent executable with (for instance) the -fno-pie flag fails with an error message like

/boot/system/(...)/bin/ld: /tmp//ccxbCP1i.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
/tmp//ccxbCP1i.o: error adding symbols: Bad value
collect2: error: ld returned 1 exit status

This is because gcc is configured to always pass either the -r or -shared flag to the linker, and there is no easy way to override this. But not everything is relocatable or a shared object, and if the user specifically requests something different, that request should be honoured.

Consequently apps like GNU Emacs that rely on support for fixed-position executables cannot be built on Haiku right now.

Attachments (6)

0001-gcc-Allow-the-user-to-build-non-PI-executables.patch (5.9 KB) - added by simonsouth 3 years ago.
Change gcc configuration to allow non-PI executables to be created
0002-gcc-CC1_SPEC-LINK_SPEC-Wrap-lines-at-80-columns.patch (6.3 KB) - added by simonsouth 3 years ago.
Wrap CC1_SPEC and LINK_SPEC lines at 80 columns
0003-gcc-LINK_SPEC-Gently-refactor.patch (3.2 KB) - added by simonsouth 3 years ago.
Gently refactor LINK_SPEC: Consolidate sequences; use more compact notation
0004-binutils-ld-Set-ELF-interpreter-to-system-runtime_lo.patch (4.9 KB) - added by simonsouth 3 years ago.
Set ELF interpreter to "/system/runtime_loader"
0005-gcc-ppc-Remove-now-redundant-CC1_SPEC.patch (868 bytes) - added by simonsouth 3 years ago.
Remove redundant CC1_SPEC from ppc
0006-Build-without-linker-warnings-about-missing-entry-sy.patch (1.5 KB) - added by simonsouth 3 years ago.
Build without linker warnings about missing entry symbols

Download all attachments as: .zip

Change History (22)

Changed 3 years ago by simonsouth

Change gcc configuration to allow non-PI executables to be created

comment:1 Changed 3 years ago by simonsouth

Has a Patch: set

Changed 3 years ago by simonsouth

Wrap CC1_SPEC and LINK_SPEC lines at 80 columns

Changed 3 years ago by simonsouth

Gently refactor LINK_SPEC: Consolidate sequences; use more compact notation

Changed 3 years ago by simonsouth

Set ELF interpreter to "/system/runtime_loader"

comment:2 Changed 3 years ago by simonsouth

Here is a set of patches that correct this issue.

The first patch modifies gcc's CC1_SPEC and LINK_SPEC strings to

  • Include -fno-PIC and -fno-PIE as command-line options that disable the generation of position-independent code (and remove the non-existent -no-fpic option).
  • Use -fPIC by default in place of -fpic to compile without restriction on the size of the global offset table (this matters only on m68k and ppc, and is already the default on ppc; users can still request this limit with -fpic).
  • Pass -shared to the linker only if it was passed to gcc.
  • Output position-independent executables by default, and request them specifically with the -pie linker option, allowing undefined symbols in shared libraries and exporting all symbols to match the behaviour of shared-object "executables" today.

The remaining patches are optional but complete the implementation. In order, they

  • Wrap the CC1_SPEC and LINK_SPEC strings neatly at 80 columns.
  • Gently refactor the LINK_SPEC string for several platforms, consolidating sequences and using a more compact notation without any change in functionality.
  • Set the ELF interpreter on generated executables.

Now that gcc is outputting "real" PIEs and not shared objects masquerading as them, the linker includes an INTERP segment in the ELF header requesting a specific interpreter to launch the program. This final patch (against ld) changes the contents of this section from the UNIX-y default to something more accurate and distinctly Haiku.

With these patches applied

  • The default behaviour of gcc is not changed. Position-independent executables are still generated by default, and these still participate in dynamic linking exactly as they do today.
  • Pre-existing executables function just as they do currently and can still be used as link targets.
  • Users can ask gcc to build a non-position-independent executable with the -fno-pic or -fno-pie options, and the request will be honoured (and with the patch for #12427 applied, the generated executable will run).
  • gcc now says what it means: When it means to build a position-independent executable, it says so explicitly by passing the -pie option to the linker. No longer does it request a shared object that just happens to function like a PIE.
  • An INTERP segment is included in every executable that identifies it as built for Haiku with a pointer to /system/runtime_loader. This is ignored by runtime_loader today, but (aside from the vanity aspect) could be useful down the road to distinguish between 32- and 64-bit executables on x86_64, or to support seamless execution of BeOS and Haiku executables together.

Changed 3 years ago by simonsouth

Remove redundant CC1_SPEC from ppc

comment:3 Changed 3 years ago by simonsouth

I realized in writing the above that with these changes, there is no longer a need for ppc to define its own CC1_SPEC.

I've added a fifth patch that removes this now-redundant code.

comment:4 Changed 3 years ago by korli

Owner: changed from nobody to korli
Status: newassigned

comment:5 Changed 3 years ago by korli

Thanks for the patches. They look correct to me. I tested on x86 and x86_64, it runs well, though I got for both those warnings on kernel add-on link (the default address changes every time)

cross-tools-x86_64/lib/gcc/x86_64-unknown-haiku/4.8.5/../../../../x86_64-unknown-haiku/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000002cb0

When loading the addons, the kernel prints warnings:

ahci: unhandled pheader type 0x6
ahci: unhandled pheader type 0x3

I can handle the "unhandled pheader type" warnings in src/system/kernel/elf.cpp. The ld warning is probably related to the KernelAddOn rule in build/jam/KernelRules. Have you an idea for this one?

comment:6 Changed 3 years ago by korli

Kernel warnings are avoided in hrev49731.

Changed 3 years ago by simonsouth

Build without linker warnings about missing entry symbols

comment:7 Changed 3 years ago by simonsouth

Yes; this latest patch should clear up these warnings.

  • From looking at the code it seems kernel add-ons are really meant to be built as shared objects (hence the lack of an apparent entry point), which just happened to be the default behaviour before. Adding -shared to the link options makes this explicit and clears up those warnings.
  • The same warning was being issued by the BuildMBR rule, which was using the -Xlinker option incorrectly in an attempt to specify the entry point to the linker (the GCC manual actually warns about this misuse). A bit of reformatting fixes this as well.

comment:8 Changed 3 years ago by korli

Patch 6 looks good. I'll give it a check with GCC 2.95 first, then push the patchset.

On a side note, would it make sense to align GCC 2.95 behavior regarding -shared?

comment:9 Changed 3 years ago by simonsouth

Yes; probably all these changes should be applied to gcc 2.95 as well (less the options it doesn't support). I'll look at that shortly.

comment:10 Changed 3 years ago by korli

The patchset is applied. Thanks for your efforts! It's appreciated.

comment:11 Changed 3 years ago by simonsouth

Great, thank you!

comment:12 Changed 3 years ago by korli

Resolution: fixed
Status: assignedclosed

comment:13 Changed 3 years ago by jessicah

FYI, the change to the -shared flag being passed onto ld has broken Haiku's TLS support when building gcc4 on Haiku.

As a result of the changes, gcc generates R_386_TLS_TPOFF32 relocations in the configure test for TLS, instead of previously R_386_TLS_DTPMOD32 & R_386_TLS_DTPOFF32. Currently, runtime_loader doesn't support R_386_TLS_TPOFF32 relocations. Due to the failed test, libstdc++.so generates different symbols (e.g. no std::__once_call), which breaks apps that use TLS (WebPositive being one).

Example test:

__thread int a;
int b;
int main() {
  return a = b;
}

My only change to gcc/config/i386/haiku.h: s/%{shared:-shared;/%{!r:-shared;/ which was enough to make TLS support work again, but obviously isn't ideal.

Last edited 3 years ago by pulkomandy (previous) (diff)

comment:14 Changed 3 years ago by simonsouth

If you'd like to open a new ticket, Jessica, assign it to me and I will find a solution for this.

comment:15 in reply to:  14 Changed 3 years ago by jessicah

Replying to simonsouth:

If you'd like to open a new ticket, Jessica, assign it to me and I will find a solution for this.

See #12451.

comment:16 Changed 3 years ago by jessicah

Some commentary from pdziepak on IRC, that you might also find useful:

well, there is more to be done before we can say the we support position dependent executables currently kernel first loads runtime_loader and then runtime_loader loads the executable itself that's unusual order and will have to be changed because we need to guarantee that there is no address conflict between runtime_loader and the executable (well, we can guarantee that on x64 if we limit our support to memory model small, for instance, but the change is needed for 32bit anyway)

Note: See TracTickets for help on using tickets.