Back to index

cell-binutils  2.17cvs20070401
rddbg.c
Go to the documentation of this file.
00001 /* rddbg.c -- Read debugging information into a generic form.
00002    Copyright 1995, 1996, 1997, 2000, 2002, 2003, 2005
00003    Free Software Foundation, Inc.
00004    Written by Ian Lance Taylor <ian@cygnus.com>.
00005 
00006    This file is part of GNU Binutils.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
00021    02110-1301, USA.  */
00022 
00023 /* This file reads debugging information into a generic form.  This
00024    file knows how to dig the debugging information out of an object
00025    file.  */
00026 
00027 #include "bfd.h"
00028 #include "bucomm.h"
00029 #include "libiberty.h"
00030 #include "debug.h"
00031 #include "budbg.h"
00032 
00033 static bfd_boolean read_section_stabs_debugging_info
00034   (bfd *, asymbol **, long, void *, bfd_boolean *);
00035 static bfd_boolean read_symbol_stabs_debugging_info
00036   (bfd *, asymbol **, long, void *, bfd_boolean *);
00037 static bfd_boolean read_ieee_debugging_info (bfd *, void *, bfd_boolean *);
00038 static void save_stab (int, int, bfd_vma, const char *);
00039 static void stab_context (void);
00040 static void free_saved_stabs (void);
00041 
00042 /* Read debugging information from a BFD.  Returns a generic debugging
00043    pointer.  */
00044 
00045 void *
00046 read_debugging_info (bfd *abfd, asymbol **syms, long symcount)
00047 {
00048   void *dhandle;
00049   bfd_boolean found;
00050 
00051   dhandle = debug_init ();
00052   if (dhandle == NULL)
00053     return NULL;
00054 
00055   if (! read_section_stabs_debugging_info (abfd, syms, symcount, dhandle,
00056                                       &found))
00057     return NULL;
00058 
00059   if (bfd_get_flavour (abfd) == bfd_target_aout_flavour)
00060     {
00061       if (! read_symbol_stabs_debugging_info (abfd, syms, symcount, dhandle,
00062                                          &found))
00063        return NULL;
00064     }
00065 
00066   if (bfd_get_flavour (abfd) == bfd_target_ieee_flavour)
00067     {
00068       if (! read_ieee_debugging_info (abfd, dhandle, &found))
00069        return NULL;
00070     }
00071 
00072   /* Try reading the COFF symbols if we didn't find any stabs in COFF
00073      sections.  */
00074   if (! found
00075       && bfd_get_flavour (abfd) == bfd_target_coff_flavour
00076       && symcount > 0)
00077     {
00078       if (! parse_coff (abfd, syms, symcount, dhandle))
00079        return NULL;
00080       found = TRUE;
00081     }
00082 
00083   if (! found)
00084     {
00085       non_fatal (_("%s: no recognized debugging information"),
00086                bfd_get_filename (abfd));
00087       return NULL;
00088     }
00089 
00090   return dhandle;
00091 }
00092 
00093 /* Read stabs in sections debugging information from a BFD.  */
00094 
00095 static bfd_boolean
00096 read_section_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount,
00097                                void *dhandle, bfd_boolean *pfound)
00098 {
00099   static struct
00100     {
00101       const char *secname;
00102       const char *strsecname;
00103     }
00104   names[] =
00105     {
00106       { ".stab", ".stabstr" },
00107       { "LC_SYMTAB.stabs", "LC_SYMTAB.stabstr" },
00108       { "$GDB_SYMBOLS$", "$GDB_STRINGS$" }
00109     };
00110   unsigned int i;
00111   void *shandle;
00112 
00113   *pfound = FALSE;
00114   shandle = NULL;
00115 
00116   for (i = 0; i < sizeof names / sizeof names[0]; i++)
00117     {
00118       asection *sec, *strsec;
00119 
00120       sec = bfd_get_section_by_name (abfd, names[i].secname);
00121       strsec = bfd_get_section_by_name (abfd, names[i].strsecname);
00122       if (sec != NULL && strsec != NULL)
00123        {
00124          bfd_size_type stabsize, strsize;
00125          bfd_byte *stabs, *strings;
00126          bfd_byte *stab;
00127          bfd_size_type stroff, next_stroff;
00128 
00129          stabsize = bfd_section_size (abfd, sec);
00130          stabs = (bfd_byte *) xmalloc (stabsize);
00131          if (! bfd_get_section_contents (abfd, sec, stabs, 0, stabsize))
00132            {
00133              fprintf (stderr, "%s: %s: %s\n",
00134                      bfd_get_filename (abfd), names[i].secname,
00135                      bfd_errmsg (bfd_get_error ()));
00136              return FALSE;
00137            }
00138 
00139          strsize = bfd_section_size (abfd, strsec);
00140          strings = (bfd_byte *) xmalloc (strsize);
00141          if (! bfd_get_section_contents (abfd, strsec, strings, 0, strsize))
00142            {
00143              fprintf (stderr, "%s: %s: %s\n",
00144                      bfd_get_filename (abfd), names[i].strsecname,
00145                      bfd_errmsg (bfd_get_error ()));
00146              return FALSE;
00147            }
00148 
00149          if (shandle == NULL)
00150            {
00151              shandle = start_stab (dhandle, abfd, TRUE, syms, symcount);
00152              if (shandle == NULL)
00153               return FALSE;
00154            }
00155 
00156          *pfound = TRUE;
00157 
00158          stroff = 0;
00159          next_stroff = 0;
00160          for (stab = stabs; stab < stabs + stabsize; stab += 12)
00161            {
00162              unsigned int strx;
00163              int type;
00164              int other;
00165              int desc;
00166              bfd_vma value;
00167 
00168              /* This code presumes 32 bit values.  */
00169 
00170              strx = bfd_get_32 (abfd, stab);
00171              type = bfd_get_8 (abfd, stab + 4);
00172              other = bfd_get_8 (abfd, stab + 5);
00173              desc = bfd_get_16 (abfd, stab + 6);
00174              value = bfd_get_32 (abfd, stab + 8);
00175 
00176              if (type == 0)
00177               {
00178                 /* Special type 0 stabs indicate the offset to the
00179                    next string table.  */
00180                 stroff = next_stroff;
00181                 next_stroff += value;
00182               }
00183              else
00184               {
00185                 char *f, *s;
00186 
00187                 f = NULL;
00188 
00189                 if (stroff + strx > strsize)
00190                   {
00191                     fprintf (stderr, "%s: %s: stab entry %ld is corrupt, strx = 0x%x, type = %d\n",
00192                             bfd_get_filename (abfd), names[i].secname,
00193                             (long) (stab - stabs) / 12, strx, type);
00194                     continue;
00195                   }
00196 
00197                 s = (char *) strings + stroff + strx;
00198 
00199                 while (s[strlen (s) - 1] == '\\'
00200                       && stab + 12 < stabs + stabsize)
00201                   {
00202                     char *p;
00203 
00204                     stab += 12;
00205                     p = s + strlen (s) - 1;
00206                     *p = '\0';
00207                     s = concat (s,
00208                               ((char *) strings
00209                                + stroff
00210                                + bfd_get_32 (abfd, stab)),
00211                               (const char *) NULL);
00212 
00213                     /* We have to restore the backslash, because, if
00214                       the linker is hashing stabs strings, we may
00215                       see the same string more than once.  */
00216                     *p = '\\';
00217 
00218                     if (f != NULL)
00219                      free (f);
00220                     f = s;
00221                   }
00222 
00223                 save_stab (type, desc, value, s);
00224 
00225                 if (! parse_stab (dhandle, shandle, type, desc, value, s))
00226                   {
00227                     stab_context ();
00228                     free_saved_stabs ();
00229                     return FALSE;
00230                   }
00231 
00232                 /* Don't free f, since I think the stabs code
00233                    expects strings to hang around.  This should be
00234                    straightened out.  FIXME.  */
00235               }
00236            }
00237 
00238          free_saved_stabs ();
00239          free (stabs);
00240 
00241          /* Don't free strings, since I think the stabs code expects
00242             the strings to hang around.  This should be straightened
00243             out.  FIXME.  */
00244        }
00245     }
00246 
00247   if (shandle != NULL)
00248     {
00249       if (! finish_stab (dhandle, shandle))
00250        return FALSE;
00251     }
00252 
00253   return TRUE;
00254 }
00255 
00256 /* Read stabs in the symbol table.  */
00257 
00258 static bfd_boolean
00259 read_symbol_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount,
00260                               void *dhandle, bfd_boolean *pfound)
00261 {
00262   void *shandle;
00263   asymbol **ps, **symend;
00264 
00265   shandle = NULL;
00266   symend = syms + symcount;
00267   for (ps = syms; ps < symend; ps++)
00268     {
00269       symbol_info i;
00270 
00271       bfd_get_symbol_info (abfd, *ps, &i);
00272 
00273       if (i.type == '-')
00274        {
00275          const char *s;
00276          char *f;
00277 
00278          if (shandle == NULL)
00279            {
00280              shandle = start_stab (dhandle, abfd, FALSE, syms, symcount);
00281              if (shandle == NULL)
00282               return FALSE;
00283            }
00284 
00285          *pfound = TRUE;
00286 
00287          s = i.name;
00288          f = NULL;
00289          while (s[strlen (s) - 1] == '\\'
00290                && ps + 1 < symend)
00291            {
00292              char *sc, *n;
00293 
00294              ++ps;
00295              sc = xstrdup (s);
00296              sc[strlen (sc) - 1] = '\0';
00297              n = concat (sc, bfd_asymbol_name (*ps), (const char *) NULL);
00298              free (sc);
00299              if (f != NULL)
00300               free (f);
00301              f = n;
00302              s = n;
00303            }
00304 
00305          save_stab (i.stab_type, i.stab_desc, i.value, s);
00306 
00307          if (! parse_stab (dhandle, shandle, i.stab_type, i.stab_desc,
00308                          i.value, s))
00309            {
00310              stab_context ();
00311              free_saved_stabs ();
00312              return FALSE;
00313            }
00314 
00315          /* Don't free f, since I think the stabs code expects
00316             strings to hang around.  This should be straightened out.
00317             FIXME.  */
00318        }
00319     }
00320 
00321   free_saved_stabs ();
00322 
00323   if (shandle != NULL)
00324     {
00325       if (! finish_stab (dhandle, shandle))
00326        return FALSE;
00327     }
00328 
00329   return TRUE;
00330 }
00331 
00332 /* Read IEEE debugging information.  */
00333 
00334 static bfd_boolean
00335 read_ieee_debugging_info (bfd *abfd, void *dhandle, bfd_boolean *pfound)
00336 {
00337   asection *dsec;
00338   bfd_size_type size;
00339   bfd_byte *contents;
00340 
00341   /* The BFD backend puts the debugging information into a section
00342      named .debug.  */
00343 
00344   dsec = bfd_get_section_by_name (abfd, ".debug");
00345   if (dsec == NULL)
00346     return TRUE;
00347 
00348   size = bfd_section_size (abfd, dsec);
00349   contents = (bfd_byte *) xmalloc (size);
00350   if (! bfd_get_section_contents (abfd, dsec, contents, 0, size))
00351     return FALSE;
00352 
00353   if (! parse_ieee (dhandle, abfd, contents, size))
00354     return FALSE;
00355 
00356   free (contents);
00357 
00358   *pfound = TRUE;
00359 
00360   return TRUE;
00361 }
00362 
00363 /* Record stabs strings, so that we can give some context for errors.  */
00364 
00365 #define SAVE_STABS_COUNT (16)
00366 
00367 struct saved_stab
00368 {
00369   int type;
00370   int desc;
00371   bfd_vma value;
00372   char *string;
00373 };
00374 
00375 static struct saved_stab saved_stabs[SAVE_STABS_COUNT];
00376 static int saved_stabs_index;
00377 
00378 /* Save a stabs string.  */
00379 
00380 static void
00381 save_stab (int type, int desc, bfd_vma value, const char *string)
00382 {
00383   if (saved_stabs[saved_stabs_index].string != NULL)
00384     free (saved_stabs[saved_stabs_index].string);
00385   saved_stabs[saved_stabs_index].type = type;
00386   saved_stabs[saved_stabs_index].desc = desc;
00387   saved_stabs[saved_stabs_index].value = value;
00388   saved_stabs[saved_stabs_index].string = xstrdup (string);
00389   saved_stabs_index = (saved_stabs_index + 1) % SAVE_STABS_COUNT;
00390 }
00391 
00392 /* Provide context for an error.  */
00393 
00394 static void
00395 stab_context (void)
00396 {
00397   int i;
00398 
00399   fprintf (stderr, _("Last stabs entries before error:\n"));
00400   fprintf (stderr, "n_type n_desc n_value  string\n");
00401 
00402   i = saved_stabs_index;
00403   do
00404     {
00405       struct saved_stab *stabp;
00406 
00407       stabp = saved_stabs + i;
00408       if (stabp->string != NULL)
00409        {
00410          const char *s;
00411 
00412          s = bfd_get_stab_name (stabp->type);
00413          if (s != NULL)
00414            fprintf (stderr, "%-6s", s);
00415          else if (stabp->type == 0)
00416            fprintf (stderr, "HdrSym");
00417          else
00418            fprintf (stderr, "%-6d", stabp->type);
00419          fprintf (stderr, " %-6d ", stabp->desc);
00420          fprintf_vma (stderr, stabp->value);
00421          if (stabp->type != 0)
00422            fprintf (stderr, " %s", stabp->string);
00423          fprintf (stderr, "\n");
00424        }
00425       i = (i + 1) % SAVE_STABS_COUNT;
00426     }
00427   while (i != saved_stabs_index);
00428 }
00429 
00430 /* Free the saved stab strings.  */
00431 
00432 static void
00433 free_saved_stabs (void)
00434 {
00435   int i;
00436 
00437   for (i = 0; i < SAVE_STABS_COUNT; i++)
00438     {
00439       if (saved_stabs[i].string != NULL)
00440        {
00441          free (saved_stabs[i].string);
00442          saved_stabs[i].string = NULL;
00443        }
00444     }
00445 
00446   saved_stabs_index = 0;
00447 }