Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Typedefs | Enumerations | Functions | Variables
elf32-arm.c File Reference
#include "bfd.h"
#include "sysdep.h"
#include "libiberty.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf-vxworks.h"
#include "elf/arm.h"
#include "elf32-target.h"

Go to the source code of this file.

Classes

struct  elf32_arm_reloc_map
struct  elf32_elf_section_map
struct  elf32_vfp11_erratum_list
struct  _arm_elf_section_data
struct  aeabi_attribute
struct  aeabi_attribute_list
struct  elf32_arm_obj_tdata
struct  elf32_arm_relocs_copied
struct  elf32_arm_link_hash_entry
struct  section_list
struct  output_arch_syminfo
union  elf32_vfp11_erratum_list.u
struct  elf32_vfp11_erratum_list.u.b
struct  elf32_vfp11_erratum_list.u.v

Defines

#define NUM_ELEM(a)   (sizeof (a) / (sizeof (a)[0]))
#define RELOC_SECTION(HTAB, NAME)   ((HTAB)->use_rel ? ".rel" NAME : ".rela" NAME)
#define RELOC_SIZE(HTAB)
#define SWAP_RELOC_IN(HTAB)
#define SWAP_RELOC_OUT(HTAB)
#define elf_info_to_howto   0
#define elf_info_to_howto_rel   elf32_arm_info_to_howto
#define ARM_ELF_ABI_VERSION   0
#define ARM_ELF_OS_ABI_VERSION   ELFOSABI_ARM
#define TARGET_LITTLE_SYM   bfd_elf32_littlearm_vec
#define TARGET_LITTLE_NAME   "elf32-littlearm"
#define TARGET_BIG_SYM   bfd_elf32_bigarm_vec
#define TARGET_BIG_NAME   "elf32-bigarm"
#define elf_backend_grok_prstatus   elf32_arm_nabi_grok_prstatus
#define elf_backend_grok_psinfo   elf32_arm_nabi_grok_psinfo
#define INTERWORK_FLAG(abfd)
#define THUMB2ARM_GLUE_SECTION_NAME   ".glue_7t"
#define THUMB2ARM_GLUE_ENTRY_NAME   "__%s_from_thumb"
#define ARM2THUMB_GLUE_SECTION_NAME   ".glue_7"
#define ARM2THUMB_GLUE_ENTRY_NAME   "__%s_from_arm"
#define VFP11_ERRATUM_VENEER_SECTION_NAME   ".vfp11_veneer"
#define VFP11_ERRATUM_VENEER_ENTRY_NAME   "__vfp11_veneer_%x"
#define ELF_DYNAMIC_INTERPRETER   "/usr/lib/ld.so.1"
#define PLT_THUMB_STUB_SIZE   4
#define elf32_arm_section_data(sec)   ((_arm_elf_section_data *) elf_section_data (sec))
#define TCB_SIZE   8
#define NUM_KNOWN_ATTRIBUTES   32
#define elf32_arm_tdata(abfd)   ((struct elf32_arm_obj_tdata *) (abfd)->tdata.any)
#define elf32_arm_local_got_tls_type(abfd)   (elf32_arm_tdata (abfd)->local_got_tls_type)
#define elf32_arm_hash_entry(ent)   ((struct elf32_arm_link_hash_entry *)(ent))
#define GOT_UNKNOWN   0
#define GOT_NORMAL   1
#define GOT_TLS_GD   2
#define GOT_TLS_IE   4
#define elf32_arm_link_hash_traverse(table, func, info)
#define elf32_arm_hash_table(info)   ((struct elf32_arm_link_hash_table *) ((info)->hash))
#define ARM2THUMB_STATIC_GLUE_SIZE   12
#define ARM2THUMB_PIC_GLUE_SIZE   16
#define THUMB2ARM_GLUE_SIZE   8
#define VFP11_ERRATUM_VENEER_SIZE   8
#define CHANGE_TO_ARM   "__%s_change_to_arm"
#define BACK_FROM_ARM   "__%s_back_from_arm"
#define LOW_HI_ORDER   0xF800F000
#define HI_LOW_ORDER   0xF000F800
#define IS_ARM_TLS_RELOC(R_TYPE)
#define add_dynamic_entry(TAG, VAL)   _bfd_elf_add_dynamic_entry (info, TAG, VAL)
#define ELF_ARCH   bfd_arch_arm
#define ELF_MACHINE_CODE   EM_ARM
#define ELF_MAXPAGESIZE   0x8000
#define ELF_MINPAGESIZE   0x1000
#define ELF_COMMONPAGESIZE   0x1000
#define bfd_elf32_mkobject   elf32_arm_mkobject
#define bfd_elf32_bfd_copy_private_bfd_data   elf32_arm_copy_private_bfd_data
#define bfd_elf32_bfd_merge_private_bfd_data   elf32_arm_merge_private_bfd_data
#define bfd_elf32_bfd_set_private_flags   elf32_arm_set_private_flags
#define bfd_elf32_bfd_print_private_bfd_data   elf32_arm_print_private_bfd_data
#define bfd_elf32_bfd_link_hash_table_create   elf32_arm_link_hash_table_create
#define bfd_elf32_bfd_reloc_type_lookup   elf32_arm_reloc_type_lookup
#define bfd_elf32_bfd_reloc_name_lookup   elf32_arm_reloc_name_lookup
#define bfd_elf32_find_nearest_line   elf32_arm_find_nearest_line
#define bfd_elf32_find_inliner_info   elf32_arm_find_inliner_info
#define bfd_elf32_new_section_hook   elf32_arm_new_section_hook
#define bfd_elf32_bfd_is_target_special_symbol   elf32_arm_is_target_special_symbol
#define bfd_elf32_close_and_cleanup   elf32_arm_close_and_cleanup
#define bfd_elf32_bfd_free_cached_info   elf32_arm_bfd_free_cached_info
#define bfd_elf32_bfd_final_link   elf32_arm_bfd_final_link
#define elf_backend_get_symbol_type   elf32_arm_get_symbol_type
#define elf_backend_gc_mark_hook   elf32_arm_gc_mark_hook
#define elf_backend_gc_mark_extra_sections   elf32_arm_gc_mark_extra_sections
#define elf_backend_gc_sweep_hook   elf32_arm_gc_sweep_hook
#define elf_backend_check_relocs   elf32_arm_check_relocs
#define elf_backend_relocate_section   elf32_arm_relocate_section
#define elf_backend_write_section   elf32_arm_write_section
#define elf_backend_adjust_dynamic_symbol   elf32_arm_adjust_dynamic_symbol
#define elf_backend_create_dynamic_sections   elf32_arm_create_dynamic_sections
#define elf_backend_finish_dynamic_symbol   elf32_arm_finish_dynamic_symbol
#define elf_backend_finish_dynamic_sections   elf32_arm_finish_dynamic_sections
#define elf_backend_size_dynamic_sections   elf32_arm_size_dynamic_sections
#define elf_backend_init_index_section   _bfd_elf_init_2_index_sections
#define elf_backend_post_process_headers   elf32_arm_post_process_headers
#define elf_backend_reloc_type_class   elf32_arm_reloc_type_class
#define elf_backend_object_p   elf32_arm_object_p
#define elf_backend_section_flags   elf32_arm_section_flags
#define elf_backend_fake_sections   elf32_arm_fake_sections
#define elf_backend_section_from_shdr   elf32_arm_section_from_shdr
#define elf_backend_final_write_processing   elf32_arm_final_write_processing
#define elf_backend_copy_indirect_symbol   elf32_arm_copy_indirect_symbol
#define elf_backend_symbol_processing   elf32_arm_symbol_processing
#define elf_backend_size_info   elf32_arm_size_info
#define elf_backend_modify_segment_map   elf32_arm_modify_segment_map
#define elf_backend_additional_program_headers   elf32_arm_additional_program_headers
#define elf_backend_output_arch_local_syms   elf32_arm_output_arch_local_syms
#define elf_backend_begin_write_processing   elf32_arm_begin_write_processing
#define elf_backend_can_refcount   1
#define elf_backend_can_gc_sections   1
#define elf_backend_plt_readonly   1
#define elf_backend_want_got_plt   1
#define elf_backend_want_plt_sym   0
#define elf_backend_may_use_rel_p   1
#define elf_backend_may_use_rela_p   0
#define elf_backend_default_use_rela_p   0
#define elf_backend_got_header_size   12
#define TARGET_LITTLE_SYM   bfd_elf32_littlearm_vxworks_vec
#define TARGET_LITTLE_NAME   "elf32-littlearm-vxworks"
#define TARGET_BIG_SYM   bfd_elf32_bigarm_vxworks_vec
#define TARGET_BIG_NAME   "elf32-bigarm-vxworks"
#define elf32_bed   elf32_arm_vxworks_bed
#define bfd_elf32_bfd_link_hash_table_create   elf32_arm_vxworks_link_hash_table_create
#define elf_backend_add_symbol_hook   elf_vxworks_add_symbol_hook
#define elf_backend_final_write_processing   elf32_arm_vxworks_final_write_processing
#define elf_backend_emit_relocs   elf_vxworks_emit_relocs
#define elf_backend_may_use_rel_p   0
#define elf_backend_may_use_rela_p   1
#define elf_backend_default_use_rela_p   1
#define elf_backend_want_plt_sym   1
#define ELF_MAXPAGESIZE   0x1000
#define TARGET_LITTLE_SYM   bfd_elf32_littlearm_symbian_vec
#define TARGET_LITTLE_NAME   "elf32-littlearm-symbian"
#define TARGET_BIG_SYM   bfd_elf32_bigarm_symbian_vec
#define TARGET_BIG_NAME   "elf32-bigarm-symbian"
#define elf32_bed   elf32_arm_symbian_bed
#define ELF_DYNAMIC_SEC_FLAGS   (SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED)
#define bfd_elf32_bfd_link_hash_table_create   elf32_arm_symbian_link_hash_table_create
#define elf_backend_special_sections   elf32_arm_symbian_special_sections
#define elf_backend_begin_write_processing   elf32_arm_symbian_begin_write_processing
#define elf_backend_final_write_processing   elf32_arm_final_write_processing
#define elf_backend_modify_segment_map   elf32_arm_symbian_modify_segment_map
#define elf_backend_got_header_size   0
#define elf_backend_want_got_plt   0
#define elf_backend_may_use_rel_p   1
#define elf_backend_may_use_rela_p   0
#define elf_backend_default_use_rela_p   0
#define elf_backend_want_plt_sym   0
#define ELF_MAXPAGESIZE   0x8000

Typedefs

typedef unsigned long int insn32
typedef unsigned short int insn16
typedef struct
elf32_elf_section_map 
elf32_arm_section_map
typedef struct
elf32_vfp11_erratum_list 
elf32_vfp11_erratum_list
typedef struct
_arm_elf_section_data 
_arm_elf_section_data
typedef struct aeabi_attribute aeabi_attribute
typedef struct aeabi_attribute_list aeabi_attribute_list
typedef struct section_list section_list

Enumerations

enum  elf32_vfp11_erratum_type { VFP11_ERRATUM_BRANCH_TO_ARM_VENEER, VFP11_ERRATUM_BRANCH_TO_THUMB_VENEER, VFP11_ERRATUM_ARM_VENEER, VFP11_ERRATUM_THUMB_VENEER }
enum  bfd_arm_vfp11_pipe { VFP11_FMAC, VFP11_LS, VFP11_DS, VFP11_BAD }
enum  { AEABI_R9_V6, AEABI_R9_SB, AEABI_R9_TLS, AEABI_R9_unused }
enum  { AEABI_PCS_RW_data_absolute, AEABI_PCS_RW_data_PCrel, AEABI_PCS_RW_data_SBrel, AEABI_PCS_RW_data_unused }
enum  { AEABI_enum_unused, AEABI_enum_short, AEABI_enum_wide, AEABI_enum_forced_wide }
enum  map_symbol_type { ARM_MAP_ARM, ARM_MAP_THUMB, ARM_MAP_DATA }

Functions

static reloc_howto_type * elf32_arm_howto_from_type (unsigned int r_type)
static void elf32_arm_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *bfd_reloc, Elf_Internal_Rela *elf_reloc)
static reloc_howto_type * elf32_arm_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
static reloc_howto_type * elf32_arm_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
static bfd_boolean elf32_arm_nabi_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
static bfd_boolean elf32_arm_nabi_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
static bfd_boolean elf32_arm_mkobject (bfd *abfd)
static struct bfd_hash_entryelf32_arm_link_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table, const char *string)
static bfd_boolean reloc_section_p (struct elf32_arm_link_hash_table *htab, const char *name, asection *s)
static bfd_boolean create_got_section (bfd *dynobj, struct bfd_link_info *info)
static bfd_boolean elf32_arm_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
static void elf32_arm_copy_indirect_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *dir, struct elf_link_hash_entry *ind)
static struct bfd_link_hash_tableelf32_arm_link_hash_table_create (bfd *abfd)
static struct elf_link_hash_entryfind_thumb_glue (struct bfd_link_info *link_info, const char *name, char **error_message)
static struct elf_link_hash_entryfind_arm_glue (struct bfd_link_info *link_info, const char *name, char **error_message)
bfd_boolean bfd_elf32_arm_allocate_interworking_sections (struct bfd_link_info *info)
static struct elf_link_hash_entryrecord_arm_to_thumb_glue (struct bfd_link_info *link_info, struct elf_link_hash_entry *h)
static void record_thumb_to_arm_glue (struct bfd_link_info *link_info, struct elf_link_hash_entry *h)
static void elf32_arm_section_map_add (asection *sec, char type, bfd_vma vma)
static bfd_vma record_vfp11_erratum_veneer (struct bfd_link_info *link_info, elf32_vfp11_erratum_list *branch, bfd *branch_bfd, asection *branch_sec, unsigned int offset)
bfd_boolean bfd_elf32_arm_add_glue_sections_to_bfd (bfd *abfd, struct bfd_link_info *info)
bfd_boolean bfd_elf32_arm_get_bfd_for_interworking (bfd *abfd, struct bfd_link_info *info)
static void check_use_blx (struct elf32_arm_link_hash_table *globals)
bfd_boolean bfd_elf32_arm_process_before_allocation (bfd *abfd, struct bfd_link_info *link_info)
void bfd_elf32_arm_init_maps (bfd *abfd)
void bfd_elf32_arm_set_vfp11_fix (bfd *obfd, struct bfd_link_info *link_info)
static unsigned int bfd_arm_vfp11_regno (unsigned int insn, bfd_boolean is_double, unsigned int rx, unsigned int x)
static void bfd_arm_vfp11_write_mask (unsigned int *wmask, unsigned int reg)
static bfd_boolean bfd_arm_vfp11_antidependency (unsigned int wmask, int *regs, int numregs)
static enum bfd_arm_vfp11_pipe bfd_arm_vfp11_insn_decode (unsigned int insn, unsigned int *destmask, int *regs, int *numregs)
static int elf32_arm_compare_mapping (const void *a, const void *b)
bfd_boolean bfd_elf32_arm_vfp11_erratum_scan (bfd *abfd, struct bfd_link_info *link_info)
void bfd_elf32_arm_vfp11_fix_veneer_locations (bfd *abfd, struct bfd_link_info *link_info)
void bfd_elf32_arm_set_target_relocs (struct bfd *output_bfd, struct bfd_link_info *link_info, int target1_is_rel, char *target2_type, int fix_v4bx, int use_blx, bfd_arm_vfp11_fix vfp11_fix, int no_enum_warn, int pic_veneer)
static insn32 insert_thumb_branch (insn32 br_insn, int rel_off)
static void put_arm_insn (struct elf32_arm_link_hash_table *htab, bfd *output_bfd, bfd_vma val, void *ptr)
static void put_thumb_insn (struct elf32_arm_link_hash_table *htab, bfd *output_bfd, bfd_vma val, void *ptr)
static int elf32_thumb_to_arm_stub (struct bfd_link_info *info, const char *name, bfd *input_bfd, bfd *output_bfd, asection *input_section, bfd_byte *hit_data, asection *sym_sec, bfd_vma offset, bfd_signed_vma addend, bfd_vma val, char **error_message)
static struct elf_link_hash_entryelf32_arm_create_thumb_stub (struct bfd_link_info *info, const char *name, bfd *input_bfd, bfd *output_bfd, asection *sym_sec, bfd_vma val, asection *s, char **error_message)
static int elf32_arm_to_thumb_stub (struct bfd_link_info *info, const char *name, bfd *input_bfd, bfd *output_bfd, asection *input_section, bfd_byte *hit_data, asection *sym_sec, bfd_vma offset, bfd_signed_vma addend, bfd_vma val, char **error_message)
static bfd_boolean elf32_arm_to_thumb_export_stub (struct elf_link_hash_entry *h, void *inf)
static void elf32_arm_begin_write_processing (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *link_info)
static int arm_real_reloc_type (struct elf32_arm_link_hash_table *globals, int r_type)
static bfd_vma dtpoff_base (struct bfd_link_info *info)
static bfd_vma tpoff (struct bfd_link_info *info, bfd_vma address)
static bfd_reloc_status_type elf32_arm_abs12_reloc (bfd *abfd, void *data, bfd_vma value)
static bfd_vma calculate_group_reloc_mask (bfd_vma value, int n, bfd_vma *final_residual)
static int identify_add_or_sub (bfd_vma insn)
static int using_thumb2 (struct elf32_arm_link_hash_table *globals)
static bfd_reloc_status_type elf32_arm_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd, bfd *output_bfd, asection *input_section, bfd_byte *contents, Elf_Internal_Rela *rel, bfd_vma value, struct bfd_link_info *info, asection *sym_sec, const char *sym_name, int sym_flags, struct elf_link_hash_entry *h, bfd_boolean *unresolved_reloc_p, char **error_message)
static int uleb128_size (unsigned int i)
static bfd_boolean is_default_attr (aeabi_attribute *attr)
static bfd_vma eabi_attr_size (int tag, aeabi_attribute *attr)
bfd_vma elf32_arm_eabi_attr_size (bfd *abfd)
static bfd_bytewrite_uleb128 (bfd_byte *p, unsigned int val)
static bfd_bytewrite_eabi_attribute (bfd_byte *p, int tag, aeabi_attribute *attr)
void elf32_arm_set_eabi_attr_contents (bfd *abfd, bfd_byte *contents, bfd_vma size)
static bfd_boolean elf32_arm_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
static void arm_add_to_rel (bfd *abfd, bfd_byte *address, reloc_howto_type *howto, bfd_signed_vma increment)
static bfd_boolean elf32_arm_relocate_section (bfd *output_bfd, struct bfd_link_info *info, bfd *input_bfd, asection *input_section, bfd_byte *contents, Elf_Internal_Rela *relocs, Elf_Internal_Sym *local_syms, asection **local_sections)
static aeabi_attributeelf32_arm_new_eabi_attr (bfd *abfd, int tag)
int elf32_arm_get_eabi_attr_int (bfd *abfd, int tag)
void elf32_arm_add_eabi_attr_int (bfd *abfd, int tag, unsigned int i)
static char * attr_strdup (bfd *abfd, const char *s)
void elf32_arm_add_eabi_attr_string (bfd *abfd, int tag, const char *s)
void elf32_arm_add_eabi_attr_compat (bfd *abfd, unsigned int i, const char *s)
static bfd_boolean elf32_arm_object_p (bfd *abfd)
static bfd_boolean elf32_arm_set_private_flags (bfd *abfd, flagword flags)
static void copy_eabi_attributes (bfd *ibfd, bfd *obfd)
static bfd_boolean elf32_arm_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
static bfd_boolean elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd)
static bfd_boolean elf32_arm_versions_compatible (unsigned iver, unsigned over)
static bfd_boolean elf32_arm_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
static bfd_boolean elf32_arm_print_private_bfd_data (bfd *abfd, void *ptr)
static int elf32_arm_get_symbol_type (Elf_Internal_Sym *elf_sym, int type)
static asectionelf32_arm_gc_mark_hook (asection *sec, struct bfd_link_info *info, Elf_Internal_Rela *rel, struct elf_link_hash_entry *h, Elf_Internal_Sym *sym)
static bfd_boolean elf32_arm_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, asection *sec, const Elf_Internal_Rela *relocs)
static bfd_boolean elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, const Elf_Internal_Rela *relocs)
static bfd_boolean elf32_arm_gc_mark_extra_sections (struct bfd_link_info *info, elf_gc_mark_hook_fn gc_mark_hook)
static bfd_boolean elf32_arm_is_target_special_symbol (bfd *abfd ATTRIBUTE_UNUSED, asymbol *sym)
static bfd_boolean arm_elf_find_function (bfd *abfd ATTRIBUTE_UNUSED, asection *section, asymbol **symbols, bfd_vma offset, const char **filename_ptr, const char **functionname_ptr)
static bfd_boolean elf32_arm_find_nearest_line (bfd *abfd, asection *section, asymbol **symbols, bfd_vma offset, const char **filename_ptr, const char **functionname_ptr, unsigned int *line_ptr)
static bfd_boolean elf32_arm_find_inliner_info (bfd *abfd, const char **filename_ptr, const char **functionname_ptr, unsigned int *line_ptr)
static bfd_boolean elf32_arm_adjust_dynamic_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *h)
static bfd_boolean allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
static bfd_boolean elf32_arm_readonly_dynrelocs (struct elf_link_hash_entry *h, PTR inf)
void bfd_elf32_arm_set_byteswap_code (struct bfd_link_info *info, int byteswap_code)
static bfd_boolean elf32_arm_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
static bfd_boolean elf32_arm_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, struct elf_link_hash_entry *h, Elf_Internal_Sym *sym)
static bfd_boolean elf32_arm_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
static void elf32_arm_post_process_headers (bfd *abfd, struct bfd_link_info *link_info ATTRIBUTE_UNUSED)
static enum elf_reloc_type_class elf32_arm_reloc_type_class (const Elf_Internal_Rela *rela)
static bfd_boolean elf32_arm_section_flags (flagword *flags, const Elf_Internal_Shdr *hdr)
static void elf32_arm_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED)
static bfd_boolean is_arm_elf_unwind_section_name (bfd *abfd ATTRIBUTE_UNUSED, const char *name)
static bfd_boolean elf32_arm_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec)
static void elf32_arm_parse_attributes (bfd *abfd, Elf_Internal_Shdr *hdr)
static bfd_boolean elf32_arm_section_from_shdr (bfd *abfd, Elf_Internal_Shdr *hdr, const char *name, int shindex)
static void record_section_with_arm_elf_section_data (asection *sec)
static struct section_listfind_arm_elf_section_entry (asection *sec)
static _arm_elf_section_dataget_arm_elf_section_data (asection *sec)
static void unrecord_section_with_arm_elf_section_data (asection *sec)
static bfd_boolean elf32_arm_ouput_plt_map_sym (output_arch_syminfo *osi, enum map_symbol_type type, bfd_vma offset)
static bfd_boolean elf32_arm_output_plt_map (struct elf_link_hash_entry *h, void *inf)
static bfd_boolean elf32_arm_output_arch_local_syms (bfd *output_bfd, struct bfd_link_info *info, void *finfo, bfd_boolean(*func)(void *, const char *, Elf_Internal_Sym *, asection *, struct elf_link_hash_entry *))
static bfd_boolean elf32_arm_new_section_hook (bfd *abfd, asection *sec)
static bfd_boolean elf32_arm_write_section (bfd *output_bfd, struct bfd_link_info *link_info, asection *sec, bfd_byte *contents)
static void unrecord_section_via_map_over_sections (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *ignore ATTRIBUTE_UNUSED)
static bfd_boolean elf32_arm_close_and_cleanup (bfd *abfd)
static bfd_boolean elf32_arm_bfd_free_cached_info (bfd *abfd)
static void elf32_arm_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, asymbol *asym)
static bfd_boolean elf32_arm_swap_symbol_in (bfd *abfd, const void *psrc, const void *pshn, Elf_Internal_Sym *dst)
static void elf32_arm_swap_symbol_out (bfd *abfd, const Elf_Internal_Sym *src, void *cdst, void *shndx)
static bfd_boolean elf32_arm_modify_segment_map (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
static int elf32_arm_additional_program_headers (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
static struct bfd_link_hash_tableelf32_arm_vxworks_link_hash_table_create (bfd *abfd)
static void elf32_arm_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker)
static struct bfd_link_hash_tableelf32_arm_symbian_link_hash_table_create (bfd *abfd)
static void elf32_arm_symbian_begin_write_processing (bfd *abfd, struct bfd_link_info *link_info)
static bfd_boolean elf32_arm_symbian_modify_segment_map (bfd *abfd, struct bfd_link_info *info)

Variables

static struct elf_backend_data
static reloc_howto_type elf32_arm_howto_table_1 []
static reloc_howto_type elf32_arm_howto_table_2 [4]
static struct elf32_arm_reloc_map []
static const bfd_vma elf32_arm_plt0_entry []
static const bfd_vma elf32_arm_plt_entry []
static const bfd_vma elf32_arm_vxworks_exec_plt0_entry []
static const bfd_vma elf32_arm_vxworks_exec_plt_entry []
static const bfd_vma elf32_arm_vxworks_shared_plt_entry []
static const bfd_vma elf32_arm_plt_thumb_stub []
static const bfd_vma elf32_arm_symbian_plt_entry []
static const insn32 a2t1_ldr_insn = 0xe59fc000
static const insn32 a2t2_bx_r12_insn = 0xe12fff1c
static const insn32 a2t3_func_addr_insn = 0x00000001
static const insn32 a2t1p_ldr_insn = 0xe59fc004
static const insn32 a2t2p_add_pc_insn = 0xe08cc00f
static const insn32 a2t3p_bx_r12_insn = 0xe12fff1c
static const insn16 t2a1_bx_pc_insn = 0x4778
static const insn16 t2a2_noop_insn = 0x46c0
static const insn32 t2a3_b_insn = 0xea000000
static section_listsections_with_arm_elf_section_data = NULL
static struct bfd_elf_special_section []

Class Documentation

struct elf32_arm_reloc_map

Definition at line 1690 of file elf32-arm.c.

Class Members
bfd_reloc_code_real_type bfd_reloc_val
unsigned char elf_reloc_val
struct elf32_elf_section_map

Definition at line 2011 of file elf32-arm.c.

Class Members
char type
bfd_vma vma
struct elf32_vfp11_erratum_list

Definition at line 2029 of file elf32-arm.c.

Collaboration diagram for elf32_vfp11_erratum_list:
Class Members
struct elf32_vfp11_erratum_list * next
elf32_vfp11_erratum_type type
union elf32_vfp11_erratum_list u
bfd_vma vma
struct _arm_elf_section_data

Definition at line 2050 of file elf32-arm.c.

Collaboration diagram for _arm_elf_section_data:
Class Members
unsigned int erratumcount
elf32_vfp11_erratum_list * erratumlist
elf32_arm_section_map * map
unsigned int mapcount
unsigned int mapsize
struct aeabi_attribute

Definition at line 2069 of file elf32-arm.c.

Class Members
unsigned int i
char * s
int type
struct aeabi_attribute_list

Definition at line 2076 of file elf32-arm.c.

Collaboration diagram for aeabi_attribute_list:
Class Members
aeabi_attribute attr
struct aeabi_attribute_list * next
int tag
struct elf32_arm_obj_tdata

Definition at line 2083 of file elf32-arm.c.

Collaboration diagram for elf32_arm_obj_tdata:
Class Members
aeabi_attribute known_eabi_attributes
char * local_got_tls_type
int no_enum_size_warning
aeabi_attribute_list * other_eabi_attributes
struct elf32_arm_relocs_copied

Definition at line 2124 of file elf32-arm.c.

Collaboration diagram for elf32_arm_relocs_copied:
Class Members
bfd_size_type count
struct elf32_arm_relocs_copied * next
bfd_size_type pc_count
asection * section
struct elf32_arm_link_hash_entry

Definition at line 2139 of file elf32-arm.c.

Collaboration diagram for elf32_arm_link_hash_entry:
Class Members
struct elf_link_hash_entry * export_glue
bfd_signed_vma plt_got_offset
bfd_signed_vma plt_thumb_refcount
struct elf32_arm_relocs_copied * relocs_copied
unsigned char tls_type
struct elf32_arm_link_hash_table

Definition at line 2178 of file elf32-arm.c.

Collaboration diagram for elf32_arm_link_hash_table:
Class Members
bfd_size_type arm_glue_size
bfd * bfd_of_glue_owner
int byteswap_code
int fix_v4bx
int num_vfp11_fixes
bfd * obfd
int pic_veneer
bfd_size_type plt_entry_size
bfd_size_type plt_header_size
asection * sdynbss
asection * sgot
asection * sgotplt
asection * splt
asection * srelbss
asection * srelgot
asection * srelplt
asection * srelplt2
int symbian_p
int target1_is_rel
int target2_reloc
bfd_size_type thumb_glue_size
union elf32_arm_link_hash_table tls_ldm_got
int use_blx
int use_rel
bfd_size_type vfp11_erratum_glue_size
bfd_arm_vfp11_fix vfp11_fix
int vxworks_p
struct section_list

Definition at line 9945 of file elf32-arm.c.

Collaboration diagram for section_list:
Class Members
struct section_list * next
struct section_list * prev
asection * sec
union elf32_vfp11_erratum_list.u

Definition at line 2033 of file elf32-arm.c.

Class Members
u b
u v
struct elf32_vfp11_erratum_list.u.b

Definition at line 2035 of file elf32-arm.c.

Class Members
struct elf32_vfp11_erratum_list * veneer
unsigned int vfp_insn
struct elf32_vfp11_erratum_list.u.v

Definition at line 2040 of file elf32-arm.c.

Class Members
struct elf32_vfp11_erratum_list * branch
unsigned int id
union elf32_arm_link_hash_table.tls_ldm_got

Definition at line 2250 of file elf32-arm.c.

Class Members
bfd_vma offset
bfd_signed_vma refcount

Define Documentation

#define add_dynamic_entry (   TAG,
  VAL 
)    _bfd_elf_add_dynamic_entry (info, TAG, VAL)
#define ARM2THUMB_GLUE_ENTRY_NAME   "__%s_from_arm"

