valgrind

Run and analyze a program with a Valgrind tool, using the specified Valgrind and program options

Syntax:

valgrind general_options [--tool=tool_name [tool_options]] program_name program_options

Runs on:

QNX Neutrino

General options:

Note: The list here provides a quick reference for only some common Valgrind options. The Core Command-line Options section of the Valgrind User Manual explains all general options.
--child-silent-after-fork=yes|no
Whether to remain silent and not show debugging or logging output for child processes created by fork(). Enabling this option makes the output less confusing for multiprocess programs and is especially useful when trace-children is enabled (provided that the child processes call exec*() after the fork() call).
By default, this option is disabled.
--error-exitcode=value
Define an alternative exit code to use if Valgrind detects errors in the program being analyzed. In such cases, the value of this option is returned; if there are no errors, Valgrind just returns whatever value the program returns.
If you set this option to 0 (or don't use it), by default, Valgrind returns the program's value, whether or not any errors were detected.
--error-limit=yes|no
Whether to stop reporting errors after 10,000,000 in total or 1,000 different errors have occurred. Enabling this option limits the performance impact of the error-tracing mechanism in programs with many errors.
By default, this option is enabled.
--extra-debuginfo-path
Specify an extra path for locating debug symbol (.sym) files. Valgrind searches several standard paths, such as /usr/lib/debug, to find debug information when analyzing a program. Sometimes, though, you may need to store the symbol files in a mounted location or a temporary writeable directory (e.g., /tmp). In these cases, you may provide an absolute path in extra-debuginfo-path. For more information about this option, see the Valgrind User Manual.
-h or --help
Display information about valgrind options, both general and tool-specific, then exit. Any other options on the command line are ignored.
--log-file=filename
Send all messages to the specified file. You can specify an absolute or relative file path. An empty filename makes Valgrind abort.
You can use %p in the filename to insert the PID; this is useful when your program creates child processes. You can use %q{VAR} to insert the contents of an environment variable. This feature is useful for multiprocess programs for which an environment variable is defined differently for each process, such as with MPI programs. Note that if the VAR token is invalid, Valgrind aborts. Finally, you can use %% to insert a single % in the filename.
By default, the output from Valgrind is sent to the terminal from where it's run.
--num-callers=number
Set the maximum number of entries to show in stack traces for program locations. Note that this value doesn't affect the overall number of errors reported, just the call chain depth.
Higher settings make Valgrind run slower and use more memory, but are necessary for programs with deep call chains. The default value is 12, and the maximum value is 500.
-q or --quiet
Run silently, printing only error messages. This is useful if you're running automated tests.
--suppressions=filename[,filename]*
Suppress the output of any errors listed in the specified files. You can name up to 100 suppression files, with the names separated by commas.
On QNX Neutrino targets, the default suppression file is /usr/lib/valgrind/default.supp. This file contains comments explaining the syntax required to specify an error to suppress.
--time-stamp=yes|no
Whether to precede each message with a timestamp in the form of days, hours, minutes, seconds, and milliseconds.
This option is disabled by default.
--tool=tool_name
Run the specified Valgrind tool. This is the most important option!
The default tool is Memcheck, so this option isn't needed if you're using that tool. The values that you can set include: cachegrind, helgrind, massif, and memcheck. There are additional tools in the Valgrind suite (and hence, additional supported values) but those listed previously are the most useful tools and the only ones that have been tested for this QNX SDP release. Details on all Valgrind tools are found in the Valgrind User Manual.
--trace-children=yes|no
Whether to trace into any process images created by exec*(). Valgrind automatically traces into any process copies created by fork(), but you must enable the trace-children option to make it follow execution into new process images initiated by exec*().
By default, this option is disabled.
-v or --verbose
Increase output verbosity. This option makes valgrind show information about various aspects of its operation, such as warnings about unusual behavior. You can use multiple -v arguments to produce more information messages, up to three levels. Each argument must be in its own option (e.g., you must specify -v -v for two levels instead of -vv).

Memcheck options:

Note: The list here provides a quick reference for only some common Memcheck options. The Memcheck Command-Line Options section of the Valgrind User Manual explains all tool-specific options.
--freelist-vol=size
Set the size, in bytes, of the space used to store recently freed blocks. A larger freelist means a longer time period in which Memcheck can store freed blocks and detect invalid accesses to them. However, it also means an increased memory footprint.
The default value is 20,000,000 (twenty million) bytes.
--leak-check=no|summary|yes|full
Specify whether to check for leaks and how much leak information to report. If set to a supported value other than no, Valgrind checks for leaks when the program exits and prints either a leak summary only (if summary is specified) or both a summary and details about the leaks found (if yes or full is specified).
The default setting is summary.
--leak-resolution=low|med|high
Control the degree to which stack traces must match to be reported as the same leak.
The option has these supported values:
  • low — only the first two entries, which represent the bottom two functions in the call chain, must match
  • med — the first four entries must match
  • high — all entries must match (this is the default setting)
Note: This option doesn't affect Memcheck's ability to find leaks, only how it presents them.
--show-leak-kinds=list|all|none
Specify which kinds of leaks to look for. This option argument can be a comma-separated list with one or more of these entries:
  • definite — no pointer to the memory can be found so the programmer couldn't have freed it
  • indirect — the blocks that point to the memory are lost themselves
  • possible — a pointer to the middle but not the start of the memory can be found
  • reachable — a pointer to the start of the memory can be found but the memory was never freed
A detailed explanation of these types is given in the Memory leak detection section of the Valgrind User Manual. The all and none settings allow you to compactly request all leak types or none. By default, Memcheck looks for definite and possible leaks.
--track-origins=yes|no
Whether to track the origin of uninitialized memory when it's used dangerously. The origin could be a heap block allocation, a stack variable within a function, a client request, or other sources. Enabling this option is helpful for interpreting undefined value use errors.
Note: This option is disabled by default because origin tracking severely degrades performance, both in speed and memory usage. But it greatly reduces the effort needed to find the cause of undefined value use errors, so it's often worth the cost.
If you enable this option, you must also enable undef-value-errors; if you don't, Valgrind doesn't run and reports an error.
--undef-value-errors=yes|no
Whether to report undefined value use errors. Disabling this option speeds up Memcheck.
This option is enabled by default.

Massif options:

Note: The list here provides a quick reference for only some common Massif options. The Massif Command-line Options section of the Valgrind User Manual explains all tool-specific options.
--detailed-freq=N
Set how often the heap snapshots are detailed, meaning Massif does an in-depth analysis of the current heap blocks. In the results, the detailed snapshots include stack traces of where the blocks were allocated as well as a breakdown of heap memory by allocation point. The lowest allowable value is 1, which makes every snapshot detailed.
The default setting is 10, so Massif does this in-depth analysis for every tenth snapshot.
--heap=yes|no
Whether to profile heap blocks.
By default, this option is enabled.
--massif-out-file=filename
Write the heap profiling data to the specified file instead of the default massif.out.pid. You can specify an absolute or relative file path. An empty filename makes Valgrind abort.
You can use %p and %q in the filename to insert the PID and the contents of an environment variable, the same as with the --log-file general option for Valgrind.
--max-snapshots=N
Set the maximum number of snapshots to keep in the results. Whenever Massif takes another snapshot and exceeds this limit, half of them are deleted. For all programs except short-running ones, the final number of snapshots is between N/2 and N.
The default limit is 100.
--peak-inaccuracy=m.n
Specify the percentage by which memory allocation must exceed the previous peak to be considered the new peak. This memory usage checking doesn't guarantee that Massif records the actual peak because there can be many high points in memory usage that are quite close together. Reducing this option's value increases the accuracy of the checking, but for low values approaching and including 0%, Massif runs very slowly.
The value is specified as a decimal number, so you can use fractions of a percent. The default setting is 1% (1.0).
--stacks=yes|no
Whether to profile stacks. Enabling this option greatly slows down Massif but produces stack usage data that's easier to interpret than what's produced with Memcheck.
This option is disabled by default.
--threshold=m.n
Set the relative size threshold for heap blocks to be reported individually in the results. Allocations for blocks smaller than this threshold are aggregated into a single results entry.
The value is specified as a decimal number, so you can use fractions of a percent. The default setting is 1% (1.0).
--time-unit=i|ms|B
Specify the time unit for measuring execution progress. The possible values are:
  • i for instructions — machine instructions, not lines of code
  • ms for milliseconds — the real time since the start of the program
  • B for bytes — the number of bytes currently allocated on the heap
The default time unit is instructions, but this might not produce the best output graph for short-running programs. This is because the setup activities might be significant against the execution time of main(), and so all of a program's heap management operations might appear as a sudden spike in the graph. In this case, you should set the option to B to use bytes. The output graph will then illustrate the history of heap size changes.

Helgrind options:

Note: The list here provides a quick reference for only some common Helgrind options. The Helgrind Command-line Options section of the Valgrind User Manual explains all tool-specific options.
--conflict-cache-size=N
The size of the cache to keep for storing information about conflicting memory accesses. This value is the number of memory addresses for which access history is kept, not the number of bytes. Note that this option is effective only when history-level is full.
The default value is 1,000,000 (one million). The minimum value is 10,000, and the maximum value is 30,000,000 (thirty million).
If you're seeing data race errors with only one stack instead of two stacks as expected, increase this value, but be aware that doing so significantly expands the memory footprint.
--history-level=none|approx|full
How much historical data to keep about conflicting memory accesses. The default setting is full and it makes Helgrind store and report two stack traces for data races—the full trace of the current access to a memory location and the partial trace (up to 8 entries) of the previous access. This setting uses a lot of CPU and memory but is very useful for finding the root cause of data races.
To improve performance, you can set a history level of approx, which makes Helgrind report the full trace of the current access and two earlier traces such that the previous access happened between those earlier traces. This information is less accurate than what's reported with full, but the program and tool run much faster.
The none value means no information is kept about previous accesses. This is the fastest setting and it lets you disable searching for data races.
--track-lockorders=no|yes
Whether to perform lock order consistency checking. By default, this option is enabled, so Helgrind monitors the order in which threads acquire locks and reports any inconsistencies in this ordering. Inconsistent locking can lead to lock cycles (i.e., patterns of circular dependency between threads acquiring the same set of locks), which create potential deadlocks. This information is useful because potential deadlocks are often missed during testing but can lead to hard-to-diagnose failures.
For programs with many bugs, the large number of lock order errors reported can be annoying, particularly if you're interested in race errors only. In this case, you can disable this option.

Cachegrind options:

Note: The list here summarizes the Cachegrind options. For more information on these options and the command-line tools for interpreting the raw output of cachegrind, see the Using Cachegrind, cg_annotate and cg_merge section in the Valgrind User Manual.
--branch-sim=no|yes
Whether to collect branch instruction and misprediction counts. When enabled this setting slows Cachegrind noticeably, so by default it's disabled. You can't set both branch-sim and cache-sim to no (because no information would be collected).
--cache-sim=no|yes
Whether to collect cache access and miss counts. By default, this setting is enabled. You can't set both branch-sim and cache-sim to no (because no information would be collected).
--cachegrind-out-file=filename
Write the profiling data to the specified file rather than the default file of cachegrind.out.pid. You can use the %p and %q modifiers to insert the PID or the value of an environment variable, similar to --log-file.
--D1=size,associativity,line size
Set the size, associativity, and line size of the first-level data cache. The first and third values are in bytes while the second value must be a power of two between 1 (for direct mapping) and 1024 (for 1024-way associativity).
--I1=size,associativity,line size
Set the size, associativity, and line size of the first-level instruction cache. The first and third values are in bytes while the second value must be a power of two between 1 (for direct mapping) and 1024 (for 1024-way associativity).
--LL=size,associativity,line size
Set the size, associativity, and line size of the last-level unified cache. The first and third values are in bytes while the second value must be a power of two between 1 (for direct mapping) and 1024 (for 1024-way associativity).

Description:

The valgrind utility lets you use a Valgrind tool to analyze a program's runtime behavior. The utility takes an executable binary and uses the selected tool to add instrumentation code, then runs the program on a synthetic CPU. This design means you don't have to recompile the program to analyze it with Valgrind. Because Valgrind simulates the execution of every machine instruction, the active tool analyzes the code not only in your program but also in all linked libraries, including the C library.

Note:
The default buildfiles shipped with most BSPs don't include this utility in the target image. To run valgrind, you can:
  • Copy the Valgrind binary and libraries you need to a writeable target location (e.g., /tmp)
  • Include the necessary Valgrind files in a location mounted on the target
  • Modify your target image to include the Valgrind files, as explained in Adding Valgrind to your target image

Your program binary and the libraries it uses must contain debug symbols if you want to see accurate file names and line numbers in the results. The exception is the libc library; its debug symbols must be provided to Valgrind for it to run at all. There are two methods of making debug symbols available, as explained in Providing debug symbols to Valgrind.

When launching Valgrind on the target, your command line must include:
  • the path and name of the valgrind binary
  • general Valgrind options that you want to set
  • the tool to use, if you're not using Memcheck
  • any options to configure the selected tool as needed
  • the path, name, and any necessary arguments of the program to analyze

For Memcheck, it's recommended to use -O1 compiler optimization but no higher, because higher settings make the tool report false positives.

You can define additional options in the VALGRIND_OPTS environment variable, which is handy for storing default options. Note that any matching options on the command line override those defined in the variable. For tool-specific options, you must prepend the option name with the tool name:
--memcheck:leak-check=yes

The online Valgrind reference describes all current tools in the distribution. Below, we provide examples of common use cases for Memcheck, Massif, Helgrind, and Cachegrind.

Note: Currently, you can't run gdb on a binary being analyzed by valgrind. To do so requires running the vgdb agent on the target, but this agent isn't supported in this release.

Adding Valgrind to your target image

When possible, you should copy the Valgrind binary and libraries to your target's filesystem or to a location mounted on the target; modifying the image is complex and time-consuming (because you have to rebuild and redeploy it). Also, you must be sure that your target image has enough space to hold the Valgrind files in addition to the rest of the image content.

To add Valgrind to your target image, in your buildfile, you must include the valgrind binary (which is included in the QNX SDP installation):
/usr/bin/valgrind=${QNX_TARGET}/${PROCESSOR}/usr/bin/valgrind
The directory containing the vgpreload_toolname-arch-nto.so libraries (which implement the various tools) must also be included:
/usr/lib/valgrind=${QNX_TARGET}/${PROCESSOR}/usr/lib/valgrind

In general, you should store the binary in /usr/bin/valgrind and the libraries and error suppression files in /usr/lib/valgrind. If your target uses a different directory structure, you must specify the alternative locations that store these files in the PATH and VALGRIND_LIB variables. Note that you must export their settings (e.g., export VALGRIND_LIB=path) to make them visible to Valgrind.

For general information on modifying your BSP buildfile and building your target image, see Building Embedded Systems or your BSP User's Guide.

Providing debug symbols to Valgrind

You can provide Valgrind with debug symbols for the program being analyzed by:
  • Running a binary and library files that contain debug symbols
  • Uploading symbol files to a target path searched by Valgrind
The first method is very easy if your target has a writeable filesystem—you don't have to do anything beyond copying the debug versions of the application binary and libraries to the target. But if your target filesystem isn't writeable, you have to rebuild your image with the debug versions of these files included. When doing so, in your buildfile, you must enable the raw attribute for all libraries used by your application, including libc. By default, mkifs strips the debug symbols from binary files, to reduce the image size. Enabling the raw attribute for a binary file keeps this information:
[+raw] libc.so

For details about determining which shared object library files you need, see the Shared libraries section of Building Embedded Systems.

For the second method, you can copy the debug symbol (.sym) files to either the same target directory where you intend to run the program (i.e., the working directory) or a directory in the LD_LIBRARY_PATH or QNX_TARGET environment variables (to use mounted locations). The valgrind binary looks for these files at startup, and always looks in the working directory before searching those other paths. You can also store the symbol files in a directory named in the extra-debuginfo-path option.

If you use LD_LIBRARY_PATH, you must store the symbol files in the same directory as the libraries themselves (i.e., the .so files), but they can be in any directory listed in the variable definition. With QNX_TARGET, you must store the files in a subdirectory within the single path listed in this variable, and this subdirectory must be named for the target architecture. For instance, if QNX_TARGET is /var/tmp and your target is an x86_64 system, the proper path for storing the files is /var/tmp/x86_64.

When setting either of these environment variables, you must export the setting (e.g., export QNX_TARGET=path) to make it visible to Valgrind.

Note: The symbol files must match the library versions used on the target, or the backtrace information won't be accurate.

For QNX SDP components delivered as libraries (e.g., audio drivers, video capture), the symbol files are available from the QNX Software Center. Some component packages contain the stripped libraries and the debug symbol files. For others, there's a separate package for the symbols. Typically, symbol packages are automatically installed, but you should confirm that the symbols you need are installed. For details, see the QNX Software Center User's Guide, available from the QNX download center.

Examples:

Memcheck

Massif

Helgrind

Cachegrind

Exit status:

0
A zero value is returned in any of these cases:
  • you use the default error exit code setting for valgrind and the program being analyzed returns a zero value, whether or not it has errors
  • you set the error-exitcode option to override the exit code to return when Valgrind detects errors, but the program being analyzed is error-free and returns a zero value
>0
A nonzero value is returned in any of these cases:
  • you use the default error exit code setting for valgrind and the program being analyzed is hard-coded to return a nonzero value, whether or not it has errors
  • you set the error-exitcode option to override the exit code to return when Valgrind detects errors, and the program being analyzed has errors
  • the valgrind binary experiences an error and can't run the program (e.g., a required library isn't found); in such cases, valgrind returns a value of 1