+2020-10-20 Siddhesh Poyarekar <siddesh.poyarekar@arm.com>
+
+ * 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 <siddesh.poyarekar@arm.com>
* cpu-aarch64.c (bfd_is_aarch64_special_symbol_name): Add
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:
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:
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;
}
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;
}
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). */
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,
+2020-10-20 Siddhesh Poyarekar <siddesh.poyarekar@arm.com>
+
+ * 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 <siddesh.poyarekar@arm.com>
* config/tc-aarch64.h (mstate): Add MAP_C64.
#include "safe-ctype.h"
#include "subsegs.h"
#include "obstack.h"
+#include "cpu-aarch64.h"
#ifdef OBJ_ELF
#include "elf/aarch64.h"
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
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
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);
{
last_label_seen = sym;
+ AARCH64_SET_C64 (sym, IS_C64);
+
dwarf2_emit_label (sym);
}
}
#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. */
(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
#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
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 *);
+2020-10-20 Siddhesh Poyarekar <siddesh.poyarekar@arm.com>
+
+ * elf/aarch64.h (aarch64_st_branch_type): New enum.
+
2020-10-20 Siddhesh Poyarekar <siddesh.poyarekar@arm.com>
* opcode/aarch64.h (aarch64_opcode_encode): Add cpu variant
END_RELOC_NUMBERS (R_AARCH64_end)
+enum aarch64_st_branch_type
+{
+ ST_BRANCH_TO_A64,
+ ST_BRANCH_TO_C64,
+};
+
#endif /* _ELF_AARCH64_H */
+2020-10-20 Siddhesh Poyarekar <siddesh.poyarekar@arm.com>
+
+ * aarch64-dis.c: Include elf/aarch64.h.
+ (get_sym_code_type): Identify C64 functions.
+
2020-10-20 Siddhesh Poyarekar <siddesh.poyarekar@arm.com>
* aarch64-asm.c (aarch64_opcode_encode): Add CPU variant
#include "opintl.h"
#include "aarch64-dis.h"
#include "elf-bfd.h"
+#include "elf/aarch64.h"
#define INSNLEN 4
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;
}