Solved

How do I prevent hard coded library path dependencies in my executables created with gcc ?

Posted on 2004-04-22
9
1,549 Views
Last Modified: 2012-05-04
My make file links the executable with shared libraries.  I have set the library search path with the "-L..\lib\x86_64".  The resultant executable then has hard coded dependency to ..\lib\x86_64 which I do not want.  When program loads, I want LD_LIBRARY_PATH to determine which shared library to link with - I do not want it hard coded.

Below is my make file for tgoctest executable.  Along with a "strings" output which proves that the executable is hard wired to a specific path.

PROJ = tgoctest
CC = gcc
LINK = gcc
SHELL=/bin/sh

#default configuation - this should be speciifed when using this makefile
CONFIG=DEBUG
#default platform - this should be specified when using this makefile
TGPLATFORM:=$(shell arch)

OBJDIR=./$(TGPLATFORM)
LIBS_EXT = -lpthread -lncurses
CFLAGSDEBUG = -g  -D "_DEBUG" -D "UNIX" -D "LINUX" -I ../include
LFLAGSDEBUG = -g -L../lib/$(TGPLATFORM) -ltgoc -ltgjpeg
CFLAGSRELEASE = -O -D "UNIX" -D "LINUX" -I ../include
LFLAGSRELEASE = -L../lib/$(TGPLATFORM) -ltgoc -ltgjpeg

TGOCTEST_DEP = ../include/tgocosdp.h \
        ../include/tgocache.h

all:    checkconfig $(OBJDIR)/$(PROJ)


checkconfig:
        @if [[ ! -d $(OBJDIR) ]]; then \
                mkdir $(OBJDIR); \
        fi

copy:
"tgoctestlinux.mak" 50L, 1116C                      


tyohe@suse64:/yam/tg/source/tgoctest> strings x86_64/tgoctest | grep lib
/lib64/ld-linux-x86-64.so.2
../lib/x86_64/libtgoc.a
../lib/x86_64/libtgjpeg.a
libpthread.so.0
libncurses.so.5
libc.so.6
__libc_start_main
Zlib Compile Flags =0x%x
Set Zlib compression level
tyohe@suse64:/yam/tg/source/tgoctest>
0
Comment
Question by:tomatoyohe
  • 5
  • 4
9 Comments
 
LVL 9

Expert Comment

by:Alf666
ID: 10892028
strings is not the right way of testing.

Use ldd.

Using -L does not hardcode library paths. -R has to be used for this. So, it's not a problem of where your libs are at compile time. If they are somewhere in the LD_LIBRARY_PATH at exec time, they will be used.

0
 

Author Comment

by:tomatoyohe
ID: 10892324
Thanks for your insight, however it is not quite on target.  ldd shows where the libraries will be loaded from if you were to execute the program and it uses LD_LIBRARY_PATH to help determine this.  When I try to load the executable, it fails even if LD_LIBRARY_PATH is set to a directory where the shared libraries reside.  The strings command shows that the shared libraries must reside in ..\lib\x8_64 relative to the current directory.

The following illustrates this.

tyohe@suse64:~/test> set | grep LD_LIBRARY_PATH
LD_LIBRARY_PATH=/home/tyohe/test/junk
tyohe@suse64:~/test> ls -l junk
total 404
-rwxr-xr-x  1 tyohe users 176803 2004-04-22 14:36 libtgjpeg.a
-rwxr-xr-x  1 tyohe users 230689 2004-04-22 14:36 libtgoc.a
tyohe@suse64:~/test> ls -l
total 200
drwxr-xr-x  2 tyohe users    112 2004-04-22 14:37 junk
-rwxr-xr-x  1 tyohe users 203259 2004-04-22 14:36 tgoctest
tyohe@suse64:~/test> ./tgoctest
./tgoctest: error while loading shared libraries: ../lib/x86_64/libtgoc.a: cannot open shared object file: No such file or directory
tyohe@suse64:~/test> pwd
/home/tyohe/test
tyohe@suse64:~/test>

Previous investigation led me to this article
http://sources.redhat.com/ml/binutils/2003-08/msg00345.html
 which indicates that ldd does not show hardcoded references - only what would be chosen by dynamic linker.
0
 
LVL 9

Expert Comment

by:Alf666
ID: 10892669
Oh no !!!

This is totally normal. The libraries you have here are "static libraries". I did not notice it in the first place.

in fact, a ".a" file is an archive file that contains ".o" files.

If you want to link with shared libraries, you have to use the following :

gcc -shared -Xlinker -x -o mylib.so myobj1.o myobj1.o

Then, link against these.

And, I'm sorry, but ldd is completely on topic. It will show you what will actually be used by the dynamic loader. So, it allows you to see that the libraries are correctly loaded.

