/* 32-bit ELF support for ARM
- Copyright (C) 1998-2014 Free Software Foundation, Inc.
+ Copyright (C) 1998-2015 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
/* No relocation. */
HOWTO (R_ARM_NONE, /* type */
0, /* rightshift */
- 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 3, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield,/* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ NULL, /* special_function */
"R_ARM_TLS_LE32", /* name */
TRUE, /* partial_inplace */
0xffffffff, /* src_mask */
struct map_stub *stub_group;
/* Number of elements in stub_group. */
- int top_id;
+ unsigned int top_id;
/* Assorted information used by elf32_arm_size_stubs. */
unsigned int bfd_count;
- int top_index;
+ unsigned int top_index;
asection **input_list;
};
return FALSE;
htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
- if (!info->shared)
+ if (!bfd_link_pic (info))
htab->srelbss = bfd_get_linker_section (dynobj,
RELOC_SECTION (htab, ".bss"));
if (!elf_vxworks_create_dynamic_sections (dynobj, info, &htab->srelplt2))
return FALSE;
- if (info->shared)
+ if (bfd_link_pic (info))
{
htab->plt_header_size = 0;
htab->plt_entry_size
if (!htab->root.splt
|| !htab->root.srelplt
|| !htab->sdynbss
- || (!info->shared && !htab->srelbss))
+ || (!bfd_link_pic (info) && !htab->srelbss))
abort ();
return TRUE;
/* Thumb to thumb. */
if (!thumb_only)
{
- stub_type = (info->shared | globals->pic_veneer)
+ stub_type = (bfd_link_pic (info) | globals->pic_veneer)
/* PIC stubs. */
? ((globals->use_blx
&& (r_type == R_ARM_THM_CALL))
}
else
{
- stub_type = (info->shared | globals->pic_veneer)
+ stub_type = (bfd_link_pic (info) | globals->pic_veneer)
/* PIC stub. */
? arm_stub_long_branch_thumb_only_pic
/* non-PIC stub. */
}
stub_type =
- (info->shared | globals->pic_veneer)
+ (bfd_link_pic (info) | globals->pic_veneer)
/* PIC stubs. */
? (r_type == R_ARM_THM_TLS_CALL
/* TLS PIC stubs. */
|| (r_type == R_ARM_JUMP24)
|| (r_type == R_ARM_PLT32))
{
- stub_type = (info->shared | globals->pic_veneer)
+ stub_type = (bfd_link_pic (info) | globals->pic_veneer)
/* PIC stubs. */
? ((globals->use_blx)
/* V5T and above. */
|| (branch_offset < ARM_MAX_BWD_BRANCH_OFFSET))
{
stub_type =
- (info->shared | globals->pic_veneer)
+ (bfd_link_pic (info) | globals->pic_veneer)
/* PIC stubs. */
? (r_type == R_ARM_TLS_CALL
/* TLS PIC Stub. */
{
int is_local = (h == NULL);
- if (info->shared || (h && h->root.type == bfd_link_hash_undefweak))
+ if (bfd_link_pic (info)
+ || (h && h->root.type == bfd_link_hash_undefweak))
return r_type;
/* We do not support relaxations for Old TLS models. */
{
bfd *input_bfd;
unsigned int bfd_count;
- int top_id, top_index;
+ unsigned int top_id, top_index;
asection *section;
asection **input_list, **list;
bfd_size_type amt;
free (tmp_name);
- if (link_info->shared || globals->root.is_relocatable_executable
+ if (bfd_link_pic (link_info)
+ || globals->root.is_relocatable_executable
|| globals->pic_veneer)
size = ARM2THUMB_PIC_GLUE_SIZE;
else if (globals->use_blx)
{
/* If we are only performing a partial
link do not bother adding the glue. */
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
return TRUE;
return arm_make_glue_section (abfd, ARM2THUMB_GLUE_SECTION_NAME)
/* If we are only performing a partial link
do not bother getting a bfd to hold the glue. */
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
return TRUE;
/* Make sure we don't attach the glue sections to a dynamic object. */
/* If we are only performing a partial link do not bother
to construct any glue. */
- if (link_info->relocatable)
+ if (bfd_link_relocatable (link_info))
return TRUE;
/* Here we have a bfd that is to be included on the link. We have a
/* If we are only performing a partial link do not bother
to construct any glue. */
- if (link_info->relocatable)
+ if (bfd_link_relocatable (link_info))
return TRUE;
/* Skip if this bfd does not correspond to an ELF image. */
struct elf32_arm_link_hash_table *globals;
char *tmp_name;
- if (link_info->relocatable)
+ if (bfd_link_relocatable (link_info))
return;
/* Skip if this bfd does not correspond to an ELF image. */
--my_offset;
myh->root.u.def.value = my_offset;
- if (info->shared || globals->root.is_relocatable_executable
+ if (bfd_link_pic (info)
+ || globals->root.is_relocatable_executable
|| globals->pic_veneer)
{
/* For relocatable objects we can't use absolute addresses,
+ root_plt->offset);
ptr = splt->contents + root_plt->offset;
- if (htab->vxworks_p && info->shared)
+ if (htab->vxworks_p && bfd_link_pic (info))
{
unsigned int i;
bfd_vma val;
if (r_type != howto->type)
howto = elf32_arm_howto_from_type (r_type);
- /* If the start address has been set, then set the EF_ARM_HASENTRY
- flag. Setting this more than once is redundant, but the cost is
- not too high, and it keeps the code simple.
-
- The test is done here, rather than somewhere else, because the
- start address is only set just before the final link commences.
-
- Note - if the user deliberately sets a start address of 0, the
- flag will not be set. */
- if (bfd_get_start_address (output_bfd) != 0)
- elf_elfheader (output_bfd)->e_flags |= EF_ARM_HASENTRY;
-
eh = (struct elf32_arm_link_hash_entry *) h;
sgot = globals->root.sgot;
local_got_offsets = elf_local_got_offsets (input_bfd);
/* When generating a shared object or relocatable executable, these
relocations are copied into the output file to be resolved at
run time. */
- if ((info->shared || globals->root.is_relocatable_executable)
+ if ((bfd_link_pic (info)
+ || globals->root.is_relocatable_executable)
&& (input_section->flags & SEC_ALLOC)
&& !(globals->vxworks_p
&& strcmp (input_section->output_section->name,
Elf_Internal_Rela outrel;
bfd_boolean skip, relocate;
+ if ((r_type == R_ARM_REL32 || r_type == R_ARM_REL32_NOI)
+ && !h->def_regular)
+ {
+ char *v = _("shared object");
+
+ if (bfd_link_executable (info))
+ v = _("PIE executable");
+
+ (*_bfd_error_handler)
+ (_("%B: relocation %s against external or undefined symbol `%s'"
+ " can not be used when making a %s; recompile with -fPIC"), input_bfd,
+ elf32_arm_howto_table_1[r_type].name, h->root.root.string, v);
+ return bfd_reloc_notsupported;
+ }
+
*unresolved_reloc_p = FALSE;
if (sreloc == NULL && globals->root.dynamic_sections_created)
memset (&outrel, 0, sizeof outrel);
else if (h != NULL
&& h->dynindx != -1
- && (!info->shared
- || !info->symbolic
+ && (!bfd_link_pic (info)
+ || !SYMBOLIC_BIND (info, h)
|| !h->def_regular))
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
else
{
if (dynreloc_st_type == STT_GNU_IFUNC)
outrel.r_info = ELF32_R_INFO (0, R_ARM_IRELATIVE);
- else if (info->shared &&
+ else if (bfd_link_pic (info) &&
(ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak))
outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
if (globals->use_rel)
bfd_put_32 (output_bfd, dynreloc_value, sgot->contents + off);
- if (info->shared || dynreloc_st_type == STT_GNU_IFUNC)
+ if (bfd_link_pic (info) || dynreloc_st_type == STT_GNU_IFUNC)
{
Elf_Internal_Rela outrel;
{
/* If we don't know the module number, create a relocation
for it. */
- if (info->shared)
+ if (bfd_link_pic (info))
{
Elf_Internal_Rela outrel;
{
bfd_boolean dyn;
dyn = globals->root.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)
|| !SYMBOL_REFERENCES_LOCAL (info, h)))
{
*unresolved_reloc_p = FALSE;
now, and emit any relocations. If both an IE GOT and a
GD GOT are necessary, we emit the GD first. */
- if ((info->shared || indx != 0)
+ if ((bfd_link_pic (info) || indx != 0)
&& (h == NULL
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak))
/* We should have relaxed, unless this is an undefined
weak symbol. */
BFD_ASSERT ((h && (h->root.type == bfd_link_hash_undefweak))
- || info->shared);
+ || bfd_link_pic (info));
BFD_ASSERT (globals->sgotplt_jump_table_size + offplt + 8
<= globals->root.sgotplt->size);
}
case R_ARM_TLS_LE32:
- if (info->shared && !info->pie)
+ if (bfd_link_dll (info))
{
(*_bfd_error_handler)
(_("%B(%A+0x%lx): R_ARM_TLS_LE32 relocation not permitted in shared object"),
relocation = (sec->output_section->vma
+ sec->output_offset
+ sym->st_value);
- if (!info->relocatable
+ if (!bfd_link_relocatable (info)
&& (sec->flags & SEC_MERGE)
&& ELF_ST_TYPE (sym->st_info) == STT_SECTION)
{
RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
rel, 1, relend, howto, 0, contents);
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
{
/* This is a relocatable link. We don't have to change
anything, unless the reloc is against a section symbol,
/* Process stub sections (eg BE8 encoding, ...). */
struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info);
- int i;
+ unsigned int i;
for (i=0; i<htab->top_id; i++)
{
sec = htab->stub_group[i].stub_sec;
/* Tag_ABI_HardFP_use is handled along with Tag_FP_arch since
the meaning of Tag_ABI_HardFP_use depends on Tag_FP_arch
when it's 0. It might mean absence of FP hardware if
- Tag_FP_arch is zero, otherwise it is effectively SP + DP. */
+ Tag_FP_arch is zero. */
#define VFP_VERSION_COUNT 9
static const struct
}
/* Both the input and the output have nonzero Tag_FP_arch.
- So Tag_ABI_HardFP_use is (SP & DP) when it's zero. */
+ So Tag_ABI_HardFP_use is implied by Tag_FP_arch when it's zero. */
/* If both the input and the output have zero Tag_ABI_HardFP_use,
do nothing. */
&& out_attr[Tag_ABI_HardFP_use].i == 0)
;
/* If the input and the output have different Tag_ABI_HardFP_use,
- the combination of them is 3 (SP & DP). */
+ the combination of them is 0 (implied by Tag_FP_arch). */
else if (in_attr[Tag_ABI_HardFP_use].i
!= out_attr[Tag_ABI_HardFP_use].i)
- out_attr[Tag_ABI_HardFP_use].i = 3;
+ out_attr[Tag_ABI_HardFP_use].i = 0;
/* Now we can handle Tag_FP_arch. */
if (flags & EF_ARM_RELEXEC)
fprintf (file, _(" [relocatable executable]"));
- if (flags & EF_ARM_HASENTRY)
- fprintf (file, _(" [has entry point]"));
-
- flags &= ~ (EF_ARM_RELEXEC | EF_ARM_HASENTRY);
+ flags &= ~EF_ARM_RELEXEC;
if (flags)
fprintf (file, _("<Unrecognised flag bits set>"));
const Elf_Internal_Rela *rel, *relend;
struct elf32_arm_link_hash_table * globals;
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
return TRUE;
globals = elf32_arm_hash_table (info);
case R_ARM_THM_MOVW_PREL_NC:
case R_ARM_THM_MOVT_PREL:
/* Should the interworking branches be here also? */
- if ((info->shared || globals->root.is_relocatable_executable)
+ if ((bfd_link_pic (info) || globals->root.is_relocatable_executable)
&& (sec->flags & SEC_ALLOC) != 0)
{
if (h == NULL
bfd_boolean may_need_local_target_p;
unsigned long nsyms;
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
return TRUE;
BFD_ASSERT (is_arm_elf (abfd));
default: tls_type = GOT_NORMAL; break;
}
- if (!info->executable && (tls_type & GOT_TLS_IE))
+ if (!bfd_link_executable (info) && (tls_type & GOT_TLS_IE))
info->flags |= DF_STATIC_TLS;
if (h != NULL)
case R_ARM_MOVT_ABS:
case R_ARM_THM_MOVW_ABS_NC:
case R_ARM_THM_MOVT_ABS:
- if (info->shared)
+ if (bfd_link_pic (info))
{
(*_bfd_error_handler)
(_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"),
/* Fall through. */
case R_ARM_ABS32:
case R_ARM_ABS32_NOI:
- if (h != NULL && info->executable)
+ if (h != NULL && bfd_link_executable (info))
{
h->pointer_equality_needed = 1;
}
case R_ARM_THM_MOVT_PREL:
/* Should the interworking branches be listed here? */
- if ((info->shared || htab->root.is_relocatable_executable)
+ if ((bfd_link_pic (info) || htab->root.is_relocatable_executable)
&& (sec->flags & SEC_ALLOC) != 0)
{
if (h == NULL
be handled correctly by relocate_section. Relocatable executables
can reference data in shared objects directly, so we don't need to
do anything here. */
- if (info->shared || globals->root.is_relocatable_executable)
+ if (bfd_link_pic (info) || globals->root.is_relocatable_executable)
return TRUE;
/* We must allocate the symbol in our .dynbss section, which will
h->got.refcount = 0;
}
- if (info->shared
+ if (bfd_link_pic (info)
|| eh->is_iplt
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
{
location in the .plt. This is required to make function
pointers compare as equal between the normal executable and
the shared library. */
- if (! info->shared
+ if (! bfd_link_pic (info)
&& !h->def_regular)
{
h->root.u.def.section = htab->root.splt;
/* VxWorks executables have a second set of relocations for
each PLT entry. They go in a separate relocation section,
which is processed by the kernel loader. */
- if (htab->vxworks_p && !info->shared)
+ if (htab->vxworks_p && !bfd_link_pic (info))
{
/* There is a relocation for the initial PLT entry:
an R_ARM_32 relocation for _GLOBAL_OFFSET_TABLE_. */
dyn = htab->root.dynamic_sections_created;
indx = 0;
- 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)
|| !SYMBOL_REFERENCES_LOCAL (info, h)))
indx = h->dynindx;
if (tls_type != GOT_NORMAL
- && (info->shared || indx != 0)
+ && (bfd_link_pic (info) || indx != 0)
&& (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak))
{
they all resolve dynamically instead. Reserve room for the
GOT entry's R_ARM_IRELATIVE relocation. */
elf32_arm_allocate_irelocs (info, htab->root.srelgot, 1);
- else if (info->shared && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
- || h->root.type != bfd_link_hash_undefweak))
+ else if (bfd_link_pic (info)
+ && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ || h->root.type != bfd_link_hash_undefweak))
/* Reserve room for the GOT entry's R_ARM_RELATIVE relocation. */
elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
}
space for pc-relative relocs that have become local due to symbol
visibility changes. */
- if (info->shared || htab->root.is_relocatable_executable)
+ if (bfd_link_pic (info) || htab->root.is_relocatable_executable)
{
/* Relocs that use pc_count are PC-relative forms, which will appear
on something like ".long foo - ." or "movw REG, foo - .". We want
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_linker_section (dynobj, ".interp");
BFD_ASSERT (s != NULL);
&& (local_iplt == NULL
|| local_iplt->arm.noncall_refcount == 0))
elf32_arm_allocate_irelocs (info, srel, 1);
- else if (info->shared || output_bfd->flags & DYNAMIC)
+ else if (bfd_link_pic (info) || output_bfd->flags & DYNAMIC)
{
- if ((info->shared && !(*local_tls_type & GOT_TLS_GDESC))
+ if ((bfd_link_pic (info) && !(*local_tls_type & GOT_TLS_GDESC))
|| *local_tls_type & GOT_TLS_GD)
elf32_arm_allocate_dynrelocs (info, srel, 1);
- if (info->shared && *local_tls_type & GOT_TLS_GDESC)
+ if (bfd_link_pic (info) && *local_tls_type & GOT_TLS_GDESC)
{
elf32_arm_allocate_dynrelocs (info,
htab->root.srelplt, 1);
for R_ARM_TLS_LDM32 relocations. */
htab->tls_ldm_got.offset = htab->root.sgot->size;
htab->root.sgot->size += 8;
- if (info->shared)
+ if (bfd_link_pic (info))
elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
}
else
#define add_dynamic_entry(TAG, VAL) \
_bfd_elf_add_dynamic_entry (info, TAG, VAL)
- if (info->executable)
+ if (bfd_link_executable (info))
{
if (!add_dynamic_entry (DT_DEBUG, 0))
return FALSE;
{
asection *tls_sec;
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
return TRUE;
tls_sec = elf_hash_table (info)->tls_sec;
if (!h->def_regular)
{
/* Mark the symbol as undefined, rather than as defined in
- the .plt section. Leave the value alone. */
+ the .plt section. */
sym->st_shndx = SHN_UNDEF;
- /* If the symbol is weak, we do need to clear the value.
+ /* If the symbol is weak we need to clear the value.
Otherwise, the PLT entry would provide a definition for
the symbol even if the symbol wasn't defined anywhere,
- and so the symbol would never be NULL. */
+ and so the symbol would never be NULL. Leave the value if
+ there were any relocations where pointer equality matters
+ (this is a clue for the dynamic linker, to make function
+ pointer comparisons work between an application and shared
+ library). */
if (!h->ref_regular_nonweak || !h->pointer_equality_needed)
sym->st_value = 0;
}
#endif
}
- if (htab->vxworks_p && !info->shared && htab->root.splt->size > 0)
+ if (htab->vxworks_p
+ && !bfd_link_pic (info)
+ && htab->root.splt->size > 0)
{
/* Correct the .rel(a).plt.unloaded relocations. They will have
incorrect symbol indexes. */
osi.sec_shndx = _bfd_elf_section_from_bfd_section
(output_bfd, osi.sec->output_section);
- if (info->shared || htab->root.is_relocatable_executable
+ if (bfd_link_pic (info) || htab->root.is_relocatable_executable
|| htab->pic_veneer)
size = ARM2THUMB_PIC_GLUE_SIZE;
else if (htab->use_blx)
if (htab->vxworks_p)
{
/* VxWorks shared libraries have no PLT header. */
- if (!info->shared)
+ if (!bfd_link_pic (info))
{
if (!elf32_arm_output_map_sym (&osi, ARM_MAP_ARM, 0))
return FALSE;
|| ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
&& (abfd->flags & DYNAMIC) == 0
&& bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour)
- elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
+ elf_tdata (info->output_bfd)->has_gnu_symbols = elf_gnu_symbol_any;
if (elf32_arm_hash_table (info) == NULL)
return FALSE;
#define elf_backend_default_use_rela_p 0
#define elf_backend_got_header_size 12
+#define elf_backend_extern_protected_data 1
#undef elf_backend_obj_attrs_vendor
#define elf_backend_obj_attrs_vendor "aeabi"