Instream prints the flat-line instruction stream of an executing program, the sequence of instructions that actually gets executed. Like single-stepping through it with a debugger (you can achieve something similar with GDB scripting). This implementation uses the hardware single-stepping feature (a.k.a. MSR tracing) of modern processors to do its job efficiently.
$ tar xf instream-0.1.tar.gz $ cd instream-0.1 $ make $ ./instream ./hello | less  Done attaching onto 7176 Target received signal 19 Target received signal 19 Entry point: 400410 400410 (02) 31ed XOR EBP, EBP 400412 (03) 4989d1 MOV R9, RDX 400415 (01) 5e POP RSI 400416 (03) 4889e2 MOV RDX, RSP 400419 (04) 4883e4f0 AND RSP, -0x10 40041d (01) 50 PUSH RAX 40041e (01) 54 PUSH RSP 40041f (07) 49c7c090054000 MOV R8, 0x400590 400426 (07) 48c7c120054000 MOV RCX, 0x400520 40042d (07) 48c7c7fd044000 MOV RDI, 0x4004fd 400434 (05) e8b7ffffff CALL 0x4003f0 ...
It should be possible to build Instream with just a C compiler, all dependencies are bundled with the source.
The mechanism Instream uses is to take control of the target through ptrace, open the ELF file to find its entry point, and inject code at the entry point. This code enables the hardware tracing features. It would be straightforward to instead turn on tracing once the target reaches a given address, or to trace at the per-branch level instead (and disassemble more code). Distorm3 is used for code disassembly (it is included in the source archive below).
- instream-0.1.tar.gz (461 KB): Source code and repository for version 0.1 (April 2014)