GDB动态库搜索路径

当GDB无法显示so动态库的信息或者显示信息有误时,通常是由于库搜索路径错误导致的,可使用set sysroot、set solib-absolute-prefix、set solib-search-path来指定库搜索路径。

1. set sysroot 与 set solib-absolute-prefix 是同一条命令,实际上,set sysroot是set solib-absolute-prefix 的别名。

2. set solib-search-path设置动态库的搜索路径,该命令可设置多个搜索路径,路径之间使用“:”隔开(在linux中为冒号,DOS和Win32中为分号)。

3. set solib-absolute-prefix 与 set solib-search-path 的区别:

总体上来说solib-absolute-prefix设置库的绝对路径前缀,只对绝对路径有效;而solib-search-path设置库的搜索路径,对绝对路径和相对路径均起作用。(编译器自动链接的so库多采用绝对路径)。

详细规则有:

set solib-search-path由于是路径前缀,所以只能设置一个路径,而solib-search-path可以设置多个搜索路径。

在载入动态库信息时Coredump会碰到两种路径:绝对路径和相对路径。编译时链接的库通常是绝对路径,例如"/lib/libc.so.6"、"/lib/libdl.so.2"等,此时在Coredump文件中也同样保存为绝对路径;而程序用dlopen函数载入的so库可能使用相对路径,例如"./libddd.so",此时Coredump文件原封不动地保存相同的路径。

为便于表述,用A表示set solib-absolute-prefix设置的路径,R(A)表示A去掉根前缀后的路径(即去掉前缀“/”符号),用Bn表示set solib-search-path设置的每一条路径,用X表示Coredump中保存的库路径,即待搜索的库文件路径,F(X)表示X中去掉目录后的文件名(路径最后“/”符号后的字符串)。

对绝对路径,搜索顺序是:

1) A / X                       // 先添加solib-absolute-prefix前缀进行搜索,成功则不再继续,否则继续2)

2) R(A) / X                 // 再把1)的根前缀去掉后进行搜索,成功则不再继续,否则继续3)

3) Bn / R(A) / X         // 再在2)的基础上逐一添加solib-search-path中的每条路径进行搜索,成功则不再继续,否则继续4)

4) Bn / F(X)               // 再只使用2)中的文件名(去掉目录段),并逐一添加solib-search-path中的每条路径进行搜索,成功则不再继续,否则继续5)

5) $PATH / R(A) / X                                    // 在2)的基础上使用环境变量$PATH中的每条路径进行搜索,成功则不再继续,否则继续6)

6) $LD_LIBRARY_PATH / R(A) / X         // 在2)的基础上使用环境变量$LD_LIBRARY_PATH中的每条路径进行搜索,成功则不再继续,否则继续7)

7) 返回失败

对相对路径,搜索顺序是:

1) X                            // 直接使用原始路径进行搜索,成功则不再继续,否则继续2)

2) Bn / X                    // 再逐一添加solib-search-path中的每条路径进行搜索,成功则不再继续,否则继续3)

3) Bn / F(X)               // 再只使用文件名(去掉目录段),并逐一添加solib-search-path中的每条路径进行搜索,成功则不再继续,否则继续4)

4) $PATH / X                                    // 再使用环境变量$PATH中的每条路径进行搜索,成功则不再继续,否则继续5)

5) $LD_LIBRARY_PATH / X         // 再使用环境变量$LD_LIBRARY_PATH中的每条路径进行搜索,成功则不再继续,否则继续6)

6) 返回失败

===================================

举例说明:

set solib-absolute-prefix /root/temp

set solib-search-path /home/evan:/home/peter

$PATH is /usr/sbin:/usr/bin

$LD_LIBRARY_PATH is /opt:/usr/games

那么对绝对路径"/lib/libc.so.6"的搜索顺序是:

1) A / X

/root/temp/lib/libc.so.6

2) R(A) / X

root/temp/lib/libc.so.6

3) Bn / R(A) / X

/home/evan/root/temp/lib/libc.so.6

/home/peter/root/temp/lib/lic.so.6

4) Bn / F(X)

/home/evan/libc.so.6

/home/peter/libc.so.6

5) $PATH / R(A) / X

/usr/sbin/root/temp/lib/libc.so.6

/usr/bin/roo/temp/lib/lic.so.6

