在 gdb 中显示参数包的值

Showing values of parameters packs in gdb

如何在 gdb 的可变参数函数中查看参数包的值?

示例代码(VariadicDebug.cpp):

template <typename... Ts> int Do(int a, Ts... ts)
{
  // Add breakpoint here. a can be seen using 'print a' but how to show ts???
  return a;
}

int main(int argc, char **argv)
{
  return Do(0, "Hello world!", 88.9);
}

编译
g++ --std=c++11 -O0 -g VariadicDebug.cpp

和运行 gdb:

$ gdb ./a.exe
GNU gdb (GDB) 7.9
Copyright (C) 2015 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-pc-msys".
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.exe...done.
(gdb) break VariadicDebug.cpp:4
Breakpoint 1 at 0x100401760: file VariadicDebug.cpp, line 4.
(gdb) run
Starting program: /c/Data/tests/a.exe
[New Thread 8008.0x1dd0]
[New Thread 8008.0x2898]
[New Thread 8008.0x26f0]
[New Thread 8008.0x1498]

Breakpoint 1, Do<char const*, double> (a=0) at VariadicDebug.cpp:4
4         return a;
(gdb) info args
a = 0

如您所见:它只给出 a 的值,不给出 ts 的值.

编辑: gdb:7.9,g++:MSYS2 上的 4.9.2

EDIT: ubuntu 15.04 (g++: 4.9.2, gdb: 7.9, binutils: 2.25) 给出相同的结果

编辑:objdump --debugging 导致:

 <1><81>: Abbrev Number: 7 (DW_TAG_subprogram)
    <82>   DW_AT_external    : 1
    <82>   DW_AT_name        : (indirect string, offset: 0x0): FindItEasy<char const*, double>
    <86>   DW_AT_decl_file   : 1
    <87>   DW_AT_decl_line   : 1
    <88>   DW_AT_linkage_name: (indirect string, offset: 0x3a): _Z10FindItEasyIIPKcdEEiiDpT_
    <8c>   DW_AT_type        : <0x67>
    <90>   DW_AT_low_pc      : 0x400529
    <98>   DW_AT_high_pc     : 0x15
    <a0>   DW_AT_frame_base  : 1 byte block: 9c         (DW_OP_call_frame_cfa)
    <a2>   DW_AT_GNU_all_call_sites: 1
    <a2>   DW_AT_sibling     : <0xdc>
 <2><a6>: Abbrev Number: 8 (DW_TAG_GNU_template_parameter_pack)
    <a7>   DW_AT_name        : Ts
    <aa>   DW_AT_sibling     : <0xb9>
 <3><ae>: Abbrev Number: 9 (DW_TAG_template_type_param)
    <af>   DW_AT_type        : <0xdc>
 <3><b3>: Abbrev Number: 9 (DW_TAG_template_type_param)
    <b4>   DW_AT_type        : <0xe7>
 <3><b8>: Abbrev Number: 0
 <2><b9>: Abbrev Number: 3 (DW_TAG_formal_parameter)
    <ba>   DW_AT_name        : (indirect string, offset: 0x20): first
    <be>   DW_AT_decl_file   : 1
    <bf>   DW_AT_decl_line   : 1
    <c0>   DW_AT_type        : <0x67>
    <c4>   DW_AT_location    : 2 byte block: 91 6c      (DW_OP_fbreg: -20)
 <2><c7>: Abbrev Number: 10 (DW_TAG_GNU_formal_parameter_pack)
    <c8>   DW_AT_decl_file   : 1
    <c9>   DW_AT_decl_line   : 1
 <3><ca>: Abbrev Number: 11 (DW_TAG_formal_parameter)
    <cb>   DW_AT_type        : <0xdc>
    <cf>   DW_AT_location    : 2 byte block: 91 60      (DW_OP_fbreg: -32)
 <3><d2>: Abbrev Number: 11 (DW_TAG_formal_parameter)
    <d3>   DW_AT_type        : <0xe7>
    <d7>   DW_AT_location    : 2 byte block: 91 58      (DW_OP_fbreg: -40)
 <3><da>: Abbrev Number: 0
 <2><db>: Abbrev Number: 0

似乎参数在这里(最后两个DW_TAG_formal_parameter)但是没有他们各自的名字!

EDIT:在生成的 .o 文件上使用 -c 和 运行ning objdump 进行编译也提供相同的输出。那么这是否意味着是我的 g++ 做错了? (如果我不自己编译它,我将不胜感激:-))

在 gdb 中总是有效的一个技巧是在展开 vars 时按 Tab 键!

所以如果你输入:

gdb > print ts tab

你得到

ts#0 ts#1

所以要打印您的变量,您只需使用:

gdb > print 'ts#1'

这里使用单引号很重要!

还有

gdb > info args

给我:

a=0 ts#0 = 0x400d06 "Hello world!" ts#1 = 88,900000000000006

gdb版本为:7.9.1,编译器为5.2.0

根据要求:

我用旧的 4.9.2 gcc 和 运行 过时的 gdb 7.7 编译了 aslo。对我来说结果相同,它也按照此处的说明工作!

编辑: 要找出问题出在哪一边(编译器还是gdb),您可以尝试手动读取调试信息:

备注:我将我的函数名称更改为 'FindItEasy' 并将参数更改为 'First/Rest' 这样我就可以在这里搜索 2 个字母:-)

objdump --debugging

    <158>   DW_AT_name        : (indirect string, offset: 0x18d): FindItEasy
    <15c>   DW_AT_decl_file   : 1
    <15d>   DW_AT_decl_line   : 14
    <15e>   DW_AT_prototyped  : 1
    <15e>   DW_AT_low_pc      : 0x400b6f
    <166>   DW_AT_high_pc     : 0x37
    <16e>   DW_AT_frame_base  : 1 byte block: 9c    (DW_OP_call_frame_cfa)
    <170>   DW_AT_GNU_all_call_sites: 1
    <170>   DW_AT_sibling     : <0x1f8>
 <2><174>: Abbrev Number: 7 (DW_TAG_formal_parameter)
    <175>   DW_AT_name        : (indirect string, offset: 0x59): first
    <179>   DW_AT_decl_file   : 1
    <17a>   DW_AT_decl_line   : 14
    <17b>   DW_AT_type        : <0x34>
    <17f>   DW_AT_location    : 0xbe (location list)
 <2><183>: Abbrev Number: 7 (DW_TAG_formal_parameter)
    <184>   DW_AT_name        : (indirect string, offset: 0x66): rest#0
    <188>   DW_AT_decl_file   : 1
    <189>   DW_AT_decl_line   : 14
    <18a>   DW_AT_type        : <0x6c>
    <18e>   DW_AT_location    : 0x10a (location list)
 <2><192>: Abbrev Number: 7 (DW_TAG_formal_parameter)
    <193>   DW_AT_name        : (indirect string, offset: 0x6d): rest#1
    <197>   DW_AT_decl_file   : 1
    <198>   DW_AT_decl_line   : 14
    <199>   DW_AT_type        : <0x2d>
    <19d>   DW_AT_location    : 0x169 (location list)
 <2><1a1>: Abbrev Number: 8 (DW_TAG_GNU_call_site)
    <1a2>   DW_AT_low_pc      : 0x400b89
    <1aa>   DW_AT_abstract_origin: <0x408>
    <1ae>   DW_AT_sibling     : <0x1ba>

您也许可以尝试在您的文件中找到调试信息。

提示:拥有gdb 和gcc 版本并不完全正确。这两个工具都建立在 binutils 之上。如果 binutils 已过时,则可能某些调试信息(如 dwarf 格式)不完整)。也许您可以检查一下!