Definition at line 1901 of file elf32-arm.c.

#define ARM2THUMB_GLUE_SECTION_NAME   ".glue_7"

Definition at line 1900 of file elf32-arm.c.

#define ARM2THUMB_PIC_GLUE_SIZE   16

Definition at line 2600 of file elf32-arm.c.

#define ARM2THUMB_STATIC_GLUE_SIZE   12

Definition at line 2595 of file elf32-arm.c.

#define ARM_ELF_ABI_VERSION   0

Definition at line 62 of file elf32-arm.c.

Definition at line 63 of file elf32-arm.c.

#define BACK_FROM_ARM   "__%s_back_from_arm"

Definition at line 10601 of file elf32-arm.c.

Definition at line 10614 of file elf32-arm.c.

Definition at line 10613 of file elf32-arm.c.

Definition at line 10611 of file elf32-arm.c.

Definition at line 10838 of file elf32-arm.c.

Definition at line 10838 of file elf32-arm.c.

Definition at line 10838 of file elf32-arm.c.

Definition at line 10602 of file elf32-arm.c.

Definition at line 10604 of file elf32-arm.c.

Definition at line 10607 of file elf32-arm.c.

Definition at line 10606 of file elf32-arm.c.

Definition at line 10603 of file elf32-arm.c.

Definition at line 10612 of file elf32-arm.c.

Definition at line 10609 of file elf32-arm.c.

Definition at line 10608 of file elf32-arm.c.

Definition at line 10599 of file elf32-arm.c.

Definition at line 10610 of file elf32-arm.c.

#define CHANGE_TO_ARM   "__%s_change_to_arm"
#define elf32_arm_hash_entry (   ent)    ((struct elf32_arm_link_hash_entry *)(ent))

Definition at line 2136 of file elf32-arm.c.

#define elf32_arm_hash_table (   info)    ((struct elf32_arm_link_hash_table *) ((info)->hash))

Definition at line 2174 of file elf32-arm.c.

#define elf32_arm_link_hash_traverse (   table,
  func,
  info 
)
Value:
(elf_link_hash_traverse                                        \
   (&(table)->root,                                            \
    (bfd_boolean (*) (struct elf_link_hash_entry *, void *)) (func),  \
    (info)))

Definition at line 2167 of file elf32-arm.c.

#define elf32_arm_local_got_tls_type (   abfd)    (elf32_arm_tdata (abfd)->local_got_tls_type)

Definition at line 2100 of file elf32-arm.c.

#define elf32_arm_section_data (   sec)    ((_arm_elf_section_data *) elf_section_data (sec))

Definition at line 2061 of file elf32-arm.c.

#define elf32_arm_tdata (   abfd)    ((struct elf32_arm_obj_tdata *) (abfd)->tdata.any)

Definition at line 2097 of file elf32-arm.c.

#define elf32_bed   elf32_arm_vxworks_bed

Definition at line 10829 of file elf32-arm.c.

#define elf32_bed   elf32_arm_symbian_bed

Definition at line 10829 of file elf32-arm.c.

#define ELF_ARCH   bfd_arch_arm

Definition at line 10589 of file elf32-arm.c.

Definition at line 10703 of file elf32-arm.c.

Definition at line 10640 of file elf32-arm.c.

Definition at line 10623 of file elf32-arm.c.

Definition at line 10846 of file elf32-arm.c.

Definition at line 10846 of file elf32-arm.c.

Definition at line 10648 of file elf32-arm.c.

#define elf_backend_can_refcount   1

Definition at line 10647 of file elf32-arm.c.

Definition at line 10620 of file elf32-arm.c.

Definition at line 10636 of file elf32-arm.c.

Definition at line 10624 of file elf32-arm.c.

Definition at line 10869 of file elf32-arm.c.

Definition at line 10869 of file elf32-arm.c.

Definition at line 10869 of file elf32-arm.c.

Definition at line 10709 of file elf32-arm.c.

Definition at line 10633 of file elf32-arm.c.

Definition at line 10849 of file elf32-arm.c.

Definition at line 10849 of file elf32-arm.c.

Definition at line 10849 of file elf32-arm.c.

Definition at line 10626 of file elf32-arm.c.

Definition at line 10625 of file elf32-arm.c.

Definition at line 10618 of file elf32-arm.c.

Definition at line 10617 of file elf32-arm.c.

Definition at line 10619 of file elf32-arm.c.

Definition at line 10616 of file elf32-arm.c.

#define elf_backend_got_header_size   12

Definition at line 10858 of file elf32-arm.c.

Definition at line 10858 of file elf32-arm.c.

Definition at line 1881 of file elf32-arm.c.

Definition at line 1882 of file elf32-arm.c.

Definition at line 10628 of file elf32-arm.c.

#define elf_backend_may_use_rel_p   1

Definition at line 10865 of file elf32-arm.c.

#define elf_backend_may_use_rel_p   0

Definition at line 10865 of file elf32-arm.c.

#define elf_backend_may_use_rel_p   1

Definition at line 10865 of file elf32-arm.c.

Definition at line 10867 of file elf32-arm.c.

Definition at line 10867 of file elf32-arm.c.

Definition at line 10867 of file elf32-arm.c.

Definition at line 10854 of file elf32-arm.c.

Definition at line 10854 of file elf32-arm.c.

Definition at line 10631 of file elf32-arm.c.

Definition at line 10642 of file elf32-arm.c.

#define elf_backend_plt_readonly   1

Definition at line 10649 of file elf32-arm.c.

Definition at line 10629 of file elf32-arm.c.

Definition at line 10630 of file elf32-arm.c.

Definition at line 10621 of file elf32-arm.c.

Definition at line 10632 of file elf32-arm.c.

Definition at line 10634 of file elf32-arm.c.

Definition at line 10627 of file elf32-arm.c.

#define elf_backend_size_info   elf32_arm_size_info

Definition at line 10638 of file elf32-arm.c.

#define elf_backend_special_sections   elf32_arm_symbian_special_sections

Definition at line 10843 of file elf32-arm.c.

Definition at line 10637 of file elf32-arm.c.

#define elf_backend_want_got_plt   1

Definition at line 10862 of file elf32-arm.c.

#define elf_backend_want_got_plt   0

Definition at line 10862 of file elf32-arm.c.

#define elf_backend_want_plt_sym   0

Definition at line 10871 of file elf32-arm.c.

#define elf_backend_want_plt_sym   1

Definition at line 10871 of file elf32-arm.c.

#define elf_backend_want_plt_sym   0

Definition at line 10871 of file elf32-arm.c.

Definition at line 10622 of file elf32-arm.c.

#define ELF_COMMONPAGESIZE   0x1000

Definition at line 10597 of file elf32-arm.c.

#define ELF_DYNAMIC_INTERPRETER   "/usr/lib/ld.so.1"

Definition at line 1908 of file elf32-arm.c.

Definition at line 10834 of file elf32-arm.c.

#define elf_info_to_howto   0

Definition at line 59 of file elf32-arm.c.

Definition at line 60 of file elf32-arm.c.

#define ELF_MACHINE_CODE   EM_ARM

Definition at line 10590 of file elf32-arm.c.

#define ELF_MAXPAGESIZE   0x8000

Definition at line 10873 of file elf32-arm.c.

#define ELF_MAXPAGESIZE   0x1000

Definition at line 10873 of file elf32-arm.c.

#define ELF_MAXPAGESIZE   0x8000

Definition at line 10873 of file elf32-arm.c.

#define ELF_MINPAGESIZE   0x1000

Definition at line 10596 of file elf32-arm.c.

#define GOT_NORMAL   1

Definition at line 2156 of file elf32-arm.c.

#define GOT_TLS_GD   2

Definition at line 2157 of file elf32-arm.c.

#define GOT_TLS_IE   4

Definition at line 2158 of file elf32-arm.c.

#define GOT_UNKNOWN   0

Definition at line 2155 of file elf32-arm.c.

#define HI_LOW_ORDER   0xF000F800

Definition at line 3955 of file elf32-arm.c.

#define INTERWORK_FLAG (   abfd)
Value:

Definition at line 1889 of file elf32-arm.c.

#define IS_ARM_TLS_RELOC (   R_TYPE)
Value:
((R_TYPE) == R_ARM_TLS_GD32        \
   || (R_TYPE) == R_ARM_TLS_LDO32  \
   || (R_TYPE) == R_ARM_TLS_LDM32  \
   || (R_TYPE) == R_ARM_TLS_DTPOFF32      \
   || (R_TYPE) == R_ARM_TLS_DTPMOD32      \
   || (R_TYPE) == R_ARM_TLS_TPOFF32       \
   || (R_TYPE) == R_ARM_TLS_LE32   \
   || (R_TYPE) == R_ARM_TLS_IE32)

Definition at line 6504 of file elf32-arm.c.

#define LOW_HI_ORDER   0xF800F000

Definition at line 3954 of file elf32-arm.c.

#define NUM_ELEM (   a)    (sizeof (a) / (sizeof (a)[0]))

Definition at line 30 of file elf32-arm.c.

#define NUM_KNOWN_ATTRIBUTES   32

Definition at line 2067 of file elf32-arm.c.

#define PLT_THUMB_STUB_SIZE   4

Definition at line 1993 of file elf32-arm.c.

#define RELOC_SECTION (   HTAB,
  NAME 
)    ((HTAB)->use_rel ? ".rel" NAME : ".rela" NAME)

Definition at line 35 of file elf32-arm.c.

#define RELOC_SIZE (   HTAB)
Value:
((HTAB)->use_rel \
   ? sizeof (Elf32_External_Rel) \
   : sizeof (Elf32_External_Rela))

Definition at line 40 of file elf32-arm.c.

#define SWAP_RELOC_IN (   HTAB)
Value:

Definition at line 47 of file elf32-arm.c.

#define SWAP_RELOC_OUT (   HTAB)
Value:

Definition at line 54 of file elf32-arm.c.

#define TARGET_BIG_NAME   "elf32-bigarm"

Definition at line 10735 of file elf32-arm.c.

#define TARGET_BIG_NAME   "elf32-bigarm-vxworks"

Definition at line 10735 of file elf32-arm.c.

#define TARGET_BIG_NAME   "elf32-bigarm-symbian"

Definition at line 10735 of file elf32-arm.c.

Definition at line 10733 of file elf32-arm.c.

Definition at line 10733 of file elf32-arm.c.

Definition at line 10733 of file elf32-arm.c.

#define TARGET_LITTLE_NAME   "elf32-littlearm"

Definition at line 10731 of file elf32-arm.c.

#define TARGET_LITTLE_NAME   "elf32-littlearm-vxworks"

Definition at line 10731 of file elf32-arm.c.

#define TARGET_LITTLE_NAME   "elf32-littlearm-symbian"

Definition at line 10731 of file elf32-arm.c.

Definition at line 10729 of file elf32-arm.c.

Definition at line 10729 of file elf32-arm.c.

Definition at line 10729 of file elf32-arm.c.

#define TCB_SIZE   8

Definition at line 2065 of file elf32-arm.c.

#define THUMB2ARM_GLUE_ENTRY_NAME   "__%s_from_thumb"

Definition at line 1898 of file elf32-arm.c.

#define THUMB2ARM_GLUE_SECTION_NAME   ".glue_7t"

Definition at line 1897 of file elf32-arm.c.

#define THUMB2ARM_GLUE_SIZE   8

Definition at line 2621 of file elf32-arm.c.

#define VFP11_ERRATUM_VENEER_ENTRY_NAME   "__vfp11_veneer_%x"

Definition at line 1904 of file elf32-arm.c.

#define VFP11_ERRATUM_VENEER_SECTION_NAME   ".vfp11_veneer"

Definition at line 1903 of file elf32-arm.c.

#define VFP11_ERRATUM_VENEER_SIZE   8

Definition at line 2626 of file elf32-arm.c.


Typedef Documentation

typedef unsigned short int insn16

Definition at line 1885 of file elf32-arm.c.

Definition at line 1884 of file elf32-arm.c.


Enumeration Type Documentation

anonymous enum
Enumerator:
AEABI_R9_V6 
AEABI_R9_SB 
AEABI_R9_TLS 
AEABI_R9_unused 

Definition at line 7040 of file elf32-arm.c.

anonymous enum
Enumerator:
AEABI_PCS_RW_data_absolute 
AEABI_PCS_RW_data_PCrel 
AEABI_PCS_RW_data_SBrel 
AEABI_PCS_RW_data_unused 

Definition at line 7049 of file elf32-arm.c.

anonymous enum
Enumerator:
AEABI_enum_unused 
AEABI_enum_short 
AEABI_enum_wide 
AEABI_enum_forced_wide 

Definition at line 7058 of file elf32-arm.c.

Enumerator:
VFP11_FMAC 
VFP11_LS 
VFP11_DS 
VFP11_BAD 

Definition at line 3336 of file elf32-arm.c.

Enumerator:
VFP11_ERRATUM_BRANCH_TO_ARM_VENEER 
VFP11_ERRATUM_BRANCH_TO_THUMB_VENEER 
VFP11_ERRATUM_ARM_VENEER 
VFP11_ERRATUM_THUMB_VENEER 

Definition at line 2020 of file elf32-arm.c.

Enumerator:
ARM_MAP_ARM 
ARM_MAP_THUMB 
ARM_MAP_DATA 

Definition at line 10055 of file elf32-arm.c.


Function Documentation

static bfd_boolean allocate_dynrelocs ( struct elf_link_hash_entry h,
void *  inf 
) [static]

Definition at line 8522 of file elf32-arm.c.

{
  struct bfd_link_info *info;
  struct elf32_arm_link_hash_table *htab;
  struct elf32_arm_link_hash_entry *eh;
  struct elf32_arm_relocs_copied *p;

  eh = (struct elf32_arm_link_hash_entry *) h;

  if (h->root.type == bfd_link_hash_indirect)
    return TRUE;

  if (h->root.type == bfd_link_hash_warning)
    /* When warning symbols are created, they **replace** the "real"
       entry in the hash table, thus we never get to see the real
       symbol in a hash traversal.  So look at it now.  */
    h = (struct elf_link_hash_entry *) h->root.u.i.link;

  info = (struct bfd_link_info *) inf;
  htab = elf32_arm_hash_table (info);

  if (htab->root.dynamic_sections_created
      && h->plt.refcount > 0)
    {
      /* Make sure this symbol is output as a dynamic symbol.
        Undefined weak syms won't yet be marked as dynamic.  */
      if (h->dynindx == -1
         && !h->forced_local)
       {
         if (! bfd_elf_link_record_dynamic_symbol (info, h))
           return FALSE;
       }

      if (info->shared
         || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
       {
         asection *s = htab->splt;

         /* If this is the first .plt entry, make room for the special
            first entry.  */
         if (s->size == 0)
           s->size += htab->plt_header_size;

         h->plt.offset = s->size;

         /* If we will insert a Thumb trampoline before this PLT, leave room
            for it.  */
         if (!htab->use_blx && eh->plt_thumb_refcount > 0)
           {
             h->plt.offset += PLT_THUMB_STUB_SIZE;
             s->size += PLT_THUMB_STUB_SIZE;
           }

         /* If this symbol is not defined in a regular file, and we are
            not generating a shared library, then set the symbol to this
            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
             && !h->def_regular)
           {
             h->root.u.def.section = s;
             h->root.u.def.value = h->plt.offset;

             /* Make sure the function is not marked as Thumb, in case
               it is the target of an ABS32 relocation, which will
               point to the PLT entry.  */
             if (ELF_ST_TYPE (h->type) == STT_ARM_TFUNC)
              h->type = ELF_ST_INFO (ELF_ST_BIND (h->type), STT_FUNC);
           }

         /* Make room for this entry.  */
         s->size += htab->plt_entry_size;

         if (!htab->symbian_p)
           {
             /* We also need to make an entry in the .got.plt section, which
               will be placed in the .got section by the linker script.  */
             eh->plt_got_offset = htab->sgotplt->size;
             htab->sgotplt->size += 4;
           }

         /* We also need to make an entry in the .rel(a).plt section.  */
         htab->srelplt->size += RELOC_SIZE (htab);

         /* 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)
           {
             /* There is a relocation for the initial PLT entry:
               an R_ARM_32 relocation for _GLOBAL_OFFSET_TABLE_.  */
             if (h->plt.offset == htab->plt_header_size)
              htab->srelplt2->size += RELOC_SIZE (htab);

             /* There are two extra relocations for each subsequent
               PLT entry: an R_ARM_32 relocation for the GOT entry,
               and an R_ARM_32 relocation for the PLT entry.  */
             htab->srelplt2->size += RELOC_SIZE (htab) * 2;
           }
       }
      else
       {
         h->plt.offset = (bfd_vma) -1;
         h->needs_plt = 0;
       }
    }
  else
    {
      h->plt.offset = (bfd_vma) -1;
      h->needs_plt = 0;
    }

  if (h->got.refcount > 0)
    {
      asection *s;
      bfd_boolean dyn;
      int tls_type = elf32_arm_hash_entry (h)->tls_type;
      int indx;

      /* Make sure this symbol is output as a dynamic symbol.
        Undefined weak syms won't yet be marked as dynamic.  */
      if (h->dynindx == -1
         && !h->forced_local)
       {
         if (! bfd_elf_link_record_dynamic_symbol (info, h))
           return FALSE;
       }

      if (!htab->symbian_p)
       {
         s = htab->sgot;
         h->got.offset = s->size;

         if (tls_type == GOT_UNKNOWN)
           abort ();

         if (tls_type == GOT_NORMAL)
           /* Non-TLS symbols need one GOT slot.  */
           s->size += 4;
         else
           {
             if (tls_type & GOT_TLS_GD)
              /* R_ARM_TLS_GD32 needs 2 consecutive GOT slots.  */
              s->size += 8;
             if (tls_type & GOT_TLS_IE)
              /* R_ARM_TLS_IE32 needs one GOT slot.  */
              s->size += 4;
           }

         dyn = htab->root.dynamic_sections_created;

         indx = 0;
         if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
             && (!info->shared
                || !SYMBOL_REFERENCES_LOCAL (info, h)))
           indx = h->dynindx;

         if (tls_type != GOT_NORMAL
             && (info->shared || indx != 0)
             && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                || h->root.type != bfd_link_hash_undefweak))
           {
             if (tls_type & GOT_TLS_IE)
              htab->srelgot->size += RELOC_SIZE (htab);

             if (tls_type & GOT_TLS_GD)
              htab->srelgot->size += RELOC_SIZE (htab);

             if ((tls_type & GOT_TLS_GD) && indx != 0)
              htab->srelgot->size += RELOC_SIZE (htab);
           }
         else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                  || h->root.type != bfd_link_hash_undefweak)
                 && (info->shared
                 || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
           htab->srelgot->size += RELOC_SIZE (htab);
       }
    }
  else
    h->got.offset = (bfd_vma) -1;

  /* Allocate stubs for exported Thumb functions on v4t.  */
  if (!htab->use_blx && h->dynindx != -1
      && h->def_regular
      && ELF_ST_TYPE (h->type) == STT_ARM_TFUNC
      && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
    {
      struct elf_link_hash_entry * th;
      struct bfd_link_hash_entry * bh;
      struct elf_link_hash_entry * myh;
      char name[1024];
      asection *s;
      bh = NULL;
      /* Create a new symbol to regist the real location of the function.  */
      s = h->root.u.def.section;
      sprintf(name, "__real_%s", h->root.root.string);
      _bfd_generic_link_add_one_symbol (info, s->owner,
                                   name, BSF_GLOBAL, s,
                                   h->root.u.def.value,
                                   NULL, TRUE, FALSE, &bh);

      myh = (struct elf_link_hash_entry *) bh;
      myh->type = ELF_ST_INFO (STB_LOCAL, STT_ARM_TFUNC);
      myh->forced_local = 1;
      eh->export_glue = myh;
      th = record_arm_to_thumb_glue (info, h);
      /* Point the symbol at the stub.  */
      h->type = ELF_ST_INFO (ELF_ST_BIND (h->type), STT_FUNC);
      h->root.u.def.section = th->root.u.def.section;
      h->root.u.def.value = th->root.u.def.value & ~1;
    }

  if (eh->relocs_copied == NULL)
    return TRUE;

  /* In the shared -Bsymbolic case, discard space allocated for
     dynamic pc-relative relocs against symbols which turn out to be
     defined in regular objects.  For the normal shared case, discard
     space for pc-relative relocs that have become local due to symbol
     visibility changes.  */

  if (info->shared || htab->root.is_relocatable_executable)
    {
      /* The only reloc thats uses pc_count are R_ARM_REL32 and
         R_ARM_REL32_NOI, which will appear on something like
         ".long foo - .".  We want calls to protected symbols to resolve
         directly to the function rather than going via the plt.  If people
         want function pointer comparisons to work as expected then they
         should avoid writing assembly like ".long foo - .".  */
      if (SYMBOL_CALLS_LOCAL (info, h))
       {
         struct elf32_arm_relocs_copied **pp;

         for (pp = &eh->relocs_copied; (p = *pp) != NULL; )
           {
             p->count -= p->pc_count;
             p->pc_count = 0;
             if (p->count == 0)
              *pp = p->next;
             else
              pp = &p->next;
           }
       }

      /* Also discard relocs on undefined weak syms with non-default
         visibility.  */
      if (eh->relocs_copied != NULL
         && h->root.type == bfd_link_hash_undefweak)
       {
         if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
           eh->relocs_copied = NULL;

         /* Make sure undefined weak symbols are output as a dynamic
            symbol in PIEs.  */
         else if (h->dynindx == -1
                 && !h->forced_local)
           {
             if (! bfd_elf_link_record_dynamic_symbol (info, h))
              return FALSE;
           }
       }

      else if (htab->root.is_relocatable_executable && h->dynindx == -1
              && h->root.type == bfd_link_hash_new)
       {
         /* Output absolute symbols so that we can create relocations
            against them.  For normal symbols we output a relocation
            against the section that contains them.  */
         if (! bfd_elf_link_record_dynamic_symbol (info, h))
           return FALSE;
       }

    }
  else
    {
      /* For the non-shared case, discard space for relocs against
        symbols which turn out to need copy relocs or are not
        dynamic.  */

      if (!h->non_got_ref
         && ((h->def_dynamic
              && !h->def_regular)
             || (htab->root.dynamic_sections_created
                && (h->root.type == bfd_link_hash_undefweak
                    || h->root.type == bfd_link_hash_undefined))))
       {
         /* Make sure this symbol is output as a dynamic symbol.
            Undefined weak syms won't yet be marked as dynamic.  */
         if (h->dynindx == -1
             && !h->forced_local)
           {
             if (! bfd_elf_link_record_dynamic_symbol (info, h))
              return FALSE;
           }

         /* If that succeeded, we know we'll be keeping all the
            relocs.  */
         if (h->dynindx != -1)
           goto keep;
       }

      eh->relocs_copied = NULL;

    keep: ;
    }

  /* Finally, allocate space.  */
  for (p = eh->relocs_copied; p != NULL; p = p->next)
    {
      asection *sreloc = elf_section_data (p->section)->sreloc;
      sreloc->size += p->count * RELOC_SIZE (htab);
    }

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void arm_add_to_rel ( bfd abfd,
bfd_byte address,
reloc_howto_type *  howto,
bfd_signed_vma  increment 
) [static]

Definition at line 6433 of file elf32-arm.c.

{
  bfd_signed_vma addend;

  if (howto->type == R_ARM_THM_CALL)
    {
      int upper_insn, lower_insn;
      int upper, lower;

      upper_insn = bfd_get_16 (abfd, address);
      lower_insn = bfd_get_16 (abfd, address + 2);
      upper = upper_insn & 0x7ff;
      lower = lower_insn & 0x7ff;

      addend = (upper << 12) | (lower << 1);
      addend += increment;
      addend >>= 1;

      upper_insn = (upper_insn & 0xf800) | ((addend >> 11) & 0x7ff);
      lower_insn = (lower_insn & 0xf800) | (addend & 0x7ff);

      bfd_put_16 (abfd, (bfd_vma) upper_insn, address);
      bfd_put_16 (abfd, (bfd_vma) lower_insn, address + 2);
    }
  else
    {
      bfd_vma        contents;

      contents = bfd_get_32 (abfd, address);

      /* Get the (signed) value from the instruction.  */
      addend = contents & howto->src_mask;
      if (addend & ((howto->src_mask + 1) >> 1))
       {
         bfd_signed_vma mask;

         mask = -1;
         mask &= ~ howto->src_mask;
         addend |= mask;
       }

      /* Add in the increment, (which is a byte value).  */
      switch (howto->type)
       {
       default:
         addend += increment;
         break;

       case R_ARM_PC24:
       case R_ARM_PLT32:
       case R_ARM_CALL:
       case R_ARM_JUMP24:
         addend <<= howto->size;
         addend += increment;

         /* Should we check for overflow here ?  */

         /* Drop any undesired bits.  */
         addend >>= howto->rightshift;
         break;
       }

      contents = (contents & ~ howto->dst_mask) | (addend & howto->dst_mask);

      bfd_put_32 (abfd, contents, address);
    }
}

Here is the caller graph for this function:

static bfd_boolean arm_elf_find_function ( bfd *abfd  ATTRIBUTE_UNUSED,
asection section,
asymbol **  symbols,
bfd_vma  offset,
const char **  filename_ptr,
const char **  functionname_ptr 
) [static]

Definition at line 8249 of file elf32-arm.c.

{
  const char * filename = NULL;
  asymbol * func = NULL;
  bfd_vma low_func = 0;
  asymbol ** p;

  for (p = symbols; *p != NULL; p++)
    {
      elf_symbol_type *q;

      q = (elf_symbol_type *) *p;

      switch (ELF_ST_TYPE (q->internal_elf_sym.st_info))
       {
       default:
         break;
       case STT_FILE:
         filename = bfd_asymbol_name (&q->symbol);
         break;
       case STT_FUNC:
       case STT_ARM_TFUNC:
       case STT_NOTYPE:
         /* Skip mapping symbols.  */
         if ((q->symbol.flags & BSF_LOCAL)
             && bfd_is_arm_special_symbol_name (q->symbol.name,
                  BFD_ARM_SPECIAL_SYM_TYPE_ANY))
           continue;
         /* Fall through.  */
         if (bfd_get_section (&q->symbol) == section
             && q->symbol.value >= low_func
             && q->symbol.value <= offset)
           {
             func = (asymbol *) q;
             low_func = q->symbol.value;
           }
         break;
       }
    }

  if (func == NULL)
    return FALSE;

  if (filename_ptr)
    *filename_ptr = filename;
  if (functionname_ptr)
    *functionname_ptr = bfd_asymbol_name (func);

  return TRUE;
}  

Here is the call graph for this function:

Here is the caller graph for this function:

static int arm_real_reloc_type ( struct elf32_arm_link_hash_table globals,
int  r_type 
) [static]

Definition at line 4326 of file elf32-arm.c.

{
  switch (r_type)
    {
    case R_ARM_TARGET1:
      if (globals->target1_is_rel)
       return R_ARM_REL32;
      else
       return R_ARM_ABS32;

    case R_ARM_TARGET2:
      return globals->target2_reloc;

    default:
      return r_type;
    }
}

Here is the caller graph for this function:

static char* attr_strdup ( bfd abfd,
const char *  s 
) [static]

Definition at line 6839 of file elf32-arm.c.

{
  char * p;
  int len;
  
  len = strlen (s) + 1;
  p = (char *)bfd_alloc(abfd, len);
  return memcpy (p, s, len);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean bfd_arm_vfp11_antidependency ( unsigned int  wmask,
int regs,
int  numregs 
) [static]

Definition at line 3380 of file elf32-arm.c.

{
  int i;
  
  for (i = 0; i < numregs; i++)
    {
      unsigned int reg = regs[i];

      if (reg < 32 && (wmask & (1 << reg)) != 0)
        return TRUE;
      
      reg -= 32;

      if (reg >= 16)
        continue;
      
      if ((wmask & (3 << (reg * 2))) != 0)
        return TRUE;
    }
  
  return FALSE;
}

Here is the caller graph for this function:

static enum bfd_arm_vfp11_pipe bfd_arm_vfp11_insn_decode ( unsigned int  insn,
unsigned int destmask,
int regs,
int numregs 
) [static]

Definition at line 3412 of file elf32-arm.c.

{
  enum bfd_arm_vfp11_pipe pipe = VFP11_BAD;
  bfd_boolean is_double = ((insn & 0xf00) == 0xb00) ? 1 : 0;

  if ((insn & 0x0f000e10) == 0x0e000a00)  /* A data-processing insn.  */
    {
      unsigned int pqrs;
      unsigned int fd = bfd_arm_vfp11_regno (insn, is_double, 12, 22);
      unsigned int fm = bfd_arm_vfp11_regno (insn, is_double, 0, 5);

      pqrs = ((insn & 0x00800000) >> 20)
           | ((insn & 0x00300000) >> 19)
           | ((insn & 0x00000040) >> 6);

      switch (pqrs)
        {
        case 0: /* fmac[sd].  */
        case 1: /* fnmac[sd].  */
        case 2: /* fmsc[sd].  */
        case 3: /* fnmsc[sd].  */
          pipe = VFP11_FMAC;
          bfd_arm_vfp11_write_mask (destmask, fd);
          regs[0] = fd;
          regs[1] = bfd_arm_vfp11_regno (insn, is_double, 16, 7);  /* Fn.  */
          regs[2] = fm;
          *numregs = 3;
          break;

        case 4: /* fmul[sd].  */
        case 5: /* fnmul[sd].  */
        case 6: /* fadd[sd].  */
        case 7: /* fsub[sd].  */
          pipe = VFP11_FMAC;
          goto vfp_binop;

        case 8: /* fdiv[sd].  */
          pipe = VFP11_DS;
          vfp_binop:
          bfd_arm_vfp11_write_mask (destmask, fd);
          regs[0] = bfd_arm_vfp11_regno (insn, is_double, 16, 7);   /* Fn.  */
          regs[1] = fm;
          *numregs = 2;
          break;

        case 15: /* extended opcode.  */
          {
            unsigned int extn = ((insn >> 15) & 0x1e)
                              | ((insn >> 7) & 1);

            switch (extn)
              {
              case 0: /* fcpy[sd].  */
              case 1: /* fabs[sd].  */
              case 2: /* fneg[sd].  */
              case 8: /* fcmp[sd].  */
              case 9: /* fcmpe[sd].  */
              case 10: /* fcmpz[sd].  */
              case 11: /* fcmpez[sd].  */
              case 16: /* fuito[sd].  */
              case 17: /* fsito[sd].  */
              case 24: /* ftoui[sd].  */
              case 25: /* ftouiz[sd].  */
              case 26: /* ftosi[sd].  */
              case 27: /* ftosiz[sd].  */
                /* These instructions will not bounce due to underflow.  */
                *numregs = 0;
                pipe = VFP11_FMAC;
                break;

              case 3: /* fsqrt[sd].  */
                /* fsqrt cannot underflow, but it can (perhaps) overwrite
                   registers to cause the erratum in previous instructions.  */
                bfd_arm_vfp11_write_mask (destmask, fd);
                pipe = VFP11_DS;
                break;

              case 15: /* fcvt{ds,sd}.  */
                {
                  int rnum = 0;

                  bfd_arm_vfp11_write_mask (destmask, fd);

                /* Only FCVTSD can underflow.  */
                  if ((insn & 0x100) != 0)
                    regs[rnum++] = fm;

                  *numregs = rnum;

                  pipe = VFP11_FMAC;
                }
                break;

              default:
                return VFP11_BAD;
              }
          }
          break;

        default:
          return VFP11_BAD;
        }
    }
  /* Two-register transfer.  */
  else if ((insn & 0x0fe00ed0) == 0x0c400a10)
    {
      unsigned int fm = bfd_arm_vfp11_regno (insn, is_double, 0, 5);
      
      if ((insn & 0x100000) == 0)
       {
          if (is_double)
            bfd_arm_vfp11_write_mask (destmask, fm);
          else
            {
              bfd_arm_vfp11_write_mask (destmask, fm);
              bfd_arm_vfp11_write_mask (destmask, fm + 1);
            }
       }

      pipe = VFP11_LS;
    }
  else if ((insn & 0x0e100e00) == 0x0c100a00)  /* A load insn.  */
    {
      int fd = bfd_arm_vfp11_regno (insn, is_double, 12, 22);
      unsigned int puw = ((insn >> 21) & 0x1) | (((insn >> 23) & 3) << 1);
      
      switch (puw)
        {
        case 0: /* Two-reg transfer.  We should catch these above.  */
          abort ();
        
        case 2: /* fldm[sdx].  */
        case 3:
        case 5:
          {
            unsigned int i, offset = insn & 0xff;

            if (is_double)
              offset >>= 1;

            for (i = fd; i < fd + offset; i++)
              bfd_arm_vfp11_write_mask (destmask, i);
          }
          break;
        
        case 4: /* fld[sd].  */
        case 6:
          bfd_arm_vfp11_write_mask (destmask, fd);
          break;
        
        default:
          return VFP11_BAD;
        }

      pipe = VFP11_LS;
    }
  /* Single-register transfer. Note L==0.  */
  else if ((insn & 0x0f100e10) == 0x0e000a10)
    {
      unsigned int opcode = (insn >> 21) & 7;
      unsigned int fn = bfd_arm_vfp11_regno (insn, is_double, 16, 7);

      switch (opcode)
        {
        case 0: /* fmsr/fmdlr.  */
        case 1: /* fmdhr.  */
          /* Mark fmdhr and fmdlr as writing to the whole of the DP
             destination register.  I don't know if this is exactly right,
             but it is the conservative choice.  */
          bfd_arm_vfp11_write_mask (destmask, fn);
          break;

        case 7: /* fmxr.  */
          break;
        }

      pipe = VFP11_LS;
    }

  return pipe;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static unsigned int bfd_arm_vfp11_regno ( unsigned int  insn,
bfd_boolean  is_double,
unsigned int  rx,
unsigned int  x 
) [static]

Definition at line 3356 of file elf32-arm.c.

{
  if (is_double)
    return (((insn >> rx) & 0xf) | (((insn >> x) & 1) << 4)) + 32;
  else
    return (((insn >> rx) & 0xf) << 1) | ((insn >> x) & 1);
}

Here is the caller graph for this function:

static void bfd_arm_vfp11_write_mask ( unsigned int wmask,
unsigned int  reg 
) [static]

Definition at line 3369 of file elf32-arm.c.

{
  if (reg < 32)
    *wmask |= 1 << reg;
  else if (reg < 48)
    *wmask |= 3 << ((reg - 32) * 2);
}

Here is the caller graph for this function:

Definition at line 2988 of file elf32-arm.c.

{
  flagword flags;
  asection *sec;

  /* If we are only performing a partial
     link do not bother adding the glue.  */
  if (info->relocatable)
    return TRUE;

  sec = bfd_get_section_by_name (abfd, ARM2THUMB_GLUE_SECTION_NAME);

  if (sec == NULL)
    {
      /* Note: we do not include the flag SEC_LINKER_CREATED, as this
        will prevent elf_link_input_bfd() from processing the contents
        of this section.  */
      flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
              | SEC_CODE | SEC_READONLY);

      sec = bfd_make_section_with_flags (abfd,
                                    ARM2THUMB_GLUE_SECTION_NAME,
                                    flags);

      if (sec == NULL
         || !bfd_set_section_alignment (abfd, sec, 2))
       return FALSE;

      /* Set the gc mark to prevent the section from being removed by garbage
        collection, despite the fact that no relocs refer to this section.  */
      sec->gc_mark = 1;
    }

  sec = bfd_get_section_by_name (abfd, THUMB2ARM_GLUE_SECTION_NAME);

  if (sec == NULL)
    {
      flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
              | SEC_CODE | SEC_READONLY);

      sec = bfd_make_section_with_flags (abfd,
                                    THUMB2ARM_GLUE_SECTION_NAME,
                                    flags);

      if (sec == NULL
         || !bfd_set_section_alignment (abfd, sec, 2))
       return FALSE;

      sec->gc_mark = 1;
    }

  sec = bfd_get_section_by_name (abfd, VFP11_ERRATUM_VENEER_SECTION_NAME);

  if (sec == NULL)
    {
      flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
              | SEC_CODE | SEC_READONLY);

      sec = bfd_make_section_with_flags (abfd,
                                    VFP11_ERRATUM_VENEER_SECTION_NAME,
                                         flags);

      if (sec == NULL
         || !bfd_set_section_alignment (abfd, sec, 2))
       return FALSE;

      sec->gc_mark = 1;
    }

  return TRUE;
}

