How do I make the linker and loader choose a shared library at a specific path? - gcc

I wrote a code for which I have a Makefile like this:
CC=gcc
CXX=g++
DEBUG=-g
COMPILER=${CXX}
#INCLUDE= -I Re2/ -I Re2/re2/
#WARN=-Wall
spambin: main.cpp Mail.o trie.o Spambin.o config.o getdns.o
${COMPILER} ${DEBUG} ${WARN} -o spambin main.cpp Mail.o trie.o Spambin.o config.o getdns.o /usr/lib/libre2.so
trie.o: trie.cpp
${COMPILER} ${DEBUG} ${WARN} -c trie.cpp ${INCLUDE}
Mail.o: Mail.cpp
${COMPILER} ${DEBUG} ${WARN} -c Mail.cpp ${INCLUDE}
config.o: config.cpp
${COMPILER} ${DEBUG} ${WARN} -c config.cpp ${INCLUDE}
Spambin.o: Spambin.cpp
${COMPILER} ${DEBUG} ${WARN} -c Spambin.cpp ${INCLUDE}
getdns.o: getdns.c
${CC} ${DEBUG} ${WARN} -c getdns.c ${INCLUDE}
clean:
rm -f *.o
The issue I'm facing is that I want my code to directly pick the /usr/lib/libre2.so.
Doing ldd on the final output binary gives:
linux-gate.so.1 => (0x00693000)
libre2.so.0 => /usr/lib/libre2.so.0 (0x00159000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x004f4000)
libm.so.6 => /lib/libm.so.6 (0x00ce8000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x002b8000)
libc.so.6 => /lib/libc.so.6 (0x00b83000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00d13000)
/lib/ld-linux.so.2 (0x00b64000)
But when I move this file to live servers and do ldd on the binary, the result is:
linux-gate.so.1 => (0x0018b000)
libre2.so.0 => /usr/local/lib/libre2.so.0 (0x00b89000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x0040f000)
libm.so.6 => /lib/libm.so.6 (0x00ad2000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00c5e000)
libc.so.6 => /lib/libc.so.6 (0x0096c000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00ab9000)
/lib/ld-linux.so.2 (0x00949000)
The binary path is /usr/local/lib/libre2.so.0.
Is there any way we can force compiler to pick the .so file from our preferred path?

Yes, there is a way: you can specify full path to the shared library when linking,e.g.:
Let my library is: libtest2.so (it is in /projects/tests/test_so)
Let my main program cpp file is: main.cpp
Then:
g++ main.cpp -o test /projects/tests/test_so/libtest2.so
Produces binary test which has embedded absolute path /projects/tests/test_so in it. No matter where you move the test binary it will always look for /projects/tests/test_so/libtest2.so
Alternatively you may look at -rpath switch that you can use with gcc (actually it is a linker switch),e.g:
gcc -Wl,-rpath,'<path-to-lib-directory>'
But this approach may cause your program to look also for other shared libraries in <path-to-lib-directory> which may not be exactly what you want.

Related

gcc linker resolving symbols

