GS base 加上 offset 不对应 gs:offset

GS base added up with offset does not correspond to gs:offset

当使用 GDB 调试 Linux 内核 运行 作为 QEMU 来宾时,我遇到了以下指令:

mov    rcx,QWORD PTR gs:0x1fbc0

问题是 rcx 寄存器确实包含 gs 基数加上值 0x1fbc0。这是我在 gdb 中发现的:

#Before execution of the instruction
(gdb) p/x $rcx
 = 0x0
(gdb) p/x $gs_base
 = 0xffff888237c80000

#Execution of the instruction
(gdb) si
vm_unmapped_area (info=info@entry=0xffffc90000eb7d70) at mm/mmap.c:2002

#Completely unclear value
(gdb) p/x $rcx
 = 0xffff888105e79980

我的第一个想法是 GDB 错误地报告了 GS 基地,但后来我从 rdmsr 工具中得到了同样的结果

$ sudo rdmsr -p 2 0xc0000101
ffff888237c80000

让事情变得更加不清楚。

为什么 gs:0x1fbc0 不会导致 $gs_base + 0x1fbc0

mov与内存源加载数据$gs_base+0x1fbc0指示的线性地址,它不加载线性将自己定位到目的地。

为了解决您的一些进一步评论,MASM-style 方言的 qword ptr 关键字表示内存访问而不是加载立即数。所有内存访问都包含在方括号 [...] 中并且其他所有内容(立即或寄存器访问)不包含在方括号中的规则是 NASM-ism。在 MASM 中,目标可以有关键字 {size} ptr 或括号 [...] 或仅指定一个变量名以指示汇编器使用内存加载。缺少其中任何一个,或者通过指定一个带有 offset 关键字前缀的变量名,它将进行编码以便加载一个立即数。

即使您的示例是立即加载,它也只是 mov rcx, 0x1fbc0 而没有 gs,因为没有 immediate-to-register 格式指令包含具有任何效果的段覆盖前缀。从技术上讲,您可以在这样的指令前面加上一个 gs 前缀,实际上它通常仍然可以很好地解码。但是, gs 前缀将毫无用处。反汇编器(如 gdb 的)希望不会显示带有 gs: 前缀的此类指令的源立即操作数。