许多寄存器(例如数据寄存器)包含与当前正在执行的进程相对应的值。但是,有一些寄存器是所有进程共用的
我想要对一些非特定于进程的寄存器进行读取访问,并且可以从 2 个不同的进程进行访问,并且仍然能够获得相同的值。
我需要 x86-64 架构的代码。 (在桌面上键入时,这 3 个命令 uname -m、-p、-i 返回 x86_64)
谢谢。
最佳答案
x86-64架构有相当多的这样的控制寄存器。其中大多数内容在没有提升权限的情况下无法读取,而那些可以读取的内容则被标记。您可能想阅读this article有关每个寄存器中位的详细说明。
在Linux上,您可以使用iopl
系统调用来获取相关的提升权限。 iopl(3)
为您提供所需的所有权限。
- 标志寄存器包含有关最近算术运算以及一些配置的信息。无需特殊权限即可使用
pushf
指令读取它。阅读 this article了解更多详情。 - 段寄存器
cs
、ds
、es
、ss
、fs
、 和 gs 包含段选择器。在现代操作系统上,这些通常对于所有进程都是固定的,并且可以使用mov r16,segr
读取,而无需提升权限。 - cr0 寄存器包含与内存保护相关的配置。任何进程都可以使用 rmsw 指令读取其低 16 位,其余位可以像所有其他控制寄存器一样使用 mov r32,cr0 以提升的权限读取。
- cr2 寄存器包含最后一个页面错误的地址。
- cr3 寄存器包含页目录的地址。
- cr4 寄存器包含额外的 CPU 配置。
- cr8 寄存器包含有关任务优先级的信息
还有一堆特定于模型的寄存器,可以使用 rmsr
指令读取。
要读取这些寄存器,请使用内联汇编。这是前面提到的所有寄存器的内联汇编。要读取 rflags
寄存器,另请参阅 this question一些注意事项。
/* 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;
关于c - 在c中访问进程独立寄存器的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45274325/