PR gdb/18021 - defend against "static virtual" methods
authorKeith Seitz <keiths@redhat.com>
Fri, 27 Feb 2015 17:55:07 +0000 (09:55 -0800)
committerKeith Seitz <keiths@redhat.com>
Mon, 23 Mar 2015 19:50:28 +0000 (12:50 -0700)
This bug appears to be caused by bad debuginfo. The method
causing the sefault in the reporter's test case is marked both static
and virtual.

This patch simply safegaurds against this case in dwarf2_add_member_fn,
where the code assumes that there is a `this' pointer when a virtual method
is seen (more specifically, when DW_AT_vtable_elem is seen).

It previously dereferenced the first formal parameter
(`this' pointer), which in this case doesn't exist. GDB consequently
segfaulted dereferencing a NULL pointer.

gdb/ChangeLog
PR gdb/18021
* dwarf2read.c (dwarf2_add_member_fn): Issue a complaint
if we find a static method with DW_AT_vtable_elem_location.

gdb/testsuite/ChangeLog
PR gdb/18021
* gdb.dwarf2/staticvirtual.exp: New test.

gdb/ChangeLog
gdb/dwarf2read.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.dwarf2/staticvirtual.exp [new file with mode: 0644]

index 9b6deb446dd1e4cc4072b07109033dd62e14b7a9..6d41940989580e4cb410436e63765914b44712ea 100644 (file)
@@ -1,3 +1,9 @@
+2015-03-23  Keith Seitz  <keiths@redhat.com>
+
+       PR gdb/18021
+       * dwarf2read.c (dwarf2_add_member_fn): Issue a complaint
+       if we find a static method with DW_AT_vtable_elem_location.
+
 2015-03-21  Eli Zaretskii  <eliz@gnu.org>
 
        * tui/tui-io.c (tui_expand_tabs): Reinitialize the column counter
index 898706f4c51aee7b9f596ea2f07151b8b86e6023..4946b4808eeadc1d60aa0b846e8194148de4297e 100644 (file)
@@ -12918,7 +12918,24 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
            dwarf2_complex_location_expr_complaint ();
 
          if (!fnp->fcontext)
-           fnp->fcontext = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (this_type, 0));
+           {
+             /* If there is no `this' field and no DW_AT_containing_type,
+                we cannot actually find a base class context for the
+                vtable!  */
+             if (TYPE_NFIELDS (this_type) == 0
+                 || !TYPE_FIELD_ARTIFICIAL (this_type, 0))
+               {
+                 complaint (&symfile_complaints,
+                            _("cannot determine context for virtual member "
+                              "function \"%s\" (offset %d)"),
+                            fieldname, die->offset.sect_off);
+               }
+             else
+               {
+                 fnp->fcontext
+                   = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (this_type, 0));
+               }
+           }
        }
       else if (attr_form_is_section_offset (attr))
         {
index 43b4eb5c987eb3861f2296cd3490392876e99aa9..265c57358675d73882431ac6b85a9d2b5751c739 100644 (file)
@@ -1,3 +1,8 @@
+2015-03-23  Keith Seitz  <keiths@redhat.com>
+
+       PR gdb/18021
+       * gdb.dwarf2/staticvirtual.exp: New test.
+
 2015-03-20  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        * Makefile.in (ALL_SUBDIRS): Remove gdb.hp.
diff --git a/gdb/testsuite/gdb.dwarf2/staticvirtual.exp b/gdb/testsuite/gdb.dwarf2/staticvirtual.exp
new file mode 100644 (file)
index 0000000..06d46e1
--- /dev/null
@@ -0,0 +1,54 @@
+# Copyright 2015 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.
+if {![dwarf2_support]} {
+    return 0
+}
+
+if { [skip_cplus_tests] } { continue }
+
+standard_testfile main.c staticvirtual-dw.S
+
+# Make DWARF for the test.
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+    cu {} {
+       compile_unit {{language @DW_LANG_C_plus_plus}} {
+           structure_type {
+               {name S}
+               {byte_size 1 DW_FORM_sdata}
+           } {
+               subprogram {
+                   {low_pc 0x1000 addr}
+                   {high_pc 0x2000 addr}
+                   {name ~S}
+                   {external 1 flag}
+                   {virtuality @DW_VIRTUALITY_virtual}
+                   {vtable_elem_location {const1u 1} SPECIAL_expr}
+               }
+           }
+       }
+    }
+}
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} \
+         [list $srcfile $asm_file] {nodebug}] } {
+    return -1
+}
+
+# gdb/18021: The test below would cause GDB to crash.
+gdb_test "p S::~S" "0x1000"