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

标签 c assembly x86 x86-64 cpu-registers

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

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

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

谢谢。

最佳答案

x86-64架构有相当多的这样的控制寄存器。其中大多数内容在没有提升权限的情况下无法读取,而那些可以读取的内容则被标记。您可能想阅读this article有关每个寄存器中位的详细说明。

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

  • 标志寄存器包含有关最近算术运算以及一些配置的信息。无需特殊权限即可使用 pushf 指令读取它。阅读 this article了解更多详情。
  • 段寄存器 csdsesssfs 、 和 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/

相关文章:

c - 返回指向 C 中常量对象的空指针

c - 如何执行逐行崩溃调试来处理 c 中的 "has stopped working"错误?

syntax - AT&T 语法如何处理其他助记符和操作数大小后缀之间的歧义?

c - 为什么我们需要读写屏障?

在 C 中比较字符串并打印存储的字符串

c++ - Cocoa 会限制 C/C++ openGL 应用程序的整体性能吗?

performance - 组装一些与 nasm 宏不相符的代码

assembly - 在汇编中将无符号字符转换为 float (为浮点向量计算做准备)

c++ - 多个数组操作

c++ - 如何在 windowsservercore docker 容器中安装 dotnetcore