X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf32-ip2k.c;h=c0c8b8ec9a71b2b381ab5e9adf17ab535459b6f8;hb=5f8989944880cad1bfffab3801214a0a9b67b72e;hp=fd261880aaf1d94768c2d7c70c4a86fafe2b66f1;hpb=07adf1816db141e2cc9c0cd5d9a6aa1a712bc979;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-ip2k.c b/bfd/elf32-ip2k.c index fd261880aa..c0c8b8ec9a 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, 2006 - Free Software Foundation, Inc. + Copyright (C) 2000-2020 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" @@ -31,7 +30,7 @@ struct misc { Elf_Internal_Shdr * symtab_hdr; Elf_Internal_Rela * irelbase; - bfd_byte * contents; + bfd_byte * contents; Elf_Internal_Sym * isymbuf; }; @@ -127,22 +126,22 @@ static const struct ip2k_opcode ip2k_skip_opcodes[] = static reloc_howto_type ip2k_elf_howto_table [] = { #define IP2K_HOWTO(t,rs,s,bs,pr,bp,name,sm,dm) \ - HOWTO(t, /* type */ \ - rs, /* rightshift */ \ - s, /* size (0 = byte, 1 = short, 2 = long) */ \ - bs, /* bitsize */ \ - pr, /* pc_relative */ \ - bp, /* bitpos */ \ - complain_overflow_dont,/* complain_on_overflow */ \ - bfd_elf_generic_reloc,/* special_function */ \ - name, /* name */ \ - FALSE, /* partial_inplace */ \ - sm, /* src_mask */ \ - dm, /* dst_mask */ \ - pr) /* pcrel_offset */ + HOWTO(t, /* type */ \ + rs, /* rightshift */ \ + s, /* size (0 = byte, 1 = short, 2 = long) */ \ + bs, /* bitsize */ \ + pr, /* pc_relative */ \ + bp, /* bitpos */ \ + complain_overflow_dont,/* complain_on_overflow */ \ + bfd_elf_generic_reloc,/* special_function */ \ + name, /* name */ \ + FALSE, /* partial_inplace */ \ + sm, /* src_mask */ \ + dm, /* dst_mask */ \ + 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, @@ -300,30 +314,30 @@ symbol_value (bfd *abfd, the prologue of a switch dispatch table with fewer than 128 entries. - sc - page $nnn0 - jmp $nnn0 - add w,wreg - add pcl,w + sc + page $nnn0 + jmp $nnn0 + add w,wreg + add pcl,w addr=> - page $nnn1 - jmp $nnn1 - page $nnn2 - jmp $nnn2 - ... - page $nnnN - jmp $nnnN + page $nnn1 + jmp $nnn1 + page $nnn2 + jmp $nnn2 + ... + page $nnnN + jmp $nnnN After relaxation. - sc - page $nnn0 - jmp $nnn0 - add pcl,w + sc + page $nnn0 + jmp $nnn0 + add pcl,w addr=> - jmp $nnn1 - jmp $nnn2 - ... - jmp $nnnN */ + jmp $nnn1 + jmp $nnn2 + ... + jmp $nnnN */ static int ip2k_is_switch_table_128 (bfd *abfd ATTRIBUTE_UNUSED, @@ -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; } } @@ -370,40 +384,40 @@ ip2k_is_switch_table_128 (bfd *abfd ATTRIBUTE_UNUSED, 256 entries but more than 127. Before relaxation. - push %lo8insn(label) ; Push address of table - push %hi8insn(label) - add w,wreg ; index*2 => offset - snc ; CARRY SET? - inc 1(sp) ; Propagate MSB into table address - add 2(sp),w ; Add low bits of offset to table address - snc ; and handle any carry-out - inc 1(sp) + push %lo8insn(label) ; Push address of table + push %hi8insn(label) + add w,wreg ; index*2 => offset + snc ; CARRY SET? + inc 1(sp) ; Propagate MSB into table address + add 2(sp),w ; Add low bits of offset to table address + snc ; and handle any carry-out + inc 1(sp) addr=> - page __indjmp ; Do an indirect jump to that location - jmp __indjmp - label: ; case dispatch table starts here - page $nnn1 - jmp $nnn1 - page $nnn2 - jmp $nnn2 - ... - page $nnnN - jmp $nnnN + page __indjmp ; Do an indirect jump to that location + jmp __indjmp + label: ; case dispatch table starts here + page $nnn1 + jmp $nnn1 + page $nnn2 + jmp $nnn2 + ... + page $nnnN + jmp $nnnN After relaxation. - push %lo8insn(label) ; Push address of table - push %hi8insn(label) - add 2(sp),w ; Add low bits of offset to table address - snc ; and handle any carry-out - inc 1(sp) + push %lo8insn(label) ; Push address of table + push %hi8insn(label) + add 2(sp),w ; Add low bits of offset to table address + snc ; and handle any carry-out + inc 1(sp) addr=> - page __indjmp ; Do an indirect jump to that location - jmp __indjmp - label: ; case dispatch table starts here - jmp $nnn1 - jmp $nnn2 - ... - jmp $nnnN */ + page __indjmp ; Do an indirect jump to that location + jmp __indjmp + label: ; case dispatch table starts here + jmp $nnn1 + jmp $nnn2 + ... + jmp $nnnN */ static int ip2k_is_switch_table_256 (bfd *abfd ATTRIBUTE_UNUSED, @@ -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; } } @@ -501,12 +515,12 @@ ip2k_nominal_page_bits (bfd *abfd ATTRIBUTE_UNUSED, /* Found a page instruction, check if conditional. */ if (addr >= 2) - { + { ip2k_get_mem (abfd, contents + addr - 2, 2, code); - if (IS_SKIP_OPCODE (code)) + if (IS_SKIP_OPCODE (code)) /* Page is conditional. */ continue; - } + } /* Unconditional page instruction => page bits should be correct. */ return page; @@ -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,40 +587,38 @@ 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; for (irel = irelbase; irel < irelend; irel++) { if (ELF32_R_TYPE (irel->r_info) != R_IP2K_NONE) - { - /* Get the value of the symbol referred to by the reloc. */ - if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) - { - asection *sym_sec; + { + /* Get the value of the symbol referred to by the reloc. */ + if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) + { + asection *sym_sec; - /* A local symbol. */ + /* A local symbol. */ isym = isymbuf + ELF32_R_SYM (irel->r_info); - sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); + sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); - if (isym->st_shndx == shndx) - { - bfd_vma baseaddr = BASEADDR (sec); - bfd_vma symval = BASEADDR (sym_sec) + isym->st_value - + irel->r_addend; + if (isym->st_shndx == shndx) + { + bfd_vma baseaddr = BASEADDR (sec); + bfd_vma symval = BASEADDR (sym_sec) + isym->st_value + + irel->r_addend; - if ((baseaddr + addr + noadj) <= symval - && symval < (baseaddr + endaddr)) - irel->r_addend += count; - } - } - } + if ((baseaddr + addr + noadj) <= symval + && symval < (baseaddr + endaddr)) + irel->r_addend += count; + } + } + } /* Do this only for PC space relocations. */ if (addr <= irel->r_offset && irel->r_offset < endaddr) - irel->r_offset += count; + irel->r_offset += count; } /* Now fix the stab relocations. */ @@ -627,8 +638,7 @@ adjust_all_relocations (bfd *abfd, { if (!bfd_malloc_and_get_section (abfd, stab, &stabcontents)) { - if (stabcontents != NULL) - free (stabcontents); + free (stabcontents); return; } @@ -646,38 +656,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 +696,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 +708,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); } @@ -767,8 +769,8 @@ adjust_all_relocations (bfd *abfd, || sym_hash->root.type == bfd_link_hash_defweak) && sym_hash->root.u.def.section == sec) { - if (addr <= sym_hash->root.u.def.value - && sym_hash->root.u.def.value < endaddr) + if (addr <= sym_hash->root.u.def.value + && sym_hash->root.u.def.value < endaddr) sym_hash->root.u.def.value += count; } } @@ -815,10 +817,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 +835,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) @@ -847,18 +849,18 @@ ip2k_relax_switch_table_128 (bfd *abfd ATTRIBUTE_UNUSED, break; /* Validate relocation entry (every entry should have a matching - relocation entry). */ + relocation entry). */ if (ireltest >= irelend) - { + { _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information.")); - return FALSE; - } + return FALSE; + } if (ireltest->r_offset != addr) - { + { _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information.")); - return FALSE; - } + return FALSE; + } if (! ip2k_test_page_insn (abfd, sec, ireltest, misc)) /* Un-removable page insn => nothing can be done. */ @@ -904,7 +906,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; @@ -920,18 +922,18 @@ ip2k_relax_switch_table_256 (bfd *abfd ATTRIBUTE_UNUSED, break; /* Validate relocation entry (every entry should have a matching - relocation entry). */ + relocation entry). */ if (ireltest >= irelend) - { - _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information.")); - return FALSE; - } + { + _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information.")); + return FALSE; + } if (ireltest->r_offset != addr) - { - _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information.")); - return FALSE; - } + { + _bfd_error_handler (_("ip2k relaxer: switch table without complete matching relocation information.")); + return FALSE; + } if (!ip2k_test_page_insn (abfd, sec, ireltest, misc)) /* Un-removable page insn => nothing can be done. */ @@ -991,7 +993,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 +1076,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 +1095,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 +1108,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) { @@ -1154,9 +1143,9 @@ ip2k_elf_relax_section (bfd *abfd, if ((pass == 1) || (new_pass && !changed)) { /* On the first pass we simply search for the lowest page that - we havn't relaxed yet. Note that the pass count is reset - each time a page is complete in order to move on to the next page. - If we can't find any more pages then we are finished. */ + we havn't relaxed yet. Note that the pass count is reset + each time a page is complete in order to move on to the next page. + If we can't find any more pages then we are finished. */ if (new_pass) { pass = 1; @@ -1191,7 +1180,7 @@ ip2k_elf_relax_section (bfd *abfd, if ((BASEADDR (sec) + sec->size >= page_start) && (BASEADDR (sec) <= page_end)) { - if (!ip2k_elf_relax_section_page (abfd, sec, &changed, &misc, page_start, page_end)) + if (!ip2k_elf_relax_section_page (abfd, sec, &changed, &misc, page_start, page_end)) return FALSE; } *again = TRUE; @@ -1220,36 +1209,41 @@ ip2k_elf_relax_section (bfd *abfd, } } - if (internal_relocs != NULL - && elf_section_data (sec)->relocs != internal_relocs) + if (elf_section_data (sec)->relocs != internal_relocs) free (internal_relocs); return TRUE; error_return: - if (isymbuf != NULL - && symtab_hdr->contents != (unsigned char *) isymbuf) + if (symtab_hdr->contents != (unsigned char *) isymbuf) free (isymbuf); - if (contents != NULL - && elf_section_data (sec)->this_hdr.contents != contents) + if (elf_section_data (sec)->this_hdr.contents != contents) free (contents); - if (internal_relocs != NULL - && elf_section_data (sec)->relocs != internal_relocs) + if (elf_section_data (sec)->relocs != internal_relocs) free (internal_relocs); return FALSE; } /* Set the howto pointer for a IP2K ELF reloc. */ -static void -ip2k_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED, +static bfd_boolean +ip2k_info_to_howto_rela (bfd * abfd, arelent * cache_ptr, Elf_Internal_Rela * dst) { unsigned int r_type; r_type = ELF32_R_TYPE (dst->r_info); + if (r_type >= (unsigned int) R_IP2K_max) + { + /* xgettext:c-format */ + _bfd_error_handler (_("%pB: unsupported relocation type %#x"), + abfd, r_type); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } cache_ptr->howto = & ip2k_elf_howto_table [r_type]; + return TRUE; } /* Perform a single relocation. @@ -1257,11 +1251,11 @@ ip2k_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED, static bfd_reloc_status_type ip2k_final_link_relocate (reloc_howto_type * howto, - bfd * input_bfd, - asection * input_section, - bfd_byte * contents, + bfd * input_bfd, + asection * input_section, + bfd_byte * contents, Elf_Internal_Rela * rel, - bfd_vma relocation) + bfd_vma relocation) { static bfd_vma page_addr = 0; @@ -1297,16 +1291,19 @@ ip2k_final_link_relocate (reloc_howto_type * howto, /* No preceding page instruction, verify that it isn't needed. */ if (PAGENO (relocation + rel->r_addend) != ip2k_nominal_page_bits (input_bfd, input_section, - rel->r_offset, contents)) - _bfd_error_handler (_("ip2k linker: missing page instruction at 0x%08lx (dest = 0x%08lx)."), - BASEADDR (input_section) + rel->r_offset, - relocation + rel->r_addend); - } + rel->r_offset, contents)) + /* xgettext:c-format */ + _bfd_error_handler + (_("ip2k linker: missing page instruction " + "at %#" PRIx64 " (dest = %#" PRIx64 ")"), + (uint64_t) (BASEADDR (input_section) + rel->r_offset), + (uint64_t) (relocation + rel->r_addend)); + } else if (ip2k_relaxed) - { - /* Preceding page instruction. Verify that the page instruction is - really needed. One reason for the relaxation to miss a page is if - the section is not marked as executable. */ + { + /* Preceding page instruction. Verify that the page instruction is + really needed. One reason for the relaxation to miss a page is if + the section is not marked as executable. */ if (!ip2k_is_switch_table_128 (input_bfd, input_section, rel->r_offset - 2, contents) && !ip2k_is_switch_table_256 (input_bfd, input_section, @@ -1314,10 +1311,13 @@ ip2k_final_link_relocate (reloc_howto_type * howto, && (PAGENO (relocation + rel->r_addend) == ip2k_nominal_page_bits (input_bfd, input_section, rel->r_offset - 2, contents))) - _bfd_error_handler (_("ip2k linker: redundant page instruction at 0x%08lx (dest = 0x%08lx)."), - page_addr, - relocation + rel->r_addend); - } + /* xgettext:c-format */ + _bfd_error_handler + (_("ip2k linker: redundant page instruction " + "at %#" PRIx64 " (dest = %#" PRIx64 ")"), + (uint64_t) page_addr, + (uint64_t) (relocation + rel->r_addend)); + } if ((relocation & IP2K_INSN_MASK) == IP2K_INSN_VALUE) relocation &= ~IP2K_INSN_MASK; else @@ -1399,29 +1399,25 @@ 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; for (rel = relocs; rel < relend; rel ++) { - reloc_howto_type * howto; - unsigned long r_symndx; - Elf_Internal_Sym * sym; - asection * sec; + reloc_howto_type * howto; + unsigned long r_symndx; + Elf_Internal_Sym * sym; + asection * sec; struct elf_link_hash_entry * h; - bfd_vma relocation; - bfd_reloc_status_type r; - const char * name = NULL; - int r_type; + bfd_vma relocation; + bfd_reloc_status_type r; + 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; @@ -1434,21 +1430,28 @@ ip2k_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name); - name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name; + name = name == NULL ? bfd_section_name (sec) : name; } 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 +1463,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; @@ -1475,10 +1478,10 @@ ip2k_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, break; /* This is how ip2k_final_link_relocate tells us of a non-kosher - reference between insn & data address spaces. */ + reference between insn & data address spaces. */ case bfd_reloc_notsupported: - if (sym != NULL) /* Only if it's not an unresolved symbol. */ - msg = _("unsupported relocation between data/insn address spaces"); + if (sym != NULL) /* Only if it's not an unresolved symbol. */ + msg = _("unsupported relocation between data/insn address spaces"); break; case bfd_reloc_dangerous: @@ -1491,18 +1494,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; } -#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 @@ -1513,12 +1513,13 @@ ip2k_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, #define elf_info_to_howto_rel NULL #define elf_info_to_howto ip2k_info_to_howto_rela -#define elf_backend_can_gc_sections 1 +#define elf_backend_can_gc_sections 1 #define elf_backend_rela_normal 1 #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"