Debugging is one of the hardest and most time-consuming activities in developing system software.
Bug reports rarely provide much more than a coredump of the failed program, and the developer is
required to turn into a detective to determine how the program arrived to the failure point.
ESD is a tool for automating most of this detective work. Without requiring any program
modifications or execution tracing, ESD finds a feasible execution of the program that exhibits
the reported bug. It then replays this execution deterministically in a regular debugger, like
gdb, in a way that is transparent to the developers: they just run the program and see the bug
manifest every time. This is particularly useful in debugging concurrency bugs, which are often
quite elusive.
ESD is a practical tool: it requires zero execution tracing, zero program modifications, and is fast: it finds the desired path on the order of seconds or minutes in real programs. It employs a combination of static analysis and symbolic execution to "synthesize" a valid bug-bound execution. We rely on the observation that, for debugging, it is sufficient to find some path leading to the reported bug; the exact path that manifested in production is rarely relevant. ESD's path is usually shorter than the one experienced at the user site, making debugging even easier. ESD relies on a set of heuristics that provide crucial hints for how to explore the space of execution paths and thread schedules efficiently. We have found ESD to be effective and practical for real systems: in software like the SQLite database, HawkNL network library, and UNIX utilities, ESD reproduces entirely automatically several concurrency and memory-error bugs within less than three minutes, starting from just a bug report. More details coming soon! |
