From 702cf3f5df18818eb62da7ffbd70544fa98da3c7 Mon Sep 17 00:00:00 2001 From: Andrew Burgess Date: Wed, 17 Mar 2021 16:48:25 +0000 Subject: [PATCH] gdb: handle invalid DWARF when compilation unit is missing Replace an abort call in process_psymtab_comp_unit with a real error, and add a test to cover this case. The case is question is when badly formed DWARF is missing a DW_TAG_compile_unit, DW_TAG_partial_unit, or DW_TAG_type_unit as its top level tag. I then tested with --target_board=readnow and added additional code to also validate the top-level tag in this case. I added an assert that would trigger for the readnow case before I added the fix. I suspect there's lots of places where badly formed DWARF could result in the builder being nullptr when it shouldn't be, but I only added this one assert, as this is the one that would have helped me in this case. gdb/ChangeLog: * dwarf2/read.c (process_psymtab_comp_unit): Replace abort with an error. (process_full_comp_unit): Validate the top-level tag before processing the first DIE. (read_func_scope): Ensure we have a valid builder. gdb/testsuite/ChangeLog: * gdb.dwarf2/dw2-missing-cu-tag.c: New file. * gdb.dwarf2/dw2-missing-cu-tag.exp: New file. --- gdb/ChangeLog | 8 ++ gdb/dwarf2/read.c | 21 ++++- gdb/testsuite/ChangeLog | 5 ++ gdb/testsuite/gdb.dwarf2/dw2-missing-cu-tag.c | 25 ++++++ .../gdb.dwarf2/dw2-missing-cu-tag.exp | 76 +++++++++++++++++++ 5 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-missing-cu-tag.c create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-missing-cu-tag.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f3e7f3f8c59..1e076546c14 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,11 @@ +2021-03-22 Andrew Burgess + + * dwarf2/read.c (process_psymtab_comp_unit): Replace abort with an + error. + (process_full_comp_unit): Validate the top-level tag before + processing the first DIE. + (read_func_scope): Ensure we have a valid builder. + 2021-03-22 Andrew Burgess * objc-lang.c (objc_demangle): Renamed to diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index acbc5fa1ad1..2bfb13d6d0e 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -7737,7 +7737,10 @@ process_psymtab_comp_unit (dwarf2_per_cu_data *this_cu, this_cu->unit_type = DW_UT_type; break; default: - abort (); + error (_("Dwarf Error: unexpected tag '%s' at offset %s [in module %s]"), + dwarf_tag_name (reader.comp_unit_die->tag), + sect_offset_str (reader.cu->per_cu->sect_off), + objfile_name (per_objfile->objfile)); } if (reader.dummy_p) @@ -9994,6 +9997,21 @@ process_full_comp_unit (dwarf2_cu *cu, enum language pretend_language) dwarf2_find_base_address (cu->dies, cu); + /* Before we start reading the top-level DIE, ensure it has a valid tag + type. */ + switch (cu->dies->tag) + { + case DW_TAG_compile_unit: + case DW_TAG_partial_unit: + case DW_TAG_type_unit: + break; + default: + error (_("Dwarf Error: unexpected tag '%s' at offset %s [in module %s]"), + dwarf_tag_name (cu->dies->tag), + sect_offset_str (cu->per_cu->sect_off), + objfile_name (per_objfile->objfile)); + } + /* Do line number decoding in read_file_scope () */ process_die (cu->dies, cu); @@ -13628,6 +13646,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) } } + gdb_assert (cu->get_builder () != nullptr); newobj = cu->get_builder ()->push_context (0, lowpc); newobj->name = new_symbol (die, read_type_die (die, cu), cu, (struct symbol *) templ_func); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index cb5dc81578c..848e089db4f 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2021-03-22 Andrew Burgess + + * gdb.dwarf2/dw2-missing-cu-tag.c: New file. + * gdb.dwarf2/dw2-missing-cu-tag.exp: New file. + 2021-03-22 Andrew Burgess * gdb.dwarf2/dw2-using-debug-str.c: New file. diff --git a/gdb/testsuite/gdb.dwarf2/dw2-missing-cu-tag.c b/gdb/testsuite/gdb.dwarf2/dw2-missing-cu-tag.c new file mode 100644 index 00000000000..a361f59e4ce --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-missing-cu-tag.c @@ -0,0 +1,25 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2021 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 + . */ + +int +main (int argc, char **argv) +{ + asm ("main_label: .globl main_label"); + + return 0; +} diff --git a/gdb/testsuite/gdb.dwarf2/dw2-missing-cu-tag.exp b/gdb/testsuite/gdb.dwarf2/dw2-missing-cu-tag.exp new file mode 100644 index 00000000000..8a11d1d5575 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-missing-cu-tag.exp @@ -0,0 +1,76 @@ +# Copyright 2021 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 . + +# This test creates some invalid DWARF, compiles this into an +# executable, then tries to load the executable using the 'file' +# command. We expect to see an error from the DWARF parser. + +load_lib dwarf.exp + +# This test can only be run on targets which support DWARF-2 and use +# gas. +if {![dwarf2_support]} { + return 0 +} + +standard_testfile .c -dw.S + +set asm_file [standard_output_file $srcfile2] +Dwarf::assemble $asm_file { + cu {} { + # We should have either one of DW_TAG_compile_unit, + # DW_TAG_partial_unit, or DW_TAG_type_unit here. + subprogram { + {external 1 flag} + {MACRO_AT_func {main}} + } + } +} + +# Don't use prepare_for_testing here as we want to manually run the +# file command (so we can check its output). +if {[build_executable "failed to build executable" $testfile \ + [list $srcfile $asm_file] {nodebug quiet}]} { + return -1 +} + +# Restart with no executable. +clean_restart + +# This pattern is hit when GDB does not use -readnow (i.e. the default +# behaviour). +set pattern1 \ + [multi_line \ + "Reading symbols from \[^\r\n\]+" \ + "Dwarf Error: unexpected tag 'DW_TAG_subprogram' at offset $hex \\\[\[^\r\n\]+\\\]" \ + "\\(No debugging symbols \[^\r\n\]+\\)"] + +# This pattern is hit when GDB does use -readnow (e.g. running with +# --target_board=readnow). +set pattern2 \ + [multi_line \ + "Reading symbols from \[^\r\n\]+" \ + "Expanding full symbols from \[^\r\n\]+" \ + "Dwarf Error: unexpected tag 'DW_TAG_subprogram' at offset $hex \\\[\[^\r\n\]+\\\]"] + +# Load the executable, we expect an error from the DWARF parser. +gdb_test_multiple "file $binfile" "file $testfile" { + -wrap -re $pattern1 { + pass $gdb_test_name + } + -re -wrap "$pattern2" { + pass $gdb_test_name + } +} -- 2.30.2