How to print the ld(linker) search path
gcc passes a few extra -L paths to the linker, which you can list with the following command:
gcc -print-search-dirs | sed '/^lib/b 1;d;:1;s,/[^/.][^/]*/\.\./,/,;t 1;s,:[^=]*=,:;,;s,;,; ,g' | tr \; \\012
The answers suggesting to use ld.so.conf and ldconfig are not correct because they refer to the paths searched by the runtime dynamic linker (i.e. whenever a program is executed), which is not the same as the path searched by ld (i.e. whenever a program is linked).
You hit the spot. I have a linking problem, during linking process linker finds manually installed libraries in /usr/local/.. which causes missing library error, and linking fails. I have to rename /usr/local everytime to exclude that search path. Is there a simple way to exclude or override /usr/local path?
You can try to manually specify library paths with the -L option to GCC, which I think (not sure) will override the system library paths. You could also try to set the LIBRARY_PATH env variable before compiling: $ LIBRARY_PATH=/somedir/ gcc .
I know that linking in command line compiling. I meant a global way to override ld s search path. For example sometimes I have to compile a source code from makefile or generating makefile from configure script or from CMakeLists.txt or even more complicated ones such as vala or srt . It’s hard for me to modify ld search path in such cases
When using CMake you can select the exact libraries which are used during the configuration phase (some of these entries are shown only in advanced mode). As for configure scripts from Autotools, see this answer: stackoverflow.com/questions/7561509/…. This doesn’t answer your question directly, but may help you do what you want.
Ah, now this explains why building with local libraries is so broken in Centos. Includes path searches are /usr/local/include then /usr/include , while linker search is /usr/lib64 then /usr/local/lib64
On Linux, you can use ldconfig , which maintains the ld.so configuration and cache, to print out the directories search by ld.so with
ldconfig -v 2>/dev/null | grep -v ^$'\t'
ldconfig -v prints out the directories search by the linker (without a leading tab) and the shared libraries found in those directories (with a leading tab); the grep gets the directories. On my machine, this line prints out
/usr/lib64/atlas: /usr/lib/llvm: /usr/lib64/llvm: /usr/lib64/mysql: /usr/lib64/nvidia: /usr/lib64/tracker-0.12: /usr/lib/wine: /usr/lib64/wine: /usr/lib64/xulrunner-2: /lib: /lib64: /usr/lib: /usr/lib64: /usr/lib64/nvidia/tls: (hwcap: 0x8000000000000000) /lib/i686: (hwcap: 0x0008000000000000) /lib64/tls: (hwcap: 0x8000000000000000) /usr/lib/sse2: (hwcap: 0x0000000004000000) /usr/lib64/tls: (hwcap: 0x8000000000000000) /usr/lib64/sse2: (hwcap: 0x0000000004000000)
The first paths, without hwcap in the line, are either built-in or read from /etc/ld.so.conf. The linker can then search additional directories under the basic library search path, with names like sse2 corresponding to additional CPU capabilities. These paths, with hwcap in the line, can contain additional libraries tailored for these CPU capabilities.
One final note: using -p instead of -v above searches the ld.so cache instead.
How can I find the full file path given a library name like libfoo.so.1?
Without implementing a linker or using ldd , how can I find the full path to a library? Is there a standard library available for that on Linux? (POSIX maybe?) Using ldd and grep on a file that is knowingly using libGL.so.1 , it looks like:
$ ldd /usr/bin/glxinfo | grep libGL libGL.so.1 => /usr/lib/libGL.so.1 (0x00007f34ff796000)
Given a library name like libGL.so.1 , how can I find the full path /usr/lib/libGL.so.1 ?. Preferably accepting an option for finding 32-bit and 64-bit libraries. If no library does that, does a program exist to do this? Something like find-library-path libGL.so.1 . The locate libGL.so.1 command does not count. I don’t want to actually load the library using dlopen or something if it executes code from that library.
5 Answers 5
Use ldconfig which is the tool that manages link space.
The -p flag lets you browse all available linkable libraries.
Thanks for your answer ,but -p prints cached entries from a file, not the current state (directories in $LD_LIBRARY_PATH are not respected for example)
@Lekensteyn If you want to find the library in any location and not rely on any mechanic that is actually used to manage libraries, find or the locate DB might be your only options. As your questions is stated, looking at the source for the loader might also be an option.
Expanding on Honky Tonk’s answer, the command echo «$(ldconfig -p | grep libGL.so.1 | tr ‘ ‘ ‘\n’ | grep /)» will give you the path alone.
If you don’t mind actually loading the library and using some nonstandard but widely-available functions, calling dladdr on any symbol from the library will return information containing the full pathname that was loaded.
I’ll have a look at the manpage, I also added another requirement to the question: the library should not execute code of the library that is being checked. EDIT: It looks like that dladdr is not going to help me as it needs dlopen first.
Well you can’t (portably) avoid executing global constructors in the library that’s loaded. There might be some non-portable hacks to get back control before the constructors run, using library dependencies and the implementation-specific order in which constructors run to call _exit (doing all of this from a forked child process) from another library’s constructor beforehand, but I think that’s getting into far-fetched hack territory. Ideally dlopen would have a RTLD_NOEXEC flag to prevent any code execution in the library, useful for tasks like yours.
Yeah, that is wishful thinking. There is a RTLD_NOLOAD, but that just returns NULL when the library is not loaded before. I don’t think there is even a solution available that takes 32-bit/64-bit into account (without building a 32-bit and 64-bit program designed to check this, that is).
Well there’s another ugly hack — you could fork a child process and ptrace it, and terminate it on the first mmap system call made. The prior open call should give you the pathname. 🙂 By the way, why do you need to know the pathname? I suspect there’s a better way to do what you’re trying to achieve.
primus intercepts GL calls and splits rendering from accelerating. These libraries do not have to sit in $LD_LIBRARY_PATH , hence I cannot pass libGL.so.1 to the dlopen function in that program and therefore I have to pass the absolute path to the libraries. In a second program, I want to lookup the libraries as stated in the question so I can pass it to the the primus program.
For systems with GNU libc and Python the following is the closest I found. It uses LD_DEBUG (described in the man page of ld.so(8) ).
LD_DEBUG=libs python3 -c "import ctypes; ctypes.CDLL('libssl.so.1.0.0')" 2>&1 | \ grep -A 1000 "initialize program: python" | grep -A 3 "find library"
The output (for libssl.so.1.0.0 ) is the following:
15370: find library=libssl.so.1.0.0 [0]; searching 15370: search cache=/etc/ld.so.cache 15370: trying file=/lib/x86_64-linux-gnu/libssl.so.1.0.0 15370: 15370: find library=libcrypto.so.1.0.0 [0]; searching 15370: search cache=/etc/ld.so.cache 15370: trying file=/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 15370:
I implemented such a script here:
#!/usr/bin/env python3 """ Like `type` but for libs. """ import sys import os from argparse import ArgumentParser from glob import glob def parse_ld_conf_file(fn): paths = [] for l in open(fn).read().splitlines(): l = l.strip() if not l: continue if l.startswith("#"): continue if l.startswith("include "): for sub_fn in glob(l[len("include "):]): paths.extend(parse_ld_conf_file(sub_fn)) continue paths.append(l) return paths def get_ld_paths(): # To be very correct, see man-page of ld.so. # And here: http://unix.stackexchange.com/questions/354295/what-is-the-default-value-of-ld-library-path/354296 # Short version, not specific to an executable, in this order: # - LD_LIBRARY_PATH # - /etc/ld.so.cache (instead we will parse /etc/ld.so.conf) # - /lib, /usr/lib (or maybe /lib64, /usr/lib64) paths = [] if "LD_LIBRARY_PATH" in os.environ: paths.extend(os.environ["LD_LIBRARY_PATH"].split(":")) paths.extend(parse_ld_conf_file("/etc/ld.so.conf")) paths.extend(["/lib", "/usr/lib", "/lib64", "/usr/lib64"]) return paths def main(): arg_parser = ArgumentParser() arg_parser.add_argument("lib") args = arg_parser.parse_args() paths = get_ld_paths() for p in paths: fn = "%s/%s" % (p, args.lib) if os.path.exists(fn): print(fn) return print("Did not found %r in %r." % (args.lib, paths), file=sys.stderr) sys.exit(1) if __name__ == "__main__": main()
Get dynamic library directory in c++ (linux)
Is there any programmatic way to get the location of a dynamic library loaded by a program? I know that it is possible to get the ‘executable’ running path. But it is not enough for me. I’m developing an external library that has some dependencies and I need to point accordingly to its location. For example, the program is running at:
/local/external/libs/faciesAnalysis
"/local/external/libs/facesAnalysis"
3 Answers 3
Since this is specifically Linux, dladdr() is a glibc extension to the dl family of functions that will lookup the filename of any symbol. Pass it the address of any function that you know exists in the library you are looking for, and you’re basically done.
Presented without appropriate error checking:
#define _GNU_SOURCE #include const char *my_fname(void)
First (and this is specific to Linux, since provided by the kernel), you can parse the /proc/self/maps pseudo-file from inside your program. Just read sequentially every line of that textual file, you’ll be able to get the full path of every mmap -ed file, including shared libraries. See proc(5) (and use dirname(3) to get a directory out of a path, perhaps also realpath(3). ). Read also dlopen(3) & ld-linux.so(8) and notice the role of LD_LIBRARY_PATH and /etc/ld.so.conf
Then, and this is specific to GNU libc (but apparently musl-libc also has that), you could use dladdr(3) on some function address from that library. Or just use dl_iterate_phdr(3) which looks exactly fit to your question.
Beware of weird cases: some program might generate a plugin and dlopen it later (my MELT is doing that), some other program might remove a plugin after dlopen , some programs might be statically linked, the dlopen -ed plugin could have been moved or renamed (perhaps because a new version has been installed while your program is running). the same plugin could have been symlinked and dlopened using different paths, etc.
How to find location of installed library
Background: I’m trying to build my program but first I need to set up libraries in NetBeans. My project is using GLU and therefore I installed libglu-dev. I didn’t note the location where the libraries were located and now I can’t find them. I’ve switched to Linux just a few days ago and so far I’m very content with it, however I couldn’t google this one out and became frustrated. Is there way to find out where files of package were installed without running the installation again? I mean if I got library xxx and installed it some time ago, is there some-command xxx that will print this info? I’ve already tried locate, find and whereis commands, but either I’m missing something or I just can’t do it correctly. For libglu, locate returns:
/usr/share/bug/libglu1-mesa /usr/share/bug/libglu1-mesa/control /usr/share/bug/libglu1-mesa/script /usr/share/doc/libglu1-mesa /usr/share/doc/libglu1-mesa/changelog.Debian.gz /usr/share/doc/libglu1-mesa/copyright /usr/share/lintian/overrides/libglu1-mesa /var/lib/dpkg/info/libglu1-mesa:i386.list /var/lib/dpkg/info/libglu1-mesa:i386.md5sums /var/lib/dpkg/info/libglu1-mesa:i386.postinst /var/lib/dpkg/info/libglu1-mesa:i386.postrm /var/lib/dpkg/info/libglu1-mesa:i386.shlibs
The other two commands fail to find anything. Now locate did its job, but I’m sure none of those paths is where the library actually resides (at least everything I was linking so far was in /usr/lib or /usr/local/lib ). libglu was introduced just as example. I’m looking for a general solution for this problem.