Linux shared lib load

Where does Ubuntu look for shared libraries?

When I run a process that links to a shared library at runtime (linked when the process starts, not linked later with dlload() ), where does it look for that shared library ( .so ) file other than LD_LIBRARY_PATH ? Background: I have some C++ code that I wrote that uses a particular third-party library. I have installed the library and compiled my code on two different platforms, both Ubuntu but different versions, and different versions of gcc as well. The library was compiled and installed from source, and is located in /usr/local/lib on both platforms. When I compile my code, I link with the pkg-config —libs parameters for the third-party library and I’ve verified that pkg-config —libs returns the exact same thing on both platforms. My code compiles successfully on both platforms, and LD_LIBRARY_PATH is not defined (or defined as empty: «» ) on both platforms. However, when I run it on one platoform it works fine, and on the other I get this error:

error while loading shared libraries: libthrift-0.9.0.so: cannot open shared object file: No such file or directory 

Funnily enough, the ones that doesn’t work is the newer version of Ubuntu and gcc. :/ So I’m trying to figure out how the working one is able to locate the library, so that I can make the broken one locate the library in the same way. (i.e., without setting LD_LIBRARY_PATH ) Update: Here’s my output from cat /etc/ld.so.conf.d/* . on the working (older) system:

/usr/lib/mesa /usr/lib32/mesa /usr/lib/alsa-lib # libc default configuration /usr/local/lib # Multiarch support /lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu 
# libc default configuration /usr/local/lib # Multiarch support /lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/mesa 

Источник

Understanding Shared Libraries in Linux

In programming, a library is an assortment of pre-compiled pieces of code that can be reused in a program. Libraries simplify life for programmers, in that they provide reusable functions, routines, classes, data structures, and so on (written by another programmer), which they can use in their programs.

For instance, if you are building an application that needs to perform math operations, you don’t have to create a new math function for that, you can simply use existing functions in libraries for that programming language.

Examples of libraries in Linux include libc (the standard C library) or Glibc (GNU version of the standard C library), libcurl (multiprotocol file transfer library), libcrypt (library used for encryption, hashing, and encoding in C), and many more.

Linux supports two classes of libraries, namely:

  • Static libraries – are bound to a program statically at compile time.
  • Dynamic or shared libraries – are loaded when a program is launched and loaded into memory and binding occurs at run time.
Читайте также:  Russian fedora российские дистрибутивы linux

Dynamic or shared libraries can further be categorized into:

  • Dynamically linked libraries – here a program is linked with the shared library and the kernel loads the library (in case it’s not in memory) upon execution.
  • Dynamically loaded libraries – the program takes full control by calling functions with the library.

Shared Library Naming Conventions

Shared libraries are named in two ways: the library name (a.k.a soname) and a “filename” (absolute path to file which stores library code).

For example, the soname for libc is libc.so.6: where lib is the prefix, c is a descriptive name, so means shared object, and 6 is the version. And its filename is: /lib64/libc.so.6. Note that the soname is actually a symbolic link to the filename.

Locating Shared Libraries in Linux

Shared libraries are loaded by ld.so (or ld.so.x) and ld-linux.so (or ld-linux.so.x) programs, where x is the version. In Linux, /lib/ld-linux.so.x searches and loads all shared libraries used by a program.

A program can call a library using its library name or filename, and a library path stores directories where libraries can be found in the filesystem. By default, libraries are located in /usr/local/lib, /usr/local/lib64, /usr/lib and /usr/lib64; system startup libraries are in /lib and /lib64. Programmers can, however, install libraries in custom locations.

The library path can be defined in /etc/ld.so.conf file which you can edit with a command-line editor.

The line(s) in this file instruct the kernel to load file in /etc/ld.so.conf.d. This way, package maintainers or programmers can add their custom library directories to the search list.

If you look into the /etc/ld.so.conf.d directory, you’ll see .conf files for some common packages (kernel, mysql, and postgresql in this case):

# ls /etc/ld.so.conf.d kernel-2.6.32-358.18.1.el6.x86_64.conf kernel-2.6.32-696.1.1.el6.x86_64.conf mariadb-x86_64.conf kernel-2.6.32-642.6.2.el6.x86_64.conf kernel-2.6.32-696.6.3.el6.x86_64.conf postgresql-pgdg-libs.conf

If you take a look at the mariadb-x86_64.conf, you will see an absolute path to package libraries.

# cat mariadb-x86_64.conf /usr/lib64/mysql

The method above sets the library path permanently. To set it temporarily, use the LD_LIBRARY_PATH environment variable on the command line. If you want to keep the changes permanent, then add this line in the shell initialization file /etc/profile (global) or ~/.profile (user-specific).

# export LD_LIBRARY_PATH=/path/to/library/file

Managing Shared Libraries in Linux

Let us now look at how to deal with shared libraries. To get a list of all shared library dependencies for a binary file, you can use the ldd utility. The output of ldd is in the form:

library name => filename (some hexadecimal value) OR filename (some hexadecimal value) #this is shown when library name can’t be read

This command shows all shared library dependencies for the ls command.

# ldd /usr/bin/ls OR # ldd /bin/ls
Sample Output
linux-vdso.so.1 => (0x00007ffebf9c2000) libselinux.so.1 => /lib64/libselinux.so.1 (0x0000003b71e00000) librt.so.1 => /lib64/librt.so.1 (0x0000003b71600000) libcap.so.2 => /lib64/libcap.so.2 (0x0000003b76a00000) libacl.so.1 => /lib64/libacl.so.1 (0x0000003b75e00000) libc.so.6 => /lib64/libc.so.6 (0x0000003b70600000) libdl.so.2 => /lib64/libdl.so.2 (0x0000003b70a00000) /lib64/ld-linux-x86-64.so.2 (0x0000561abfc09000) libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003b70e00000) libattr.so.1 => /lib64/libattr.so.1 (0x0000003b75600000)

Because shared libraries can exist in many different directories, searching through all of these directories when a program is launched would be greatly inefficient: which is one of the likely disadvantages of dynamic libraries. Therefore a mechanism of caching is employed, performed by the program ldconfig.

Читайте также:  About grep command in linux

By default, ldconfig reads the content of /etc/ld.so.conf, creates the appropriate symbolic links in the dynamic link directories, and then writes a cache to /etc/ld.so.cache which is then easily used by other programs.

This is very important especially when you have just installed new shared libraries or created your own, or created new library directories. You need to run the ldconfig command to effect the changes.

# ldconfig OR # ldconfig -v #shows files and directories it works with

After creating your shared library, you need to install it. You can either move it into any of the standard directories mentioned above and run the ldconfig command.

Alternatively, run the following command to create symbolic links from the soname to the filename:

# ldconfig -n /path/to/your/shared/libraries

To get started with creating your own libraries, check out this guide from The Linux Documentation Project(TLDP).

That’s all for now! In this article, we gave you an introduction to libraries and explained shared libraries, and how to manage them in Linux. If you have any queries or additional ideas to share, use the comment form below.

Источник

Dynamically loading Linux shared libraries?

I do not wish to install it with ldconfig , etc. The target process looks like this:

#include #include void func1() < printf("%d\n", 1); >void func2() < printf("%d\n", 2); >void func3() < printf("%d\n", 3); >int main() < void* lib_handle = dlopen("/home/mike/Desktop/TargetProcess/MyLib.so.1.0.1", RTLD_NOW|RTLD_GLOBAL); if(lib_handle == NULL) < printf("Failed loading lib\n"); >else < printf("Loaded lib successfully\n"); void (*some_func)() = dlsym(lib_handle, "someFunc"); printf("%p\n", some_func); dlclose(lib_handle); >func1(); func2(); func3(); return 0; > 

The target is compiled as so:

all: gcc TestProg.c -ldl -o TestProg 
  1. With the dynamic loading with dlopen as above, why does my_load not appear to be called?
  2. With the same method, why does dlsym always return nil even though dlopen returns non-null? Similarly, nm doesn’t list either my_load or someFunc as symbols of the .so.
  3. Is it possible to use LD_PRELOAD to load the library? I tried copying the .so into the same directory as the target then invoking LD_PRELOAD=»./MyLib.so.1.0.1″ ./TestProg but again my_load seems not to be being called.

1 Answer 1

Your object files was no linked into your library:

gcc -shared -W1,-soname,MyLib.so.1 -o MyLib.so.1.0.1 -lc 

Change it to include your object file MyLib.o:

gcc MyLib.o -shared -W1,-soname,MyLib.so.1 -o MyLib.so.1.0.1 -lc 

UPDATE: just tryed your command locally (without any MyLib.c or MyLib.o):

$ gcc -shared -W1,-soname,MyLib.so.1 -o MyLib.so.1.0.1 -lc && echo ok ok $ nm MyLib.so.1.0.1 xxxxxxxx a _DYNAMIC xxxxxxxx a _GLOBAL_OFFSET_TABLE_ w _Jv_RegisterClasses xxxxxxxx A __bss_start w __cxa_finalize@@xxxxxxxxxxx xxxxxxxx d __dso_handle w __gmon_start__ xxxxxxxx t __i686.get_pc_thunk.bx xxxxxxxx A _edata xxxxxxxx A _end xxxxxxxx T _fini xxxxxxxx T _init 

It is an empty dynamic library.

Читайте также:  Unreal engine linux установка

Источник

When / How does Linux load shared libraries into address space?

When is the address of shared objects specified in programs? During linking? Loading? If I wanted to find the memory address of the system command inside of libc inside of my program I could find it easily in gdb , but what if I don’t want to bring the program into a debugger? Could this address change from run to run? Are there any other static analysis tool that will allow be to view where libraries or functions will be loaded into this program’s memory space when run? I want this information outside of the program (ie. using utilities like objdump to gather information)

5 Answers 5

Libraries are loaded by ld.so (dynamic linker or run-time linker aka rtld, ld-linux.so.2 or ld-linux.so.* in case of Linux; part of glibc). It is declared as «interpreter» (INTERP; .interp section) of all dynamic linked ELF binaries. So, when you start program, Linux will start an ld.so (load into memory and jump to its entry point), then ld.so will load your program into memory, prepare it and then run it. You can also start dynamic program with

 /lib/ld-linux.so.2 ./your_program your_prog_params 

ld.so does an actual open and mmap of all needed ELF files, both ELF file of your program and ELF files of all neeeded libraries. Also, it fills GOT and PLT tables and does relocations resolving (it writes addresses of functions from libraries to call sites, in many cases with indirect calls).

The typical load address of some library you can get with ldd utility. It is actually a bash script, which sets a debug environment variable of ld.so (actually LD_TRACE_LOADED_OBJECTS=1 in case of glibc’s rtld) and starts a program. You even can also do it yourself without needs of the script, e.g. with using bash easy changing of environment variables for single run:

 LD_TRACE_LOADED_OBJECTS=1 /bin/echo 

The ld.so will see this variable and will resolve all needed libraries and print load addresses of them. But with this variable set, ld.so will not actually start a program (not sure about static constructors of program or libraries). If the ASLR feature is disabled, load address will be the same most times. Modern Linuxes often has ASLR enabled, so to disable it, use echo 0 | sudo tee /proc/sys/kernel/randomize_va_space .

You can find offset of system function inside the libc.so with nm utility from binutils. I think, you should use nm -D /lib/libc.so or objdump -T /lib/libc.so and grep output.

Источник

Оцените статью
Adblock
detector