From: Siddhesh Poyarekar Date: Fri, 11 Sep 2020 03:48:05 +0000 (+0530) Subject: [Morello] Set LSB for c64 symbols in object code X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8b21361b83664e13b65264c1ef44030bfa927663;p=thirdparty%2Fbinutils-gdb.git [Morello] Set LSB for c64 symbols in object code The Morello processor takes the LSB of the PCC (i.e. the capability equivalent of PC) as a hint to set PE state to C64 when set and A64 otherwise. bfd/ChangeLog: 2020-10-20 Siddhesh Poyarekar * elfnn-aarch64.c (elfNN_aarch64_final_link_relocate): Set LSB for C64 symbols. (elfNN_aarch64_output_map_sym, elfNN_aarch64_output_stub_sym): Initialise st_target_internal. (aarch64_elfNN_swap_symbol_in, aarch64_elfNN_swap_symbol_out): New functions. (elfNN_aarch64_size_info): Add them as callbacks. gas/ChangeLog: 2020-10-20 Siddhesh Poyarekar * config/tc-aarch64.c: Include cpu-aarch64.h. (IS_C64): New macro. (make_mapping_symbol, aarch64_frob_label): Set LSB of C64 symbol. (aarch64_adjust_symtab): Mark all C64 functions. (parse_operands): Set LSB when target of ADR is a function. (aarch64_fix_adjustable): New function. * config/tc-aarch64.h (AARCH64_SET_FLAG, AARCH64_RESET_FLAG, AARCH64_FLAG_C64, AARCH64_IS_C64, AARCH64_SET_C64): New macros. (aarch64_fix_adjustable): New function. (tc_fix_adjustable): Use it. include/ChangeLog: 2020-10-20 Siddhesh Poyarekar * elf/aarch64.h (aarch64_st_branch_type): New enum. opcodes/ChangeLog: 2020-10-20 Siddhesh Poyarekar * aarch64-dis.c: Include elf/aarch64.h. (get_sym_code_type): Identify C64 functions. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 7b83a289204..37089f3f606 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +2020-10-20 Siddhesh Poyarekar + + * elfnn-aarch64.c (elfNN_aarch64_final_link_relocate): Set LSB for C64 symbols. + (elfNN_aarch64_output_map_sym, elfNN_aarch64_output_stub_sym): + Initialise st_target_internal. + (aarch64_elfNN_swap_symbol_in, aarch64_elfNN_swap_symbol_out): + New functions. + (elfNN_aarch64_size_info): Add them as callbacks. + 2020-10-20 Siddhesh Poyarekar * cpu-aarch64.c (bfd_is_aarch64_special_symbol_name): Add diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index a38da729738..cce538f7a34 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -5893,6 +5893,10 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, place, value, signed_addend, weak_undef_p); + + if (bfd_r_type == BFD_RELOC_AARCH64_ADR_LO21_PCREL && sym != NULL + && sym->st_target_internal & ST_BRANCH_TO_C64) + value |= 1; break; case BFD_RELOC_AARCH64_BRANCH19: @@ -5931,6 +5935,10 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type, place, value, signed_addend, weak_undef_p); + if (bfd_r_type == BFD_RELOC_AARCH64_ADD_LO12 && sym != NULL + && sym->st_target_internal & ST_BRANCH_TO_C64) + value |= 1; + break; case BFD_RELOC_AARCH64_ADR_GOT_PAGE: @@ -8268,6 +8276,7 @@ elfNN_aarch64_output_map_sym (output_arch_syminfo *osi, sym.st_other = 0; sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_NOTYPE); sym.st_shndx = osi->sec_shndx; + sym.st_target_internal = 0; return osi->func (osi->finfo, names[type], &sym, osi->sec, NULL) == 1; } @@ -8285,6 +8294,7 @@ elfNN_aarch64_output_stub_sym (output_arch_syminfo *osi, const char *name, sym.st_other = 0; sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FUNC); sym.st_shndx = osi->sec_shndx; + sym.st_target_internal = 0; return osi->func (osi->finfo, name, &sym, osi->sec, NULL) == 1; } @@ -9915,6 +9925,48 @@ elfNN_aarch64_merge_gnu_properties (struct bfd_link_info *info, bprop, prop); } +/* Demangle c64 function symbols as we read them in. */ + +static bfd_boolean +aarch64_elfNN_swap_symbol_in (bfd * abfd, + const void *psrc, + const void *pshn, + Elf_Internal_Sym *dst) +{ + if (!bfd_elfNN_swap_symbol_in (abfd, psrc, pshn, dst)) + return FALSE; + + dst->st_target_internal = 0; + + if (ELF_ST_TYPE (dst->st_info) == STT_FUNC + || ELF_ST_TYPE (dst->st_info) == STT_GNU_IFUNC) + { + dst->st_target_internal = dst->st_value & ST_BRANCH_TO_C64; + dst->st_value &= ~(bfd_vma) ST_BRANCH_TO_C64; + } + + return TRUE; +} + + +/* Mangle c64 function symbols as we write them out. */ + +static void +aarch64_elfNN_swap_symbol_out (bfd *abfd, + const Elf_Internal_Sym *src, + void *cdst, + void *shndx) +{ + Elf_Internal_Sym newsym = *src; + + if ((ELF_ST_TYPE (newsym.st_info) == STT_FUNC + || ELF_ST_TYPE (newsym.st_info) == STT_GNU_IFUNC) + && newsym.st_shndx != SHN_UNDEF) + newsym.st_value |= newsym.st_target_internal; + + bfd_elfNN_swap_symbol_out (abfd, &newsym, cdst, shndx); +} + /* We use this so we can override certain functions (though currently we don't). */ @@ -9937,8 +9989,8 @@ const struct elf_size_info elfNN_aarch64_size_info = bfd_elfNN_write_shdrs_and_ehdr, bfd_elfNN_checksum_contents, bfd_elfNN_write_relocs, - bfd_elfNN_swap_symbol_in, - bfd_elfNN_swap_symbol_out, + aarch64_elfNN_swap_symbol_in, + aarch64_elfNN_swap_symbol_out, bfd_elfNN_slurp_reloc_table, bfd_elfNN_slurp_symbol_table, bfd_elfNN_swap_dyn_in, diff --git a/gas/ChangeLog b/gas/ChangeLog index bf0b6dcc593..aed6c2d7605 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,18 @@ +2020-10-20 Siddhesh Poyarekar + + * config/tc-aarch64.c: Include cpu-aarch64.h. + (IS_C64): New macro. + (make_mapping_symbol, aarch64_frob_label): Set LSB of C64 + symbol. + (aarch64_adjust_symtab): Mark all C64 functions. + (parse_operands): Set LSB when target of ADR is a function. + (aarch64_fix_adjustable): New function. + * config/tc-aarch64.h (AARCH64_SET_FLAG, AARCH64_RESET_FLAG, + AARCH64_FLAG_C64, AARCH64_IS_C64, AARCH64_SET_C64): New + macros. + (aarch64_fix_adjustable): New function. + (tc_fix_adjustable): Use it. + 2020-10-20 Siddhesh Poyarekar * config/tc-aarch64.h (mstate): Add MAP_C64. diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index e768c041b12..4616c39bf3c 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -27,6 +27,7 @@ #include "safe-ctype.h" #include "subsegs.h" #include "obstack.h" +#include "cpu-aarch64.h" #ifdef OBJ_ELF #include "elf/aarch64.h" @@ -48,6 +49,9 @@ AARCH64_FEATURE_C64) \ ? MAP_C64 : MAP_INSN) +#define IS_C64 (AARCH64_CPU_HAS_FEATURE (cpu_variant, AARCH64_FEATURE_C64) \ + ? 1 : 0) + static aarch64_feature_set cpu_variant; /* Variables that we set while parsing command-line options. Once all @@ -1564,6 +1568,11 @@ make_mapping_symbol (enum mstate state, valueT value, fragS * frag) symbolP = symbol_new (symname, now_seg, frag, value); symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL; + if (state == MAP_C64) + AARCH64_SET_C64 (symbolP, 1); + else if (state == MAP_INSN) + AARCH64_SET_C64 (symbolP, 0); + /* Save the mapping symbols for future reference. Also check that we do not place two mapping symbols at the same offset within a frag. We'll handle overlap between frags in @@ -6337,6 +6346,21 @@ parse_operands (char *str, const aarch64_opcode *opcode) case pcreladdr: gas_assert (operands[i] == AARCH64_OPND_ADDR_PCREL21); inst.reloc.type = BFD_RELOC_AARCH64_ADR_LO21_PCREL; + if (inst.reloc.exp.X_op == O_symbol + && inst.reloc.exp.X_add_symbol != NULL) + { + symbolS *sym = inst.reloc.exp.X_add_symbol; + + /* We set LSB for C64 local functions. We do not do + this for local labels even in code section because + it could be embedded data. */ + if (S_IS_DEFINED (sym) && AARCH64_IS_C64 (sym) + && (symbol_get_bfdsym (sym)->flags & BSF_FUNCTION)) + { + inst.reloc.exp.X_add_number += 1; + } + } + break; default: gas_assert (0); @@ -7251,6 +7275,8 @@ aarch64_frob_label (symbolS * sym) { last_label_seen = sym; + AARCH64_SET_C64 (sym, IS_C64); + dwarf2_emit_label (sym); } @@ -8677,12 +8703,54 @@ check_mapping_symbols (bfd * abfd ATTRIBUTE_UNUSED, asection * sec, } #endif +/* Avoid relocations from using section symbols in some cases. */ +bfd_boolean +aarch64_fix_adjustable (struct fix *fixP) +{ + switch (fixP->fx_r_type) + { + /* A64 <-> C64 transitions are handled by the static linker, so keep + symbol information intact to allow the linker to do something useful + with it. */ + case BFD_RELOC_AARCH64_ADR_LO21_PCREL: + case BFD_RELOC_AARCH64_ADD_LO12: + case BFD_RELOC_AARCH64_BRANCH19: + case BFD_RELOC_AARCH64_TSTBR14: + case BFD_RELOC_AARCH64_JUMP26: + case BFD_RELOC_AARCH64_CALL26: + if (AARCH64_IS_C64 (fixP->fx_addsy)) + return FALSE; + break; + default: + break; + } + + return TRUE; +} + /* Adjust the symbol table. */ void aarch64_adjust_symtab (void) { #ifdef OBJ_ELF + symbolS * sym; + + for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym)) + { + if (AARCH64_IS_C64 (sym) + && (symbol_get_bfdsym (sym)->flags & BSF_FUNCTION)) + { + elf_symbol_type * elf_sym; + + elf_sym = elf_symbol (symbol_get_bfdsym (sym)); + + if (!bfd_is_aarch64_special_symbol_name + (elf_sym->symbol.name, BFD_AARCH64_SPECIAL_SYM_TYPE_ANY)) + elf_sym->internal_elf_sym.st_target_internal = ST_BRANCH_TO_C64; + } + } + /* Remove any overlapping mapping symbols generated by alignment frags. */ bfd_map_over_sections (stdoutput, check_mapping_symbols, (char *) 0); /* Now do generic ELF adjustments. */ diff --git a/gas/config/tc-aarch64.h b/gas/config/tc-aarch64.h index edaed03eea7..18f409444dc 100644 --- a/gas/config/tc-aarch64.h +++ b/gas/config/tc-aarch64.h @@ -122,7 +122,15 @@ enum pointer_auth_key { (FIX)->tc_fix_data.opnd = AARCH64_OPND_NIL; } #define TC_SYMFIELD_TYPE unsigned int -#define AARCH64_GET_FLAG(s) (*symbol_get_tc (s)) +#define AARCH64_GET_FLAG(s) (*symbol_get_tc (s)) +#define AARCH64_SET_FLAG(s,v) (*symbol_get_tc (s) |= (v)) +#define AARCH64_RESET_FLAG(s,v) (*symbol_get_tc (s) &= ~(v)) + +#define AARCH64_FLAG_C64 (1 << 0) /* C64 function. */ + +#define AARCH64_IS_C64(s) (AARCH64_GET_FLAG (s) & AARCH64_FLAG_C64) +#define AARCH64_SET_C64(s,t) ((t) ? AARCH64_SET_FLAG (s, AARCH64_FLAG_C64) \ + : AARCH64_RESET_FLAG (s, AARCH64_FLAG_C64)) void aarch64_copy_symbol_attributes (symbolS *, symbolS *); #ifndef TC_COPY_SYMBOL_ATTRIBUTES @@ -248,7 +256,7 @@ extern void aarch64_after_parse_args (void); #if defined OBJ_ELF || defined OBJ_COFF # define EXTERN_FORCE_RELOC 1 -# define tc_fix_adjustable(FIX) 1 +# define tc_fix_adjustable(f) aarch64_fix_adjustable (f) /* Values passed to md_apply_fix don't include the symbol value. */ # define MD_APPLY_SYM_VALUE(FIX) 0 @@ -265,6 +273,7 @@ extern void aarch64_frob_label (symbolS *); extern void aarch64_frob_section (asection *sec); extern int aarch64_data_in_code (void); extern char * aarch64_canonicalize_symbol_name (char *); +extern bfd_boolean aarch64_fix_adjustable (struct fix *); extern void aarch64_adjust_symtab (void); extern void aarch64elf_frob_symbol (symbolS *, int *); extern void cons_fix_new_aarch64 (fragS *, int, int, expressionS *); diff --git a/include/ChangeLog b/include/ChangeLog index 331e08d1fca..07a8257adb2 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2020-10-20 Siddhesh Poyarekar + + * elf/aarch64.h (aarch64_st_branch_type): New enum. + 2020-10-20 Siddhesh Poyarekar * opcode/aarch64.h (aarch64_opcode_encode): Add cpu variant diff --git a/include/elf/aarch64.h b/include/elf/aarch64.h index 96ca5c72408..c55e74026b8 100644 --- a/include/elf/aarch64.h +++ b/include/elf/aarch64.h @@ -444,4 +444,10 @@ RELOC_NUMBER (R_AARCH64_IRELATIVE, 1032) END_RELOC_NUMBERS (R_AARCH64_end) +enum aarch64_st_branch_type +{ + ST_BRANCH_TO_A64, + ST_BRANCH_TO_C64, +}; + #endif /* _ELF_AARCH64_H */ diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index c33d91e68ef..fcea5b08e34 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,8 @@ +2020-10-20 Siddhesh Poyarekar + + * aarch64-dis.c: Include elf/aarch64.h. + (get_sym_code_type): Identify C64 functions. + 2020-10-20 Siddhesh Poyarekar * aarch64-asm.c (aarch64_opcode_encode): Add CPU variant diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c index 10840e642b7..f6a942f5a44 100644 --- a/opcodes/aarch64-dis.c +++ b/opcodes/aarch64-dis.c @@ -25,6 +25,7 @@ #include "opintl.h" #include "aarch64-dis.h" #include "elf-bfd.h" +#include "elf/aarch64.h" #define INSNLEN 4 @@ -3352,12 +3353,11 @@ get_sym_code_type (struct disassemble_info *info, int n, type = ELF_ST_TYPE (es->internal_elf_sym.st_info); - /* If the symbol has function type then use that. Set mapping symbol as - MAP_INSN only if transitioning from MAP_DATA. We do this to conserve any - previous MAP_C64 type. */ + /* ST_TARGET_INTERNAL is set for C64. */ if (type == STT_FUNC) { - *map_type = *map_type == MAP_DATA ? MAP_INSN : *map_type; + *map_type = (es->internal_elf_sym.st_target_internal & ST_BRANCH_TO_C64 + ? MAP_C64 : MAP_INSN); return TRUE; }