【问题标题】:How can I tell whether SIGILL originated from an illegal instruction or from kill -ILL?如何判断 SIGILL 是来自非法指令还是来自 kill -ILL?
【发布时间】:2013-06-28 14:30:12
【问题描述】:

在通过void (*sa_sigaction)(int, siginfo_t *, void *); 安装的信号处理程序中,如何判断 SIGILL 是源自非法指令还是源自发送 SIGILL 的某个进程?我查看了 siginfo_t 的si_pid,但这似乎是未初始化的,以防遇到非法指令,因此我无法根据它做出决定。 - 当然,我正在寻找一种更简单且可移植的解决方案,而不是阅读si_addr 处的指令代码并试图确定它是否合法。

【问题讨论】:

  • 你为什么要这样做?
  • ... 为了找到 Xenomai 线程终止的原因,其中 gdb 说“程序以信号 4 终止,非法指令。”,但在 $pc 有一个合法的核心文件中的分支指令。

标签: linux unix signals posix


【解决方案1】:

善意 SIGILL 将具有 ILL_ 值之一的si_code(例如,ILL_ILLADR)。用户请求的 SIGILL 将具有一个 SI_ 值(通常是 SI_USER)的si_code

relevant POSIX values 是:

[Kernel-generated]
ILL_ILLOPC  Illegal opcode.
ILL_ILLOPN  Illegal operand.
ILL_ILLADR  Illegal addressing mode.
ILL_ILLTRP  Illegal trap.
ILL_PRVOPC  Privileged opcode.
ILL_PRVREG  Privileged register.
ILL_COPROC  Coprocessor error.
ILL_BADSTK  Internal stack error.

[User-requested]
SI_USER     Signal sent by kill().
SI_QUEUE    Signal sent by the sigqueue().
SI_TIMER    Signal generated by expiration of a timer set by timer_settime().
SI_ASYNCIO  Signal generated by completion of an asynchronous I/O request.
SI_MESGQ    Signal generated by arrival of a message on an empty message queue.

例如,recipe in this question 给我 ILL_ILLOPN,而kill(1)kill(2) 给我零 (SI_USER)。

当然,您的实现可能会向 POSIX 列表添加值。从历史上看,user- or process-generated si_code values were <= 0,这仍然很常见。您的实现也可能有一个方便的宏来提供帮助。例如,Linux 提供:

#define SI_FROMUSER(siptr)      ((siptr)->si_code <= 0)
#define SI_FROMKERNEL(siptr)    ((siptr)->si_code > 0)

【讨论】:

  • 其实kill产生的信号的si_code应该是SI_USER,一般为0,但在某些系统上可能是别的东西。它将与所有 ILL_ 值不同。
  • @nos,是的,但是 OP 的测试表明他不能单独依赖该字段。
  • 谢谢,你是对的,当然。我被手册的措辞弄糊涂了以下值可以放在 si_code 中作为 SIGILL 信号
猜你喜欢
  • 1970-01-01
  • 2013-12-11
  • 1970-01-01
  • 1970-01-01
  • 2010-10-15
  • 1970-01-01
  • 2017-01-03
  • 2023-04-01
  • 2016-11-12
相关资源
最近更新 更多