about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--pyproject.toml1
-rw-r--r--src/focaccia/deterministic.py2
-rw-r--r--src/focaccia/native/tracer.py9
-rw-r--r--src/focaccia/qemu/_qemu_tool.py3
-rw-r--r--src/focaccia/qemu/target.py4
-rw-r--r--uv.lock16
6 files changed, 28 insertions, 7 deletions
diff --git a/pyproject.toml b/pyproject.toml
index eaa8997..98365c1 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -18,6 +18,7 @@ dependencies = [
 	"brotli",
 	'msgpack',
 	"pycapnp",
+	"pyroaring",
 	"setuptools",
 	"python-ptrace",
 	"cpuid @ git+https://github.com/taugoust/cpuid.py.git@master",
diff --git a/src/focaccia/deterministic.py b/src/focaccia/deterministic.py
index 58d9fd9..4070504 100644
--- a/src/focaccia/deterministic.py
+++ b/src/focaccia/deterministic.py
@@ -30,7 +30,7 @@ class MemoryWrite:
         self.data = data
 
     def __repr__(self) -> str:
-        return f'{{ tid: {hex(self.tid)}, addr: {hex(self.address)}:{hex(self.address+self.size)}\n' \
+        return f'{{ tid: {self.tid}, addr: {hex(self.address)}:{hex(self.address+self.size)}\n' \
                f'   conservative? {self.is_conservative}, holes: {self.holes}\n' \
                f'   data: {self.data} }}'
 
diff --git a/src/focaccia/native/tracer.py b/src/focaccia/native/tracer.py
index eed5206..af53c89 100644
--- a/src/focaccia/native/tracer.py
+++ b/src/focaccia/native/tracer.py
@@ -33,9 +33,12 @@ def match_event(event: Event, target: ReadableProgramState) -> bool:
         for reg, value in event.registers.items():
             if value == event.pc:
                 continue
-            if target.read_register(reg) != value:
-                print(f'Failed match for {reg}: {hex(value)} != {hex(target.read_register(reg))}')
-                return False
+            try:
+                if target.read_register(reg) != value:
+                    print(f'Failed match for {reg}: {hex(value)} != {hex(target.read_register(reg))}')
+                    return False
+            except Exception as e:
+                warn(f'Unable to read register: {e}')
         return True
     return False
 
diff --git a/src/focaccia/qemu/_qemu_tool.py b/src/focaccia/qemu/_qemu_tool.py
index 5a59e15..c838f2b 100644
--- a/src/focaccia/qemu/_qemu_tool.py
+++ b/src/focaccia/qemu/_qemu_tool.py
@@ -8,6 +8,7 @@ work to do.
 
 import logging
 import traceback
+import pyroaring
 from typing import Iterable, Optional
 
 import focaccia.parser as parser
@@ -164,7 +165,7 @@ def collect_conc_trace(gdb: GDBServerStateIterator, strace: Trace) \
 
     # An online trace matching algorithm.
     info(f'Tracing QEMU between {hex(start_addr)}:{hex(strace.env.stop_address) if strace.env.stop_address else "end"}')
-    traced_address_set = frozenset(strace.addresses)
+    traced_address_set = pyroaring.BitMap64(strace.addresses)
 
     transform: Optional[SymbolicTransform] = None
     while True:
diff --git a/src/focaccia/qemu/target.py b/src/focaccia/qemu/target.py
index 28fe805..790249c 100644
--- a/src/focaccia/qemu/target.py
+++ b/src/focaccia/qemu/target.py
@@ -260,7 +260,7 @@ class GDBServerStateIterator(GDBServerConnector):
         self._thread_context = {
         }
         info(f'Synchronized at PC={hex(first_state.read_pc())} to event:\n{event}')
-        debug(f'Thread mapping at this point: {hex(event.tid)}: {hex(self.current_tid())}')
+        debug(f'Thread mapping at this point: {event.tid}: {self.current_tid()}')
 
     def _handle_syscall(self, event: Event, post_event: Event) -> ReadableProgramState:
         call = event.registers.get(self.arch.get_syscall_reg())
@@ -308,7 +308,7 @@ class GDBServerStateIterator(GDBServerConnector):
                 info(f'New thread created TID={hex(new_tid)} corresponds to native {hex(event_new_tid)}')
                 debug('Thread mapping at this point:')
                 for event_tid, (tid, _) in self._thread_map.items():
-                    debug(f'{hex(event_tid)}: {hex(tid)}')
+                    debug(f'{event_tid}: {tid}')
 
             next_state = GDBProgramState(self._process, gdb.selected_frame(), self.arch)
 
diff --git a/uv.lock b/uv.lock
index 96f0947..d433a91 100644
--- a/uv.lock
+++ b/uv.lock
@@ -91,6 +91,7 @@ dependencies = [
     { name = "msgpack", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" },
     { name = "orjson", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" },
     { name = "pycapnp", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" },
+    { name = "pyroaring", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" },
     { name = "python-ptrace", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" },
     { name = "setuptools", marker = "(platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')" },
 ]
@@ -114,6 +115,7 @@ requires-dist = [
     { name = "orjson" },
     { name = "pycapnp" },
     { name = "pyright", marker = "extra == 'dev'" },
+    { name = "pyroaring" },
     { name = "pytest", marker = "extra == 'dev'" },
     { name = "python-ptrace" },
     { name = "ruff", marker = "extra == 'dev'" },
@@ -298,6 +300,20 @@ wheels = [
 ]
 
 [[package]]
+name = "pyroaring"
+version = "1.0.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/0f/e4/975f0fa77fc3590820b4a3ac49704644b389795409bc12eb91729f845812/pyroaring-1.0.3.tar.gz", hash = "sha256:cd7392d1c010c9e41c11c62cd0610c8852e7e9698b1f7f6c2fcdefe50e7ef6da", size = 188688, upload-time = "2025-10-09T09:08:22.448Z" }
+wheels = [
+    { url = "https://files.pythonhosted.org/packages/86/9e/b00c38a7e62a73e152055f593595c37152e61fc2896fd11538a7c71fbe4e/pyroaring-1.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2b2eb8bd1c35c772994889be9f7dda09477475d7aa1e2af9ab4ef18619326f6", size = 1869251, upload-time = "2025-10-09T09:07:14.584Z" },
+    { url = "https://files.pythonhosted.org/packages/4f/33/f32d00ca105b66303deab43d027c3574c8ade8525dac0e5b50a9fb4d1b76/pyroaring-1.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d31f4c1c906f1af14ce61a3959d04a14a64c594f8a768399146a45bbd341f21f", size = 2071551, upload-time = "2025-10-09T09:07:15.713Z" },
+    { url = "https://files.pythonhosted.org/packages/5d/89/e953cae181ba4c7523334855a1ca0ae8eeea3cee8d7cd39c56bd99709d3f/pyroaring-1.0.3-cp312-cp312-manylinux_2_24_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53be988fc86698d56c11049bfe5113a2f6990adb1fa2782b29636509808b6aa7", size = 1781071, upload-time = "2025-10-09T09:07:17.19Z" },
+    { url = "https://files.pythonhosted.org/packages/f5/9e/684ea0568ce7d30fc4e01ad1c666e9ce1a5b1702fa630231f4f6bdb96539/pyroaring-1.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:34a781f1f9766897f63ef18be129827340ae37764015b83fdcff1efb9e29136d", size = 2849305, upload-time = "2025-10-09T09:07:20.388Z" },
+    { url = "https://files.pythonhosted.org/packages/7c/fd/d7773a2adf91f45d8924197954c66b1694325afd2f27e02edaac07338402/pyroaring-1.0.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1f414343b4ed0756734328cdf2a91022fc54503769e3f8d79bd0b672ea815a16", size = 2692843, upload-time = "2025-10-09T09:07:22.042Z" },
+    { url = "https://files.pythonhosted.org/packages/ca/94/e6ed1f682d850e039c71b2032bacdefc5082dc809796cf34b9e6f24c604d/pyroaring-1.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f888447bf22dde7759108bfe6dfbeb6bbb61b14948de9c4cb6843c4dd57e2215", size = 3117542, upload-time = "2025-10-09T09:07:25.104Z" },
+]
+
+[[package]]
 name = "pytest"
 version = "8.4.2"
 source = { registry = "https://pypi.org/simple" }