X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=binutils%2Freadelf.c;h=20a7681f411841a0a29ebfc1829af5e3856995b2;hb=f4236fe4560a39155dd1e633f88914b1ac28d824;hp=e550f6fba7f1264756bf5bb96ab98ae285ec56cc;hpb=6bd1a22c3eecb1892841a530544d8cdf43af5263;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/readelf.c b/binutils/readelf.c index e550f6fba7..20a7681f41 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -1,6 +1,6 @@ /* 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 Modifications by Nick Clifton @@ -493,7 +493,11 @@ print_vma (bfd_vma vma, print_mode mode) #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 @@ -502,7 +506,11 @@ print_vma (bfd_vma vma, print_mode mode) #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 @@ -514,10 +522,17 @@ print_vma (bfd_vma vma, print_mode mode) 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)); @@ -529,7 +544,11 @@ print_vma (bfd_vma vma, print_mode mode) #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 @@ -846,10 +865,40 @@ slurp_rel_relocs (FILE *file, 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, @@ -869,12 +918,12 @@ dump_relocations (FILE *file, 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) @@ -915,53 +964,36 @@ dump_relocations (FILE *file, 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) { @@ -977,10 +1009,17 @@ dump_relocations (FILE *file, : "%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 " @@ -1103,11 +1142,6 @@ dump_relocations (FILE *file, 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: @@ -1329,8 +1363,14 @@ dump_relocations (FILE *file, 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) @@ -1349,11 +1389,10 @@ dump_relocations (FILE *file, putchar ('\n'); } +#endif /* BFD64 */ } free (rels); - - return 1; } static const char * @@ -2181,6 +2220,8 @@ get_machine_flags (unsigned e_flags, unsigned e_machine) 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 @@ -3530,6 +3571,11 @@ process_program_headers (FILE *file) 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) @@ -3544,23 +3590,21 @@ process_program_headers (FILE *file) } 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; @@ -4118,6 +4162,16 @@ process_section_headers (FILE *file) 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) \ @@ -5016,8 +5070,7 @@ slurp_ia64_unwind_table (FILE *file, } 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) @@ -5033,16 +5086,8 @@ slurp_ia64_unwind_table (FILE *file, 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")) { @@ -5429,7 +5474,6 @@ slurp_hppa_unwind_table (FILE *file, free (table); /* Third, apply any relocations to the unwind table. */ - for (relsec = section_headers; relsec < section_headers + elf_header.e_shnum; ++relsec) @@ -5445,16 +5489,8 @@ slurp_hppa_unwind_table (FILE *file, 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")) @@ -7820,7 +7856,11 @@ dump_section_as_strings (Elf_Internal_Shdr *section, FILE *file) if (data < end) { +#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; } @@ -7928,95 +7968,344 @@ dump_section_as_bytes (Elf_Internal_Shdr *section, FILE *file) 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 ) 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 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; } @@ -8029,63 +8318,41 @@ debug_apply_rela_addends (void *file, 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 @@ -8111,7 +8378,7 @@ load_debug_section (enum dwarf_section_display_enum debug, void *file) 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; } @@ -8550,6 +8817,32 @@ display_power_gnu_attribute (unsigned char *p, int tag) 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 @@ -8598,6 +8891,9 @@ display_mips_gnu_attribute (unsigned char *p, int tag) case 3: printf ("Soft float\n"); break; + case 4: + printf ("64-bit float (-mips32r2 -mfp64)\n"); + break; default: printf ("??? (%d)\n", val); break; @@ -9280,6 +9576,8 @@ get_note_type (unsigned e_type) 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: @@ -9688,8 +9986,6 @@ get_file_header (FILE *file) get_64bit_section_headers (file, 1); } - is_relocatable = elf_header.e_type == ET_REL; - return 1; }