This is a draft of a control flow tracer based on source code instrumentation with a low overhead.
Instrument your software with instrumenter.py
. When running instrumented software, the trace is written into a file.
The format is basically one character (plus an optional number)
for each source code block on the trace.
For accurate retracing, retrace.py
uses symbolic execution.
Any software which is written in C/C++, with the source code available.
- python3
- libclang (
pip install libclang
)
- C compiler (or your build system at choice) to compile the instrumented software
- C compiler (or your build system at choice) to compile the instrumented software
- python3
- angr for symbolic execution (
pip install angr
)
- Run make
make
- Install the python package
pip install .
-
Optionally: Change configuration in
include/src_tracer/constants.h
. -
Load the environmental variables
source env.sh
-
First run the pre-processor
cd examples/ cpp -I${SRC_TRACER_INCL} checksum.c -o checksum.i
-
Instrument it (the pre-processed version)
instrumenter.py checksum.i -o checksum_inst.c
For a list of functions together with the
num
generated by the instrumenter, have a look at the newly createdfunctions_database.db
.
- Compile it with
_TRACE_MODE
gcc -D_TRACE_MODE -L${SRC_TRACER_LIB} -I${SRC_TRACER_INCL} checksum_inst.c -o checksum_trace -lsrc_tracer
- Note: you might want to use a diferent compiler like
clang
instead ofgcc
- Note: you might also want compiler optimizations like
-O3
for recording/replaying - Note: if you enabled
TRACEFORK_ZSTD
ininclude/src_tracer/constants.h
, you would need-lzstd
here
- Note: you might want to use a diferent compiler like
- Run it (replace
42
to get another trace)The name of the recorded trace corresponds to the current time, e.g../checksum_trace 42
2023-04-28-143402-checksum.c.trace
. - Display the trace (replace the trace name with the correct one!)
print_trace.py 2023-04-28-143402-checksum.c.trace
- Note: if you enabled
TRACEFORK_ZSTD
ininclude/src_tracer/constants.h
, you would need to decompress the trace first usingzstd -d
- Note: if you enabled
- Compile it with
_RETRACE_MODE
(you might also want different compiler optimizations for recording/replaying)gcc -D_RETRACE_MODE -g -I${SRC_TRACER_INCL} -L${SRC_TRACER_LIB} checksum_inst.c -o checksum_retrace -lsrc_tracer
- Retrace it (use
python -i
to work with the tracedstate
in the interactive shell)The last one just retraces functionretrace.py checksum_retrace 2023-04-28-143402-checksum.c.trace echo "C1 IIO" > sub.trace.txt retrace.py checksum_retrace sub.trace.txt
checksum
.
An example to instrument and retrace busybox with musl-libc can be found in the wiki
You can do it manually as for the checksum.c
example.
For a more automatic way that works well with make scripts, make use of cc_wrapper/
for the gcc compiler.
- Set some envirenmental variables.
This will set CC, CFLAGS and LIBS.
source gcc_env.sh
- Now you can ./configure your project:
export SRC_TRACER="" ./configure
- Before the actual compilation:
export SRC_TRACER="-D_TRACE_MODE"
- Then build your project with
make
,gcc
or similar. Example:gcc $CFLAGS checksum.c -o checksum_trace2 $LIBS
- Traces will be stored in
~/.src_tracer
by default!
- Same envirenmental variables as before.
- If you want to
./configure
your project again (e.g. with other options likeCFLAGS
with-g
) make sure to setSRC_TRACER=""
(as empty string) before you run./configure
. - Before the actual compilation:
export SRC_TRACER="-D_RETRACE_MODE"
- Then build your project with
make
,gcc
or similar. Example:gcc $CFLAGS checksum.c -o checksum_retrace2 $LIBS
It can be a bit tricky to get the binary linking correctly, make sure that the record/replay executable includes the record/replay version of the app and its libraries.