c - dladdr 不返回函数名

标签 c linux elf

我正在尝试使用 dladdr。它正确定位了库,但未找到函数名称。我可以调用 objdump,做一些数学运算,然后获取我传递给 dladdr 的函数的地址。如果 objdump 可以看到它,为什么 dladdr 不能?

这是我的功能:

const char *FuncName(const void *pFunc)
{
Dl_info  DlInfo;
int  nRet;

    // Lookup the name of the function given the function pointer
    if ((nRet = dladdr(pFunc, &DlInfo)) != 0)
        return DlInfo.dli_sname;
    return NULL;
}

这是一个 gdb 记录,显示了我得到的结果。

Program received signal SIGINT, Interrupt.
[Switching to Thread 0xf7f4c6c0 (LWP 28365)]
0xffffe410 in __kernel_vsyscall ()
(gdb) p MatchRec8Cmp
$2 = {void (TCmp *, TWork *, TThread *)} 0xf1b62e73 <MatchRec8Cmp>
(gdb) call FuncName(MatchRec8Cmp)
$3 = 0x0
(gdb) call FuncName(0xf1b62e73)
$4 = 0x0
(gdb) b FuncName
Breakpoint 1 at 0xf44bdddb: file threads.c, line 3420.
(gdb) call FuncName(MatchRec8Cmp)

Breakpoint 1, FuncName (pFunc=0xf1b62e73) at threads.c:3420
3420    {
The program being debugged stopped while in a function called from GDB.
When the function (FuncName) is done executing, GDB will silently
stop (instead of continuing to evaluate the expression containing
the function call).
(gdb) s
3426            if ((nRet = dladdr(pFunc, &DlInfo)) != 0)
(gdb) 
3427                    return DlInfo.dli_sname;
(gdb) p DlInfo 
$5 = {dli_fname = 0x8302e08 "/xxx/libdata.so", dli_fbase = 0xf1a43000, dli_sname = 0x0, dli_saddr = 0x0}
(gdb) p nRet
$6 = 1
(gdb) p MatchRec8Cmp - 0xf1a43000
$7 = (void (*)(TCmp *, TWork *, TThread *)) 0x11fe73
(gdb) q
The program is running.  Exit anyway? (y or n) y

这是我从 objdmp 得到的

$ objdump --syms /xxx/libdata.so | grep MatchRec8Cmp
0011fe73 l     F .text  00000a98              MatchRec8Cmp

果然,0011fe73 = MatchRec8Cmp - 0xf1a43000。任何人都知道为什么 dladdr 不能返回 dli_sname = "MatchRec8Cmp"???

我正在运行 Red Hat Enterprise Linux Server 5.4 版 (Tikanga)。我以前看过这个作品。也许这是我的编译开关:

CFLAGS = -m32 -march=i686 -msse3 -ggdb3 -pipe -fno-common -fomit-frame-pointer \
        -Ispio -fms-extensions  -Wmissing-declarations -Wstrict-prototypes -Wunused  -Wall \
        -Wno-multichar -Wdisabled-optimization -Wmissing-prototypes -Wnested-externs \
        -Wpointer-arith -Wextra -Wno-sign-compare -Wno-sequence-point \
        -I../../../include -I/usr/local/include -fPIC \
        -D$(Uname) -D_REENTRANT -D_GNU_SOURCE 

虽然我认为调试符号与 elf 没有任何关系,但我已尝试使用 -g 而不是 -ggdb3。

最佳答案

If objdump can see it, why can't dladdr

dladdr 只能看到动态符号表中exported 的函数。很有可能

 nm -D /xxx/libdata.so | grep MatchRec8Cmp

什么都不显示。事实上,您的 objdump 显示该符号是本地,这证明这是原因。

符号是局部的,因为它具有隐藏的可见性,是静态的,或者因为您以其他方式(例如使用链接描述文件)隐藏了它。

更新:

Those marked with the 'U' work with dladdr. They get "exported" automatically somehow.

它们之所以有效,是因为它们是从一些其他共享库 导出的。 U 代表未解决,即在别处定义。

关于c - dladdr 不返回函数名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11731229/

相关文章:

c - 在 C 中的位域结构中添加额外的位

c - SerialRead 在无限循环之外时无法正常工作

c - 如何在用户输入字母 "q"时退出 while 循环 - C 编程

java - Tesseract redhat tomcat 8 配置 - TessApi classdefnotfound

c - 在与 ARM 架构兼容的 ELF 文件中查找 C 结构的地址

c - C 中如何处理字符串?

linux - 在smartgit中配置ssh私钥

regex - 在文本文件中按列对唯一元素进行排序

macos - 如何在 Mac OS X 上创建 ELF 可执行文件?

c - 如何使用 GNU ld 将两个或多个可重定位 ELF 文件合并为一个可重定位 ELF 文件?