Here is the call graph for this function:

Definition at line 2630 of file elf32-arm.c.

{
  asection * s;
  bfd_byte * foo;
  struct elf32_arm_link_hash_table * globals;

  globals = elf32_arm_hash_table (info);

  BFD_ASSERT (globals != NULL);

  if (globals->arm_glue_size != 0)
    {
      BFD_ASSERT (globals->bfd_of_glue_owner != NULL);

      s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
                               ARM2THUMB_GLUE_SECTION_NAME);

      BFD_ASSERT (s != NULL);

      foo = bfd_alloc (globals->bfd_of_glue_owner, globals->arm_glue_size);

      BFD_ASSERT (s->size == globals->arm_glue_size);
      s->contents = foo;
    }

  if (globals->thumb_glue_size != 0)
    {
      BFD_ASSERT (globals->bfd_of_glue_owner != NULL);

      s = bfd_get_section_by_name
       (globals->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);

      BFD_ASSERT (s != NULL);

      foo = bfd_alloc (globals->bfd_of_glue_owner, globals->thumb_glue_size);

      BFD_ASSERT (s->size == globals->thumb_glue_size);
      s->contents = foo;
    }
  
  if (globals->vfp11_erratum_glue_size != 0)
    {
      BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
      
      s = bfd_get_section_by_name
        (globals->bfd_of_glue_owner, VFP11_ERRATUM_VENEER_SECTION_NAME);
      
      BFD_ASSERT (s != NULL);
      
      foo = bfd_alloc (globals->bfd_of_glue_owner,
                     globals->vfp11_erratum_glue_size);
      
      BFD_ASSERT (s->size == globals->vfp11_erratum_glue_size);
      s->contents = foo;
    }

  return TRUE;
}

Here is the call graph for this function:

Definition at line 3066 of file elf32-arm.c.

{
  struct elf32_arm_link_hash_table *globals;

  /* If we are only performing a partial link
     do not bother getting a bfd to hold the glue.  */
  if (info->relocatable)
    return TRUE;

  /* Make sure we don't attach the glue sections to a dynamic object.  */
  BFD_ASSERT (!(abfd->flags & DYNAMIC));

  globals = elf32_arm_hash_table (info);

  BFD_ASSERT (globals != NULL);

  if (globals->bfd_of_glue_owner != NULL)
    return TRUE;

  /* Save the bfd for later use.  */
  globals->bfd_of_glue_owner = abfd;

  return TRUE;
}
void bfd_elf32_arm_init_maps ( bfd abfd)

Definition at line 3264 of file elf32-arm.c.

