Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH v2 1/2] gdb, testsuite: adapt function_range expected name
@ 2022-08-04 13:03 Nils-Christian Kempke via Gdb-patches
  2022-08-04 13:03 ` [PATCH v2 2/2] gdb, dwarf: create symbols for template tags without names Nils-Christian Kempke via Gdb-patches
  2022-08-10 12:31 ` [PATCH v2 1/2] gdb, testsuite: adapt function_range expected name Bruno Larsen via Gdb-patches
  0 siblings, 2 replies; 5+ messages in thread
From: Nils-Christian Kempke via Gdb-patches @ 2022-08-04 13:03 UTC (permalink / raw)
  To: gdb-patches

When writing a dwarf testcase for some C++ code I wanted to use the
MACRO_AT_range which in turn uses the function_range proc in dwarf.exp
to extract the bounds of 'main'.

However, the macro failed as GDB prints the C++ 'main' with its
arguments as 'main(int, char**)' or 'main()'.

The reason for this is that in read.c::dwarf2_compute_name we call
c_type_print_args on C++ functions and append their arguments to the
function name.  This does not only happen for 'main' but also for all
other C++ functions.  However, other functions often also have a
DW_AT_linkage_name which gets printed over the function name in
'disassemble' and similar functions.  So, I could only really reproduce
the fail of MARCRO_AT_rang with the C++ 'main' function.

An example might make this more clear.  Given the following code

  >> cat c.cpp
  int foo (int a, float b)
  {
    return 0;
  }

  int main (int argc, char **argv)
  {
    return 0;
  }

which is legal in both languages, C and C++, and compiling it with
e.g. clang or gcc will make the disassemble command look like:

  >> clang --version
  clang version 10.0.0-4ubuntu1
  ...
  >> clang -O0 -g ./c.cpp
  >> gdb -q ./a.out -ex "start"
  ...
  (gdb) disassemble main
  Dump of assembler code for function main(int, char**):
     0x0000000000401120 <+0>:     push   %rbp
     0x0000000000401121 <+1>:     mov    %rsp,%rbp
  ...
     0x0000000000401135 <+21>:    ret
  End of assembler dump.
  (gdb) disassemble foo
  Dump of assembler code for function _Z3fooif:
     0x0000000000401110 <+0>:     push   %rbp
     0x0000000000401111 <+1>:     mov    %rsp,%rbp
  ...
     0x000000000040111f <+15>:    ret
  End of assembler dump.

Note, that main is emitted with its arguments while for foo the linkage
name is being printed, as also visible in its DWARF:

  >> objdump ./a.out --dwarf=info | grep "foo" -A3 -B3
      <2b>   DW_AT_low_pc      : 0x401110
      <33>   DW_AT_high_pc     : 0x10
      <37>   DW_AT_frame_base  : 1 byte block: 56         (DW_OP_reg6 (rbp))
      <39>   DW_AT_linkage_name: (indirect string, offset: 0x39): _Z3fooif
      <3d>   DW_AT_name        : (indirect string, offset: 0x42): foo
      <41>   DW_AT_decl_file   : 1
      <42>   DW_AT_decl_line   : 1
      <43>   DW_AT_type        : <0x9a>

Now, let's rename the C++ file and compile it as C:

  >> mv c.cpp c.c
  >> clang -O0 -g ./c.c
  >> gdb -q ./a.out -ex "start'
  ...
  (gdb) disassemble main
  Dump of assembler code for function main:
     0x0000000000401120 <+0>:     push   %rbp
     0x0000000000401121 <+1>:     mov    %rsp,%rbp
  ...
     0x0000000000401135 <+21>:    ret
  End of assembler dump.
  (gdb) disassemble foo
  Dump of assembler code for function foo:
     0x0000000000401110 <+0>:     push   %rbp
     0x0000000000401111 <+1>:     mov    %rsp,%rbp
  ...
     0x000000000040111f <+15>:    ret
  End of assembler dump.

Note, for foo we did not get a linkage name emitted in DWARF, so
it is printed by its name:

  >> objdump --dwarf=info ./a.out | grep foo -A3 -B3
      <2b>   DW_AT_low_pc      : 0x401110
      <33>   DW_AT_high_pc     : 0x10
      <37>   DW_AT_frame_base  : 1 byte block: 56         (DW_OP_reg6 (rbp))
      <39>   DW_AT_name        : (indirect string, offset: 0x37): foo
      <3d>   DW_AT_decl_file   : 1
      <3e>   DW_AT_decl_line   : 1
      <3f>   DW_AT_prototyped  : 1

To make the macro and proc work with C++ as well, an optional argument
list was added to the regex matching the function name in the
disassemble command in function_range.  This does not change any used
behavior as currently, there exists no C++ test using the proc
function_range.

Signed-off-by: Nils-Christian Kempke <nils-christian.kempke@intel.com>
---
 gdb/testsuite/lib/dwarf.exp | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp
index 356451bcaac..2c1c4056346 100644
--- a/gdb/testsuite/lib/dwarf.exp
+++ b/gdb/testsuite/lib/dwarf.exp
@@ -391,10 +391,14 @@ proc function_range { func src {options {debug}} } {
     }
 
     # Compute the size of the last instruction.
