13d8817e4Smiod /* rddbg.c -- Read debugging information into a generic form.
23d8817e4Smiod Copyright 1995, 1996, 1997, 2000, 2002, 2003, 2005
33d8817e4Smiod Free Software Foundation, Inc.
43d8817e4Smiod Written by Ian Lance Taylor <ian@cygnus.com>.
53d8817e4Smiod
63d8817e4Smiod This file is part of GNU Binutils.
73d8817e4Smiod
83d8817e4Smiod This program is free software; you can redistribute it and/or modify
93d8817e4Smiod it under the terms of the GNU General Public License as published by
103d8817e4Smiod the Free Software Foundation; either version 2 of the License, or
113d8817e4Smiod (at your option) any later version.
123d8817e4Smiod
133d8817e4Smiod This program is distributed in the hope that it will be useful,
143d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
153d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
163d8817e4Smiod GNU General Public License for more details.
173d8817e4Smiod
183d8817e4Smiod You should have received a copy of the GNU General Public License
193d8817e4Smiod along with this program; if not, write to the Free Software
203d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
213d8817e4Smiod 02110-1301, USA. */
223d8817e4Smiod
233d8817e4Smiod /* This file reads debugging information into a generic form. This
243d8817e4Smiod file knows how to dig the debugging information out of an object
253d8817e4Smiod file. */
263d8817e4Smiod
273d8817e4Smiod #include "bfd.h"
283d8817e4Smiod #include "bucomm.h"
293d8817e4Smiod #include "libiberty.h"
303d8817e4Smiod #include "debug.h"
313d8817e4Smiod #include "budbg.h"
323d8817e4Smiod
333d8817e4Smiod static bfd_boolean read_section_stabs_debugging_info
343d8817e4Smiod (bfd *, asymbol **, long, void *, bfd_boolean *);
353d8817e4Smiod static bfd_boolean read_symbol_stabs_debugging_info
363d8817e4Smiod (bfd *, asymbol **, long, void *, bfd_boolean *);
373d8817e4Smiod static bfd_boolean read_ieee_debugging_info (bfd *, void *, bfd_boolean *);
383d8817e4Smiod static void save_stab (int, int, bfd_vma, const char *);
393d8817e4Smiod static void stab_context (void);
403d8817e4Smiod static void free_saved_stabs (void);
413d8817e4Smiod
423d8817e4Smiod /* Read debugging information from a BFD. Returns a generic debugging
433d8817e4Smiod pointer. */
443d8817e4Smiod
453d8817e4Smiod void *
read_debugging_info(bfd * abfd,asymbol ** syms,long symcount)463d8817e4Smiod read_debugging_info (bfd *abfd, asymbol **syms, long symcount)
473d8817e4Smiod {
483d8817e4Smiod void *dhandle;
493d8817e4Smiod bfd_boolean found;
503d8817e4Smiod
513d8817e4Smiod dhandle = debug_init ();
523d8817e4Smiod if (dhandle == NULL)
533d8817e4Smiod return NULL;
543d8817e4Smiod
553d8817e4Smiod if (! read_section_stabs_debugging_info (abfd, syms, symcount, dhandle,
563d8817e4Smiod &found))
573d8817e4Smiod return NULL;
583d8817e4Smiod
593d8817e4Smiod if (bfd_get_flavour (abfd) == bfd_target_aout_flavour)
603d8817e4Smiod {
613d8817e4Smiod if (! read_symbol_stabs_debugging_info (abfd, syms, symcount, dhandle,
623d8817e4Smiod &found))
633d8817e4Smiod return NULL;
643d8817e4Smiod }
653d8817e4Smiod
663d8817e4Smiod if (bfd_get_flavour (abfd) == bfd_target_ieee_flavour)
673d8817e4Smiod {
683d8817e4Smiod if (! read_ieee_debugging_info (abfd, dhandle, &found))
693d8817e4Smiod return NULL;
703d8817e4Smiod }
713d8817e4Smiod
723d8817e4Smiod /* Try reading the COFF symbols if we didn't find any stabs in COFF
733d8817e4Smiod sections. */
743d8817e4Smiod if (! found
753d8817e4Smiod && bfd_get_flavour (abfd) == bfd_target_coff_flavour
763d8817e4Smiod && symcount > 0)
773d8817e4Smiod {
783d8817e4Smiod if (! parse_coff (abfd, syms, symcount, dhandle))
793d8817e4Smiod return NULL;
803d8817e4Smiod found = TRUE;
813d8817e4Smiod }
823d8817e4Smiod
833d8817e4Smiod if (! found)
843d8817e4Smiod {
853d8817e4Smiod non_fatal (_("%s: no recognized debugging information"),
863d8817e4Smiod bfd_get_filename (abfd));
873d8817e4Smiod return NULL;
883d8817e4Smiod }
893d8817e4Smiod
903d8817e4Smiod return dhandle;
913d8817e4Smiod }
923d8817e4Smiod
933d8817e4Smiod /* Read stabs in sections debugging information from a BFD. */
943d8817e4Smiod
953d8817e4Smiod static bfd_boolean
read_section_stabs_debugging_info(bfd * abfd,asymbol ** syms,long symcount,void * dhandle,bfd_boolean * pfound)963d8817e4Smiod read_section_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount,
973d8817e4Smiod void *dhandle, bfd_boolean *pfound)
983d8817e4Smiod {
993d8817e4Smiod static struct
1003d8817e4Smiod {
1013d8817e4Smiod const char *secname;
1023d8817e4Smiod const char *strsecname;
1033d8817e4Smiod }
1043d8817e4Smiod names[] =
1053d8817e4Smiod {
1063d8817e4Smiod { ".stab", ".stabstr" },
1073d8817e4Smiod { "LC_SYMTAB.stabs", "LC_SYMTAB.stabstr" },
1083d8817e4Smiod { "$GDB_SYMBOLS$", "$GDB_STRINGS$" }
1093d8817e4Smiod };
1103d8817e4Smiod unsigned int i;
1113d8817e4Smiod void *shandle;
1123d8817e4Smiod
1133d8817e4Smiod *pfound = FALSE;
1143d8817e4Smiod shandle = NULL;
1153d8817e4Smiod
1163d8817e4Smiod for (i = 0; i < sizeof names / sizeof names[0]; i++)
1173d8817e4Smiod {
1183d8817e4Smiod asection *sec, *strsec;
1193d8817e4Smiod
1203d8817e4Smiod sec = bfd_get_section_by_name (abfd, names[i].secname);
1213d8817e4Smiod strsec = bfd_get_section_by_name (abfd, names[i].strsecname);
1223d8817e4Smiod if (sec != NULL && strsec != NULL)
1233d8817e4Smiod {
1243d8817e4Smiod bfd_size_type stabsize, strsize;
1253d8817e4Smiod bfd_byte *stabs, *strings;
1263d8817e4Smiod bfd_byte *stab;
1273d8817e4Smiod bfd_size_type stroff, next_stroff;
1283d8817e4Smiod
1293d8817e4Smiod stabsize = bfd_section_size (abfd, sec);
1303d8817e4Smiod stabs = (bfd_byte *) xmalloc (stabsize);
1313d8817e4Smiod if (! bfd_get_section_contents (abfd, sec, stabs, 0, stabsize))
1323d8817e4Smiod {
1333d8817e4Smiod fprintf (stderr, "%s: %s: %s\n",
1343d8817e4Smiod bfd_get_filename (abfd), names[i].secname,
1353d8817e4Smiod bfd_errmsg (bfd_get_error ()));
1363d8817e4Smiod return FALSE;
1373d8817e4Smiod }
1383d8817e4Smiod
1393d8817e4Smiod strsize = bfd_section_size (abfd, strsec);
1403d8817e4Smiod strings = (bfd_byte *) xmalloc (strsize);
1413d8817e4Smiod if (! bfd_get_section_contents (abfd, strsec, strings, 0, strsize))
1423d8817e4Smiod {
1433d8817e4Smiod fprintf (stderr, "%s: %s: %s\n",
1443d8817e4Smiod bfd_get_filename (abfd), names[i].strsecname,
1453d8817e4Smiod bfd_errmsg (bfd_get_error ()));
1463d8817e4Smiod return FALSE;
1473d8817e4Smiod }
1483d8817e4Smiod
1493d8817e4Smiod if (shandle == NULL)
1503d8817e4Smiod {
1513d8817e4Smiod shandle = start_stab (dhandle, abfd, TRUE, syms, symcount);
1523d8817e4Smiod if (shandle == NULL)
1533d8817e4Smiod return FALSE;
1543d8817e4Smiod }
1553d8817e4Smiod
1563d8817e4Smiod *pfound = TRUE;
1573d8817e4Smiod
1583d8817e4Smiod stroff = 0;
1593d8817e4Smiod next_stroff = 0;
1603d8817e4Smiod for (stab = stabs; stab < stabs + stabsize; stab += 12)
1613d8817e4Smiod {
1623d8817e4Smiod unsigned int strx;
1633d8817e4Smiod int type;
1643d8817e4Smiod int other;
1653d8817e4Smiod int desc;
1663d8817e4Smiod bfd_vma value;
1673d8817e4Smiod
1683d8817e4Smiod /* This code presumes 32 bit values. */
1693d8817e4Smiod
1703d8817e4Smiod strx = bfd_get_32 (abfd, stab);
1713d8817e4Smiod type = bfd_get_8 (abfd, stab + 4);
1723d8817e4Smiod other = bfd_get_8 (abfd, stab + 5);
1733d8817e4Smiod desc = bfd_get_16 (abfd, stab + 6);
1743d8817e4Smiod value = bfd_get_32 (abfd, stab + 8);
1753d8817e4Smiod
1763d8817e4Smiod if (type == 0)
1773d8817e4Smiod {
1783d8817e4Smiod /* Special type 0 stabs indicate the offset to the
1793d8817e4Smiod next string table. */
1803d8817e4Smiod stroff = next_stroff;
1813d8817e4Smiod next_stroff += value;
1823d8817e4Smiod }
1833d8817e4Smiod else
1843d8817e4Smiod {
1853d8817e4Smiod char *f, *s;
1863d8817e4Smiod
1873d8817e4Smiod f = NULL;
1883d8817e4Smiod
1893d8817e4Smiod if (stroff + strx > strsize)
1903d8817e4Smiod {
1913d8817e4Smiod fprintf (stderr, "%s: %s: stab entry %ld is corrupt, strx = 0x%x, type = %d\n",
1923d8817e4Smiod bfd_get_filename (abfd), names[i].secname,
1933d8817e4Smiod (long) (stab - stabs) / 12, strx, type);
1943d8817e4Smiod continue;
1953d8817e4Smiod }
1963d8817e4Smiod
1973d8817e4Smiod s = (char *) strings + stroff + strx;
1983d8817e4Smiod
199*d2386abeSmiod while (*s != '\0' && s[strlen (s) - 1] == '\\'
2003d8817e4Smiod && stab + 12 < stabs + stabsize)
2013d8817e4Smiod {
2023d8817e4Smiod char *p;
2033d8817e4Smiod
2043d8817e4Smiod stab += 12;
2053d8817e4Smiod p = s + strlen (s) - 1;
2063d8817e4Smiod *p = '\0';
2073d8817e4Smiod s = concat (s,
2083d8817e4Smiod ((char *) strings
2093d8817e4Smiod + stroff
2103d8817e4Smiod + bfd_get_32 (abfd, stab)),
2113d8817e4Smiod (const char *) NULL);
2123d8817e4Smiod
2133d8817e4Smiod /* We have to restore the backslash, because, if
2143d8817e4Smiod the linker is hashing stabs strings, we may
2153d8817e4Smiod see the same string more than once. */
2163d8817e4Smiod *p = '\\';
2173d8817e4Smiod
2183d8817e4Smiod if (f != NULL)
2193d8817e4Smiod free (f);
2203d8817e4Smiod f = s;
2213d8817e4Smiod }
2223d8817e4Smiod
2233d8817e4Smiod save_stab (type, desc, value, s);
2243d8817e4Smiod
2253d8817e4Smiod if (! parse_stab (dhandle, shandle, type, desc, value, s))
2263d8817e4Smiod {
2273d8817e4Smiod stab_context ();
2283d8817e4Smiod free_saved_stabs ();
2293d8817e4Smiod return FALSE;
2303d8817e4Smiod }
2313d8817e4Smiod
2323d8817e4Smiod /* Don't free f, since I think the stabs code
2333d8817e4Smiod expects strings to hang around. This should be
2343d8817e4Smiod straightened out. FIXME. */
2353d8817e4Smiod }
2363d8817e4Smiod }
2373d8817e4Smiod
2383d8817e4Smiod free_saved_stabs ();
2393d8817e4Smiod free (stabs);
2403d8817e4Smiod
2413d8817e4Smiod /* Don't free strings, since I think the stabs code expects
2423d8817e4Smiod the strings to hang around. This should be straightened
2433d8817e4Smiod out. FIXME. */
2443d8817e4Smiod }
2453d8817e4Smiod }
2463d8817e4Smiod
2473d8817e4Smiod if (shandle != NULL)
2483d8817e4Smiod {
2493d8817e4Smiod if (! finish_stab (dhandle, shandle))
2503d8817e4Smiod return FALSE;
2513d8817e4Smiod }
2523d8817e4Smiod
2533d8817e4Smiod return TRUE;
2543d8817e4Smiod }
2553d8817e4Smiod
2563d8817e4Smiod /* Read stabs in the symbol table. */
2573d8817e4Smiod
2583d8817e4Smiod static bfd_boolean
read_symbol_stabs_debugging_info(bfd * abfd,asymbol ** syms,long symcount,void * dhandle,bfd_boolean * pfound)2593d8817e4Smiod read_symbol_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount,
2603d8817e4Smiod void *dhandle, bfd_boolean *pfound)
2613d8817e4Smiod {
2623d8817e4Smiod void *shandle;
2633d8817e4Smiod asymbol **ps, **symend;
2643d8817e4Smiod
2653d8817e4Smiod shandle = NULL;
2663d8817e4Smiod symend = syms + symcount;
2673d8817e4Smiod for (ps = syms; ps < symend; ps++)
2683d8817e4Smiod {
2693d8817e4Smiod symbol_info i;
2703d8817e4Smiod
2713d8817e4Smiod bfd_get_symbol_info (abfd, *ps, &i);
2723d8817e4Smiod
2733d8817e4Smiod if (i.type == '-')
2743d8817e4Smiod {
2753d8817e4Smiod const char *s;
2763d8817e4Smiod char *f;
2773d8817e4Smiod
2783d8817e4Smiod if (shandle == NULL)
2793d8817e4Smiod {
2803d8817e4Smiod shandle = start_stab (dhandle, abfd, FALSE, syms, symcount);
2813d8817e4Smiod if (shandle == NULL)
2823d8817e4Smiod return FALSE;
2833d8817e4Smiod }
2843d8817e4Smiod
2853d8817e4Smiod *pfound = TRUE;
2863d8817e4Smiod
2873d8817e4Smiod s = i.name;
2883d8817e4Smiod f = NULL;
2893d8817e4Smiod while (s[strlen (s) - 1] == '\\'
2903d8817e4Smiod && ps + 1 < symend)
2913d8817e4Smiod {
2923d8817e4Smiod char *sc, *n;
2933d8817e4Smiod
2943d8817e4Smiod ++ps;
2953d8817e4Smiod sc = xstrdup (s);
2963d8817e4Smiod sc[strlen (sc) - 1] = '\0';
2973d8817e4Smiod n = concat (sc, bfd_asymbol_name (*ps), (const char *) NULL);
2983d8817e4Smiod free (sc);
2993d8817e4Smiod if (f != NULL)
3003d8817e4Smiod free (f);
3013d8817e4Smiod f = n;
3023d8817e4Smiod s = n;
3033d8817e4Smiod }
3043d8817e4Smiod
3053d8817e4Smiod save_stab (i.stab_type, i.stab_desc, i.value, s);
3063d8817e4Smiod
3073d8817e4Smiod if (! parse_stab (dhandle, shandle, i.stab_type, i.stab_desc,
3083d8817e4Smiod i.value, s))
3093d8817e4Smiod {
3103d8817e4Smiod stab_context ();
3113d8817e4Smiod free_saved_stabs ();
3123d8817e4Smiod return FALSE;
3133d8817e4Smiod }
3143d8817e4Smiod
3153d8817e4Smiod /* Don't free f, since I think the stabs code expects
3163d8817e4Smiod strings to hang around. This should be straightened out.
3173d8817e4Smiod FIXME. */
3183d8817e4Smiod }
3193d8817e4Smiod }
3203d8817e4Smiod
3213d8817e4Smiod free_saved_stabs ();
3223d8817e4Smiod
3233d8817e4Smiod if (shandle != NULL)
3243d8817e4Smiod {
3253d8817e4Smiod if (! finish_stab (dhandle, shandle))
3263d8817e4Smiod return FALSE;
3273d8817e4Smiod }
3283d8817e4Smiod
3293d8817e4Smiod return TRUE;
3303d8817e4Smiod }
3313d8817e4Smiod
3323d8817e4Smiod /* Read IEEE debugging information. */
3333d8817e4Smiod
3343d8817e4Smiod static bfd_boolean
read_ieee_debugging_info(bfd * abfd,void * dhandle,bfd_boolean * pfound)3353d8817e4Smiod read_ieee_debugging_info (bfd *abfd, void *dhandle, bfd_boolean *pfound)
3363d8817e4Smiod {
3373d8817e4Smiod asection *dsec;
3383d8817e4Smiod bfd_size_type size;
3393d8817e4Smiod bfd_byte *contents;
3403d8817e4Smiod
3413d8817e4Smiod /* The BFD backend puts the debugging information into a section
3423d8817e4Smiod named .debug. */
3433d8817e4Smiod
3443d8817e4Smiod dsec = bfd_get_section_by_name (abfd, ".debug");
3453d8817e4Smiod if (dsec == NULL)
3463d8817e4Smiod return TRUE;
3473d8817e4Smiod
3483d8817e4Smiod size = bfd_section_size (abfd, dsec);
3493d8817e4Smiod contents = (bfd_byte *) xmalloc (size);
3503d8817e4Smiod if (! bfd_get_section_contents (abfd, dsec, contents, 0, size))
3513d8817e4Smiod return FALSE;
3523d8817e4Smiod
3533d8817e4Smiod if (! parse_ieee (dhandle, abfd, contents, size))
3543d8817e4Smiod return FALSE;
3553d8817e4Smiod
3563d8817e4Smiod free (contents);
3573d8817e4Smiod
3583d8817e4Smiod *pfound = TRUE;
3593d8817e4Smiod
3603d8817e4Smiod return TRUE;
3613d8817e4Smiod }
3623d8817e4Smiod
3633d8817e4Smiod /* Record stabs strings, so that we can give some context for errors. */
3643d8817e4Smiod
3653d8817e4Smiod #define SAVE_STABS_COUNT (16)
3663d8817e4Smiod
3673d8817e4Smiod struct saved_stab
3683d8817e4Smiod {
3693d8817e4Smiod int type;
3703d8817e4Smiod int desc;
3713d8817e4Smiod bfd_vma value;
3723d8817e4Smiod char *string;
3733d8817e4Smiod };
3743d8817e4Smiod
3753d8817e4Smiod static struct saved_stab saved_stabs[SAVE_STABS_COUNT];
3763d8817e4Smiod static int saved_stabs_index;
3773d8817e4Smiod
3783d8817e4Smiod /* Save a stabs string. */
3793d8817e4Smiod
3803d8817e4Smiod static void
save_stab(int type,int desc,bfd_vma value,const char * string)3813d8817e4Smiod save_stab (int type, int desc, bfd_vma value, const char *string)
3823d8817e4Smiod {
3833d8817e4Smiod if (saved_stabs[saved_stabs_index].string != NULL)
3843d8817e4Smiod free (saved_stabs[saved_stabs_index].string);
3853d8817e4Smiod saved_stabs[saved_stabs_index].type = type;
3863d8817e4Smiod saved_stabs[saved_stabs_index].desc = desc;
3873d8817e4Smiod saved_stabs[saved_stabs_index].value = value;
3883d8817e4Smiod saved_stabs[saved_stabs_index].string = xstrdup (string);
3893d8817e4Smiod saved_stabs_index = (saved_stabs_index + 1) % SAVE_STABS_COUNT;
3903d8817e4Smiod }
3913d8817e4Smiod
3923d8817e4Smiod /* Provide context for an error. */
3933d8817e4Smiod
3943d8817e4Smiod static void
stab_context(void)3953d8817e4Smiod stab_context (void)
3963d8817e4Smiod {
3973d8817e4Smiod int i;
3983d8817e4Smiod
3993d8817e4Smiod fprintf (stderr, _("Last stabs entries before error:\n"));
4003d8817e4Smiod fprintf (stderr, "n_type n_desc n_value string\n");
4013d8817e4Smiod
4023d8817e4Smiod i = saved_stabs_index;
4033d8817e4Smiod do
4043d8817e4Smiod {
4053d8817e4Smiod struct saved_stab *stabp;
4063d8817e4Smiod
4073d8817e4Smiod stabp = saved_stabs + i;
4083d8817e4Smiod if (stabp->string != NULL)
4093d8817e4Smiod {
4103d8817e4Smiod const char *s;
4113d8817e4Smiod
4123d8817e4Smiod s = bfd_get_stab_name (stabp->type);
4133d8817e4Smiod if (s != NULL)
4143d8817e4Smiod fprintf (stderr, "%-6s", s);
4153d8817e4Smiod else if (stabp->type == 0)
4163d8817e4Smiod fprintf (stderr, "HdrSym");
4173d8817e4Smiod else
4183d8817e4Smiod fprintf (stderr, "%-6d", stabp->type);
4193d8817e4Smiod fprintf (stderr, " %-6d ", stabp->desc);
4203d8817e4Smiod fprintf_vma (stderr, stabp->value);
4213d8817e4Smiod if (stabp->type != 0)
4223d8817e4Smiod fprintf (stderr, " %s", stabp->string);
4233d8817e4Smiod fprintf (stderr, "\n");
4243d8817e4Smiod }
4253d8817e4Smiod i = (i + 1) % SAVE_STABS_COUNT;
4263d8817e4Smiod }
4273d8817e4Smiod while (i != saved_stabs_index);
4283d8817e4Smiod }
4293d8817e4Smiod
4303d8817e4Smiod /* Free the saved stab strings. */
4313d8817e4Smiod
4323d8817e4Smiod static void
free_saved_stabs(void)4333d8817e4Smiod free_saved_stabs (void)
4343d8817e4Smiod {
4353d8817e4Smiod int i;
4363d8817e4Smiod
4373d8817e4Smiod for (i = 0; i < SAVE_STABS_COUNT; i++)
4383d8817e4Smiod {
4393d8817e4Smiod if (saved_stabs[i].string != NULL)
4403d8817e4Smiod {
4413d8817e4Smiod free (saved_stabs[i].string);
4423d8817e4Smiod saved_stabs[i].string = NULL;
4433d8817e4Smiod }
4443d8817e4Smiod }
4453d8817e4Smiod
4463d8817e4Smiod saved_stabs_index = 0;
4473d8817e4Smiod }
448