[v3] gdb/dwarf: fix assert failed for missing containing type

Message ID 20251225070238.224671-1-liuke.gehry@bytedance.com
State New
Headers
Series [v3] gdb/dwarf: fix assert failed for missing containing type |

Commit Message

Sockke Dec. 25, 2025, 7:02 a.m. UTC
  gdb/dwarf: fix assert failed for missing containing type

This patch fixes an assertion failure that occurs when handling
missing type units.

If the TU referenced by a `DW_AT_containing_type` cannot be
found (e.g., due to DWP overflow), the error type returned from the
DWARF reader is incorrectly passed to `set_type_vptr_fieldno`, causing
an assertion failure:

gdb/gdbtypes.c:1919: internal-error: internal_type_vptr_fieldno: Assertion `type->code () == TYPE_CODE_STRUCT || type->code () == TYPE_CODE_UNION' failed.

---
 gdb/dwarf2/read.c                             |  8 ++-
 .../gdb.dwarf2/missing-containing-type.exp    | 71 +++++++++++++++++++
 2 files changed, 78 insertions(+), 1 deletion(-)
 create mode 100644 gdb/testsuite/gdb.dwarf2/missing-containing-type.exp
  

Comments

Keith Seitz Jan. 15, 2026, 5:12 p.m. UTC | #1
Hi,

On 12/24/25 11:02 PM, Sockke wrote:
> gdb/dwarf: fix assert failed for missing containing type
> 
> This patch fixes an assertion failure that occurs when handling
> missing type units.

Thank you for the revision. In an effort to get this moving, Simon's
question about an assignment aside 
[https://inbox.sourceware.org/gdb-patches/678d6038-2d42-4167-9b10-891317a669c3@simark.ca/], 
this
patch is looking near complete/ready.

I just have a comment or two.

> diff --git a/gdb/testsuite/gdb.dwarf2/missing-containing-type.exp b/gdb/testsuite/gdb.dwarf2/missing-containing-type.exp
> new file mode 100644
> index 00000000..301c8432
> --- /dev/null
> +++ b/gdb/testsuite/gdb.dwarf2/missing-containing-type.exp
> @@ -0,0 +1,71 @@
> +# Copyright 2025 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/>.
> +load_lib dwarf.exp
> +
> +# This test can only be run on targets which support DWARF-2 and use gas.
> +require dwarf2_support
> +
> +require allow_cplus_tests
> +
> +standard_testfile main.c -dw4.S
> +
> +# Make some DWARF for the test.
> +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 container_decl abase_client_type
> +           DW_TAG_namespace {
> +               DW_AT_name NS
> +           } {
> +               container_decl: DW_TAG_class_type {
> +                   DW_AT_signature     0x1122334455667788 DW_FORM_ref_sig8
> +                   DW_AT_declaration   1                  DW_FORM_flag
> +               } {
> +                   abase_client_type: DW_TAG_class_type {
> +                       DW_AT_name           C
> +                       DW_AT_byte_size      0x170              DW_FORM_sdata
> +                       DW_AT_containing_type :$container_decl
> +                   } {
> +                       DW_TAG_subprogram { DW_AT_name "~C" }
> +                   }
> +               }
> +           }
> +       }
> +    }
> +    # The referenced TU has been lost.
> +    #tu {} 0x1122334455667788 container_type {
> +    #   DW_TAG_type_unit {
> +    #       DW_AT_language @DW_LANG_C_plus_plus
> +    #   } {
> +    #       DW_AT_container_type: class_type {
> +    #           {DW_AT_name C}
> +    #           {DW_AT_byte_size 1 sdata}
> +    #       }
> +    #   }
> +    #}
> +}
> +
> +
> +if { [prepare_for_testing "failed to prepare" ${testfile} \
> +	  [list $srcfile $asm_file] {nodebug}] } {
> +    return
> +}
> +
> +gdb_test_no_output "set language c++"
> +
> +gdb_test "ptype NS::C" "No symbol .*"

Please add a comment explaining that this used to cause gdb to
assert.

And please fix the result of gdb.src/pre-commit.exp. There are
simple whitespace errors to sort out:

$ make check TESTS=gdb.src/pre-commit.exp
[snip]
Running 
/home/keiths/work/gdb/branches/sockke-assert-missing-containing_type/linux/gdb/testsuite/../../../src/gdb/testsuite/gdb.src/pre-commit.exp 
...
FAIL: gdb.src/pre-commit.exp: pre-commit checks

		=== gdb Summary ===

# of unexpected failures	1

Otherwise, LGTM.

Reviewed-By: Keith Seitz <keiths@redhat.com>

Keith
  
Simon Marchi Jan. 15, 2026, 9:21 p.m. UTC | #2
On 1/15/26 12:12 PM, Keith Seitz wrote:
> Hi,
> 
> On 12/24/25 11:02 PM, Sockke wrote:
>> gdb/dwarf: fix assert failed for missing containing type
>>
>> This patch fixes an assertion failure that occurs when handling
>> missing type units.
> 
> Thank you for the revision. In an effort to get this moving, Simon's
> question about an assignment aside [https://inbox.sourceware.org/gdb-patches/678d6038-2d42-4167-9b10-891317a669c3@simark.ca/], this
> patch is looking near complete/ready.
> 
> I just have a comment or two.
> 
>> diff --git a/gdb/testsuite/gdb.dwarf2/missing-containing-type.exp b/gdb/testsuite/gdb.dwarf2/missing-containing-type.exp
>> new file mode 100644
>> index 00000000..301c8432
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.dwarf2/missing-containing-type.exp
>> @@ -0,0 +1,71 @@
>> +# Copyright 2025 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/>.
>> +load_lib dwarf.exp
>> +
>> +# This test can only be run on targets which support DWARF-2 and use gas.
>> +require dwarf2_support
>> +
>> +require allow_cplus_tests
>> +
>> +standard_testfile main.c -dw4.S
>> +
>> +# Make some DWARF for the test.
>> +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 container_decl abase_client_type
>> +           DW_TAG_namespace {
>> +               DW_AT_name NS
>> +           } {
>> +               container_decl: DW_TAG_class_type {
>> +                   DW_AT_signature     0x1122334455667788 DW_FORM_ref_sig8
>> +                   DW_AT_declaration   1                  DW_FORM_flag
>> +               } {
>> +                   abase_client_type: DW_TAG_class_type {
>> +                       DW_AT_name           C
>> +                       DW_AT_byte_size      0x170              DW_FORM_sdata
>> +                       DW_AT_containing_type :$container_decl
>> +                   } {
>> +                       DW_TAG_subprogram { DW_AT_name "~C" }
>> +                   }
>> +               }
>> +           }
>> +       }
>> +    }
>> +    # The referenced TU has been lost.
>> +    #tu {} 0x1122334455667788 container_type {
>> +    #   DW_TAG_type_unit {
>> +    #       DW_AT_language @DW_LANG_C_plus_plus
>> +    #   } {
>> +    #       DW_AT_container_type: class_type {
>> +    #           {DW_AT_name C}
>> +    #           {DW_AT_byte_size 1 sdata}
>> +    #       }
>> +    #   }
>> +    #}
>> +}
>> +
>> +
>> +if { [prepare_for_testing "failed to prepare" ${testfile} \
>> +      [list $srcfile $asm_file] {nodebug}] } {
>> +    return
>> +}
>> +
>> +gdb_test_no_output "set language c++"
>> +
>> +gdb_test "ptype NS::C" "No symbol .*"
> 
> Please add a comment explaining that this used to cause gdb to
> assert.
> 
> And please fix the result of gdb.src/pre-commit.exp. There are
> simple whitespace errors to sort out:
> 
> $ make check TESTS=gdb.src/pre-commit.exp
> [snip]
> Running /home/keiths/work/gdb/branches/sockke-assert-missing-containing_type/linux/gdb/testsuite/../../../src/gdb/testsuite/gdb.src/pre-commit.exp ...
> FAIL: gdb.src/pre-commit.exp: pre-commit checks
> 
>         === gdb Summary ===
> 
> # of unexpected failures    1

When you apply the patch, git tells you about these (I guess they are
the same):

Applying: gdb/dwarf: fix assert failed for missing containing type
Patch failed at 0001 gdb/dwarf: fix assert failed for missing containing type
/home/smarchi/src/binutils-gdb/.git/rebase-apply/patch:63: indent with spaces.
           DW_AT_language @DW_LANG_C_plus_plus
/home/smarchi/src/binutils-gdb/.git/rebase-apply/patch:65: indent with spaces.
           declare_labels container_decl abase_client_type
/home/smarchi/src/binutils-gdb/.git/rebase-apply/patch:66: indent with spaces.
           DW_TAG_namespace {
/home/smarchi/src/binutils-gdb/.git/rebase-apply/patch:67: indent with spaces.
               DW_AT_name NS
/home/smarchi/src/binutils-gdb/.git/rebase-apply/patch:68: indent with spaces.
           } {

Otherwise, it might be a bit easier to see the results if you run
pre-commit directly:

  $ pre-commit run --all-files

Instructions on how to set up pre-commit:

  https://sourceware.org/gdb/wiki/DeveloperTips#Setting_up_pre-commit

Simon
  

Patch

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 4e2644ba..8daa80e3 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -11549,10 +11549,16 @@  process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
 				 "not found when defining class '%s'"),
 			       type->name () ? type->name () : "");
 		}
-	      else
+	      else if (t->code () == TYPE_CODE_STRUCT
+		       || t->code () == TYPE_CODE_UNION)
 		{
 		  set_type_vptr_fieldno (type, TYPE_VPTR_FIELDNO (t));
 		}
+	      else
+		{
+		  complaint (_("unable to retrieve the vptr from "
+			       "this type '%s'"), TYPE_ERROR_NAME (t));
+		}
 	    }
 	  else if (cu->producer_is_xlc ())
 	    {
diff --git a/gdb/testsuite/gdb.dwarf2/missing-containing-type.exp b/gdb/testsuite/gdb.dwarf2/missing-containing-type.exp
new file mode 100644
index 00000000..301c8432
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/missing-containing-type.exp
@@ -0,0 +1,71 @@ 
+# Copyright 2025 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/>.
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+require dwarf2_support
+
+require allow_cplus_tests
+
+standard_testfile main.c -dw4.S
+
+# Make some DWARF for the test.
+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 container_decl abase_client_type
+           DW_TAG_namespace {
+               DW_AT_name NS
+           } {
+               container_decl: DW_TAG_class_type {
+                   DW_AT_signature     0x1122334455667788 DW_FORM_ref_sig8
+                   DW_AT_declaration   1                  DW_FORM_flag
+               } {
+                   abase_client_type: DW_TAG_class_type {
+                       DW_AT_name           C
+                       DW_AT_byte_size      0x170              DW_FORM_sdata
+                       DW_AT_containing_type :$container_decl
+                   } {
+                       DW_TAG_subprogram { DW_AT_name "~C" }
+                   }
+               }
+           }
+       }
+    }
+    # The referenced TU has been lost.
+    #tu {} 0x1122334455667788 container_type {
+    #   DW_TAG_type_unit {
+    #       DW_AT_language @DW_LANG_C_plus_plus
+    #   } {
+    #       DW_AT_container_type: class_type {
+    #           {DW_AT_name C}
+    #           {DW_AT_byte_size 1 sdata}
+    #       }
+    #   }
+    #}
+}
+
+
+if { [prepare_for_testing "failed to prepare" ${testfile} \
+	  [list $srcfile $asm_file] {nodebug}] } {
+    return
+}
+
+gdb_test_no_output "set language c++"
+
+gdb_test "ptype NS::C" "No symbol .*"