{
  Elf_Internal_Sym *isymbuf;
  Elf_Internal_Shdr *hdr;
  unsigned int i, localsyms;

  if ((abfd->flags & DYNAMIC) != 0)
    return;

  hdr = &elf_tdata (abfd)->symtab_hdr;
  localsyms = hdr->sh_info;

  /* Obtain a buffer full of symbols for this BFD. The hdr->sh_info field
     should contain the number of local symbols, which should come before any
     global symbols.  Mapping symbols are always local.  */
  isymbuf = bfd_elf_get_elf_syms (abfd, hdr, localsyms, 0, NULL, NULL,
                              NULL);

  /* No internal symbols read?  Skip this BFD.  */
  if (isymbuf == NULL)
    return;

  for (i = 0; i < localsyms; i++)
    {
      Elf_Internal_Sym *isym = &isymbuf[i];
      asection *sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
      const char *name;
      
      if (sec != NULL
          && ELF_ST_BIND (isym->st_info) == STB_LOCAL)
        {
          name = bfd_elf_string_from_elf_section (abfd,
            hdr->sh_link, isym->st_name);
          
          if (bfd_is_arm_special_symbol_name (name,
                                         BFD_ARM_SPECIAL_SYM_TYPE_MAP))
            elf32_arm_section_map_add (sec, name[1], isym->st_value);
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3098 of file elf32-arm.c.

{
  Elf_Internal_Shdr *symtab_hdr;
  Elf_Internal_Rela *internal_relocs = NULL;
  Elf_Internal_Rela *irel, *irelend;
  bfd_byte *contents = NULL;

  asection *sec;
  struct elf32_arm_link_hash_table *globals;

  /* If we are only performing a partial link do not bother
     to construct any glue.  */
  if (link_info->relocatable)
    return TRUE;

  /* Here we have a bfd that is to be included on the link.  We have a hook
     to do reloc rummaging, before section sizes are nailed down.  */
  globals = elf32_arm_hash_table (link_info);
  check_use_blx (globals);

  BFD_ASSERT (globals != NULL);
  BFD_ASSERT (globals->bfd_of_glue_owner != NULL);

  if (globals->byteswap_code && !bfd_big_endian (abfd))
    {
      _bfd_error_handler (_("%B: BE8 images only valid in big-endian mode."),
                       abfd);
      return FALSE;
    }

  /* Rummage around all the relocs and map the glue vectors.  */
  sec = abfd->sections;

  if (sec == NULL)
    return TRUE;

  for (; sec != NULL; sec = sec->next)
    {
      if (sec->reloc_count == 0)
       continue;

      if ((sec->flags & SEC_EXCLUDE) != 0)
       continue;

      symtab_hdr = &elf_tdata (abfd)->symtab_hdr;

      /* Load the relocs.  */
      internal_relocs
       = _bfd_elf_link_read_relocs (abfd, sec, (void *) NULL,
                                 (Elf_Internal_Rela *) NULL, FALSE);

      if (internal_relocs == NULL)
       goto error_return;

      irelend = internal_relocs + sec->reloc_count;
      for (irel = internal_relocs; irel < irelend; irel++)
       {
         long r_type;
         unsigned long r_index;

         struct elf_link_hash_entry *h;

         r_type = ELF32_R_TYPE (irel->r_info);
         r_index = ELF32_R_SYM (irel->r_info);

         /* These are the only relocation types we care about.  */
         if (   r_type != R_ARM_PC24
             && r_type != R_ARM_PLT32
             && r_type != R_ARM_CALL
             && r_type != R_ARM_JUMP24
             && r_type != R_ARM_THM_CALL)
           continue;

         /* Get the section contents if we haven't done so already.  */
         if (contents == NULL)
           {
             /* Get cached copy if it exists.  */
             if (elf_section_data (sec)->this_hdr.contents != NULL)
              contents = elf_section_data (sec)->this_hdr.contents;
             else
              {
                /* Go get them off disk.  */
                if (! bfd_malloc_and_get_section (abfd, sec, &contents))
                  goto error_return;
              }
           }

         /* If the relocation is not against a symbol it cannot concern us.  */
         h = NULL;

         /* We don't care about local symbols.  */
         if (r_index < symtab_hdr->sh_info)
           continue;

         /* This is an external symbol.  */
         r_index -= symtab_hdr->sh_info;
         h = (struct elf_link_hash_entry *)
           elf_sym_hashes (abfd)[r_index];

         /* If the relocation is against a static symbol it must be within
            the current section and so cannot be a cross ARM/Thumb relocation.  */
         if (h == NULL)
           continue;

         /* If the call will go through a PLT entry then we do not need
            glue.  */
         if (globals->splt != NULL && h->plt.offset != (bfd_vma) -1)
           continue;

         switch (r_type)
           {
           case R_ARM_PC24:
           case R_ARM_PLT32:
           case R_ARM_CALL:
           case R_ARM_JUMP24:
             /* This one is a call from arm code.  We need to look up
                the target of the call.  If it is a thumb target, we
                insert glue.  */
             if (ELF_ST_TYPE(h->type) == STT_ARM_TFUNC
                && !(r_type == R_ARM_CALL && globals->use_blx))
              record_arm_to_thumb_glue (link_info, h);
             break;

           case R_ARM_THM_CALL:
             /* This one is a call from thumb code.  We look
                up the target of the call.  If it is not a thumb
                 target, we insert glue.  */
             if (ELF_ST_TYPE (h->type) != STT_ARM_TFUNC && !globals->use_blx)
              record_thumb_to_arm_glue (link_info, h);
             break;

           default:
             abort ();
           }
       }

      if (contents != NULL
         && elf_section_data (sec)->this_hdr.contents != contents)
       free (contents);
      contents = NULL;

      if (internal_relocs != NULL
         && elf_section_data (sec)->relocs != internal_relocs)
       free (internal_relocs);
      internal_relocs = NULL;
    }

  return TRUE;

error_return:
  if (contents != NULL
      && elf_section_data (sec)->this_hdr.contents != contents)
    free (contents);
  if (internal_relocs != NULL
      && elf_section_data (sec)->relocs != internal_relocs)
    free (internal_relocs);

  return FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void bfd_elf32_arm_set_byteswap_code ( struct bfd_link_info info,
int  byteswap_code 
)

Definition at line 8869 of file elf32-arm.c.

{
  struct elf32_arm_link_hash_table *globals;

  globals = elf32_arm_hash_table (info);
  globals->byteswap_code = byteswap_code;
}
void bfd_elf32_arm_set_target_relocs ( struct bfd output_bfd,
struct bfd_link_info link_info,
int  target1_is_rel,
char *  target2_type,
int  fix_v4bx,
int  use_blx,
bfd_arm_vfp11_fix  vfp11_fix,
int  no_enum_warn,
int  pic_veneer 
)

Definition at line 3893 of file elf32-arm.c.

{
  struct elf32_arm_link_hash_table *globals;

  globals = elf32_arm_hash_table (link_info);

  globals->target1_is_rel = target1_is_rel;
  if (strcmp (target2_type, "rel") == 0)
    globals->target2_reloc = R_ARM_REL32;
  else if (strcmp (target2_type, "abs") == 0)
    globals->target2_reloc = R_ARM_ABS32;
  else if (strcmp (target2_type, "got-rel") == 0)
    globals->target2_reloc = R_ARM_GOT_PREL;
  else
    {
      _bfd_error_handler (_("Invalid TARGET2 relocation type '%s'."),
                       target2_type);
    }
  globals->fix_v4bx = fix_v4bx;
  globals->use_blx |= use_blx;
  globals->vfp11_fix = vfp11_fix;
  globals->pic_veneer = pic_veneer;

  elf32_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
}

Here is the call graph for this function:

void bfd_elf32_arm_set_vfp11_fix ( bfd obfd,
struct bfd_link_info link_info 
)

Definition at line 3307 of file elf32-arm.c.

{
  struct elf32_arm_link_hash_table *globals = elf32_arm_hash_table (link_info);
  aeabi_attribute *out_attr = elf32_arm_tdata (obfd)->known_eabi_attributes;
  
  /* We assume that ARMv7+ does not need the VFP11 denorm erratum fix.  */
  if (out_attr[Tag_CPU_arch].i >= TAG_CPU_ARCH_V7)
    {
      switch (globals->vfp11_fix)
        {
        case BFD_ARM_VFP11_FIX_DEFAULT:
        case BFD_ARM_VFP11_FIX_NONE:
          globals->vfp11_fix = BFD_ARM_VFP11_FIX_NONE;
          break;
        
        default:
          /* Give a warning, but do as the user requests anyway.  */
          (*_bfd_error_handler) (_("%B: warning: selected VFP11 erratum "
            "workaround is not necessary for target architecture"), obfd);
        }
    }
  else if (globals->vfp11_fix == BFD_ARM_VFP11_FIX_DEFAULT)
    /* For earlier architectures, we might need the workaround, but do not
       enable it by default.  If users is running with broken hardware, they
       must enable the erratum fix explicitly.  */
    globals->vfp11_fix = BFD_ARM_VFP11_FIX_NONE;
}

Definition at line 3605 of file elf32-arm.c.

{
  asection *sec;
  bfd_byte *contents = NULL;
  int state = 0;
  int regs[3], numregs = 0;
  struct elf32_arm_link_hash_table *globals = elf32_arm_hash_table (link_info);
  int use_vector = (globals->vfp11_fix == BFD_ARM_VFP11_FIX_VECTOR);
  
  /* We use a simple FSM to match troublesome VFP11 instruction sequences.
     The states transition as follows:
     
       0 -> 1 (vector) or 0 -> 2 (scalar)
           A VFP FMAC-pipeline instruction has been seen. Fill
           regs[0]..regs[numregs-1] with its input operands. Remember this
           instruction in 'first_fmac'.

       1 -> 2
           Any instruction, except for a VFP instruction which overwrites
           regs[*].
       
       1 -> 3 [ -> 0 ]  or
       2 -> 3 [ -> 0 ]
           A VFP instruction has been seen which overwrites any of regs[*].
           We must make a veneer!  Reset state to 0 before examining next
           instruction.
       
       2 -> 0
           If we fail to match anything in state 2, reset to state 0 and reset
           the instruction pointer to the instruction after 'first_fmac'.

     If the VFP11 vector mode is in use, there must be at least two unrelated
     instructions between anti-dependent VFP11 instructions to properly avoid
     triggering the erratum, hence the use of the extra state 1.
  */

  /* If we are only performing a partial link do not bother
     to construct any glue.  */
  if (link_info->relocatable)
    return TRUE;

  /* We should have chosen a fix type by the time we get here.  */
  BFD_ASSERT (globals->vfp11_fix != BFD_ARM_VFP11_FIX_DEFAULT);

  if (globals->vfp11_fix == BFD_ARM_VFP11_FIX_NONE)
    return TRUE;
  
  for (sec = abfd->sections; sec != NULL; sec = sec->next)
    {
      unsigned int i, span, first_fmac = 0, veneer_of_insn = 0;
      struct _arm_elf_section_data *sec_data;

      /* If we don't have executable progbits, we're not interested in this
         section.  Also skip if section is to be excluded.  */
      if (elf_section_type (sec) != SHT_PROGBITS
          || (elf_section_flags (sec) & SHF_EXECINSTR) == 0
          || (sec->flags & SEC_EXCLUDE) != 0
          || strcmp (sec->name, VFP11_ERRATUM_VENEER_SECTION_NAME) == 0)
        continue;

      sec_data = elf32_arm_section_data (sec);
      
      if (sec_data->mapcount == 0)
        continue;
      
      if (elf_section_data (sec)->this_hdr.contents != NULL)
       contents = elf_section_data (sec)->this_hdr.contents;
      else if (! bfd_malloc_and_get_section (abfd, sec, &contents))
       goto error_return;

      qsort (sec_data->map, sec_data->mapcount, sizeof (elf32_arm_section_map),
            elf32_arm_compare_mapping);

      for (span = 0; span < sec_data->mapcount; span++)
        {
          unsigned int span_start = sec_data->map[span].vma;
          unsigned int span_end = (span == sec_data->mapcount - 1)
                              ? sec->size : sec_data->map[span + 1].vma;
          char span_type = sec_data->map[span].type;
          
          /* FIXME: Only ARM mode is supported at present.  We may need to
             support Thumb-2 mode also at some point.  */
          if (span_type != 'a')
            continue;

          for (i = span_start; i < span_end;)
            {
              unsigned int next_i = i + 4;
              unsigned int insn = bfd_big_endian (abfd)
                ? (contents[i] << 24)
                  | (contents[i + 1] << 16)
                  | (contents[i + 2] << 8)
                  | contents[i + 3]
                : (contents[i + 3] << 24)
                  | (contents[i + 2] << 16)
                  | (contents[i + 1] << 8)
                  | contents[i];
              unsigned int writemask = 0;
              enum bfd_arm_vfp11_pipe pipe;

              switch (state)
                {
                case 0:
                  pipe = bfd_arm_vfp11_insn_decode (insn, &writemask, regs,
                                                    &numregs);
                  /* I'm assuming the VFP11 erratum can trigger with denorm
                     operands on either the FMAC or the DS pipeline. This might
                     lead to slightly overenthusiastic veneer insertion.  */
                  if (pipe == VFP11_FMAC || pipe == VFP11_DS)
                    {
                      state = use_vector ? 1 : 2;
                      first_fmac = i;
                      veneer_of_insn = insn;
                    }
                  break;

                case 1:
                  {
                    int other_regs[3], other_numregs;
                    pipe = bfd_arm_vfp11_insn_decode (insn, &writemask,
                                                other_regs,
                                                      &other_numregs);
                    if (pipe != VFP11_BAD
                        && bfd_arm_vfp11_antidependency (writemask, regs,
                                                  numregs))
                      state = 3;
                    else
                      state = 2;
                  }
                  break;

                case 2:
                  {
                    int other_regs[3], other_numregs;
                    pipe = bfd_arm_vfp11_insn_decode (insn, &writemask,
                                                other_regs,
                                                      &other_numregs);
                    if (pipe != VFP11_BAD
                        && bfd_arm_vfp11_antidependency (writemask, regs,
                                                  numregs))
                      state = 3;
                    else
                      {
                        state = 0;
                        next_i = first_fmac + 4;
                      }
                  }
                  break;

                case 3:
                  abort ();  /* Should be unreachable.  */
                }

              if (state == 3)
                {
                  elf32_vfp11_erratum_list *newerr
                    = bfd_zmalloc (sizeof (elf32_vfp11_erratum_list));
                  int errcount;

                  errcount = ++(elf32_arm_section_data (sec)->erratumcount);

                  newerr->u.b.vfp_insn = veneer_of_insn;

                  switch (span_type)
                    {
                    case 'a':
                      newerr->type = VFP11_ERRATUM_BRANCH_TO_ARM_VENEER;
                      break;
                    
                    default:
                      abort ();
                    }

                  record_vfp11_erratum_veneer (link_info, newerr, abfd, sec,
                                          first_fmac);

                  newerr->vma = -1;

                  newerr->next = sec_data->erratumlist;
                  sec_data->erratumlist = newerr;

                  state = 0;
                }

              i = next_i;
            }
        }
      
      if (contents != NULL
          && elf_section_data (sec)->this_hdr.contents != contents)
        free (contents);
      contents = NULL;
    }

  return TRUE;

error_return:
  if (contents != NULL
      && elf_section_data (sec)->this_hdr.contents != contents)
    free (contents);
  
  return FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3813 of file elf32-arm.c.

{
  asection *sec;
  struct elf32_arm_link_hash_table *globals;
  char *tmp_name;
  
  if (link_info->relocatable)
    return;
  
  globals = elf32_arm_hash_table (link_info);
  
  tmp_name = bfd_malloc ((bfd_size_type) strlen
                        (VFP11_ERRATUM_VENEER_ENTRY_NAME) + 10);

  for (sec = abfd->sections; sec != NULL; sec = sec->next)
    {
      struct _arm_elf_section_data *sec_data = elf32_arm_section_data (sec);
      elf32_vfp11_erratum_list *errnode = sec_data->erratumlist;
      
      for (; errnode != NULL; errnode = errnode->next)
        {
          struct elf_link_hash_entry *myh;
          bfd_vma vma;

          switch (errnode->type)
            {
            case VFP11_ERRATUM_BRANCH_TO_ARM_VENEER:
            case VFP11_ERRATUM_BRANCH_TO_THUMB_VENEER:
              /* Find veneer symbol.  */
              sprintf (tmp_name, VFP11_ERRATUM_VENEER_ENTRY_NAME,
                     errnode->u.b.veneer->u.v.id);

              myh = elf_link_hash_lookup
                (&(globals)->root, tmp_name, FALSE, FALSE, TRUE);

              if (myh == NULL)
                (*_bfd_error_handler) (_("%B: unable to find VFP11 veneer "
                                    "`%s'"), abfd, tmp_name);

              vma = myh->root.u.def.section->output_section->vma
                    + myh->root.u.def.section->output_offset
                    + myh->root.u.def.value;

              errnode->u.b.veneer->vma = vma;
              break;

           case VFP11_ERRATUM_ARM_VENEER:
            case VFP11_ERRATUM_THUMB_VENEER:
              /* Find return location.  */
              sprintf (tmp_name, VFP11_ERRATUM_VENEER_ENTRY_NAME "_r",
                       errnode->u.v.id);

              myh = elf_link_hash_lookup
                (&(globals)->root, tmp_name, FALSE, FALSE, TRUE);

              if (myh == NULL)
                (*_bfd_error_handler) (_("%B: unable to find VFP11 veneer "
                                    "`%s'"), abfd, tmp_name);

              vma = myh->root.u.def.section->output_section->vma
                    + myh->root.u.def.section->output_offset
                    + myh->root.u.def.value;

              errnode->u.v.branch->vma = vma;
              break;
            
            default:
              abort ();
            }
        }
    }
  
  free (tmp_name);
}

Here is the call graph for this function:

static bfd_vma calculate_group_reloc_mask ( bfd_vma  value,
int  n,
bfd_vma final_residual 
) [static]

Definition at line 4395 of file elf32-arm.c.

{
  int current_n;
  bfd_vma g_n;
  bfd_vma encoded_g_n = 0;
  bfd_vma residual = value; /* Also known as Y_n.  */

  for (current_n = 0; current_n <= n; current_n++)
    {
      int shift;

      /* Calculate which part of the value to mask.  */
      if (residual == 0)
        shift = 0;
      else
        {
          int msb;

          /* Determine the most significant bit in the residual and
             align the resulting value to a 2-bit boundary.  */
          for (msb = 30; msb >= 0; msb -= 2)
            if (residual & (3 << msb))
              break;

          /* The desired shift is now (msb - 6), or zero, whichever
             is the greater.  */
          shift = msb - 6;
          if (shift < 0)
            shift = 0;
        }

      /* Calculate g_n in 32-bit as well as encoded constant+rotation form.  */
      g_n = residual & (0xff << shift);
      encoded_g_n = (g_n >> shift)
                    | ((g_n <= 0xff ? 0 : (32 - shift) / 2) << 8);

      /* Calculate the residual for the next time around.  */
      residual &= ~g_n;
    }

  *final_residual = residual;

  return encoded_g_n;
}

Here is the caller graph for this function:

static void check_use_blx ( struct elf32_arm_link_hash_table globals) [static]

Definition at line 3091 of file elf32-arm.c.

{
  if (elf32_arm_get_eabi_attr_int (globals->obfd, Tag_CPU_arch) > 2)
    globals->use_blx = 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void copy_eabi_attributes ( bfd ibfd,
bfd obfd 
) [static]

Definition at line 6941 of file elf32-arm.c.

{
  aeabi_attribute *in_attr;
  aeabi_attribute *out_attr;
  aeabi_attribute_list *list;
  int i;

  in_attr = &elf32_arm_tdata (ibfd)->known_eabi_attributes[4];
  out_attr = &elf32_arm_tdata (obfd)->known_eabi_attributes[4];
  for (i = 4; i < NUM_KNOWN_ATTRIBUTES; i++)
    {
      out_attr->i = in_attr->i;
      if (in_attr->s && *in_attr->s)
       out_attr->s = attr_strdup (obfd, in_attr->s);
      in_attr++;
      out_attr++;
    }

  for (list = elf32_arm_tdata (ibfd)->other_eabi_attributes;
       list;
       list = list->next)
    {
      in_attr = &list->attr;
      switch (in_attr->type)
       {
       case 1:
         elf32_arm_add_eabi_attr_int (obfd, list->tag, in_attr->i);
         break;
       case 2:
         elf32_arm_add_eabi_attr_string (obfd, list->tag, in_attr->s);
         break;
       case 3:
         elf32_arm_add_eabi_attr_compat (obfd, in_attr->i, in_attr->s);
         break;
       default:
         abort();
       }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean create_got_section ( bfd dynobj,
struct bfd_link_info info 
) [static]

Definition at line 2312 of file elf32-arm.c.

{
  struct elf32_arm_link_hash_table *htab;

  htab = elf32_arm_hash_table (info);
  /* BPABI objects never have a GOT, or associated sections.  */
  if (htab->symbian_p)
    return TRUE;

  if (! _bfd_elf_create_got_section (dynobj, info))
    return FALSE;

  htab->sgot = bfd_get_section_by_name (dynobj, ".got");
  htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
  if (!htab->sgot || !htab->sgotplt)
    abort ();

  htab->srelgot = bfd_make_section_with_flags (dynobj,
                                          RELOC_SECTION (htab, ".got"),
                                          (SEC_ALLOC | SEC_LOAD
                                          | SEC_HAS_CONTENTS
                                          | SEC_IN_MEMORY
                                          | SEC_LINKER_CREATED
                                          | SEC_READONLY));
  if (htab->srelgot == NULL
      || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2))
    return FALSE;
  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_vma dtpoff_base ( struct bfd_link_info info) [static]

Definition at line 4350 of file elf32-arm.c.

{
  /* If tls_sec is NULL, we should have signalled an error already.  */
  if (elf_hash_table (info)->tls_sec == NULL)
    return 0;
  return elf_hash_table (info)->tls_sec->vma;
}

Here is the caller graph for this function:

static bfd_vma eabi_attr_size ( int  tag,
aeabi_attribute attr 
) [static]

Definition at line 6271 of file elf32-arm.c.

{
  bfd_vma size;

  if (is_default_attr (attr))
    return 0;

  size = uleb128_size (tag);
  if (attr->type & 1)
    size += uleb128_size (attr->i);
  if (attr->type & 2)
    size += strlen ((char *)attr->s) + 1;
  return size;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_reloc_status_type elf32_arm_abs12_reloc ( bfd abfd,
void *  data,
bfd_vma  value 
) [static]

Definition at line 4378 of file elf32-arm.c.

{
  if (value > 0xfff)
    return bfd_reloc_overflow;

  value |= bfd_get_32 (abfd, data) & 0xfffff000;
  bfd_put_32 (abfd, value, data);
  return bfd_reloc_ok;
}

Here is the caller graph for this function:

void elf32_arm_add_eabi_attr_compat ( bfd abfd,
unsigned int  i,
const char *  s 
)

Definition at line 6860 of file elf32-arm.c.

{
  aeabi_attribute_list *list;
  aeabi_attribute_list *p;
  aeabi_attribute_list **lastp;

  list = (aeabi_attribute_list *)
    bfd_alloc (abfd, sizeof (aeabi_attribute_list));
  memset (list, 0, sizeof (aeabi_attribute_list));
  list->tag = Tag_compatibility;
  list->attr.type = 3;
  list->attr.i = i;
  list->attr.s = attr_strdup (abfd, s);

  lastp = &elf32_arm_tdata (abfd)->other_eabi_attributes;
  for (p = *lastp; p; p = p->next)
    {
      int cmp;
      if (p->tag != Tag_compatibility)
       break;
      cmp = strcmp(s, p->attr.s);
      if (cmp < 0 || (cmp == 0 && i < p->attr.i))
       break;
      lastp = &p->next;
    }
  list->next = *lastp;
  *lastp = list;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void elf32_arm_add_eabi_attr_int ( bfd abfd,
int  tag,
unsigned int  i 
)

Definition at line 6829 of file elf32-arm.c.

{
  aeabi_attribute *attr;

  attr = elf32_arm_new_eabi_attr (abfd, tag);
  attr->type = 1;
  attr->i = i;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void elf32_arm_add_eabi_attr_string ( bfd abfd,
int  tag,
const char *  s 
)

Definition at line 6850 of file elf32-arm.c.

{
  aeabi_attribute *attr;

  attr = elf32_arm_new_eabi_attr (abfd, tag);
  attr->type = 2;
  attr->s = attr_strdup (abfd, s);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int elf32_arm_additional_program_headers ( bfd abfd,
struct bfd_link_info *info  ATTRIBUTE_UNUSED 
) [static]

Definition at line 10548 of file elf32-arm.c.

{
  asection *sec;

  sec = bfd_get_section_by_name (abfd, ".ARM.exidx");
  if (sec != NULL && (sec->flags & SEC_LOAD) != 0)
    return 1;
  else
    return 0;
}

Here is the call graph for this function:

Definition at line 8376 of file elf32-arm.c.

{
  bfd * dynobj;
  asection * s;
  unsigned int power_of_two;
  struct elf32_arm_link_hash_entry * eh;
  struct elf32_arm_link_hash_table *globals;

  globals = elf32_arm_hash_table (info);
  dynobj = elf_hash_table (info)->dynobj;

  /* Make sure we know what is going on here.  */
  BFD_ASSERT (dynobj != NULL
             && (h->needs_plt
                || h->u.weakdef != NULL
                || (h->def_dynamic
                    && h->ref_regular
                    && !h->def_regular)));

  eh = (struct elf32_arm_link_hash_entry *) h;

  /* If this is a function, put it in the procedure linkage table.  We
     will fill in the contents of the procedure linkage table later,
     when we know the address of the .got section.  */
  if (h->type == STT_FUNC || h->type == STT_ARM_TFUNC
      || h->needs_plt)
    {
      if (h->plt.refcount <= 0
         || SYMBOL_CALLS_LOCAL (info, h)
         || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
             && h->root.type == bfd_link_hash_undefweak))
       {
         /* This case can occur if we saw a PLT32 reloc in an input
            file, but the symbol was never referred to by a dynamic
            object, or if all references were garbage collected.  In
            such a case, we don't actually need to build a procedure
            linkage table, and we can just do a PC24 reloc instead.  */
         h->plt.offset = (bfd_vma) -1;
         eh->plt_thumb_refcount = 0;
         h->needs_plt = 0;
       }

      return TRUE;
    }
  else
    {
      /* It's possible that we incorrectly decided a .plt reloc was
        needed for an R_ARM_PC24 or similar reloc to a non-function sym
        in check_relocs.  We can't decide accurately between function
        and non-function syms in check-relocs; Objects loaded later in
        the link may change h->type.  So fix it now.  */
      h->plt.offset = (bfd_vma) -1;
      eh->plt_thumb_refcount = 0;
    }

  /* If this is a weak symbol, and there is a real definition, the
     processor independent code will have arranged for us to see the
     real definition first, and we can just use the same value.  */
  if (h->u.weakdef != NULL)
    {
      BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
                || h->u.weakdef->root.type == bfd_link_hash_defweak);
      h->root.u.def.section = h->u.weakdef->root.u.def.section;
      h->root.u.def.value = h->u.weakdef->root.u.def.value;
      return TRUE;
    }

  /* If there are no non-GOT references, we do not need a copy
     relocation.  */
  if (!h->non_got_ref)
    return TRUE;

  /* This is a reference to a symbol defined by a dynamic object which
     is not a function.  */

  /* If we are creating a shared library, we must presume that the
     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.  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)
    return TRUE;

  if (h->size == 0)
    {
      (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
                          h->root.root.string);
      return TRUE;
    }

  /* We must allocate the symbol in our .dynbss section, which will
     become part of the .bss section of the executable.  There will be
     an entry for this symbol in the .dynsym section.  The dynamic
     object will contain position independent code, so all references
     from the dynamic object to this symbol will go through the global
     offset table.  The dynamic linker will use the .dynsym entry to
     determine the address it must put in the global offset table, so
     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");
  BFD_ASSERT (s != NULL);

  /* We must generate a R_ARM_COPY reloc to tell the dynamic linker to
     copy the initial value out of the dynamic object and into the
     runtime process image.  We need to remember the offset into the
     .rel(a).bss section we are going to use.  */
  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
    {
      asection *srel;

      srel = bfd_get_section_by_name (dynobj, RELOC_SECTION (globals, ".bss"));
      BFD_ASSERT (srel != NULL);
      srel->size += RELOC_SIZE (globals);
      h->needs_copy = 1;
    }

  /* We need to figure out the alignment required for this symbol.  I
     have no idea how ELF linkers handle this.  */
  power_of_two = bfd_log2 (h->size);
  if (power_of_two > 3)
    power_of_two = 3;

  /* Apply the required alignment.  */
  s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
  if (power_of_two > bfd_get_section_alignment (dynobj, s))
    {
      if (! bfd_set_section_alignment (dynobj, s, power_of_two))
       return FALSE;
    }

  /* Define the symbol as being at this point in the section.  */
  h->root.u.def.section = s;
  h->root.u.def.value = s->size;

  /* Increment the section size to make room for the symbol.  */
  s->size += h->size;

  return TRUE;
}

Here is the call graph for this function:

static void elf32_arm_begin_write_processing ( bfd *abfd  ATTRIBUTE_UNUSED,
struct bfd_link_info link_info 
) [static]

Definition at line 4305 of file elf32-arm.c.

{
  struct elf32_arm_link_hash_table * globals;

  if (!link_info)
    return;

  globals = elf32_arm_hash_table (link_info);
  /* If blx is available then exported Thumb symbols are OK and there is
     nothing to do.  */
  if (globals->use_blx)
    return;

  elf_link_hash_traverse (&globals->root, elf32_arm_to_thumb_export_stub,
                       link_info);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean elf32_arm_bfd_final_link ( bfd abfd,
struct bfd_link_info info 
) [static]

Definition at line 6380 of file elf32-arm.c.

{
  asection *o;
  struct bfd_link_order *p;
  asection *attr_section = NULL;
  bfd_byte *contents;
  bfd_vma size = 0;

  /* elf32_arm_merge_private_bfd_data will already have merged the
     object attributes.  Remove the input sections from the link, and set
     the contents of the output secton.  */
  for (o = abfd->sections; o != NULL; o = o->next)
    {
      if (strcmp (o->name, ".ARM.attributes") == 0)
       {
         for (p = o->map_head.link_order; p != NULL; p = p->next)
           {
             asection *input_section;

             if (p->type != bfd_indirect_link_order)
              continue;
             input_section = p->u.indirect.section;
             /* Hack: reset the SEC_HAS_CONTENTS flag so that
               elf_link_input_bfd ignores this section.  */
             input_section->flags &= ~SEC_HAS_CONTENTS;
           }
           
         size = elf32_arm_eabi_attr_size (abfd);
         bfd_set_section_size (abfd, o, size);
         attr_section = o;
         /* Skip this section later on.  */
         o->map_head.link_order = NULL;
       }
    }
  /* Invoke the ELF linker to do all the work.  */
  if (!bfd_elf_final_link (abfd, info))
    return FALSE;

  if (attr_section)
    {
      contents = bfd_malloc(size);
      if (contents == NULL)
       return FALSE;
      elf32_arm_set_eabi_attr_contents (abfd, contents, size);
      bfd_set_section_contents (abfd, attr_section, contents, 0, size);
      free (contents);
    }
  return TRUE;
}

Here is the call graph for this function:

static bfd_boolean elf32_arm_bfd_free_cached_info ( bfd abfd) [static]

Definition at line 10428 of file elf32-arm.c.

Here is the call graph for this function:

static bfd_boolean elf32_arm_check_relocs ( bfd abfd,
struct bfd_link_info info,
asection sec,
const Elf_Internal_Rela relocs 
) [static]

Definition at line 7864 of file elf32-arm.c.

{
  Elf_Internal_Shdr *symtab_hdr;
  struct elf_link_hash_entry **sym_hashes;
  struct elf_link_hash_entry **sym_hashes_end;
  const Elf_Internal_Rela *rel;
  const Elf_Internal_Rela *rel_end;
  bfd *dynobj;
  asection *sreloc;
  bfd_vma *local_got_offsets;
  struct elf32_arm_link_hash_table *htab;

  if (info->relocatable)
    return TRUE;

  htab = elf32_arm_hash_table (info);
  sreloc = NULL;

  /* Create dynamic sections for relocatable executables so that we can
     copy relocations.  */
  if (htab->root.is_relocatable_executable
      && ! htab->root.dynamic_sections_created)
    {
      if (! _bfd_elf_link_create_dynamic_sections (abfd, info))
       return FALSE;
    }

  dynobj = elf_hash_table (info)->dynobj;
  local_got_offsets = elf_local_got_offsets (abfd);

  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_end = relocs + sec->reloc_count;
  for (rel = relocs; rel < rel_end; rel++)
    {
      struct elf_link_hash_entry *h;
      struct elf32_arm_link_hash_entry *eh;
      unsigned long r_symndx;
      int r_type;

      r_symndx = ELF32_R_SYM (rel->r_info);
      r_type = ELF32_R_TYPE (rel->r_info);
      r_type = arm_real_reloc_type (htab, r_type);

      if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
       {
         (*_bfd_error_handler) (_("%B: bad symbol index: %d"), abfd,
                             r_symndx);
         return FALSE;
       }

      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;
       }

      eh = (struct elf32_arm_link_hash_entry *) h;

      switch (r_type)
        {
         case R_ARM_GOT32:
         case R_ARM_GOT_PREL:
         case R_ARM_TLS_GD32:
         case R_ARM_TLS_IE32:
           /* This symbol requires a global offset table entry.  */
           {
             int tls_type, old_tls_type;

             switch (r_type)
              {
              case R_ARM_TLS_GD32: tls_type = GOT_TLS_GD; break;
              case R_ARM_TLS_IE32: tls_type = GOT_TLS_IE; break;
              default: tls_type = GOT_NORMAL; break;
              }

             if (h != NULL)
              {
                h->got.refcount++;
                old_tls_type = elf32_arm_hash_entry (h)->tls_type;
              }
             else
              {
                bfd_signed_vma *local_got_refcounts;

                /* This is a global offset table entry for a local symbol.  */
                local_got_refcounts = elf_local_got_refcounts (abfd);
                if (local_got_refcounts == NULL)
                  {
                    bfd_size_type size;
                    
                    size = symtab_hdr->sh_info;
                    size *= (sizeof (bfd_signed_vma) + sizeof(char));
                    local_got_refcounts = bfd_zalloc (abfd, size);
                    if (local_got_refcounts == NULL)
                     return FALSE;
                    elf_local_got_refcounts (abfd) = local_got_refcounts;
                    elf32_arm_local_got_tls_type (abfd)
                     = (char *) (local_got_refcounts + symtab_hdr->sh_info);
                  }
                local_got_refcounts[r_symndx] += 1;
                old_tls_type = elf32_arm_local_got_tls_type (abfd) [r_symndx];
              }

             /* We will already have issued an error message if there is a
               TLS / non-TLS mismatch, based on the symbol type.  We don't
               support any linker relaxations.  So just combine any TLS
               types needed.  */
             if (old_tls_type != GOT_UNKNOWN && old_tls_type != GOT_NORMAL
                && tls_type != GOT_NORMAL)
              tls_type |= old_tls_type;

             if (old_tls_type != tls_type)
              {
                if (h != NULL)
                  elf32_arm_hash_entry (h)->tls_type = tls_type;
                else
                  elf32_arm_local_got_tls_type (abfd) [r_symndx] = tls_type;
              }
           }
           /* Fall through */

         case R_ARM_TLS_LDM32:
           if (r_type == R_ARM_TLS_LDM32)
              htab->tls_ldm_got.refcount++;
           /* Fall through */

         case R_ARM_GOTOFF32:
         case R_ARM_GOTPC:
           if (htab->sgot == NULL)
             {
              if (htab->root.dynobj == NULL)
                htab->root.dynobj = abfd;
              if (!create_got_section (htab->root.dynobj, info))
                return FALSE;
             }
           break;

         case R_ARM_ABS12:
           /* VxWorks uses dynamic R_ARM_ABS12 relocations for
              ldr __GOTT_INDEX__ offsets.  */
           if (!htab->vxworks_p)
             break;
           /* Fall through */

         case R_ARM_ABS32:
         case R_ARM_ABS32_NOI:
         case R_ARM_REL32:
         case R_ARM_REL32_NOI:
         case R_ARM_PC24:
         case R_ARM_PLT32:
         case R_ARM_CALL:
         case R_ARM_JUMP24:
         case R_ARM_PREL31:
         case R_ARM_THM_CALL:
         case R_ARM_MOVW_ABS_NC:
         case R_ARM_MOVT_ABS:
         case R_ARM_MOVW_PREL_NC:
         case R_ARM_MOVT_PREL:
         case R_ARM_THM_MOVW_ABS_NC:
         case R_ARM_THM_MOVT_ABS:
         case R_ARM_THM_MOVW_PREL_NC:
         case R_ARM_THM_MOVT_PREL:
           /* Should the interworking branches be listed here?  */
           if (h != NULL)
             {
              /* If this reloc is in a read-only section, we might
                 need a copy reloc.  We can't check reliably at this
                 stage whether the section is read-only, as input
                 sections have not yet been mapped to output sections.
                 Tentatively set the flag for now, and correct in
                 adjust_dynamic_symbol.  */
              if (!info->shared)
                h->non_got_ref = 1;

              /* We may need a .plt entry if the function this reloc
                 refers to is in a different object.  We can't tell for
                 sure yet, because something later might force the
                 symbol local.  */
              if (r_type != R_ARM_ABS32
                    && r_type != R_ARM_REL32
                    && r_type != R_ARM_ABS32_NOI
                    && r_type != R_ARM_REL32_NOI)
                h->needs_plt = 1;

              /* If we create a PLT entry, this relocation will reference
                 it, even if it's an ABS32 relocation.  */
              h->plt.refcount += 1;

              if (r_type == R_ARM_THM_CALL)
                eh->plt_thumb_refcount += 1;
             }

           /* If we are creating a shared library or relocatable executable,
              and this is a reloc against a global symbol, or a non PC
              relative reloc against a local symbol, then we need to copy
              the reloc into the shared library.  However, if we are linking
              with -Bsymbolic, we do not need to copy a reloc against a
               global symbol which is defined in an object we are
               including in the link (i.e., DEF_REGULAR is set).  At
               this point we have not seen all the input files, so it is
               possible that DEF_REGULAR is not set now but will be set
               later (it is never cleared).  We account for that
               possibility below by storing information in the
               relocs_copied field of the hash table entry.  */
           if ((info->shared || htab->root.is_relocatable_executable)
              && (sec->flags & SEC_ALLOC) != 0
              && ((r_type == R_ARM_ABS32 || r_type == R_ARM_ABS32_NOI)
                  || (h != NULL && ! h->needs_plt
                     && (! info->symbolic || ! h->def_regular))))
             {
              struct elf32_arm_relocs_copied *p, **head;

               /* When creating a shared object, we must copy these
                   reloc types into the output file.  We create a reloc
                   section in dynobj and make room for this reloc.  */
               if (sreloc == NULL)
                {
                  const char * name;

                  name = (bfd_elf_string_from_elf_section
                         (abfd,
                          elf_elfheader (abfd)->e_shstrndx,
                          elf_section_data (sec)->rel_hdr.sh_name));
                  if (name == NULL)
                    return FALSE;

                  BFD_ASSERT (reloc_section_p (htab, name, sec));

                  sreloc = bfd_get_section_by_name (dynobj, name);
                  if (sreloc == NULL)
                    {
                      flagword flags;

                      flags = (SEC_HAS_CONTENTS | SEC_READONLY
                              | SEC_IN_MEMORY | SEC_LINKER_CREATED);
                      if ((sec->flags & SEC_ALLOC) != 0
                         /* BPABI objects never have dynamic
                            relocations mapped.  */
                         && !htab->symbian_p)
                       flags |= SEC_ALLOC | SEC_LOAD;
                      sreloc = bfd_make_section_with_flags (dynobj,
                                                       name,
                                                       flags);
                      if (sreloc == NULL
                         || ! bfd_set_section_alignment (dynobj, sreloc, 2))
                       return FALSE;
                    }

                  elf_section_data (sec)->sreloc = sreloc;
                }

              /* If this is a global symbol, we count the number of
                 relocations we need for this symbol.  */
              if (h != NULL)
                {
                  head = &((struct elf32_arm_link_hash_entry *) h)->relocs_copied;
                }
              else
                {
                  /* Track dynamic relocs needed for local syms too.
                     We really need local syms available to do this
                     easily.  Oh well.  */

                  asection *s;
                  void *vpp;

                  s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
                                             sec, r_symndx);
                  if (s == NULL)
                    return FALSE;

                  vpp = &elf_section_data (s)->local_dynrel;
                  head = (struct elf32_arm_relocs_copied **) vpp;
                }

              p = *head;
              if (p == NULL || p->section != sec)
                {
                  bfd_size_type amt = sizeof *p;

                  p = bfd_alloc (htab->root.dynobj, amt);
                  if (p == NULL)
                    return FALSE;
                  p->next = *head;
                  *head = p;
                  p->section = sec;
                  p->count = 0;
                  p->pc_count = 0;
                }

              if (r_type == R_ARM_REL32 || r_type == R_ARM_REL32_NOI)
                p->pc_count += 1;
              p->count += 1;
             }
           break;

        /* This relocation describes the C++ object vtable hierarchy.
           Reconstruct it for later use during GC.  */
        case R_ARM_GNU_VTINHERIT:
          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
            return FALSE;
          break;

        /* This relocation describes which C++ vtable entries are actually
           used.  Record for later use during GC.  */
        case R_ARM_GNU_VTENTRY:
          if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
            return FALSE;
          break;
        }
    }

  return TRUE;
}

Here is the call graph for this function:

static bfd_boolean elf32_arm_close_and_cleanup ( bfd abfd) [static]

Definition at line 10417 of file elf32-arm.c.

Here is the call graph for this function:

static int elf32_arm_compare_mapping ( const void *  a,
const void *  b 
) [static]

Definition at line 10238 of file elf32-arm.c.

{
  return ((const elf32_arm_section_map *) a)->vma
        > ((const elf32_arm_section_map *) b)->vma;
}

Here is the caller graph for this function:

Definition at line 2398 of file elf32-arm.c.

{
  struct elf32_arm_link_hash_entry *edir, *eind;

  edir = (struct elf32_arm_link_hash_entry *) dir;
  eind = (struct elf32_arm_link_hash_entry *) ind;

  if (eind->relocs_copied != NULL)
    {
      if (edir->relocs_copied != NULL)
       {
         struct elf32_arm_relocs_copied **pp;
         struct elf32_arm_relocs_copied *p;

         /* Add reloc counts against the indirect sym to the direct sym
            list.  Merge any entries against the same section.  */
         for (pp = &eind->relocs_copied; (p = *pp) != NULL; )
           {
             struct elf32_arm_relocs_copied *q;

             for (q = edir->relocs_copied; q != NULL; q = q->next)
              if (q->section == p->section)
                {
                  q->pc_count += p->pc_count;
                  q->count += p->count;
                  *pp = p->next;
                  break;
                }
             if (q == NULL)
              pp = &p->next;
           }
         *pp = edir->relocs_copied;
       }

      edir->relocs_copied = eind->relocs_copied;
      eind->relocs_copied = NULL;
    }

  if (ind->root.type == bfd_link_hash_indirect)
    {
      /* Copy over PLT info.  */
      edir->plt_thumb_refcount += eind->plt_thumb_refcount;
      eind->plt_thumb_refcount = 0;

      if (dir->got.refcount <= 0)
       {
         edir->tls_type = eind->tls_type;
         eind->tls_type = GOT_UNKNOWN;
       }
    }

  _bfd_elf_link_hash_copy_indirect (info, dir, ind);
}

Here is the call graph for this function:

static bfd_boolean elf32_arm_copy_private_bfd_data ( bfd ibfd,
bfd obfd 
) [static]

Definition at line 6985 of file elf32-arm.c.

{
  flagword in_flags;
  flagword out_flags;

  if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
    return TRUE;

  in_flags  = elf_elfheader (ibfd)->e_flags;
  out_flags = elf_elfheader (obfd)->e_flags;

  if (elf_flags_init (obfd)
      && EF_ARM_EABI_VERSION (out_flags) == EF_ARM_EABI_UNKNOWN
      && in_flags != out_flags)
    {
      /* Cannot mix APCS26 and APCS32 code.  */
      if ((in_flags & EF_ARM_APCS_26) != (out_flags & EF_ARM_APCS_26))
       return FALSE;

      /* Cannot mix float APCS and non-float APCS code.  */
      if ((in_flags & EF_ARM_APCS_FLOAT) != (out_flags & EF_ARM_APCS_FLOAT))
       return FALSE;

      /* If the src and dest have different interworking flags
         then turn off the interworking bit.  */
      if ((in_flags & EF_ARM_INTERWORK) != (out_flags & EF_ARM_INTERWORK))
       {
         if (out_flags & EF_ARM_INTERWORK)
           _bfd_error_handler
             (_("Warning: Clearing the interworking flag of %B because non-interworking code in %B has been linked with it"),
              obfd, ibfd);

         in_flags &= ~EF_ARM_INTERWORK;
       }

      /* Likewise for PIC, though don't warn for this case.  */
      if ((in_flags & EF_ARM_PIC) != (out_flags & EF_ARM_PIC))
       in_flags &= ~EF_ARM_PIC;
    }

  elf_elfheader (obfd)->e_flags = in_flags;
  elf_flags_init (obfd) = TRUE;

  /* Also copy the EI_OSABI field.  */
  elf_elfheader (obfd)->e_ident[EI_OSABI] =
    elf_elfheader (ibfd)->e_ident[EI_OSABI];

  /* Copy EABI object attributes.  */
  copy_eabi_attributes (ibfd, obfd);

  return TRUE;
}

Here is the call graph for this function:

static bfd_boolean elf32_arm_create_dynamic_sections ( bfd dynobj,
struct bfd_link_info info 
) [static]

Definition at line 2347 of file elf32-arm.c.

{
  struct elf32_arm_link_hash_table *htab;

  htab = elf32_arm_hash_table (info);
  if (!htab->sgot && !create_got_section (dynobj, info))
    return FALSE;

  if (!_bfd_elf_create_dynamic_sections (dynobj, info))
    return FALSE;

  htab->splt = bfd_get_section_by_name (dynobj, ".plt");
  htab->srelplt = bfd_get_section_by_name (dynobj,
                                      RELOC_SECTION (htab, ".plt"));
  htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
  if (!info->shared)
    htab->srelbss = bfd_get_section_by_name (dynobj,
                                        RELOC_SECTION (htab, ".bss"));

  if (htab->vxworks_p)
    {
      if (!elf_vxworks_create_dynamic_sections (dynobj, info, &htab->srelplt2))
       return FALSE;

      if (info->shared)
       {
         htab->plt_header_size = 0;
         htab->plt_entry_size
           = 4 * ARRAY_SIZE (elf32_arm_vxworks_shared_plt_entry);
       }
      else
       {
         htab->plt_header_size
           = 4 * ARRAY_SIZE (elf32_arm_vxworks_exec_plt0_entry);
         htab->plt_entry_size
           = 4 * ARRAY_SIZE (elf32_arm_vxworks_exec_plt_entry);
       }
    }

  if (!htab->splt 
      || !htab->srelplt
      || !htab->sdynbss
      || (!info->shared && !htab->srelbss))
    abort ();

  return TRUE;
}

Here is the call graph for this function:

static struct elf_link_hash_entry* elf32_arm_create_thumb_stub ( struct bfd_link_info info,
const char *  name,
bfd input_bfd,
bfd output_bfd,
asection sym_sec,
bfd_vma  val,
asection s,
char **  error_message 
) [static, read]

Definition at line 4120 of file elf32-arm.c.

{
  bfd_vma my_offset;
  long int ret_offset;
  struct elf_link_hash_entry * myh;
  struct elf32_arm_link_hash_table * globals;

  myh = find_arm_glue (info, name, error_message);
  if (myh == NULL)
    return NULL;

  globals = elf32_arm_hash_table (info);

  BFD_ASSERT (globals != NULL);
  BFD_ASSERT (globals->bfd_of_glue_owner != NULL);

  my_offset = myh->root.u.def.value;

  if ((my_offset & 0x01) == 0x01)
    {
      if (sym_sec != NULL
         && sym_sec->owner != NULL
         && !INTERWORK_FLAG (sym_sec->owner))
       {
         (*_bfd_error_handler)
           (_("%B(%s): warning: interworking not enabled.\n"
              "  first occurrence: %B: arm call to thumb"),
            sym_sec->owner, input_bfd, name);
       }

      --my_offset;
      myh->root.u.def.value = my_offset;

      if (info->shared || globals->root.is_relocatable_executable
         || globals->pic_veneer)
       {
         /* For relocatable objects we can't use absolute addresses,
            so construct the address from a relative offset.  */
         /* TODO: If the offset is small it's probably worth
            constructing the address with adds.  */
         put_arm_insn (globals, output_bfd, (bfd_vma) a2t1p_ldr_insn,
                     s->contents + my_offset);
         put_arm_insn (globals, output_bfd, (bfd_vma) a2t2p_add_pc_insn,
                     s->contents + my_offset + 4);
         put_arm_insn (globals, output_bfd, (bfd_vma) a2t3p_bx_r12_insn,
                     s->contents + my_offset + 8);
         /* Adjust the offset by 4 for the position of the add,
            and 8 for the pipeline offset.  */
         ret_offset = (val - (s->output_offset
                            + s->output_section->vma
                            + my_offset + 12))
                     | 1;
         bfd_put_32 (output_bfd, ret_offset,
                    s->contents + my_offset + 12);
       }
      else
       {
         put_arm_insn (globals, output_bfd, (bfd_vma) a2t1_ldr_insn,
                     s->contents + my_offset);

         put_arm_insn (globals, output_bfd, (bfd_vma) a2t2_bx_r12_insn,
                     s->contents + my_offset + 4);

         /* It's a thumb address.  Add the low order bit.  */
         bfd_put_32 (output_bfd, val | a2t3_func_addr_insn,
                    s->contents + my_offset + 8);
       }
    }

  BFD_ASSERT (my_offset <= globals->arm_glue_size);

  return myh;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 6288 of file elf32-arm.c.

{
  bfd_vma size;
  aeabi_attribute *attr;
  aeabi_attribute_list *list;
  int i;

  attr = elf32_arm_tdata (abfd)->known_eabi_attributes;
  size = 16; /* 'A' <size> "aeabi" 0x1 <size>.  */
  for (i = 4; i < NUM_KNOWN_ATTRIBUTES; i++)
    size += eabi_attr_size (i, &attr[i]);

  for (list = elf32_arm_tdata (abfd)->other_eabi_attributes;
       list;
       list = list->next)
    size += eabi_attr_size (list->tag, &list->attr);

  return size;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean elf32_arm_fake_sections ( bfd abfd,
Elf_Internal_Shdr hdr,
asection sec 
) [static]

Definition at line 9779 of file elf32-arm.c.

{
  const char * name;

  name = bfd_get_section_name (abfd, sec);

  if (is_arm_elf_unwind_section_name (abfd, name))
    {
      hdr->sh_type = SHT_ARM_EXIDX;
      hdr->sh_flags |= SHF_LINK_ORDER;
    }
  else if (strcmp(name, ".ARM.attributes") == 0)
    {
      hdr->sh_type = SHT_ARM_ATTRIBUTES;
    }
  return TRUE;
}

Here is the call graph for this function:

static bfd_reloc_status_type elf32_arm_final_link_relocate ( reloc_howto_type *  howto,
bfd input_bfd,
bfd output_bfd,
asection input_section,
bfd_byte contents,
Elf_Internal_Rela rel,
bfd_vma  value,
struct bfd_link_info info,
asection sym_sec,
const char *  sym_name,
int  sym_flags,
struct elf_link_hash_entry h,
bfd_boolean unresolved_reloc_p,
char **  error_message 
) [static]

Definition at line 4467 of file elf32-arm.c.

{
  unsigned long                 r_type = howto->type;
  unsigned long                 r_symndx;
  bfd_byte *                    hit_data = contents + rel->r_offset;
  bfd *                         dynobj = NULL;
  Elf_Internal_Shdr *           symtab_hdr;
  struct elf_link_hash_entry ** sym_hashes;
  bfd_vma *                     local_got_offsets;
  asection *                    sgot = NULL;
  asection *                    splt = NULL;
  asection *                    sreloc = NULL;
  bfd_vma                       addend;
  bfd_signed_vma                signed_addend;
  struct elf32_arm_link_hash_table * globals;

  globals = elf32_arm_hash_table (info);

  /* Some relocation type map to different relocations depending on the
     target.  We pick the right one here.  */
  r_type = arm_real_reloc_type (globals, r_type);
  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;

  dynobj = elf_hash_table (info)->dynobj;
  if (dynobj)
    {
      sgot = bfd_get_section_by_name (dynobj, ".got");
      splt = bfd_get_section_by_name (dynobj, ".plt");
    }
  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
  sym_hashes = elf_sym_hashes (input_bfd);
  local_got_offsets = elf_local_got_offsets (input_bfd);
  r_symndx = ELF32_R_SYM (rel->r_info);

  if (globals->use_rel)
    {
      addend = bfd_get_32 (input_bfd, hit_data) & howto->src_mask;

      if (addend & ((howto->src_mask + 1) >> 1))
       {
         signed_addend = -1;
         signed_addend &= ~ howto->src_mask;
         signed_addend |= addend;
       }
      else
       signed_addend = addend;
    }
  else
    addend = signed_addend = rel->r_addend;

  switch (r_type)
    {
    case R_ARM_NONE:
      /* We don't need to find a value for this symbol.  It's just a
        marker.  */
      *unresolved_reloc_p = FALSE;
      return bfd_reloc_ok;

    case R_ARM_ABS12:
      if (!globals->vxworks_p)
       return elf32_arm_abs12_reloc (input_bfd, hit_data, value + addend);

    case R_ARM_PC24:
    case R_ARM_ABS32:
    case R_ARM_ABS32_NOI:
    case R_ARM_REL32:
    case R_ARM_REL32_NOI:
    case R_ARM_CALL:
    case R_ARM_JUMP24:
    case R_ARM_XPC25:
    case R_ARM_PREL31:
    case R_ARM_PLT32:
      /* Handle relocations which should use the PLT entry.  ABS32/REL32
        will use the symbol's value, which may point to a PLT entry, but we
        don't need to handle that here.  If we created a PLT entry, all
        branches in this object should go to it.  */
      if ((r_type != R_ARM_ABS32 && r_type != R_ARM_REL32
           && r_type != R_ARM_ABS32_NOI && r_type != R_ARM_REL32_NOI)
         && h != NULL
         && splt != NULL
         && h->plt.offset != (bfd_vma) -1)
       {
         /* If we've created a .plt section, and assigned a PLT entry to
            this function, it should not be known to bind locally.  If
            it were, we would have cleared the PLT entry.  */
         BFD_ASSERT (!SYMBOL_CALLS_LOCAL (info, h));

         value = (splt->output_section->vma
                 + splt->output_offset
                 + h->plt.offset);
         *unresolved_reloc_p = FALSE;
         return _bfd_final_link_relocate (howto, input_bfd, input_section,
                                      contents, rel->r_offset, value,
                                      rel->r_addend);
       }

      /* 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)
         && (input_section->flags & SEC_ALLOC)
         && ((r_type != R_ARM_REL32 && r_type != R_ARM_REL32_NOI)
             || !SYMBOL_CALLS_LOCAL (info, h))
         && (h == NULL
             || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
             || h->root.type != bfd_link_hash_undefweak)
         && r_type != R_ARM_PC24
         && r_type != R_ARM_CALL
         && r_type != R_ARM_JUMP24
         && r_type != R_ARM_PREL31
         && r_type != R_ARM_PLT32)
       {
         Elf_Internal_Rela outrel;
         bfd_byte *loc;
         bfd_boolean skip, relocate;

         *unresolved_reloc_p = FALSE;

         if (sreloc == NULL)
           {
             const char * name;

             name = (bfd_elf_string_from_elf_section
                    (input_bfd,
                     elf_elfheader (input_bfd)->e_shstrndx,
                     elf_section_data (input_section)->rel_hdr.sh_name));
             if (name == NULL)
              return bfd_reloc_notsupported;

             BFD_ASSERT (reloc_section_p (globals, name, input_section));

             sreloc = bfd_get_section_by_name (dynobj, name);
             BFD_ASSERT (sreloc != NULL);
           }

         skip = FALSE;
         relocate = FALSE;

         outrel.r_addend = addend;
         outrel.r_offset =
           _bfd_elf_section_offset (output_bfd, info, input_section,
                                 rel->r_offset);
         if (outrel.r_offset == (bfd_vma) -1)
           skip = TRUE;
         else if (outrel.r_offset == (bfd_vma) -2)
           skip = TRUE, relocate = TRUE;
         outrel.r_offset += (input_section->output_section->vma
                           + input_section->output_offset);

         if (skip)
           memset (&outrel, 0, sizeof outrel);
         else if (h != NULL
                 && h->dynindx != -1
                 && (!info->shared
                     || !info->symbolic
                     || !h->def_regular))
           outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
         else
           {
             int symbol;

             /* This symbol is local, or marked to become local.  */
             if (sym_flags == STT_ARM_TFUNC)
              value |= 1;
             if (globals->symbian_p)
              {
                asection *osec;

                /* On Symbian OS, the data segment and text segement
                   can be relocated independently.  Therefore, we
                   must indicate the segment to which this
                   relocation is relative.  The BPABI allows us to
                   use any symbol in the right segment; we just use
                   the section symbol as it is convenient.  (We
                   cannot use the symbol given by "h" directly as it
                   will not appear in the dynamic symbol table.)

                   Note that the dynamic linker ignores the section
                   symbol value, so we don't subtract osec->vma
                   from the emitted reloc addend.  */
                if (sym_sec)
                  osec = sym_sec->output_section;
                else
                  osec = input_section->output_section;
                symbol = elf_section_data (osec)->dynindx;
                if (symbol == 0)
                  {
                    struct elf_link_hash_table *htab = elf_hash_table (info);

                    if ((osec->flags & SEC_READONLY) == 0
                       && htab->data_index_section != NULL)
                     osec = htab->data_index_section;
                    else
                     osec = htab->text_index_section;
                    symbol = elf_section_data (osec)->dynindx;
                  }
                BFD_ASSERT (symbol != 0);
              }
             else
              /* On SVR4-ish systems, the dynamic loader cannot
                 relocate the text and data segments independently,
                 so the symbol does not matter.  */
              symbol = 0;
             outrel.r_info = ELF32_R_INFO (symbol, R_ARM_RELATIVE);
             if (globals->use_rel)
              relocate = TRUE;
             else
              outrel.r_addend += value;
           }

         loc = sreloc->contents;
         loc += sreloc->reloc_count++ * RELOC_SIZE (globals);
         SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);

         /* If this reloc is against an external symbol, we do not want to
            fiddle with the addend.  Otherwise, we need to include the symbol
            value so that it becomes an addend for the dynamic reloc.  */
         if (! relocate)
           return bfd_reloc_ok;

         return _bfd_final_link_relocate (howto, input_bfd, input_section,
                                      contents, rel->r_offset, value,
                                      (bfd_vma) 0);
       }
      else switch (r_type)
       {
       case R_ARM_ABS12:
         return elf32_arm_abs12_reloc (input_bfd, hit_data, value + addend);

       case R_ARM_XPC25:      /* Arm BLX instruction.  */
       case R_ARM_CALL:
       case R_ARM_JUMP24:
       case R_ARM_PC24:       /* Arm B/BL instruction */
       case R_ARM_PLT32:
         if (r_type == R_ARM_XPC25)
           {
             /* Check for Arm calling Arm function.  */
             /* FIXME: Should we translate the instruction into a BL
               instruction instead ?  */
             if (sym_flags != STT_ARM_TFUNC)
              (*_bfd_error_handler)
                (_("\%B: Warning: Arm BLX instruction targets Arm function '%s'."),
                 input_bfd,
                 h ? h->root.root.string : "(local)");
           }
         else if (r_type != R_ARM_CALL || !globals->use_blx)
           {
             /* Check for Arm calling Thumb function.  */
             if (sym_flags == STT_ARM_TFUNC)
              {
                if (elf32_arm_to_thumb_stub (info, sym_name, input_bfd,
                                          output_bfd, input_section,
                                          hit_data, sym_sec, rel->r_offset,
                                          signed_addend, value,
                                          error_message))
                  return bfd_reloc_ok;
                else
                  return bfd_reloc_dangerous;
              }
           }

         /* 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;
         if (globals->use_rel)
           value += (signed_addend << howto->size);
         else
           /* RELA addends do not have to be adjusted by howto->size.  */
           value += signed_addend;

         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;
           }

         addend = (value & 2);

         value = (signed_addend & howto->dst_mask)
           | (bfd_get_32 (input_bfd, hit_data) & (~ howto->dst_mask));

         /* Set the H bit in the BLX instruction.  */
         if (sym_flags == STT_ARM_TFUNC)
           {
             if (addend)
              value |= (1 << 24);
             else
              value &= ~(bfd_vma)(1 << 24);
           }
         if (r_type == R_ARM_CALL)
           {
             /* Select the correct instruction (BL or BLX).  */
             if (sym_flags == STT_ARM_TFUNC)
              value |= (1 << 28);
             else
              {
                value &= ~(bfd_vma)(1 << 28);
                value |= (1 << 24);
              }
           }
         break;

       case R_ARM_ABS32:
         value += addend;
         if (sym_flags == STT_ARM_TFUNC)
           value |= 1;
         break;

       case R_ARM_ABS32_NOI:
         value += addend;
         break;

       case R_ARM_REL32:
         value += addend;
         if (sym_flags == STT_ARM_TFUNC)
           value |= 1;
         value -= (input_section->output_section->vma
                  + input_section->output_offset + rel->r_offset);
         break;

       case R_ARM_REL32_NOI:
         value += addend;
         value -= (input_section->output_section->vma
                  + input_section->output_offset + rel->r_offset);
         break;

       case R_ARM_PREL31:
         value -= (input_section->output_section->vma
                  + input_section->output_offset + rel->r_offset);
         value += signed_addend;
         if (! h || h->root.type != bfd_link_hash_undefweak)
           {
             /* Check for overflow */
             if ((value ^ (value >> 1)) & (1 << 30))
              return bfd_reloc_overflow;
           }
         value &= 0x7fffffff;
         value |= (bfd_get_32 (input_bfd, hit_data) & 0x80000000);
         if (sym_flags == STT_ARM_TFUNC)
           value |= 1;
         break;
       }

      bfd_put_32 (input_bfd, value, hit_data);
      return bfd_reloc_ok;

    case R_ARM_ABS8:
      value += addend;
      if ((long) value > 0x7f || (long) value < -0x80)
       return bfd_reloc_overflow;

      bfd_put_8 (input_bfd, value, hit_data);
      return bfd_reloc_ok;

    case R_ARM_ABS16:
      value += addend;

      if ((long) value > 0x7fff || (long) value < -0x8000)
       return bfd_reloc_overflow;

      bfd_put_16 (input_bfd, value, hit_data);
      return bfd_reloc_ok;

    case R_ARM_THM_ABS5:
      /* Support ldr and str instructions for the thumb.  */
      if (globals->use_rel)
       {
         /* Need to refetch addend.  */
         addend = bfd_get_16 (input_bfd, hit_data) & howto->src_mask;
         /* ??? Need to determine shift amount from operand size.  */
         addend >>= howto->rightshift;
       }
      value += addend;

      /* ??? Isn't value unsigned?  */
      if ((long) value > 0x1f || (long) value < -0x10)
       return bfd_reloc_overflow;

      /* ??? Value needs to be properly shifted into place first.  */
      value |= bfd_get_16 (input_bfd, hit_data) & 0xf83f;
      bfd_put_16 (input_bfd, value, hit_data);
      return bfd_reloc_ok;

    case R_ARM_THM_ALU_PREL_11_0:
      /* Corresponds to: addw.w reg, pc, #offset (and similarly for subw).  */
      {
       bfd_vma insn;
       bfd_signed_vma relocation;

       insn = (bfd_get_16 (input_bfd, hit_data) << 16)
             | bfd_get_16 (input_bfd, hit_data + 2);

        if (globals->use_rel)
          {
            signed_addend = (insn & 0xff) | ((insn & 0x7000) >> 4)
                          | ((insn & (1 << 26)) >> 15);
            if (insn & 0xf00000)
              signed_addend = -signed_addend;
          }

       relocation = value + signed_addend;
       relocation -= (input_section->output_section->vma
                     + input_section->output_offset
                     + rel->r_offset);

        value = abs (relocation);

        if (value >= 0x1000)
          return bfd_reloc_overflow;

       insn = (insn & 0xfb0f8f00) | (value & 0xff)
             | ((value & 0x700) << 4)
             | ((value & 0x800) << 15);
        if (relocation < 0)
          insn |= 0xa00000;

       bfd_put_16 (input_bfd, insn >> 16, hit_data);
       bfd_put_16 (input_bfd, insn & 0xffff, hit_data + 2);

        return bfd_reloc_ok;
      }

    case R_ARM_THM_PC12:
      /* Corresponds to: ldr.w reg, [pc, #offset].  */
      {
       bfd_vma insn;
       bfd_signed_vma relocation;

       insn = (bfd_get_16 (input_bfd, hit_data) << 16)
             | bfd_get_16 (input_bfd, hit_data + 2);

        if (globals->use_rel)
          {
            signed_addend = insn & 0xfff;
            if (!(insn & (1 << 23)))
              signed_addend = -signed_addend;
          }

       relocation = value + signed_addend;
       relocation -= (input_section->output_section->vma
                     + input_section->output_offset
                     + rel->r_offset);

        value = abs (relocation);

        if (value >= 0x1000)
          return bfd_reloc_overflow;

       insn = (insn & 0xff7ff000) | value;
        if (relocation >= 0)
          insn |= (1 << 23);

       bfd_put_16 (input_bfd, insn >> 16, hit_data);
       bfd_put_16 (input_bfd, insn & 0xffff, hit_data + 2);

        return bfd_reloc_ok;
      }

    case R_ARM_THM_XPC22:
    case R_ARM_THM_CALL:
      /* Thumb BL (branch long instruction).  */
      {
       bfd_vma relocation;
        bfd_vma reloc_sign;
       bfd_boolean overflow = FALSE;
       bfd_vma upper_insn = bfd_get_16 (input_bfd, hit_data);
       bfd_vma lower_insn = bfd_get_16 (input_bfd, hit_data + 2);
       bfd_signed_vma reloc_signed_max;
       bfd_signed_vma reloc_signed_min;
       bfd_vma check;
       bfd_signed_vma signed_check;
       int bitsize;
       int thumb2 = using_thumb2 (globals);

       /* Fetch the addend.  We use the Thumb-2 encoding (backwards compatible
           with Thumb-1) involving the J1 and J2 bits.  */
       if (globals->use_rel)
         {
            bfd_vma s = (upper_insn & (1 << 10)) >> 10;
            bfd_vma upper = upper_insn & 0x3ff;
            bfd_vma lower = lower_insn & 0x7ff;
           bfd_vma j1 = (lower_insn & (1 << 13)) >> 13;
           bfd_vma j2 = (lower_insn & (1 << 11)) >> 11;
            bfd_vma i1 = j1 ^ s ? 0 : 1;
            bfd_vma i2 = j2 ^ s ? 0 : 1;

            addend = (i1 << 23) | (i2 << 22) | (upper << 12) | (lower << 1);
            /* Sign extend.  */
            addend = (addend | ((s ? 0 : 1) << 24)) - (1 << 24);

           signed_addend = addend;
         }

       if (r_type == R_ARM_THM_XPC22)
         {
           /* Check for Thumb to Thumb call.  */
           /* FIXME: Should we translate the instruction into a BL
              instruction instead ?  */
           if (sym_flags == STT_ARM_TFUNC)
             (*_bfd_error_handler)
              (_("%B: Warning: Thumb BLX instruction targets thumb function '%s'."),
               input_bfd,
               h ? h->root.root.string : "(local)");
         }
       else
         {
           /* If it is not a call to Thumb, assume call to Arm.
              If it is a call relative to a section name, then it is not a
              function call at all, but rather a long jump.  Calls through
              the PLT do not require stubs.  */
           if (sym_flags != STT_ARM_TFUNC && sym_flags != STT_SECTION
              && (h == NULL || splt == NULL
                  || h->plt.offset == (bfd_vma) -1))
             {
              if (globals->use_blx)
                {
                  /* Convert BL to BLX.  */
                  lower_insn = (lower_insn & ~0x1000) | 0x0800;
                }
              else if (elf32_thumb_to_arm_stub
                  (info, sym_name, input_bfd, output_bfd, input_section,
                   hit_data, sym_sec, rel->r_offset, signed_addend, value,
                   error_message))
                return bfd_reloc_ok;
              else
                return bfd_reloc_dangerous;
             }
           else if (sym_flags == STT_ARM_TFUNC && globals->use_blx)
             {
              /* Make sure this is a BL.  */
              lower_insn |= 0x1800;
             }
         }

       /* Handle calls via the PLT.  */
       if (h != NULL && splt != NULL && h->plt.offset != (bfd_vma) -1)
         {
           value = (splt->output_section->vma
                   + splt->output_offset
                   + h->plt.offset);
           if (globals->use_blx)
             {
              /* If the Thumb BLX instruction is available, convert the
                 BL to a BLX instruction to call the ARM-mode PLT entry.  */
              lower_insn = (lower_insn & ~0x1000) | 0x0800;
             }
           else
             /* Target the Thumb stub before the ARM PLT entry.  */
             value -= PLT_THUMB_STUB_SIZE;
           *unresolved_reloc_p = FALSE;
         }

       relocation = value + signed_addend;

       relocation -= (input_section->output_section->vma
                     + input_section->output_offset
                     + rel->r_offset);

       check = relocation >> howto->rightshift;

       /* If this is a signed value, the rightshift just dropped
          leading 1 bits (assuming twos complement).  */
       if ((bfd_signed_vma) relocation >= 0)
         signed_check = check;
       else
         signed_check = check | ~((bfd_vma) -1 >> howto->rightshift);

       /* Calculate the permissable maximum and minimum values for
          this relocation according to whether we're relocating for
          Thumb-2 or not.  */
       bitsize = howto->bitsize;
       if (!thumb2)
         bitsize -= 2;
       reloc_signed_max = ((1 << (bitsize - 1)) - 1) >> howto->rightshift;
       reloc_signed_min = ~reloc_signed_max;

       /* Assumes two's complement.  */
       if (signed_check > reloc_signed_max || signed_check < reloc_signed_min)
         overflow = TRUE;

       if ((lower_insn & 0x1800) == 0x0800)
         /* For a BLX instruction, make sure that the relocation is rounded up
            to a word boundary.  This follows the semantics of the instruction
            which specifies that bit 1 of the target address will come from bit
            1 of the base address.  */
         relocation = (relocation + 2) & ~ 3;

       /* Put RELOCATION back into the insn.  Assumes two's complement.
          We use the Thumb-2 encoding, which is safe even if dealing with
          a Thumb-1 instruction by virtue of our overflow check above.  */
        reloc_sign = (signed_check < 0) ? 1 : 0;
       upper_insn = (upper_insn & ~(bfd_vma) 0x7ff)
                     | ((relocation >> 12) & 0x3ff)
                     | (reloc_sign << 10);
       lower_insn = (lower_insn & ~(bfd_vma) 0x2fff) 
                     | (((!((relocation >> 23) & 1)) ^ reloc_sign) << 13)
                     | (((!((relocation >> 22) & 1)) ^ reloc_sign) << 11)
                     | ((relocation >> 1) & 0x7ff);

       /* Put the relocated value back in the object file:  */
       bfd_put_16 (input_bfd, upper_insn, hit_data);
       bfd_put_16 (input_bfd, lower_insn, hit_data + 2);

       return (overflow ? bfd_reloc_overflow : bfd_reloc_ok);
      }
      break;

    case R_ARM_THM_JUMP24:
      /* Thumb32 unconditional branch instruction.  */
      {
       bfd_vma relocation;
       bfd_boolean overflow = FALSE;
       bfd_vma upper_insn = bfd_get_16 (input_bfd, hit_data);
       bfd_vma lower_insn = bfd_get_16 (input_bfd, hit_data + 2);
       bfd_signed_vma reloc_signed_max = ((1 << (howto->bitsize - 1)) - 1) >> howto->rightshift;
       bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
       bfd_vma check;
       bfd_signed_vma signed_check;

       /* Need to refetch the addend, reconstruct the top three bits, and glue the
          two pieces together.  */
       if (globals->use_rel)
         {
           bfd_vma S  = (upper_insn & 0x0400) >> 10;
           bfd_vma hi = (upper_insn & 0x03ff);
           bfd_vma I1 = (lower_insn & 0x2000) >> 13;
           bfd_vma I2 = (lower_insn & 0x0800) >> 11;
           bfd_vma lo = (lower_insn & 0x07ff);

           I1 = !(I1 ^ S);
           I2 = !(I2 ^ S);
           S  = !S;

           signed_addend = (S << 24) | (I1 << 23) | (I2 << 22) | (hi << 12) | (lo << 1);
           signed_addend -= (1 << 24); /* Sign extend.  */
         }

       /* ??? Should handle interworking?  GCC might someday try to
          use this for tail calls.  */

       relocation = value + signed_addend;
       relocation -= (input_section->output_section->vma
                     + input_section->output_offset
                     + rel->r_offset);

       check = relocation >> howto->rightshift;

       /* If this is a signed value, the rightshift just dropped
          leading 1 bits (assuming twos complement).  */
       if ((bfd_signed_vma) relocation >= 0)
         signed_check = check;
       else
         signed_check = check | ~((bfd_vma) -1 >> howto->rightshift);

       /* Assumes two's complement.  */
       if (signed_check > reloc_signed_max || signed_check < reloc_signed_min)
         overflow = TRUE;

       /* Put RELOCATION back into the insn.  */
       {
         bfd_vma S  = (relocation & 0x01000000) >> 24;
         bfd_vma I1 = (relocation & 0x00800000) >> 23;
         bfd_vma I2 = (relocation & 0x00400000) >> 22;
         bfd_vma hi = (relocation & 0x003ff000) >> 12;
         bfd_vma lo = (relocation & 0x00000ffe) >>  1;

         I1 = !(I1 ^ S);
         I2 = !(I2 ^ S);

         upper_insn = (upper_insn & (bfd_vma) 0xf800) | (S << 10) | hi;
         lower_insn = (lower_insn & (bfd_vma) 0xd000) | (I1 << 13) | (I2 << 11) | lo;
       }

       /* Put the relocated value back in the object file:  */
       bfd_put_16 (input_bfd, upper_insn, hit_data);
       bfd_put_16 (input_bfd, lower_insn, hit_data + 2);

       return (overflow ? bfd_reloc_overflow : bfd_reloc_ok);
      }

    case R_ARM_THM_JUMP19:
      /* Thumb32 conditional branch instruction.  */
      {
       bfd_vma relocation;
       bfd_boolean overflow = FALSE;
       bfd_vma upper_insn = bfd_get_16 (input_bfd, hit_data);
       bfd_vma lower_insn = bfd_get_16 (input_bfd, hit_data + 2);
       bfd_signed_vma reloc_signed_max = ((1 << (howto->bitsize - 1)) - 1) >> howto->rightshift;
       bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
       bfd_vma check;
       bfd_signed_vma signed_check;

       /* Need to refetch the addend, reconstruct the top three bits,
          and squish the two 11 bit pieces together.  */
       if (globals->use_rel)
         {
           bfd_vma S     = (upper_insn & 0x0400) >> 10;
           bfd_vma upper = (upper_insn & 0x001f);
           bfd_vma J1    = (lower_insn & 0x2000) >> 13;
           bfd_vma J2    = (lower_insn & 0x0800) >> 11;
           bfd_vma lower = (lower_insn & 0x07ff);

           upper |= J2 << 6;
           upper |= J1 << 7;
           upper |= ~S << 8;
           upper -= 0x0100; /* Sign extend.  */

           addend = (upper << 12) | (lower << 1);
           signed_addend = addend;
         }

       /* ??? Should handle interworking?  GCC might someday try to
          use this for tail calls.  */

       relocation = value + signed_addend;
       relocation -= (input_section->output_section->vma
                     + input_section->output_offset
                     + rel->r_offset);

       check = relocation >> howto->rightshift;

       /* If this is a signed value, the rightshift just dropped
          leading 1 bits (assuming twos complement).  */
       if ((bfd_signed_vma) relocation >= 0)
         signed_check = check;
       else
         signed_check = check | ~((bfd_vma) -1 >> howto->rightshift);

       /* Assumes two's complement.  */
       if (signed_check > reloc_signed_max || signed_check < reloc_signed_min)
         overflow = TRUE;

       /* Put RELOCATION back into the insn.  */
       {
         bfd_vma S  = (relocation & 0x00100000) >> 20;
         bfd_vma J2 = (relocation & 0x00080000) >> 19;
         bfd_vma J1 = (relocation & 0x00040000) >> 18;
         bfd_vma hi = (relocation & 0x0003f000) >> 12;
         bfd_vma lo = (relocation & 0x00000ffe) >>  1;

         upper_insn = (upper_insn & 0xfb30) | (S << 10) | hi;
         lower_insn = (lower_insn & 0xd000) | (J1 << 13) | (J2 << 11) | lo;
       }

       /* Put the relocated value back in the object file:  */
       bfd_put_16 (input_bfd, upper_insn, hit_data);
       bfd_put_16 (input_bfd, lower_insn, hit_data + 2);

       return (overflow ? bfd_reloc_overflow : bfd_reloc_ok);
      }

    case R_ARM_THM_JUMP11:
    case R_ARM_THM_JUMP8:
    case R_ARM_THM_JUMP6:
      /* Thumb B (branch) instruction).  */
      {
       bfd_signed_vma relocation;
       bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
       bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
       bfd_signed_vma signed_check;

       /* CZB cannot jump backward.  */
       if (r_type == R_ARM_THM_JUMP6)
         reloc_signed_min = 0;

       if (globals->use_rel)
         {
           /* Need to refetch addend.  */
           addend = bfd_get_16 (input_bfd, hit_data) & howto->src_mask;
           if (addend & ((howto->src_mask + 1) >> 1))
             {
              signed_addend = -1;
              signed_addend &= ~ howto->src_mask;
              signed_addend |= addend;
             }
           else
             signed_addend = addend;
           /* The value in the insn has been right shifted.  We need to
              undo this, so that we can perform the address calculation
              in terms of bytes.  */
           signed_addend <<= howto->rightshift;
         }
       relocation = value + signed_addend;

       relocation -= (input_section->output_section->vma
                     + input_section->output_offset
                     + rel->r_offset);

       relocation >>= howto->rightshift;
       signed_check = relocation;

       if (r_type == R_ARM_THM_JUMP6)
         relocation = ((relocation & 0x0020) << 4) | ((relocation & 0x001f) << 3);
       else
         relocation &= howto->dst_mask;
       relocation |= (bfd_get_16 (input_bfd, hit_data) & (~ howto->dst_mask));

       bfd_put_16 (input_bfd, relocation, hit_data);

       /* Assumes two's complement.  */
       if (signed_check > reloc_signed_max || signed_check < reloc_signed_min)
         return bfd_reloc_overflow;

       return bfd_reloc_ok;
      }

    case R_ARM_ALU_PCREL7_0:
    case R_ARM_ALU_PCREL15_8:
    case R_ARM_ALU_PCREL23_15:
      {
       bfd_vma insn;
       bfd_vma relocation;

       insn = bfd_get_32 (input_bfd, hit_data);
       if (globals->use_rel)
         {
           /* Extract the addend.  */
           addend = (insn & 0xff) << ((insn & 0xf00) >> 7);
           signed_addend = addend;
         }
       relocation = value + signed_addend;

       relocation -= (input_section->output_section->vma
                     + input_section->output_offset
                     + rel->r_offset);
       insn = (insn & ~0xfff)
              | ((howto->bitpos << 7) & 0xf00)
              | ((relocation >> howto->bitpos) & 0xff);
       bfd_put_32 (input_bfd, value, hit_data);
      }
      return bfd_reloc_ok;

    case R_ARM_GNU_VTINHERIT:
    case R_ARM_GNU_VTENTRY:
      return bfd_reloc_ok;

    case R_ARM_GOTOFF32:
      /* Relocation is relative to the start of the
         global offset table.  */

      BFD_ASSERT (sgot != NULL);
      if (sgot == NULL)
        return bfd_reloc_notsupported;

      /* If we are addressing a Thumb function, we need to adjust the
        address by one, so that attempts to call the function pointer will
        correctly interpret it as Thumb code.  */
      if (sym_flags == STT_ARM_TFUNC)
       value += 1;

      /* Note that sgot->output_offset is not involved in this
         calculation.  We always want the start of .got.  If we
         define _GLOBAL_OFFSET_TABLE in a different way, as is
         permitted by the ABI, we might have to change this
         calculation.  */
      value -= sgot->output_section->vma;
      return _bfd_final_link_relocate (howto, input_bfd, input_section,
                                   contents, rel->r_offset, value,
                                   rel->r_addend);

    case R_ARM_GOTPC:
      /* Use global offset table as symbol value.  */
      BFD_ASSERT (sgot != NULL);

      if (sgot == NULL)
        return bfd_reloc_notsupported;

      *unresolved_reloc_p = FALSE;
      value = sgot->output_section->vma;
      return _bfd_final_link_relocate (howto, input_bfd, input_section,
                                   contents, rel->r_offset, value,
                                   rel->r_addend);

    case R_ARM_GOT32:
    case R_ARM_GOT_PREL:
      /* Relocation is to the entry for this symbol in the
         global offset table.  */
      if (sgot == NULL)
       return bfd_reloc_notsupported;

      if (h != NULL)
       {
         bfd_vma off;
         bfd_boolean dyn;

         off = h->got.offset;
         BFD_ASSERT (off != (bfd_vma) -1);
         dyn = globals->root.dynamic_sections_created;

         if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
             || (info->shared
                && SYMBOL_REFERENCES_LOCAL (info, h))
             || (ELF_ST_VISIBILITY (h->other)
                && h->root.type == bfd_link_hash_undefweak))
           {
             /* This is actually a static link, or it is a -Bsymbolic link
               and the symbol is defined locally.  We must initialize this
               entry in the global offset table.  Since the offset must
               always be a multiple of 4, we use the least significant bit
               to record whether we have initialized it already.

               When doing a dynamic link, we create a .rel(a).got relocation
               entry to initialize the value.  This is done in the
               finish_dynamic_symbol routine.  */
             if ((off & 1) != 0)
              off &= ~1;
             else
              {
                /* If we are addressing a Thumb function, we need to
                   adjust the address by one, so that attempts to
                   call the function pointer will correctly
                   interpret it as Thumb code.  */
                if (sym_flags == STT_ARM_TFUNC)
                  value |= 1;

                bfd_put_32 (output_bfd, value, sgot->contents + off);
                h->got.offset |= 1;
              }
           }
         else
           *unresolved_reloc_p = FALSE;

         value = sgot->output_offset + off;
       }
      else
       {
         bfd_vma off;

         BFD_ASSERT (local_got_offsets != NULL &&
                    local_got_offsets[r_symndx] != (bfd_vma) -1);

         off = local_got_offsets[r_symndx];

         /* The offset must always be a multiple of 4.  We use the
            least significant bit to record whether we have already
            generated the necessary reloc.  */
         if ((off & 1) != 0)
           off &= ~1;
         else
           {
             /* If we are addressing a Thumb function, we need to
               adjust the address by one, so that attempts to
               call the function pointer will correctly
               interpret it as Thumb code.  */
             if (sym_flags == STT_ARM_TFUNC)
              value |= 1;

             if (globals->use_rel)
              bfd_put_32 (output_bfd, value, sgot->contents + off);

             if (info->shared)
              {
                asection * srelgot;
                Elf_Internal_Rela outrel;
                bfd_byte *loc;

                srelgot = (bfd_get_section_by_name
                          (dynobj, RELOC_SECTION (globals, ".got")));
                BFD_ASSERT (srelgot != NULL);

                outrel.r_addend = addend + value;
                outrel.r_offset = (sgot->output_section->vma
                                 + sgot->output_offset
                                 + off);
                outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
                loc = srelgot->contents;
                loc += srelgot->reloc_count++ * RELOC_SIZE (globals);
                SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
              }

             local_got_offsets[r_symndx] |= 1;
           }

         value = sgot->output_offset + off;
       }
      if (r_type != R_ARM_GOT32)
       value += sgot->output_section->vma;

      return _bfd_final_link_relocate (howto, input_bfd, input_section,
                                   contents, rel->r_offset, value,
                                   rel->r_addend);

    case R_ARM_TLS_LDO32:
      value = value - dtpoff_base (info);

      return _bfd_final_link_relocate (howto, input_bfd, input_section,
                                   contents, rel->r_offset, value,
                                   rel->r_addend);

    case R_ARM_TLS_LDM32:
      {
       bfd_vma off;

       if (globals->sgot == NULL)
         abort ();

       off = globals->tls_ldm_got.offset;

       if ((off & 1) != 0)
         off &= ~1;
       else
         {
           /* If we don't know the module number, create a relocation
              for it.  */
           if (info->shared)
             {
              Elf_Internal_Rela outrel;
              bfd_byte *loc;

              if (globals->srelgot == NULL)
                abort ();

              outrel.r_addend = 0;
              outrel.r_offset = (globals->sgot->output_section->vma
                               + globals->sgot->output_offset + off);
              outrel.r_info = ELF32_R_INFO (0, R_ARM_TLS_DTPMOD32);

              if (globals->use_rel)
                bfd_put_32 (output_bfd, outrel.r_addend,
                           globals->sgot->contents + off);

              loc = globals->srelgot->contents;
              loc += globals->srelgot->reloc_count++ * RELOC_SIZE (globals);
              SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
             }
           else
             bfd_put_32 (output_bfd, 1, globals->sgot->contents + off);

           globals->tls_ldm_got.offset |= 1;
         }

       value = globals->sgot->output_section->vma + globals->sgot->output_offset + off 
         - (input_section->output_section->vma + input_section->output_offset + rel->r_offset);

       return _bfd_final_link_relocate (howto, input_bfd, input_section,
                                    contents, rel->r_offset, value,
                                    rel->r_addend);
      }

    case R_ARM_TLS_GD32:
    case R_ARM_TLS_IE32:
      {
       bfd_vma off;
       int indx;
       char tls_type;

       if (globals->sgot == NULL)
         abort ();

       indx = 0;
       if (h != NULL)
         {
           bfd_boolean dyn;
           dyn = globals->root.dynamic_sections_created;
           if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
              && (!info->shared
                  || !SYMBOL_REFERENCES_LOCAL (info, h)))
             {
              *unresolved_reloc_p = FALSE;
              indx = h->dynindx;
             }
           off = h->got.offset;
           tls_type = ((struct elf32_arm_link_hash_entry *) h)->tls_type;
         }
       else
         {
           if (local_got_offsets == NULL)
             abort ();
           off = local_got_offsets[r_symndx];
           tls_type = elf32_arm_local_got_tls_type (input_bfd)[r_symndx];
         }

       if (tls_type == GOT_UNKNOWN)
         abort ();

       if ((off & 1) != 0)
         off &= ~1;
       else
         {
           bfd_boolean need_relocs = FALSE;
           Elf_Internal_Rela outrel;
           bfd_byte *loc = NULL;
           int cur_off = off;

           /* The GOT entries have not been initialized yet.  Do it
              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)
              && (h == NULL
                  || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                  || h->root.type != bfd_link_hash_undefweak))
             {
              need_relocs = TRUE;
              if (globals->srelgot == NULL)
                abort ();
              loc = globals->srelgot->contents;
              loc += globals->srelgot->reloc_count * RELOC_SIZE (globals);
             }

           if (tls_type & GOT_TLS_GD)
             {
              if (need_relocs)
                {
                  outrel.r_addend = 0;
                  outrel.r_offset = (globals->sgot->output_section->vma
                                   + globals->sgot->output_offset
                                   + cur_off);
                  outrel.r_info = ELF32_R_INFO (indx, R_ARM_TLS_DTPMOD32);

                  if (globals->use_rel)
                    bfd_put_32 (output_bfd, outrel.r_addend,
                              globals->sgot->contents + cur_off);

                  SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
                  globals->srelgot->reloc_count++;
                  loc += RELOC_SIZE (globals);

                  if (indx == 0)
                    bfd_put_32 (output_bfd, value - dtpoff_base (info),
                              globals->sgot->contents + cur_off + 4);
                  else
                    {
                     outrel.r_addend = 0;
                     outrel.r_info = ELF32_R_INFO (indx,
                                                R_ARM_TLS_DTPOFF32);
                     outrel.r_offset += 4;

                     if (globals->use_rel)
                       bfd_put_32 (output_bfd, outrel.r_addend,
                                  globals->sgot->contents + cur_off + 4);


                     SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
                     globals->srelgot->reloc_count++;
                     loc += RELOC_SIZE (globals);
                    }
                }
              else
                {
                  /* If we are not emitting relocations for a
                     general dynamic reference, then we must be in a
                     static link or an executable link with the
                     symbol binding locally.  Mark it as belonging
                     to module 1, the executable.  */
                  bfd_put_32 (output_bfd, 1,
                            globals->sgot->contents + cur_off);
                  bfd_put_32 (output_bfd, value - dtpoff_base (info),
                            globals->sgot->contents + cur_off + 4);
                }

              cur_off += 8;
             }

           if (tls_type & GOT_TLS_IE)
             {
              if (need_relocs)
                {
                  if (indx == 0)
                    outrel.r_addend = value - dtpoff_base (info);
                  else
                    outrel.r_addend = 0;
                  outrel.r_offset = (globals->sgot->output_section->vma
                                   + globals->sgot->output_offset
                                   + cur_off);
                  outrel.r_info = ELF32_R_INFO (indx, R_ARM_TLS_TPOFF32);

                  if (globals->use_rel)
                    bfd_put_32 (output_bfd, outrel.r_addend,
                              globals->sgot->contents + cur_off);

                  SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc);
                  globals->srelgot->reloc_count++;
                  loc += RELOC_SIZE (globals);
                }
              else
                bfd_put_32 (output_bfd, tpoff (info, value),
                           globals->sgot->contents + cur_off);
              cur_off += 4;
             }

           if (h != NULL)
             h->got.offset |= 1;
           else
             local_got_offsets[r_symndx] |= 1;
         }

       if ((tls_type & GOT_TLS_GD) && r_type != R_ARM_TLS_GD32)
         off += 8;
       value = globals->sgot->output_section->vma + globals->sgot->output_offset + off 
         - (input_section->output_section->vma + input_section->output_offset + rel->r_offset);

       return _bfd_final_link_relocate (howto, input_bfd, input_section,
                                    contents, rel->r_offset, value,
                                    rel->r_addend);
      }

    case R_ARM_TLS_LE32:
      if (info->shared)
       {
         (*_bfd_error_handler)
           (_("%B(%A+0x%lx): R_ARM_TLS_LE32 relocation not permitted in shared object"),
            input_bfd, input_section,
            (long) rel->r_offset, howto->name);
         return FALSE;        
       }
      else
       value = tpoff (info, value);
      
      return _bfd_final_link_relocate (howto, input_bfd, input_section,
                                   contents, rel->r_offset, value,
                                   rel->r_addend);

    case R_ARM_V4BX:
      if (globals->fix_v4bx)
        {
          bfd_vma insn = bfd_get_32 (input_bfd, hit_data);

          /* Ensure that we have a BX instruction.  */
          BFD_ASSERT ((insn & 0x0ffffff0) == 0x012fff10);

          /* Preserve Rm (lowest four bits) and the condition code
             (highest four bits). Other bits encode MOV PC,Rm.  */
          insn = (insn & 0xf000000f) | 0x01a0f000;

          bfd_put_32 (input_bfd, insn, hit_data);
        }
      return bfd_reloc_ok;

    case R_ARM_MOVW_ABS_NC:
    case R_ARM_MOVT_ABS:
    case R_ARM_MOVW_PREL_NC:
    case R_ARM_MOVT_PREL:
    /* Until we properly support segment-base-relative addressing then
       we assume the segment base to be zero, as for the group relocations.
       Thus R_ARM_MOVW_BREL_NC has the same semantics as R_ARM_MOVW_ABS_NC
       and R_ARM_MOVT_BREL has the same semantics as R_ARM_MOVT_ABS.  */
    case R_ARM_MOVW_BREL_NC:
    case R_ARM_MOVW_BREL:
    case R_ARM_MOVT_BREL:
      {
       bfd_vma insn = bfd_get_32 (input_bfd, hit_data);

       if (globals->use_rel)
         {
           addend = ((insn >> 4) & 0xf000) | (insn & 0xfff);
           signed_addend = (addend ^ 0x10000) - 0x10000;
         }

       value += signed_addend;

       if (r_type == R_ARM_MOVW_PREL_NC || r_type == R_ARM_MOVT_PREL)
         value -= (input_section->output_section->vma
                  + input_section->output_offset + rel->r_offset);

       if (r_type == R_ARM_MOVW_BREL && value >= 0x10000)
          return bfd_reloc_overflow;

       if (sym_flags == STT_ARM_TFUNC)
         value |= 1;

       if (r_type == R_ARM_MOVT_ABS || r_type == R_ARM_MOVT_PREL
            || r_type == R_ARM_MOVT_BREL)
         value >>= 16;

       insn &= 0xfff0f000;
       insn |= value & 0xfff;
       insn |= (value & 0xf000) << 4;
       bfd_put_32 (input_bfd, insn, hit_data);
      }
      return bfd_reloc_ok;

    case R_ARM_THM_MOVW_ABS_NC:
    case R_ARM_THM_MOVT_ABS:
    case R_ARM_THM_MOVW_PREL_NC:
    case R_ARM_THM_MOVT_PREL:
    /* Until we properly support segment-base-relative addressing then
       we assume the segment base to be zero, as for the above relocations.
       Thus R_ARM_THM_MOVW_BREL_NC has the same semantics as
       R_ARM_THM_MOVW_ABS_NC and R_ARM_THM_MOVT_BREL has the same semantics
       as R_ARM_THM_MOVT_ABS.  */
    case R_ARM_THM_MOVW_BREL_NC:
    case R_ARM_THM_MOVW_BREL:
    case R_ARM_THM_MOVT_BREL:
      {
       bfd_vma insn;
       
       insn = bfd_get_16 (input_bfd, hit_data) << 16;
       insn |= bfd_get_16 (input_bfd, hit_data + 2);

       if (globals->use_rel)
         {
           addend = ((insn >> 4)  & 0xf000)
                 | ((insn >> 15) & 0x0800)
                 | ((insn >> 4)  & 0x0700)
                 | (insn         & 0x00ff);
           signed_addend = (addend ^ 0x10000) - 0x10000;
         }

       value += signed_addend;

       if (r_type == R_ARM_THM_MOVW_PREL_NC || r_type == R_ARM_THM_MOVT_PREL)
         value -= (input_section->output_section->vma
                  + input_section->output_offset + rel->r_offset);

       if (r_type == R_ARM_THM_MOVW_BREL && value >= 0x10000)
          return bfd_reloc_overflow;

       if (sym_flags == STT_ARM_TFUNC)
         value |= 1;

       if (r_type == R_ARM_THM_MOVT_ABS || r_type == R_ARM_THM_MOVT_PREL
            || r_type == R_ARM_THM_MOVT_BREL)
         value >>= 16;

       insn &= 0xfbf08f00;
       insn |= (value & 0xf000) << 4;
       insn |= (value & 0x0800) << 15;
       insn |= (value & 0x0700) << 4;
       insn |= (value & 0x00ff);

       bfd_put_16 (input_bfd, insn >> 16, hit_data);
       bfd_put_16 (input_bfd, insn & 0xffff, hit_data + 2);
      }
      return bfd_reloc_ok;

    case R_ARM_ALU_PC_G0_NC:
    case R_ARM_ALU_PC_G1_NC:
    case R_ARM_ALU_PC_G0:
    case R_ARM_ALU_PC_G1:
    case R_ARM_ALU_PC_G2:
    case R_ARM_ALU_SB_G0_NC:
    case R_ARM_ALU_SB_G1_NC:
    case R_ARM_ALU_SB_G0:
    case R_ARM_ALU_SB_G1:
    case R_ARM_ALU_SB_G2:
      {
       bfd_vma insn = bfd_get_32 (input_bfd, hit_data);
        bfd_vma pc = input_section->output_section->vma
                   + input_section->output_offset + rel->r_offset;
        /* sb should be the origin of the *segment* containing the symbol.
           It is not clear how to obtain this OS-dependent value, so we
           make an arbitrary choice of zero.  */
        bfd_vma sb = 0;
        bfd_vma residual;
        bfd_vma g_n;
       bfd_signed_vma signed_value;
        int group = 0;

        /* Determine which group of bits to select.  */
        switch (r_type)
          {
          case R_ARM_ALU_PC_G0_NC:
          case R_ARM_ALU_PC_G0:
          case R_ARM_ALU_SB_G0_NC:
          case R_ARM_ALU_SB_G0:
            group = 0;
            break;

          case R_ARM_ALU_PC_G1_NC:
          case R_ARM_ALU_PC_G1:
          case R_ARM_ALU_SB_G1_NC:
          case R_ARM_ALU_SB_G1:
            group = 1;
            break;

          case R_ARM_ALU_PC_G2:
          case R_ARM_ALU_SB_G2:
            group = 2;
            break;

          default:
            abort();
          }

        /* If REL, extract the addend from the insn.  If RELA, it will
           have already been fetched for us.  */
       if (globals->use_rel)
          {
            int negative;
            bfd_vma constant = insn & 0xff;
            bfd_vma rotation = (insn & 0xf00) >> 8;

            if (rotation == 0)
              signed_addend = constant;
            else
              {
                /* Compensate for the fact that in the instruction, the
                   rotation is stored in multiples of 2 bits.  */
                rotation *= 2;

                /* Rotate "constant" right by "rotation" bits.  */
                signed_addend = (constant >> rotation) |
                                (constant << (8 * sizeof (bfd_vma) - rotation));
              }

            /* Determine if the instruction is an ADD or a SUB.
               (For REL, this determines the sign of the addend.)  */
            negative = identify_add_or_sub (insn);
            if (negative == 0)
              {
                (*_bfd_error_handler)
                  (_("%B(%A+0x%lx): Only ADD or SUB instructions are allowed for ALU group relocations"),
                  input_bfd, input_section,
                  (long) rel->r_offset, howto->name);
                return bfd_reloc_overflow;         
             }

            signed_addend *= negative;
          }

       /* Compute the value (X) to go in the place.  */
        if (r_type == R_ARM_ALU_PC_G0_NC
            || r_type == R_ARM_ALU_PC_G1_NC
            || r_type == R_ARM_ALU_PC_G0
            || r_type == R_ARM_ALU_PC_G1
            || r_type == R_ARM_ALU_PC_G2)
          /* PC relative.  */
          signed_value = value - pc + signed_addend;
        else
          /* Section base relative.  */
          signed_value = value - sb + signed_addend;

        /* If the target symbol is a Thumb function, then set the
           Thumb bit in the address.  */
       if (sym_flags == STT_ARM_TFUNC)
         signed_value |= 1;

        /* Calculate the value of the relevant G_n, in encoded
           constant-with-rotation format.  */
        g_n = calculate_group_reloc_mask (abs (signed_value), group,
                                          &residual);

        /* Check for overflow if required.  */
        if ((r_type == R_ARM_ALU_PC_G0
             || r_type == R_ARM_ALU_PC_G1
             || r_type == R_ARM_ALU_PC_G2
             || r_type == R_ARM_ALU_SB_G0
             || r_type == R_ARM_ALU_SB_G1
             || r_type == R_ARM_ALU_SB_G2) && residual != 0)
          {
            (*_bfd_error_handler)
              (_("%B(%A+0x%lx): Overflow whilst splitting 0x%lx for group relocation %s"),
              input_bfd, input_section,
              (long) rel->r_offset, abs (signed_value), howto->name);
            return bfd_reloc_overflow;
          }

        /* Mask out the value and the ADD/SUB part of the opcode; take care
           not to destroy the S bit.  */
        insn &= 0xff1ff000;

        /* Set the opcode according to whether the value to go in the
           place is negative.  */
        if (signed_value < 0)
          insn |= 1 << 22;
        else
          insn |= 1 << 23;

        /* Encode the offset.  */
        insn |= g_n;

       bfd_put_32 (input_bfd, insn, hit_data);
      }
      return bfd_reloc_ok;

    case R_ARM_LDR_PC_G0:
    case R_ARM_LDR_PC_G1:
    case R_ARM_LDR_PC_G2:
    case R_ARM_LDR_SB_G0:
    case R_ARM_LDR_SB_G1:
    case R_ARM_LDR_SB_G2:
      {
       bfd_vma insn = bfd_get_32 (input_bfd, hit_data);
        bfd_vma pc = input_section->output_section->vma
                   + input_section->output_offset + rel->r_offset;
        bfd_vma sb = 0; /* See note above.  */
        bfd_vma residual;
       bfd_signed_vma signed_value;
        int group = 0;

        /* Determine which groups of bits to calculate.  */
        switch (r_type)
          {
          case R_ARM_LDR_PC_G0:
          case R_ARM_LDR_SB_G0:
            group = 0;
            break;

          case R_ARM_LDR_PC_G1:
          case R_ARM_LDR_SB_G1:
            group = 1;
            break;

          case R_ARM_LDR_PC_G2:
          case R_ARM_LDR_SB_G2:
            group = 2;
            break;

          default:
            abort();
          }

        /* If REL, extract the addend from the insn.  If RELA, it will
           have already been fetched for us.  */
       if (globals->use_rel)
          {
            int negative = (insn & (1 << 23)) ? 1 : -1;
            signed_addend = negative * (insn & 0xfff);
          }

       /* Compute the value (X) to go in the place.  */
        if (r_type == R_ARM_LDR_PC_G0
            || r_type == R_ARM_LDR_PC_G1
            || r_type == R_ARM_LDR_PC_G2)
          /* PC relative.  */
          signed_value = value - pc + signed_addend;
        else
          /* Section base relative.  */
          signed_value = value - sb + signed_addend;

        /* Calculate the value of the relevant G_{n-1} to obtain
           the residual at that stage.  */
        calculate_group_reloc_mask (abs (signed_value), group - 1, &residual);

        /* Check for overflow.  */
        if (residual >= 0x1000)
          {
            (*_bfd_error_handler)
              (_("%B(%A+0x%lx): Overflow whilst splitting 0x%lx for group relocation %s"),
              input_bfd, input_section,
              (long) rel->r_offset, abs (signed_value), howto->name);
            return bfd_reloc_overflow;
          }

        /* Mask out the value and U bit.  */
        insn &= 0xff7ff000;

        /* Set the U bit if the value to go in the place is non-negative.  */
        if (signed_value >= 0)
          insn |= 1 << 23;

        /* Encode the offset.  */
        insn |= residual;

       bfd_put_32 (input_bfd, insn, hit_data);
      }
      return bfd_reloc_ok;

    case R_ARM_LDRS_PC_G0:
    case R_ARM_LDRS_PC_G1:
    case R_ARM_LDRS_PC_G2:
    case R_ARM_LDRS_SB_G0:
    case R_ARM_LDRS_SB_G1:
    case R_ARM_LDRS_SB_G2:
      {
       bfd_vma insn = bfd_get_32 (input_bfd, hit_data);
        bfd_vma pc = input_section->output_section->vma
                   + input_section->output_offset + rel->r_offset;
        bfd_vma sb = 0; /* See note above.  */
        bfd_vma residual;
       bfd_signed_vma signed_value;
        int group = 0;

        /* Determine which groups of bits to calculate.  */
        switch (r_type)
          {
          case R_ARM_LDRS_PC_G0:
          case R_ARM_LDRS_SB_G0:
            group = 0;
            break;

          case R_ARM_LDRS_PC_G1:
          case R_ARM_LDRS_SB_G1:
            group = 1;
            break;

          case R_ARM_LDRS_PC_G2:
          case R_ARM_LDRS_SB_G2:
            group = 2;
            break;

          default:
            abort();
          }

        /* If REL, extract the addend from the insn.  If RELA, it will
           have already been fetched for us.  */
       if (globals->use_rel)
          {
            int negative = (insn & (1 << 23)) ? 1 : -1;
            signed_addend = negative * (((insn & 0xf00) >> 4) + (insn & 0xf));
          }

       /* Compute the value (X) to go in the place.  */
        if (r_type == R_ARM_LDRS_PC_G0
            || r_type == R_ARM_LDRS_PC_G1
            || r_type == R_ARM_LDRS_PC_G2)
          /* PC relative.  */
          signed_value = value - pc + signed_addend;
        else
          /* Section base relative.  */
          signed_value = value - sb + signed_addend;

        /* Calculate the value of the relevant G_{n-1} to obtain
           the residual at that stage.  */
        calculate_group_reloc_mask (abs (signed_value), group - 1, &residual);

        /* Check for overflow.  */
        if (residual >= 0x100)
          {
            (*_bfd_error_handler)
              (_("%B(%A+0x%lx): Overflow whilst splitting 0x%lx for group relocation %s"),
              input_bfd, input_section,
              (long) rel->r_offset, abs (signed_value), howto->name);
            return bfd_reloc_overflow;
          }

        /* Mask out the value and U bit.  */
        insn &= 0xff7ff0f0;

        /* Set the U bit if the value to go in the place is non-negative.  */
        if (signed_value >= 0)
          insn |= 1 << 23;

        /* Encode the offset.  */
        insn |= ((residual & 0xf0) << 4) | (residual & 0xf);

       bfd_put_32 (input_bfd, insn, hit_data);
      }
      return bfd_reloc_ok;

    case R_ARM_LDC_PC_G0:
    case R_ARM_LDC_PC_G1:
    case R_ARM_LDC_PC_G2:
    case R_ARM_LDC_SB_G0:
    case R_ARM_LDC_SB_G1:
    case R_ARM_LDC_SB_G2:
      {
       bfd_vma insn = bfd_get_32 (input_bfd, hit_data);
        bfd_vma pc = input_section->output_section->vma
                   + input_section->output_offset + rel->r_offset;
        bfd_vma sb = 0; /* See note above.  */
        bfd_vma residual;
       bfd_signed_vma signed_value;
        int group = 0;

        /* Determine which groups of bits to calculate.  */
        switch (r_type)
          {
          case R_ARM_LDC_PC_G0:
          case R_ARM_LDC_SB_G0:
            group = 0;
            break;

          case R_ARM_LDC_PC_G1:
          case R_ARM_LDC_SB_G1:
            group = 1;
            break;

          case R_ARM_LDC_PC_G2:
          case R_ARM_LDC_SB_G2:
            group = 2;
            break;

          default:
            abort();
          }

        /* If REL, extract the addend from the insn.  If RELA, it will
           have already been fetched for us.  */
       if (globals->use_rel)
          {
            int negative = (insn & (1 << 23)) ? 1 : -1;
            signed_addend = negative * ((insn & 0xff) << 2);
          }

       /* Compute the value (X) to go in the place.  */
        if (r_type == R_ARM_LDC_PC_G0
            || r_type == R_ARM_LDC_PC_G1
            || r_type == R_ARM_LDC_PC_G2)
          /* PC relative.  */
          signed_value = value - pc + signed_addend;
        else
          /* Section base relative.  */
          signed_value = value - sb + signed_addend;

        /* Calculate the value of the relevant G_{n-1} to obtain
           the residual at that stage.  */
        calculate_group_reloc_mask (abs (signed_value), group - 1, &residual);

        /* Check for overflow.  (The absolute value to go in the place must be
           divisible by four and, after having been divided by four, must
           fit in eight bits.)  */
        if ((residual & 0x3) != 0 || residual >= 0x400)
          {
            (*_bfd_error_handler)
              (_("%B(%A+0x%lx): Overflow whilst splitting 0x%lx for group relocation %s"),
              input_bfd, input_section,
              (long) rel->r_offset, abs (signed_value), howto->name);
            return bfd_reloc_overflow;
          }

        /* Mask out the value and U bit.  */
        insn &= 0xff7fff00;

        /* Set the U bit if the value to go in the place is non-negative.  */
        if (signed_value >= 0)
          insn |= 1 << 23;

        /* Encode the offset.  */
        insn |= residual >> 2;

       bfd_put_32 (input_bfd, insn, hit_data);
      }
      return bfd_reloc_ok;

    default:
      return bfd_reloc_notsupported;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void elf32_arm_final_write_processing ( bfd abfd,
bfd_boolean linker  ATTRIBUTE_UNUSED 
) [static]

Definition at line 9760 of file elf32-arm.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean elf32_arm_find_inliner_info ( bfd abfd,
const char **  filename_ptr,
const char **  functionname_ptr,
unsigned int line_ptr 
) [static]

Definition at line 8357 of file elf32-arm.c.

{
  bfd_boolean found;
  found = _bfd_dwarf2_find_inliner_info (abfd, filename_ptr,
                                    functionname_ptr, line_ptr,
                                    & elf_tdata (abfd)->dwarf2_find_line_info);
  return found;
}

Here is the call graph for this function:

static bfd_boolean elf32_arm_find_nearest_line ( bfd abfd,
asection section,
asymbol **  symbols,
bfd_vma  offset,
const char **  filename_ptr,
const char **  functionname_ptr,
unsigned int line_ptr 
) [static]

Definition at line 8311 of file elf32-arm.c.

{
  bfd_boolean found = FALSE;

  /* We skip _bfd_dwarf1_find_nearest_line since no known ARM toolchain uses it.  */

  if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
                                 filename_ptr, functionname_ptr,
                                 line_ptr, 0,
                                 & elf_tdata (abfd)->dwarf2_find_line_info))
    {
      if (!*functionname_ptr)
       arm_elf_find_function (abfd, section, symbols, offset,
                            *filename_ptr ? NULL : filename_ptr,
                            functionname_ptr);

      return TRUE;
    }

  if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
                                        & found, filename_ptr,
                                        functionname_ptr, line_ptr,
                                        & elf_tdata (abfd)->line_info))
    return FALSE;

  if (found && (*functionname_ptr || *line_ptr))
    return TRUE;

  if (symbols == NULL)
    return FALSE;

  if (! arm_elf_find_function (abfd, section, symbols, offset,
                            filename_ptr, functionname_ptr))
    return FALSE;

  *line_ptr = 0;
  return TRUE;
}

