/* Motorola 68k series support for 32-bit ELF
- Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
- 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"
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 */
+ /* GNU extension to record C++ vtable hierarchy. */
HOWTO (R_68K_GNU_VTINHERIT, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
0, /* src_mask */
0, /* dst_mask */
FALSE),
- /* GNU extension to record C++ vtable member usage */
+ /* GNU extension to record C++ vtable member usage. */
HOWTO (R_68K_GNU_VTENTRY, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
#define bfd_elf32_bfd_reloc_type_lookup reloc_type_lookup
#define ELF_ARCH bfd_arch_m68k
-/* end code generated by elf.el */
\f
/* Functions for the m68k ELF linker. */
return &ret->root.root;
}
-/* Keep m68k-specific flags in the ELF header */
+/* Keep m68k-specific flags in the ELF header. */
static bfd_boolean
elf32_m68k_set_private_flags (abfd, flags)
bfd *abfd;
return TRUE;
}
-/* Display the flags field */
+/* Display the flags field. */
static bfd_boolean
elf32_m68k_print_private_bfd_data (abfd, ptr)
bfd *abfd;
asection *srelgot;
asection *sreloc;
- if (info->relocateable)
+ if (info->relocatable)
return TRUE;
dynobj = elf_hash_table (info)->dynobj;
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (!bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (!bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (!bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (!bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
|| !bfd_set_section_alignment (dynobj, sreloc, 2))
return FALSE;
}
+ elf_section_data (sec)->sreloc = sreloc;
}
if (sec->flags & SEC_READONLY
/* 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))
+ 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))
+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
return FALSE;
break;
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;
- 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;
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (abfd);
+ local_got_refcounts = elf_local_got_refcounts (abfd);
+
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:
if (h->dynindx == -1
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
{
- if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* 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);
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);
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)
{
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
- if (info->relocateable)
+ if (info->relocatable)
return TRUE;
dynobj = elf_hash_table (info)->dynobj;
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);
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 = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
+ 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)
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
h->got.offset |= 1;
}
}
+ else
+ unresolved_reloc = FALSE;
}
else
{
relocation = (splt->output_section->vma
+ splt->output_offset
+ h->plt.offset);
+ unresolved_reloc = FALSE;
break;
case R_68K_PLT8O:
}
relocation = h->plt.offset;
+ unresolved_reloc = FALSE;
/* This relocation does not use the addend. */
rel->r_addend = 0;
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;
bfd_byte *loc;
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;
relocate = FALSE;
if (skip)
memset (&outrel, 0, sizeof outrel);
- /* h->dynindx may be -1 if the symbol was marked to
- become local. */
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);
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;
{
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)
{
}
}
+ 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);
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;
}
}
}
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);
bfd_byte *p;
bfd_size_type amt;
- BFD_ASSERT (! info->relocateable);
+ BFD_ASSERT (! info->relocatable);
*errmsg = NULL;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
/* 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)
_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 \