/* 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 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] =
{
- 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 */
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;
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
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. */
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;
}
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;
}
}
-
- /* 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;
- }
+#undef add_dynamic_entry
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;
-}
-
/* 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. */
-/*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 && !info->no_undefined)
+ 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)))
+ input_section, rel->r_offset,
+ (!info->shared || info->no_undefined
+ || ELF_ST_VISIBILITY (h->other)))))
return false;
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;
}
}
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;
+ 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);
+
+ *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. */
+ amt = symtab_hdr->sh_info * sizeof (Elf32_External_Sym);
+ if (info->keep_memory)
+ extsyms = (Elf32_External_Sym *) bfd_alloc (abfd, amt);
+ else
+ 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_bread (extsyms, amt, abfd) != amt)
+ goto error_return;
+ if (info->keep_memory)
+ symtab_hdr->contents = (unsigned char *) extsyms;
+ }
- /* Set up the section symbols for the output sections. */
+ 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;
+ }
- sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
- BFD_ASSERT (sdynsym != NULL);
+ /* 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;
- sym.st_size = 0;
- sym.st_name = 0;
- sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
- sym.st_other = 0;
+ amt = (bfd_size_type) datasec->reloc_count * 12;
+ relsec->contents = (bfd_byte *) bfd_alloc (abfd, amt);
+ if (relsec->contents == NULL)
+ goto error_return;
- c = 0;
- for (s = output_bfd->sections; s != NULL; s = s->next)
- {
- int indx;
+ p = relsec->contents;
- if (elf_section_data (s)->dynindx == 0)
- continue;
+ irelend = internal_relocs + datasec->reloc_count;
+ for (irel = internal_relocs; irel < irelend; irel++, p += 12)
+ {
+ asection *targetsec;
+
+ /* 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. */
+
+ /* 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;
+ }
- sym.st_value = s->vma;
+ /* 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;
- indx = elf_section_data (s)->this_idx;
- BFD_ASSERT (indx > 0);
- sym.st_shndx = indx;
+ /* A local symbol. */
+ 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);
- bfd_elf32_swap_symbol_out (output_bfd, &sym,
- (PTR) (((Elf32_External_Sym *)
- sdynsym->contents)
- + elf_section_data (s)->dynindx));
+ targetsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
+ }
+ else
+ {
+ unsigned long indx;
+ struct elf_link_hash_entry *h;
- ++c;
+ /* 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 (shndx_buf != NULL)
+ free (shndx_buf);
+ if (free_extsyms != NULL)
+ free (free_extsyms);
+ if (free_relocs != NULL)
+ free (free_relocs);
return true;
+
+error_return:
+ if (shndx_buf != NULL)
+ free (shndx_buf);
+ if (free_extsyms != NULL)
+ free (free_extsyms);
+ if (free_relocs != NULL)
+ free (free_relocs);
+ 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
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