diff options
| -rw-r--r-- | reproducers/1370-minimal.S | 44 | ||||
| -rw-r--r-- | src/focaccia/qemu/_qemu_tool.py | 20 | ||||
| -rw-r--r-- | src/focaccia/reproducer.py | 7 | ||||
| -rwxr-xr-x | src/focaccia/tools/validate_qemu.py | 4 |
4 files changed, 71 insertions, 4 deletions
diff --git a/reproducers/1370-minimal.S b/reproducers/1370-minimal.S new file mode 100644 index 0000000..4f213d9 --- /dev/null +++ b/reproducers/1370-minimal.S @@ -0,0 +1,44 @@ +.section .text +.global _start + +_bb_0x401040: +blsiq %rax, %rbx +ret + +_start: +call _setup_dyn +call _setup_regs +call _bb_0x401040 +call _exit + +_exit: +movq $0, %rdi +movq $60, %rax +syscall + +_alloc: +movq $4096, %rsi +movq $(PROT_READ | PROT_WRITE), %rdx +movq $(MAP_PRIVATE | MAP_ANONYMOUS), %r10 +movq $-1, %r8 +movq $0, %r9 +movq $syscall_mmap, %rax +syscall +ret + +_setup_regs: +mov $0x0, %rax +ret + +_setup_dyn: +ret + +.section .data +PROT_READ = 0x1 +PROT_WRITE = 0x2 +MAP_PRIVATE = 0x2 +MAP_ANONYMOUS = 0x20 +syscall_mmap = 9 + +_setup_mem: + diff --git a/src/focaccia/qemu/_qemu_tool.py b/src/focaccia/qemu/_qemu_tool.py index 7ca556b..d667cdd 100644 --- a/src/focaccia/qemu/_qemu_tool.py +++ b/src/focaccia/qemu/_qemu_tool.py @@ -45,6 +45,12 @@ qemu_crash = { 'snap': None, } +verbosity = { + 'info': ErrorTypes.INFO, + 'warning': ErrorTypes.POSSIBLE, + 'error': ErrorTypes.CONFIRMED, +} + def match_event(event: Event, target: ReadableProgramState) -> bool: # Match just on PC debug(f'Matching for PC {hex(target.read_pc())} with event {hex(event.pc)}') @@ -597,6 +603,20 @@ def main(): except Exception as e: raise Exception(f'Unable to serialize snapshots to file {args.output}: {e}') + if args.reproducer: + from focaccia.reproducer import Reproducer + try: + for r in res: + errs = [e for e in r['errors'] if e.severity >= verbosity[args.error_level]] + if not errs: + continue + + rep = Reproducer(symb_transforms.env.binary_name, symb_transforms.env.argv, symb_transforms.env.envp, r['snap'], r['ref']) + with open(args.reproducer, 'w') as file: + file.write(rep.asm()) + except Exception as e: + raise Exception(f'Unable to generate reproducer: {e}') + if __name__ == "__main__": main() diff --git a/src/focaccia/reproducer.py b/src/focaccia/reproducer.py index 90e1378..6af259d 100644 --- a/src/focaccia/reproducer.py +++ b/src/focaccia/reproducer.py @@ -1,5 +1,5 @@ -from .lldb_target import LLDBConcreteTarget +from .native.lldb_target import LLDBLocalTarget from .snapshot import ProgramState from .symbolic import SymbolicTransform, eval_symbol from .arch import x86 @@ -12,9 +12,9 @@ class ReproducerRegisterError(Exception): pass class Reproducer(): - def __init__(self, oracle: str, argv: str, snap: ProgramState, sym: SymbolicTransform) -> None: + def __init__(self, oracle: str, argv: str, envp: str, snap: ProgramState, sym: SymbolicTransform) -> None: - target = LLDBConcreteTarget(oracle) + target = LLDBLocalTarget(oracle, argv, envp) self.pc = snap.read_register("pc") self.bb = target.get_basic_block_inst(self.pc) @@ -140,7 +140,6 @@ class Reproducer(): asm += f'.section .text\n' asm += f'.global _start\n' asm += f'\n' - asm += f'.org {hex(self.pc)}\n' asm += self.get_bb() asm += self.get_start() asm += self.get_exit() diff --git a/src/focaccia/tools/validate_qemu.py b/src/focaccia/tools/validate_qemu.py index 4b5160f..0b01f87 100755 --- a/src/focaccia/tools/validate_qemu.py +++ b/src/focaccia/tools/validate_qemu.py @@ -86,6 +86,10 @@ memory, and stepping forward by single instructions. help='GDB binary to invoke.') prog.add_argument('--deterministic-log', default=None, help='The directory containing rr traces') + prog.add_argument('--reproducer', + type=str, + help='Generate repoducer executables for detected' + ' errors.') return prog def quoted(s: str) -> str: |