PR gas/3800
authorNick Clifton <nickc@redhat.com>
Tue, 6 Feb 2007 15:15:13 +0000 (15:15 +0000)
committerNick Clifton <nickc@redhat.com>
Tue, 6 Feb 2007 15:15:13 +0000 (15:15 +0000)
* readelf.c: Include elf/h8.h twice.  The first time in order to get the reloc
  numbers, the second time in order to get the reloc decoder function.
  (dump_section): Tell the user if the section being displayed has unprocessed
  relocs associated with it.
  (get_reloc_size): New function - returns the size of a reloc.
  (debug_apply_rela_addends): Use get_reloc_size().
* dwarf.c (read_and_display_attr_value): Extend number of languages known for
  the DW_AT_language attribute.
  (process_debug_info): Display the attribute offset before decoding the
  attribute, in case there are problems.

binutils/ChangeLog
binutils/dwarf.c
binutils/readelf.c

index cd39f65..b4f78a0 100644 (file)
@@ -1,3 +1,18 @@
+2007-02-06  Nick Clifton  <nickc@redhat.com>
+
+       PR gas/3800
+       * readelf.c: Include elf/h8.h twice.  The first time in order to
+       get the reloc numbers, the second time in order to get the reloc
+       decoder function.
+       (dump_section): Tell the user if the section being displayed has
+       unprocessed relocs associated with it.
+       (get_reloc_size): New function - returns the size of a reloc.
+       (debug_apply_rela_addends): Use get_reloc_size().
+       * dwarf.c (read_and_display_attr_value): Extend number of
+       languages known for the DW_AT_language attribute.
+       (process_debug_info): Display the attribute offset before decoding
+       the attribute, in case there are problems.
+
 2007-02-05  Dave Brolley  <brolley@redhat.com>
 
        * readelf.c (dump_relocations): Don't check for
index fe75b63..ad709b9 100644 (file)
@@ -1,5 +1,5 @@
 /* dwarf.c -- display DWARF contents of a BFD binary file
-   Copyright 2005, 2006
+   Copyright 2005, 2006, 2007
    Free Software Foundation, Inc.
 
    This file is part of GNU Binutils.
@@ -1213,26 +1213,37 @@ read_and_display_attr_value (unsigned long attribute,
     case DW_AT_language:
       switch (uvalue)
        {
-       case DW_LANG_C:                 printf ("(non-ANSI C)"); break;
+         /* Ordered by the numeric value of these constants.  */
        case DW_LANG_C89:               printf ("(ANSI C)"); break;
+       case DW_LANG_C:                 printf ("(non-ANSI C)"); break;
+       case DW_LANG_Ada83:             printf ("(Ada)"); break;
        case DW_LANG_C_plus_plus:       printf ("(C++)"); break;
+       case DW_LANG_Cobol74:           printf ("(Cobol 74)"); break;
+       case DW_LANG_Cobol85:           printf ("(Cobol 85)"); break;
        case DW_LANG_Fortran77:         printf ("(FORTRAN 77)"); break;
        case DW_LANG_Fortran90:         printf ("(Fortran 90)"); break;
-       case DW_LANG_Modula2:           printf ("(Modula 2)"); break;
        case DW_LANG_Pascal83:          printf ("(ANSI Pascal)"); break;
-       case DW_LANG_Ada83:             printf ("(Ada)"); break;
-       case DW_LANG_Cobol74:           printf ("(Cobol 74)"); break;
-       case DW_LANG_Cobol85:           printf ("(Cobol 85)"); break;
+       case DW_LANG_Modula2:           printf ("(Modula 2)"); break;
          /* DWARF 2.1 values.  */
+       case DW_LANG_Java:              printf ("(Java)"); break;
        case DW_LANG_C99:               printf ("(ANSI C99)"); break;
        case DW_LANG_Ada95:             printf ("(ADA 95)"); break;
        case DW_LANG_Fortran95:         printf ("(Fortran 95)"); break;
