Line 2352... |
Line 2352... |
static const insn_sequence elf32_arm_stub_a8_veneer_blx[] =
|
static const insn_sequence elf32_arm_stub_a8_veneer_blx[] =
|
{
|
{
|
ARM_REL_INSN(0xea000000, -8) /* b original_branch_dest. */
|
ARM_REL_INSN(0xea000000, -8) /* b original_branch_dest. */
|
};
|
};
|
|
|
/* Section name for stubs is the associated section name plus this
|
/* For each section group there can be a specially created linker section
|
string. */
|
to hold the stubs for that group. The name of the stub section is based
|
#define STUB_SUFFIX ".stub"
|
upon the name of another section within that group with the suffix below
|
|
applied.
|
|
|
|
PR 13049: STUB_SUFFIX used to be ".stub", but this allowed the user to
|
|
create what appeared to be a linker stub section when it actually
|
|
contained user code/data. For example, consider this fragment:
|
|
|
|
const char * stubborn_problems[] = { "np" };
|
|
|
|
If this is compiled with "-fPIC -fdata-sections" then gcc produces a
|
|
section called:
|
|
|
|
.data.rel.local.stubborn_problems
|
|
|
|
This then causes problems in arm32_arm_build_stubs() as it triggers:
|
|
|
|
// Ignore non-stub sections.
|
|
if (!strstr (stub_sec->name, STUB_SUFFIX))
|
|
continue;
|
|
|
|
And so the section would be ignored instead of being processed. Hence
|
|
the change in definition of STUB_SUFFIX to a name that cannot be a valid
|
|
C identifier. */
|
|
#define STUB_SUFFIX ".__stub"
|
|
|
/* One entry per long/short branch stub defined above. */
|
/* One entry per long/short branch stub defined above. */
|
#define DEF_STUBS \
|
#define DEF_STUBS \
|
DEF_STUB(long_branch_any_any) \
|
DEF_STUB(long_branch_any_any) \
|
DEF_STUB(long_branch_v4t_arm_thumb) \
|
DEF_STUB(long_branch_v4t_arm_thumb) \
|
Line 3795... |
Line 3818... |
{
|
{
|
asection *link_sec;
|
asection *link_sec;
|
asection *stub_sec;
|
asection *stub_sec;
|
|
|
link_sec = htab->stub_group[section->id].link_sec;
|
link_sec = htab->stub_group[section->id].link_sec;
|
|
BFD_ASSERT (link_sec != NULL);
|
stub_sec = htab->stub_group[section->id].stub_sec;
|
stub_sec = htab->stub_group[section->id].stub_sec;
|
|
|
if (stub_sec == NULL)
|
if (stub_sec == NULL)
|
{
|
{
|
stub_sec = htab->stub_group[link_sec->id].stub_sec;
|
stub_sec = htab->stub_group[link_sec->id].stub_sec;
|
if (stub_sec == NULL)
|
if (stub_sec == NULL)
|
{
|
{
|
Line 8218... |
Line 8243... |
|
|
if (stub_type != arm_stub_none)
|
if (stub_type != arm_stub_none)
|
{
|
{
|
/* The target is out of reach, so redirect the
|
/* The target is out of reach, so redirect the
|
branch to the local stub for this function. */
|
branch to the local stub for this function. */
|
|
|
stub_entry = elf32_arm_get_stub_entry (input_section,
|
stub_entry = elf32_arm_get_stub_entry (input_section,
|
sym_sec, h,
|
sym_sec, h,
|
rel, globals,
|
rel, globals,
|
stub_type);
|
stub_type);
|
|
{
|
if (stub_entry != NULL)
|
if (stub_entry != NULL)
|
value = (stub_entry->stub_offset
|
value = (stub_entry->stub_offset
|
+ stub_entry->stub_sec->output_offset
|
+ stub_entry->stub_sec->output_offset
|
+ stub_entry->stub_sec->output_section->vma);
|
+ stub_entry->stub_sec->output_section->vma);
|
|
|
|
if (plt_offset != (bfd_vma) -1)
|
|
*unresolved_reloc_p = FALSE;
|
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
/* If the call goes through a PLT entry, make sure to
|
/* If the call goes through a PLT entry, make sure to
|
check distance to the right destination address. */
|
check distance to the right destination address. */
|
Line 8651... |
Line 8680... |
stub_entry = elf32_arm_get_stub_entry (input_section,
|
stub_entry = elf32_arm_get_stub_entry (input_section,
|
sym_sec, h,
|
sym_sec, h,
|
rel, globals,
|
rel, globals,
|
stub_type);
|
stub_type);
|
if (stub_entry != NULL)
|
if (stub_entry != NULL)
|
|
{
|
value = (stub_entry->stub_offset
|
value = (stub_entry->stub_offset
|
+ stub_entry->stub_sec->output_offset
|
+ stub_entry->stub_sec->output_offset
|
+ stub_entry->stub_sec->output_section->vma);
|
+ stub_entry->stub_sec->output_section->vma);
|
|
|
|
if (plt_offset != (bfd_vma) -1)
|
|
*unresolved_reloc_p = FALSE;
|
|
}
|
|
|
/* If this call becomes a call to Arm, force BLX. */
|
/* If this call becomes a call to Arm, force BLX. */
|
if (globals->use_blx && (r_type == R_ARM_THM_CALL))
|
if (globals->use_blx && (r_type == R_ARM_THM_CALL))
|
{
|
{
|
if ((stub_entry
|
if ((stub_entry
|
&& !arm_stub_is_thumb (stub_entry->stub_type))
|
&& !arm_stub_is_thumb (stub_entry->stub_type))
|
Line 10375... |
Line 10409... |
/* Dynamic relocs are not propagated for SEC_DEBUGGING sections
|
/* Dynamic relocs are not propagated for SEC_DEBUGGING sections
|
because such sections are not SEC_ALLOC and thus ld.so will
|
because such sections are not SEC_ALLOC and thus ld.so will
|
not process them. */
|
not process them. */
|
if (unresolved_reloc
|
if (unresolved_reloc
|
&& !((input_section->flags & SEC_DEBUGGING) != 0
|
&& !((input_section->flags & SEC_DEBUGGING) != 0
|
&& h->def_dynamic))
|
&& h->def_dynamic)
|
|
&& _bfd_elf_section_offset (output_bfd, info, input_section,
|
|
rel->r_offset) != (bfd_vma) -1)
|
{
|
{
|
(*_bfd_error_handler)
|
(*_bfd_error_handler)
|
(_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
|
(_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
|
input_bfd,
|
input_bfd,
|
input_section,
|
input_section,
|
Line 11511... |
Line 11547... |
}
|
}
|
break;
|
break;
|
case Tag_PCS_config:
|
case Tag_PCS_config:
|
if (out_attr[i].i == 0)
|
if (out_attr[i].i == 0)
|
out_attr[i].i = in_attr[i].i;
|
out_attr[i].i = in_attr[i].i;
|
else if (in_attr[i].i != 0 && out_attr[i].i != 0)
|
else if (in_attr[i].i != 0 && out_attr[i].i != in_attr[i].i)
|
{
|
{
|
/* It's sometimes ok to mix different configs, so this is only
|
/* It's sometimes ok to mix different configs, so this is only
|
a warning. */
|
a warning. */
|
_bfd_error_handler
|
_bfd_error_handler
|
(_("Warning: %B: Conflicting platform configuration"), ibfd);
|
(_("Warning: %B: Conflicting platform configuration"), ibfd);
|
Line 12609... |
Line 12645... |
{
|
{
|
bfd_boolean found = FALSE;
|
bfd_boolean found = FALSE;
|
|
|
/* We skip _bfd_dwarf1_find_nearest_line since no known ARM toolchain uses it. */
|
/* We skip _bfd_dwarf1_find_nearest_line since no known ARM toolchain uses it. */
|
|
|
if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
|
if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections,
|
|
section, symbols, offset,
|
filename_ptr, functionname_ptr,
|
filename_ptr, functionname_ptr,
|
line_ptr, 0,
|
line_ptr, 0,
|
& elf_tdata (abfd)->dwarf2_find_line_info))
|
& elf_tdata (abfd)->dwarf2_find_line_info))
|
{
|
{
|
if (!*functionname_ptr)
|
if (!*functionname_ptr)
|
Line 14504... |
Line 14541... |
!= 0)
|
!= 0)
|
&& (osi.sec->flags & (SEC_HAS_CONTENTS | SEC_LINKER_CREATED))
|
&& (osi.sec->flags & (SEC_HAS_CONTENTS | SEC_LINKER_CREATED))
|
== SEC_HAS_CONTENTS
|
== SEC_HAS_CONTENTS
|
&& get_arm_elf_section_data (osi.sec) != NULL
|
&& get_arm_elf_section_data (osi.sec) != NULL
|
&& get_arm_elf_section_data (osi.sec)->mapcount == 0
|
&& get_arm_elf_section_data (osi.sec)->mapcount == 0
|
&& osi.sec->size > 0)
|
&& osi.sec->size > 0
|
|
&& (osi.sec->flags & SEC_EXCLUDE) == 0)
|
{
|
{
|
osi.sec_shndx = _bfd_elf_section_from_bfd_section
|
osi.sec_shndx = _bfd_elf_section_from_bfd_section
|
(output_bfd, osi.sec->output_section);
|
(output_bfd, osi.sec->output_section);
|
if (osi.sec_shndx != (int)SHN_BAD)
|
if (osi.sec_shndx != (int)SHN_BAD)
|
elf32_arm_output_map_sym (&osi, ARM_MAP_DATA, 0);
|
elf32_arm_output_map_sym (&osi, ARM_MAP_DATA, 0);
|