Go to file
Andrew Burgess b303c6f688 gdb: Remove cleanup from dw2_do_instantiate_symtab
When running the test gdb.dwarf2/dw2-bad-parameter-type.exp under
valgrind, I see the following issue reported (on x86-64 Fedora):

  (gdb) ptype f
  ==5203== Invalid read of size 1
  ==5203==    at 0x6931FE: process_die_scope::~process_die_scope() (dwarf2read.c:10642)
  ==5203==    by 0x66818F: process_die(die_info*, dwarf2_cu*) (dwarf2read.c:10664)
  ==5203==    by 0x66A01F: read_file_scope(die_info*, dwarf2_cu*) (dwarf2read.c:11650)
  ==5203==    by 0x667F2D: process_die(die_info*, dwarf2_cu*) (dwarf2read.c:10672)
  ==5203==    by 0x6677B6: process_full_comp_unit(dwarf2_per_cu_data*, language) (dwarf2read.c:10445)
  ==5203==    by 0x66657A: process_queue(dwarf2_per_objfile*) (dwarf2read.c:9945)
  ==5203==    by 0x6559B4: dw2_do_instantiate_symtab(dwarf2_per_cu_data*) (dwarf2read.c:3163)
  ==5203==    by 0x66683D: psymtab_to_symtab_1(partial_symtab*) (dwarf2read.c:10034)
  ==5203==    by 0x66622A: dwarf2_read_symtab(partial_symtab*, objfile*) (dwarf2read.c:9811)
  ==5203==    by 0x787984: psymtab_to_symtab(objfile*, partial_symtab*) (psymtab.c:792)
  ==5203==    by 0x786E3E: psym_lookup_symbol(objfile*, int, char const*, domain_enum_tag) (psymtab.c:522)
  ==5203==    by 0x804BD0: lookup_symbol_via_quick_fns(objfile*, int, char const*, domain_enum_tag) (symtab.c:2383)
  ==5203==  Address 0x147ed063 is 291 bytes inside a block of size 4,064 free'd
  ==5203==    at 0x4C2CD5A: free (vg_replace_malloc.c:530)
  ==5203==    by 0x444415: void xfree<void>(void*) (common-utils.h:60)
  ==5203==    by 0x9DA8C2: call_freefun (obstack.c:103)
  ==5203==    by 0x9DAD35: _obstack_free (obstack.c:280)
  ==5203==    by 0x44464C: auto_obstack::~auto_obstack() (gdb_obstack.h:73)
  ==5203==    by 0x68AFB0: dwarf2_cu::~dwarf2_cu() (dwarf2read.c:25080)
  ==5203==    by 0x68B204: free_one_cached_comp_unit(dwarf2_per_cu_data*) (dwarf2read.c:25174)
  ==5203==    by 0x66668C: dwarf2_release_queue(void*) (dwarf2read.c:9982)
  ==5203==    by 0x563A4C: do_my_cleanups(cleanup**, cleanup*) (cleanups.c:154)
  ==5203==    by 0x563AA7: do_cleanups(cleanup*) (cleanups.c:176)
  ==5203==    by 0x5646CE: throw_exception_cxx(gdb_exception) (common-exceptions.c:289)
  ==5203==    by 0x5647B7: throw_exception(gdb_exception) (common-exceptions.c:317)
  ==5203==  Block was alloc'd at
  ==5203==    at 0x4C2BBAD: malloc (vg_replace_malloc.c:299)
  ==5203==    by 0x564BE8: xmalloc (common-utils.c:44)
  ==5203==    by 0x9DA872: call_chunkfun (obstack.c:94)
  ==5203==    by 0x9DA935: _obstack_begin_worker (obstack.c:141)
  ==5203==    by 0x9DAA3C: _obstack_begin (obstack.c:164)
  ==5203==    by 0x4445E0: auto_obstack::auto_obstack() (gdb_obstack.h:70)
  ==5203==    by 0x68AE07: dwarf2_cu::dwarf2_cu(dwarf2_per_cu_data*) (dwarf2read.c:25073)
  ==5203==    by 0x661A8A: init_cutu_and_read_dies(dwarf2_per_cu_data*, abbrev_table*, int, int, void (*)(die_reader_specs const*, unsigned char const*, die_info*, int, void*), void*) (dwarf2read.c:7869)
  ==5203==    by 0x666A29: load_full_comp_unit(dwarf2_per_cu_data*, language) (dwarf2read.c:10108)
  ==5203==    by 0x655847: load_cu(dwarf2_per_cu_data*) (dwarf2read.c:3120)
  ==5203==    by 0x655928: dw2_do_instantiate_symtab(dwarf2_per_cu_data*) (dwarf2read.c:3148)
  ==5203==    by 0x66683D: psymtab_to_symtab_1(partial_symtab*) (dwarf2read.c:10034)

