/* Motorola 68k series support for 32-bit ELF
- Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
static boolean elf32_m68k_set_private_flags
PARAMS ((bfd *, flagword));
-static boolean elf32_m68k_copy_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
PARAMS ((bfd *, PTR));
static enum elf_reloc_type_class elf32_m68k_reloc_type_class
- PARAMS ((int));
+ 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),
bfd *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, sizeof (struct elf_m68k_link_hash_table)));
+ 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;
}
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;
-}
-
/* Merge backend specific data from an object file to the output
object file when linking. */
static boolean
/* 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);
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)
{
/* Allocate relocation space. */
srelgot->_raw_size += sizeof (Elf32_External_Rela);
}
- else
- h->got.refcount++;
+ h->got.refcount++;
}
else
{
/* This is a global offset table entry for a local symbol. */
if (local_got_refcounts == NULL)
{
- size_t size;
+ bfd_size_type size;
- size = symtab_hdr->sh_info * sizeof (bfd_signed_vma);
+ 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;
elf_local_got_refcounts (abfd) = local_got_refcounts;
- memset (local_got_refcounts, -1, 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)
{
srelgot->_raw_size += sizeof (Elf32_External_Rela);
}
}
- else
- local_got_refcounts[r_symndx]++;
+ local_got_refcounts[r_symndx]++;
}
break;
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:
}
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:
/* 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;
}
{
/* 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
if (p == NULL)
{
p = ((struct elf_m68k_pcrel_relocs_copied *)
- bfd_alloc (dynobj, sizeof *p));
+ bfd_alloc (dynobj, (bfd_size_type) sizeof *p));
if (p == NULL)
return false;
p->next = eh->pcrel_relocs_copied;
}
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 (abfd, sym->st_shndx);
}
return NULL;
must add the entries now so that we get the correct size for
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))
+
if (!info->shared)
{
- if (!bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
+ if (!add_dynamic_entry (DT_DEBUG, 0))
return false;
}
if (plt)
{
- if (!bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0)
- || !bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0)
- || !bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
- || !bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0))
+ if (!add_dynamic_entry (DT_PLTGOT, 0)
+ || !add_dynamic_entry (DT_PLTRELSZ, 0)
+ || !add_dynamic_entry (DT_PLTREL, DT_RELA)
+ || !add_dynamic_entry (DT_JMPREL, 0))
return false;
}
if (relocs)
{
- if (!bfd_elf32_add_dynamic_entry (info, DT_RELA, 0)
- || !bfd_elf32_add_dynamic_entry (info, DT_RELASZ, 0)
- || !bfd_elf32_add_dynamic_entry (info, DT_RELAENT,
- sizeof (Elf32_External_Rela)))
+ if (!add_dynamic_entry (DT_RELA, 0)
+ || !add_dynamic_entry (DT_RELASZ, 0)
+ || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
return false;
}
if ((info->flags & DF_TEXTREL) != 0)
{
- if (!bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
+ if (!add_dynamic_entry (DT_TEXTREL, 0))
return false;
}
}
+#undef add_dynamic_entry
return true;
}
{
struct elf_m68k_pcrel_relocs_copied *s;
+ if (h->root.root.type == bfd_link_hash_warning)
+ h = (struct elf_m68k_link_hash_entry *) h->root.root.u.i.link;
+
/* 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;
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
+ if (info->relocateable)
+ return true;
+
dynobj = elf_hash_table (info)->dynobj;
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd);
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;
{
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
{
}
else if (h->root.type == bfd_link_hash_undefweak)
relocation = 0;
- else if (info->shared && !info->symbolic
+ else if (info->shared
+ && (!info->symbolic || info->allow_shlib_undefined)
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
relocation = 0;
case R_68K_16:
case R_68K_32:
if (info->shared
+ && r_symndx != 0
&& (input_section->flags & SEC_ALLOC) != 0
&& ((r_type != R_68K_PC8
&& r_type != R_68K_PC16
}
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;
- }
-
+ 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;
- }
+ memset (&outrel, 0, sizeof outrel);
/* h->dynindx may be -1 if the symbol was marked to
become local. */
else if (h != NULL
& 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;
}
BFD_ASSERT (indx > 0);
}
- relocate = false;
outrel.r_info = ELF32_R_INFO (indx, r_type);
outrel.r_addend = relocation + rel->r_addend;
}
rela.r_offset = (sgot->output_section->vma
+ sgot->output_offset
- + (h->got.offset &~ 1));
+ + (h->got.offset &~ (bfd_vma) 1));
/* If this is a -Bsymbolic link, and the symbol is defined
locally, we just want to emit a RELATIVE reloc. Likewise if
rela.r_info = ELF32_R_INFO (0, R_68K_RELATIVE);
rela.r_addend = bfd_get_signed_32 (output_bfd,
(sgot->contents
- + (h->got.offset & ~1)));
+ + (h->got.offset &~ (bfd_vma) 1)));
}
else
{
bfd_put_32 (output_bfd, (bfd_vma) 0,
- sgot->contents + (h->got.offset & ~1));
+ sgot->contents + (h->got.offset &~ (bfd_vma) 1));
rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_GLOB_DAT);
rela.r_addend = 0;
}
char **errmsg;
{
Elf_Internal_Shdr *symtab_hdr;
+ Elf_Internal_Shdr *shndx_hdr;
Elf32_External_Sym *extsyms;
Elf32_External_Sym *free_extsyms = NULL;
+ Elf_External_Sym_Shndx *shndx_buf = NULL;
Elf_Internal_Rela *internal_relocs;
Elf_Internal_Rela *free_relocs = NULL;
Elf_Internal_Rela *irel, *irelend;
bfd_byte *p;
+ bfd_size_type amt;
BFD_ASSERT (! info->relocateable);
else
{
/* Go get them off disk. */
+ amt = symtab_hdr->sh_info * sizeof (Elf32_External_Sym);
if (info->keep_memory)
- extsyms = ((Elf32_External_Sym *)
- bfd_alloc (abfd, symtab_hdr->sh_size));
+ extsyms = (Elf32_External_Sym *) bfd_alloc (abfd, amt);
else
- extsyms = ((Elf32_External_Sym *)
- bfd_malloc (symtab_hdr->sh_size));
+ extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
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_read (extsyms, 1, symtab_hdr->sh_size, abfd)
- != symtab_hdr->sh_size))
+ || bfd_bread (extsyms, amt, abfd) != amt)
goto error_return;
if (info->keep_memory)
- symtab_hdr->contents = extsyms;
+ symtab_hdr->contents = (unsigned char *) extsyms;
+ }
+
+ shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+ if (shndx_hdr->sh_size != 0)
+ {
+ amt = symtab_hdr->sh_info * sizeof (Elf_External_Sym_Shndx);
+ shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+ if (shndx_buf == NULL)
+ goto error_return;
+ if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
+ || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
+ goto error_return;
}
/* Get a copy of the native relocations. */
if (! info->keep_memory)
free_relocs = internal_relocs;
- relsec->contents = (bfd_byte *) bfd_alloc (abfd, datasec->reloc_count * 12);
+ amt = (bfd_size_type) datasec->reloc_count * 12;
+ relsec->contents = (bfd_byte *) bfd_alloc (abfd, amt);
if (relsec->contents == NULL)
goto error_return;
/* Get the target section referred to by the reloc. */
if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
{
+ Elf32_External_Sym *esym;
+ Elf_External_Sym_Shndx *shndx;
Elf_Internal_Sym isym;
/* A local symbol. */
- bfd_elf32_swap_symbol_in (abfd,
- extsyms + ELF32_R_SYM (irel->r_info),
- &isym);
+ esym = extsyms + ELF32_R_SYM (irel->r_info);
+ shndx = shndx_buf + (shndx_buf ? ELF32_R_SYM (irel->r_info) : 0);
+ bfd_elf32_swap_symbol_in (abfd, esym, shndx, &isym);
targetsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
}
strncpy (p + 4, targetsec->output_section->name, 8);
}
+ if (shndx_buf != NULL)
+ free (shndx_buf);
if (free_extsyms != NULL)
free (free_extsyms);
if (free_relocs != NULL)
return true;
error_return:
+ if (shndx_buf != NULL)
+ free (shndx_buf);
if (free_extsyms != NULL)
free (free_extsyms);
if (free_relocs != NULL)
}
static enum elf_reloc_type_class
-elf32_m68k_reloc_type_class (type)
- int type;
+elf32_m68k_reloc_type_class (rela)
+ const Elf_Internal_Rela *rela;
{
- switch (type)
+ switch ((int) ELF32_R_TYPE (rela->r_info))
{
case R_68K_RELATIVE:
return reloc_class_relative;
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 \
#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"