无法在gdb中找到.bss部分中定义的变量名称

时间:2017-06-30 08:46:30

标签: assembly gdb elf debug-symbols gas

我正在尝试一个简单的汇编代码:

.section .data
output:
    .ascii "The processor Vendor ID is 'xxxxxxxxxxxx'\n"
.section .bss
    .lcomm buffer, 12
.section .text
.code32
.globl _start
_start:
    movl $0, %eax
    cpuid
    movl $output, %edi

在.bss部分,我定义了一个名为“buffer”的变量

当我尝试在gdb中获取其地址/值时,它只会打印:

(gdb) p $buffer
$1 = void

使用objdump,我发现该名称不在ELF文件中,那么如何在运行as和ld时保留这些名称信息?谢谢!

3 个答案:

答案 0 :(得分:5)

  

使用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位静态或动态二进制文件,直接使用gccasld。或者使用NASM和ld

请注意,.code32不会更改目标文件格式。您需要使用构建选项,因此最好省略{{1}如果您尝试将32位代码构建到64位目标文件中,那么您更有可能获得错误(例如来自.code32)。)

直接使用push %ebxas (gcc在幕后工作,使用ld查看方式),我也得到相同的结果。< / p>

gcc -v

在GDB 中,正如Jester指出的那样,打印地址而不是值。 GDB并不知道它是一个数组,因为你没有使用任何指令来创建调试信息。 (我不建议手动编写这样的指令。例如,查看$ 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 ... gcc -S发出的内容(单独在文件中)。

无论如何,如果你正确使用它,GDB会起作用:

static char foo[100];

您可以通过投射或使用$ 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

对于调试asm,我在(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

中有这个
~/.gdbinit

但是既然你用AT&amp; T语法写作,你可能不想要英特尔风格的反汇编。不过,set disassembly-flavor intel layout reg set print static-members off / layout asm太棒了。另请参阅标记wiki末尾的调试技巧。标签维基充满了文档和指南的链接。

答案 1 :(得分:3)

您应该{"id"=>1, "car_make_id"=>"1",.........} 而不是p &bufferp $buffer是立即操作数的汇编语法,而在gdb中是便捷变量(和寄存器)前缀。要打印内容,请使用$x/12c &buffer

之类的内容

PS:调试信息也适用于本地人,你不需要它是全球性的。

答案 2 :(得分:2)

.lcomm定义了一个本地公共符号。常用符号仅存在于目标文件中,而不存在于可执行文件中,因此ld不会显示它们。

如果您想要ld可见的符号,则应将其设为.global(或.globl,具体取决于您的汇编程序。)

通用符号的概念是允许您在多个编译单元中定义相同的符号。它们在链接后就消失了。