about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--focaccia/lldb_target.py7
-rw-r--r--focaccia/symbolic.py44
2 files changed, 32 insertions, 19 deletions
diff --git a/focaccia/lldb_target.py b/focaccia/lldb_target.py
index 2ed0757..1f31337 100644
--- a/focaccia/lldb_target.py
+++ b/focaccia/lldb_target.py
@@ -189,6 +189,13 @@ class LLDBConcreteTarget:
         try:
             reg = self._get_register(regname)
             assert(reg.IsValid())
+            if reg.size > 8:  # reg is a vector register
+                reg.data.byte_order = lldb.eByteOrderLittle
+                val = 0
+                for ui64 in reversed(reg.data.uint64s):
+                    val <<= 64
+                    val |= ui64
+                return val
             return reg.GetValueAsUnsigned()
         except ConcreteRegisterError as err:
             flags = self.read_flags()
diff --git a/focaccia/symbolic.py b/focaccia/symbolic.py
index 6338a14..0f381a4 100644
--- a/focaccia/symbolic.py
+++ b/focaccia/symbolic.py
@@ -420,26 +420,32 @@ class SymbolicTransform:
 
         return res[:-1]  # Remove trailing newline
 
+class MemoryBinstream:
+    """A binary stream interface that reads bytes from a program state's
+    memory."""
+    def __init__(self, state: ReadableProgramState):
+        self._state = state
+
+    def __len__(self):
+        return 0xffffffff
+
+    def __getitem__(self, key: int | slice):
+        if isinstance(key, slice):
+            return self._state.read_memory(key.start, key.stop - key.start)
+        return self._state.read_memory(key, 1)
+
 class DisassemblyContext:
-    def __init__(self, binary):
+    def __init__(self, target: ReadableProgramState):
         self.loc_db = LocationDB()
 
-        # Load the binary
-        with open(binary, 'rb') as bin_file:
-            cont = ContainerELF.from_stream(bin_file, self.loc_db)
-        self.entry_point = cont.entry_point
-
         # Determine the binary's architecture
-        self.machine = Machine(cont.arch)
-        if self.machine.name not in supported_architectures:
-            raise NotImplementedError(f'[ERROR] {self.machine.name} is not'
-                                      f' supported.')
-        self.arch = supported_architectures[self.machine.name]
-        """Focaccia's description of an instruction set architecture."""
+        self.machine = make_machine(target.arch)
+        self.arch = target.arch
 
         # Create disassembly/lifting context
         assert(self.machine.dis_engine is not None)
-        self.mdis = self.machine.dis_engine(cont.bin_stream, loc_db=self.loc_db)
+        binstream = MemoryBinstream(target)
+        self.mdis = self.machine.dis_engine(binstream, loc_db=self.loc_db)
         self.mdis.follow_call = True
         self.lifter = self.machine.lifter(self.loc_db)
 
@@ -573,8 +579,8 @@ class _LLDBConcreteState(ReadableProgramState):
     target. This saves us the trouble of recording a full program state, and
     allows us instead to read values from LLDB on demand.
     """
-    def __init__(self, target: LLDBConcreteTarget, arch: Arch):
-        super().__init__(arch)
+    def __init__(self, target: LLDBConcreteTarget):
+        super().__init__(target.arch)
         self._target = target
 
     def read_register(self, reg: str) -> int:
@@ -604,14 +610,14 @@ def collect_symbolic_trace(env: TraceEnvironment,
     """
     binary = env.binary_name
 
-    ctx = DisassemblyContext(binary)
-    arch = ctx.arch
-
     # Set up concrete reference state
     target = LLDBConcreteTarget(binary, env.argv, env.envp)
     if start_addr is not None:
         target.run_until(start_addr)
-    lldb_state = _LLDBConcreteState(target, arch)
+    lldb_state = _LLDBConcreteState(target)
+
+    ctx = DisassemblyContext(lldb_state)
+    arch = ctx.arch
 
     # Trace concolically
     strace: list[SymbolicTransform] = []