* objdump.c (dump_section_stabs): Fix test for stabs sections
authorStu Grossman <grossman@cygnus>
Mon, 22 Jul 1996 15:49:34 +0000 (15:49 +0000)
committerStu Grossman <grossman@cygnus>
Mon, 22 Jul 1996 15:49:34 +0000 (15:49 +0000)
ending with numbers.  This fixes a problem with .stab being
confused with .stab.index.

binutils/ChangeLog
binutils/objdump.c

index 68e98dfab50a6c8f25479ab4cd44b97a056690f3..951d45642c994bf97fa6b016517e9cf1e78d4fdb 100644 (file)
@@ -1,3 +1,9 @@
+Mon Jul 22 08:46:15 1996  Stu Grossman  (grossman@lisa.cygnus.com)
+
+       * objdump.c (dump_section_stabs):  Fix test for stabs sections
+       ending with numbers.  This fixes a problem with .stab being
+       confused with .stab.index.
+
 Wed Jul 10 13:32:28 1996  Ian Lance Taylor  <ian@cygnus.com>
 
        * stabs.c (stab_demangle_fund_type): Return a void * for a
index 7fbe1353e46d4fdaddd36da6bde354fedbbd7b3d..74d8f4b8be4a0aad29311e6a16eac422432b1f38 100644 (file)
@@ -42,32 +42,32 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 extern int fprintf PARAMS ((FILE *, const char *, ...));
 #endif
 
-char *default_target = NULL;   /* default at runtime */
+static char *default_target = NULL;    /* default at runtime */
 
 extern char *program_version;
 