I have been struggling a bit to understand how the gcc linker works and how things are different when linking a shared library with another shared library and when linking a binary with a shared library. I am using Ubuntu 16.04.1 LTS, gcc 5.4.0 and ld 2.26.1.
Following are two sets of a sequence of commands executed on some C source files.
Sequence 1:-
ammal#ubuntu:~/linktest6$ cat a.c
#include <stdio.h>
int a_func() {
printf("Running a_func()\n");
return 0;
}
ammal#ubuntu:~/linktest6$ cat b.c
#include <stdio.h>
int a_func();
int b_func() {
printf("Running b_func()\n");
a_func();
return 0;
}
ammal#ubuntu:~/linktest6$ cat d.c
#include <stdio.h>
int b_func();
int d_func() {
printf("Running d_func()\n");
b_func();
return 0;
}
ammal#ubuntu:~/linktest6$ cat myprog.c
#include <stdio.h>
int d_func();
int main() {
printf("Running myprog_func()\n");
d_func();
return 0;
}
ammal#ubuntu:~/linktest6$ gcc -shared -fPIC -o liba.so a.c
ammal#ubuntu:~/linktest6$ ldd -r liba.so
linux-vdso.so.1 => (0x00007ffc6fded000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1898da3000)
/lib64/ld-linux-x86-64.so.2 (0x0000555e2853c000)
ammal#ubuntu:~/linktest6$ gcc -shared -fPIC -o libb.so b.c
ammal#ubuntu:~/linktest6$ ldd -r libb.so
linux-vdso.so.1 => (0x00007ffd82127000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0cc6253000)
/lib64/ld-linux-x86-64.so.2 (0x00005586e6a36000)
undefined symbol: a_func (./libb.so)
ammal#ubuntu:~/linktest6$ gcc -shared -fPIC -o libd.so d.c
ammal#ubuntu:~/linktest6$ ldd -r libd.so
linux-vdso.so.1 => (0x00007ffc3addb000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f408db59000)
/lib64/ld-linux-x86-64.so.2 (0x0000558720efc000)
undefined symbol: b_func (./libd.so)
ammal#ubuntu:~/linktest6$ gcc -fPIC -o myprog myprog.c -L. -ld -lb -la
ammal#ubuntu:~/linktest6$ ldd -r myprog
linux-vdso.so.1 => (0x00007ffe807aa000)
libd.so => not found
libb.so => not found
liba.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f344acce000)
/lib64/ld-linux-x86-64.so.2 (0x0000563a89eb4000)
undefined symbol: d_func (./myprog)
Sequence 2:-
ammal#ubuntu:~/linktest6$ cat a.c
#include <stdio.h>
int a_func() {
printf("Running a_func()\n");
return 0;
}
ammal#ubuntu:~/linktest6$ cat b.c
#include <stdio.h>
int a_func();
int b_func() {
printf("Running b_func()\n");
a_func();
return 0;
}
ammal#ubuntu:~/linktest6$ cat d.c
#include <stdio.h>
int b_func();
int d_func() {
printf("Running d_func()\n");
b_func();
return 0;
}
ammal#ubuntu:~/linktest6$ cat myprog.c
#include <stdio.h>
int d_func();
int main() {
printf("Running myprog_func()\n");
d_func();
return 0;
}
ammal#ubuntu:~/linktest6$ gcc -shared -fPIC -o liba.so a.c
ammal#ubuntu:~/linktest6$ ldd -r liba.so
linux-vdso.so.1 => (0x00007ffe8c9ee000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f88b91c2000)
/lib64/ld-linux-x86-64.so.2 (0x0000555cf72ef000)
ammal#ubuntu:~/linktest6$ gcc -shared -fPIC -o libb.so b.c
ammal#ubuntu:~/linktest6$ ldd -r libb.so
linux-vdso.so.1 => (0x00007fffbffc4000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f69ea310000)
/lib64/ld-linux-x86-64.so.2 (0x000055996b3e5000)
undefined symbol: a_func (./libb.so)
ammal#ubuntu:~/linktest6$ gcc -shared -fPIC -o libd.so d.c -L. -lb -Wl,-rpath=/home/ammal/linktest6
ammal#ubuntu:~/linktest6$ ldd -r libd.so
linux-vdso.so.1 => (0x00007ffe21bb6000)
libb.so => /home/ammal/linktest6/libb.so (0x00007fca1cdb6000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fca1c9d5000)
/lib64/ld-linux-x86-64.so.2 (0x000055f517b11000)
undefined symbol: a_func (/home/ammal/linktest6/libb.so)
ammal#ubuntu:~/linktest6$ gcc -fPIC -o myprog myprog.c -L. -ld -lb -la
./libb.so: undefined reference to `a_func'
collect2: error: ld returned 1 exit status
My question is, why I am able to successfully compile the binary in the first case and not the second.
In Sequence 2, libd.so is linked to a shared object (namely to libb.so). gcc needs a path to resolve it. Try the following.
$ gcc -fPIC -o myprog myprog.c -L. -ld -lb -la -Wl,-rpath=/home/ammal/linktest6

RTLD_NEXT is not working properly

I reduced my problem using below test codes,
main.cc
#include <iostream>
int main(int argc, const char** argv) {
void init2();
init2();
return 0;
}
2.cc
#include <iostream>
int init2() {
void init1();
init1();
std::cout<<"init2 called\n";
return 0;
}
1.cc
#include <dlfcn.h>
#include <pthread.h>
#include <stdio.h>
#include <iostream>
typedef FILE* (*FopenFunction)(const char* path, const char* mode);
static FopenFunction g_libc_fopen = NULL;
void init1() {
g_libc_fopen = reinterpret_cast<FopenFunction>(
dlsym(RTLD_NEXT, "fopen"));
std::cout<<"init1: fopen addr:"<<(void*)g_libc_fopen<<"\n";
}
__attribute__ ((__visibility__("default")))
FILE* fopen_override(const char* path, const char* mode) __asm__ ("fopen");
__attribute__ ((__visibility__("default")))
FILE* fopen_override(const char* path, const char* mode) {
return g_libc_fopen(path, mode);
}
Compiled 1.cc into a lib1.so and 2.cc into lib2.so like below,
g++ 1.cc -shared -ldl -fvisibility=default -fPIC -o lib1.so -L.
g++ 2.cc -shared -ldl -fvisibility=default -fPIC -o lib2.so -l1 -L.
g++ main.cc -l2 -l1 -L.
Above steps will produce lib1.so, lib2.so and a.out. The problem here is while running the executable a.out, it is unable to lookup the original "fread" symbol when using dlsym(RTLD_NEXT).
The output is,
arunprasadr#demo:~/works/myex/c++/rtdl_next$ LD_LIBRARY_PATH=./ ./a.out
init1: fopen addr:0
init2 called
But if the change the link process of lib2.so(like below), it seems to be working
g++ 2.cc -shared -ldl -fvisibility=default -fPIC -o lib2.so -L.
g++ main.cc -l2 -l1 -L.
LD_LIBRARY_PATH=./ ./a.out
output:
arunprasadr#demo:~/works/myex/c++/rtdl_next$ LD_LIBRARY_PATH=./ ./a.out
init1: fopen addr:0x7f9e84a9e2c0
init2 called
Can anyone please explain what is happening in the background? Thanks in advance.
This is an interesting (and unexpected for me) result.
First, using your original commands, I observe:
LD_DEBUG=symbols,bindings LD_LIBRARY_PATH=./ ./a.out |& grep fopen
10204: symbol=fopen; lookup in file=/lib/x86_64-linux-gnu/libm.so.6 [0]
10204: symbol=fopen; lookup in file=/lib64/ld-linux-x86-64.so.2 [0]
10204: symbol=fopen; lookup in file=/lib/x86_64-linux-gnu/libgcc_s.so.1 [0]
10204: symbol=fopen; lookup in file=/lib/x86_64-linux-gnu/libdl.so.2 [0]
init1: fopen addr:0
Compare this with the with the same output, but removing -l1 from lib2.sos link line:
LD_DEBUG=symbols,bindings LD_LIBRARY_PATH=./ ./a.out |& grep fopen
10314: symbol=fopen; lookup in file=/usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0]
10314: symbol=fopen; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
10314: binding file ./lib1.so [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `fopen'
init1: fopen addr:0x7f03692352c0
The question then is: why isn't the loader searching libc.so.6 for fopen in the first case?
The answer: the loader has a linear list of libraries in the _r_debug.r_map link chain, and for RTLD_NEXT will search libraries after the one that is calling dlopen.
Is the order of libraries different for case 1 and case 2? You bet:
case 1:
LD_LIBRARY_PATH=./ ldd ./a.out
linux-vdso.so.1 => (0x00007fff2f1ff000)
lib2.so => ./lib2.so (0x00007f54a2b12000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f54a27f1000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f54a2430000)
lib1.so => ./lib1.so (0x00007f54a222e000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f54a1f32000)
/lib64/ld-linux-x86-64.so.2 (0x00007f54a2d16000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f54a1d1b000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f54a1b17000)
case 2:
LD_LIBRARY_PATH=./ ldd ./a.out
linux-vdso.so.1 => (0x00007fff39fff000)
lib2.so => ./lib2.so (0x00007f8502329000)
lib1.so => ./lib1.so (0x00007f8502127000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f8501e05000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8501a45000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f8501841000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f8501544000)
/lib64/ld-linux-x86-64.so.2 (0x00007f850252d000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f850132e000)
It should now be clear, that for case 2 libc.so.6 follows lib1.so, but for case 1 it does not.
I do not yet understand what causes this particular ordering though. I'll have to think some more about it.

