问题描述
在x86(无论是64位或32位)的Linux -
例如:
On x86 (either 64-bit or 32-bit) Linux --for example:
void signal_handler(int) {
// want to know where the program is interrupted ...
}
int main() {
...
signal(SIGALRM, signal_handler);
alarm(5);
...
printf(...); <------- at this point, we trigger signal_handler
...
}
在signal_handler,我们怎么能知道我们是在以printf的主要打断()?
In signal_handler, how can we know we are interrupted at printf in main()?
推荐答案
使用 SA_SIGINFO在其中sa_flags设置。
Use sigaction with SA_SIGINFO set in sa_flags.
原型code:
#define _GNU_SOURCE 1 /* To pick up REG_RIP */
#include <stdio.h>
#include <signal.h>
#include <assert.h>
static void
handler(int signo, siginfo_t *info, void *context)
{
const ucontext_t *con = (ucontext_t *)context;
/* I know, never call printf from a signal handler. Meh. */
printf("IP: %lx\n", con->uc_mcontext.gregs[REG_RIP]);
}
int
main(int argc, char *argv[])
{
struct sigaction sa = { };
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
assert(sigaction(SIGINT, &sa, NULL) == 0);
for (;;);
return 0;
}
运行它,按按Ctrl-C 骨节病>。 (使用按Ctrl - \\ 骨节病>终止...)
Run it and hit . (Use to terminate...)
这是x86_64的。对于32位x86,使用 REG_EIP
而不是 REG_RIP
。
This is for x86_64. For 32-bit x86, use REG_EIP
instead of REG_RIP
.
当然,如果你实际上是在一个库函数(如的printf
)或系统调用(如写
)时,RIP / EIP寄存器可能指向有趣的地方...
Of course, if you are actually in a library function (like printf
) or a system call (like write
), the RIP/EIP register might point somewhere funny...
您可能需要使用抓取堆栈。
You might want to use libunwind to crawl the stack.
这篇关于在信号处理程序,怎么知道那里的程序被中断?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!