6) $LD_LIBRARY_PATH / R(A) / X

/opt/root/temp/lib/libc.so.6

/usr/games/root/temp/lib/libc.so.6

对相对路径"./libddd.so"的搜索顺序是

1) X

./libddd.so

2) Bn / X

/home/evan/./libddd.so

/home/peter/./libddd.so

3) Bn / F(X)

/home/evan/libddd.so

/home/peter/libddd.so

4) $PATH / X

/usr/sbin/./libddd.so

/usr/bin/./libddd.so

5) $LD_LIBRARY_PATH / X

/opt/./libddd.so

/usr/games/./libddd.so

从上面看到,对绝对路径和相对路径都有一步是采用文件名和solib-search-path拼接来查找(绝对路径的第4步和相对路径的第3步),所以只要用set solib-search-path设置了每一个库文件所在的直接目录,那么就能保证每一个库都能被找到。

4. 查看so库的加载路径是否正确可使用info sharedlibrary命令,如果已找到对应的文件则其From和To的加载地址会有值,并且右边路径显示的就是加载文件所在的地址,这个时候,如果so库文件含符号信息,则syms Read的值为Yes,否则为No,如果未找到对应的文件则From和To的地址为空,syms Read的值为No,此时右边路径显示的是Coredump文件中库文件路径。

5. 如果在Coredump文件载入过程中,或者info sharedlibrary命令时,出现" Cannot access memory at address 0x87000069 "这样的错误,这通常是由于所使用的主执行文件("file"命令或"exec-file"命令)与Coredump文件("core"命令或"core-file"命令)两者不匹配导致的。这个时候应检查主执行文件是否是生成Coredump时所用的主执行文件,只要差一点,就可能导致动态库信息读取错误。

6. 如果载入过程中有" warning: .dynamic section for "/lib/librt.so.1" is not at the expected address (wrong library or version mismatch?) "这样的提示,这通常是库搜索路径设置错误,GDB载入了错误的库文件导致的。这时,应使用info sharedlibrary命令查看相应库的载入路径,并使用set sysroot或set solib-search-path修改搜索路径来将错误的库修正到正确的路径上。

7. 在设置了搜索路路径后,最好先用file命令载入主执行文件,再用core命令载入Coredump文件,这样才能保证正确载入库的符号表。否则,如果先用core命令载入Coredump文件,再用file命令载入主执行文件,那么会造成库只是被搜索但并不载入符号(使用info sharedlibrary命令可以看到),这时再重新执行一次core命令就可以了。

8. 一个实际的搜索例子:

当前目录为/home

主执行文件在/home/evan/gdbso/mips/gdbso

Core文件在/home/evan/gdbso/mips/Coredump

所用动态库与拷贝到主执行文件同一目录下

编译主执行文件所用的标准库被拷贝到主执行文件的lib目录下/home/evan/gdbso/mips/lib/libxxx.so

进入GDB,用file命令载入主执行文件:

[email protected]:/home$ mips-linux-gnu-gdb
...
(gdb) file evan/gdbso/mips/gdbso
Reading symbols from /home/evan/gdbso/mips/gdbso...done.
(gdb) info sharedlibrary 
No shared libraries loaded at this time.

可以看到只载入了主执行文件时,是无法得到动态库信息的。

再用core命令载入Coredump文件:

(gdb) core evan/gdbso/mips/Coredump
...
warning: .dynamic section for "/lib/libc.so.6" is not at the expected address (wrong library or version mismatch?)
...
(gdb) info sharedlibrary 
From        To          Syms Read   Shared Object Library
0x2aad98c0  0x2aadd6d8  Yes         /lib/librt.so.1
0x2aaf3460  0x2ab0db98  Yes         /lib/libm.so.6
0x2ab7e2e0  0x2ab89b28  Yes         /lib/libpthread.so.0
0x2abba9a0  0x2acb2bd8  Yes         /lib/libc.so.6
0x2ad06a40  0x2ad07988  Yes         /lib/libdl.so.2
                        No          /lib/ld.so.1
                        No          ./libddd.so
(gdb)

在同时有了主执行文件和Coredump文件后,用info sharedlibrary就可以看到动态库信息了。但在载入过程中有库版本不匹配的提示。通过info sharedlibrary也看到GDB错误地载入了系统中自带的标准库。

