Search code examples
malloclinker-errorsglibcrelocationfpic

Can I build only glibc malloc as a shared library?


I want to build glibc malloc as a shared library instead of it being part of libc.so

I'm not using any chroot but directly trying to build it.

When I make glibc as a normal build, it outputs the command that is being used to build malloc namely:

gcc malloc.c -c -std=gnu99 -fgnu89-inline -O2 -Wall -Winline -Wundef -Wwrite-strings -fmerge-all-constants -frounding-math -g -Wstrict-prototypes -fPIC -DMORECORE_CLEARS=2 -I../include -I/home/sharath.g/glibc-2.20/build/malloc -I/home/sharath.g/glibc-2.20/build -I../sysdeps/unix/sysv/linux/x86_64/64 -I../sysdeps/unix/sysv/linux/x86_64 -I../sysdeps/unix/sysv/linux/x86 -I../sysdeps/unix/sysv/linux/wordsize-64 -I../sysdeps/x86_64/nptl -I../sysdeps/unix/sysv/linux -I../sysdeps/nptl -I../sysdeps/pthread -I../sysdeps/gnu -I../sysdeps/unix/inet -I../sysdeps/unix/sysv -I../sysdeps/unix/x86_64 -I../sysdeps/unix -I../sysdeps/posix -I../sysdeps/x86_64/64 -I../sysdeps/x86_64/fpu/multiarch -I../sysdeps/x86_64/fpu -I../sysdeps/x86/fpu -I../sysdeps/x86_64/multiarch -I../sysdeps/x86_64 -I../sysdeps/x86 -I../sysdeps/ieee754/ldbl-96 -I../sysdeps/ieee754/dbl-64/wordsize-64 -I../sysdeps/ieee754/dbl-64 -I../sysdeps/ieee754/flt-32 -I../sysdeps/wordsize-64 -I../sysdeps/ieee754 -I../sysdeps/generic -I.. -I../libio -I. -D_LIBC_REENTRANT -include ../include/libc-symbols.h -DPIC -DSHARED -o /home/sharath.g/glibc-2.20/build/malloc/malloc.o -MD -MP -MF /home/sharath.g/glibc-2.20/build/malloc/malloc.os.dt -MT /home/sharath.g/glibc-2.20/build/malloc/malloc.os

As you can see, malloc is built using -fPIC so I should be able to simply link it as a shared library.

However when I run this command gcc -shared -Wl,-soname,libmalloc.so -shared -lpthread -lm -lrt -o /home/sharath.g/glibc-2.20/build/malloc/libmalloc.so /home/sharath.g/glibc-2.20/build/malloc/malloc.o

I get an error relocation R_X86_64_PC32 against undefined symbol `__libc_multiple_threads' can not be used when making a shared object; recompile with -fPIC

I don't understand why this error shows up? clearly I've compiled malloc.c with -fPIC


Solution

  • I don't understand why this error shows up?

    The symbol is referenced by malloc.o via inline assembly, like so:

    # 69 "../sysdeps/unix/sysv/linux/x86_64/lowlevellock.h"
    #define __lll_trylock_asm "cmpl $0, __libc_multiple_threads(%%rip)\n\t" "je 0f\n\t" "lock; cmpxchgl %2, %1\n\t" "jmp 1f\n\t" "0:\tcmpxchgl %2, %1\n\t" "1:"
    

    As such, it generates R_X86_64_PC32 relocation (normal calls to external routines generate R_X86_64_PLT32 relocations when compiled with -fPIC). This form of assembly assumes that the symbol will be defined in the same ELF image.

    In the normal build, this symbol is defined as a hidden symbol (meaning it's defined inside libc.so.6 and is not exported from it) in nptl/libc_multiple_threads.c.

    Since you are not linking in libc_multiple_threads.o into your libmalloc.so, the symbol remains undefined, and the linker correctly complains: this symbol can't come from outside (wrong relocation for that) and isn't defined inside your libmalloc.so.

    You might think that simply linking in libc_mutiple_threads.os would solve this, but you'll be wrong: your libmalloc.so would behave as if your process is single-threaded, regardless of whether it actually is or not.

    TL;DR: what you are trying to do is unlikely to work, except by accident. It is very likely to be broken in multiple ways, some of which could be quite subtle.