This is the mail archive of the
libc-help@sourceware.org
mailing list for the glibc project.
Re: Gcc 5.4 Compilation failure with -fPIC: undefined reference to `getrpcbynumber'
On 21/07/2016 18:45, Matt wrote:
>> I thinking you are missing the point here: glibc already provides
>> both the shared and library and static library for static case.
> Indeed great ! Thanks for the help.
>
> I work on a project called DCE
> (https://www.nsnam.org/docs/dce/release/1.8/manual/html/intro.html),
> whose goal is to allow to run real software such as iperf/ip/ping
> within the Network Simulation tool "ns3". To do so, DCE creates a
> *fake* libc that overrides some of the calls and keep the native libc
> function otherwise. It loads one *fake* libc per application, and the
> applications are run within a single process (it's a complex program
> IMO).
Function/syscalls interposing is not new (ltrace, strace, etc.).
>
> The project does so in a somewhat hackish manner (using wrapper
> functions towards functoin pointers in a struct that is filled later
> on when it's loaded by the simulator etc...) and I wanted to explore
> alternatives such as static linking the libc calls that are not
> overriden, aka the native calls.
The problem is libc maintains some internal states that are not meant to
have multiple copies in different shared libraries. And if you do get
some shared library linked in a hacking manner you might get issue with
symbol versioning (since now that you are building with -fpic).
> I've written a small file libc.c:
> ==
> extern int printf(const char*, ...);
> int toto()
> {
> printf("holy libc");
> }
> ==
>
> My idea is to have the original printf glibc code linked in my own
> version of libc.so:
> $ gcc -nostdlib -fPIC libc.c -L/home/teto/glibc/f -lc_pic -shared -o mylibc.so
>
> which returns:
> /usr/bin/ld.bfd.real: libc.so: version node not found for symbol
> pthread_cond_wait@@GLIBC_2.3.2
> /usr/bin/ld.bfd.real: failed to set dynamic section sizes: Bad value
>
> I don't understand why "pthread_cond_wait" would be needed at all ? I
> thought that static linking would only copy the required (printf) code
> and its dependancies in mylibc.so
> Maybe I should compile libc with libpthread as an addon:
> https://www.gnu.org/software/hurd/open_issues/libpthread_addon.html
I do not think this is fix this particular issue. The problem is since you are
building with PIC the version information for a lot of function are also being
generated and without a proper version definition input file the linker won't
be able to generate a correct shared version. One option would be to hack
libc to not generate version information with PIC build, but I would advise
against.
Just to take give you an example of what kind of issue you might see, the
'printf' function you are trying to override requires the undefined
'__libc_multiple_threads' symbol for internal locking handling (an x86
optimization to avoid atomic operation for single-thread). It is initialized
as 0 by default (since it is on .bss).
It might work correctly for single-thread programs, however you will get wrong
result as soon you link your override shared library with a thread program.
The GLIBC have some internal logic to update its value in thread creating (in
allocate_stack by updating __libc_multiple_threads_ptr). However, since the
symbol is hidden the program will virtually have two internal states: one for
the linker glibc for the program and one for your shared library. And your
interposed library won't be updated. It won't help if you link against
libpthread.a either, unless you override *all* the pthread symbols that
might update '__libc_multiple_threads'.
>
> Feel free to ignore this question if you deem it too *newbish* but
> having some pointers/help would be great, I am a bit new to linking
> concepts.
>
> Cheers
> Matt
>
> 2016-07-21 22:17 GMT+02:00 Adhemerval Zanella <adhemerval.zanella@linaro.org>:
>>
>>
>> On 21/07/2016 15:40, Matt wrote:
>>> Hi,
>>>
>>> I've been trying various branches (master branch, 2.23 tag) and
>>> various configurations in order to compile libc on ubuntu 16.04 with
>>> gcc-5.real (Ubuntu 5.4.0-6ubuntu1~16.04.1) 5.4.0 20160609 with -fPIC
>>> (I want to create a shared library statically linking some glibc
>>> functions.
>>
>> I thinking you are missing the point here: glibc already provides
>> both the shared and library and static library for static case. Also
>> static linking a shared library with a libc.a is problematic in a sense
>> libc maintains some internal states that might be interfered with the
>> libc shared library.
>>
>> Why exactly do you need the libc functions on the shared library? Why
>> can't you just statically link libc against the program itself?
>>
>>>
>>> I came up with this command:
>>> $ CFLAGS=" -fPIC -O2 -fno-stack-protector -U_FORTIFY_SOURCE "
>>> LD_LIBRARY_PATH="" ../configure --prefix=/home/teto/libcinstall
>>> --disable-shared --enable-static-nss --enable-obsolete-rpc
>>> --disable-werror
>>>
>>> but I keep ending up with:
>>> ===
>>> make[2]: Entering directory '/home/teto/glibc/nss'
>>> gcc -nostdlib -nostartfiles -static -o /home/teto/glibc/d/nss/getent
>>> /home/teto/glibc/d/csu/crt1.o /home/teto/glibc/d/csu/crti.o `gcc
>>> --print-file-name=crtbeginT.o` /home/teto/glibc/d/nss/getent.o
>>> -Wl,--start-group /home/teto/glibc/d/libc.a -lgcc -lgcc_eh
>>> -Wl,--end-group `gcc --print-file-name=crtend.o`
>>> /home/teto/glibc/d/csu/crtn.o
>>> /home/teto/glibc/d/nss/getent.o: In function `rpc_keys':
>>> getent.c:(.text+0xc37): undefined reference to `getrpcbynumber'
>>> getent.c:(.text+0xc64): undefined reference to `getrpcbyname'
>>> getent.c:(.text+0xc93): undefined reference to `setrpcent'
>>> getent.c:(.text+0xca9): undefined reference to `getrpcent'
>>> getent.c:(.text+0xcb3): undefined reference to `endrpcent'
>>> collect2: error: ld returned 1 exit status
>>> ../Rules:147: recipe for target '/home/teto/glibc/d/nss/getent' failed
>>> make[2]: *** [/home/teto/glibc/d/nss/getent] Error 1
>>> ====
>>> is there anything I can do to fix this ?
>>> also if I don't compile first with a simpler command, "libc-modules.h"
>>> doesn't get created, thus stopping the compilation process :/
>>>
>>> Best regards
>>>