diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/focaccia/parser.py | 53 | ||||
| -rw-r--r-- | src/focaccia/qemu/_qemu_tool.py | 8 | ||||
| -rwxr-xr-x | src/focaccia/tools/capture_transforms.py | 7 | ||||
| -rwxr-xr-x | src/focaccia/tools/validate_qemu.py | 4 |
4 files changed, 59 insertions, 13 deletions
diff --git a/src/focaccia/parser.py b/src/focaccia/parser.py index 4df14ec..9c7b283 100644 --- a/src/focaccia/parser.py +++ b/src/focaccia/parser.py @@ -2,8 +2,9 @@ import re import base64 +import msgpack import orjson as json -from typing import TextIO +from typing import TextIO, Literal from .arch import supported_architectures, Arch from .snapshot import ProgramState @@ -30,15 +31,49 @@ def parse_transformations(json_stream: TextIO) -> TraceContainer[SymbolicTransfo return TraceContainer(strace, env) -def serialize_transformations(transforms: Trace[SymbolicTransform], - out_stream: TextIO): +def stream_transformation(stream) -> Trace[SymbolicTransform]: + unpacker = msgpack.Unpacker(stream, raw=False) + + # First object always contains env + header = next(unpacker) + env = TraceEnvironment.from_json(header['env']) + addresses = header.get('addresses') + + def state_iter(): + for obj in unpacker: + t = SymbolicTransform.from_json(obj['state']) + yield t + + return Trace(state_iter(), addresses, env) + +def serialize_transformations(trace: Trace[SymbolicTransform], + out_file: str, + out_type: Literal['msgpack', 'json'] = 'json'): """Serialize symbolic transformations to a text stream.""" - data = json.dumps({ - 'env': transforms.env.to_json(), - 'addrs': transforms.addresses, - 'states': [t.to_json() for t in transforms], - }, option=json.OPT_INDENT_2).decode() - out_stream.write(data) + if out_type == 'json': + with open(out_file, 'w') as out_stream: + data = json.dumps({ + 'env': trace.env.to_json(), + 'addrs': trace.addresses, + 'states': [t.to_json() for t in trace], + }, option=json.OPT_INDENT_2).decode() + out_stream.write(data) + elif out_type == 'msgpack': + with open(out_file, 'wb') as out_stream: + pack = msgpack.Packer() + + # Header: env + addresses (list[int]) + header = { + "env": trace.env.to_json(), + "addresses": getattr(trace, "addresses", None), + } + out_stream.write(pack.pack(header)) + + # States streamed one by one + for state in trace: + out_stream.write(pack.pack({"state": state.to_json()})) + else: + raise NotImplementedError(f'Unable to write transformations to type {out_type}') def parse_snapshots(json_stream: TextIO) -> TraceContainer[ProgramState]: """Parse snapshots from our JSON format.""" diff --git a/src/focaccia/qemu/_qemu_tool.py b/src/focaccia/qemu/_qemu_tool.py index 42f1628..7f1d108 100644 --- a/src/focaccia/qemu/_qemu_tool.py +++ b/src/focaccia/qemu/_qemu_tool.py @@ -261,8 +261,12 @@ def main(): # Read pre-computed symbolic trace try: - with open(args.symb_trace, 'r') as strace: - symb_transforms = parser.parse_transformations(strace) + if args.trace_type == 'json': + file = open(args.symb_trace, 'r') + symb_transforms = parser.parse_transformations(file) + else: + file = open(args.symb_trace, 'rb') + symb_transforms = parser.stream_transformation(file) except Exception as e: raise Exception(f'Failed to parse state transformations from native trace: {e}') diff --git a/src/focaccia/tools/capture_transforms.py b/src/focaccia/tools/capture_transforms.py index 268af36..d69c786 100755 --- a/src/focaccia/tools/capture_transforms.py +++ b/src/focaccia/tools/capture_transforms.py @@ -51,6 +51,10 @@ def main(): type=utils.to_num, help='Set a time limit for executing an instruction symbolically, skip' 'instruction when limit is exceeded') + prog.add_argument('--out-type', + default='json', + choices=['json', 'msgpack'], + help='Symbolic trace output format') args = prog.parse_args() if args.debug: @@ -77,6 +81,5 @@ def main(): trace = tracer.trace(time_limit=args.insn_time_limit) - with open(args.output, 'w') as file: - parser.serialize_transformations(trace, file) + parser.serialize_transformations(trace, args.output, args.out_type) diff --git a/src/focaccia/tools/validate_qemu.py b/src/focaccia/tools/validate_qemu.py index 4b5160f..1d713bd 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('--trace-type', + default='json', + choices=['msgpack', 'json'], + help='The format of the input symbolic trace') return prog def quoted(s: str) -> str: |