Using PSPP-Perl-Module on Ubuntu 12.04

I want to use the PSPP-Perl-Module, but it seem to be much harder than expected. I would be fine using any version of the module, but since it seems like one has to build it on every mashine (please correct my if I am wrong) I go for Ubuntu LTS versions:
pspp-0.7.9+git20120319 is the PSPP version in Ubuntu LTS 12.04.
First try: CPAN install
cpan PSPP:Sysfile
Will build a pretty old version
CPAN.pm: Going to build P/PD/PDONELAN/PSPP-Perl-0.7.2.20090730.tar.gz
and asks for a configured source directory which I don't have at the moment.
Enter the location of the build directory of the configured pspp source: []
Second try: apt-get source -b
cd ~
apt-get build-dep pspp
apt-get source -b pspp
Downloads the source of 0.7.9+git20120319 into the current directory and builds it. Building seems to work for quite a while but ends with an error in test phase:
...
| configure:43806: $? = 0
| configure:43806: gcc -std=gnu99 -c -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -Wdeclaration-after-statement -D_FORTIFY_SOURCE=2 -pthread -I/usr/include/cairo -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/pango-1.0 conftest.c >&5
| conftest.c: In function 'main':
| conftest.c:444:22: error: expected expression before ')' token
| configure:43806: $? = 1
| configure: failed program was:
| | /* confdefs.h */
...
| This file was extended by GNU PSPP config.status 0.7.9, which was
| generated by GNU Autoconf 2.68. Invocation command line was
|
| CONFIG_FILES =
| CONFIG_HEADERS =
| CONFIG_LINKS =
| CONFIG_COMMANDS =
| $ ./config.status config.h
|
| on agnes
|
| config.status:2635: creating config.h
make[1]: *** [override_dh_auto_test] Fehler 1
make[1]: Verlasse Verzeichnis '/root/pspp-0.7.9+git20120319'
make: *** [build] Fehler 2
dpkg-buildpackage: Fehler: Fehler-Exitstatus von debian/rules build war 2
Build-Befehl »cd pspp-0.7.9+git20120319 && dpkg-buildpackage -b -uc« fehlgeschlagen.
E: Kindprozess fehlgeschlagen
The PSPP users mailinglist discussed some problems building the Perl-Module this January, and I quote:
Basically you are right, you will need to compile PSPP first, but you don't need
to install it. At a risk of contradicting that sentence, you should follow the
instructions in the file called INSTALL. However, to save yourself a bit of
time and from having to install lots of things you won't need, you can pass
various --without-* flags to configure, thus:
./configure --without-gui --without-cairo --without-libncurses
make
cd perl-module
make install
So with my unfinished build I entered the perl-module directory
cd pspp-0.7.9+git20120319/perl-module
make install
Files found in blib/arch: installing files in blib/lib into architecture dependent library tree
Installing /usr/lib/perl/5.14.2/auto/PSPP/PSPP.so
Installing /usr/lib/perl/5.14.2/auto/PSPP/PSPP.bs
Installing /usr/lib/perl/5.14.2/PSPP.pm
Installing /usr/man/man3/PSPP.3pm
Installing /usr/man/man3/PSPP::Examples.3pm
Appending installation info to /usr/lib/perl/5.14.2/perllocal.pod
Long story short: Still no success using the perl-module:
#!/usr/bin/perl
use PSPP;
Can't load '/usr/local/lib/perl/5.14.2/auto/PSPP/PSPP.so' for module PSPP: libpspp-core-0.7.9.so: Kann die Shared-Object-Datei nicht öffnen: Datei oder Verzeichnis nicht gefunden at /usr/share/perl/5.14/XSLoader.pm line 71.
at /usr/local/lib/perl/5.14.2/PSPP.pm line 26
BEGIN failed--compilation aborted at /usr/local/lib/perl/5.14.2/PSPP.pm line 27.
Compilation failed in require at ./test2.pl line 2.
BEGIN failed--compilation aborted at ./test2.pl line 2.
:-(
The file PSPP.so in question exists:
ls /usr/local/lib/perl/5.14.2/auto/PSPP
libpspp-0.7.9.so libpspp-core-0.7.9.so libpspp-core.so libpspp.so PSPP.bs PSPP.so
This is where I am stuck. Any hints on any approaches are very very welcome. My understanding is, that CPAN has an uploaded old version 0.7.2 of the PSPP-Module, but that the PSPP-Module is actually part of the main PSPP source. Why is the module not automatically installed on by mashine as part of apt-get install pspp. Is it? Am I too stupid to find/use it?
Many thanks in advance, Steve
Thanks to an answer on PSPP's friendy mailinglist, I found a solution:
ldd /usr/local/lib/perl/5.14.2/auto/PSPP/PSPP.so
linux-vdso.so.1 => (0x00007fffe23d2000)
libpspp-core-0.7.9.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7b66a35000)
/lib64/ld-linux-x86-64.so.2 (0x00007f7b6702c000)
Then I created a file
echo '/usr/local/lib/perl/5.14.2/auto/PSPP' > /etc/ld.so.conf.d/pspp.conf
ldconfig
And now it looks better!
ldd /usr/local/lib/perl/5.14.2/auto/PSPP/PSPP.so
linux-vdso.so.1 => (0x00007fff1a5ff000)
libpspp-core-0.7.9.so =>
/usr/local/lib/perl/5.14.2/auto/PSPP/libpspp-core-0.7.9.so
(0x00007f4daf913000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4daf554000)
libxml2.so.2 => /usr/lib/x86_64-linux-gnu/libxml2.so.2
(0x00007f4daf1f8000)
libpq.so.5 => /usr/lib/libpq.so.5 (0x00007f4daefcb000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f4daedb4000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f4daeab7000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4dafe06000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f4dae8b3000)
libssl.so.0.9.8 => /lib/x86_64-linux-gnu/libssl.so.0.9.8
(0x00007f4dae660000)
libcrypto.so.0.9.8 => /lib/x86_64-linux-gnu/libcrypto.so.0.9.8
(0x00007f4dae2d2000)
libkrb5.so.3 => /usr/lib/x86_64-linux-gnu/libkrb5.so.3
(0x00007f4dae004000)
libcom_err.so.2 => /lib/x86_64-linux-gnu/libcom_err.so.2
(0x00007f4dade00000)
libgssapi_krb5.so.2 =>
/usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2 (0x00007f4dadbc1000)
libldap_r-2.4.so.2 =>
/usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2 (0x00007f4dad972000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0
(0x00007f4dad755000)
libk5crypto.so.3 => /usr/lib/x86_64-linux-gnu/libk5crypto.so.3
(0x00007f4dad52c000)
libkrb5support.so.0 =>
/usr/lib/x86_64-linux-gnu/libkrb5support.so.0 (0x00007f4dad324000)
libkeyutils.so.1 => /lib/x86_64-linux-gnu/libkeyutils.so.1
(0x00007f4dad120000)
libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2
(0x00007f4dacf03000)
liblber-2.4.so.2 => /usr/lib/x86_64-linux-gnu/liblber-2.4.so.2
(0x00007f4daccf5000)
libsasl2.so.2 => /usr/lib/x86_64-linux-gnu/libsasl2.so.2
(0x00007f4dacada000)
libgssapi.so.3 => /usr/lib/x86_64-linux-gnu/libgssapi.so.3
(0x00007f4dac89b000)
libgnutls.so.26 => /usr/lib/x86_64-linux-gnu/libgnutls.so.26
(0x00007f4dac5df000)
libgcrypt.so.11 => /lib/x86_64-linux-gnu/libgcrypt.so.11
(0x00007f4dac361000)
libheimntlm.so.0 => /usr/lib/x86_64-linux-gnu/libheimntlm.so.0
(0x00007f4dac159000)
libkrb5.so.26 => /usr/lib/x86_64-linux-gnu/libkrb5.so.26
(0x00007f4dabed3000)
libasn1.so.8 => /usr/lib/x86_64-linux-gnu/libasn1.so.8
(0x00007f4dabc33000)
libhcrypto.so.4 => /usr/lib/x86_64-linux-gnu/libhcrypto.so.4
(0x00007f4dab9fe000)
libroken.so.18 => /usr/lib/x86_64-linux-gnu/libroken.so.18
(0x00007f4dab7e9000)
libtasn1.so.3 => /usr/lib/x86_64-linux-gnu/libtasn1.so.3
(0x00007f4dab5d8000)
libp11-kit.so.0 => /usr/lib/x86_64-linux-gnu/libp11-kit.so.0
(0x00007f4dab3c5000)
libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0
(0x00007f4dab1c1000)
libwind.so.0 => /usr/lib/x86_64-linux-gnu/libwind.so.0
(0x00007f4daaf98000)
libheimbase.so.1 => /usr/lib/x86_64-linux-gnu/libheimbase.so.1
(0x00007f4daad88000)
libhx509.so.5 => /usr/lib/x86_64-linux-gnu/libhx509.so.5
(0x00007f4daab3e000)
libsqlite3.so.0 => /usr/lib/x86_64-linux-gnu/libsqlite3.so.0
(0x00007f4daa89b000)
libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1
(0x00007f4daa661000)
I can now run the example Perl code that uses the PSPP native libs.

Missing a library in ldd after using gcc -l

I'm compiling an executable called "interrogate" with:
g++ -o built/bin/interrogate -Lbuilt/lib -Lbuilt/tmp -L/usr/X11R6/lib \
built/tmp/interrogate_composite1.o built/tmp/interrogate_composite2.o \
-lp3cppParser -lp3dtool -lp3dtoolconfig -lp3pystub -pthread -ldl
After the compilation, when i try to execute the executable:
$ LD_LIBRARY_PATH=built/lib built/bin/interrogate
built/bin/interrogate: symbol lookup error: built/lib/libp3dtool.so.1.8: undefined symbol: _Py_NoneStruct
This symbol is provided by the libp3pystub.so, but the interrogate executable doesn't have any reference to this library (I did used the -lp3pystub):
$ LD_LIBRARY_PATH=built/lib ldd built/bin/interrogate
linux-vdso.so.1 => (0x00007fff2016a000)
libp3dtool.so.1.8 => built/lib/libp3dtool.so.1.8 (0x00007f498d57a000)
libp3dtoolconfig.so.1.8 => built/lib/libp3dtoolconfig.so.1.8 (0x00007f498d51b000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f498d1f2000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f498cfdc000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f498cdbf000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f498c9ff000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f498c7fb000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f498c4ff000)
/lib64/ld-linux-x86-64.so.2 (0x00007f498d5bc000)
If i manually load the libp3pystub.so, the executable works:
$ LD_PRELOAD=built/lib/libp3pystub.so LD_LIBRARY_PATH=built/lib built/bin/interrogate
Usage:
interrogate [opts] file.C [file.C ...]
interrogate -h
My question is: why the library i've added with -lp3pystub is not referenced by the interrogate executable?
I actually find the answer myself. I was compiling on Ubuntu, and they added a default optimization flags: -Wl,--as-needed. This optimization check if no symbol from the libraries passed with -l are used in the main executable, they will be removed.
And that's where my error was: _Py_NoneStruct is not directly used by interrogate, but by another shared library. So i must manually specify that the p3pystub is needed.
One possible fix would be:
$ g++ -o built/bin/interrogate -Lbuilt/lib -Lbuilt/tmp -L/usr/X11R6/lib \
built/tmp/interrogate_composite1.o built/tmp/interrogate_composite2.o \
-Wl,--no-as-needed -lp3cppParser -lp3dtool -lp3dtoolconfig -lp3pystub \
-pthread -ldl
And then i correctly got the library in the ldd output:
$ LD_LIBRARY_PATH=built/lib ldd built/bin/interrogate
linux-vdso.so.1 => (0x00007fff0edff000)
libp3dtool.so.1.8 => built/lib/libp3dtool.so.1.8 (0x00007fa1c36be000)
libp3dtoolconfig.so.1.8 => built/lib/libp3dtoolconfig.so.1.8 (0x00007fa1c365f000)
>>> libp3pystub.so.1.8 => built/lib/libp3pystub.so.1.8 (0x00007fa1c3658000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa1c342f000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fa1c312c000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa1c2e2f000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fa1c2c19000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa1c29fc000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa1c263c000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa1c3700000)
Reference:
https://wiki.ubuntu.com/NattyNarwhal/ToolchainTransition

How to retrieve lib directory?

How can I use bash to retrieve lib directory? For example: /usr/lib or /usr/lib64?
Edit
I'm packaging an RPM which copies some files to %{_libdir}. So I'd like to know the path to lib directory… I can use if [ -f "path-to-my-file" ]; then ... but I wonder if there is a command line?
ldd - print shared library dependencies
$ ldd /bin/ls
linux-vdso.so.1 => (0x00007fffbeecc000)
libselinux.so.1 => /lib/libselinux.so.1 (0x00007fa9aa630000)
librt.so.1 => /lib/librt.so.1 (0x00007fa9aa428000)
libacl.so.1 => /lib/libacl.so.1 (0x00007fa9aa220000)
libc.so.6 => /lib/libc.so.6 (0x00007fa9a9ebe000)
libdl.so.2 => /lib/libdl.so.2 (0x00007fa9a9cba000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa9aa868000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00007fa9a9a9d000)
libattr.so.1 => /lib/libattr.so.1 (0x00007fa9a9899000)
cat /etc/ld.so.conf /etc/ld.so.conf.d/*
Will show you where the linker looks for libraries by default.

Resources