-int show_version = 0;          /* show the version number */
-int dump_section_contents;     /* -s */
-int dump_section_headers;      /* -h */
-boolean dump_file_header;      /* -f */
-int dump_symtab;               /* -t */
-int dump_dynamic_symtab;       /* -T */
-int dump_reloc_info;           /* -r */
-int dump_dynamic_reloc_info;   /* -R */
-int dump_ar_hdrs;              /* -a */
-int dump_private_headers;      /* -p */
-int with_line_numbers;         /* -l */
-boolean with_source_code;      /* -S */
-int show_raw_insn;             /* --show-raw-insn */
-int dump_stab_section_info;    /* --stabs */
-boolean disassemble;           /* -d */
-boolean disassemble_all;       /* -D */
-boolean formats_info;          /* -i */
-char *only;                    /* -j secname */
-int wide_output;               /* -w */
-bfd_vma start_address = (bfd_vma) -1; /* --start-address */
-bfd_vma stop_address = (bfd_vma) -1;  /* --stop-address */
-int dump_debugging;            /* --debugging */
+static int show_version = 0;           /* show the version number */
+static int dump_section_contents;      /* -s */
+static int dump_section_headers;       /* -h */
+static boolean dump_file_header;       /* -f */
+static int dump_symtab;                        /* -t */
+static int dump_dynamic_symtab;                /* -T */
+static int dump_reloc_info;            /* -r */
+static int dump_dynamic_reloc_info;    /* -R */
+static int dump_ar_hdrs;               /* -a */
+static int dump_private_headers;       /* -p */
+static int with_line_numbers;          /* -l */
+static boolean with_source_code;       /* -S */
+static int show_raw_insn;              /* --show-raw-insn */
+static int dump_stab_section_info;     /* --stabs */
+static boolean disassemble;            /* -d */
+static boolean disassemble_all;                /* -D */
+static boolean formats_info;           /* -i */
+static char *only;                     /* -j secname */
+static int wide_output;                        /* -w */
+static bfd_vma start_address = (bfd_vma) -1; /* --start-address */
+static bfd_vma stop_address = (bfd_vma) -1;  /* --stop-address */
+static int dump_debugging;             /* --debugging */
 
 /* Extra info to pass to the disassembler address printing function.  */
 struct objdump_disasm_info {
@@ -77,25 +77,28 @@ struct objdump_disasm_info {
 };
 
 /* Architecture to disassemble for, or default if NULL.  */
-char *machine = (char *) NULL;
+static char *machine = (char *) NULL;
+
+/* Endianness to disassemble for, or default if BFD_ENDIAN_UNKNOWN.  */
+static enum bfd_endian endian = BFD_ENDIAN_UNKNOWN;
 
 /* The symbol table.  */
-asymbol **syms;
+static asymbol **syms;
 
 /* Number of symbols in `syms'.  */
-long symcount = 0;
+static long symcount = 0;
 
 /* The sorted symbol table.  */
-asymbol **sorted_syms;
+static asymbol **sorted_syms;
 
 /* Number of symbols in `sorted_syms'.  */
-long sorted_symcount = 0;
+static long sorted_symcount = 0;
 
 /* The dynamic symbol table.  */
-asymbol **dynsyms;
+static asymbol **dynsyms;
 
 /* Number of symbols in `dynsyms'.  */
-long dynsymcount = 0;
+static long dynsymcount = 0;
 
 /* Forward declarations.  */
 
@@ -112,7 +115,7 @@ static void
 dump_dynamic_relocs PARAMS ((bfd * abfd));
 
 static void
-dump_reloc_set PARAMS ((bfd *, arelent **, long));
+dump_reloc_set PARAMS ((bfd *, asection *, arelent **, long));
 
 static void
 dump_symbols PARAMS ((bfd *abfd, boolean dynamic));
@@ -132,7 +135,7 @@ show_line PARAMS ((bfd *, asection *, bfd_vma));
 static const char *
 endian_string PARAMS ((enum bfd_endian));
 \f
-void
+static void
 usage (stream, status)
      FILE *stream;
      int status;
@@ -148,7 +151,7 @@ Usage: %s [-ahifdDprRtTxsSlw] [-b bfdname] [-m machine] [-j section-name]\n\
        [--syms] [--all-headers] [--dynamic-syms] [--dynamic-reloc]\n\
        [--wide] [--version] [--help] [--private-headers]\n\
        [--start-address=addr] [--stop-address=addr]\n\
-       [--show-raw-insn] objfile...\n\
+       [--show-raw-insn] [-EB|-EL] [--endian={big|little}] objfile...\n\
 at least one option besides -l (--line-numbers) must be given\n");
   list_supported_targets (program_name, stream);
   exit (status);
@@ -156,7 +159,8 @@ at least one option besides -l (--line-numbers) must be given\n");
 
 /* 150 isn't special; it's just an arbitrary non-ASCII char value.  */
 
-#define OPTION_START_ADDRESS (150)
+#define OPTION_ENDIAN (150)
+#define OPTION_START_ADDRESS (OPTION_ENDIAN + 1)
 #define OPTION_STOP_ADDRESS (OPTION_START_ADDRESS + 1)
 
 static struct option long_options[]=
@@ -170,6 +174,7 @@ static struct option long_options[]=
   {"disassemble-all", no_argument, NULL, 'D'},
   {"dynamic-reloc", no_argument, NULL, 'R'},
   {"dynamic-syms", no_argument, NULL, 'T'},
+  {"endian", required_argument, NULL, OPTION_ENDIAN},
   {"file-headers", no_argument, NULL, 'f'},
   {"full-contents", no_argument, NULL, 's'},
   {"headers", no_argument, NULL, 'h'},
@@ -347,7 +352,7 @@ slurp_dynamic_symtab (abfd)
    COUNT is the number of elements in SYMBOLS.
    Return the number of useful symbols. */
 
-long
+static long
 remove_useless_symbols (symbols, count)
      asymbol **symbols;
      long count;
@@ -905,7 +910,7 @@ objdump_sprintf (va_alist)
 }
 #endif
 
-void
+static void
 disassemble_data (abfd)
      bfd *abfd;
 {
@@ -950,6 +955,16 @@ disassemble_data (abfd)
       abfd->arch_info = info;
     }
 
