21
int main(int argc, char **argv)
{
    return 0;
}

I cross compile (host= linux x86_64, target= linux aarch64)

/path/to/clang --target=aarch64-linux-gnu -v main.cpp -o main -fuse-ld=lld -L./libs -lc -lc_nonshared -Xlinker -Map=a.map

In the -L./libs folder I've put all the dependencies from the target. When I exclude libgcc.a this linker error happens

ld.lld: error: unable to find library -lgcc

I've added the -Map option to get information about the linked static libraries. In the map file I cannot see references to libgcc.a ... but I battle to read the map file. There are plenty of lines with <internal>. Not sure what those are. See a.map at the bottom

Questions

  1. Why is libgcc.a still required for such a simple program? I read 1 and 2 and I looked at 3.
  2. Does
    • (a) the linker require libgcc to do its own linking work, or
    • (b) does the linker use libgcc because my code requires something that is provided for by libgcc
    • I think it's (b), but I just want to be sure.

a.map

     VMA              LMA     Size Align Out     In      Symbol
   10270            10270       1b     1 .interp
   10270            10270       1b     1         <internal>:(.interp)
   10290            10290       a8     8 .dynsym
   10290            10290       a8     8         <internal>:(.dynsym)
   10338            10338        e     2 .gnu.version
   10338            10338        e     2         <internal>:(.gnu.version)
   10348            10348       20     4 .gnu.version_r
   10348            10348       20     4         <internal>:(.gnu.version_r)
   10368            10368       1c     8 .gnu.hash
   10368            10368       1c     8         <internal>:(.gnu.hash)
   10384            10384       87     1 .dynstr
   10384            10384       87     1         <internal>:(.dynstr)
   10410            10410       18     8 .rela.dyn
   10410            10410       18     8         <internal>:(.rela.dyn)
   10428            10428       48     8 .rela.plt
   10428            10428       48     8         <internal>:(.rela.plt)
   10470            10470       20     4 .note.ABI-tag
   10470            10470       20     4         crt1.o:(.note.ABI-tag)
   10470            10470        0     1                 $d
   10490            10490        4     4 .rodata
   10490            10490        4     4         <internal>:(.rodata)
   10494            10494        c     4 .eh_frame_hdr
   10494            10494        c     4         <internal>:(.eh_frame_hdr)
   104a0            104a0        4     4 .eh_frame
   20000            20000      210     8 .text
   20000            20000       48     8         crt1.o:(.text)
   20000            20000        0     1                 $x
   20000            20000        0     1                 _start
   2002c            2002c        0     1                 $d
   20048            20048       14     4         crti.o:(.text)
   20048            20048        0     1                 $x
   20048            20048       14     1                 call_weak_fn
   20060            20060       e0     8         crtbegin.o:(.text)
   20060            20060        0     1                 $x
   20060            20060        0     1                 deregister_tm_clones
   20090            20090        0     1                 $d
   20098            20098        0     1                 $x
   20098            20098        0     1                 register_tm_clones
   200d0            200d0        0     1                 $d
   200d8            200d8        0     1                 $x
   200d8            200d8        0     1                 __do_global_dtors_aux
   20108            20108        0     1                 frame_dummy
   20138            20138        0     1                 $d
   20140            20140       54     4         /tmp/main-762849.o:(.text)
   20140            20140        0     1                 $x.0
   20140            20140       10     1                 do_math(int*)
   20150            20150       44     1                 main
   20194            20194       7c     4         ./libs/libc_nonshared.a(elf-init.oS):(.text)
   20194            20194        0     1                 $x
   20194            20194       78     1                 __libc_csu_init
   2020c            2020c        4     1                 __libc_csu_fini
   20210            20210        0     1         crtend.o:(.text)
   20210            20210        0     1         crtn.o:(.text)
   20210            20210       14     4 .init
   20210            20210        c     4         crti.o:(.init)
   20210            20210        0     1                 $x
   20210            20210        0     1                 _init
   2021c            2021c        8     1         crtn.o:(.init)
   2021c            2021c        0     1                 $x
   20224            20224       10     4 .fini
   20224            20224        8     4         crti.o:(.fini)
   20224            20224        0     1                 $x
   20224            20224        0     1                 _fini
   2022c            2022c        8     1         crtn.o:(.fini)
   2022c            2022c        0     1                 $x
   20240            20240       50    16 .plt
   20240            20240       50    16         <internal>:(.plt)
   30000            30000       10     8 .data
   30000            30000        4     1         crt1.o:(.data)
   30000            30000        0     1                 data_start
   30000            30000        0     1                 __data_start
   30004            30004        0     1         crti.o:(.data)
   30008            30008        8     8         crtbegin.o:(.data)
   30008            30008        0     1                 $d
   30008            30008        0     1                 __dso_handle
   30010            30010        0     1         ./libs/libc_nonshared.a(elf-init.oS):(.data)
   30010            30010        0     1         crtend.o:(.data)
   30010            30010        0     1         crtn.o:(.data)
   30010            30010        0     8 .tm_clone_table
   30010            30010        0     8         crtbegin.o:(.tm_clone_table)
   30010            30010        0     1                 __TMC_LIST__
   30010            30010        0     8         crtend.o:(.tm_clone_table)
   30010            30010        0     1                 __TMC_END__
   30010            30010       30     8 .got.plt
   30010            30010       30     8         <internal>:(.got.plt)
   40000            40000        8     8 .jcr
   40000            40000        0     8         crtbegin.o:(.jcr)
   40000            40000        0     1                 __JCR_LIST__
   40000            40000        8     8         crtend.o:(.jcr)
   40000            40000        0     1                 $d
   40000            40000        0     1                 __JCR_END__
   40008            40008        8     8 .fini_array
   40008            40008        8     8         crtbegin.o:(.fini_array)
   40008            40008        0     1                 $d
   40008            40008        0     1                 __do_global_dtors_aux_fini_array_entry
   40010            40010        8     8 .init_array
   40010            40010        8     8         crtbegin.o:(.init_array)
   40010            40010        0     1                 $d
   40010            40010        0     1                 __frame_dummy_init_array_entry
   40018            40018      180     8 .dynamic
   40018            40018      180     8         <internal>:(.dynamic)
   40198            40198        8     8 .got
   40198            40198        8     8         <internal>:(.got)
   50000            50000        1     1 .bss
   50000            50000        0     1         crt1.o:(.bss)
   50000            50000        0     1         crti.o:(.bss)
   50000            50000        1     1         crtbegin.o:(.bss)
   50000            50000        1     1                 completed.7557
   50000            50000        0     1                 $d
   50001            50001        0     1         ./libs/libc_nonshared.a(elf-init.oS):(.bss)
   50001            50001        0     1         crtend.o:(.bss)
   50001            50001        0     1         crtn.o:(.bss)
       0                0       24     1 .gnu_debuglink
       0                0        c     1         crt1.o:(.gnu_debuglink)
       c                c        c     1         crti.o:(.gnu_debuglink)
      18               18        c     1         crtn.o:(.gnu_debuglink)
       0                0       9d     1 .comment
       0                0       9d     1         <internal>:(.comment)
       0                0      5b8     8 .symtab
       0                0      5b8     8         <internal>:(.symtab)
       0                0      119     1 .shstrtab
       0                0      119     1         <internal>:(.shstrtab)
       0                0      228     1 .strtab
       0                0      228     1         <internal>:(.strtab)
