[PATCH] PR symtab/1651: core dump reading xlc compiled binaries

Roger Sayle
2004-11-21T02:01:33Z

Please be gentle, I'm a "gdb-patches" virgin...

The following patch is my proposed solution to GDB's PR symtab/1651.
GCC currently fails to bootstrap on AIX 5.1 hosted from the native
IBM VisualAge compiler xlc; that problem is that the xlc compiler is
miscompiling the stage1 compiler resulting in a comparison failure.
However, in trying to debug the "cc1" executable created by xlc, I
rapidly discovered that gdb immediately dumps core with a segmentation
fault just reading in the xlc-compiled "cc1" binary.

Please forgive the following terminology, I understand very little
about debuggers (except that they shouldn't segfault). The problem
is that xcoffread isn't prepared to handle the way xlc splits the
debug information for enumerated types in its "symtab". For cc1,
xlc splits the debug info for enumerated type "insn_code" in the
debug info using XCOFF '?' continuations. GDB's reader can handle
these, but unfortunately it makes the assumptions that these only
occur in psymtabs, not in symtabs. This leads to two related logic
errors:

Firstly, in scan_xcoff_symtab to handle continuation symbols, the
code calls next_symbol_text, which is a macro that invokes the function
pointer next_symbol_text_func. Unfortunately, in xcoffread.c, this
variable, next_symbol_text_func, is only initialized (to
xcoff_next_symbol_text) in xcoff_psymtab_to_symtab which isn't executed
prior to the failure when reading xlc generated binaries.

The possible solutions to this first issue are to either initialize
next_symbol_text_func earlier (perhaps at the top of scan_xcoff_symtab),
or alternatively, as implemented below, bypass the virtual dispatch
inside xcoffread.c, and instead call xcoff_next_symbol_text directly.

Secondly, in xcoff_next_symbol_text, there's already a FIXME at the
top of the function about how it ignores it's objfile argument and
instead uses this_symtab_psymtab->objfile instead. As mentioned above,
this function can now be called for "symbtab" symbols in addition to
"psymtab" symbols, so in the case of this failure this_symtab_psymtab
is NULL when we invoke this function. The least intrusive fix to this
problem is to only overwrite objfile when this_symtab_psymtab is non-NULL.
An alternative fix might be to always use the objfile argument as
specified by the caller. I wasn't confident enough to risk this.

With these two tweaks, I was able to get gdb to read in an debug the
xlc-compiled cc1 binary from mainline GCC.

The following patch has been tested on powerpc-ibm-aix5.2.0.0 by
building "gdb" from CVS (6.3.50_2004_11_20-cvs -nx) configured with
"--enable-64-bit-bfd" and running "make check" in the gdb/ directory
with no new regressions. The results seem non-deterministic and
I had to run "make check" a second time to get identical results.
Searching GDB's GNATS database reveals that this failure is actually
PR symtab/1651. I have absolutely no idea how to write a GDB test
case, and I don't have CVS access nor copyright assignments for GDB.
Hopefully the changes below should be small enough not to require an
assignment as this is my first GDB patch submission.

So how did I do? Ok for mainline?

2004-11-20 Roger Sayle <roger@eyesopen.com>

PR symtab/1651
* xcoffread.c (xcoff_next_symbol_text): Check this_symtab_psymtab
for NULL before assigning this_symtab_psymtab->objfile to objfile.
(scan_xcoff_symtab): Call xcoff_next_symbol_text directly instead
of next_symbol_text as next_symbol_text_func might not be assigned.

Index: xcoffread.c
===================================================================
RCS file: /cvs/src/src/gdb/xcoffread.c,v
retrieving revision 1.44
diff -c -3 -p -r1.44 xcoffread.c
*** xcoffread.c 23 Oct 2004 16:18:09 -0000 1.44
--- xcoffread.c 20 Nov 2004 23:29:18 -0000
*************** xcoff_next_symbol_text (struct objfile *
*** 868,874 ****
struct internal_syment symbol;
char *retval;
/* FIXME: is this the same as the passed arg? */
! objfile = this_symtab_psymtab->objfile;

bfd_coff_swap_sym_in (objfile->obfd, raw_symbol, &symbol);
if (symbol.n_zeroes)
--- 868,875 ----
struct internal_syment symbol;
char *retval;
/* FIXME: is this the same as the passed arg? */
! if (this_symtab_psymtab)
! objfile = this_symtab_psymtab->objfile;

bfd_coff_swap_sym_in (objfile->obfd, raw_symbol, &symbol);
if (symbol.n_zeroes)
*************** scan_xcoff_symtab (struct objfile *objfi
*** 2691,2697 ****
/* Check for and handle cretinous dbx symbol name
continuation! */
if (*p == '\\' || (*p == '?' && p[1] == '\0'))
! p = next_symbol_text (objfile);

/* Point to the character after the name
of the enum constant. */
--- 2692,2698 ----
/* Check for and handle cretinous dbx symbol name
continuation! */
if (*p == '\\' || (*p == '?' && p[1] == '\0'))
! p = xcoff_next_symbol_text (objfile);

/* Point to the character after the name
of the enum constant. */