Struct iced_x86::SpecializedFormatter
source · pub struct SpecializedFormatter<TraitOptions: SpecializedFormatterTraitOptions> { /* private fields */ }
Expand description
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;
// For a few percent faster code, you can also override `verify_output_has_enough_bytes_left()` and return `false`
// 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§
source§impl<TraitOptions: SpecializedFormatterTraitOptions> SpecializedFormatter<TraitOptions>
impl<TraitOptions: SpecializedFormatterTraitOptions> SpecializedFormatter<TraitOptions>
sourcepub fn try_with_options(
symbol_resolver: Option<Box<dyn SymbolResolver>>
) -> Result<Self, IcedError>
pub fn try_with_options( 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
sourcepub fn options(&self) -> &FastFormatterOptions
pub fn options(&self) -> &FastFormatterOptions
Gets the formatter options (immutable)
Note that the TraitOptions
generic parameter can override any option and hard code them,
see SpecializedFormatterTraitOptions
sourcepub fn options_mut(&mut self) -> &mut FastFormatterOptions
pub fn options_mut(&mut self) -> &mut FastFormatterOptions
Gets the formatter options (mutable)
Note that the TraitOptions
generic parameter can override any option and hard code them,
see SpecializedFormatterTraitOptions
sourcepub fn format(&mut self, instruction: &Instruction, output: &mut String)
pub fn format(&mut self, instruction: &Instruction, output: &mut String)
Formats the whole instruction: prefixes, mnemonic, operands
Arguments
instruction
: Instructionoutput
: Output