4

I am building for arm-eabi (alias for arm-none-eabi) using GCC hosted on OS X and on Debian. The code concerned doesn’t use C++. However, the link fails on Debian with

/opt/gnat-gpl-2015/bin/../lib/gcc/arm-eabi/4.9.3/../../../../arm-eabi/bin/ld: cannot find libstdc++.a
collect2: error: ld returned 1 exit status

This surprises me because the reported link line (with -Wl,-v) doesn’t mention libstdc++ either (see at end).

The Debian build doesn’t have a cross-libstdc++.a, while the OS X build does (I don’t know how that happened; it only contains empty_arm_object.o). If I copy this libstdc++.a to the Debian side, the build works OK; but I would like to understand why it’s needed in the first place.

The link command line (edited for clarity, I hope) is

/opt/gnat-gpl-2015/bin/../lib/gcc/arm-eabi/4.9.3/../../../../arm-eabi/bin/ld                            \
-plugin                                                                                                 \
/opt/gnat-gpl-2015/bin/../libexec/gcc/arm-eabi/4.9.3/liblto_plugin.so                                   \
-plugin-opt=/opt/gnat-gpl-2015/bin/../libexec/gcc/arm-eabi/4.9.3/lto-wrapper                            \
-plugin-opt=-fresolution=/tmp/cctcp4CP.res                                                              \
-EL                                                                                                     \
-X                                                                                                      \
-o                                                                                                      \
/home/simon/cortex-gnat-rts/test-stm32f4//testbed                                                       \
-L/home/simon/cortex-gnat-rts/test-stm32f4/.build/                                                      \
-L/home/simon/cortex-gnat-rts/test-stm32f4/.build/                                                      \
-L/home/simon/cortex-gnat-rts/test-stm32f4/../stm32f429i-disco-rtos/adalib/                             \
-L/opt/gnat-gpl-2015/bin/../lib/gcc/arm-eabi/4.9.3/fpu                                                  \
-L/opt/gnat-gpl-2015/bin/../lib/gcc/arm-eabi/4.9.3/../../../../arm-eabi/lib/fpu                         \
-L/opt/gnat-gpl-2015/bin/../lib/gcc/arm-eabi/4.9.3                                                      \
-L/opt/gnat-gpl-2015/bin/../lib/gcc                                                                     \
-L/opt/gnat-gpl-2015/bin/../lib/gcc/arm-eabi/4.9.3/../../../../arm-eabi/lib                             \
testbed.o                                                                                               \
b__testbed.o                                                                                            \
/home/simon/cortex-gnat-rts/test-stm32f4/.build/last_chance_handler.o                                   \
/home/simon/cortex-gnat-rts/test-stm32f4/.build/memory_streams.o                                        \
/home/simon/cortex-gnat-rts/test-stm32f4/.build/containing.o                                            \
/home/simon/cortex-gnat-rts/test-stm32f4/.build/dispatching.o                                           \
/home/simon/cortex-gnat-rts/test-stm32f4/.build/iteration.o                                             \
/home/simon/cortex-gnat-rts/test-stm32f4/.build/so.o                                                    \
/home/simon/cortex-gnat-rts/test-stm32f4/.build/streams.o                                               \
/home/simon/cortex-gnat-rts/test-stm32f4/.build/strings.o                                               \
/home/simon/cortex-gnat-rts/test-stm32f4/../stm32f429i-disco-rtos//adalib/libgnat.a                     \
/home/simon/cortex-gnat-rts/test-stm32f4/../stm32f429i-disco-rtos//adalib/libbsp-rtos.a                 \
-lgcc                                                                                                   \
-Map /home/simon/cortex-gnat-rts/test-stm32f4/testbed.map                                               \
-T /home/simon/cortex-gnat-rts/test-stm32f4/../stm32f429i-disco-rtos//adalib/stm32f429i-flash.ld
/opt/gnat-gpl-2015/bin/../lib/gcc/arm-eabi/4.9.3/../../../../arm-eabi/bin/ld: cannot find libstdc++.a
collect2: error: ld returned 1 exit status

The end of the linker script contains

/DISCARD/ :
{
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
    libstdc++.a ( * )
}

/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }

