gcc -g -c -fPIC -Wall mod1.c mod2.c mod3.c #create PIC object files
gcc -g -shared -o libfoo.so mod1.o mod2.o mod3.o #create shared library
gcc -g -fPIC -Wall mod1.c mod2.c mod3.c -shared -o libfoo.so #create & compile share library
gcc -g -Wall -Wl,-rpath,/home/mtk/pdir -o prog prog.c libdemo.so
# –rpath : insert library path into the ELF for runtime lookup
gcc -g -Wall -o prog prog.c -Wl,--enable-new-dtags -Wl,-rpath,/home/mtk/pdir/d1 \ -L/home/mtk/pdir/d1 -lx1 #enable DT_RUNPATH in ELF
gcc -Wl,-rpath,'$ORIGIN'/lib
#to locate runtime library based on the application location
gcc -g -shared -Wl,-Bsymbolic -o libfoo.so foo.o
#To let the symbol reference to the symbol in the same library, use -Bsymbolic
# like dlopen's flag = RTLD_DEEPBIND
gcc -Wl,--export-dynamic main.c
gcc -export-dynamic main.c
#Let the library use symbols in the main program:
Runtime Library Lookup inside the ELF file
gcc -g -Wall -Wl,-rpath,/home/mtk/pdir -o prog prog.c libdemo.so
–rpath : insert library path into the ELF for runtime lookup
environment variable:
LD_RUN_PATH # used only if -rpath is NOT specified.
At run time, search for library: (precedence)
DT_RPATH //OLD in ELF
LD_LIBRARY_PATH //env variable
DT_RUNPATH //NEW in ELF
Link Env Variable
LD_PRELOAD=libalt.so ./program
The LD_PRELOAD environment variable controls preloading on a per-process basis.
/etc/ld.so.preload #system wide basis.
LD_PRELOAD >> /etc/ld.so.preload (precedence)
set-user-ID and set-group-ID programs ignore LD_PRELOAD.
LD_DEBUG
# grab RPATH from elf
$ readelf -d ./hello|grep RPATH
0x0000000f (RPATH) Library rpath: [/usr/local/lib/hello/B:/usr/local/lib/hello/A]
***********
The dynamic linker(runtime) looks in these places to find the library: (From book Linkers and Loaders)
If the dynamic segment contains an entry called DT_RPATH, it's a colon-separated list of directories to search for libraries. This entry is added by a command line switch or environment variable to the regular (not dynamic) linker at the time a program is linked. It's mostly used for subsystems like databases that load a collection of programs and supporting libraries into a single directory.
If there's an environment symbol LD_LIBRARY_PATH, it's treated as a colon-separated list of directories in which the linker looks for the library. This lets a developer build a new version of a library, put it in the LD_LIBRARY_PATH and use it with existing linked programs either to test the new library, or equally well to instrument the behavior of the program. (It skips this step if the program is set-uid, for security reasons.)
The linker looks in the library cache file /etc/ld.so.conf which contains a list of library names and paths. If the library name is present, it uses the corresponding path. This is the usual way that most libraries are found. (The file name at the end of the path need not be exactly the same as the library name, see the section on library versions, below.)
If all else fails, it looks in the default directory /usr/lib, and if the library's still not found, displays an error message and exits.
** LIBRARY_PATH is for linking time to search for the library, like -L option for linker!
Read the dlopen(3) man page (e.g. by typing man dlopen in a terminal on your machine):
If filename contains a slash ("/"), then it is interpreted as a (relative or absolute) pathname. Otherwise, the dynamic linker searches for the library as follows (see ld.so(8) for further details):
o (ELF only) If the executable file for the calling program
contains a DT_RPATH tag, and does not contain a DT_RUNPATH tag,
then the directories listed in the DT_RPATH tag are searched.
o If, at the time that the program was started, the environment
variable LD_LIBRARY_PATH was defined to contain a colon-separated
list of directories, then these are searched. (As a security
measure this variable is ignored for set-user-ID and set-group-ID
programs.)
o (ELF only) If the executable file for the calling program
contains a DT_RUNPATH tag, then the directories listed in that
tag are searched.
o The cache file /etc/ld.so.cache (maintained by ldconfig(8)) is
checked to see whether it contains an entry for filename.
o The directories /lib and /usr/lib are searched (in that order).
So you need to call dlopen("./libLibraryName.so", RTLD_NOW)
not just dlopen("libLibraryName.so", RTLD_NOW) which wants your plugin to be in your $LD_LIBRARY_PATH on in /usr/lib/ etc .... - or add . to your LD_LIBRARY_PATH
(don't recommend for security reasons).
Should use and display the result of dlerror when dlopen (or dlsym) fails:
void* dlh = dlopen("./libLibraryName.so", RTLD_NOW); if (!dlh) { fprintf(stderr, "dlopen failed: %s\n", dlerror()); exit(EXIT_FAILURE); };
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.