Better coping with different reloc types.
authorNick Clifton <nickc@redhat.com>
Fri, 28 May 1999 10:14:11 +0000 (10:14 +0000)
committerNick Clifton <nickc@redhat.com>
Fri, 28 May 1999 10:14:11 +0000 (10:14 +0000)
binutils/ChangeLog
binutils/readelf.c

index 627dad7..eddefe4 100644 (file)
@@ -1,3 +1,13 @@
+1999-05-28  Nick Clifton  <nickc@cygnus.com>
+
+       * readelf.c (dump_relocations): Add extra parameter: is_rela to
+       specify the kind of relocations to be dumped.  Call guess_is_rela
+       if this parameter has a value of UNKNOWN.
+       (guess_is_rela): New function:  Guess the kind of reloc being used
+       baced on the machine number.
+       (process_relocs): Determine type of reloc before calling
+       dump_relocations.
+
 1999-05-28  Ian Lance Taylor  <ian@zembu.com>
 
        * readelf.c: Include "elf/i960.h".
index 520344c..d2e1552 100644 (file)
@@ -118,7 +118,7 @@ unsigned int                num_dump_sects = 0;
 static unsigned long (*   byte_get)                   PARAMS ((unsigned char *, int));
 static const char *       get_mips_dynamic_type       PARAMS ((unsigned long type));
 static const char *       get_dynamic_type            PARAMS ((unsigned long type));
-static int                dump_relocations            PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *, char *));
+static int                dump_relocations            PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *, char *, int));
 static char *             get_file_type               PARAMS ((unsigned e_type));
 static char *             get_machine_name            PARAMS ((unsigned e_machine));
 static char *             get_machine_data            PARAMS ((unsigned e_data));
@@ -174,9 +174,16 @@ static void                  request_dump                PARAMS ((unsigned int, char));
 static const char *       get_elf_class               PARAMS ((unsigned char));
 static const char *       get_data_encoding           PARAMS ((unsigned char));
 static const char *       get_osabi_name              PARAMS ((unsigned char));
+static int               guess_is_rela               PARAMS ((unsigned long));
 
 typedef int Elf32_Word;
 
+#ifndef TRUE
+#define TRUE     1
+#define FALSE    0
+#endif
+#define UNKNOWN -1
+
 #define SECTION_NAME(X)        (string_table + (X)->sh_name)
 
 #define DT_VERSIONTAGIDX(tag)  (DT_VERNEEDNUM - (tag)) /* Reverse order! */
@@ -329,24 +336,12 @@ byte_get_big_endian (field, size)
 }
 
 
-/* Display the contents of the relocation data
-   found at the specified offset.  */
+/* Guess the relocation sized based on the sized commonly used by the specific machine.  */
 static int