and the first is clearly where arm-eabi-ld is finding a reference to libstdc++.a. I’m afraid that these sections were copied blindly from somewhere on the web, and I don’t know what the first is in fact for. Is it “anything from libstdc++.a that you haven’t already allocated”?

Simon Wright
  • 25,108
  • 2
  • 35
  • 62
  • 1
    Can you share the contents of the linker-script? `/home/simon/cortex-gnat-rts/test-stm32f4/../stm32f429i-disco-rtos//adalib/stm32f429i-flash.ld` it may contain some pointers as to how `libstdc++` got linked... – TheCodeArtist Aug 04 '15 at 07:49
  • 1
    Note that any code compiled with `g++` links to `libstdc++` by default. Also if any of the pre-compiled `.o` objects are built using a different toolchain that contains `libstdc++` then there might be references to it. – TheCodeArtist Aug 04 '15 at 10:23
  • I found `libstdc++.a` at the end of the linker script, & have updated the question with the relevant `/DISCARD/` sections. Thanks for the pointer .. but I don’t know whether it’s safe to omit these sections. Will the linker just junk all inputs it doesn’t find a place for under `SECTIONS`? – Simon Wright Aug 04 '15 at 17:40
  • 2
    The special output section name `/DISCARD/` may be used to discard input sections. Any input sections which are assigned to an output section named `/DISCARD/` are not included in the output file. If any of the input object files have references to `libstdc++` then this might be the reason for the linker error. Without more details of the compilation and the code, one reason i can think of for an implicit reference to `libstdc++` would be that one or more input **object-files** or **static-libraries** were compiled using `g++`. – TheCodeArtist Aug 05 '15 at 04:02
  • Another possibility would be a difference in the **order of object files in the list** (between the successful link on OSX and the failing link on Debian.) [**The order of the object files is important**](http://stackoverflow.com/a/9631940/319204). – TheCodeArtist Aug 05 '15 at 06:26
  • The compiler was built without C++ support, and the `libstdc++.a` on OS X came from a previous build that I hadn’t cleared out properly. Clean compiler builds behave the same on both OS X and Debian. I ran `arm-eabi-ld` under GDB, and the error message is posted while trying to read an input BFD from within the `/DISCARD/` section. If I comment out the `libstdc++.a` in the `/DISCARD/` section, the error goes away. – Simon Wright Aug 05 '15 at 07:32
  • What is even more interesting is that if I comment out that whole `/DISCARD/` section, the link fails because it fails to find e.g. `__errno`, which comes from `libc.a`. Looking at my link command line I don’t see `-lc`. So including a library in a `/DISCARD/` section means that it gets read in _and any required symbols are available for the link_!! This is with binutils 2.24. – Simon Wright Aug 05 '15 at 07:37
  • 1
    Hmmm... thats interesting indeed! Is it possible for you to prepare a minimal reproducible *code+makefile+linkerscript* setup that anyone can use to reproduce the error? (...and if you are lucky the above process of stripping away the non-essential bits will resolve the issue and you will get to know the problem yourself.) – TheCodeArtist Aug 05 '15 at 08:39
  • Use [`-nostdlib`, `-nostartfile` and/or `-nodefaultlibs`](https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html). This will at least tell you where you have symbols which may need these libraries. You can link the `-lgcc` for the built-in functions manually. – artless noise Aug 05 '15 at 13:28
  • Thanks for all the help. My problem is resolved, and I’ve posted an answer; I’d be happy to accept another answer... – Simon Wright Aug 05 '15 at 21:49
  • You could up vote any helpful comments; it makes them more obvious to anyone who comes to look at this question. – artless noise Aug 07 '15 at 13:46

1 Answers1

3

The reason that the linker was looking for libstdc++.a was that the library was mentioned in the linker script in a /DISCARD/ section.

It seems odd to include a whole file in a /DISCARD/ section, the purpose of which is to omit some sections of the input. If you don’t want to include the file, leave it out of the link command line!

Investigation revealed that ld has an unexpected behaviour in this case, in that including libc.a in a /DISCARD/ section has a very similar (if not identical) effect to including -lc in the link command line; and the link command line in use in this case ended -nostdlib -lgcc. It should have been -nostdlib -lgcc -lc. This, together with removing the peculiar /DISCARD/ section, resolved the problem.

Simon Wright
  • 25,108
  • 2
  • 35
  • 62