E6121 Reliable Software

Fall 2011 -- Junfeng Yang

Lab 2 is due 11:59pm ET 11/06.

Lab 2: Instruction-Level Recorder

Nondeterministic bugs, or "heisenbugs", are difficult to track down. The moment you attach the buggy program to a debugger, you perturb timing or memory layouts, potentially masking the heisenbugs.

In this lab, you'll build an instruction-level recorder to record a faithful trace of key instructions executed. From this trace, you can reconstruct the buggy execution where the heisenbug surfaced, so that developers can track down the cause.

Our recorder will log four program constructs:

To log these program constructs, our recorder will operate in two steps. In the first step, it instruments a program in LLVM bitcode format, to insert extra calls to the recorder functions. In the second step, when the instrumented program is run, it will call into the recorder's runtime, to log information.

Part A: Setup

You will conduct this programming lab on our server workbench.cs.columbia.edu. You will access this server using SSH using the same username and password as in lab 1. You will again use Git to get and manage the source code of lab 2. (Review lab 1's page if you want to refresh yourself with Git commands.) To get started, log on to workbench.cs.columbia.edu and run the following command

$ git clone /home/e6121/lab2

to clone the lab 2 skeleton into your home directory. Configure and build the skeleton by running

$ cd lab2
$ mkdir obj
$ cd obj
$ ../configure
$ make ENABLE_OPTIMIZED=0

Lab 2 uses "out of the tree" build. Specifically, it allows you to create an output directory for build-generated files, so that you don't have to "taint" the source tree. The obj directory in the above commands is this output directory.

Once the built finishes, you should see files obj/Debug/bin/tern-instr and obj/Debug/lib/libinstr.a obj/Debug/lib/libruntime.a.

Part B: Understanding the Recorder Skeleton

Directory lab2/lib/instr contains two LLVM modules that implements the instrumentation part of the recorder. File lab2/lib/instr/init.cpp intercepts the program begin and end. File lab2/lib/instr/log.cpp intercepts other types of program constructs, such as load and store instructions. These two files are the main files you need to modify for this lab.

Directory lab2/tool/tern-instr uses the two LLVM modules to generate an instrumentation program called tern-instr. When you run this program on a bitcode file X.bc or X.ll, it should generate a X-record.bc file (or X-record.ll if the -S option is present).

We've defined a recorder runtime for you. File lab2/include/tern/runtime/loghooks.h declares the interface of the recorder runtime, and file lab2/lib/runtime/loghooks.cpp provides a simple implementation.

Directory lab2/test contains a few testcases we've created for you. To run the tests, first reconfigure llvm by running

$ cd $LLVM_ROOT/llvm-obj
$ ../llvm-2.7/configure --prefix=$LLVM_ROOT/install

so that the configure script can pick up the runtest command. Then, go back to lab2/obj/test, and run

$ make ENABLE_OPTIMIZED=0

Part C: Recorder Instrumentation

Fill in the missing pieces in lab2/lib/instr/init.cpp and lab2/lib/instr/log.cpp. To intercept program begin and end, we suggest you to add a static constructor and a static destructor to the instrumented program. Refer to function InsertProfilingShutdownCall in LLVM source for an example. The LLVM doxygen documentation will also be helpful, but keep in mind that these documents are generated from the latest source, and may be inconsistent with LLVM 2.7 we're using. The best documentation is the source code itself.

Part D: Record Coreutils

Apply your recorder to the coreutils bc files you built from lab 1.

Submission Instructions

You are required to submit a patch including all your source code changes; see the instructions from lab 1