robor
  • 2,969
  • 2
  • 31
  • 48
  • A ref from Bing: https://gcc.gnu.org/gcc-3.0/libgcc.html and https://compiler-rt.llvm.org/ – jw_ Dec 05 '19 at 08:58

3 Answers3

13

Clang does not come with a linker, it relies on ld instead. And ld depends on libgcc.a and/or libgcc.so on your system (regardless this is the LLVM linker ld.lld or GNU ld). This is the reason why you have this error message.

So the answer is actually:

(a) the linker requires libgcc to do its own linking work

A lot more details on this are available here at omniprog.info:

If we want to get rid of GCC and use clang as our default compiler on the system, we may have to make some adjustments on some RPM-based systems. Clang does not provide a linker, but relies on the system's linker, typically ld, to link executables. This is the case even on FreeBSD and Mac OS X systems where Clang is the default compiler. We can see this using the -v option to clang++. Now, ld won't work without the following files:

libgcc.a
libgcc_s.so
[...]

Shlublu
  • 10,917
  • 4
  • 51
  • 70
  • 1
    When I call clang with -v there is a call to ld.lld which I thought is the llvm linker. Does ld.lld still use the GNU ld? – robor Jul 04 '18 at 12:52
  • 1
    If the linker is invoked with `-lgcc`, it must look for libgcc, even if it later notices that none of the objects of libgcc are referenced and thus not linked into the final executable. I assume the developers did not bother to differentiate the call based on the linker being used. – PaulR Jul 04 '18 at 12:59
  • 2
    @robor78 Yes, ld.lld is the LLVM linker. It seems it still uses libgcc even though they don't mention it: https://lld.llvm.org/ - Maybe an issue to report if not done already. – Shlublu Jul 04 '18 at 13:01
  • 7
    libgcc contains system-specific code/information the current llvm contributors don't particularly want to duplicate or keep in sync, but your program often needs. This is sort of intentional, in the sense that it's known and that working on it isn't a priority for any of the developers. If someone were to step up with a functional patch, things might change. – arnt Jul 04 '18 at 13:25
7

You must compile with the option -nodefaultlibs or -nostdlibs.

Here a quote from GCC documentation (clang interface is just the same):

One of the standard libraries bypassed by -nostdlib and -nodefaultlibs is libgcc.a, a library of internal subroutines which GCC uses to overcome shortcomings of particular machines, or special needs for some languages.

You may have to execute c++ static initialization routines and/or use what is provided by the object files crt<x>.o in the lib directory. These files are part of libc and provides executable entry point.

Vladimir Panteleev
  • 24,651
  • 6
  • 70
  • 114
Oliv
  • 17,610
  • 1
  • 29
  • 72
0

Just in case I use Qt and for running apps on Android with Qt versions greater than 5.11, had this problem with the latest Android SDK with NDK-r20c. and after some struggles, finally it worked with NDK-r19c. In latest Qt at time(5.11) compiling with latest Android NDK should be OK as the documentations said. But it didn't work with errors of not finding things related to GCC (Android NDK uses Clang and shouldn't complain about GCC). after digging and not finding answer, I replaced latest Android NDK-r20 with an earlier one NDK-r19 and surprisingly it worked!

  • Can you explain a bit more? – Dieter Meemken Jun 18 '19 at 13:48
  • Sorry for late answer. all I remember is that, in latest Qt at time(5.11) compiling with latest Android NDK should be OK as the documentations said. but it didn't work with errors of not finding things related to GCC. after digging and not finding answer, I replaced latest Android NDK-r20 with an earlier one NDK-r19 and surprisingly it worked! – hameed abbasi Sep 08 '19 at 09:46