Home | History | Annotate | Line # | Download | only in binutils
      1   1.1  christos /* rddbg.c -- Read debugging information into a generic form.
      2  1.10  christos    Copyright (C) 1995-2025 Free Software Foundation, Inc.
      3   1.1  christos    Written by Ian Lance Taylor <ian (at) cygnus.com>.
      4   1.1  christos 
      5   1.1  christos    This file is part of GNU Binutils.
      6   1.1  christos 
      7   1.1  christos    This program is free software; you can redistribute it and/or modify
      8   1.1  christos    it under the terms of the GNU General Public License as published by
      9   1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10   1.1  christos    (at your option) any later version.
     11   1.1  christos 
     12   1.1  christos    This program is distributed in the hope that it will be useful,
     13   1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14   1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15   1.1  christos    GNU General Public License for more details.
     16   1.1  christos 
     17   1.1  christos    You should have received a copy of the GNU General Public License
     18   1.1  christos    along with this program; if not, write to the Free Software
     19   1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
     20   1.1  christos    02110-1301, USA.  */
     21   1.1  christos 
     22   1.1  christos 
     23   1.1  christos /* This file reads debugging information into a generic form.  This
     24   1.1  christos    file knows how to dig the debugging information out of an object
     25   1.1  christos    file.  */
     26   1.1  christos 
     27   1.1  christos #include "sysdep.h"
     28   1.1  christos #include "bfd.h"
     29   1.1  christos #include "libiberty.h"
     30   1.1  christos #include "bucomm.h"
     31   1.1  christos #include "debug.h"
     32   1.1  christos #include "budbg.h"
     33   1.1  christos 
     34   1.8  christos static bool read_section_stabs_debugging_info
     35   1.8  christos   (bfd *, asymbol **, long, void *, bool *);
     36   1.8  christos static bool read_symbol_stabs_debugging_info
     37   1.8  christos   (bfd *, asymbol **, long, void *, bool *);
     38   1.1  christos static void save_stab (int, int, bfd_vma, const char *);
     39   1.1  christos static void stab_context (void);
     40   1.1  christos static void free_saved_stabs (void);
     41   1.1  christos 
     42   1.1  christos /* Read debugging information from a BFD.  Returns a generic debugging
     43   1.1  christos    pointer.  */
     44   1.1  christos 
     45   1.1  christos void *
     46   1.8  christos read_debugging_info (bfd *abfd, asymbol **syms, long symcount,
     47   1.8  christos 		     bool no_messages)
     48   1.1  christos {
     49   1.1  christos   void *dhandle;
     50   1.8  christos   bool found;
     51   1.1  christos 
     52   1.9  christos   dhandle = debug_init (abfd);
     53   1.1  christos   if (dhandle == NULL)
     54   1.1  christos     return NULL;
     55   1.1  christos 
     56   1.9  christos   if (!debug_set_filename (dhandle, bfd_get_filename (abfd)))
     57   1.9  christos     return NULL;
     58   1.9  christos 
     59   1.1  christos   if (! read_section_stabs_debugging_info (abfd, syms, symcount, dhandle,
     60   1.1  christos 					   &found))
     61   1.9  christos     return NULL;
     62   1.1  christos 
     63   1.1  christos   if (bfd_get_flavour (abfd) == bfd_target_aout_flavour)
     64   1.1  christos     {
     65   1.1  christos       if (! read_symbol_stabs_debugging_info (abfd, syms, symcount, dhandle,
     66   1.1  christos 					      &found))
     67   1.9  christos 	return NULL;
     68   1.1  christos     }
     69   1.1  christos 
     70   1.1  christos   /* Try reading the COFF symbols if we didn't find any stabs in COFF
     71   1.1  christos      sections.  */
     72   1.1  christos   if (! found
     73   1.1  christos       && bfd_get_flavour (abfd) == bfd_target_coff_flavour
     74   1.1  christos       && symcount > 0)
     75   1.1  christos     {
     76   1.1  christos       if (! parse_coff (abfd, syms, symcount, dhandle))
     77   1.9  christos 	return NULL;
     78   1.8  christos       found = true;
     79   1.1  christos     }
     80   1.1  christos 
     81   1.1  christos   if (! found)
     82   1.1  christos     {
     83   1.1  christos       if (! no_messages)
     84   1.1  christos 	non_fatal (_("%s: no recognized debugging information"),
     85   1.1  christos 		   bfd_get_filename (abfd));
     86   1.1  christos       return NULL;
     87   1.1  christos     }
     88   1.1  christos 
     89   1.1  christos   return dhandle;
     90   1.1  christos }
     91   1.1  christos 
     92   1.1  christos /* Read stabs in sections debugging information from a BFD.  */
     93   1.1  christos 
     94   1.8  christos static bool
     95   1.1  christos read_section_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount,
     96   1.8  christos 				   void *dhandle, bool *pfound)
     97   1.1  christos {
     98   1.1  christos   static struct
     99   1.1  christos     {
    100   1.1  christos       const char *secname;
    101   1.1  christos       const char *strsecname;
    102   1.1  christos     }
    103   1.1  christos   names[] =
    104   1.1  christos     {
    105   1.1  christos       { ".stab", ".stabstr" },
    106   1.1  christos       { "LC_SYMTAB.stabs", "LC_SYMTAB.stabstr" },
    107   1.1  christos       { "$GDB_SYMBOLS$", "$GDB_STRINGS$" }
    108   1.1  christos     };
    109   1.1  christos   unsigned int i;
    110   1.1  christos   void *shandle;
    111   1.9  christos   bool ret = false;
    112   1.1  christos 
    113   1.8  christos   *pfound = false;
    114   1.1  christos   shandle = NULL;
    115   1.1  christos 
    116   1.1  christos   for (i = 0; i < sizeof names / sizeof names[0]; i++)
    117   1.1  christos     {
    118   1.1  christos       asection *sec, *strsec;
    119   1.1  christos 
    120   1.1  christos       sec = bfd_get_section_by_name (abfd, names[i].secname);
    121   1.1  christos       strsec = bfd_get_section_by_name (abfd, names[i].strsecname);
    122   1.9  christos       if (sec != NULL
    123   1.9  christos 	  && (bfd_section_flags (sec) & SEC_HAS_CONTENTS) != 0
    124   1.9  christos 	  && bfd_section_size (sec) >= 12
    125   1.9  christos 	  && strsec != NULL
    126   1.9  christos 	  && (bfd_section_flags (strsec) & SEC_HAS_CONTENTS) != 0)
    127   1.1  christos 	{
    128   1.1  christos 	  bfd_size_type stabsize, strsize;
    129   1.1  christos 	  bfd_byte *stabs, *strings;
    130   1.1  christos 	  bfd_byte *stab;
    131   1.1  christos 	  bfd_size_type stroff, next_stroff;
    132   1.1  christos 
    133   1.9  christos 	  if (!bfd_malloc_and_get_section (abfd, sec, &stabs))
    134   1.1  christos 	    {
    135   1.1  christos 	      fprintf (stderr, "%s: %s: %s\n",
    136   1.1  christos 		       bfd_get_filename (abfd), names[i].secname,
    137   1.1  christos 		       bfd_errmsg (bfd_get_error ()));
    138   1.9  christos 	      goto out;
    139   1.1  christos 	    }
    140   1.1  christos 
    141   1.9  christos 	  if (!bfd_malloc_and_get_section (abfd, strsec, &strings))
    142   1.1  christos 	    {
    143   1.1  christos 	      fprintf (stderr, "%s: %s: %s\n",
    144   1.1  christos 		       bfd_get_filename (abfd), names[i].strsecname,
    145   1.1  christos 		       bfd_errmsg (bfd_get_error ()));
    146   1.7  christos 	      free (stabs);
    147   1.9  christos 	      goto out;
    148   1.1  christos 	    }
    149   1.3  christos 	  /* Zero terminate the strings table, just in case.  */
    150   1.9  christos 	  strsize = bfd_section_size (strsec);
    151   1.9  christos 	  if (strsize != 0)
    152   1.9  christos 	    strings [strsize - 1] = 0;
    153   1.1  christos 	  if (shandle == NULL)
    154   1.1  christos 	    {
    155   1.8  christos 	      shandle = start_stab (dhandle, abfd, true, syms, symcount);
    156   1.1  christos 	      if (shandle == NULL)
    157   1.7  christos 		{
    158   1.7  christos 		  free (strings);
    159   1.7  christos 		  free (stabs);
    160   1.9  christos 		  goto out;
    161   1.7  christos 		}
    162   1.1  christos 	    }
    163   1.1  christos 
    164   1.8  christos 	  *pfound = true;
    165   1.1  christos 
    166   1.1  christos 	  stroff = 0;
    167   1.1  christos 	  next_stroff = 0;
    168   1.9  christos 	  stabsize = bfd_section_size (sec);
    169   1.3  christos 	  /* PR 17512: file: 078-60391-0.001:0.1.  */
    170   1.3  christos 	  for (stab = stabs; stab <= (stabs + stabsize) - 12; stab += 12)
    171   1.1  christos 	    {
    172   1.1  christos 	      unsigned int strx;
    173   1.1  christos 	      int type;
    174   1.1  christos 	      int other ATTRIBUTE_UNUSED;
    175   1.1  christos 	      int desc;
    176   1.1  christos 	      bfd_vma value;
    177   1.1  christos 
    178   1.1  christos 	      /* This code presumes 32 bit values.  */
    179   1.1  christos 
    180   1.1  christos 	      strx = bfd_get_32 (abfd, stab);
    181   1.1  christos 	      type = bfd_get_8 (abfd, stab + 4);
    182   1.1  christos 	      other = bfd_get_8 (abfd, stab + 5);
    183   1.1  christos 	      desc = bfd_get_16 (abfd, stab + 6);
    184   1.1  christos 	      value = bfd_get_32 (abfd, stab + 8);
    185   1.1  christos 
    186   1.1  christos 	      if (type == 0)
    187   1.1  christos 		{
    188   1.1  christos 		  /* Special type 0 stabs indicate the offset to the
    189   1.1  christos 		     next string table.  */
    190   1.1  christos 		  stroff = next_stroff;
    191   1.1  christos 		  next_stroff += value;
    192   1.1  christos 		}
    193   1.1  christos 	      else
    194   1.1  christos 		{
    195   1.3  christos 		  size_t len;
    196   1.1  christos 		  char *f, *s;
    197   1.1  christos 
    198   1.3  christos 		  if (stroff + strx >= strsize)
    199   1.1  christos 		    {
    200   1.3  christos 		      fprintf (stderr, _("%s: %s: stab entry %ld is corrupt, strx = 0x%x, type = %d\n"),
    201   1.1  christos 			       bfd_get_filename (abfd), names[i].secname,
    202   1.1  christos 			       (long) (stab - stabs) / 12, strx, type);
    203   1.1  christos 		      continue;
    204   1.1  christos 		    }
    205   1.1  christos 
    206   1.1  christos 		  s = (char *) strings + stroff + strx;
    207   1.3  christos 		  f = NULL;
    208   1.1  christos 
    209   1.3  christos 		  /* PR 17512: file: 002-87578-0.001:0.1.
    210   1.3  christos 		     It is possible to craft a file where, without the 'strlen (s) > 0',
    211   1.3  christos 		     an attempt to read the byte before 'strings' would occur.  */
    212   1.3  christos 		  while ((len = strlen (s)) > 0
    213   1.3  christos 			 && s[len  - 1] == '\\'
    214   1.8  christos 			 && stab + 16 <= stabs + stabsize)
    215   1.1  christos 		    {
    216   1.1  christos 		      char *p;
    217   1.1  christos 
    218   1.1  christos 		      stab += 12;
    219   1.3  christos 		      p = s + len - 1;
    220   1.1  christos 		      *p = '\0';
    221   1.3  christos 		      strx = stroff + bfd_get_32 (abfd, stab);
    222   1.3  christos 		      if (strx >= strsize)
    223   1.3  christos 			{
    224   1.3  christos 			  fprintf (stderr, _("%s: %s: stab entry %ld is corrupt\n"),
    225   1.3  christos 				   bfd_get_filename (abfd), names[i].secname,
    226   1.3  christos 				   (long) (stab - stabs) / 12);
    227   1.3  christos 			  break;
    228   1.3  christos 			}
    229   1.7  christos 
    230   1.7  christos 		      s = concat (s, (char *) strings + strx,
    231   1.7  christos 				  (const char *) NULL);
    232   1.1  christos 
    233   1.1  christos 		      /* We have to restore the backslash, because, if
    234   1.1  christos 			 the linker is hashing stabs strings, we may
    235   1.1  christos 			 see the same string more than once.  */
    236   1.1  christos 		      *p = '\\';
    237   1.1  christos 
    238   1.7  christos 		      free (f);
    239   1.1  christos 		      f = s;
    240   1.1  christos 		    }
    241   1.1  christos 
    242   1.1  christos 		  save_stab (type, desc, value, s);
    243   1.1  christos 
    244   1.9  christos 		  if (!parse_stab (dhandle, shandle, type, desc, value, s))
    245   1.1  christos 		    {
    246   1.1  christos 		      stab_context ();
    247   1.1  christos 		      free_saved_stabs ();
    248   1.7  christos 		      free (f);
    249   1.7  christos 		      free (stabs);
    250   1.7  christos 		      free (strings);
    251   1.9  christos 		      goto out;
    252   1.1  christos 		    }
    253   1.1  christos 
    254   1.9  christos 		  free (f);
    255   1.1  christos 		}
    256   1.1  christos 	    }
    257   1.1  christos 
    258   1.1  christos 	  free_saved_stabs ();
    259   1.1  christos 	  free (stabs);
    260   1.9  christos 	  free (strings);
    261   1.1  christos 	}
    262   1.1  christos     }
    263   1.9  christos   ret = true;
    264   1.1  christos 
    265   1.9  christos  out:
    266   1.1  christos   if (shandle != NULL)
    267   1.1  christos     {
    268   1.9  christos       if (! finish_stab (dhandle, shandle, ret))
    269   1.8  christos 	return false;
    270   1.1  christos     }
    271   1.1  christos 
    272   1.9  christos   return ret;
    273   1.1  christos }
    274   1.1  christos 
    275   1.1  christos /* Read stabs in the symbol table.  */
    276   1.1  christos 
    277   1.8  christos static bool
    278   1.1  christos read_symbol_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount,
    279   1.8  christos 				  void *dhandle, bool *pfound)
    280   1.1  christos {
    281   1.1  christos   void *shandle;
    282   1.1  christos   asymbol **ps, **symend;
    283   1.1  christos 
    284   1.1  christos   shandle = NULL;
    285   1.1  christos   symend = syms + symcount;
    286   1.1  christos   for (ps = syms; ps < symend; ps++)
    287   1.1  christos     {
    288   1.1  christos       symbol_info i;
    289   1.1  christos 
    290   1.1  christos       bfd_get_symbol_info (abfd, *ps, &i);
    291   1.1  christos 
    292   1.1  christos       if (i.type == '-')
    293   1.1  christos 	{
    294   1.1  christos 	  const char *s;
    295   1.1  christos 	  char *f;
    296   1.1  christos 
    297   1.1  christos 	  if (shandle == NULL)
    298   1.1  christos 	    {
    299   1.8  christos 	      shandle = start_stab (dhandle, abfd, false, syms, symcount);
    300   1.1  christos 	      if (shandle == NULL)
    301   1.8  christos 		return false;
    302   1.1  christos 	    }
    303   1.1  christos 
    304   1.8  christos 	  *pfound = true;
    305   1.1  christos 
    306   1.1  christos 	  s = i.name;
    307   1.6  christos 	  if (s == NULL || strlen (s) < 1)
    308   1.9  christos 	    break;
    309   1.1  christos 	  f = NULL;
    310   1.6  christos 
    311   1.6  christos 	  while (strlen (s) > 0
    312   1.6  christos 		 && s[strlen (s) - 1] == '\\'
    313   1.1  christos 		 && ps + 1 < symend)
    314   1.1  christos 	    {
    315   1.1  christos 	      char *sc, *n;
    316   1.1  christos 
    317   1.1  christos 	      ++ps;
    318   1.1  christos 	      sc = xstrdup (s);
    319   1.1  christos 	      sc[strlen (sc) - 1] = '\0';
    320   1.1  christos 	      n = concat (sc, bfd_asymbol_name (*ps), (const char *) NULL);
    321   1.1  christos 	      free (sc);
    322   1.8  christos 	      free (f);
    323   1.1  christos 	      f = n;
    324   1.1  christos 	      s = n;
    325   1.1  christos 	    }
    326   1.1  christos 
    327   1.1  christos 	  save_stab (i.stab_type, i.stab_desc, i.value, s);
    328   1.1  christos 
    329   1.9  christos 	  if (!parse_stab (dhandle, shandle, i.stab_type, i.stab_desc,
    330   1.9  christos 			   i.value, s))
    331   1.1  christos 	    {
    332   1.1  christos 	      stab_context ();
    333   1.9  christos 	      free (f);
    334   1.9  christos 	      break;
    335   1.1  christos 	    }
    336   1.1  christos 
    337   1.9  christos 	  free (f);
    338   1.1  christos 	}
    339   1.1  christos     }
    340   1.9  christos   bool ret = ps >= symend;
    341   1.1  christos 
    342   1.1  christos   free_saved_stabs ();
    343   1.1  christos 
    344   1.1  christos   if (shandle != NULL)
    345   1.1  christos     {
    346   1.9  christos       if (! finish_stab (dhandle, shandle, ret))
    347   1.8  christos 	return false;
    348   1.1  christos     }
    349   1.1  christos 
    350   1.9  christos   return ret;
    351   1.1  christos }
    352   1.1  christos 
    353   1.1  christos /* Record stabs strings, so that we can give some context for errors.  */
    355   1.1  christos 
    356   1.1  christos #define SAVE_STABS_COUNT (16)
    357   1.1  christos 
    358   1.1  christos struct saved_stab
    359   1.1  christos {
    360   1.1  christos   int type;
    361   1.1  christos   int desc;
    362   1.1  christos   bfd_vma value;
    363   1.1  christos   char *string;
    364   1.1  christos };
    365   1.1  christos 
    366   1.1  christos static struct saved_stab saved_stabs[SAVE_STABS_COUNT];
    367   1.1  christos static int saved_stabs_index;
    368   1.1  christos 
    369   1.1  christos /* Save a stabs string.  */
    370   1.1  christos 
    371   1.1  christos static void
    372   1.1  christos save_stab (int type, int desc, bfd_vma value, const char *string)
    373   1.8  christos {
    374   1.1  christos   free (saved_stabs[saved_stabs_index].string);
    375   1.1  christos   saved_stabs[saved_stabs_index].type = type;
    376   1.1  christos   saved_stabs[saved_stabs_index].desc = desc;
    377   1.1  christos   saved_stabs[saved_stabs_index].value = value;
    378   1.1  christos   saved_stabs[saved_stabs_index].string = xstrdup (string);
    379   1.1  christos   saved_stabs_index = (saved_stabs_index + 1) % SAVE_STABS_COUNT;
    380   1.1  christos }
    381   1.1  christos 
    382   1.1  christos /* Provide context for an error.  */
    383   1.1  christos 
    384   1.1  christos static void
    385   1.1  christos stab_context (void)
    386   1.1  christos {
    387   1.1  christos   int i;
    388   1.1  christos 
    389   1.1  christos   fprintf (stderr, _("Last stabs entries before error:\n"));
    390   1.1  christos   fprintf (stderr, "n_type n_desc n_value  string\n");
    391   1.1  christos 
    392   1.1  christos   i = saved_stabs_index;
    393   1.1  christos   do
    394   1.1  christos     {
    395   1.1  christos       struct saved_stab *stabp;
    396   1.1  christos 
    397   1.1  christos       stabp = saved_stabs + i;
    398   1.1  christos       if (stabp->string != NULL)
    399   1.1  christos 	{
    400   1.1  christos 	  const char *s;
    401   1.1  christos 
    402   1.1  christos 	  s = bfd_get_stab_name (stabp->type);
    403   1.1  christos 	  if (s != NULL)
    404   1.1  christos 	    fprintf (stderr, "%-6s", s);
    405   1.1  christos 	  else if (stabp->type == 0)
    406   1.1  christos 	    fprintf (stderr, "HdrSym");
    407   1.1  christos 	  else
    408   1.1  christos 	    fprintf (stderr, "%-6d", stabp->type);
    409   1.9  christos 	  fprintf (stderr, " %-6d ", stabp->desc);
    410   1.1  christos 	  fprintf (stderr, "%08" PRIx64, (uint64_t) stabp->value);
    411   1.1  christos 	  if (stabp->type != 0)
    412   1.1  christos 	    fprintf (stderr, " %s", stabp->string);
    413   1.1  christos 	  fprintf (stderr, "\n");
    414   1.1  christos 	}
    415   1.1  christos       i = (i + 1) % SAVE_STABS_COUNT;
    416   1.1  christos     }
    417   1.1  christos   while (i != saved_stabs_index);
    418   1.1  christos }
    419   1.1  christos 
    420   1.1  christos /* Free the saved stab strings.  */
    421   1.1  christos 
    422   1.1  christos static void
    423   1.1  christos free_saved_stabs (void)
    424   1.1  christos {
    425   1.1  christos   int i;
    426   1.1  christos 
    427   1.1  christos   for (i = 0; i < SAVE_STABS_COUNT; i++)
    428   1.8  christos     {
    429   1.8  christos       free (saved_stabs[i].string);
    430   1.1  christos       saved_stabs[i].string = NULL;
    431   1.1  christos     }
    432   1.1  christos 
    433   1.1  christos   saved_stabs_index = 0;
    434                 }
    435