readelf group errors/warnings
[external/binutils.git] / binutils / objdump.c
index 7d0c6a4..7381e48 100644 (file)
@@ -382,10 +382,10 @@ nonfatal (const char *msg)
 static const char *
 sanitize_string (const char * in)
 {
-  static char *        buffer = NULL;
-  static unsigned int  buffer_len = 0;
-  const char *         original = in;
-  char *               out;
+  static char *  buffer = NULL;
+  static size_t  buffer_len = 0;
+  const char *   original = in;
+  char *         out;
 
   /* Paranoia.  */
   if (in == NULL)
@@ -987,6 +987,30 @@ objdump_print_symname (bfd *abfd, struct disassemble_info *inf,
     free (alloc);
 }
 
+static inline bfd_boolean
+sym_ok (bfd_boolean               want_section,
+       bfd *                     abfd ATTRIBUTE_UNUSED,
+       long                      place,
+       asection *                sec,
+       struct disassemble_info * inf)
+{
+  if (want_section)
+    {
+      /* Note - we cannot just compare section pointers because they could
+        be different, but the same...  Ie the symbol that we are trying to
+        find could have come from a separate debug info file.  Under such
+        circumstances the symbol will be associated with a section in the
+        debug info file, whilst the section we want is in a normal file.
+        So the section pointers will be different, but the section names
+        will be the same.  */
+      if (strcmp (bfd_section_name (abfd, sorted_syms[place]->section),
+                 bfd_section_name (abfd, sec)) != 0)
+       return FALSE;
+    }
+
+  return inf->symbol_is_valid (sorted_syms[place], inf);
+}
+
 /* Locate a symbol given a bfd and a section (from INFO->application_data),
    and a VMA.  If INFO->application_data->require_sec is TRUE, then always
    require the symbol to be in the section.  Returns NULL if there is no
@@ -1062,8 +1086,7 @@ find_symbol_for_address (bfd_vma vma,
         && (bfd_asymbol_value (sorted_syms[min])
             == bfd_asymbol_value (sorted_syms[thisplace])))
     {
-      if (sorted_syms[min]->section == sec
-         && inf->symbol_is_valid (sorted_syms[min], inf))
+      if (sym_ok (TRUE, abfd, min, sec, inf))
        {
          thisplace = min;
 
@@ -1090,16 +1113,15 @@ find_symbol_for_address (bfd_vma vma,
                      && vma >= bfd_get_section_vma (abfd, sec)
                      && vma < (bfd_get_section_vma (abfd, sec)
                                + bfd_section_size (abfd, sec) / opb)));
-  if ((sorted_syms[thisplace]->section != sec && want_section)
-      || ! inf->symbol_is_valid (sorted_syms[thisplace], inf))
+  
+  if (! sym_ok (want_section, abfd, thisplace, sec, inf))
     {
       long i;
       long newplace = sorted_symcount;
 
       for (i = min - 1; i >= 0; i--)
        {
-         if ((sorted_syms[i]->section == sec || !want_section)
-             && inf->symbol_is_valid (sorted_syms[i], inf))
+         if (sym_ok (want_section, abfd, i, sec, inf))
            {
              if (newplace == sorted_symcount)
                newplace = i;
@@ -1122,8 +1144,7 @@ find_symbol_for_address (bfd_vma vma,
             Look for one with a larger value.  */
          for (i = thisplace + 1; i < sorted_symcount; i++)
            {
-             if ((sorted_syms[i]->section == sec || !want_section)
-                 && inf->symbol_is_valid (sorted_syms[i], inf))
+             if (sym_ok (want_section, abfd, i, sec, inf))
                {
                  thisplace = i;
                  break;
@@ -1131,8 +1152,7 @@ find_symbol_for_address (bfd_vma vma,
            }
        }
 
-      if ((sorted_syms[thisplace]->section != sec && want_section)
-         || ! inf->symbol_is_valid (sorted_syms[thisplace], inf))
+      if (! sym_ok (want_section, abfd, thisplace, sec, inf))
        /* There is no suitable symbol.  */
        return NULL;
     }
@@ -1926,7 +1946,8 @@ disassemble_bytes (struct disassemble_info * inf,
              inf->stream = &sfile;
              inf->bytes_per_line = 0;
              inf->bytes_per_chunk = 0;
-             inf->flags = disassemble_all ? DISASSEMBLE_DATA : 0;
+             inf->flags = ((disassemble_all ? DISASSEMBLE_DATA : 0)
+                           | (wide_output ? WIDE_OUTPUT : 0));
              if (machine)
                inf->flags |= USER_SPECIFIED_MACHINE_TYPE;
 
@@ -1971,6 +1992,7 @@ disassemble_bytes (struct disassemble_info * inf,
                   disassembling code of course, and when -D is in effect.  */
                inf->stop_vma = section->vma + stop_offset;
 
+             inf->stop_offset = stop_offset;
              octets = (*disassemble_fn) (section->vma + addr_offset, inf);
 
              inf->stop_vma = 0;
@@ -2460,7 +2482,7 @@ disassemble_section (bfd *abfd, asection *section, void *inf)
       else
        {
 #define is_valid_next_sym(SYM) \
-  ((SYM)->section == section \
+  (strcmp (bfd_section_name (abfd, (SYM)->section), bfd_section_name (abfd, section)) == 0 \
    && (bfd_asymbol_value (SYM) > bfd_asymbol_value (sym)) \
    && pinfo->symbol_is_valid (SYM, pinfo))
 
@@ -2659,6 +2681,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
   bfd *abfd = (bfd *) file;
   bfd_byte *contents;
   bfd_size_type amt;
+  size_t alloced;
 
   if (section->start != NULL)
     {
@@ -2674,8 +2697,9 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
   section->address = bfd_get_section_vma (abfd, sec);
   section->user_data = sec;
   section->size = bfd_get_section_size (sec);
-  amt = section->size + 1;
-  if (amt == 0 || amt > bfd_get_file_size (abfd))
+  /* PR 24360: On 32-bit hosts sizeof (size_t) < sizeof (bfd_size_type). */
+  alloced = amt = section->size + 1;
+  if (alloced != amt || alloced == 0)
     {
       section->start = NULL;
       free_debug_section (debug);
@@ -2684,7 +2708,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
              (unsigned long long) section->size);
       return FALSE;
     }
-  section->start = contents = malloc (amt);
+  section->start = contents = malloc (alloced);
   if (section->start == NULL
       || !bfd_get_full_section_contents (abfd, sec, &contents))
     {
@@ -2882,24 +2906,18 @@ dump_dwarf_section (bfd *abfd, asection *section,
 static void
 dump_dwarf (bfd *abfd)
 {
-  bfd * separates;
-
-  is_relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
-
-  eh_addr_size = bfd_arch_bits_per_address (abfd) / 8;
-
-  if (bfd_big_endian (abfd))
-    byte_get = byte_get_big_endian;
-  else if (bfd_little_endian (abfd))
-    byte_get = byte_get_little_endian;
-  else
-    /* PR 17512: file: objdump-s-endless-loop.tekhex.  */
+  /* The byte_get pointer should have been set at the start of dump_bfd().  */
+  if (byte_get == NULL)
     {
       warn (_("File %s does not contain any dwarf debug information\n"),
            bfd_get_filename (abfd));
       return;
     }
 
+  is_relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
+
+  eh_addr_size = bfd_arch_bits_per_address (abfd) / 8;
+
   switch (bfd_get_arch (abfd))
     {
     case bfd_arch_i386:
@@ -2946,14 +2964,7 @@ dump_dwarf (bfd *abfd)
       break;
     }
 
-  separates = load_separate_debug_file (abfd, bfd_get_filename (abfd));
-
   bfd_map_over_sections (abfd, dump_dwarf_section, NULL);
-
-  if (separates)
-    bfd_map_over_sections (separates, dump_dwarf_section, NULL);
-
-  free_debug_memory ();
 }
 \f
 /* Read ABFD's stabs section STABSECT_NAME, and return a pointer to
@@ -3622,7 +3633,7 @@ dump_relocs_in_section (bfd *abfd,
                        asection *section,
                        void *dummy ATTRIBUTE_UNUSED)
 {
-  arelent **relpp;
+  arelent **relpp = NULL;
   long relcount;
   long relsize;
 
@@ -3633,47 +3644,28 @@ dump_relocs_in_section (bfd *abfd,
       || ((section->flags & SEC_RELOC) == 0))
     return;
 
-  relsize = bfd_get_reloc_upper_bound (abfd, section);
-  if (relsize < 0)
-    bfd_fatal (bfd_get_filename (abfd));
-
   printf ("RELOCATION RECORDS FOR [%s]:", sanitize_string (section->name));
 
+  relsize = bfd_get_reloc_upper_bound (abfd, section);
   if (relsize == 0)
     {
       printf (" (none)\n\n");
       return;
     }
 
-  if ((bfd_get_file_flags (abfd) & (BFD_IN_MEMORY | BFD_LINKER_CREATED)) == 0
-      && (/* Check that the size of the relocs is reasonable.  Note that some
-            file formats, eg aout, can have relocs whose internal size is
-            larger than their external size, thus we check the size divided
-            by four against the file size.  See PR 23931 for an example of
-            this.  */
-         ((ufile_ptr) (relsize / 4) > bfd_get_file_size (abfd))
-         /* Also check the section's reloc count since if this is negative
-            (or very large) the computation in bfd_get_reloc_upper_bound
-            may have resulted in returning a small, positive integer.
-            See PR 22508 for a reproducer.
-
-            Note - we check against file size rather than section size as
-            it is possible for there to be more relocs that apply to a
-            section than there are bytes in that section.  */
-         || (section->reloc_count > bfd_get_file_size (abfd))))
+  if (relsize < 0)
+    relcount = relsize;
+  else
     {
-      printf (" (too many: %#x relocs)\n", section->reloc_count);
-      bfd_set_error (bfd_error_file_truncated);
-      bfd_fatal (bfd_get_filename (abfd));
+      relpp = (arelent **) xmalloc (relsize);
+      relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms);
     }
 
-  relpp = (arelent **) xmalloc (relsize);
-  relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms);
-
   if (relcount < 0)
     {
       printf ("\n");
-      non_fatal (_("failed to read relocs in: %s"), sanitize_string (bfd_get_filename (abfd)));
+      non_fatal (_("failed to read relocs in: %s"),
+                sanitize_string (bfd_get_filename (abfd)));
       bfd_fatal (_("error message was"));
     }
   else if (relcount == 0)
@@ -3758,11 +3750,67 @@ adjust_addresses (bfd *abfd ATTRIBUTE_UNUSED,
     }
 }
 
+/* Return the sign-extended form of an ARCH_SIZE sized VMA.  */
+
+static bfd_vma
+sign_extend_address (bfd *abfd ATTRIBUTE_UNUSED,
+                    bfd_vma vma,
+                    unsigned arch_size)
+{
+  bfd_vma mask;
+  mask = (bfd_vma) 1 << (arch_size - 1);
+  return (((vma & ((mask << 1) - 1)) ^ mask) - mask);
+}
+
 /* Dump selected contents of ABFD.  */
 
 static void
-dump_bfd (bfd *abfd)
+dump_bfd (bfd *abfd, bfd_boolean is_mainfile)
 {
+  const struct elf_backend_data * bed;
+
+  if (bfd_big_endian (abfd))
+    byte_get = byte_get_big_endian;
+  else if (bfd_little_endian (abfd))
+    byte_get = byte_get_little_endian;
+  else
+    byte_get = NULL;
+
+  /* Load any separate debug information files.
+     We do this now and without checking do_follow_links because separate
+     debug info files may contain symbol tables that we will need when
+     displaying information about the main file.  Any memory allocated by
+     load_separate_debug_files will be released when we call
+     free_debug_memory below.
+     
+     The test on is_mainfile is there because the chain of separate debug
+     info files is a global variable shared by all invocations of dump_bfd.  */
+  if (is_mainfile)
+    {
+      load_separate_debug_files (abfd, bfd_get_filename (abfd));
+
+      /* If asked to do so, recursively dump the separate files.  */
+      if (do_follow_links)
+       {
+         separate_info * i;
+
+         for (i = first_separate_info; i != NULL; i = i->next)
+           dump_bfd (i->handle, FALSE);
+       }
+    }
+
+  /* Adjust user-specified start and stop limits for targets that use
+     signed addresses.  */
+  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+      && (bed = get_elf_backend_data (abfd)) != NULL
+      && bed->sign_extend_vma)
+    {
+      start_address = sign_extend_address (abfd, start_address,
+                                          bed->s->arch_size);
+      stop_address = sign_extend_address (abfd, stop_address,
+                                         bed->s->arch_size);
+    }
+
   /* If we are adjusting section VMA's, change them all now.  Changing
      the BFD information is a hack.  However, we must do it, or
      bfd_find_nearest_line will not do the right thing.  */
@@ -3792,7 +3840,40 @@ dump_bfd (bfd *abfd)
       || disassemble
       || dump_debugging
       || dump_dwarf_section_info)
-    syms = slurp_symtab (abfd);
+    {
+      syms = slurp_symtab (abfd);
+
+      /* If following links, load any symbol tables from the linked files as well.  */
+      if (do_follow_links && is_mainfile)
+       {
+         separate_info * i;
+
+         for (i = first_separate_info; i != NULL; i = i->next)
+           {
+             asymbol **  extra_syms;
+             long        old_symcount = symcount;
+             
+             extra_syms = slurp_symtab (i->handle);
+
+             if (extra_syms)
+               {
+                 if (old_symcount == 0)
+                   {
+                     syms = extra_syms;
+                   }
+                 else
+                   {
+                     syms = xrealloc (syms, (symcount + old_symcount) * sizeof (asymbol *));
+                     memcpy (syms + old_symcount,
+                             extra_syms,
+                             symcount * sizeof (asymbol *));
+                   }
+               }
+
+             symcount += old_symcount;
+           }
+       }
+    }
 
   if (dump_section_headers)
     dump_headers (abfd);
@@ -3800,6 +3881,7 @@ dump_bfd (bfd *abfd)
   if (dump_dynamic_symtab || dump_dynamic_reloc_info
       || (disassemble && bfd_get_dynamic_symtab_upper_bound (abfd) > 0))
     dynsyms = slurp_dynamic_symtab (abfd);
+
   if (disassemble)
     {
       synthcount = bfd_get_synthetic_symtab (abfd, symcount, syms,
@@ -3873,6 +3955,9 @@ dump_bfd (bfd *abfd)
   symcount = 0;
   dynsymcount = 0;
   synthcount = 0;
+
+  if (is_mainfile)
+    free_debug_memory ();
 }
 
 static void
@@ -3882,7 +3967,7 @@ display_object_bfd (bfd *abfd)
 
   if (bfd_check_format_matches (abfd, bfd_object, &matching))
     {
-      dump_bfd (abfd);
+      dump_bfd (abfd, TRUE);
       return;
     }
 
@@ -3902,7 +3987,7 @@ display_object_bfd (bfd *abfd)
 
   if (bfd_check_format_matches (abfd, bfd_core, &matching))
     {
-      dump_bfd (abfd);
+      dump_bfd (abfd, TRUE);
       return;
     }