A short example :

serval:/tmp # cat test.c
doit() {
  printf("test\n") ;
}

serval:/tmp # cat test2.c
extern doit() ;

main() {

  doit() ;

}

serval:/tmp # gcc -c test.c
serval:/tmp # gcc -shared -Xlinker -x -o libtest.so test.o
serval:/tmp # gcc test2.c -o test2 -L/tmp -ltest

serval:/tmp # ls -al test*
-rw-r--r--    1 root     root           32 Apr 22 21:15 test.c
-rw-r--r--    1 root     root          760 Apr 22 21:22 test.o
-rwxr-xr-x    1 root     root         8466 Apr 22 21:22 test2
-rw-r--r--    1 root     root           41 Apr 22 21:16 test2.c

serval:/tmp # mkdir foo
serval:/tmp # cd foo/
serval:/tmp/foo # ldd ../test2
        libtest.so => not found
        libc.so.6 => /lib/i686/libc.so.6 (0x40032000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

serval:/tmp/foo # export LD_LIBRARY_PATH=/tmp
serval:/tmp/foo # ldd ../test2
        libtest.so => /tmp/libtest.so (0x4001a000)
        libc.so.6 => /lib/i686/libc.so.6 (0x40034000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

serval:/tmp/foo # ../test2
test


See ?
0
 
LVL 9

Expert Comment

by:Alf666
ID: 10892684
Oh. And, yes. ldd only shows what's used.
But you don't care about static references if your dynamic linker is able to find the libraries where you want them to be.
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 9

Expert Comment

by:Alf666
ID: 10892752
Sorry. One more.

Works on Linux, but not on all systems.

serval:/tmp # unset LD_LIBRARY_PATH
serval:/tmp # gcc test2.c -o test2 -Wl,-rpath,/tmp -L/tmp -ltest
serval:/tmp # cd foo/
serval:/tmp/foo # ldd ../test2
        libtest.so => /tmp/libtest.so (0x4001a000)
        libc.so.6 => /lib/i686/libc.so.6 (0x40034000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

Some systems (like Solaris) use the '-R' option to the compiler.

These differences is the reason why most big projects make use of libtool. libtool standardizes the calls to the compiler/linker and adapt to the actual system's options.
0
 

Author Comment

by:tomatoyohe
ID: 10892860
As far as I know, libtgoc.a is not a static library but a shared library.  When I built it, I thought I specified it to be shared.  Here is pertinent part of the make file:

PROJ = libtgoc.a

CC = gcc
LINK = gcc
SHELL=/bin/sh

#default configuation - this should be speciifed when using this makefile
CONFIG=RELEASE
#default platform - this should be specified when using this makefile
TGPLATFORM:=$(shell arch)

OBJDIR=./$(TGPLATFORM)


CFLAGSDEBUG = -g -fPIC -D "_DEBUG" -D "UNIX" -D "LINUX" -I ../include
LFLAGSDEBUG = -shared -fPIC -Wl,-Bsymbolic -ldl

CFLAGSRELEASE = -fPIC -O3 -D "UNIX" -D "LINUX" -I ../include
LFLAGSRELEASE = -shared -fPIC -Wl,-Bsymbolic -ldl

LIBS_EXT =  -l m -l c -l pthread
0
 

Author Comment

by:tomatoyohe
ID: 10892931
Furthermore, objdump utility indicates that the library is dynamic (not static).

tyohe@suse64:~/test/junk> objdump -f libtgoc.a

libtgoc.a:     file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x0000000000007470
0
 
LVL 9

Accepted Solution

by:
Alf666 earned 250 total points
ID: 10893848
Ok. Just a naming convention problem then. It should be named .so and not .a. (I'm not sure if it makes a difference, but you might want to try).

Can you show me the output of ldd on tgoctest ?
0
 

Author Comment

by:tomatoyohe
ID: 10894064
Well after simply renaming the ".a" files to ".so" files the hard coded paths are now removed from the executable!  Thank you.

tyohe@suse64:/yam/tg/source/tgoctest> strings x86_64/tgoctest | grep lib
/lib64/ld-linux-x86-64.so.2
libtgoc.so
libtgjpeg.so
libpthread.so.0
libncurses.so.5
libc.so.6
__libc_start_main
../lib/x86_64
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Have you ever been frustrated by having to click seven times in order to retrieve a small bit of information from the web, always the same seven clicks, scrolling down and down until you reach your target? When you know the benefits of the command l…
The purpose of this article is to demonstrate how we can upgrade Python from version 2.7.6 to Python 2.7.10 on the Linux Mint operating system. I am using an Oracle Virtual Box where I have installed Linux Mint operating system version 17.2. Once yo…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now