|
| 1 | +# BAP emulation trace generator |
| 2 | + |
| 3 | +This QEMU fork implements the TCG plugin to generate execution traces in the |
| 4 | +[bap-frame](https://github.com/BinaryAnalysisPlatform/bap-frames) format. |
| 5 | + |
| 6 | +This plugin does not yet support all targets. |
| 7 | +If not listed below it is untested. |
| 8 | + |
| 9 | +Known to work: |
| 10 | + |
| 11 | +- Sparc |
| 12 | +- Hexagon |
| 13 | +- PPC |
| 14 | + |
| 15 | +Needs fixes: |
| 16 | + |
| 17 | +- ARM (cannot get current mode of VCPU if target can switch between ARM/Thumb). |
| 18 | + |
| 19 | +Previous traces were generated with a patched QEMU. |
| 20 | +You can find these in tracewrap-* branches. |
| 21 | + |
| 22 | +## Dependencies |
| 23 | + |
| 24 | +1. Install [piqi](https://piqi.org/downloads/) so you have the `piqi` binary in `PATH`. |
| 25 | +2. Install the developer package of `protobuf-c`. E.g. `protobuf-c-devel` (Fedora), `libprotobuf-c-dev` (Debian). |
| 26 | +3. QEMU dependencies (see [QEMU docs](https://www.qemu.org/docs/master/devel/build-environment.html)). |
| 27 | + |
| 28 | +## Building |
| 29 | + |
| 30 | +```bash |
| 31 | +mkdir build |
| 32 | +cd build |
| 33 | +# See `../configure --help` for a list of targets. |
| 34 | +../configure --enable-plugins --target-list=<target> |
| 35 | +make |
| 36 | +``` |
| 37 | + |
| 38 | +## Tracing a binary |
| 39 | + |
| 40 | +The plugin takes two required arguments: |
| 41 | + |
| 42 | +`bin_path`: The path to the binary emulated. Due to a [QEMU bug](https://gitlab.com/qemu-project/qemu/-/issues/3014) this cannot be inferred. |
| 43 | +`out`: The output file to save the trace into. |
| 44 | +`endianness`: The architecture endanness. |
| 45 | + |
| 46 | +```bash |
| 47 | +./qemu-sparc64 -plugin file=buil/contrib/plugins/bap-tracing/libbap_tracing.so,bin_path=<bin_path>,out=<output-file>,endianness=[b/l] -d plugin <bin_path> |
| 48 | +ls <output-file> |
| 49 | +``` |
| 50 | + |
| 51 | +You can also use the helper shell script: |
| 52 | + |
| 53 | +```bash |
| 54 | +./gen-trace.sh ./build/ sparc64 b <path_to_bin> |
| 55 | +``` |
| 56 | + |
| 57 | +> [!NOTE] |
| 58 | +> The trace plugin currently only generates standard frames. |
| 59 | +> This is due to the limitations of the QEMU plugin API. |
| 60 | +> |
| 61 | +> If the traced binary exits due to an exception it can only indirectly be observed. |
| 62 | +> It will produce a standard frame without any logged post register state. |
| 63 | +> Any completed memory read/write might still be logged. |
| 64 | +> |
| 65 | +> If you suspect this, execute the binary with the `execlog` plugin (see `gen-trace.sh` or `gen-execlog.sh`) |
| 66 | +> to check of the execution stops earlier than expected. |
| 67 | +
|
| 68 | + |
| 69 | +## Trace format |
| 70 | + |
| 71 | +The generated trace consists of three parts: the header, |
| 72 | +a table of contents (TOC) holding the frame entries, and an index into the TOC. |
| 73 | + |
| 74 | +Each frame entry starts with the size of the frame, followed by the actual frame data. |
| 75 | +A fixed number of frame entries are considered one _entry_ in the TOC. |
| 76 | + |
| 77 | +The TOC index is stored at the end. |
| 78 | + |
| 79 | +For specifics about the frame contents, please refer |
| 80 | +to the [definitions](https://github.com/BinaryAnalysisPlatform/bap-frames/tree/master/piqi) in |
| 81 | +the BAP-frames repository. |
| 82 | + |
| 83 | +**Format** |
| 84 | + |
| 85 | +| Offset | Type | Field | Trace section | |
| 86 | +|--------|------|-------|------| |
| 87 | +| 0x0 | uint64_t | magic number (7456879624156307493LL) | Header begin | |
| 88 | +| 0x8 | uint64_t | trace version number | | |
| 89 | +| 0x10 | uint64_t | frame_architecture | | |
| 90 | +| 0x18 | uint64_t | frame_machine, 0 for unspecified. | | |
| 91 | +| 0x20 | uint64_t | n = total number of frames in trace. | | |
| 92 | +| 0x28 | uint64_t | T = offset to TOC index. | | |
| 93 | +| 0x30 | uint64_t | sizeof(frame_0) | TOC begin | |
| 94 | +| 0x38 | meta_frame | frame_0 | | |
| 95 | +| 0x40 | uint64_t | sizeof(frame_1) | | |
| 96 | +| 0x48 | type(frame_1) | frame_1 | | |
| 97 | +| ... | ... | ... | | |
| 98 | +| T-0x10 | uint64_t | sizeof(frame_n-1) | | |
| 99 | +| T-0x8 | type(frame_n-1) | frame_n-1 | | |
| 100 | +| T+0 | uint64_t | m = number of frames per TOC entry | TOC index begin | |
| 101 | +| T+0x8 | uint64_t | offset toc_entry(0) | | |
| 102 | +| T+0x10 | uint64_t | offset toc_entry(1) | | |
| 103 | +| ... | ... | ... | | |
| 104 | +| T+0x8+(0x8*ceil(n/m)) | uint64_t | offset toc_entry(ceil(n/m)) | | |
0 commit comments