Here is the call graph for this function:

static bfd_boolean elf32_arm_finish_dynamic_sections ( bfd output_bfd,
struct bfd_link_info info 
) [static]

Definition at line 9426 of file elf32-arm.c.

{
  bfd * dynobj;
  asection * sgot;
  asection * sdyn;

  dynobj = elf_hash_table (info)->dynobj;

  sgot = bfd_get_section_by_name (dynobj, ".got.plt");
  BFD_ASSERT (elf32_arm_hash_table (info)->symbian_p || sgot != NULL);
  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");

  if (elf_hash_table (info)->dynamic_sections_created)
    {
      asection *splt;
      Elf32_External_Dyn *dyncon, *dynconend;
      struct elf32_arm_link_hash_table *htab;

      htab = elf32_arm_hash_table (info);
      splt = bfd_get_section_by_name (dynobj, ".plt");
      BFD_ASSERT (splt != NULL && sdyn != NULL);

      dyncon = (Elf32_External_Dyn *) sdyn->contents;
      dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);

      for (; dyncon < dynconend; dyncon++)
       {
         Elf_Internal_Dyn dyn;
         const char * name;
         asection * s;

         bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);

         switch (dyn.d_tag)
           {
             unsigned int type;

           default:
             break;

           case DT_HASH:
             name = ".hash";
             goto get_vma_if_bpabi;
           case DT_STRTAB:
             name = ".dynstr";
             goto get_vma_if_bpabi;
           case DT_SYMTAB:
             name = ".dynsym";
             goto get_vma_if_bpabi;
           case DT_VERSYM:
             name = ".gnu.version";
             goto get_vma_if_bpabi;
           case DT_VERDEF:
             name = ".gnu.version_d";
             goto get_vma_if_bpabi;
           case DT_VERNEED:
             name = ".gnu.version_r";
             goto get_vma_if_bpabi;

           case DT_PLTGOT:
             name = ".got";
             goto get_vma;
           case DT_JMPREL:
             name = RELOC_SECTION (htab, ".plt");
           get_vma:
             s = bfd_get_section_by_name (output_bfd, name);
             BFD_ASSERT (s != NULL);
             if (!htab->symbian_p)
              dyn.d_un.d_ptr = s->vma;
             else
              /* In the BPABI, tags in the PT_DYNAMIC section point
                 at the file offset, not the memory address, for the
                 convenience of the post linker.  */
              dyn.d_un.d_ptr = s->filepos;
             bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
             break;

           get_vma_if_bpabi:
             if (htab->symbian_p)
              goto get_vma;
             break;

           case DT_PLTRELSZ:
             s = bfd_get_section_by_name (output_bfd,
                                      RELOC_SECTION (htab, ".plt"));
             BFD_ASSERT (s != NULL);
             dyn.d_un.d_val = s->size;
             bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
             break;
             
           case DT_RELSZ:
           case DT_RELASZ:
             if (!htab->symbian_p)
              {
                /* My reading of the SVR4 ABI indicates that the
                   procedure linkage table relocs (DT_JMPREL) should be
                   included in the overall relocs (DT_REL).  This is
                   what Solaris does.  However, UnixWare can not handle
                   that case.  Therefore, we override the DT_RELSZ entry
                   here to make it not include the JMPREL relocs.  Since
                   the linker script arranges for .rel(a).plt to follow all
                   other relocation sections, we don't have to worry
                   about changing the DT_REL entry.  */
                s = bfd_get_section_by_name (output_bfd,
                                          RELOC_SECTION (htab, ".plt"));
                if (s != NULL)
                  dyn.d_un.d_val -= s->size;
                bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
                break;
              }
             /* Fall through */

           case DT_REL:
           case DT_RELA:
             /* In the BPABI, the DT_REL tag must point at the file
               offset, not the VMA, of the first relocation
               section.  So, we use code similar to that in
               elflink.c, but do not check for SHF_ALLOC on the
               relcoation section, since relocations sections are
               never allocated under the BPABI.  The comments above
               about Unixware notwithstanding, we include all of the
               relocations here.  */
             if (htab->symbian_p)
              {
                unsigned int i;
                type = ((dyn.d_tag == DT_REL || dyn.d_tag == DT_RELSZ)
                       ? SHT_REL : SHT_RELA);
                dyn.d_un.d_val = 0;
                for (i = 1; i < elf_numsections (output_bfd); i++)
                  {
                    Elf_Internal_Shdr *hdr 
                     = elf_elfsections (output_bfd)[i];
                    if (hdr->sh_type == type)
                     {
                       if (dyn.d_tag == DT_RELSZ 
                           || dyn.d_tag == DT_RELASZ)
                         dyn.d_un.d_val += hdr->sh_size;
                       else if ((ufile_ptr) hdr->sh_offset
                               <= dyn.d_un.d_val - 1)
                         dyn.d_un.d_val = hdr->sh_offset;
                     }
                  }
                bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
              }
             break;

             /* Set the bottom bit of DT_INIT/FINI if the
               corresponding function is Thumb.  */
           case DT_INIT:
             name = info->init_function;
             goto get_sym;
           case DT_FINI:
             name = info->fini_function;
           get_sym:
             /* If it wasn't set by elf_bfd_final_link
               then there is nothing to adjust.  */
             if (dyn.d_un.d_val != 0)
              {
                struct elf_link_hash_entry * eh;

                eh = elf_link_hash_lookup (elf_hash_table (info), name,
                                        FALSE, FALSE, TRUE);
                if (eh != (struct elf_link_hash_entry *) NULL
                    && ELF_ST_TYPE (eh->type) == STT_ARM_TFUNC)
                  {
                    dyn.d_un.d_val |= 1;
                    bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
                  }
              }
             break;
           }
       }

      /* Fill in the first entry in the procedure linkage table.  */
      if (splt->size > 0 && elf32_arm_hash_table (info)->plt_header_size)
       {
         const bfd_vma *plt0_entry;
         bfd_vma got_address, plt_address, got_displacement;

         /* Calculate the addresses of the GOT and PLT.  */
         got_address = sgot->output_section->vma + sgot->output_offset;
         plt_address = splt->output_section->vma + splt->output_offset;

         if (htab->vxworks_p)
           {
             /* The VxWorks GOT is relocated by the dynamic linker.
               Therefore, we must emit relocations rather than simply
               computing the values now.  */
             Elf_Internal_Rela rel;

             plt0_entry = elf32_arm_vxworks_exec_plt0_entry;
             put_arm_insn (htab, output_bfd, plt0_entry[0],
                         splt->contents + 0);
             put_arm_insn (htab, output_bfd, plt0_entry[1],
                         splt->contents + 4);
             put_arm_insn (htab, output_bfd, plt0_entry[2],
                         splt->contents + 8);
             bfd_put_32 (output_bfd, got_address, splt->contents + 12);

             /* Generate a relocation for _GLOBAL_OFFSET_TABLE_. */
             rel.r_offset = plt_address + 12;
             rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_ARM_ABS32);
             rel.r_addend = 0;
             SWAP_RELOC_OUT (htab) (output_bfd, &rel,
                                 htab->srelplt2->contents);
           }
         else
           {
             got_displacement = got_address - (plt_address + 16);

             plt0_entry = elf32_arm_plt0_entry;
             put_arm_insn (htab, output_bfd, plt0_entry[0],
                         splt->contents + 0);
             put_arm_insn (htab, output_bfd, plt0_entry[1],
                         splt->contents + 4);
             put_arm_insn (htab, output_bfd, plt0_entry[2],
                         splt->contents + 8);
             put_arm_insn (htab, output_bfd, plt0_entry[3],
                         splt->contents + 12);

#ifdef FOUR_WORD_PLT
             /* The displacement value goes in the otherwise-unused
               last word of the second entry.  */
             bfd_put_32 (output_bfd, got_displacement, splt->contents + 28);
#else
             bfd_put_32 (output_bfd, got_displacement, splt->contents + 16);
#endif
           }
       }

      /* UnixWare sets the entsize of .plt to 4, although that doesn't
        really seem like the right value.  */
      if (splt->output_section->owner == output_bfd)
       elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;

      if (htab->vxworks_p && !info->shared && htab->splt->size > 0)
       {
         /* Correct the .rel(a).plt.unloaded relocations.  They will have
            incorrect symbol indexes.  */
         int num_plts;
         unsigned char *p;

         num_plts = ((htab->splt->size - htab->plt_header_size)
                    / htab->plt_entry_size);
         p = htab->srelplt2->contents + RELOC_SIZE (htab);

         for (; num_plts; num_plts--)
           {
             Elf_Internal_Rela rel;

             SWAP_RELOC_IN (htab) (output_bfd, p, &rel);
             rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_ARM_ABS32);
             SWAP_RELOC_OUT (htab) (output_bfd, &rel, p);
             p += RELOC_SIZE (htab);

             SWAP_RELOC_IN (htab) (output_bfd, p, &rel);
             rel.r_info = ELF32_R_INFO (htab->root.hplt->indx, R_ARM_ABS32);
             SWAP_RELOC_OUT (htab) (output_bfd, &rel, p);
             p += RELOC_SIZE (htab);
           }
       }
    }

  /* Fill in the first three entries in the global offset table.  */
  if (sgot)
    {
      if (sgot->size > 0)
       {
         if (sdyn == NULL)
           bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
         else
           bfd_put_32 (output_bfd,
                     sdyn->output_section->vma + sdyn->output_offset,
                     sgot->contents);
         bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 4);
         bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 8);
       }

      elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
    }

  return TRUE;
}

