summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/riscv/src/lib.rs38
1 files changed, 38 insertions, 0 deletions
diff --git a/arch/riscv/src/lib.rs b/arch/riscv/src/lib.rs
index 1f822524..2bc0427c 100644
--- a/arch/riscv/src/lib.rs
+++ b/arch/riscv/src/lib.rs
@@ -637,6 +637,20 @@ struct RiscVArch<D: RiscVDisassembler> {
_dis: PhantomData<D>,
}
+impl<D: RiscVDisassembler> RiscVArch<D> {
+ fn decode_zero(data: &[u8]) -> Option<usize> {
+ if <D::CompressedExtension as riscv_dis::StandardExtension>::supported()
+ && data.len() >= 2
+ && data[0] == 0
+ && data[1] == 0
+ {
+ Some(2)
+ } else {
+ None
+ }
+ }
+}
+
impl<D: RiscVDisassembler> Architecture for RiscVArch<D> {
type Handle = CustomArchitectureHandle<Self>;
@@ -687,6 +701,14 @@ impl<D: RiscVDisassembler> Architecture for RiscVArch<D> {
}
fn instruction_info(&self, data: &[u8], addr: u64) -> Option<InstructionInfo> {
+ // 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<D: RiscVDisassembler> Architecture for RiscVArch<D> {
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<D: RiscVDisassembler> Architecture for RiscVArch<D> {
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) {