Linux dynamic link

参考文档

  1. http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
  2. http://man7.org/linux/man-pages/man8/ld.so.8.html
  3. The Linux Programming Interface chapter 41

原理

glibc

glibc提供了系统级的c语言库(也叫libc6),其他版本libc已基本被淘汰。现在Linux编译程序都依赖用glibc2编译,小版本号已经到了glibc2.23。

so文件的加载

glibc2编译的程序,如果要加载so文件,都是由/lib64/ld-linux-x86-64.so.2完成的。例如/bin/ls -l的运行,其实是执行了

/lib64/ld-linux-x86-64.so.2 /bin/ls -l

so文件加载顺序

  1. LD_LIBRARY_PATH
  2. /etc/ld.so.cache
  3. /lib,/usr/lib for 32bit OS
  4. /lib64,/usr/lib64 for 64bit OS

指定so加载目录

gcc -g -Wall -Wl,-rpath,/home/mtk/pdir -o prog prog.c libdemo.so
gcc -Wl,-rpath,'$ORIGIN'/lib ...

指定dynamic linker

g++ main.o -o myapp ... \
   -Wl,--rpath=/path/to/newglibc \
   -Wl,--dynamic-linker=/path/to/newglibc/ld-linux.so.2

可以通过这个命令看gcc的默认值

% gcc -dumpspecs
......
*link:
...%{m16|m32|mx32:;:-dynamic-linker %{muclibc:/lib/ld64-uClibc.so.0;:%{mbionic:/system/bin/linker64;:/lib64/ld-linux-x86-64.so.2}}}...
......

ld.so.cache

so文件被缓存在/etc/ld.so.cache里,用ldconfig -p可以打印出来

ldconfig和ld.so.conf

ldconfig会把/etc/ld.so.conf描述的so文件,放入/etc/ld.so.cache

so文件存放位置

  1. /usr/lib ,ubuntu或centos的库放在这里
  2. /lib,开机就需要的库放在这里
  3. /usr/local/lib, 用户自己编译的代码

相关环境变量

LD_LIBRARY_PATH=xxx command #指定so文件目录
LD_PRELOAD=xx.so command       #指定提前加载的so,这些会override默认的so文件

LD_DEBUG=help commond
LD_DEBUG=files commond      #显示verbose信息
LD_DEBUG=bindings commond   #显示符号绑定
LD_DEBUG=libs commond       #显示search path
LD_DEBUG=versions command   #显示版本依赖
LD_DEBUG=all commond

加载时候是动态link

编译动态链接库时候,需要制定-fPIC参数

  • PIC : position-independent code

安装so文件

  1. copy so file to /usr/lib
  2. 根据soname建立符号链接
  3. run ldconfig

目录

  1. /lib 系统启动的时候依赖的库,/lib被mount比较早
  2. /usr/lib 一般都安装在这里
  3. /usr/local/lib,非标准的,或者用户自己编译的体验版
  4. /etc/ld.so.conf描述的目录

Tools

ldd

ldd会至少2个so

  1. ld-linux.so.2 : the dynamic linker
  2. libc.so.6 : the standard C library
ldd /bin/ls

nm

搜索哪个lib有crypt函数定义

# nm -A /usr/lib/lib*.so 2> /dev/null | grep ' crypt$'
/usr/lib/libcrypt.so:00007080 W crypt

ldconfig

  1. 搜索一个so,需要很久,ldconfig帮忙引入cache => /etc/ld.so.cache
  2. 更新so库时候,需要运行ldconfig
ldconfig -p #display the cache
ldconfig -v #修改so后,会显示变化

so的版本管理

引入soname概念

  1. libdemo.so.1.0.1
  2. libdemo.so.1.0.2 主版本没变化,小版本有变化,和以前兼容
  3. libdemo.so.2.0.0 主版本变化,因此和以前不兼容

soname一般设置成libname.so.major-id,如

  1. libdemo.so.1 -> libdemo.so.1.0.2
  2. libdemo.so.2 -> libdemo.so.2.0.0
  3. libreadline.so.5 -> libreadline.so.5.0

so文件的兼容性

Application Binary Interface (ABI)

查看glibc版本

/lib64/libc.so.6
ldd --version
strings /lib64/libc.so.6 |grep GLIBC_

https://benohead.com/linux-check-glibc-version/

安装多版本glibc

使用patchelf
https://stackoverflow.com/questions/847179/multiple-glibc-libraries-on-a-single-host/851229#851229

替换新库

例如替换glibc,先编译好glibc

rm /lib64/libc.so.6
ln -s /lib64/libc-2.17.so /lib64/libc.so.6

你可能感兴趣的:(Linux dynamic link)