我们将绝对路径设置到一个不存在的目录来看看Coredump中保存的原始路径名:

(gdb) set sysroot /noexist
...
(gdb) info sharedlibrary 
From        To          Syms Read   Shared Object Library
                        No          /lib/librt.so.1
                        No          /lib/libm.so.6
                        No          /lib/libpthread.so.0
                        No          /lib/libc.so.6
                        No          /lib/libdl.so.2
                        No          /lib/ld.so.1
                        No          ./libddd.so
(gdb)

Coredump中保存的原始路径名为/lib/librt.so.1,为了让GDB使用正确的库/home/evan/gdbso/mips/lib/librt.so.1,只需要将绝对路径前缀设置为/home/evan/gdbso/mips即可,这里设置为evan/gdbso/mips来演示效果:

(gdb) set sysroot evan/gdbso/mips
...
(gdb) info sharedlibrary 
From        To          Syms Read   Shared Object Library
0x2aad98c0  0x2aade270  Yes         evan/gdbso/mips/lib/librt.so.1
0x2aaf3110  0x2ab31b70  Yes         evan/gdbso/mips/lib/libm.so.6
0x2ab7e320  0x2ab8e620  Yes         evan/gdbso/mips/lib/libpthread.so.0
0x2abba6a0  0x2accc3f0  Yes         evan/gdbso/mips/lib/libc.so.6
0x2ad06b50  0x2ad07c70  Yes         evan/gdbso/mips/lib/libdl.so.2
0x2aaa8810  0x2aac2e40  Yes         evan/gdbso/mips/lib/ld.so.1
                        No          ./libddd.so
(gdb)

可以看到,GDB已经正确地载入了绝对路径。但相对路径"./libddd.so"还没有找到,为了使用/home/evan/gdbso/mips/libddd.so,设置库搜索路径包含/home/evan/gdbso/mips即可。为了查看效果,这里还添加了一个不存在的搜索路径:

(gdb) set solib-search-path /noexist:/home/evan/gdbso/mips
...
(gdb) info sharedlibrary 
From        To          Syms Read   Shared Object Library
0x2aad98c0  0x2aade270  Yes         evan/gdbso/mips/lib/librt.so.1
0x2aaf3110  0x2ab31b70  Yes         evan/gdbso/mips/lib/libm.so.6
0x2ab7e320  0x2ab8e620  Yes         evan/gdbso/mips/lib/libpthread.so.0
0x2abba6a0  0x2accc3f0  Yes         evan/gdbso/mips/lib/libc.so.6
0x2ad06b50  0x2ad07c70  Yes         evan/gdbso/mips/lib/libdl.so.2
0x2aaa8810  0x2aac2e40  Yes         evan/gdbso/mips/lib/ld.so.1
0x2ad1a590  0x2ad1a770  Yes         /home/evan/gdbso/mips/libddd.so
(gdb)

可以看到,所有的库都找到正确的路径了,Syms也被正确地载入。

来源:http://blog.csdn.net/_xiao/article/details/23289971

时间: 2024-10-11 22:37:04

GDB动态库搜索路径的相关文章

Linux动态库搜索路径的技巧

众所周知,Linux动态库的默认搜索路径是/lib和/usr/lib.动态库被创建后,一般都复制到这两个目录中.当程序执行时需要某动态库,并且该动态库还未加载到内存中,则系统会自动到这两个默认搜索路径中去查找相应的动态库文件,然后加载该文件到内存中,这样程序就可以使用该动态库中的函数,以及该动态库的其它资源了.在Linux 中,动态库的搜索路径除了默认的搜索路径外,还可以通过以下三种方法来指定. 方法一:在配置文件/etc/ld.so.conf中指定动态库搜索路径. 可以通过编辑配置文件/etc

linux添加动态库搜索路径

在有时运行程序出现动态库找不着的问题,而明明装了的.这时候可能是没有将相应的路径添加到系统中去. 具体说:cd /etc/ld.so.conf.d/ 可以发现里面有一堆*.conf的文件 我们要做的就是建一个自己的文件,里面写上我们的动态库路径.具体形式如果有问题可以参考其他的*.conf文件 添加完毕之后记得在terminal里面输入sudo ldconfig

Linux C头文件查找与动态库搜索

