ks1*_*322 30
您也可以使用gdb而不是addr2line来检查内存地址.在gdb中加载可执行文件并打印存储在该地址的符号名称.16检查符号表.
(gdb) info symbol 0x4005BDC
Run Code Online (Sandbox Code Playgroud)
Kun*_*ing 21
请检查:
-g,addr2line只有支持函数具有编译的调试信息-g.text部分中的偏移量.在该.text部分中,该地址应指向二进制中的指令以下是来自的消息man addr2line.
addr2line - 将地址转换为文件名和行号.
的addresses应在一个可执行或可重定位目标的部分的偏移地址.
输出类似于FILENAME:LINENO源文件名和文件中的行号
就拿helloworld作为一个例子.
#include <stdio.h>
int main()
{
printf("hello\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在编译之后gcc -g hello.c,我们首先可以objdump用来了解生成的a.out文件中的偏移信息.
以下是倾销拆卸的一部分:
Disassembly of section .text:
0000000000400440 <_start>:
400440: 31 ed xor %ebp,%ebp
400442: 49 89 d1 mov %rdx,%r9
400445: 5e pop %rsi
400446: 48 89 e2 mov %rsp,%rdx
400449: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
40044d: 50 push %rax
40044e: 54 push %rsp
40044f: 49 c7 c0 c0 05 40 00 mov $0x4005c0,%r8
400456: 48 c7 c1 50 05 40 00 mov $0x400550,%rcx
40045d: 48 c7 c7 36 05 40 00 mov $0x400536,%rdi
400464: e8 b7 ff ff ff callq 400420 <__libc_start_main@plt>
400469: f4 hlt
40046a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
...
0000000000400536 <main>:
#include <stdio.h>
int main()
{
400536: 55 push %rbp
400537: 48 89 e5 mov %rsp,%rbp
printf("hello\n");
40053a: bf d4 05 40 00 mov $0x4005d4,%edi
40053f: e8 cc fe ff ff callq 400410 <puts@plt>
return 0;
400544: b8 00 00 00 00 mov $0x0,%eax
}
400549: 5d pop %rbp
40054a: c3 retq
40054b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
Run Code Online (Sandbox Code Playgroud)
代码的最左列是二进制文件中的偏移量.__start函数来自标准C库,并且在没有调试信息的情况下进行预编译.main函数来自我们的helloworld代码,它具有自我们编译文件以来的调试信息-g.
以下是输出addr2line:
$ addr2line -e a.out 0x400442 #offset in the `__start` function
??:?
$ addr2line -e a.out 0x400536 #offset in the `main` function
hello.c:21
$ addr2line -e a.out 0x40054b -f #The last instruction of the `main` function
main
??:?
Run Code Online (Sandbox Code Playgroud)
我们可以从上面的输出中得出一些结论:
-gflag 生成的代码段(这意味着该段具有调试信息)才能成功生成文件名和亚麻码信息.-gflag 编译的函数体的偏移量都将成功输出文件名和亚麻布.偏移0x40054b是在最后指令ret的指令main功能,但我们无法得到的信息.tde*_*ton 17
您需要为addr2line 指定偏移量,而不是虚拟地址(VA).假设您关闭了地址空间随机化,您可以使用完整的VA,但在大多数现代操作系统中,地址空间随机化以用于新进程.
鉴于VA 0x4005BDCby valgrind,在内存中找到进程或库的基址.通过/proc/<PID>/maps在程序运行时检查文件来执行此操作.感兴趣的行是text您的流程的一部分,可以通过r-xp您的程序或库的权限和名称来识别.
假设基础VA是0x0x4005000.然后你会发现valgrind提供的VA和基础VA之间的区别:0xbdc.然后,将其提供给add2line:
addr2line -e a.out -j .text 0xbdc
Run Code Online (Sandbox Code Playgroud)
并查看是否能获得您的行号.
Mat*_*Mat 11
这正是你如何使用它.但是,您所拥有的地址可能与源代码中的某些内容不对应.
例如:
$ cat t.c
#include <stdio.h>
int main()
{
printf("hello\n");
return 0;
}
$ gcc -g t.c
$ addr2line -e a.out 0x400534
/tmp/t.c:3
$ addr2line -e a.out 0x400550
??:0
Run Code Online (Sandbox Code Playgroud)
0x400534是main我的地址.0x400408也是一个有效的函数地址a.out,但它是由GCC生成/导入的一段代码,没有调试信息.(在这种情况下,__libc_csu_init您可以看到可执行文件的布局readelf -a your_exe.)
addr2line如果您包含没有调试信息的库,则失败的其他时间.
| 归档时间: |
|
| 查看次数: |
84775 次 |
| 最近记录: |