There's actually a series of three issues reported, but it turns out
they're all related, so we can consider on the first one.

The invalid read is triggered from a destructor which is being invoked
as part of a stack unwind after throwing an error.  At the time the
error is thrown, the stack looks like this:

    #0  0x00000000009f4ecd in __cxa_throw ()
    #1  0x0000000000564761 in throw_exception_cxx (exception=...) at ../../src/gdb/common/common-exceptions.c:303
    #2  0x00000000005647b8 in throw_exception (exception=...) at ../../src/gdb/common/common-exceptions.c:317
    #3  0x00000000005648ff in throw_it(return_reason, errors, const char *, typedef __va_list_tag __va_list_tag *) (reason=RETURN_ERROR,
        error=GENERIC_ERROR, fmt=0xb33020 "Dwarf Error: Cannot find DIE at 0x%x referenced from DIE at 0x%x [in module %s]",
        ap=0x7fff387f2d68) at ../../src/gdb/common/common-exceptions.c:373
    #4  0x0000000000564929 in throw_verror (error=GENERIC_ERROR,
        fmt=0xb33020 "Dwarf Error: Cannot find DIE at 0x%x referenced from DIE at 0x%x [in module %s]", ap=0x7fff387f2d68)
        at ../../src/gdb/common/common-exceptions.c:379
    #5  0x0000000000867be4 in verror (string=0xb33020 "Dwarf Error: Cannot find DIE at 0x%x referenced from DIE at 0x%x [in module %s]",
        args=0x7fff387f2d68) at ../../src/gdb/utils.c:251
    #6  0x000000000056879d in error (fmt=0xb33020 "Dwarf Error: Cannot find DIE at 0x%x referenced from DIE at 0x%x [in module %s]")
        at ../../src/gdb/common/errors.c:43
    #7  0x0000000000686875 in follow_die_ref (src_die=0x30bc8a0, attr=0x30bc8c8, ref_cu=0x7fff387f2ed0) at ../../src/gdb/dwarf2read.c:22969
    #8  0x00000000006844cd in lookup_die_type (die=0x30bc8a0, attr=0x30bc8c8, cu=0x30bc5d0) at ../../src/gdb/dwarf2read.c:21976
    #9  0x0000000000683f27 in die_type (die=0x30bc8a0, cu=0x30bc5d0) at ../../src/gdb/dwarf2read.c:21832
    #10 0x0000000000679b39 in read_subroutine_type (die=0x30bc830, cu=0x30bc5d0) at ../../src/gdb/dwarf2read.c:17343
    #11 0x00000000006845fb in read_type_die_1 (die=0x30bc830, cu=0x30bc5d0) at ../../src/gdb/dwarf2read.c:22035
    #12 0x0000000000684576 in read_type_die (die=0x30bc830, cu=0x30bc5d0) at ../../src/gdb/dwarf2read.c:22010
    #13 0x000000000067003f in read_func_scope (die=0x30bc830, cu=0x30bc5d0) at ../../src/gdb/dwarf2read.c:13822
    #14 0x0000000000667f5e in process_die (die=0x30bc830, cu=0x30bc5d0) at ../../src/gdb/dwarf2read.c:10679
    #15 0x000000000066a020 in read_file_scope (die=0x30bc720, cu=0x30bc5d0) at ../../src/gdb/dwarf2read.c:11650
    #16 0x0000000000667f2e in process_die (die=0x30bc720, cu=0x30bc5d0) at ../../src/gdb/dwarf2read.c:10672
    #17 0x00000000006677b7 in process_full_comp_unit (per_cu=0x3089b80, pretend_language=language_minimal)
        at ../../src/gdb/dwarf2read.c:10445
    #18 0x000000000066657b in process_queue (dwarf2_per_objfile=0x30897d0) at ../../src/gdb/dwarf2read.c:9945
    #19 0x00000000006559b5 in dw2_do_instantiate_symtab (per_cu=0x3089b80) at ../../src/gdb/dwarf2read.c:3163
    #20 0x000000000066683e in psymtab_to_symtab_1 (pst=0x3089bd0) at ../../src/gdb/dwarf2read.c:10034
    #21 0x000000000066622b in dwarf2_read_symtab (self=0x3089bd0, objfile=0x3073f40) at ../../src/gdb/dwarf2read.c:9811
    #22 0x0000000000787985 in psymtab_to_symtab (objfile=0x3073f40, pst=0x3089bd0) at ../../src/gdb/psymtab.c:792
    #23 0x0000000000786e3f in psym_lookup_symbol (objfile=0x3073f40, block_index=1, name=0x30b2e30 "f", domain=VAR_DOMAIN)
        at ../../src/gdb/psymtab.c:522
    #24 0x0000000000804bd1 in lookup_symbol_via_quick_fns (objfile=0x3073f40, block_index=1, name=0x30b2e30 "f", domain=VAR_DOMAIN)
        at ../../src/gdb/symtab.c:2383
    #25 0x0000000000804fe4 in lookup_symbol_in_objfile (objfile=0x3073f40, block_index=1, name=0x30b2e30 "f", domain=VAR_DOMAIN)
        at ../../src/gdb/symtab.c:2558
    #26 0x0000000000805125 in lookup_static_symbol (name=0x30b2e30 "f", domain=VAR_DOMAIN) at ../../src/gdb/symtab.c:2595
    #27 0x0000000000804357 in lookup_symbol_aux (name=0x30b2e30 "f", match_type=symbol_name_match_type::FULL, block=0x0,
        domain=VAR_DOMAIN, language=language_c, is_a_field_of_this=0x0) at ../../src/gdb/symtab.c:2105
    #28 0x0000000000803ad9 in lookup_symbol_in_language (name=0x30b2e30 "f", block=0x0, domain=VAR_DOMAIN, lang=language_c,
        is_a_field_of_this=0x0) at ../../src/gdb/symtab.c:1887
    #29 0x0000000000803b53 in lookup_symbol (name=0x30b2e30 "f", block=0x0, domain=VAR_DOMAIN, is_a_field_of_this=0x0)
        at ../../src/gdb/symtab.c:1899
    #30 0x000000000053b246 in classify_name (par_state=0x7fff387f6090, block=0x0, is_quoted_name=false, is_after_structop=false)
        at ../../src/gdb/c-exp.y:2879
    #31 0x000000000053b7e9 in c_yylex () at ../../src/gdb/c-exp.y:3083
    #32 0x000000000053414a in c_yyparse () at c-exp.c:1903
    #33 0x000000000053c2e7 in c_parse (par_state=0x7fff387f6090) at ../../src/gdb/c-exp.y:3255
    #34 0x0000000000774a02 in parse_exp_in_context_1 (stringptr=0x7fff387f61c0, pc=0, block=0x0, comma=0, void_context_p=0, out_subexp=0x0)
        at ../../src/gdb/parse.c:1213
    #35 0x000000000077476a in parse_exp_in_context (stringptr=0x7fff387f61c0, pc=0, block=0x0, comma=0, void_context_p=0, out_subexp=0x0)
        at ../../src/gdb/parse.c:1115
    #36 0x0000000000774714 in parse_exp_1 (stringptr=0x7fff387f61c0, pc=0, block=0x0, comma=0) at ../../src/gdb/parse.c:1106
    #37 0x0000000000774c53 in parse_expression (string=0x27ff996 "f") at ../../src/gdb/parse.c:1253
    #38 0x0000000000861dc4 in whatis_exp (exp=0x27ff996 "f", show=1) at ../../src/gdb/typeprint.c:472
    #39 0x00000000008620d8 in ptype_command (type_name=0x27ff996 "f", from_tty=1) at ../../src/gdb/typeprint.c:561
    #40 0x000000000047430b in do_const_cfunc (c=0x3012010, args=0x27ff996 "f", from_tty=1) at ../../src/gdb/cli/cli-decode.c:106
    #41 0x000000000047715e in cmd_func (cmd=0x3012010, args=0x27ff996 "f", from_tty=1) at ../../src/gdb/cli/cli-decode.c:1886
    #42 0x00000000008431bb in execute_command (p=0x27ff996 "f", from_tty=1) at ../../src/gdb/top.c:630
    #43 0x00000000006bf946 in command_handler (command=0x27ff990 "ptype f") at ../../src/gdb/event-top.c:583
    #44 0x00000000006bfd12 in command_line_handler (rl=0x30bb3a0 "\240\305\v\003") at ../../src/gdb/event-top.c:774

