aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_trace_ui.py (follow)
Commit message (Collapse)AuthorAgeFilesLines
* trace: paint the execution trail — including on the decompilerblasty12 hours1-1/+55
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Both code views now show where you came from and where you're going: the instruction you're on ('now'), the ~96 steps behind it ('past', warm) and the ~96 ahead ('future', cool). A trail, not all of history. Painting every address the trace ever touched says almost nothing on a loop-heavy program; the last and next few dozen steps say how you GOT here. Where an address appears on both sides — a loop body, which is most of them — the nearer side wins, because that's the one explaining the step you just took or are about to. **The pseudocode is painted too**, which is the reason to build this here rather than use Tenet. A trace records instructions, so that's what Tenet paints. We already have decomp_map from the split-view work, saying which instructions each C line covers, so the same trail lands on the decompilation: line 46 now | v3 = getenv("POSIXLY_CORRECT"); line 47 future | v4 = (__int64)*a2; line 49 future | if ( v3 ) A C line covers many instructions, so it takes the strongest kind present: now beats past beats future — if the instruction you're standing on belongs to this line, this line is where you are. Two things kept cheap: the trail is recomputed per SEEK rather than per repaint (~200 lookups, and repaints vastly outnumber steps), and decomp_map is cached per function because it's an RPC and stepping is interactive. The colours sit deliberately under the code palette — the trail says "you came through here", the text still has to read as code. tests: +8 UI (21) — the listing carries now/past/future and it reaches the screen; pseudocode is painted; exactly ONE C line is 'now' and it is the line covering the current instruction (not merely some executed line, which is the mistake this check exists to catch). 209/0 scenarios, 27/0 model, 10/0 diff.
* trace: docked registers + timeline, and stepping through timeblasty12 hours1-0/+148
M0 of the trace viewer. --trace FILE loads a Tenet trace beside the binary and docks a pane on the right: where you are in time, the register state there, and a timeline. Docked rather than modal on purpose. A trace turns every other view into "state at time T", so time and registers are context you read WHILE looking at code, not something you open and dismiss. The registers the current instruction WROTE are highlighted. That difference is the entire reason a delta trace is readable, and it's free — the trace already says which registers each line changed. ] / [ step one instruction. } / { step over, by following the stack pointer: a call pushes, so the callee runs with SP below where we started, and stepping until SP comes back up lands after the return. That's cheaper and more portable than recognising call instructions per architecture, and it degrades correctly — on an instruction that calls nothing, SP is already >= the start and it's one step. Verified on a real call: t=13 -> 18, past 5 instructions, where a plain step gives 14. The load waits for the function index because rebasing needs the database's addresses: our echo trace runs at 0x7ffff6faa000 and the same code sits at 0x2000 in the database. Rebased -0x7ffff6fa8000, 12 functions touched. Register values stay as the trace recorded them (they're machine state) while everything else on screen is in database addresses, so the header shows both — "pc 0x2aed (trace 0x7ffff6faaaed)" — rather than leaving the two to be puzzled over side by side. tests: test_trace_ui.py (13) records its own trace with the QEMU tracer and drives the real UI — loads, rebases onto real functions, the dock renders, ] and [ step and the code view follows, and } steps OVER a call found in that trace rather than at a hardcoded index. Skips with a message if the tracer isn't built. 209/0 scenarios. One thing worth recording: my first attempt to add the key bindings SILENTLY did nothing — the pattern contained a literal \\u2026 where the file has a real ellipsis, so the replace matched nothing and the bindings never appeared. The action worked when called directly, which made it look like a key-routing problem. Assert on the replacement, not on the diff looking plausible.