使用 objdump 发现名字不在 ELF 文件中
在带有 GNU binutils 2.28.0-3 的 Arch Linux 上为我工作。也许你在链接后剥离了你的二进制文件?
$ gcc -Wall -m32 -nostdlib gas-symbols.S
$ file a.out
a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, BuildID[sha1]=d5fdff41cc52e9de3b4cdae34cf4129de2b4a69f, not stripped
$ nm a.out
080490ee B __bss_start
080490f0 b buffer ### local symbol in the bss
080490ee D _edata
080490fc B _end
080490c4 d output
080480b8 T _start
我不需要-g 来保留可执行文件中的符号。而且,在我的系统上,-static 是-nostdlib 的默认值。情况并非总是如此,请参阅 this Q&A 关于将 asm 源代码构建为 32 或 64 位静态或动态二进制文件,使用 gcc 或直接使用 as 和 ld。或者使用 NASM 和 ld。
(请注意.code32 不会更改目标文件格式。您需要使用构建选项,因此最好省略.code32,这样您更有可能得到错误(例如来自push %ebx)如果您尝试将 32 位代码构建到 64 位目标文件中。)
直接使用as 和ld(gcc 在后台使用,使用gcc -v 看看如何),我也得到了相同的结果。
$ as gas-symbols.S -o gas-symbols.o --32 &&
ld -o a.out gas-symbols.o -m elf_i386
$ nm a.out
...
080490b0 b buffer ## Still there
...
在 GDB 中,正如 Jester 指出的那样,打印地址而不是值。 GDB 不知道它是一个数组,因为您没有使用任何指令来创建调试信息。 (我不建议尝试手动编写此类指令。例如,查看 gcc -S 为 static char foo[100]; 发出的内容(在文件中)。
无论如何,如果你使用得当,GDB 就可以工作:
$ gdb ./a.out
(gdb) b _start
(gdb) r
Starting program: /home/peter/src/SO/a.out
Breakpoint 1, _start () at gas-symbols.S:10
(gdb) p buffer
$1 = 0
(gdb) p &buffer
$2 = (<data variable, no debug info> *) 0x80490f0 <buffer>
(gdb) ptype buffer
type = <data variable, no debug info>
您可以通过强制转换或使用x 命令来解决缺少类型信息的问题:
(gdb) p (char[12])buffer
$4 = '\000' <repeats 11 times>
(gdb) p /x (char[12])buffer
$5 = {0x0 <repeats 12 times>}
(gdb) x /4w &buffer # eXamine the memory as 4 "words" (32-bit).
0x80490f0 <buffer>: 0x00000000 0x00000000 0x00000000 0x00000000
(gdb) help x # read this to learn about options for dumping memory
对于调试 asm,我的 ~/.gdbinit 中有这个:
set disassembly-flavor intel
layout reg
set print static-members off
但由于您使用 AT&T 语法编写,您可能不想要 intel 风格的反汇编。不过,layout asm / layout reg 很棒。另请参阅x86 标签 wiki 末尾的调试提示。标签 wiki 充满了文档和指南的链接。