考虑下面的程序:
main.c
为什么我只在最后一次运行中得到分段错误而不是预期的中止信号?
man 7 signal:
main.c
#include <stdlib.h>
void my_asm_func(void);
__asm__(
".global my_asm_func;"
"my_asm_func:;"
"call abort;"
"ret;"
);
int main(int argc, char **argv) {
if (argv[1][0] == '0') {
abort();
} else if (argv[1][0] == '1') {
__asm__("call abort");
} else {
my_asm_func();
}
}
我编译为:
gcc -ggdb3 -O0 -o main.out main.c
然后我有:
$ ./main.out 0; echo $?
Aborted (core dumped)
134
$ ./main.out 1; echo $?
Aborted (core dumped)
134
$ ./main.out 2; echo $?
Segmentation fault (core dumped)
139
为什么我只在最后一次运行中得到分段错误而不是预期的中止信号?
man 7 signal:
SIGABRT 6 Core Abort signal from abort(3)
SIGSEGV 11 Core Invalid memory reference
确认由128 + SIGNUM规则产生的信号。
为了进行健全性检查,我还尝试从汇编中调用其他函数,如下:
#include <stdlib.h>
void my_asm_func(void);
__asm__(
".global my_asm_func;"
"my_asm_func:;"
"lea puts_message(%rip), %rdi;"
"call puts;"
"ret;"
"puts_message: .asciz \"hello puts\""
);
int main(void) {
my_asm_func();
}
这样做可以正常运行并打印:
hello puts
在Ubuntu 19.04 amd64、GCC 8.3.0和glibc 2.29中进行了测试。
我还在一个Ubuntu 18.04的Docker容器中尝试了它,结果相同,只是程序运行时会输出:
./main.out: Symbol `abort' causes overflow in R_X86_64_PC32 relocation
./main.out: Symbol `abort' causes overflow in R_X86_64_PC32 relocation
这感觉像是一个很好的线索。
call abort@plt
或call *abort@GOTPCREL(%rip)
。我不知道为什么在Ubuntu 19.04上您没有遇到这个问题。 - Peter Cordes