在 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 了解更多详情。
- 段寄存器
cs
、ds
、es
、ss
、fs
和 gs
包含段选择器。在现代操作系统上,这些通常对所有进程都是固定的,并且可以使用 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;
许多寄存器,如数据寄存器,包含与当前正在执行的进程相对应的值。但是,有些寄存器对所有进程都是通用的
我想要读取某些非进程特定的寄存器,并且可以从 2 个不同的进程访问并且仍然能够获得相同的值。
我需要 x86-64 架构的代码。 (这 3 个命令 uname -m,-p,-i return x86_64,在我的桌面上输入时)
谢谢。
x86-64架构有不少这样的控制寄存器。如果没有提升的权限,它们中的大多数是无法读取的,那些可以被标记的。您可能需要阅读 this article 以获得每个寄存器中的位的详细描述。
在Linux上,您可以使用iopl
系统调用获得相关的提升权限。 iopl(3)
为您提供所需的所有权限。
- 标志寄存器包含有关最近的算术运算以及一些配置的信息。无需特殊权限即可使用
pushf
指令读取。阅读 this article 了解更多详情。 - 段寄存器
cs
、ds
、es
、ss
、fs
和gs
包含段选择器。在现代操作系统上,这些通常对所有进程都是固定的,并且可以使用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;