diff --git a/arch/riscv/src/lib.rs b/arch/riscv/src/lib.rs index 1f822524d..2bc0427c3 100644 --- a/arch/riscv/src/lib.rs +++ b/arch/riscv/src/lib.rs @@ -637,6 +637,20 @@ struct RiscVArch { _dis: PhantomData, } +impl RiscVArch { + fn decode_zero(data: &[u8]) -> Option { + if ::supported() + && data.len() >= 2 + && data[0] == 0 + && data[1] == 0 + { + Some(2) + } else { + None + } + } +} + impl Architecture for RiscVArch { type Handle = CustomArchitectureHandle; @@ -687,6 +701,14 @@ impl Architecture for RiscVArch { } fn instruction_info(&self, data: &[u8], addr: u64) -> Option { + // Special handling for 0000, which is often used by compilers + // after jumps/calls in noreturn functions to trap execution + if let Some(inst_len) = Self::decode_zero(data) { + let mut res = InstructionInfo::new(inst_len, 0); + res.add_branch(BranchKind::Unresolved); + return Some(res); + } + let (inst_len, op) = match D::decode(addr, data) { Ok(Instr::Rv16(op)) => (2, op), Ok(Instr::Rv32(op)) => (4, op), @@ -752,6 +774,15 @@ impl Architecture for RiscVArch { use riscv_dis::Operand; use InstructionTextTokenKind::*; + // Special handling for 0000, which is often used by compilers + // after jumps/calls in noreturn functions to trap execution + if let Some(inst_len) = Self::decode_zero(data) { + return Some(( + inst_len, + vec![InstructionTextToken::new("trap", Instruction)], + )); + } + let inst = match D::decode(addr, data) { Ok(i) => i, _ => return None, @@ -1065,6 +1096,13 @@ impl Architecture for RiscVArch { addr: u64, il: &LowLevelILMutableFunction, ) -> Option<(usize, bool)> { + // Special handling for 0000, which is often used by compilers + // after jumps/calls in noreturn functions to trap execution + if let Some(inst_len) = Self::decode_zero(data) { + il.trap(0).append(); + return Some((inst_len, true)); + } + let max_width = self.default_integer_size(); let (inst_len, op) = match D::decode(addr, data) {