/* ADI Blackfin BFD support for 32-bit ELF.
- Copyright 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2005-2015 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
bfd *abfd ATTRIBUTE_UNUSED,
arelent *reloc_entry ATTRIBUTE_UNUSED,
asymbol *symbol ATTRIBUTE_UNUSED,
- PTR data ATTRIBUTE_UNUSED,
+ void * data ATTRIBUTE_UNUSED,
asection *input_section ATTRIBUTE_UNUSED,
bfd *output_bfd ATTRIBUTE_UNUSED,
char **error_message ATTRIBUTE_UNUSED)
bfin_pcrel24_reloc (bfd *abfd,
arelent *reloc_entry,
asymbol *symbol,
- PTR data,
+ void * data,
asection *input_section,
bfd *output_bfd,
char **error_message ATTRIBUTE_UNUSED)
/* if rightshift is 1 and the number odd, return error. */
if (howto->rightshift && (relocation & 0x01))
{
- fprintf(stderr, "relocation should be even number\n");
+ (*_bfd_error_handler) (_("relocation should be even number"));
return bfd_reloc_overflow;
}
bfin_imm16_reloc (bfd *abfd,
arelent *reloc_entry,
asymbol *symbol,
- PTR data,
+ void * data,
asection *input_section,
bfd *output_bfd,
char **error_message ATTRIBUTE_UNUSED)
bfin_byte4_reloc (bfd *abfd,
arelent *reloc_entry,
asymbol *symbol,
- PTR data,
+ void * data,
asection *input_section,
bfd *output_bfd,
char **error_message ATTRIBUTE_UNUSED)
bfin_bfd_reloc (bfd *abfd,
arelent *reloc_entry,
asymbol *symbol,
- PTR data,
+ void * data,
asection *input_section,
bfd *output_bfd,
char **error_message ATTRIBUTE_UNUSED)
/* If rightshift is 1 and the number odd, return error. */
if (howto->rightshift && (relocation & 0x01))
{
- fprintf(stderr, "relocation should be even number\n");
+ (*_bfd_error_handler) (_("relocation should be even number"));
return bfd_reloc_overflow;
}
/* This reloc does nothing. . */
HOWTO (R_BFIN_UNUSED0, /* 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_BFIN_UNUSED0", /* name. */
FALSE, /* partial_inplace. */
HOWTO (R_BFIN_UNUSED1, /* 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_BFIN_UNUSED1", /* name. */
FALSE, /* partial_inplace. */
HOWTO (R_BFIN_UNUSEDB, /* 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_dont, /* complain_on_overflow. */
HOWTO (R_BFIN_UNUSEDC, /* 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_dont, /* complain_on_overflow. */
bfd_reloc_code_real_type code)
{
unsigned int i;
- unsigned int r_type = BFIN_RELOC_MIN;
+ unsigned int r_type = (unsigned int) -1;
- for (i = sizeof (bfin_reloc_map) / sizeof (bfin_reloc_map[0]); --i;)
+ for (i = sizeof (bfin_reloc_map) / sizeof (bfin_reloc_map[0]); i--;)
if (bfin_reloc_map[i].bfd_reloc_val == code)
r_type = bfin_reloc_map[i].bfin_reloc_val;
- if (r_type <= BFIN_RELOC_MAX && r_type > BFIN_RELOC_MIN)
+ if (r_type <= BFIN_RELOC_MAX)
return &bfin_howto_table [r_type];
else if (r_type >= BFIN_GNUEXT_RELOC_MIN && r_type <= BFIN_GNUEXT_RELOC_MAX)
/* Given a bfin relocation type, return the howto. */
static reloc_howto_type *
bfin_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
- unsigned int r_type)
+ unsigned int r_type)
{
if (r_type <= BFIN_RELOC_MAX)
return &bfin_howto_table [r_type];
return (reloc_howto_type *) NULL;
}
+/* Set by ld emulation if --code-in-l1. */
+bfd_boolean elf32_bfin_code_in_l1 = 0;
+
+/* Set by ld emulation if --data-in-l1. */
+bfd_boolean elf32_bfin_data_in_l1 = 0;
+
+static void
+elf32_bfin_final_write_processing (bfd *abfd,
+ bfd_boolean linker ATTRIBUTE_UNUSED)
+{
+ if (elf32_bfin_code_in_l1)
+ elf_elfheader (abfd)->e_flags |= EF_BFIN_CODE_IN_L1;
+ if (elf32_bfin_data_in_l1)
+ elf_elfheader (abfd)->e_flags |= EF_BFIN_DATA_IN_L1;
+}
+
/* Return TRUE if the name is a local label.
bfin local labels begin with L$. */
static bfd_boolean
-bfin_is_local_label_name (
- bfd *abfd,
- const char *label)
+bfin_is_local_label_name (bfd *abfd, const char *label)
{
if (label[0] == 'L' && label[1] == '$' )
return TRUE;
const Elf_Internal_Rela *rel_end;
asection *sgot;
asection *srelgot;
- if (info->relocatable)
+
+ if (bfd_link_relocatable (info))
return TRUE;
dynobj = elf_hash_table (info)->dynobj;
if (r_symndx < symtab_hdr->sh_info)
h = NULL;
else
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ {
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+
+ /* PR15323, ref flags aren't set for references in the same
+ object. */
+ h->root.non_ir_ref = 1;
+ }
switch (ELF32_R_TYPE (rel->r_info))
{
if (sgot == NULL)
{
- sgot = bfd_get_section_by_name (dynobj, ".got");
+ sgot = bfd_get_linker_section (dynobj, ".got");
BFD_ASSERT (sgot != NULL);
}
- if (srelgot == NULL && (h != NULL || info->shared))
+ if (srelgot == NULL && (h != NULL || bfd_link_pic (info)))
{
- srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+ srelgot = bfd_get_linker_section (dynobj, ".rela.got");
if (srelgot == NULL)
{
flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
| SEC_IN_MEMORY | SEC_LINKER_CREATED
| SEC_READONLY);
- srelgot = bfd_make_section_with_flags (dynobj, ".rela.got",
- flags);
+ srelgot = bfd_make_section_anyway_with_flags (dynobj,
+ ".rela.got",
+ flags);
if (srelgot == NULL
|| !bfd_set_section_alignment (dynobj, srelgot, 2))
return FALSE;
if (local_got_refcounts[r_symndx] == 0)
{
sgot->size += 4;
- if (info->shared)
+ if (bfd_link_pic (info))
{
/* If we are generating a shared object, we need to
output a R_68K_RELATIVE reloc so that the dynamic
}
static enum elf_reloc_type_class
-elf32_bfin_reloc_type_class (const Elf_Internal_Rela * rela)
+elf32_bfin_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))
{
}
else
{
- 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);
}
- if (sec != NULL && elf_discarded_section (sec))
- {
- /* For relocs against symbols from removed linkonce sections,
- or sections discarded by a linker script, we just want the
- section contents zeroed. Avoid any special processing. */
- _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
- rel->r_info = 0;
- rel->r_addend = 0;
- continue;
- }
+ if (sec != NULL && discarded_section (sec))
+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+ rel, 1, relend, howto, 0, contents);
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
continue;
address = rel->r_offset;
if (sgot == NULL)
{
- sgot = bfd_get_section_by_name (dynobj, ".got");
+ sgot = bfd_get_linker_section (dynobj, ".got");
BFD_ASSERT (sgot != NULL);
}
BFD_ASSERT (off != (bfd_vma) - 1);
dyn = elf_hash_table (info)->dynamic_sections_created;
- if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
- || (info->shared
+ if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
+ bfd_link_pic (info),
+ h)
+ || (bfd_link_pic (info)
&& (info->symbolic
|| h->dynindx == -1
|| h->forced_local)
{
bfd_put_32 (output_bfd, relocation, sgot->contents + off);
- if (info->shared)
+ if (bfd_link_pic (info))
{
asection *s;
Elf_Internal_Rela outrel;
bfd_byte *loc;
- s = bfd_get_section_by_name (dynobj, ".rela.got");
+ s = bfd_get_linker_section (dynobj, ".rela.got");
BFD_ASSERT (s != NULL);
outrel.r_offset = (sgot->output_section->vma
because such sections are not SEC_ALLOC and thus ld.so will
not process them. */
if (unresolved_reloc
- && !((input_section->flags & SEC_DEBUGGING) != 0 && h->def_dynamic))
+ && !((input_section->flags & SEC_DEBUGGING) != 0 && h->def_dynamic)
+ && _bfd_elf_section_offset (output_bfd, info, input_section,
+ rel->r_offset) != (bfd_vma) -1)
{
(*_bfd_error_handler)
(_("%B(%A+0x%lx): unresolvable relocation against symbol `%s'"),
sym_hashes = elf_sym_hashes (abfd);
local_got_refcounts = elf_local_got_refcounts (abfd);
- sgot = bfd_get_section_by_name (dynobj, ".got");
- srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+ sgot = bfd_get_linker_section (dynobj, ".got");
+ srelgot = bfd_get_linker_section (dynobj, ".rela.got");
relend = relocs + sec->reloc_count;
for (rel = relocs; rel < relend; rel++)
{
/* We don't need the .got entry any more. */
sgot->size -= 4;
- if (info->shared)
+ if (bfd_link_pic (info))
srelgot->size -= sizeof (Elf32_External_Rela);
}
}
return TRUE;
}
\f
-extern const bfd_target bfd_elf32_bfinfdpic_vec;
-#define IS_FDPIC(bfd) ((bfd)->xvec == &bfd_elf32_bfinfdpic_vec)
+extern const bfd_target bfin_elf32_fdpic_vec;
+#define IS_FDPIC(bfd) ((bfd)->xvec == &bfin_elf32_fdpic_vec)
-/* An extension of the elf hash table data structure, containing some
- additional Blackfin-specific data. */
+/* An extension of the elf hash table data structure,
+ containing some additional Blackfin-specific data. */
struct bfinfdpic_elf_link_hash_table
{
struct elf_link_hash_table elf;
/* A hash table holding information about which symbols were
referenced with which PIC-related relocations. */
struct htab *relocs_info;
+ /* Summary reloc information collected by
+ _bfinfdpic_count_got_plt_entries. */
+ struct _bfinfdpic_dynamic_got_info *g;
};
/* Get the Blackfin ELF linker hash table from a link_info structure. */
#define bfinfdpic_hash_table(info) \
- ((struct bfinfdpic_elf_link_hash_table *) ((info)->hash))
+ (elf_hash_table_id ((struct elf_link_hash_table *) ((info)->hash)) \
+ == BFIN_ELF_DATA ? ((struct bfinfdpic_elf_link_hash_table *) ((info)->hash)) : NULL)
#define bfinfdpic_got_section(info) \
(bfinfdpic_hash_table (info)->sgot)
(bfinfdpic_hash_table (info)->got0)
#define bfinfdpic_plt_initial_offset(info) \
(bfinfdpic_hash_table (info)->plt0)
+#define bfinfdpic_dynamic_got_plt_info(info) \
+ (bfinfdpic_hash_table (info)->g)
/* The name of the dynamic interpreter. This is put in the .interp
section. */
struct bfinfdpic_elf_link_hash_table *ret;
bfd_size_type amt = sizeof (struct bfinfdpic_elf_link_hash_table);
- ret = bfd_zalloc (abfd, amt);
+ ret = bfd_zmalloc (amt);
if (ret == NULL)
return NULL;
if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd,
_bfd_elf_link_hash_newfunc,
- sizeof (struct elf_link_hash_entry)))
+ sizeof (struct elf_link_hash_entry),
+ BFIN_ELF_DATA))
{
free (ret);
return NULL;
const struct bfinfdpic_relocs_info *entry,
enum insert_option insert)
{
- struct bfinfdpic_relocs_info **loc =
- (struct bfinfdpic_relocs_info **) htab_find_slot (ht, entry, insert);
+ struct bfinfdpic_relocs_info **loc;
+
+ if (!ht)
+ return NULL;
+
+ loc = (struct bfinfdpic_relocs_info **) htab_find_slot (ht, entry, insert);
if (! loc)
return NULL;
for memory allocation purposes. */
inline static struct bfinfdpic_relocs_info *
bfinfdpic_relocs_info_for_global (struct htab *ht,
- bfd *abfd,
- struct elf_link_hash_entry *h,
- bfd_vma addend,
- enum insert_option insert)
+ bfd *abfd,
+ struct elf_link_hash_entry *h,
+ bfd_vma addend,
+ enum insert_option insert)
{
struct bfinfdpic_relocs_info entry;
inline static void
bfinfdpic_pic_merge_early_relocs_info (struct bfinfdpic_relocs_info *e2,
- struct bfinfdpic_relocs_info const *e1)
+ struct bfinfdpic_relocs_info const *e1)
{
e2->got17m4 |= e1->got17m4;
e2->gothilo |= e1->gothilo;
static bfd_vma
_bfinfdpic_add_rofixup (bfd *output_bfd, asection *rofixup, bfd_vma offset,
- struct bfinfdpic_relocs_info *entry)
+ struct bfinfdpic_relocs_info *entry)
{
bfd_vma fixup_offset;
asection *sec,
Elf_Internal_Sym *sym,
bfd_vma addend)
-
{
- bfd_vma fd_lazy_rel_offset = (bfd_vma)-1;
+ bfd_vma fd_lazy_rel_offset = (bfd_vma) -1;
int dynindx = -1;
if (entry->done)
dynindx = entry->d.h->dynindx;
else
{
- if (sec->output_section
+ if (sec
+ && sec->output_section
&& ! bfd_is_abs_section (sec->output_section)
&& ! bfd_is_und_section (sec->output_section))
dynindx = elf_section_data (sec->output_section)->dynindx;
/* If we're linking an executable at a fixed address, we can
omit the dynamic relocation as long as the symbol is local to
this module. */
- if (info->executable && !info->pie
+ if (bfd_link_pde (info)
&& (entry->symndx != -1
|| BFINFDPIC_SYM_LOCAL (info, entry->d.h)))
{
if (entry->symndx == -1
&& ! BFINFDPIC_FUNCDESC_LOCAL (info, entry->d.h)
&& BFINFDPIC_SYM_LOCAL (info, entry->d.h)
- && !(info->executable && !info->pie))
+ && !bfd_link_pde (info))
{
reloc = R_BFIN_FUNCDESC;
idx = elf_section_data (entry->d.h->root.u.def.section
dynamic symbol entry for the got section, so idx will be
zero, which means we can and should compute the address
of the private descriptor ourselves. */
- if (info->executable && !info->pie
+ if (bfd_link_pde (info)
&& (entry->symndx != -1
|| BFINFDPIC_FUNCDESC_LOCAL (info, entry->d.h)))
{
/* If we're linking an executable at a fixed address, we can
omit the dynamic relocation as long as the symbol is local to
this module. */
- if (info->executable && !info->pie
+ if (bfd_link_pde (info)
&& (entry->symndx != -1 || BFINFDPIC_SYM_LOCAL (info, entry->d.h)))
{
if (sec)
/* If we've omitted the dynamic relocation, just emit the fixed
addresses of the symbol and of the local GOT base offset. */
- if (info->executable && !info->pie && sec && sec->output_section)
+ if (bfd_link_pde (info)
+ && sec
+ && sec->output_section)
{
lowword = ad;
highword = bfinfdpic_got_section (info)->output_section->vma
of the section. For a non-local function, it's
disregarded. */
lowword = ad;
- if (entry->symndx == -1 && entry->d.h->dynindx != -1
- && entry->d.h->dynindx == idx)
+ if (sec == NULL
+ || (entry->symndx == -1 && entry->d.h->dynindx != -1
+ && entry->d.h->dynindx == idx))
highword = 0;
else
highword = _bfinfdpic_osec_to_segment
Elf_Internal_Rela *relend;
unsigned isec_segment, got_segment, plt_segment,
check_segment[2];
- int silence_segment_error = !(info->shared || info->pie);
+ int silence_segment_error = !bfd_link_pic (info);
symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd);
}
else
{
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
bfd_boolean unresolved_reloc;
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);
osec = sec;
}
- if (sec != NULL && elf_discarded_section (sec))
- {
- /* For relocs against symbols from removed linkonce sections,
- or sections discarded by a linker script, we just want the
- section contents zeroed. Avoid any special processing. */
- _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
- rel->r_info = 0;
- rel->r_addend = 0;
- continue;
- }
+ if (sec != NULL && discarded_section (sec))
+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+ rel, 1, relend, howto, 0, contents);
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
continue;
if (h != NULL
default:
non_fdpic:
picrel = NULL;
- if (h && ! BFINFDPIC_SYM_LOCAL (info, h))
+ if (h && ! BFINFDPIC_SYM_LOCAL (info, h)
+ && _bfd_elf_section_offset (output_bfd, info, input_section,
+ rel->r_offset) != (bfd_vma) -1)
{
info->callbacks->warning
(info, _("relocation references symbol not defined in the module"),
section+offset. */
if (h && ! BFINFDPIC_FUNCDESC_LOCAL (info, h)
&& BFINFDPIC_SYM_LOCAL (info, h)
- && !(info->executable && !info->pie))
+ && !bfd_link_pde (info))
{
dynindx = elf_section_data (h->root.u.def.section
->output_section)->dynindx;
dynamic symbol entry for the got section, so idx will
be zero, which means we can and should compute the
address of the private descriptor ourselves. */
- if (info->executable && !info->pie
+ if (bfd_link_pde (info)
&& (!h || BFINFDPIC_FUNCDESC_LOCAL (info, h)))
{
+ bfd_vma offset;
+
addend += bfinfdpic_got_section (info)->output_section->vma;
if ((bfd_get_section_flags (output_bfd,
input_section->output_section)
name, input_bfd, input_section, rel->r_offset);
return FALSE;
}
- _bfinfdpic_add_rofixup (output_bfd,
- bfinfdpic_gotfixup_section
- (info),
- _bfd_elf_section_offset
- (output_bfd, info,
- input_section, rel->r_offset)
- + input_section
- ->output_section->vma
- + input_section->output_offset,
- picrel);
+
+ offset = _bfd_elf_section_offset
+ (output_bfd, info,
+ input_section, rel->r_offset);
+
+ if (offset != (bfd_vma)-1)
+ _bfinfdpic_add_rofixup (output_bfd,
+ bfinfdpic_gotfixup_section
+ (info),
+ offset + input_section
+ ->output_section->vma
+ + input_section->output_offset,
+ picrel);
}
}
else if ((bfd_get_section_flags (output_bfd,
}
offset = _bfd_elf_section_offset (output_bfd, info,
input_section, rel->r_offset);
- /* Only output a reloc for a not deleted entry. */
- if (offset >= (bfd_vma) -2)
- _bfinfdpic_add_dyn_reloc (output_bfd,
- bfinfdpic_gotrel_section (info),
- 0,
- R_BFIN_UNUSED0,
- dynindx, addend, picrel);
- else
+
+ if (offset != (bfd_vma)-1)
_bfinfdpic_add_dyn_reloc (output_bfd,
bfinfdpic_gotrel_section (info),
offset + input_section
can omit the dynamic relocation as long as the symbol
is defined in the current link unit (which is implied
by its output section not being NULL). */
- if (info->executable && !info->pie
+ if (bfd_link_pde (info)
&& (!h || BFINFDPIC_SYM_LOCAL (info, h)))
{
if (osec)
}
if (!h || h->root.type != bfd_link_hash_undefweak)
{
- /* Only output a reloc for a not deleted entry. */
- if (offset >= (bfd_vma)-2)
- _bfinfdpic_add_rofixup (output_bfd,
- bfinfdpic_gotfixup_section
- (info), -1, picrel);
- else
- _bfinfdpic_add_rofixup (output_bfd,
- bfinfdpic_gotfixup_section
- (info),
- offset + input_section
- ->output_section->vma
- + input_section->output_offset,
- picrel);
-
- if (r_type == R_BFIN_FUNCDESC_VALUE)
+ if (offset != (bfd_vma)-1)
{
- if (offset >= (bfd_vma)-2)
- _bfinfdpic_add_rofixup
- (output_bfd,
- bfinfdpic_gotfixup_section (info),
- -1, picrel);
- else
+ _bfinfdpic_add_rofixup (output_bfd,
+ bfinfdpic_gotfixup_section
+ (info),
+ offset + input_section
+ ->output_section->vma
+ + input_section->output_offset,
+ picrel);
+
+ if (r_type == R_BFIN_FUNCDESC_VALUE)
_bfinfdpic_add_rofixup
(output_bfd,
bfinfdpic_gotfixup_section (info),
name, input_bfd, input_section, rel->r_offset);
return FALSE;
}
- /* Only output a reloc for a not deleted entry. */
- if (offset >= (bfd_vma)-2)
- _bfinfdpic_add_dyn_reloc (output_bfd,
- bfinfdpic_gotrel_section (info),
- 0, R_BFIN_UNUSED0, dynindx, addend, picrel);
- else
+
+ if (offset != (bfd_vma)-1)
_bfinfdpic_add_dyn_reloc (output_bfd,
bfinfdpic_gotrel_section (info),
offset
- + input_section
- ->output_section->vma
+ + input_section->output_section->vma
+ input_section->output_offset,
r_type, dynindx, addend, picrel);
}
relocation = addend - rel->r_addend;
}
- if (r_type == R_BFIN_FUNCDESC_VALUE && offset < (bfd_vma)-2)
+ if (r_type == R_BFIN_FUNCDESC_VALUE)
{
/* If we've omitted the dynamic relocation, just emit
the fixed addresses of the symbol and of the local
GOT base offset. */
- if (info->executable && !info->pie
+ if (bfd_link_pde (info)
&& (!h || BFINFDPIC_SYM_LOCAL (info, h)))
bfd_put_32 (output_bfd,
bfinfdpic_got_section (info)->output_section->vma
if (silence_segment_error == 1)
silence_segment_error =
(strlen (input_bfd->filename) == 6
- && strcmp (input_bfd->filename, "crt0.o") == 0)
+ && filename_cmp (input_bfd->filename, "crt0.o") == 0)
|| (strlen (input_bfd->filename) > 6
- && strcmp (input_bfd->filename
- + strlen (input_bfd->filename) - 7,
+ && filename_cmp (input_bfd->filename
+ + strlen (input_bfd->filename) - 7,
"/crt0.o") == 0)
? -1 : 0;
#endif
&& picrel->d.h->root.type == bfd_link_hash_undefined))
info->callbacks->warning
(info,
- (info->shared || info->pie)
+ bfd_link_pic (info)
? _("relocations between different segments are not supported")
: _("warning: relocation references a different segment"),
name, input_bfd, input_section, rel->r_offset);
- if (!silence_segment_error && (info->shared || info->pie))
+ if (!silence_segment_error && bfd_link_pic (info))
return FALSE;
elf_elfheader (output_bfd)->e_flags |= EF_BFIN_PIC;
}
struct elf_link_hash_entry *h;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
int ptralign;
- int offset;
/* This function may be called more than once. */
- s = bfd_get_section_by_name (abfd, ".got");
- if (s != NULL && (s->flags & SEC_LINKER_CREATED) != 0)
+ s = bfd_get_linker_section (abfd, ".got");
+ if (s != NULL)
return TRUE;
/* Machine specific: although pointers are 32-bits wide, we want the
| SEC_LINKER_CREATED);
pltflags = flags;
- s = bfd_make_section_with_flags (abfd, ".got", flags);
+ s = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
if (s == NULL
|| !bfd_set_section_alignment (abfd, s, ptralign))
return FALSE;
if (bed->want_got_plt)
{
- s = bfd_make_section_with_flags (abfd, ".got.plt", flags);
+ s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags);
if (s == NULL
|| !bfd_set_section_alignment (abfd, s, ptralign))
return FALSE;
if (! bfinfdpic_relocs_info (info))
return FALSE;
- s = bfd_make_section_with_flags (abfd, ".rel.got",
- (flags | SEC_READONLY));
+ s = bfd_make_section_anyway_with_flags (abfd, ".rel.got",
+ (flags | SEC_READONLY));
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, 2))
return FALSE;
bfinfdpic_gotrel_section (info) = s;
/* Machine-specific. */
- s = bfd_make_section_with_flags (abfd, ".rofixup",
- (flags | SEC_READONLY));
+ s = bfd_make_section_anyway_with_flags (abfd, ".rofixup",
+ (flags | SEC_READONLY));
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, 2))
return FALSE;
bfinfdpic_gotfixup_section (info) = s;
- offset = -2048;
- flags = BSF_GLOBAL;
}
- else
- {
- offset = 2048;
- flags = BSF_GLOBAL | BSF_WEAK;
- }
-
- return TRUE;
-}
-
-/* Make sure the got and plt sections exist, and that our pointers in
- the link hash table point to them. */
-
-static bfd_boolean
-elf32_bfinfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
-{
- /* This is mostly copied from
- elflink.c:_bfd_elf_create_dynamic_sections(). */
- flagword flags, pltflags;
- asection *s;
- const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-
- /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
- .rel[a].bss sections. */
- flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
- | SEC_LINKER_CREATED);
-
- pltflags = flags;
pltflags |= SEC_CODE;
if (bed->plt_not_loaded)
pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);
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);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
return FALSE;
{
/* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
.plt section. */
- struct elf_link_hash_entry *h;
struct bfd_link_hash_entry *bh = NULL;
if (! (_bfd_generic_link_add_one_symbol
h->def_regular = 1;
h->type = STT_OBJECT;
- if (! info->executable
+ if (! bfd_link_executable (info)
&& ! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
/* Blackfin-specific: we want rel relocations for the plt. */
- s = bfd_make_section_with_flags (abfd, ".rel.plt", flags | SEC_READONLY);
+ s = bfd_make_section_anyway_with_flags (abfd, ".rel.plt",
+ flags | SEC_READONLY);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
/* Blackfin-specific: remember it. */
bfinfdpic_pltrel_section (info) = s;
+ return TRUE;
+}
+
+/* Make sure the got and plt sections exist, and that our pointers in
+ the link hash table point to them. */
+
+static bfd_boolean
+elf32_bfinfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
+{
+ /* This is mostly copied from
+ elflink.c:_bfd_elf_create_dynamic_sections(). */
+ flagword flags;
+ asection *s;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED);
+
+ /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
+ .rel[a].bss sections. */
+
/* Blackfin-specific: we want to create the GOT in the Blackfin way. */
if (! _bfin_create_got_section (abfd, info))
return FALSE;
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);
if (s == NULL)
return FALSE;
/* The .rel[a].bss section holds copy relocs. This section is not
- normally needed. We need to create it here, though, so that the
- linker will map it to an output section. We can't just create it
- only if we need it, because we will not know whether we need it
- until we have seen all the input files, and the first time the
- main linker code calls BFD after examining all the input files
- (size_dynamic_sections) the input sections have already been
- mapped to the output sections. If the section turns out not to
- be needed, we can discard it later. We will never need this
- section when generating a shared object, since they do not use
- copy relocs. */
- if (! info->shared)
+ normally needed. We need to create it here, though, so that the
+ linker will map it to an output section. We can't just create it
+ only if we need it, because we will not know whether we need it
+ until we have seen all the input files, and the first time the
+ main linker code calls BFD after examining all the input files
+ (size_dynamic_sections) the input sections have already been
+ mapped to the output sections. If the section turns out not to
+ be needed, we can discard it later. We will never need this
+ section when generating a shared object, since they do not use
+ copy relocs. */
+ if (! bfd_link_pic (info))
{
- 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,
+ ".rela.bss",
+ flags | SEC_READONLY);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
the symbol, an entry pointing to its function descriptor, and a
private function descriptors taking two words. */
-static int
-_bfinfdpic_count_got_plt_entries (void **entryp, void *dinfo_)
+static void
+_bfinfdpic_count_nontls_entries (struct bfinfdpic_relocs_info *entry,
+ struct _bfinfdpic_dynamic_got_info *dinfo)
{
- struct bfinfdpic_relocs_info *entry = *entryp;
- struct _bfinfdpic_dynamic_got_info *dinfo = dinfo_;
- unsigned relocs = 0, fixups = 0;
-
/* Allocate space for a GOT entry pointing to the symbol. */
if (entry->got17m4)
dinfo->got17m4 += 4;
if (entry->lazyplt)
dinfo->lzplt += LZPLT_NORMAL_SIZE;
+}
- if (!dinfo->info->executable || dinfo->info->pie)
+/* Compute the number of dynamic relocations and fixups that a symbol
+ requires, and add (or subtract) from the grand and per-symbol
+ totals. */
+
+static void
+_bfinfdpic_count_relocs_fixups (struct bfinfdpic_relocs_info *entry,
+ struct _bfinfdpic_dynamic_got_info *dinfo,
+ bfd_boolean subtract)
+{
+ bfd_vma relocs = 0, fixups = 0;
+
+ if (!bfd_link_pde (dinfo->info))
relocs = entry->relocs32 + entry->relocsfd + entry->relocsfdv;
else
{
relocs += entry->relocsfd;
}
+ if (subtract)
+ {
+ relocs = - relocs;
+ fixups = - fixups;
+ }
+
entry->dynrelocs += relocs;
entry->fixups += fixups;
dinfo->relocs += relocs;
dinfo->fixups += fixups;
+}
+
+/* Compute the total GOT and PLT size required by each symbol in each range. *
+ Symbols may require up to 4 words in the GOT: an entry pointing to
+ the symbol, an entry pointing to its function descriptor, and a
+ private function descriptors taking two words. */
+
+static int
+_bfinfdpic_count_got_plt_entries (void **entryp, void *dinfo_)
+{
+ struct bfinfdpic_relocs_info *entry = *entryp;
+ struct _bfinfdpic_dynamic_got_info *dinfo = dinfo_;
+
+ _bfinfdpic_count_nontls_entries (entry, dinfo);
+
+ _bfinfdpic_count_relocs_fixups (entry, dinfo, FALSE);
return 1;
}
return 1;
}
+/* Cancel out any effects of calling _bfinfdpic_assign_got_entries and
+ _bfinfdpic_assign_plt_entries. */
+
+static int
+_bfinfdpic_reset_got_plt_entries (void **entryp, void *ignore ATTRIBUTE_UNUSED)
+{
+ struct bfinfdpic_relocs_info *entry = *entryp;
+
+ entry->got_entry = 0;
+ entry->fdgot_entry = 0;
+ entry->fd_entry = 0;
+ entry->plt_entry = (bfd_vma)-1;
+ entry->lzplt_entry = (bfd_vma)-1;
+
+ return 1;
+}
+
/* Follow indirect and warning hash entries so that each got entry
points to the final symbol definition. P must point to a pointer
to the hash table we're traversing. Since this traversal may
return 1;
}
-/* Set the sizes of the dynamic sections. */
+/* Compute the total size of the GOT, the PLT, the dynamic relocations
+ section and the rofixup section. Assign locations for GOT and PLT
+ entries. */
static bfd_boolean
-elf32_bfinfdpic_size_dynamic_sections (bfd *output_bfd,
- struct bfd_link_info *info)
+_bfinfdpic_size_got_plt (bfd *output_bfd,
+ struct _bfinfdpic_dynamic_got_plt_info *gpinfop)
{
- bfd *dynobj;
- asection *s;
- struct _bfinfdpic_dynamic_got_plt_info gpinfo;
bfd_signed_vma odd;
bfd_vma limit;
+ struct bfd_link_info *info = gpinfop->g.info;
+ bfd *dynobj = elf_hash_table (info)->dynobj;
- dynobj = elf_hash_table (info)->dynobj;
- BFD_ASSERT (dynobj != NULL);
-
- if (elf_hash_table (info)->dynamic_sections_created)
- {
- /* Set the contents of the .interp section to the interpreter. */
- if (info->executable)
- {
- s = bfd_get_section_by_name (dynobj, ".interp");
- BFD_ASSERT (s != NULL);
- s->size = sizeof ELF_DYNAMIC_INTERPRETER;
- s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
- }
- }
-
- memset (&gpinfo, 0, sizeof (gpinfo));
- gpinfo.g.info = info;
-
- for (;;)
- {
- htab_t relocs = bfinfdpic_relocs_info (info);
-
- htab_traverse (relocs, _bfinfdpic_resolve_final_relocs_info, &relocs);
-
- if (relocs == bfinfdpic_relocs_info (info))
- break;
- }
-
- htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_count_got_plt_entries,
- &gpinfo.g);
+ memcpy (bfinfdpic_dynamic_got_plt_info (info), &gpinfop->g,
+ sizeof (gpinfop->g));
odd = 12;
/* Compute the total size taken by entries in the 18-bit range,
to tell how many PLT function descriptors we can bring into it
without causing it to overflow. */
- limit = odd + gpinfo.g.got17m4 + gpinfo.g.fd17m4;
+ limit = odd + gpinfop->g.got17m4 + gpinfop->g.fd17m4;
if (limit < (bfd_vma)1 << 18)
limit = ((bfd_vma)1 << 18) - limit;
else
limit = 0;
- if (gpinfo.g.fdplt < limit)
- limit = gpinfo.g.fdplt;
+ if (gpinfop->g.fdplt < limit)
+ limit = gpinfop->g.fdplt;
/* Determine the ranges of GOT offsets that we can use for each
range of addressing modes. */
- odd = _bfinfdpic_compute_got_alloc_data (&gpinfo.got17m4,
+ odd = _bfinfdpic_compute_got_alloc_data (&gpinfop->got17m4,
0,
odd,
16,
- gpinfo.g.got17m4,
- gpinfo.g.fd17m4,
+ gpinfop->g.got17m4,
+ gpinfop->g.fd17m4,
limit,
(bfd_vma)1 << (18-1));
- odd = _bfinfdpic_compute_got_alloc_data (&gpinfo.gothilo,
- gpinfo.got17m4.min,
+ odd = _bfinfdpic_compute_got_alloc_data (&gpinfop->gothilo,
+ gpinfop->got17m4.min,
odd,
- gpinfo.got17m4.max,
- gpinfo.g.gothilo,
- gpinfo.g.fdhilo,
- gpinfo.g.fdplt - gpinfo.got17m4.fdplt,
+ gpinfop->got17m4.max,
+ gpinfop->g.gothilo,
+ gpinfop->g.fdhilo,
+ gpinfop->g.fdplt - gpinfop->got17m4.fdplt,
(bfd_vma)1 << (32-1));
/* Now assign (most) GOT offsets. */
htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_assign_got_entries,
- &gpinfo);
+ gpinfop);
- bfinfdpic_got_section (info)->size = gpinfo.gothilo.max
- - gpinfo.gothilo.min
+ bfinfdpic_got_section (info)->size = gpinfop->gothilo.max
+ - gpinfop->gothilo.min
/* If an odd word is the last word of the GOT, we don't need this
word to be part of the GOT. */
- - (odd + 4 == gpinfo.gothilo.max ? 4 : 0);
+ - (odd + 4 == gpinfop->gothilo.max ? 4 : 0);
if (bfinfdpic_got_section (info)->size == 0)
bfinfdpic_got_section (info)->flags |= SEC_EXCLUDE;
else if (bfinfdpic_got_section (info)->size == 12
/* Subtract the number of lzplt entries, since those will generate
relocations in the pltrel section. */
bfinfdpic_gotrel_section (info)->size =
- (gpinfo.g.relocs - gpinfo.g.lzplt / LZPLT_NORMAL_SIZE)
+ (gpinfop->g.relocs - gpinfop->g.lzplt / LZPLT_NORMAL_SIZE)
* get_elf_backend_data (output_bfd)->s->sizeof_rel;
else
- BFD_ASSERT (gpinfo.g.relocs == 0);
+ BFD_ASSERT (gpinfop->g.relocs == 0);
if (bfinfdpic_gotrel_section (info)->size == 0)
bfinfdpic_gotrel_section (info)->flags |= SEC_EXCLUDE;
else
return FALSE;
}
- bfinfdpic_gotfixup_section (info)->size = (gpinfo.g.fixups + 1) * 4;
+ bfinfdpic_gotfixup_section (info)->size = (gpinfop->g.fixups + 1) * 4;
if (bfinfdpic_gotfixup_section (info)->size == 0)
bfinfdpic_gotfixup_section (info)->flags |= SEC_EXCLUDE;
else
}
if (elf_hash_table (info)->dynamic_sections_created)
+ bfinfdpic_pltrel_section (info)->size =
+ gpinfop->g.lzplt / LZPLT_NORMAL_SIZE * get_elf_backend_data (output_bfd)->s->sizeof_rel;
+ if (bfinfdpic_pltrel_section (info)->size == 0)
+ bfinfdpic_pltrel_section (info)->flags |= SEC_EXCLUDE;
+ else
{
- bfinfdpic_pltrel_section (info)->size =
- gpinfo.g.lzplt / LZPLT_NORMAL_SIZE * get_elf_backend_data (output_bfd)->s->sizeof_rel;
- if (bfinfdpic_pltrel_section (info)->size == 0)
- bfinfdpic_pltrel_section (info)->flags |= SEC_EXCLUDE;
- else
- {
- bfinfdpic_pltrel_section (info)->contents =
- (bfd_byte *) bfd_zalloc (dynobj,
- bfinfdpic_pltrel_section (info)->size);
- if (bfinfdpic_pltrel_section (info)->contents == NULL)
- return FALSE;
- }
+ bfinfdpic_pltrel_section (info)->contents =
+ (bfd_byte *) bfd_zalloc (dynobj,
+ bfinfdpic_pltrel_section (info)->size);
+ if (bfinfdpic_pltrel_section (info)->contents == NULL)
+ return FALSE;
}
/* Add 4 bytes for every block of at most 65535 lazy PLT entries,
block size. */
if (elf_hash_table (info)->dynamic_sections_created)
{
- bfinfdpic_plt_section (info)->size = gpinfo.g.lzplt
- + ((gpinfo.g.lzplt + (BFINFDPIC_LZPLT_BLOCK_SIZE - 4) - LZPLT_NORMAL_SIZE)
+ bfinfdpic_plt_section (info)->size = gpinfop->g.lzplt
+ + ((gpinfop->g.lzplt + (BFINFDPIC_LZPLT_BLOCK_SIZE - 4) - LZPLT_NORMAL_SIZE)
/ (BFINFDPIC_LZPLT_BLOCK_SIZE - 4) * LZPLT_RESOLVER_EXTRA);
}
/* Reset it, such that _bfinfdpic_assign_plt_entries() can use it to
actually assign lazy PLT entries addresses. */
- gpinfo.g.lzplt = 0;
+ gpinfop->g.lzplt = 0;
/* Save information that we're going to need to generate GOT and PLT
entries. */
- bfinfdpic_got_initial_offset (info) = -gpinfo.gothilo.min;
+ bfinfdpic_got_initial_offset (info) = -gpinfop->gothilo.min;
if (get_elf_backend_data (output_bfd)->want_got_sym)
elf_hash_table (info)->hgot->root.u.def.value
- += bfinfdpic_got_initial_offset (info);
+ = bfinfdpic_got_initial_offset (info);
if (elf_hash_table (info)->dynamic_sections_created)
bfinfdpic_plt_initial_offset (info) =
bfinfdpic_plt_section (info)->size;
htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_assign_plt_entries,
- &gpinfo);
+ gpinfop);
/* Allocate the PLT section contents only after
_bfinfdpic_assign_plt_entries has a chance to add the size of the
non-lazy PLT entries. */
- if (elf_hash_table (info)->dynamic_sections_created)
+ if (bfinfdpic_plt_section (info)->size == 0)
+ bfinfdpic_plt_section (info)->flags |= SEC_EXCLUDE;
+ else
{
- if (bfinfdpic_plt_section (info)->size == 0)
- bfinfdpic_plt_section (info)->flags |= SEC_EXCLUDE;
- else
+ bfinfdpic_plt_section (info)->contents =
+ (bfd_byte *) bfd_zalloc (dynobj,
+ bfinfdpic_plt_section (info)->size);
+ if (bfinfdpic_plt_section (info)->contents == NULL)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Set the sizes of the dynamic sections. */
+
+static bfd_boolean
+elf32_bfinfdpic_size_dynamic_sections (bfd *output_bfd,
+ struct bfd_link_info *info)
+{
+ struct elf_link_hash_table *htab;
+ bfd *dynobj;
+ asection *s;
+ struct _bfinfdpic_dynamic_got_plt_info gpinfo;
+
+ htab = elf_hash_table (info);
+ dynobj = htab->dynobj;
+ BFD_ASSERT (dynobj != NULL);
+
+ if (htab->dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+ if (bfd_link_executable (info))
{
- bfinfdpic_plt_section (info)->contents =
- (bfd_byte *) bfd_zalloc (dynobj,
- bfinfdpic_plt_section (info)->size);
- if (bfinfdpic_plt_section (info)->contents == NULL)
- return FALSE;
+ s = bfd_get_linker_section (dynobj, ".interp");
+ BFD_ASSERT (s != NULL);
+ s->size = sizeof ELF_DYNAMIC_INTERPRETER;
+ s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
}
}
+ memset (&gpinfo, 0, sizeof (gpinfo));
+ gpinfo.g.info = info;
+
+ for (;;)
+ {
+ htab_t relocs = bfinfdpic_relocs_info (info);
+
+ htab_traverse (relocs, _bfinfdpic_resolve_final_relocs_info, &relocs);
+
+ if (relocs == bfinfdpic_relocs_info (info))
+ break;
+ }
+
+ htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_count_got_plt_entries,
+ &gpinfo.g);
+
+ /* Allocate space to save the summary information, we're going to
+ use it if we're doing relaxations. */
+ bfinfdpic_dynamic_got_plt_info (info) = bfd_alloc (dynobj, sizeof (gpinfo.g));
+
+ if (!_bfinfdpic_size_got_plt (output_bfd, &gpinfo))
+ return FALSE;
+
if (elf_hash_table (info)->dynamic_sections_created)
{
if (bfinfdpic_got_section (info)->size)
return FALSE;
}
+ s = bfd_get_linker_section (dynobj, ".dynbss");
+ if (s && s->size == 0)
+ s->flags |= SEC_EXCLUDE;
+
+ s = bfd_get_linker_section (dynobj, ".rela.bss");
+ if (s && s->size == 0)
+ s->flags |= SEC_EXCLUDE;
+
return TRUE;
}
elf32_bfinfdpic_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_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;
- }
- }
+ if (!bfd_link_relocatable (info)
+ && !bfd_elf_stack_segment_size (output_bfd, info,
+ "__stacksize", DEFAULT_STACK_SIZE))
+ return FALSE;
return TRUE;
}
+/* Check whether any of the relocations was optimized away, and
+ subtract it from the relocation or fixup count. */
static bfd_boolean
-elf32_bfinfdpic_modify_program_headers (bfd *output_bfd,
- struct bfd_link_info *info)
+_bfinfdpic_check_discarded_relocs (bfd *abfd, asection *sec,
+ struct bfd_link_info *info,
+ bfd_boolean *changed)
{
- struct elf_obj_tdata *tdata = elf_tdata (output_bfd);
- struct elf_segment_map *m;
- Elf_Internal_Phdr *p;
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
+ Elf_Internal_Rela *rel, *erel;
- /* objcopy and strip preserve what's already there using
- elf32_bfinfdpic_copy_private_bfd_data (). */
- if (! info)
+ if ((sec->flags & SEC_RELOC) == 0
+ || sec->reloc_count == 0)
return TRUE;
- for (p = tdata->phdr, m = tdata->segment_map; m != NULL; m = m->next, p++)
- if (m->p_type == PT_GNU_STACK)
- break;
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (abfd);
+ sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf32_External_Sym);
+ if (!elf_bad_symtab (abfd))
+ sym_hashes_end -= symtab_hdr->sh_info;
+
+ rel = elf_section_data (sec)->relocs;
- if (m)
+ /* Now examine each relocation. */
+ for (erel = rel + sec->reloc_count; rel < erel; rel++)
{
struct elf_link_hash_entry *h;
+ unsigned long r_symndx;
+ struct bfinfdpic_relocs_info *picrel;
+ struct _bfinfdpic_dynamic_got_info *dinfo;
- /* Obtain the pointer to the __stacksize symbol. */
- h = elf_link_hash_lookup (elf_hash_table (info), "__stacksize",
- FALSE, FALSE, FALSE);
- if (h)
+ if (ELF32_R_TYPE (rel->r_info) != R_BFIN_BYTE4_DATA
+ && ELF32_R_TYPE (rel->r_info) != R_BFIN_FUNCDESC)
+ continue;
+
+ if (_bfd_elf_section_offset (sec->output_section->owner,
+ info, sec, rel->r_offset)
+ != (bfd_vma)-1)
+ continue;
+
+ r_symndx = ELF32_R_SYM (rel->r_info);
+ if (r_symndx < symtab_hdr->sh_info)
+ h = NULL;
+ else
{
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
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);
+ h = (struct elf_link_hash_entry *)h->root.u.i.link;
}
- /* 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;
+ if (h != NULL)
+ picrel = bfinfdpic_relocs_info_for_global (bfinfdpic_relocs_info (info),
+ abfd, h,
+ rel->r_addend, NO_INSERT);
else
- p->p_memsz = DEFAULT_STACK_SIZE;
+ picrel = bfinfdpic_relocs_info_for_local (bfinfdpic_relocs_info (info),
+ abfd, r_symndx,
+ rel->r_addend, NO_INSERT);
+
+ if (! picrel)
+ return FALSE;
- p->p_align = 8;
+ *changed = TRUE;
+ dinfo = bfinfdpic_dynamic_got_plt_info (info);
+
+ _bfinfdpic_count_relocs_fixups (picrel, dinfo, TRUE);
+ if (ELF32_R_TYPE (rel->r_info) == R_BFIN_BYTE4_DATA)
+ picrel->relocs32--;
+ else /* we know (ELF32_R_TYPE (rel->r_info) == R_BFIN_FUNCDESC) */
+ picrel->relocsfd--;
+ _bfinfdpic_count_relocs_fixups (picrel, dinfo, FALSE);
+ }
+
+ return TRUE;
+}
+
+static bfd_boolean
+bfinfdpic_elf_discard_info (bfd *ibfd,
+ struct elf_reloc_cookie *cookie ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info)
+{
+ bfd_boolean changed = FALSE;
+ asection *s;
+ bfd *obfd = NULL;
+
+ /* Account for relaxation of .eh_frame section. */
+ for (s = ibfd->sections; s; s = s->next)
+ if (s->sec_info_type == SEC_INFO_TYPE_EH_FRAME)
+ {
+ if (!_bfinfdpic_check_discarded_relocs (ibfd, s, info, &changed))
+ return FALSE;
+ obfd = s->output_section->owner;
+ }
+
+ if (changed)
+ {
+ struct _bfinfdpic_dynamic_got_plt_info gpinfo;
+
+ memset (&gpinfo, 0, sizeof (gpinfo));
+ memcpy (&gpinfo.g, bfinfdpic_dynamic_got_plt_info (info),
+ sizeof (gpinfo.g));
+
+ /* Clear GOT and PLT assignments. */
+ htab_traverse (bfinfdpic_relocs_info (info),
+ _bfinfdpic_reset_got_plt_entries,
+ NULL);
+
+ if (!_bfinfdpic_size_got_plt (obfd, &gpinfo))
+ return FALSE;
}
return TRUE;
* sizeof (Elf32_External_Rel)));
}
- sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+ sdyn = bfd_get_linker_section (dynobj, ".dynamic");
if (elf_hash_table (info)->dynamic_sections_created)
{
regular object. */
static bfd_boolean
-elf32_bfinfdpic_adjust_dynamic_symbol
-(struct bfd_link_info *info,
- struct elf_link_hash_entry *h)
+elf32_bfinfdpic_adjust_dynamic_symbol (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h)
{
bfd * dynobj;
bfd *dynobj;
struct bfinfdpic_relocs_info *picrel;
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
return TRUE;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
return TRUE;
}
-/* Copy backend specific data from one object module to another. */
-
-static bfd_boolean
-bfin_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
-elf32_bfinfdpic_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
-{
- unsigned i;
-
- if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
- || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return TRUE;
-
- if (! bfin_elf_copy_private_bfd_data (ibfd, obfd))
- return FALSE;
-
- if (! elf_tdata (ibfd) || ! elf_tdata (ibfd)->phdr
- || ! elf_tdata (obfd) || ! elf_tdata (obfd)->phdr)
- return TRUE;
-
- /* Copy the stack size. */
- for (i = 0; i < elf_elfheader (ibfd)->e_phnum; i++)
- if (elf_tdata (ibfd)->phdr[i].p_type == PT_GNU_STACK)
- {
- Elf_Internal_Phdr *iphdr = &elf_tdata (ibfd)->phdr[i];
-
- for (i = 0; i < elf_elfheader (obfd)->e_phnum; i++)
- if (elf_tdata (obfd)->phdr[i].p_type == PT_GNU_STACK)
- {
- memcpy (&elf_tdata (obfd)->phdr[i], iphdr, sizeof (*iphdr));
-
- /* Rewrite the phdrs, since we're only called after they
- were first written. */
- if (bfd_seek (obfd, (bfd_signed_vma) get_elf_backend_data (obfd)
- ->s->sizeof_ehdr, SEEK_SET) != 0
- || get_elf_backend_data (obfd)->s
- ->write_out_phdrs (obfd, elf_tdata (obfd)->phdr,
- elf_elfheader (obfd)->e_phnum) != 0)
- return FALSE;
- break;
- }
-
- break;
- }
-
- return TRUE;
-}
-
-
/* Display the flags field. */
static bfd_boolean
-elf32_bfin_print_private_bfd_data (bfd * abfd, PTR ptr)
+elf32_bfin_print_private_bfd_data (bfd * abfd, void * ptr)
{
FILE *file = (FILE *) ptr;
flagword flags;
if (new_flags & EF_BFIN_FDPIC)
new_flags &= ~EF_BFIN_PIC;
-#ifdef DEBUG
+#ifndef DEBUG
+ if (0)
+#endif
(*_bfd_error_handler) ("old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s, filename = %s",
old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no",
bfd_get_filename (ibfd));
-#endif
if (!elf_flags_init (obfd)) /* First call, no flags set. */
{
struct bfin_link_hash_table *ret;
bfd_size_type amt = sizeof (struct bfin_link_hash_table);
- ret = bfd_zalloc (abfd, amt);
+ ret = bfd_zmalloc (amt);
if (ret == NULL)
return NULL;
if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
bfin_link_hash_newfunc,
- sizeof (struct elf_link_hash_entry)))
+ sizeof (struct elf_link_hash_entry),
+ BFIN_ELF_DATA))
{
free (ret);
return NULL;
static bfd_boolean
bfin_finish_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
- struct bfd_link_info *info)
+ struct bfd_link_info *info)
{
bfd *dynobj;
asection *sdyn;
dynobj = elf_hash_table (info)->dynobj;
- sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+ sdyn = bfd_get_linker_section (dynobj, ".dynamic");
if (elf_hash_table (info)->dynamic_sections_created)
{
static bfd_boolean
bfin_finish_dynamic_symbol (bfd * output_bfd,
- struct bfd_link_info *info,
- struct elf_link_hash_entry *h,
- Elf_Internal_Sym * sym)
+ struct bfd_link_info *info,
+ struct elf_link_hash_entry *h,
+ Elf_Internal_Sym * sym)
{
bfd *dynobj;
/* This symbol has an entry in the global offset table.
Set it up. */
- sgot = bfd_get_section_by_name (dynobj, ".got");
- srela = bfd_get_section_by_name (dynobj, ".rela.got");
+ sgot = bfd_get_linker_section (dynobj, ".got");
+ srela = bfd_get_linker_section (dynobj, ".rela.got");
BFD_ASSERT (sgot != NULL && srela != NULL);
rela.r_offset = (sgot->output_section->vma
the symbol was forced to be local because of a version file.
The entry in the global offset table will already have been
initialized in the relocate_section function. */
- if (info->shared
+ if (bfd_link_pic (info)
&& (info->symbolic
|| h->dynindx == -1 || h->forced_local) && h->def_regular)
{
- fprintf(stderr, "*** check this relocation %s\n", __FUNCTION__);
+ (*_bfd_error_handler) (_("*** check this relocation %s"),
+ __FUNCTION__);
rela.r_info = ELF32_R_INFO (0, R_BFIN_PCREL24);
rela.r_addend = bfd_get_signed_32 (output_bfd,
(sgot->contents
static bfd_boolean
bfin_adjust_dynamic_symbol (struct bfd_link_info *info,
- struct elf_link_hash_entry *h)
+ struct elf_link_hash_entry *h)
{
bfd *dynobj;
asection *s;
only references to the symbol are via the global offset table.
For such cases we need not do anything here; the relocations will
be handled correctly by relocate_section. */
- if (info->shared)
+ if (bfd_link_pic (info))
return TRUE;
/* We must allocate the symbol in our .dynbss section, which will
both the dynamic object and the regular object will refer to the
same memory location for the variable. */
- s = bfd_get_section_by_name (dynobj, ".dynbss");
+ s = bfd_get_linker_section (dynobj, ".dynbss");
BFD_ASSERT (s != NULL);
/* We must generate a R_68K_COPY reloc to tell the dynamic linker to
{
asection *srel;
- srel = bfd_get_section_by_name (dynobj, ".rela.bss");
+ srel = bfd_get_linker_section (dynobj, ".rela.bss");
BFD_ASSERT (srel != NULL);
srel->size += sizeof (Elf32_External_Rela);
h->needs_copy = 1;
case. */
static bfd_boolean
-bfin_discard_copies (struct elf_link_hash_entry *h, PTR inf)
+bfin_discard_copies (struct elf_link_hash_entry *h, void * inf)
{
struct bfd_link_info *info = (struct bfd_link_info *) inf;
struct bfin_pcrel_relocs_copied *s;
- if (h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
if (!h->def_regular || (!info->symbolic && !h->forced_local))
{
if ((info->flags & DF_TEXTREL) == 0)
static bfd_boolean
bfin_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
- struct bfd_link_info *info)
+ struct bfd_link_info *info)
{
bfd *dynobj;
asection *s;
if (elf_hash_table (info)->dynamic_sections_created)
{
/* Set the contents of the .interp section to the interpreter. */
- if (info->executable)
+ if (bfd_link_executable (info))
{
- 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;
not actually use these entries. Reset the size of .rela.got,
which will cause it to get stripped from the output file
below. */
- s = bfd_get_section_by_name (dynobj, ".rela.got");
+ s = bfd_get_linker_section (dynobj, ".rela.got");
if (s != NULL)
s->size = 0;
}
against symbols that have become local due to visibility changes.
We allocated space for them in the check_relocs routine, but we
will not fill them in in the relocate_section routine. */
- if (info->shared)
+ if (bfd_link_pic (info))
elf_link_hash_traverse (elf_hash_table (info),
- bfin_discard_copies, (PTR) info);
+ bfin_discard_copies, info);
/* The check_relocs and adjust_dynamic_symbol entry points have
determined the sizes of the various dynamic sections. Allocate
#define add_dynamic_entry(TAG, VAL) \
_bfd_elf_add_dynamic_entry (info, TAG, VAL)
- if (!info->shared)
+ if (!bfd_link_pic (info))
{
if (!add_dynamic_entry (DT_DEBUG, 0))
return FALSE;
after the add_symbols entry point has been called for all the
objects, and before the final_link entry point is called. */
-bfd_boolean bfd_bfin_elf32_create_embedded_relocs
- PARAMS ((bfd *, struct bfd_link_info *, asection *, asection *, char **));
-
bfd_boolean
-bfd_bfin_elf32_create_embedded_relocs (
- bfd *abfd,
- struct bfd_link_info *info,
- asection *datasec,
- asection *relsec,
- char **errmsg)
+bfd_bfin_elf32_create_embedded_relocs (bfd *abfd,
+ struct bfd_link_info *info,
+ asection *datasec,
+ asection *relsec,
+ char **errmsg)
{
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Sym *isymbuf = NULL;
bfd_byte *p;
bfd_size_type amt;
- BFD_ASSERT (! info->relocatable);
+ BFD_ASSERT (! bfd_link_relocatable (info));
*errmsg = NULL;
/* Get a copy of the native relocations. */
internal_relocs = (_bfd_elf_link_read_relocs
- (abfd, datasec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
+ (abfd, datasec, NULL, (Elf_Internal_Rela *) NULL,
info->keep_memory));
if (internal_relocs == NULL)
goto error_return;
};
\f
-#define TARGET_LITTLE_SYM bfd_elf32_bfin_vec
+#define TARGET_LITTLE_SYM bfin_elf32_vec
#define TARGET_LITTLE_NAME "elf32-bfin"
#define ELF_ARCH bfd_arch_bfin
+#define ELF_TARGET_ID BFIN_ELF_DATA
#define ELF_MACHINE_CODE EM_BLACKFIN
#define ELF_MAXPAGESIZE 0x1000
#define elf_symbol_leading_char '_'
elf32_bfin_set_private_flags
#define bfd_elf32_bfd_print_private_bfd_data \
elf32_bfin_print_private_bfd_data
+#define elf_backend_final_write_processing \
+ elf32_bfin_final_write_processing
#define elf_backend_reloc_type_class elf32_bfin_reloc_type_class
+#define elf_backend_stack_align 8
#define elf_backend_can_gc_sections 1
#define elf_backend_special_sections elf32_bfin_special_sections
#define elf_backend_can_refcount 1
#include "elf32-target.h"
#undef TARGET_LITTLE_SYM
-#define TARGET_LITTLE_SYM bfd_elf32_bfinfdpic_vec
+#define TARGET_LITTLE_SYM bfin_elf32_fdpic_vec
#undef TARGET_LITTLE_NAME
#define TARGET_LITTLE_NAME "elf32-bfinfdpic"
#undef elf32_bed
#undef elf_backend_always_size_sections
#define elf_backend_always_size_sections \
elf32_bfinfdpic_always_size_sections
-#undef elf_backend_modify_program_headers
-#define elf_backend_modify_program_headers \
- elf32_bfinfdpic_modify_program_headers
-#undef bfd_elf32_bfd_copy_private_bfd_data
-#define bfd_elf32_bfd_copy_private_bfd_data \
- elf32_bfinfdpic_copy_private_bfd_data
#undef elf_backend_create_dynamic_sections
#define elf_backend_create_dynamic_sections \
#define elf_backend_finish_dynamic_sections \
elf32_bfinfdpic_finish_dynamic_sections
+#undef elf_backend_discard_info
+#define elf_backend_discard_info \
+ bfinfdpic_elf_discard_info
#undef elf_backend_can_make_relative_eh_frame
#define elf_backend_can_make_relative_eh_frame \
bfinfdpic_elf_use_relative_eh_frame