在 c 中访问进程独立寄存器的值

Accessing values of process independent registers in c

许多寄存器,如数据寄存器,包含与当前正在执行的进程相对应的值。但是,有些寄存器对所有进程都是通用的

我想要读取某些非进程特定的寄存器,并且可以从 2 个不同的进程访问并且仍然能够获得相同的值。

我需要 x86-64 架构的代码。 (这 3 个命令 uname -m,-p,-i return x86_64,在我的桌面上输入时)

谢谢。

x86-64架构有不少这样的控制寄存器。如果没有提升的权限,它们中的大多数是无法读取的,那些可以被标记的。您可能需要阅读 this article 以获得每个寄存器中的位的详细描述。

在Linux上,您可以使用iopl系统调用获得相关的提升权限。 iopl(3) 为您提供所需的所有权限。

  • 标志寄存器包含有关最近的算术运算以及一些配置的信息。无需特殊权限即可使用 pushf 指令读取。阅读 this article 了解更多详情。
  • 段寄存器 csdsesssfsgs 包含段选择器。在现代操作系统上,这些通常对所有进程都是固定的,并且可以使用 mov r16,segr 读取而无需提升权限。
  • cr0 寄存器包含与内存保护相关的配置。它的低 16 位可以被任何进程使用 rmsw 指令读取,其余位可以使用 mov r32,cr0 以提升的权限读取,就像所有其他控制寄存器一样。
  • cr2 寄存器包含最后一个页面错误的地址。
  • cr3 寄存器包含页面目录的地址。
  • cr4 寄存器包含额外的 CPU 配置。
  • cr8 寄存器包含有关任务优先级的信息

还有一堆特定于模型的寄存器,可以使用 rmsr 指令读取。

要读取这些寄存器,请使用内联汇编。这是前面提到的所有寄存器的内联汇编。要阅读 rflags 寄存器,请参阅 了解一些注意事项。

/* read rflags */
uint64_t rflags;
asm("pushf; popf %0" : "=rm"(rflags));

/* read segment register, replace sr with the segment you want */
uint16_t seg;
asm("mov %sr,%0" : "=rm"(seg));

/* read low bits of cr0 */
/* on some CPUs, only the low 16 bits are correct,
/* on others all 32 bit are correct */
uint32_t cr0;
asm("smsw %0" : "=r"(cr0));

/* everything below here requires elevated privileges */

/* read control register, replace cr with register name */
uint64_t cr;
asm("mov %cr,%0" : "=rm"(cr));

/* read model specific register. msr contains register number */
uint32_t msr_no = 0xC0000080, msr_hi, msr_lo;
asm("rdmsr" : "=a"(msr_lo), "=d"(msr_hi) : "c"(msr_no));
uint64_t msr_val = (uint64_)msr_hi << 32 | msr_lo;