Here is the call graph for this function:

static bfd_boolean elf32_arm_finish_dynamic_symbol ( bfd output_bfd,
struct bfd_link_info info,
struct elf_link_hash_entry h,
Elf_Internal_Sym *  sym 
) [static]

Definition at line 9137 of file elf32-arm.c.

{
  bfd * dynobj;
  struct elf32_arm_link_hash_table *htab;
  struct elf32_arm_link_hash_entry *eh;

  dynobj = elf_hash_table (info)->dynobj;
  htab = elf32_arm_hash_table (info);
  eh = (struct elf32_arm_link_hash_entry *) h;

  if (h->plt.offset != (bfd_vma) -1)
    {
      asection * splt;
      asection * srel;
      bfd_byte *loc;
      bfd_vma plt_index;
      Elf_Internal_Rela rel;

      /* This symbol has an entry in the procedure linkage table.  Set
        it up.  */

      BFD_ASSERT (h->dynindx != -1);

      splt = bfd_get_section_by_name (dynobj, ".plt");
      srel = bfd_get_section_by_name (dynobj, RELOC_SECTION (htab, ".plt"));
      BFD_ASSERT (splt != NULL && srel != NULL);

      /* Fill in the entry in the procedure linkage table.  */
      if (htab->symbian_p)
       {
         put_arm_insn (htab, output_bfd, 
                    elf32_arm_symbian_plt_entry[0],
                    splt->contents + h->plt.offset);
         bfd_put_32 (output_bfd, 
                    elf32_arm_symbian_plt_entry[1],
                    splt->contents + h->plt.offset + 4);
         
         /* Fill in the entry in the .rel.plt section.  */
         rel.r_offset = (splt->output_section->vma
                       + splt->output_offset
                       + h->plt.offset + 4);
         rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_GLOB_DAT);

         /* Get the index in the procedure linkage table which
            corresponds to this symbol.  This is the index of this symbol
            in all the symbols for which we are making plt entries.  The
            first entry in the procedure linkage table is reserved.  */
         plt_index = ((h->plt.offset - htab->plt_header_size) 
                     / htab->plt_entry_size);
       }
      else
       {
         bfd_vma got_offset, got_address, plt_address;
         bfd_vma got_displacement;
         asection * sgot;
         bfd_byte * ptr;
         
         sgot = bfd_get_section_by_name (dynobj, ".got.plt");
         BFD_ASSERT (sgot != NULL);

         /* Get the offset into the .got.plt table of the entry that
            corresponds to this function.  */
         got_offset = eh->plt_got_offset;

         /* Get the index in the procedure linkage table which
            corresponds to this symbol.  This is the index of this symbol
            in all the symbols for which we are making plt entries.  The
            first three entries in .got.plt are reserved; after that
            symbols appear in the same order as in .plt.  */
         plt_index = (got_offset - 12) / 4;

         /* Calculate the address of the GOT entry.  */
         got_address = (sgot->output_section->vma
                      + sgot->output_offset
                      + got_offset);

         /* ...and the address of the PLT entry.  */
         plt_address = (splt->output_section->vma
                      + splt->output_offset
                      + h->plt.offset);

         ptr = htab->splt->contents + h->plt.offset;
         if (htab->vxworks_p && info->shared)
           {
             unsigned int i;
             bfd_vma val;

             for (i = 0; i != htab->plt_entry_size / 4; i++, ptr += 4)
              {
                val = elf32_arm_vxworks_shared_plt_entry[i];
                if (i == 2)
                  val |= got_address - sgot->output_section->vma;
                if (i == 5)
                  val |= plt_index * RELOC_SIZE (htab);
                if (i == 2 || i == 5)
                  bfd_put_32 (output_bfd, val, ptr);
                else
                  put_arm_insn (htab, output_bfd, val, ptr);
              }
           }
         else if (htab->vxworks_p)
           {
             unsigned int i;
             bfd_vma val;

             for (i = 0; i != htab->plt_entry_size / 4; i++)
              {
                val = elf32_arm_vxworks_exec_plt_entry[i];
                if (i == 2)
                  val |= got_address;
                if (i == 4)
                  val |= 0xffffff & -((h->plt.offset + i * 4 + 8) >> 2);
                if (i == 5)
                  val |= plt_index * RELOC_SIZE (htab);
                if (i == 2 || i == 5)
                  bfd_put_32 (output_bfd, val, ptr);
                else
                  put_arm_insn (htab, output_bfd, val, ptr);
              }

             loc = (htab->srelplt2->contents
                   + (plt_index * 2 + 1) * RELOC_SIZE (htab));

             /* Create the .rela.plt.unloaded R_ARM_ABS32 relocation
               referencing the GOT for this PLT entry.  */
             rel.r_offset = plt_address + 8;
             rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_ARM_ABS32);
             rel.r_addend = got_offset;
             SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc);
             loc += RELOC_SIZE (htab);

             /* Create the R_ARM_ABS32 relocation referencing the
               beginning of the PLT for this GOT entry.  */
             rel.r_offset = got_address;
             rel.r_info = ELF32_R_INFO (htab->root.hplt->indx, R_ARM_ABS32);
             rel.r_addend = 0;
             SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc);
           }
         else
           {
             /* Calculate the displacement between the PLT slot and the
               entry in the GOT.  The eight-byte offset accounts for the
               value produced by adding to pc in the first instruction
               of the PLT stub.  */
             got_displacement = got_address - (plt_address + 8);

             BFD_ASSERT ((got_displacement & 0xf0000000) == 0);

             if (!htab->use_blx && eh->plt_thumb_refcount > 0)
              {
                put_thumb_insn (htab, output_bfd,
                              elf32_arm_plt_thumb_stub[0], ptr - 4);
                put_thumb_insn (htab, output_bfd,
                              elf32_arm_plt_thumb_stub[1], ptr - 2);
              }

             put_arm_insn (htab, output_bfd,
                         elf32_arm_plt_entry[0]
                         | ((got_displacement & 0x0ff00000) >> 20),
                         ptr + 0);
             put_arm_insn (htab, output_bfd,
                         elf32_arm_plt_entry[1]
                         | ((got_displacement & 0x000ff000) >> 12),
                         ptr+ 4);
             put_arm_insn (htab, output_bfd,
                         elf32_arm_plt_entry[2]
                         | (got_displacement & 0x00000fff),
                         ptr + 8);
#ifdef FOUR_WORD_PLT
             bfd_put_32 (output_bfd, elf32_arm_plt_entry[3], ptr + 12);
#endif
           }

         /* Fill in the entry in the global offset table.  */
         bfd_put_32 (output_bfd,
                    (splt->output_section->vma
                     + splt->output_offset),
                    sgot->contents + got_offset);
         
         /* Fill in the entry in the .rel(a).plt section.  */
         rel.r_addend = 0;
         rel.r_offset = got_address;
         rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_JUMP_SLOT);
       }

      loc = srel->contents + plt_index * RELOC_SIZE (htab);
      SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc);

      if (!h->def_regular)
       {
         /* Mark the symbol as undefined, rather than as defined in
            the .plt section.  Leave the value alone.  */
         sym->st_shndx = SHN_UNDEF;
         /* If the symbol is weak, we do 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.  */
         if (!h->ref_regular_nonweak)
           sym->st_value = 0;
       }
    }

  if (h->got.offset != (bfd_vma) -1
      && (elf32_arm_hash_entry (h)->tls_type & GOT_TLS_GD) == 0
      && (elf32_arm_hash_entry (h)->tls_type & GOT_TLS_IE) == 0)
    {
      asection * sgot;
      asection * srel;
      Elf_Internal_Rela rel;
      bfd_byte *loc;
      bfd_vma offset;

      /* This symbol has an entry in the global offset table.  Set it
        up.  */
      sgot = bfd_get_section_by_name (dynobj, ".got");
      srel = bfd_get_section_by_name (dynobj, RELOC_SECTION (htab, ".got"));
      BFD_ASSERT (sgot != NULL && srel != NULL);

      offset = (h->got.offset & ~(bfd_vma) 1);
      rel.r_addend = 0;
      rel.r_offset = (sgot->output_section->vma
                    + sgot->output_offset
                    + offset);

      /* If this is a static link, or it is a -Bsymbolic link and the
        symbol is defined locally or was forced to be local because
        of a version file, we just want to emit a RELATIVE reloc.
        The entry in the global offset table will already have been
        initialized in the relocate_section function.  */
      if (info->shared
         && SYMBOL_REFERENCES_LOCAL (info, h))
       {
         BFD_ASSERT((h->got.offset & 1) != 0);
         rel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
         if (!htab->use_rel)
           {
             rel.r_addend = bfd_get_32 (output_bfd, sgot->contents + offset);
             bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + offset);
           }
       }
      else
       {
         BFD_ASSERT((h->got.offset & 1) == 0);
         bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + offset);
         rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_GLOB_DAT);
       }

      loc = srel->contents + srel->reloc_count++ * RELOC_SIZE (htab);
      SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc);
    }

  if (h->needs_copy)
    {
      asection * s;
      Elf_Internal_Rela rel;
      bfd_byte *loc;

      /* This symbol needs a copy reloc.  Set it up.  */
      BFD_ASSERT (h->dynindx != -1
                && (h->root.type == bfd_link_hash_defined
                    || h->root.type == bfd_link_hash_defweak));

      s = bfd_get_section_by_name (h->root.u.def.section->owner,
                               RELOC_SECTION (htab, ".bss"));
      BFD_ASSERT (s != NULL);

      rel.r_addend = 0;
      rel.r_offset = (h->root.u.def.value
                    + h->root.u.def.section->output_section->vma
                    + h->root.u.def.section->output_offset);
      rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_COPY);
      loc = s->contents + s->reloc_count++ * RELOC_SIZE (htab);
      SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc);
    }

  /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  On VxWorks,
     the _GLOBAL_OFFSET_TABLE_ symbol is not absolute: it is relative
     to the ".got" section.  */
  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
      || (!htab->vxworks_p && h == htab->root.hgot))
    sym->st_shndx = SHN_ABS;

  return TRUE;
}

