是否在环0中运行abort

Does abort run in ring 0?

本文关键字:运行 abort 是否      更新时间:2023-10-16

最近我在一个博客上发现了c语言中提到的abort函数。

下面是abort函数的源代码:http://cristi.indefero.net/p/uClibc-cristi/source/tree/0_9_14/libc/stdlib/abort.c

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

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

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

顺便说一句,我试着在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;
}

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

raise(SIGABRT);
然后调用无效指令:
/* Still here?  Try to suicide with an illegal instruction */
if (been_there_done_that == 2) {
    been_there_done_that++;
    ABORT_INSTRUCTION;
}

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

您可能想看一下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