Tha*_*raj 34 c debugging shared-libraries stack-trace
backtrace函数给出一组回溯如何用函数名/文件名/行号映射它?
for ex:-
backtrace() returned 8 addresses
./libtst.so(myfunc5+0x2b) [0xb7767767]
./libtst.so(fun4+0x4a) [0xb7767831]
./libtst.so(fun3+0x48) [0xb776787f]
./libtst.so(fun2+0x35) [0xb77678ba]
./libtst.so(fun1+0x35) [0xb77678f5]
./a.out() [0x80485b9]
/lib/libc.so.6(__libc_start_main+0xe5) [0xb75e9be5]
./a.out() [0x80484f1]
Run Code Online (Sandbox Code Playgroud)
从上面的堆栈我怎样才能获得文件名和行号?我做了以下事情,但没有运气.如果我错了,请纠正我:)
for ex:-
./libtst.so(fun2+0x35) [0xb77dc887]
0xb77dc887(fun2 addr+offset)-0xb77b6000 (lib starting addr) = 0x26887 (result)
result is no way related to function in nm output.
I used addr2line command:-
addr2line -f -e libtst.so 0xb77dc887
??
??:0
Run Code Online (Sandbox Code Playgroud)
那么,我如何在运行时或运行后解析?提前致谢...
nm:-
00000574 T _init
00000680 t __do_global_dtors_aux
00000700 t frame_dummy
00000737 t __i686.get_pc_thunk.bx
0000073c T myfunc5
000007e7 T fun4
00000837 T fun3
00000885 T fun2
000008c0 T fun1
00000900 t __do_global_ctors_aux
00000938 T _fini
000009b4 r __FRAME_END__
00001efc d __CTOR_LIST__
00001f00 d __CTOR_END__
00001f04 d __DTOR_LIST__
00001f08 d __DTOR_END__
00001f0c d __JCR_END__
00001f0c d __JCR_LIST__
00001f10 a _DYNAMIC
00001ff4 a _GLOBAL_OFFSET_TABLE_
00002030 d __dso_handle
00002034 A __bss_start
00002034 A _edata
00002034 b completed.5773
00002038 b dtor_idx.5775
0000203c B funptr
00002040 A _end
U backtrace@@GLIBC_2.1
U backtrace_symbols@@GLIBC_2.1
U free@@GLIBC_2.0
U __isoc99_scanf@@GLIBC_2.7
U perror@@GLIBC_2.0
U printf@@GLIBC_2.0
U puts@@GLIBC_2.0
w __cxa_finalize@@GLIBC_2.1.3
w __gmon_start__
w _Jv_RegisterClasses
pmap:-
START SIZE RSS PSS DIRTY SWAP PERM MAPPING
08048000 4K 4K 4K 0K 0K r-xp /home/test/libtofun/a.out
08049000 4K 4K 4K 4K 0K r--p /home/test/libtofun/a.out
0804a000 4K 4K 4K 4K 0K rw-p /home/test/libtofun/a.out
...
b7767000 4K 4K 4K 0K 0K r-xp /home/test/libtofun/libtst.so
b7768000 4K 4K 4K 4K 0K r--p /home/test/libtofun/libtst.so
b7769000 4K 4K 4K 4K 0K rw-p /home/test/libtofun/libtst.so
....
Total: 1688K 376K 82K 72K 0K
Run Code Online (Sandbox Code Playgroud)
128K可写私有,1560K只读私有,0K共享,376K引用
libtst.c:-
void myfunc5(void){
int j, nptrs;
#define SIZE 100
void *buffer[100];
char **strings;
nptrs = backtrace(buffer, SIZE);
printf("backtrace() returned %d addresses\n", nptrs);
strings = backtrace_symbols(buffer, nptrs);
if (strings == NULL) {
perror("backtrace_symbols");
}
for (j = 0; j < nptrs; j++)
printf("%s\n", strings[j]);
free(strings);
}
void fun4(){
char ip;
char *fun = "fun4\0";
printf("Fun name %s\n",fun);
scanf("%c",&ip);
myfunc5();
}
void fun3(){
char *fun = "fun3\0";
printf("Fun name %s\n",fun);
funptr = fun4;
funptr();
}
void fun2(){
char *fun = "fun2\0";
printf("Fun name %s\n",fun);
fun3();
}
void fun1(){
char *fun = "fun1\0";
printf("Fun name %s\n",fun);
fun2();
}
main.c:-
int main(){
char ip;
funptr = &fun1;
scanf("%c",&ip);
funptr();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果需要更多信息,请告诉我......
tde*_*ton 33
尝试为addr2line提供偏移量以及节名称.像这样:
addr2line -j .text -e libtst.so 0x26887
编辑:顺便说一下,如果不清楚,那么0x26887来自你提供的内容:
0xb77dc887(fun2 addr+offset)-0xb77b6000 (lib starting addr) = 0x26887 (result)
Rob*_*Rob 20
我已经看过glibc源代码中的文件backtrace.c和backtracesyms.c文件(git://sourceware.org/git/glibc.git,commit 2482ae433a4249495859343ae1fba408300f2c2e).
假设我没有误读/误解事物:backtrace()本身看起来它只会给你运行时的符号地址,我认为这意味着你需要库加载地址,因为它来自pmap或类似的.但是,backtrace_symbols()会重新计算内容,以便地址相对于共享库ELF,而不是运行时的进程,这非常方便.这意味着您不需要来自pmap的信息.
所以,如果您使用-g(或使用-rdynamic)进行编译,那么您很幸运.您应该能够执行以下操作:
$ # get the address in the ELF so using objdump or nm
$ nm libtst.so | grep myfunc
0000073c T myfunc5
$ # get the (hex) address after adding the offset
$ # from the start of the symbol (as provided by backtrace_syms())
$ python -c 'print hex(0x0000073c+0x2b)'
0x767
$ # use addr2line to get the line information, assuming any is available
addr2line -e libtst.so 0x767
Run Code Online (Sandbox Code Playgroud)
或者,使用gdb:
$ gdb libtst.so
(gdb) info address myfunc
Symbol "myfunc" is at 0x073c in a file compiled without debugging. # (Faked output)
(gdb) info line *(0x073c+0x2b)
Line 27 of "foo.cpp" starts at address 0x767 <myfunc()+21> and ends at 0x769 <something>. # (Faked output)
Run Code Online (Sandbox Code Playgroud)
此外,如果你已经剥离了库,但是隐藏了调试符号以供以后使用,那么你可能只会通过backtrace_syms()打印掉ELF偏移量并且没有符号名称(原始问题中的情况并非如此):在这种情况下,使用gdb可以说比使用其他命令行工具更方便.假设你已经完成了这个,你需要像这样调用gdb(例如):
$ gdb -s debug/libtst.debug -e libtst.so
Run Code Online (Sandbox Code Playgroud)
然后使用'info line'和'info address'进行上述类似的序列,具体取决于您是否只有ELF符号偏移,或符号名称加偏移.
objdump -x --disassemble -l <objfile>
Run Code Online (Sandbox Code Playgroud)
除其他外,这应该转储机器代码的每个编译指令以及它来自的C文件行.
在运行时eu-addr2line(自动查找库并计算偏移量):
//-------------------------------------
#include <sys/types.h>
#include <unistd.h>
int i;
#define SIZE 100
void *buffer[100];
int nptrs = backtrace(buffer, SIZE);
for (i = 1; i < nptrs; ++i) {
char syscom[1024];
syscom[0] = '\0';
snprintf(syscom, 1024, "eu-addr2line '%p' --pid=%d > /dev/stderr\n", buffer[i], getpid());
if (system(syscom) != 0)
fprintf(stderr, "eu-addr2line failed\n");
}
Run Code Online (Sandbox Code Playgroud)
--debuginfo-path=...如果您的调试文件位于其他位置(与构建 ID 等匹配),请保留该选项。
eu-addr2line位于elfutils您的发行版包中。
| 归档时间: |
|
| 查看次数: |
28421 次 |
| 最近记录: |