C/C++ How to link with ossp-uuid while there is name-conflict with uuid_* functions of libc ?

didier

Member

Reaction score: 12
Messages: 48

I attempt to port swi/prolog to FreeBSD.
All is fine but one thing.
All is in the title.

SWI/Prolog depends on libossp-uuid. It uses for this goal uuid_create().
But libc defines a uuid_create() function too.
Infortunately, uuid_create() from libc is dynamically linked instead of the desired ossp's one.

I tried -nostdlib but libc is linked despite of this directive.

What may I do ?

Thank you a lot for your smart suggestions.

Didier.
 

Jose

Daemon

Reaction score: 1,007
Messages: 1,210

How are you linking ossp-uuid? According to this, the correct way is
Code:
-L/usr/local/lib -lossp-uuid
 

ekvz

Well-Known Member

Reaction score: 278
Messages: 431

I think you can use objcopy --redefine-sym to rename the offending symbols inside the library. Obviously you should create a copy to do that but i have my doubts if this is a good approach at all. I mean why is there a library that collides with libc? That doesn't realy seem to make a lot of sense.
 

mark_j

Daemon

Reaction score: 721
Messages: 1,254

I attempt to port swi/prolog to FreeBSD.
All is fine but one thing.
All is in the title.

SWI/Prolog depends on libossp-uuid. It uses for this goal uuid_create().
But libc defines a uuid_create() function too.
Infortunately, uuid_create() from libc is dynamically linked instead of the desired ossp's one.

I tried -nostdlib but libc is linked despite of this directive.

What may I do ?

Thank you a lot for your smart suggestions.

Didier.
Just change the order on the command line of the library you want the symbol from, the compiler will take the first one it encounters.
 
OP
D

didier

Member

Reaction score: 12
Messages: 48

Just change the order on the command line of the library you want the symbol from, the compiler will take the first one it encounters.
Yes that's my first idea. As it concerns libc, to do so, I'm obliged to add -nostdlib to take control of its position in command line. But as I said, -nostdlib is inhibited while a -lossp-uuid is present (or any other lib dependency).

So, I wonder if I could reorder the pathlist to shared libs in the final elf, making ossp-uuid precedes libc.
 
OP
D

didier

Member

Reaction score: 12
Messages: 48

didier@NomadBSD ~/s/b/p/clib> /usr/bin/cc -nodefaultlibs -Dplugin_uuid_EXPORTS -I/usr/local/include/ossp -I/home/didier/swipl-8.2.1/build_debug/packages/clib -I/home/didier/swipl-8.2.1/src/os -I/home/didier/swipl-8.2.1/src -g -fPIC -Wall -D__SWI_PROLOG__ /home/didier/swipl-8.2.1/packages/clib/uuid.c -g -shared -o uuid.so -Wl,-rpath,/usr/local/lib: -lossp-uuid -L/usr/local/lib/

didier@NomadBSD ~/s/b/p/clib> ldd ./uuid.so
./uuid.so:
libossp-uuid.so.16 => /usr/local/lib/libossp-uuid.so.16 (0x800674000)
libc.so.7 => /lib/libc.so.7 (0x80024a000)
didier@NomadBSD ~/s/b/p/clib> gdb /home/didier/swipl-8.2.1/build_debug/src/swipl

GNU gdb (GDB) 9.2 [GDB v9.2 for FreeBSD]
Reading symbols from /home/didier/swipl-8.2.1/build_debug/src/swipl...
(gdb) r "-p" "foreign=:/home/didier/swipl-8.2.1/build_debug/packages/clib:/home/didier/swipl-8.2.1/build_debug/packages/sgml:/home/didier/swipl-8.2.1/build_debug/packages/http" "-f" "none" "--no-packs" "-s" "/home/didier/swipl-8.2.1/packages/pengines/test_pengines.pl" "-g" "test_pengines" "-t" "halt"
Starting program: /home/didier/swipl-8.2.1/build_debug/src/swipl "-p" "foreign=:/home/didier/swipl-8.2.1/build_debug/packages/clib:/home/didier/swipl-8.2.1/build_debug/packages/sgml:/home/didier/swipl-8.2.1/build_debug/packages/http" "-f" "none" "--no-packs" "-s" "/home/didier/swipl-8.2.1/packages/pengines/test_pengines.pl" "-g" "test_pengines" "-t" "halt"
[New LWP 101221 of process 2050]
% PL-Unit: local_pengines
Thread 1 received signal SIGBUS, Bus error.
0x000000080172f656 in uuid_make () from /usr/local/lib/libossp-uuid.so.16
(gdb) b uuid_create
Breakpoint 1 at 0x8004e3464 (2 locations)
(gdb) c
Continuing.
[LWP 101221 of process 2050 exited]

