X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Felf32-m68k.c;h=39832be83cf1af00138e4b0e25fb5f6e44686c44;hb=72adc230457cc2885fe394ab4647dceab2d9d0aa;hp=80613f11e4395a77d107442e1e9c268a88311272;hpb=f51e552e0e058cee7ac698cbd8aaac033607dd86;p=binutils-gdb.git diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c index 80613f11e43..39832be83cf 100644 --- a/bfd/elf32-m68k.c +++ b/bfd/elf32-m68k.c @@ -1,22 +1,22 @@ /* Motorola 68k series support for 32-bit ELF - Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001 - Free Software Foundation, Inc. + Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, + 2004 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "bfd.h" #include "sysdep.h" @@ -28,96 +28,96 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ static reloc_howto_type *reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type)); static void rtype_to_howto - PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *)); + PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); static struct bfd_hash_entry *elf_m68k_link_hash_newfunc PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); static struct bfd_link_hash_table *elf_m68k_link_hash_table_create PARAMS ((bfd *)); -static boolean elf_m68k_check_relocs +static bfd_boolean elf_m68k_check_relocs PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *)); static asection *elf_m68k_gc_mark_hook - PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *, + PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, struct elf_link_hash_entry *, Elf_Internal_Sym *)); -static boolean elf_m68k_gc_sweep_hook +static bfd_boolean elf_m68k_gc_sweep_hook PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *)); -static boolean elf_m68k_adjust_dynamic_symbol +static bfd_boolean elf_m68k_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); -static boolean elf_m68k_size_dynamic_sections +static bfd_boolean elf_m68k_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); -static boolean elf_m68k_relocate_section +static bfd_boolean elf_m68k_discard_copies + PARAMS ((struct elf_link_hash_entry *, PTR)); +static bfd_boolean elf_m68k_relocate_section PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); -static boolean elf_m68k_finish_dynamic_symbol +static bfd_boolean elf_m68k_finish_dynamic_symbol PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, Elf_Internal_Sym *)); -static boolean elf_m68k_finish_dynamic_sections +static bfd_boolean elf_m68k_finish_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); -static boolean elf32_m68k_set_private_flags +static bfd_boolean elf32_m68k_set_private_flags PARAMS ((bfd *, flagword)); -static boolean elf32_m68k_copy_private_bfd_data +static bfd_boolean elf32_m68k_merge_private_bfd_data PARAMS ((bfd *, bfd *)); -static boolean elf32_m68k_merge_private_bfd_data - PARAMS ((bfd *, bfd *)); -static boolean elf32_m68k_print_private_bfd_data +static bfd_boolean elf32_m68k_print_private_bfd_data PARAMS ((bfd *, PTR)); static enum elf_reloc_type_class elf32_m68k_reloc_type_class PARAMS ((const Elf_Internal_Rela *)); static reloc_howto_type howto_table[] = { - HOWTO(R_68K_NONE, 0, 0, 0, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_NONE", false, 0, 0x00000000,false), - HOWTO(R_68K_32, 0, 2,32, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_32", false, 0, 0xffffffff,false), - HOWTO(R_68K_16, 0, 1,16, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_16", false, 0, 0x0000ffff,false), - HOWTO(R_68K_8, 0, 0, 8, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_8", false, 0, 0x000000ff,false), - HOWTO(R_68K_PC32, 0, 2,32, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_PC32", false, 0, 0xffffffff,true), - HOWTO(R_68K_PC16, 0, 1,16, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PC16", false, 0, 0x0000ffff,true), - HOWTO(R_68K_PC8, 0, 0, 8, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PC8", false, 0, 0x000000ff,true), - HOWTO(R_68K_GOT32, 0, 2,32, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_GOT32", false, 0, 0xffffffff,true), - HOWTO(R_68K_GOT16, 0, 1,16, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT16", false, 0, 0x0000ffff,true), - HOWTO(R_68K_GOT8, 0, 0, 8, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT8", false, 0, 0x000000ff,true), - HOWTO(R_68K_GOT32O, 0, 2,32, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_GOT32O", false, 0, 0xffffffff,false), - HOWTO(R_68K_GOT16O, 0, 1,16, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT16O", false, 0, 0x0000ffff,false), - HOWTO(R_68K_GOT8O, 0, 0, 8, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT8O", false, 0, 0x000000ff,false), - HOWTO(R_68K_PLT32, 0, 2,32, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_PLT32", false, 0, 0xffffffff,true), - HOWTO(R_68K_PLT16, 0, 1,16, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT16", false, 0, 0x0000ffff,true), - HOWTO(R_68K_PLT8, 0, 0, 8, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT8", false, 0, 0x000000ff,true), - HOWTO(R_68K_PLT32O, 0, 2,32, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_PLT32O", false, 0, 0xffffffff,false), - HOWTO(R_68K_PLT16O, 0, 1,16, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT16O", false, 0, 0x0000ffff,false), - HOWTO(R_68K_PLT8O, 0, 0, 8, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT8O", false, 0, 0x000000ff,false), - HOWTO(R_68K_COPY, 0, 0, 0, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_COPY", false, 0, 0xffffffff,false), - HOWTO(R_68K_GLOB_DAT, 0, 2,32, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_GLOB_DAT", false, 0, 0xffffffff,false), - HOWTO(R_68K_JMP_SLOT, 0, 2,32, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_JMP_SLOT", false, 0, 0xffffffff,false), - HOWTO(R_68K_RELATIVE, 0, 2,32, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_RELATIVE", false, 0, 0xffffffff,false), - /* GNU extension to record C++ vtable hierarchy */ + HOWTO(R_68K_NONE, 0, 0, 0, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_NONE", FALSE, 0, 0x00000000,FALSE), + HOWTO(R_68K_32, 0, 2,32, FALSE,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_32", FALSE, 0, 0xffffffff,FALSE), + HOWTO(R_68K_16, 0, 1,16, FALSE,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_16", FALSE, 0, 0x0000ffff,FALSE), + HOWTO(R_68K_8, 0, 0, 8, FALSE,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_8", FALSE, 0, 0x000000ff,FALSE), + HOWTO(R_68K_PC32, 0, 2,32, TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_PC32", FALSE, 0, 0xffffffff,TRUE), + HOWTO(R_68K_PC16, 0, 1,16, TRUE, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PC16", FALSE, 0, 0x0000ffff,TRUE), + HOWTO(R_68K_PC8, 0, 0, 8, TRUE, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PC8", FALSE, 0, 0x000000ff,TRUE), + HOWTO(R_68K_GOT32, 0, 2,32, TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_GOT32", FALSE, 0, 0xffffffff,TRUE), + HOWTO(R_68K_GOT16, 0, 1,16, TRUE, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT16", FALSE, 0, 0x0000ffff,TRUE), + HOWTO(R_68K_GOT8, 0, 0, 8, TRUE, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT8", FALSE, 0, 0x000000ff,TRUE), + HOWTO(R_68K_GOT32O, 0, 2,32, FALSE,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_GOT32O", FALSE, 0, 0xffffffff,FALSE), + HOWTO(R_68K_GOT16O, 0, 1,16, FALSE,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT16O", FALSE, 0, 0x0000ffff,FALSE), + HOWTO(R_68K_GOT8O, 0, 0, 8, FALSE,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT8O", FALSE, 0, 0x000000ff,FALSE), + HOWTO(R_68K_PLT32, 0, 2,32, TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_PLT32", FALSE, 0, 0xffffffff,TRUE), + HOWTO(R_68K_PLT16, 0, 1,16, TRUE, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT16", FALSE, 0, 0x0000ffff,TRUE), + HOWTO(R_68K_PLT8, 0, 0, 8, TRUE, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT8", FALSE, 0, 0x000000ff,TRUE), + HOWTO(R_68K_PLT32O, 0, 2,32, FALSE,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_PLT32O", FALSE, 0, 0xffffffff,FALSE), + HOWTO(R_68K_PLT16O, 0, 1,16, FALSE,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT16O", FALSE, 0, 0x0000ffff,FALSE), + HOWTO(R_68K_PLT8O, 0, 0, 8, FALSE,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT8O", FALSE, 0, 0x000000ff,FALSE), + HOWTO(R_68K_COPY, 0, 0, 0, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_COPY", FALSE, 0, 0xffffffff,FALSE), + HOWTO(R_68K_GLOB_DAT, 0, 2,32, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_GLOB_DAT", FALSE, 0, 0xffffffff,FALSE), + HOWTO(R_68K_JMP_SLOT, 0, 2,32, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_JMP_SLOT", FALSE, 0, 0xffffffff,FALSE), + HOWTO(R_68K_RELATIVE, 0, 2,32, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_RELATIVE", FALSE, 0, 0xffffffff,FALSE), + /* GNU extension to record C++ vtable hierarchy. */ HOWTO (R_68K_GNU_VTINHERIT, /* 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 */ NULL, /* special_function */ "R_68K_GNU_VTINHERIT", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ - false), - /* GNU extension to record C++ vtable member usage */ + FALSE), + /* GNU extension to record C++ vtable member usage. */ HOWTO (R_68K_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_68K_GNU_VTENTRY", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ - false), + FALSE), }; static void @@ -181,9 +181,6 @@ reloc_type_lookup (abfd, code) #define bfd_elf32_bfd_reloc_type_lookup reloc_type_lookup #define ELF_ARCH bfd_arch_m68k -/* end code generated by elf.el */ - -#define USE_RELA /* Functions for the m68k ELF linker. */ @@ -276,25 +273,17 @@ struct elf_m68k_link_hash_entry struct elf_m68k_pcrel_relocs_copied *pcrel_relocs_copied; }; +#define elf_m68k_hash_entry(ent) ((struct elf_m68k_link_hash_entry *) (ent)) + /* m68k ELF linker hash table. */ struct elf_m68k_link_hash_table { struct elf_link_hash_table root; -}; - -/* Declare this now that the above structures are defined. */ -static boolean elf_m68k_discard_copies - PARAMS ((struct elf_m68k_link_hash_entry *, PTR)); - -/* Traverse an m68k ELF linker hash table. */ - -#define elf_m68k_link_hash_traverse(table, func, info) \ - (elf_link_hash_traverse \ - (&(table)->root, \ - (boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \ - (info))) + /* Small local sym to section mapping cache. */ + struct sym_sec_cache sym_sec; +}; /* Get the m68k ELF linker hash table from a link_info structure. */ @@ -309,28 +298,22 @@ elf_m68k_link_hash_newfunc (entry, table, string) struct bfd_hash_table *table; const char *string; { - struct elf_m68k_link_hash_entry *ret = - (struct elf_m68k_link_hash_entry *) entry; + struct bfd_hash_entry *ret = entry; /* Allocate the structure if it has not already been allocated by a subclass. */ - if (ret == (struct elf_m68k_link_hash_entry *) NULL) - ret = ((struct elf_m68k_link_hash_entry *) - bfd_hash_allocate (table, - sizeof (struct elf_m68k_link_hash_entry))); - if (ret == (struct elf_m68k_link_hash_entry *) NULL) - return (struct bfd_hash_entry *) ret; + if (ret == NULL) + ret = bfd_hash_allocate (table, + sizeof (struct elf_m68k_link_hash_entry)); + if (ret == NULL) + return ret; /* Call the allocation method of the superclass. */ - ret = ((struct elf_m68k_link_hash_entry *) - _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret, - table, string)); - if (ret != (struct elf_m68k_link_hash_entry *) NULL) - { - ret->pcrel_relocs_copied = NULL; - } + ret = _bfd_elf_link_hash_newfunc (ret, table, string); + if (ret != NULL) + elf_m68k_hash_entry (ret)->pcrel_relocs_copied = NULL; - return (struct bfd_hash_entry *) ret; + return ret; } /* Create an m68k ELF linker hash table. */ @@ -342,54 +325,36 @@ elf_m68k_link_hash_table_create (abfd) struct elf_m68k_link_hash_table *ret; bfd_size_type amt = sizeof (struct elf_m68k_link_hash_table); - ret = (struct elf_m68k_link_hash_table *) bfd_alloc (abfd, amt); + ret = (struct elf_m68k_link_hash_table *) bfd_malloc (amt); if (ret == (struct elf_m68k_link_hash_table *) NULL) return NULL; if (! _bfd_elf_link_hash_table_init (&ret->root, abfd, elf_m68k_link_hash_newfunc)) { - bfd_release (abfd, ret); + free (ret); return NULL; } + ret->sym_sec.abfd = NULL; + return &ret->root.root; } -/* Keep m68k-specific flags in the ELF header */ -static boolean +/* Keep m68k-specific flags in the ELF header. */ +static bfd_boolean elf32_m68k_set_private_flags (abfd, flags) bfd *abfd; flagword flags; { elf_elfheader (abfd)->e_flags = flags; - elf_flags_init (abfd) = true; - return true; -} - -/* Copy m68k-specific data from one module to another */ -static boolean -elf32_m68k_copy_private_bfd_data (ibfd, obfd) - bfd *ibfd; - bfd *obfd; -{ - flagword in_flags; - - if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour - || bfd_get_flavour (obfd) != bfd_target_elf_flavour) - return true; - - in_flags = elf_elfheader (ibfd)->e_flags; - - elf_elfheader (obfd)->e_flags = in_flags; - elf_flags_init (obfd) = true; - - return true; + elf_flags_init (abfd) = TRUE; + return TRUE; } /* Merge backend specific data from an object file to the output object file when linking. */ -static boolean +static bfd_boolean elf32_m68k_merge_private_bfd_data (ibfd, obfd) bfd *ibfd; bfd *obfd; @@ -399,22 +364,22 @@ elf32_m68k_merge_private_bfd_data (ibfd, obfd) if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour || bfd_get_flavour (obfd) != bfd_target_elf_flavour) - return true; + return TRUE; in_flags = elf_elfheader (ibfd)->e_flags; out_flags = elf_elfheader (obfd)->e_flags; if (!elf_flags_init (obfd)) { - elf_flags_init (obfd) = true; + elf_flags_init (obfd) = TRUE; elf_elfheader (obfd)->e_flags = in_flags; } - return true; + return TRUE; } -/* Display the flags field */ -static boolean +/* Display the flags field. */ +static bfd_boolean elf32_m68k_print_private_bfd_data (abfd, ptr) bfd *abfd; PTR ptr; @@ -429,20 +394,23 @@ elf32_m68k_print_private_bfd_data (abfd, ptr) /* Ignore init flag - it may not be set, despite the flags field containing valid data. */ /* xgettext:c-format */ - fprintf (file, _ ("private flags = %lx:"), elf_elfheader (abfd)->e_flags); + fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags); if (elf_elfheader (abfd)->e_flags & EF_CPU32) - fprintf (file, _ (" [cpu32]")); + fprintf (file, _(" [cpu32]")); + + if (elf_elfheader (abfd)->e_flags & EF_M68000) + fprintf (file, _(" [m68000]")); fputc ('\n', file); - return true; + return TRUE; } /* Look through the relocs for a section during the first phase, and allocate space in the global offset table or procedure linkage table. */ -static boolean +static bfd_boolean elf_m68k_check_relocs (abfd, info, sec, relocs) bfd *abfd; struct bfd_link_info *info; @@ -459,8 +427,8 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) asection *srelgot; asection *sreloc; - if (info->relocateable) - return true; + if (info->relocatable) + return TRUE; dynobj = elf_hash_table (info)->dynobj; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; @@ -503,7 +471,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) /* Create the .got section. */ elf_hash_table (info)->dynobj = dynobj = abfd; if (!_bfd_elf_create_got_section (dynobj, info)) - return false; + return FALSE; } if (sgot == NULL) @@ -528,21 +496,20 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) | SEC_LINKER_CREATED | SEC_READONLY)) || !bfd_set_section_alignment (dynobj, srelgot, 2)) - return false; + return FALSE; } } if (h != NULL) { - if (h->got.refcount == -1) + if (h->got.refcount == 0) { - h->got.refcount = 1; - /* Make sure this symbol is output as a dynamic symbol. */ - if (h->dynindx == -1) + if (h->dynindx == -1 + && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) { - if (!bfd_elf32_link_record_dynamic_symbol (info, h)) - return false; + if (!bfd_elf_link_record_dynamic_symbol (info, h)) + return FALSE; } /* Allocate space in the .got section. */ @@ -550,8 +517,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) /* Allocate relocation space. */ srelgot->_raw_size += sizeof (Elf32_External_Rela); } - else - h->got.refcount++; + h->got.refcount++; } else { @@ -563,16 +529,13 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) size = symtab_hdr->sh_info; size *= sizeof (bfd_signed_vma); local_got_refcounts = ((bfd_signed_vma *) - bfd_alloc (abfd, size)); + bfd_zalloc (abfd, size)); if (local_got_refcounts == NULL) - return false; + return FALSE; elf_local_got_refcounts (abfd) = local_got_refcounts; - memset (local_got_refcounts, -1, (size_t) size); } - if (local_got_refcounts[r_symndx] == -1) + if (local_got_refcounts[r_symndx] == 0) { - local_got_refcounts[r_symndx] = 1; - sgot->_raw_size += 4; if (info->shared) { @@ -582,8 +545,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) srelgot->_raw_size += sizeof (Elf32_External_Rela); } } - else - local_got_refcounts[r_symndx]++; + local_got_refcounts[r_symndx]++; } break; @@ -603,10 +565,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) continue; h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; - if (h->plt.refcount == -1) - h->plt.refcount = 1; - else - h->plt.refcount++; + h->plt.refcount++; break; case R_68K_PLT8O: @@ -620,21 +579,19 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) local symbol. FIXME: does it? How to handle it if it does make sense? */ bfd_set_error (bfd_error_bad_value); - return false; + return FALSE; } /* Make sure this symbol is output as a dynamic symbol. */ - if (h->dynindx == -1) + if (h->dynindx == -1 + && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) { - if (!bfd_elf32_link_record_dynamic_symbol (info, h)) - return false; + if (!bfd_elf_link_record_dynamic_symbol (info, h)) + return FALSE; } h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; - if (h->plt.refcount == -1) - h->plt.refcount = 1; - else - h->plt.refcount++; + h->plt.refcount++; break; case R_68K_PC8: @@ -654,6 +611,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) && (sec->flags & SEC_ALLOC) != 0 && h != NULL && (!info->symbolic + || h->root.type == bfd_link_hash_defweak || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0))) { @@ -662,10 +620,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) /* Make sure a plt entry is created for this symbol if it turns out to be a function defined by a dynamic object. */ - if (h->plt.refcount == -1) - h->plt.refcount = 1; - else - h->plt.refcount++; + h->plt.refcount++; } break; } @@ -677,10 +632,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) { /* Make sure a plt entry is created for this symbol if it turns out to be a function defined by a dynamic object. */ - if (h->plt.refcount == -1) - h->plt.refcount = 1; - else - h->plt.refcount++; + h->plt.refcount++; } /* If we are creating a shared library, we need to copy the @@ -700,7 +652,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) elf_elfheader (abfd)->e_shstrndx, elf_section_data (sec)->rel_hdr.sh_name)); if (name == NULL) - return false; + return FALSE; BFD_ASSERT (strncmp (name, ".rela", 5) == 0 && strcmp (bfd_get_section_name (abfd, sec), @@ -719,32 +671,56 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) | SEC_LINKER_CREATED | SEC_READONLY)) || !bfd_set_section_alignment (dynobj, sreloc, 2)) - return false; + return FALSE; } - if (sec->flags & SEC_READONLY) - info->flags |= DF_TEXTREL; + elf_section_data (sec)->sreloc = sreloc; } + if (sec->flags & SEC_READONLY + /* Don't set DF_TEXTREL yet for PC relative + relocations, they might be discarded later. */ + && !(ELF32_R_TYPE (rel->r_info) == R_68K_PC8 + || ELF32_R_TYPE (rel->r_info) == R_68K_PC16 + || ELF32_R_TYPE (rel->r_info) == R_68K_PC32)) + info->flags |= DF_TEXTREL; + sreloc->_raw_size += sizeof (Elf32_External_Rela); - /* If we are linking with -Bsymbolic, we count the number of - PC relative relocations we have entered for this symbol, - so that we can discard them again if the symbol is later - defined by a regular object. Note that this function is - only called if we are using an m68kelf linker hash table, - which means that h is really a pointer to an + /* We count the number of PC relative relocations we have + entered for this symbol, so that we can discard them + again if, in the -Bsymbolic case, the symbol is later + defined by a regular object, or, in the normal shared + case, the symbol is forced to be local. Note that this + function is only called if we are using an m68kelf linker + hash table, which means that h is really a pointer to an elf_m68k_link_hash_entry. */ - if ((ELF32_R_TYPE (rel->r_info) == R_68K_PC8 - || ELF32_R_TYPE (rel->r_info) == R_68K_PC16 - || ELF32_R_TYPE (rel->r_info) == R_68K_PC32) - && info->symbolic) + if (ELF32_R_TYPE (rel->r_info) == R_68K_PC8 + || ELF32_R_TYPE (rel->r_info) == R_68K_PC16 + || ELF32_R_TYPE (rel->r_info) == R_68K_PC32) { - struct elf_m68k_link_hash_entry *eh; struct elf_m68k_pcrel_relocs_copied *p; + struct elf_m68k_pcrel_relocs_copied **head; - eh = (struct elf_m68k_link_hash_entry *) h; + if (h != NULL) + { + struct elf_m68k_link_hash_entry *eh + = elf_m68k_hash_entry (h); + head = &eh->pcrel_relocs_copied; + } + else + { + asection *s; + s = (bfd_section_from_r_symndx + (abfd, &elf_m68k_hash_table (info)->sym_sec, + sec, r_symndx)); + if (s == NULL) + return FALSE; + + head = ((struct elf_m68k_pcrel_relocs_copied **) + &elf_section_data (s)->local_dynrel); + } - for (p = eh->pcrel_relocs_copied; p != NULL; p = p->next) + for (p = *head; p != NULL; p = p->next) if (p->section == sreloc) break; @@ -753,9 +729,9 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) p = ((struct elf_m68k_pcrel_relocs_copied *) bfd_alloc (dynobj, (bfd_size_type) sizeof *p)); if (p == NULL) - return false; - p->next = eh->pcrel_relocs_copied; - eh->pcrel_relocs_copied = p; + return FALSE; + p->next = *head; + *head = p; p->section = sreloc; p->count = 0; } @@ -769,15 +745,15 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) /* This relocation describes the C++ object vtable hierarchy. Reconstruct it for later use during GC. */ case R_68K_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_68K_GNU_VTENTRY: - if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) - return false; + if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) + return FALSE; break; default: @@ -785,15 +761,15 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) } } - return true; + return TRUE; } /* Return the section that should be marked against GC for a given relocation. */ static asection * -elf_m68k_gc_mark_hook (abfd, info, rel, h, sym) - bfd *abfd; +elf_m68k_gc_mark_hook (sec, info, rel, h, sym) + asection *sec; struct bfd_link_info *info ATTRIBUTE_UNUSED; Elf_Internal_Rela *rel; struct elf_link_hash_entry *h; @@ -823,22 +799,14 @@ elf_m68k_gc_mark_hook (abfd, info, rel, h, sym) } } else - { - if (!(elf_bad_symtab (abfd) - && 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 (abfd, sym->st_shndx); - } - } + return bfd_section_from_elf_index (sec->owner, sym->st_shndx); return NULL; } /* Update the got entry reference counts for the section being removed. */ -static boolean +static bfd_boolean elf_m68k_gc_sweep_hook (abfd, info, sec, relocs) bfd *abfd; struct bfd_link_info *info; @@ -849,26 +817,27 @@ elf_m68k_gc_sweep_hook (abfd, info, sec, relocs) struct elf_link_hash_entry **sym_hashes; bfd_signed_vma *local_got_refcounts; const Elf_Internal_Rela *rel, *relend; - unsigned long r_symndx; - struct elf_link_hash_entry *h; bfd *dynobj; asection *sgot; asection *srelgot; + dynobj = elf_hash_table (info)->dynobj; + if (dynobj == NULL) + return TRUE; + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); local_got_refcounts = elf_local_got_refcounts (abfd); - dynobj = elf_hash_table (info)->dynobj; - if (dynobj == NULL) - return true; - sgot = bfd_get_section_by_name (dynobj, ".got"); srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; rel++) { + unsigned long r_symndx; + struct elf_link_hash_entry *h; + switch (ELF32_R_TYPE (rel->r_info)) { case R_68K_GOT8: @@ -934,7 +903,7 @@ elf_m68k_gc_sweep_hook (abfd, info, sec, relocs) } } - return true; + return TRUE; } /* Adjust a symbol defined by a dynamic object and referenced by a @@ -943,7 +912,7 @@ elf_m68k_gc_sweep_hook (abfd, info, sec, relocs) change the definition to something the rest of the link can understand. */ -static boolean +static bfd_boolean elf_m68k_adjust_dynamic_symbol (info, h) struct bfd_link_info *info; struct elf_link_hash_entry *h; @@ -986,7 +955,7 @@ elf_m68k_adjust_dynamic_symbol (info, h) reloc instead. */ BFD_ASSERT ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0); h->plt.offset = (bfd_vma) -1; - return true; + return TRUE; } /* GC may have rendered this entry unused. */ @@ -994,14 +963,15 @@ elf_m68k_adjust_dynamic_symbol (info, h) { h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; h->plt.offset = (bfd_vma) -1; - return true; + return TRUE; } /* Make sure this symbol is output as a dynamic symbol. */ - if (h->dynindx == -1) + if (h->dynindx == -1 + && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) { - if (! bfd_elf32_link_record_dynamic_symbol (info, h)) - return false; + if (! bfd_elf_link_record_dynamic_symbol (info, h)) + return FALSE; } s = bfd_get_section_by_name (dynobj, ".plt"); @@ -1039,18 +1009,16 @@ elf_m68k_adjust_dynamic_symbol (info, h) /* We also need to make an entry in the .got.plt section, which will be placed in the .got section by the linker script. */ - s = bfd_get_section_by_name (dynobj, ".got.plt"); BFD_ASSERT (s != NULL); s->_raw_size += 4; /* We also need to make an entry in the .rela.plt section. */ - s = bfd_get_section_by_name (dynobj, ".rela.plt"); BFD_ASSERT (s != NULL); s->_raw_size += sizeof (Elf32_External_Rela); - return true; + return TRUE; } /* Reinitialize the plt offset now that it is not used as a reference @@ -1066,7 +1034,7 @@ elf_m68k_adjust_dynamic_symbol (info, h) || h->weakdef->root.type == bfd_link_hash_defweak); h->root.u.def.section = h->weakdef->root.u.def.section; h->root.u.def.value = h->weakdef->root.u.def.value; - return true; + return TRUE; } /* This is a reference to a symbol defined by a dynamic object which @@ -1077,7 +1045,7 @@ elf_m68k_adjust_dynamic_symbol (info, h) For such cases we need not do anything here; the relocations will be handled correctly by relocate_section. */ if (info->shared) - return true; + return TRUE; /* We must allocate the symbol in our .dynbss section, which will become part of the .bss section of the executable. There will be @@ -1118,7 +1086,7 @@ elf_m68k_adjust_dynamic_symbol (info, h) if (power_of_two > bfd_get_section_alignment (dynobj, s)) { if (!bfd_set_section_alignment (dynobj, s, power_of_two)) - return false; + return FALSE; } /* Define the symbol as being at this point in the section. */ @@ -1128,20 +1096,20 @@ elf_m68k_adjust_dynamic_symbol (info, h) /* Increment the section size to make room for the symbol. */ s->_raw_size += h->size; - return true; + return TRUE; } /* Set the sizes of the dynamic sections. */ -static boolean +static bfd_boolean elf_m68k_size_dynamic_sections (output_bfd, info) bfd *output_bfd ATTRIBUTE_UNUSED; struct bfd_link_info *info; { bfd *dynobj; asection *s; - boolean plt; - boolean relocs; + bfd_boolean plt; + bfd_boolean relocs; dynobj = elf_hash_table (info)->dynobj; BFD_ASSERT (dynobj != NULL); @@ -1149,7 +1117,7 @@ elf_m68k_size_dynamic_sections (output_bfd, info) if (elf_hash_table (info)->dynamic_sections_created) { /* Set the contents of the .interp section to the interpreter. */ - if (!info->shared) + if (info->executable) { s = bfd_get_section_by_name (dynobj, ".interp"); BFD_ASSERT (s != NULL); @@ -1169,24 +1137,26 @@ elf_m68k_size_dynamic_sections (output_bfd, info) s->_raw_size = 0; } - /* If this is a -Bsymbolic shared link, then we need to discard all PC - relative relocs against symbols defined in a regular object. We - allocated space for them in the check_relocs routine, but we will not - fill them in in the relocate_section routine. */ - if (info->shared && info->symbolic) - elf_m68k_link_hash_traverse (elf_m68k_hash_table (info), - elf_m68k_discard_copies, - (PTR) NULL); + /* If this is a -Bsymbolic shared link, then we need to discard all + PC relative relocs against symbols defined in a regular object. + For the normal shared case we discard the PC relative relocs + against symbols that have become local due to visibility changes. + We allocated space for them in the check_relocs routine, but we + will not fill them in in the relocate_section routine. */ + if (info->shared) + elf_link_hash_traverse (elf_hash_table (info), + elf_m68k_discard_copies, + (PTR) info); /* The check_relocs and adjust_dynamic_symbol entry points have determined the sizes of the various dynamic sections. Allocate memory for them. */ - plt = false; - relocs = false; + plt = FALSE; + relocs = FALSE; for (s = dynobj->sections; s != NULL; s = s->next) { const char *name; - boolean strip; + bfd_boolean strip; if ((s->flags & SEC_LINKER_CREATED) == 0) continue; @@ -1195,7 +1165,7 @@ elf_m68k_size_dynamic_sections (output_bfd, info) of the dynobj section names depend upon the input files. */ name = bfd_get_section_name (dynobj, s); - strip = false; + strip = FALSE; if (strcmp (name, ".plt") == 0) { @@ -1203,12 +1173,12 @@ elf_m68k_size_dynamic_sections (output_bfd, info) { /* Strip this section if we don't need it; see the comment below. */ - strip = true; + strip = TRUE; } else { /* Remember whether there is a PLT. */ - plt = true; + plt = TRUE; } } else if (strncmp (name, ".rela", 5) == 0) @@ -1224,11 +1194,11 @@ elf_m68k_size_dynamic_sections (output_bfd, info) adjust_dynamic_symbol is called, and it is that function which decides whether anything needs to go into these sections. */ - strip = true; + strip = TRUE; } else { - relocs = true; + relocs = TRUE; /* We use the reloc_count field as a counter if we need to copy relocs into the output file. */ @@ -1255,7 +1225,7 @@ elf_m68k_size_dynamic_sections (output_bfd, info) contents to zero. */ s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); if (s->contents == NULL && s->_raw_size != 0) - return false; + return FALSE; } if (elf_hash_table (info)->dynamic_sections_created) @@ -1266,12 +1236,12 @@ elf_m68k_size_dynamic_sections (output_bfd, info) the .dynamic section. The DT_DEBUG entry is filled in by the dynamic linker and used by the debugger. */ #define add_dynamic_entry(TAG, VAL) \ - bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL)) + _bfd_elf_add_dynamic_entry (info, TAG, VAL) if (!info->shared) { if (!add_dynamic_entry (DT_DEBUG, 0)) - return false; + return FALSE; } if (plt) @@ -1280,7 +1250,7 @@ elf_m68k_size_dynamic_sections (output_bfd, info) || !add_dynamic_entry (DT_PLTRELSZ, 0) || !add_dynamic_entry (DT_PLTREL, DT_RELA) || !add_dynamic_entry (DT_JMPREL, 0)) - return false; + return FALSE; } if (relocs) @@ -1288,46 +1258,75 @@ elf_m68k_size_dynamic_sections (output_bfd, info) if (!add_dynamic_entry (DT_RELA, 0) || !add_dynamic_entry (DT_RELASZ, 0) || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela))) - return false; + return FALSE; } if ((info->flags & DF_TEXTREL) != 0) { if (!add_dynamic_entry (DT_TEXTREL, 0)) - return false; + return FALSE; } } #undef add_dynamic_entry - return true; + return TRUE; } -/* This function is called via elf_m68k_link_hash_traverse if we are - creating a shared object with -Bsymbolic. It discards the space - allocated to copy PC relative relocs against symbols which are defined - in regular objects. We allocated space for them in the check_relocs - routine, but we won't fill them in in the relocate_section routine. */ - -static boolean -elf_m68k_discard_copies (h, ignore) - struct elf_m68k_link_hash_entry *h; - PTR ignore ATTRIBUTE_UNUSED; +/* This function is called via elf_link_hash_traverse if we are + creating a shared object. In the -Bsymbolic case it discards the + space allocated to copy PC relative relocs against symbols which + are defined in regular objects. For the normal shared case, it + discards space for pc-relative relocs that have become local due to + symbol visibility changes. We allocated space for them in the + check_relocs routine, but we won't fill them in in the + relocate_section routine. + + We also check whether any of the remaining relocations apply + against a readonly section, and set the DF_TEXTREL flag in this + case. */ + +static bfd_boolean +elf_m68k_discard_copies (h, inf) + struct elf_link_hash_entry *h; + PTR inf; { + struct bfd_link_info *info = (struct bfd_link_info *) inf; struct elf_m68k_pcrel_relocs_copied *s; - /* We only discard relocs for symbols defined in a regular object. */ - if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) - return true; + if (h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0 + || (!info->symbolic + && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)) + { + if ((info->flags & DF_TEXTREL) == 0) + { + /* Look for relocations against read-only sections. */ + for (s = elf_m68k_hash_entry (h)->pcrel_relocs_copied; + s != NULL; + s = s->next) + if ((s->section->flags & SEC_READONLY) != 0) + { + info->flags |= DF_TEXTREL; + break; + } + } + + return TRUE; + } - for (s = h->pcrel_relocs_copied; s != NULL; s = s->next) + for (s = elf_m68k_hash_entry (h)->pcrel_relocs_copied; + s != NULL; + s = s->next) s->section->_raw_size -= s->count * sizeof (Elf32_External_Rela); - return true; + return TRUE; } /* Relocate an M68K ELF section. */ -static boolean +static bfd_boolean elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, contents, relocs, local_syms, local_sections) bfd *output_bfd; @@ -1349,6 +1348,9 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, Elf_Internal_Rela *rel; Elf_Internal_Rela *relend; + if (info->relocatable) + return TRUE; + dynobj = elf_hash_table (info)->dynobj; symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); @@ -1369,126 +1371,38 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, Elf_Internal_Sym *sym; asection *sec; bfd_vma relocation; + bfd_boolean unresolved_reloc; bfd_reloc_status_type r; r_type = ELF32_R_TYPE (rel->r_info); if (r_type < 0 || r_type >= (int) R_68K_max) { bfd_set_error (bfd_error_bad_value); - return false; + return FALSE; } howto = howto_table + r_type; 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. */ h = NULL; sym = NULL; sec = NULL; + unresolved_reloc = FALSE; + 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); + 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; - if (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - { - sec = h->root.u.def.section; - if (((r_type == R_68K_PLT8 - || r_type == R_68K_PLT16 - || r_type == R_68K_PLT32 - || r_type == R_68K_PLT8O - || r_type == R_68K_PLT16O - || r_type == R_68K_PLT32O) - && h->plt.offset != (bfd_vma) -1 - && elf_hash_table (info)->dynamic_sections_created) - || ((r_type == R_68K_GOT8O - || r_type == R_68K_GOT16O - || r_type == R_68K_GOT32O - || ((r_type == R_68K_GOT8 - || r_type == R_68K_GOT16 - || r_type == R_68K_GOT32) - && strcmp (h->root.root.string, - "_GLOBAL_OFFSET_TABLE_") != 0)) - && elf_hash_table (info)->dynamic_sections_created - && (! info->shared - || (! info->symbolic && h->dynindx != -1) - || (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0)) - || (info->shared - && ((! info->symbolic && h->dynindx != -1) - || (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0) - && ((input_section->flags & SEC_ALLOC) != 0 - /* DWARF will emit R_68K_32 relocations in its - sections against symbols defined externally - in shared libraries. We can't do anything - with them here. */ - || ((input_section->flags & SEC_DEBUGGING) != 0 - && (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_DYNAMIC) != 0)) - && (r_type == R_68K_8 - || r_type == R_68K_16 - || r_type == R_68K_32 - || r_type == R_68K_PC8 - || r_type == R_68K_PC16 - || r_type == R_68K_PC32))) - { - /* In these cases, we don't need the relocation - value. We check specially because in some - obscure cases sec->output_section will be NULL. */ - relocation = 0; - } - else - 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->shared - && (!info->symbolic || info->allow_shlib_undefined) - && !info->no_undefined - && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) - relocation = 0; - else - { - if (!(info->callbacks->undefined_symbol - (info, h->root.root.string, input_bfd, - input_section, rel->r_offset, - (!info->shared || info->no_undefined - || ELF_ST_VISIBILITY (h->other))))) - return false; - relocation = 0; - } + bfd_boolean warned; + + RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, + r_symndx, symtab_hdr, sym_hashes, + h, sec, relocation, + unresolved_reloc, warned); } switch (r_type) @@ -1519,13 +1433,18 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, if (h != NULL) { + bfd_boolean dyn; + off = h->got.offset; BFD_ASSERT (off != (bfd_vma) -1); - if (!elf_hash_table (info)->dynamic_sections_created + dyn = elf_hash_table (info)->dynamic_sections_created; + if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) || (info->shared - && (info->symbolic || h->dynindx == -1) - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) + && (info->symbolic + || h->dynindx == -1 + || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0) + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) != 0) { /* This is actually a static link, or it is a -Bsymbolic link and the symbol is defined @@ -1548,6 +1467,8 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, h->got.offset |= 1; } } + else + unresolved_reloc = FALSE; } else { @@ -1567,22 +1488,21 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, if (info->shared) { - asection *srelgot; + asection *s; Elf_Internal_Rela outrel; + bfd_byte *loc; - srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); - BFD_ASSERT (srelgot != NULL); + s = bfd_get_section_by_name (dynobj, ".rela.got"); + BFD_ASSERT (s != NULL); outrel.r_offset = (sgot->output_section->vma + sgot->output_offset + off); outrel.r_info = ELF32_R_INFO (0, R_68K_RELATIVE); outrel.r_addend = relocation; - bfd_elf32_swap_reloca_out (output_bfd, &outrel, - (((Elf32_External_Rela *) - srelgot->contents) - + srelgot->reloc_count)); - ++srelgot->reloc_count; + loc = s->contents; + loc += s->reloc_count++ * sizeof (Elf32_External_Rela); + bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); } local_got_offsets[r_symndx] |= 1; @@ -1631,6 +1551,7 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, relocation = (splt->output_section->vma + splt->output_offset + h->plt.offset); + unresolved_reloc = FALSE; break; case R_68K_PLT8O: @@ -1647,6 +1568,7 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, } relocation = h->plt.offset; + unresolved_reloc = FALSE; /* This relocation does not use the addend. */ rel->r_addend = 0; @@ -1656,91 +1578,71 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, case R_68K_PC8: case R_68K_PC16: case R_68K_PC32: - if (h == NULL) + if (h == NULL + || (info->shared + && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)) break; /* Fall through. */ case R_68K_8: case R_68K_16: case R_68K_32: if (info->shared + && r_symndx != 0 && (input_section->flags & SEC_ALLOC) != 0 + && (h == NULL + || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + || h->root.type != bfd_link_hash_undefweak) && ((r_type != R_68K_PC8 && r_type != R_68K_PC16 && r_type != R_68K_PC32) - || (!info->symbolic - || (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0))) + || (h != NULL + && h->dynindx != -1 + && (!info->symbolic + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0)))) { Elf_Internal_Rela outrel; - boolean skip, relocate; + bfd_byte *loc; + bfd_boolean skip, relocate; /* When generating a shared object, these relocations are copied into the output file to be resolved at run time. */ - if (sreloc == NULL) - { - const char *name; - - name = (bfd_elf_string_from_elf_section - (input_bfd, - elf_elfheader (input_bfd)->e_shstrndx, - elf_section_data (input_section)->rel_hdr.sh_name)); - if (name == NULL) - return false; - - BFD_ASSERT (strncmp (name, ".rela", 5) == 0 - && strcmp (bfd_get_section_name (input_bfd, - input_section), - name + 5) == 0); - - sreloc = bfd_get_section_by_name (dynobj, name); - BFD_ASSERT (sreloc != NULL); - } - - skip = false; - - if (elf_section_data (input_section)->stab_info == NULL) - outrel.r_offset = rel->r_offset; - else - { - bfd_vma off; - - off = (_bfd_stab_section_offset - (output_bfd, &elf_hash_table (info)->stab_info, - input_section, - &elf_section_data (input_section)->stab_info, - rel->r_offset)); - if (off == (bfd_vma) -1) - skip = true; - outrel.r_offset = off; - } + skip = FALSE; + relocate = FALSE; + outrel.r_offset = + _bfd_elf_section_offset (output_bfd, info, input_section, + rel->r_offset); + if (outrel.r_offset == (bfd_vma) -1) + skip = TRUE; + else if (outrel.r_offset == (bfd_vma) -2) + skip = TRUE, relocate = TRUE; outrel.r_offset += (input_section->output_section->vma + input_section->output_offset); if (skip) - { - memset (&outrel, 0, sizeof outrel); - relocate = false; - } - /* h->dynindx may be -1 if the symbol was marked to - become local. */ + memset (&outrel, 0, sizeof outrel); else if (h != NULL - && ((! info->symbolic && h->dynindx != -1) + && h->dynindx != -1 + && (r_type == R_68K_PC8 + || r_type == R_68K_PC16 + || r_type == R_68K_PC32 + || !info->shared + || !info->symbolic || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)) { - BFD_ASSERT (h->dynindx != -1); - relocate = false; outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); - outrel.r_addend = relocation + rel->r_addend; + outrel.r_addend = rel->r_addend; } else { + /* This symbol is local, or marked to become local. */ if (r_type == R_68K_32) { - relocate = true; + relocate = TRUE; outrel.r_info = ELF32_R_INFO (0, R_68K_RELATIVE); outrel.r_addend = relocation + rel->r_addend; } @@ -1748,21 +1650,12 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, { long indx; - if (h == NULL) - sec = local_sections[r_symndx]; - else - { - BFD_ASSERT (h->root.type == bfd_link_hash_defined - || (h->root.type - == bfd_link_hash_defweak)); - sec = h->root.u.def.section; - } - if (sec != NULL && bfd_is_abs_section (sec)) + if (bfd_is_abs_section (sec)) indx = 0; else if (sec == NULL || sec->owner == NULL) { bfd_set_error (bfd_error_bad_value); - return false; + return FALSE; } else { @@ -1773,17 +1666,18 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, BFD_ASSERT (indx > 0); } - relocate = false; outrel.r_info = ELF32_R_INFO (indx, r_type); outrel.r_addend = relocation + rel->r_addend; } } - bfd_elf32_swap_reloca_out (output_bfd, &outrel, - (((Elf32_External_Rela *) - sreloc->contents) - + sreloc->reloc_count)); - ++sreloc->reloc_count; + sreloc = elf_section_data (input_section)->sreloc; + if (sreloc == NULL) + abort (); + + loc = sreloc->contents; + loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela); + bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); /* This reloc will be computed at runtime, so there's no need to do anything now, except for R_68K_32 @@ -1804,50 +1698,69 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, break; } + /* Dynamic relocs are not propagated for SEC_DEBUGGING sections + because such sections are not SEC_ALLOC and thus ld.so will + not process them. */ + if (unresolved_reloc + && !((input_section->flags & SEC_DEBUGGING) != 0 + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0)) + { + (*_bfd_error_handler) + (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"), + bfd_archive_filename (input_bfd), + bfd_get_section_name (input_bfd, input_section), + (long) rel->r_offset, + h->root.root.string); + return FALSE; + } + r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents, rel->r_offset, relocation, rel->r_addend); if (r != bfd_reloc_ok) { - switch (r) + const char *name; + + if (h != NULL) + name = h->root.root.string; + else { - default: - case bfd_reloc_outofrange: - abort (); - case bfd_reloc_overflow: - { - const char *name; + name = bfd_elf_string_from_elf_section (input_bfd, + symtab_hdr->sh_link, + sym->st_name); + if (name == NULL) + return FALSE; + if (*name == '\0') + name = bfd_section_name (input_bfd, sec); + } - 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) - return false; - if (*name == '\0') - name = bfd_section_name (input_bfd, sec); - } - if (!(info->callbacks->reloc_overflow - (info, name, howto->name, (bfd_vma) 0, - input_bfd, input_section, rel->r_offset))) - return false; - } - break; + if (r == bfd_reloc_overflow) + { + if (!(info->callbacks->reloc_overflow + (info, name, howto->name, (bfd_vma) 0, + input_bfd, input_section, rel->r_offset))) + return FALSE; + } + else + { + (*_bfd_error_handler) + (_("%s(%s+0x%lx): reloc against `%s': error %d"), + bfd_archive_filename (input_bfd), + bfd_get_section_name (input_bfd, input_section), + (long) rel->r_offset, name, (int) r); + return FALSE; } } } - return true; + return TRUE; } /* Finish up dynamic symbol handling. We set the contents of various dynamic sections here. */ -static boolean +static bfd_boolean elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym) bfd *output_bfd; struct bfd_link_info *info; @@ -1867,6 +1780,7 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym) bfd_vma plt_index; bfd_vma got_offset; Elf_Internal_Rela rela; + bfd_byte *loc; /* This symbol has an entry in the procedure linkage table. Set it up. */ @@ -1939,9 +1853,8 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym) + got_offset); rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_JMP_SLOT); rela.r_addend = 0; - bfd_elf32_swap_reloca_out (output_bfd, &rela, - ((Elf32_External_Rela *) srela->contents - + plt_index)); + loc = srela->contents + plt_index * sizeof (Elf32_External_Rela); + bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) { @@ -1956,6 +1869,7 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym) asection *sgot; asection *srela; Elf_Internal_Rela rela; + bfd_byte *loc; /* This symbol has an entry in the global offset table. Set it up. */ @@ -1974,7 +1888,9 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym) The entry in the global offset table will already have been initialized in the relocate_section function. */ if (info->shared - && (info->symbolic || h->dynindx == -1) + && (info->symbolic + || h->dynindx == -1 + || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0) && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) { rela.r_info = ELF32_R_INFO (0, R_68K_RELATIVE); @@ -1990,16 +1906,16 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym) rela.r_addend = 0; } - bfd_elf32_swap_reloca_out (output_bfd, &rela, - ((Elf32_External_Rela *) srela->contents - + srela->reloc_count)); - ++srela->reloc_count; + loc = srela->contents; + loc += srela->reloc_count++ * sizeof (Elf32_External_Rela); + bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); } if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) { asection *s; Elf_Internal_Rela rela; + bfd_byte *loc; /* This symbol needs a copy reloc. Set it up. */ @@ -2016,10 +1932,8 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym) + h->root.u.def.section->output_offset); rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_COPY); rela.r_addend = 0; - bfd_elf32_swap_reloca_out (output_bfd, &rela, - ((Elf32_External_Rela *) s->contents - + s->reloc_count)); - ++s->reloc_count; + loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela); + bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); } /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */ @@ -2027,12 +1941,12 @@ elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym) || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) sym->st_shndx = SHN_ABS; - return true; + return TRUE; } /* Finish up the dynamic sections. */ -static boolean +static bfd_boolean elf_m68k_finish_dynamic_sections (output_bfd, info) bfd *output_bfd; struct bfd_link_info *info; @@ -2166,7 +2080,7 @@ elf_m68k_finish_dynamic_sections (output_bfd, info) elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; - return true; + return TRUE; } /* Given a .data section and a .emreloc in-memory section, store @@ -2176,7 +2090,7 @@ elf_m68k_finish_dynamic_sections (output_bfd, info) after the add_symbols entry point has been called for all the objects, and before the final_link entry point is called. */ -boolean +bfd_boolean bfd_m68k_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) bfd *abfd; struct bfd_link_info *info; @@ -2185,53 +2099,27 @@ bfd_m68k_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) char **errmsg; { Elf_Internal_Shdr *symtab_hdr; - Elf32_External_Sym *extsyms; - Elf32_External_Sym *free_extsyms = NULL; - Elf_Internal_Rela *internal_relocs; - Elf_Internal_Rela *free_relocs = NULL; + Elf_Internal_Sym *isymbuf = NULL; + Elf_Internal_Rela *internal_relocs = NULL; Elf_Internal_Rela *irel, *irelend; bfd_byte *p; bfd_size_type amt; - BFD_ASSERT (! info->relocateable); + BFD_ASSERT (! info->relocatable); *errmsg = NULL; if (datasec->reloc_count == 0) - return true; + return TRUE; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - /* Read this BFD's symbols if we haven't done so already, or get the cached - copy if it exists. */ - if (symtab_hdr->contents != NULL) - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - else - { - /* Go get them off disk. */ - if (info->keep_memory) - extsyms = (Elf32_External_Sym *) bfd_alloc (abfd, symtab_hdr->sh_size); - else - extsyms = (Elf32_External_Sym *) bfd_malloc (symtab_hdr->sh_size); - if (extsyms == NULL) - goto error_return; - if (! info->keep_memory) - free_extsyms = extsyms; - if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || (bfd_bread (extsyms, symtab_hdr->sh_size, abfd) - != symtab_hdr->sh_size)) - goto error_return; - if (info->keep_memory) - symtab_hdr->contents = extsyms; - } /* Get a copy of the native relocations. */ - internal_relocs = (_bfd_elf32_link_read_relocs + internal_relocs = (_bfd_elf_link_read_relocs (abfd, datasec, (PTR) NULL, (Elf_Internal_Rela *) NULL, info->keep_memory)); if (internal_relocs == NULL) goto error_return; - if (! info->keep_memory) - free_relocs = internal_relocs; amt = (bfd_size_type) datasec->reloc_count * 12; relsec->contents = (bfd_byte *) bfd_alloc (abfd, amt); @@ -2262,14 +2150,23 @@ bfd_m68k_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) /* Get the target section referred to by the reloc. */ if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) { - Elf_Internal_Sym isym; - /* A local symbol. */ - bfd_elf32_swap_symbol_in (abfd, - extsyms + ELF32_R_SYM (irel->r_info), - &isym); + Elf_Internal_Sym *isym; + + /* Read this BFD's local symbols if we haven't done so already. */ + if (isymbuf == NULL) + { + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) + goto error_return; + } - targetsec = bfd_section_from_elf_index (abfd, isym.st_shndx); + isym = isymbuf + ELF32_R_SYM (irel->r_info); + targetsec = bfd_section_from_elf_index (abfd, isym->st_shndx); } else { @@ -2293,18 +2190,20 @@ bfd_m68k_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) strncpy (p + 4, targetsec->output_section->name, 8); } - if (free_extsyms != NULL) - free (free_extsyms); - if (free_relocs != NULL) - free (free_relocs); - return true; + if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (internal_relocs != NULL + && elf_section_data (datasec)->relocs != internal_relocs) + free (internal_relocs); + return TRUE; error_return: - if (free_extsyms != NULL) - free (free_extsyms); - if (free_relocs != NULL) - free (free_relocs); - return false; + if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (internal_relocs != NULL + && elf_section_data (datasec)->relocs != internal_relocs) + free (internal_relocs); + return FALSE; } static enum elf_reloc_type_class @@ -2332,7 +2231,7 @@ elf32_m68k_reloc_type_class (rela) _bfd_elf_create_dynamic_sections #define bfd_elf32_bfd_link_hash_table_create \ elf_m68k_link_hash_table_create -#define bfd_elf32_bfd_final_link _bfd_elf32_gc_common_final_link +#define bfd_elf32_bfd_final_link bfd_elf_gc_common_final_link #define elf_backend_check_relocs elf_m68k_check_relocs #define elf_backend_adjust_dynamic_symbol \ @@ -2346,8 +2245,6 @@ elf32_m68k_reloc_type_class (rela) elf_m68k_finish_dynamic_sections #define elf_backend_gc_mark_hook elf_m68k_gc_mark_hook #define elf_backend_gc_sweep_hook elf_m68k_gc_sweep_hook -#define bfd_elf32_bfd_copy_private_bfd_data \ - elf32_m68k_copy_private_bfd_data #define bfd_elf32_bfd_merge_private_bfd_data \ elf32_m68k_merge_private_bfd_data #define bfd_elf32_bfd_set_private_flags \ @@ -2357,9 +2254,11 @@ elf32_m68k_reloc_type_class (rela) #define elf_backend_reloc_type_class elf32_m68k_reloc_type_class #define elf_backend_can_gc_sections 1 +#define elf_backend_can_refcount 1 #define elf_backend_want_got_plt 1 #define elf_backend_plt_readonly 1 #define elf_backend_want_plt_sym 0 #define elf_backend_got_header_size 12 +#define elf_backend_rela_normal 1 #include "elf32-target.h"