Controlling Program Execution through Binary Instrumentation

Heidi Pan, Krste Asanović, Robert Cohn & Chi-Keung Luk


Overview

Proposals for new computer architecture features are usually evaluated through extensive simulation. Many simulators are divided into a front-end functional simulator that executes instructions to model their effect on the architectural state of the machine, and a back-end performance model which takes instruction information from the functional simulator and calculates expected behaviour of a proposed microarchitecture. For simpler microarchitectures, no feedback is required from the back-end performance model to the front-end functional simulator, and the front-end could be replaced with a stored trace of program execution. Many modern microarchitectures, however, are considerably more complex, and accurate execution-driven simulation requires that the back-end control the execution of the front-end. For example, with speculative execution, the back-end directs the front-end to execute down the predicted path until the branch is resolved, at which point the front-end should restore the architectural state at the point of the misprediction before continuing along the correct path.

Binary instrumentation is a powerful technique for implementing architectural simulators, whereby an application executable binary is translated into a new version with instrumentation code added. For example, the binary can be instrumented to insert code before every memory instruction to simulate the effect of the memory reference on the cache. Binary instrumentation provides a much faster implementation of the front-end functional simulator compared with conventional instruction set interpreters, as the instrumented binary runs natively with no interpretive overhead. Another important advantage is that binary instrumentation can leverage the host machine environment to provide compilation tool chains, system call interfaces, and user-level libraries. However, current binary instrumentation infrastructures do not allow instrumentation code to alter the application's execution path, effectively restricting their use to providing feeders for trace-driven simulators.

In this project, we extended the Pin dynamic binary instrumentation infrastructure [1] to allow the program path of execution to be controlled by instrumentation code. We designed a new API that hides details of the underlying dynamic binary translation system from the instrumentation code, and built prototype binary instrumentation tools that model a transactional memory system and a thread scheduler.

Reference(s)

[1] Chi-Keung Luk, Robert Cohn, Robert Muth, Harish Patil, Artur Klauser, Geoff Lowney, Steven Wallace, Vijay Janapa Reddi, Kim Hazelwood, "Pin: Building Customized Program Analysis Tools with Dynamic Instrumentation," Programming Language Design and Implementation (PLDI), Chicago, IL, June 2005.