diff --git a/fugue-core/src/lifter.rs b/fugue-core/src/lifter.rs
index 23fc586..1ff020d 100644
--- a/fugue-core/src/lifter.rs
+++ b/fugue-core/src/lifter.rs
@@ -1,59 +1,30 @@
use std::cell::{Cell, Ref, RefCell};
-use std::mem;
use fugue_ir::disassembly::lift::ArenaVec;
-use fugue_ir::disassembly::{ContextDatabase, IRBuilderArena, PCodeData, ParserContext};
+use fugue_ir::disassembly::PCodeRaw;
+use fugue_ir::disassembly::{ContextDatabase, IRBuilderArena, PCodeData};
use fugue_ir::error::Error;
+use fugue_ir::il::instruction::Instruction;
+use fugue_ir::translator::TranslationContext;
use fugue_ir::{Address, Translator};
-use ouroboros::self_referencing;
-
use crate::ir::{Insn, PCode};
-#[self_referencing]
-struct LifterInner<'a> {
- translator: &'a Translator,
- irb: IRBuilderArena,
- ctx: ContextDatabase,
- #[borrows(irb)]
- #[covariant]
- pctx: ParserContext<'a, 'this>,
-}
-
+#[derive(Clone)]
#[repr(transparent)]
-pub struct Lifter<'a>(LifterInner<'a>);
-
-impl<'a> Clone for Lifter<'a> {
- fn clone(&self) -> Self {
- // we recreate based on the current context database
- let translator = *self.0.borrow_translator();
- let ctx = self.0.borrow_ctx().clone();
-
- Self::new_with(translator, ctx)
- }
-
- fn clone_from(&mut self, source: &Self) {
- // we only need to copy the context database
- let sctx = source.0.borrow_ctx().clone();
- self.0.with_ctx_mut(|ctx| *ctx = sctx);
- }
-}
+pub struct Lifter<'a>(TranslationContext<'a>);
impl<'a> Lifter<'a> {
pub fn new(translator: &'a Translator) -> Self {
- Self::new_with(translator, translator.context_database())
+ Self(TranslationContext::new(translator))
}
pub fn new_with(translator: &'a Translator, ctx: ContextDatabase) -> Self {
- let irb = IRBuilderArena::with_capacity(4096);
-
- Self(LifterInner::new(translator, irb, ctx, |irb| {
- ParserContext::empty(irb, translator.manager())
- }))
+ Self(TranslationContext::new_with(translator, ctx))
}
pub fn irb(&self, size: usize) -> IRBuilderArena {
- IRBuilderArena::with_capacity(size)
+ self.0.irb(size)
}
pub fn disassemble<'z>(
@@ -62,39 +33,23 @@ impl<'a> Lifter<'a> {
address: impl Into
,
bytes: impl AsRef<[u8]>,
) -> Result, Error> {
+ let address = address.into();
let bytes = bytes.as_ref();
- self.0.with_mut(|slf| {
- let address = address.into();
- let address_val = slf.translator.address(address.into());
-
- let (mnemonic, operand_str, delay_slots, length) = slf.translator.disassemble_aux(
- slf.ctx,
- slf.pctx,
- slf.irb,
- address_val,
- bytes,
- |fmt, delay_slots, length| -> Result<_, Error> {
- let mnemonic = fmt.mnemonic_str(irb);
- let operand_str = fmt.operands_str(irb);
-
- Ok((mnemonic, operand_str, delay_slots, length))
- },
- )?;
-
- if length as usize > bytes.len() {
- return Err(Error::Disassembly(
- fugue_ir::disassembly::Error::InstructionResolution,
- ));
- }
-
- Ok(Insn {
- address,
- mnemonic,
- operands: operand_str,
- delay_slots: delay_slots as u8,
- length: length as u8,
- })
+ let Instruction {
+ mnemonic,
+ operands,
+ delay_slots,
+ length,
+ ..
+ } = self.0.disassemble(irb, address, bytes)?;
+
+ Ok(Insn {
+ address,
+ mnemonic,
+ operands,
+ delay_slots: delay_slots as u8,
+ length: length as u8,
})
}
@@ -104,49 +59,34 @@ impl<'a> Lifter<'a> {
address: impl Into,
bytes: impl AsRef<[u8]>,
) -> Result, Error> {
+ let address = address.into();
let bytes = bytes.as_ref();
- self.0.with_mut(|slf| {
- let address = address.into();
- let address_val = slf.translator.address(address.into());
- let mut irbb = irb.builder(&slf.translator);
-
- let pcode_raw = slf.translator.lift_with(
- slf.ctx,
- slf.pctx,
- slf.irb,
- &mut irbb,
- address_val,
- bytes,
- )?;
-
- if pcode_raw.length as usize > bytes.len() {
- return Err(Error::Disassembly(
- fugue_ir::disassembly::Error::InstructionResolution,
- ));
- }
-
- Ok(PCode {
- address,
- operations: pcode_raw.operations,
- delay_slots: pcode_raw.delay_slots as u8,
- length: pcode_raw.length as u8,
- })
+ let PCodeRaw {
+ operations,
+ delay_slots,
+ length,
+ ..
+ } = self.0.lift(irb, address, bytes)?;
+
+ Ok(PCode {
+ address,
+ operations,
+ delay_slots: delay_slots as u8,
+ length: length as u8,
})
}
pub fn translator(&self) -> &Translator {
- self.0.borrow_translator()
+ self.0.translator()
}
- pub fn reset(&mut self) {
- let translator = *self.0.borrow_translator();
- let mut ctx = translator.context_database();
-
- // we preserve the old context database
- self.0.with_ctx_mut(|old_ctx| mem::swap(old_ctx, &mut ctx));
+ pub fn context(&self) -> &ContextDatabase {
+ self.0.context()
+ }
- *self = Self::new_with(translator, ctx);
+ pub fn reset(&mut self) {
+ self.0.reset();
}
}
diff --git a/fugue-ir/Cargo.toml b/fugue-ir/Cargo.toml
index c3810d6..c91535f 100644
--- a/fugue-ir/Cargo.toml
+++ b/fugue-ir/Cargo.toml
@@ -16,9 +16,11 @@ fugue-bytes = { path = "../fugue-bytes", version = "0.3" }
iset = { version = "0.2", features = ["serde"] }
itertools = "0.12"
log = "0.4"
+ouroboros = "0.18"
roxmltree = "0.19"
serde = { version = "1", features = ["derive", "rc"] }
smallvec = { version = "1", features = ["serde"] }
+stack-map = "1.0"
thiserror = "1"
ustr = { version = "1.0", features = ["serde"] }
walkdir = "2"
diff --git a/fugue-ir/src/disassembly/lift.rs b/fugue-ir/src/disassembly/lift.rs
index f59281e..3021d86 100644
--- a/fugue-ir/src/disassembly/lift.rs
+++ b/fugue-ir/src/disassembly/lift.rs
@@ -4,6 +4,7 @@ use std::ops::Deref;
use std::sync::Arc;
use ahash::AHashMap as Map;
+use stack_map::StackMap;
use ustr::Ustr;
use crate::address::AddressValue;
@@ -16,7 +17,7 @@ use crate::disassembly::{Error, ParserContext, ParserWalker};
use crate::float_format::FloatFormat;
use crate::space::AddressSpace;
use crate::space_manager::SpaceManager;
-use crate::Translator;
+use crate::translator::{Translator, MAX_DELAY_SLOTS};
pub use bumpalo::collections::String as ArenaString;
pub use bumpalo::collections::Vec as ArenaVec;
@@ -349,14 +350,6 @@ impl IRBuilderArena {
&self.0
}
- pub fn builder<'b, 'z>(&'z self, translator: &'b Translator) -> IRBuilderBase<'b, 'z> {
- IRBuilderBase::empty(
- &self,
- translator.manager(),
- translator.unique_mask(),
- )
- }
-
pub fn boxed<'z, T>(&'z self, val: T) -> ArenaRef<'z, T> {
ArenaRef::new_in(self, val)
}
@@ -382,34 +375,31 @@ impl Deref for IRBuilderArena {
}
}
-pub struct IRBuilderBase<'b, 'z> {
+pub struct IRBuilderBase<'b, 'cz> {
const_space: &'b AddressSpace,
unique_mask: u64,
- alloc: &'z IRBuilderArena,
-
label_base: usize,
label_count: usize,
- label_refs: ArenaVec<'z, RelativeRecord>,
- labels: ArenaVec<'z, u64>,
+ label_refs: ArenaVec<'cz, RelativeRecord>,
+ labels: ArenaVec<'cz, u64>,
manager: &'b SpaceManager,
}
-impl<'b, 'z> IRBuilderBase<'b, 'z> {
+impl<'b, 'cz> IRBuilderBase<'b, 'cz> {
pub fn empty(
- alloc: &'z IRBuilderArena,
+ alloc_inner: &'cz IRBuilderArena,
manager: &'b SpaceManager,
unique_mask: u64,
) -> Self {
Self {
const_space: manager.constant_space_ref(),
unique_mask,
- alloc,
label_base: 0,
label_count: 0,
- labels: ArenaVec::with_capacity_in(16, alloc.inner()),
- label_refs: ArenaVec::with_capacity_in(16, alloc.inner()),
+ labels: ArenaVec::with_capacity_in(16, alloc_inner.inner()),
+ label_refs: ArenaVec::with_capacity_in(16, alloc_inner.inner()),
manager,
}
}
@@ -421,6 +411,7 @@ impl<'b, 'z> IRBuilderBase<'b, 'z> {
self.label_refs.clear();
}
+ /*
pub(crate) fn arena(&self) -> &'z Arena {
self.alloc
}
@@ -432,13 +423,15 @@ impl<'b, 'z> IRBuilderBase<'b, 'z> {
pub fn alloc_vec(&self) -> ArenaVec<'z, T> {
ArenaVec::new_in(self.alloc)
}
+ */
}
pub struct IRBuilder<'b, 'c, 'cz, 'z> {
- base: &'c mut IRBuilderBase<'b, 'z>,
+ base: &'c mut IRBuilderBase<'b, 'cz>,
+ arena: &'z IRBuilderArena,
unique_offset: u64,
issued: ArenaVec<'z, PCodeData<'z>>,
- delay_contexts: Map>,
+ delay_contexts: StackMap, MAX_DELAY_SLOTS>,
walker: ParserWalker<'b, 'c, 'cz>,
}
@@ -466,7 +459,7 @@ pub struct IRBuilder<'b, 'c> {
*/
impl<'b, 'c, 'cz, 'z> Deref for IRBuilder<'b, 'c, 'cz, 'z> {
- type Target = &'c mut IRBuilderBase<'b, 'z>;
+ type Target = &'c mut IRBuilderBase<'b, 'cz>;
fn deref(&self) -> &Self::Target {
&self.base
@@ -475,20 +468,19 @@ impl<'b, 'c, 'cz, 'z> Deref for IRBuilder<'b, 'c, 'cz, 'z> {
impl<'b, 'c, 'cz, 'z> IRBuilder<'b, 'c, 'cz, 'z> {
pub fn new(
- base: &'c mut IRBuilderBase<'b, 'z>,
+ base: &'c mut IRBuilderBase<'b, 'cz>,
+ arena: &'z IRBuilderArena,
walker: ParserWalker<'b, 'c, 'cz>,
- delay_contexts: &'c mut Map>,
+ delay_contexts: StackMap, MAX_DELAY_SLOTS>,
) -> Self {
base.reinitialise();
Self {
unique_offset: (walker.address().offset() & base.unique_mask) >> 4,
- issued: ArenaVec::with_capacity_in(16, &base.alloc),
+ issued: ArenaVec::with_capacity_in(16, arena),
base,
+ arena,
walker,
- delay_contexts: delay_contexts
- .iter_mut()
- .map(|(k, v)| (k.clone(), v))
- .collect(),
+ delay_contexts,
}
}
@@ -686,7 +678,7 @@ impl<'b, 'c, 'cz, 'z> IRBuilder<'b, 'c, 'cz, 'z> {
pub fn dump(&mut self, op: &'b OpTpl) -> Result<(), Error> {
let input_count = op.input_count();
- let mut pcode = PCodeData::new_in(&self.base.arena(), op.opcode(), input_count);
+ let mut pcode = PCodeData::new_in(self.arena, op.opcode(), input_count);
for i in 0..input_count {
let input = op.input(i);
@@ -696,7 +688,7 @@ impl<'b, 'c, 'cz, 'z> IRBuilder<'b, 'c, 'cz, 'z> {
let index = VarnodeData::new(self.const_space, spc.index() as u64, 0);
self.issued.push(PCodeData {
opcode: Opcode::Load,
- inputs: arena_vec![in self.base.alloc; index, ptr],
+ inputs: arena_vec![in self.arena; index, ptr],
output: Some(varnode.clone()),
});
pcode.inputs.push(varnode);
@@ -720,7 +712,7 @@ impl<'b, 'c, 'cz, 'z> IRBuilder<'b, 'c, 'cz, 'z> {
let index = VarnodeData::new(self.const_space, spc.index() as u64, 0);
self.issued.push(PCodeData {
opcode: Opcode::Store,
- inputs: arena_vec![in self.base.alloc; index, ptr, outp],
+ inputs: arena_vec![in self.arena; index, ptr, outp],
output: None,
})
}
@@ -782,8 +774,8 @@ impl<'b, 'c, 'cz, 'z> IRBuilder<'b, 'c, 'cz, 'z> {
)));
}
Some(label) => {
- let res =
- label.wrapping_sub(rel.instruction as u64) & bits::calculate_mask(varnode.size());
+ let res = label.wrapping_sub(rel.instruction as u64)
+ & bits::calculate_mask(varnode.size());
varnode.offset = res;
}
}
@@ -796,7 +788,7 @@ impl<'b, 'c, 'cz, 'z> IRBuilder<'b, 'c, 'cz, 'z> {
let mut slf = self;
slf.walker.base_state();
- let mut operations = ArenaVec::new_in(&slf.base.alloc);
+ let mut operations = ArenaVec::new_in(slf.arena);
swap(&mut slf.issued, &mut operations);
PCodeRaw {
diff --git a/fugue-ir/src/disassembly/walker.rs b/fugue-ir/src/disassembly/walker.rs
index 79310fa..281f003 100644
--- a/fugue-ir/src/disassembly/walker.rs
+++ b/fugue-ir/src/disassembly/walker.rs
@@ -225,7 +225,6 @@ impl<'b, 'z> ParserContext<'b, 'z> {
pub fn reinitialise(
&mut self,
- _arena: &'z IRBuilderArena,
context_db: &ContextDatabase,
address: AddressValue,
buffer: &[u8],
diff --git a/fugue-ir/src/translator.rs b/fugue-ir/src/translator.rs
index 096fb79..f99a1de 100644
--- a/fugue-ir/src/translator.rs
+++ b/fugue-ir/src/translator.rs
@@ -1,6 +1,8 @@
+use std::array;
use std::borrow::Borrow;
use std::fs::File;
use std::io::Read;
+use std::mem;
use std::path::Path;
use std::sync::Arc;
@@ -8,7 +10,8 @@ use ahash::AHashMap as Map;
use fugue_arch::ArchitectureDef;
use itertools::Itertools;
-
+use ouroboros::self_referencing;
+use stack_map::StackMap;
use ustr::Ustr;
use crate::address::AddressValue;
@@ -31,6 +34,9 @@ use crate::float_format::FloatFormat;
use crate::il::instruction::{Instruction, InstructionFull};
use crate::register::RegisterNames;
use crate::space_manager::SpaceManager;
+use crate::Address;
+
+pub(crate) const MAX_DELAY_SLOTS: usize = 8;
// Translator is used for parsing the processor spec XML and
// lifting instructions
@@ -57,7 +63,159 @@ pub struct Translator {
source_files: Map,
}
+struct TranslationContextState<'a, 'az> {
+ translation_parser_insn_ctx: ParserContext<'a, 'az>, // for main instruction
+ translation_parser_delay_ctxs: [ParserContext<'a, 'az>; MAX_DELAY_SLOTS],
+ translation_builder_base: IRBuilderBase<'a, 'az>,
+}
+
+#[self_referencing]
+struct TranslationContextInner<'a> {
+ translator: &'a Translator,
+ translation_context_db: ContextDatabase,
+
+ translation_allocator: IRBuilderArena, // for translation temporaries
+
+ #[borrows(translation_allocator)]
+ #[covariant]
+ translation_context_state: TranslationContextState<'a, 'this>,
+}
+
+#[repr(transparent)]
+pub struct TranslationContext<'a>(TranslationContextInner<'a>);
+
+impl<'a> TranslationContext<'a> {
+ pub fn new(translator: &'a Translator) -> Self {
+ Self::new_with(translator, translator.context_database())
+ }
+
+ pub fn new_with(translator: &'a Translator, context_db: ContextDatabase) -> Self {
+ Self(TranslationContextInner::new(
+ translator,
+ context_db,
+ IRBuilderArena::with_capacity(1024),
+ |arena| TranslationContextState {
+ translation_parser_insn_ctx: ParserContext::empty(arena, translator.manager()),
+ translation_parser_delay_ctxs: array::from_fn(|_| {
+ ParserContext::empty(arena, translator.manager())
+ }),
+ translation_builder_base: IRBuilderBase::empty(
+ arena,
+ translator.manager(),
+ translator.unique_mask(),
+ ),
+ },
+ ))
+ }
+
+ pub fn irb(&self, size: usize) -> IRBuilderArena {
+ IRBuilderArena::with_capacity(size)
+ }
+
+ pub fn disassemble<'z>(
+ &mut self,
+ irb: &'z IRBuilderArena,
+ addr: impl Into,
+ bytes: impl AsRef<[u8]>,
+ ) -> Result, Error> {
+ self.0.with_mut(|slf| {
+ let addr = addr.into();
+ let addr_val = slf.translator.address(addr.into());
+
+ let bytes = bytes.as_ref();
+
+ let insn = slf.translator.disassemble_with(
+ slf.translation_context_db,
+ &mut slf.translation_context_state.translation_parser_insn_ctx,
+ irb,
+ addr_val,
+ bytes,
+ )?;
+
+ if insn.length() > bytes.len() {
+ return Err(Error::Disassembly(DisassemblyError::InstructionResolution));
+ }
+
+ Ok(insn)
+ })
+ }
+
+ pub fn lift<'z>(
+ &mut self,
+ irb: &'z IRBuilderArena,
+ addr: impl Into,
+ bytes: impl AsRef<[u8]>,
+ ) -> Result, Error> {
+ self.0.with_mut(|slf| {
+ let addr = addr.into();
+ let addr_val = slf.translator.address(addr.into());
+
+ let bytes = bytes.as_ref();
+
+ let insn = slf.translator.lift_with(
+ slf.translation_context_db,
+ &mut slf.translation_context_state.translation_parser_insn_ctx,
+ &mut slf.translation_context_state.translation_parser_delay_ctxs,
+ &mut slf.translation_context_state.translation_builder_base,
+ irb,
+ addr_val,
+ bytes,
+ )?;
+
+ if insn.length() > bytes.len() {
+ return Err(Error::Disassembly(DisassemblyError::InstructionResolution));
+ }
+
+ Ok(insn)
+ })
+ }
+
+ pub fn translator(&self) -> &Translator {
+ self.0.borrow_translator()
+ }
+
+ pub fn context(&self) -> &ContextDatabase {
+ self.0.borrow_translation_context_db()
+ }
+
+ pub fn reset(&mut self) {
+ let translator = *self.0.borrow_translator();
+ let mut context_db = translator.context_database();
+
+ self.0.with_translation_context_db_mut(|old_context_db| {
+ mem::swap(old_context_db, &mut context_db);
+ });
+
+ *self = Self::new_with(translator, context_db);
+ }
+}
+
+impl<'a> Clone for TranslationContext<'a> {
+ fn clone(&self) -> Self {
+ let translator = *self.0.borrow_translator();
+ let context_db = self.0.borrow_translation_context_db().clone();
+
+ Self::new_with(translator, context_db)
+ }
+
+ fn clone_from(&mut self, source: &Self) {
+ // we only need to copy the context database
+ let sctx = source.0.borrow_translation_context_db();
+ self.0.with_translation_context_db_mut(|ctx| {
+ ctx.clone_from(sctx);
+ });
+ }
+}
+
impl Translator {
+ pub fn context<'a>(&'a self) -> TranslationContext<'a> {
+ TranslationContext::new(self)
+ }
+
+ pub fn context_with<'a>(&'a self, db: ContextDatabase) -> TranslationContext<'a> {
+ TranslationContext::new_with(self, db)
+ }
+
pub fn is_big_endian(&self) -> bool {
self.big_endian
}
@@ -413,14 +571,13 @@ impl Translator {
) -> Result, Error> {
let arena = IRBuilderArena::with_capacity(4096);
let mut ctxt = ParserContext::empty(&arena, self.manager());
- self.disassemble_with(db, &mut ctxt, &arena, builder, address, bytes)
+ self.disassemble_with(db, &mut ctxt, builder, address, bytes)
}
pub fn disassemble_aux<'a, 'az, 'c, T, E, F>(
&'a self,
db: &mut ContextDatabase,
context: &'c mut ParserContext<'a, 'az>,
- arena: &'az IRBuilderArena,
address: AddressValue,
bytes: &[u8],
mut f: F,
@@ -439,7 +596,7 @@ impl Translator {
}
}
- context.reinitialise(arena, db, address.clone(), bytes);
+ context.reinitialise(db, address.clone(), bytes);
let mut walker = ParserWalker::new(context, self);
Translator::resolve(&mut walker, self.root.id(), &self.symbol_table)?;
@@ -466,12 +623,11 @@ impl Translator {
&'a self,
db: &mut ContextDatabase,
context: &mut ParserContext<'a, 'az>,
- arena: &'az IRBuilderArena,
builder: &'z IRBuilderArena,
address: AddressValue,
bytes: &[u8],
) -> Result, Error> {
- self.disassemble_aux(db, context, arena, address, bytes, |fmt, delay_slots, length| {
+ self.disassemble_aux(db, context, address, bytes, |fmt, delay_slots, length| {
let mnemonic = fmt.mnemonic_str(builder);
let operands = fmt.operands_str(builder);
@@ -489,12 +645,11 @@ impl Translator {
&'a self,
db: &mut ContextDatabase,
context: &mut ParserContext<'a, 'az>,
- arena: &'az IRBuilderArena,
builder: &'z IRBuilderArena,
address: AddressValue,
bytes: &[u8],
) -> Result, Error> {
- self.disassemble_aux(db, context, arena, address, bytes, |fmt, delay_slots, length| {
+ self.disassemble_aux(db, context, address, bytes, |fmt, delay_slots, length| {
let mnemonic = fmt.mnemonic_str(builder);
let operands = fmt.operands_str(builder);
let operand_data = fmt.operand_data(builder);
@@ -519,16 +674,26 @@ impl Translator {
) -> Result, Error> {
let arena = IRBuilderArena::with_capacity(1024);
let mut context = ParserContext::empty(&arena, self.manager());
- let mut base = builder.builder(self);
- self.lift_with(db, &mut context, &arena, &mut base, address, bytes)
+ let mut dcontexts = array::from_fn(|_| ParserContext::empty(&arena, self.manager()));
+ let mut base = IRBuilderBase::empty(&arena, self.manager(), self.unique_mask());
+ self.lift_with(
+ db,
+ &mut context,
+ &mut dcontexts,
+ &mut base,
+ builder,
+ address,
+ bytes,
+ )
}
pub fn lift_with<'a, 'az, 'z>(
&'a self,
db: &mut ContextDatabase,
context: &mut ParserContext<'a, 'az>,
- arena: &'az IRBuilderArena,
- builder: &mut IRBuilderBase<'a, 'z>,
+ delay_contexts: &mut [ParserContext<'a, 'az>; MAX_DELAY_SLOTS],
+ builder: &mut IRBuilderBase<'a, 'az>,
+ builder_arena: &'z IRBuilderArena,
address: AddressValue,
bytes: &[u8],
) -> Result, Error> {
@@ -542,7 +707,7 @@ impl Translator {
}
// Main instruction
- context.reinitialise(arena, db, address.clone(), bytes);
+ context.reinitialise(db, address, bytes);
let mut walker = ParserWalker::new(context, self);
Translator::resolve(&mut walker, self.root.id(), &self.symbol_table)?;
@@ -554,18 +719,25 @@ impl Translator {
let mut fall_offset = walker.length();
let delay_slots = walker.delay_slot();
- let mut delay_contexts = Map::default();
+
+ let mut delay_context_mapping = StackMap::<_, _, MAX_DELAY_SLOTS>::new();
if delay_slots > 0 {
let mut byte_count = 0;
- loop {
+
+ // NOTE: this loop assumes we have enough mappings
+ for dcontext in delay_contexts.iter_mut() {
+ /*
let mut dcontext = ParserContext::new(
arena,
db,
address.clone() + fall_offset,
&bytes[fall_offset..],
);
- let mut dwalker = ParserWalker::new(&mut dcontext, self);
+ */
+
+ dcontext.reinitialise(db, address + fall_offset, &bytes[fall_offset..]);
+ let mut dwalker = ParserWalker::new(dcontext, self);
Translator::resolve(&mut dwalker, self.root.id(), &self.symbol_table)?;
Translator::resolve_handles(&mut dwalker, &self.manager, &self.symbol_table)?;
@@ -575,7 +747,7 @@ impl Translator {
let length = dwalker.length();
- delay_contexts.insert(address.clone() + fall_offset, dcontext);
+ delay_context_mapping.insert(address.clone() + fall_offset, dcontext);
fall_offset += length;
byte_count += length;
@@ -584,18 +756,23 @@ impl Translator {
break;
}
}
+
walker.set_next_address(address.clone() + fall_offset);
}
if let Some(ctor) = walker.constructor()? {
let tmpl = ctor.unchecked_template();
- let mut builder =
- IRBuilder::new(builder, ParserWalker::new(context, self), &mut delay_contexts);
+ let mut builder = IRBuilder::new(
+ builder,
+ builder_arena,
+ ParserWalker::new(context, self),
+ delay_context_mapping,
+ );
builder.build(tmpl, None, &self.symbol_table)?;
builder.resolve_relatives()?;
Ok(builder.emit(fall_offset))
} else {
- Ok(PCodeRaw::nop_in(builder.arena(), address, walker.length()))
+ Ok(PCodeRaw::nop_in(builder_arena, address, walker.length()))
}
}
@@ -747,6 +924,30 @@ mod test {
Ok(())
}
+ #[test]
+ fn test_tctx() -> Result<(), Error> {
+ let mut translator = Translator::from_file(
+ "pc",
+ &ArchitectureDef::new("AARCH64", Endian::Little, 64, "v8A"),
+ &Map::default(),
+ "./data/processors/AARCH64/AARCH64.sla",
+ )?;
+
+ translator.set_variable_default("ShowPAC", 0);
+ translator.set_variable_default("PAC_clobber", 0);
+ translator.set_variable_default("ShowBTI", 0);
+ translator.set_variable_default("ShowMemTag", 0);
+
+ let bytes = [0x20, 0xf8, 0x48, 0x4f];
+ let mut trans = translator.context();
+
+ let irb = trans.irb(4096);
+
+ trans.lift(&irb, 0x1000u32, &bytes)?;
+
+ Ok(())
+ }
+
#[test]
#[ignore = "test arm32 bug #6"]
fn test_arm32_bug_6() -> Result<(), Box> {