/* 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.
const Elf_Internal_Rela *));
static boolean elf_m68k_adjust_dynamic_symbol
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
-static boolean elf_m68k_adjust_dynindx
- PARAMS ((struct elf_link_hash_entry *, PTR));
static boolean elf_m68k_size_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
static boolean elf_m68k_relocate_section
static void
rtype_to_howto (abfd, cache_ptr, dst)
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
arelent *cache_ptr;
Elf_Internal_Rela *dst;
{
static reloc_howto_type *
reloc_type_lookup (abfd, code)
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
bfd_reloc_code_real_type code;
{
unsigned int i;
/* 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] =
{
- 0x20, 0x7b, 0x01, 0x70, /* moveal %pc@(0xc), %a0 */
+ 0x2f, 0x3b, 0x01, 0x70, /* move.l (%pc,addr),-(%sp) */
0, 0, 0, 0, /* replaced with offset to .got + 4. */
- 0x4e, 0xd0, /* jmp %a0@ */
- 0, 0, 0, 0, /* replace with offset to .got +8. */
- 0, 0, 0, 0, /* pad out to 24 bytes. */
+ 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, /* pad out to 24 bytes. */
0, 0
};
static const bfd_byte elf_cpu32_plt_entry[PLT_CPU32_ENTRY_SIZE] =
{
- 0x20, 0x7b, 0x01, 0x70, /* moveal %pc@(0xc), %a0 */
+ 0x22, 0x7b, 0x01, 0x70, /* moveal %pc@(0xc), %a1 */
0, 0, 0, 0, /* replaced with offset to symbol's .got entry. */
- 0x4e, 0xd0, /* jmp %a0@ */
+ 0x4e, 0xd1, /* jmp %a1@ */
0x2f, 0x3c, /* move.l #offset,-(%sp) */
0, 0, 0, 0, /* replaced with offset into relocation table. */
0x60, 0xff, /* bra.l .plt */
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;
}
static asection *
elf_m68k_gc_mark_hook (abfd, info, rel, h, sym)
bfd *abfd;
- struct bfd_link_info *info;
+ struct bfd_link_info *info ATTRIBUTE_UNUSED;
Elf_Internal_Rela *rel;
struct elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
local_got_refcounts = elf_local_got_refcounts (abfd);
dynobj = elf_hash_table (info)->dynobj;
- if (dynobj)
- {
- sgot = bfd_get_section_by_name (dynobj, ".got");
- srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
- }
+ 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++)
}
}
}
- else
+ else if (local_got_refcounts != NULL)
{
if (local_got_refcounts[r_symndx] > 0)
{
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
if (strip)
{
- _bfd_strip_section_from_output (s);
+ _bfd_strip_section_from_output (info, s);
continue;
}
/* Allocate memory for the section contents. */
- s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
+ /* FIXME: This should be a call to bfd_alloc not bfd_zalloc.
+ Unused entries should be reclaimed before the section's contents
+ are written out, but at the moment this does not happen. Thus in
+ order to prevent writing out garbage, we initialise the section's
+ contents to zero. */
+ s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
if (s->contents == NULL && s->_raw_size != 0)
return false;
}
{
if (!bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
return false;
+ info->flags |= DF_TEXTREL;
}
}
- /* If we are generating a shared library, we generate a section
- symbol for each output section for which we might need to copy
- relocs. These are local symbols, which means that they must come
- first in the dynamic symbol table. That means we must increment
- the dynamic symbol index of every other dynamic symbol. */
- if (info->shared)
- {
- int c;
-
- c = 0;
- for (s = output_bfd->sections; s != NULL; s = s->next)
- {
- if ((s->flags & SEC_LINKER_CREATED) != 0
- || (s->flags & SEC_ALLOC) == 0)
- continue;
-
- elf_section_data (s)->dynindx = c + 1;
-
- /* These symbols will have no names, so we don't need to
- fiddle with dynstr_index. */
-
- ++c;
- }
-
- elf_link_hash_traverse (elf_hash_table (info),
- elf_m68k_adjust_dynindx,
- (PTR) &c);
- elf_hash_table (info)->dynsymcount += c;
- }
-
- return true;
-}
-
-/* Increment the index of a dynamic symbol by a given amount. Called
- via elf_link_hash_traverse. */
-
-static boolean
-elf_m68k_adjust_dynindx (h, cparg)
- struct elf_link_hash_entry *h;
- PTR cparg;
-{
- int *cp = (int *) cparg;
-
- if (h->dynindx != -1)
- h->dynindx += *cp;
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;
- PTR ignore;
+ PTR ignore ATTRIBUTE_UNUSED;
{
struct elf_m68k_pcrel_relocs_copied *s;
}
else if (h->root.type == bfd_link_hash_undefweak)
relocation = 0;
- else if (info->shared && !info->symbolic && !info->no_undefined)
+ else if (info->shared && !info->symbolic
+ && !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)))
+ input_section, rel->r_offset,
+ (!info->shared || info->no_undefined
+ || ELF_ST_VISIBILITY (h->other)))))
return false;
relocation = 0;
}
bfd *dynobj;
asection *sgot;
asection *sdyn;
- int plt_entry0_size, plt_off1, plt_off2;
dynobj = elf_hash_table (info)->dynobj;
+ 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;
}
}
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
- if (info->shared)
+ return true;
+}
+
+/* Given a .data section and a .emreloc in-memory section, store
+ relocation information into the .emreloc section which can be
+ used at runtime to relocate the section. This is called by the
+ linker when the --embedded-relocs switch is used. This is called
+ after the add_symbols entry point has been called for all the
+ objects, and before the final_link entry point is called. */
+
+boolean
+bfd_m68k_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *datasec;
+ asection *relsec;
+ 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_Rela *irel, *irelend;
+ bfd_byte *p;
+
+ BFD_ASSERT (! info->relocateable);
+
+ *errmsg = NULL;
+
+ if (datasec->reloc_count == 0)
+ 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
{
- asection *sdynsym;
- asection *s;
- Elf_Internal_Sym sym;
- int c;
+ /* 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_read (extsyms, 1, symtab_hdr->sh_size, abfd)
+ != symtab_hdr->sh_size))
+ goto error_return;
+ if (info->keep_memory)
+ symtab_hdr->contents = extsyms;
+ }
- /* Set up the section symbols for the output sections. */
+ /* Get a copy of the native relocations. */
+ internal_relocs = (_bfd_elf32_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;
- sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
- BFD_ASSERT (sdynsym != NULL);
+ relsec->contents = (bfd_byte *) bfd_alloc (abfd, datasec->reloc_count * 12);
+ if (relsec->contents == NULL)
+ goto error_return;
- sym.st_size = 0;
- sym.st_name = 0;
- sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
- sym.st_other = 0;
+ p = relsec->contents;
- c = 0;
- for (s = output_bfd->sections; s != NULL; s = s->next)
- {
- int indx;
+ irelend = internal_relocs + datasec->reloc_count;
+ for (irel = internal_relocs; irel < irelend; irel++, p += 12)
+ {
+ asection *targetsec;
- if (elf_section_data (s)->dynindx == 0)
- continue;
+ /* We are going to write a four byte longword into the runtime
+ reloc section. The longword will be the address in the data
+ section which must be relocated. It is followed by the name
+ of the target section NUL-padded or truncated to 8
+ characters. */
- sym.st_value = s->vma;
+ /* We can only relocate absolute longword relocs at run time. */
+ if (ELF32_R_TYPE (irel->r_info) != (int) R_68K_32)
+ {
+ *errmsg = _("unsupported reloc type");
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
- indx = elf_section_data (s)->this_idx;
- BFD_ASSERT (indx > 0);
- sym.st_shndx = indx;
+ /* Get the target section referred to by the reloc. */
+ if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
+ {
+ Elf_Internal_Sym isym;
- bfd_elf32_swap_symbol_out (output_bfd, &sym,
- (PTR) (((Elf32_External_Sym *)
- sdynsym->contents)
- + elf_section_data (s)->dynindx));
+ /* A local symbol. */
+ bfd_elf32_swap_symbol_in (abfd,
+ extsyms + ELF32_R_SYM (irel->r_info),
+ &isym);
- ++c;
+ targetsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
+ }
+ else
+ {
+ unsigned long indx;
+ struct elf_link_hash_entry *h;
+
+ /* An external symbol. */
+ indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
+ h = elf_sym_hashes (abfd)[indx];
+ BFD_ASSERT (h != NULL);
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ targetsec = h->root.u.def.section;
+ else
+ targetsec = NULL;
}
- /* Set the sh_info field of the output .dynsym section to the
- index of the first global symbol. */
- elf_section_data (sdynsym->output_section)->this_hdr.sh_info = c + 1;
+ bfd_put_32 (abfd, irel->r_offset + datasec->output_offset, p);
+ memset (p + 4, 0, 8);
+ if (targetsec != NULL)
+ strncpy (p + 4, targetsec->output_section->name, 8);
}
+ if (free_extsyms != NULL)
+ free (free_extsyms);
+ if (free_relocs != NULL)
+ free (free_relocs);
return true;
+
+error_return:
+ if (free_extsyms != NULL)
+ free (free_extsyms);
+ if (free_relocs != NULL)
+ free (free_relocs);
+ return false;
}
#define TARGET_BIG_SYM bfd_elf32_m68k_vec