中止是否在0环中运行?

时间:2011-08-26 09:32:07

标签: c++ c x86

这些天我在C中找到了一个提到中止功能的博客。

以下是中止功能的源代码: http://cristi.indefero.net/p/uClibc-cristi/source/tree/0_9_14/libc/stdlib/abort.c

我发现它使用hlt指令(我的电脑是x86)。

但似乎hlt必须在第0环中运行。 (参考维基http://en.wikipedia.org/wiki/HLT

似乎中止正在用户空间中运行。因此,在中止中使用hlt指令似乎是非法的。

BTW,我尝试在linux和windows中运行hlt。但我遇到了错误。

在linux中:

#include <iostream>
using namespace std;

#define HLT_INST asm("hlt")

int main(){
  cout<<"whill run halt"<<endl;

  HLT_INST; //result in SIGSEGV error
  return 0;
}

在Windows中:

cout<<"will run hlg"<<endl;
/*Unhandled exception at 0x0040101d in test_learn.exe: 0xC0000096: Privileged instruction.
*/
__asm{
    hlt;
}

2 个答案:

答案 0 :(得分:6)

abort函数仅在发送hlt失败后才使用SIGABRT指令。如果您阅读源代码,该函数首先尝试:

raise(SIGABRT);

然后调用无效指令:

/* Still here?  Try to suicide with an illegal instruction */
if (been_there_done_that == 2) {
    been_there_done_that++;
    ABORT_INSTRUCTION;
}

所以你是对的,hlt需要第0个特权。这正是使它成为无效指令的原因。执行它会调用一个无效的指令处理程序,在你的情况下(我想)SIGSEGV。

答案 1 :(得分:3)

您可能需要查看SIGABRT POSIX信号

例如,如果您在使用GDB进行调试时遇到abort()来电,则会看到:

Program received signal SIGABRT, Aborted.
0x0000003c47e352d5 in raise () from /lib64/libc.so.6
(gdb) where
#0  0x0000003c47e352d5 in raise () from /lib64/libc.so.6
#1  0x0000003c47e36beb in abort () from /lib64/libc.so.6
#2  0x0000000000400721 in main (argc=1, argv=0x7fffffffde18) at test.c:27

正如@kbok所提到的,abort函数的反汇编包括hlt指令:

(gdb)  disassemble abort
Dump of assembler code for function abort:
...
0x0000003c47e36b08 <+152>:  hlt
...

(但确实SEGFAULT indeed

(gdb) break *0x0000003c47e36b08
Breakpoint 2 at 0x3c47e36b08
(gdb) jump *0x0000003c47e36b08
Breakpoint 2, 0x0000003c47e36b08 in abort () from /lib64/libc.so.6
(gdb) next
Single stepping until exit from function abort,which has no line number information.
Program received signal SIGSEGV, Segmentation fault.
0x0000003c47e36b08 in abort () from /lib64/libc.so.6