about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/focaccia/deterministic.py10
-rw-r--r--src/focaccia/qemu/_qemu_tool.py67
2 files changed, 72 insertions, 5 deletions
diff --git a/src/focaccia/deterministic.py b/src/focaccia/deterministic.py
index 1cfda0d..ffd519c 100644
--- a/src/focaccia/deterministic.py
+++ b/src/focaccia/deterministic.py
@@ -180,7 +180,8 @@ class MemoryMapping:
                  source: str,
                  offset: int,
                  mmap_prot: int,
-                 mmap_flags: int):
+                 mmap_flags: int,
+                 name: str | None = None):
         self.event_count = event_count
         self.start_address = start_address
         self.length = end_address - self.start_address
@@ -188,10 +189,13 @@ class MemoryMapping:
         self.offset = offset
         self.mmap_prot = mmap_prot
         self.mmap_flags = mmap_flags
+        self.name = name
 
     def __repr__(self) -> str:
-        return f'Memory mapping at event {self.event_count}\n' \
-               f'start = {hex(self.start_address)}\n' \
+        header = f'Memory mapping at event {self.event_count}\n'
+        if self.name:
+            header += f'name = {self.name}\n'
+        return header + f'start = {hex(self.start_address)}\n' \
                f'length = {self.length}\n' \
                f'source = {self.source}\n' \
                f'offset = {self.offset}\n' \
diff --git a/src/focaccia/qemu/_qemu_tool.py b/src/focaccia/qemu/_qemu_tool.py
index 188ecf2..e6394e5 100644
--- a/src/focaccia/qemu/_qemu_tool.py
+++ b/src/focaccia/qemu/_qemu_tool.py
@@ -6,6 +6,7 @@ But please use `tools/validate_qemu.py` instead because we have some more setup
 work to do.
 """
 
+import re
 import gdb
 import logging
 import traceback
@@ -156,11 +157,13 @@ class GDBServerStateIterator:
         self.arch = supported_architectures[archname]
         self.binary = self._process.progspace.filename
 
+        first_state = self.current_state()
         self._log_matcher = LogStateMatcher(self._deterministic_log.events(),
                                             self._deterministic_log.mmaps(),
                                             match_event,
-                                            from_state=self.current_state())
-        info(f'Synchronizing at PC {hex(self.current_state().read_pc())} with {self._log_matcher.matched_events()}')
+                                            from_state=first_state)
+        event, _ = self._log_matcher.match(first_state)
+        info(f'Synchronized at PC={hex(first_state.read_pc())} to event:\n{event}')
 
     def current_state(self) -> ReadableProgramState:
         return GDBProgramState(self._process, gdb.selected_frame(), self.arch)
@@ -272,6 +275,66 @@ class GDBServerStateIterator:
     def _step(self):
         gdb.execute('si', to_string=True)
 
+    def get_sections(self) -> list[MemoryMapping]:
+        mappings = []
+
+        # Skip everything until the header line
+        started = False
+
+        text = gdb.execute('info proc mappings', to_string=True)
+        for line in text.splitlines():
+            line = line.strip()
+            if not line:
+                continue
+
+            # Detect header line once
+            if line.startswith("Start Addr"):
+                started = True
+                continue
+
+            if not started:
+                continue
+
+            # Lines look like:
+            # 0x0000000000400000 0x0000000000401000 0x1000 0x0 r--p /path
+            # or:
+            # 0x... 0x... 0x... 0x... rw-p  [vdso]
+            parts = line.split(None, 6)
+
+            if len(parts) < 5:
+                continue
+
+            start   = int(parts[0], 16)
+            end     = int(parts[1], 16)
+            size    = int(parts[2], 16)
+            offset  = int(parts[3], 16)
+            perms   = parts[4]
+
+            file_or_tag = None
+            is_special = False
+
+            if len(parts) >= 6:
+                tail = parts[5]
+
+                # If it's [tag], mark as special
+                if tail.startswith("[") and tail.endswith("]"):
+                    file_or_tag = tail.strip()
+                    is_special = True
+                else:
+                    # Might be a filename or absent
+                    file_or_tag = tail
+
+            mapping = MemoryMapping(0,
+                                    start,
+                                    end,
+                                    '',
+                                    offset,
+                                    0,
+                                    0)
+            mappings.append(mapping)
+
+        return mappings
+
 def record_minimal_snapshot(prev_state: ReadableProgramState,
                             cur_state: ReadableProgramState,
                             prev_transform: SymbolicTransform,