Program terminated with signal SIGBUS, Bus error.
The program no longer exists.
(gdb) r
Starting program: /home/didier/swipl-8.2.1/build_debug/src/swipl "-p" "foreign=:/home/didier/swipl-8.2.1/build_debug/packages/clib:/home/didier/swipl-8.2.1/build_debug/packages/sgml:/home/didier/swipl-8.2.1/build_debug/packages/http" "-f" "none" "--no-packs" "-s" "/home/didier/swipl-8.2.1/packages/pengines/test_pengines.pl" "-g" "test_pengines" "-t" "halt"
[New LWP 101223 of process 2051]
% PL-Unit: local_pengines
Thread 1 hit Breakpoint 1, 0x00000008004e3464 in uuid_create () from /lib/libc.so.7
(gdb) up
#1 0x0000000801726520 in pl_uuid (UUID=476, options=477)
at /home/didier/swipl-8.2.1/packages/clib/uuid.c:139
139 uuid_create(&uuid);
(gdb) finish
Run till exit from #1 0x0000000801726520 in pl_uuid (UUID=476, options=477)
at /home/didier/swipl-8.2.1/packages/clib/uuid.c:139

Thread 1 received signal SIGBUS, Bus error.
0x000000080172f656 in uuid_make () from /usr/local/lib/libossp-uuid.so.16
(gdb)


I'd tried with -nodefaultlibs too. This is the same result.

As you can see, b uuid_create causes the creation of two breakpoints at different location. One in libossp-uuid and the other in libc.

And when runing, the program stops at libc:uuid_create, the unexpected function with a different parameters count. As the caller expects calling ossp-uuid:uuid_create, it badly cleans up the stack.

As the result, a bus error raises on stack.
 

ekvz

Well-Known Member

Reaction score: 278
Messages: 431

I figure libc might be present because libossp-uuid itself depends on it. Not that this would make any sense to me but if it's true i don't think you'll get around renaming the symbols (or in an ideal world: recompile libossp-uuid with non colliding function names).
 

mark_j

Daemon

Reaction score: 721
Messages: 1,254

didier@NomadBSD ~/s/b/p/clib> /usr/bin/cc -nodefaultlibs -Dplugin_uuid_EXPORTS -I/usr/local/include/ossp -I/home/didier/swipl-8.2.1/build_debug/packages/clib -I/home/didier/swipl-8.2.1/src/os -I/home/didier/swipl-8.2.1/src -g -fPIC -Wall -D__SWI_PROLOG__ /home/didier/swipl-8.2.1/packages/clib/uuid.c -g -shared -o uuid.so -Wl,-rpath,/usr/local/lib: -lossp-uuid -L/usr/local/lib/

didier@NomadBSD ~/s/b/p/clib> ldd ./uuid.so
./uuid.so:
libossp-uuid.so.16 => /usr/local/lib/libossp-uuid.so.16 (0x800674000)
libc.so.7 => /lib/libc.so.7 (0x80024a000)
didier@NomadBSD ~/s/b/p/clib> gdb /home/didier/swipl-8.2.1/build_debug/src/swipl

