Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 为什么是segfault而不是特权指令错误?_Linux_Performance_Assembly_X86 - Fatal编程技术网

Linux 为什么是segfault而不是特权指令错误?

Linux 为什么是segfault而不是特权指令错误?,linux,performance,assembly,x86,Linux,Performance,Assembly,X86,我试图在用户模式下执行特权指令rdmsr,我希望得到某种特权错误,但我得到了一个segfault。我已经检查了asm,并且正在将0x186加载到ecx,根据第1171页的 segfault的原因是什么,我如何修改下面的代码来修复它? 我想在破解内核模块之前解决这个问题,因为我不想让这个segfault炸毁我的内核 更新:我运行的是英特尔(R)至强(R)CPU X3470 #define _GNU_SOURCE #include <stdio.h> #include <stdl

我试图在用户模式下执行特权指令
rdmsr
,我希望得到某种特权错误,但我得到了一个segfault。我已经检查了
asm
,并且正在将
0x186
加载到
ecx
,根据第1171页的

segfault的原因是什么,我如何修改下面的代码来修复它?

我想在破解内核模块之前解决这个问题,因为我不想让这个segfault炸毁我的内核

更新:我运行的是
英特尔(R)至强(R)CPU X3470

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

#include <sched.h>
#include <assert.h>

uint64_t
read_msr(int ecx)
{
    unsigned int a, d;
    __asm __volatile("rdmsr" : "=a"(a), "=d"(d) : "c"(ecx));
    return ((uint64_t)a) | (((uint64_t)d) << 32);
}

int main(int ac, char **av)
{
    uint64_t start, end;
    cpu_set_t cpuset;
    unsigned int c = 0x186;
    int i = 0;

    CPU_ZERO(&cpuset);
        CPU_SET(i, &cpuset);
        assert(sched_setaffinity(0, sizeof(cpuset), &cpuset) == 0);

    printf("%lu\n", read_msr(c));
    return 0;
}
定义GNU源
#包括
#包括
#包括
#包括
#包括
uint64\u t
读取msr(内部ecx)
{
无符号整数a,d;
__挥发性物质(“rdmsr”):“=a”(a),“=d”(d):“c”(ecx));

return((uint64_t)a)|((uint64_t)d)我将尝试回答的问题:为什么上面的代码会导致
SIGSEGV
而不是
SIGILL
,尽管代码没有内存错误,但却是一条非法指令(从非特权用户速度调用的特权指令)


我希望得到一个带有
si_code
ILL_PRVOPC
SIGILL
,而不是segfault。你的问题已经问了3年了,今天,我发现了同样的行为。我也很失望:-(


故障的原因是什么

原因似乎是Linux内核代码决定发送
SIGSEGV
看看函数的最后一行

在中,您得到了其他汇编指令的列表,这些指令作为
SIGSEGV
传播到用户空间,尽管它们实际上是一般保护故障。我发现了您的问题,因为我使用
cli
触发了该行为

我如何修改下面的代码来修复它

从Linux内核4.9开始,我不知道有什么可靠的方法来区分内存错误(我认为是
SIGSEGV
)和来自用户空间的特权指令错误

识别这些情况的方法可能非常粗糙且不可移植。当特权指令导致
SIGSEGV
时,
siginfo\u t
SIU code
设置为一个值,该值未直接列在
man 2 sigaction
SIGSEGV
部分中。记录的值为
SEGV MAPERR
SEGV_ACCERR
SEGV_PKUERR
,但是我在我的系统上得到了
SI_内核(0x80)。根据手册页,
SI_内核
是一个代码“可以为任何信号放入SI_代码中”。在图中,您可以看到
SIGSEGV{SI_signo signo signo SIGSEGV,SI_code=SI_内核,SI_addr=0}
。负责的内核代码是

也可以为字符串grep
dmesg

请永远不要使用这两种方法来区分生产系统上的GPF和内存错误


代码的具体解决方案:不要从用户空间运行
rdmsr
。但是如果您正在寻找一种通用方法来找出程序为什么收到
SIGSEGV

请参阅
dmesg
输出,我想您会看到
陷阱,这表明您正在尝试执行privil来自usermode的ege指令。@rakib,dmesg的输出:
通用保护ip:4005d0 sp:7fff6dea4070错误:0
。我想这就是我需要知道的。我会接受这个答案,并单独问后续问题。真的需要在单独的问题中问这个吗?你得到了你想要的。我对此很好奇,因为我正在深入研究要了解更多的asm
asm
,我想更全面地了解什么样的事情会导致伪
segfaults