X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felf32-arm.c;h=aa01a59e9a2d787ce4ba40243fdadf752ecca97a;hb=017e6bceee1a96d4b57175687560b4d625fdb150;hp=2ed4741b98506dedf8ed0ed9bd77d3feee64c576;hpb=aba8c3de87953e47e5ab45f63789363a22aa0841;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 2ed4741b98..aa01a59e9a 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -1,6 +1,5 @@ /* 32-bit ELF support for ARM - Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. + Copyright (C) 1998-2015 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -80,7 +79,7 @@ static reloc_howto_type elf32_arm_howto_table_1[] = /* No relocation. */ HOWTO (R_ARM_NONE, /* type */ 0, /* rightshift */ - 0, /* size (0 = byte, 1 = short, 2 = long) */ + 3, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ @@ -1607,7 +1606,7 @@ static reloc_howto_type elf32_arm_howto_table_1[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + NULL, /* special_function */ "R_ARM_TLS_LE32", /* name */ TRUE, /* partial_inplace */ 0xffffffff, /* src_mask */ @@ -2041,9 +2040,9 @@ elf32_arm_nabi_write_core_note (bfd *abfd, char *buf, int *bufsiz, } } -#define TARGET_LITTLE_SYM bfd_elf32_littlearm_vec +#define TARGET_LITTLE_SYM arm_elf32_le_vec #define TARGET_LITTLE_NAME "elf32-littlearm" -#define TARGET_BIG_SYM bfd_elf32_bigarm_vec +#define TARGET_BIG_SYM arm_elf32_be_vec #define TARGET_BIG_NAME "elf32-bigarm" #define elf_backend_grok_prstatus elf32_arm_nabi_grok_prstatus @@ -2126,7 +2125,7 @@ static const bfd_vma elf32_arm_plt_entry [] = 0x00000000, /* unused */ }; -#else +#else /* not FOUR_WORD_PLT */ /* The first entry in a procedure linkage table looks like this. It is set up so that any shared library function that is @@ -2141,16 +2140,55 @@ static const bfd_vma elf32_arm_plt0_entry [] = 0x00000000, /* &GOT[0] - . */ }; -/* Subsequent entries in a procedure linkage table look like - this. */ -static const bfd_vma elf32_arm_plt_entry [] = +/* By default subsequent entries in a procedure linkage table look like + this. Offsets that don't fit into 28 bits will cause link error. */ +static const bfd_vma elf32_arm_plt_entry_short [] = { 0xe28fc600, /* add ip, pc, #0xNN00000 */ 0xe28cca00, /* add ip, ip, #0xNN000 */ 0xe5bcf000, /* ldr pc, [ip, #0xNNN]! */ }; -#endif +/* When explicitly asked, we'll use this "long" entry format + which can cope with arbitrary displacements. */ +static const bfd_vma elf32_arm_plt_entry_long [] = +{ + 0xe28fc200, /* add ip, pc, #0xN0000000 */ + 0xe28cc600, /* add ip, ip, #0xNN00000 */ + 0xe28cca00, /* add ip, ip, #0xNN000 */ + 0xe5bcf000, /* ldr pc, [ip, #0xNNN]! */ +}; + +static bfd_boolean elf32_arm_use_long_plt_entry = FALSE; + +#endif /* not FOUR_WORD_PLT */ + +/* The first entry in a procedure linkage table looks like this. + It is set up so that any shared library function that is called before the + relocation has been set up calls the dynamic linker first. */ +static const bfd_vma elf32_thumb2_plt0_entry [] = +{ + /* NOTE: As this is a mixture of 16-bit and 32-bit instructions, + an instruction maybe encoded to one or two array elements. */ + 0xf8dfb500, /* push {lr} */ + 0x44fee008, /* ldr.w lr, [pc, #8] */ + /* add lr, pc */ + 0xff08f85e, /* ldr.w pc, [lr, #8]! */ + 0x00000000, /* &GOT[0] - . */ +}; + +/* Subsequent entries in a procedure linkage table for thumb only target + look like this. */ +static const bfd_vma elf32_thumb2_plt_entry [] = +{ + /* NOTE: As this is a mixture of 16-bit and 32-bit instructions, + an instruction maybe encoded to one or two array elements. */ + 0x0c00f240, /* movw ip, #0xNNNN */ + 0x0c00f2c0, /* movt ip, #0xNNNN */ + 0xf8dc44fc, /* add ip, pc */ + 0xbf00f000 /* ldr.w pc, [ip] */ + /* nop */ +}; /* The format of the first entry in the procedure linkage table for a VxWorks executable. */ @@ -2245,6 +2283,8 @@ static const bfd_vma elf32_arm_nacl_plt_entry [] = #define THM_MAX_BWD_BRANCH_OFFSET (-(1 << 22) + 4) #define THM2_MAX_FWD_BRANCH_OFFSET (((1 << 24) - 2) + 4) #define THM2_MAX_BWD_BRANCH_OFFSET (-(1 << 24) + 4) +#define THM2_MAX_FWD_COND_BRANCH_OFFSET (((1 << 20) -2) + 4) +#define THM2_MAX_BWD_COND_BRANCH_OFFSET (-(1 << 20) + 4) enum stub_insn_type { @@ -2416,6 +2456,33 @@ static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_tls_pic[] = DATA_WORD (0, R_ARM_REL32, -4), /* dcd R_ARM_REL32(X) */ }; +/* NaCl ARM -> ARM long branch stub. */ +static const insn_sequence elf32_arm_stub_long_branch_arm_nacl[] = +{ + ARM_INSN (0xe59fc00c), /* ldr ip, [pc, #12] */ + ARM_INSN (0xe3ccc13f), /* bic ip, ip, #0xc000000f */ + ARM_INSN (0xe12fff1c), /* bx ip */ + ARM_INSN (0xe320f000), /* nop */ + ARM_INSN (0xe125be70), /* bkpt 0x5be0 */ + DATA_WORD (0, R_ARM_ABS32, 0), /* dcd R_ARM_ABS32(X) */ + DATA_WORD (0, R_ARM_NONE, 0), /* .word 0 */ + DATA_WORD (0, R_ARM_NONE, 0), /* .word 0 */ +}; + +/* NaCl ARM -> ARM long branch stub, PIC. */ +static const insn_sequence elf32_arm_stub_long_branch_arm_nacl_pic[] = +{ + ARM_INSN (0xe59fc00c), /* ldr ip, [pc, #12] */ + ARM_INSN (0xe08cc00f), /* add ip, ip, pc */ + ARM_INSN (0xe3ccc13f), /* bic ip, ip, #0xc000000f */ + ARM_INSN (0xe12fff1c), /* bx ip */ + ARM_INSN (0xe125be70), /* bkpt 0x5be0 */ + DATA_WORD (0, R_ARM_REL32, 8), /* dcd R_ARM_REL32(X+8) */ + DATA_WORD (0, R_ARM_NONE, 0), /* .word 0 */ + DATA_WORD (0, R_ARM_NONE, 0), /* .word 0 */ +}; + + /* Cortex-A8 erratum-workaround stubs. */ /* Stub used for conditional branches (which may be beyond +/-1MB away, so we @@ -2492,6 +2559,8 @@ static const insn_sequence elf32_arm_stub_a8_veneer_blx[] = DEF_STUB(long_branch_thumb_only_pic) \ DEF_STUB(long_branch_any_tls_pic) \ DEF_STUB(long_branch_v4t_thumb_tls_pic) \ + DEF_STUB(long_branch_arm_nacl) \ + DEF_STUB(long_branch_arm_nacl_pic) \ DEF_STUB(a8_veneer_b_cond) \ DEF_STUB(a8_veneer_b) \ DEF_STUB(a8_veneer_bl) \ @@ -2502,7 +2571,7 @@ enum elf32_arm_stub_type { arm_stub_none, DEF_STUBS - /* Note the first a8_veneer type */ + /* Note the first a8_veneer type. */ arm_stub_a8_veneer_lwm = arm_stub_a8_veneer_b_cond }; #undef DEF_STUB @@ -2984,7 +3053,7 @@ struct elf32_arm_link_hash_table bfd *stub_bfd; /* Linker call-backs. */ - asection * (*add_stub_section) (const char *, asection *); + asection * (*add_stub_section) (const char *, asection *, unsigned int); void (*layout_sections_again) (void); /* Array to keep track of which stub sections have been created, and @@ -2992,11 +3061,11 @@ struct elf32_arm_link_hash_table struct map_stub *stub_group; /* Number of elements in stub_group. */ - int top_id; + unsigned int top_id; /* Assorted information used by elf32_arm_size_stubs. */ unsigned int bfd_count; - int top_index; + unsigned int top_index; asection **input_list; }; @@ -3289,6 +3358,37 @@ create_ifunc_sections (struct bfd_link_info *info) return TRUE; } +/* Determine if we're dealing with a Thumb only architecture. */ + +static bfd_boolean +using_thumb_only (struct elf32_arm_link_hash_table *globals) +{ + int arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC, + Tag_CPU_arch); + int profile; + + if (arch == TAG_CPU_ARCH_V6_M || arch == TAG_CPU_ARCH_V6S_M) + return TRUE; + + if (arch != TAG_CPU_ARCH_V7 && arch != TAG_CPU_ARCH_V7E_M) + return FALSE; + + profile = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC, + Tag_CPU_arch_profile); + + return profile == 'M'; +} + +/* Determine if we're dealing with a Thumb-2 object. */ + +static bfd_boolean +using_thumb2 (struct elf32_arm_link_hash_table *globals) +{ + int arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC, + Tag_CPU_arch); + return arch == TAG_CPU_ARCH_V6T2 || arch >= TAG_CPU_ARCH_V7; +} + /* Create .plt, .rel(a).plt, .got, .got.plt, .rel(a).got, .dynbss, and .rel(a).bss sections in DYNOBJ, and set up shortcuts to them in our hash table. */ @@ -3309,7 +3409,7 @@ elf32_arm_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) return FALSE; htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss"); - if (!info->shared) + if (!bfd_link_pic (info)) htab->srelbss = bfd_get_linker_section (dynobj, RELOC_SECTION (htab, ".bss")); @@ -3318,7 +3418,7 @@ elf32_arm_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) if (!elf_vxworks_create_dynamic_sections (dynobj, info, &htab->srelplt2)) return FALSE; - if (info->shared) + if (bfd_link_pic (info)) { htab->plt_header_size = 0; htab->plt_entry_size @@ -3332,11 +3432,27 @@ elf32_arm_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) = 4 * ARRAY_SIZE (elf32_arm_vxworks_exec_plt_entry); } } + else + { + /* PR ld/16017 + Test for thumb only architectures. Note - we cannot just call + using_thumb_only() as the attributes in the output bfd have not been + initialised at this point, so instead we use the input bfd. */ + bfd * saved_obfd = htab->obfd; + + htab->obfd = dynobj; + if (using_thumb_only (htab)) + { + htab->plt_header_size = 4 * ARRAY_SIZE (elf32_thumb2_plt0_entry); + htab->plt_entry_size = 4 * ARRAY_SIZE (elf32_thumb2_plt_entry); + } + htab->obfd = saved_obfd; + } if (!htab->root.splt || !htab->root.srelplt || !htab->sdynbss - || (!info->shared && !htab->srelbss)) + || (!bfd_link_pic (info) && !htab->srelbss)) abort (); return TRUE; @@ -3409,6 +3525,18 @@ elf32_arm_copy_indirect_symbol (struct bfd_link_info *info, _bfd_elf_link_hash_copy_indirect (info, dir, ind); } +/* Destroy an ARM elf linker hash table. */ + +static void +elf32_arm_link_hash_table_free (bfd *obfd) +{ + struct elf32_arm_link_hash_table *ret + = (struct elf32_arm_link_hash_table *) obfd->link.hash; + + bfd_hash_table_free (&ret->stub_hash_table); + _bfd_elf_link_hash_table_free (obfd); +} + /* Create an ARM elf linker hash table. */ static struct bfd_link_hash_table * @@ -3436,7 +3564,7 @@ elf32_arm_link_hash_table_create (bfd *abfd) ret->plt_entry_size = 16; #else ret->plt_header_size = 20; - ret->plt_entry_size = 12; + ret->plt_entry_size = elf32_arm_use_long_plt_entry ? 16 : 12; #endif ret->use_rel = 1; ret->obfd = abfd; @@ -3444,56 +3572,14 @@ elf32_arm_link_hash_table_create (bfd *abfd) if (!bfd_hash_table_init (&ret->stub_hash_table, stub_hash_newfunc, sizeof (struct elf32_arm_stub_hash_entry))) { - free (ret); + _bfd_elf_link_hash_table_free (abfd); return NULL; } + ret->root.root.hash_table_free = elf32_arm_link_hash_table_free; return &ret->root.root; } -/* Free the derived linker hash table. */ - -static void -elf32_arm_hash_table_free (struct bfd_link_hash_table *hash) -{ - struct elf32_arm_link_hash_table *ret - = (struct elf32_arm_link_hash_table *) hash; - - bfd_hash_table_free (&ret->stub_hash_table); - _bfd_elf_link_hash_table_free (hash); -} - -/* Determine if we're dealing with a Thumb only architecture. */ - -static bfd_boolean -using_thumb_only (struct elf32_arm_link_hash_table *globals) -{ - int arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC, - Tag_CPU_arch); - int profile; - - if (arch == TAG_CPU_ARCH_V6_M || arch == TAG_CPU_ARCH_V6S_M) - return TRUE; - - if (arch != TAG_CPU_ARCH_V7 && arch != TAG_CPU_ARCH_V7E_M) - return FALSE; - - profile = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC, - Tag_CPU_arch_profile); - - return profile == 'M'; -} - -/* Determine if we're dealing with a Thumb-2 object. */ - -static bfd_boolean -using_thumb2 (struct elf32_arm_link_hash_table *globals) -{ - int arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC, - Tag_CPU_arch); - return arch == TAG_CPU_ARCH_V6T2 || arch >= TAG_CPU_ARCH_V7; -} - /* Determine what kind of NOPs are available. */ static bfd_boolean @@ -3581,6 +3667,13 @@ arm_type_of_stub (struct bfd_link_info *info, r_type = ELF32_R_TYPE (rel->r_info); + /* ST_BRANCH_TO_ARM is nonsense to thumb-only targets when we + are considering a function call relocation. */ + if (thumb_only && (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24 + || r_type == R_ARM_THM_JUMP19) + && branch_type == ST_BRANCH_TO_ARM) + branch_type = ST_BRANCH_TO_THUMB; + /* For TLS call relocs, it is the caller's responsibility to provide the address of the appropriate trampoline. */ if (r_type != R_ARM_TLS_CALL @@ -3621,7 +3714,7 @@ arm_type_of_stub (struct bfd_link_info *info, branch_offset = (bfd_signed_vma)(destination - location); if (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24 - || r_type == R_ARM_THM_TLS_CALL) + || r_type == R_ARM_THM_TLS_CALL || r_type == R_ARM_THM_JUMP19) { /* Handle cases where: - this call goes too far (different Thumb/Thumb2 max @@ -3637,10 +3730,15 @@ arm_type_of_stub (struct bfd_link_info *info, || (thumb2 && (branch_offset > THM2_MAX_FWD_BRANCH_OFFSET || (branch_offset < THM2_MAX_BWD_BRANCH_OFFSET))) + || (thumb2 + && (branch_offset > THM2_MAX_FWD_COND_BRANCH_OFFSET + || (branch_offset < THM2_MAX_BWD_COND_BRANCH_OFFSET)) + && (r_type == R_ARM_THM_JUMP19)) || (branch_type == ST_BRANCH_TO_ARM && (((r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_TLS_CALL) && !globals->use_blx) - || (r_type == R_ARM_THM_JUMP24)) + || (r_type == R_ARM_THM_JUMP24) + || (r_type == R_ARM_THM_JUMP19)) && !use_plt)) { if (branch_type == ST_BRANCH_TO_THUMB) @@ -3648,7 +3746,7 @@ arm_type_of_stub (struct bfd_link_info *info, /* Thumb to thumb. */ if (!thumb_only) { - stub_type = (info->shared | globals->pic_veneer) + stub_type = (bfd_link_pic (info) | globals->pic_veneer) /* PIC stubs. */ ? ((globals->use_blx && (r_type == R_ARM_THM_CALL)) @@ -3670,7 +3768,7 @@ arm_type_of_stub (struct bfd_link_info *info, } else { - stub_type = (info->shared | globals->pic_veneer) + stub_type = (bfd_link_pic (info) | globals->pic_veneer) /* PIC stub. */ ? arm_stub_long_branch_thumb_only_pic /* non-PIC stub. */ @@ -3691,10 +3789,10 @@ arm_type_of_stub (struct bfd_link_info *info, } stub_type = - (info->shared | globals->pic_veneer) + (bfd_link_pic (info) | globals->pic_veneer) /* PIC stubs. */ ? (r_type == R_ARM_THM_TLS_CALL - /* TLS PIC stubs */ + /* TLS PIC stubs. */ ? (globals->use_blx ? arm_stub_long_branch_any_tls_pic : arm_stub_long_branch_v4t_thumb_tls_pic) : ((globals->use_blx && r_type == R_ARM_THM_CALL) @@ -3745,7 +3843,7 @@ arm_type_of_stub (struct bfd_link_info *info, || (r_type == R_ARM_JUMP24) || (r_type == R_ARM_PLT32)) { - stub_type = (info->shared | globals->pic_veneer) + stub_type = (bfd_link_pic (info) | globals->pic_veneer) /* PIC stubs. */ ? ((globals->use_blx) /* V5T and above. */ @@ -3768,14 +3866,18 @@ arm_type_of_stub (struct bfd_link_info *info, || (branch_offset < ARM_MAX_BWD_BRANCH_OFFSET)) { stub_type = - (info->shared | globals->pic_veneer) + (bfd_link_pic (info) | globals->pic_veneer) /* PIC stubs. */ ? (r_type == R_ARM_TLS_CALL - /* TLS PIC Stub */ + /* TLS PIC Stub. */ ? arm_stub_long_branch_any_tls_pic - : arm_stub_long_branch_any_arm_pic) + : (globals->nacl_p + ? arm_stub_long_branch_arm_nacl_pic + : arm_stub_long_branch_any_arm_pic)) /* non-PIC stubs. */ - : arm_stub_long_branch_any_any; + : (globals->nacl_p + ? arm_stub_long_branch_arm_nacl + : arm_stub_long_branch_any_any); } } } @@ -3911,7 +4013,8 @@ elf32_arm_create_or_find_stub_sec (asection **link_sec_p, asection *section, memcpy (s_name, link_sec->name, namelen); memcpy (s_name + namelen, STUB_SUFFIX, sizeof (STUB_SUFFIX)); - stub_sec = (*htab->add_stub_section) (s_name, link_sec); + stub_sec = (*htab->add_stub_section) (s_name, link_sec, + htab->nacl_p ? 4 : 3); if (stub_sec == NULL) return NULL; htab->stub_group[link_sec->id].stub_sec = stub_sec; @@ -3994,7 +4097,8 @@ elf32_arm_tls_transition (struct bfd_link_info *info, int r_type, { int is_local = (h == NULL); - if (info->shared || (h && h->root.type == bfd_link_hash_undefweak)) + if (bfd_link_pic (info) + || (h && h->root.type == bfd_link_hash_undefweak)) return r_type; /* We do not support relaxations for Old TLS models. */ @@ -4044,6 +4148,10 @@ arm_stub_required_alignment (enum elf32_arm_stub_type stub_type) case arm_stub_a8_veneer_blx: return 4; + case arm_stub_long_branch_arm_nacl: + case arm_stub_long_branch_arm_nacl_pic: + return 16; + default: abort (); /* Should be unreachable. */ } @@ -4053,7 +4161,7 @@ static bfd_boolean arm_build_one_stub (struct bfd_hash_entry *gen_entry, void * in_arg) { -#define MAXRELOCS 2 +#define MAXRELOCS 3 struct elf32_arm_stub_hash_entry *stub_entry; struct elf32_arm_link_hash_table *globals; struct bfd_link_info *info; @@ -4324,7 +4432,7 @@ elf32_arm_setup_section_lists (bfd *output_bfd, { bfd *input_bfd; unsigned int bfd_count; - int top_id, top_index; + unsigned int top_id, top_index; asection *section; asection **input_list, **list; bfd_size_type amt; @@ -4338,7 +4446,7 @@ elf32_arm_setup_section_lists (bfd *output_bfd, /* Count the number of input BFDs and find the top input section id. */ for (input_bfd = info->input_bfds, bfd_count = 0, top_id = 0; input_bfd != NULL; - input_bfd = input_bfd->link_next) + input_bfd = input_bfd->link.next) { bfd_count += 1; for (section = input_bfd->sections; @@ -4865,7 +4973,8 @@ elf32_arm_size_stubs (bfd *output_bfd, bfd *stub_bfd, struct bfd_link_info *info, bfd_signed_vma group_size, - asection * (*add_stub_section) (const char *, asection *), + asection * (*add_stub_section) (const char *, asection *, + unsigned int), void (*layout_sections_again) (void)) { bfd_size_type stub_group_size; @@ -4946,7 +5055,7 @@ elf32_arm_size_stubs (bfd *output_bfd, num_a8_fixes = 0; for (input_bfd = info->input_bfds, bfd_indx = 0; input_bfd != NULL; - input_bfd = input_bfd->link_next, bfd_indx++) + input_bfd = input_bfd->link.next, bfd_indx++) { Elf_Internal_Shdr *symtab_hdr; asection *section; @@ -5096,7 +5205,7 @@ elf32_arm_size_stubs (bfd *output_bfd, if (!sym_sec) /* This is an undefined symbol. It can never - be resolved. */ + be resolved. */ continue; if (ELF_ST_TYPE (sym->st_info) != STT_SECTION) @@ -5247,7 +5356,8 @@ elf32_arm_size_stubs (bfd *output_bfd, /* For historical reasons, use the existing names for ARM-to-Thumb and Thumb-to-ARM stubs. */ if ((r_type == (unsigned int) R_ARM_THM_CALL - || r_type == (unsigned int) R_ARM_THM_JUMP24) + || r_type == (unsigned int) R_ARM_THM_JUMP24 + || r_type == (unsigned int) R_ARM_THM_JUMP19) && branch_type == ST_BRANCH_TO_ARM) sprintf (stub_entry->output_name, THUMB2ARM_GLUE_ENTRY_NAME, sym_name); @@ -5729,7 +5839,8 @@ record_arm_to_thumb_glue (struct bfd_link_info * link_info, free (tmp_name); - if (link_info->shared || globals->root.is_relocatable_executable + if (bfd_link_pic (link_info) + || globals->root.is_relocatable_executable || globals->pic_veneer) size = ARM2THUMB_PIC_GLUE_SIZE; else if (globals->use_blx) @@ -5983,6 +6094,15 @@ arm_make_glue_section (bfd * abfd, const char * name) return TRUE; } +/* Set size of .plt entries. This function is called from the + linker scripts in ld/emultempl/{armelf}.em. */ + +void +bfd_elf32_arm_use_long_plt (void) +{ + elf32_arm_use_long_plt_entry = TRUE; +} + /* Add the glue sections to ABFD. This function is called from the linker scripts in ld/emultempl/{armelf}.em. */ @@ -5992,7 +6112,7 @@ bfd_elf32_arm_add_glue_sections_to_bfd (bfd *abfd, { /* If we are only performing a partial link do not bother adding the glue. */ - if (info->relocatable) + if (bfd_link_relocatable (info)) return TRUE; return arm_make_glue_section (abfd, ARM2THUMB_GLUE_SECTION_NAME) @@ -6012,7 +6132,7 @@ bfd_elf32_arm_get_bfd_for_interworking (bfd *abfd, struct bfd_link_info *info) /* If we are only performing a partial link do not bother getting a bfd to hold the glue. */ - if (info->relocatable) + if (bfd_link_relocatable (info)) return TRUE; /* Make sure we don't attach the glue sections to a dynamic object. */ @@ -6064,7 +6184,7 @@ bfd_elf32_arm_process_before_allocation (bfd *abfd, /* If we are only performing a partial link do not bother to construct any glue. */ - if (link_info->relocatable) + if (bfd_link_relocatable (link_info)) return TRUE; /* Here we have a bfd that is to be included on the link. We have a @@ -6628,7 +6748,7 @@ bfd_elf32_arm_vfp11_erratum_scan (bfd *abfd, struct bfd_link_info *link_info) /* If we are only performing a partial link do not bother to construct any glue. */ - if (link_info->relocatable) + if (bfd_link_relocatable (link_info)) return TRUE; /* Skip if this bfd does not correspond to an ELF image. */ @@ -6814,7 +6934,7 @@ bfd_elf32_arm_vfp11_fix_veneer_locations (bfd *abfd, struct elf32_arm_link_hash_table *globals; char *tmp_name; - if (link_info->relocatable) + if (bfd_link_relocatable (link_info)) return; /* Skip if this bfd does not correspond to an ELF image. */ @@ -7102,7 +7222,8 @@ elf32_arm_create_thumb_stub (struct bfd_link_info * info, --my_offset; myh->root.u.def.value = my_offset; - if (info->shared || globals->root.is_relocatable_executable + if (bfd_link_pic (info) + || globals->root.is_relocatable_executable || globals->pic_veneer) { /* For relocatable objects we can't use absolute addresses, @@ -7413,6 +7534,8 @@ elf32_arm_allocate_plt_entry (struct bfd_link_info *info, first entry. */ if (splt->size == 0) splt->size += htab->plt_header_size; + + htab->next_tls_desc_index++; } /* Allocate the PLT entry itself, including any leading Thumb stub. */ @@ -7425,7 +7548,10 @@ elf32_arm_allocate_plt_entry (struct bfd_link_info *info, { /* We also need to make an entry in the .got.plt section, which will be placed in the .got section by the linker script. */ - arm_plt->got_offset = sgotplt->size - 8 * htab->num_tls_desc; + if (is_iplt_entry) + arm_plt->got_offset = sgotplt->size; + else + arm_plt->got_offset = sgotplt->size - 8 * htab->num_tls_desc; sgotplt->size += 4; } } @@ -7449,9 +7575,11 @@ arm_movt_immediate (bfd_vma value) ROOT_PLT points to the offset of the PLT entry from the start of its section (.iplt or .plt). ARM_PLT points to the symbol's ARM-specific - bookkeeping information. */ + bookkeeping information. -static void + Returns FALSE if there was a problem. */ + +static bfd_boolean elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info, union gotplt_union *root_plt, struct arm_plt_info *arm_plt, @@ -7546,7 +7674,7 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info, + root_plt->offset); ptr = splt->contents + root_plt->offset; - if (htab->vxworks_p && info->shared) + if (htab->vxworks_p && bfd_link_pic (info)) { unsigned int i; bfd_vma val; @@ -7641,6 +7769,46 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info, | (tail_displacement & 0x00ffffff), ptr + 12); } + else if (using_thumb_only (htab)) + { + /* PR ld/16017: Generate thumb only PLT entries. */ + if (!using_thumb2 (htab)) + { + /* FIXME: We ought to be able to generate thumb-1 PLT + instructions... */ + _bfd_error_handler (_("%B: Warning: thumb-1 mode PLT generation not currently supported"), + output_bfd); + return FALSE; + } + + /* Calculate the displacement between the PLT slot and the entry in + the GOT. The 12-byte offset accounts for the value produced by + adding to pc in the 3rd instruction of the PLT stub. */ + got_displacement = got_address - (plt_address + 12); + + /* As we are using 32 bit instructions we have to use 'put_arm_insn' + instead of 'put_thumb_insn'. */ + put_arm_insn (htab, output_bfd, + elf32_thumb2_plt_entry[0] + | ((got_displacement & 0x000000ff) << 16) + | ((got_displacement & 0x00000700) << 20) + | ((got_displacement & 0x00000800) >> 1) + | ((got_displacement & 0x0000f000) >> 12), + ptr + 0); + put_arm_insn (htab, output_bfd, + elf32_thumb2_plt_entry[1] + | ((got_displacement & 0x00ff0000) ) + | ((got_displacement & 0x07000000) << 4) + | ((got_displacement & 0x08000000) >> 17) + | ((got_displacement & 0xf0000000) >> 28), + ptr + 4); + put_arm_insn (htab, output_bfd, + elf32_thumb2_plt_entry[2], + ptr + 8); + put_arm_insn (htab, output_bfd, + elf32_thumb2_plt_entry[3], + ptr + 12); + } else { /* Calculate the displacement between the PLT slot and the @@ -7649,8 +7817,6 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info, of the PLT stub. */ got_displacement = got_address - (plt_address + 8); - BFD_ASSERT ((got_displacement & 0xf0000000) == 0); - if (elf32_arm_plt_needs_thumb_stub_p (info, arm_plt)) { put_thumb_insn (htab, output_bfd, @@ -7659,21 +7825,45 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info, 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); + if (!elf32_arm_use_long_plt_entry) + { + BFD_ASSERT ((got_displacement & 0xf0000000) == 0); + + put_arm_insn (htab, output_bfd, + elf32_arm_plt_entry_short[0] + | ((got_displacement & 0x0ff00000) >> 20), + ptr + 0); + put_arm_insn (htab, output_bfd, + elf32_arm_plt_entry_short[1] + | ((got_displacement & 0x000ff000) >> 12), + ptr+ 4); + put_arm_insn (htab, output_bfd, + elf32_arm_plt_entry_short[2] + | (got_displacement & 0x00000fff), + ptr + 8); #ifdef FOUR_WORD_PLT - bfd_put_32 (output_bfd, elf32_arm_plt_entry[3], ptr + 12); + bfd_put_32 (output_bfd, elf32_arm_plt_entry_short[3], ptr + 12); #endif + } + else + { + put_arm_insn (htab, output_bfd, + elf32_arm_plt_entry_long[0] + | ((got_displacement & 0xf0000000) >> 28), + ptr + 0); + put_arm_insn (htab, output_bfd, + elf32_arm_plt_entry_long[1] + | ((got_displacement & 0x0ff00000) >> 20), + ptr + 4); + put_arm_insn (htab, output_bfd, + elf32_arm_plt_entry_long[2] + | ((got_displacement & 0x000ff000) >> 12), + ptr+ 8); + put_arm_insn (htab, output_bfd, + elf32_arm_plt_entry_long[3] + | (got_displacement & 0x00000fff), + ptr + 12); + } } /* Fill in the entry in the .rel(a).(i)plt section. */ @@ -7706,6 +7896,8 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info, loc = srel->contents + plt_index * RELOC_SIZE (htab); SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc); } + + return TRUE; } /* Some relocations map to different relocations depending on the @@ -7901,7 +8093,7 @@ elf32_arm_tls_relax (struct elf32_arm_link_hash_table *globals, break; case R_ARM_THM_TLS_CALL: - /* GD->IE relaxation */ + /* GD->IE relaxation. */ if (!is_local) /* add r0,pc; ldr r0, [r0] */ insn = 0x44786800; @@ -8045,18 +8237,6 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, if (r_type != howto->type) howto = elf32_arm_howto_from_type (r_type); - /* If the start address has been set, then set the EF_ARM_HASENTRY - flag. Setting this more than once is redundant, but the cost is - not too high, and it keeps the code simple. - - The test is done here, rather than somewhere else, because the - start address is only set just before the final link commences. - - Note - if the user deliberately sets a start address of 0, the - flag will not be set. */ - if (bfd_get_start_address (output_bfd) != 0) - elf_elfheader (output_bfd)->e_flags |= EF_ARM_HASENTRY; - eh = (struct elf32_arm_link_hash_entry *) h; sgot = globals->root.sgot; local_got_offsets = elf_local_got_offsets (input_bfd); @@ -8085,6 +8265,14 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, else addend = signed_addend = rel->r_addend; + /* ST_BRANCH_TO_ARM is nonsense to thumb-only targets when we + are resolving a function call relocation. */ + if (using_thumb_only (globals) + && (r_type == R_ARM_THM_CALL + || r_type == R_ARM_THM_JUMP24) + && branch_type == ST_BRANCH_TO_ARM) + branch_type = ST_BRANCH_TO_THUMB; + /* Record the symbol information that should be used in dynamic relocations. */ dynreloc_st_type = st_type; @@ -8113,9 +8301,11 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, plt_offset--; else { - elf32_arm_populate_plt_entry (output_bfd, info, root_plt, arm_plt, - -1, dynreloc_value); - root_plt->offset |= 1; + if (elf32_arm_populate_plt_entry (output_bfd, info, root_plt, arm_plt, + -1, dynreloc_value)) + root_plt->offset |= 1; + else + return bfd_reloc_notsupported; } /* Static relocations always resolve to the .iplt entry. */ @@ -8196,7 +8386,8 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, /* When generating a shared object or relocatable executable, these relocations are copied into the output file to be resolved at run time. */ - if ((info->shared || globals->root.is_relocatable_executable) + if ((bfd_link_pic (info) + || globals->root.is_relocatable_executable) && (input_section->flags & SEC_ALLOC) && !(globals->vxworks_p && strcmp (input_section->output_section->name, @@ -8217,6 +8408,21 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, Elf_Internal_Rela outrel; bfd_boolean skip, relocate; + if ((r_type == R_ARM_REL32 || r_type == R_ARM_REL32_NOI) + && !h->def_regular) + { + char *v = _("shared object"); + + if (bfd_link_executable (info)) + v = _("PIE executable"); + + (*_bfd_error_handler) + (_("%B: relocation %s against external or undefined symbol `%s'" + " can not be used when making a %s; recompile with -fPIC"), input_bfd, + elf32_arm_howto_table_1[r_type].name, h->root.root.string, v); + return bfd_reloc_notsupported; + } + *unresolved_reloc_p = FALSE; if (sreloc == NULL && globals->root.dynamic_sections_created) @@ -8246,8 +8452,8 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, memset (&outrel, 0, sizeof outrel); else if (h != NULL && h->dynindx != -1 - && (!info->shared - || !info->symbolic + && (!bfd_link_pic (info) + || !SYMBOLIC_BIND (info, h) || !h->def_regular)) outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); else @@ -8541,6 +8747,9 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, return bfd_reloc_ok; case R_ARM_ABS8: + /* PR 16202: Refectch the addend using the correct size. */ + if (globals->use_rel) + addend = bfd_get_8 (input_bfd, hit_data); value += addend; /* There is no way to tell whether the user intended to use a signed or @@ -8553,6 +8762,9 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, return bfd_reloc_ok; case R_ARM_ABS16: + /* PR 16202: Refectch the addend using the correct size. */ + if (globals->use_rel) + addend = bfd_get_16 (input_bfd, hit_data); value += addend; /* See comment for R_ARM_ABS8. */ @@ -8604,7 +8816,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, + input_section->output_offset + rel->r_offset); - value = abs (relocation); + value = relocation; if (value >= 0x1000) return bfd_reloc_overflow; @@ -8639,7 +8851,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, + input_section->output_offset + rel->r_offset); - value = abs (relocation); + value = relocation; /* We do not check for overflow of this reloc. Although strictly speaking this is incorrect, it appears to be necessary in order @@ -8676,7 +8888,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, + input_section->output_offset + rel->r_offset); - value = abs (relocation); + value = relocation; if (value >= 0x1000) return bfd_reloc_overflow; @@ -8844,7 +9056,9 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, + splt->output_offset + plt_offset); - if (globals->use_blx && r_type == R_ARM_THM_CALL) + if (globals->use_blx + && r_type == R_ARM_THM_CALL + && ! using_thumb_only (globals)) { /* If the Thumb BLX instruction is available, convert the BL to a BLX instruction to call the ARM-mode @@ -8854,8 +9068,9 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, } else { - /* Target the Thumb stub before the ARM PLT entry. */ - value -= PLT_THUMB_STUB_SIZE; + if (! using_thumb_only (globals)) + /* Target the Thumb stub before the ARM PLT entry. */ + value -= PLT_THUMB_STUB_SIZE; branch_type = ST_BRANCH_TO_THUMB; } *unresolved_reloc_p = FALSE; @@ -8926,6 +9141,9 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, bfd_signed_vma reloc_signed_max = 0xffffe; bfd_signed_vma reloc_signed_min = -0x100000; bfd_signed_vma signed_check; + enum elf32_arm_stub_type stub_type = arm_stub_none; + struct elf32_arm_stub_hash_entry *stub_entry; + struct elf32_arm_link_hash_entry *hash; /* Need to refetch the addend, reconstruct the top three bits, and squish the two 11 bit pieces together. */ @@ -8957,8 +9175,25 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, *unresolved_reloc_p = FALSE; } - /* ??? Should handle interworking? GCC might someday try to - use this for tail calls. */ + hash = (struct elf32_arm_link_hash_entry *)h; + + stub_type = arm_type_of_stub (info, input_section, rel, + st_type, &branch_type, + hash, value, sym_sec, + input_bfd, sym_name); + if (stub_type != arm_stub_none) + { + stub_entry = elf32_arm_get_stub_entry (input_section, + sym_sec, h, + rel, globals, + stub_type); + if (stub_entry != NULL) + { + value = (stub_entry->stub_offset + + stub_entry->stub_sec->output_offset + + stub_entry->stub_sec->output_section->vma); + } + } relocation = value + signed_addend; relocation -= (input_section->output_section->vma @@ -9167,7 +9402,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, { if (dynreloc_st_type == STT_GNU_IFUNC) outrel.r_info = ELF32_R_INFO (0, R_ARM_IRELATIVE); - else if (info->shared && + else if (bfd_link_pic (info) && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak)) outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE); @@ -9216,7 +9451,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, if (globals->use_rel) bfd_put_32 (output_bfd, dynreloc_value, sgot->contents + off); - if (info->shared || dynreloc_st_type == STT_GNU_IFUNC) + if (bfd_link_pic (info) || dynreloc_st_type == STT_GNU_IFUNC) { Elf_Internal_Rela outrel; @@ -9265,7 +9500,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, { /* If we don't know the module number, create a relocation for it. */ - if (info->shared) + if (bfd_link_pic (info)) { Elf_Internal_Rela outrel; @@ -9315,8 +9550,10 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, { bfd_boolean dyn; dyn = globals->root.dynamic_sections_created; - if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) - && (!info->shared + if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, + bfd_link_pic (info), + h) + && (!bfd_link_pic (info) || !SYMBOL_REFERENCES_LOCAL (info, h))) { *unresolved_reloc_p = FALSE; @@ -9353,7 +9590,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, now, and emit any relocations. If both an IE GOT and a GD GOT are necessary, we emit the GD first. */ - if ((info->shared || indx != 0) + if ((bfd_link_pic (info) || indx != 0) && (h == NULL || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak)) @@ -9369,7 +9606,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, /* We should have relaxed, unless this is an undefined weak symbol. */ BFD_ASSERT ((h && (h->root.type == bfd_link_hash_undefweak)) - || info->shared); + || bfd_link_pic (info)); BFD_ASSERT (globals->sgotplt_jump_table_size + offplt + 8 <= globals->root.sgotplt->size); @@ -9550,7 +9787,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, else { lower_insn = 0xc000; - /* Round up the offset to a word boundary */ + /* Round up the offset to a word boundary. */ offset = (offset + 2) & ~2; } @@ -9569,7 +9806,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, /* These relocations needs special care, as besides the fact they point somewhere in .gotplt, the addend must be adjusted accordingly depending on the type of instruction - we refer to */ + we refer to. */ else if ((r_type == R_ARM_TLS_GOTDESC) && (tls_type & GOT_TLS_GDESC)) { unsigned long data, insn; @@ -9644,7 +9881,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, } case R_ARM_TLS_LE32: - if (info->shared && !info->pie) + if (bfd_link_dll (info)) { (*_bfd_error_handler) (_("%B(%A+0x%lx): R_ARM_TLS_LE32 relocation not permitted in shared object"), @@ -9800,10 +10037,8 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, 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; + /* sb is the origin of the *segment* containing the symbol. */ + bfd_vma sb = sym_sec ? sym_sec->output_section->vma : 0; bfd_vma residual; bfd_vma g_n; bfd_signed_vma signed_value; @@ -9890,8 +10125,8 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, /* 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); + g_n = calculate_group_reloc_mask (signed_value < 0 ? - signed_value : signed_value, + group, &residual); /* Check for overflow if required. */ if ((r_type == R_ARM_ALU_PC_G0 @@ -9904,7 +10139,8 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, (*_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); + (long) rel->r_offset, signed_value < 0 ? - signed_value : signed_value, + howto->name); return bfd_reloc_overflow; } @@ -9936,7 +10172,8 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, 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. */ + /* sb is the origin of the *segment* containing the symbol. */ + bfd_vma sb = sym_sec ? sym_sec->output_section->vma : 0; bfd_vma residual; bfd_signed_vma signed_value; int group = 0; @@ -9983,15 +10220,16 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, /* 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); + calculate_group_reloc_mask (signed_value < 0 ? - signed_value : 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); + input_bfd, input_section, + (long) rel->r_offset, labs (signed_value), howto->name); return bfd_reloc_overflow; } @@ -10019,7 +10257,8 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, 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. */ + /* sb is the origin of the *segment* containing the symbol. */ + bfd_vma sb = sym_sec ? sym_sec->output_section->vma : 0; bfd_vma residual; bfd_signed_vma signed_value; int group = 0; @@ -10066,15 +10305,16 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, /* 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); + calculate_group_reloc_mask (signed_value < 0 ? - signed_value : 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); + input_bfd, input_section, + (long) rel->r_offset, labs (signed_value), howto->name); return bfd_reloc_overflow; } @@ -10102,7 +10342,8 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, 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. */ + /* sb is the origin of the *segment* containing the symbol. */ + bfd_vma sb = sym_sec ? sym_sec->output_section->vma : 0; bfd_vma residual; bfd_signed_vma signed_value; int group = 0; @@ -10149,7 +10390,8 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, /* 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); + calculate_group_reloc_mask (signed_value < 0 ? - signed_value : 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 @@ -10159,7 +10401,7 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, (*_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); + (long) rel->r_offset, labs (signed_value), howto->name); return bfd_reloc_overflow; } @@ -10364,7 +10606,7 @@ elf32_arm_relocate_section (bfd * output_bfd, relocation = (sec->output_section->vma + sec->output_offset + sym->st_value); - if (!info->relocatable + if (!bfd_link_relocatable (info) && (sec->flags & SEC_MERGE) && ELF_ST_TYPE (sym->st_info) == STT_SECTION) { @@ -10457,12 +10699,12 @@ elf32_arm_relocate_section (bfd * output_bfd, } else { - bfd_boolean warned; + bfd_boolean warned, ignored; RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, r_symndx, symtab_hdr, sym_hashes, h, sec, relocation, - unresolved_reloc, warned); + unresolved_reloc, warned, ignored); sym_type = h->type; } @@ -10471,7 +10713,7 @@ elf32_arm_relocate_section (bfd * output_bfd, RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, rel, 1, relend, howto, 0, contents); - if (info->relocatable) + if (bfd_link_relocatable (info)) { /* This is a relocatable link. We don't have to change anything, unless the reloc is against a section symbol, @@ -10520,7 +10762,7 @@ elf32_arm_relocate_section (bfd * output_bfd, done, i.e., the relaxation produced the final output we want, and we won't let anybody mess with it. Also, we have to do addend adjustments in case of a R_ARM_TLS_GOTDESC relocation - both in relaxed and non-relaxed cases */ + both in relaxed and non-relaxed cases. */ if ((elf32_arm_tls_transition (info, r_type, h) != (unsigned)r_type) || (IS_ARM_TLS_GNU_RELOC (r_type) && !((h ? elf32_arm_hash_entry (h)->tls_type : @@ -10717,7 +10959,7 @@ elf32_arm_fix_exidx_coverage (asection **text_section_order, /* Walk over all EXIDX sections, and create backlinks from the corrsponding text sections. */ - for (inp = info->input_bfds; inp != NULL; inp = inp->link_next) + for (inp = info->input_bfds; inp != NULL; inp = inp->link.next) { asection *sec; @@ -10899,7 +11141,7 @@ elf32_arm_final_link (bfd *abfd, struct bfd_link_info *info) /* Process stub sections (eg BE8 encoding, ...). */ struct elf32_arm_link_hash_table *htab = elf32_arm_hash_table (info); - int i; + unsigned int i; for (i=0; itop_id; i++) { sec = htab->stub_group[i].stub_sec; @@ -11089,14 +11331,7 @@ elf32_arm_copy_private_bfd_data (bfd *ibfd, bfd *obfd) 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 object attributes. */ - _bfd_elf_copy_obj_attributes (ibfd, obfd); - - return TRUE; + return _bfd_elf_copy_private_bfd_data (ibfd, obfd); } /* Values for Tag_ABI_PCS_R9_use. */ @@ -11478,6 +11713,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) static const int order_021[3] = {0, 2, 1}; int i; bfd_boolean result = TRUE; + const char *sec_name = get_elf_backend_data (ibfd)->obj_attrs_section; /* Skip the linker stubs file. This preserves previous behavior of accepting unknown attributes in the first input file - but @@ -11485,6 +11721,12 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) if (ibfd->flags & BFD_LINKER_CREATED) return TRUE; + /* Skip any input that hasn't attribute section. + This enables to link object files without attribute section with + any others. */ + if (bfd_get_section_by_name (ibfd, sec_name) == NULL) + return TRUE; + if (!elf_known_obj_attributes_proc (obfd)[0].i) { /* This is the first object. Copy the attributes. */ @@ -11524,10 +11766,14 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) /* 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 the object doesn't use floating point. */ - if (out_attr[Tag_ABI_FP_number_model].i == 0) + /* Ignore mismatches if the object doesn't use floating point or is + floating point ABI independent. */ + if (out_attr[Tag_ABI_FP_number_model].i == AEABI_FP_number_model_none + || (in_attr[Tag_ABI_FP_number_model].i != AEABI_FP_number_model_none + && out_attr[Tag_ABI_VFP_args].i == AEABI_VFP_args_compatible)) 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) + else if (in_attr[Tag_ABI_FP_number_model].i != AEABI_FP_number_model_none + && in_attr[Tag_ABI_VFP_args].i != AEABI_VFP_args_compatible) { _bfd_error_handler (_("error: %B uses VFP register arguments, %B does not"), @@ -11544,7 +11790,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) { case Tag_CPU_raw_name: case Tag_CPU_name: - /* These are merged after Tag_CPU_arch. */ + /* These are merged after Tag_CPU_arch. */ break; case Tag_ABI_optimization_goals: @@ -11556,7 +11802,9 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) { int secondary_compat = -1, secondary_compat_out = -1; unsigned int saved_out_attr = out_attr[i].i; - static const char *name_table[] = { + int arch_attr; + static const char *name_table[] = + { /* These aren't real CPU names, but we can't guess that from the architecture version alone. */ "Pre v4", @@ -11578,10 +11826,17 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) /* Merge Tag_CPU_arch and Tag_also_compatible_with. */ secondary_compat = get_secondary_compatible_arch (ibfd); secondary_compat_out = get_secondary_compatible_arch (obfd); - out_attr[i].i = tag_cpu_arch_combine (ibfd, out_attr[i].i, - &secondary_compat_out, - in_attr[i].i, - secondary_compat); + arch_attr = tag_cpu_arch_combine (ibfd, out_attr[i].i, + &secondary_compat_out, + in_attr[i].i, + secondary_compat); + + /* Return with error if failed to merge. */ + if (arch_attr == -1) + return FALSE; + + out_attr[i].i = arch_attr; + set_secondary_compatible_arch (obfd, secondary_compat_out); /* Merge Tag_CPU_name and Tag_CPU_raw_name. */ @@ -11698,7 +11953,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) else if (in_attr[i].i == 0 || (in_attr[i].i == 'S' && (out_attr[i].i == 'A' || out_attr[i].i == 'R'))) - ; /* Do nothing. */ + ; /* Do nothing. */ else { _bfd_error_handler @@ -11715,9 +11970,9 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) /* Tag_ABI_HardFP_use is handled along with Tag_FP_arch since the meaning of Tag_ABI_HardFP_use depends on Tag_FP_arch when it's 0. It might mean absence of FP hardware if - Tag_FP_arch is zero, otherwise it is effectively SP + DP. */ + Tag_FP_arch is zero. */ -#define VFP_VERSION_COUNT 8 +#define VFP_VERSION_COUNT 9 static const struct { int ver; @@ -11731,7 +11986,8 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) {3, 16}, {4, 32}, {4, 16}, - {8, 32} + {8, 32}, + {8, 16} }; int ver; int regs; @@ -11756,7 +12012,7 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) } /* Both the input and the output have nonzero Tag_FP_arch. - So Tag_ABI_HardFP_use is (SP & DP) when it's zero. */ + So Tag_ABI_HardFP_use is implied by Tag_FP_arch when it's zero. */ /* If both the input and the output have zero Tag_ABI_HardFP_use, do nothing. */ @@ -11764,10 +12020,10 @@ elf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) && out_attr[Tag_ABI_HardFP_use].i == 0) ; /* If the input and the output have different Tag_ABI_HardFP_use, - the combination of them is 3 (SP & DP). */ + the combination of them is 0 (implied by Tag_FP_arch). */ else if (in_attr[Tag_ABI_HardFP_use].i != out_attr[Tag_ABI_HardFP_use].i) - out_attr[Tag_ABI_HardFP_use].i = 3; + out_attr[Tag_ABI_HardFP_use].i = 0; /* Now we can handle Tag_FP_arch. */ @@ -12136,10 +12392,7 @@ elf32_arm_print_private_bfd_data (bfd *abfd, void * ptr) if (flags & EF_ARM_RELEXEC) fprintf (file, _(" [relocatable executable]")); - if (flags & EF_ARM_HASENTRY) - fprintf (file, _(" [has entry point]")); - - flags &= ~ (EF_ARM_RELEXEC | EF_ARM_HASENTRY); + flags &= ~EF_ARM_RELEXEC; if (flags) fprintf (file, _("")); @@ -12205,7 +12458,7 @@ elf32_arm_gc_sweep_hook (bfd * abfd, const Elf_Internal_Rela *rel, *relend; struct elf32_arm_link_hash_table * globals; - if (info->relocatable) + if (bfd_link_relocatable (info)) return TRUE; globals = elf32_arm_hash_table (info); @@ -12303,11 +12556,11 @@ elf32_arm_gc_sweep_hook (bfd * abfd, case R_ARM_THM_MOVW_PREL_NC: case R_ARM_THM_MOVT_PREL: /* Should the interworking branches be here also? */ - if ((info->shared || globals->root.is_relocatable_executable) + if ((bfd_link_pic (info) || globals->root.is_relocatable_executable) && (sec->flags & SEC_ALLOC) != 0) { if (h == NULL - && (r_type == R_ARM_REL32 || r_type == R_ARM_REL32_NOI)) + && elf32_arm_howto_from_type (r_type)->pc_relative) { call_reloc_p = TRUE; may_need_local_target_p = TRUE; @@ -12401,7 +12654,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, bfd_boolean may_need_local_target_p; unsigned long nsyms; - if (info->relocatable) + if (bfd_link_relocatable (info)) return TRUE; BFD_ASSERT (is_arm_elf (abfd)); @@ -12518,6 +12771,9 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, default: tls_type = GOT_NORMAL; break; } + if (!bfd_link_executable (info) && (tls_type & GOT_TLS_IE)) + info->flags |= DF_STATIC_TLS; + if (h != NULL) { h->got.refcount++; @@ -12548,7 +12804,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, /* If the symbol is accessed in both IE and GDESC method, we're able to relax. Turn off the GDESC flag, without messing up with any other kind of tls types - that may be involved */ + that may be involved. */ if ((tls_type & GOT_TLS_IE) && (tls_type & GOT_TLS_GDESC)) tls_type &= ~GOT_TLS_GDESC; @@ -12600,7 +12856,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_ARM_MOVT_ABS: case R_ARM_THM_MOVW_ABS_NC: case R_ARM_THM_MOVT_ABS: - if (info->shared) + if (bfd_link_pic (info)) { (*_bfd_error_handler) (_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"), @@ -12613,6 +12869,11 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, /* Fall through. */ case R_ARM_ABS32: case R_ARM_ABS32_NOI: + if (h != NULL && bfd_link_executable (info)) + { + h->pointer_equality_needed = 1; + } + /* Fall through. */ case R_ARM_REL32: case R_ARM_REL32_NOI: case R_ARM_MOVW_PREL_NC: @@ -12621,11 +12882,11 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_ARM_THM_MOVT_PREL: /* Should the interworking branches be listed here? */ - if ((info->shared || htab->root.is_relocatable_executable) + if ((bfd_link_pic (info) || htab->root.is_relocatable_executable) && (sec->flags & SEC_ALLOC) != 0) { if (h == NULL - && (r_type == R_ARM_REL32 || r_type == R_ARM_REL32_NOI)) + && elf32_arm_howto_from_type (r_type)->pc_relative) { /* In shared libraries and relocatable executables, we treat local relative references as calls; @@ -12771,7 +13032,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, p->pc_count = 0; } - if (r_type == R_ARM_REL32 || r_type == R_ARM_REL32_NOI) + if (elf32_arm_howto_from_type (r_type)->pc_relative) p->pc_count += 1; p->count += 1; } @@ -12799,7 +13060,7 @@ elf32_arm_gc_mark_extra_sections (struct bfd_link_info *info, while (again) { again = FALSE; - for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) + for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) { asection *o; @@ -12844,8 +13105,8 @@ 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, + asection * section, bfd_vma offset, const char ** filename_ptr, const char ** functionname_ptr) @@ -12906,31 +13167,33 @@ arm_elf_find_function (bfd * abfd ATTRIBUTE_UNUSED, static bfd_boolean elf32_arm_find_nearest_line (bfd * abfd, - asection * section, asymbol ** symbols, + asection * section, bfd_vma offset, const char ** filename_ptr, const char ** functionname_ptr, - unsigned int * line_ptr) + unsigned int * line_ptr, + unsigned int * discriminator_ptr) { 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, dwarf_debug_sections, - section, symbols, offset, + if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset, filename_ptr, functionname_ptr, - line_ptr, NULL, 0, + line_ptr, discriminator_ptr, + dwarf_debug_sections, 0, & elf_tdata (abfd)->dwarf2_find_line_info)) { if (!*functionname_ptr) - arm_elf_find_function (abfd, section, symbols, offset, + arm_elf_find_function (abfd, symbols, section, offset, *filename_ptr ? NULL : filename_ptr, functionname_ptr); return TRUE; } + /* Skip _bfd_dwarf1_find_nearest_line since no known ARM toolchain + uses DWARF1. */ + if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset, & found, filename_ptr, functionname_ptr, line_ptr, @@ -12943,7 +13206,7 @@ elf32_arm_find_nearest_line (bfd * abfd, if (symbols == NULL) return FALSE; - if (! arm_elf_find_function (abfd, section, symbols, offset, + if (! arm_elf_find_function (abfd, symbols, section, offset, filename_ptr, functionname_ptr)) return FALSE; @@ -13062,7 +13325,7 @@ elf32_arm_adjust_dynamic_symbol (struct bfd_link_info * info, be handled correctly by relocate_section. Relocatable executables can reference data in shared objects directly, so we don't need to do anything here. */ - if (info->shared || globals->root.is_relocatable_executable) + if (bfd_link_pic (info) || globals->root.is_relocatable_executable) return TRUE; /* We must allocate the symbol in our .dynbss section, which will @@ -13090,7 +13353,7 @@ elf32_arm_adjust_dynamic_symbol (struct bfd_link_info * info, h->needs_copy = 1; } - return _bfd_elf_adjust_dynamic_copy (h, s); + return _bfd_elf_adjust_dynamic_copy (info, h, s); } /* Allocate space in .plt, .got and associated reloc sections for @@ -13144,7 +13407,7 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf) h->got.refcount = 0; } - if (info->shared + if (bfd_link_pic (info) || eh->is_iplt || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h)) { @@ -13155,7 +13418,7 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf) location in the .plt. This is required to make function pointers compare as equal between the normal executable and the shared library. */ - if (! info->shared + if (! bfd_link_pic (info) && !h->def_regular) { h->root.u.def.section = htab->root.splt; @@ -13167,12 +13430,10 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf) h->target_internal = ST_BRANCH_TO_ARM; } - htab->next_tls_desc_index++; - /* VxWorks executables have a second set of relocations for each PLT entry. They go in a separate relocation section, which is processed by the kernel loader. */ - if (htab->vxworks_p && !info->shared) + if (htab->vxworks_p && !bfd_link_pic (info)) { /* There is a relocation for the initial PLT entry: an R_ARM_32 relocation for _GLOBAL_OFFSET_TABLE_. */ @@ -13259,13 +13520,15 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf) dyn = htab->root.dynamic_sections_created; indx = 0; - if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) - && (!info->shared + if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, + bfd_link_pic (info), + h) + && (!bfd_link_pic (info) || !SYMBOL_REFERENCES_LOCAL (info, h))) indx = h->dynindx; if (tls_type != GOT_NORMAL - && (info->shared || indx != 0) + && (bfd_link_pic (info) || indx != 0) && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak)) { @@ -13299,8 +13562,9 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf) they all resolve dynamically instead. Reserve room for the GOT entry's R_ARM_IRELATIVE relocation. */ elf32_arm_allocate_irelocs (info, htab->root.srelgot, 1); - else if (info->shared && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT - || h->root.type != bfd_link_hash_undefweak)) + else if (bfd_link_pic (info) + && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + || h->root.type != bfd_link_hash_undefweak)) /* Reserve room for the GOT entry's R_ARM_RELATIVE relocation. */ elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1); } @@ -13350,14 +13614,14 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf) space for pc-relative relocs that have become local due to symbol visibility changes. */ - if (info->shared || htab->root.is_relocatable_executable) + if (bfd_link_pic (info) || htab->root.is_relocatable_executable) { - /* The only relocs that use 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 - .". */ + /* Relocs that use pc_count are PC-relative forms, which will appear + on something like ".long foo - ." or "movw REG, 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 elf_dyn_relocs **pp; @@ -13526,7 +13790,7 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED, if (elf_hash_table (info)->dynamic_sections_created) { /* Set the contents of the .interp section to the interpreter. */ - if (info->executable) + if (bfd_link_executable (info) && !info->nointerp) { s = bfd_get_linker_section (dynobj, ".interp"); BFD_ASSERT (s != NULL); @@ -13537,7 +13801,7 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED, /* Set up .got offsets for local syms, and space for local dynamic relocs. */ - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) { bfd_signed_vma *local_got; bfd_signed_vma *end_local_got; @@ -13678,13 +13942,13 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED, && (local_iplt == NULL || local_iplt->arm.noncall_refcount == 0)) elf32_arm_allocate_irelocs (info, srel, 1); - else if (info->shared || output_bfd->flags & DYNAMIC) + else if (bfd_link_pic (info) || output_bfd->flags & DYNAMIC) { - if ((info->shared && !(*local_tls_type & GOT_TLS_GDESC)) + if ((bfd_link_pic (info) && !(*local_tls_type & GOT_TLS_GDESC)) || *local_tls_type & GOT_TLS_GD) elf32_arm_allocate_dynrelocs (info, srel, 1); - if (info->shared && *local_tls_type & GOT_TLS_GDESC) + if (bfd_link_pic (info) && *local_tls_type & GOT_TLS_GDESC) { elf32_arm_allocate_dynrelocs (info, htab->root.srelplt, 1); @@ -13703,7 +13967,7 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED, for R_ARM_TLS_LDM32 relocations. */ htab->tls_ldm_got.offset = htab->root.sgot->size; htab->root.sgot->size += 8; - if (info->shared) + if (bfd_link_pic (info)) elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1); } else @@ -13714,7 +13978,7 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED, elf_link_hash_traverse (& htab->root, allocate_dynrelocs_for_symbol, info); /* Here we rummage through the found bfds to collect glue information. */ - for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) { if (! is_arm_elf (ibfd)) continue; @@ -13839,7 +14103,7 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED, #define add_dynamic_entry(TAG, VAL) \ _bfd_elf_add_dynamic_entry (info, TAG, VAL) - if (info->executable) + if (bfd_link_executable (info)) { if (!add_dynamic_entry (DT_DEBUG, 0)) return FALSE; @@ -13907,7 +14171,7 @@ elf32_arm_always_size_sections (bfd *output_bfd, { asection *tls_sec; - if (info->relocatable) + if (bfd_link_relocatable (info)) return TRUE; tls_sec = elf_hash_table (info)->tls_sec; @@ -13964,20 +14228,25 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd, if (!eh->is_iplt) { BFD_ASSERT (h->dynindx != -1); - elf32_arm_populate_plt_entry (output_bfd, info, &h->plt, &eh->plt, - h->dynindx, 0); + if (! elf32_arm_populate_plt_entry (output_bfd, info, &h->plt, &eh->plt, + h->dynindx, 0)) + return FALSE; } if (!h->def_regular) { /* Mark the symbol as undefined, rather than as defined in - the .plt section. Leave the value alone. */ + the .plt section. */ sym->st_shndx = SHN_UNDEF; - /* If the symbol is weak, we do need to clear the value. + /* If the symbol is weak we need to clear the value. Otherwise, the PLT entry would provide a definition for the symbol even if the symbol wasn't defined anywhere, - and so the symbol would never be NULL. */ - if (!h->ref_regular_nonweak) + and so the symbol would never be NULL. Leave the value if + there were any relocations where pointer equality matters + (this is a clue for the dynamic linker, to make function + pointer comparisons work between an application and shared + library). */ + if (!h->ref_regular_nonweak || !h->pointer_equality_needed) sym->st_value = 0; } else if (eh->is_iplt && eh->plt.noncall_refcount != 0) @@ -14315,6 +14584,20 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info else if (htab->nacl_p) arm_nacl_put_plt0 (htab, output_bfd, splt, got_address + 8 - (plt_address + 16)); + else if (using_thumb_only (htab)) + { + got_displacement = got_address - (plt_address + 12); + + plt0_entry = elf32_thumb2_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_displacement, splt->contents + 12); + } else { got_displacement = got_address - (plt_address + 16); @@ -14379,7 +14662,9 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info #endif } - if (htab->vxworks_p && !info->shared && htab->root.splt->size > 0) + if (htab->vxworks_p + && !bfd_link_pic (info) + && htab->root.splt->size > 0) { /* Correct the .rel(a).plt.unloaded relocations. They will have incorrect symbol indexes. */ @@ -14443,7 +14728,7 @@ elf32_arm_post_process_headers (bfd * abfd, struct bfd_link_info * link_info ATT if (EF_ARM_EABI_VERSION (i_ehdrp->e_flags) == EF_ARM_EABI_UNKNOWN) i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_ARM; else - i_ehdrp->e_ident[EI_OSABI] = 0; + _bfd_elf_post_process_headers (abfd, link_info); i_ehdrp->e_ident[EI_ABIVERSION] = ARM_ELF_ABI_VERSION; if (link_info) @@ -14457,7 +14742,7 @@ elf32_arm_post_process_headers (bfd * abfd, struct bfd_link_info * link_info ATT && ((i_ehdrp->e_type == ET_DYN) || (i_ehdrp->e_type == ET_EXEC))) { int abi = bfd_elf_get_obj_attr_int (abfd, OBJ_ATTR_PROC, Tag_ABI_VFP_args); - if (abi) + if (abi == AEABI_VFP_args_vfp) i_ehdrp->e_flags |= EF_ARM_ABI_FLOAT_HARD; else i_ehdrp->e_flags |= EF_ARM_ABI_FLOAT_SOFT; @@ -14653,6 +14938,11 @@ elf32_arm_output_plt_map_1 (output_arch_syminfo *osi, if (!elf32_arm_output_map_sym (osi, ARM_MAP_ARM, addr)) return FALSE; } + else if (using_thumb_only (htab)) + { + if (!elf32_arm_output_map_sym (osi, ARM_MAP_THUMB, addr)) + return FALSE; + } else { bfd_boolean thumb_stub_p; @@ -14860,7 +15150,7 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd, mapping symbols. */ for (input_bfd = info->input_bfds; input_bfd != NULL; - input_bfd = input_bfd->link_next) + input_bfd = input_bfd->link.next) { if ((input_bfd->flags & (BFD_LINKER_CREATED | HAS_SYMS)) == HAS_SYMS) for (osi.sec = input_bfd->sections; @@ -14893,7 +15183,7 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd, osi.sec_shndx = _bfd_elf_section_from_bfd_section (output_bfd, osi.sec->output_section); - if (info->shared || htab->root.is_relocatable_executable + if (bfd_link_pic (info) || htab->root.is_relocatable_executable || htab->pic_veneer) size = ARM2THUMB_PIC_GLUE_SIZE; else if (htab->use_blx) @@ -14971,7 +15261,7 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd, if (htab->vxworks_p) { /* VxWorks shared libraries have no PLT header. */ - if (!info->shared) + if (!bfd_link_pic (info)) { if (!elf32_arm_output_map_sym (&osi, ARM_MAP_ARM, 0)) return FALSE; @@ -14984,6 +15274,15 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd, if (!elf32_arm_output_map_sym (&osi, ARM_MAP_ARM, 0)) return FALSE; } + else if (using_thumb_only (htab)) + { + if (!elf32_arm_output_map_sym (&osi, ARM_MAP_THUMB, 0)) + return FALSE; + if (!elf32_arm_output_map_sym (&osi, ARM_MAP_DATA, 12)) + return FALSE; + if (!elf32_arm_output_map_sym (&osi, ARM_MAP_THUMB, 16)) + return FALSE; + } else if (!htab->symbian_p) { if (!elf32_arm_output_map_sym (&osi, ARM_MAP_ARM, 0)) @@ -15009,7 +15308,7 @@ elf32_arm_output_arch_local_syms (bfd *output_bfd, elf_link_hash_traverse (&htab->root, elf32_arm_output_plt_map, &osi); for (input_bfd = info->input_bfds; input_bfd != NULL; - input_bfd = input_bfd->link_next) + input_bfd = input_bfd->link.next) { struct arm_local_iplt_info **local_iplt; unsigned int i, num_syms; @@ -15640,10 +15939,14 @@ elf32_arm_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, Elf_Internal_Sym *sym, const char **namep, flagword *flagsp, asection **secp, bfd_vma *valp) { - if ((abfd->flags & DYNAMIC) == 0 - && (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC - || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)) - elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE; + if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC + || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE) + && (abfd->flags & DYNAMIC) == 0 + && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) + elf_tdata (info->output_bfd)->has_gnu_symbols = elf_gnu_symbol_any; + + if (elf32_arm_hash_table (info) == NULL) + return FALSE; if (elf32_arm_hash_table (info)->vxworks_p && !elf_vxworks_add_symbol_hook (abfd, info, sym, namep, @@ -15684,13 +15987,212 @@ const struct elf_size_info elf32_arm_size_info = bfd_elf32_swap_reloca_out }; +static bfd_vma +read_code32 (const bfd *abfd, const bfd_byte *addr) +{ + /* V7 BE8 code is always little endian. */ + if ((elf_elfheader (abfd)->e_flags & EF_ARM_BE8) != 0) + return bfd_getl32 (addr); + + return bfd_get_32 (abfd, addr); +} + +static bfd_vma +read_code16 (const bfd *abfd, const bfd_byte *addr) +{ + /* V7 BE8 code is always little endian. */ + if ((elf_elfheader (abfd)->e_flags & EF_ARM_BE8) != 0) + return bfd_getl16 (addr); + + return bfd_get_16 (abfd, addr); +} + +/* Return size of plt0 entry starting at ADDR + or (bfd_vma) -1 if size can not be determined. */ + +static bfd_vma +elf32_arm_plt0_size (const bfd *abfd, const bfd_byte *addr) +{ + bfd_vma first_word; + bfd_vma plt0_size; + + first_word = read_code32 (abfd, addr); + + if (first_word == elf32_arm_plt0_entry[0]) + plt0_size = 4 * ARRAY_SIZE (elf32_arm_plt0_entry); + else if (first_word == elf32_thumb2_plt0_entry[0]) + plt0_size = 4 * ARRAY_SIZE (elf32_thumb2_plt0_entry); + else + /* We don't yet handle this PLT format. */ + return (bfd_vma) -1; + + return plt0_size; +} + +/* Return size of plt entry starting at offset OFFSET + of plt section located at address START + or (bfd_vma) -1 if size can not be determined. */ + +static bfd_vma +elf32_arm_plt_size (const bfd *abfd, const bfd_byte *start, bfd_vma offset) +{ + bfd_vma first_insn; + bfd_vma plt_size = 0; + const bfd_byte *addr = start + offset; + + /* PLT entry size if fixed on Thumb-only platforms. */ + if (read_code32 (abfd, start) == elf32_thumb2_plt0_entry[0]) + return 4 * ARRAY_SIZE (elf32_thumb2_plt_entry); + + /* Respect Thumb stub if necessary. */ + if (read_code16 (abfd, addr) == elf32_arm_plt_thumb_stub[0]) + { + plt_size += 2 * ARRAY_SIZE(elf32_arm_plt_thumb_stub); + } + + /* Strip immediate from first add. */ + first_insn = read_code32 (abfd, addr + plt_size) & 0xffffff00; + +#ifdef FOUR_WORD_PLT + if (first_insn == elf32_arm_plt_entry[0]) + plt_size += 4 * ARRAY_SIZE (elf32_arm_plt_entry); +#else + if (first_insn == elf32_arm_plt_entry_long[0]) + plt_size += 4 * ARRAY_SIZE (elf32_arm_plt_entry_long); + else if (first_insn == elf32_arm_plt_entry_short[0]) + plt_size += 4 * ARRAY_SIZE (elf32_arm_plt_entry_short); +#endif + else + /* We don't yet handle this PLT format. */ + return (bfd_vma) -1; + + return plt_size; +} + +/* Implementation is shamelessly borrowed from _bfd_elf_get_synthetic_symtab. */ + +static long +elf32_arm_get_synthetic_symtab (bfd *abfd, + long symcount ATTRIBUTE_UNUSED, + asymbol **syms ATTRIBUTE_UNUSED, + long dynsymcount, + asymbol **dynsyms, + asymbol **ret) +{ + asection *relplt; + asymbol *s; + arelent *p; + long count, i, n; + size_t size; + Elf_Internal_Shdr *hdr; + char *names; + asection *plt; + bfd_vma offset; + bfd_byte *data; + + *ret = NULL; + + if ((abfd->flags & (DYNAMIC | EXEC_P)) == 0) + return 0; + + if (dynsymcount <= 0) + return 0; + + relplt = bfd_get_section_by_name (abfd, ".rel.plt"); + if (relplt == NULL) + return 0; + + hdr = &elf_section_data (relplt)->this_hdr; + if (hdr->sh_link != elf_dynsymtab (abfd) + || (hdr->sh_type != SHT_REL && hdr->sh_type != SHT_RELA)) + return 0; + + plt = bfd_get_section_by_name (abfd, ".plt"); + if (plt == NULL) + return 0; + + if (!elf32_arm_size_info.slurp_reloc_table (abfd, relplt, dynsyms, TRUE)) + return -1; + + data = plt->contents; + if (data == NULL) + { + if (!bfd_get_full_section_contents(abfd, (asection *) plt, &data) || data == NULL) + return -1; + bfd_cache_section_contents((asection *) plt, data); + } + + count = relplt->size / hdr->sh_entsize; + size = count * sizeof (asymbol); + p = relplt->relocation; + for (i = 0; i < count; i++, p += elf32_arm_size_info.int_rels_per_ext_rel) + { + size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt"); + if (p->addend != 0) + size += sizeof ("+0x") - 1 + 8; + } + + s = *ret = (asymbol *) bfd_malloc (size); + if (s == NULL) + return -1; + + offset = elf32_arm_plt0_size (abfd, data); + if (offset == (bfd_vma) -1) + return -1; + + names = (char *) (s + count); + p = relplt->relocation; + n = 0; + for (i = 0; i < count; i++, p += elf32_arm_size_info.int_rels_per_ext_rel) + { + size_t len; + + bfd_vma plt_size = elf32_arm_plt_size (abfd, data, offset); + if (plt_size == (bfd_vma) -1) + break; + + *s = **p->sym_ptr_ptr; + /* Undefined syms won't have BSF_LOCAL or BSF_GLOBAL set. Since + we are defining a symbol, ensure one of them is set. */ + if ((s->flags & BSF_LOCAL) == 0) + s->flags |= BSF_GLOBAL; + s->flags |= BSF_SYNTHETIC; + s->section = plt; + s->value = offset; + s->name = names; + s->udata.p = NULL; + len = strlen ((*p->sym_ptr_ptr)->name); + memcpy (names, (*p->sym_ptr_ptr)->name, len); + names += len; + if (p->addend != 0) + { + char buf[30], *a; + + memcpy (names, "+0x", sizeof ("+0x") - 1); + names += sizeof ("+0x") - 1; + bfd_sprintf_vma (abfd, buf, p->addend); + for (a = buf; *a == '0'; ++a) + ; + len = strlen (a); + memcpy (names, a, len); + names += len; + } + memcpy (names, "@plt", sizeof ("@plt")); + names += sizeof ("@plt"); + ++s, ++n; + offset += plt_size; + } + + return n; +} + #define ELF_ARCH bfd_arch_arm #define ELF_TARGET_ID ARM_ELF_DATA #define ELF_MACHINE_CODE EM_ARM #ifdef __QNXTARGET__ #define ELF_MAXPAGESIZE 0x1000 #else -#define ELF_MAXPAGESIZE 0x8000 +#define ELF_MAXPAGESIZE 0x10000 #endif #define ELF_MINPAGESIZE 0x1000 #define ELF_COMMONPAGESIZE 0x1000 @@ -15702,7 +16204,6 @@ const struct elf_size_info elf32_arm_size_info = #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_link_hash_table_free elf32_arm_hash_table_free #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 @@ -15710,6 +16211,7 @@ const struct elf_size_info elf32_arm_size_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_bfd_final_link elf32_arm_final_link +#define bfd_elf32_get_synthetic_symtab elf32_arm_get_synthetic_symtab #define elf_backend_get_symbol_type elf32_arm_get_symbol_type #define elf_backend_gc_mark_hook elf32_arm_gc_mark_hook @@ -15749,6 +16251,7 @@ const struct elf_size_info elf32_arm_size_info = #define elf_backend_default_use_rela_p 0 #define elf_backend_got_header_size 12 +#define elf_backend_extern_protected_data 1 #undef elf_backend_obj_attrs_vendor #define elf_backend_obj_attrs_vendor "aeabi" @@ -15766,11 +16269,11 @@ const struct elf_size_info elf32_arm_size_info = /* Native Client targets. */ #undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM bfd_elf32_littlearm_nacl_vec +#define TARGET_LITTLE_SYM arm_elf32_nacl_le_vec #undef TARGET_LITTLE_NAME #define TARGET_LITTLE_NAME "elf32-littlearm-nacl" #undef TARGET_BIG_SYM -#define TARGET_BIG_SYM bfd_elf32_bigarm_nacl_vec +#define TARGET_BIG_SYM arm_elf32_nacl_be_vec #undef TARGET_BIG_NAME #define TARGET_BIG_NAME "elf32-bigarm-nacl" @@ -15807,20 +16310,42 @@ elf32_arm_nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info) && nacl_modify_segment_map (abfd, info)); } +static void +elf32_arm_nacl_final_write_processing (bfd *abfd, bfd_boolean linker) +{ + elf32_arm_final_write_processing (abfd, linker); + nacl_final_write_processing (abfd, linker); +} + +static bfd_vma +elf32_arm_nacl_plt_sym_val (bfd_vma i, const asection *plt, + const arelent *rel ATTRIBUTE_UNUSED) +{ + return plt->vma + + 4 * (ARRAY_SIZE (elf32_arm_nacl_plt0_entry) + + i * ARRAY_SIZE (elf32_arm_nacl_plt_entry)); +} + #undef elf32_bed -#define elf32_bed elf32_arm_nacl_bed +#define elf32_bed elf32_arm_nacl_bed #undef bfd_elf32_bfd_link_hash_table_create #define bfd_elf32_bfd_link_hash_table_create \ elf32_arm_nacl_link_hash_table_create #undef elf_backend_plt_alignment -#define elf_backend_plt_alignment 4 +#define elf_backend_plt_alignment 4 #undef elf_backend_modify_segment_map #define elf_backend_modify_segment_map elf32_arm_nacl_modify_segment_map #undef elf_backend_modify_program_headers #define elf_backend_modify_program_headers nacl_modify_program_headers +#undef elf_backend_final_write_processing +#define elf_backend_final_write_processing elf32_arm_nacl_final_write_processing +#undef bfd_elf32_get_synthetic_symtab +#undef elf_backend_plt_sym_val +#define elf_backend_plt_sym_val elf32_arm_nacl_plt_sym_val + +#undef ELF_MINPAGESIZE +#undef ELF_COMMONPAGESIZE -#undef ELF_MAXPAGESIZE -#define ELF_MAXPAGESIZE 0x10000 #include "elf32-target.h" @@ -15829,15 +16354,22 @@ elf32_arm_nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info) #undef elf_backend_modify_segment_map #define elf_backend_modify_segment_map elf32_arm_modify_segment_map #undef elf_backend_modify_program_headers +#undef elf_backend_final_write_processing +#define elf_backend_final_write_processing elf32_arm_final_write_processing +#undef ELF_MINPAGESIZE +#define ELF_MINPAGESIZE 0x1000 +#undef ELF_COMMONPAGESIZE +#define ELF_COMMONPAGESIZE 0x1000 + /* VxWorks Targets. */ #undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM bfd_elf32_littlearm_vxworks_vec +#define TARGET_LITTLE_SYM arm_elf32_vxworks_le_vec #undef TARGET_LITTLE_NAME #define TARGET_LITTLE_NAME "elf32-littlearm-vxworks" #undef TARGET_BIG_SYM -#define TARGET_BIG_SYM bfd_elf32_bigarm_vxworks_vec +#define TARGET_BIG_SYM arm_elf32_vxworks_be_vec #undef TARGET_BIG_NAME #define TARGET_BIG_NAME "elf32-bigarm-vxworks" @@ -16119,11 +16651,11 @@ elf32_arm_merge_private_bfd_data (bfd * ibfd, bfd * obfd) /* Symbian OS Targets. */ #undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM bfd_elf32_littlearm_symbian_vec +#define TARGET_LITTLE_SYM arm_elf32_symbian_le_vec #undef TARGET_LITTLE_NAME #define TARGET_LITTLE_NAME "elf32-littlearm-symbian" #undef TARGET_BIG_SYM -#define TARGET_BIG_SYM bfd_elf32_bigarm_symbian_vec +#define TARGET_BIG_SYM arm_elf32_symbian_be_vec #undef TARGET_BIG_NAME #define TARGET_BIG_NAME "elf32-bigarm-symbian"