-dump_relocations (file, rel_offset, rel_size, symtab, strtab)
-     FILE *                 file;
-     unsigned long          rel_offset;
-     unsigned long          rel_size;
-     Elf_Internal_Sym *     symtab;
-     char *                 strtab;
+guess_is_rela (e_machine)
+     unsigned long e_machine;
 {
-  unsigned int        i;
-  int                 is_rela;
-  Elf_Internal_Rel *  rels;
-  Elf_Internal_Rela * relas;
-
-
-  /* Compute number of relocations and read them in.  */
-  switch (elf_header.e_machine)
+  switch (e_machine)
     {
       /* Targets that use REL relocations.  */
     case EM_ARM:
@@ -357,30 +352,8 @@ dump_relocations (file, rel_offset, rel_size, symtab, strtab)
     case EM_CYGNUS_D10V:
     case EM_MIPS:
     case EM_MIPS_RS4_BE:
-      {
-       Elf32_External_Rel * erels;
-
-       GET_DATA_ALLOC (rel_offset, rel_size, erels,
-                       Elf32_External_Rel *, "relocs");
-
-       rel_size = rel_size / sizeof (Elf32_External_Rel);
-
-       rels = (Elf_Internal_Rel *) malloc (rel_size *
-                                           sizeof (Elf_Internal_Rel));
-
-       for (i = 0; i < rel_size; i++)
-         {
-           rels[i].r_offset = BYTE_GET (erels[i].r_offset);
-           rels[i].r_info   = BYTE_GET (erels[i].r_info);
-         }
-
-       free (erels);
-
-       is_rela = 0;
-       relas   = (Elf_Internal_Rela *) rels;
-      }
-    break;
-
+      return FALSE;
+      
       /* Targets that use RELA relocations.  */
     case EM_68K:
     case EM_SPARC:
@@ -390,37 +363,95 @@ dump_relocations (file, rel_offset, rel_size, symtab, strtab)
     case EM_CYGNUS_MN10200:
     case EM_CYGNUS_MN10300:
     case EM_CYGNUS_FR30:
+/* start-sanitize-venus */
+    case EM_CYGNUS_VENUS:
+/* end-sanitize-venus */
     case EM_SH:
     case EM_ALPHA:
     case EM_MCORE:
-      {
-       Elf32_External_Rela * erelas;
-
-       GET_DATA_ALLOC (rel_offset, rel_size, erelas,
-                       Elf32_External_Rela *, "relocs");
-
-       rel_size = rel_size / sizeof (Elf32_External_Rela);
-
-       relas = (Elf_Internal_Rela *) malloc (rel_size *
-                                             sizeof (Elf_Internal_Rela));
+      return TRUE;
+      
+    default:
+      warn (_("Don't know about relocations on this machine architecture\n"));
+      return FALSE;
+    }
+}
 
-       for (i = 0; i < rel_size; i++)
-         {
-           relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
-           relas[i].r_info   = BYTE_GET (erelas[i].r_info);
-           relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
-         }
+/* Display the contents of the relocation data
+   found at the specified offset.  */
+static int
+dump_relocations (file, rel_offset, rel_size, symtab, strtabm, is_rela)
+     FILE *                 file;
+     unsigned long          rel_offset;
+     unsigned long          rel_size;
+     Elf_Internal_Sym *     symtab;
+     char *                 strtab;
+     int                    is_rela;
+{
+  unsigned int        i;
+  Elf_Internal_Rel *  rels;
+  Elf_Internal_Rela * relas;
 
-       free (erelas);
+  
+  if (is_rela == UNKNOWN)
+    is_rela = guess_is_rela (elf_header.e_machine);
 
-       is_rela = 1;
-       rels    = (Elf_Internal_Rel *) relas;
-      }
-    break;
+  if (is_rela)
+    {
+      Elf32_External_Rela * erelas;
+      
+      GET_DATA_ALLOC (rel_offset, rel_size, erelas,
+                     Elf32_External_Rela *, "relocs");
+      
+      rel_size = rel_size / sizeof (Elf32_External_Rela);
+      
+      relas = (Elf_Internal_Rela *) malloc (rel_size *
+                                           sizeof (Elf_Internal_Rela));
+      
+      if (relas == NULL)
+       {
+         error(_("out of memory parsing relocs"));
+         return 0;
+       }
+      
+      for (i = 0; i < rel_size; i++)
+       {
+         relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
+         relas[i].r_info   = BYTE_GET (erelas[i].r_info);
+         relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
+       }
+      
+      free (erelas);
+      
+      rels = (Elf_Internal_Rel *) relas;
+    }
+  else
+    {
+      Elf32_External_Rel * erels;
+      unsigned long        saved_rel_size = rel_size;
 
-    default:
-      warn (_("Don't know about relocations on this machine architecture\n"));
-      return 0;
+      GET_DATA_ALLOC (rel_offset, rel_size, erels,
+                     Elf32_External_Rel *, "relocs");
+      
+      rel_size = rel_size / sizeof (Elf32_External_Rel);
+      
+      rels = (Elf_Internal_Rel *) malloc (rel_size *
+                                         sizeof (Elf_Internal_Rel));
+      if (rels == NULL)
+       {
+         error(_("out of memory parsing relocs"));
+         return 0;
+       }
+      
+      for (i = 0; i < rel_size; i++)
+       {
+         rels[i].r_offset = BYTE_GET (erels[i].r_offset);
+         rels[i].r_info   = BYTE_GET (erels[i].r_info);
+       }
+      
+      free (erels);
+      
+      relas = (Elf_Internal_Rela *) rels;
     }
 
   if (is_rela)
@@ -1827,6 +1858,8 @@ process_relocs (file)
 
   if (do_using_dynamic)
     {
+      int is_rela;
+
       rel_size   = 0;
       rel_offset = 0;
 
@@ -1834,16 +1867,19 @@ process_relocs (file)
        {
          rel_offset = dynamic_info[DT_REL];
          rel_size   = dynamic_info[DT_RELSZ];
+         is_rela    = FALSE;
        }
       else if (dynamic_info [DT_RELA])
        {
          rel_offset = dynamic_info[DT_RELA];
          rel_size   = dynamic_info[DT_RELASZ];
+         is_rela    = TRUE;
        }
       else if (dynamic_info[DT_JMPREL])
        {
          rel_offset = dynamic_info[DT_JMPREL];
          rel_size   = dynamic_info[DT_PLTRELSZ];
+         is_rela    = UNKNOWN;
        }
 
       if (rel_size)
@@ -1853,7 +1889,7 @@ process_relocs (file)
             rel_offset, rel_size);
 
          dump_relocations (file, rel_offset - loadaddr, rel_size,
-                           dynamic_symbols, dynamic_strings);
+                           dynamic_symbols, dynamic_strings, is_rela);
        }
       else
        printf (_("\nThere are no dynamic relocations in this file.\n"));
@@ -1881,13 +1917,26 @@ process_relocs (file)
              Elf32_Internal_Shdr * symsec;
              Elf_Internal_Sym *    symtab;
              char *                strtab;
-
+             int                   is_rela;
+             
              printf (_("\nRelocation section "));
 
              if (string_table == NULL)
-               printf ("%d", section->sh_name);
+               {
+                 printf ("%d", section->sh_name);
+                 is_rela = UNKNOWN;
+               }
              else
-               printf ("'%s'", SECTION_NAME (section));
+               {
+                 printf ("'%s'", SECTION_NAME (section));
+
+                 if (strncmp (".rela.", SECTION_NAME (section), 6) == 0)
+                   is_rela = TRUE;
+                 else if (strncmp (".rel.", SECTION_NAME (section), 5) == 0)
+                   is_rela = FALSE;
+                 else
+                   is_rela = UNKNOWN;
+               }
 
              printf (_(" at offset 0x%lx contains %lu entries:\n"),
                 rel_offset, (unsigned long) (rel_size / section->sh_entsize));
@@ -1905,7 +1954,7 @@ process_relocs (file)
              GET_DATA_ALLOC (strsec->sh_offset, strsec->sh_size, strtab,
                              char *, "string table");
 
-             dump_relocations (file, rel_offset, rel_size, symtab, strtab);
+             dump_relocations (file, rel_offset, rel_size, symtab, strtab, is_rela);
 
              free (strtab);
              free (symtab);