10

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とは何の関係もないと思いますが、-ggdb3の代わりに-gを使用して試しました。

4

4 に答える 4

8

objdumpがそれを見ることができるのなら、なぜdladdrができないのか

dladdr動的シンボルテーブルにエクスポートされた関数のみを表示できます。最も可能性が高い

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

何も表示されません。実際、objdumpは、シンボルがローカルであることを示しています。これは、これが原因であることを証明しています。

シンボルは、非表示の可視性があるか、静的であるか、または他の方法(リンカースクリプトなど)で非表示にするため、ローカルです。

アップデート:

'U'でマークされたものは、dladdrで機能します。それらはどういうわけか自動的に「エクスポート」されます。

これらは、他の共有ライブラリからエクスポートされるため、機能します。U未解決、つまり他の場所で定義されていることを表します。

于 2012-07-31T04:00:04.047 に答える
5

-rdynamicLDFLAGSに追加しました。

man gcc言う:

-rdynamic
    Pass the flag -export-dynamic to the ELF linker, on targets that support it. This instructs the linker to add all symbols, not only used ones, to the
    dynamic symbol table. This option is needed for some uses of "dlopen" or to allow obtaining backtraces from within a program.
于 2016-05-25T10:08:26.330 に答える
4

gccオプション「-export-dynamic」を追加すると、これが解決しました。

于 2012-08-15T21:50:01.853 に答える
1

hinesmrソリューションは私のために働いた。gccに渡した正確なオプションは「-Wl、-export-dynamic」で、すべての関数がdladdrに表示されるようになりました。

于 2013-02-09T03:48:04.763 に答える