/* Motorola 68k series support for 32-bit ELF
- Copyright 1993, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
+ Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ 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 ((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),
/* end code generated by elf.el */
#define USE_RELA
-
\f
/* Functions for the m68k ELF linker. */
/* Procedure linkage table entries for the cpu32 */
static const bfd_byte elf_cpu32_plt0_entry[PLT_CPU32_ENTRY_SIZE] =
{
- 0x22, 0x7b, 0x01, 0x70, /* moveal %pc@(0xc), %a1 */
+ 0x2f, 0x3b, 0x01, 0x70, /* move.l (%pc,addr),-(%sp) */
0, 0, 0, 0, /* replaced with offset to .got + 4. */
+ 0x22, 0x7b, 0x01, 0x70, /* moveal %pc@(0xc), %a1 */
+ 0, 0, 0, 0, /* replace with offset to .got +8. */
0x4e, 0xd1, /* jmp %a1@ */
- 0, 0, 0, 0, /* replace with offset to .got +8. */
- 0, 0, 0, 0, /* pad out to 24 bytes. */
0, 0, 0, 0, /* pad out to 24 bytes. */
0, 0
};
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_alloc (abfd, amt);
if (ret == (struct elf_m68k_link_hash_table *) NULL)
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
|| !bfd_set_section_alignment (dynobj, sreloc, 2))
return false;
}
+ if (sec->flags & SEC_READONLY)
+ info->flags |= DF_TEXTREL;
}
sreloc->_raw_size += sizeof (Elf32_External_Rela);
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;
return true;
}
-
/* Adjust a symbol defined by a dynamic object and referenced by a
regular object. The current definition is in some section of the
dynamic object, but we're not including those sections. We have to
static boolean
elf_m68k_size_dynamic_sections (output_bfd, info)
- bfd *output_bfd;
+ bfd *output_bfd ATTRIBUTE_UNUSED;
struct bfd_link_info *info;
{
bfd *dynobj;
asection *s;
boolean plt;
boolean relocs;
- boolean reltext;
dynobj = elf_hash_table (info)->dynobj;
BFD_ASSERT (dynobj != NULL);
memory for them. */
plt = false;
relocs = false;
- reltext = false;
for (s = dynobj->sections; s != NULL; s = s->next)
{
const char *name;
}
else
{
- asection *target;
-
- /* Remember whether there are any reloc sections other
- than .rela.plt. */
- if (strcmp (name, ".rela.plt") != 0)
- {
- const char *outname;
-
- relocs = true;
-
- /* If this relocation section applies to a read only
- section, then we probably need a DT_TEXTREL
- entry. .rela.plt is actually associated with
- .got.plt, which is never readonly. */
- outname = bfd_get_section_name (output_bfd,
- s->output_section);
- target = bfd_get_section_by_name (output_bfd, outname + 5);
- if (target != NULL
- && (target->flags & SEC_READONLY) != 0
- && (target->flags & SEC_ALLOC) != 0)
- reltext = true;
- }
+ relocs = true;
/* We use the reloc_count field as a counter if we need
to copy relocs into the output file. */
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 (reltext)
+ 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;
- info->flags |= DF_TEXTREL;
}
}
+#undef add_dynamic_entry
return true;
}
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. */
-/*ARGSUSED*/
static boolean
elf_m68k_discard_copies (h, ignore)
struct elf_m68k_link_hash_entry *h;
{
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
{
&& ((! info->symbolic && h->dynindx != -1)
|| (h->elf_link_hash_flags
& ELF_LINK_HASH_DEF_REGULAR) == 0)
- && (input_section->flags & SEC_ALLOC) != 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
}
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;
- }
-
+ outrel.r_offset =
+ _bfd_elf_section_offset (output_bfd, info, input_section,
+ rel->r_offset);
+ if (outrel.r_offset == (bfd_vma) -1)
+ skip = true;
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
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;
}
+ sgot->output_offset + 8
- (splt->output_section->vma + 10)),
splt->contents + 12);
- elf_section_data (splt->output_section)->this_hdr.sh_entsize
+ elf_section_data (splt->output_section)->this_hdr.sh_entsize
= PLT_ENTRY_SIZE;
}
else /* cpu32 */
(sgot->output_section->vma
+ sgot->output_offset + 8
- (splt->output_section->vma + 10)),
- splt->contents + 10);
- elf_section_data (splt->output_section)->this_hdr.sh_entsize
+ splt->contents + 12);
+ elf_section_data (splt->output_section)->this_hdr.sh_entsize
= PLT_CPU32_ENTRY_SIZE;
}
}
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);
}
if (targetsec != NULL)
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)
return false;
}
+static enum elf_reloc_type_class
+elf32_m68k_reloc_type_class (rela)
+ const Elf_Internal_Rela *rela;
+{
+ switch ((int) ELF32_R_TYPE (rela->r_info))
+ {
+ case R_68K_RELATIVE:
+ return reloc_class_relative;
+ case R_68K_JMP_SLOT:
+ return reloc_class_plt;
+ case R_68K_COPY:
+ return reloc_class_copy;
+ default:
+ return reloc_class_normal;
+ }
+}
+
#define TARGET_BIG_SYM bfd_elf32_m68k_vec
#define TARGET_BIG_NAME "elf32-m68k"
#define ELF_MACHINE_CODE EM_68K
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 \
elf32_m68k_set_private_flags
#define bfd_elf32_bfd_print_private_bfd_data \
elf32_m68k_print_private_bfd_data
+#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