+ else
+#endif
+ {
+ /* Check for Arm calling Thumb function. */
+ if (sym_flags == STT_ARM_TFUNC)
+ {
+ elf32_arm_to_thumb_stub (info, sym_name, input_bfd, output_bfd,
+ input_section, hit_data, sym_sec, rel->r_offset,
+ signed_addend, value);
+ return bfd_reloc_ok;
+ }
+ }
+
+ if ( strcmp (bfd_get_target (input_bfd), "elf32-littlearm-oabi") == 0
+ || strcmp (bfd_get_target (input_bfd), "elf32-bigarm-oabi") == 0)
+ {
+ /* The old way of doing things. Trearing the addend as a
+ byte sized field and adding in the pipeline offset. */
+ value -= (input_section->output_section->vma
+ + input_section->output_offset);
+ value -= rel->r_offset;
+ value += addend;
+
+ if (! globals->no_pipeline_knowledge)
+ value -= 8;
+ }
+ else
+ {
+ /* The ARM ELF ABI says that this reloc is computed as: S - P + A
+ where:
+ S is the address of the symbol in the relocation.
+ P is address of the instruction being relocated.
+ A is the addend (extracted from the instruction) in bytes.
+
+ S is held in 'value'.
+ P is the base address of the section containing the instruction
+ plus the offset of the reloc into that section, ie:
+ (input_section->output_section->vma +
+ input_section->output_offset +
+ rel->r_offset).
+ A is the addend, converted into bytes, ie:
+ (signed_addend * 4)
+
+ Note: None of these operations have knowledge of the pipeline
+ size of the processor, thus it is up to the assembler to encode
+ this information into the addend. */
+ value -= (input_section->output_section->vma
+ + input_section->output_offset);
+ value -= rel->r_offset;
+ value += (signed_addend << howto->size);
+
+ /* Previous versions of this code also used to add in the pipeline
+ offset here. This is wrong because the linker is not supposed
+ to know about such things, and one day it might change. In order
+ to support old binaries that need the old behaviour however, so
+ we attempt to detect which ABI was used to create the reloc. */
+ if (! globals->no_pipeline_knowledge)
+ {
+ Elf_Internal_Ehdr * i_ehdrp; /* Elf file header, internal form */
+
+ i_ehdrp = elf_elfheader (input_bfd);
+
+ if (i_ehdrp->e_ident[EI_OSABI] == 0)
+ value -= 8;
+ }
+ }
+
+ signed_addend = value;
+ signed_addend >>= howto->rightshift;
+
+ /* It is not an error for an undefined weak reference to be
+ out of range. Any program that branches to such a symbol
+ is going to crash anyway, so there is no point worrying
+ about getting the destination exactly right. */
+ if (! h || h->root.type != bfd_link_hash_undefweak)
+ {
+ /* Perform a signed range check. */
+ if ( signed_addend > ((bfd_signed_vma) (howto->dst_mask >> 1))
+ || signed_addend < - ((bfd_signed_vma) ((howto->dst_mask + 1) >> 1)))
+ return bfd_reloc_overflow;
+ }
+
+#ifndef OLD_ARM_ABI
+ /* If necessary set the H bit in the BLX instruction. */
+ if (r_type == R_ARM_XPC25 && ((value & 2) == 2))
+ value = (signed_addend & howto->dst_mask)
+ | (bfd_get_32 (input_bfd, hit_data) & (~ howto->dst_mask))
+ | (1 << 24);
+ else
+#endif
+ value = (signed_addend & howto->dst_mask)
+ | (bfd_get_32 (input_bfd, hit_data) & (~ howto->dst_mask));