一.编译程序时,头文件路径搜索 本文介绍在linux中头文件的搜索路径,也就是说你通过include指定的头文件,linux下的gcc编译器它是怎么找到它的呢.在此之前,先了解一个基本概念. 头文件是一种文本文件,使用文本编辑器将代码编写好之后,以扩展名.h保存就行了.头文件中一般放一些重复使用的代码,例如函数声明.变量声明.常数定义.宏的定义等等.当使用#include语句将头文件引用时,相当于将头文件中所有内容,复制到#include处.#include有两种写法形式,分别是: #inclu

环境变量,include搜索路径,lib库搜索路径

环境变量 系统环境变量 我们知道,我们经常要设置一些环境变量,系统环境变量我们非常容易理解.其实我们在windows中经常容易接触.其实环境变量是一个非常广泛的一个概念,它与web应用程序中的web.config所处的角色很像.什么意思呢?就是说,程序(系统或应用)要运行的时候,它的基本业务逻辑可能是一定的,但是实现业务逻辑的时候有些设置性的东西却可以改变程序很多.如web应用程序,编译之后他的业务逻辑基本不会发生改变,但是如果你更改一些web.config中的参数,程序的运行就会发生相应的改变

[转]谈谈Linux下动态库查找路径的问题

http://blog.chinaunix.net/uid-23069658-id-4028681.html 学习到了一个阶段之后,就需要不断的总结.沉淀.清零,然后才能继续“上路”.回想起自己当年刚接触Linux时,不管是用源码包编译程序,还是程序运行时出现的和动态库的各种恩恩怨怨,心里那真叫一个难受.那时候脑袋里曾经也犯过嘀咕,为啥Linux不弄成windows那样呢,装个软件那个麻烦不说,连运行软件都这么恼火呢?如果那样的话就不叫Linux了.借用小米公司CEO雷军一句话:小米,为发烧而生

谈谈Linux下动态库查找路径的问题 ldconfig LD_LIBRARY_PATH PKG_CONFIG_PATH

谈谈Linux下动态库查找路径的问题 ldconfig LD_LIBRARY_PATH  PKG_CONFIG_PATH 转载自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=23069658&id=4028681 学习到了一个阶段之后,就需要不断的总结.沉淀.清零,然后才能继续“上路”.回想起自己当年刚接触Linux时,不管是用源码包编译程序,还是程序运行时出现的和动态库的各种恩恩怨怨,心里那真叫一个难受.那时候脑袋里曾经

转:谈谈Linux下动态库查找路径的问题

http://blog.chinaunix.net/uid-23069658-id-4028681.html 学习到了一个阶段之后,就需要不断的总结.沉淀.清零,然后才能继续"上路".回想起自己当年刚接触Linux时,不管是用源码包编译程序,还是程序运行时出现的和动态库的各种恩恩怨怨,心里那真叫一个难受.那时候脑袋里曾经也犯过嘀咕,为啥Linux不弄成windows那样呢,装个软件那个麻烦不说,连运行软件都这么恼火呢?如果那样的话就不叫Linux了.借用小米公司CEO雷军一句话:小米,

ubuntu---记录.动态库默认路径的踩坑

发现这个问题,还是经过一个报错问题卡了好多天,然后请求好多人的支援,最后个人的疑问:为什么明明指明了路径,生成 .SO 没有问题,在调用.SO 就有问题,报错各种找不到函数或者未定义,然后把缺的 *.so 都一顿拷贝至 /lib  或者 /usr/lib 中 有时又可以解决问题,但不是每次都好用 ?   --- linux动态链接库的加载顺序. linux动态链接库的加载顺序: 它有5个地方会查找, 1. 编译时指定的run path 2. LD_LIBRARY_PATH 指定的地方 3. ld

gdb动态库延迟断点及线程/进程创建相关事件处理(下)

一.被调试任务所有so文件如何枚举在前一篇博客中,大致说明了gdb是通过一个动态库提供的回调函数(_dl_debug_state)处埋伏断点,然后通过约定好的_r_debug全局变量来得到exe程序对应的link_map,然后以该结构为队列头来遍历被调试任务中所有的so文件.当时也说了这个地方比较模糊,只是说了一个思路,所以这里再试图把这个实现相对详细的描述一下.二.定义被调试任务(debuggee)的link_map地址同样是在gdb-6.5\gdb\solib-svr4.c文件中,其中包含了