diff --git a/core/arch/arch.c b/core/arch/arch.c index 0c29eb58b89..88e2604d394 100644 --- a/core/arch/arch.c +++ b/core/arch/arch.c @@ -426,8 +426,9 @@ 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 AARCHXX - /* ARM has no thread-private gencode, so our clone syscall is shared */ +# if defined(AARCHXX) || defined(RISCV64) + /* ARM/AArch64/RISC-V 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, true /*shared*/, &gencode->do_clone_syscall_offs); @@ -726,7 +727,10 @@ d_r_arch_init(void) #ifdef AARCHXX 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) + ASSERT(dr_reg_stolen >= DR_REG_STOLEN_MIN && dr_reg_stolen <= DR_REG_STOLEN_MAX); +#elif defined(RISCV64) + dr_reg_stolen = DR_REG_X0 + DYNAMO_OPTION(steal_reg); + ASSERT(dr_reg_stolen >= DR_REG_STOLEN_MIN && dr_reg_stolen <= DR_REG_STOLEN_MAX); #endif /* Ensure we have no unexpected padding inside structs that include @@ -1206,7 +1210,7 @@ arch_thread_init(dcontext_t *dcontext) return; #endif -#ifdef AARCHXX +#if defined(AARCHXX) || defined(RISCV64) /* 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()); @@ -3105,15 +3109,12 @@ hook_vsyscall(dcontext_t *dcontext, bool method_changing) instr_free(dcontext, &instr); return res; # undef CHECK -# elif defined(AARCHXX) - /* No vsyscall support needed for our ARM targets -- still called on +# elif defined(AARCHXX) || defined(RISCV64) + /* No vsyscall support needed for our ARM/AArch64/RISC-V targets -- still called on * os_process_under_dynamorio(). */ ASSERT(!method_changing); return false; -# elif defined(RISCV64) - ASSERT_NOT_IMPLEMENTED(false); - return false; # endif /* X86/ARM/RISCV64 */ } @@ -3152,12 +3153,9 @@ unhook_vsyscall(void) ASSERT(res); } return true; -# elif defined(AARCHXX) +# elif defined(AARCHXX) || defined(RISCV64) ASSERT_NOT_IMPLEMENTED(get_syscall_method() != SYSCALL_METHOD_SYSENTER); return false; -# elif defined(RISCV64) - ASSERT_NOT_IMPLEMENTED(false); - return false; # endif /* X86/ARM/RISCV64 */ } #endif /* LINUX */ @@ -3856,7 +3854,7 @@ dump_mcontext(priv_mcontext_t *context, file_t f, bool dump_xml) #endif } -#ifdef AARCHXX +#if defined(AARCHXX) || defined(RISCV64) reg_t get_stolen_reg_val(priv_mcontext_t *mc) { diff --git a/core/arch/arch.h b/core/arch/arch.h index 9d8e2d3e55f..eb219675c5f 100644 --- a/core/arch/arch.h +++ b/core/arch/arch.h @@ -600,6 +600,8 @@ mangle_rel_addr(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr, instr_t * mangle_special_registers(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr, instr_t *next_instr); +#endif +#if defined(AARCHXX) || defined(RISCV64) instr_t * mangle_exclusive_monitor_op(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr, instr_t *next_instr); @@ -627,7 +629,7 @@ mangle_insert_clone_code(dcontext_t *dcontext, instrlist_t *ilist, #elif defined(ARM) # define ABI_STACK_ALIGNMENT 8 #elif defined(RISCV64) -# define ABI_STACK_ALIGNMENT 8 +# define ABI_STACK_ALIGNMENT 16 #endif /* Returns the number of bytes the stack pointer has to be aligned to. */ diff --git a/core/arch/arch_exports.h b/core/arch/arch_exports.h index af728182e98..d5d6f44165b 100644 --- a/core/arch/arch_exports.h +++ b/core/arch/arch_exports.h @@ -450,7 +450,7 @@ void dr_mcontext_init(dr_mcontext_t *mc); void dump_mcontext(priv_mcontext_t *context, file_t f, bool dump_xml); -#ifdef AARCHXX +#if defined(AARCHXX) || defined(RISCV64) reg_t get_stolen_reg_val(priv_mcontext_t *context); void diff --git a/core/arch/emit_utils_shared.c b/core/arch/emit_utils_shared.c index 525fadf67aa..1ddd1dd148b 100644 --- a/core/arch/emit_utils_shared.c +++ b/core/arch/emit_utils_shared.c @@ -3262,6 +3262,8 @@ append_ibl_found(dcontext_t *dcontext, instrlist_t *ilist, ibl_code_t *ibl_code, ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569: NYI on AArch64 */ #elif defined(ARM) ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1551: NYI on ARM */ +#elif defined(RISCV64) + ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#3544: NYI on RISCV64 */ #endif } else { APP(ilist, SAVE_TO_TLS(dcontext, SCRATCH_REG2, INDIRECT_STUB_SPILL_SLOT)); @@ -5554,11 +5556,13 @@ emit_special_ibl_xfer(dcontext_t *dcontext, byte *pc, generated_code_t *code, ui instrlist_t ilist; patch_list_t patch; instr_t *in; - /* For AArch64 the linkstub has to be in X0 and the app's X0 has to be - * spilled in TLS_REG0_SLOT before calling the ibl routine. + /* For AArch64/RISCV64 the linkstub has to be in SCRATCH_REG0 and the app's + * SCRATCH_REG0 has to be spilled in TLS_REG0_SLOT before calling the ibl routine. */ - reg_id_t stub_reg = IF_AARCH64_ELSE(SCRATCH_REG0, SCRATCH_REG1); - ushort stub_slot = IF_AARCH64_ELSE(TLS_REG0_SLOT, TLS_REG1_SLOT); + reg_id_t stub_reg = + IF_AARCH64_ELSE(SCRATCH_REG0, IF_RISCV64_ELSE(SCRATCH_REG0, SCRATCH_REG1)); + ushort stub_slot = + IF_AARCH64_ELSE(TLS_REG0_SLOT, IF_RISCV64_ELSE(TLS_REG0_SLOT, TLS_REG1_SLOT)); IF_X86(size_t len;) byte *ibl_linked_tgt = special_ibl_xfer_tgt(dcontext, code, IBL_LINKED, ibl_type); byte *ibl_unlinked_tgt = special_ibl_xfer_tgt(dcontext, code, IBL_UNLINKED, ibl_type); @@ -5628,12 +5632,6 @@ emit_special_ibl_xfer(dcontext_t *dcontext, byte *pc, generated_code_t *code, ui opnd_create_reg(DR_REG_XCX))); insert_shared_restore_dcontext_reg(dcontext, &ilist, NULL); APP(&ilist, XINST_CREATE_jump(dcontext, opnd_create_pc(ibl_unlinked_tgt))); -# elif defined(RISCV64) - /* FIXME i#3544: Not implemented */ - ASSERT_NOT_IMPLEMENTED(false); - /* Marking as unused to silence -Wunused-variable. */ - (void)ibl_unlinked_tgt; - (void)ibl_linked_tgt; # elif defined(AARCHXX) /* Reuse SCRATCH_REG5 which contains dcontext currently. */ APP(&ilist, @@ -5658,7 +5656,21 @@ emit_special_ibl_xfer(dcontext_t *dcontext, byte *pc, generated_code_t *code, ui dcontext, opnd_create_reg(DR_REG_PC), OPND_TLS_FIELD(get_ibl_entry_tls_offs(dcontext, ibl_unlinked_tgt)))); # endif /* AARCH64/ARM */ -# endif /* X86/AARCHXX */ +# elif defined(RISCV64) + /* Reuse SCRATCH_REG5 which contains dcontext currently. */ + APP(&ilist, + INSTR_CREATE_lb(dcontext, opnd_create_reg(SCRATCH_REG5), + OPND_DC_FIELD(false, dcontext, OPSZ_1, SIGPENDING_OFFSET))); + APP(&ilist, + INSTR_CREATE_beq(dcontext, opnd_create_instr(skip_unlinked_tgt_jump), + opnd_create_reg(SCRATCH_REG5), opnd_create_reg(DR_REG_X0))); + insert_shared_restore_dcontext_reg(dcontext, &ilist, NULL); + APP(&ilist, + INSTR_CREATE_ld( + dcontext, opnd_create_reg(SCRATCH_REG1), + OPND_TLS_FIELD(get_ibl_entry_tls_offs(dcontext, ibl_unlinked_tgt)))); + APP(&ilist, XINST_CREATE_jump_reg(dcontext, opnd_create_reg(SCRATCH_REG1))); +# endif /* X86/AARCHXX/RISCV64 */ APP(&ilist, skip_unlinked_tgt_jump); # ifdef X86 APP(&ilist, @@ -5716,10 +5728,22 @@ emit_special_ibl_xfer(dcontext_t *dcontext, byte *pc, generated_code_t *code, ui INSTR_CREATE_ldr( dcontext, opnd_create_reg(DR_REG_PC), OPND_TLS_FIELD(get_ibl_entry_tls_offs(dcontext, ibl_linked_tgt)))); +#elif defined(RISCV64) + /* Unlike X86 and ARM which use 1 instruction for an indirect jump, + * RISCV64, same as Aarch64, requires 2 instructions: LD+JR. This requires adjusting + * special_ibl_unlink_offs to point to the LD when relinking by + * relink_special_ibl_xfer(). See adjustment below, to offs_instr passed to + * add_patch_marker(). + */ + APP(&ilist, + INSTR_CREATE_ld( + dcontext, opnd_create_reg(SCRATCH_REG1), + OPND_TLS_FIELD(get_ibl_entry_tls_offs(dcontext, ibl_linked_tgt)))); + APP(&ilist, XINST_CREATE_jump_reg(dcontext, opnd_create_reg(SCRATCH_REG1))); #endif instr_t *offs_instr = instrlist_last(&ilist); -#if defined(AARCH64) +#if defined(AARCH64) || defined(RISCV64) offs_instr = instr_get_prev(offs_instr); #endif add_patch_marker(&patch, offs_instr, PATCH_UINT_SIZED /* pc relative */, @@ -5814,6 +5838,10 @@ emit_clean_call_save(dcontext_t *dcontext, byte *pc, generated_code_t *code) /* save all registers */ insert_push_all_registers(dcontext, NULL, &ilist, NULL, (uint)PAGE_SIZE, OPND_CREATE_INT32(0), REG_NULL, true); +#elif defined(RISCV64) + /* save all registers */ + insert_push_all_registers(dcontext, NULL, &ilist, NULL, (uint)PAGE_SIZE, + OPND_CREATE_INT32(0), REG_NULL); #endif #ifdef WINDOWS @@ -5852,6 +5880,8 @@ emit_clean_call_save(dcontext_t *dcontext, byte *pc, generated_code_t *code) OPND_CREATE_INT16(get_clean_call_temp_stack_size()))); #elif defined(AARCH64) APP(&ilist, INSTR_CREATE_br(dcontext, opnd_create_reg(DR_REG_X30))); +#elif defined(RISCV64) + APP(&ilist, XINST_CREATE_jump_reg(dcontext, opnd_create_reg(DR_REG_RA))); #else /* FIXME i#1621: NYI on AArch32 */ ASSERT_NOT_IMPLEMENTED(false); @@ -5915,6 +5945,10 @@ emit_clean_call_restore(dcontext_t *dcontext, byte *pc, generated_code_t *code) insert_pop_all_registers(dcontext, NULL, &ilist, NULL, (uint)PAGE_SIZE, true); APP(&ilist, INSTR_CREATE_br(dcontext, opnd_create_reg(DR_REG_X30))); +#elif defined(RISCV64) + insert_pop_all_registers(dcontext, NULL, &ilist, NULL, (uint)PAGE_SIZE); + + APP(&ilist, XINST_CREATE_jump_reg(dcontext, opnd_create_reg(DR_REG_RA))); #else /* FIXME i#1621: NYI on AArch32 */ ASSERT_NOT_IMPLEMENTED(false); diff --git a/core/arch/interp.c b/core/arch/interp.c index 825c07dd4e1..350687c8d13 100644 --- a/core/arch/interp.c +++ b/core/arch/interp.c @@ -5467,6 +5467,7 @@ recreate_fragment_ilist(dcontext_t *dcontext, byte *pc, /* XXX i#5062 In the future this call should be placed inside mangle_trace() */ IF_AARCH64(fixup_indirect_trace_exit(dcontext, ilist)); + IF_RISCV64(ASSERT_NOT_IMPLEMENTED(false)); /* PR 214962: re-apply client changes, this time storing translation * info for modified instrs @@ -6196,6 +6197,7 @@ mangle_indirect_branch_in_trace(dcontext_t *dcontext, instrlist_t *trace, } } # endif +/* end of X86 */ #elif defined(AARCH64) instr_t *instr; reg_id_t jump_target_reg; @@ -6277,11 +6279,11 @@ mangle_indirect_branch_in_trace(dcontext_t *dcontext, instrlist_t *trace, instrlist_remove(trace, targeter); instr_destroy(dcontext, targeter); added_size -= AARCH64_INSTR_SIZE; - -#elif defined(ARM) - /* FIXME i#1551: NYI on ARM */ +/* end of AARCH64 */ +#else + /* FIXME i#1551 i#3544: NYI on ARM/RISCV64 */ ASSERT_NOT_IMPLEMENTED(false); -#endif /* X86/ARM */ +#endif /* X86/ARM/RISCV64 */ return added_size; } diff --git a/core/arch/mangle_shared.c b/core/arch/mangle_shared.c index 4615edeedf6..e76d02b801e 100644 --- a/core/arch/mangle_shared.c +++ b/core/arch/mangle_shared.c @@ -898,7 +898,10 @@ mangle_rseq_write_exit_reason(dcontext_t *dcontext, instrlist_t *ilist, insert_mov_immed_ptrsz(dcontext, EXIT_REASON_RSEQ_ABORT, opnd_create_reg(scratch2), ilist, insert_at, NULL, NULL); # endif +# ifdef RISCV64 /* FIXME i#3544: Not implemented */ + ASSERT_NOT_IMPLEMENTED(false); +# endif PRE(ilist, insert_at, XINST_CREATE_store_2bytes( dcontext, diff --git a/core/arch/x86_code.c b/core/arch/x86_code.c index b754693fab6..e70edeadd18 100644 --- a/core/arch/x86_code.c +++ b/core/arch/x86_code.c @@ -294,13 +294,11 @@ new_thread_setup(priv_mcontext_t *mc) mc->IF_X86_ELSE(xax, IF_RISCV64_ELSE(a0, r0)) = 0; /* clear pc */ mc->pc = 0; -# ifdef AARCHXX +# if defined(AARCHXX) || defined(RISCV64) /* set the stolen register's app value */ set_stolen_reg_val(mc, get_clone_record_stolen_value(crec)); /* set the thread register if necessary */ set_thread_register_from_clone_record(crec); -# elif defined(RISCV64) - ASSERT_NOT_IMPLEMENTED(false); # endif DEBUG_DECLARE(int rc =) diff --git a/core/dispatch.c b/core/dispatch.c index 37e6bb531f9..067482bb0ab 100644 --- a/core/dispatch.c +++ b/core/dispatch.c @@ -494,7 +494,7 @@ dispatch_enter_fcache(dcontext_t *dcontext, fragment_t *targetf) (fcache_enter_func_t) /* DEFAULT_ISA_MODE as we want the ISA mode of our gencode */ convert_data_to_function(PC_AS_JMP_TGT(DEFAULT_ISA_MODE, (app_pc)fcache_enter)), -#ifdef AARCH64 +#if defined(AARCH64) || defined(RISCV64) /* Entry to fcache requires indirect branch. */ PC_AS_JMP_TGT(FRAG_ISA_MODE(targetf->flags), FCACHE_PREFIX_ENTRY_PC(targetf)) #else diff --git a/core/fragment.h b/core/fragment.h index 85b3285783c..674c64e86d9 100644 --- a/core/fragment.h +++ b/core/fragment.h @@ -191,8 +191,10 @@ #define FRAG_ISA_MODE(flags) \ IF_X86_ELSE( \ IF_X64_ELSE((FRAG_IS_32(flags)) ? DR_ISA_IA32 : DR_ISA_AMD64, DR_ISA_IA32), \ - IF_X64_ELSE(DR_ISA_ARM_A64, \ - (TEST(FRAG_THUMB, (flags)) ? DR_ISA_ARM_THUMB : DR_ISA_ARM_A32))) + IF_AARCHXX_ELSE(IF_X64_ELSE(DR_ISA_ARM_A64, \ + (TEST(FRAG_THUMB, (flags)) ? DR_ISA_ARM_THUMB \ + : DR_ISA_ARM_A32)), \ + DR_ISA_RV64IMAFDC)) static inline uint frag_flags_from_isa_mode(dr_isa_mode_t mode) diff --git a/core/ir/disassemble_shared.c b/core/ir/disassemble_shared.c index 19241476ca2..a68390c34ca 100644 --- a/core/ir/disassemble_shared.c +++ b/core/ir/disassemble_shared.c @@ -1508,8 +1508,9 @@ common_disassemble_fragment(dcontext_t *dcontext, fragment_t *f_in, file_t outfi } if (LINKSTUB_DIRECT(l->flags) && DIRECT_EXIT_STUB_DATA_SZ > 0) { ASSERT(DIRECT_EXIT_STUB_DATA_SZ == - sizeof(cache_pc) - IF_AARCH64(+DIRECT_EXIT_STUB_DATA_SLOT_ALIGNMENT_PADDING)); + sizeof(cache_pc) IF_AARCH64_ELSE( + +DIRECT_EXIT_STUB_DATA_SLOT_ALIGNMENT_PADDING, + IF_RISCV64(+DIRECT_EXIT_STUB_DATA_SLOT_ALIGNMENT_PADDING))); if (stub_is_patched(dcontext, f, EXIT_STUB_PC(dcontext, f, l))) { print_file(outfile, " \n", *(cache_pc *)IF_AARCH64_ELSE(ALIGN_FORWARD(next_stop_pc, 8), diff --git a/core/ir/opnd.h b/core/ir/opnd.h index 533f2b2216f..4d90ac18369 100644 --- a/core/ir/opnd.h +++ b/core/ir/opnd.h @@ -332,6 +332,11 @@ extern reg_id_t dr_reg_stolen; # define DR_REG_STOLEN_MAX DR_REG_X31 /* DR's stolen register for TLS access. */ extern reg_id_t dr_reg_stolen; +#elif defined(RISCV64) +/* DR's stolen register for TLS access */ +# define DR_REG_STOLEN_MIN DR_REG_X18 /* DR_REG_SYSNUM + 1 */ +# define DR_REG_STOLEN_MAX DR_REG_X31 +extern reg_id_t dr_reg_stolen; #endif #endif /* _OPND_H_ */ diff --git a/core/ir/opnd_shared.c b/core/ir/opnd_shared.c index 982362e9f66..ee37480456b 100644 --- a/core/ir/opnd_shared.c +++ b/core/ir/opnd_shared.c @@ -1168,7 +1168,7 @@ bool opnd_is_memory_reference(opnd_t opnd) { return (opnd_is_base_disp(opnd) IF_X86_64(|| opnd_is_abs_addr(opnd)) || -#if defined(X64) || defined(ARM) +#if (defined(X64) || defined(ARM)) && !defined(RISCV64) opnd_is_rel_addr(opnd) || #endif opnd_is_mem_instr(opnd)); @@ -2376,11 +2376,8 @@ opnd_compute_address_priv(opnd_t opnd, priv_mcontext_t *mc) default: scaled_index = index_val; } #elif defined(RISCV64) - /* FIXME i#3544: Not implemented */ /* Marking as unused to silence -Wunused-variable. */ - CLIENT_ASSERT(false, "Not implemented"); (void)index; - return NULL; #endif } return opnd_compute_address_helper(opnd, mc, scaled_index); diff --git a/core/ir/riscv64/decode.c b/core/ir/riscv64/decode.c index 0df7b3e1be8..4677e16bda8 100644 --- a/core/ir/riscv64/decode.c +++ b/core/ir/riscv64/decode.c @@ -64,9 +64,8 @@ dr_app_pc_as_load_target(dr_isa_mode_t isa_mode, app_pc pc) byte * decode_eflags_usage(void *drcontext, byte *pc, uint *usage, dr_opnd_query_flags_t flags) { - /* FIXME i#3544: Not implemented */ - ASSERT_NOT_IMPLEMENTED(false); - return NULL; + *usage = 0; /* No eflags on RISC-V. */ + return decode_next_pc(drcontext, pc); } byte * @@ -92,9 +91,8 @@ decode_from_copy(void *drcontext, byte *copy_pc, byte *orig_pc, instr_t *instr) byte * decode_cti(void *drcontext, byte *pc, instr_t *instr) { - /* FIXME i#3544: Not implemented */ - ASSERT_NOT_IMPLEMENTED(false); - return NULL; + dcontext_t *dcontext = (dcontext_t *)drcontext; + return decode(dcontext, pc, instr); } byte * diff --git a/core/monitor.c b/core/monitor.c index 908de250caf..b8a82a5fcf6 100644 --- a/core/monitor.c +++ b/core/monitor.c @@ -1210,6 +1210,7 @@ end_and_emit_trace(dcontext_t *dcontext, fragment_t *cur_f) /* XXX i#5062 In the future this call should be placed inside mangle_trace() */ IF_AARCH64(md->emitted_size += fixup_indirect_trace_exit(dcontext, trace)); + IF_RISCV64(ASSERT_NOT_IMPLEMENTED(false)); if (DYNAMO_OPTION(speculate_last_exit) #ifdef HASHTABLE_STATISTICS diff --git a/core/synch.c b/core/synch.c index f5eef1e5c79..902c01c9ba9 100644 --- a/core/synch.c +++ b/core/synch.c @@ -1801,11 +1801,14 @@ translate_from_synchall_to_dispatch(thread_record_t *tr, thread_synch_state_t sy * But the stolen reg was restored to the application value during * translate_mcontext. */ - IF_AARCHXX({ - /* Preserve the translated value from mc before we clobber it. */ - dcontext->local_state->spill_space.reg_stolen = get_stolen_reg_val(mc); - set_stolen_reg_val(mc, (reg_t)os_get_dr_tls_base(dcontext)); - }); +#ifdef AARCHXX + /* Preserve the translated value from mc before we clobber it. */ + dcontext->local_state->spill_space.reg_stolen = get_stolen_reg_val(mc); + set_stolen_reg_val(mc, (reg_t)os_get_dr_tls_base(dcontext)); +#elif defined(RISCV64) + ASSERT_NOT_IMPLEMENTED(false); +#endif + #ifdef WINDOWS /* i#25: we could have interrupted thread in DR, where has priv fls data * in TEB, and fcache_return blindly copies into app fls: so swap to app diff --git a/core/translate.c b/core/translate.c index 59bf5f0fd6e..d327e0fd751 100644 --- a/core/translate.c +++ b/core/translate.c @@ -1205,7 +1205,7 @@ recreate_selfmod_ilist(dcontext_t *dcontext, fragment_t *f) static void restore_stolen_register(dcontext_t *dcontext, priv_mcontext_t *mcontext) { -#ifdef AARCHXX +#if defined(AARCHXX) || defined(RISCV64) /* dr_reg_stolen is holding DR's TLS on receiving a signal, * so we need put app's reg value into mcontext instead */ diff --git a/core/unix/loader_linux.c b/core/unix/loader_linux.c index 9f5b851521a..f194e6ad00e 100644 --- a/core/unix/loader_linux.c +++ b/core/unix/loader_linux.c @@ -134,7 +134,7 @@ static size_t client_tls_size = 2 * 4096; * good way to guess how big this allocation was. Instead we use this estimate. */ /* On A32, the pthread is put before tcbhead instead tcbhead being part of pthread */ -static size_t tcb_size = IF_X86_ELSE(IF_X64_ELSE(0x900, 0x490), 0x40); +static size_t tcb_size = IF_X64_ELSE(0x900, 0x490); /* thread contol block header type from * - sysdeps/x86_64/nptl/tls.h @@ -220,7 +220,6 @@ typedef struct _dr_pthread_t { */ # define APP_LIBC_TLS_SIZE 0 #elif defined(RISCV64) -/* FIXME i#3544: Not implemented */ # define APP_LIBC_TLS_SIZE 0 #endif @@ -235,8 +234,9 @@ privload_mod_tls_init(privmod_t *mod) { os_privmod_data_t *opd; size_t offset; +# ifndef RISCV64 int first_byte; - +# endif IF_X86(ASSERT(TLS_APP_SELF_OFFSET_ASM == offsetof(tcb_head_t, self))); ASSERT_OWN_RECURSIVE_LOCK(true, &privload_lock); opd = (os_privmod_data_t *)mod->os_privmod_data; @@ -249,6 +249,7 @@ privload_mod_tls_init(privmod_t *mod) tls_info.mods[tls_info.num_mods] = mod; opd->tls_modid = tls_info.num_mods; offset = (opd->tls_modid == 0) ? APP_LIBC_TLS_SIZE : tls_info.offset; +# ifndef RISCV64 /* decide the offset of each module in the TLS segment from * thread pointer. * Because the tls memory is located before thread pointer, we use @@ -260,12 +261,17 @@ privload_mod_tls_init(privmod_t *mod) /* increase offset size by adding current mod's tls size: * 1. increase the tls_block_size with the right alignment * using ALIGN_FORWARD() - * 2. add first_byte to make the first byte with right alighment. + * 2. add first_byte to make the first byte with right alignment. */ offset = first_byte + ALIGN_FORWARD(offset + opd->tls_block_size + first_byte, opd->tls_align); opd->tls_offset = offset; tls_info.offs[tls_info.num_mods] = offset; +# else /* RISCV64 */ + opd->tls_offset = offset; + tls_info.offs[tls_info.num_mods] = offset; + offset = ALIGN_FORWARD(offset + opd->tls_block_size, opd->tls_align); +# endif tls_info.offset = offset; LOG(GLOBAL, LOG_LOADER, 2, "%s for #%d %s: offset %zu\n", __FUNCTION__, opd->tls_modid, mod->name, offset); @@ -282,7 +288,8 @@ privload_copy_tls_block(app_pc priv_tls_base, uint mod_idx) os_privmod_data_t *opd = tls_info.mods[mod_idx]->os_privmod_data; void *dest; /* now copy the tls memory from the image */ - dest = priv_tls_base - tls_info.offs[mod_idx]; + dest = + priv_tls_base + IF_RISCV64_ELSE(tls_info.offs[mod_idx], -tls_info.offs[mod_idx]); LOG(GLOBAL, LOG_LOADER, 2, "%s: copying ELF TLS from " PFX " to " PFX " block %zu image %zu\n", __FUNCTION__, opd->tls_image, dest, opd->tls_block_size, opd->tls_image_size); @@ -331,7 +338,7 @@ privload_tls_init(void *app_tp) dr_tp = heap_mmap(client_tls_alloc_size, MEMPROT_READ | MEMPROT_WRITE, VMM_SPECIAL_MMAP | VMM_PER_THREAD); ASSERT(APP_LIBC_TLS_SIZE + TLS_PRE_TCB_SIZE + tcb_size <= client_tls_alloc_size); -#ifdef AARCHXX +#if defined(AARCHXX) || defined(RISCV64) /* GDB reads some pthread members (e.g., pid, tid), so we must make sure * the size and member locations match to avoid gdb crash. */ @@ -340,24 +347,33 @@ privload_tls_init(void *app_tp) #endif LOG(GLOBAL, LOG_LOADER, 2, "%s: allocated %d at " PFX "\n", __FUNCTION__, client_tls_alloc_size, dr_tp); +#ifdef RISCV64 + dr_tp = dr_tp + TLS_PRE_TCB_SIZE + sizeof(tcb_head_t); + dr_tcb = (tcb_head_t *)(dr_tp - sizeof(tcb_head_t)); +#else dr_tp = dr_tp + client_tls_alloc_size - tcb_size; dr_tcb = (tcb_head_t *)dr_tp; +#endif LOG(GLOBAL, LOG_LOADER, 2, "%s: adjust thread pointer to " PFX "\n", __FUNCTION__, dr_tp); /* We copy the whole tcb to avoid initializing it by ourselves. * and update some fields accordingly. */ if (app_tp != NULL && - !safe_read_ex(app_tp - APP_LIBC_TLS_SIZE - TLS_PRE_TCB_SIZE, - APP_LIBC_TLS_SIZE + TLS_PRE_TCB_SIZE + tcb_size, - dr_tp - APP_LIBC_TLS_SIZE - TLS_PRE_TCB_SIZE, &tls_bytes_read)) { + !safe_read_ex( + app_tp - APP_LIBC_TLS_SIZE - TLS_PRE_TCB_SIZE IF_RISCV64(-sizeof(tcb_head_t)), + APP_LIBC_TLS_SIZE + TLS_PRE_TCB_SIZE + tcb_size, + dr_tp - APP_LIBC_TLS_SIZE - TLS_PRE_TCB_SIZE IF_RISCV64(-sizeof(tcb_head_t)), + &tls_bytes_read)) { 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 AARCHXX +#if defined(AARCHXX) || defined(RISCV64) } else { - dr_pthread_t *dp = (dr_pthread_t *)(dr_tp - APP_LIBC_TLS_SIZE - TLS_PRE_TCB_SIZE); + dr_pthread_t *dp = + (dr_pthread_t *)(dr_tp - APP_LIBC_TLS_SIZE - + TLS_PRE_TCB_SIZE IF_RISCV64(-sizeof(tcb_head_t))); dp->pid = get_process_id(); dp->tid = get_sys_thread_id(); #endif @@ -373,7 +389,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(AARCHXX) +#elif defined(AARCHXX) || defined(RISCV64) dr_tcb->dtv = NULL; dr_tcb->private = NULL; #endif @@ -397,7 +413,11 @@ privload_tls_exit(void *dr_tp) size_t client_tls_alloc_size = ALIGN_FORWARD(client_tls_size, PAGE_SIZE); if (dr_tp == NULL) return; +#ifdef RISCV64 + dr_tp = dr_tp - TLS_PRE_TCB_SIZE - sizeof(tcb_head_t); +#else dr_tp = dr_tp + tcb_size - client_tls_alloc_size; +#endif heap_munmap(dr_tp, client_tls_alloc_size, VMM_SPECIAL_MMAP | VMM_PER_THREAD); } @@ -417,8 +437,15 @@ redirect___tls_get_addr(tls_index_t *ti) LOG(GLOBAL, LOG_LOADER, 4, "__tls_get_addr: module: %d, offset: %d\n", ti->ti_module, ti->ti_offset); ASSERT(ti->ti_module < tls_info.num_mods); +#ifndef RISCV64 return (os_get_priv_tls_base(NULL, TLS_REG_LIB) - tls_info.offs[ti->ti_module] + ti->ti_offset); +#else +# define TLS_DTV_OFFSET 0x800 + return (os_get_priv_tls_base(NULL, TLS_REG_LIB) + tls_info.offs[ti->ti_module] + + ti->ti_offset + TLS_DTV_OFFSET); +# undef TLS_DTV_OFFSET +#endif } void * @@ -444,6 +471,7 @@ redirect____tls_get_addr() #elif defined(RISCV64) /* FIXME i#3544: Check if ti is in a0. */ asm("sd a0, %0" : "=m"((ti)) : : "a0"); + ASSERT_NOT_REACHED(); #endif /* X86/ARM/RISCV64 */ LOG(GLOBAL, LOG_LOADER, 4, "__tls_get_addr: module: %d, offset: %d\n", ti->ti_module, ti->ti_offset); diff --git a/core/unix/os.c b/core/unix/os.c index 2529c4f5666..2e65895a737 100644 --- a/core/unix/os.c +++ b/core/unix/os.c @@ -2011,7 +2011,7 @@ get_os_tls_from_dc(dcontext_t *dcontext) return (os_local_state_t *)(local_state - offsetof(os_local_state_t, state)); } -#ifdef AARCHXX +#if defined(AARCHXX) || defined(RISCV64) bool os_set_app_tls_base(dcontext_t *dcontext, reg_id_t reg, void *base) { @@ -4125,7 +4125,7 @@ dr_create_client_thread(void (*func)(void *param), void *arg) * to the app's. */ os_clone_pre(dcontext); -# ifdef AARCHXX +# if defined(AARCHXX) || defined(RISCV64) /* We need to invalidate DR's TLS to avoid get_thread_private_dcontext() finding one * and hitting asserts in dynamo_thread_init lock calls -- yet we don't want to for * app threads, so we're doing this here and not in os_clone_pre(). @@ -4137,7 +4137,7 @@ dr_create_client_thread(void (*func)(void *param), void *arg) thread_id_t newpid = dynamorio_clone(flags, xsp, NULL, NULL, NULL, client_thread_run); /* i#3526 switch DR's tls back to the original one before cloning. */ os_clone_post(dcontext); -# ifdef AARCHXX +# if defined(AARCHXX) || defined(RISCV64) write_thread_register(tls); # endif /* i#501 the app's tls was switched in os_clone_pre. */ @@ -6804,7 +6804,7 @@ os_switch_seg_to_context(dcontext_t *dcontext, reg_id_t seg, bool to_app) base = os_get_priv_tls_base(dcontext, seg); } return os_switch_seg_to_base(dcontext, os_tls, seg, to_app, base); -#elif defined(AARCHXX) +#elif defined(AARCHXX) || defined(RISCV64) bool res = false; os_thread_data_t *ostd = (os_thread_data_t *)dcontext->os_field; ASSERT(INTERNAL_OPTION(private_loader)); @@ -6890,12 +6890,6 @@ 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, d_r_get_thread_id()); return res; -#elif defined(RISCV64) - /* FIXME i#3544: Not implemented */ - ASSERT_NOT_IMPLEMENTED(false); - /* Marking as unused to silence -Wunused-variable. */ - (void)os_tls; - return false; #endif /* X86/AARCHXX/RISCV64 */ } diff --git a/core/unix/os_exports.h b/core/unix/os_exports.h index c234c265ccb..526c8605fda 100644 --- a/core/unix/os_exports.h +++ b/core/unix/os_exports.h @@ -531,11 +531,11 @@ get_clone_record_app_xsp(void *record); byte * get_clone_record_dstack(void *record); -#ifdef AARCHXX +#if defined(AARCHXX) || defined(RISCV64) reg_t get_clone_record_stolen_value(void *record); -# ifndef AARCH64 +# ifdef ARM uint /* dr_isa_mode_t but we have a header ordering problem */ get_clone_record_isa_mode(void *record); # endif diff --git a/core/unix/os_private.h b/core/unix/os_private.h index 46b3e96bda7..b80c37029bd 100644 --- a/core/unix/os_private.h +++ b/core/unix/os_private.h @@ -219,7 +219,7 @@ os_get_priv_tls_base(dcontext_t *dcontext, reg_id_t seg); void os_tls_thread_exit(local_state_t *local_state); -#ifdef AARCHXX +#if defined(AARCHXX) || defined(RISCV64) bool os_set_app_tls_base(dcontext_t *dcontext, reg_id_t reg, void *base); #endif diff --git a/core/unix/signal.c b/core/unix/signal.c index a9b63abf485..c8f8a069932 100644 --- a/core/unix/signal.c +++ b/core/unix/signal.c @@ -217,13 +217,13 @@ typedef struct _clone_record_t { thread_sig_info_t info; thread_sig_info_t *parent_info; void *pcprofile_info; -#ifdef AARCHXX +#if defined(AARCHXX) || defined(RISCV64) /* To ensure we have the right value as of the point of the clone, we * store it here (we'll have races if we try to get it during new thread * init). */ reg_t app_stolen_value; -# ifndef AARCH64 +# ifdef ARM dr_isa_mode_t isa_mode; # endif /* To ensure we have the right app lib tls base in child thread, @@ -846,9 +846,9 @@ create_clone_record(dcontext_t *dcontext, reg_t *app_thread_xsp) record->info.app_sigstack.ss_flags = SS_DISABLE; record->parent_info = (thread_sig_info_t *)dcontext->signal_field; record->pcprofile_info = dcontext->pcprofile_field; -#ifdef AARCHXX +#if defined(AARCHXX) || defined(RISCV64) record->app_stolen_value = get_stolen_reg_val(get_mcontext(dcontext)); -# ifndef AARCH64 +# ifdef ARM record->isa_mode = dr_get_isa_mode(dcontext); # endif /* If the child thread shares the same TLS with parent by not setting @@ -972,7 +972,7 @@ get_clone_record_dstack(void *record) return ((clone_record_t *)record)->dstack; } -#ifdef AARCHXX +#if defined(AARCHXX) || defined(RISCV64) reg_t get_clone_record_stolen_value(void *record) { @@ -980,7 +980,7 @@ get_clone_record_stolen_value(void *record) return ((clone_record_t *)record)->app_stolen_value; } -# ifndef AARCH64 +# ifdef ARM uint /* dr_isa_mode_t but we have a header ordering problem */ get_clone_record_isa_mode(void *record) { @@ -2784,6 +2784,8 @@ sig_full_initialize(sig_full_cxt_t *sc_full, kernel_ucontext_t *ucxt) #elif defined(AARCH64) sc_full->fp_simd_state = &ucxt->IF_MACOS64_ELSE(uc_mcontext64->__ns, uc_mcontext.__reserved); +#elif defined(RISCV64) + sc_full->fp_simd_state = &ucxt->uc_mcontext.sc_fpregs; #else ASSERT_NOT_IMPLEMENTED(false); #endif @@ -3330,8 +3332,7 @@ sig_has_restorer(thread_sig_info_t *info, int sig) */ return false; # elif defined(RISCV64) - /* FIXME i#3544: Not implemented */ - ASSERT_NOT_IMPLEMENTED(false); + /* FIXME i#3544: Is this same as AArch64? */ return false; # endif if (info->sighand->action[sig]->restorer == NULL) @@ -4065,6 +4066,8 @@ transfer_from_sig_handler_to_fcache_return(dcontext_t *dcontext, kernel_ucontext /* We're going to our fcache_return gencode which uses DEFAULT_ISA_MODE */ set_pc_mode_in_cpsr(sc, DEFAULT_ISA_MODE); # endif +#elif defined(RISCV64) + ASSERT_NOT_IMPLEMENTED(false); #endif #if defined(X64) || defined(ARM) @@ -4285,8 +4288,17 @@ abort_on_fault(dcontext_t *dcontext, uint dumpcore_flag, app_pc pc, byte *target # else # error NYI on AArch64 # endif +#elif defined(RISCV64) + " pc=" PFX " ra=" PFX " sp =" PFX " gp =" PFX "\n" + "\ttp=" PFX " t0=" PFX " t1 =" PFX " t2 =" PFX "\n" + "\ts0=" PFX " s1=" PFX " a0 =" PFX " a1 =" PFX "\n" + "\ta2=" PFX " a3=" PFX " a4 =" PFX " a5 =" PFX "\n" + "\ta6=" PFX " a7=" PFX " s2 =" PFX " s3 =" PFX "\n" + "\ts4=" PFX " s5=" PFX " s6 =" PFX " s7 =" PFX "\n" + "\ts8=" PFX " s9=" PFX " s10=" PFX " s11=" PFX "\n" + "\tt3=" PFX " t4=" PFX " t5 =" PFX " t6 =" PFX "\n" #endif /* X86/ARM */ - "\teflags=" PFX; + IF_NOT_RISCV64("\teflags=" PFX); #if defined(STATIC_LIBRARY) && defined(LINUX) /* i#2119: if we're invoking an app handler, disable a fatal coredump. */ @@ -7376,6 +7388,8 @@ handle_sigreturn(dcontext_t *dcontext, void *ucxt_param, int style) /* We're going to our fcache_return gencode which uses DEFAULT_ISA_MODE */ set_pc_mode_in_cpsr(sc, DEFAULT_ISA_MODE); # endif +# elif defined(RISCV64) + ASSERT_NOT_IMPLEMENTED(false); # endif #endif diff --git a/core/unix/signal_linux_riscv64.c b/core/unix/signal_linux_riscv64.c index 0e66a8d646a..2fc3b406a37 100644 --- a/core/unix/signal_linux_riscv64.c +++ b/core/unix/signal_linux_riscv64.c @@ -57,30 +57,35 @@ save_fpstate(dcontext_t *dcontext, sigframe_rt_t *frame) void dump_sigcontext(dcontext_t *dcontext, sigcontext_t *sc) { - /* FIXME i#3544: Not implemented */ - ASSERT_NOT_IMPLEMENTED(false); + LOG(THREAD, LOG_ASYNCH, 1, "FIXME i#3544: NYI on RISCV64"); } #endif /* DEBUG */ void sigcontext_to_mcontext_simd(priv_mcontext_t *mc, sig_full_cxt_t *sc_full) { - /* FIXME i#3544: Not implemented */ - ASSERT_NOT_IMPLEMENTED(false); + struct __riscv_d_ext_state *fpc = + (struct __riscv_d_ext_state *)sc_full->fp_simd_state; + if (fpc == NULL) + return; + mc->fcsr = fpc->fcsr; + memcpy(&mc->f0, &fpc->f, sizeof(fpc->f)); } void mcontext_to_sigcontext_simd(sig_full_cxt_t *sc_full, priv_mcontext_t *mc) { - /* FIXME i#3544: Not implemented */ - ASSERT_NOT_IMPLEMENTED(false); + struct __riscv_d_ext_state *fpc = + (struct __riscv_d_ext_state *)sc_full->fp_simd_state; + if (fpc == NULL) + return; + fpc->fcsr = mc->fcsr; + memcpy(&fpc->f, &mc->f0, sizeof(fpc->f)); } size_t signal_frame_extra_size(bool include_alignment) { - /* FIXME i#3544: Not implemented */ - ASSERT_NOT_IMPLEMENTED(false); return 0; } diff --git a/core/utils.c b/core/utils.c index 1560ed91e2b..76e987e1f5f 100644 --- a/core/utils.c +++ b/core/utils.c @@ -1973,7 +1973,7 @@ d_r_notify(syslog_event_type_t priority, bool internal, bool synch, * instead of MAXIMUM_PATH since it has different length on Linux and makes this buffer * too long. */ #ifdef X64 -# define REPORT_MSG_MAX (271 + 17 * 8 + 8 * 23 + 2) /* wider, + more regs */ +# define REPORT_MSG_MAX (271 + 32 * 23) /* wider, + more regs */ #elif defined(ARM) # define REPORT_MSG_MAX (271 + 17 * 8) /* more regs */ #else diff --git a/core/utils.h b/core/utils.h index 428851539ef..bae8850a402 100644 --- a/core/utils.h +++ b/core/utils.h @@ -1189,11 +1189,11 @@ bitmap_check_consistency(bitmap_t b, uint bitmap_size, uint expect_free); # define MAX_LOG_LENGTH_MINUS_ONE IF_X64_ELSE(1279, 767) #else /* need more space for printing out longer option strings */ -/* For client we have a larger stack and 2048 option length so go bigger +/* For client we have a larger stack and 2560 option length so go bigger * so clients don't have dr_printf truncated as often. */ -# define MAX_LOG_LENGTH 2048 -# define MAX_LOG_LENGTH_MINUS_ONE 2047 +# define MAX_LOG_LENGTH 2560 +# define MAX_LOG_LENGTH_MINUS_ONE 2559 #endif #if defined(DEBUG) && !defined(STANDALONE_DECODER) diff --git a/core/vmareas.c b/core/vmareas.c index 4b4af0aa854..ab012016335 100644 --- a/core/vmareas.c +++ b/core/vmareas.c @@ -8309,10 +8309,10 @@ check_thread_vm_area(dcontext_t *dcontext, app_pc pc, app_pc tag, void **vmlist, } /* we are building a real bb, assert consistency checks */ - /* XXX i#4257: These memqueries are surprisingly slow on Mac64 and AArch64. + /* XXX i#4257: These memqueries are surprisingly slow on Mac64, AArch64 and RISC-V. * Investigation is needed. For now we avoid them in default debug runs. */ - DOCHECK(IF_MACOS64_ELSE(3, IF_AARCH64_ELSE(3, 1)), { + DOCHECK(IF_MACOS64_ELSE(3, IF_AARCH64_ELSE(3, IF_RISCV64_ELSE(3, 1))), { uint prot2; ok = get_memory_info(pc, NULL, NULL, &prot2); ASSERT(!ok || !TEST(MEMPROT_WRITE, prot2) ||