Can someone provide a quick top level explanation of how Valgrind works? An example: how does it know when memory is allocated and freed?
Valgrind is a Dynamic Binary Analysis (DPA) tool that uses Dynamic Binary Instrumentation (DPI) framework to check memory allocation, to detect deadlocks and to profile the applications. DPI framework has its own low level memory manager, scheduler, thread handler and signal handler. Valgrind tool suite includes tool like
Valgrind tool uses disassemble and resynthesize mechanism where it loads the application into a process, disassembles the application code, add the instrumentation code for analysis, assembles it back and executes the application. It uses Just Intime Compiler (JIT) to embed the application with the instrumentation code.
Valgrind Tool = Valgrind Core + Tool Plugin
Valgrind Core disassembles the application code and passes the code fragment to tool plugin for instrumentation. The tool plugin adds the analysis code and assembles it back. Thus, Valgrind provides the flexibility to write our own tool on top of the Valgrind framework. Valgrind uses shadow registers and shadow memory to instrument read/write instructions, read/write system call, stack and heap allocations.
Valgrind provides wrappers around the system call and registers for pre and post callbacks for every system call to track the memory accessed as part of the system call. Thus, Valgrind is a OS abstraction layer between Linux Operating system and client application.
The diagram illustrates the 8 phases of Valgrind :
