r_type = ELF32_R_TYPE (rel->r_info);
+ /* Don't pretend we know what stub to use (if any) when we target a
+ Thumb-only target and we don't know the actual destination
+ type. */
+ if (branch_type == ST_BRANCH_UNKNOWN && thumb_only)
+ return stub_type;
+
/* ST_BRANCH_TO_ARM is nonsense to thumb-only targets when we
are considering a function call relocation. */
if (thumb_only && (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24
|| r_type == R_ARM_THM_JUMP19)
&& branch_type == ST_BRANCH_TO_ARM)
- branch_type = ST_BRANCH_TO_THUMB;
+ {
+ if (sym_sec == bfd_abs_section_ptr)
+ /* As an exception, assume that absolute symbols are of the
+ right kind (Thumb). They are presumably defined in the
+ linker script, where it is not possible to declare them as
+ Thumb (and thus are seen as Arm mode). We'll inform the
+ user with a warning, though, in
+ elf32_arm_final_link_relocate. */
+ branch_type = ST_BRANCH_TO_THUMB;
+ else
+ /* Otherwise do not silently build a stub, and let the users
+ know they have to fix their code. Indeed, we could decide
+ to insert a stub involving Arm code and/or BLX, leading to
+ a run-time crash. */
+ return stub_type;
+ }
/* For TLS call relocs, it is the caller's responsibility to provide
the address of the appropriate trampoline. */
else
addend = signed_addend = rel->r_addend;
- /* ST_BRANCH_TO_ARM is nonsense to thumb-only targets when we
- are resolving a function call relocation. */
- if (using_thumb_only (globals)
- && (r_type == R_ARM_THM_CALL
- || r_type == R_ARM_THM_JUMP24)
- && branch_type == ST_BRANCH_TO_ARM)
- branch_type = ST_BRANCH_TO_THUMB;
-
/* Record the symbol information that should be used in dynamic
relocations. */
dynreloc_st_type = st_type;
gotplt_offset = (bfd_vma) -1;
}
+ /* ST_BRANCH_TO_ARM is nonsense to thumb-only targets when we are
+ resolving a function call relocation. We want to inform the user
+ that something is wrong. */
+ if (using_thumb_only (globals)
+ && (r_type == R_ARM_THM_CALL
+ || r_type == R_ARM_THM_JUMP24)
+ && branch_type == ST_BRANCH_TO_ARM
+ /* Calls through a PLT are special: the assembly source code
+ cannot be annotated with '.type foo(PLT), %function', and
+ they handled specifically below anyway. */
+ && splt == NULL)
+ {
+ if (sym_sec == bfd_abs_section_ptr)
+ {
+ /* As an exception, assume that absolute symbols are of the
+ right kind (Thumb). They are presumably defined in the
+ linker script, where it is not possible to declare them as
+ Thumb (and thus are seen as Arm mode). Inform the user with
+ a warning, though. */
+ branch_type = ST_BRANCH_TO_THUMB;
+
+ if (sym_sec->owner)
+ _bfd_error_handler
+ (_("warning: %pB(%s): Forcing bramch to absolute symbol in Thumb mode (Thumb-only CPU)"
+ " in %pB"),
+ sym_sec->owner, sym_name, input_bfd);
+ else
+ _bfd_error_handler
+ (_("warning: (%s): Forcing branch to absolute symbol in Thumb mode (Thumb-only CPU)"
+ " in %pB"),
+ sym_name, input_bfd);
+ }
+ else
+ /* Otherwise do not silently build a stub, and let the users
+ know they have to fix their code. Indeed, we could decide
+ to insert a stub involving Arm code and/or BLX, leading to
+ a run-time crash. */
+ branch_type = ST_BRANCH_UNKNOWN;
+ }
+
+ /* Fail early if branch_type is ST_BRANCH_UNKNOWN and we target a
+ Thumb-only CPU. We could emit a warning on Arm-capable targets
+ too, but that would be too verbose (a lot of legacy code does not
+ use the .type foo, %function directive). */
+ if (using_thumb_only (globals)
+ && (r_type == R_ARM_THM_CALL
+ || r_type == R_ARM_THM_JUMP24)
+ && branch_type == ST_BRANCH_UNKNOWN)
+ {
+ if (sym_sec != NULL
+ && sym_sec->owner != NULL)
+ _bfd_error_handler
+ (_("%pB(%s): Unknown destination type (ARM/Thumb) in %pB"),
+ sym_sec->owner, sym_name, input_bfd);
+ else
+ _bfd_error_handler
+ (_("(%s): Unknown destination type (ARM/Thumb) in %pB"),
+ sym_name, input_bfd);
+
+ return bfd_reloc_notsupported;
+ }
+
resolved_to_zero = (h != NULL
&& UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
sym.st_other = 0;
sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_NOTYPE);
sym.st_shndx = osi->sec_shndx;
- sym.st_target_internal = 0;
+ sym.st_target_internal = ST_BRANCH_TO_ARM;
elf32_arm_section_map_add (osi->sec, names[type][1], offset);
return osi->func (osi->flaginfo, names[type], &sym, osi->sec, NULL) == 1;
}
sym.st_other = 0;
sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FUNC);
sym.st_shndx = osi->sec_shndx;
- sym.st_target_internal = 0;
+ sym.st_target_internal = ST_BRANCH_TO_ARM;
return osi->func (osi->flaginfo, name, &sym, osi->sec, NULL) == 1;
}
{
if (!bfd_elf32_swap_symbol_in (abfd, psrc, pshn, dst))
return false;
- dst->st_target_internal = 0;
+ dst->st_target_internal = ST_BRANCH_TO_ARM;
/* New EABI objects mark thumb function symbols by setting the low bit of
the address. */