How does valgrind work?

Solution 1:

Valgrind basically runs your application in a "sandbox." While running in this sandbox, it is able to insert its own instructions to do advanced debugging and profiling.

From the manual:

Your program is then run on a synthetic CPU provided by the Valgrind core. As new code is executed for the first time, the core hands the code to the selected tool. The tool adds its own instrumentation code to this and hands the result back to the core, which coordinates the continued execution of this instrumented code.

So basically, valgrind provides a virtual processor that executes your application. However, before your application instructions are processed, they are passed to tools (such as memcheck). These tools are kind of like plugins, and they are able to modify your application before it is run on the processor.

The great thing about this approach is that you don't have to modify or relink your program at all to run it in valgrind. It does cause your program to run slower, however valgrind isn't meant to measure performance or run during normal execution of your application, so this isn't really an issue.

Solution 2:

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

  1. Memcheck - tracks the memory allocation dynamically and reports memory leaks.
  2. Helgrind - detects and reports dead locks, potential data races and lock reversals.
  3. Cachegrind - simulates how the application interacts with system cache and provides information about cache misses.
  4. Nulgrind - a simple valgrind that never do any analysis. Used by developers for performance benchmark.
  5. Massif - a tool to analyse the heap memory usage of the application.

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 :

8 phases of Valgrind

Solution 3:

valgrind sits as a layer between your program and the OS, intercepting calls to the OS requesting memory (de)allocation and recording what is being manipulated before then actually allocating the memory and passing back an equivalent. It's essentially how most code profilers work, except at a much lower level (system calls instead of program function calls).

Solution 4:

Here you can find some nice info:

  • Valgrind: A Framework for Heavyweight Dynamic Binary Instrumentation
  • http://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.wrapping

Besides familiarize yourself with LD_PRELOAD.

Solution 5:

Valgrind is basically a virtual machine that executes your program. It is a virtual architecture that intercepts each call to allocate/free memory.