在 .bss 段中定义的变量名在 gdb 中找不到
The variable name defined in .bss section can not be found in gdb
我正在尝试一个简单的汇编代码:
.section .data
output:
.ascii "The processor Vendor ID is 'xxxxxxxxxxxx'\n"
.section .bss
.lcomm buffer, 12
.section .text
.code32
.globl _start
_start:
movl [=10=], %eax
cpuid
movl $output, %edi
在 .bss 部分我定义了一个名为 "buffer"
的变量
当我尝试在 gdb 中获取它的 address/value 时,它只是打印:
(gdb) p $buffer
= void
使用objdump,我发现ELF文件中没有这个名字,那么运行as和ld时如何保留这些名字信息呢?谢谢!
.lcomm
定义了一个本地公共符号。公共符号只存在于目标文件中,不存在于可执行文件中,因此它们对ld
.
不可见
如果您想要一个对 ld
可见的符号,您应该将其设为 .global
(或 .globl
,具体取决于您的汇编程序)。
公共符号的思想是允许您在多个编译单元中定义相同的符号。他们在链接后消失了。
你应该 p &buffer
而不是 p $buffer
。 $
是立即操作数的汇编语法,而在 gdb 中它是一个方便的变量(和寄存器)前缀。要打印内容,请使用 x/12c &buffer
或 p (char[12])buffer
PS: 调试信息也适用于本地,你不需要它是全局的。
Using objdump, I found the name is not in ELF file
适用于 Arch Linux 和 GNU binutils 2.28.0-3。也许您在链接后删除了二进制文件?
$ 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
因此,如果您尝试将 32 位代码构建到 64 位目标文件中,则更有可能出错(例如来自 push %ebx
)。)
直接使用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
= 0
(gdb) p &buffer
= (<data variable, no debug info> *) 0x80490f0 <buffer>
(gdb) ptype buffer
type = <data variable, no debug info>
您可以通过强制转换或使用 x
命令来解决缺少类型信息的问题:
(gdb) p (char[12])buffer
= '[=13=]0' <repeats 11 times>
(gdb) p /x (char[12])buffer
= {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 语法,因此您可能不希望使用英特尔风格的反汇编。不过,layout asm
/ layout reg
太棒了。另请参阅 x86 标签 wiki 末尾的调试提示。标签维基充满了文档和指南的链接。
我正在尝试一个简单的汇编代码:
.section .data
output:
.ascii "The processor Vendor ID is 'xxxxxxxxxxxx'\n"
.section .bss
.lcomm buffer, 12
.section .text
.code32
.globl _start
_start:
movl [=10=], %eax
cpuid
movl $output, %edi
在 .bss 部分我定义了一个名为 "buffer"
的变量当我尝试在 gdb 中获取它的 address/value 时,它只是打印:
(gdb) p $buffer = void
使用objdump,我发现ELF文件中没有这个名字,那么运行as和ld时如何保留这些名字信息呢?谢谢!
.lcomm
定义了一个本地公共符号。公共符号只存在于目标文件中,不存在于可执行文件中,因此它们对ld
.
如果您想要一个对 ld
可见的符号,您应该将其设为 .global
(或 .globl
,具体取决于您的汇编程序)。
公共符号的思想是允许您在多个编译单元中定义相同的符号。他们在链接后消失了。
你应该 p &buffer
而不是 p $buffer
。 $
是立即操作数的汇编语法,而在 gdb 中它是一个方便的变量(和寄存器)前缀。要打印内容,请使用 x/12c &buffer
或 p (char[12])buffer
PS: 调试信息也适用于本地,你不需要它是全局的。
Using objdump, I found the name is not in ELF file
适用于 Arch Linux 和 GNU binutils 2.28.0-3。也许您在链接后删除了二进制文件?
$ 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
因此,如果您尝试将 32 位代码构建到 64 位目标文件中,则更有可能出错(例如来自 push %ebx
)。)
直接使用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
= 0
(gdb) p &buffer
= (<data variable, no debug info> *) 0x80490f0 <buffer>
(gdb) ptype buffer
type = <data variable, no debug info>
您可以通过强制转换或使用 x
命令来解决缺少类型信息的问题:
(gdb) p (char[12])buffer
= '[=13=]0' <repeats 11 times>
(gdb) p /x (char[12])buffer
= {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 语法,因此您可能不希望使用英特尔风格的反汇编。不过,layout asm
/ layout reg
太棒了。另请参阅 x86 标签 wiki 末尾的调试提示。标签维基充满了文档和指南的链接。