Here is the call graph for this function:

Definition at line 8195 of file elf32-arm.c.

{
  bfd *sub;
  Elf_Internal_Shdr **elf_shdrp;
  bfd_boolean again;

  /* Marking EH data may cause additional code sections to be marked,
     requiring multiple passes.  */
  again = TRUE;
  while (again)
    {
      again = FALSE;
      for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
       {
         asection *o;

         if (bfd_get_flavour (sub) != bfd_target_elf_flavour)
           continue;

         elf_shdrp = elf_elfsections (sub);
         for (o = sub->sections; o != NULL; o = o->next)
           {
             Elf_Internal_Shdr *hdr;
             hdr = &elf_section_data (o)->this_hdr;
             if (hdr->sh_type == SHT_ARM_EXIDX && hdr->sh_link
                && !o->gc_mark
                && elf_shdrp[hdr->sh_link]->bfd_section->gc_mark)
              {
                again = TRUE;
                if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
                  return FALSE;
              }
           }
       }
    }

  return TRUE;
}

Here is the call graph for this function:

static asection* elf32_arm_gc_mark_hook ( asection sec,
struct bfd_link_info info,
Elf_Internal_Rela rel,
struct elf_link_hash_entry h,
Elf_Internal_Sym *  sym 
) [static]

Definition at line 7718 of file elf32-arm.c.

{
  if (h != NULL)
    switch (ELF32_R_TYPE (rel->r_info))
      {
      case R_ARM_GNU_VTINHERIT:
      case R_ARM_GNU_VTENTRY:
       return NULL;
      }

  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
}

Here is the call graph for this function:

static bfd_boolean elf32_arm_gc_sweep_hook ( bfd abfd,
struct bfd_link_info info,
asection sec,
const Elf_Internal_Rela relocs 
) [static]

Definition at line 7738 of file elf32-arm.c.

