Inspect template parameter pack in gdb - c++

I'm trying to debug the following simple program:
#include <iostream>
template <class... Args>
void printAll(Args&&... args) {
using swallow = int[];
swallow{0,
(std::cout << args, 0)...
};
}
int main() {
printAll(1, "23", 4);
}
Compiled with gcc 4.9.2 using:
g++ -std=c++11 -g -O0 foo.cxx
And then debugging with gdb 7.9 using:
gdb a.out
(gdb) break foo.cxx:5
Breakpoint 1 at 0x400884: file foo.cxx, line 5.
(gdb) run
Starting program: /..[snip]../a.out
Breakpoint 1, printAll<int, char const (&) [3], int>(int&&, char const (&) [3], int&&) () at foo.cxx:6
6 swallow{0,
(gdb) bt
#0 printAll<int, char const (&) [3], int>(int&&, char const (&) [3], int&&) () at foo.cxx:6
#1 0x0000000000400813 in main () at foo.cxx:12
I'm in the right function, but I have no way to inspect the parameter pack:
(gdb) info args
No arguments.
(gdb) print args
No symbol "args" in current context.
(gdb) inspect args
No symbol "args" in current context.
How do I actually examine the arguments?

Related: Showing values of parameters packs in gdb
There are two problems here; the first is that g++ emits parameter pack debugging information in the DWARF format using the tags DW_TAG_GNU_template_parameter_pack and DW_TAG_GNU_formal_parameter_pack, which gdb does not yet support (PR linked).
Even when this is fixed, we run into another problem, which is that the debugging information g++ emits is broken; it's missing the parameter name (DW_AT_name) (PR linked).
TBH gdb support for C++11 is pretty abysmal (unsurprising as it was effectively abandoned for so long); another near-showstopper bug for C++11 is that it didn't support rvalue references (DW_TAG_rvalue_reference_type) until version 8, printing error messages like <unknown type in /tmp/a.out, CU 0x0, DIE 0x7f>.
The workaround (other than using clang, or an ancient version of g++ that doesn't use the DW_TAG_GNU_template_parameter_pack tags, e.g. 4.4.7) is to use the stabs debugging format with GCC extensions:
g++ -std=c++11 -gstabs+ -O0 foo.cxx
</>
(gdb) s
void printAll<int, char const (&) [3], int>(int, int&&, char const (&) [3], int&&) (i=999, args#0=#0x7fffffffe45c: 1, args#1=..., args#2=#0x7fffffffe458: 4)
at p.cpp:7
7 swallow{0,
(gdb) p 'args#0'
$1 = (int &) #0x7fffffffe45c: 1

Related

bad_function_call thrown and segmentation fault caused when passing avx variables to std::function

This problem is found when writing some code related to computer graphics, a simplified version of the code is shown below:
#include <bits/stdc++.h>
#define __AVX__ 1
#define __AVX2__ 1
#pragma GCC target("avx,avx2,popcnt,tune=native")
#include <immintrin.h>
namespace with_avx {
class vec {
public:
vec(double x = 0, double y = 0, double z = 0, double t = 0) {
vec_data = _mm256_set_pd(t, z, y, x);
}
__m256d vec_data;
};
} // namespace with_avx
namespace without_avx {
class vec {
public:
vec(double x = 0, double y = 0, double z = 0, double t = 0) {
vec_data[0] = x, vec_data[1] = y, vec_data[2] = z, vec_data[3] = t;
}
double vec_data[4];
};
} // namespace without_avx
#ifdef USE_AVX
using namespace with_avx;
#else
using namespace without_avx;
#endif
vec same(vec x) { return x; }
std::function<vec(vec)> stdfunc = same;
int main() {
vec rand_vec(rand(), rand(), rand());
vec ret = stdfunc(rand_vec);
std::cout<<(double)ret.vec_data[0];
}
If I compile the code with the flag USE_AVX like the following:
g++-12 stdfunction_test.cpp -o ../build/unit_test -D USE_AVX -g
g++ will output some warnings:
In file included from /usr/include/c++/12/functional:59,
from /usr/include/x86_64-linux-gnu/c++/12/bits/stdc++.h:71,
from stdfunction_test.cpp:2:
/usr/include/c++/12/bits/std_function.h: In member function ‘_Res std::function<_Res(_ArgTypes ...)>::operator()(_ArgTypes ...) const [with _Res = with_avx::vec; _ArgTypes = {with_avx::vec}]’:
/usr/include/c++/12/bits/std_function.h:587:7: note: the ABI for passing parameters with 32-byte alignment has changed in GCC 4.6
587 | operator()(_ArgTypes... __args) const
| ^~~~~~~~
Then if I run the code, sometimes segmentation fault is caused with the following output:
[1] 12710 segmentation fault ../build/unit_test
Sometimes, bad_function_call is thrown with the following output:
terminate called after throwing an instance of 'std::bad_function_call'
what(): bad_function_call
[1] 12678 IOT instruction ../build/unit_test
Both of these two errors are made when this line is executed:
vec ret = stdfunc(rand_vec);
I then used gdb for backtrace:
(gdb) bt
#0 0x00007ffff7e35521 in __cxa_throw () from /lib/x86_64-linux-gnu/libstdc++.so.6
#1 0x00007ffff7e2c6f4 in std::__throw_bad_function_call() () from /lib/x86_64-linux-gnu/libstdc++.so.6
#2 0x000055555555558b in std::function<with_avx::vec (with_avx::vec)>::operator()(with_avx::vec) const (this=0x7fffffffda74,
__args#0=...) at /usr/include/c++/12/bits/std_function.h:590
#3 0x000055555555528d in main () at stdfunction_test.cpp:39
However if I don't add the flag, the code would run normally.
I think this is possibly caused by some kind of alignment problems like the warning sait I just don't know how to solve this.
My environment is listed on the following, hope they will be useful:
g++ version: g++-12 (Ubuntu 12-20220319-1ubuntu1) 12.0.1 20220319 (experimental) [master r12-7719-g8ca61ad148f]
OS: Ubuntu-22.04 running on WSL2
Changing the target architecture half way through the file is causing your issue. Presumably parts of std::function's implementation changes with the target architecture. Moving your pragma to the start of the file fixes the problem: https://godbolt.org/z/WP5ah38WP
It'll be safer in general if you set your architecture target via the compiler command line (e.g. -mavx2) which will ensure all your code is compiled with the same architectures: https://godbolt.org/z/z5j79c5eh
Or better, use -march=haswell or -march=native to also set tuning options and enabled related ISA features like BMI1/2, because of things like Why doesn't gcc resolve _mm256_loadu_pd as single vmovupd?
The calling convention for passing a double __attribute__((vector_size(32))) (such as __m256d) changes when AVX is available.
As you can see on Godbolt, without AVX, it's returned via a hidden pointer (in RDI) to the return-value object. A caller assuming an AVX calling convention won't set RDI to a valid pointer, just pass it in YMM0. (For passing by value, on the stack vs. in YMM0 will cause wrong data, but not a segfault directly.)
The std::function member functions were defined without AVX because you included C++ standard headers before that pragma. But your later code will be using it with __m256d.

Have GDB show the type of a template argument

Let's say I'm running GDB on a complicated piece of templated C++ code, and I want to know what types are in the current instanciation ... for example:
template <typename T>
void foo ()
{
/// I've got a breakpoint in here somewhere.
}
So I hit my breakpoint, and I want to know what type T is. How can I do that?
Just type frame in gdb prompt:
(gdb) frame
The function name along with template argument will be printed in the first line of output. See online doc:
All of these commands end by printing two lines of output describing
the frame. The first line shows the frame number, the function name,
the arguments, and the source file and line number of execution in
that frame. The second line shows the text of that source line.
If your compiler emits proper debugging information for template parameters (for non-variadic templates, gcc has done this for several years), you can just reference T as if it were an ordinary type, e.g. with ptype.
I tried this test program:
template<typename T>
T f()
{
return 23;
}
int main()
{
return f<int>();
}
Compiled with -g and set a breakpoint inside f:
(gdb) b 4
Breakpoint 1 at 0x4005c5: file q.cc, line 4.
(gdb) r
Starting program: /tmp/q
Breakpoint 1, f<int> () at q.cc:4
4 return 23;
(gdb) ptype T
type = int
How can I do that?
This will give you mangled name of the current symbol:
(gdb) info symbol $pc
This will give you demangled name:
(gdb) main demangle symbol_name
(gdb) shell c++filt symbol_name
You could also break using regexp as follows:
(gdb) rbreak foo<.*>()
This can also be applied to templated class methods
(gdb) rbreak MyClass<.*>::my_method()

Calling a lambda function in GDB

//gdb-call-lambda.cpp
#include <iostream>
void do_something(void) {
std::cout << "blah blah" << std::endl;
auto lambda_func = [](void){
std::cout << "in lambda" << std::endl;
return;
};
lambda_func();
std::cout << "..." << std::endl;
return;
}
int main(int argc, char **argv) {
do_something();
return 0;
}
In this example program, if you compile (g++ gdb-call-lambda.cpp --std=c++11 -g) and then run it in gdb (gdb ./a.out), you can have GDB call any "normal" function. Example:
(gdb) break main
Breakpoint 1 at 0x4008e7: file gdb-call-lambda.cpp, line 20.
(gdb) r
Starting program: /home/keithb/dev/mytest/gdb-call-lambda/a.out
Breakpoint 1, main (argc=1, argv=0x7fffffffdfb8) at gdb-call-lambda.cpp:20
20 do_something();
(gdb) call do_something()
blah blah
in lambda
...
However, if you then try to call the lambda:
(gdb) break do_something
Breakpoint 2 at 0x400891: file gdb-call-lambda.cpp, line 5.
(gdb) c
Continuing.
Breakpoint 2, do_something () at gdb-call-lambda.cpp:5
5 std::cout << "blah blah" << std::endl;
(gdb) n
blah blah
12 lambda_func();
(gdb) n
in lambda
14 std::cout << "..." << std::endl;
(gdb) call lambda_func()
Invalid data type for function to be called
GDB kinda freaks out. So my question is thus: how do you call a lambda in GDB? Asking GDB what it expects reveals nothing of interest when compared to a normal function:
(gdb) whatis lambda_func
type = __lambda0
(gdb) whatis do_something
type = void (void)
I went to see if lambda_func has any special members, eg a function pointer to call, akin to std::function and/or std::bind:
(gdb) print lambda_func
$1 = {<No data fields>}
No special members? Okay maybe it's just a glorified function pointer?
(gdb) call ((void (void)) lambda_func)()
Program received signal SIGSEGV, Segmentation fault.
0x00007fffffffdeaf in ?? ()
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on".
Evaluation of the expression containing the function
(at 0x0x7fffffffdeaf) will be abandoned.
When the function is done executing, GDB will silently stop.
So I'm not even 100% sure what order to pass any arguments or especially captured types.
I tried additionally call lambda_func.operator()(), call lambda_func::operator(), call lambda_func::operator()(), call __lambda0, call __lambda0(), call __lambda0::operator(), call __lambda0::operator()(), all to no avail.
A search on google reveals things about setting breakpoints in lambdas, but nothing on how to call those lambdas from the debugger.
For what it's worth, this is on Ubuntu 14.04 64-bit using g++ 4.8.2-19ubuntu1 and gdb 7.7-0ubuntu3.1
I was expecting call __lambdaX::operator()() works but it doesn't. I think it is related to GCC implementation. I am not sure if there is a better way but this is my workaround solution when I need to call lambda in GDB.
Briefly, GDB has disassemble command and it gives __lambda0::operator()() const as debug information at the call instruction line. Then, convert that address into a function pointer and call it.
Example explains better.
$ g++ -g -std=c++0x lambda.cpp
$ ./a.out
blah blah
in lambda
...
GDB:
$ gdb ./a.out
GNU gdb (GDB) Fedora 7.7.1-13.fc20
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./a.out...done.
(gdb) b do_something()
Breakpoint 1 at 0x4008a3: file lambda.cpp, line 4.
(gdb) run
Starting program: /home/alper/cplusplus/a.out
Breakpoint 1, do_something () at lambda.cpp:4
4 std::cout << "blah blah" << std::endl;
Missing separate debuginfos, use:
(gdb) n
blah blah
11 lambda_func();
Disassemble do_something
(gdb) disassemble do_something
Dump of assembler code for function do_something():
0x40089b <+0>: push %rbp
0x40089c <+1>: mov %rsp,%rbp
0x40089f <+4>: sub $0x10,%rsp
=> 0x4008a3 <+8>: mov $0x4009fb,%esi
0x4008a8 <+13>: mov $0x601060,%edi
0x4008ad <+18>: callq 0x400750 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc#plt>
0x4008b2 <+23>: mov $0x400770,%esi
0x4008b7 <+28>: mov %rax,%rdi
0x4008ba <+31>: callq 0x400760 <_ZNSolsEPFRSoS_E#plt>
0x4008bf <+36>: lea -0x1(%rbp),%rax
0x4008c3 <+40>: mov %rax,%rdi
0x4008c6 <+43>: callq 0x400870 <__lambda0::operator()() const>
0x4008cb <+48>: mov $0x400a05,%esi
0x4008d0 <+53>: mov $0x601060,%edi
0x4008d5 <+58>: callq 0x400750 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc#plt>
0x4008da <+63>: mov $0x400770,%esi
0x4008df <+68>: mov %rax,%rdi
0x4008e2 <+71>: callq 0x400760 <_ZNSolsEPFRSoS_E#plt>
0x4008e7 <+76>: nop
0x4008e8 <+77>: leaveq
0x4008e9 <+78>: retq
GDB outputs line callq 0x400870 <__lambda0::operator()() const> so convert 0x400870 into a function pointer and call it.
(gdb) call ((void (*)()) 0x400870)()
in lambda
(gdb) call ((void (*)()) 0x400870)()
in lambda
(gdb) call ((void (*)()) 0x400870)()
in lambda
Note: If GCC inlines the lambda, there is nothing to call. For example, if the example above is compiled with optimisation switch -O3, there is no line with __lambda0::operator()() const in GDB disassemble output.
In a less synthetic use case I had success in calling the lambda by calling it as
call myLambda.operator()(param1,param2)
But in the test case in the OP GDB appears to think the function is inlined — even though it's not. I've reported this as bug 28137.
Note: these methods are not guaranteed to work with C++14 generic lambda.
Case 1. When modifying the source code is allowed
Requires modifying the source code for each individual lambda.
Method 1.1. std::function
Wrap the lambda in a std::function, and explicitly instantiate it.
(it does have an extra performance hit for dynamically allocate memory, but it doesn't matter because this is only the debug build)
If the lambda itself
does not take any local data types as input or return one,
it's possible to explicitly instantiate the whole class
Otherwise, operator() can be instantiated by using it in the program.
#include<iostream>
#include<functional>
template class std::function<int(int)>; // explicit instantiation
int main(){
auto a=[](int x){
std::cout<<x<<'\n';
return x+1;
};
std::function a_function{a};
a_function(1); // implicit instantiation
__builtin_trap();
}
Call in gdb as a_function.operator()(1).
Reference:
C++, STL, GDB: Cannot evaluate function maybe inlined - Stack Overflow
c++ - gdb stl functions still show as inlined after disabling optimizations - Stack Overflow
Method 1.2: store the address of the lambda
Program:
#include<iostream>
int main(){
auto a=[](int x){
std::cout<<x<<'\n';
return x+1;
};
auto a_operator_call=&decltype(a)::operator();
__builtin_trap();
}
Call like this: (requires appropriate compilation option so that value of a_operator_call is not optimized out)
(gdb) print (a.*a_operator_call)(1)
1
$1 = 2
Reference:
c++ - Possible to call inline functions in gdb and/or emit them using GCC? - Stack Overflow
Case 2. When modifying the source code is not allowed
Case 2.1. Global lambda
#include<iostream>
auto a=[](int x){
std::cout<<x<<'\n';
return x+1;
};
int main(){
__builtin_trap();
}
You need to disable xmethod (at least in my current gdb version. I think it's a bug)
and call with the syntax a.operator()(...):
(gdb) print a
$1 = {<No data fields>}
(gdb) print a(1)
Invalid data type for function to be called.
(gdb) print a.operator()(1)
Python Exception <class 'TypeError'> expected string or bytes-like object:
Error while looking for matching xmethod workers defined in Python.
(gdb) disable xmethod
(gdb) print a.operator()(1)
1
$2 = 2
Reference:
#836820 - gdb: Python Exception <class 'TypeError'> expected string or bytes-like object: - Debian Bug report logs
Gentoo Forums :: View topic - [solved] gdb can't print types anymore
Case 2.2. Local lambda
Note: for this method it may be required to compile with -fkeep-inline-functions.
Consider a simple program
#include<iostream>
int main(){
auto a=[](int x){
std::cout<<x<<'\n';
return x+1;
};
__builtin_trap();
}
And see what symbols are generated in the executable:
(gdb) shell nm --demangle ./a.out |grep lambda
000000000001fe4c t main::{lambda(int)#1}::operator()(int) const
000000000001ff5c t main::{lambda(int)#1}::operator int (*)(int)() const
000000000001ff40 t main::{lambda(int)#1}::_FUN(int)
(gdb) print 'main::{lambda(int)#1}::operator()(int) const'
$1 = {int (const struct {...} * const, int)} 0x555555573e4c <operator()(int) const>
(gdb) print 'main::{lambda(int)#1}::operator()(int) const' (a, 1)
No symbol "(null)" in current context.
(gdb) set $c='main::{lambda(int)#1}::operator()(int) const'
(gdb) print (a.*$c)(1)
Non-pointer-to-member value used in pointer-to-member construct
(gdb) print $c(&a, 1)
1
$2 = 2
You can see that the symbol has the type of a function pointer, not a pointer-to-member-function,
so it must be called with normal syntax (although as can be seen in method 1.2 above gdb does support function-to-member dereference)
It's possible (for example with a Python program) to
automatically parse the symbols with lambda in its demangled name
get its type with maintenance print type command
on lambda invocation: get the lambda object's actual type with the maintenance print type command
(ptype alone is insufficient as some different types have identical string representation and considered equal by gdb, see example below)
then match the types against each other to determine the correct symbol.
Failed attempts
Use gdb:
(gdb) print a
$1 = {<No data fields>}
(gdb) ptype a
type = struct {
}
(gdb) ptype $c
type = int (*)(const struct {...} * const, int)
Use Python API:
Unfortunately, for some reason it consider different types with identical definition equal.
For example in this program:
#include<iostream>
int main(){
auto a=[](int x){ std::cout<<x<<'\n'; return x+1; };
auto b=[](int x){ std::cout<<x<<'\n'; return x+2; };
struct{ int x; } c;
struct{ int x; } d;
struct{ int y; } e;
__builtin_trap();
}
in an IPython interactive shell embedded in gdb:
In [1]: gdb.parse_and_eval("a").type == gdb.parse_and_eval("b").type
Out[38]: True
In [39]: gdb.parse_and_eval("c").type == gdb.parse_and_eval("d").type
Out[39]: True
In [40]: gdb.parse_and_eval("c").type == gdb.parse_and_eval("e").type
Out[40]: False
Things that can be tried out (although not necessary in this particular case)
-fno-inline-functions
-fkeep-inline-functions
-gdwarf-5
-g3
__attribute__((used))
-fno-eliminate-unused-debug-types
-fkeep-static-functions
-fkeep-static-consts
Reference:
c++ - Cannot evaluate function -- may be inlined - Stack Overflow
c++ - Function to mangle/demangle functions - Stack Overflow
c++ - Getting mangled name from demangled name - Stack Overflow
compiler construction - What is Linux utility to mangle a C++ symbol name? - Stack Overflow
Debugging Options (Using the GNU Compiler Collection (GCC))
How to make gdb show the original non-mangling function name on disassembly model? - Stack Overflow
https://dwarfstd.org/doc/Debugging%20using%20DWARF.pdf

missing call stack frame with assert for gdb 7.6 on mac

When debugging a program that fails an assert I can't get the call stack in gdb. I'm using g++4.8 and gdb from Homebrew on Mavericks.
/usr/local/bin/g++-4.8 --version
g++-4.8 (GCC) 4.8.2
/usr/local/bin/gdb --version
GNU gdb (GDB) 7.6.2
Here is the smallest test to reconstruct the problem
//test.cpp
#include <iostream>
#include <cassert>
int main()
{
int i = 42;
std::cout << "Hello World!" << i << std::endl;
assert(0); // this also happens with abort() which assert(0) winds up calling
}
Compiling and with
/usr/local/bin/g++-4.8 -g -c test.cpp -o test.o
/usr/local/bin/g++-4.8 -g test.o -o test
/usr/local/bin/gdb test
(gdb) r
Starting program: /Users/pmelsted/tmp/test/test
Hello World!42
Assertion failed: (0), function main, file test.cpp, line 7.
Program received signal SIGABRT, Aborted.
0x00007fff9447d866 in ?? ()
(gdb) where
#0 0x00007fff9447d866 in ?? ()
#1 0x00007fff9229835c in ?? ()
#2 0x0000000000000000 in ?? ()
It seems gdb on MacOS don't display call stack correctly (or call stack is corrupted after assert() function call) for 64-bit programs. Here is the program slightly modified:
//test.cpp
#include <iostream>
#include <cassert>
int foo() {
assert(0);
}
int bar() {
return foo();
}
int main()
{
int i = 42;
std::cout << "Hello World!" << i << std::endl;
return bar();
}
I have compiled it invoking the g++ -g 15.cpp -m32 command and have ran it under ggdb. The bt full command shows call stack as the following:
(gdb) bt full
#0 0x9843f952 in ?? ()
No symbol table info available.
#1 0x96193340 in ?? ()
No symbol table info available.
#2 0x9615e43e in ?? ()
No symbol table info available.
#3 0x0000216f in foo () at 15.cpp:6
No locals.
#4 0x0000217b in bar () at 15.cpp:9
No locals.
#5 0x000021e4 in main () at 15.cpp:15
i = 42
(gdb) quit
So, all debug symbols are displayed correctly, first 3 function addresses are corrected and have no name because my libgcc is in release mode.
If I don't use -m32 key during compilation, the call stack is as follows:
(gdb) bt full
#0 0x00007fff8b442866 in ?? ()
No symbol table info available.
#1 0x00007fff8c64735c in ?? ()
No symbol table info available.
#2 0x0000000000000000 in ?? ()
No symbol table info available.
That is definitely wrong call stack, #2 frame function address is 0x0. So, the root cause is gdb can't display call stack correctly for 64-bit applications.
I found a workaround for the problem. Just set the breakpoint to abort() function in gdb:
b abort
then when assert is called it will halt at the breakpoint and at this moment one can see the call stack with bt.

debugging templates with GDB

My gdb is GNU gdb Red Hat Linux (6.3.0.0-1.162.el4rh) and I can't debug templates. How can I debug templates with this debugger?
if your problem is just about placing breakpoint in your code. Here is a little snippet
ex: main.cpp
#include <iostream>
template <typename T>
void coin(T v)
{
std::cout << v << std::endl;
}
template<typename T>
class Foo
{
public:
T bar(T c)
{
return c * 2;
}
};
int main(int argc, char** argv)
{
Foo<int> f;
coin(f.bar(21));
}
compile with
g++ -O0 -g main.cpp
gdb ./a.out
(gdb) b Foo<int>::bar(int)
Breakpoint 2 at 0x804871d: file main.cpp, line 16.
(gdb) b void coin<int>(int)
Breakpoint 1 at 0x804872a: file main.cpp, line 6.
(gdb) r
... debugging start
otherwise you could just use
(gdb) b main.cpp:16
I was having a hard time trying to get gdb debugging to
work with templates code using gdb 6.8 with code compiled with gcc version 4.4.1
After ripping my hair for a while, I found that it magically
started working perfectly when I add the -fPIC switch to the g++ compile arguments.