/* Lattice Mico32-specific support for 32-bit ELF
- Copyright 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+ Copyright (C) 2008-2015 Free Software Foundation, Inc.
Contributed by Jon Beniston <jon@beniston.com>
This file is part of BFD, the Binary File Descriptor library.
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf/lm32.h"
#define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1"
-extern const bfd_target bfd_elf32_lm32fdpic_vec;
+extern const bfd_target lm32_elf32_fdpic_vec;
-#define IS_FDPIC(bfd) ((bfd)->xvec == &bfd_elf32_lm32fdpic_vec)
+#define IS_FDPIC(bfd) ((bfd)->xvec == &lm32_elf32_fdpic_vec)
static bfd_reloc_status_type lm32_elf_gprel_reloc
(bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
struct elf_lm32_link_hash_table *ret;
bfd_size_type amt = sizeof (struct elf_lm32_link_hash_table);
- ret = bfd_malloc (amt);
+ ret = bfd_zmalloc (amt);
if (ret == NULL)
return NULL;
return NULL;
}
- ret->sgot = NULL;
- ret->sgotplt = NULL;
- ret->srelgot = NULL;
- ret->sfixup32 = NULL;
- ret->splt = NULL;
- ret->srelplt = NULL;
- ret->sdynbss = NULL;
- ret->srelbss = NULL;
- ret->relocs32 = 0;
-
return &ret->root.root;
}
asection *s;
/* This function may be called more than once. */
- s = bfd_get_section_by_name (dynobj, ".got");
- if (s != NULL && (s->flags & SEC_LINKER_CREATED) != 0)
+ s = bfd_get_linker_section (dynobj, ".got");
+ if (s != NULL)
return TRUE;
htab = lm32_elf_hash_table (info);
if (! _bfd_elf_create_got_section (dynobj, info))
return FALSE;
- htab->sgot = bfd_get_section_by_name (dynobj, ".got");
- htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
- htab->srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+ htab->sgot = bfd_get_linker_section (dynobj, ".got");
+ htab->sgotplt = bfd_get_linker_section (dynobj, ".got.plt");
+ htab->srelgot = bfd_get_linker_section (dynobj, ".rela.got");
if (! htab->sgot || ! htab->sgotplt || ! htab->srelgot)
abort ();
return FALSE;
/* Fixup section for R_LM32_32 relocs. */
- lm32fdpic_fixup32_section (info) = bfd_make_section_with_flags (dynobj,
- ".rofixup",
- (SEC_ALLOC
- | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_LINKER_CREATED
- | SEC_READONLY));
+ lm32fdpic_fixup32_section (info)
+ = bfd_make_section_anyway_with_flags (dynobj,
+ ".rofixup",
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED
+ | SEC_READONLY));
if (lm32fdpic_fixup32_section (info) == NULL
- || ! bfd_set_section_alignment (dynobj, lm32fdpic_fixup32_section (info), 2))
+ || ! bfd_set_section_alignment (dynobj,
+ lm32fdpic_fixup32_section (info), 2))
return FALSE;
return TRUE;
/* This reloc does nothing. */
HOWTO (R_LM32_NONE, /* type */
0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
- 32, /* bitsize */
+ 3, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_bitfield,/* complain_on_overflow */
+ complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_LM32_NONE", /* name */
FALSE, /* partial_inplace */
unsigned int r_type;
r_type = ELF32_R_TYPE (dst->r_info);
- BFD_ASSERT (r_type < (unsigned int) R_LM32_max);
+ if (r_type >= (unsigned int) R_LM32_max)
+ {
+ _bfd_error_handler (_("%B: invalid LM32 reloc number: %d"), abfd, r_type);
+ r_type = 0;
+ }
cache_ptr->howto = &lm32_elf_howto_table[r_type];
}
Elf_Internal_Phdr *p;
/* Find the segment that contains the output_section. */
- for (m = elf_tdata (output_bfd)->segment_map,
- p = elf_tdata (output_bfd)->phdr;
+ for (m = elf_seg_map (output_bfd), p = elf_tdata (output_bfd)->phdr;
m != NULL;
m = m->next, p++)
{
{
/* It's a global symbol. */
bfd_boolean unresolved_reloc;
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
name = h->root.root.string;
}
- if (sec != NULL && elf_discarded_section (sec))
+ if (sec != NULL && discarded_section (sec))
RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
- rel, relend, howto, contents);
+ rel, 1, relend, howto, 0, contents);
if (info->relocatable)
{
/* We need to generate a R_LM32_RELATIVE reloc
for the dynamic linker. */
- srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+ srelgot = bfd_get_linker_section (dynobj,
+ ".rela.got");
BFD_ASSERT (srelgot != NULL);
outrel.r_offset = (sgot->output_section->vma
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;
+
+ /* PR15323, ref flags aren't set for references in the same
+ object. */
+ h->root.non_ir_ref = 1;
}
/* Some relocs require a global offset table. */
/* Create .rofixup section */
if (htab->sfixup32 == NULL)
{
- if (! create_rofixup_section (abfd, info))
+ if (! create_rofixup_section (dynobj, info))
return FALSE;
}
break;
/* Create .rofixup section. */
if (htab->sfixup32 == NULL)
{
- if (! create_rofixup_section (abfd, info))
+ if (dynobj == NULL)
+ htab->root.dynobj = dynobj = abfd;
+ if (! create_rofixup_section (dynobj, info))
return FALSE;
}
break;
dynobj = htab->root.dynobj;
sgot = htab->sgotplt;
- sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+ sdyn = bfd_get_linker_section (dynobj, ".dynamic");
if (htab->root.dynamic_sections_created)
{
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak));
- s = bfd_get_section_by_name (h->root.u.def.section->owner,
- ".rela.bss");
+ s = bfd_get_linker_section (htab->root.dynobj, ".rela.bss");
BFD_ASSERT (s != NULL);
rela.r_offset = (h->root.u.def.value
}
/* Mark some specially defined symbols as absolute. */
- if (strcmp (h->root.root.string, "_DYNAMIC") == 0
- || h == htab->root.hgot)
+ if (h == htab->root.hdynamic || h == htab->root.hgot)
sym->st_shndx = SHN_ABS;
return TRUE;
}
static enum elf_reloc_type_class
-lm32_elf_reloc_type_class (const Elf_Internal_Rela *rela)
+lm32_elf_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ const asection *rel_sec ATTRIBUTE_UNUSED,
+ const Elf_Internal_Rela *rela)
{
switch ((int) ELF32_R_TYPE (rela->r_info))
{
h->needs_copy = 1;
}
- return _bfd_elf_adjust_dynamic_copy (h, s);
+ return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
/* Allocate space in .plt, .got and associated reloc sections for
/* Set the contents of the .interp section to the interpreter. */
if (info->executable)
{
- s = bfd_get_section_by_name (dynobj, ".interp");
+ s = bfd_get_linker_section (dynobj, ".interp");
BFD_ASSERT (s != NULL);
s->size = sizeof ELF_DYNAMIC_INTERPRETER;
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
/* Set up .got offsets for local syms, and space for local dynamic
relocs. */
- for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
{
bfd_signed_vma *local_got;
bfd_signed_vma *end_local_got;
int r32_count = 0;
int rgot_count = 0;
/* Look for deleted sections. */
- for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
{
for (s = ibfd->sections; s != NULL; s = s->next)
{
/* Don't generate entries for weak symbols. */
if (!h || (h && h->root.type != bfd_link_hash_undefweak))
{
- if (!elf_discarded_section (s) && !((bfd_get_section_flags (ibfd, s) & SEC_ALLOC) == 0))
+ if (!discarded_section (s) && !((bfd_get_section_flags (ibfd, s) & SEC_ALLOC) == 0))
{
switch (ELF32_R_TYPE (internal_relocs->r_info))
{
if (!strcmp (current->name, h->root.root.string))
break;
}
- if (!current && !elf_discarded_section (s) && (bfd_get_section_flags (ibfd, s) & SEC_ALLOC))
+ if (!current && !discarded_section (s) && (bfd_get_section_flags (ibfd, s) & SEC_ALLOC))
{
/* Will this have an entry in the GOT. */
if (ELF32_R_TYPE (internal_relocs->r_info) == R_LM32_16_GOT)
if (bed->plt_readonly)
pltflags |= SEC_READONLY;
- s = bfd_make_section_with_flags (abfd, ".plt", pltflags);
+ s = bfd_make_section_anyway_with_flags (abfd, ".plt", pltflags);
htab->splt = s;
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
return FALSE;
}
- s = bfd_make_section_with_flags (abfd,
- bed->default_use_rela_p ? ".rela.plt" : ".rel.plt",
- flags | SEC_READONLY);
+ s = bfd_make_section_anyway_with_flags (abfd,
+ bed->default_use_rela_p
+ ? ".rela.plt" : ".rel.plt",
+ flags | SEC_READONLY);
htab->srelplt = s;
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, ptralign))
&& ! create_got_section (abfd, info))
return FALSE;
- {
- const char *secname;
- char *relname;
- flagword secflags;
- asection *sec;
-
- for (sec = abfd->sections; sec; sec = sec->next)
- {
- secflags = bfd_get_section_flags (abfd, sec);
- if ((secflags & (SEC_DATA | SEC_LINKER_CREATED))
- || ((secflags & SEC_HAS_CONTENTS) != SEC_HAS_CONTENTS))
- continue;
- secname = bfd_get_section_name (abfd, sec);
- relname = bfd_malloc ((bfd_size_type) strlen (secname) + 6);
- strcpy (relname, ".rela");
- strcat (relname, secname);
- if (bfd_get_section_by_name (abfd, secname))
- continue;
- s = bfd_make_section_with_flags (abfd, relname,
- flags | SEC_READONLY);
- if (s == NULL
- || ! bfd_set_section_alignment (abfd, s, ptralign))
- return FALSE;
- }
- }
-
if (bed->want_dynbss)
{
/* The .dynbss section is a place to put symbols which are defined
image and use a R_*_COPY reloc to tell the dynamic linker to
initialize them at run time. The linker script puts the .dynbss
section into the .bss section of the final image. */
- s = bfd_make_section_with_flags (abfd, ".dynbss",
- SEC_ALLOC | SEC_LINKER_CREATED);
+ s = bfd_make_section_anyway_with_flags (abfd, ".dynbss",
+ SEC_ALLOC | SEC_LINKER_CREATED);
htab->sdynbss = s;
if (s == NULL)
return FALSE;
copy relocs. */
if (! info->shared)
{
- s = bfd_make_section_with_flags (abfd,
- (bed->default_use_rela_p
- ? ".rela.bss" : ".rel.bss"),
- flags | SEC_READONLY);
+ s = bfd_make_section_anyway_with_flags (abfd,
+ (bed->default_use_rela_p
+ ? ".rela.bss" : ".rel.bss"),
+ flags | SEC_READONLY);
htab->srelbss = s;
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, ptralign))
}
static bfd_boolean
-lm32_elf_always_size_sections (bfd *output_bfd,
- struct bfd_link_info *info)
+lm32_elf_always_size_sections (bfd *output_bfd, struct bfd_link_info *info)
{
if (!info->relocatable)
{
- struct elf_link_hash_entry *h;
-
- /* Force a PT_GNU_STACK segment to be created. */
- if (! elf_tdata (output_bfd)->stack_flags)
- elf_tdata (output_bfd)->stack_flags = PF_R | PF_W | PF_X;
-
- /* Define __stacksize if it's not defined yet. */
- h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize",
- FALSE, FALSE, FALSE);
- if (! h || h->root.type != bfd_link_hash_defined
- || h->type != STT_OBJECT
- || !h->def_regular)
- {
- struct bfd_link_hash_entry *bh = NULL;
+ if (!bfd_elf_stack_segment_size (output_bfd, info,
+ "__stacksize", DEFAULT_STACK_SIZE))
+ return FALSE;
- if (!(_bfd_generic_link_add_one_symbol
- (info, output_bfd, "__stacksize",
- BSF_GLOBAL, bfd_abs_section_ptr, DEFAULT_STACK_SIZE,
- (const char *) NULL, FALSE,
- get_elf_backend_data (output_bfd)->collect, &bh)))
- return FALSE;
-
- h = (struct elf_link_hash_entry *) bh;
- h->def_regular = 1;
- h->type = STT_OBJECT;
- /* This one must NOT be hidden. */
- }
- }
-
- return TRUE;
-}
-
-static bfd_boolean
-lm32_elf_modify_segment_map (bfd *output_bfd,
- struct bfd_link_info *info)
-{
- struct elf_segment_map *m;
-
- /* objcopy and strip preserve what's already there using elf32_lm32fdpic_copy_
- private_bfd_data (). */
- if (! info)
- return TRUE;
-
- for (m = elf_tdata (output_bfd)->segment_map; m != NULL; m = m->next)
- if (m->p_type == PT_GNU_STACK)
- break;
-
- if (m)
- {
asection *sec = bfd_get_section_by_name (output_bfd, ".stack");
- struct elf_link_hash_entry *h;
-
if (sec)
- {
- /* Obtain the pointer to the __stacksize symbol. */
- h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize",
- FALSE, FALSE, FALSE);
- 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;
- BFD_ASSERT (h->root.type == bfd_link_hash_defined);
-
- /* Set the section size from the symbol value. We
- intentionally ignore the symbol section. */
- if (h->root.type == bfd_link_hash_defined)
- sec->size = h->root.u.def.value;
- else
- sec->size = DEFAULT_STACK_SIZE;
-
- /* Add the stack section to the PT_GNU_STACK segment,
- such that its size and alignment requirements make it
- to the segment. */
- m->sections[m->count] = sec;
- m->count++;
- }
- }
-
- return TRUE;
-}
-
-static bfd_boolean
-lm32_elf_modify_program_headers (bfd *output_bfd,
- struct bfd_link_info *info)
-{
- struct elf_obj_tdata *tdata = elf_tdata (output_bfd);
- struct elf_segment_map *m;
- Elf_Internal_Phdr *p;
-
- if (! info)
- return TRUE;
-
- for (p = tdata->phdr, m = tdata->segment_map; m != NULL; m = m->next, p++)
- if (m->p_type == PT_GNU_STACK)
- break;
-
- if (m)
- {
- struct elf_link_hash_entry *h;
-
- /* Obtain the pointer to the __stacksize symbol. */
- h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize",
- FALSE, FALSE, FALSE);
- if (h)
- {
- 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;
- BFD_ASSERT (h->root.type == bfd_link_hash_defined);
- }
-
- /* Set the header p_memsz from the symbol value. We
- intentionally ignore the symbol section. */
- if (h && h->root.type == bfd_link_hash_defined)
- p->p_memsz = h->root.u.def.value;
- else
- p->p_memsz = DEFAULT_STACK_SIZE;
-
- p->p_align = 8;
+ sec->size = info->stacksize >= 0 ? info->stacksize : 0;
}
return TRUE;
}
-
-static bfd_boolean
-lm32_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
-{
- if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
- || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return TRUE;
-
- BFD_ASSERT (!elf_flags_init (obfd)
- || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
-
- elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
- elf_flags_init (obfd) = TRUE;
-
- /* Copy object attributes. */
- _bfd_elf_copy_obj_attributes (ibfd, obfd);
-
- return TRUE;
-}
-
-
static bfd_boolean
lm32_elf_fdpic_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
{
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
return TRUE;
- if (! lm32_elf_copy_private_bfd_data (ibfd, obfd))
+ if (! _bfd_elf_copy_private_bfd_data (ibfd, obfd))
return FALSE;
if (! elf_tdata (ibfd) || ! elf_tdata (ibfd)->phdr
#define ELF_MACHINE_CODE EM_LATTICEMICO32
#define ELF_MAXPAGESIZE 0x1000
-#define TARGET_BIG_SYM bfd_elf32_lm32_vec
+#define TARGET_BIG_SYM lm32_elf32_vec
#define TARGET_BIG_NAME "elf32-lm32"
#define bfd_elf32_bfd_reloc_type_lookup lm32_reloc_type_lookup
#define elf_backend_rela_normal 1
#define elf_backend_object_p lm32_elf_object_p
#define elf_backend_final_write_processing lm32_elf_final_write_processing
+#define elf_backend_stack_align 8
#define elf_backend_can_gc_sections 1
#define elf_backend_can_refcount 1
#define elf_backend_gc_mark_hook lm32_elf_gc_mark_hook
#undef TARGET_BIG_SYM
-#define TARGET_BIG_SYM bfd_elf32_lm32fdpic_vec
+#define TARGET_BIG_SYM lm32_elf32_fdpic_vec
#undef TARGET_BIG_NAME
#define TARGET_BIG_NAME "elf32-lm32fdpic"
#undef elf32_bed
#undef elf_backend_always_size_sections
#define elf_backend_always_size_sections lm32_elf_always_size_sections
-#undef elf_backend_modify_segment_map
-#define elf_backend_modify_segment_map lm32_elf_modify_segment_map
-#undef elf_backend_modify_program_headers
-#define elf_backend_modify_program_headers lm32_elf_modify_program_headers
#undef bfd_elf32_bfd_copy_private_bfd_data
#define bfd_elf32_bfd_copy_private_bfd_data lm32_elf_fdpic_copy_private_bfd_data