【问题标题】:How to use a logical address with an FS or GS base in gdb?如何在 gdb 中使用具有 FS 或 GS​​ 基数的逻辑地址?
【发布时间】:2012-05-08 09:42:09
【问题描述】:

gdb 提供读取或写入特定线性地址的功能,例如:

(gdb) x/1wx 0x080483e4
0x80483e4 <main>:       0x83e58955
(gdb) 

但是如何指定逻辑地址?我遇到了以下说明:

   0x0804841a <+6>:     mov    %gs:0x14,%eax

如何在 gdb 中读取“%gs:0x14”处的内存,或者将此逻辑地址转换为可以在x 命令中使用的线性地址?

注意:我知道在这条指令之后我可以简单地阅读 %eax,但这不是我关心的问题

【问题讨论】:

标签: gdb x86 memory-segmentation


【解决方案1】:

如何读取 gdb 中“%gs:0x14”处的内存

你不能:GDB 无法知道%gs 所指的段是如何设置的。

或将此逻辑地址转换为我可以在 x 命令中使用的线性地址

同样,您一般不能这样做。但是,您似乎在 32 位 x86 Linux 上,您可以这样做 -- %gs 设置为通过 set_thread_area 系统调用指向线程描述符。 p>

您可以在 GDB 中执行catch syscall set_thread_area,并检查参数(每个线程都会有一个这样的调用)。实际执行此操作的代码是here。知道%gs 的设置方式后,只需将0x14 添加到base_addr,即可完成。

【讨论】:

  • 不错的答案。不幸的是,我的程序似乎没有调用 set_thread_area(2)。您可以在这里查看源代码:pastebin.com/us5sbzVg(源代码中提供了编译选项)。
  • @user368507 你的程序只有一个线程。程序确实调用set_thread_area(您应该能够在strace 下看到)。我能够用 GDB 接听那个电话;不知道你为什么声称 set_thread_area 没有被调用。
  • 我的错误。我在 OP 之后使用了另一台计算机。这是一个 x86-64 ......你的 anwser 在 32 位 x86 上运行良好。我想 x86-64 上的情况有所不同。
  • @user368507 “我猜 x86-64 上的情况有所不同”——确实如此。在x86_64 上没有set_thread_area 系统调用,并且它不使用%gs 来访问线程局部变量。
  • 我不相信“GDB 无法知道%gs 所指的段是如何设置的”。 GDB 在用户模式下运行,无法读取 GDT/LDT,但它可以将 mov %gs:0x14,%eax 之类的机器代码写入它控制的某个内存中,然后跳转到它。这样,它就可以“读取”%gs:0x14
【解决方案2】:

我认为最简单的方法是读取 EAX 寄存器的内容,因为您可以看到 %gs:0x14 的值已移至 EAX。

在 GDB 中,在 0x0804841a 之后的地址处设置断点并使用 break。例如

break *0x0804841e

然后运行程序,就可以打印EAX寄存器的内容了

info registers eax

【讨论】:

  • 是的,但是问题已经提到了这种方法:注意:我知道我可以在这条指令之后简单地阅读 %eax,但这不是我关心的问题。一些代码执行sub %gs:0x14, %eax/jnz 之类的操作,而不是先将其加载到单独的寄存器中。 (例如,GCC 的 -fstack-protector-strong 会这样做来检查堆栈 cookie。)
【解决方案3】:

正如Using GDB to read MSRs 中的回答,这可以通过 gdb 8 使用寄存器 $fs_base$gs_base

【讨论】:

    猜你喜欢
    • 2020-05-04
    • 2020-07-10
    • 2011-09-30
    • 1970-01-01
    • 2015-07-14
    • 2015-06-25
    • 2018-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多