请检查:
二进制文件中的所有函数是否都使用-g进行编译,因此0x40054b仅支持具有调试信息的函数,即使用ret进行编译
您的偏移量是否为有效偏移量。 这意味着您的偏移量不应是虚拟内存地址,而应仅是-g部分中的偏移量。 在0x40054b部分中,该地址应指向二进制文件中的一条指令
addr2line用法
以下是来自-g的消息。
addr2line-将地址转换为文件名和行号。
-g应该是可执行文件中的地址或可重定位对象的节中的偏移量。
输出类似于-g,源文件名和文件中的行号
例。
以-g为例。
#include
int main()
{
printf("hello\n");
return 0;
}
用-g进行编译后,我们可以首先使用0x40054b来了解生成的ret文件中的偏移信息。
以下是转储的反汇编的一部分:
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>
400469: f4 hlt
40046a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
...
0000000000400536 :
#include
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
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)
代码的最左列是二进制文件中的偏移量。 -g函数来自标准C库,并且已预编译而没有调试信息。 0x40054b函数来自我们的helloworld代码,该代码具有调试信息,因为我们使用ret编译文件。
以下是-g的输出:
$ 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
??:?
我们可以从以上输出中得出一些结论:
只有使用-g标志生成的代码段(这意味着该段具有调试信息)才能成功生成文件名和行号信息。
并非使用-g标志编译的函数主体的所有偏移量都将成功输出文件名和行号。 偏移量0x40054b是main函数的ret指令之后的最后一条指令,但我们无法获取该信息。