X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf32-ip2k.c;h=820e1461fcb6dba02cd4009fbc2afd2fefd1ba3f;hb=1d3843e0b714cfceed7fb3604ce7b88f0beb47e9;hp=135ef1314ba58948b099ab35ef6b08260fe68836;hpb=01f0fe5e0450edf168c1f612feb93cf588e4e7ea;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-ip2k.c b/bfd/elf32-ip2k.c index 135ef1314b..820e1461fc 100644 --- a/bfd/elf32-ip2k.c +++ b/bfd/elf32-ip2k.c @@ -1,12 +1,11 @@ /* Ubicom IP2xxx specific support for 32-bit ELF - Copyright 2000, 2001, 2002, 2003, 2004, 2005 - Free Software Foundation, Inc. + Copyright (C) 2000-2016 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -19,8 +18,8 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "libbfd.h" #include "elf-bfd.h" #include "elf/ip2k.h" @@ -142,7 +141,7 @@ static reloc_howto_type ip2k_elf_howto_table [] = pr) /* pcrel_offset */ /* This reloc does nothing. */ - IP2K_HOWTO (R_IP2K_NONE, 0,2,32, FALSE, 0, "R_IP2K_NONE", 0, 0), + IP2K_HOWTO (R_IP2K_NONE, 0,3,0, FALSE, 0, "R_IP2K_NONE", 0, 0), /* A 16 bit absolute relocation. */ IP2K_HOWTO (R_IP2K_16, 0,1,16, FALSE, 0, "R_IP2K_16", 0, 0xffff), /* A 32 bit absolute relocation. */ @@ -223,6 +222,21 @@ ip2k_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, return NULL; } +static reloc_howto_type * +ip2k_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) +{ + unsigned int i; + + for (i = 0; + i < sizeof (ip2k_elf_howto_table) / sizeof (ip2k_elf_howto_table[0]); + i++) + if (ip2k_elf_howto_table[i].name != NULL + && strcasecmp (ip2k_elf_howto_table[i].name, r_name) == 0) + return &ip2k_elf_howto_table[i]; + + return NULL; +} + static void ip2k_get_mem (bfd *abfd ATTRIBUTE_UNUSED, bfd_byte *addr, @@ -332,8 +346,8 @@ ip2k_is_switch_table_128 (bfd *abfd ATTRIBUTE_UNUSED, bfd_byte *contents) { bfd_byte code[4]; - int index = 0; - + int table_index = 0; + /* Check current page-jmp. */ if (addr + 4 > sec->size) return -1; @@ -343,7 +357,7 @@ ip2k_is_switch_table_128 (bfd *abfd ATTRIBUTE_UNUSED, if ((! IS_PAGE_OPCODE (code + 0)) || (! IS_JMP_OPCODE (code + 2))) return -1; - + /* Search back. */ while (1) { @@ -354,13 +368,13 @@ ip2k_is_switch_table_128 (bfd *abfd ATTRIBUTE_UNUSED, ip2k_get_mem (abfd, contents + addr - 4, 4, code); if ((IS_ADD_W_WREG_OPCODE (code + 0)) && (IS_ADD_PCL_W_OPCODE (code + 2))) - return index; + return table_index; if ((! IS_PAGE_OPCODE (code + 0)) || (! IS_JMP_OPCODE (code + 2))) return -1; - index++; + table_index++; addr -= 4; } } @@ -412,8 +426,8 @@ ip2k_is_switch_table_256 (bfd *abfd ATTRIBUTE_UNUSED, bfd_byte *contents) { bfd_byte code[16]; - int index = 0; - + int table_index = 0; + /* Check current page-jmp. */ if (addr + 4 > sec->size) return -1; @@ -422,7 +436,7 @@ ip2k_is_switch_table_256 (bfd *abfd ATTRIBUTE_UNUSED, if ((! IS_PAGE_OPCODE (code + 0)) || (! IS_JMP_OPCODE (code + 2))) return -1; - + /* Search back. */ while (1) { @@ -439,7 +453,7 @@ ip2k_is_switch_table_256 (bfd *abfd ATTRIBUTE_UNUSED, && (IS_INC_1SP_OPCODE (code + 10)) && (IS_PAGE_OPCODE (code + 12)) && (IS_JMP_OPCODE (code + 14))) - return index; + return table_index; if ((IS_ADD_W_WREG_OPCODE (code + 2)) && (IS_SNC_OPCODE (code + 4)) @@ -448,13 +462,13 @@ ip2k_is_switch_table_256 (bfd *abfd ATTRIBUTE_UNUSED, && (IS_SNC_OPCODE (code + 10)) && (IS_INC_1SP_OPCODE (code + 12)) && (IS_JMP_OPCODE (code + 14))) - return index; - + return table_index; + if ((! IS_PAGE_OPCODE (code + 0)) || (! IS_JMP_OPCODE (code + 2))) return -1; - index++; + table_index++; addr -= 4; } } @@ -562,7 +576,6 @@ adjust_all_relocations (bfd *abfd, Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Sym *isymbuf, *isym, *isymend; unsigned int shndx; - bfd_byte *contents; Elf_Internal_Rela *irel, *irelend, *irelbase; struct elf_link_hash_entry **sym_hashes; struct elf_link_hash_entry **end_hashes; @@ -574,8 +587,6 @@ adjust_all_relocations (bfd *abfd, shndx = _bfd_elf_section_from_bfd_section (abfd, sec); - contents = elf_section_data (sec)->this_hdr.contents; - irelbase = elf_section_data (sec)->relocs; irelend = irelbase + sec->reloc_count; @@ -646,38 +657,33 @@ adjust_all_relocations (bfd *abfd, if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) { asection *sym_sec; - + /* A local symbol. */ isym = isymbuf + ELF32_R_SYM (irel->r_info); sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); - + if (sym_sec == sec) { const char *name; - unsigned long strx; - unsigned char type, other; - unsigned short desc; + unsigned char type; bfd_vma value; bfd_vma baseaddr = BASEADDR (sec); bfd_vma symval = BASEADDR (sym_sec) + isym->st_value + irel->r_addend; - + if ((baseaddr + addr) <= symval && symval <= (baseaddr + endaddr)) irel->r_addend += count; /* Go hunt up a function and fix its line info if needed. */ - stabp = stabcontents + irel->r_offset - 8; + stabp = stabcontents + irel->r_offset - 8; /* Go pullout the stab entry. */ - strx = bfd_h_get_32 (abfd, stabp + STRDXOFF); type = bfd_h_get_8 (abfd, stabp + TYPEOFF); - other = bfd_h_get_8 (abfd, stabp + OTHEROFF); - desc = bfd_h_get_16 (abfd, stabp + DESCOFF); value = bfd_h_get_32 (abfd, stabp + VALOFF); - + name = bfd_get_stab_name (type); - + if (strcmp (name, "FUN") == 0) { int function_adjusted = 0; @@ -691,10 +697,7 @@ adjust_all_relocations (bfd *abfd, for (;stabp < stabend; stabp += STABSIZE) { /* Go pullout the stab entry. */ - strx = bfd_h_get_32 (abfd, stabp + STRDXOFF); type = bfd_h_get_8 (abfd, stabp + TYPEOFF); - other = bfd_h_get_8 (abfd, stabp + OTHEROFF); - desc = bfd_h_get_16 (abfd, stabp + DESCOFF); value = bfd_h_get_32 (abfd, stabp + VALOFF); name = bfd_get_stab_name (type); @@ -706,7 +709,7 @@ adjust_all_relocations (bfd *abfd, { /* Adjust the value. */ value += count; - + /* We need to put it back. */ bfd_h_put_32 (abfd, value,stabp + VALOFF); } @@ -815,10 +818,10 @@ ip2k_delete_page_insn (bfd *abfd ATTRIBUTE_UNUSED, /* Delete the PAGE insn. */ if (!ip2k_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 2)) return FALSE; - + /* Modified => will need to iterate relaxation again. */ *again = TRUE; - + return TRUE; } @@ -833,7 +836,7 @@ ip2k_relax_switch_table_128 (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Rela *ireltest = irel; bfd_byte code[4]; bfd_vma addr; - + /* Test all page instructions. */ addr = irel->r_offset; while (1) @@ -904,7 +907,7 @@ ip2k_relax_switch_table_256 (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Rela *ireltest = irel; bfd_byte code[12]; bfd_vma addr; - + /* Test all page instructions. */ addr = irel->r_offset; @@ -991,7 +994,7 @@ ip2k_elf_relax_section_page (bfd *abfd, Elf_Internal_Rela *irel; int switch_table_128; int switch_table_256; - + /* Walk thru the section looking for relaxation opportunities. */ for (irel = misc->irelbase; irel < irelend; irel++) { @@ -1074,7 +1077,6 @@ ip2k_elf_relax_section (bfd *abfd, static bfd_boolean new_pass = FALSE; static bfd_boolean changed = FALSE; struct misc misc; - asection *stab; /* Assume nothing changes. */ *again = FALSE; @@ -1094,7 +1096,7 @@ ip2k_elf_relax_section (bfd *abfd, /* We don't have to do anything for a relocatable link, if this section does not have relocs, or if this is not a code section. */ - if (link_info->relocatable + if (bfd_link_relocatable (link_info) || (sec->flags & SEC_RELOC) == 0 || sec->reloc_count == 0 || (sec->flags & SEC_CODE) == 0) @@ -1107,18 +1109,6 @@ ip2k_elf_relax_section (bfd *abfd, if (internal_relocs == NULL) goto error_return; - /* Make sure the stac.rela stuff gets read in. */ - stab = bfd_get_section_by_name (abfd, ".stab"); - - if (stab) - { - /* So stab does exits. */ - Elf_Internal_Rela * irelbase; - - irelbase = _bfd_elf_link_read_relocs (abfd, stab, NULL, NULL, - link_info->keep_memory); - } - /* Get section contents cached copy if it exists. */ if (contents == NULL) { @@ -1249,6 +1239,11 @@ ip2k_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED, unsigned int r_type; r_type = ELF32_R_TYPE (dst->r_info); + if (r_type >= (unsigned int) R_IP2K_max) + { + _bfd_error_handler (_("%B: invalid IP2K reloc number: %d"), abfd, r_type); + r_type = 0; + } cache_ptr->howto = & ip2k_elf_howto_table [r_type]; } @@ -1399,9 +1394,6 @@ ip2k_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, Elf_Internal_Rela *rel; Elf_Internal_Rela *relend; - if (info->relocatable) - return TRUE; - symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); relend = relocs + input_section->reloc_count; @@ -1418,10 +1410,9 @@ ip2k_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, const char * name = NULL; int r_type; - /* This is a final link. */ r_type = ELF32_R_TYPE (rel->r_info); r_symndx = ELF32_R_SYM (rel->r_info); - howto = ip2k_elf_howto_table + ELF32_R_TYPE (rel->r_info); + howto = ip2k_elf_howto_table + r_type; h = NULL; sym = NULL; sec = NULL; @@ -1438,17 +1429,24 @@ ip2k_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, } else { - bfd_boolean warned; + bfd_boolean warned, ignored; bfd_boolean unresolved_reloc; RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, r_symndx, symtab_hdr, sym_hashes, h, sec, relocation, - unresolved_reloc, warned); + unresolved_reloc, warned, ignored); name = h->root.root.string; } + if (sec != NULL && discarded_section (sec)) + RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, + rel, 1, relend, howto, 0, contents); + + if (bfd_link_relocatable (info)) + continue; + /* Finally, the sole IP2K-specific part. */ r = ip2k_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation); @@ -1460,13 +1458,13 @@ ip2k_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, switch (r) { case bfd_reloc_overflow: - r = info->callbacks->reloc_overflow + (*info->callbacks->reloc_overflow) (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0, input_bfd, input_section, rel->r_offset); break; case bfd_reloc_undefined: - r = info->callbacks->undefined_symbol + (*info->callbacks->undefined_symbol) (info, name, input_bfd, input_section, rel->r_offset, TRUE); break; @@ -1491,65 +1489,15 @@ ip2k_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, } if (msg) - r = info->callbacks->warning - (info, msg, name, input_bfd, input_section, rel->r_offset); - - if (! r) - return FALSE; + (*info->callbacks->warning) (info, msg, name, input_bfd, + input_section, rel->r_offset); } } return TRUE; } -static asection * -ip2k_elf_gc_mark_hook (asection *sec, - struct bfd_link_info *info ATTRIBUTE_UNUSED, - Elf_Internal_Rela *rel, - struct elf_link_hash_entry *h, - Elf_Internal_Sym *sym) -{ - if (h != NULL) - { - switch (ELF32_R_TYPE (rel->r_info)) - { - default: - switch (h->root.type) - { - case bfd_link_hash_defined: - case bfd_link_hash_defweak: - return h->root.u.def.section; - - case bfd_link_hash_common: - return h->root.u.c.p->section; - - default: - break; - } - } - } - else - { - if (!(elf_bad_symtab (sec->owner) - && ELF_ST_BIND (sym->st_info) != STB_LOCAL) - && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE) - && sym->st_shndx != SHN_COMMON)) - return bfd_section_from_elf_index (sec->owner, sym->st_shndx); - } - return NULL; -} - -static bfd_boolean -ip2k_elf_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED, - struct bfd_link_info *info ATTRIBUTE_UNUSED, - asection *sec ATTRIBUTE_UNUSED, - const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED) -{ - /* We don't use got and plt entries for ip2k. */ - return TRUE; -} - -#define TARGET_BIG_SYM bfd_elf32_ip2k_vec +#define TARGET_BIG_SYM ip2k_elf32_vec #define TARGET_BIG_NAME "elf32-ip2k" #define ELF_ARCH bfd_arch_ip2k @@ -1562,12 +1510,11 @@ ip2k_elf_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED, #define elf_backend_can_gc_sections 1 #define elf_backend_rela_normal 1 -#define elf_backend_gc_mark_hook ip2k_elf_gc_mark_hook -#define elf_backend_gc_sweep_hook ip2k_elf_gc_sweep_hook #define elf_backend_relocate_section ip2k_elf_relocate_section #define elf_symbol_leading_char '_' #define bfd_elf32_bfd_reloc_type_lookup ip2k_reloc_type_lookup +#define bfd_elf32_bfd_reloc_name_lookup ip2k_reloc_name_lookup #define bfd_elf32_bfd_relax_section ip2k_elf_relax_section #include "elf32-target.h"