Struct iced_x86::SpecializedFormatter [−][src]
Fast specialized formatter with less formatting options and with a masm-like syntax. Use it if formatting speed is more important than being able to re-assemble formatted instructions.
The TraitOptions
generic parameter is a SpecializedFormatterTraitOptions
trait. It can
be used to hard code options so the compiler can create a smaller and faster formatter.
See also FastFormatter
which allows changing the options at runtime at the cost of
being a little bit slower and using a little bit more code.
This formatter is ~3.3x faster than the gas/intel/masm/nasm formatters (the time includes decoding + formatting).
Examples
use iced_x86::*; let bytes = b"\x62\xF2\x4F\xDD\x72\x50\x01"; let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE); let instr = decoder.decode(); // If you like the default options, you can also use DefaultSpecializedFormatterTraitOptions // instead of impl the options trait. struct MyTraitOptions; impl SpecializedFormatterTraitOptions for MyTraitOptions { fn space_after_operand_separator(_options: &FastFormatterOptions) -> bool { // We hard code the value to `true` which means it's not possible to // change this option at runtime, i.e., this will do nothing: // formatter.options_mut().set_space_after_operand_separator(false); true } fn rip_relative_addresses(options: &FastFormatterOptions) -> bool { // Since we return the input, we can change this value at runtime, i.e., // this works: // formatter.options_mut().set_rip_relative_addresses(false); options.rip_relative_addresses() } } type MyFormatter = SpecializedFormatter<MyTraitOptions>; let mut output = String::new(); let mut formatter = MyFormatter::new(); formatter.format(&instr, &mut output); assert_eq!(output, "vcvtne2ps2bf16 zmm2{k5}{z}, zmm6, dword bcst [rax+0x4]");
Fastest possible disassembly
For fastest possible disassembly, you should not enable the db
feature (or you should set ENABLE_DB_DW_DD_DQ
to false
)
and you should also override the unsafe verify_output_has_enough_bytes_left()
and return false
.
use iced_x86::*; struct MyTraitOptions; impl SpecializedFormatterTraitOptions for MyTraitOptions { // If you never create a db/dw/dd/dq 'instruction', we don't need this feature. const ENABLE_DB_DW_DD_DQ: bool = false; // It reserves 300 bytes at the start of format() which is enough for all // instructions. See the docs for more info. unsafe fn verify_output_has_enough_bytes_left() -> bool { false } } type MyFormatter = SpecializedFormatter<MyTraitOptions>; // Assume this is a big slice and not just one instruction let bytes = b"\x62\xF2\x4F\xDD\x72\x50\x01"; let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE); let mut output = String::new(); let mut instruction = Instruction::default(); let mut formatter = MyFormatter::new(); while decoder.can_decode() { decoder.decode_out(&mut instruction); output.clear(); formatter.format(&instruction, &mut output); // do something with 'output' here, eg.: // println!("{}", output); }
Also add this to your Cargo.toml
file:
[profile.release]
codegen-units = 1
lto = true
opt-level = 3
Using a symbol resolver
The symbol resolver is disabled by default, but it’s easy to enable it (or you can just use FastFormatter
)
use iced_x86::*; use std::collections::HashMap; let bytes = b"\x48\x8B\x8A\xA5\x5A\xA5\x5A"; let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE); let instr = decoder.decode(); struct MyTraitOptions; impl SpecializedFormatterTraitOptions for MyTraitOptions { const ENABLE_SYMBOL_RESOLVER: bool = true; } type MyFormatter = SpecializedFormatter<MyTraitOptions>; struct MySymbolResolver { map: HashMap<u64, String> } impl SymbolResolver for MySymbolResolver { fn symbol(&mut self, instruction: &Instruction, operand: u32, instruction_operand: Option<u32>, address: u64, address_size: u32) -> Option<SymbolResult> { if let Some(symbol_string) = self.map.get(&address) { // The 'address' arg is the address of the symbol and doesn't have to be identical // to the 'address' arg passed to symbol(). If it's different from the input // address, the formatter will add +N or -N, eg. '[rax+symbol+123]' Some(SymbolResult::with_str(address, symbol_string.as_str())) } else { None } } } // Hard code the symbols, it's just an example!😄 let mut sym_map: HashMap<u64, String> = HashMap::new(); sym_map.insert(0x5AA55AA5, String::from("my_data")); let mut output = String::new(); let resolver = Box::new(MySymbolResolver { map: sym_map }); let mut formatter = MyFormatter::try_with_options(Some(resolver)).unwrap(); formatter.format(&instr, &mut output); assert_eq!("mov rcx,[rdx+my_data]", output);
Implementations
impl<TraitOptions: SpecializedFormatterTraitOptions> SpecializedFormatter<TraitOptions>
[src]
#[must_use]pub fn new() -> Self
[src]
Creates a new instance of this formatter
#[must_use]pub fn with_options(symbol_resolver: Option<Box<dyn SymbolResolver>>) -> Self
[src]
This method can panic, use try_with_options() instead.
Creates a new instance of this formatter
Panics
Panics if TraitOptions::ENABLE_SYMBOL_RESOLVER
is false
and symbol_resolver.is_some()
Arguments
symbol_resolver
: Symbol resolver orNone
pub fn try_with_options(
symbol_resolver: Option<Box<dyn SymbolResolver>>
) -> Result<Self, IcedError>
[src]
symbol_resolver: Option<Box<dyn SymbolResolver>>
) -> Result<Self, IcedError>
Creates a new instance of this formatter
Errors
Fails if TraitOptions::ENABLE_SYMBOL_RESOLVER
is false
and symbol_resolver.is_some()
Arguments
symbol_resolver
: Symbol resolver orNone
#[must_use]pub fn options(&self) -> &FastFormatterOptions
[src]
Gets the formatter options (immutable)
Note that the TraitOptions
generic parameter can override any option and hard code them,
see SpecializedFormatterTraitOptions
#[must_use]pub fn options_mut(&mut self) -> &mut FastFormatterOptions
[src]
Gets the formatter options (mutable)
Note that the TraitOptions
generic parameter can override any option and hard code them,
see SpecializedFormatterTraitOptions
pub fn format(&mut self, instruction: &Instruction, output: &mut String)
[src]
Formats the whole instruction: prefixes, mnemonic, operands
Arguments
instruction
: Instructionoutput
: Output
Trait Implementations
impl<TraitOptions: SpecializedFormatterTraitOptions> Default for SpecializedFormatter<TraitOptions>
[src]
Auto Trait Implementations
impl<TraitOptions> !RefUnwindSafe for SpecializedFormatter<TraitOptions>
impl<TraitOptions> !Send for SpecializedFormatter<TraitOptions>
impl<TraitOptions> !Sync for SpecializedFormatter<TraitOptions>
impl<TraitOptions> Unpin for SpecializedFormatter<TraitOptions>
impl<TraitOptions> !UnwindSafe for SpecializedFormatter<TraitOptions>
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
pub fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
pub fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,