+         /* DWARF 3 values.  */
+       case DW_LANG_PLI:               printf ("(PLI)"); break;
+       case DW_LANG_ObjC:              printf ("(Objective C)"); break;
+       case DW_LANG_ObjC_plus_plus:    printf ("(Objective C++)"); break;
+       case DW_LANG_UPC:               printf ("(Unified Parallel C)"); break;
+       case DW_LANG_D:                 printf ("(D)"); break;
          /* MIPS extension.  */
        case DW_LANG_Mips_Assembler:    printf ("(MIPS assembler)"); break;
          /* UPC extension.  */
        case DW_LANG_Upc:               printf ("(Unified Parallel C)"); break;
        default:
-         printf ("(Unknown: %lx)", uvalue);
+         if (uvalue >= DW_LANG_lo_user && uvalue <= DW_LANG_hi_user)
+           printf ("(implementation defined: %lx)", uvalue);
+         else
+           printf ("(Unknown: %lx)", uvalue);
          break;
        }
       break;
@@ -1684,6 +1695,13 @@ process_debug_info (struct dwarf_section *section, void *file,
              continue;
            }
 
+         if (!do_loc)
+           printf (_(" <%d><%lx>: Abbrev Number: %lu"),
+                   level,
+                   (unsigned long) (tags - section_begin
+                                    - bytes_read),
+                   abbrev_number);
          /* Scan through the abbreviation list until we reach the
             correct entry.  */
          for (entry = first_abbrev;
@@ -1693,18 +1711,18 @@ process_debug_info (struct dwarf_section *section, void *file,
 
          if (entry == NULL)
            {
+             if (!do_loc)
+               {
+                 printf ("\n");
+                 fflush (stdout);
+               }
              warn (_("Unable to locate entry %lu in the abbreviation table\n"),
                    abbrev_number);
              return 0;
            }
 
          if (!do_loc)
-           printf (_(" <%d><%lx>: Abbrev Number: %lu (%s)\n"),
-                   level,
-                   (unsigned long) (tags - section_begin
-                                    - bytes_read),
-                   abbrev_number,
-                   get_TAG_name (entry->tag));
+           printf (_(" (%s)\n"), get_TAG_name (entry->tag));
  
          switch (entry->tag)
            {
@@ -1724,14 +1742,20 @@ process_debug_info (struct dwarf_section *section, void *file,
            }
 
          for (attr = entry->first_attr; attr; attr = attr->next)
-           tags = read_and_display_attr (attr->attribute,
-                                         attr->form,
-                                         tags, cu_offset,
-                                         compunit.cu_pointer_size,
-                                         offset_size,
-                                         compunit.cu_version,
-                                         &debug_information [unit],
-                                         do_loc);
+           {
+             if (! do_loc)
+               /* Show the offset from where the tag was extracted.  */
+               printf ("  <%2lx>", tags - section_begin);
+
+             tags = read_and_display_attr (attr->attribute,
+                                           attr->form,
+                                           tags, cu_offset,
+                                           compunit.cu_pointer_size,
+                                           offset_size,
+                                           compunit.cu_version,
+                                           &debug_information [unit],
+                                           do_loc);
+           }
  
          if (entry->children)
            ++level;
@@ -2507,7 +2531,6 @@ display_debug_str (struct dwarf_section *section,
   return 1;
 }
 
-
 static int
 display_debug_info (struct dwarf_section *section, void *file)
 {
index f1f849f..b1b5c5c 100644 (file)
@@ -1,5 +1,5 @@
 /* readelf.c -- display contents of an ELF format file
-   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
    Originally developed by Eric Youngdale <eric@andante.jic.com>
 #include "elf/external.h"
 #include "elf/internal.h"
 
+
+/* Included here, before RELOC_MACROS_GEN_FUNC is defined, so that
+   we can obtain the H8 reloc numbers.  We need these for the
+   get_reloc_size() function.  We include h8.h again after defining
+   RELOC_MACROS_GEN_FUNC so that we get the naming function as well.  */
+
+#include "elf/h8.h"
+#undef _ELF_H8_H
+
+/* Undo the effects of #including reloc-macros.h.  */
+
+#undef START_RELOC_NUMBERS
+#undef RELOC_NUMBER
+#undef FAKE_RELOC
+#undef EMPTY_RELOC
+#undef END_RELOC_NUMBERS
+#undef _RELOC_MACROS_H
+
 /* The following headers use the elf/reloc-macros.h file to
    automatically generate relocation recognition functions
    such as elf_mips_reloc_type()  */
@@ -7644,6 +7662,7 @@ disassemble_section (Elf_Internal_Shdr *section, FILE *file)
 static int
 dump_section (Elf_Internal_Shdr *section, FILE *file)
 {
+  Elf_Internal_Shdr *relsec;
   bfd_size_type bytes;
   bfd_vma addr;
   unsigned char *data;
@@ -7667,6 +7686,26 @@ dump_section (Elf_Internal_Shdr *section, FILE *file)
   if (!start)
     return 0;
 
+  /* If the section being dumped has relocations against it the user might
+     be expecting these relocations to have been applied.  Check for this
+     case and issue a warning message in order to avoid confusion.
+     FIXME: Maybe we ought to have an option that dumps a section with
+     relocs applied ?  */
+  for (relsec = section_headers;
+       relsec < section_headers + elf_header.e_shnum;
+       ++relsec)
+    {
+      if (relsec->sh_type != SHT_RELA
+         || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
+         || SECTION_HEADER (relsec->sh_info) != section
+         || relsec->sh_size == 0
+         || SECTION_HEADER_INDEX (relsec->sh_link) >= elf_header.e_shnum)
+       continue;
+
+      printf (_(" NOTE: This section has relocations against it, but these have NOT been applied to this dump.\n"));
+      break;
+    }
+  
   data = start;
 
   while (bytes)
@@ -7708,9 +7747,47 @@ dump_section (Elf_Internal_Shdr *section, FILE *file)
 
   free (start);
 
+  putchar ('\n');
   return 1;
 }
 
+/* Return the number of bytes affected by a given reloc.
+   This information is architecture and reloc dependent.
+   Returns 4 by default, although this is not always correct.
+   It should return 0 if a decision cannot be made.
+   FIXME: This is not the correct way to solve this problem.
+   The proper way is to have target specific reloc sizing functions
+   created by the reloc-macros.h header, in the same way that it
+   already creates the reloc naming functions.  */
+
+static unsigned int
+get_reloc_size (Elf_Internal_Rela * reloc)
+{
+  switch (elf_header.e_machine)
+    {
+    case EM_H8S:
+    case EM_H8_300:
+    case EM_H8_300H:
+    case EM_H8_500:
+      switch (ELF32_R_TYPE (reloc->r_info))
+       {
+         /* PR gas/3800 - without this information we do not correctly
+            decode the debug information generated by the h8300 assembler.  */
+       case R_H8_DIR16:
+         return 2;
+       default:
+         return 4;
+       }
+    default:
+      /* FIXME: We need to extend this switch statement to cope with other
+        architecture's relocs.  (When those relocs are used against debug
+        sections, and when their size is not 4).  But see the multiple
+        inclusions of <elf/h8.h> for an example of the hoops that we need
+        to jump through in order to obtain the reloc numbers.  */
+      return 4;
+    }
+}
+
 /* Apply addends of RELA relocations.  */
 
 static int
@@ -7720,15 +7797,10 @@ debug_apply_rela_addends (void *file,
 {
   Elf_Internal_Shdr *relsec;
   unsigned char *end = start + section->sh_size;
-  /* FIXME: The relocation field size is relocation type dependent.  */
-  unsigned int reloc_size = 4;
 
   if (!is_relocatable)
     return 1;
 
-  if (section->sh_size < reloc_size)
-    return 1;
-
   for (relsec = section_headers;
        relsec < section_headers + elf_header.e_shnum;
        ++relsec)
@@ -7756,6 +7828,16 @@ debug_apply_rela_addends (void *file,
       for (rp = rela; rp < rela + nrelas; ++rp)
        {
          unsigned char *loc;
+         unsigned int reloc_size;
+
+         reloc_size = get_reloc_size (rp);
+         if (reloc_size == 0)
+           {
+             warn (_("skipping relocation of unknown size against offset 0x%lx in section %s\n"),
+                   (unsigned long) rp->r_offset,
+                   SECTION_NAME (section));
+             continue;
+           }
 
          loc = start + rp->r_offset;
          if ((loc + reloc_size) > end)