The problem is that in `process_die` (frames 14 and 16) we create a
`process_die_scope` object, that takes a copy of the `struct
dwarf2_cu *` passed into the frame.  The destructor of the
`process_die_scope` dereferences the stored pointer.  This wouldn't be
an issue, except...

... in dw2_do_instantiate_symtab (frame 19) a clean up was registered that
clears the dwarf2_queue in case of an error.  Part of this clean up
involves deleting the `struct dwarf2_cu`s referenced from the queue..

The problem then, is that cleanups are processed at the site of the
throw, while, class destructors are invoked as we unwind their frame.
The result is that we process the frame 19 cleanup (and delete the
struct dwarf2_cu) before we process the destructors in frames 14 and 16.
When we do get back to frames 14 and 16 the objects being references
have already been deleted.

The solution is to remove the cleanup from dw2_do_instantiate_symtab, and
instead use a destructor to release the dwarf2_queue instead.  With this
patch in place, the valgrind errors are now resolved.

gdb/ChangeLog:

	* dwarf2read.c (dwarf2_release_queue): Delete function, move body
	into...
	(class dwarf2_queue_guard): ...the destructor of this new class.
	(dw2_do_instantiate_symtab): Create instance of the new class
	dwarf2_queue_guard, remove cleanup.
2018-02-12 21:43:45 +00:00
bfd Add support for reading msdos MZ executables. 2018-02-12 13:15:56 +00:00
binutils Speed up readelf and objdump by not looking for DWO links unless the user has requested that they be displayed/followed. 2018-02-08 12:29:07 +00:00
config Fix PR ld/22263 on SPARC. 2018-02-06 18:17:39 +01:00
cpu
elfcpp
etc
gas MIPS/GAS/test: Fix an n32 `.reginfo' size test failure 2018-02-12 16:04:05 +00:00
gdb gdb: Remove cleanup from dw2_do_instantiate_symtab 2018-02-12 21:43:45 +00:00
gold Revert "PowerPC PLT speculative execution barriers" 2018-02-07 14:23:08 +10:30
gprof
include Add support for reading msdos MZ executables. 2018-02-12 13:15:56 +00:00
intl
ld Revert "PowerPC PLT speculative execution barriers" 2018-02-07 14:23:08 +10:30
libdecnumber
libiberty
opcodes MIPS: Fix encoding for MIPSr6 sigrie instruction. 2018-02-12 14:50:42 +00:00
readline
sim
texinfo
zlib
.cvsignore
.gitattributes
.gitignore
ChangeLog
compile
config-ml.in
config.guess
config.rpath
config.sub
configure
configure.ac
COPYING
COPYING3
COPYING3.LIB
COPYING.LIB
COPYING.LIBGLOSS
COPYING.NEWLIB
depcomp
djunpack.bat
install-sh
libtool.m4
lt~obsolete.m4
ltgcc.m4
ltmain.sh
ltoptions.m4
ltsugar.m4
ltversion.m4
MAINTAINERS
Makefile.def
Makefile.in
Makefile.tpl
makefile.vms
missing
mkdep
mkinstalldirs
move-if-change
README
README-maintainer-mode
setup.com
src-release.sh
symlink-tree
ylwrap

		   README for GNU development tools

This directory contains various GNU compilers, assemblers, linkers, 
debuggers, etc., plus their support routines, definitions, and documentation.

If you are receiving this as part of a GDB release, see the file gdb/README.
If with a binutils release, see binutils/README;  if with a libg++ release,
see libg++/README, etc.  That'll give you info about this
package -- supported targets, how to use it, how to report bugs, etc.

It is now possible to automatically configure and build a variety of
tools with one command.  To build all of the tools contained herein,
run the ``configure'' script here, e.g.:

	./configure 
	make

To install them (by default in /usr/local/bin, /usr/local/lib, etc),
then do:
	make install

(If the configure script can't determine your type of computer, give it
the name as an argument, for instance ``./configure sun4''.  You can
use the script ``config.sub'' to test whether a name is recognized; if
it is, config.sub translates it to a triplet specifying CPU, vendor,
and OS.)

If you have more than one compiler on your system, it is often best to
explicitly set CC in the environment before running configure, and to
also set CC when running make.  For example (assuming sh/bash/ksh):

	CC=gcc ./configure
	make

A similar example using csh:

	setenv CC gcc
	./configure
	make

Much of the code and documentation enclosed is copyright by
the Free Software Foundation, Inc.  See the file COPYING or
COPYING.LIB in the various directories, for a description of the
GNU General Public License terms under which you can copy the files.

REPORTING BUGS: Again, see gdb/README, binutils/README, etc., for info
on where and how to report problems.