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/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cb633492f2dd544887ef1208696cb2b156049828;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 1e5ab5b38a5..1b8ae4e27aa 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 2757812b400..d6de86042e6 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -5896,6 +5896,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: @@ -5934,6 +5938,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: @@ -8362,6 +8370,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; } @@ -8379,6 +8388,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; } @@ -10011,6 +10021,48 @@ elfNN_aarch64_merge_gnu_properties (struct bfd_link_info *info, bprop, prop); } +/* Demangle c64 function symbols as we read them in. */ + +static bool +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). */ @@ -10033,8 +10085,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 ddeee976e8c..9605a7431d7 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 0c191eb959f..81b1f0a5372 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 @@ -1539,6 +1543,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 @@ -7018,6 +7027,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); @@ -8130,6 +8154,8 @@ aarch64_frob_label (symbolS * sym) { last_label_seen = sym; + AARCH64_SET_C64 (sym, IS_C64); + dwarf2_emit_label (sym); } @@ -9475,12 +9501,54 @@ check_mapping_symbols (bfd * abfd ATTRIBUTE_UNUSED, asection * sec, } #endif +/* Avoid relocations from using section symbols in some cases. */ +bool +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 b463840b444..67deb2133e2 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 @@ -250,7 +258,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 @@ -267,6 +275,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 bool 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 1a9cfd33992..b5857cb9750 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 e368ff2dffe..ec04bb6a17b 100644 --- a/include/elf/aarch64.h +++ b/include/elf/aarch64.h @@ -447,4 +447,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 fce7b298278..dd5b8bea9a7 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 48d818d0268..fd56b7aa888 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 @@ -3586,12 +3587,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; }