{
  Elf_Internal_Shdr *symtab_hdr;
  struct elf_link_hash_entry **sym_hashes;
  bfd_signed_vma *local_got_refcounts;
  const Elf_Internal_Rela *rel, *relend;
  struct elf32_arm_link_hash_table * globals;

  globals = elf32_arm_hash_table (info);

  elf_section_data (sec)->local_dynrel = NULL;

  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
  sym_hashes = elf_sym_hashes (abfd);
  local_got_refcounts = elf_local_got_refcounts (abfd);

  relend = relocs + sec->reloc_count;
  for (rel = relocs; rel < relend; rel++)
    {
      unsigned long r_symndx;
      struct elf_link_hash_entry *h = NULL;
      int r_type;

      r_symndx = ELF32_R_SYM (rel->r_info);
      if (r_symndx >= symtab_hdr->sh_info)
       {
         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;
       }

      r_type = ELF32_R_TYPE (rel->r_info);
      r_type = arm_real_reloc_type (globals, r_type);
      switch (r_type)
       {
       case R_ARM_GOT32:
       case R_ARM_GOT_PREL:
       case R_ARM_TLS_GD32:
       case R_ARM_TLS_IE32:
         if (h != NULL)
           {
             if (h->got.refcount > 0)
              h->got.refcount -= 1;
           }
         else if (local_got_refcounts != NULL)
           {
             if (local_got_refcounts[r_symndx] > 0)
              local_got_refcounts[r_symndx] -= 1;
           }
         break;

       case R_ARM_TLS_LDM32:
         elf32_arm_hash_table (info)->tls_ldm_got.refcount -= 1;
         break;

       case R_ARM_ABS32:
       case R_ARM_ABS32_NOI:
       case R_ARM_REL32:
       case R_ARM_REL32_NOI:
       case R_ARM_PC24:
       case R_ARM_PLT32:
       case R_ARM_CALL:
       case R_ARM_JUMP24:
       case R_ARM_PREL31:
       case R_ARM_THM_CALL:
       case R_ARM_MOVW_ABS_NC:
       case R_ARM_MOVT_ABS:
       case R_ARM_MOVW_PREL_NC:
       case R_ARM_MOVT_PREL:
       case R_ARM_THM_MOVW_ABS_NC:
       case R_ARM_THM_MOVT_ABS:
       case R_ARM_THM_MOVW_PREL_NC:
       case R_ARM_THM_MOVT_PREL:
         /* Should the interworking branches be here also?  */

         if (h != NULL)
           {
             struct elf32_arm_link_hash_entry *eh;
             struct elf32_arm_relocs_copied **pp;
             struct elf32_arm_relocs_copied *p;

             eh = (struct elf32_arm_link_hash_entry *) h;

             if (h->plt.refcount > 0)
              {
                h->plt.refcount -= 1;
                if (ELF32_R_TYPE (rel->r_info) == R_ARM_THM_CALL)
                  eh->plt_thumb_refcount--;
              }

             if (r_type == R_ARM_ABS32
                || r_type == R_ARM_REL32
                  || r_type == R_ARM_ABS32_NOI
                  || r_type == R_ARM_REL32_NOI)
              {
                for (pp = &eh->relocs_copied; (p = *pp) != NULL;
                     pp = &p->next)
                if (p->section == sec)
                  {
                    p->count -= 1;
                    if (ELF32_R_TYPE (rel->r_info) == R_ARM_REL32
                          || ELF32_R_TYPE (rel->r_info) == R_ARM_REL32_NOI)
                     p->pc_count -= 1;
                    if (p->count == 0)
                     *pp = p->next;
                    break;
                  }
              }
           }
         break;

       default:
         break;
       }
    }

  return TRUE;
}

Here is the call graph for this function:

int elf32_arm_get_eabi_attr_int ( bfd abfd,
int  tag 
)

Definition at line 6804 of file elf32-arm.c.

{
  aeabi_attribute_list *p;

  if (tag < NUM_KNOWN_ATTRIBUTES)
    {
      /* Knwon tags are preallocated.  */
      return elf32_arm_tdata (abfd)->known_eabi_attributes[tag].i;
    }
  else
    {
      for (p = elf32_arm_tdata (abfd)->other_eabi_attributes;
          p;
          p = p->next)
       {
         if (tag == p->tag)
           return p->attr.i;
         if (tag < p->tag)
           break;
       }
      return 0;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int elf32_arm_get_symbol_type ( Elf_Internal_Sym *  elf_sym,
int  type 
) [static]

Definition at line 7694 of file elf32-arm.c.

{
  switch (ELF_ST_TYPE (elf_sym->st_info))
    {
    case STT_ARM_TFUNC:
      return ELF_ST_TYPE (elf_sym->st_info);

    case STT_ARM_16BIT:
      /* If the symbol is not an object, return the STT_ARM_16BIT flag.
        This allows us to distinguish between data used by Thumb instructions
        and non-data (which is probably code) inside Thumb regions of an
        executable.  */
      if (type != STT_OBJECT && type != STT_TLS)
       return ELF_ST_TYPE (elf_sym->st_info);
      break;

    default:
      break;
    }

  return type;
}
static reloc_howto_type* elf32_arm_howto_from_type ( unsigned int  r_type) [static]

Definition at line 1668 of file elf32-arm.c.

{
  if (r_type < NUM_ELEM (elf32_arm_howto_table_1))
    return &elf32_arm_howto_table_1[r_type];

  if (r_type >= R_ARM_RREL32
      && r_type < R_ARM_RREL32 + NUM_ELEM (elf32_arm_howto_table_2))
    return &elf32_arm_howto_table_2[r_type - R_ARM_RREL32];

  return NULL;
}

Here is the caller graph for this function:

static void elf32_arm_info_to_howto ( bfd *abfd  ATTRIBUTE_UNUSED,
arelent bfd_reloc,
Elf_Internal_Rela elf_reloc 
) [static]

Definition at line 1681 of file elf32-arm.c.

{
  unsigned int r_type;

  r_type = ELF32_R_TYPE (elf_reloc->r_info);
  bfd_reloc->howto = elf32_arm_howto_from_type (r_type);
}

Here is the call graph for this function:

static bfd_boolean elf32_arm_is_target_special_symbol ( bfd *abfd  ATTRIBUTE_UNUSED,
asymbol sym 
) [static]

Definition at line 8238 of file elf32-arm.c.

Here is the call graph for this function:

static struct bfd_hash_entry* elf32_arm_link_hash_newfunc ( struct bfd_hash_entry entry,
struct bfd_hash_table table,
const char *  string 
) [static, read]

Definition at line 2265 of file elf32-arm.c.

{
  struct elf32_arm_link_hash_entry * ret =
    (struct elf32_arm_link_hash_entry *) entry;

  /* Allocate the structure if it has not already been allocated by a
     subclass.  */
  if (ret == (struct elf32_arm_link_hash_entry *) NULL)
    ret = bfd_hash_allocate (table, sizeof (struct elf32_arm_link_hash_entry));
  if (ret == NULL)
    return (struct bfd_hash_entry *) ret;

  /* Call the allocation method of the superclass.  */
  ret = ((struct elf32_arm_link_hash_entry *)
        _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
                                 table, string));
  if (ret != NULL)
    {
      ret->relocs_copied = NULL;
      ret->tls_type = GOT_UNKNOWN;
      ret->plt_thumb_refcount = 0;
      ret->plt_got_offset = -1;
      ret->export_glue = NULL;
    }

  return (struct bfd_hash_entry *) ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct bfd_link_hash_table* elf32_arm_link_hash_table_create ( bfd abfd) [static, read]

Definition at line 2457 of file elf32-arm.c.

{
  struct elf32_arm_link_hash_table *ret;
  bfd_size_type amt = sizeof (struct elf32_arm_link_hash_table);

  ret = bfd_malloc (amt);
  if (ret == NULL)
    return NULL;

  if (!_bfd_elf_link_hash_table_init (& ret->root, abfd,
                                  elf32_arm_link_hash_newfunc,
                                  sizeof (struct elf32_arm_link_hash_entry)))
    {
      free (ret);
      return NULL;
    }

  ret->sgot = NULL;
  ret->sgotplt = NULL;
  ret->srelgot = NULL;
  ret->splt = NULL;
  ret->srelplt = NULL;
  ret->sdynbss = NULL;
  ret->srelbss = NULL;
  ret->srelplt2 = NULL;
  ret->thumb_glue_size = 0;
  ret->arm_glue_size = 0;
  ret->vfp11_fix = BFD_ARM_VFP11_FIX_NONE;
  ret->vfp11_erratum_glue_size = 0;
  ret->num_vfp11_fixes = 0;
  ret->bfd_of_glue_owner = NULL;
  ret->byteswap_code = 0;
  ret->target1_is_rel = 0;
  ret->target2_reloc = R_ARM_NONE;
#ifdef FOUR_WORD_PLT
  ret->plt_header_size = 16;
  ret->plt_entry_size = 16;
#else
  ret->plt_header_size = 20;
  ret->plt_entry_size = 12;
#endif
  ret->fix_v4bx = 0;
  ret->use_blx = 0;
  ret->vxworks_p = 0;
  ret->symbian_p = 0;
  ret->use_rel = 1;
  ret->sym_sec.abfd = NULL;
  ret->obfd = abfd;
  ret->tls_ldm_got.refcount = 0;

  return &ret->root.root;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean elf32_arm_merge_eabi_attributes ( bfd ibfd,
bfd obfd 
) [static]

Definition at line 7069 of file elf32-arm.c.

{
  aeabi_attribute *in_attr;
  aeabi_attribute *out_attr;
  aeabi_attribute_list *in_list;
  aeabi_attribute_list *out_list;
  /* Some tags have 0 = don't care, 1 = strong requirement,
     2 = weak requirement.  */
  static const int order_312[3] = {3, 1, 2};
  int i;

  if (!elf32_arm_tdata (obfd)->known_eabi_attributes[0].i)
    {
      /* This is the first object.  Copy the attributes.  */
      copy_eabi_attributes (ibfd, obfd);

      /* Use the Tag_null value to indicate the attributes have been
        initialized.  */
      elf32_arm_tdata (obfd)->known_eabi_attributes[0].i = 1;

      return TRUE;
    }

  in_attr = elf32_arm_tdata (ibfd)->known_eabi_attributes;
  out_attr = elf32_arm_tdata (obfd)->known_eabi_attributes;
  /* This needs to happen before Tag_ABI_FP_number_model is merged.  */
  if (in_attr[Tag_ABI_VFP_args].i != out_attr[Tag_ABI_VFP_args].i)
    {
      /* Ignore mismatches if teh object doesn't use floating point.  */
      if (out_attr[Tag_ABI_FP_number_model].i == 0)
       out_attr[Tag_ABI_VFP_args].i = in_attr[Tag_ABI_VFP_args].i;
      else if (in_attr[Tag_ABI_FP_number_model].i != 0)
       {
         _bfd_error_handler
           (_("ERROR: %B uses VFP register arguments, %B does not"),
            ibfd, obfd);
         return FALSE;
       }
    }

  for (i = 4; i < NUM_KNOWN_ATTRIBUTES; i++)
    {
      /* Merge this attribute with existing attributes.  */
      switch (i)
       {
       case Tag_CPU_raw_name:
       case Tag_CPU_name:
         /* Use whichever has the greatest architecture requirements.  We
            won't necessarily have both the above tags, so make sure input
            name is non-NULL.  */
         if (in_attr[Tag_CPU_arch].i > out_attr[Tag_CPU_arch].i
             && in_attr[i].s)
           out_attr[i].s = attr_strdup(obfd, in_attr[i].s);
         break;

       case Tag_ABI_optimization_goals:
       case Tag_ABI_FP_optimization_goals:
         /* Use the first value seen.  */
         break;

       case Tag_CPU_arch:
       case Tag_ARM_ISA_use:
       case Tag_THUMB_ISA_use:
       case Tag_VFP_arch:
       case Tag_WMMX_arch:
       case Tag_NEON_arch:
         /* ??? Do NEON and WMMX conflict?  */
       case Tag_ABI_FP_rounding:
       case Tag_ABI_FP_denormal:
       case Tag_ABI_FP_exceptions:
       case Tag_ABI_FP_user_exceptions:
       case Tag_ABI_FP_number_model:
       case Tag_ABI_align8_preserved:
       case Tag_ABI_HardFP_use:
         /* Use the largest value specified.  */
         if (in_attr[i].i > out_attr[i].i)
           out_attr[i].i = in_attr[i].i;
         break;

       case Tag_CPU_arch_profile:
         /* Warn if conflicting architecture profiles used.  */
         if (out_attr[i].i && in_attr[i].i && in_attr[i].i != out_attr[i].i)
           {
             _bfd_error_handler
              (_("ERROR: %B: Conflicting architecture profiles %c/%c"),
               ibfd, in_attr[i].i, out_attr[i].i);
             return FALSE;
           }
         if (in_attr[i].i)
           out_attr[i].i = in_attr[i].i;
         break;
       case Tag_PCS_config:
         if (out_attr[i].i == 0)
           out_attr[i].i = in_attr[i].i;
         else if (in_attr[i].i != 0 && out_attr[i].i != 0)
           {
             /* It's sometimes ok to mix different configs, so this is only
                a warning.  */
             _bfd_error_handler
              (_("Warning: %B: Conflicting platform configuration"), ibfd);
           }
         break;
       case Tag_ABI_PCS_R9_use:
         if (in_attr[i].i != out_attr[i].i
             && out_attr[i].i != AEABI_R9_unused
             && in_attr[i].i != AEABI_R9_unused)
           {
             _bfd_error_handler
              (_("ERROR: %B: Conflicting use of R9"), ibfd);
             return FALSE;
           }
         if (out_attr[i].i == AEABI_R9_unused)
           out_attr[i].i = in_attr[i].i;
         break;
       case Tag_ABI_PCS_RW_data:
         if (in_attr[i].i == AEABI_PCS_RW_data_SBrel
             && out_attr[Tag_ABI_PCS_R9_use].i != AEABI_R9_SB
             && out_attr[Tag_ABI_PCS_R9_use].i != AEABI_R9_unused)
           {
             _bfd_error_handler
              (_("ERROR: %B: SB relative addressing conflicts with use of R9"),
               ibfd);
             return FALSE;
           }
         /* Use the smallest value specified.  */
         if (in_attr[i].i < out_attr[i].i)
           out_attr[i].i = in_attr[i].i;
         break;
       case Tag_ABI_PCS_RO_data:
         /* Use the smallest value specified.  */
         if (in_attr[i].i < out_attr[i].i)
           out_attr[i].i = in_attr[i].i;
         break;
       case Tag_ABI_PCS_GOT_use:
         if (in_attr[i].i > 2 || out_attr[i].i > 2
             || order_312[in_attr[i].i] < order_312[out_attr[i].i])
           out_attr[i].i = in_attr[i].i;
         break;
       case Tag_ABI_PCS_wchar_t:
         if (out_attr[i].i && in_attr[i].i && out_attr[i].i != in_attr[i].i)
           {
             _bfd_error_handler
              (_("ERROR: %B: Conflicting definitions of wchar_t"), ibfd);
             return FALSE;
           }
         if (in_attr[i].i)
           out_attr[i].i = in_attr[i].i;
         break;
       case Tag_ABI_align8_needed:
         /* ??? Check against Tag_ABI_align8_preserved.  */
         if (in_attr[i].i > 2 || out_attr[i].i > 2
             || order_312[in_attr[i].i] < order_312[out_attr[i].i])
           out_attr[i].i = in_attr[i].i;
         break;
       case Tag_ABI_enum_size:
         if (in_attr[i].i != AEABI_enum_unused)
           {
             if (out_attr[i].i == AEABI_enum_unused
                || out_attr[i].i == AEABI_enum_forced_wide)
              {
                /* The existing object is compatible with anything.
                   Use whatever requirements the new object has.  */
                out_attr[i].i = in_attr[i].i;
              }
             else if (in_attr[i].i != AEABI_enum_forced_wide
                     && out_attr[i].i != in_attr[i].i
                     && !elf32_arm_tdata (obfd)->no_enum_size_warning)
              {
                const char *aeabi_enum_names[] =
                  { "", "variable-size", "32-bit", "" };
                _bfd_error_handler
                  (_("warning: %B uses %s enums yet the output is to use %s enums; use of enum values across objects may fail"),
                   ibfd, aeabi_enum_names[in_attr[i].i],
                   aeabi_enum_names[out_attr[i].i]);
              }
           }
         break;
       case Tag_ABI_VFP_args:
         /* Aready done.  */
         break;
       case Tag_ABI_WMMX_args:
         if (in_attr[i].i != out_attr[i].i)
           {
             _bfd_error_handler
              (_("ERROR: %B uses iWMMXt register arguments, %B does not"),
               ibfd, obfd);
             return FALSE;
           }
         break;
       default: /* All known attributes should be explicitly covered.   */
         abort ();
       }
    }

  in_list = elf32_arm_tdata (ibfd)->other_eabi_attributes;
  out_list = elf32_arm_tdata (ibfd)->other_eabi_attributes;
  while (in_list && in_list->tag == Tag_compatibility)
    {
      in_attr = &in_list->attr;
      if (in_attr->i == 0)
       continue;
      if (in_attr->i == 1)
       {
         _bfd_error_handler
           (_("ERROR: %B: Must be processed by '%s' toolchain"),
            ibfd, in_attr->s);
         return FALSE;
       }
      if (!out_list || out_list->tag != Tag_compatibility
         || strcmp (in_attr->s, out_list->attr.s) != 0)
       {
         /* Add this compatibility tag to the output.  */
         elf32_arm_add_eabi_attr_compat (obfd, in_attr->i, in_attr->s);
         continue;
       }
      out_attr = &out_list->attr;
      /* Check all the input tags with the same identifier.  */
      for (;;)
       {
         if (out_list->tag != Tag_compatibility
             || in_attr->i != out_attr->i
             || strcmp (in_attr->s, out_attr->s) != 0)
           {
             _bfd_error_handler
              (_("ERROR: %B: Incompatible object tag '%s':%d"),
               ibfd, in_attr->s, in_attr->i);
             return FALSE;
           }
         in_list = in_list->next;
         if (in_list->tag != Tag_compatibility
             || strcmp (in_attr->s, in_list->attr.s) != 0)
           break;
         in_attr = &in_list->attr;
         out_list = out_list->next;
         if (out_list)
           out_attr = &out_list->attr;
       }

      /* Check the output doesn't have extra tags with this identifier.  */
      if (out_list && out_list->tag == Tag_compatibility
         && strcmp (in_attr->s, out_list->attr.s) == 0)
       {
         _bfd_error_handler
           (_("ERROR: %B: Incompatible object tag '%s':%d"),
            ibfd, in_attr->s, out_list->attr.i);
         return FALSE;
       }
    }

  for (; in_list; in_list = in_list->next)
    {
      if ((in_list->tag & 128) < 64)
       {
         _bfd_error_handler
           (_("Warning: %B: Unknown EABI object attribute %d"),
            ibfd, in_list->tag);
         break;
       }
    }
  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean elf32_arm_merge_private_bfd_data ( bfd ibfd,
bfd obfd 
) [static]

Definition at line 7350 of file elf32-arm.c.

{
  flagword out_flags;
  flagword in_flags;
  bfd_boolean flags_compatible = TRUE;
  asection *sec;

  /* Check if we have the same endianess.  */
  if (! _bfd_generic_verify_endian_match (ibfd, obfd))
    return FALSE;

  if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
    return TRUE;

  if (!elf32_arm_merge_eabi_attributes (ibfd, obfd))
    return FALSE;

  /* The input BFD must have had its flags initialised.  */
  /* The following seems bogus to me -- The flags are initialized in
     the assembler but I don't think an elf_flags_init field is
     written into the object.  */
  /* BFD_ASSERT (elf_flags_init (ibfd)); */

  in_flags  = elf_elfheader (ibfd)->e_flags;
  out_flags = elf_elfheader (obfd)->e_flags;

  if (!elf_flags_init (obfd))
    {
      /* If the input is the default architecture and had the default
        flags then do not bother setting the flags for the output
        architecture, instead allow future merges to do this.  If no
        future merges ever set these flags then they will retain their
         uninitialised values, which surprise surprise, correspond
         to the default values.  */
      if (bfd_get_arch_info (ibfd)->the_default
         && elf_elfheader (ibfd)->e_flags == 0)
       return TRUE;

      elf_flags_init (obfd) = TRUE;
      elf_elfheader (obfd)->e_flags = in_flags;

      if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
         && bfd_get_arch_info (obfd)->the_default)
       return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));

      return TRUE;
    }

  /* Determine what should happen if the input ARM architecture
     does not match the output ARM architecture.  */
  if (! bfd_arm_merge_machines (ibfd, obfd))
    return FALSE;

  /* Identical flags must be compatible.  */
  if (in_flags == out_flags)
    return TRUE;

  /* Check to see if the input BFD actually contains any sections.  If
     not, its flags may not have been initialised either, but it
     cannot actually cause any incompatiblity.  Do not short-circuit
     dynamic objects; their section list may be emptied by
    elf_link_add_object_symbols.

    Also check to see if there are no code sections in the input.
    In this case there is no need to check for code specific flags.
    XXX - do we need to worry about floating-point format compatability
    in data sections ?  */
  if (!(ibfd->flags & DYNAMIC))
    {
      bfd_boolean null_input_bfd = TRUE;
      bfd_boolean only_data_sections = TRUE;

      for (sec = ibfd->sections; sec != NULL; sec = sec->next)
       {
         /* Ignore synthetic glue sections.  */
         if (strcmp (sec->name, ".glue_7")
             && strcmp (sec->name, ".glue_7t"))
           {
             if ((bfd_get_section_flags (ibfd, sec)
                 & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
                == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
              only_data_sections = FALSE;

             null_input_bfd = FALSE;
             break;
           }
       }

      if (null_input_bfd || only_data_sections)
       return TRUE;
    }

  /* Complain about various flag mismatches.  */
  if (!elf32_arm_versions_compatible (EF_ARM_EABI_VERSION (in_flags),
                                  EF_ARM_EABI_VERSION (out_flags)))
    {
      _bfd_error_handler
       (_("ERROR: Source object %B has EABI version %d, but target %B has EABI version %d"),
        ibfd, obfd,
        (in_flags & EF_ARM_EABIMASK) >> 24,
        (out_flags & EF_ARM_EABIMASK) >> 24);
      return FALSE;
    }

  /* Not sure what needs to be checked for EABI versions >= 1.  */
  /* VxWorks libraries do not use these flags.  */
  if (get_elf_backend_data (obfd) != &elf32_arm_vxworks_bed
      && get_elf_backend_data (ibfd) != &elf32_arm_vxworks_bed
      && EF_ARM_EABI_VERSION (in_flags) == EF_ARM_EABI_UNKNOWN)
    {
      if ((in_flags & EF_ARM_APCS_26) != (out_flags & EF_ARM_APCS_26))
       {
         _bfd_error_handler
           (_("ERROR: %B is compiled for APCS-%d, whereas target %B uses APCS-%d"),
            ibfd, obfd,
            in_flags & EF_ARM_APCS_26 ? 26 : 32,
            out_flags & EF_ARM_APCS_26 ? 26 : 32);
         flags_compatible = FALSE;
       }

      if ((in_flags & EF_ARM_APCS_FLOAT) != (out_flags & EF_ARM_APCS_FLOAT))
       {
         if (in_flags & EF_ARM_APCS_FLOAT)
           _bfd_error_handler
             (_("ERROR: %B passes floats in float registers, whereas %B passes them in integer registers"),
              ibfd, obfd);
         else
           _bfd_error_handler
             (_("ERROR: %B passes floats in integer registers, whereas %B passes them in float registers"),
              ibfd, obfd);

         flags_compatible = FALSE;
       }

      if ((in_flags & EF_ARM_VFP_FLOAT) != (out_flags & EF_ARM_VFP_FLOAT))
       {
         if (in_flags & EF_ARM_VFP_FLOAT)
           _bfd_error_handler
             (_("ERROR: %B uses VFP instructions, whereas %B does not"),
              ibfd, obfd);
         else
           _bfd_error_handler
             (_("ERROR: %B uses FPA instructions, whereas %B does not"),
              ibfd, obfd);

         flags_compatible = FALSE;
       }

      if ((in_flags & EF_ARM_MAVERICK_FLOAT) != (out_flags & EF_ARM_MAVERICK_FLOAT))
       {
         if (in_flags & EF_ARM_MAVERICK_FLOAT)
           _bfd_error_handler
             (_("ERROR: %B uses Maverick instructions, whereas %B does not"),
              ibfd, obfd);
         else
           _bfd_error_handler
             (_("ERROR: %B does not use Maverick instructions, whereas %B does"),
              ibfd, obfd);

         flags_compatible = FALSE;
       }

#ifdef EF_ARM_SOFT_FLOAT
      if ((in_flags & EF_ARM_SOFT_FLOAT) != (out_flags & EF_ARM_SOFT_FLOAT))
       {
         /* We can allow interworking between code that is VFP format
            layout, and uses either soft float or integer regs for
            passing floating point arguments and results.  We already
            know that the APCS_FLOAT flags match; similarly for VFP
            flags.  */
         if ((in_flags & EF_ARM_APCS_FLOAT) != 0
             || (in_flags & EF_ARM_VFP_FLOAT) == 0)
           {
             if (in_flags & EF_ARM_SOFT_FLOAT)
              _bfd_error_handler
                (_("ERROR: %B uses software FP, whereas %B uses hardware FP"),
                 ibfd, obfd);
             else
              _bfd_error_handler
                (_("ERROR: %B uses hardware FP, whereas %B uses software FP"),
                 ibfd, obfd);

             flags_compatible = FALSE;
           }
       }
#endif

      /* Interworking mismatch is only a warning.  */
      if ((in_flags & EF_ARM_INTERWORK) != (out_flags & EF_ARM_INTERWORK))
       {
         if (in_flags & EF_ARM_INTERWORK)
           {
             _bfd_error_handler
              (_("Warning: %B supports interworking, whereas %B does not"),
               ibfd, obfd);
           }
         else
           {
             _bfd_error_handler
              (_("Warning: %B does not support interworking, whereas %B does"),
               ibfd, obfd);
           }
       }
    }

  return flags_compatible;
}

Here is the call graph for this function:

static bfd_boolean elf32_arm_mkobject ( bfd abfd) [static]

Definition at line 2104 of file elf32-arm.c.

{
  if (abfd->tdata.any == NULL)
    {
      bfd_size_type amt = sizeof (struct elf32_arm_obj_tdata);
      abfd->tdata.any = bfd_zalloc (abfd, amt);
      if (abfd->tdata.any == NULL)
       return FALSE;
    }
  return bfd_elf_mkobject (abfd);
}

Here is the call graph for this function:

static bfd_boolean elf32_arm_modify_segment_map ( bfd abfd,
struct bfd_link_info *info  ATTRIBUTE_UNUSED 
) [static]

Definition at line 10513 of file elf32-arm.c.

{
  struct elf_segment_map *m;
  asection *sec;

  sec = bfd_get_section_by_name (abfd, ".ARM.exidx");
  if (sec != NULL && (sec->flags & SEC_LOAD) != 0)
    {
      /* If there is already a PT_ARM_EXIDX header, then we do not
        want to add another one.  This situation arises when running
        "strip"; the input binary already has the header.  */
      m = elf_tdata (abfd)->segment_map;
      while (m && m->p_type != PT_ARM_EXIDX)
       m = m->next;
      if (!m)
       {
         m = bfd_zalloc (abfd, sizeof (struct elf_segment_map));
         if (m == NULL)
           return FALSE;
         m->p_type = PT_ARM_EXIDX;
         m->count = 1;
         m->sections[0] = sec;

         m->next = elf_tdata (abfd)->segment_map;
         elf_tdata (abfd)->segment_map = m;
       }
    }

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean elf32_arm_nabi_grok_prstatus ( bfd abfd,
Elf_Internal_Note note 
) [static]

Definition at line 1817 of file elf32-arm.c.

{
  int offset;
  size_t size;

  switch (note->descsz)
    {
      default:
       return FALSE;

      case 148:             /* Linux/ARM 32-bit*/
       /* pr_cursig */
       elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);

       /* pr_pid */
       elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);

       /* pr_reg */
       offset = 72;
       size = 72;

       break;
    }

  /* Make a ".reg/999" section.  */
  return _bfd_elfcore_make_pseudosection (abfd, ".reg",
                                     size, note->descpos + offset);
}

Here is the call graph for this function:

static bfd_boolean elf32_arm_nabi_grok_psinfo ( bfd abfd,
Elf_Internal_Note note 
) [static]

Definition at line 1847 of file elf32-arm.c.

{
  switch (note->descsz)
    {
      default:
       return FALSE;

      case 124:             /* Linux/ARM elf_prpsinfo */
       elf_tdata (abfd)->core_program
        = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16);
       elf_tdata (abfd)->core_command
        = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80);
    }

  /* Note that for some reason, a spurious space is tacked
     onto the end of the args in some (at least one anyway)
     implementations, so strip it off if it exists.  */

  {
    char *command = elf_tdata (abfd)->core_command;
    int n = strlen (command);

    if (0 < n && command[n - 1] == ' ')
      command[n - 1] = '\0';
  }

  return TRUE;
}

Here is the call graph for this function:

static aeabi_attribute* elf32_arm_new_eabi_attr ( bfd abfd,
int  tag 
) [static]

Definition at line 6767 of file elf32-arm.c.

{
  aeabi_attribute *attr;
  aeabi_attribute_list *list;
  aeabi_attribute_list *p;
  aeabi_attribute_list **lastp;


  if (tag < NUM_KNOWN_ATTRIBUTES)
    {
      /* Knwon tags are preallocated.  */
      attr = &elf32_arm_tdata (abfd)->known_eabi_attributes[tag];
    }
  else
    {
      /* Create a new tag.  */
      list = (aeabi_attribute_list *)
       bfd_alloc (abfd, sizeof (aeabi_attribute_list));
      memset (list, 0, sizeof (aeabi_attribute_list));
      list->tag = tag;
      /* Keep the tag list in order.  */
      lastp = &elf32_arm_tdata (abfd)->other_eabi_attributes;
      for (p = *lastp; p; p = p->next)
       {
         if (tag < p->tag)
           break;
         lastp = &p->next;
       }
      list->next = *lastp;
      *lastp = list;
      attr = &list->attr;
    }

  return attr;
}

Here is the call graph for this function:

Here is the caller graph for this function: