Binutils with MCST patches
ec6a20c268
One of our users reported that trying to print the following expression, caused GDB to SEGV: (gdb) print some_package.some_type (val) In this particular instance, the crash occurred inside ada_args_match because it is given a NULL "func", leading to the SEGV because of: struct type *func_type = SYMBOL_TYPE (func); This NULL symbol comes from a list of symbols which was given to ada_resolve_function (parameter called "syms") which then iterates over each of them to discard the ones that don't match the actuals: for (k = 0; k < nsyms; k += 1) { struct type *type = ada_check_typedef (SYMBOL_TYPE (syms[k].symbol)); if (ada_args_match (syms[k].symbol, args, nargs) && (fallback || return_match (type, context_type))) [...] } What's really interesting is that, when entering the block above for the first time, all entries in SYMS have a valid (non-NULL) symbol. However, once we return from the call to ada_check_typedef, the first entry of our SYMS table gets set to all zeros: (gdb) p syms[0] $2 = {symbol = 0x0, block = 0x0} Hence the call to ada_args_match with a NULL symbol, and the ensuing SEGV. To find out why this happen, we need to step back a little and look at how syms was allocated. This list of symbols comes from a symbol lookup, which means ada_lookup_symbol_list_worker. We have our first hint when we look at the function's documentation and see: This vector is transient---good only to the next call of ada_lookup_symbol_list. Implementation-wise, this is done by using a static global obstack, which we just re-initialize each time ada_lookup_symbol_list_worker gets called: obstack_free (&symbol_list_obstack, NULL); obstack_init (&symbol_list_obstack); This property was probably established in order to facilitate the use of the returned vector, since the users of that function would not have to worry about releasing that memory when no longer needed. However, I found during this investigation that it is all to easy to indirectly trigger another symbol lookup while still using the results of a previous lookup. In our particular case, there is the call to ada_check_typedef, which leads to check_typedef. As it happens, my first symbol had a type which was a typedef to a stub type, so check_typedef calls lookup_symbol to find the non-stub version. This in turn eventually leads us back to ada_lookup_symbol_list_worker, where the first thing it does is free the memory area when our list of symbols have been residing and then recreates a new one. in other words, SYMS then becomes a dangling pointer! This patch fixes the issue by having ada_lookup_symbol_list_worker return a copy of the list of symbols, with the responsibility of deallocating that list now transfered to the users of that list. More generally speaking, it is absolutely amazing that we haven't seen consequences of this issue before. This can happen fairly frequently. For instance, I found that ada-exp.y::write_var_or_type calls ada_lookup_symbol_list, and then, while processing that list, calls select_possible_type_sym, which leads to ada_prefer_type, eventually leading to ada_check_typedef again (via eg. ada_is_array_descriptor_type). Even more amazing is the fact that, while I was able to produce multiple scenarios where the corruption occurs, none of them leads to incorrect behavior at the user level. In other words, it requires a very precise set of conditions for the corruption to become user-visible, and despite having a megalarge program where the crash occured, using that as a template for creating a reproducer did not work (pb goes away). This is why this patch does not come with a reproducer. On the other hand, this should not be a problem in terms of testing coverage, as the changes are made in common areas which, at least for the most part, are routinely exercised during testing. gdb/ChangeLog: * ada-lang.c (symbol_list_obstack): Delete. (resolve_subexp): Make sure "candidates" gets xfree'ed. (ada_lookup_symbol_list_worker): Remove the limitation that the result is only good until the next call, now making it the responsibility of the caller to free the result when no longer needed. Adjust the function's intro comment accordingly. (ada_lookup_symbol_list): Adjust the function's intro comment. (ada_iterate_over_symbols): Make sure "results" gets xfree'ed. (ada_lookup_encoded_symbol, get_var_value): Likewise. (_initialize_ada_language): Remove symbol_list_obstack initialization. * ada-exp.y (block_lookup): Make sure "syms" gets xfree'ed. (write_var_or_type, write_name_assoc): Likewise. Tested on x86_64-linux. |
||
---|---|---|
bfd | ||
binutils | ||
config | ||
cpu | ||
elfcpp | ||
etc | ||
gas | ||
gdb | ||
gold | ||
gprof | ||
include | ||
intl | ||
ld | ||
libdecnumber | ||
libiberty | ||
opcodes | ||
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.