In debuggers, stepping into a function with arguments that involve function calls may step into the nested function calls, even if they are simple and uninteresting, such as those found in the C++ STL.
GDB
Consider the following example:
1 |
|
When GDB stops at the foo
call, the step
(s
) command will step into std::vector::back
and std::unique_ptr::operator*
. While you can execute
finish
(fin
) and then execute s
again, it's time-consuming and distracting, especially when dealing with
complex argument expressions.
1 | % g++ -g a.cc -o a |
This problem was tracked as a feature request in 2003: https://sourceware.org/bugzilla/show_bug.cgi?id=8287.
Fortunately, GDB provides the skip
command to skip functions that match a regex or filenames that match
a glob (GDB 7.12 feature). You can skip all demangled function names
that start with std::
.
1 | skip -rfu ^std:: |
Alternatively, you can execute
skip -gfi /usr/include/c++/*/bits/*
to skip these libstdc++
files.
Important note:
The skip
command's file matching behavior uses the
fnmatch
function with the FNM_FILE_NAME
flag. This means the wildcard character (*
) won't match
slashes. So, skip -gfi /usr/*
won't exclude
/usr/include/c++/14.2.1/bits/stl_vector.h
.
I proposed to drop
the FNM_FILE_NAME
flag. If this is accepted, I will be
able to skip a project directory with
1
skip -gfi */include/llvm/ADT/*
instead of 1
skip -gfi /home/ray/llvm/llvm/include/llvm/ADT/*
User functions called by skipped functions
When a function (let's call it "A") is skipped during debugging, any user-defined functions that are called by "A" will also be skipped.
For example, consider the following code snippet:
1 | std::vector<int> a{1, 2}; |
If std::all_of
is skipped due to a skip
command, predicate
called within std::all_of
will also be skipped when you execute s
at the if
statement.
LLDB
By default, LLDB avoids stepping into functions whose names start
with std::
when you use the s
(step
, thread step-in
) command. This behavior
is controlled by a setting:
1 | (lldb) settings show target.process.thread.step-avoid-regexp |
target.process.thread.step-avoid-libraries
can be used
to skip functions defined in a library.
While the command settings set
is long, you can shorten
it to set set
.
Visual Studio
Visual Studio provides a debugging feature Just My Code that automatically steps over calls to system, framework, and other non-user code.
It also supports a Step Into Specific
command, which
seems interesting.
The implementation inserts a call to
__CheckForDebuggerJustMyCode
at the start of every user
function. The function
(void __CheckForDebuggerJustMyCode(const char *flag)
) takes
a global variable defined in the .msvcjmc
section and
determines whether the debugger should stop.
This LLDB feature request has a nice description: https://github.com/llvm/llvm-project/issues/61152.
For the all_of
example, the feature can possibly allow
the debugger to stop at test
.
1 | std::vector<int> a{1, 2}; |
Fuchsia zxdb
The Fuchsia debugger "zxdb" provides a command "ss" similar to Visual Studio's "Step Into Specific".
1 | [zxdb] ss |