GDB info registers命令 - 输出的第二列

Jay*_*iya 7 gdb cpu-registers

info registers在gdb中运行时,我们得到类似于以下内容的输出:

rax            0x1c 28
rbx            0x0  0
rcx            0x400a60 4196960
rdx            0x7fffffffde88   140737488346760
rsi            0x1  1
rdi            0x400932 4196658
rbp            0x0  0x0
rsp            0x7fffffffde68   0x7fffffffde68
r8             0x400ad0 4197072
r9             0x7ffff7dea560   140737351951712
r10            0x7fffffffdc30   140737488346160
r11            0x7ffff7732dd0   140737344908752
r12            0x4007f0 4196336
r13            0x7fffffffde80   140737488346752
r14            0x0  0
r15            0x0  0
rip            0x7ffff7732dd0   0x7ffff7732dd0
eflags         0x202    [ IF ]
cs             0x33 51
ss             0x2b 43
ds             0x0  0
es             0x0  0
fs             0x0  0
gs             0x0  0
Run Code Online (Sandbox Code Playgroud)

虽然我明白了rax,rcx等等,GDB被转换为10进制的第二列中的值,这似乎并不一致.有些寄存器,即rsprip显示在十六进制的值相同,甚至在第二列.eflags另一方面,显示第二列中的标志.

这样做的原因是gdb什么?如果它将显示相同的信息(如果rsprip),是不是多余?此外,这如何概括其他架构?(以上输出适用于x86-64).

Rak*_*ish 8

info registers命令以原始格式(十六进制)和自然格式打印输出寄存器.

自然格式基于寄存器的类型,在gdb源代码的xml文件中声明.例如,i386/64bit-core.xml包含:

<reg name="rax" bitsize="64" type="int64"/>
<reg name="rbx" bitsize="64" type="int64"/>
<reg name="rcx" bitsize="64" type="int64"/>
<reg name="rdx" bitsize="64" type="int64"/>
<reg name="rsi" bitsize="64" type="int64"/>
<reg name="rdi" bitsize="64" type="int64"/>
<reg name="rbp" bitsize="64" type="data_ptr"/>
<reg name="rsp" bitsize="64" type="data_ptr"/>
<reg name="r8" bitsize="64" type="int64"/>
<reg name="r9" bitsize="64" type="int64"/>
<reg name="r10" bitsize="64" type="int64"/>
<reg name="r11" bitsize="64" type="int64"/>
<reg name="r12" bitsize="64" type="int64"/>
<reg name="r13" bitsize="64" type="int64"/>
<reg name="r14" bitsize="64" type="int64"/>
<reg name="r15" bitsize="64" type="int64"/>

<reg name="rip" bitsize="64" type="code_ptr"/>
<reg name="eflags" bitsize="32" type="i386_eflags"/>
<reg name="cs" bitsize="32" type="int32"/>
<reg name="ss" bitsize="32" type="int32"/>
<reg name="ds" bitsize="32" type="int32"/>
<reg name="es" bitsize="32" type="int32"/>
<reg name="fs" bitsize="32" type="int32"/>
<reg name="gs" bitsize="32" type="int32"/>
Run Code Online (Sandbox Code Playgroud)

您可以看到带有type="int64"和的寄存器type="int32"在其自然输出中显示为十进制值,因为它们通常是通用寄存器,可用于引用内存和赋值.

注册时以自然格式注册type="data_ptr"type="code_ptr"具有十六进制值,因为它们通常用于引用内存地址.

对于带有type="i386_eflags"输出的寄存器,设置为"true"的标志,因为对于这个寄存器,对于人类而言,在知道哪个标志设置为"True"而不是十六进制值时更有意义.

对于其他架构,它取决于在源代码中如何定义寄存器类型.您可以在binutils -gdb / gdb/features /中 查看ARM,ARM-64,x86-32bit和许多其他源代码.


编辑:

来源:@MarkPlotnick回答为什么gdb中的"info register ebp"没有显示十进制数?和@perror在https://reverseengineering.stackexchange.com/questions/9221/output-of-gdb-info-registers/9222#9222上回答.

对不起,我忘了提及来源.


per*_*ror 5

事实上,在汇编中你只能找到三种类型的值:

  1. 数值;
  2. 内存地址;
  3. 指令(操作码)。

通用寄存器,例如rax, rbx, ... 用于存储数值(将触发程序的行为)或内存地址(以了解读取/写入或跳转的位置)。

当然,由于大多数人习惯于将程序中使用的值使用十进制格式,因此当寄存器可能包含此类值时,显示十进制格式很重要。

现在,重要的是要知道内存地址通常以十六进制格式给出(主要是出于紧凑性原因)。而且,通用寄存器也可能包含内存地址。这就是为什么同时gdb显示十进制和十六进制格式的原因,以防万一最适合当前值。

寄存器rsp, rip(和rbp) 是特殊情况,因为它们专门用于存储地址(并且仅用于存储地址),因此将此类寄存器的内容转换为十进制格式是没有用的。这就是为什么gdb只为这些寄存器提供十六进制格式。

最后,rflags/的情况eflags有点特殊,因为该寄存器的含义是逐位相关的(见下图)。

EFLAGS 位元详细信息

因此,给出十进制、十六进制或二进制格式对用户来说并不是真正有用的(除非您可以立即将数字与标志相关联)。但是,提供设置为“true”的标志列表(这是[ IF ]您在示例中看到的)会更有用。然而,gdb给出了 的十六进制值,eflags因为它可以被访问并用作程序中的值(我已经看到了这个用于混淆目的)。