如何判断SIGILL是来自非法指令还是来自kill -ILL?

Arm*_*ali 3 unix linux posix signals

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

pil*_*row 7

善意 SIGILL将具有si_code所述ILL_值中的一个(例如,IL_ILLADR)的.用户请求的SIGILL将具有si_codeSI_值之一(通常为SI_USER).

相关的POSIX值是:

[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.
Run Code Online (Sandbox Code Playgroud)

举例来说,在这个问题上的食谱给我ILL_ILLOPN,而kill(1)kill(2)给我零(SI_USER).

当然,您的实现可能会为POSIX列表添加值.从历史上看,用户或流程生成的si_code值<= 0,这仍然很常见.您的实现也可能有一个方便的宏来协助.例如,Linux提供:

#define SI_FROMUSER(siptr)      ((siptr)->si_code <= 0)
#define SI_FROMKERNEL(siptr)    ((siptr)->si_code > 0)
Run Code Online (Sandbox Code Playgroud)