#[repr(C)]
#[derive(Default, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct signalfd_siginfo
{
pub ssi_signo: u32,
pub ssi_errno: i32,
pub ssi_code: i32,
pub ssi_pid: i32,
pub ssi_uid: u32,
pub ssi_fd: i32,
pub ssi_tid: u32,
pub ssi_band: u32,
pub ssi_overrun: u32,
pub ssi_trapno: u32,
pub ssi_status: i32,
pub ssi_int: i32,
pub ssi_ptr: u64,
pub ssi_utime: u64,
pub ssi_stime: u64,
pub ssi_addr: u64,
pub ssi_addr_lsb: u16,
_pad2: u16,
pub ssi_syscall: i32,
pub ssi_call_addr: u64,
pub ssi_arch: u32,
_pad: [u8; 28],
}
impl signalfd_siginfo
{
#[inline(always)]
pub(crate) fn parse_signal(&self) -> ParsedSignal
{
use self::ParsedSignal::*;
if self.is_kernel_generated()
{
if likely!(self.ssi_signo < u8::MAX as u32)
{
match self.ssi_signo as u8
{
Signal::SIGILL_ => self.kernel_generated_Fault::<IllegalInstructionCode, _>(FaultCode::SIGILL),
Signal::SIGFPE_ => self.kernel_generated_Fault::<ArithmeticErrorCode, _>(FaultCode::SIGFPE),
Signal::SIGSEGV_ => self.kernel_generated_Fault::<SegmentationFaultCode, _>(FaultCode::SIGSEGV),
Signal::SIGTRAP_ => self.kernel_generated_Fault::<TrapCode, _>(FaultCode::SIGTRAP),
#[cfg(any(target_arch = "mips64", target_arch = "sparc64"))] Signal::SIGEMT_ => self.kernel_generated_Fault::<EmulatorTrapCode, _>(FaultCode::SIGEMT),
Signal::SIGCHLD_ => self.kernel_generated::<ChildCode, _>(|child_code|
{
debug_assert_eq!(self.ssi_errno, 0);
Child
{
process_identifier: ProcessIdentifier::try_from(self.ssi_pid).expect("Zero or negative process identifier from kernel"),
user_identifier: UserIdentifier::from(self.ssi_uid),
status: ChildStatus::parse(self.ssi_status).expect("Invalid status from kernel"),
user_cpu_time_consumed_in_clock_ticks: ClockTicks::from(self.ssi_utime),
system_cpu_time_consumed_in_clock_ticks: ClockTicks::from(self.ssi_stime),
child_code,
}
}),
Signal::SIGIO_ => self.kernel_generated::<PollCode, _>(|poll_code|
{
debug_assert_eq!(self.ssi_errno, 0);
Poll
{
signal: Signal::SIGIO,
band_event: self.ssi_band,
file_descriptor: self.ssi_fd,
poll_code,
}
}),
Signal::SIGSYS_ => self.kernel_generated::<SystemCallCode, _>(|system_call_code| SeccompSystemCall
{
seccomp_ret_data: self.ssi_errno,
system_call_number: UnconstrainedSystemCallNumber::from(self.ssi_syscall),
address: VirtualAddress::from(self.ssi_call_addr),
audit_architecture: AuditArchitecture::optional_architecture(self.ssi_arch),
system_call_code,
}),
Signal::SIGBUS_ => if self.ssi_code <= BusCode::InclusiveMaximum.into()
{
Fault
{
address: VirtualAddress::from(self.ssi_addr),
#[cfg(any(target_arch = "mips64", target_arch = "sparc64"))] trap_number: self.ssi_trapno,
#[cfg(any(target_arch = "aarch64", target_arch = "powerpc64"))] trap_number: self.ssi_errno,
fault_code: FaultCode::SIGBUS(unsafe { transmute(self.ssi_code) })
}
}
else if (self.ssi_code >= HardwareErrorMachineCheckBusCode::ActionRequired.into()) && (self.ssi_code <= HardwareErrorMachineCheckBusCode::ActionOptional.into())
{
debug_assert_eq!(self.ssi_errno, 0);
FaultMachineCheck
{
address: VirtualAddress::from(self.ssi_addr),
#[cfg(any(target_arch = "mips64", target_arch = "sparc64"))] trap_number: self.ssi_trapno,
#[cfg(any(target_arch = "aarch64", target_arch = "powerpc64"))] trap_number: self.ssi_errno,
hardware_error_machine_check_bus_code: unsafe { transmute(self.ssi_code) },
address_least_significant_bit: self.ssi_addr_lsb,
}
}
else
{
self.kernel_generated_fallthrough()
},
_ => self.kernel_generated_fallthrough()
}
}
else
{
self.kernel_generated_fallthrough()
}
}
else
{
let signal = Signal::parse_raw_signal_number_u32(self.ssi_signo);
match self.ssi_code
{
SI_TIMER => UserspaceTimer
{
signal,
error_number: self.ssi_errno,
timer_identifier: self.ssi_tid,
overrun_count: self.ssi_overrun,
pointer: VirtualAddress::from(self.ssi_ptr),
int: self.ssi_int,
},
SI_SIGIO => UserspacePoll
{
signal,
error_number: self.ssi_errno,
band_event: self.ssi_band,
file_descriptor: self.ssi_fd,
},
_ =>
{
let process_identifier = ProcessIdentifier::try_from(self.ssi_pid);
let user_identifier = UserIdentifier::from(self.ssi_uid);
if self.ssi_code < SI_USER
{
UserspaceRealTime
{
signal,
error_number: self.ssi_errno,
process_identifier,
user_identifier,
pointer: VirtualAddress::from(self.ssi_ptr),
int: self.ssi_int,
userspace_signal_code: UserspaceSignalCode::from_si_code(self.ssi_code),
}
}
else
{
#[cfg(target_arch = "sparc64")]
assert_ne!(si_code, SI_NOINFO, "SI_NOINFO on sparc64 is not supported");
Kill
{
signal: signal.expect("Linux kernel specified an invalid signal number"),
process_identifier: process_identifier.expect("Zero or negative process identifier from kernel"),
user_identifier,
}
}
}
}
}
}
#[inline(always)]
fn is_kernel_generated(&self) -> bool
{
(self.ssi_code > SI_USER) && (self.ssi_code < SI_KERNEL)
}
#[inline(always)]
fn kernel_generated<C: Code, Constructor: FnOnce(C) -> ParsedSignal>(&self, constructor: Constructor) -> ParsedSignal
{
let inclusive_maximum = C::InclusiveMaximum.into();
if self.ssi_code <= inclusive_maximum
{
constructor(C::rehydrate(self.ssi_code))
}
else
{
self.kernel_generated_fallthrough()
}
}
#[inline(always)]
fn kernel_generated_Fault<C: Code, Constructor: FnOnce(C) -> FaultCode>(&self, fault_code: Constructor) -> ParsedSignal
{
self.kernel_generated::<C, _>(|code| ParsedSignal::Fault
{
address: VirtualAddress::from(self.ssi_addr),
#[cfg(any(target_arch = "mips64", target_arch = "sparc64"))] trap_number: self.ssi_trapno,
#[cfg(any(target_arch = "arrch64", target_arch = "powerpc64"))] trap_number: self.ssi_errno,
fault_code: fault_code(code)
})
}
#[inline(always)]
fn kernel_generated_fallthrough(&self) -> ParsedSignal
{
use self::ParsedSignal::*;
let signal = Signal::parse_raw_signal_number_u32(self.ssi_signo).expect("Kernel specified an invalid signal number");
debug_assert_eq!(self.ssi_errno, 0);
if self.ssi_code <= PollCode::InclusiveMaximum.into()
{
Poll
{
signal,
band_event: self.ssi_band,
file_descriptor: self.ssi_fd,
poll_code: unsafe { transmute(self.ssi_code) },
}
}
else
{
Kill
{
signal,
process_identifier: ProcessIdentifier::try_from(self.ssi_pid).expect("Zero or negative process identifier from kernel"),
user_identifier: UserIdentifier::from(self.ssi_uid),
}
}
}
}