From c2ecca24db224f9d5fe2a5193dacfa6af826b9d0 Mon Sep 17 00:00:00 2001 From: Edmund Grimley Evans Date: Fri, 11 Mar 2016 10:12:50 +0000 Subject: [PATCH] i#1569 AArch64: Make AArch64 build. It builds, but binaries are non-functional as many things are not yet implemented. Review-URL: https://codereview.appspot.com/293720043 --- api/samples/CMakeLists.txt | 12 ++- core/arch/arch.c | 24 +++--- core/arch/arch.h | 4 +- core/arch/arch_exports.h | 59 +++++++++++--- core/arch/asm_defines.asm | 112 ++++++++++++++++---------- core/arch/decode.h | 8 +- core/arch/emit_utils_shared.c | 35 ++++++-- core/arch/instr.h | 6 +- core/arch/instr_create_shared.h | 2 + core/arch/instr_inline.h | 12 ++- core/arch/instr_shared.c | 20 +++-- core/arch/interp.c | 20 +++-- core/arch/opnd.h | 16 +++- core/arch/opnd_shared.c | 27 ++++--- core/arch/proc.h | 4 +- core/fragment.h | 6 +- core/globals.h | 4 +- core/lib/globals_shared.h | 13 ++- core/lib/instrument.c | 20 +++-- core/lib/mcxtx.h | 4 +- core/optionsx.h | 52 ++++++------ core/os_shared.h | 4 +- core/translate.c | 3 + core/unix/include/syscall.h | 2 +- core/unix/include/syscall_linux_arm.h | 24 +++--- core/unix/injector.c | 43 +++++++--- core/unix/loader.c | 20 +++-- core/unix/loader_linux.c | 35 ++++---- core/unix/module_elf.c | 19 +++-- core/unix/module_elf.h | 60 ++++++++------ core/unix/native_elf.c | 4 +- core/unix/os.c | 43 +++++----- core/unix/os_exports.h | 13 ++- core/unix/os_private.h | 4 + core/unix/os_public.h | 50 ++++++------ core/unix/signal.c | 53 +++++++++--- core/unix/signal_linux.c | 2 +- core/unix/signal_private.h | 19 ++++- core/unix/tls.h | 16 ++-- ext/drreg/drreg.c | 2 +- ext/drutil/drutil.c | 8 +- ext/drwrap/drwrap.c | 14 ++-- ext/drwrap/drwrap.h | 7 +- ext/drx/drx.c | 12 +-- ext/drx/drx.h | 2 +- 45 files changed, 581 insertions(+), 338 deletions(-) diff --git a/api/samples/CMakeLists.txt b/api/samples/CMakeLists.txt index e523ea030e7..5a7519bf0b9 100644 --- a/api/samples/CMakeLists.txt +++ b/api/samples/CMakeLists.txt @@ -206,11 +206,13 @@ configure_DynamoRIO_global(OFF ON) # Use ;-separated lists for source files and extensions. -add_sample_client(bbbuf "bbbuf.c" "drmgr;drreg") +if (NOT AARCH64) # FIXME i#1569: port to AArch64 + add_sample_client(bbbuf "bbbuf.c" "drmgr;drreg") +endif () add_sample_client(bbsize "bbsize.c" "drmgr") add_sample_client(empty "empty.c" "") add_sample_client(memtrace_simple "memtrace_simple.c;utils.c" "drmgr;drutil;drx") -if (NOT ARM) # FIXME i#1551: port to ARM +if (X86) # FIXME i#1551, i#1569: port to ARM and AArch64 add_sample_client(bbcount "bbcount.c" "drmgr;drreg") add_sample_client(cbr "cbr.c" "drmgr") add_sample_client(countcalls "countcalls.c" "") @@ -227,13 +229,15 @@ if (NOT ARM) # FIXME i#1551: port to ARM add_sample_client(instrcalls "instrcalls.c;utils.c" "drmgr;drsyms;drx") # dr_insert_cbr_instrument_ex is NYI add_sample_client(cbrtrace "cbrtrace.c;utils.c" "drx") -endif (NOT ARM) +endif (X86) add_sample_client(wrap "wrap.c" "drmgr;drwrap") add_sample_client(signal "signal.c" "drmgr") add_sample_client(syscall "syscall.c" "drmgr") add_sample_client(inline "inline.c" "") add_sample_client(inscount "inscount.c" "drmgr") -add_sample_client(opcodes "opcodes.c" "drx") +if (NOT AARCH64) # FIXME i#1569: port to AArch64 + add_sample_client(opcodes "opcodes.c" "drx") +endif () add_sample_client(stl_test "stl_test.cpp" "") # add utils.h for installation # NON-PUBLIC set(srcs ${srcs} "utils.h") # NON-PUBLIC diff --git a/core/arch/arch.c b/core/arch/arch.c index 6c427144a02..e3587db549b 100644 --- a/core/arch/arch.c +++ b/core/arch/arch.c @@ -417,7 +417,7 @@ shared_gencode_emit(generated_code_t *gencode _IF_X86_64(bool x86_mode)) gencode->do_syscall = pc; pc = emit_do_syscall(GLOBAL_DCONTEXT, gencode, pc, gencode->fcache_return, true/*shared*/, 0, &gencode->do_syscall_offs); -# ifdef ARM +# if defined(ARM) || defined(AARCH64) /* ARM has no thread-private gencode, so our clone syscall is shared */ gencode->do_clone_syscall = pc; pc = emit_do_clone_syscall(GLOBAL_DCONTEXT, gencode, pc, gencode->fcache_return, @@ -559,7 +559,7 @@ shared_gencode_init(IF_X86_64_ELSE(gencode_mode_t gencode_mode, void)) protect_generated_code(gencode, READONLY); } -#ifdef ARM +#if defined(ARM) || defined(AARCH64) /* Called during a reset when all threads are suspended */ void arch_reset_stolen_reg(void) @@ -570,6 +570,9 @@ arch_reset_stolen_reg(void) */ dr_isa_mode_t old_mode; dcontext_t *dcontext; +#ifdef AARCH64 + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ +#endif if (DR_REG_R0 + INTERNAL_OPTION(steal_reg_at_reset) == dr_reg_stolen) return; SYSLOG_INTERNAL_INFO("swapping stolen reg from %s to %s", @@ -595,6 +598,9 @@ arch_reset_stolen_reg(void) void arch_mcontext_reset_stolen_reg(dcontext_t *dcontext, priv_mcontext_t *mc) { +#ifdef AARCH64 + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ +#endif /* Put the app value in the old stolen reg */ *(reg_t*)(((byte *)mc) + opnd_get_reg_dcontext_offs(DR_REG_R0 + INTERNAL_OPTION(steal_reg))) = @@ -664,7 +670,7 @@ arch_init(void) ASSERT(syscall_method != SYSCALL_METHOD_UNINITIALIZED); #endif -#ifdef ARM +#if defined(ARM) || defined(AARCH64) dr_reg_stolen = DR_REG_R0 + DYNAMO_OPTION(steal_reg); ASSERT(dr_reg_stolen >= DR_REG_STOLEN_MIN && dr_reg_stolen <= DR_REG_STOLEN_MAX) #endif @@ -1104,7 +1110,7 @@ arch_thread_init(dcontext_t *dcontext) return; #endif -#ifdef ARM +#if defined(ARM) || defined(AARCH64) /* Store addresses we access via TLS from exit stubs and gencode. */ get_local_state_extended()->spill_space.fcache_return = PC_AS_JMP_TGT(isa_mode, fcache_return_shared_routine()); @@ -2837,7 +2843,7 @@ hook_vsyscall(dcontext_t *dcontext) instr_free(dcontext, &instr); return res; # undef CHECK -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) /* No vsyscall support needed for our ARM targets */ ASSERT_NOT_REACHED(); return false; @@ -2870,7 +2876,7 @@ unhook_vsyscall(void) ASSERT(res); } return true; -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) ASSERT_NOT_IMPLEMENTED(get_syscall_method() != SYSCALL_METHOD_SYSENTER); return false; #endif /* X86/ARM */ @@ -2892,7 +2898,7 @@ check_syscall_method(dcontext_t *dcontext, instr_t *instr) else if (instr_get_opcode(instr) == OP_call_ind) new_method = SYSCALL_METHOD_WOW64; # endif -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) if (instr_get_opcode(instr) == OP_svc) new_method = SYSCALL_METHOD_SVC; #endif /* X86/ARM */ @@ -3262,7 +3268,7 @@ dump_mcontext(priv_mcontext_t *context, file_t f, bool dump_xml) , context->r8, context->r9, context->r10, context->r11, context->r12, context->r13, context->r14, context->r15 # endif /* X64 */ -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) context->r0, context->r1, context->r2, context->r3, context->r4, context->r5, context->r6, context->r7, context->r8, context->r9, context->r10, context->r11, @@ -3324,7 +3330,7 @@ dump_mcontext(priv_mcontext_t *context, file_t f, bool dump_xml) context->xflags, context->pc); } -#ifdef ARM +#if defined(ARM) || defined(AARCH64) reg_t get_stolen_reg_val(priv_mcontext_t *mc) { diff --git a/core/arch/arch.h b/core/arch/arch.h index f5bd7f48dc4..f097e221194 100644 --- a/core/arch/arch.h +++ b/core/arch/arch.h @@ -114,7 +114,7 @@ mixed_mode_enabled(void) # define SCRATCH_REG3_OFFS XDX_OFFSET # define SCRATCH_REG4_OFFS XSI_OFFSET # define SCRATCH_REG5_OFFS XDI_OFFSET -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) # define R0_OFFSET ((MC_OFFS) + (offsetof(priv_mcontext_t, r0))) # define R1_OFFSET ((MC_OFFS) + (offsetof(priv_mcontext_t, r1))) # define R2_OFFSET ((MC_OFFS) + (offsetof(priv_mcontext_t, r2))) @@ -1291,7 +1291,7 @@ add_patch_entry_internal(patch_list_t *patch, instr_t *instr, ushort patch_flags cache_pc get_direct_exit_target(dcontext_t *dcontext, uint flags); -#ifdef ARM +#if defined(ARM) || defined(AARCH64) size_t get_fcache_return_tls_offs(dcontext_t *dcontext, uint flags); diff --git a/core/arch/arch_exports.h b/core/arch/arch_exports.h index e98b5966353..5d2d94fe336 100644 --- a/core/arch/arch_exports.h +++ b/core/arch/arch_exports.h @@ -125,7 +125,7 @@ typedef struct _table_stat_state_t { #endif } table_stat_state_t; -#ifdef ARM +#if defined(ARM) || defined(AARCH64) typedef struct _ibl_entry_pc_t { byte *ibl; byte *unlinked; @@ -140,13 +140,13 @@ typedef struct _spill_state_t { /* Four registers are used in the indirect branch lookup routines */ #ifdef X86 reg_t xax, xbx, xcx, xdx; /* general-purpose registers */ -#elif defined (ARM) +#elif defined (ARM) || defined(AARCH64) reg_t r0, r1, r2, r3; reg_t reg_stolen; /* slot for the stolen register */ #endif /* FIXME: move this below the tables to fit more on cache line */ dcontext_t *dcontext; -#ifdef ARM +#if defined(ARM) || defined(AARCH64) /* We store addresses here so we can load pointer-sized addresses into * registers with a single instruction in our exit stubs and gencode. */ @@ -184,7 +184,7 @@ typedef struct _local_state_extended_t { # define SCRATCH_REG1 DR_REG_XBX # define SCRATCH_REG2 DR_REG_XCX # define SCRATCH_REG3 DR_REG_XDX -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) # define TLS_REG0_SLOT ((ushort)offsetof(spill_state_t, r0)) # define TLS_REG1_SLOT ((ushort)offsetof(spill_state_t, r1)) # define TLS_REG2_SLOT ((ushort)offsetof(spill_state_t, r2)) @@ -198,7 +198,7 @@ typedef struct _local_state_extended_t { #define IBL_TARGET_REG SCRATCH_REG2 #define IBL_TARGET_SLOT TLS_REG2_SLOT #define TLS_DCONTEXT_SLOT ((ushort)offsetof(spill_state_t, dcontext)) -#ifdef ARM +#if defined(ARM) || defined(AARCH64) # define TLS_FCACHE_RETURN_SLOT ((ushort)offsetof(spill_state_t, fcache_return)) #endif @@ -485,7 +485,39 @@ static inline int64 atomic_add_exchange_int64(volatile int64 *var, int64 value) # define SET_FLAG(cc, flag) __asm__ __volatile__("set"#cc " %0" :"=qm" (flag) ) # define SET_IF_NOT_ZERO(flag) SET_FLAG(nz, flag) # define SET_IF_NOT_LESS(flag) SET_FLAG(nl, flag) + +# elif defined(AARCH64) + +/* FIXME i#1569: NYI */ +# define AARCH64_NYI do { ASSERT_NOT_IMPLEMENTED(false); } while (0) + +# define ATOMIC_INC_int(var) do { AARCH64_NYI; ++var; } while (0) +# define ATOMIC_INC_int64(var) do { AARCH64_NYI; ++var; } while (0) +# define ATOMIC_DEC_int(var) do { AARCH64_NYI; --var; } while (0) +# define ATOMIC_DEC_int64(var) do { AARCH64_NYI; --var; } while (0) +# define ATOMIC_ADD_int(var, val) do { AARCH64_NYI; var += val; } while (0) +# define ATOMIC_ADD_int64(var, val) do { AARCH64_NYI; var += val; } while (0) +# define ATOMIC_ADD_EXCHANGE_int(var, val, res) \ + do { AARCH64_NYI; res = *var; *var += val; } while (0) +# define ATOMIC_ADD_EXCHANGE_int64(var, val, res) \ + do { AARCH64_NYI; res = *var; *var += val; } while (0) +# define ATOMIC_COMPARE_EXCHANGE_int(var, compare, exchange) AARCH64_NYI +# define ATOMIC_COMPARE_EXCHANGE_int64(var, compare, exchange) AARCH64_NYI +# define ATOMIC_EXCHANGE(var, newval, result) \ + do { AARCH64_NYI; result = var; var = newval; } while (0) +# define SPINLOCK_PAUSE() AARCH64_NYI +uint64 proc_get_timestamp(void); +# define RDTSC_LL(llval) AARCH64_NYI + +# define GET_FRAME_PTR(var) asm volatile("mov %0, x29" : "=r"(var)) +# define GET_STACK_PTR(var) asm volatile("mov %0, sp" : "=r"(var)) + +# define SET_FLAG(cc, flag) do { AARCH64_NYI; flag = 0; } while (0) +# define SET_IF_NOT_ZERO(flag) SET_FLAG(ne, flag) +# define SET_IF_NOT_LESS(flag) SET_FLAG(ge, flag) + # else /* ARM */ + # define ATOMIC_4BYTE_WRITE(target, value, hot_patch) do { \ ASSERT(sizeof(value) == 4); \ /* Load and store instructions are atomic on ARM if aligned. */ \ @@ -825,7 +857,7 @@ void arch_thread_exit(dcontext_t *dcontext _IF_WINDOWS(bool detach_stacked_callb void arch_thread_profile_exit(dcontext_t *dcontext); void arch_profile_exit(void); #endif -#ifdef ARM +#if defined(ARM) || defined(AARCH64) void arch_reset_stolen_reg(void); void arch_mcontext_reset_stolen_reg(dcontext_t *dcontext, priv_mcontext_t *mc); #endif @@ -843,7 +875,7 @@ priv_mcontext_t *dr_mcontext_as_priv_mcontext(dr_mcontext_t *mc); priv_mcontext_t *get_priv_mcontext_from_dstack(dcontext_t *dcontext); void dr_mcontext_init(dr_mcontext_t *mc); void dump_mcontext(priv_mcontext_t *context, file_t f, bool dump_xml); -#ifdef ARM +#if defined(ARM) || defined(AARCH64) reg_t get_stolen_reg_val(priv_mcontext_t *context); void set_stolen_reg_val(priv_mcontext_t *mc, reg_t newval); #endif @@ -1323,7 +1355,7 @@ decode_init(void); # define MAX_PAD_SIZE 3 /****************************************************************************/ -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) # ifdef X64 # define FRAG_IS_THUMB(flags) false @@ -1573,6 +1605,13 @@ enum { CTI_IAT_LENGTH = 6, /* FF 15 38 10 80 7C call dword ptr ds:[7C801038h] */ CTI_FAR_ABS_LENGTH = 7, /* 9A 1B 07 00 34 39 call 0739:3400071B */ /* 07 */ +#elif defined(AARCH64) + MAX_INSTR_LENGTH = 4, + CBR_LONG_LENGTH = 4, + JMP_LONG_LENGTH = 4, + JMP_SHORT_LENGTH = 4, + CBR_SHORT_REWRITE_LENGTH = 4, + SVC_LENGTH = 4, #elif defined(ARM) MAX_INSTR_LENGTH = ARM_INSTR_SIZE, CBR_LONG_LENGTH = ARM_INSTR_SIZE, @@ -1946,7 +1985,9 @@ typedef struct dr_jmp_buf_t { reg_t r8, r9, r10, r11, r12, r13, r14, r15; # endif #elif defined(ARM) /* for arm.asm */ - reg_t regs[IF_X64_ELSE(32, 16)/*DR_NUM_GPR_REGS*/]; + reg_t regs[16/*DR_NUM_GPR_REGS*/]; +#elif defined(AARCH64) /* for aarch64.asm */ + reg_t regs[22]; /* callee-save regs: X19-X30, (gap), SP, D8-D15 */ #endif /* X86/ARM */ #if defined(UNIX) && defined(DEBUG) /* i#226/PR 492568: we avoid the cost of storing this by using the diff --git a/core/arch/asm_defines.asm b/core/arch/asm_defines.asm index 71be7857472..53cf4ff4646 100644 --- a/core/arch/asm_defines.asm +++ b/core/arch/asm_defines.asm @@ -49,17 +49,20 @@ # define X86 #endif -#if (defined(ARM_64) || defined(ARM_32)) && !defined(ARM) +#if defined(ARM_64) && !defined(AARCH64) +# define AARCH64 +#endif + +#if defined(ARM_32) && !defined(ARM) # define ARM #endif -#ifdef ARM -# ifdef X64 -# error 64-bit ARM is not supported -# endif -# ifdef WINDOWS -# error ARM on Windows is not supported -# endif +#if (defined(ARM) && defined(X64)) || (defined(AARCH64) && !defined(X64)) +# error ARM is only 32-bit; AARCH64 is 64-bit +#endif + +#if (defined(ARM) || defined(AARCH64)) && defined(WINDOWS) +# error ARM/AArch64 on Windows is not supported #endif #undef WEAK /* avoid conflict with C define */ @@ -99,7 +102,7 @@ # else # define SYMREF(sym) [sym] # endif -# elif defined(ARM) +# elif defined(ARM) || defined(AARCH64) # define BYTE /* nothing */ # define WORD /* nothing */ # define DWORD /* nothing */ @@ -235,39 +238,37 @@ ASSUME fs:_DATA @N@\ /* Macros for writing cross-platform 64-bit + 32-bit code */ /* register set */ -#ifdef ARM +#if defined(ARM) # define REG_SP sp -# ifdef X64 -# define REG_R0 x0 -# define REG_R1 x1 -# define REG_R2 x2 -# define REG_R3 x3 -# define REG_R4 x4 -# define REG_R5 x5 -# define REG_R6 x6 -# define REG_R7 x7 -# define REG_R8 x8 -# define REG_R9 x9 -# define REG_R10 x10 -# define REG_R11 x11 -# define REG_R12 x12 -/* skip [x16..x30], only available on AArch64 */ -# else /* 32-bit */ -# define REG_R0 r0 -# define REG_R1 r1 -# define REG_R2 r2 -# define REG_R3 r3 -# define REG_R4 r4 -# define REG_R5 r5 -# define REG_R6 r6 -# define REG_R7 r7 -# define REG_R8 r8 -# define REG_R9 r9 -# define REG_R10 r10 -# define REG_R11 r11 -# define REG_R12 r12 +# define REG_R0 r0 +# define REG_R1 r1 +# define REG_R2 r2 +# define REG_R3 r3 +# define REG_R4 r4 +# define REG_R5 r5 +# define REG_R6 r6 +# define REG_R7 r7 +# define REG_R8 r8 +# define REG_R9 r9 +# define REG_R10 r10 +# define REG_R11 r11 +# define REG_R12 r12 /* {r13, r14, r15} are used for {sp, lr, pc} on AArch32 */ -# endif /* 64/32-bit */ +#elif defined(AARCH64) +# define REG_R0 x0 +# define REG_R1 x1 +# define REG_R2 x2 +# define REG_R3 x3 +# define REG_R4 x4 +# define REG_R5 x5 +# define REG_R6 x6 +# define REG_R7 x7 +# define REG_R8 x8 +# define REG_R9 x9 +# define REG_R10 x10 +# define REG_R11 x11 +# define REG_R12 x12 +/* skip [x13..x30], not available on AArch32 */ #else /* Intel X86 */ # ifdef X64 # define REG_XAX rax @@ -302,7 +303,7 @@ ASSUME fs:_DATA @N@\ # define PTRSZ DWORD #endif -#ifdef ARM +#if defined(ARM) || defined(AARCH64) /* ARM AArch64 calling convention: * SP: stack pointer * x30(LR): link register @@ -590,6 +591,27 @@ ASSUME fs:_DATA @N@\ SETARG(0, ARG1, p1) @N@\ call callee @N@\ STACK_UNPAD_LE4(2, 3) +#elif defined(AARCH64) +# define CALLC0(callee) \ + bl callee +# define CALLC1(callee, p1) \ + mov ARG1, p1 @N@\ + bl callee +# define CALLC2(callee, p1, p2) \ + mov ARG2, p2 @N@\ + mov ARG1, p1 @N@\ + bl callee +# define CALLC3(callee, p1, p2, p3) \ + mov ARG3, p3 @N@\ + mov ARG2, p2 @N@\ + mov ARG1, p1 @N@\ + bl callee +# define CALLC4(callee, p1, p2, p3, p4) \ + mov ARG4, p4 @N@\ + mov ARG3, p3 @N@\ + mov ARG2, p2 @N@\ + mov ARG1, p1 @N@\ + bl callee #elif defined(ARM) /* Our assembly is ARM but our C code is Thumb so we use blx */ # define CALLC0(callee) \ @@ -643,12 +665,16 @@ ASSUME fs:_DATA @N@\ # define RETURN ret # define INC(reg) inc reg # define DEC(reg) dec reg -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) # define REG_SCRATCH0 REG_R0 # define REG_SCRATCH1 REG_R1 # define REG_SCRATCH2 REG_R2 # define JUMP b -# define RETURN bx lr +# ifdef X64 +# define RETURN ret +# else +# define RETURN bx lr +# endif # define INC(reg) add reg, reg, POUND 1 # define DEC(reg) sub reg, reg, POUND 1 #endif /* X86/ARM */ diff --git a/core/arch/decode.h b/core/arch/decode.h index df4dc1dd964..0513ce5c7ce 100644 --- a/core/arch/decode.h +++ b/core/arch/decode.h @@ -187,7 +187,7 @@ enum { */ #ifdef X86 OPSZ_NA = DR_REG_INVALID+1, /**< Sentinel value: not a valid size. */ /* = 140 */ -#elif defined(ARM) +#else OPSZ_NA = 0, /**< Sentinel value: not a valid size. */ #endif OPSZ_FIRST = OPSZ_NA, @@ -402,7 +402,9 @@ enum { # define OPSZ_STATS OPSZ_4 #endif -#define IT_BLOCK_MAX_INSTRS 4 +#ifdef ARM +# define IT_BLOCK_MAX_INSTRS 4 +#endif /* in encode.c, not exported to non-arch/ files */ const instr_info_t * get_encoding_info(instr_t *instr); @@ -432,7 +434,7 @@ bool is_isa_mode_legal(dr_isa_mode_t mode); * Later, if needed, we can introduce a new field in dcontext_t (xref i#862). */ # define X64_CACHE_MODE_DC(dc) (X64_MODE_DC(dc) IF_X64(|| DYNAMO_OPTION(x86_to_x64))) -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) # define X64_MODE_DC(dc) IF_X64_ELSE(true, false) # define X64_CACHE_MODE_DC(dc) IF_X64_ELSE(true, false) #endif diff --git a/core/arch/emit_utils_shared.c b/core/arch/emit_utils_shared.c index 364af3e50d9..0b7f42ad447 100644 --- a/core/arch/emit_utils_shared.c +++ b/core/arch/emit_utils_shared.c @@ -792,8 +792,8 @@ coarse_indirect_stub_jmp_target(cache_pc stub) ASSERT(*prefix_tgt == JMP_OPCODE); tgt = (cache_pc) PC_RELATIVE_TARGET(prefix_tgt+1); return tgt; -#elif defined(ARM) - /* FIXMED i#1551: NYI on ARM */ +#elif defined(ARM) || defined(AARCH64) + /* FIXME i#1551, i#1569: NYI on ARM/AArch64 */ ASSERT_NOT_IMPLEMENTED(false); return NULL; #endif /* X86/ARM */ @@ -1871,9 +1871,13 @@ append_jmp_to_fcache_target(dcontext_t *dcontext, instrlist_t *ilist, } else { if (shared) { /* next_tag placed into tls slot earlier in this routine */ +#ifdef AARCH64 + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ +#else APP(ilist, XINST_CREATE_jump_mem(dcontext, OPND_TLS_FIELD(FCACHE_ENTER_TARGET_SLOT))); +#endif } else { #ifdef WINDOWS @@ -2421,7 +2425,11 @@ append_fcache_return_common(dcontext_t *dcontext, generated_code_t *code, * so if our hook suspends all other threads to protect vs cross-thread * attacks, the dstack is not perfectly protected. */ +#ifdef AARCH64 + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ +#else APP(ilist, RESTORE_FROM_DC(dcontext, REG_XSP, DSTACK_OFFSET)); +#endif append_save_clear_xflags(dcontext, ilist, absolute); instr_targets = append_call_enter_dr_hook(dcontext, ilist, ibl_end, absolute) || @@ -2994,9 +3002,13 @@ append_ibl_found(dcontext_t *dcontext, instrlist_t *ilist, /* FIXME: do we want this? seems to be a problem, I'm disabling: * ASSERT(!collision || start_pc_offset == FRAGMENT_START_PC_OFFS); // c \imply FRAGMENT */ +#ifdef AARCH64 + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ +#else APP(ilist, XINST_CREATE_jump_mem(dcontext, OPND_CREATE_MEMPTR(SCRATCH_REG2, start_pc_offset))); +#endif } else { /* There is no prefix so we must restore all and jmp through memory: * mov start_pc_offset(%xcx), %xcx @@ -3017,11 +3029,15 @@ append_ibl_found(dcontext_t *dcontext, instrlist_t *ilist, MANGLE_XCX_SPILL_SLOT)); else APP(ilist, RESTORE_FROM_DC(dcontext, SCRATCH_REG2, SCRATCH_REG2_OFFS)); +#ifdef AARCH64 + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ +#else APP(ilist, XINST_CREATE_jump_mem(dcontext, OPND_DC_FIELD(absolute, dcontext, OPSZ_PTR, SCRATCH_REG2_OFFS))); +#endif #elif defined(ARM) /* FIXMED i#1551: NYI on ARM */ ASSERT_NOT_REACHED(); @@ -3035,9 +3051,13 @@ append_ibl_found(dcontext_t *dcontext, instrlist_t *ilist, #endif APP(ilist, RESTORE_FROM_TLS(dcontext, SCRATCH_REG2, MANGLE_XCX_SPILL_SLOT)); +#ifdef AARCH64 + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ +#else APP(ilist, XINST_CREATE_jump_mem(dcontext, OPND_TLS_FIELD(INDIRECT_STUB_SPILL_SLOT))); +#endif } } @@ -3334,7 +3354,7 @@ instr_t * create_syscall_instr(dcontext_t *dcontext) { int method = get_syscall_method(); -#ifdef ARM +#if defined(ARM) || defined(AARCH64) if (method == SYSCALL_METHOD_SVC || method == SYSCALL_METHOD_UNINITIALIZED) { return INSTR_CREATE_svc(dcontext, opnd_create_immed_int((char)0x0, OPSZ_1)); } @@ -5124,6 +5144,9 @@ emit_special_ibl_xfer(dcontext_t *dcontext, byte *pc, generated_code_t *code, APP(&ilist, nop_inst); } APP(&ilist, XINST_CREATE_jump(dcontext, opnd_create_pc(ibl_tgt))); +#elif defined(AARCH64) + (void)ibl_tgt; + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ #elif defined(ARM) APP(&ilist, INSTR_CREATE_ldr(dcontext, opnd_create_reg(DR_REG_PC), OPND_TLS_FIELD(get_ibl_entry_tls_offs @@ -5205,8 +5228,10 @@ byte * emit_clean_call_save(dcontext_t *dcontext, byte *pc, generated_code_t *code) { instrlist_t ilist; -#ifdef ARM - /* FIXME i#1551: NYI on ARM (no assert here, it's in get_clean_call_save()) */ +#if defined(ARM) || defined(AARCH64) + /* FIXME i#1551, i#1569: + * NYI on ARM/AArch64 (no assert here, it's in get_clean_call_save()) + */ return pc; #endif diff --git a/core/arch/instr.h b/core/arch/instr.h index 6d2cb899506..5284e0fae54 100644 --- a/core/arch/instr.h +++ b/core/arch/instr.h @@ -66,6 +66,8 @@ struct instr_info_t; #ifdef API_EXPORT_ONLY #ifdef X86 # include "dr_ir_opcodes_x86.h" +#elif defined(AARCH64) +# include "dr_ir_opcodes_aarch64.h" #elif defined(ARM) # include "dr_ir_opcodes_arm.h" #endif @@ -1692,6 +1694,7 @@ DR_API bool instr_writes_memory(instr_t *instr); +#ifdef X86 DR_API /** * Returns true iff \p instr writes to an xmm register and zeroes the top half @@ -1701,6 +1704,7 @@ DR_API */ bool instr_zeroes_ymmh(instr_t *instr); +#endif /* DR_API EXPORT BEGIN */ #if defined(X64) || defined(ARM) @@ -2822,7 +2826,7 @@ enum { EFLAGS_ARITH = EFLAGS_CF|EFLAGS_PF|EFLAGS_AF|EFLAGS_ZF|EFLAGS_SF|EFLAGS_OF, }; -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) # define EFLAGS_READ_N 0x00000001 /**< Reads N (negative flag). */ # define EFLAGS_READ_Z 0x00000002 /**< Reads Z (zero flag). */ # define EFLAGS_READ_C 0x00000004 /**< Reads C (carry flag). */ diff --git a/core/arch/instr_create_shared.h b/core/arch/instr_create_shared.h index ccb09948ca0..afbd8f0ae89 100644 --- a/core/arch/instr_create_shared.h +++ b/core/arch/instr_create_shared.h @@ -51,6 +51,8 @@ #ifdef API_EXPORT_ONLY #ifdef X86 # include "dr_ir_macros_x86.h" +#elif defined(AARCH64) +# include "dr_ir_macros_aarch64.h" #elif defined(ARM) # include "dr_ir_macros_arm.h" #endif diff --git a/core/arch/instr_inline.h b/core/arch/instr_inline.h index a3327103fa4..e522603a2cd 100644 --- a/core/arch/instr_inline.h +++ b/core/arch/instr_inline.h @@ -154,10 +154,14 @@ opnd_is_far_rel_addr(opnd_t opnd) return IF_X86_ELSE(opnd.kind == REL_ADDR_kind && opnd.aux.segment != DR_REG_NULL, false); } -# elif defined(ARM) -# define OPND_IS_REL_ADDR(op) \ +# elif defined(ARM) || defined(AARCH64) +# ifdef ARM +# define OPND_IS_REL_ADDR(op) \ ((op).kind == REL_ADDR_kind || \ (opnd_is_base_disp(op) && opnd_get_base(op) == DR_REG_PC)) +# else +# define OPND_IS_REL_ADDR(op) ((op).kind == REL_ADDR_kind) +# endif # define opnd_is_rel_addr OPND_IS_REL_ADDR INSTR_INLINE @@ -254,7 +258,7 @@ opnd_create_pc(app_pc pc) opnd_is_immed_int(opnd), \ "opnd_get_flags called on non-reg non-base-disp non-immed-int opnd") \ 0) -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) # define OPND_GET_FLAGS(opnd) \ (CLIENT_ASSERT_(opnd_is_reg(opnd) || opnd_is_base_disp(opnd) || \ opnd_is_immed_int(opnd), \ @@ -289,7 +293,7 @@ opnd_create_pc(app_pc pc) opnd_is_rel_addr(opnd)), \ "opnd_get_segment called on invalid opnd type") \ (opnd).aux.segment) -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) # define OPND_GET_SEGMENT(opnd) DR_REG_NULL #endif #define opnd_get_segment OPND_GET_SEGMENT diff --git a/core/arch/instr_shared.c b/core/arch/instr_shared.c index 926be066170..f04e8f19089 100644 --- a/core/arch/instr_shared.c +++ b/core/arch/instr_shared.c @@ -1925,6 +1925,7 @@ instr_writes_memory(instr_t *instr) return false; } +#ifdef X86 bool instr_zeroes_ymmh(instr_t *instr) { @@ -1943,6 +1944,7 @@ instr_zeroes_ymmh(instr_t *instr) } return false; } +#endif /* X86 */ #if defined(X64) || defined(ARM) /* PR 251479: support general re-relativization. If INSTR_RIP_REL_VALID is set and @@ -3074,8 +3076,13 @@ instr_create_save_immed_to_dc_via_reg(dcontext_t *dcontext, reg_id_t basereg, instr_t * instr_create_jump_via_dcontext(dcontext_t *dcontext, int offs) { +#ifdef AARCH64 + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ + return 0; +#else opnd_t memopnd = opnd_create_dcontext_field(dcontext, offs); return XINST_CREATE_jump_mem(dcontext, memopnd); +#endif } /* there is no corresponding save routine since we no longer support @@ -3122,8 +3129,8 @@ instr_raw_is_tls_spill(byte *pc, reg_id_t reg, ushort offs) /* 0x1e for ebx, 0x0e for ecx, 0x06 for eax */ *(pc+2) == MODRM_BYTE(0/*mod*/, reg_get_bits(reg), 6/*rm*/) && *((uint*)(pc+4)) == os_tls_offset(offs)); -#elif defined(ARM) - /* FIXME i#1551: NYI on ARM */ +#elif defined(ARM) || defined(AARCH64) + /* FIXME i#1551, i#1569: NYI on ARM/AArch64 */ ASSERT_NOT_IMPLEMENTED(false); return false; #endif /* X86/ARM */ @@ -3161,7 +3168,7 @@ instr_check_tls_spill_restore(instr_t *instr, bool *spill, reg_id_t *reg, int *o opnd_is_far_base_disp(memop) && opnd_get_segment(memop) == SEG_TLS && opnd_is_abs_base_disp(memop) -#elif defined (ARM) +#elif defined (ARM) || defined(AARCH64) opnd_is_base_disp(memop) && opnd_get_base(memop) == dr_reg_stolen && opnd_get_index(memop) == DR_REG_NULL @@ -3216,8 +3223,8 @@ instr_is_tls_xcx_spill(instr_t *instr) REG_ECX, MANGLE_XCX_SPILL_SLOT); } else return instr_is_tls_spill(instr, REG_ECX, MANGLE_XCX_SPILL_SLOT); -#elif defined(ARM) - /* FIXME i#1551: NYI on ARM */ +#elif defined(ARM) || defined(AARCH64) + /* FIXME i#1551, i#1569: NYI on ARM/AArch64 */ ASSERT_NOT_IMPLEMENTED(false); return false; #endif @@ -3416,6 +3423,9 @@ move_mm_reg_opcode(bool aligned16, bool aligned32) # elif defined(ARM) /* FIXME i#1551: which one we should return, OP_vmov, OP_vldr, or OP_vstr? */ return OP_vmov; +# elif defined(AARCH64) + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ + return 0; # endif /* X86/ARM */ } diff --git a/core/arch/interp.c b/core/arch/interp.c index cb578c66787..443bc6e90b2 100644 --- a/core/arch/interp.c +++ b/core/arch/interp.c @@ -2511,8 +2511,8 @@ bb_process_IAT_convertible_indjmp(dcontext_t *dcontext, build_bb_t *bb, bb->exit_target = target; *elide_continue = false; /* matching, but should stop bb */ return true; /* matching */ -#elif defined(ARM) - /* FIXME i#1551: NYI on ARM */ +#elif defined(ARM) || defined(AARCH64) + /* FIXME i#1551, i#1569: NYI on ARM/AArch64 */ ASSERT_NOT_IMPLEMENTED(false); return false; #endif /* X86/ARM */ @@ -2622,8 +2622,8 @@ bb_process_IAT_convertible_indcall(dcontext_t *dcontext, build_bb_t *bb, */ *elide_continue = false; /* matching, but should stop bb */ return true; /* converted indirect to direct */ -#elif defined(ARM) - /* FIXME i#1551: NYI on ARM */ +#elif defined(ARM) || defined(AARCH64) + /* FIXME i#1551, i#1569: NYI on ARM/AArch64 */ ASSERT_NOT_IMPLEMENTED(false); return false; #endif /* X86/ARM */ @@ -3266,7 +3266,7 @@ build_bb_ilist(dcontext_t *dcontext, build_bb_t *bb) } LOG(THREAD, LOG_INTERP, 3, "\ninterp%s: ", - IF_X64_ELSE(X64_MODE_DC(dcontext) ? "" : " (x86 mode)", "")); + IF_X86_64_ELSE(X64_MODE_DC(dcontext) ? "" : " (x86 mode)", "")); BBPRINT(bb, 3, "start_pc = "PFX"\n", bb->start_pc); DOSTATS({ @@ -4701,11 +4701,15 @@ build_native_exec_bb(dcontext_t *dcontext, build_bb_t *bb) SCRATCH_REG0, SCRATCH_REG0_OFFS)); insert_shared_restore_dcontext_reg(dcontext, bb->ilist, NULL); +#ifdef AARCH64 + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ +#else /* this is the jump to native code */ instrlist_append(bb->ilist, opnd_is_pc(jmp_tgt) ? XINST_CREATE_jump(dcontext, jmp_tgt) : XINST_CREATE_jump_mem(dcontext, jmp_tgt)); +#endif /* mark all as do-not-mangle, so selfmod, etc. will leave alone (in absence * of selfmod only really needed for the jmp to native code) @@ -5698,8 +5702,8 @@ instr_is_trace_cmp(dcontext_t *dcontext, instr_t *inst) instr_get_opcode(inst) == OP_jmp # endif ; -#elif defined(ARM) - /* FIXME i#1551: NYI on ARM */ +#elif defined(ARM) || defined(AARCH64) + /* FIXME i#1551, i#1569: NYI on ARM/AArch64 */ ASSERT_NOT_IMPLEMENTED(DYNAMO_OPTION(disable_traces)); return false; #endif @@ -8069,7 +8073,7 @@ emulate(dcontext_t *dcontext, app_pc pc, priv_mcontext_t *mc) } #ifdef X64 else if (sz == 8) { - if (opc == OP_inc) + if (opc == IF_X86_ELSE(OP_inc, OP_add)) (*target)++; else (*target)--; diff --git a/core/arch/opnd.h b/core/arch/opnd.h index af422fb9c78..3e71d0ebc91 100644 --- a/core/arch/opnd.h +++ b/core/arch/opnd.h @@ -180,7 +180,7 @@ enum { DR_REG_YMM12,DR_REG_YMM13,DR_REG_YMM14,DR_REG_YMM15, /****************************************************************************/ -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) DR_REG_INVALID, /**< Sentinel value indicating an invalid register. */ /* 64-bit general purpose */ DR_REG_X0, DR_REG_X1, DR_REG_X2, DR_REG_X3, @@ -257,11 +257,13 @@ enum { DR_REG_B24, DR_REG_B25, DR_REG_B26, DR_REG_B27, DR_REG_B28, DR_REG_B29, DR_REG_B30, DR_REG_B31, +# ifndef X64 /* Coprocessor registers */ DR_REG_CR0, DR_REG_CR1, DR_REG_CR2, DR_REG_CR3, DR_REG_CR4, DR_REG_CR5, DR_REG_CR6, DR_REG_CR7, DR_REG_CR8, DR_REG_CR9, DR_REG_CR10, DR_REG_CR11, DR_REG_CR12, DR_REG_CR13, DR_REG_CR14, DR_REG_CR15, +# endif /* We decided against DR_REG_RN_TH (top half), DR_REG_RN_BH (bottom half * for 32-bit as we have the W versions for 64-bit), and DR_REG_RN_BB @@ -282,7 +284,11 @@ enum { * OP_mrs and OP_msr to distinguish them and make things clearer. */ # endif +# ifdef X64 + DR_REG_NZCV, DR_REG_FPCR, DR_REG_FPSR, +# else DR_REG_CPSR, DR_REG_SPSR, DR_REG_FPSCR, +# endif /* AArch32 Thread Registers */ DR_REG_TPIDRURW, /**< User Read/Write Thread ID Register */ @@ -336,8 +342,10 @@ enum { DR_REG_SL = DR_REG_R10, /**< Alias for the r10 register. */ DR_REG_FP = DR_REG_R11, /**< Alias for the r11 register. */ DR_REG_IP = DR_REG_R12, /**< Alias for the r12 register. */ +# ifndef X64 /** Alias for cpsr register (thus this is the full cpsr, not just the apsr bits). */ DR_REG_APSR = DR_REG_CPSR, +# endif /* AArch64 Thread Registers */ /** Thread Pointer/ID Register, EL0. */ @@ -459,7 +467,7 @@ extern const reg_id_t dr_reg_fixer[]; #ifdef X86 # define REG_START_SPILL DR_REG_XAX # define REG_STOP_SPILL DR_REG_XDI -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) /* We only normally use r0-r3 but we support more in translation code */ # define REG_START_SPILL DR_REG_R0 # define REG_STOP_SPILL DR_REG_R10 /* r10 might be used in syscall mangling */ @@ -2241,7 +2249,7 @@ enum { REGPARM_END_ALIGN = sizeof(XSP_SZ), # endif # endif /* 64/32 */ -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) REGPARM_0 = DR_REG_R0, REGPARM_1 = DR_REG_R1, REGPARM_2 = DR_REG_R2, @@ -2265,7 +2273,7 @@ extern const reg_id_t regparms[]; /* arch-specific */ uint opnd_immed_float_arch(uint opcode); -#ifdef ARM +#if defined(ARM) || defined(AARCH64) # define DR_REG_STOLEN_MIN DR_REG_R8 /* no syscall regs */ # define DR_REG_STOLEN_MAX IF_X64_ELSE(DR_REG_X29, DR_REG_R12) /* DR's stolen register for TLS access */ diff --git a/core/arch/opnd_shared.c b/core/arch/opnd_shared.c index 2c11e7b3173..92ccd8aeea5 100644 --- a/core/arch/opnd_shared.c +++ b/core/arch/opnd_shared.c @@ -41,7 +41,9 @@ #include "opnd.h" #include "arch.h" /* FIXME i#1551: refactor this file and avoid this x86-specific include in base arch/ */ +#ifndef AARCH64 #include "x86/decode_private.h" +#endif #include /* for memcpy */ @@ -832,8 +834,10 @@ bool opnd_is_memory_reference(opnd_t opnd) { return (opnd_is_base_disp(opnd) - IF_X64(|| opnd_is_abs_addr(opnd) || opnd_is_rel_addr(opnd)) || - IF_ARM(opnd_is_rel_addr(opnd) ||) + IF_X86_64(|| opnd_is_abs_addr(opnd)) || +#if defined(X64) || defined(ARM) + opnd_is_rel_addr(opnd) || +#endif opnd_is_mem_instr(opnd)); } @@ -962,7 +966,7 @@ const reg_id_t regparms[] = { REGPARM_4, REGPARM_5, # endif # endif -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) REGPARM_0, REGPARM_1, REGPARM_2, REGPARM_3, # ifdef X64 REGPARM_4, REGPARM_5, REGPARM_6, REGPARM_7, @@ -1047,7 +1051,7 @@ opnd_replace_reg(opnd_t *opnd, reg_id_t old_reg, reg_id_t new_reg) reg_id_t b = (old_reg == ob) ? new_reg : ob; reg_id_t i = (old_reg == oi) ? new_reg : oi; int d = opnd_get_disp(*opnd); -#ifdef ARM +#if defined(ARM) || defined(AARCH64) uint amount; dr_shift_type_t shift = opnd_get_index_shift(*opnd, &amount); dr_opnd_flags_t flags = opnd_get_flags(*opnd); @@ -1783,6 +1787,9 @@ opnd_compute_address_priv(opnd_t opnd, priv_mcontext_t *mc) #ifdef X86 ptr_int_t scale = opnd_get_scale(opnd); scaled_index = scale * reg_get_value_priv(index, mc); +#elif defined(AARCH64) + (void)index; + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ #elif defined(ARM) uint amount; dr_shift_type_t type = opnd_get_index_shift(opnd, &amount); @@ -1844,7 +1851,7 @@ reg_32_to_16(reg_id_t reg) CLIENT_ASSERT(reg >= REG_START_32 && reg <= REG_STOP_32, "reg_32_to_16: passed non-32-bit reg"); return (reg - REG_START_32) + REG_START_16; -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) CLIENT_ASSERT(false, "reg_32_to_16 not supported on ARM"); return REG_NULL; #endif @@ -1866,7 +1873,7 @@ reg_32_to_8(reg_id_t reg) # endif } return r8; -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) CLIENT_ASSERT(false, "reg_32_to_8 not supported on ARM"); return REG_NULL; #endif @@ -2047,7 +2054,7 @@ reg_get_size(reg_id_t reg) /* i#176 add reg size handling for floating point registers */ if (reg >= REG_START_FLOAT && reg <= REG_STOP_FLOAT) return OPSZ_10; -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) if (reg >= DR_REG_Q0 && reg <= DR_REG_Q31) return OPSZ_16; if (reg >= DR_REG_D0 && reg <= DR_REG_D31) @@ -2058,14 +2065,16 @@ reg_get_size(reg_id_t reg) return OPSZ_2; if (reg >= DR_REG_B0 && reg <= DR_REG_B31) return OPSZ_1; +# ifdef ARM if (reg >= DR_REG_CR0 && reg <= DR_REG_CR15) return OPSZ_PTR; if (reg >= DR_REG_CPSR && reg <= DR_REG_FPSCR) return OPSZ_4; +# endif if (reg == DR_REG_TPIDRURW || reg == DR_REG_TPIDRURO) return OPSZ_PTR; -# ifdef X64 -# error FIXME i#1569: NYI on AArch64 +# ifdef AARCH64 + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ # endif #endif CLIENT_ASSERT(false, "reg_get_size: invalid register"); diff --git a/core/arch/proc.h b/core/arch/proc.h index de637eef2d9..7132521cea4 100644 --- a/core/arch/proc.h +++ b/core/arch/proc.h @@ -72,10 +72,12 @@ # define DR_FPSTATE_BUF_SIZE 512 #elif defined(ARM) # define DR_FPSTATE_BUF_SIZE (32*64) +#elif defined(AARCH64) +# define DR_FPSTATE_BUF_SIZE (32*128) #endif /** The alignment requirements of floating point state buffer. */ -#ifdef X86 +#if defined(X86) || defined(AARCH64) # define DR_FPSTATE_ALIGN 16 #elif defined(ARM) # define DR_FPSTATE_ALIGN 4 diff --git a/core/fragment.h b/core/fragment.h index c88e9a60062..ce2b88e0359 100644 --- a/core/fragment.h +++ b/core/fragment.h @@ -192,16 +192,14 @@ frag_flags_from_isa_mode(dr_isa_mode_t mode) ASSERT(mode == DR_ISA_IA32); return 0; # endif -#elif defined(ARM) -# ifdef X64 +#elif defined(AARCH64) ASSERT(mode == DR_ISA_ARM_A64); return 0; -# else +#elif defined(ARM) if (mode == DR_ISA_ARM_THUMB) return FRAG_THUMB; ASSERT(mode == DR_ISA_ARM_A32); return 0; -# endif #endif } diff --git a/core/globals.h b/core/globals.h index c8a8d0b65fe..289b267bdbe 100644 --- a/core/globals.h +++ b/core/globals.h @@ -200,8 +200,8 @@ typedef byte * cache_pc; /* fragment cache pc */ #endif /* make sure defines are consistent */ -#if !defined(X86) && !defined(ARM) -# error Must define X86 or ARM, no other platforms are supported +#if !defined(X86) && !defined(ARM) && !defined(AARCH64) +# error Must define X86, ARM or AARCH64: no other platforms are supported #endif #if defined(PAPI) && defined(WINDOWS) diff --git a/core/lib/globals_shared.h b/core/lib/globals_shared.h index 9cc3ac8bb6d..4502083d7fc 100644 --- a/core/lib/globals_shared.h +++ b/core/lib/globals_shared.h @@ -74,9 +74,14 @@ # if (defined(X86_64) && defined(X86_32)) || defined(ARM_32) || defined(ARM_64) # error Target architecture over-specified: must define only one # endif -#elif defined(ARM_32) || defined(ARM_64) +#elif defined(ARM_32) # define ARM -# if defined(X86_32) || defined(X86_64) || (defined(ARM_64) && defined(ARM_32)) +# if defined(X86_32) || defined(X86_64) || defined(ARM_64) +# error Target architecture over-specified: must define only one +# endif +#elif defined(ARM_64) +# define AARCH64 +# if defined(X86_32) || defined(X86_64) || defined(ARM_32) # error Target architecture over-specified: must define only one # endif #else @@ -630,6 +635,7 @@ typedef struct _instr_t instr_t; # define IF_X86_(x) x, # define _IF_X86(x) , x # define IF_NOT_X86(x) +# define IF_NOT_X86_(x) # define _IF_NOT_X86(x) #else # define IF_X86(x) @@ -637,6 +643,7 @@ typedef struct _instr_t instr_t; # define IF_X86_(x) # define _IF_X86(x) # define IF_NOT_X86(x) x +# define IF_NOT_X86_(x) x, # define _IF_NOT_X86(x) , x #endif @@ -1740,7 +1747,7 @@ typedef union _dr_ymm_t { reg_t reg[IF_X64_ELSE(4,8)]; /**< Representation as 4 or 8 registers. */ } dr_ymm_t; -#ifdef ARM +#if defined(ARM) || defined(AARCH64) /** * 128-bit ARM SIMD Vn register. * We're not using any uint64 fields here to avoid alignment padding in diff --git a/core/lib/instrument.c b/core/lib/instrument.c index 4868ad7ff11..b062585fb75 100644 --- a/core/lib/instrument.c +++ b/core/lib/instrument.c @@ -5320,10 +5320,7 @@ static const reg_id_t SPILL_SLOT_MC_REG[NUM_SPILL_SLOTS - NUM_TLS_SPILL_SLOTS] = REG_R15, REG_R14, REG_R13, REG_R12, REG_R11, REG_R10, REG_R9, REG_R8, # endif REG_XDI, REG_XSI, REG_XBP, REG_XDX, REG_XCX, REG_XBX -#elif defined(ARM) -# ifdef X64 -# error NYI -# endif +#elif defined(ARM) || defined(AARCH64) DR_REG_R6, DR_REG_R5, DR_REG_R4, DR_REG_R3, DR_REG_R2, DR_REG_R1 #endif /* X86/ARM */ }; @@ -5651,6 +5648,9 @@ dr_save_arith_flags_to_reg(void *drcontext, instrlist_t *ilist, INSTR_CREATE_mrs(dcontext, opnd_create_reg(reg), opnd_create_reg(DR_REG_CPSR))); +#elif defined(AARCH64) + (void)dcontext; + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ #endif /* X86/ARM */ } @@ -5682,6 +5682,10 @@ dr_restore_arith_flags_from_reg(void *drcontext, instrlist_t *ilist, INSTR_CREATE_msr(dcontext, opnd_create_reg(DR_REG_CPSR), OPND_CREATE_INT_MSR_NZCVQG(), opnd_create_reg(reg))); +#elif defined(AARCH64) + /* flag restoring code: mrs reg, nzcv */ + (void)dcontext; + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ #endif /* X86/ARM */ } @@ -7177,9 +7181,9 @@ DR_API int dr_remove_it_instrs(void *drcontext, instrlist_t *ilist) { -#ifdef X86 +#if !defined(ARM) return 0; -#elif defined(ARM) +#else int res = 0; instr_t *inst, *next; for (inst = instrlist_first(ilist); inst != NULL; inst = next) { @@ -7198,9 +7202,9 @@ DR_API int dr_insert_it_instrs(void *drcontext, instrlist_t *ilist) { -#ifdef X86 +#if !defined(ARM) return 0; -#elif defined(ARM) +#else instr_t *first = instrlist_first(ilist); if (first == NULL || instr_get_isa_mode(first) != DR_ISA_ARM_THUMB) return 0; diff --git a/core/lib/mcxtx.h b/core/lib/mcxtx.h index ad276f9dbfc..df2ef39b612 100644 --- a/core/lib/mcxtx.h +++ b/core/lib/mcxtx.h @@ -39,7 +39,7 @@ */ /* START INCLUDE */ -#ifdef ARM +#if defined(ARM) || defined(AARCH64) # ifdef AVOID_API_EXPORT /* FIXME: have special comment syntax instead of bogus ifdef to * get genapi to strip out internal-only comments? */ @@ -94,7 +94,7 @@ * The program counter. * \note This field is not always set or read by all API routines. */ - reg_t pc; + byte *pc; # else /* 32-bit */ union { reg_t r13; /**< The r13 register. */ diff --git a/core/optionsx.h b/core/optionsx.h index 9da2807fd88..507b3be0d09 100644 --- a/core/optionsx.h +++ b/core/optionsx.h @@ -283,7 +283,7 @@ #ifdef KSTATS /* turn on kstats by default for debug builds */ /* For ARM we have no cheap tsc so we disable by default (i#1581) */ - OPTION_DEFAULT(bool, kstats, IF_DEBUG_ELSE_0(IF_ARM_ELSE(false, true)), + OPTION_DEFAULT(bool, kstats, IF_DEBUG_ELSE_0(IF_X86_ELSE(true, false)), "enable path timing statistics") #endif @@ -518,8 +518,8 @@ * All the optimizations assume that clean callee will not be changed * later. */ - /* FIXME i#1551: NYI on ARM */ - OPTION_DEFAULT_INTERNAL(uint, opt_cleancall, IF_ARM_ELSE(0, 2), + /* FIXME i#1551, i#1569: NYI on ARM/AArch64 */ + OPTION_DEFAULT_INTERNAL(uint, opt_cleancall, IF_X86_ELSE(2, 0), "optimization level on optimizing clean call sequences") /* Assuming the client's clean call does not rely on the cleared eflags, * i.e., initialize the eflags before using it, we can skip the eflags @@ -567,7 +567,7 @@ "Optimize ibl code with extra 64-bit registers in x86_to_x64 mode.") #endif -#ifdef ARM +#if defined(ARM) || defined(AARCH64) /* we only allow register between r8 and r12(A32)/r29(A64) to be used */ OPTION_DEFAULT_INTERNAL(uint, steal_reg, IF_X64_ELSE(28/*r28*/, 10/*r10*/), "the register stolen/used by DynamoRIO") @@ -772,14 +772,14 @@ * turn them on. * We mark as pcache-affecting though we have other explicit checks */ - /* FIXME i#1551: enable traces on ARM once we have them working */ - OPTION_COMMAND(bool, disable_traces, IF_ARM_ELSE(true, false), "disable_traces", { + /* FIXME i#1551, i#1569: enable traces on ARM/AArch64 once we have them working */ + OPTION_COMMAND(bool, disable_traces, IF_X86_ELSE(false, true), "disable_traces", { if (options->disable_traces) { /* else leave alone */ DISABLE_TRACES(options); } }, "disable trace creation (block fragments only)", STATIC, OP_PCACHE_GLOBAL) - /* FIXME i#1551: enable traces on ARM once we have them working */ - OPTION_COMMAND(bool, enable_traces, IF_ARM_ELSE(false, true), "enable_traces", { + /* FIXME i#1551, i#1569: enable traces on ARM/AArch64 once we have them working */ + OPTION_COMMAND(bool, enable_traces, IF_X86_ELSE(true, false), "enable_traces", { if (options->enable_traces) { /* else leave alone */ REENABLE_TRACES(options); } @@ -815,8 +815,8 @@ * off -shared_traces to avoid tripping over un-initialized ibl tables * PR 361894: if no TLS available, we fall back to thread-private */ - /* FIXME i#1551: enable traces on ARM once we have them working */ - OPTION_COMMAND(bool, shared_traces, IF_HAVE_TLS_ELSE(IF_ARM_ELSE(false, true), false), + /* FIXME i#1551, i#1569: enable traces on ARM/AArch64 once we have them working */ + OPTION_COMMAND(bool, shared_traces, IF_HAVE_TLS_ELSE(IF_X86_ELSE(true, false), false), "shared_traces", { /* for -no_shared_traces, set options back to defaults for private traces: */ IF_NOT_X64_OR_ARM(options->private_ib_in_tls = options->shared_traces;) @@ -898,9 +898,9 @@ /* XXX i#1611: for ARM, our far links go through the stub and hence can't * be shared with an unlinked fall-through. If we switch to allowing - * "ldr pc, [pc + X]" as an exit cti we can turn this back on. + * "ldr pc, [pc + X]" as an exit cti we can turn this back on for 32-bit ARM. */ - OPTION_DEFAULT_INTERNAL(bool, cbr_single_stub, IF_ARM_ELSE(false, true), + OPTION_DEFAULT_INTERNAL(bool, cbr_single_stub, IF_X86_ELSE(true, false), "both sides of a cbr share a single stub") /* PR 210990: Improvement is in the noise for spec2k on P4, but is noticeable on @@ -911,7 +911,7 @@ * avoid a stub unless we use "ldr pc, [r10+offs]" as an exit cti, which * complicates the code that handles exit ctis and doesn't work for A64. */ - OPTION_COMMAND(bool, indirect_stubs, IF_ARM_ELSE(true, false), "indirect_stubs", { + OPTION_COMMAND(bool, indirect_stubs, IF_X86_ELSE(false, true), "indirect_stubs", { /* we put inlining back in place if we have stubs, for private, * though should re-measure whether inlining is worthwhile */ if (options->thread_private && options->indirect_stubs) { @@ -949,8 +949,8 @@ OPTION_DEFAULT(bool, ibl_table_in_tls, IF_HAVE_TLS_ELSE(true, false), "use TLS to hold IBL table addresses & masks") - /* FIXME i#1551: enable traces on ARM once we have them working */ - OPTION_DEFAULT(bool, bb_ibl_targets, IF_ARM_ELSE(true, false), "enable BB to BB IBL") + /* FIXME i#1551, i#1569: enable traces on ARM/AArch64 once we have them working */ + OPTION_DEFAULT(bool, bb_ibl_targets, IF_X86_ELSE(false, true), "enable BB to BB IBL") /* IBL code cannot target both single restore prefix and full prefix frags * simultaneously since the restore of %eax in the former case means that the @@ -1000,9 +1000,9 @@ /* control sharing of indirect branch lookup routines */ /* Default TRUE as it's needed for shared_traces (which is on by default) */ /* PR 361894: if no TLS available, we fall back to thread-private */ - /* FIXME i#1551: enable traces on ARM once we have them working */ + /* FIXME i#1551, i#1569: enable traces on ARM/AArch64 once we have them working */ OPTION_DEFAULT(bool, shared_trace_ibl_routine, - IF_HAVE_TLS_ELSE(IF_ARM_ELSE(false, true), false), + IF_HAVE_TLS_ELSE(IF_X86_ELSE(true, false), false), "share ibl routine for traces") OPTION_DEFAULT(bool, speculate_last_exit, false, "enable speculative linking of trace last IB exit") @@ -1325,7 +1325,7 @@ /* FIXME i#1674: enable on ARM once bugs are fixed, along with all the * reset_* trigger options as well. */ - OPTION_COMMAND(bool, enable_reset, IF_ARM_ELSE(false, true), "enable_reset", { + OPTION_COMMAND(bool, enable_reset, IF_X86_ELSE(true, false), "enable_reset", { if (!options->enable_reset) { DISABLE_RESET(options); } @@ -1344,28 +1344,28 @@ "if we hit the reset_at_vmm_*_limit switch to requesting from the os (so we'll " "only actually reset once the os is out and we're at the limit)") OPTION_DEFAULT(bool, reset_at_switch_to_os_at_vmm_limit, - IF_ARM_ELSE(false, true), /* i#1674: re-enable on ARM once xl8 bugs are fixed */ + IF_X86_ELSE(true, false), /* i#1674: re-enable on ARM once xl8 bugs are fixed */ "schedule a reset the first (and only the first) time we switch to the os " "allocations from -switch_to_os_at_vmm_reset_limit above") OPTION_DEFAULT(uint, reset_at_vmm_percent_free_limit, - IF_ARM_ELSE(0, 10), /* i#1674: re-enable on ARM once xl8 bugs are fixed */ + IF_X86_ELSE(10, 0), /* i#1674: re-enable on ARM once xl8 bugs are fixed */ "reset all when vmm heap % free is < reset_at_vmm_percent_free (0 disables)") OPTION_DEFAULT(uint_size, reset_at_vmm_free_limit, 0, "reset all when vmm heap has less then reset_at_vmm_free free memory remaining") OPTION_DEFAULT(uint, report_reset_vmm_threshold, 3, "syslog one thrash warning message after this many resets at low vmm heap free") OPTION_DEFAULT(bool, reset_at_vmm_full, - IF_ARM_ELSE(false, true), /* i#1674: re-enable on ARM once xl8 bugs are fixed */ + IF_X86_ELSE(true, false), /* i#1674: re-enable on ARM once xl8 bugs are fixed */ "reset all caches the first time vmm heap runs out of space") OPTION_DEFAULT(uint, reset_at_commit_percent_free_limit, 0, - "reset all less then this % of the commit limit remains free (0 disables)") + "reset all less than this % of the commit limit remains free (0 disables)") OPTION_DEFAULT(uint_size, reset_at_commit_free_limit, - IF_ARM_ELSE(0, (32 * 1024 * 1024)), /* i#1674: re-enable once ARM bugs fixed */ + IF_X86_ELSE((32 * 1024 * 1024), 0), /* i#1674: re-enable once ARM bugs fixed */ "reset all when less then this much free committable memory remains") OPTION_DEFAULT(uint, report_reset_commit_threshold, 3, "syslog one thrash warning message after this many resets at low commit") OPTION_DEFAULT(uint, reset_every_nth_pending, - IF_ARM_ELSE(0, 35), /* i#1674: re-enable on ARM once xl8 bugs are fixed */ + IF_X86_ELSE(35, 0), /* i#1674: re-enable on ARM once xl8 bugs are fixed */ "reset all caches when pending deletion has this many entries") /* the reset-by-unit options focus on filled units and not created units * to avoid being triggered by new, empty, private units for new threads @@ -1975,7 +1975,7 @@ IF_RCT_IND_BRANCH(options->rct_ind_jump = OPTION_DISABLED;) #ifdef WINDOWS PC_OPTION_INTERNAL(bool, noasynch, "disable asynchronous event interceptions") #endif - PC_OPTION_DEFAULT_INTERNAL(bool, hw_cache_consistency, IF_ARM_ELSE(false, true), + PC_OPTION_DEFAULT_INTERNAL(bool, hw_cache_consistency, IF_X86_ELSE(true, false), "keep code cache consistent in face of hardware implicit icache sync") OPTION_DEFAULT_INTERNAL(bool, sandbox_writes, true, "check each sandboxed write for selfmod?") /* FIXME: off by default until dll load perf issues are solved: case 3559 */ @@ -2207,7 +2207,7 @@ IF_RCT_IND_BRANCH(options->rct_ind_jump = OPTION_DISABLED;) * these don't affect pcaches since the trampoline bbs won't be coarse-grain. */ /* XXX i#1582: add ARM support for native_exec */ - OPTION_DEFAULT(bool, native_exec, IF_ARM_ELSE(false, true), + OPTION_DEFAULT(bool, native_exec, IF_X86_ELSE(true, false), "attempt to execute certain libraries natively (WARNING: lots of issues with this, use at own risk)") /* initially populated w/ all dlls we've needed to get .NET, MS JVM, Sun JVM, * Symantec JVM, and Panda AV working, but with very limited workload testing so far diff --git a/core/os_shared.h b/core/os_shared.h index 37491fe788e..27f6f330ce8 100644 --- a/core/os_shared.h +++ b/core/os_shared.h @@ -1017,9 +1017,9 @@ enum { JMP_ABS_MEM_IND64_MODRM = 0x25, # endif }; -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) enum { - /* FIXME i#1551: this is for A32 for now to get things compiling */ + /* FIXME i#1551, i#1569: this is for A32 for now to get things compiling */ JMP_REL32_OPCODE = 0xec000000, JMP_REL32_SIZE = 4, CALL_REL32_OPCODE = 0xed000000, diff --git a/core/translate.c b/core/translate.c index 67ca83bc79c..eb63451846e 100644 --- a/core/translate.c +++ b/core/translate.c @@ -119,6 +119,9 @@ instr_is_inline_syscall_jmp(dcontext_t *dcontext, instr_t *inst) # ifdef X86 return (instr_get_opcode(inst) == OP_jmp_short && opnd_is_instr(instr_get_target(inst))); +# elif defined(AARCH64) + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ + return false; # elif defined(ARM) return ((instr_get_opcode(inst) == OP_b_short || /* A32 uses a regular jump */ diff --git a/core/unix/include/syscall.h b/core/unix/include/syscall.h index cac78ba16e4..0dae0e3ffbd 100644 --- a/core/unix/include/syscall.h +++ b/core/unix/include/syscall.h @@ -20,7 +20,7 @@ #ifdef X86 # include "syscall_linux_x86.h" -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) # include "syscall_linux_arm.h" #endif diff --git a/core/unix/include/syscall_linux_arm.h b/core/unix/include/syscall_linux_arm.h index 1fc030b7180..e8142ab97ec 100644 --- a/core/unix/include/syscall_linux_arm.h +++ b/core/unix/include/syscall_linux_arm.h @@ -18,12 +18,7 @@ # error Only use this file on Linux #endif -#ifdef X64 - -/* FIXME i#1569: add AArch64 support */ -# error NYI - -#else /* X64 */ +#if defined(ARM) || defined(AARCH64) /* FIXME i#1569: arm64 has different numbers */ /* From /usr/include/arm-linux-gnueabihf/asm/unistd.h */ @@ -435,14 +430,9 @@ # undef __NR_syscall # undef __NR_ipc -#endif /* !X64 */ - -#ifdef X64 +#endif /* ARM || AARCH64 */ -/* FIXME i#1569: add AArch64 support */ -# error NYI - -#else /* X64 */ +#if defined(ARM) || defined(AARCH64) /* FIXME i#1569: arm64 has different numbers */ /* From /usr/include/arm-linux-gnueabihf/bits/syscall.h */ @@ -786,6 +776,12 @@ # define SYS_usr __ARM_NR_usr # define SYS_usr __ARM_NR_usr # define SYS_set_tls __ARM_NR_set_tls -#endif /* !X64 */ +#endif /* ARM || AARCH64 */ + +/* FIXME i#1569: arm64 does not have these system calls */ +#ifdef AARCH64 +# define SYS_mmap 1001 +# define SYS_getrlimit 1002 +#endif #endif /* _SYSCALL_LINUX_ARM_H_ */ diff --git a/core/unix/injector.c b/core/unix/injector.c index 7bfb334e079..021a7a7625b 100644 --- a/core/unix/injector.c +++ b/core/unix/injector.c @@ -788,7 +788,6 @@ enum { MAX_SHELL_CODE = 4096 }; # define REG_SP_FIELD IF_X64_ELSE(rsp, esp) # define REG_RETVAL_FIELD IF_X64_ELSE(rax, eax) #elif defined(ARM) -# ifndef X64 /* On AArch32, glibc uses user_regs instead of user_regs_struct. * struct user_regs { * unsigned long int uregs[18]; @@ -797,14 +796,16 @@ enum { MAX_SHELL_CODE = 4096 }; * - uregs[16] is for cpsr, * - uregs[17] is for "orig_r0". */ -# define USER_REGS_TYPE user_regs -# define REG_PC_FIELD uregs[15] /* r15 in user_regs */ -# define REG_SP_FIELD uregs[13] /* r13 in user_regs */ +# define USER_REGS_TYPE user_regs +# define REG_PC_FIELD uregs[15] /* r15 in user_regs */ +# define REG_SP_FIELD uregs[13] /* r13 in user_regs */ /* On ARM, all reg args are also reg retvals. */ -# define REG_RETVAL_FIELD uregs[0] /* r0 in user_regs */ -# else -# error AArch64 is not supported -# endif +# define REG_RETVAL_FIELD uregs[0] /* r0 in user_regs */ +#elif defined(AARCH64) +# define USER_REGS_TYPE user_regs_struct +# define REG_PC_FIELD pc +# define REG_SP_FIELD sp +# define REG_RETVAL_FIELD regs[0] /* x0 in user_regs_struct */ #endif enum { REG_PC_OFFSET = offsetof(struct USER_REGS_TYPE, REG_PC_FIELD) }; @@ -837,14 +838,18 @@ static const enum_name_pair_t pt_req_map[] = { {PTRACE_CONT, "PTRACE_CONT"}, {PTRACE_KILL, "PTRACE_KILL"}, {PTRACE_SINGLESTEP, "PTRACE_SINGLESTEP"}, +#ifndef AARCH64 {PTRACE_GETREGS, "PTRACE_GETREGS"}, {PTRACE_SETREGS, "PTRACE_SETREGS"}, {PTRACE_GETFPREGS, "PTRACE_GETFPREGS"}, {PTRACE_SETFPREGS, "PTRACE_SETFPREGS"}, +#endif {PTRACE_ATTACH, "PTRACE_ATTACH"}, {PTRACE_DETACH, "PTRACE_DETACH"}, +#ifndef AARCH64 {PTRACE_GETFPXREGS, "PTRACE_GETFPXREGS"}, {PTRACE_SETFPXREGS, "PTRACE_SETFPXREGS"}, +#endif {PTRACE_SYSCALL, "PTRACE_SYSCALL"}, {PTRACE_SETOPTIONS, "PTRACE_SETOPTIONS"}, {PTRACE_GETEVENTMSG, "PTRACE_GETEVENTMSG"}, @@ -853,6 +858,12 @@ static const enum_name_pair_t pt_req_map[] = { {0} }; +#ifdef AARCH64 +/* FIXME i#1569: must use GETREGSET/SETREGSET instead of GETREGS/SETREGS */ +#define PTRACE_GETREGS PTRACE_GETREGSET +#define PTRACE_SETREGS PTRACE_SETREGSET +#endif + /* Ptrace syscall wrapper, for logging. * XXX: We could call libc's ptrace instead of using dynamorio_syscall. * Initially I used the raw syscall to avoid adding a libc import, but calling @@ -1042,6 +1053,10 @@ injectee_run_get_retval(dr_inject_info_t *info, void *dc, instrlist_t *ilist) long r; ptr_int_t failure = -EUNATCH; /* Unlikely to be used by most syscalls. */ +#ifdef AARCH64 + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ +#endif + /* Get register state before executing the shellcode. */ r = our_ptrace(PTRACE_GETREGS, info->pid, NULL, ®s); if (r < 0) @@ -1253,9 +1268,6 @@ user_regs_to_mc(priv_mcontext_t *mc, struct USER_REGS_TYPE *regs) mc->edi = regs->edi; # endif #elif defined(ARM) -# ifdef X64 -# error AArch64 is not supported -# else mc->r0 = regs->uregs[0]; mc->r1 = regs->uregs[1]; mc->r2 = regs->uregs[2]; @@ -1273,7 +1285,8 @@ user_regs_to_mc(priv_mcontext_t *mc, struct USER_REGS_TYPE *regs) mc->r14 = regs->uregs[14]; mc->r15 = regs->uregs[15]; mc->cpsr = regs->uregs[16]; -# endif /* 64/32-bit */ +#elif defined(AARCH64) + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ #endif /* X86/ARM */ } @@ -1333,6 +1346,10 @@ inject_ptrace(dr_inject_info_t *info, const char *library_path) int status; int signal; +#ifdef AARCH64 + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ +#endif + /* Attach to the process in question. */ r = our_ptrace(PTRACE_ATTACH, info->pid, NULL, NULL); if (r < 0) { @@ -1408,7 +1425,7 @@ inject_ptrace(dr_inject_info_t *info, const char *library_path) strncpy(args.home_dir, getenv("HOME"), BUFFER_SIZE_ELEMENTS(args.home_dir)); NULL_TERMINATE_BUFFER(args.home_dir); -#if defined(X86) || defined(ARM) +#if defined(X86) || defined(ARM) || defined(AARCH64) regs.REG_SP_FIELD -= REDZONE_SIZE; /* Need to preserve x64 red zone. */ regs.REG_SP_FIELD -= sizeof(args); /* Allocate space for args. */ regs.REG_SP_FIELD = ALIGN_BACKWARD(regs.REG_SP_FIELD, REGPARM_END_ALIGN); diff --git a/core/unix/loader.c b/core/unix/loader.c index 1761610417d..f7013038697 100644 --- a/core/unix/loader.c +++ b/core/unix/loader.c @@ -72,8 +72,10 @@ extern size_t wcslen(const wchar_t *str); /* in string.c */ */ #define SYSTEM_LIBRARY_PATH_VAR "LD_LIBRARY_PATH" char *ld_library_path = NULL; -static const char *system_lib_paths[] = { +static const char *const system_lib_paths[] = { +#ifdef X86 "/lib/tls/i686/cmov", +#endif "/usr/lib", "/lib", "/usr/local/lib", /* Ubuntu: /etc/ld.so.conf.d/libc.conf */ @@ -95,12 +97,19 @@ static const char *system_lib_paths[] = { "/usr/lib/arm-linux-gnueabi", # endif #else + /* 64-bit Ubuntu */ +# ifdef X86 "/lib64/tls/i686/cmov", +# endif "/usr/lib64", "/lib64", - /* 64-bit Ubuntu */ +# ifdef X86 "/lib/x86_64-linux-gnu", /* /etc/ld.so.conf.d/x86_64-linux-gnu.conf */ "/usr/lib/x86_64-linux-gnu", /* /etc/ld.so.conf.d/x86_64-linux-gnu.conf */ +# elif defined(AARCH64) + "/lib/aarch64-linux-gnu", + "/usr/lib/aarch64-linux-gnu", +# endif #endif }; #define NUM_SYSTEM_LIB_PATHS \ @@ -1549,9 +1558,10 @@ privload_mem_is_elf_so_header(byte *mem) if (elf_hdr->e_type != ET_DYN) return false; /* ARM or X86 */ - if (elf_hdr->e_machine != IF_ARM_ELSE(EM_ARM, - IF_X64_ELSE(EM_X86_64, - EM_386))) + if (elf_hdr->e_machine != IF_X86_ELSE(IF_X64_ELSE(EM_X86_64, + EM_386), + IF_X64_ELSE(EM_AARCH64, + EM_ARM))) return false; if (elf_hdr->e_ehsize != sizeof(ELF_HEADER_TYPE)) return false; diff --git a/core/unix/loader_linux.c b/core/unix/loader_linux.c index a6a443a7160..664f0d2ca22 100644 --- a/core/unix/loader_linux.c +++ b/core/unix/loader_linux.c @@ -149,23 +149,21 @@ typedef struct _tcb_head_t { ptr_uint_t stack_guard; ptr_uint_t pointer_guard; +#elif defined(AARCH64) + /* FIXME i#1569: This may be wrong! */ + void *dtv; + void *private; #elif defined(ARM) -# ifdef X64 -# error NYI on AArch64 -# else void *dtv; void *private; byte padding[2]; /* make it 16-byte align */ -# endif #endif /* X86/ARM */ } tcb_head_t; #ifdef X86 # define TLS_PRE_TCB_SIZE 0 -#elif defined(ARM) -# ifdef X64 -# error NYI on AArch64 -# else +#elif defined(ARM) || defined(AARCH64) +/* FIXME i#1569: This may be wrong for AArch64! */ /* Data structure to match libc pthread. * GDB reads some slot in TLS, which is pid/tid of pthread, so we must make sure * the size and member locations match to avoid gdb crash. @@ -176,10 +174,9 @@ typedef struct _dr_pthread_t { thread_id_t pid; byte data2[0x450]; /* # of bytes after pid within pthread */ } dr_pthread_t; -# define TLS_PRE_TCB_SIZE sizeof(dr_pthread_t) -# define LIBC_PTHREAD_SIZE 0x4c0 -# define LIBC_PTHREAD_TID_OFFSET 0x68 -# endif +# define TLS_PRE_TCB_SIZE sizeof(dr_pthread_t) +# define LIBC_PTHREAD_SIZE 0x4c0 +# define LIBC_PTHREAD_TID_OFFSET 0x68 #endif /* X86/ARM */ #ifdef X86 @@ -190,8 +187,8 @@ typedef struct _dr_pthread_t { * (i#46), we need to copy this data from before the thread pointer. */ # define APP_LIBC_TLS_SIZE 0x400 -#elif defined(ARM) -/* FIXME i#1551: investigate the difference between ARM and X86 on TLS. +#elif defined(ARM) || defined(AARCH64) +/* FIXME i#1551, i#1569: investigate the difference between ARM and X86 on TLS. * On ARM, it seems that TLS variables are not put before the thread pointer * as they are on X86. */ @@ -257,7 +254,7 @@ privload_tls_init(void *app_tp) __FUNCTION__, app_tp); dr_tp = heap_mmap(max_client_tls_size); ASSERT(APP_LIBC_TLS_SIZE + TLS_PRE_TCB_SIZE + tcb_size <= max_client_tls_size); -#ifdef ARM +#if defined(ARM) || defined(AARCH64) /* GDB reads some pthread members (e.g., pid, tid), so we must make sure * the size and member locations match to avoid gdb crash. */ @@ -287,7 +284,7 @@ privload_tls_init(void *app_tp) LOG(GLOBAL, LOG_LOADER, 2, "%s: read failed, tcb was 0x%lx bytes " "instead of 0x%lx\n", __FUNCTION__, tls_bytes_read - APP_LIBC_TLS_SIZE, tcb_size); -#ifdef ARM +#if defined(ARM) || defined(AARCH64) } else { dr_pthread_t *dp = (dr_pthread_t *)(dr_tp - APP_LIBC_TLS_SIZE - TLS_PRE_TCB_SIZE); @@ -306,7 +303,7 @@ privload_tls_init(void *app_tp) dr_tcb->self = dr_tcb; /* i#555: replace app's vsyscall with DR's int0x80 syscall */ dr_tcb->sysinfo = (ptr_uint_t)client_int_syscall; -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) dr_tcb->dtv = NULL; dr_tcb->private = NULL; #endif @@ -367,6 +364,10 @@ redirect____tls_get_addr() */ #ifdef X86 asm("mov %%"ASM_XAX", %0" : "=m"((ti)) : : ASM_XAX); +#elif defined(AARCH64) + /* FIXME i#1569: NYI */ + asm("str x0, %0" : "=m"((ti)) : : "x0"); + ASSERT_NOT_REACHED(); #elif defined(ARM) /* XXX: assuming ti is passed via r0? */ asm("str r0, %0" : "=m"((ti)) : : "r0"); diff --git a/core/unix/module_elf.c b/core/unix/module_elf.c index 22b191cd805..0cc37ae38ca 100644 --- a/core/unix/module_elf.c +++ b/core/unix/module_elf.c @@ -209,9 +209,10 @@ is_elf_so_header_common(app_pc base, size_t size, bool memory) if (INTERNAL_OPTION(private_loader) && ((elf_header.e_version != 1) || (memory && elf_header.e_ehsize != sizeof(ELF_HEADER_TYPE)) || - (memory && elf_header.e_machine != IF_ARM_ELSE(EM_ARM, - IF_X64_ELSE(EM_X86_64, - EM_386))))) + (memory && elf_header.e_machine != IF_X86_ELSE(IF_X64_ELSE(EM_X86_64, + EM_386), + IF_X64_ELSE(EM_AARCH64, + EM_ARM))))) return false; #endif /* FIXME - should we add any of these to the check? For real @@ -221,9 +222,10 @@ is_elf_so_header_common(app_pc base, size_t size, bool memory) ASSERT_CURIOSITY(elf_header.e_ident[EI_OSABI] == ELFOSABI_SYSV || elf_header.e_ident[EI_OSABI] == ELFOSABI_LINUX); ASSERT_CURIOSITY(!memory || - elf_header.e_machine == IF_ARM_ELSE(EM_ARM, - IF_X64_ELSE(EM_X86_64, - EM_386))); + elf_header.e_machine == IF_X86_ELSE(IF_X64_ELSE(EM_X86_64, + EM_386), + IF_X64_ELSE(EM_AARCH64, + EM_ARM))); return true; } return false; @@ -993,9 +995,10 @@ module_get_platform(file_t f, dr_platform_t *platform, dr_platform_t *alt_platfo ASSERT(offsetof(Elf64_Ehdr, e_machine) == offsetof(Elf32_Ehdr, e_machine)); switch (elf_header.elf64.e_machine) { - case EM_X86_64: *platform = DR_PLATFORM_64BIT; break; + case EM_X86_64: + case EM_AARCH64: *platform = DR_PLATFORM_64BIT; break; case EM_386: - case EM_ARM: *platform = DR_PLATFORM_32BIT; break; + case EM_ARM: *platform = DR_PLATFORM_32BIT; break; default: return false; } diff --git a/core/unix/module_elf.h b/core/unix/module_elf.h index 061ed59c86d..fc3d5dcad43 100644 --- a/core/unix/module_elf.h +++ b/core/unix/module_elf.h @@ -143,33 +143,45 @@ * offset for the symbol. */ # endif +#elif defined(AARCH64) +# define ELF_R_TYPE ELF64_R_TYPE +# define ELF_R_SYM ELF64_R_SYM +/* relocation type */ +# define ELF_R_NONE R_AARCH64_NONE /* No relocation. */ +# define ELF_R_DIRECT R_AARCH64_ABS64 /* Direct 64 bit. */ +# define ELF_R_COPY R_AARCH64_COPY /* Copy symbol at runtime. */ +# define ELF_R_GLOB_DAT R_AARCH64_GLOB_DAT /* Create GOT entry. */ +# define ELF_R_JUMP_SLOT R_AARCH64_JUMP_SLOT /* Create PLT entry. */ +# define ELF_R_RELATIVE R_AARCH64_RELATIVE /* Adjust by program base. */ +# define ELF_R_IRELATIVE R_AARCH64_IRELATIVE /* STT_GNU_IFUNC relocation. */ +/* tls related */ +# define ELF_R_TLS_DTPMOD 1028 /* R_AARCH64_TLS_DTPMOD64 Module number. */ +# define ELF_R_TLS_TPOFF 1030 /* R_AARCH64_TLS_TPREL64 TP-relative offset. */ +# define ELF_R_TLS_DTPOFF 1029 /* R_AARCH64_TLS_DTPREL64 Module-relative offset. */ +# define ELF_R_TLS_DESC 1031 /* R_AARCH64_TLSDESC TLS Descriptor. */ #elif defined(ARM) -# ifdef X64 -# error NYI -# else -# define ELF_R_TYPE ELF32_R_TYPE -# define ELF_R_SYM ELF32_R_SYM -# define ELF_R_INFO ELF32_R_INFO +# define ELF_R_TYPE ELF32_R_TYPE +# define ELF_R_SYM ELF32_R_SYM +# define ELF_R_INFO ELF32_R_INFO /* relocation type */ -# define ELF_R_NONE R_ARM_NONE /* No reloc */ -# define ELF_R_DIRECT R_ARM_ABS32 /* Direct 32 bit */ -# define ELF_R_COPY R_ARM_COPY /* Copy symbol at runtime */ -# define ELF_R_GLOB_DAT R_ARM_GLOB_DAT /* GOT entry */ -# define ELF_R_JUMP_SLOT R_ARM_JUMP_SLOT /* PLT entry */ -# define ELF_R_RELATIVE R_ARM_RELATIVE /* Adjust by program delta */ -# define ELF_R_IRELATIVE R_ARM_IRELATIVE /* Adjust indirectly by program base */ +# define ELF_R_NONE R_ARM_NONE /* No reloc */ +# define ELF_R_DIRECT R_ARM_ABS32 /* Direct 32 bit */ +# define ELF_R_COPY R_ARM_COPY /* Copy symbol at runtime */ +# define ELF_R_GLOB_DAT R_ARM_GLOB_DAT /* GOT entry */ +# define ELF_R_JUMP_SLOT R_ARM_JUMP_SLOT /* PLT entry */ +# define ELF_R_RELATIVE R_ARM_RELATIVE /* Adjust by program delta */ +# define ELF_R_IRELATIVE R_ARM_IRELATIVE /* Adjust indirectly by program base */ /* tls related */ -# define ELF_R_TLS_DTPMOD R_ARM_TLS_DTPMOD32 /* Module ID */ -# define ELF_R_TLS_TPOFF R_ARM_TLS_TPOFF32 /* Negated offsets in static TLS block */ -# define ELF_R_TLS_DTPOFF R_ARM_TLS_DTPOFF32 /* Offset in TLS block */ -# ifndef ANDROID -# define ELF_R_TLS_DESC R_ARM_TLS_DESC /* TLS descriptor containing - * pointer to code and to - * argument, returning the TLS - * offset for the symbol. - */ -# endif /* ANDROID */ -# endif /* 64/32 */ +# define ELF_R_TLS_DTPMOD R_ARM_TLS_DTPMOD32 /* Module ID */ +# define ELF_R_TLS_TPOFF R_ARM_TLS_TPOFF32 /* Negated offsets in static TLS block */ +# define ELF_R_TLS_DTPOFF R_ARM_TLS_DTPOFF32 /* Offset in TLS block */ +# ifndef ANDROID +# define ELF_R_TLS_DESC R_ARM_TLS_DESC /* TLS descriptor containing + * pointer to code and to + * argument, returning the TLS + * offset for the symbol. + */ +# endif /* ANDROID */ #endif /* X86/ARM */ bool diff --git a/core/unix/native_elf.c b/core/unix/native_elf.c index 54a3108d8a0..16eccf1de8c 100644 --- a/core/unix/native_elf.c +++ b/core/unix/native_elf.c @@ -150,8 +150,8 @@ find_dl_fixup(dcontext_t *dcontext, app_pc resolver) } instr_free(dcontext, &instr); return fixup; -#elif defined(ARM) - /* FIXME i#1551: NYI on ARM */ +#elif defined(ARM) || defined(AARCH64) + /* FIXME i#1551, i#1569: NYI on ARM/AArch64 */ ASSERT_NOT_IMPLEMENTED(false); return NULL; #endif /* X86/ARM */ diff --git a/core/unix/os.c b/core/unix/os.c index 30ece214eb5..91d66c72287 100644 --- a/core/unix/os.c +++ b/core/unix/os.c @@ -143,16 +143,16 @@ struct compat_rlimit { * values in xdx:xax. */ #define MCXT_SYSCALL_RES(mc) ((mc)->IF_X86_ELSE(xax, r0)) -#ifdef ARM -# ifdef X64 -# define ASM_R3 "x3" -# define READ_TP_TO_R3 "NYI on ARM" /* FIXME i#1551: NYI on ARM */ -# else -# define ASM_R3 "r3" -# define READ_TP_TO_R3 \ +#if defined(AARCH64) +# define ASM_R3 "x3" +# define READ_TP_TO_R3 \ + "mrs "ASM_R3", tpidr_el0\n\t" \ + "ldr "ASM_R3", ["ASM_R3", #"STRINGIFY(DR_TLS_BASE_OFFSET)"] \n\t" +#elif defined(ARM) +# define ASM_R3 "r3" +# define READ_TP_TO_R3 \ "mrc p15, 0, "ASM_R3", c13, c0, "STRINGIFY(USR_TLS_REG_OPCODE)" \n\t" \ "ldr "ASM_R3", ["ASM_R3", #"STRINGIFY(DR_TLS_BASE_OFFSET)"] \n\t" -# endif /* 64/32-bit */ #endif /* ARM */ /* Prototype for all functions in .init_array. */ @@ -1311,7 +1311,7 @@ os_timeout(int time_in_milliseconds) asm("movzw"IF_X64_ELSE("q","l")" %0, %%"ASM_XAX : : "m"((offs)) : ASM_XAX); \ asm("mov %"ASM_SEG":(%%"ASM_XAX"), %%"ASM_XAX : : : ASM_XAX); \ asm("mov %%"ASM_XAX", %0" : "=m"((var)) : : ASM_XAX); -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) # define WRITE_TLS_SLOT_IMM(imm, var) \ __asm__ __volatile__( \ READ_TP_TO_R3 \ @@ -1371,7 +1371,7 @@ is_thread_tls_initialized(void) } # endif return false; -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) byte **dr_tls_base_addr; if (tls_global_type == TLS_TYPE_NONE) return false; @@ -1557,7 +1557,7 @@ get_segment_base(uint seg) # else return (byte *) POINTER_MAX; #endif /* HAVE_TLS */ -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) /* XXX i#1551: should we rename/refactor to avoid "segment"? */ return (byte *) read_thread_register(seg); #endif @@ -2154,7 +2154,7 @@ os_should_swap_state(void) /* -private_loader currently implies -mangle_app_seg, but let's be safe. */ return (INTERNAL_OPTION(mangle_app_seg) && IF_CLIENT_INTERFACE_ELSE(INTERNAL_OPTION(private_loader), false)); -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) /* FIXME i#1551: we may need swap TLS for private libraries */ return false; #endif @@ -3263,7 +3263,7 @@ dr_create_client_thread(void (*func)(void *param), void *arg) LOG(THREAD, LOG_ALL, 1, "dr_create_client_thread xsp="PFX" dstack="PFX"\n", xsp, get_clone_record_dstack(crec)); thread_id_t newpid = dynamorio_clone(flags, xsp, NULL, - IF_ARM_ELSE(NULL, IF_X64_ELSE(NULL, &desc)), + IF_X86_ELSE(IF_X64_ELSE(NULL, &desc), NULL), NULL, client_thread_run); /* i#501 switch to app's tls before creating client thread */ if (IF_CLIENT_INTERFACE_ELSE(INTERNAL_OPTION(private_loader), false)) @@ -4569,7 +4569,7 @@ ignorable_system_call_normalized(int num) case SYS_ugetrlimit: #endif case SYS_setrlimit: -#if defined(LINUX) && !defined(ARM) +#if defined(LINUX) && defined(X86) /* i#784: app may have behavior relying on SIGALRM */ case SYS_alarm: #endif @@ -4638,17 +4638,13 @@ const reg_id_t syscall_regparms[MAX_SYSCALL_ARGS] = { DR_REG_EDI, DR_REG_EBP # endif /* 64/32-bit */ -#elif defined(ARM) -# ifdef X64 -# error AArch64 syscall not supported -# else +#elif defined(ARM) || defined(AARCH64) DR_REG_R0, DR_REG_R1, DR_REG_R2, DR_REG_R3, DR_REG_R4, DR_REG_R5, -# endif /* 64/32-bit */ #endif /* X86/ARM */ }; @@ -5929,7 +5925,10 @@ os_switch_seg_to_context(dcontext_t *dcontext, reg_id_t seg, bool to_app) LOG(THREAD, LOG_LOADER, 2, "%s %s: set_tls swap success=%d for thread "TIDFMT"\n", __FUNCTION__, to_app ? "to app" : "to DR", res, get_thread_id()); -#endif /* X86/ARM */ +#elif defined(AARCH64) + (void)os_tls; + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ +#endif /* X86/ARM/AARCH64 */ return res; } @@ -6621,7 +6620,7 @@ pre_system_call(dcontext_t *dcontext) dcontext->sys_param0 = sys_param(dcontext, 0); dcontext->sys_param1 = sys_param(dcontext, 1); break; -#if defined(LINUX) && !defined(ARM) +#if defined(LINUX) && defined(X86) case SYS_alarm: /* 27 on x86 and 37 on x64 */ dcontext->sys_param0 = sys_param(dcontext, 0); handle_pre_alarm(dcontext, (unsigned int) dcontext->sys_param0); @@ -7772,7 +7771,7 @@ post_system_call(dcontext_t *dcontext) handle_post_getitimer(dcontext, success, (int) dcontext->sys_param0, (struct itimerval *) dcontext->sys_param1); break; -#if defined(LINUX) && !defined(ARM) +#if defined(LINUX) && defined(X86) case SYS_alarm: /* 27 on x86 and 37 on x64 */ handle_post_alarm(dcontext, success, (unsigned int) dcontext->sys_param0); break; diff --git a/core/unix/os_exports.h b/core/unix/os_exports.h index 756f3d156f9..516b11c4359 100644 --- a/core/unix/os_exports.h +++ b/core/unix/os_exports.h @@ -83,7 +83,7 @@ # define LIB_SEG_TLS SEG_GS /* libc+loader tls */ # define LIB_ASM_SEG "%gs" # endif -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) /* The SEG_TLS is not preserved by all kernels (older 32-bit, or all 64-bit), so we * end up having to steal the app library TPID register for priv lib use. * When in DR state, we steal a field inside the priv lib TLS to store the DR base. @@ -104,10 +104,7 @@ #define DR_REG_SYSNUM IF_X86_ELSE(REG_EAX/* not XAX */, DR_REG_R7) -#ifdef ARM -# ifdef X64 -# error NYI on AArch64 -# endif +#if defined(ARM) || defined(AARCH64) # ifdef ANDROID /* We have our own slot at the end of our instance of Android's pthread_internal_t */ # define DR_TLS_BASE_OFFSET IF_X64_ELSE(616, 588) @@ -210,7 +207,7 @@ bool disable_env(const char *name); # define DECLARE_DATA_SECTION(name, wx) \ asm(".section "name", \"a"wx"\", @progbits"); \ asm(".align 0x1000"); -# elif defined(ARM) +# elif defined(ARM) || defined(AARCH64) # define DECLARE_DATA_SECTION(name, wx) \ asm(".section "name", \"a"wx"\""); \ asm(".align 12"); /* 2^12 */ @@ -234,7 +231,7 @@ bool disable_env(const char *name); asm(".section .data"); \ asm(".align 0x1000"); \ asm(".text"); -# elif defined(ARM) +# elif defined(ARM) || defined(AARCH64) # define END_DATA_SECTION_DECLARATIONS() \ asm(".section .data"); \ asm(".align 12"); \ @@ -360,7 +357,7 @@ get_clone_record_app_xsp(void *record); byte * get_clone_record_dstack(void *record); -#ifdef ARM +#if defined(ARM) || defined(AARCH64) reg_t get_clone_record_stolen_value(void *record); diff --git a/core/unix/os_private.h b/core/unix/os_private.h index 432eda23bf9..a482b5a3e3e 100644 --- a/core/unix/os_private.h +++ b/core/unix/os_private.h @@ -59,6 +59,10 @@ # define ASM_XBP "ebp" # define ASM_XSP "esp" # endif /* 64/32-bit */ +#elif defined(AARCH64) +# define ASM_R0 "x0" +# define ASM_R1 "x1" +# define ASM_XSP "sp" #elif defined(ARM) # define ASM_R0 "r0" # define ASM_R1 "r1" diff --git a/core/unix/os_public.h b/core/unix/os_public.h index 22b8568717c..3c7ece5e85a 100644 --- a/core/unix/os_public.h +++ b/core/unix/os_public.h @@ -109,31 +109,33 @@ typedef struct sigcontext sigcontext_t; # endif /* 64/32-bit */ # define SC_FP SC_XBP # define SC_SYSNUM_REG SC_XAX -#elif defined(ARM) -# ifdef X64 +#elif defined(AARCH64) /* FIXME i#1569: NYI */ -# error 64-bit ARM is not supported -# else -# define SC_XIP SC_FIELD(arm_pc) -# define SC_FP SC_FIELD(arm_fp) -# define SC_R0 SC_FIELD(arm_r0) -# define SC_R1 SC_FIELD(arm_r1) -# define SC_R2 SC_FIELD(arm_r2) -# define SC_R3 SC_FIELD(arm_r3) -# define SC_R4 SC_FIELD(arm_r4) -# define SC_R5 SC_FIELD(arm_r5) -# define SC_R6 SC_FIELD(arm_r6) -# define SC_R7 SC_FIELD(arm_r7) -# define SC_R8 SC_FIELD(arm_r8) -# define SC_R9 SC_FIELD(arm_r9) -# define SC_R10 SC_FIELD(arm_r10) -# define SC_R11 SC_FIELD(arm_fp) -# define SC_R12 SC_FIELD(arm_ip) -# define SC_XSP SC_FIELD(arm_sp) -# define SC_LR SC_FIELD(arm_lr) -# define SC_XFLAGS SC_FIELD(arm_cpsr) -# define SC_SYSNUM_REG SC_R7 -# endif /* 64/32-bit */ +# define SC_XIP SC_FIELD(pc) +# define SC_FP SC_FIELD(regs[29]) +# define SC_R0 SC_FIELD(regs[0]) +# define SC_XSP SC_FIELD(sp) +# define SC_XFLAGS SC_FIELD(pstate) +#elif defined(ARM) +# define SC_XIP SC_FIELD(arm_pc) +# define SC_FP SC_FIELD(arm_fp) +# define SC_R0 SC_FIELD(arm_r0) +# define SC_R1 SC_FIELD(arm_r1) +# define SC_R2 SC_FIELD(arm_r2) +# define SC_R3 SC_FIELD(arm_r3) +# define SC_R4 SC_FIELD(arm_r4) +# define SC_R5 SC_FIELD(arm_r5) +# define SC_R6 SC_FIELD(arm_r6) +# define SC_R7 SC_FIELD(arm_r7) +# define SC_R8 SC_FIELD(arm_r8) +# define SC_R9 SC_FIELD(arm_r9) +# define SC_R10 SC_FIELD(arm_r10) +# define SC_R11 SC_FIELD(arm_fp) +# define SC_R12 SC_FIELD(arm_ip) +# define SC_XSP SC_FIELD(arm_sp) +# define SC_LR SC_FIELD(arm_lr) +# define SC_XFLAGS SC_FIELD(arm_cpsr) +# define SC_SYSNUM_REG SC_R7 #endif /* X86/ARM */ #endif /* _OS_PUBLIC_H_ 1 */ diff --git a/core/unix/signal.c b/core/unix/signal.c index 84b9117cb6a..db1726d02f4 100644 --- a/core/unix/signal.c +++ b/core/unix/signal.c @@ -1905,6 +1905,9 @@ sigcontext_to_mcontext(priv_mcontext_t *mc, sig_full_cxt_t *sc_full) mc->r14 = sc->SC_FIELD(r14); mc->r15 = sc->SC_FIELD(r15); # endif /* X64 */ +#elif defined(AARCH64) + (void)sc; + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ #elif defined (ARM) mc->r0 = sc->SC_FIELD(arm_r0); mc->r1 = sc->SC_FIELD(arm_r1); @@ -1971,6 +1974,9 @@ mcontext_to_sigcontext(sig_full_cxt_t *sc_full, priv_mcontext_t *mc) sc->SC_FIELD(r14) = mc->r14; sc->SC_FIELD(r15) = mc->r15; # endif /* X64 */ +#elif defined(AARCH64) + (void)sc; + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ #elif defined(ARM) sc->SC_FIELD(arm_r0) = mc->r0; sc->SC_FIELD(arm_r1) = mc->r1; @@ -2012,7 +2018,7 @@ mcontext_to_ucontext(kernel_ucontext_t *uc, priv_mcontext_t *mc) mcontext_to_sigcontext(&sc_full, mc); } -#ifdef ARM +#if defined(ARM) || defined(AARCH64) static void set_sigcxt_stolen_reg(sigcontext_t *sc, reg_t val) { @@ -2025,6 +2031,7 @@ get_sigcxt_stolen_reg(sigcontext_t *sc) return *(&sc->SC_R0 + (dr_reg_stolen - DR_REG_R0)); } +# ifdef ARM static dr_isa_mode_t get_pc_mode_from_cpsr(sigcontext_t *sc) { @@ -2039,6 +2046,7 @@ set_pc_mode_in_cpsr(sigcontext_t *sc, dr_isa_mode_t isa_mode) else sc->SC_XFLAGS &= ~EFLAGS_T; } +# endif #endif /* Returns whether successful. If avoid_failure, tries to translate @@ -2141,6 +2149,8 @@ thread_set_self_context(void *cxt) # else asm("jmp dynamorio_sigreturn"); # endif /* MACOS/LINUX */ +#elif defined(AARCH64) + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ #elif defined(ARM) asm("ldr "ASM_XSP", %0" : : "m"(xsp_for_sigreturn)); asm("b dynamorio_sigreturn"); @@ -2202,6 +2212,11 @@ sig_has_restorer(thread_sig_info_t *info, int sig) {0x77, 0x70, 0xa0, 0xe3, 0x00, 0x00, 0x00, 0xef}; static const byte SIGRET_RT[8] = {0xad, 0x70, 0xa0, 0xe3, 0x00, 0x00, 0x00, 0xef}; +# elif defined(AARCH64) + /* FIXME i#1569 */ + static const byte SIGRET_NONRT[8] = { 0 }; + static const byte SIGRET_RT[8] = { 0 }; + ASSERT_NOT_IMPLEMENTED(false); # endif byte buf[MAX(sizeof(SIGRET_NONRT), sizeof(SIGRET_RT))]= {0}; if (safe_read(info->app_sigaction[sig]->restorer, sizeof(buf), buf) && @@ -2730,6 +2745,10 @@ transfer_from_sig_handler_to_fcache_return(dcontext_t *dcontext, sigcontext_t *s dcontext->next_tag = canonicalize_pc_target(dcontext, next_pc); IF_ARM(dr_set_isa_mode(dcontext, get_pc_mode_from_cpsr(sc), NULL)); +#ifdef AARCH64 + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ +#endif + /* Set our sigreturn context to point to fcache_return! * Then we'll go back through kernel, appear in fcache_return, * and go through dispatch & interp, without messing up dynamo stack. @@ -3078,10 +3097,9 @@ interrupted_inlined_syscall(dcontext_t *dcontext, fragment_t *f, ASSERT(SYSENTER_LENGTH == SYSCALL_LENGTH); syslen = SYSCALL_LENGTH; }, { - if (FRAG_IS_THUMB(f->flags)) - syslen = SVC_THUMB_LENGTH; - else - syslen = SVC_ARM_LENGTH; + syslen = IF_ARM_ELSE((FRAG_IS_THUMB(f->flags) ? + SVC_THUMB_LENGTH : SVC_ARM_LENGTH), + SVC_LENGTH); }); nxt_pc = decode(dcontext, pc - syslen, &instr); if (nxt_pc != NULL && instr_valid(&instr) && @@ -3209,7 +3227,7 @@ adjust_syscall_for_restart(dcontext_t *dcontext, thread_sig_info_t *info, int si } dr_set_isa_mode(dcontext, isa_mode, &old_mode); sys_inst_len = (isa_mode == DR_ISA_ARM_THUMB) ? SVC_THUMB_LENGTH : SVC_ARM_LENGTH; -#elif defined(X86) +#else ASSERT(INT_LENGTH == SYSCALL_LENGTH && INT_LENGTH == SYSENTER_LENGTH); sys_inst_len = INT_LENGTH; @@ -4446,6 +4464,8 @@ execute_handler_from_cache(dcontext_t *dcontext, int sig, sigframe_rt_t *our_fra sc->SC_XDI = sig; sc->SC_XSI = (reg_t) &((sigframe_rt_t *)xsp)->info; sc->SC_XDX = (reg_t) &((sigframe_rt_t *)xsp)->uc; +#elif defined(AARCH64) + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ #elif defined(ARM) sc->SC_R0 = sig; if (IS_RT_FOR_APP(info, sig)) { @@ -4657,7 +4677,7 @@ execute_handler_from_dispatch(dcontext_t *dcontext, int sig) mcontext->xdi = sig; mcontext->xsi = (reg_t) &((sigframe_rt_t *)xsp)->info; mcontext->xdx = (reg_t) &((sigframe_rt_t *)xsp)->uc; -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) mcontext->r0 = sig; if (IS_RT_FOR_APP(info, sig)) { mcontext->r1 = (reg_t) &((sigframe_rt_t *)xsp)->info; @@ -5133,11 +5153,15 @@ handle_sigreturn(dcontext_t *dcontext, void *ucxt_param, int style) ASSERT(sig > 0 && sig <= MAX_SIGNUM && !IS_RT_FOR_APP(info, sig)); sc = get_sigcontext_from_app_frame(info, sig, (void *) frame); /* discard blocked signals, re-set from prev mask stored in frame */ +#ifdef AARCH64 + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ +#else prevset.sig[0] = frame->IF_X86_ELSE(sc.oldmask, uc.uc_mcontext.oldmask); if (_NSIG_WORDS > 1) { memcpy(&prevset.sig[1], &frame->IF_X86_ELSE(extramask, uc.sigset_ex), sizeof(prevset.sig[1])); } +#endif set_blocked(dcontext, &prevset, true/*absolute*/); } #endif @@ -5218,11 +5242,16 @@ handle_sigreturn(dcontext_t *dcontext, void *ucxt_param, int style) * look like whatever would happen to the app... */ ASSERT((app_pc)sc->SC_XIP != next_pc); -# ifdef ARM +# if defined(ARM) || defined(AARCH64) +# ifdef AARCH64 + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */ +# endif set_stolen_reg_val(get_mcontext(dcontext), get_sigcxt_stolen_reg(sc)); set_sigcxt_stolen_reg(sc, (reg_t) *get_dr_tls_base_addr()); +# ifndef AARCH64 /* We're going to our fcache_return gencode which uses DEFAULT_ISA_MODE */ set_pc_mode_in_cpsr(sc, DEFAULT_ISA_MODE); +# endif # endif #endif @@ -5998,10 +6027,10 @@ handle_suspend_signal(dcontext_t *dcontext, kernel_ucontext_t *ucxt) asm("movl $1,(%"ASM_XAX")"); asm("jmp dynamorio_futex_wake_and_exit"); # endif -#elif defined(ARM) - asm("ldr %%"ASM_R0", %0" : : "m"(term)); - asm("mov %"ASM_R1", #1"); - asm("str %"ASM_R1",[%"ASM_R0"]"); +#elif defined(ARM) || defined(AARCH64) + asm("ldr "ASM_R0", %0" : : "m"(term)); + asm("mov "ASM_R1", #1"); + asm("str "ASM_R1",["ASM_R0"]"); asm("b dynamorio_futex_wake_and_exit"); #endif } else { diff --git a/core/unix/signal_linux.c b/core/unix/signal_linux.c index 0e8a49fca35..24379e93462 100644 --- a/core/unix/signal_linux.c +++ b/core/unix/signal_linux.c @@ -227,7 +227,7 @@ sysnum_is_not_restartable(int sysnum) IF_X86_64(sysnum == SYS_epoll_wait_old ||) sysnum == SYS_epoll_wait || sysnum == SYS_epoll_pwait || sysnum == SYS_poll || sysnum == SYS_ppoll || - IF_NOT_ARM(sysnum == SYS_select ||) + IF_X86(sysnum == SYS_select ||) sysnum == SYS_pselect6 || #ifdef X64 sysnum == SYS_msgrcv || sysnum == SYS_msgsnd || sysnum == SYS_semop || diff --git a/core/unix/signal_private.h b/core/unix/signal_private.h index 51af78fd977..c506fad5c1b 100644 --- a/core/unix/signal_private.h +++ b/core/unix/signal_private.h @@ -133,18 +133,33 @@ struct _old_sigaction_t { * this is adapted from asm/ucontext.h: */ typedef struct { +# if defined(X86) unsigned long uc_flags; struct ucontext *uc_link; stack_t uc_stack; sigcontext_t uc_mcontext; kernel_sigset_t uc_sigmask; /* mask last for extensibility */ -# ifdef ARM +# elif defined(AARCH64) + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + kernel_sigset_t uc_sigmask; + unsigned char sigset_ex[1024 / 8 - sizeof(kernel_sigset_t)]; + sigcontext_t uc_mcontext; /* last for future expansion */ +# elif defined(ARM) + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + sigcontext_t uc_mcontext; + kernel_sigset_t uc_sigmask; int sigset_ex[32 - (sizeof(kernel_sigset_t)/sizeof(int))]; /* coprocessor state is here */ union { unsigned long uc_regspace[128] __attribute__((__aligned__(8))); struct vfp_sigframe uc_vfp; } coproc; +# else +# error NYI # endif } kernel_ucontext_t; @@ -228,7 +243,7 @@ typedef struct rt_sigframe { char retcode[RETCODE_SIZE]; # endif /* In 2.6.28+, fpstate/xstate goes here */ -# elif defined(ARM) +# elif defined(ARM) || defined(AARCH64) siginfo_t info; kernel_ucontext_t uc; char retcode[RETCODE_SIZE]; diff --git a/core/unix/tls.h b/core/unix/tls.h index 2887461a201..07531082637 100644 --- a/core/unix/tls.h +++ b/core/unix/tls.h @@ -106,17 +106,13 @@ typedef struct _our_modify_ldt_t { ASSERT(sizeof(val) == sizeof(reg_t)); \ asm volatile("mov %0,%%"ASM_XAX"; mov %%"ASM_XAX", %"LIB_ASM_SEG";" \ : : "m" ((val)) : ASM_XAX); -#elif defined(ARM) -# ifdef X64 -# error NYI on AArch64 -# else -# define WRITE_DR_SEG(val) ASSERT_NOT_REACHED() -# define WRITE_LIB_SEG(val) ASSERT_NOT_REACHED() -# endif /* 64/32-bit */ +#elif defined(ARM) || defined(AARCH64) +# define WRITE_DR_SEG(val) ASSERT_NOT_REACHED() +# define WRITE_LIB_SEG(val) ASSERT_NOT_REACHED() # define TLS_SLOT_VAL_EXITED ((byte *)PTR_UINT_MINUS_1) #endif /* X86/ARM */ -static inline uint +static inline ptr_uint_t read_thread_register(reg_id_t reg) { uint sel; @@ -135,7 +131,7 @@ read_thread_register(reg_id_t reg) * is_segment_register_initialized(). */ sel &= 0xffff; -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) if (reg == DR_REG_TPIDRURO) { IF_X64_ELSE({ asm volatile("mrs %0, tpidrro_el0" : "=r"(sel)); @@ -236,7 +232,7 @@ tls_thread_init(os_local_state_t *os_tls, byte *segment); void tls_thread_free(tls_type_t tls_type, int index); -#ifdef ARM +#if defined(ARM) || defined(AARCH64) byte ** get_dr_tls_base_addr(void); #endif diff --git a/ext/drreg/drreg.c b/ext/drreg/drreg.c index 001bdda2424..900fba3a8d1 100644 --- a/ext/drreg/drreg.c +++ b/ext/drreg/drreg.c @@ -1209,7 +1209,7 @@ drreg_event_restore_state(void *drcontext, bool restore_memory, if (spilled_to_aflags < MAX_SPILLS) { reg_t val = get_spilled_value(drcontext, spilled_to_aflags); reg_t newval = info->mcontext->xflags; -#ifdef ARM +#if defined(ARM) || defined(AARCH64) newval &= ~(EFLAGS_ARITH); newval |= val; #elif defined(X86) diff --git a/ext/drutil/drutil.c b/ext/drutil/drutil.c index ca64a1a9eb6..6287091f868 100644 --- a/ext/drutil/drutil.c +++ b/ext/drutil/drutil.c @@ -95,7 +95,7 @@ drutil_exit(void) static bool drutil_insert_get_mem_addr_x86(void *drcontext, instrlist_t *bb, instr_t *where, opnd_t memref, reg_id_t dst, reg_id_t scratch); -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) static bool drutil_insert_get_mem_addr_arm(void *drcontext, instrlist_t *bb, instr_t *where, opnd_t memref, reg_id_t dst, reg_id_t scratch); @@ -119,7 +119,7 @@ drutil_insert_get_mem_addr(void *drcontext, instrlist_t *bb, instr_t *where, { #ifdef X86 return drutil_insert_get_mem_addr_x86(drcontext, bb, where, memref, dst, scratch); -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) return drutil_insert_get_mem_addr_arm(drcontext, bb, where, memref, dst, scratch); #endif } @@ -221,7 +221,7 @@ drutil_insert_get_mem_addr_x86(void *drcontext, instrlist_t *bb, instr_t *where, } return true; } -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) static bool instr_has_opnd(instr_t *instr, opnd_t opnd) { @@ -277,7 +277,7 @@ drutil_insert_get_mem_addr_arm(void *drcontext, instrlist_t *bb, instr_t *where, { if (!opnd_is_base_disp(memref)) return false; - if (opnd_get_base(memref) == DR_REG_PC) { + if (IF_ARM_ELSE(opnd_get_base(memref) == DR_REG_PC, false)) { app_pc target; instr_t *first, *second; /* We need the app instr for getting the rel_addr_target. diff --git a/ext/drwrap/drwrap.c b/ext/drwrap/drwrap.c index bb203028abe..fd51d80d9f8 100644 --- a/ext/drwrap/drwrap.c +++ b/ext/drwrap/drwrap.c @@ -559,7 +559,7 @@ drwrap_get_mcontext_internal(drwrap_context_t *wrapcxt, dr_mcontext_flags_t flag * trap flag or other flags so instead of zeroing we copy cur flags * (xref i#806). */ -#ifdef ARM +#if defined(ARM) || defined(AARCH64) wrapcxt->mc->xflags = 0; /*0 is fine for ARM */ #else # ifdef WINDOWS @@ -625,7 +625,7 @@ drwrap_arg_addr(drwrap_context_t *wrapcxt, int arg) drwrap_get_mcontext_internal(wrapcxt, DR_MC_INTEGER); /* already have xsp */ switch (wrapcxt->callconv) { -#ifdef ARM /* registers are platform-exclusive */ +#if defined(ARM) || defined(AARCH64) /* registers are platform-exclusive */ case DRWRAP_CALLCONV_ARM: switch (arg) { case 0: return &wrapcxt->mc->r0; @@ -1190,7 +1190,7 @@ drwrap_replace_native(app_pc original, app_pc replacement, bool at_entry, replace_native_t *rn; if (stack_adjust > max_stack_adjust || !ALIGNED(stack_adjust, sizeof(void*)) - IF_ARM(|| stack_adjust != 0)) + IF_NOT_X86(|| stack_adjust != 0)) return false; if (replacement == NULL) rn = NULL; @@ -1270,7 +1270,7 @@ drwrap_replace_native_push_retaddr(void *drcontext, instrlist_t *bb, app_pc pc, ptr_int_t pushval, opnd_size_t stacksz _IF_X86_64(bool x86)) { -#ifdef ARM +#if defined(ARM) || defined(AARCH64) instr_t *mov1, *mov2; instrlist_insert_mov_immed_ptrsz(drcontext, pushval, opnd_create_reg(DR_REG_LR), bb, NULL, &mov1, &mov2); @@ -1752,7 +1752,7 @@ drwrap_ensure_postcall(void *drcontext, wrap_entry_t *wrap, /* called via clean call at the top of callee */ static void -drwrap_in_callee(void *arg1, reg_t xsp _IF_ARM(reg_t lr)) +drwrap_in_callee(void *arg1, reg_t xsp _IF_NOT_X86(reg_t lr)) { void *drcontext = dr_get_current_drcontext(); per_thread_t *pt = (per_thread_t *) drmgr_get_tls_field(drcontext, tls_idx); @@ -1787,7 +1787,7 @@ drwrap_in_callee(void *arg1, reg_t xsp _IF_ARM(reg_t lr)) NOTIFY(2, "%s: level %d function "PFX"\n", __FUNCTION__, pt->wrap_level+1, pc); drwrap_context_init(drcontext, &wrapcxt, pc, &mc, DRWRAP_WHERE_PRE_FUNC, - IF_ARM_ELSE((app_pc)lr, get_retaddr_at_entry(xsp))); + IF_X86_ELSE(get_retaddr_at_entry(xsp), (app_pc)lr)); drwrap_in_callee_check_unwind(drcontext, pt, &mc); @@ -2172,7 +2172,7 @@ drwrap_event_bb_insert(void *drcontext, void *tag, instrlist_t *bb, instr_t *ins OPND_CREATE_INTPTR((ptr_int_t)arg1), /* pass in xsp to avoid dr_get_mcontext */ opnd_create_reg(DR_REG_XSP) - _IF_ARM(opnd_create_reg(DR_REG_LR))); + _IF_NOT_X86(opnd_create_reg(DR_REG_LR))); } dr_recurlock_unlock(wrap_lock); diff --git a/ext/drwrap/drwrap.h b/ext/drwrap/drwrap.h index b4902e11059..5e5c062ac34 100644 --- a/ext/drwrap/drwrap.h +++ b/ext/drwrap/drwrap.h @@ -370,9 +370,12 @@ typedef enum { DRWRAP_CALLCONV_FASTCALL = 0x05000000, /** The Microsoft IA-32 thiscall calling convention. */ DRWRAP_CALLCONV_THISCALL = 0x06000000, + /** The ARM AArch64 calling convention. */ + DRWRAP_CALLCONV_AARCH64 = 0x07000000, #ifdef X64 -# ifdef ARM -# error NYI ARM X64 +# ifdef AARCH64 + /** Default calling convention for the platform. */ + DRWRAP_CALLCONV_DEFAULT = DRWRAP_CALLCONV_AARCH64, # elif defined(UNIX) /* x64 */ /** Default calling convention for the platform. */ DRWRAP_CALLCONV_DEFAULT = DRWRAP_CALLCONV_AMD64, diff --git a/ext/drx/drx.c b/ext/drx/drx.c index 292eeaba5cb..d157c617189 100644 --- a/ext/drx/drx.c +++ b/ext/drx/drx.c @@ -179,7 +179,7 @@ drx_aflags_are_dead(instr_t *where) * INSTRUMENTATION */ -#ifdef ARM +#if defined(ARM) || defined(AARCH64) /* XXX i#1603: add liveness analysis and pick dead regs */ # define SCRATCH_REG0 DR_REG_R0 # define SCRATCH_REG1 DR_REG_R1 @@ -236,7 +236,7 @@ drx_save_arith_flags(void *drcontext, instrlist_t *ilist, instr_t *where, instr = INSTR_CREATE_setcc(drcontext, OP_seto, opnd_create_reg(DR_REG_AL)); MINSERT(ilist, where, instr); } -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) ASSERT(reg >= DR_REG_START_GPR && reg <= DR_REG_STOP_GPR, "reg must be a GPR"); if (save_reg) { ASSERT(slot >= SPILL_SLOT_1 && slot <= SPILL_SLOT_MAX, @@ -295,7 +295,7 @@ drx_restore_arith_flags(void *drcontext, instrlist_t *ilist, instr_t *where, dr_restore_reg(drcontext, ilist, where, DR_REG_XAX, slot); } } -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) ASSERT(reg >= DR_REG_START_GPR && reg <= DR_REG_STOP_GPR, "reg must be a GPR"); instr = INSTR_CREATE_mrs(drcontext, opnd_create_reg(reg), opnd_create_reg(DR_REG_CPSR)); @@ -383,14 +383,14 @@ counter_crosses_cache_line(byte *addr, size_t size) DR_EXPORT bool drx_insert_counter_update(void *drcontext, instrlist_t *ilist, instr_t *where, - dr_spill_slot_t slot, IF_ARM_(dr_spill_slot_t slot2) + dr_spill_slot_t slot, IF_NOT_X86_(dr_spill_slot_t slot2) void *addr, int value, uint flags) { instr_t *instr; bool use_drreg = false; #ifdef X86 bool save_aflags = true; -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) bool save_regs = true; reg_id_t reg1, reg2; #endif @@ -477,7 +477,7 @@ drx_insert_counter_update(void *drcontext, instrlist_t *ilist, instr_t *where, slot, DR_REG_NULL); } } -#elif defined(ARM) +#elif defined(ARM) || defined(AARCH64) /* FIXME i#1551: implement 64-bit counter support */ ASSERT(!is_64, "DRX_COUNTER_64BIT is not implemented"); diff --git a/ext/drx/drx.h b/ext/drx/drx.h index d995b775589..3fd7b956b47 100644 --- a/ext/drx/drx.h +++ b/ext/drx/drx.h @@ -159,7 +159,7 @@ DR_EXPORT */ bool drx_insert_counter_update(void *drcontext, instrlist_t *ilist, instr_t *where, - dr_spill_slot_t slot, IF_ARM_(dr_spill_slot_t slot2) + dr_spill_slot_t slot, IF_NOT_X86_(dr_spill_slot_t slot2) void *addr, int value, uint flags); /***************************************************************************