/* readelf.c -- display contents of an ELF format file
- Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
- Free Software Foundation, Inc.
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+ 2008 Free Software Foundation, Inc.
Originally developed by Eric Youngdale <eric@andante.jic.com>
Modifications by Nick Clifton <nickc@redhat.com>
#if BFD_HOST_64BIT_LONG
return nc + printf ("%lx", vma);
#elif BFD_HOST_64BIT_LONG_LONG
+#ifndef __MSVCRT__
return nc + printf ("%llx", vma);
+#else
+ return nc + printf ("%I64x", vma);
+#endif
#else
return nc + print_hex_vma (vma);
#endif
#if BFD_HOST_64BIT_LONG
return printf ("%ld", vma);
#elif BFD_HOST_64BIT_LONG_LONG
+#ifndef __MSVCRT__
return printf ("%lld", vma);
+#else
+ return printf ("%I64d", vma);
+#endif
#else
return print_dec_vma (vma, 1);
#endif
else
return printf ("%#lx", vma);
#elif BFD_HOST_64BIT_LONG_LONG
+#ifndef __MSVCRT__
if (vma <= 99999)
return printf ("%5lld", vma);
else
return printf ("%#llx", vma);
+#else
+ if (vma <= 99999)
+ return printf ("%5I64d", vma);
+ else
+ return printf ("%#I64x", vma);
+#endif
#else
if (vma <= 99999)
return printf ("%5ld", _bfd_int64_low (vma));
#if BFD_HOST_64BIT_LONG
return printf ("%lu", vma);
#elif BFD_HOST_64BIT_LONG_LONG
+#ifndef __MSVCRT__
return printf ("%llu", vma);
+#else
+ return printf ("%I64u", vma);
+#endif
#else
return print_dec_vma (vma, 0);
#endif
/* Guess the relocation size commonly used by the specific machines. */
static int
-guess_is_rela (unsigned long e_machine)
+guess_is_rela (unsigned int e_machine)
{
switch (e_machine)
{
return 1;
}
+/* Returns the reloc type extracted from the reloc info field. */
+
+static unsigned int
+get_reloc_type (bfd_vma reloc_info)
+{
+ if (is_32bit_elf)
+ return ELF32_R_TYPE (reloc_info);
+
+ switch (elf_header.e_machine)
+ {
+ case EM_MIPS:
+ /* Note: We assume that reloc_info has already been adjusted for us. */
+ return ELF64_MIPS_R_TYPE (reloc_info);
+
+ case EM_SPARCV9:
+ return ELF64_R_TYPE_ID (reloc_info);
+
+ default:
+ return ELF64_R_TYPE (reloc_info);
+ }
+}
+
+/* Return the symbol index extracted from the reloc info field. */
+
+static bfd_vma
+get_reloc_symindex (bfd_vma reloc_info)
+{
+ return is_32bit_elf ? ELF32_R_SYM (reloc_info) : ELF64_R_SYM (reloc_info);
+}
+
/* Display the contents of the relocation data found at the specified
offset. */
-static int
+static void
dump_relocations (FILE *file,
unsigned long rel_offset,
unsigned long rel_size,
if (is_rela)
{
if (!slurp_rela_relocs (file, rel_offset, rel_size, &rels, &rel_size))
- return 0;
+ return;
}
else
{
if (!slurp_rel_relocs (file, rel_offset, rel_size, &rels, &rel_size))
- return 0;
+ return;
}
if (is_32bit_elf)
for (i = 0; i < rel_size; i++)
{
const char *rtype;
- const char *rtype2 = NULL;
- const char *rtype3 = NULL;
bfd_vma offset;
bfd_vma info;
bfd_vma symtab_index;
bfd_vma type;
- bfd_vma type2 = 0;
- bfd_vma type3 = 0;
offset = rels[i].r_offset;
info = rels[i].r_info;
- if (is_32bit_elf)
+ /* The #ifdef BFD64 below is to prevent a compile time warning.
+ We know that if we do not have a 64 bit data type that we
+ will never execute this code anyway. */
+#ifdef BFD64
+ if (!is_32bit_elf
+ && elf_header.e_machine == EM_MIPS
+ && elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
{
- type = ELF32_R_TYPE (info);
- symtab_index = ELF32_R_SYM (info);
+ /* In little-endian objects, r_info isn't really a 64-bit
+ little-endian value: it has a 32-bit little-endian
+ symbol index followed by four individual byte fields.
+ Reorder INFO accordingly. */
+ info = (((info & 0xffffffff) << 32)
+ | ((info >> 56) & 0xff)
+ | ((info >> 40) & 0xff00)
+ | ((info >> 24) & 0xff0000)
+ | ((info >> 8) & 0xff000000));
}
- else
- {
- /* The #ifdef BFD64 below is to prevent a compile time warning.
- We know that if we do not have a 64 bit data type that we
- will never execute this code anyway. */
-#ifdef BFD64
- if (elf_header.e_machine == EM_MIPS)
- {
- /* In little-endian objects, r_info isn't really a 64-bit
- little-endian value: it has a 32-bit little-endian
- symbol index followed by four individual byte fields.
- Reorder INFO accordingly. */
- if (elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
- info = (((info & 0xffffffff) << 32)
- | ((info >> 56) & 0xff)
- | ((info >> 40) & 0xff00)
- | ((info >> 24) & 0xff0000)
- | ((info >> 8) & 0xff000000));
- type = ELF64_MIPS_R_TYPE (info);
- type2 = ELF64_MIPS_R_TYPE2 (info);
- type3 = ELF64_MIPS_R_TYPE3 (info);
- }
- else if (elf_header.e_machine == EM_SPARCV9)
- type = ELF64_R_TYPE_ID (info);
- else
- type = ELF64_R_TYPE (info);
+#endif /* BFD64 */
- symtab_index = ELF64_R_SYM (info);
-#endif
- }
+ type = get_reloc_type (info);
+ symtab_index = get_reloc_symindex (info);
if (is_32bit_elf)
{
: "%12.12lx %12.12lx ",
offset, info);
#elif BFD_HOST_64BIT_LONG_LONG
+#ifndef __MSVCRT__
printf (do_wide
? "%16.16llx %16.16llx "
: "%12.12llx %12.12llx ",
offset, info);
+#else
+ printf (do_wide
+ ? "%16.16I64x %16.16I64x "
+ : "%12.12I64x %12.12I64x ",
+ offset, info);
+#endif
#else
printf (do_wide
? "%8.8lx%8.8lx %8.8lx%8.8lx "
case EM_MIPS:
case EM_MIPS_RS3_LE:
rtype = elf_mips_reloc_type (type);
- if (!is_32bit_elf)
- {
- rtype2 = elf_mips_reloc_type (type2);
- rtype3 = elf_mips_reloc_type (type3);
- }
break;
case EM_ALPHA:
putchar ('\n');
+#ifdef BFD64
if (! is_32bit_elf && elf_header.e_machine == EM_MIPS)
{
+ bfd_vma type2 = ELF64_MIPS_R_TYPE2 (info);
+ bfd_vma type3 = ELF64_MIPS_R_TYPE3 (info);
+ const char *rtype2 = elf_mips_reloc_type (type2);
+ const char *rtype3 = elf_mips_reloc_type (type3);
+
printf (" Type2: ");
if (rtype2 == NULL)
putchar ('\n');
}
+#endif /* BFD64 */
}
free (rels);
-
- return 1;
}
static const char *
case E_MIPS_MACH_5500: strcat (buf, ", 5500"); break;
case E_MIPS_MACH_SB1: strcat (buf, ", sb1"); break;
case E_MIPS_MACH_9000: strcat (buf, ", 9000"); break;
+ case E_MIPS_MACH_LS2E: strcat (buf, ", loongson-2e"); break;
+ case E_MIPS_MACH_LS2F: strcat (buf, ", loongson-2f"); break;
case 0:
/* We simply ignore the field in this case to avoid confusion:
MIPS ELF does not specify EF_MIPS_MACH, it is a GNU
switch (optarg[index++])
{
case 'i':
- case 'I':
do_debug_info = 1;
break;
case 'a':
- case 'A':
do_debug_abbrevs = 1;
break;
case 'l':
- case 'L':
do_debug_lines = 1;
break;
case 'p':
- case 'P':
do_debug_pubnames = 1;
break;
break;
case 'm':
- case 'M':
do_debug_macinfo = 1;
break;
case 's':
- case 'S':
do_debug_str = 1;
break;
case 'o':
- case 'O':
do_debug_loc = 1;
break;
return 0;
}
+ init_dwarf_regnames (elf_header.e_machine);
+
if (do_header)
{
int i;
if (dynamic_addr)
error (_("more than one dynamic segment\n"));
+ /* By default, assume that the .dynamic section is the first
+ section in the DYNAMIC segment. */
+ dynamic_addr = segment->p_offset;
+ dynamic_size = segment->p_filesz;
+
/* Try to locate the .dynamic section. If there is
a section header table, we can easily locate it. */
if (section_headers != NULL)
}
if (sec->sh_type == SHT_NOBITS)
- break;
+ {
+ dynamic_size = 0;
+ break;
+ }
dynamic_addr = sec->sh_offset;
dynamic_size = sec->sh_size;
if (dynamic_addr < segment->p_offset
|| dynamic_addr > segment->p_offset + segment->p_filesz)
- warn (_("the .dynamic section is not contained within the dynamic segment\n"));
+ warn (_("the .dynamic section is not contained"
+ " within the dynamic segment\n"));
else if (dynamic_addr > segment->p_offset)
- warn (_("the .dynamic section is not the first section in the dynamic segment.\n"));
- }
- else
- {
- /* Otherwise, we can only assume that the .dynamic
- section is the first section in the DYNAMIC segment. */
- dynamic_addr = segment->p_offset;
- dynamic_size = segment->p_filesz;
+ warn (_("the .dynamic section is not the first section"
+ " in the dynamic segment.\n"));
}
break;
eh_addr_size = 4;
break;
}
+ break;
+
+ case EM_M32C:
+ switch (elf_header.e_flags & EF_M32C_CPU_MASK)
+ {
+ case EF_M32C_CPU_M16C:
+ eh_addr_size = 2;
+ break;
+ }
+ break;
}
#define CHECK_ENTSIZE_VALUES(section, i, size32, size64) \
}
free (table);
- /* Third, apply any relocations to the unwind table: */
-
+ /* Third, apply any relocations to the unwind table: */
for (relsec = section_headers;
relsec < section_headers + elf_header.e_shnum;
++relsec)
for (rp = rela; rp < rela + nrelas; ++rp)
{
- if (is_32bit_elf)
- {
- relname = elf_ia64_reloc_type (ELF32_R_TYPE (rp->r_info));
- sym = aux->symtab + ELF32_R_SYM (rp->r_info);
- }
- else
- {
- relname = elf_ia64_reloc_type (ELF64_R_TYPE (rp->r_info));
- sym = aux->symtab + ELF64_R_SYM (rp->r_info);
- }
+ relname = elf_ia64_reloc_type (get_reloc_type (rp->r_info));
+ sym = aux->symtab + get_reloc_symindex (rp->r_info);
if (! const_strneq (relname, "R_IA64_SEGREL"))
{
free (table);
/* Third, apply any relocations to the unwind table. */
-
for (relsec = section_headers;
relsec < section_headers + elf_header.e_shnum;
++relsec)
for (rp = rela; rp < rela + nrelas; ++rp)
{
- if (is_32bit_elf)
- {
- relname = elf_hppa_reloc_type (ELF32_R_TYPE (rp->r_info));
- sym = aux->symtab + ELF32_R_SYM (rp->r_info);
- }
- else
- {
- relname = elf_hppa_reloc_type (ELF64_R_TYPE (rp->r_info));
- sym = aux->symtab + ELF64_R_SYM (rp->r_info);
- }
+ relname = elf_hppa_reloc_type (get_reloc_type (rp->r_info));
+ sym = aux->symtab + get_reloc_symindex (rp->r_info);
/* R_PARISC_SEGREL32 or R_PARISC_SEGREL64. */
if (! const_strneq (relname, "R_PARISC_SEGREL"))
return i_data;
}
+static void
+print_dynamic_symbol (bfd_vma si, unsigned long hn)
+{
+ Elf_Internal_Sym *psym;
+ int n;
+
+ psym = dynamic_symbols + si;
+
+ n = print_vma (si, DEC_5);
+ if (n < 5)
+ fputs (" " + n, stdout);
+ printf (" %3lu: ", hn);
+ print_vma (psym->st_value, LONG_HEX);
+ putchar (' ');
+ print_vma (psym->st_size, DEC_5);
+
+ printf (" %6s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));
+ printf (" %6s", get_symbol_binding (ELF_ST_BIND (psym->st_info)));
+ printf (" %3s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
+ /* Check to see if any other bits in the st_other field are set.
+ Note - displaying this information disrupts the layout of the
+ table being generated, but for the moment this case is very
+ rare. */
+ if (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other))
+ printf (" [%s] ", get_symbol_other (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other)));
+ printf (" %3.3s ", get_symbol_index_type (psym->st_shndx));
+ if (VALID_DYNAMIC_NAME (psym->st_name))
+ print_symbol (25, GET_DYNAMIC_NAME (psym->st_name));
+ else
+ printf (" <corrupt: %14ld>", psym->st_name);
+ putchar ('\n');
+}
+
/* Dump the symbol table. */
static int
process_symbol_table (FILE *file)
bfd_vma ngnubuckets = 0;
bfd_vma *gnubuckets = NULL;
bfd_vma *gnuchains = NULL;
+ bfd_vma gnusymidx = 0;
if (! do_syms && !do_histogram)
return 1;
- if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL)
- || do_histogram))
+ if (dynamic_info[DT_HASH]
+ && (do_histogram
+ || (do_using_dynamic && dynamic_strings != NULL)))
{
unsigned char nb[8];
unsigned char nc[8];
return 0;
}
- if (do_syms
- && dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL)
+ if (dynamic_info_DT_GNU_HASH
+ && (do_histogram
+ || (do_using_dynamic && dynamic_strings != NULL)))
{
- unsigned long hn;
- bfd_vma si;
+ unsigned char nb[16];
+ bfd_vma i, maxchain = 0xffffffff, bitmaskwords;
+ bfd_vma buckets_vma;
+
+ if (fseek (file,
+ (archive_file_offset
+ + offset_from_vma (file, dynamic_info_DT_GNU_HASH,
+ sizeof nb)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ return 0;
+ }
- printf (_("\nSymbol table for image:\n"));
+ if (fread (nb, 16, 1, file) != 1)
+ {
+ error (_("Failed to read in number of buckets\n"));
+ return 0;
+ }
+
+ ngnubuckets = byte_get (nb, 4);
+ gnusymidx = byte_get (nb + 4, 4);
+ bitmaskwords = byte_get (nb + 8, 4);
+ buckets_vma = dynamic_info_DT_GNU_HASH + 16;
if (is_32bit_elf)
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
+ buckets_vma += bitmaskwords * 4;
else
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
+ buckets_vma += bitmaskwords * 8;
- for (hn = 0; hn < nbuckets; hn++)
+ if (fseek (file,
+ (archive_file_offset
+ + offset_from_vma (file, buckets_vma, 4)),
+ SEEK_SET))
{
- if (! buckets[hn])
- continue;
+ error (_("Unable to seek to start of dynamic information\n"));
+ return 0;
+ }
- for (si = buckets[hn]; si < nchains && si > 0; si = chains[si])
+ gnubuckets = get_dynamic_data (file, ngnubuckets, 4);
+
+ if (gnubuckets == NULL)
+ return 0;
+
+ for (i = 0; i < ngnubuckets; i++)
+ if (gnubuckets[i] != 0)
+ {
+ if (gnubuckets[i] < gnusymidx)
+ return 0;
+
+ if (maxchain == 0xffffffff || gnubuckets[i] > maxchain)
+ maxchain = gnubuckets[i];
+ }
+
+ if (maxchain == 0xffffffff)
+ return 0;
+
+ maxchain -= gnusymidx;
+
+ if (fseek (file,
+ (archive_file_offset
+ + offset_from_vma (file, buckets_vma
+ + 4 * (ngnubuckets + maxchain), 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ return 0;
+ }
+
+ do
+ {
+ if (fread (nb, 4, 1, file) != 1)
{
- Elf_Internal_Sym *psym;
- int n;
+ error (_("Failed to determine last chain length\n"));
+ return 0;
+ }
- psym = dynamic_symbols + si;
+ if (maxchain + 1 == 0)
+ return 0;
- n = print_vma (si, DEC_5);
- if (n < 5)
- fputs (" " + n, stdout);
- printf (" %3lu: ", hn);
- print_vma (psym->st_value, LONG_HEX);
- putchar (' ');
- print_vma (psym->st_size, DEC_5);
+ ++maxchain;
+ }
+ while ((byte_get (nb, 4) & 1) == 0);
- printf (" %6s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));
- printf (" %6s", get_symbol_binding (ELF_ST_BIND (psym->st_info)));
- printf (" %3s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
- /* Check to see if any other bits in the st_other field are set.
- Note - displaying this information disrupts the layout of the
- table being generated, but for the moment this case is very rare. */
- if (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other))
- printf (" [%s] ", get_symbol_other (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other)));
- printf (" %3.3s ", get_symbol_index_type (psym->st_shndx));
- if (VALID_DYNAMIC_NAME (psym->st_name))
- print_symbol (25, GET_DYNAMIC_NAME (psym->st_name));
- else
- printf (" <corrupt: %14ld>", psym->st_name);
- putchar ('\n');
+ if (fseek (file,
+ (archive_file_offset
+ + offset_from_vma (file, buckets_vma + 4 * ngnubuckets, 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ return 0;
+ }
+
+ gnuchains = get_dynamic_data (file, maxchain, 4);
+
+ if (gnuchains == NULL)
+ return 0;
+ }
+
+ if ((dynamic_info[DT_HASH] || dynamic_info_DT_GNU_HASH)
+ && do_syms
+ && do_using_dynamic
+ && dynamic_strings != NULL)
+ {
+ unsigned long hn;
+
+ if (dynamic_info[DT_HASH])
+ {
+ bfd_vma si;
+
+ printf (_("\nSymbol table for image:\n"));
+ if (is_32bit_elf)
+ printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
+ else
+ printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
+
+ for (hn = 0; hn < nbuckets; hn++)
+ {
+ if (! buckets[hn])
+ continue;
+
+ for (si = buckets[hn]; si < nchains && si > 0; si = chains[si])
+ print_dynamic_symbol (si, hn);
}
}
+
+ if (dynamic_info_DT_GNU_HASH)
+ {
+ printf (_("\nSymbol table of `.gnu.hash' for image:\n"));
+ if (is_32bit_elf)
+ printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
+ else
+ printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
+
+ for (hn = 0; hn < ngnubuckets; ++hn)
+ if (gnubuckets[hn] != 0)
+ {
+ bfd_vma si = gnubuckets[hn];
+ bfd_vma off = si - gnusymidx;
+
+ do
+ {
+ print_dynamic_symbol (si, hn);
+ si++;
+ }
+ while ((gnuchains[off++] & 1) == 0);
+ }
+ }
}
else if (do_syms && !do_using_dynamic)
{
if (do_histogram && dynamic_info_DT_GNU_HASH)
{
- unsigned char nb[16];
- bfd_vma i, maxchain = 0xffffffff, symidx, bitmaskwords;
unsigned long *lengths;
unsigned long *counts;
unsigned long hn;
unsigned long maxlength = 0;
unsigned long nzero_counts = 0;
unsigned long nsyms = 0;
- bfd_vma buckets_vma;
-
- if (fseek (file,
- (archive_file_offset
- + offset_from_vma (file, dynamic_info_DT_GNU_HASH,
- sizeof nb)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- return 0;
- }
-
- if (fread (nb, 16, 1, file) != 1)
- {
- error (_("Failed to read in number of buckets\n"));
- return 0;
- }
-
- ngnubuckets = byte_get (nb, 4);
- symidx = byte_get (nb + 4, 4);
- bitmaskwords = byte_get (nb + 8, 4);
- buckets_vma = dynamic_info_DT_GNU_HASH + 16;
- if (is_32bit_elf)
- buckets_vma += bitmaskwords * 4;
- else
- buckets_vma += bitmaskwords * 8;
-
- if (fseek (file,
- (archive_file_offset
- + offset_from_vma (file, buckets_vma, 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- return 0;
- }
-
- gnubuckets = get_dynamic_data (file, ngnubuckets, 4);
-
- if (gnubuckets == NULL)
- return 0;
-
- for (i = 0; i < ngnubuckets; i++)
- if (gnubuckets[i] != 0)
- {
- if (gnubuckets[i] < symidx)
- return 0;
-
- if (maxchain == 0xffffffff || gnubuckets[i] > maxchain)
- maxchain = gnubuckets[i];
- }
-
- if (maxchain == 0xffffffff)
- return 0;
-
- maxchain -= symidx;
-
- if (fseek (file,
- (archive_file_offset
- + offset_from_vma (file, buckets_vma
- + 4 * (ngnubuckets + maxchain), 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- return 0;
- }
-
- do
- {
- if (fread (nb, 4, 1, file) != 1)
- {
- error (_("Failed to determine last chain length\n"));
- return 0;
- }
-
- if (maxchain + 1 == 0)
- return 0;
-
- ++maxchain;
- }
- while ((byte_get (nb, 4) & 1) == 0);
-
- if (fseek (file,
- (archive_file_offset
- + offset_from_vma (file, buckets_vma + 4 * ngnubuckets, 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- return 0;
- }
-
- gnuchains = get_dynamic_data (file, maxchain, 4);
-
- if (gnuchains == NULL)
- return 0;
lengths = calloc (ngnubuckets, sizeof (*lengths));
if (lengths == NULL)
{
bfd_vma off, length = 1;
- for (off = gnubuckets[hn] - symidx;
+ for (off = gnubuckets[hn] - gnusymidx;
(gnuchains[off] & 1) == 0; ++off)
++length;
lengths[hn] = length;
if (data < end)
{
- printf (" [%6zx] %s\n", data - start, data);
+#ifndef __MSVCRT__
+ printf (" [%6tx] %s\n", data - start, data);
+#else
+ printf (" [%6Ix] %s\n", (size_t) (data - start), data);
+#endif
data += strlen (data);
some_strings_shown = TRUE;
}
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. */
+/* Returns TRUE iff RELOC_TYPE is a 32-bit absolute RELA relocation used in
+ DWARF debug sections. This is a target specific test. Note - we do not
+ go through the whole including-target-headers-multiple-times route, (as
+ we have already done with <elf/h8.h>) because this would become very
+ messy and even then this function would have to contain target specific
+ information (the names of the relocs instead of their numeric values).
+ FIXME: This is not the correct way to solve this problem. The proper way
+ is to have target specific reloc sizing and typing 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)
+static bfd_boolean
+is_32bit_abs_reloc (unsigned int reloc_type)
{
switch (elf_header.e_machine)
{
+ case EM_386:
+ case EM_486:
+ return reloc_type == 1; /* R_386_32. */
+ case EM_68K:
+ return reloc_type == 1; /* R_68K_32. */
+ case EM_860:
+ return reloc_type == 1; /* R_860_32. */
+ case EM_ALPHA:
+ return reloc_type == 1; /* XXX Is this right ? */
+ case EM_ARC:
+ return reloc_type == 1; /* R_ARC_32. */
+ case EM_ARM:
+ return reloc_type == 2; /* R_ARM_ABS32 */
+ case EM_AVR_OLD:
+ case EM_AVR:
+ return reloc_type == 1;
+ case EM_BLACKFIN:
+ return reloc_type == 0x12; /* R_byte4_data. */
+ case EM_CRIS:
+ return reloc_type == 3; /* R_CRIS_32. */
+ case EM_CR16:
+ return reloc_type == 3; /* R_CR16_NUM32. */
+ case EM_CRX:
+ return reloc_type == 15; /* R_CRX_NUM32. */
+ case EM_CYGNUS_FRV:
+ return reloc_type == 1;
+ case EM_CYGNUS_D10V:
+ case EM_D10V:
+ return reloc_type == 6; /* R_D10V_32. */
+ case EM_CYGNUS_D30V:
+ case EM_D30V:
+ return reloc_type == 12; /* R_D30V_32_NORMAL. */
+ case EM_DLX:
+ return reloc_type == 3; /* R_DLX_RELOC_32. */
+ case EM_CYGNUS_FR30:
+ case EM_FR30:
+ return reloc_type == 3; /* R_FR30_32. */
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;
- }
+ return reloc_type == 1; /* R_H8_DIR32. */
+ case EM_IA_64:
+ return reloc_type == 0x65; /* R_IA64_SECREL32LSB. */
+ case EM_IP2K_OLD:
+ case EM_IP2K:
+ return reloc_type == 2; /* R_IP2K_32. */
+ case EM_IQ2000:
+ return reloc_type == 2; /* R_IQ2000_32. */
+ case EM_M32C:
+ return reloc_type == 3; /* R_M32C_32. */
+ case EM_M32R:
+ return reloc_type == 34; /* R_M32R_32_RELA. */
+ case EM_MCORE:
+ return reloc_type == 1; /* R_MCORE_ADDR32. */
+ case EM_CYGNUS_MEP:
+ return reloc_type == 4; /* R_MEP_32. */
+ case EM_MIPS:
+ return reloc_type == 2; /* R_MIPS_32. */
+ case EM_MMIX:
+ return reloc_type == 4; /* R_MMIX_32. */
+ case EM_CYGNUS_MN10200:
+ case EM_MN10200:
+ return reloc_type == 1; /* R_MN10200_32. */
+ case EM_CYGNUS_MN10300:
+ case EM_MN10300:
+ return reloc_type == 1; /* R_MN10300_32. */
+ case EM_MSP430_OLD:
+ case EM_MSP430:
+ return reloc_type == 1; /* R_MSP43_32. */
+ case EM_MT:
+ return reloc_type == 2; /* R_MT_32. */
+ case EM_ALTERA_NIOS2:
+ case EM_NIOS32:
+ return reloc_type == 1; /* R_NIOS_32. */
+ case EM_OPENRISC:
+ case EM_OR32:
+ return reloc_type == 1; /* R_OR32_32. */
+ case EM_PARISC:
+ return reloc_type == 1; /* R_PARISC_DIR32. */
+ case EM_PJ:
+ case EM_PJ_OLD:
+ return reloc_type == 1; /* R_PJ_DATA_DIR32. */
+ case EM_PPC64:
+ return reloc_type == 1; /* R_PPC64_ADDR32. */
+ case EM_PPC:
+ return reloc_type == 1; /* R_PPC_ADDR32. */
+ case EM_S370:
+ return reloc_type == 1; /* R_I370_ADDR31. */
+ case EM_S390_OLD:
+ case EM_S390:
+ return reloc_type == 4; /* R_S390_32. */
+ case EM_SCORE:
+ return reloc_type == 8; /* R_SCORE_ABS32. */
+ case EM_SH:
+ return reloc_type == 1; /* R_SH_DIR32. */
+ case EM_SPARC32PLUS:
+ case EM_SPARCV9:
+ case EM_SPARC:
+ return reloc_type == 3 /* R_SPARC_32. */
+ || reloc_type == 23; /* R_SPARC_UA32. */
+ case EM_SPU:
+ return reloc_type == 6; /* R_SPU_ADDR32 */
+ case EM_CYGNUS_V850:
+ case EM_V850:
+ return reloc_type == 6; /* R_V850_ABS32. */
+ case EM_VAX:
+ return reloc_type == 1; /* R_VAX_32. */
+ case EM_X86_64:
+ return reloc_type == 10; /* R_X86_64_32. */
+ case EM_XSTORMY16:
+ return reloc_type == 1; /* R_XSTROMY16_32. */
+ case EM_XTENSA_OLD:
+ case EM_XTENSA:
+ return reloc_type == 1; /* R_XTENSA_32. */
+
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;
+ error (_("Missing knowledge of 32-bit reloc types used in DWARF sections of machine number %d\n"),
+ elf_header.e_machine);
+ abort ();
}
}
-/* Apply addends of RELA relocations. */
+/* Like is_32bit_abs_reloc except that it returns TRUE iff RELOC_TYPE is
+ a 32-bit pc-relative RELA relocation used in DWARF debug sections. */
-static int
-debug_apply_rela_addends (void *file,
- Elf_Internal_Shdr *section,
- unsigned char *start)
+static bfd_boolean
+is_32bit_pcrel_reloc (unsigned int reloc_type)
+{
+ switch (elf_header.e_machine)
+ {
+ case EM_386:
+ case EM_486:
+ return reloc_type == 2; /* R_386_PC32. */
+ case EM_68K:
+ return reloc_type == 4; /* R_68K_PC32. */
+ case EM_ALPHA:
+ return reloc_type == 10; /* R_ALPHA_SREL32. */
+ case EM_ARM:
+ return reloc_type == 3; /* R_ARM_REL32 */
+ case EM_PARISC:
+ return reloc_type == 0; /* R_PARISC_NONE. *//* FIXME: This reloc is generated, but it may be a bug. */
+ case EM_PPC:
+ return reloc_type == 26; /* R_PPC_REL32. */
+ case EM_PPC64:
+ return reloc_type == 26; /* R_PPC64_REL32. */
+ case EM_S390_OLD:
+ case EM_S390:
+ return reloc_type == 5; /* R_390_PC32. */
+ case EM_SH:
+ return reloc_type == 2; /* R_SH_REL32. */
+ case EM_SPARC32PLUS:
+ case EM_SPARCV9:
+ case EM_SPARC:
+ return reloc_type == 6; /* R_SPARC_DISP32. */
+ case EM_SPU:
+ return reloc_type == 13; /* R_SPU_REL32. */
+ case EM_X86_64:
+ return reloc_type == 2; /* R_X86_64_PC32. */
+ case EM_XTENSA_OLD:
+ case EM_XTENSA:
+ return reloc_type == 14; /* R_XTENSA_32_PCREL. */
+ default:
+ /* Do not abort or issue an error message here. Not all targets use
+ pc-relative 32-bit relocs in their DWARF debug information and we
+ have already tested for target coverage in is_32bit_abs_reloc. A
+ more helpful warning message will be generated by
+ debug_apply_relocations anyway, so just return. */
+ return FALSE;
+ }
+}
+
+/* Like is_32bit_abs_reloc except that it returns TRUE iff RELOC_TYPE is
+ a 64-bit absolute RELA relocation used in DWARF debug sections. */
+
+static bfd_boolean
+is_64bit_abs_reloc (unsigned int reloc_type)
+{
+ switch (elf_header.e_machine)
+ {
+ case EM_ALPHA:
+ return reloc_type == 2; /* R_ALPHA_REFQUAD. */
+ case EM_IA_64:
+ return reloc_type == 0x27; /* R_IA64_DIR64LSB. */
+ case EM_PARISC:
+ return reloc_type == 80; /* R_PARISC_DIR64. */
+ case EM_PPC64:
+ return reloc_type == 38; /* R_PPC64_ADDR64. */
+ case EM_SPARC32PLUS:
+ case EM_SPARCV9:
+ case EM_SPARC:
+ return reloc_type == 54; /* R_SPARC_UA64. */
+ case EM_X86_64:
+ return reloc_type == 1; /* R_X86_64_64. */
+ case EM_S390_OLD:
+ case EM_S390:
+ return reloc_type == 22; /* R_S390_64 */
+ default:
+ return FALSE;
+ }
+}
+
+/* Like is_32bit_abs_reloc except that it returns TRUE iff RELOC_TYPE is
+ a 16-bit absolute RELA relocation used in DWARF debug sections. */
+
+static bfd_boolean
+is_16bit_abs_reloc (unsigned int reloc_type)
+{
+ switch (elf_header.e_machine)
+ {
+ case EM_AVR_OLD:
+ case EM_AVR:
+ return reloc_type == 4; /* R_AVR_16. */
+ case EM_CYGNUS_D10V:
+ case EM_D10V:
+ return reloc_type == 3; /* R_D10V_16. */
+ case EM_H8S:
+ case EM_H8_300:
+ case EM_H8_300H:
+ return reloc_type == R_H8_DIR16;
+ case EM_IP2K_OLD:
+ case EM_IP2K:
+ return reloc_type == 1; /* R_IP2K_16. */
+ case EM_M32C:
+ return reloc_type == 1; /* R_M32C_16 */
+ case EM_MSP430_OLD:
+ case EM_MSP430:
+ return reloc_type == 5; /* R_MSP430_16_BYTE. */
+ case EM_ALTERA_NIOS2:
+ case EM_NIOS32:
+ return reloc_type == 9; /* R_NIOS_16. */
+ default:
+ return FALSE;
+ }
+}
+
+/* Apply relocations to a debug section. */
+
+static void
+debug_apply_relocations (void *file,
+ Elf_Internal_Shdr *section,
+ unsigned char *start)
{
Elf_Internal_Shdr *relsec;
unsigned char *end = start + section->sh_size;
- if (!is_relocatable)
- return 1;
-
- /* SH uses RELA but uses in place value instead of the addend field. */
- if (elf_header.e_machine == EM_SH)
- return 0;
+ if (elf_header.e_type != ET_REL)
+ return;
+ /* Find the reloc section associated with the debug section. */
for (relsec = section_headers;
relsec < section_headers + elf_header.e_shnum;
++relsec)
{
- unsigned long nrelas;
- Elf_Internal_Rela *rela, *rp;
+ bfd_boolean is_rela;
+ unsigned long num_relocs;
+ Elf_Internal_Rela *relocs, *rp;
Elf_Internal_Shdr *symsec;
Elf_Internal_Sym *symtab;
Elf_Internal_Sym *sym;
- if (relsec->sh_type != SHT_RELA
+ if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
|| 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;
- if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
- &rela, &nrelas))
- return 0;
+ is_rela = relsec->sh_type == SHT_RELA;
+
+ if (is_rela)
+ {
+ if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
+ & relocs, & num_relocs))
+ return;
+ }
+ else
+ {
+ if (!slurp_rel_relocs (file, relsec->sh_offset, relsec->sh_size,
+ & relocs, & num_relocs))
+ return;
+ }
+
+ /* SH uses RELA but uses in place value instead of the addend field. */
+ if (elf_header.e_machine == EM_SH)
+ is_rela = FALSE;
symsec = SECTION_HEADER (relsec->sh_link);
symtab = GET_ELF_SYMBOLS (file, symsec);
- for (rp = rela; rp < rela + nrelas; ++rp)
- {
- unsigned char *loc;
- unsigned int reloc_size;
-
- reloc_size = get_reloc_size (rp);
- if (reloc_size == 0)
+ for (rp = relocs; rp < relocs + num_relocs; ++rp)
+ {
+ bfd_vma addend;
+ unsigned int reloc_type;
+ unsigned int reloc_size;
+ unsigned char * loc;
+
+ /* In MIPS little-endian objects, r_info isn't really a
+ 64-bit little-endian value: it has a 32-bit little-endian
+ symbol index followed by four individual byte fields.
+ Reorder INFO accordingly. */
+ if (!is_32bit_elf
+ && elf_header.e_machine == EM_MIPS
+ && elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
+ rp->r_info = (((rp->r_info & 0xffffffff) << 32)
+ | ((rp->r_info >> 56) & 0xff)
+ | ((rp->r_info >> 40) & 0xff00)
+ | ((rp->r_info >> 24) & 0xff0000)
+ | ((rp->r_info >> 8) & 0xff000000));
+
+ reloc_type = get_reloc_type (rp->r_info);
+
+ if (is_32bit_abs_reloc (reloc_type)
+ || is_32bit_pcrel_reloc (reloc_type))
+ reloc_size = 4;
+ else if (is_64bit_abs_reloc (reloc_type))
+ reloc_size = 8;
+ else if (is_16bit_abs_reloc (reloc_type))
+ reloc_size = 2;
+ else
{
- warn (_("skipping relocation of unknown size against offset 0x%lx in section %s\n"),
- (unsigned long) rp->r_offset,
- SECTION_NAME (section));
+ warn (_("unable to apply unsupported reloc type %d to section %s\n"),
+ reloc_type, SECTION_NAME (section));
continue;
}
continue;
}
- if (is_32bit_elf)
+ sym = symtab + get_reloc_symindex (rp->r_info);
+
+ /* If the reloc has a symbol associated with it,
+ make sure that it is of an appropriate type. */
+ if (sym != symtab
+ && ELF_ST_TYPE (sym->st_info) != STT_SECTION
+ /* Relocations against symbols without type can happen.
+ Gcc -feliminate-dwarf2-dups may generate symbols
+ without type for debug info. */
+ && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
+ /* Relocations against object symbols can happen,
+ eg when referencing a global array. For an
+ example of this see the _clz.o binary in libgcc.a. */
+ && ELF_ST_TYPE (sym->st_info) != STT_OBJECT)
{
- sym = symtab + ELF32_R_SYM (rp->r_info);
-
- if (ELF32_R_SYM (rp->r_info) != 0
- && ELF32_ST_TYPE (sym->st_info) != STT_SECTION
- /* Relocations against symbols without type can happen.
- Gcc -feliminate-dwarf2-dups may generate symbols
- without type for debug info. */
- && ELF32_ST_TYPE (sym->st_info) != STT_NOTYPE
- /* Relocations against object symbols can happen,
- eg when referencing a global array. For an
- example of this see the _clz.o binary in libgcc.a. */
- && ELF32_ST_TYPE (sym->st_info) != STT_OBJECT)
- {
- warn (_("skipping unexpected symbol type %s in relocation in section .rela%s\n"),
- get_symbol_type (ELF32_ST_TYPE (sym->st_info)),
- SECTION_NAME (section));
- continue;
- }
- }
- else
- {
- /* In MIPS little-endian objects, r_info isn't really a
- 64-bit little-endian value: it has a 32-bit little-endian
- symbol index followed by four individual byte fields.
- Reorder INFO accordingly. */
- if (elf_header.e_machine == EM_MIPS
- && elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
- rp->r_info = (((rp->r_info & 0xffffffff) << 32)
- | ((rp->r_info >> 56) & 0xff)
- | ((rp->r_info >> 40) & 0xff00)
- | ((rp->r_info >> 24) & 0xff0000)
- | ((rp->r_info >> 8) & 0xff000000));
-
- sym = symtab + ELF64_R_SYM (rp->r_info);
-
- if (ELF64_R_SYM (rp->r_info) != 0
- && ELF64_ST_TYPE (sym->st_info) != STT_SECTION
- && ELF64_ST_TYPE (sym->st_info) != STT_NOTYPE
- && ELF64_ST_TYPE (sym->st_info) != STT_OBJECT)
- {
- warn (_("skipping unexpected symbol type %s in relocation in section .rela.%s\n"),
- get_symbol_type (ELF64_ST_TYPE (sym->st_info)),
- SECTION_NAME (section));
- continue;
- }
+ warn (_("skipping unexpected symbol type %s in %ld'th relocation in section %s\n"),
+ get_symbol_type (ELF_ST_TYPE (sym->st_info)),
+ (long int)(rp - relocs),
+ SECTION_NAME (relsec));
+ continue;
}
- byte_put (loc, rp->r_addend, reloc_size);
+ addend = is_rela ? rp->r_addend : byte_get (loc, reloc_size);
+
+ if (is_32bit_pcrel_reloc (reloc_type))
+ byte_put (loc, (addend + sym->st_value) - rp->r_offset,
+ reloc_size);
+ else
+ byte_put (loc, addend + sym->st_value, reloc_size);
}
free (symtab);
- free (rela);
+ free (relocs);
break;
}
- return 1;
}
int
sec->sh_size, buf);
if (debug_displays [debug].relocate)
- debug_apply_rela_addends (file, sec, section->start);
+ debug_apply_relocations (file, sec, section->start);
return section->start != NULL;
}
return p;
}
+ if (tag == Tag_GNU_Power_ABI_Vector)
+ {
+ val = read_uleb128 (p, &len);
+ p += len;
+ printf (" Tag_GNU_Power_ABI_Vector: ");
+ switch (val)
+ {
+ case 0:
+ printf ("Any\n");
+ break;
+ case 1:
+ printf ("Generic\n");
+ break;
+ case 2:
+ printf ("AltiVec\n");
+ break;
+ case 3:
+ printf ("SPE\n");
+ break;
+ default:
+ printf ("??? (%d)\n", val);
+ break;
+ }
+ return p;
+ }
+
if (tag & 1)
type = 1; /* String. */
else
case 3:
printf ("Soft float\n");
break;
+ case 4:
+ printf ("64-bit float (-mips32r2 -mfp64)\n");
+ break;
default:
printf ("??? (%d)\n", val);
break;
return _("NT_TASKSTRUCT (task structure)");
case NT_PRXFPREG:
return _("NT_PRXFPREG (user_xfpregs structure)");
+ case NT_PPC_VMX:
+ return _("NT_PPC_VMX (ppc Altivec registers)");
case NT_PSTATUS:
return _("NT_PSTATUS (pstatus structure)");
case NT_FPREGS:
get_64bit_section_headers (file, 1);
}
- is_relocatable = elf_header.e_type == ET_REL;
-
return 1;
}