Skip to content

Commit

Permalink
Attempt to fix s390x
Browse files Browse the repository at this point in the history
The MachBuffer was registering trap codes with the first byte of the
trap, but the SIGILL handler was expecting it to be registered with the
last byte of the trap. Exploit that SIGILL is always represented with a
2-byte instruction and always march 2-backwards for SIGILL, continuing
to march backwards 1 byte for SIGFPE-generating instructions.
  • Loading branch information
alexcrichton committed Mar 14, 2023
1 parent 9863e58 commit 0fd035c
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 9 deletions.
3 changes: 2 additions & 1 deletion cranelift/codegen/src/isa/s390x/inst/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3587,7 +3587,8 @@ impl Inst {
if let Some(s) = state.take_stack_map() {
sink.add_stack_map(StackMapExtent::UpcomingBytes(2), s);
}
put_with_trap(sink, &enc_e(0x0000), trap_code);
sink.add_trap(trap_code);
sink.put_data(&Inst::TRAP_OPCODE);
}
&Inst::TrapIf { cond, trap_code } => {
let label = sink.defer_trap(trap_code, state.take_stack_map());
Expand Down
22 changes: 14 additions & 8 deletions crates/runtime/src/traphandlers/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,15 +184,21 @@ unsafe fn get_pc_and_fp(cx: *mut libc::c_void, _signum: libc::c_int) -> (*const
// On s390x, SIGILL and SIGFPE are delivered with the PSW address
// pointing *after* the faulting instruction, while SIGSEGV and
// SIGBUS are delivered with the PSW address pointing *to* the
// faulting instruction. To handle this, the code generator registers
// any trap that results in one of "late" signals on the last byte
// of the instruction, and any trap that results in one of the "early"
// signals on the first byte of the instruction (as usual). This
// means we simply need to decrement the reported PSW address by
// one in the case of a "late" signal here to ensure we always
// correctly find the associated trap handler.
// faulting instruction.
//
// SIGILL is currently always generated with a 2-byte opcode of
// 0x0000, so for SIGILL the program counter is moved back 2 bytes.
//
// For SIGFPE the code generator registers traps on the last byte
// of the instruction, meaning we need to decrement the reported
// PSW address by one in the case of a "late" signal here to ensure
// we always correctly find the associated trap handler.
//
// For all other signals traps are registered with the first byte of
// the instruction so no extra handling is necessary.
let trap_offset = match _signum {
libc::SIGILL | libc::SIGFPE => 1,
libc::SIGILL => 2,
libc::SIGFPE => 1,
_ => 0,
};
let cx = &*(cx as *const libc::ucontext_t);
Expand Down

0 comments on commit 0fd035c

Please sign in to comment.