+  if (endian != BFD_ENDIAN_UNKNOWN)
+    {
+      struct bfd_target *xvec;
+
+      xvec = (struct bfd_target *) xmalloc (sizeof (struct bfd_target));
+      memcpy (xvec, abfd->xvec, sizeof (struct bfd_target));
+      xvec->byteorder = endian;
+      abfd->xvec = xvec;
+    }
+
   disassemble_fn = disassembler (abfd);
   if (!disassemble_fn)
     {
@@ -1050,8 +1065,13 @@ disassemble_data (abfd)
          int bytes;
          boolean need_nl = false;
 
-         if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 &&
-             data[i + 3] == 0)
+         if (data[i] == 0
+             && (i + 1 >= stop
+                 || (data[i + 1] == 0
+                     && (i + 2 >= stop
+                         || (data[i + 2] == 0
+                             && (i + 3 >= stop
+                                 || data[i + 3] == 0))))))
            {
              if (done_dot == false)
                {
@@ -1166,14 +1186,13 @@ disassemble_data (abfd)
    could be a direct-mapped table, but instead we build one the first
    time we need it.  */
 
-void dump_section_stabs PARAMS ((bfd *abfd, char *stabsect_name,
-                                char *strsect_name));
+static void dump_section_stabs PARAMS ((bfd *abfd, char *stabsect_name,
+                                       char *strsect_name));
 
 /* Dump the stabs sections from an object file that has a section that
-   uses Sun stabs encoding.  It has to use some hooks into BFD because
-   string table sections are not normally visible to BFD callers.  */
+   uses Sun stabs encoding.  */
 
-void
+static void
 dump_stabs (abfd)
      bfd *abfd;
 {
@@ -1183,7 +1202,7 @@ dump_stabs (abfd)
   dump_section_stabs (abfd, "$GDB_SYMBOLS$", "$GDB_STRINGS$");
 }
 
-static struct internal_nlist *stabs;
+static bfd_byte *stabs;
 static bfd_size_type stab_size;
 
 static char *strtab;
@@ -1194,7 +1213,7 @@ static bfd_size_type stabstr_size;
    If the section exists and was read, allocate the space and return true.
    Otherwise return false.  */
 
-boolean
+static boolean
 read_section_stabs (abfd, stabsect_name, strsect_name)
      bfd *abfd;
      char *stabsect_name;
@@ -1220,7 +1239,7 @@ read_section_stabs (abfd, stabsect_name, strsect_name)
   stab_size    = bfd_section_size (abfd, stabsect);
   stabstr_size = bfd_section_size (abfd, stabstrsect);
 
-  stabs  = (struct internal_nlist *) xmalloc (stab_size);
+  stabs  = (bfd_byte *) xmalloc (stab_size);
   strtab = (char *) xmalloc (stabstr_size);
   
   if (! bfd_get_section_contents (abfd, stabsect, (PTR) stabs, 0, stab_size))
@@ -1247,20 +1266,25 @@ read_section_stabs (abfd, stabsect_name, strsect_name)
   return true;
 }
 
-#define SWAP_SYMBOL(symp, abfd) \
-{ \
-    (symp)->n_strx = bfd_h_get_32(abfd,                        \
-                                 (unsigned char *)&(symp)->n_strx);    \
-    (symp)->n_desc = bfd_h_get_16 (abfd,                       \
-                                  (unsigned char *)&(symp)->n_desc);   \
-    (symp)->n_value = bfd_h_get_32 (abfd,                      \
-                                   (unsigned char *)&(symp)->n_value); \
-}
+/* Stabs entries use a 12 byte format:
+     4 byte string table index
+     1 byte stab type
+     1 byte stab other field
+     2 byte stab desc field
+     4 byte stab value
+   FIXME: This will have to change for a 64 bit object format.  */
+
+#define STRDXOFF (0)
+#define TYPEOFF (4)
+#define OTHEROFF (5)
+#define DESCOFF (6)
+#define VALOFF (8)
+#define STABSIZE (12)
 
 /* Print ABFD's stabs section STABSECT_NAME (in `stabs'),
    using string table section STRSECT_NAME (in `strtab').  */
 
-void
+static void
 print_section_stabs (abfd, stabsect_name, strsect_name)
      bfd *abfd;
      char *stabsect_name;
@@ -1268,8 +1292,10 @@ print_section_stabs (abfd, stabsect_name, strsect_name)
 {
   int i;
   unsigned file_string_table_offset = 0, next_file_string_table_offset = 0;
-  struct internal_nlist *stabp = stabs,
-  *stabs_end = (struct internal_nlist *) (stab_size + (char *) stabs);
+  bfd_byte *stabp, *stabs_end;
+
+  stabp = stabs;
+  stabs_end = stabp + stab_size;
 
   printf ("Contents of %s section:\n\n", stabsect_name);
   printf ("Symnum n_type n_othr n_desc n_value  n_strx String\n");
@@ -1279,41 +1305,50 @@ print_section_stabs (abfd, stabsect_name, strsect_name)
      We start the index at -1 because there is a dummy symbol on
      the front of stabs-in-{coff,elf} sections that supplies sizes.  */
 
-  for (i = -1; stabp < stabs_end; stabp++, i++)
+  for (i = -1; stabp < stabs_end; stabp += STABSIZE, i++)
     {
       const char *name;
+      unsigned long strx;
+      unsigned char type, other;
+      unsigned short desc;
+      bfd_vma value;
+
+      strx = bfd_h_get_32 (abfd, stabp + STRDXOFF);
+      type = bfd_h_get_8 (abfd, stabp + TYPEOFF);
+      other = bfd_h_get_8 (abfd, stabp + OTHEROFF);
+      desc = bfd_h_get_16 (abfd, stabp + DESCOFF);
+      value = bfd_h_get_32 (abfd, stabp + VALOFF);
 
-      SWAP_SYMBOL (stabp, abfd);
       printf ("\n%-6d ", i);
       /* Either print the stab name, or, if unnamed, print its number
         again (makes consistent formatting for tools like awk). */
-      name = bfd_get_stab_name (stabp->n_type);
+      name = bfd_get_stab_name (type);
       if (name != NULL)
        printf ("%-6s", name);
-      else if (stabp->n_type == N_UNDF)
+      else if (type == N_UNDF)
        printf ("HdrSym");
       else
-       printf ("%-6d", stabp->n_type);
-      printf (" %-6d %-6d ", stabp->n_other, stabp->n_desc);
-      printf_vma (stabp->n_value);
-      printf (" %-6lu", stabp->n_strx);
+       printf ("%-6d", type);
+      printf (" %-6d %-6d ", other, desc);
+      printf_vma (value);
+      printf (" %-6lu", strx);
 
       /* Symbols with type == 0 (N_UNDF) specify the length of the
         string table associated with this file.  We use that info
         to know how to relocate the *next* file's string table indices.  */
 
-      if (stabp->n_type == N_UNDF)
+      if (type == N_UNDF)
        {
          file_string_table_offset = next_file_string_table_offset;
-         next_file_string_table_offset += stabp->n_value;
+         next_file_string_table_offset += value;
        }
       else
        {
          /* Using the (possibly updated) string table offset, print the
             string (if any) associated with this symbol.  */
 
-         if ((stabp->n_strx + file_string_table_offset) < stabstr_size)
-           printf (" %s", &strtab[stabp->n_strx + file_string_table_offset]);
+         if ((strx + file_string_table_offset) < stabstr_size)
+           printf (" %s", &strtab[strx + file_string_table_offset]);
          else
            printf (" *");
        }
@@ -1321,7 +1356,7 @@ print_section_stabs (abfd, stabsect_name, strsect_name)
   printf ("\n\n");
 }
 
-void
+static void
 dump_section_stabs (abfd, stabsect_name, strsect_name)
      bfd *abfd;
      char *stabsect_name;
@@ -1335,8 +1370,15 @@ dump_section_stabs (abfd, stabsect_name, strsect_name)
        s != NULL;
        s = s->next)
     {
-      if (strncmp (stabsect_name, s->name, strlen (stabsect_name)) == 0
-         && strncmp (strsect_name, s->name, strlen (strsect_name)) != 0)
+      int len;
+
+      len = strlen (stabsect_name);
+
+/* If the prefix matches, and the files section name ends with a nul or a digit,
+   then we match.  Ie: we want either an exact match or a a section followed by 
+   a number.  */
+      if (strncmp (stabsect_name, s->name, len) == 0
+         && (s->name[len] == '\000' || isdigit (s->name[len])))
        {
          if (read_section_stabs (abfd, s->name, strsect_name))
            {
@@ -1381,6 +1423,7 @@ bfd *abfd;
 {
   bfd_print_private_bfd_data (abfd, stdout);
 }
+
 static void
 display_bfd (abfd)
      bfd *abfd;
@@ -1679,7 +1722,7 @@ dump_relocs (abfd)
          else
            {
              printf ("\n");
-             dump_reloc_set (abfd, relpp, relcount);
+             dump_reloc_set (abfd, a, relpp, relcount);
              printf ("\n\n");
            }
          free (relpp);
@@ -1718,7 +1761,7 @@ dump_dynamic_relocs (abfd)
       else
        {
          printf ("\n");
-         dump_reloc_set (abfd, relpp, relcount);
+         dump_reloc_set (abfd, (asection *) NULL, relpp, relcount);
          printf ("\n\n");
        }
       free (relpp);
@@ -1726,12 +1769,15 @@ dump_dynamic_relocs (abfd)
 }
 
 static void
-dump_reloc_set (abfd, relpp, relcount)
+dump_reloc_set (abfd, sec, relpp, relcount)
      bfd *abfd;
+     asection *sec;
      arelent **relpp;
      long relcount;
 {
   arelent **p;
+  char *last_filename, *last_functionname;
+  unsigned int last_line;
 
   /* Get column headers lined up reasonably.  */
   {
@@ -1745,11 +1791,17 @@ dump_reloc_set (abfd, relpp, relcount)
     printf ("OFFSET %*s TYPE %*s VALUE \n", width, "", 12, "");
   }
 
+  last_filename = NULL;
+  last_functionname = NULL;
+  last_line = 0;
+
   for (p = relpp; relcount && *p != (arelent *) NULL; p++, relcount--)
     {
       arelent *q = *p;
-      CONST char *sym_name;
-      CONST char *section_name;
+      const char *filename, *functionname;
+      unsigned int line;
+      const char *sym_name;
+      const char *section_name;
 
       if (start_address != (bfd_vma) -1
          && q->address < start_address)
@@ -1758,6 +1810,37 @@ dump_reloc_set (abfd, relpp, relcount)
          && q->address > stop_address)
        continue;
 
+      if (with_line_numbers
+         && sec != NULL
+         && bfd_find_nearest_line (abfd, sec, syms, q->address,
+                                   &filename, &functionname, &line))
+       {
+         if (functionname != NULL
+             && (last_functionname == NULL
+                 || strcmp (functionname, last_functionname) != 0))
+           {
+             printf ("%s():\n", functionname);
+             if (last_functionname != NULL)
+               free (last_functionname);
+             last_functionname = xstrdup (functionname);
+           }
+         if (line > 0
+             && (line != last_line
+                 || (filename != NULL
+                     && last_filename != NULL
+                     && strcmp (filename, last_filename) != 0)))
+           {
+             printf ("%s:%u\n", filename == NULL ? "???" : filename, line);
+             last_line = line;
+             if (last_filename != NULL)
+               free (last_filename);
+             if (filename == NULL)
+               last_filename = NULL;
+             else
+               last_filename = xstrdup (filename);
+           }
+       }
+
       if (q->sym_ptr_ptr && *q->sym_ptr_ptr)
        {
          sym_name = (*(q->sym_ptr_ptr))->name;
@@ -1989,8 +2072,8 @@ main (argc, argv)
 
   bfd_init ();
 
-  while ((c = getopt_long (argc, argv, "pib:m:VdDlfahrRtTxsSj:w", long_options,
-                          (int *) 0))
+  while ((c = getopt_long (argc, argv, "pib:m:VdDlfahrRtTxsSj:wE:",
+                          long_options, (int *) 0))
         != EOF)
     {
       if (c != 'l' && c != OPTION_START_ADDRESS && c != OPTION_STOP_ADDRESS)
@@ -2073,6 +2156,29 @@ main (argc, argv)
        case OPTION_STOP_ADDRESS:
          stop_address = parse_vma (optarg, "--stop-address");
          break;
+       case 'E':
+         if (strcmp (optarg, "B") == 0)
+           endian = BFD_ENDIAN_BIG;
+         else if (strcmp (optarg, "L") == 0)
+           endian = BFD_ENDIAN_LITTLE;
+         else
+           {
+             fprintf (stderr, "%s: unrecognized -E option\n", program_name);
+             usage (stderr, 1);
+           }
+         break;
+       case OPTION_ENDIAN:
+         if (strncmp (optarg, "big", strlen (optarg)) == 0)
+           endian = BFD_ENDIAN_BIG;
+         else if (strncmp (optarg, "little", strlen (optarg)) == 0)
+           endian = BFD_ENDIAN_LITTLE;
+         else
+           {
+             fprintf (stderr, "%s: unrecognized --endian type `%s'\n",
+                     program_name, optarg);
+             usage (stderr, 1);
+           }
+         break;
        default:
          usage (stderr, 1);
        }