0

I am trying to link a large project with GCC 4.8.1 from MinGW for a x86 target. I am calling the linker like this

D:\MyGCCPath\gcc -L [LIBPATHS]  -nostdlib -Wl,-Map,D:\PathToMapFile.map,--emit-relocs [OBJECTFILES AND LIBS] -lmsvcrt -lgcc -o D:\PathToMyOutputFile

With this call I get this linker rror:

libgcc.a(__main.o):(.text+0x5a): undefined reference to `atexit'

I tried different msvcr versions (100 and 90), but this was more a desperate attempt, since I am not very familiar with this problem. I am using the correct libraries provided by MinGW. Is there any way I can fix this error?

Toby
  • 3,815
  • 14
  • 51
  • 67

3 Answers3

4

You are linking with -nostdlib, and atexit() is a function from stdlib.h.

According to GCC Link Options:

-nostdlib

Do not use the standard system startup files or libraries when linking. No startup files and only the libraries you specify are passed to the linker, and options specifying linkage of the system libraries, such as -static-libgcc or -shared-libgcc, are ignored.

Community
  • 1
  • 1
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • 1
    But as stated in the Answer to this Question http://stackoverflow.com/questions/6394512/standard-c-library-in-mingw MinGW GCC doesn not build against libc and builds instead against libmsvcrt, which is included in the libraries I pass to the linker. But even if not, MinGW does not provide the libc anyway. – Toby Nov 06 '13 at 13:50
  • 1
    Ok, for the sake of it I got rid of the `-nostdlib` and it works - but can someone explain why this works? (Excuse me if this is a dumb question, but I'm serious with it!) – Toby Nov 06 '13 at 13:54
  • @Toby The answer you quoted says MinGW doesn't build against *glibc*, which is the GNU version of *libc*. They are not the same thing. – Yu Hao Nov 06 '13 at 13:57
  • On MinGW `libmsvcrt` *is* a standard library, so `-nostdlib` removes it. – ams Nov 06 '13 at 13:57
  • 1
    @Yu Hao - Ok but there is still no libc - or in other words - which lib contains what I am missing? Shouldnt it be the libmsvcrt? – Toby Nov 06 '13 at 13:58
  • @Toby *glibc* is the GNU implementation of standard library, on MinGW you are using a different standard C library. They don't contain each other. – Yu Hao Nov 06 '13 at 14:04
  • 1
    @YuHao I get that, but as far as i know the libmsvcrt is the standard c-library for Windows. In my original linker call I add `-lmsvcrt` to the added libraries - this means I actually link it to my program. Since I get the `undefined reference` it means that `lmsvcrt` does **not** contain `atexit`. If I get rid of the `-nostdlib` it works - this means that there is a standard library for mingw gcc which contains `atexit` - I would like to know which one it is since it is not `lmsvcrt`. – Toby Nov 06 '13 at 14:08
  • @Toby Even if you link with `lmsvcrt`, and `msvcrt` contains `atexit`, but with `-nostdlib`, GCC doesn't use (most) standard library, simple as that. – Yu Hao Nov 06 '13 at 14:18
  • 1
    @YuHao Doesn`t `-nostdlib` just mean, that the GCC Linker ignores the implicit link against these libs? Meaning that if I specify a standard library explicity by hand ( as with `-lmsvcrt` ) he still links it, even tho I am using `-nostdlib`? Or did I get this so wrong? – Toby Nov 06 '13 at 14:22
  • @Toby In a way, yes, you specify a library explicitly by hand, GCC will link it. But the library you specified happened to be the standard library, so GCC doesn't use it. If you specify a non-standard library, it will be used. – Yu Hao Nov 06 '13 at 14:32
  • 1
    @YuHao I am asking this now more out of curiosity: This would mean that I can't add one single standard library - if I don't use any flag it will ad all stdlibs and if I use the `-nostdlibs` Flag I can't add any standardlib by hand...? (What I am meaning is to add only ONE of the stdlibs) – Toby Nov 06 '13 at 14:38
  • @Toby My answer is purely based on the documentation as I haven't used MinGW, but isn't `msvcrt` the default standard library MinGW used? – Yu Hao Nov 06 '13 at 14:48
  • 1
    @YuHao Well afaik msvcrt is kinda the windows equivalent to the libc. I just tried to interpret the GCC documentation (http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html) - At the description to `-nostdlib` they advice the user to add ´-lgcc` by hand. This would mean that `-nostdlib` just ignores the **implicit** linkage of the standardlibs - but when I specify them explicitly (like me with `lmsvcrt`) they are still linked, despite the `-nostdlib` - Which would bring me to my initial question - which lib from mingw contains the `atexit` since it's apparently not `msvcrt` – Toby Nov 06 '13 at 14:54
  • @Toby No, `GCC` and `glibc` are not the same thing, they are independent to each other. `-lgcc` adds the support of some internal functions, not the standard library. – Yu Hao Nov 06 '13 at 15:01
  • 1
    According to GCC Documentation `libgcc` is accounted as a standard library Source: http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html `One of the standard libraries bypassed by -nostdlib and -nodefaultlibs is libgcc.a` – Toby Nov 06 '13 at 15:04
  • @Toby Again, does `libgcc` have some internal standard library functions? Yes. Is `libgcc` a full standard C libray? No, it's not `glibc`, see http://gcc.gnu.org/onlinedocs/gccint/Libgcc.html – Yu Hao Nov 06 '13 at 15:11
  • 1
    The `libgcc` was just an example to tell that the option `-nostdlib` **does not** prevent linkage of explicitly added libraries to the linker call. I am not saying that `libgcc` is a full standard C-Library, but it is implicitly linked by the GCC-linker. And it is **not** linked when I use `nostdlib` - **UNLESS** I add it it with an explicit option `-lgcc`. So waht I am trying to say is that EVEN IF I use the `nostdlib` option I still CAN add standard libraries - This leads to the point that EVEN IF I use `nostdlib` I still can add `lmsvcrt` to my link process **which I did** (see next comment – Toby Nov 06 '13 at 15:19
  • 1
    This means that in my example from the question `lmscvrt` will be linked to my program thus meaning that `lmsvcrt` does NOT contain the `atexit`. Which leads back to the question which library from MinGW does contain it? (This is what I wanted to know all along...) – Toby Nov 06 '13 at 15:21
  • @Toby OK, one final comment because this is really too much. The `mscvrt` contains `atexit`. And why is `libgcc` mentioned that is passed `-nostdlib`? Because it's a special one that is taken care of by GCC. End of discussion. Wait and see if another answer is coming because that's all I got. – Yu Hao Nov 06 '13 at 15:27
  • 1
    @YuHao Since I was curious about this "problem" with `-nostdlib` I asked a seperate question here: http://stackoverflow.com/questions/19816382/does-gcc-nostdlib-prevent-explicit-appending-of-standardlibs/19817123?noredirect=1#comment29465373_19817123 So this means `stdlib` just means "it does not add the standardlibs by itself" but it doesn't prevent if I add them by myself - this means, that `atexit` is unlikely part of `lmsvcrt` since I added it manually - or there is something completely different wrong – Toby Nov 06 '13 at 16:48
0

Libraries are checked in the order used on the command line so use -lgcc -lmsvcrt.

Timothy Baldwin
  • 3,551
  • 1
  • 14
  • 23
0

The reasoning in your comment chain with Yu Hao is completely correct.

You need to import libmsvcr120.a with -lmsvcr120 to get the atexit symbol.

You may also need some of these, depending on what symbols you reference, but this is speculation based on very briefly grepping through the source code in clang/lib/Driver/ToolChains for the string OPT_nostdlib:

  • lgcc_eh
  • lgcc_s
  • lgcc
  • lgomp
  • liomp5md
  • lmingw32
  • lmingwex
  • lmingwthrd
  • lmoldname
  • lmsvcr100
  • lmsvcr110
  • lmsvcr80
  • lmsvcr90
  • lmsvcrt-os
  • lomp
  • lssp_nonshared
  • lssp

In general, you can find which libraries contain the symbols you're looking for by calling MinGW's nm.exe (or GNU nm on Linux) on all of the libraries you have (in x86_64-w64-mingw32\lib for example), and piping the output to a text file. You'll get a few hundred thousand lines of text like this that you can search through:

libmsvcr120_defs01591.o:
0000000000000000 b .bss
0000000000000000 d .data
0000000000000000 i .idata$4
0000000000000000 i .idata$5
0000000000000000 i .idata$6
0000000000000000 i .idata$7
0000000000000000 t .text
0000000000000000 I __imp_atexit
                 U _head_lib64_libmsvcr120_def_a
0000000000000000 T atexit

The T atexit (uppercase T) denotes the symbol being exported, with its definition in the .text section.

If you see U atexit, that means "I don't know where atexit is, but it's needed here". If an import library only contains lines with U atexit, then the definition is not in that import library.

You'll notice atexit also defined by libmsvcr120d.a, which is the debug version of libmsvcr120.a, and defined by libmsvcr120_app.a, which is (from what I gather) the version you would link against when distributing an executable on the Windows App Store.

Zaaier
  • 685
  • 8
  • 22