]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - binutils/readelf.c
2004-09-02 Paolo Bonzini <bonzini@gnu.org>
[thirdparty/binutils-gdb.git] / binutils / readelf.c
index fbafd2bac39b95532659622d424ff3c34c2ace29..eb9b451181ecdf20f776d4667d5e21a69010f9c3 100644 (file)
 #include "elf/vax.h"
 #include "elf/x86-64.h"
 #include "elf/xstormy16.h"
+#include "elf/crx.h"
 #include "elf/iq2000.h"
 #include "elf/xtensa.h"
 
@@ -678,6 +679,7 @@ guess_is_rela (unsigned long e_machine)
     case EM_MSP430:
     case EM_MSP430_OLD:
     case EM_XSTORMY16:
+    case EM_CRX:
     case EM_VAX:
     case EM_IP2K:
     case EM_IP2K_OLD:
@@ -1166,6 +1168,10 @@ dump_relocations (FILE *file,
          rtype = elf_xstormy16_reloc_type (type);
          break;
 
+       case EM_CRX:
+         rtype = elf_crx_reloc_type (type);
+         break;
+
        case EM_VAX:
          rtype = elf_vax_reloc_type (type);
          break;
@@ -1219,7 +1225,7 @@ dump_relocations (FILE *file,
 
                      if (psym->st_shndx < SHN_LORESERVE)
                        sec_index = psym->st_shndx;
-                     else if (psym->st_shndx > SHN_LORESERVE)
+                     else if (psym->st_shndx > SHN_HIRESERVE)
                        sec_index = psym->st_shndx - (SHN_HIRESERVE + 1
                                                      - SHN_LORESERVE);
 
@@ -1660,6 +1666,7 @@ get_machine_name (unsigned e_machine)
     case EM_XSTORMY16:         return "Sanyo Xstormy16 CPU core";
     case EM_OPENRISC:
     case EM_OR32:              return "OpenRISC";
+    case EM_CRX:               return "National Semiconductor CRX microprocessor";
     case EM_DLX:               return "OpenDLX";
     case EM_IP2K_OLD:
     case EM_IP2K:              return "Ubicom IP2xxx 8-bit microcontrollers";
@@ -1988,6 +1995,29 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
 
          break;
 
+       case EM_SH:
+         switch ((e_flags & EF_SH_MACH_MASK))
+           {
+           case EF_SH1: strcat (buf, ", sh1"); break;
+           case EF_SH2: strcat (buf, ", sh2"); break;
+           case EF_SH3: strcat (buf, ", sh3"); break;
+           case EF_SH_DSP: strcat (buf, ", sh-dsp"); break;
+           case EF_SH3_DSP: strcat (buf, ", sh3-dsp"); break;
+           case EF_SH4AL_DSP: strcat (buf, ", sh4al-dsp"); break;
+           case EF_SH3E: strcat (buf, ", sh3e"); break;
+           case EF_SH4: strcat (buf, ", sh4"); break;
+           case EF_SH5: strcat (buf, ", sh5"); break;
+           case EF_SH2E: strcat (buf, ", sh2e"); break;
+           case EF_SH4A: strcat (buf, ", sh4a"); break;
+           case EF_SH2A: strcat (buf, ", sh2a"); break;
+           case EF_SH4_NOFPU: strcat (buf, ", sh4-nofpu"); break;
+           case EF_SH4A_NOFPU: strcat (buf, ", sh4a-nofpu"); break;
+           case EF_SH2A_NOFPU: strcat (buf, ", sh2a-nofpu"); break;
+           default: strcat (buf, ", unknown ISA"); break;
+           }
+
+         break;
+         
        case EM_SPARCV9:
          if (e_flags & EF_SPARC_32PLUS)
            strcat (buf, ", v8+");
@@ -8476,6 +8506,88 @@ read_and_display_attr (unsigned long attribute,
   return data;
 }
 
+/* Apply addends of RELA relocations.  */
+
+static int
+debug_apply_rela_addends (FILE *file,
+                         Elf_Internal_Shdr *section,
+                         int reloc_size,
+                         unsigned char *sec_data,
+                         unsigned char *start,
+                         unsigned char *end)
+{
+  Elf_Internal_Shdr *relsec;
+
+  if (end - start < reloc_size)
+    return 1;
+
+  for (relsec = section_headers;
+       relsec < section_headers + elf_header.e_shnum;
+       ++relsec)
+    {
+      unsigned long nrelas;
+      Elf_Internal_Rela *rela, *rp;
+      Elf_Internal_Shdr *symsec;
+      Elf_Internal_Sym *symtab;
+      Elf_Internal_Sym *sym;
+
+      if (relsec->sh_type != SHT_RELA
+         || SECTION_HEADER (relsec->sh_info) != section
+         || relsec->sh_size == 0)
+       continue;
+
+      if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
+                             &rela, &nrelas))
+       return 0;
+
+      symsec = SECTION_HEADER (relsec->sh_link);
+      symtab = GET_ELF_SYMBOLS (file, symsec);
+
+      for (rp = rela; rp < rela + nrelas; ++rp)
+       {
+         unsigned char *loc;
+
+         if (rp->r_offset >= (bfd_vma) (start - sec_data)
+             && rp->r_offset < (bfd_vma) (end - sec_data) - reloc_size)
+           loc = sec_data + rp->r_offset;
+         else
+           continue;
+
+         if (is_32bit_elf)
+           {
+             sym = symtab + ELF32_R_SYM (rp->r_info);
+
+             if (ELF32_R_SYM (rp->r_info) != 0
+                 && ELF32_ST_TYPE (sym->st_info) != STT_SECTION)
+               {
+                 warn (_("Skipping unexpected symbol type %u\n"),
+                       ELF32_ST_TYPE (sym->st_info));
+                 continue;
+               }
+           }
+         else
+           {
+             sym = symtab + ELF64_R_SYM (rp->r_info);
+
+             if (ELF64_R_SYM (rp->r_info) != 0
+                 && ELF64_ST_TYPE (sym->st_info) != STT_SECTION)
+               {
+                 warn (_("Skipping unexpected symbol type %u\n"),
+                       ELF64_ST_TYPE (sym->st_info));
+                 continue;
+               }
+           }
+
+         byte_put (loc, rp->r_addend, reloc_size);
+       }
+
+      free (symtab);
+      free (rela);
+      break;
+    }
+  return 1;
+}
+
 static int
 display_debug_info (Elf_Internal_Shdr *section,
                    unsigned char *start,
@@ -8492,7 +8604,6 @@ display_debug_info (Elf_Internal_Shdr *section,
   while (start < end)
     {
       DWARF2_Internal_CompUnit compunit;
-      Elf_Internal_Shdr *relsec;
       unsigned char *hdrptr;
       unsigned char *cu_abbrev_offset_ptr;
       unsigned char *tags;
@@ -8522,71 +8633,13 @@ display_debug_info (Elf_Internal_Shdr *section,
       compunit.cu_version = byte_get (hdrptr, 2);
       hdrptr += 2;
 
-      /* Apply addends of RELA relocations.  */
-      for (relsec = section_headers;
-          relsec < section_headers + elf_header.e_shnum;
-          ++relsec)
-       {
-         unsigned long nrelas;
-         Elf_Internal_Rela *rela, *rp;
-         Elf_Internal_Shdr *symsec;
-         Elf_Internal_Sym *symtab;
-         Elf_Internal_Sym *sym;
-
-         if (relsec->sh_type != SHT_RELA
-             || SECTION_HEADER (relsec->sh_info) != section
-             || relsec->sh_size == 0)
-           continue;
-
-         if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
-                                 & rela, & nrelas))
-           return 0;
-
-         symsec = SECTION_HEADER (relsec->sh_link);
-         symtab = GET_ELF_SYMBOLS (file, symsec);
-
-         for (rp = rela; rp < rela + nrelas; ++rp)
-           {
-             unsigned char *loc;
-
-             if (rp->r_offset >= (bfd_vma) (hdrptr - section_begin)
-                 && section->sh_size > (bfd_vma) offset_size
-                 && rp->r_offset <= section->sh_size - offset_size)
-               loc = section_begin + rp->r_offset;
-             else
-               continue;
-
-             if (is_32bit_elf)
-               {
-                 sym = symtab + ELF32_R_SYM (rp->r_info);
-
-                 if (ELF32_R_SYM (rp->r_info) != 0
-                     && ELF32_ST_TYPE (sym->st_info) != STT_SECTION)
-                   {
-                     warn (_("Skipping unexpected symbol type %u\n"),
-                           ELF32_ST_TYPE (sym->st_info));
-                     continue;
-                   }
-               }
-             else
-               {
-                 sym = symtab + ELF64_R_SYM (rp->r_info);
-
-                 if (ELF64_R_SYM (rp->r_info) != 0
-                     && ELF64_ST_TYPE (sym->st_info) != STT_SECTION)
-                   {
-                     warn (_("Skipping unexpected symbol type %u\n"),
-                           ELF64_ST_TYPE (sym->st_info));
-                     continue;
-                   }
-               }
-
-             byte_put (loc, rp->r_addend, offset_size);
-           }
+      cu_offset = start - section_begin;
+      start += compunit.cu_length + initial_length_size;
 
-         free (rela);
-         break;
-       }
+      if (elf_header.e_type == ET_REL
+         && !debug_apply_rela_addends (file, section, offset_size,
+                                       section_begin, hdrptr, start))
+       return 0;
 
       cu_abbrev_offset_ptr = hdrptr;
       compunit.cu_abbrev_offset = byte_get (hdrptr, offset_size);
@@ -8596,8 +8649,6 @@ display_debug_info (Elf_Internal_Shdr *section,
       hdrptr += 1;
 
       tags = hdrptr;
-      cu_offset = start - section_begin;
-      start += compunit.cu_length + initial_length_size;
 
       printf (_("  Compilation Unit @ %lx:\n"), cu_offset);
       printf (_("   Length:        %ld\n"), compunit.cu_length);
@@ -8987,6 +9038,11 @@ display_debug_frames (Elf_Internal_Shdr *section,
       block_end = saved_start + length + initial_length_size;
       cie_id = byte_get (start, offset_size); start += offset_size;
 
+      if (elf_header.e_type == ET_REL
+         && !debug_apply_rela_addends (file, section, offset_size,
+                                       section_start, start, block_end))
+       return 0;
+
       if (is_eh ? (cie_id == 0) : (cie_id == DW_CIE_ID))
        {
          int version;
@@ -9151,7 +9207,10 @@ display_debug_frames (Elf_Internal_Shdr *section,
            encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
 
          fc->pc_begin = get_encoded_value (start, fc->fde_encoding);
-         if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel)
+         if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel
+             /* Don't adjust for ET_REL since there's invariably a pcrel
+                reloc here, which we haven't applied.  */
+             && elf_header.e_type != ET_REL)
            fc->pc_begin += section->sh_addr + (start - section_start);
          start += encoded_ptr_size;
          fc->pc_range = byte_get (start, encoded_ptr_size);
@@ -9350,7 +9409,8 @@ display_debug_frames (Elf_Internal_Shdr *section,
 
            case DW_CFA_set_loc:
              vma = get_encoded_value (start, fc->fde_encoding);
-             if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel)
+             if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel
+                 && elf_header.e_type != ET_REL)
                vma += section->sh_addr + (start - section_start);
              start += encoded_ptr_size;
              if (do_debug_frames_interp)