X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Felf32-xstormy16.c;h=53c40ad45407f085e87bb95e8cd252ae547d0ad0;hb=78bc95e3ba62e558030ff978725cdbbb48564f96;hp=5d3d171eeac3dec291bf1119641d7edb52fe18a1;hpb=9ad5cbcfb23cb74d34bd04f88f4e47c0f5de5155;p=binutils-gdb.git diff --git a/bfd/elf32-xstormy16.c b/bfd/elf32-xstormy16.c index 5d3d171eeac..53c40ad4540 100644 --- a/bfd/elf32-xstormy16.c +++ b/bfd/elf32-xstormy16.c @@ -1,60 +1,73 @@ -/* XSTORMY16-specific support for 32-bit ELF. - Copyright (C) 2000, 2001 Free Software Foundation, Inc. +/* Xstormy16-specific support for 32-bit ELF. + Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. -This file is part of BFD, the Binary File Descriptor library. + 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 -(at your option) any later version. + 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 3 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + 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/xstormy16.h" +#include "libiberty.h" + +/* Handle the R_XSTORMY16_24 reloc, which has an odd bit arrangement. */ + +static bfd_reloc_status_type +xstormy16_elf_24_reloc (bfd *abfd, + arelent *reloc_entry, + asymbol *symbol, + void * data, + asection *input_section, + bfd *output_bfd, + char **error_message ATTRIBUTE_UNUSED) +{ + bfd_vma relocation, x; + + if (output_bfd != NULL) + { + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } + + if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) + return bfd_reloc_outofrange; + + if (bfd_is_com_section (symbol->section)) + relocation = 0; + else + relocation = symbol->value; + + relocation += symbol->section->output_section->vma; + relocation += symbol->section->output_offset; + relocation += reloc_entry->addend; + + x = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); + x &= 0x0000ff00; + x |= relocation & 0xff; + x |= (relocation << 8) & 0xffff0000; + bfd_put_32 (abfd, x, (bfd_byte *) data + reloc_entry->address); -/* Forward declarations. */ -static reloc_howto_type * xstormy16_reloc_type_lookup - PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); -static void xstormy16_info_to_howto_rela - PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *)); -static bfd_reloc_status_type xstormy16_elf_24_reloc - PARAMS ((bfd *abfd, arelent *reloc_entry, asymbol *symbol, - PTR data, asection *input_section, bfd *output_bfd, - char **error_message)); -static boolean xstormy16_elf_check_relocs - PARAMS ((bfd *, struct bfd_link_info *, asection *, - const Elf_Internal_Rela *)); -static boolean xstormy16_relax_plt_check - PARAMS ((struct elf_link_hash_entry *, PTR)); -static boolean xstormy16_relax_plt_realloc - PARAMS ((struct elf_link_hash_entry *, PTR)); -static boolean xstormy16_elf_relax_section - PARAMS ((bfd *abfd, asection *sec, struct bfd_link_info *link_info, - boolean *again)); -static boolean xstormy16_elf_always_size_sections - PARAMS ((bfd *, struct bfd_link_info *)); -static boolean xstormy16_elf_relocate_section - PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, - Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); -static boolean xstormy16_elf_finish_dynamic_sections - PARAMS((bfd *, struct bfd_link_info *)); -static boolean xstormy16_elf_gc_sweep_hook - PARAMS ((bfd *, struct bfd_link_info *, asection *, - const Elf_Internal_Rela *)); -static asection * xstormy16_elf_gc_mark_hook - PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *, - struct elf_link_hash_entry *, Elf_Internal_Sym *)); + if (relocation & ~ (bfd_vma) 0xffffff) + return bfd_reloc_overflow; + + return bfd_reloc_ok; +} static reloc_howto_type xstormy16_elf_howto_table [] = { @@ -63,152 +76,197 @@ static reloc_howto_type xstormy16_elf_howto_table [] = 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_XSTORMY16_NONE", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* A 32 bit absolute relocation. */ HOWTO (R_XSTORMY16_32, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_XSTORMY16_32", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ - + FALSE), /* pcrel_offset */ + /* A 16 bit absolute relocation. */ HOWTO (R_XSTORMY16_16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_XSTORMY16_16", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ - + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* An 8 bit absolute relocation. */ - HOWTO (R_XSTORMY16_8, /* type */ + HOWTO (R_XSTORMY16_8, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 8, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ + complain_overflow_unsigned, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_XSTORMY16_8", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ - 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ - + 0xff, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* A 32 bit pc-relative relocation. */ HOWTO (R_XSTORMY16_PC32, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ - true, /* pc_relative */ + TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_XSTORMY16_PC32", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ - true), /* pcrel_offset */ - + TRUE), /* pcrel_offset */ + /* A 16 bit pc-relative relocation. */ HOWTO (R_XSTORMY16_PC16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - true, /* pc_relative */ + TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_XSTORMY16_PC16", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ - true), /* pcrel_offset */ - + TRUE), /* pcrel_offset */ + /* An 8 bit pc-relative relocation. */ HOWTO (R_XSTORMY16_PC8, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 8, /* bitsize */ - true, /* pc_relative */ + TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_XSTORMY16_PC8", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ - true), /* pcrel_offset */ - + TRUE), /* pcrel_offset */ + /* A 12-bit pc-relative relocation suitable for the branch instructions. */ HOWTO (R_XSTORMY16_REL_12, /* type */ 1, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 11, /* bitsize */ - true, /* pc_relative */ + TRUE, /* pc_relative */ 1, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_XSTORMY16_REL_12", /* name */ - true, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ - 0x0fff, /* dst_mask */ - true), /* pcrel_offset */ - + 0x0ffe, /* dst_mask */ + TRUE), /* pcrel_offset */ + /* A 24-bit absolute relocation suitable for the jump instructions. */ HOWTO (R_XSTORMY16_24, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 24, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_unsigned, /* complain_on_overflow */ xstormy16_elf_24_reloc, /* special_function */ "R_XSTORMY16_24", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0, /* src_mask */ 0xffff00ff, /* dst_mask */ - true), /* pcrel_offset */ - + TRUE), /* pcrel_offset */ + /* A 16 bit absolute relocation to a function pointer. */ HOWTO (R_XSTORMY16_FPTR16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_XSTORMY16_FPTR16", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ + + /* Low order 16 bit value of a high memory address. */ + HOWTO (R_XSTORMY16_LO16, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_XSTORMY16_LO16", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* High order 16 bit value of a high memory address. */ + HOWTO (R_XSTORMY16_HI16, /* type */ + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_XSTORMY16_HI16", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A 12 bit absolute relocation. */ + HOWTO (R_XSTORMY16_12, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_XSTORMY16_12", /* name */ + FALSE, /* partial_inplace */ + 0x0000, /* src_mask */ + 0x0fff, /* dst_mask */ + FALSE), /* pcrel_offset */ }; - + static reloc_howto_type xstormy16_elf_howto_table2 [] = { /* GNU extension to record C++ vtable hierarchy */ @@ -216,83 +274,116 @@ static reloc_howto_type xstormy16_elf_howto_table2 [] = 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ NULL, /* special_function */ "R_XSTORMY16_GNU_VTINHERIT", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* GNU extension to record C++ vtable member usage */ HOWTO (R_XSTORMY16_GNU_VTENTRY, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ _bfd_elf_rel_vtable_reloc_fn, /* special_function */ "R_XSTORMY16_GNU_VTENTRY", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ - false), /* pcrel_offset */ - + FALSE), /* pcrel_offset */ + }; /* Map BFD reloc types to XSTORMY16 ELF reloc types. */ -struct xstormy16_reloc_map +typedef struct xstormy16_reloc_map { - bfd_reloc_code_real_type bfd_reloc_val; - unsigned int xstormy16_reloc_val; -}; + bfd_reloc_code_real_type bfd_reloc_val; + unsigned int xstormy16_reloc_val; + reloc_howto_type * table; +} reloc_map; -static const struct xstormy16_reloc_map xstormy16_reloc_map [] = +static const reloc_map xstormy16_reloc_map [] = { - { BFD_RELOC_NONE, R_XSTORMY16_NONE }, - { BFD_RELOC_32, R_XSTORMY16_32 }, - { BFD_RELOC_16, R_XSTORMY16_16 }, - { BFD_RELOC_8, R_XSTORMY16_8 }, - { BFD_RELOC_32_PCREL, R_XSTORMY16_PC32 }, - { BFD_RELOC_16_PCREL, R_XSTORMY16_PC16 }, - { BFD_RELOC_8_PCREL, R_XSTORMY16_PC8 }, - { BFD_RELOC_XSTORMY16_REL_12, R_XSTORMY16_REL_12 }, - { BFD_RELOC_XSTORMY16_24, R_XSTORMY16_24 }, - { BFD_RELOC_XSTORMY16_FPTR16, R_XSTORMY16_FPTR16 }, - { BFD_RELOC_VTABLE_INHERIT, R_XSTORMY16_GNU_VTINHERIT }, - { BFD_RELOC_VTABLE_ENTRY, R_XSTORMY16_GNU_VTENTRY }, + { BFD_RELOC_NONE, R_XSTORMY16_NONE, xstormy16_elf_howto_table }, + { BFD_RELOC_32, R_XSTORMY16_32, xstormy16_elf_howto_table }, + { BFD_RELOC_16, R_XSTORMY16_16, xstormy16_elf_howto_table }, + { BFD_RELOC_8, R_XSTORMY16_8, xstormy16_elf_howto_table }, + { BFD_RELOC_32_PCREL, R_XSTORMY16_PC32, xstormy16_elf_howto_table }, + { BFD_RELOC_16_PCREL, R_XSTORMY16_PC16, xstormy16_elf_howto_table }, + { BFD_RELOC_8_PCREL, R_XSTORMY16_PC8, xstormy16_elf_howto_table }, + { BFD_RELOC_XSTORMY16_REL_12, R_XSTORMY16_REL_12, xstormy16_elf_howto_table }, + { BFD_RELOC_XSTORMY16_24, R_XSTORMY16_24, xstormy16_elf_howto_table }, + { BFD_RELOC_XSTORMY16_FPTR16, R_XSTORMY16_FPTR16, xstormy16_elf_howto_table }, + { BFD_RELOC_LO16, R_XSTORMY16_LO16, xstormy16_elf_howto_table }, + { BFD_RELOC_HI16, R_XSTORMY16_HI16, xstormy16_elf_howto_table }, + { BFD_RELOC_XSTORMY16_12, R_XSTORMY16_12, xstormy16_elf_howto_table }, + { BFD_RELOC_VTABLE_INHERIT, R_XSTORMY16_GNU_VTINHERIT, xstormy16_elf_howto_table2 }, + { BFD_RELOC_VTABLE_ENTRY, R_XSTORMY16_GNU_VTENTRY, xstormy16_elf_howto_table2 }, }; static reloc_howto_type * -xstormy16_reloc_type_lookup (abfd, code) - bfd * abfd ATTRIBUTE_UNUSED; - bfd_reloc_code_real_type code; +xstormy16_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, + bfd_reloc_code_real_type code) { unsigned int i; - for (i = sizeof (xstormy16_reloc_map) / sizeof (xstormy16_reloc_map[0]); - --i;) - if (xstormy16_reloc_map [i].bfd_reloc_val == code) - return & xstormy16_elf_howto_table [xstormy16_reloc_map[i].xstormy16_reloc_val]; - + for (i = ARRAY_SIZE (xstormy16_reloc_map); --i;) + { + const reloc_map * entry; + + entry = xstormy16_reloc_map + i; + + if (entry->bfd_reloc_val == code) + return entry->table + (entry->xstormy16_reloc_val + - entry->table[0].type); + } + + return NULL; +} + +static reloc_howto_type * +xstormy16_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, + const char *r_name) +{ + unsigned int i; + + for (i = 0; + i < (sizeof (xstormy16_elf_howto_table) + / sizeof (xstormy16_elf_howto_table[0])); + i++) + if (xstormy16_elf_howto_table[i].name != NULL + && strcasecmp (xstormy16_elf_howto_table[i].name, r_name) == 0) + return &xstormy16_elf_howto_table[i]; + + for (i = 0; + i < (sizeof (xstormy16_elf_howto_table2) + / sizeof (xstormy16_elf_howto_table2[0])); + i++) + if (xstormy16_elf_howto_table2[i].name != NULL + && strcasecmp (xstormy16_elf_howto_table2[i].name, r_name) == 0) + return &xstormy16_elf_howto_table2[i]; + return NULL; } /* Set the howto pointer for an XSTORMY16 ELF reloc. */ static void -xstormy16_info_to_howto_rela (abfd, cache_ptr, dst) - bfd * abfd ATTRIBUTE_UNUSED; - arelent * cache_ptr; - Elf32_Internal_Rela * dst; +xstormy16_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED, + arelent * cache_ptr, + Elf_Internal_Rela * dst) { unsigned int r_type = ELF32_R_TYPE (dst->r_info); - if (r_type <= (unsigned int) R_XSTORMY16_FPTR16) + if (r_type <= (unsigned int) R_XSTORMY16_12) cache_ptr->howto = &xstormy16_elf_howto_table [r_type]; else if (r_type - R_XSTORMY16_GNU_VTINHERIT <= (unsigned int) R_XSTORMY16_GNU_VTENTRY) @@ -301,51 +392,6 @@ xstormy16_info_to_howto_rela (abfd, cache_ptr, dst) else abort (); } - -/* Handle the R_XSTORMY16_24 reloc, which has an odd bit arrangement. */ - -static bfd_reloc_status_type -xstormy16_elf_24_reloc (abfd, reloc_entry, symbol, data, input_section, - output_bfd, error_message) - bfd *abfd; - arelent *reloc_entry; - asymbol *symbol; - PTR data; - asection *input_section; - bfd *output_bfd; - char **error_message ATTRIBUTE_UNUSED; -{ - bfd_vma relocation, x; - - if (output_bfd != NULL) - { - reloc_entry->address += input_section->output_offset; - return bfd_reloc_ok; - } - - if (reloc_entry->address > input_section->_cooked_size) - return bfd_reloc_outofrange; - - if (bfd_is_com_section (symbol->section)) - relocation = 0; - else - relocation = symbol->value; - - relocation += symbol->section->output_section->vma; - relocation += symbol->section->output_offset; - relocation += reloc_entry->addend; - - x = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); - x &= 0x0000ff00; - x |= relocation & 0xff; - x |= (relocation << 8) & 0xffff0000; - bfd_put_32 (abfd, x, (bfd_byte *) data + reloc_entry->address); - - if (relocation & ~ (bfd_vma) 0xffffff) - return bfd_reloc_overflow; - - return bfd_reloc_ok; -} /* We support 16-bit pointers to code above 64k by generating a thunk below 64k containing a JMPF instruction to the final address. We @@ -353,12 +399,11 @@ xstormy16_elf_24_reloc (abfd, reloc_entry, symbol, data, input_section, -relax switch is given, as otherwise we have no idea where the sections will fall in the address space. */ -static boolean -xstormy16_elf_check_relocs (abfd, info, sec, relocs) - bfd *abfd; - struct bfd_link_info *info; - asection *sec; - const Elf_Internal_Rela *relocs; +static bfd_boolean +xstormy16_elf_check_relocs (bfd *abfd, + struct bfd_link_info *info, + asection *sec, + const Elf_Internal_Rela *relocs) { const Elf_Internal_Rela *rel, *relend; struct elf_link_hash_entry **sym_hashes; @@ -367,8 +412,8 @@ xstormy16_elf_check_relocs (abfd, info, sec, relocs) asection *splt; bfd *dynobj; - if (info->relocateable) - return true; + if (info->relocatable) + return TRUE; symtab_hdr = &elf_tdata(abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); @@ -414,18 +459,18 @@ xstormy16_elf_check_relocs (abfd, info, sec, relocs) splt = bfd_get_section_by_name (dynobj, ".plt"); if (splt == NULL) { - splt = bfd_make_section (dynobj, ".plt"); + splt = bfd_make_section_with_flags (dynobj, ".plt", + (SEC_ALLOC + | SEC_LOAD + | SEC_HAS_CONTENTS + | SEC_IN_MEMORY + | SEC_LINKER_CREATED + | SEC_READONLY + | SEC_CODE)); + if (splt == NULL - || ! bfd_set_section_flags (dynobj, splt, - (SEC_ALLOC - | SEC_LOAD - | SEC_HAS_CONTENTS - | SEC_IN_MEMORY - | SEC_LINKER_CREATED - | SEC_READONLY - | SEC_CODE)) || ! bfd_set_section_alignment (dynobj, splt, 1)) - return false; + return FALSE; } } @@ -439,11 +484,11 @@ xstormy16_elf_check_relocs (abfd, info, sec, relocs) unsigned int i; size = symtab_hdr->sh_info * sizeof (bfd_vma); - local_plt_offsets = (bfd_vma *) bfd_alloc (abfd, size); + local_plt_offsets = bfd_alloc (abfd, size); if (local_plt_offsets == NULL) - return false; + return FALSE; elf_local_got_offsets (abfd) = local_plt_offsets; - + for (i = 0; i < symtab_hdr->sh_info; i++) local_plt_offsets[i] = (bfd_vma) -1; } @@ -452,28 +497,30 @@ xstormy16_elf_check_relocs (abfd, info, sec, relocs) if (*offset == (bfd_vma) -1) { - *offset = splt->_raw_size; - splt->_raw_size += 4; + *offset = splt->size; + splt->size += 4; } break; /* This relocation describes the C++ object vtable hierarchy. Reconstruct it for later use during GC. */ case R_XSTORMY16_GNU_VTINHERIT: - if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) - return false; + if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) + return FALSE; break; - + /* This relocation describes which C++ vtable entries are actually used. Record for later use during GC. */ case R_XSTORMY16_GNU_VTENTRY: - if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) - return false; + BFD_ASSERT (h != NULL); + if (h != NULL + && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) + return FALSE; break; } } - return true; + return TRUE; } /* A subroutine of xstormy16_elf_relax_section. If the global symbol H @@ -482,16 +529,17 @@ xstormy16_elf_check_relocs (abfd, info, sec, relocs) struct relax_plt_data { asection *splt; - boolean *again; + bfd_boolean *again; }; -static boolean -xstormy16_relax_plt_check (h, xdata) - struct elf_link_hash_entry *h; - PTR xdata; +static bfd_boolean +xstormy16_relax_plt_check (struct elf_link_hash_entry *h, void * xdata) { struct relax_plt_data *data = (struct relax_plt_data *) xdata; + if (h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + if (h->plt.offset != (bfd_vma) -1) { bfd_vma address; @@ -507,64 +555,59 @@ xstormy16_relax_plt_check (h, xdata) if (address <= 0xffff) { h->plt.offset = -1; - data->splt->_cooked_size -= 4; - *data->again = true; + data->splt->size -= 4; + *data->again = TRUE; } } - return true; + return TRUE; } /* A subroutine of xstormy16_elf_relax_section. If the global symbol H previously had a plt entry, give it a new entry offset. */ -static boolean -xstormy16_relax_plt_realloc (h, xdata) - struct elf_link_hash_entry *h; - PTR xdata; +static bfd_boolean +xstormy16_relax_plt_realloc (struct elf_link_hash_entry *h, void * xdata) { bfd_vma *entry = (bfd_vma *) xdata; + if (h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + if (h->plt.offset != (bfd_vma) -1) { h->plt.offset = *entry; *entry += 4; } - return true; + return TRUE; } -static boolean -xstormy16_elf_relax_section (dynobj, splt, info, again) - bfd *dynobj; - asection *splt; - struct bfd_link_info *info; - boolean *again; +static bfd_boolean +xstormy16_elf_relax_section (bfd *dynobj, + asection *splt, + struct bfd_link_info *info, + bfd_boolean *again) { struct relax_plt_data relax_plt_data; bfd *ibfd; /* Assume nothing changes. */ - *again = false; + *again = FALSE; - if (info->relocateable) - return true; + if (info->relocatable) + return TRUE; /* We only relax the .plt section at the moment. */ if (dynobj != elf_hash_table (info)->dynobj || strcmp (splt->name, ".plt") != 0) - return true; + return TRUE; /* Quick check for an empty plt. */ - if (splt->_raw_size == 0) - return true; - - /* If this is the first time we have been called for this section, - initialize the cooked size. */ - if (splt->_cooked_size == 0) - splt->_cooked_size = splt->_raw_size; + if (splt->size == 0) + return TRUE; - /* Map across all global symbols; see which ones happen to + /* Map across all global symbols; see which ones happen to fall in the low 64k. */ relax_plt_data.splt = splt; relax_plt_data.again = again; @@ -572,105 +615,75 @@ xstormy16_elf_relax_section (dynobj, splt, info, again) &relax_plt_data); /* Likewise for local symbols, though that's somewhat less convenient - as we have walk the list of input bfds and swap in symbol data. */ + as we have to walk the list of input bfds and swap in symbol data. */ for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next) { bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd); Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *shndx_hdr; - Elf32_External_Sym *extsyms; - Elf_External_Sym_Shndx *shndx_buf; + Elf_Internal_Sym *isymbuf = NULL; unsigned int idx; if (! local_plt_offsets) continue; symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; - shndx_hdr = &elf_tdata (ibfd)->symtab_shndx_hdr; - - if (symtab_hdr->contents != NULL) - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - else + if (symtab_hdr->sh_info != 0) { - bfd_size_type amt; - - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf32_External_Sym); - extsyms = (Elf32_External_Sym *) bfd_malloc (amt); - if (extsyms == NULL) - return false; - if (bfd_seek (ibfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) extsyms, amt, ibfd) != amt) - { - error_ret_free_extsyms: - free (extsyms); - return false; - } - } - - shndx_buf = NULL; - if (shndx_hdr->sh_size != 0) - { - bfd_size_type amt; - - amt = symtab_hdr->sh_info; - amt *= sizeof (Elf_External_Sym_Shndx); - shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt); - if (shndx_buf == NULL) - goto error_ret_free_extsyms; - if (bfd_seek (ibfd, shndx_hdr->sh_offset, SEEK_SET) != 0 - || bfd_bread ((PTR) shndx_buf, amt, ibfd) != amt) - { - free (shndx_buf); - goto error_ret_free_extsyms; - } - shndx_hdr->contents = (bfd_byte *) shndx_buf; + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (ibfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) + return FALSE; } for (idx = 0; idx < symtab_hdr->sh_info; ++idx) { - Elf_External_Sym_Shndx *shndx; - Elf_Internal_Sym isym; + Elf_Internal_Sym *isym; asection *tsec; bfd_vma address; if (local_plt_offsets[idx] == (bfd_vma) -1) continue; - shndx = shndx_buf; - if (shndx != NULL) - shndx += idx; - bfd_elf32_swap_symbol_in (ibfd, extsyms + idx, shndx, &isym); - if (isym.st_shndx == SHN_UNDEF) + isym = &isymbuf[idx]; + if (isym->st_shndx == SHN_UNDEF) continue; - else if (isym.st_shndx == SHN_ABS) + else if (isym->st_shndx == SHN_ABS) tsec = bfd_abs_section_ptr; - else if (isym.st_shndx == SHN_COMMON) + else if (isym->st_shndx == SHN_COMMON) tsec = bfd_com_section_ptr; else - tsec = bfd_section_from_elf_index (ibfd, isym.st_shndx); + tsec = bfd_section_from_elf_index (ibfd, isym->st_shndx); address = (tsec->output_section->vma + tsec->output_offset - + isym.st_value); + + isym->st_value); if (address <= 0xffff) { local_plt_offsets[idx] = -1; - splt->_cooked_size -= 4; - *again = true; + splt->size -= 4; + *again = TRUE; } } - if (shndx_buf != NULL) - free (shndx_buf); - - if ((Elf32_External_Sym *) symtab_hdr->contents != extsyms) - free (extsyms); + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + { + if (! info->keep_memory) + free (isymbuf); + else + { + /* Cache the symbols for elf_link_input_bfd. */ + symtab_hdr->contents = (unsigned char *) isymbuf; + } + } } /* If we changed anything, walk the symbols again to reallocate .plt entry addresses. */ - if (*again && splt->_cooked_size > 0) + if (*again && splt->size > 0) { bfd_vma entry = 0; @@ -695,39 +708,34 @@ xstormy16_elf_relax_section (dynobj, splt, info, again) } } - splt->_raw_size = splt->_cooked_size; - return true; + return TRUE; } -static boolean -xstormy16_elf_always_size_sections (output_bfd, info) - bfd *output_bfd ATTRIBUTE_UNUSED; - struct bfd_link_info *info; +static bfd_boolean +xstormy16_elf_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info) { bfd *dynobj; asection *splt; - if (info->relocateable) - return true; + if (info->relocatable) + return TRUE; dynobj = elf_hash_table (info)->dynobj; if (dynobj == NULL) - return true; + return TRUE; splt = bfd_get_section_by_name (dynobj, ".plt"); BFD_ASSERT (splt != NULL); - splt->contents = (bfd_byte *) bfd_zalloc (dynobj, splt->_raw_size); + splt->contents = bfd_zalloc (dynobj, splt->size); if (splt->contents == NULL) - return false; + return FALSE; - return true; + return TRUE; } /* Relocate an XSTORMY16 ELF section. - There is some attempt to make this function usable for many architectures, - both USE_REL and USE_RELA ['twould be nice if such a critter existed], - if only to serve as a learning tool. The RELOCATE_SECTION function is called by the new ELF backend linker to handle the relocations for a section. @@ -737,7 +745,7 @@ xstormy16_elf_always_size_sections (output_bfd, info) zero. This function is responsible for adjusting the section contents as - necessary, and (if using Rela relocs and generating a relocateable + necessary, and (if using Rela relocs and generating a relocatable output file) adjusting the reloc addend as necessary. This function does not have to worry about setting the reloc @@ -751,23 +759,21 @@ xstormy16_elf_always_size_sections (output_bfd, info) The global hash table entry for the global symbols can be found via elf_sym_hashes (input_bfd). - When generating relocateable output, this function must handle + When generating relocatable output, this function must handle STB_LOCAL/STT_SECTION symbols specially. The output symbol is going to be the section symbol corresponding to the output section, which means that the addend must be adjusted accordingly. */ -static boolean -xstormy16_elf_relocate_section (output_bfd, info, input_bfd, input_section, - contents, relocs, local_syms, local_sections) - bfd * output_bfd ATTRIBUTE_UNUSED; - struct bfd_link_info * info; - bfd * input_bfd; - asection * input_section; - bfd_byte * contents; - Elf_Internal_Rela * relocs; - Elf_Internal_Sym * local_syms; - asection ** local_sections; +static bfd_boolean +xstormy16_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, + struct bfd_link_info * info, + bfd * input_bfd, + asection * input_section, + bfd_byte * contents, + Elf_Internal_Rela * relocs, + Elf_Internal_Sym * local_syms, + asection ** local_sections) { Elf_Internal_Shdr * symtab_hdr; struct elf_link_hash_entry ** sym_hashes; @@ -796,92 +802,66 @@ xstormy16_elf_relocate_section (output_bfd, info, input_bfd, input_section, bfd_reloc_status_type r; const char * name = NULL; int r_type; - + r_type = ELF32_R_TYPE (rel->r_info); - + if ( r_type == R_XSTORMY16_GNU_VTINHERIT || r_type == R_XSTORMY16_GNU_VTENTRY) continue; - - r_symndx = ELF32_R_SYM (rel->r_info); - - if (info->relocateable) - { - /* This is a relocateable link. We don't have to change - anything, unless the reloc is against a section symbol, - in which case we have to adjust according to where the - section symbol winds up in the output section. */ - if (r_symndx < symtab_hdr->sh_info) - { - sym = local_syms + r_symndx; - - if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) - { - sec = local_sections [r_symndx]; - rel->r_addend += sec->output_offset + sym->st_value; - } - } - - continue; - } - /* This is a final link. */ + r_symndx = ELF32_R_SYM (rel->r_info); howto = xstormy16_elf_howto_table + ELF32_R_TYPE (rel->r_info); h = NULL; sym = NULL; sec = NULL; - + if (r_symndx < symtab_hdr->sh_info) { sym = local_syms + r_symndx; sec = local_sections [r_symndx]; - relocation = (sec->output_section->vma - + sec->output_offset - + sym->st_value); - - 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; + relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); } else { - h = sym_hashes [r_symndx - symtab_hdr->sh_info]; - - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; + bfd_boolean unresolved_reloc, warned; - name = h->root.root.string; - - if (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - { - sec = h->root.u.def.section; - relocation = (h->root.u.def.value - + sec->output_section->vma - + sec->output_offset); - } - else if (h->root.type == bfd_link_hash_undefweak) - { - relocation = 0; - } - else - { - if (! ((*info->callbacks->undefined_symbol) - (info, h->root.root.string, input_bfd, - input_section, rel->r_offset, true))) - return false; - relocation = 0; - } + RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, + r_symndx, symtab_hdr, sym_hashes, + h, sec, relocation, + unresolved_reloc, warned); + } + + if (sec != NULL && elf_discarded_section (sec)) + { + /* For relocs against symbols from removed linkonce sections, + or sections discarded by a linker script, we just want the + section contents zeroed. Avoid any special processing. */ + _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset); + rel->r_info = 0; + rel->r_addend = 0; + continue; } - + + if (info->relocatable) + continue; + + if (h != NULL) + name = h->root.root.string; + else + { + name = (bfd_elf_string_from_elf_section + (input_bfd, symtab_hdr->sh_link, sym->st_name)); + if (name == NULL || *name == '\0') + name = bfd_section_name (input_bfd, sec); + } + switch (ELF32_R_TYPE (rel->r_info)) { case R_XSTORMY16_24: { bfd_vma reloc = relocation + rel->r_addend; unsigned int x; - + x = bfd_get_32 (input_bfd, contents + rel->r_offset); x &= 0x0000ff00; x |= reloc & 0xff; @@ -948,22 +928,22 @@ xstormy16_elf_relocate_section (output_bfd, info, input_bfd, input_section, if (r != bfd_reloc_ok) { - const char * msg = (const char *) NULL; + const char * msg = NULL; switch (r) { case bfd_reloc_overflow: r = info->callbacks->reloc_overflow - (info, name, howto->name, (bfd_vma) 0, - input_bfd, input_section, rel->r_offset); + (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, name, input_bfd, input_section, rel->r_offset, - true); + TRUE); break; - + case bfd_reloc_outofrange: msg = _("internal error: out of range error"); break; @@ -986,19 +966,18 @@ xstormy16_elf_relocate_section (output_bfd, info, input_bfd, input_section, (info, msg, name, input_bfd, input_section, rel->r_offset); if (! r) - return false; + return FALSE; } } - return true; + return TRUE; } /* This must exist if dynobj is ever set. */ -static boolean -xstormy16_elf_finish_dynamic_sections (abfd, info) - bfd *abfd ATTRIBUTE_UNUSED; - struct bfd_link_info *info; +static bfd_boolean +xstormy16_elf_finish_dynamic_sections (bfd *abfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info) { bfd *dynobj; asection *splt; @@ -1010,69 +989,38 @@ xstormy16_elf_finish_dynamic_sections (abfd, info) && (splt = bfd_get_section_by_name (dynobj, ".plt")) != NULL) { bfd_byte *contents = splt->contents; - unsigned int i, size = splt->_raw_size; + unsigned int i, size = splt->size; + for (i = 0; i < size; i += 4) { unsigned int x = bfd_get_32 (dynobj, contents + i); + BFD_ASSERT (x != 0); } } - return true; + return TRUE; } /* Return the section that should be marked against GC for a given relocation. */ static asection * -xstormy16_elf_gc_mark_hook (abfd, info, rel, h, sym) - bfd * abfd; - struct bfd_link_info * info ATTRIBUTE_UNUSED; - Elf_Internal_Rela * rel; - struct elf_link_hash_entry * h; - Elf_Internal_Sym * sym; +xstormy16_elf_gc_mark_hook (asection *sec, + struct bfd_link_info *info, + Elf_Internal_Rela *rel, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) { if (h != NULL) - { - switch (ELF32_R_TYPE (rel->r_info)) - { - case R_XSTORMY16_GNU_VTINHERIT: - case R_XSTORMY16_GNU_VTENTRY: - break; - - 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 - { - return bfd_section_from_elf_index (abfd, sym->st_shndx); - } - - return NULL; -} - -/* Update the got entry reference counts for the section being removed. */ - -static boolean -xstormy16_elf_gc_sweep_hook (abfd, info, sec, relocs) - bfd * abfd ATTRIBUTE_UNUSED; - struct bfd_link_info * info ATTRIBUTE_UNUSED; - asection * sec ATTRIBUTE_UNUSED; - const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED; -{ - return true; + switch (ELF32_R_TYPE (rel->r_info)) + { + case R_XSTORMY16_GNU_VTINHERIT: + case R_XSTORMY16_GNU_VTENTRY: + return NULL; + } + + return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); } #define ELF_ARCH bfd_arch_xstormy16 @@ -1086,16 +1034,20 @@ xstormy16_elf_gc_sweep_hook (abfd, info, sec, relocs) #define elf_info_to_howto xstormy16_info_to_howto_rela #define elf_backend_relocate_section xstormy16_elf_relocate_section #define elf_backend_gc_mark_hook xstormy16_elf_gc_mark_hook -#define elf_backend_gc_sweep_hook xstormy16_elf_gc_sweep_hook #define elf_backend_check_relocs xstormy16_elf_check_relocs #define elf_backend_always_size_sections \ xstormy16_elf_always_size_sections +#define elf_backend_omit_section_dynsym \ + ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true) #define elf_backend_finish_dynamic_sections \ xstormy16_elf_finish_dynamic_sections #define elf_backend_can_gc_sections 1 +#define elf_backend_rela_normal 1 #define bfd_elf32_bfd_reloc_type_lookup xstormy16_reloc_type_lookup +#define bfd_elf32_bfd_reloc_name_lookup \ + xstormy16_reloc_name_lookup #define bfd_elf32_bfd_relax_section xstormy16_elf_relax_section #include "elf32-target.h"