Adding debug symbols and instrumentation code to binaries
The active build configuration determines which make commands are used to compile and link binaries in the current project. To debug and analyze your program with certain tools, you must define the right options in those commands.
When you use the IDE to create a project based on standard makefiles, the IDE generates a default makefile that defines the compiler and linker flags required to build different binary versions. These flags are stored in variables with descriptive names (e.g., CCFLAGS_debug, LDFLAGS_profile).
- debug
- release
- coverage
- profile
No tool-enabling options should be used with the release version because it's intended for use in post-deployment (i.e., customer) environments. Also, for some activities, such as profiling, you may have to change the flags and rebuild if you want to measure different metrics.
For QNX Legacy Recursive Make projects, which use managed recursive makefiles, you must adjust the project properties to build the binary for debugging or for generating analysis data. You can't edit the makefiles directly.
Enabling debug symbols
CCFLAGS_debug += -g -O0 -fno-builtin
Or if you're using the C++ compiler:
CXXFLAGS_debug += -g -O0 -fno-builtin
- Choose .
- In the Build Variants tab, expand the listings for all architectural variants that you want to build.
- Check the debug boxes for all variants that you want to debug.
-
Click OK to confirm the settings and exit the properties window.
The IDE updates the makefile and rebuilds the project.
Enabling Code Coverage instrumentation
CCFLAGS_coverage += -g -O0 -ftest-coverage -fprofile-arcs
LDFLAGS_coverage += -ftest-coverage -fprofile-arcs
The above example uses CCFLAGS_coverage, which is meant for the
C compiler, qcc. If you're using the C++ compiler,
q++,you must use CXXFLAGS_coverage (and
LDFLAGS_coverage).- -O0 (
big-oh zero
) — turns off compiler optimization; optimization eliminates some lines of code, making it impossible to maintain separate execution counts for each line - -fprofile-arcs — adds code to the object files to record program arcs (flow)
- -ftest-coverage — generates notes files (.gcno), which are needed to report program coverage
- Choose .
-
In the Options tab, under Build Options, check Build with Code Coverage.
You must have only one architecture and variant selected in the Build Variants tab. Otherwise, the IDE displays an error and won't build the project until you fix the configuration.
-
In the Compiler tab, under Code Generation Options, set Optimization Level to
No optimize
.Code optimization should be turned off because it can produce inaccurate coverage results. Also, in this release, you don't need to explicitly specify the -f options for the compiler flags (CCFLAGS or CXXFLAGS) or linker flags (LDFLAGS).
-
Click OK to confirm the settings and exit the properties window.
The IDE updates the makefile and rebuilds the project.
Full details about all UI fields that control the building of these types of projects are given in the QNX C/C++ Project properties reference.
Enabling call count instrumentation
The qconn agent periodically samples the execution position of a running process, by recording the current address every millisecond. This means that you don't need to instrument the binary to see where in the code your application spends most of its time. However, runtimes estimates based on statistical sampling don't tell the full story because you still need to know how often a function gets called when determining what areas to optimize.
CCFLAGS_debug += -p -g -O0
LDFLAGS_debug += -p -nopie
The above example uses CCFLAGS_debug, which is meant for
the C compiler, qcc. If you're using the C++ compiler,
q++, you must use CXXFLAGS_debug (and
LDFLAGS_debug).For the compiler, the -p option makes it insert code at every function entry to gather call information. This information allows the IDE to display who called that function and its place in the program's call graph, through the right-click menu of the Execution Time view. For the linker, the option makes it link in the profiling version of libc. Note that with the default makefile content, you may have to create the LDFLAGS_debug variable.
When the Sampling profiling method is selected in the Application Profiler UI fields, the IDE always shows runtime estimates in the results, even if -p isn't specified. But in this case, neither the call counts nor the call information previously mentioned are shown. Also, if you enable Use Call Count Instrumentation and then try to run an application binary built without the -p option, the IDE doesn't launch the application and instead displays an error.
- Choose .
- In the Options tab, under Build Options, check Build for Profiling (Call Count Instrumentation).
-
Click OK to confirm the settings and exit the properties window.
The IDE updates the makefile and rebuilds the project.
Enabling function instrumentation
CCFLAGS_profile += -g -O0 -finstrument-functions
LIBS_profile += -lprofilingS
The above example uses CCFLAGS_profile, which is meant for the
C compiler, qcc. If you're using the C++ compiler,
q++, you must use CXXFLAGS_profile (and
LDFLAGS_profile).For the compiler, the -finstrument-functions option makes it insert code at every function entry and exit. This code calls a profiling library function that records the current time. When displaying the results, the IDE can then calculate the total time spent inside a given function, based on its entry and exit timestamps.
For the linker, the -lprofilingS option shown in this example makes it link against the static shared library libprofilingS.a, which implements the time-recording methods needed for profiling. Depending on your system, you may prefer to use the static library file. In this case, you would specify -lprofiling to link against libprofiling.a.
- Choose .
- In the Options tab, under Build Options, check Build for Profiling (Function Instrumentation).
-
Click OK to confirm the settings and exit the properties window.
The IDE updates the makefile and rebuilds the project.