-    if { $func_length == 0 } then {
-	set func_pattern "$func"
-    } else {
-	set func_pattern "$func\\+$func_length"
+    # For C++ GDB appends arguments to the names of functions.  These names
+    # will (if no linkage name is present, and, e.g., main generally has none)
+    # make 'dissasemble' print main (and possibly others) as 'main()' or
+    # 'main(int argc, char **argv)' so we take this into accound here by
+    # allowing an optinal argument list after the function name.
+    set func_pattern "$func\(\?\:\\(\.\*\\)\)?"
+    if { $func_length != 0 } {
+	set func_pattern "$func_pattern\\+$func_length"
     }
     set test "x/2i $func+$func_length"
     gdb_test_multiple $test $test {
-- 
2.25.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 2/2] gdb, dwarf: create symbols for template tags without names
  2022-08-04 13:03 [PATCH v2 1/2] gdb, testsuite: adapt function_range expected name Nils-Christian Kempke via Gdb-patches
@ 2022-08-04 13:03 ` Nils-Christian Kempke via Gdb-patches
  2022-08-10 12:49   ` Bruno Larsen via Gdb-patches
  2022-08-10 12:31 ` [PATCH v2 1/2] gdb, testsuite: adapt function_range expected name Bruno Larsen via Gdb-patches
  1 sibling, 1 reply; 5+ messages in thread
From: Nils-Christian Kempke via Gdb-patches @ 2022-08-04 13:03 UTC (permalink / raw)
  To: gdb-patches

The following GDB behavior was also reported as a GDB bug in

  https://sourceware.org/bugzilla/show_bug.cgi?id=28396

I will reiterate the problem a bit and give some more information here.
This patch closes the above mentioned bug.

The DWARF 5 standard 2.23 'Template Parameters' reads:

   A template type parameter is represented by a debugging information
   entry with the tag DW_TAG_template_type_parameter.  A template value
   parameter is represented by a debugging information entry with the tag
   DW_TAG_template_value_parameter.  The actual template parameter entries
   appear in the same order as the corresponding template formal
   parameter declarations in the source progam.

   A type or value parameter entry may have a DW_AT_name attribute, whose
   value is a null-terminated string containing the name of the
   corresponding formal parameter.

So the DW_AT_name attribute for DW_TAG_template_type_parameter and
DW_TAG_template_value_parameter is optional.

Within GDB, creating a new symbol from some read DIE usually requires the
presence of a DW_AT_name for the DIE (an exception here is the case of
unnamed namespaces or the existence of a linkage name).

This patch makes the presence of the DW_AT_name for template value/type
tags optional, similar to the unnamed namespaces.

For unnamed namespaces dwarf2_name simply returns the constant string
CP_ANONYMOUS_NAMESPACE_STR '(anonymous namespace)'.  For template tags a
case was added to the switch statement calling the
unnamed_template_tag_name helper.  Within the scope of parent which
the template parameter is a child of, the helper counts the position
of the template tag within the unnamed template tags and returns
'<unnamedNUMBER>' where NUMBER is its position.  This way we end up with
unique names within the respective scope of the function/class/struct
(these are the only currenltly supported template kinds within GDB and
usually the compilers) where we discovered the template tags in.

While I do not know of a way to bring GCC to emit template tags without
names there is one for clang/icpx.  Consider the following example

  template<typename A, typename B, typename C>
  class Foo {};

  template<typename, typename B, typename>
  class Foo;

  int main () {
    Foo<double, int, float> f;
    return 0;
  }

The forward declaration for 'Foo' with the missing template type names
'A' and 'C' makes clang emit a bunch of template tags without names:

 ...
  <2><43>: Abbrev Number: 3 (DW_TAG_variable)
    <44>   DW_AT_location    : 2 byte block: 91 78      (DW_OP_fbreg: -8)
    <47>   DW_AT_name        : (indirect string, offset: 0x63): f
    <4b>   DW_AT_decl_file   : 1
    <4c>   DW_AT_decl_line   : 8
    <4d>   DW_AT_type        : <0x59>
 ...
 <1><59>: Abbrev Number: 5 (DW_TAG_class_type)
    <5a>   DW_AT_calling_convention: 5  (pass by value)
    <5b>   DW_AT_name        : (indirect string, offset: 0x74): Foo<double, int, float>
    <5f>   DW_AT_byte_size   : 1
    <60>   DW_AT_decl_file   : 1
    <61>   DW_AT_decl_line   : 2
 <2><62>: Abbrev Number: 6 (DW_TAG_template_type_param)
    <63>   DW_AT_type        : <0x76>
 <2><67>: Abbrev Number: 7 (DW_TAG_template_type_param)
    <68>   DW_AT_type        : <0x52>
    <6c>   DW_AT_name        : (indirect string, offset: 0x6c): B
 <2><70>: Abbrev Number: 6 (DW_TAG_template_type_param)
    <71>   DW_AT_type        : <0x7d>
 ...

Befor this patch, GDB would not create any symbols for the read template
tag DIEs and thus lose knowledge about them.  Breaking at the return
statement and printing f's type would read

  (gdb) ptype f
  type = class Foo<double, int, float> [with B = int] {
      <no data fields>
  }

After this patch GDB does generate symbols from the DWARF (with their
artificial names:

  (gdb) ptype f
  type = class Foo<double, int, float> [with <unnamed0> = double, B = int,
  <unnamed1> = float] {
      <no data fields>
  }

The same principle theoretically applies to template functions.  Also
here, GDB would not record unnamed template TAGs but I know of no visual
way to trigger and test this changed behavior.  Template functions do
not emit a '[with...]' list and their name generation also does not
suffer from template tags without names.  GDB does not check whether or
not a template tag has a name in 'dwarf2_compute_name' and thus, the
names of the template functions are created independently of whether or
not the template TAGs have a DW_TAT_name attribute.  A testcase has
been added in the gdb.dwarf2 for template classes and structs.

Bug:  https://sourceware.org/bugzilla/show_bug.cgi?id=28396
---
 gdb/dwarf2/read.c                             |  46 ++++-
 .../missing-type-name-for-templates.cc        |  58 ++++++
 .../missing-type-name-for-templates.exp       | 170 ++++++++++++++++++
 3 files changed, 273 insertions(+), 1 deletion(-)
 create mode 100644 gdb/testsuite/gdb.dwarf2/missing-type-name-for-templates.cc
 create mode 100644 gdb/testsuite/gdb.dwarf2/missing-type-name-for-templates.exp

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index f03151983dc..178fb2a55ba 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -21893,6 +21893,42 @@ typename_concat (struct obstack *obs, const char *prefix, const char *suffix,
     }
 }
 
+/* Return a generic name for a DW_TAG_template_type_param or
+   DW_TAG_template_value_param tag, missing a DW_AT_name attribute.  We do this
+   per parent, so each function/class/struct template will have their own set
+   of template parameters named <unnnamed0>, <unnamed1>, ... where the
+   enumeration starts at 0 and represents the position of the template tag in
+   the list of unnamed template tags for this parent, counting both, type and
+   value tags.  */
+
+static const char *
+unnamed_template_tag_name (die_info *die, dwarf2_cu *cu)
+{
+  if (die->parent == nullptr)
+    return nullptr;
+
+  /* Count the parent types unnamed template type and value children until, we
+     arrive at our entry.  */
+  size_t nth_unnamed = 0;
+
+  die_info* child = die->parent->child;
+  while (child != die && child != nullptr)
+  {
+    if (child->tag == DW_TAG_template_type_param
+	|| child->tag == DW_TAG_template_value_param)
+      {
+	if (dwarf2_attr (child, DW_AT_name, cu) == nullptr)
+	  ++nth_unnamed;
+      }
+    child = child->sibling;
+  }
+  gdb_assert (child == die);
+
+  const std::string name_str = "<unnamed" + std::to_string (nth_unnamed) + ">";
+  return obstack_strndup (&cu->per_objfile->objfile->per_bfd->storage_obstack,
+			  name_str.c_str (), name_str.size ());
+}
+
 /* Get name of a die, return NULL if not found.  */
 
 static const char *
@@ -21928,7 +21964,9 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu)
       && die->tag != DW_TAG_interface_type
       && die->tag != DW_TAG_structure_type
       && die->tag != DW_TAG_namelist
-      && die->tag != DW_TAG_union_type)
+      && die->tag != DW_TAG_union_type
+      && die->tag != DW_TAG_template_type_param
+      && die->tag != DW_TAG_template_value_param)
     return NULL;
 
   switch (die->tag)
@@ -21948,6 +21986,12 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu)
 	return attr_name;
       return CP_ANONYMOUS_NAMESPACE_STR;
 
+    /* DWARF does not actually require template tags to have a name.  */
+    case DW_TAG_template_type_param:
+    case DW_TAG_template_value_param:
+      if (attr_name == nullptr)
+	return unnamed_template_tag_name (die, cu);
+      /* FALLTHROUGH.  */
     case DW_TAG_class_type:
     case DW_TAG_interface_type:
     case DW_TAG_structure_type:
diff --git a/gdb/testsuite/gdb.dwarf2/missing-type-name-for-templates.cc b/gdb/testsuite/gdb.dwarf2/missing-type-name-for-templates.cc
new file mode 100644
index 00000000000..54a47f286ef
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/missing-type-name-for-templates.cc
@@ -0,0 +1,58 @@
+/* Copyright (C) 2022 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+template<typename first, typename second>
+class template_var1
+{
+  first me;
+  second me2;
+};
+
+template<typename first, typename second>
+class template_var2
+{
+  first me;
+  second me2;
+};
+
+template<int val1, typename first, int val2, typename second>
+class template_var3
+{
+  first me;
+  second me2;
+};
+
+template<typename, typename second>
+class template_var1;
+
+template<typename, typename>
+class template_var2;
+
+template<int, typename, int, typename>
+class template_var3;
+
+int
+main (int argc, char **argv)
+{
+  asm ("main_label: .globl main_label");
+
+  template_var1<int, float> var1;
+  template_var2<int, float> var2;
+  template_var3<0, int, 11, float> var3;
+
+  return 0;
+}
\ No newline at end of file
diff --git a/gdb/testsuite/gdb.dwarf2/missing-type-name-for-templates.exp b/gdb/testsuite/gdb.dwarf2/missing-type-name-for-templates.exp
new file mode 100644
index 00000000000..14339c86ded
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/missing-type-name-for-templates.exp
@@ -0,0 +1,170 @@
+# Copyright 2022 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This tests GDB's handling of DW_TAG_template_type_parameter and
+# DW_TAG_template_value_parameter tags that do not have a DW_AT_name attribute.
+# The attribute is optional for the tags and a bug about GDB not recording
+# the respective symbols (because of the missing name) was reported in PR
+# gdb/28396.
+
+load_lib dwarf.exp
+
+if {![dwarf2_support]} {
+    return 0
+}
+
+standard_testfile .cc .S
+
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+    cu {} {
+	DW_TAG_compile_unit {
+	    {DW_AT_language @DW_LANG_C_plus_plus}
+	} {
+	    declare_labels int float template_var1 template_var2 template_var3
+
+	    int: DW_TAG_base_type {
+		{DW_AT_name "int"}
+		{DW_AT_byte_size 4 DW_FORM_data1}
+		{DW_AT_encoding @DW_ATE_signed}
+	    }
+
+	    float: base_type {
+		{DW_AT_name float}
+		{DW_AT_byte_size 4 DW_FORM_sdata}
+		{DW_AT_encoding @DW_ATE_float}
+	    }
+
+	    DW_TAG_subprogram {
+		{DW_AT_name "main"}
+		{MACRO_AT_range "main"}
+		{DW_AT_type :$int}
+		{DW_AT_external 1 DW_FORM_flag}
+	    } {
+		DW_TAG_variable {
+		    {DW_AT_name "var1"}
+		    {DW_AT_type :$template_var1}
+		}
+		DW_TAG_variable {
+		    {DW_AT_name "var2"}
+		    {DW_AT_type :$template_var2}
+		}
+		DW_TAG_variable {
+		    {DW_AT_name "var3"}
+		    {DW_AT_type :$template_var3}
+		}
+	    }
+
+	    # A variable whose type is a template instantiation with two
+	    # template parameters, one unnamed.
+	    template_var1: DW_TAG_structure_type {
+		{DW_AT_name "template_var1<int, float>"}
+	    } {
+		DW_TAG_member {
+		    {DW_AT_name "me"}
+		    {DW_AT_type :$int}
+		}
+		DW_TAG_member {
+		    {DW_AT_name "me2"}
+		    {DW_AT_type :$float}
+		}
+		DW_TAG_template_type_param {
+		    {DW_AT_type :$int}
+		}
+		DW_TAG_template_type_param {
+		    {DW_AT_name "second"}
+		    {DW_AT_type :$float}
+		}
+	    }
+
+	    # A variable whose type is a template instantiation with two
+	    # template parameters, both unnamed.
+	    template_var2: DW_TAG_class_type {
+		{DW_AT_name "template_var2<int, float>"}
+	    } {
+		DW_TAG_member {
+		    {DW_AT_name "me"}
+		    {DW_AT_type :$int}
+		}
+		DW_TAG_member {
+		    {DW_AT_name "me2"}
+		    {DW_AT_type :$float}
+		}
+		DW_TAG_template_type_param {
+		    {DW_AT_type :$int}
+		}
+		DW_TAG_template_type_param {
+		    {DW_AT_type :$float}
+		}
+	    }
+
+	    # A variable whose type is a template instantiation with four
+	    # template arguments, two types, two values, all unnamed.
+	    template_var3: DW_TAG_structure_type {
+		{DW_AT_name "template_var3<0, int, 11, float>"}
+	    } {
+		DW_TAG_member {
+		    {DW_AT_name "me"}
+		    {DW_AT_type :$int}
+		}
+		DW_TAG_member {
+		    {DW_AT_name "me2"}
+		    {DW_AT_type :$float}
+		}
+		DW_TAG_template_value_param {
+		    {DW_AT_type :$int}
+		    {DW_AT_const_value 0 DW_FORM_sdata}
+		}
+		DW_TAG_template_type_param {
+		    {DW_AT_type :$int}
+		}
+		DW_TAG_template_value_param {
+		    {DW_AT_type :$int}
+		    {DW_AT_const_value 11 DW_FORM_sdata}
+		}
+		DW_TAG_template_type_param {
+		    {DW_AT_type :$float}
+		}
+	    }
+	}
+    }
+}
+
+if { [prepare_for_testing "failed to prepare" ${testfile} \
+	[list $srcfile $asm_file] {nodebug c++}] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+gdb_test "ptype var1" [multi_line \
+    "type = struct template_var1<int, float> \\\[with <unnamed0> = int, second = float\\\] {" \
+    "    <unnamed0> me;" \
+    "    second me2;" \
+    "}"]
+
+gdb_test "ptype var2" [multi_line \
+    "type = class template_var2<int, float> \\\[with <unnamed0> = int, <unnamed1> = float\\\] {" \
+    "    <unnamed0> me;" \
+    "    <unnamed1> me2;" \
+    "}"]
+
+gdb_test "ptype var3" [multi_line \
+    "type = struct template_var3<0, int, 11, float> \\\[with <unnamed1> = int, <unnamed3> = float\\\] {" \
+    "    <unnamed1> me;" \
+    "    <unnamed3> me2;" \
+    "}"]
-- 
2.25.1

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] gdb, testsuite: adapt function_range expected name
  2022-08-04 13:03 [PATCH v2 1/2] gdb, testsuite: adapt function_range expected name Nils-Christian Kempke via Gdb-patches
  2022-08-04 13:03 ` [PATCH v2 2/2] gdb, dwarf: create symbols for template tags without names Nils-Christian Kempke via Gdb-patches
@ 2022-08-10 12:31 ` Bruno Larsen via Gdb-patches
  2022-08-23 15:35   ` Kempke, Nils-Christian via Gdb-patches
  1 sibling, 1 reply; 5+ messages in thread
From: Bruno Larsen via Gdb-patches @ 2022-08-10 12:31 UTC (permalink / raw)
  To: Nils-Christian Kempke, gdb-patches


On 04/08/2022 15:03, Nils-Christian Kempke wrote:
> When writing a dwarf testcase for some C++ code I wanted to use the
> MACRO_AT_range which in turn uses the function_range proc in dwarf.exp
> to extract the bounds of 'main'.
>
> However, the macro failed as GDB prints the C++ 'main' with its
> arguments as 'main(int, char**)' or 'main()'.
>
> The reason for this is that in read.c::dwarf2_compute_name we call
> c_type_print_args on C++ functions and append their arguments to the
> function name.  This does not only happen for 'main' but also for all
> other C++ functions.  However, other functions often also have a
> DW_AT_linkage_name which gets printed over the function name in
> 'disassemble' and similar functions.  So, I could only really reproduce
> the fail of MARCRO_AT_rang with the C++ 'main' function.

Hi Nils, thank you for working on this!

I found this explanation a bit confusing, maybe you could condense it to 
something like

The reason for this is that in read.c::dwarf2_compute_name we call
c_type_print_args on C++ functions and append their arguments to the
function name.  This happens to all c++ functions, but is only visible when
it doesn't have a linkage name.


>
> An example might make this more clear.  Given the following code
>
>    >> cat c.cpp
>    int foo (int a, float b)
>    {
>      return 0;
>    }
>
>    int main (int argc, char **argv)
>    {
>      return 0;
>    }
>
> which is legal in both languages, C and C++, and compiling it with
> e.g. clang or gcc will make the disassemble command look like:
>
>    >> clang --version
>    clang version 10.0.0-4ubuntu1
>    ...
>    >> clang -O0 -g ./c.cpp
>    >> gdb -q ./a.out -ex "start"
>    ...
>    (gdb) disassemble main
>    Dump of assembler code for function main(int, char**):
>       0x0000000000401120 <+0>:     push   %rbp
>       0x0000000000401121 <+1>:     mov    %rsp,%rbp
>    ...
>       0x0000000000401135 <+21>:    ret
>    End of assembler dump.
>    (gdb) disassemble foo
>    Dump of assembler code for function _Z3fooif:
>       0x0000000000401110 <+0>:     push   %rbp
>       0x0000000000401111 <+1>:     mov    %rsp,%rbp
>    ...
>       0x000000000040111f <+15>:    ret
>    End of assembler dump.
>
> Note, that main is emitted with its arguments while for foo the linkage
> name is being printed, as also visible in its DWARF:
>
>    >> objdump ./a.out --dwarf=info | grep "foo" -A3 -B3
>        <2b>   DW_AT_low_pc      : 0x401110
>        <33>   DW_AT_high_pc     : 0x10
>        <37>   DW_AT_frame_base  : 1 byte block: 56         (DW_OP_reg6 (rbp))
>        <39>   DW_AT_linkage_name: (indirect string, offset: 0x39): _Z3fooif
>        <3d>   DW_AT_name        : (indirect string, offset: 0x42): foo
>        <41>   DW_AT_decl_file   : 1
>        <42>   DW_AT_decl_line   : 1
>        <43>   DW_AT_type        : <0x9a>
>
> Now, let's rename the C++ file and compile it as C:
>
>    >> mv c.cpp c.c
>    >> clang -O0 -g ./c.c
>    >> gdb -q ./a.out -ex "start'
>    ...
>    (gdb) disassemble main
>    Dump of assembler code for function main:
>       0x0000000000401120 <+0>:     push   %rbp
>       0x0000000000401121 <+1>:     mov    %rsp,%rbp
>    ...
>       0x0000000000401135 <+21>:    ret
>    End of assembler dump.
>    (gdb) disassemble foo
>    Dump of assembler code for function foo:
>       0x0000000000401110 <+0>:     push   %rbp
>       0x0000000000401111 <+1>:     mov    %rsp,%rbp
>    ...
>       0x000000000040111f <+15>:    ret
>    End of assembler dump.
>
> Note, for foo we did not get a linkage name emitted in DWARF, so
> it is printed by its name:
>
>    >> objdump --dwarf=info ./a.out | grep foo -A3 -B3
>        <2b>   DW_AT_low_pc      : 0x401110
>        <33>   DW_AT_high_pc     : 0x10
>        <37>   DW_AT_frame_base  : 1 byte block: 56         (DW_OP_reg6 (rbp))
>        <39>   DW_AT_name        : (indirect string, offset: 0x37): foo
>        <3d>   DW_AT_decl_file   : 1
>        <3e>   DW_AT_decl_line   : 1
>        <3f>   DW_AT_prototyped  : 1
>
> To make the macro and proc work with C++ as well, an optional argument
> list was added to the regex matching the function name in the
> disassemble command in function_range.  This does not change any used
> behavior as currently, there exists no C++ test using the proc
> function_range.
>
> Signed-off-by: Nils-Christian Kempke <nils-christian.kempke@intel.com>
> ---
>   gdb/testsuite/lib/dwarf.exp | 12 ++++++++----
>   1 file changed, 8 insertions(+), 4 deletions(-)
>
> diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp
> index 356451bcaac..2c1c4056346 100644
> --- a/gdb/testsuite/lib/dwarf.exp
> +++ b/gdb/testsuite/lib/dwarf.exp
> @@ -391,10 +391,14 @@ proc function_range { func src {options {debug}} } {
>       }
>   
>       # Compute the size of the last instruction.
> -    if { $func_length == 0 } then {
> -	set func_pattern "$func"
> -    } else {
> -	set func_pattern "$func\\+$func_length"
> +    # For C++ GDB appends arguments to the names of functions.  These names
> +    # will (if no linkage name is present, and, e.g., main generally has none)
> +    # make 'dissasemble' print main (and possibly others) as 'main()' or
> +    # 'main(int argc, char **argv)' so we take this into accound here by
> +    # allowing an optinal argument list after the function name.

I also think the explanation here could be improved a bit. Maybe 
something like:

# For C++, GDB appends arguments to the names of functions if they don't 
have

# a linkage name. For example, asking gdb to disassemble main will print the

# function name as main() or main(int argc, char **argv). Take this into 
account

# by optionally allowing an argument list after the function name.


The code itself LGTM, however I can't approve patches for pushing.

-- 
Cheers,
Bruno

> +    set func_pattern "$func\(\?\:\\(\.\*\\)\)?"
> +    if { $func_length != 0 } {
> +	set func_pattern "$func_pattern\\+$func_length"
>       }
>       set test "x/2i $func+$func_length"
>       gdb_test_multiple $test $test {


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 2/2] gdb, dwarf: create symbols for template tags without names
  2022-08-04 13:03 ` [PATCH v2 2/2] gdb, dwarf: create symbols for template tags without names Nils-Christian Kempke via Gdb-patches
@ 2022-08-10 12:49   ` Bruno Larsen via Gdb-patches
  0 siblings, 0 replies; 5+ messages in thread
From: Bruno Larsen via Gdb-patches @ 2022-08-10 12:49 UTC (permalink / raw)
  To: Nils-Christian Kempke, gdb-patches


On 04/08/2022 15:03, Nils-Christian Kempke wrote:
> The following GDB behavior was also reported as a GDB bug in
>
>    https://sourceware.org/bugzilla/show_bug.cgi?id=28396
>
> I will reiterate the problem a bit and give some more information here.
> This patch closes the above mentioned bug.
>
> The DWARF 5 standard 2.23 'Template Parameters' reads:
>
>     A template type parameter is represented by a debugging information
>     entry with the tag DW_TAG_template_type_parameter.  A template value
>     parameter is represented by a debugging information entry with the tag
>     DW_TAG_template_value_parameter.  The actual template parameter entries
>     appear in the same order as the corresponding template formal
>     parameter declarations in the source progam.
>
>     A type or value parameter entry may have a DW_AT_name attribute, whose
>     value is a null-terminated string containing the name of the
>     corresponding formal parameter.
>
> So the DW_AT_name attribute for DW_TAG_template_type_parameter and
> DW_TAG_template_value_parameter is optional.
>
> Within GDB, creating a new symbol from some read DIE usually requires the
> presence of a DW_AT_name for the DIE (an exception here is the case of
> unnamed namespaces or the existence of a linkage name).
>
> This patch makes the presence of the DW_AT_name for template value/type
> tags optional, similar to the unnamed namespaces.
>
> For unnamed namespaces dwarf2_name simply returns the constant string
> CP_ANONYMOUS_NAMESPACE_STR '(anonymous namespace)'.  For template tags a
> case was added to the switch statement calling the
> unnamed_template_tag_name helper.  Within the scope of parent which
> the template parameter is a child of, the helper counts the position
> of the template tag within the unnamed template tags and returns
> '<unnamedNUMBER>' where NUMBER is its position.  This way we end up with
> unique names within the respective scope of the function/class/struct
> (these are the only currenltly supported template kinds within GDB and
> usually the compilers) where we discovered the template tags in.
>
> While I do not know of a way to bring GCC to emit template tags without
> names there is one for clang/icpx.  Consider the following example
>
>    template<typename A, typename B, typename C>
>    class Foo {};
>
>    template<typename, typename B, typename>
>    class Foo;
>
>    int main () {
>      Foo<double, int, float> f;
>      return 0;
>    }
>
> The forward declaration for 'Foo' with the missing template type names
> 'A' and 'C' makes clang emit a bunch of template tags without names:
>
>   ...
>    <2><43>: Abbrev Number: 3 (DW_TAG_variable)
>      <44>   DW_AT_location    : 2 byte block: 91 78      (DW_OP_fbreg: -8)
>      <47>   DW_AT_name        : (indirect string, offset: 0x63): f
>      <4b>   DW_AT_decl_file   : 1
>      <4c>   DW_AT_decl_line   : 8
>      <4d>   DW_AT_type        : <0x59>
>   ...
>   <1><59>: Abbrev Number: 5 (DW_TAG_class_type)
>      <5a>   DW_AT_calling_convention: 5  (pass by value)
>      <5b>   DW_AT_name        : (indirect string, offset: 0x74): Foo<double, int, float>
>      <5f>   DW_AT_byte_size   : 1
>      <60>   DW_AT_decl_file   : 1
>      <61>   DW_AT_decl_line   : 2
>   <2><62>: Abbrev Number: 6 (DW_TAG_template_type_param)
>      <63>   DW_AT_type        : <0x76>
>   <2><67>: Abbrev Number: 7 (DW_TAG_template_type_param)
>      <68>   DW_AT_type        : <0x52>
>      <6c>   DW_AT_name        : (indirect string, offset: 0x6c): B
>   <2><70>: Abbrev Number: 6 (DW_TAG_template_type_param)
>      <71>   DW_AT_type        : <0x7d>
>   ...
>
> Befor this patch, GDB would not create any symbols for the read template
> tag DIEs and thus lose knowledge about them.  Breaking at the return
> statement and printing f's type would read
>
>    (gdb) ptype f
>    type = class Foo<double, int, float> [with B = int] {
>        <no data fields>
>    }
>
> After this patch GDB does generate symbols from the DWARF (with their
> artificial names:
>
>    (gdb) ptype f
>    type = class Foo<double, int, float> [with <unnamed0> = double, B = int,
>    <unnamed1> = float] {
>        <no data fields>
>    }
>
> The same principle theoretically applies to template functions.  Also
> here, GDB would not record unnamed template TAGs but I know of no visual
> way to trigger and test this changed behavior.  Template functions do
> not emit a '[with...]' list and their name generation also does not
> suffer from template tags without names.  GDB does not check whether or
> not a template tag has a name in 'dwarf2_compute_name' and thus, the
> names of the template functions are created independently of whether or
> not the template TAGs have a DW_TAT_name attribute.  A testcase has
> been added in the gdb.dwarf2 for template classes and structs.
>
> Bug:  https://sourceware.org/bugzilla/show_bug.cgi?id=28396

Hi Nils,

Thanks for working on this. This version looks OK to me, and is no 
longer failing. I can't approve patches, but it gets a +1 from me

-- 
Cheers,
Bruno


^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: [PATCH v2 1/2] gdb, testsuite: adapt function_range expected name
  2022-08-10 12:31 ` [PATCH v2 1/2] gdb, testsuite: adapt function_range expected name Bruno Larsen via Gdb-patches
@ 2022-08-23 15:35   ` Kempke, Nils-Christian via Gdb-patches
  0 siblings, 0 replies; 5+ messages in thread
From: Kempke, Nils-Christian via Gdb-patches @ 2022-08-23 15:35 UTC (permalink / raw)
  To: Bruno Larsen, gdb-patches



> -----Original Message-----
> From: Bruno Larsen <blarsen@redhat.com>
> Sent: Wednesday, August 10, 2022 2:32 PM
> To: Kempke, Nils-Christian <nils-christian.kempke@intel.com>; gdb-
> patches@sourceware.org
> Subject: Re: [PATCH v2 1/2] gdb, testsuite: adapt function_range expected
> name
> 
> 
> On 04/08/2022 15:03, Nils-Christian Kempke wrote:
> > When writing a dwarf testcase for some C++ code I wanted to use the
> > MACRO_AT_range which in turn uses the function_range proc in dwarf.exp
> > to extract the bounds of 'main'.
> >
> > However, the macro failed as GDB prints the C++ 'main' with its
> > arguments as 'main(int, char**)' or 'main()'.
> >
> > The reason for this is that in read.c::dwarf2_compute_name we call
> > c_type_print_args on C++ functions and append their arguments to the
> > function name.  This does not only happen for 'main' but also for all
> > other C++ functions.  However, other functions often also have a
> > DW_AT_linkage_name which gets printed over the function name in
> > 'disassemble' and similar functions.  So, I could only really reproduce
> > the fail of MARCRO_AT_rang with the C++ 'main' function.
> 
> Hi Nils, thank you for working on this!
> 
> I found this explanation a bit confusing, maybe you could condense it to
> something like
> 
> The reason for this is that in read.c::dwarf2_compute_name we call
> c_type_print_args on C++ functions and append their arguments to the
> function name.  This happens to all c++ functions, but is only visible when
> it doesn't have a linkage name.
> 
> 
> >
> > An example might make this more clear.  Given the following code
> >
> >    >> cat c.cpp
> >    int foo (int a, float b)
> >    {
> >      return 0;
> >    }
> >
> >    int main (int argc, char **argv)
> >    {
> >      return 0;
> >    }
> >
> > which is legal in both languages, C and C++, and compiling it with
> > e.g. clang or gcc will make the disassemble command look like:
> >
> >    >> clang --version
> >    clang version 10.0.0-4ubuntu1
> >    ...
> >    >> clang -O0 -g ./c.cpp
> >    >> gdb -q ./a.out -ex "start"
> >    ...
> >    (gdb) disassemble main
> >    Dump of assembler code for function main(int, char**):
> >       0x0000000000401120 <+0>:     push   %rbp
> >       0x0000000000401121 <+1>:     mov    %rsp,%rbp
> >    ...
> >       0x0000000000401135 <+21>:    ret
> >    End of assembler dump.
> >    (gdb) disassemble foo
> >    Dump of assembler code for function _Z3fooif:
> >       0x0000000000401110 <+0>:     push   %rbp
> >       0x0000000000401111 <+1>:     mov    %rsp,%rbp
> >    ...
> >       0x000000000040111f <+15>:    ret
> >    End of assembler dump.
> >
> > Note, that main is emitted with its arguments while for foo the linkage
> > name is being printed, as also visible in its DWARF:
> >
> >    >> objdump ./a.out --dwarf=info | grep "foo" -A3 -B3
> >        <2b>   DW_AT_low_pc      : 0x401110
> >        <33>   DW_AT_high_pc     : 0x10
> >        <37>   DW_AT_frame_base  : 1 byte block: 56         (DW_OP_reg6 (rbp))
> >        <39>   DW_AT_linkage_name: (indirect string, offset: 0x39): _Z3fooif
> >        <3d>   DW_AT_name        : (indirect string, offset: 0x42): foo
> >        <41>   DW_AT_decl_file   : 1
> >        <42>   DW_AT_decl_line   : 1
> >        <43>   DW_AT_type        : <0x9a>
> >
> > Now, let's rename the C++ file and compile it as C:
> >
> >    >> mv c.cpp c.c
> >    >> clang -O0 -g ./c.c
> >    >> gdb -q ./a.out -ex "start'
> >    ...
> >    (gdb) disassemble main
> >    Dump of assembler code for function main:
> >       0x0000000000401120 <+0>:     push   %rbp
> >       0x0000000000401121 <+1>:     mov    %rsp,%rbp
> >    ...
> >       0x0000000000401135 <+21>:    ret
> >    End of assembler dump.
> >    (gdb) disassemble foo
> >    Dump of assembler code for function foo:
> >       0x0000000000401110 <+0>:     push   %rbp
> >       0x0000000000401111 <+1>:     mov    %rsp,%rbp
> >    ...
> >       0x000000000040111f <+15>:    ret
> >    End of assembler dump.
> >
> > Note, for foo we did not get a linkage name emitted in DWARF, so
> > it is printed by its name:
> >
> >    >> objdump --dwarf=info ./a.out | grep foo -A3 -B3
> >        <2b>   DW_AT_low_pc      : 0x401110
> >        <33>   DW_AT_high_pc     : 0x10
> >        <37>   DW_AT_frame_base  : 1 byte block: 56         (DW_OP_reg6 (rbp))
> >        <39>   DW_AT_name        : (indirect string, offset: 0x37): foo
> >        <3d>   DW_AT_decl_file   : 1
> >        <3e>   DW_AT_decl_line   : 1
> >        <3f>   DW_AT_prototyped  : 1
> >
> > To make the macro and proc work with C++ as well, an optional argument
> > list was added to the regex matching the function name in the
> > disassemble command in function_range.  This does not change any used
> > behavior as currently, there exists no C++ test using the proc
> > function_range.
> >
> > Signed-off-by: Nils-Christian Kempke <nils-christian.kempke@intel.com>
> > ---
> >   gdb/testsuite/lib/dwarf.exp | 12 ++++++++----
> >   1 file changed, 8 insertions(+), 4 deletions(-)
> >
> > diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp
> > index 356451bcaac..2c1c4056346 100644
> > --- a/gdb/testsuite/lib/dwarf.exp
> > +++ b/gdb/testsuite/lib/dwarf.exp
> > @@ -391,10 +391,14 @@ proc function_range { func src {options {debug}} }
> {
> >       }
> >
> >       # Compute the size of the last instruction.
> > -    if { $func_length == 0 } then {
> > -	set func_pattern "$func"
> > -    } else {
> > -	set func_pattern "$func\\+$func_length"
> > +    # For C++ GDB appends arguments to the names of functions.  These
> names
> > +    # will (if no linkage name is present, and, e.g., main generally has none)
> > +    # make 'dissasemble' print main (and possibly others) as 'main()' or
> > +    # 'main(int argc, char **argv)' so we take this into accound here by
> > +    # allowing an optinal argument list after the function name.
> 
> I also think the explanation here could be improved a bit. Maybe
> something like:
> 
> # For C++, GDB appends arguments to the names of functions if they don't
> have
> 
> # a linkage name. For example, asking gdb to disassemble main will print the
> 
> # function name as main() or main(int argc, char **argv). Take this into
> account
> 
> # by optionally allowing an argument list after the function name.
> 
> 
> The code itself LGTM, however I can't approve patches for pushing.
> 
> --
> Cheers,
> Bruno
> 
> > +    set func_pattern "$func\(\?\:\\(\.\*\\)\)?"
> > +    if { $func_length != 0 } {
> > +	set func_pattern "$func_pattern\\+$func_length"
> >       }
> >       set test "x/2i $func+$func_length"
> >       gdb_test_multiple $test $test {


Hi Bruno,

Thanks for reviewing this!  I adapted comment and commit message and
will send version 3 shortly. 

Cheers,
Nils
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-08-23 15:36 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-04 13:03 [PATCH v2 1/2] gdb, testsuite: adapt function_range expected name Nils-Christian Kempke via Gdb-patches
2022-08-04 13:03 ` [PATCH v2 2/2] gdb, dwarf: create symbols for template tags without names Nils-Christian Kempke via Gdb-patches
2022-08-10 12:49   ` Bruno Larsen via Gdb-patches
2022-08-10 12:31 ` [PATCH v2 1/2] gdb, testsuite: adapt function_range expected name Bruno Larsen via Gdb-patches
2022-08-23 15:35   ` Kempke, Nils-Christian via Gdb-patches

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox