gcc(4.5.3) + ld(2.21.1) with -fno-common option reports link error with multiple definition not only global variable but also function

Issue #341 open
Takehiko NOZAKI repo owner created an issue

Generally RTLD shouldn’t depends on libc’s function because there’s no libc function are loaded on memory until RTLD itself do.

our RTLD implementation(=ld.elf_so) uses some libc’s function(such as mem* and str*), it is safe because not dynamic link by -lc but static link by -lc_pic(PIC archive).

but there’s different between ld.elf_so and libc_pic.a of exit(3) function, prior don’t call __cxa_finalize set by__attribute__((destructor)) but latter do it, these two version’s difference comes from ifdef _LIBC.

void (*__cleanup)(void);

void
exit(int status)
{

#ifdef _LIBC
        __cxa_finalize(NULL);
#endif
        if (__cleanup)
                (*__cleanup)();
        _exit(status);
}

so ld_elf.so has own version of exit.o and -lc_pic(exit.pico) shold be ignored it.

but this two version of exit(3) cause conflict by COPTS+=-fcommon.

gcc   -symbolic  -shared -nostartfiles -nodefaultlibs -Wl,-static -Wl,--warn-shared-textrel -Wl,-e,.rtld_start -o ld.elf_so rtld_start.o mdreloc.o rtld.o reloc.o symbol.o xmalloc.o xprintf.o debug.o map_object.o load.o search.o headers.o paths.o expand.o tls.o symver.o stack_protector.o exit.o -L/usr/src/lib/libc -L/usr/lib -lc_pic
/usr/src/lib/libc/libc_pic.a(exit.pico): In function `exit':
/usr/src/lib/libc/stdlib/exit.c:55: multiple definition of `exit'
exit.o:exit.c:(.text+0x0): first defined here
*** Error code 1

Stop.

Comments (7)

  1. Takehiko NOZAKI reporter

    this is a false alarm caused by __cleanup is a tentative definition without storage class and initializer(see 6.9.2).

    if -fcommon option is set, tentative definition may places common block and all tentative definition has same name in common block are assembled to single global variable when link time.

    on the other hand -fno-common, tentative definition promoted to external linkage per compile unit, so throw link time error with multiple definition.

    but this case, ld(1) should do link ld.elf_so’s exit.o and should completely ignore libc_pic.a’s exit.pico. this is a bug of gcc/binutils. this case is never been conflict between multiple definitions.

    to fix this problem:

    1. rename ld.elf_so’s exit(3) to another name (rtld_exit and so on). we already have rtld_die() function
    2. cheating ld, set __cleanup as tentiative definition on common block by setting __attribute__((__common__)) or COPTS.exit.c+=-fcommon
    3. cheating ld, set option “-z muldefs” and ignore the error
    4. upgrade latest gcc/binutils, there’s no problems on N HEAD(gcc10.4.0/binutils2.39)

  2. Takehiko NOZAKI reporter

    BUGFIX: Issue #341 - gcc(4.5.3) + ld(2.21.1) with -fno-common option reports link error with multiple definition not only global variable but also function add linker option -Wl,-r,muldefs until we upgrade base gcc/binutils

    → <<cset 29b47a7df9b9>>

  3. Takehiko NOZAKI reporter
    • changed status to open

    reopen, to avoid conflict crunchgen(1) by -Wl,-z,muldefs make binary huge size(or libhack.o is not working?)

  4. Log in to comment