GNU gdb (GDB) 9.2 [GDB v9.2 for FreeBSD]
Reading symbols from /home/didier/swipl-8.2.1/build_debug/src/swipl...
(gdb) r "-p" "foreign=:/home/didier/swipl-8.2.1/build_debug/packages/clib:/home/didier/swipl-8.2.1/build_debug/packages/sgml:/home/didier/swipl-8.2.1/build_debug/packages/http" "-f" "none" "--no-packs" "-s" "/home/didier/swipl-8.2.1/packages/pengines/test_pengines.pl" "-g" "test_pengines" "-t" "halt"
Starting program: /home/didier/swipl-8.2.1/build_debug/src/swipl "-p" "foreign=:/home/didier/swipl-8.2.1/build_debug/packages/clib:/home/didier/swipl-8.2.1/build_debug/packages/sgml:/home/didier/swipl-8.2.1/build_debug/packages/http" "-f" "none" "--no-packs" "-s" "/home/didier/swipl-8.2.1/packages/pengines/test_pengines.pl" "-g" "test_pengines" "-t" "halt"
[New LWP 101221 of process 2050]
% PL-Unit: local_pengines
Thread 1 received signal SIGBUS, Bus error.
0x000000080172f656 in uuid_make () from /usr/local/lib/libossp-uuid.so.16
(gdb) b uuid_create
Breakpoint 1 at 0x8004e3464 (2 locations)
(gdb) c
Continuing.
[LWP 101221 of process 2050 exited]

Program terminated with signal SIGBUS, Bus error.
The program no longer exists.
(gdb) r
Starting program: /home/didier/swipl-8.2.1/build_debug/src/swipl "-p" "foreign=:/home/didier/swipl-8.2.1/build_debug/packages/clib:/home/didier/swipl-8.2.1/build_debug/packages/sgml:/home/didier/swipl-8.2.1/build_debug/packages/http" "-f" "none" "--no-packs" "-s" "/home/didier/swipl-8.2.1/packages/pengines/test_pengines.pl" "-g" "test_pengines" "-t" "halt"
[New LWP 101223 of process 2051]
% PL-Unit: local_pengines
Thread 1 hit Breakpoint 1, 0x00000008004e3464 in uuid_create () from /lib/libc.so.7
(gdb) up
#1 0x0000000801726520 in pl_uuid (UUID=476, options=477)
at /home/didier/swipl-8.2.1/packages/clib/uuid.c:139
139 uuid_create(&uuid);
(gdb) finish
Run till exit from #1 0x0000000801726520 in pl_uuid (UUID=476, options=477)
at /home/didier/swipl-8.2.1/packages/clib/uuid.c:139

Thread 1 received signal SIGBUS, Bus error.
0x000000080172f656 in uuid_make () from /usr/local/lib/libossp-uuid.so.16
(gdb)


I'd tried with -nodefaultlibs too. This is the same result.

As you can see, b uuid_create causes the creation of two breakpoints at different location. One in libossp-uuid and the other in libc.

And when runing, the program stops at libc:uuid_create, the unexpected function with a different parameters count. As the caller expects calling ossp-uuid:uuid_create, it badly cleans up the stack.

As the result, a bus error raises on stack.
Ok, then you have a few options, none of them pleasant.
1. Build your own library from the source of the libossp, rename it & link to it in your project. Change all your project's references to that. This assumes an open source library.
2. You can use dlopen(3) to open the library & dlsym(3) to access the correct symbol. Then change your project code to access it. This assumes a closed source library.

I don't know your level of expertise, but option 2 is the quickest.
 

memreflect

Well-Known Member

Reaction score: 220
Messages: 257

Since it's causing so much trouble, you can the disable UUID plugin using -DUUID_LIBRARY:FILEPATH=UUID_LIBRARY-NOTFOUND when you invoke cmake. Running the test suite with this setting always resulted in 100% success on my system when I tested it, but I also ran it <10 times.

I don't know anything about Prolog or the software itself, so I can't fathom how crucial misc/ossp-uuid might be. If you feel it's essential, I have created what I hope is a port-friendly patch. Applying it outside of ports is as simple as patch < /path/to/the/patch-file in the source directory. The other files in the gist make up my original hacks.

The test suite is 100% successful usually, but I did encounter occasional failures in pengines:pengines, http:proxy, or http:websocket. When I run those specific tests or even the entire test suite again, the problem disappeared, yet another of those tests might then fail. I have no idea what causes it because of this strange behavior, so I recommend disabling the UUID plugin until you find a better solution, assuming you don't get test failures with it disabled.

Edit: After looking at the test logs, it looks like any test failures with my patch seem to be caused by a common network error: ECONNRESET, a.k.a. "Connection reset by peer". That's why the tests usually pass. At the very least, they never segfault.
 
Top