#[derive(Copy, Clone, Debug, PartialEq, Eq)] pubenum OpcodeX86 {
Null,
FrameBased {
stack_offset_in_bytes: u16,
saved_regs: [Option<RegisterNameX86>; 5],
},
FramelessImmediate {
stack_size_in_bytes: u16,
saved_regs: [Option<RegisterNameX86>; 6],
},
FramelessIndirect { /// Offset from the start of the function into the middle of a `sub` /// instruction, pointing right at the instruction's "immediate" which /// is a u32 value with the offset we need. (NOTE: not divided by anything!)
immediate_offset_from_function_start: u8,
/// An offset to add to the loaded stack size. /// This allows the stack size to differ slightly from the `sub`, to /// compensate for any function prologue that pushes a bunch of /// pointer-sized registers. This adjust value includes the return /// address on the stack. For example, if the function begins with six push /// instructions, followed by a sub instruction, then stack_adjust_in_bytes /// is 28: 4 bytes for the return address + 6 * 4 for each pushed register.
stack_adjust_in_bytes: u8,
/// The registers, in the order that they need to be popped in when /// returning / unwinding from this function. (Reverse order from /// function prologue!) /// Can have leading `None`s.
saved_regs: [Option<RegisterNameX86>; 6],
},
Dwarf {
eh_frame_fde: u32,
},
InvalidFrameless,
UnrecognizedKind(u8),
}
impl OpcodeX86 { pubfn parse(opcode: u32) -> Self { match OpcodeBitfield::new(opcode).kind() {
OPCODE_KIND_NULL => OpcodeX86::Null,
OPCODE_KIND_X86_FRAMEBASED => OpcodeX86::FrameBased {
stack_offset_in_bytes: (((opcode >> 16) & 0xff) as u16) * 4,
saved_regs: [
RegisterNameX86::parse(((opcode >> 12) & 0b111) as u8),
RegisterNameX86::parse(((opcode >> 9) & 0b111) as u8),
RegisterNameX86::parse(((opcode >> 6) & 0b111) as u8),
RegisterNameX86::parse(((opcode >> 3) & 0b111) as u8),
RegisterNameX86::parse((opcode & 0b111) as u8),
],
},
OPCODE_KIND_X86_FRAMELESS_IMMEDIATE => { let stack_size_in_bytes = (((opcode >> 16) & 0xff) as u16) * 4; let register_count = (opcode >> 10) & 0b111; let register_permutation = opcode & 0b11_1111_1111; let saved_registers = match decode_permutation_6(register_count, register_permutation) {
Ok(regs) => regs,
Err(_) => return OpcodeX86::InvalidFrameless,
};
OpcodeX86::FramelessImmediate {
stack_size_in_bytes,
saved_regs: [
RegisterNameX86::parse(saved_registers[0]),
RegisterNameX86::parse(saved_registers[1]),
RegisterNameX86::parse(saved_registers[2]),
RegisterNameX86::parse(saved_registers[3]),
RegisterNameX86::parse(saved_registers[4]),
RegisterNameX86::parse(saved_registers[5]),
],
}
}
OPCODE_KIND_X86_FRAMELESS_INDIRECT => { let immediate_offset_from_function_start = (opcode >> 16) as u8; let stack_adjust_in_bytes = ((opcode >> 13) & 0b111) as u8 * 4; let register_count = (opcode >> 10) & 0b111; let register_permutation = opcode & 0b11_1111_1111; let saved_registers = match decode_permutation_6(register_count, register_permutation) {
Ok(regs) => regs,
Err(_) => return OpcodeX86::InvalidFrameless,
};
OpcodeX86::FramelessIndirect {
immediate_offset_from_function_start,
stack_adjust_in_bytes,
saved_regs: [
RegisterNameX86::parse(saved_registers[0]),
RegisterNameX86::parse(saved_registers[1]),
RegisterNameX86::parse(saved_registers[2]),
RegisterNameX86::parse(saved_registers[3]),
RegisterNameX86::parse(saved_registers[4]),
RegisterNameX86::parse(saved_registers[5]),
],
}
}
OPCODE_KIND_X86_DWARF => OpcodeX86::Dwarf {
eh_frame_fde: (opcode & 0xffffff),
},
kind => OpcodeX86::UnrecognizedKind(kind),
}
}
}
impl Display for OpcodeX86 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { matchself {
OpcodeX86::Null => {
write!(f, "(uncovered)")?;
}
OpcodeX86::FrameBased {
stack_offset_in_bytes,
saved_regs,
} => { // ebp was set to esp before the saved registers were pushed. // The first pushed register is at ebp - 4 (== CFA - 12), the last at ebp - stack_offset_in_bytes.
write!(f, "CFA=reg6+8: reg6=[CFA-8], reg16=[CFA-4]")?; let max_count = (*stack_offset_in_bytes / 4) as usize; letmut offset = *stack_offset_in_bytes + 8; // + 2 for rbp, return address for reg in saved_regs.iter().rev().take(max_count) { iflet Some(reg) = reg {
write!(f, ", {}=[CFA-{}]", reg.dwarf_name(), offset)?;
}
offset -= 4;
}
}
OpcodeX86::FramelessImmediate {
stack_size_in_bytes,
saved_regs,
} => { if *stack_size_in_bytes == 0 {
write!(f, "CFA=reg7:",)?;
} else {
write!(f, "CFA=reg7+{}:", *stack_size_in_bytes)?;
}
write!(f, " reg16=[CFA-4]")?; letmut offset = 2 * 4; for reg in saved_regs.iter().rev().flatten() {
write!(f, ", {}=[CFA-{}]", reg.dwarf_name(), offset)?;
offset += 4;
}
}
OpcodeX86::FramelessIndirect {
immediate_offset_from_function_start,
stack_adjust_in_bytes,
saved_regs,
} => {
write!(
f, "CFA=[function_start+{}]+{}",
immediate_offset_from_function_start, stack_adjust_in_bytes
)?;
write!(f, " reg16=[CFA-4]")?; letmut offset = 2 * 4; for reg in saved_regs.iter().rev().flatten() {
write!(f, ", {}=[CFA-{}]", reg.dwarf_name(), offset)?;
offset += 4;
}
}
OpcodeX86::Dwarf { eh_frame_fde } => {
write!(f, "(check eh_frame FDE 0x{:x})", eh_frame_fde)?;
}
OpcodeX86::InvalidFrameless => {
write!(
f, "!! frameless immediate or indirect with invalid permutation encoding"
)?;
}
OpcodeX86::UnrecognizedKind(kind) => {
write!(f, "!! Unrecognized kind {}", kind)?;
}
}
Ok(())
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.