From 39d911fc3c6519799ca1af4365d4b56f9d71ca94 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Tue, 10 May 2016 16:14:23 +0100 Subject: [PATCH] Use getters/setters to access ARM branch type 2016-05-10 Thomas Preud'homme bfd/ * elf32-arm.c (elf32_arm_size_stubs): Use new macros ARM_GET_SYM_BRANCH_TYPE and ARM_SET_SYM_BRANCH_TYPE to respectively get and set branch type of a symbol. (bfd_elf32_arm_process_before_allocation): Likewise. (elf32_arm_relocate_section): Likewise and fix identation along the way. (allocate_dynrelocs_for_symbol): Likewise. (elf32_arm_finish_dynamic_symbol): Likewise. (elf32_arm_swap_symbol_in): Likewise. (elf32_arm_swap_symbol_out): Likewise. gas/ * config/tc-arm.c (arm_adjust_symtab): Use ARM_SET_SYM_BRANCH_TYPE to set branch type of a symbol. gdb/ * arm-tdep.c (arm_elf_make_msymbol_special): Use ARM_GET_SYM_BRANCH_TYPE to get branch type of a symbol. include/ * arm.h (enum arm_st_branch_type): Add new ST_BRANCH_ENUM_SIZE enumerator. (NUM_ENUM_ARM_ST_BRANCH_TYPE_BITS): New macro. (ENUM_ARM_ST_BRANCH_TYPE_BITMASK): Likewise. (ARM_SYM_BRANCH_TYPE): Replace by ... (ARM_GET_SYM_BRANCH_TYPE): This and ... (ARM_SET_SYM_BRANCH_TYPE): This in two versions depending on whether BFD_ASSERT is defined or not. ld/ * emultempl/armelf.em (gld${EMULATION_NAME}_finish): Use ARM_GET_SYM_BRANCH_TYPE to get branch type of a symbol. opcodes/ * arm-dis.c (get_sym_code_type): Use ARM_GET_SYM_BRANCH_TYPE to get branch type of a symbol. (print_insn): Likewise. --- bfd/ChangeLog | 13 +++++++ bfd/elf32-arm.c | 85 ++++++++++++++++++++++++------------------ gas/ChangeLog | 5 +++ gas/config/tc-arm.c | 4 +- gdb/ChangeLog | 5 +++ gdb/arm-tdep.c | 4 +- include/ChangeLog | 12 ++++++ include/elf/arm.h | 25 +++++++++++-- ld/ChangeLog | 5 +++ ld/emultempl/armelf.em | 3 +- opcodes/ChangeLog | 6 +++ opcodes/arm-dis.c | 9 +++-- 12 files changed, 129 insertions(+), 47 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 5acc4d0b5a..73fb2ad40a 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,16 @@ +2016-05-10 Thomas Preud'homme + + * elf32-arm.c (elf32_arm_size_stubs): Use new macros + ARM_GET_SYM_BRANCH_TYPE and ARM_SET_SYM_BRANCH_TYPE to respectively get + and set branch type of a symbol. + (bfd_elf32_arm_process_before_allocation): Likewise. + (elf32_arm_relocate_section): Likewise and fix identation along the + way. + (allocate_dynrelocs_for_symbol): Likewise. + (elf32_arm_finish_dynamic_symbol): Likewise. + (elf32_arm_swap_symbol_in): Likewise. + (elf32_arm_swap_symbol_out): Likewise. + 2016-05-10 Thomas Preud'homme * bfd-in.h (elf32_arm_size_stubs): Add an output section parameter. diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index e1ee67315f..76ad7e003c 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -5465,7 +5465,8 @@ elf32_arm_size_stubs (bfd *output_bfd, + sym_sec->output_offset + sym_sec->output_section->vma); st_type = ELF_ST_TYPE (sym->st_info); - branch_type = ARM_SYM_BRANCH_TYPE (sym); + branch_type = + ARM_GET_SYM_BRANCH_TYPE (sym->st_target_internal); sym_name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, @@ -5540,7 +5541,8 @@ elf32_arm_size_stubs (bfd *output_bfd, goto error_ret_free_internal; } st_type = hash->root.type; - branch_type = hash->root.target_internal; + branch_type = + ARM_GET_SYM_BRANCH_TYPE (hash->root.target_internal); sym_name = hash->root.root.root.string; } @@ -6629,7 +6631,8 @@ bfd_elf32_arm_process_before_allocation (bfd *abfd, /* 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 (h->target_internal == ST_BRANCH_TO_THUMB) + if (ARM_GET_SYM_BRANCH_TYPE (h->target_internal) + == ST_BRANCH_TO_THUMB) record_arm_to_thumb_glue (link_info, h); break; @@ -11490,28 +11493,34 @@ elf32_arm_relocate_section (bfd * output_bfd, 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. */ - 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 : - elf32_arm_local_got_tls_type (input_bfd)[r_symndx]) - & GOT_TLS_GDESC))) - { - r = elf32_arm_tls_relax (globals, input_bfd, input_section, - contents, rel, h == NULL); - /* This may have been marked unresolved because it came from - a shared library. But we've just dealt with that. */ - unresolved_reloc = 0; - } - else - r = bfd_reloc_continue; + 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 : + elf32_arm_local_got_tls_type (input_bfd)[r_symndx]) + & GOT_TLS_GDESC))) + { + r = elf32_arm_tls_relax (globals, input_bfd, input_section, + contents, rel, h == NULL); + /* This may have been marked unresolved because it came from + a shared library. But we've just dealt with that. */ + unresolved_reloc = 0; + } + else + r = bfd_reloc_continue; - if (r == bfd_reloc_continue) - r = elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, - input_section, contents, rel, - relocation, info, sec, name, sym_type, - (h ? h->target_internal - : ARM_SYM_BRANCH_TYPE (sym)), h, - &unresolved_reloc, &error_message); + if (r == bfd_reloc_continue) + { + unsigned char branch_type = + h ? ARM_GET_SYM_BRANCH_TYPE (h->target_internal) + : ARM_GET_SYM_BRANCH_TYPE (sym->st_target_internal); + + r = elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, + input_section, contents, rel, + relocation, info, sec, name, + sym_type, branch_type, h, + &unresolved_reloc, + &error_message); + } /* Dynamic relocs are not propagated for SEC_DEBUGGING sections because such sections are not SEC_ALLOC and thus ld.so will @@ -14254,7 +14263,7 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf) /* 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. */ - h->target_internal = ST_BRANCH_TO_ARM; + ARM_SET_SYM_BRANCH_TYPE (h->target_internal, ST_BRANCH_TO_ARM); } /* VxWorks executables have a second set of relocations for @@ -14402,7 +14411,7 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf) /* Allocate stubs for exported Thumb functions on v4t. */ if (!htab->use_blx && h->dynindx != -1 && h->def_regular - && h->target_internal == ST_BRANCH_TO_THUMB + && ARM_GET_SYM_BRANCH_TYPE (h->target_internal) == ST_BRANCH_TO_THUMB && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) { struct elf_link_hash_entry * th; @@ -14422,12 +14431,12 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf) myh = (struct elf_link_hash_entry *) bh; myh->type = ELF_ST_INFO (STB_LOCAL, STT_FUNC); myh->forced_local = 1; - myh->target_internal = ST_BRANCH_TO_THUMB; + ARM_SET_SYM_BRANCH_TYPE (myh->target_internal, ST_BRANCH_TO_THUMB); 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->target_internal = ST_BRANCH_TO_ARM; + ARM_SET_SYM_BRANCH_TYPE (h->target_internal, ST_BRANCH_TO_ARM); h->root.u.def.section = th->root.u.def.section; h->root.u.def.value = th->root.u.def.value & ~1; } @@ -15082,7 +15091,7 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd, /* At least one non-call relocation references this .iplt entry, so the .iplt entry is the function's canonical address. */ sym->st_info = ELF_ST_INFO (ELF_ST_BIND (sym->st_info), STT_FUNC); - sym->st_target_internal = ST_BRANCH_TO_ARM; + ARM_SET_SYM_BRANCH_TYPE (sym->st_target_internal, ST_BRANCH_TO_ARM); sym->st_shndx = (_bfd_elf_section_from_bfd_section (output_bfd, htab->root.iplt->output_section)); sym->st_value = (h->plt.offset @@ -15366,7 +15375,9 @@ elf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info eh = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, TRUE); - if (eh != NULL && eh->target_internal == ST_BRANCH_TO_THUMB) + if (eh != NULL + && ARM_GET_SYM_BRANCH_TYPE (eh->target_internal) + == ST_BRANCH_TO_THUMB) { dyn.d_un.d_val |= 1; bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); @@ -17542,6 +17553,7 @@ elf32_arm_swap_symbol_in (bfd * abfd, { if (!bfd_elf32_swap_symbol_in (abfd, psrc, pshn, dst)) return FALSE; + dst->st_target_internal = 0; /* New EABI objects mark thumb function symbols by setting the low bit of the address. */ @@ -17551,20 +17563,21 @@ elf32_arm_swap_symbol_in (bfd * abfd, if (dst->st_value & 1) { dst->st_value &= ~(bfd_vma) 1; - dst->st_target_internal = ST_BRANCH_TO_THUMB; + ARM_SET_SYM_BRANCH_TYPE (dst->st_target_internal, + ST_BRANCH_TO_THUMB); } else - dst->st_target_internal = ST_BRANCH_TO_ARM; + ARM_SET_SYM_BRANCH_TYPE (dst->st_target_internal, ST_BRANCH_TO_ARM); } else if (ELF_ST_TYPE (dst->st_info) == STT_ARM_TFUNC) { dst->st_info = ELF_ST_INFO (ELF_ST_BIND (dst->st_info), STT_FUNC); - dst->st_target_internal = ST_BRANCH_TO_THUMB; + ARM_SET_SYM_BRANCH_TYPE (dst->st_target_internal, ST_BRANCH_TO_THUMB); } else if (ELF_ST_TYPE (dst->st_info) == STT_SECTION) - dst->st_target_internal = ST_BRANCH_LONG; + ARM_SET_SYM_BRANCH_TYPE (dst->st_target_internal, ST_BRANCH_LONG); else - dst->st_target_internal = ST_BRANCH_UNKNOWN; + ARM_SET_SYM_BRANCH_TYPE (dst->st_target_internal, ST_BRANCH_UNKNOWN); return TRUE; } @@ -17584,7 +17597,7 @@ elf32_arm_swap_symbol_out (bfd *abfd, of the address set, as per the new EABI. We do this unconditionally because objcopy does not set the elf header flags until after it writes out the symbol table. */ - if (src->st_target_internal == ST_BRANCH_TO_THUMB) + if (ARM_GET_SYM_BRANCH_TYPE (src->st_target_internal) == ST_BRANCH_TO_THUMB) { newsym = *src; if (ELF_ST_TYPE (src->st_info) != STT_GNU_IFUNC) diff --git a/gas/ChangeLog b/gas/ChangeLog index 73fa083112..0012cd7b73 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,8 @@ +2016-05-10 Thomas Preud'homme + + * config/tc-arm.c (arm_adjust_symtab): Use ARM_SET_SYM_BRANCH_TYPE to + set branch type of a symbol. + 2016-05-10 Thomas Preud'homme * NEWS: Document ARMv8-M and ARMv8-M Security and DSP Extensions. diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index e8619b6705..b5f378661e 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -24694,8 +24694,8 @@ arm_adjust_symtab (void) /* If it's a .thumb_func, declare it as so, otherwise tag label as .code 16. */ if (THUMB_IS_FUNC (sym)) - elf_sym->internal_elf_sym.st_target_internal - = ST_BRANCH_TO_THUMB; + ARM_SET_SYM_BRANCH_TYPE (elf_sym->internal_elf_sym.st_target_internal, + ST_BRANCH_TO_THUMB); else if (EF_ARM_EABI_VERSION (meabi_flags) < EF_ARM_EABI_VER4) elf_sym->internal_elf_sym.st_info = ELF_ST_INFO (bind, STT_ARM_16BIT); diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 35119af4bd..519c6d1d7c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2016-05-10 Thomas Preud'homme + + * arm-tdep.c (arm_elf_make_msymbol_special): Use + ARM_GET_SYM_BRANCH_TYPE to get branch type of a symbol. + 2016-05-07 Trevor Saunders * aarch64-linux-tdep.c (aarch64_linux_sigframe_init): Remove unused diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index c7d84be5d8..157f8a12fb 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -8538,7 +8538,9 @@ coff_sym_is_thumb (int val) static void arm_elf_make_msymbol_special(asymbol *sym, struct minimal_symbol *msym) { - if (ARM_SYM_BRANCH_TYPE (&((elf_symbol_type *)sym)->internal_elf_sym) + elf_symbol_type *elfsym = (elf_symbol_type *) sym; + + if (ARM_GET_SYM_BRANCH_TYPE (elfsym->internal_elf_sym.st_target_internal) == ST_BRANCH_TO_THUMB) MSYMBOL_SET_SPECIAL (msym); } diff --git a/include/ChangeLog b/include/ChangeLog index 63d68c39ec..3d17849176 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,15 @@ +2016-05-10 Thomas Preud'homme + Nick Clifton + + * arm.h (enum arm_st_branch_type): Add new ST_BRANCH_ENUM_SIZE + enumerator. + (NUM_ENUM_ARM_ST_BRANCH_TYPE_BITS): New macro. + (ENUM_ARM_ST_BRANCH_TYPE_BITMASK): Likewise. + (ARM_SYM_BRANCH_TYPE): Replace by ... + (ARM_GET_SYM_BRANCH_TYPE): This and ... + (ARM_SET_SYM_BRANCH_TYPE): This in two versions depending on whether + BFD_ASSERT is defined or not. + 2016-05-10 Thomas Preud'homme * elf/arm.h (Tag_DSP_extension): Define. diff --git a/include/elf/arm.h b/include/elf/arm.h index bd9fd8bcf5..bafc03c52e 100644 --- a/include/elf/arm.h +++ b/include/elf/arm.h @@ -359,10 +359,29 @@ enum arm_st_branch_type { ST_BRANCH_TO_ARM, ST_BRANCH_TO_THUMB, ST_BRANCH_LONG, - ST_BRANCH_UNKNOWN + ST_BRANCH_UNKNOWN, + ST_BRANCH_ENUM_SIZE }; -#define ARM_SYM_BRANCH_TYPE(SYM) \ - ((enum arm_st_branch_type) (SYM)->st_target_internal) +#define NUM_ENUM_ARM_ST_BRANCH_TYPE_BITS 2 +#define ENUM_ARM_ST_BRANCH_TYPE_BITMASK \ + ((1 << NUM_ENUM_ARM_ST_BRANCH_TYPE_BITS) - 1) + +#define ARM_GET_SYM_BRANCH_TYPE(STI) \ + ((enum arm_st_branch_type) ((STI) & ENUM_ARM_ST_BRANCH_TYPE_BITMASK)) +#ifdef BFD_ASSERT +#define ARM_SET_SYM_BRANCH_TYPE(STI, TYPE) \ + do { \ + BFD_ASSERT (TYPE <= ST_BRANCH_ENUM_SIZE); \ + BFD_ASSERT ((1 << NUM_ENUM_ARM_ST_BRANCH_TYPE_BITS) \ + >= ST_BRANCH_ENUM_SIZE); \ + (STI) = (((STI) & ~ENUM_ARM_ST_BRANCH_TYPE_BITMASK) \ + | ((TYPE) & ENUM_ARM_ST_BRANCH_TYPE_BITMASK)); \ + } while (0) +#else +#define ARM_SET_SYM_BRANCH_TYPE(STI, TYPE) \ + (STI) = (((STI) & ~ENUM_ARM_ST_BRANCH_TYPE_BITMASK) \ + | ((TYPE) & ENUM_ARM_ST_BRANCH_TYPE_BITMASK)) +#endif #endif /* _ELF_ARM_H */ diff --git a/ld/ChangeLog b/ld/ChangeLog index e7a4316855..9e0e7fbb6e 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,8 @@ +2016-05-10 Thomas Preud'homme + + * emultempl/armelf.em (gld${EMULATION_NAME}_finish): Use + ARM_GET_SYM_BRANCH_TYPE to get branch type of a symbol. + 2016-05-10 Thomas Preud'homme * emultempl/armelf.em (elf32_arm_add_stub_section): Add output_section diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em index bfb7ee498a..caa2fbfff3 100644 --- a/ld/emultempl/armelf.em +++ b/ld/emultempl/armelf.em @@ -447,7 +447,8 @@ gld${EMULATION_NAME}_finish (void) h = bfd_link_hash_lookup (link_info.hash, entry_symbol.name, FALSE, FALSE, TRUE); eh = (struct elf_link_hash_entry *)h; - if (!h || eh->target_internal != ST_BRANCH_TO_THUMB) + if (!h || ARM_GET_SYM_BRANCH_TYPE (eh->target_internal) + != ST_BRANCH_TO_THUMB) return; } diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 2e2aaf5cb2..2472fd5175 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,9 @@ +2016-05-10 Thomas Preud'homme + + * arm-dis.c (get_sym_code_type): Use ARM_GET_SYM_BRANCH_TYPE to get + branch type of a symbol. + (print_insn): Likewise. + 2016-05-10 Thomas Preud'homme * arm-dis.c (coprocessor_opcodes): Add entries for VFP ARMv8-M diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index 3d69c7d89b..688981598c 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -6288,7 +6288,8 @@ get_sym_code_type (struct disassemble_info *info, /* If the symbol has function type then use that. */ if (type == STT_FUNC || type == STT_GNU_IFUNC) { - if (ARM_SYM_BRANCH_TYPE (&es->internal_elf_sym) == ST_BRANCH_TO_THUMB) + if (ARM_GET_SYM_BRANCH_TYPE (es->internal_elf_sym.st_target_internal) + == ST_BRANCH_TO_THUMB) *map_type = MAP_THUMB; else *map_type = MAP_ARM; @@ -6655,9 +6656,9 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little) es = *(elf_symbol_type **)(info->symbols); type = ELF_ST_TYPE (es->internal_elf_sym.st_info); - is_thumb = ((ARM_SYM_BRANCH_TYPE (&es->internal_elf_sym) - == ST_BRANCH_TO_THUMB) - || type == STT_ARM_16BIT); + is_thumb = + ((ARM_GET_SYM_BRANCH_TYPE (es->internal_elf_sym.st_target_internal) + == ST_BRANCH_TO_THUMB) || type == STT_ARM_16BIT); } else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_mach_o_flavour)