about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorTheofilos Augoustis <theofilos.augoustis@gmail.com>2025-11-19 10:04:02 +0000
committerTheofilos Augoustis <theofilos.augoustis@gmail.com>2025-11-20 09:46:17 +0000
commit1740b1f01faa59a2bc1883554bf47f0c24d23d0f (patch)
tree6cd9cde001acdc3cc9432e178419a85f09a75ec2
parent533fedb9093323594cac81a4ed3c3873a575c468 (diff)
downloadfocaccia-1740b1f01faa59a2bc1883554bf47f0c24d23d0f.tar.gz
focaccia-1740b1f01faa59a2bc1883554bf47f0c24d23d0f.zip
Add basic matching for thread IDs
-rw-r--r--src/focaccia/qemu/_qemu_tool.py15
-rw-r--r--src/focaccia/qemu/deterministic.py7
-rw-r--r--src/focaccia/qemu/syscall.py7
-rw-r--r--src/focaccia/qemu/x86.py4
4 files changed, 31 insertions, 2 deletions
diff --git a/src/focaccia/qemu/_qemu_tool.py b/src/focaccia/qemu/_qemu_tool.py
index 2d1d144..f4b9752 100644
--- a/src/focaccia/qemu/_qemu_tool.py
+++ b/src/focaccia/qemu/_qemu_tool.py
@@ -27,7 +27,7 @@ from focaccia.deterministic import (
     SyscallEvent,
     MemoryMapping,
 )
-from focaccia.qemu.deterministic import emulated_system_calls
+from focaccia.qemu.deterministic import emulated_system_calls, passthrough_system_calls
 
 from focaccia.tools.validate_qemu import make_argparser, verbosity
 
@@ -199,6 +199,19 @@ class GDBServerStateIterator:
 
             return next_state
 
+        syscall = passthrough_system_calls[self.arch.archname].get(call, None)
+        if syscall is not None:
+            info(f'System call number {hex(call)} passed through')
+            self._step()
+            if self._is_exited():
+                raise StopIteration
+            # Check if new thread was created
+            if syscall.creates_thread:
+                new_tid = self.current_state().read_register(self.arch.get_syscall_reg())
+                info(f'New thread created TID={hex(new_tid)} corresponds to native {hex(event.tid)}')
+
+            return GDBProgramState(self._process, gdb.selected_frame(), self.arch)
+
         info(f'System call number {hex(call)} not replayed')
         self._step()
         if self._is_exited():
diff --git a/src/focaccia/qemu/deterministic.py b/src/focaccia/qemu/deterministic.py
index d2d314e..51fe9e6 100644
--- a/src/focaccia/qemu/deterministic.py
+++ b/src/focaccia/qemu/deterministic.py
@@ -1,4 +1,5 @@
 from focaccia.qemu.x86 import emulated_system_calls as x86_emu_syscalls
+from focaccia.qemu.x86 import passthrough_system_calls as x86_pass_syscalls
 
 emulated_system_calls = {
     'x86_64': x86_emu_syscalls,
@@ -7,3 +8,9 @@ emulated_system_calls = {
     'aarch64b': { }
 }
 
+passthrough_system_calls = {
+    'x86_64': x86_pass_syscalls,
+    'aarch64': { },
+    'aarch64l': { },
+    'aarch64b': { }
+}
diff --git a/src/focaccia/qemu/syscall.py b/src/focaccia/qemu/syscall.py
index 956f5c9..90016f1 100644
--- a/src/focaccia/qemu/syscall.py
+++ b/src/focaccia/qemu/syscall.py
@@ -2,13 +2,18 @@ class SyscallInfo:
     def __init__(self, 
                  name: str,
                  patchup_registers: list[str] | None = None,
-                 patchup_address_registers: list[str] | None = None):
+                 patchup_address_registers: list[str] | None = None,
+                 creates_thread: bool = False):
         """Describes a syscall by its name and outputs.
 
         :param name: The name of a system call.
         :param patchup_registers: Registers that must be replaced with deterministic values.
+        :param patchup_address_registers: Registers that contain addresses to be looked up when
+        mapping to native addresses.
+        :param creates_thread: True when the system call creates a new thread.
         """
         self.name = name
         self.patchup_registers = patchup_registers
         self.patchup_address_registers = patchup_address_registers
+        self.creates_thread = creates_thread
 
diff --git a/src/focaccia/qemu/x86.py b/src/focaccia/qemu/x86.py
index 347bbc4..7d11c0e 100644
--- a/src/focaccia/qemu/x86.py
+++ b/src/focaccia/qemu/x86.py
@@ -8,3 +8,7 @@ emulated_system_calls = {
     318: SyscallInfo('getrandom', patchup_address_registers=['rdi'])
 }
 
+passthrough_system_calls = {
+    56:  SyscallInfo('clone', patchup_address_registers=['rdx', 'r10'], creates_thread=True),
+}
+