From 350f0f40437567482f45e32a066118669a094a2f Mon Sep 17 00:00:00 2001 From: Daniil Kutz Date: Wed, 27 Mar 2024 15:38:41 +0300 Subject: [PATCH 01/14] i#3544 RV64: Implement return address handling for postcall wrappers --- ext/drwrap/drwrap.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/ext/drwrap/drwrap.c b/ext/drwrap/drwrap.c index 1f4621334ca..7d418a200e6 100644 --- a/ext/drwrap/drwrap.c +++ b/ext/drwrap/drwrap.c @@ -1940,12 +1940,9 @@ drwrap_ensure_postcall(void *drcontext, per_thread_t *pt, wrap_entry_t *wrap, pt->retaddr[pt->wrap_level] = wrapcxt->retaddr; /* Original, not load tgt. */ #ifdef X86 set_retaddr_on_stack(wrapcxt->mc->xsp, (app_pc)replace_retaddr_sentinel); -#elif defined(RISCV64) - /* FIXME i#3544: Not implemented */ - ASSERT(false, "Not implemented"); #else drwrap_get_mcontext_internal(wrapcxt, DR_MC_CONTROL); - wrapcxt->mc->lr = (reg_t)replace_retaddr_sentinel; + wrapcxt->mc->IF_RISCV64_ELSE(ra, lr) = (reg_t)replace_retaddr_sentinel; wrapcxt->mc_modified = true; #endif return; @@ -1986,7 +1983,7 @@ drwrap_ensure_postcall(void *drcontext, per_thread_t *pt, wrap_entry_t *wrap, /* called via clean call at the top of callee */ static void -drwrap_in_callee(void *arg1, reg_t xsp _IF_NOT_X86(reg_t lr)) +drwrap_in_callee(void *arg1, reg_t xsp _IF_NOT_X86(IF_RISCV64_ELSE(reg_t ra, reg_t lr))) { void *drcontext = dr_get_current_drcontext(); per_thread_t *pt = (per_thread_t *)drmgr_get_tls_field(drcontext, tls_idx); @@ -2006,6 +2003,8 @@ drwrap_in_callee(void *arg1, reg_t xsp _IF_NOT_X86(reg_t lr)) #ifdef AARCHXX /* ditto */ mc.lr = lr; +#elif defined(RISCV64) + mc.ra = ra; #endif mc.flags = 0; /* if anything else is asked for, lazily initialize */ @@ -2020,7 +2019,7 @@ drwrap_in_callee(void *arg1, reg_t xsp _IF_NOT_X86(reg_t lr)) NOTIFY(2, "%s: level %d function " PFX "\n", __FUNCTION__, pt->wrap_level + 1, pc); - app_pc retaddr = IF_X86_ELSE(get_retaddr_from_stack(xsp), (app_pc)lr); + app_pc retaddr = IF_X86_ELSE(get_retaddr_from_stack(xsp), (app_pc)IF_AARCHXX_ELSE(lr, ra)); if (TEST(DRWRAP_REPLACE_RETADDR, global_flags)) { /* In case of a tailcall, the return address has already been replaced by * the sentinel in the stack, we need to retrieve the return address from the @@ -2467,12 +2466,11 @@ drwrap_event_bb_insert_where(void *drcontext, void *tag, instrlist_t *bb, instr_ ? (DR_CLEANCALL_NOSAVE_FLAGS | DR_CLEANCALL_NOSAVE_XMM_NONPARAM) : 0; flags |= DR_CLEANCALL_READS_APP_CONTEXT | DR_CLEANCALL_WRITES_APP_CONTEXT; - /* FIXME i#3544: Adapt to a real RISC-V clean call implementation */ dr_insert_clean_call_ex( drcontext, bb, where, (void *)drwrap_in_callee, flags, - IF_AARCHXX_ELSE(3, 2), OPND_CREATE_INTPTR((ptr_int_t)arg1), + IF_AARCHXX_OR_RISCV64_ELSE(3, 2), OPND_CREATE_INTPTR((ptr_int_t)arg1), /* pass in xsp to avoid dr_get_mcontext */ - opnd_create_reg(DR_REG_XSP) _IF_AARCHXX(opnd_create_reg(DR_REG_LR))); + opnd_create_reg(DR_REG_XSP) _IF_AARCHXX_OR_RISCV64(opnd_create_reg(IF_AARCHXX_ELSE(DR_REG_LR, DR_REG_RA)))); } dr_recurlock_unlock(wrap_lock); } From 2f6658376dadf382e5ee0a125079f70f542162ee Mon Sep 17 00:00:00 2001 From: Daniil Kutz Date: Wed, 27 Mar 2024 15:49:16 +0300 Subject: [PATCH 02/14] Fix style --- ext/drwrap/drwrap.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ext/drwrap/drwrap.c b/ext/drwrap/drwrap.c index 7d418a200e6..65759162fae 100644 --- a/ext/drwrap/drwrap.c +++ b/ext/drwrap/drwrap.c @@ -2019,7 +2019,8 @@ drwrap_in_callee(void *arg1, reg_t xsp _IF_NOT_X86(IF_RISCV64_ELSE(reg_t ra, reg NOTIFY(2, "%s: level %d function " PFX "\n", __FUNCTION__, pt->wrap_level + 1, pc); - app_pc retaddr = IF_X86_ELSE(get_retaddr_from_stack(xsp), (app_pc)IF_AARCHXX_ELSE(lr, ra)); + app_pc retaddr = + IF_X86_ELSE(get_retaddr_from_stack(xsp), (app_pc)IF_AARCHXX_ELSE(lr, ra)); if (TEST(DRWRAP_REPLACE_RETADDR, global_flags)) { /* In case of a tailcall, the return address has already been replaced by * the sentinel in the stack, we need to retrieve the return address from the @@ -2470,7 +2471,8 @@ drwrap_event_bb_insert_where(void *drcontext, void *tag, instrlist_t *bb, instr_ drcontext, bb, where, (void *)drwrap_in_callee, flags, IF_AARCHXX_OR_RISCV64_ELSE(3, 2), OPND_CREATE_INTPTR((ptr_int_t)arg1), /* pass in xsp to avoid dr_get_mcontext */ - opnd_create_reg(DR_REG_XSP) _IF_AARCHXX_OR_RISCV64(opnd_create_reg(IF_AARCHXX_ELSE(DR_REG_LR, DR_REG_RA)))); + opnd_create_reg(DR_REG_XSP) _IF_AARCHXX_OR_RISCV64( + opnd_create_reg(IF_AARCHXX_ELSE(DR_REG_LR, DR_REG_RA)))); } dr_recurlock_unlock(wrap_lock); } From 2048ced933f04831faef8aed0cc06befd45b0888 Mon Sep 17 00:00:00 2001 From: Daniil Kutz Date: Fri, 29 Mar 2024 18:45:11 +0300 Subject: [PATCH 03/14] Try to compile drwrap tests for RISCV64 --- core/arch/asm_defines.asm | 3 +++ suite/tests/CMakeLists.txt | 10 +++++--- .../client-interface/drwrap-drreg-test.dll.c | 25 ++++++++++++++----- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/core/arch/asm_defines.asm b/core/arch/asm_defines.asm index 042d6337141..cb4662a8fb3 100644 --- a/core/arch/asm_defines.asm +++ b/core/arch/asm_defines.asm @@ -418,6 +418,9 @@ ASSUME fs:_DATA @N@\ # define REG_R29 x29 # define REG_R30 x30 # define REG_R31 x31 +# define REG_A0 x10 +# define REG_A1 x11 +# define REG_A2 x12 #else /* Intel X86 */ # ifdef X64 # define REG_XAX rax diff --git a/suite/tests/CMakeLists.txt b/suite/tests/CMakeLists.txt index 1879f194e84..b32bbdee361 100644 --- a/suite/tests/CMakeLists.txt +++ b/suite/tests/CMakeLists.txt @@ -3029,7 +3029,7 @@ if (X86 OR AARCH64) endif () endif () -if (NOT RISCV64) +#if (NOT RISCV64) # TODO i#3544: Port tests to RISC-V 64 tobuild_appdll(client.drwrap-test client-interface/drwrap-test.c) get_target_path_for_execution(drwrap_libpath client.drwrap-test.appdll @@ -3037,7 +3037,7 @@ if (NOT RISCV64) tobuild_ci(client.drwrap-test client-interface/drwrap-test.c "" "" "${drwrap_libpath}") use_DynamoRIO_extension(client.drwrap-test.dll drwrap) tochcon(client.drwrap-test.appdll textrel_shlib_t) -endif (NOT RISCV64) + #endif (NOT RISCV64) if (WIN32) # export from asm code @@ -3058,7 +3058,7 @@ if (NOT APPLE AND NOT RISCV64) # XXX i#1997: static DR not fully supported on Ma link_with_pthread(client.drwrap-test-detach) endif () -if (NOT RISCV64) # TODO i#3544: Port tests to RISC-V 64 +#if (NOT RISCV64) # TODO i#3544: Port tests to RISC-V 64 tobuild_appdll(client.drwrap-drreg-test client-interface/drwrap-drreg-test.c) get_target_path_for_execution(drwrap_drreg_libpath client.drwrap-drreg-test.appdll "${location_suffix}") @@ -3067,7 +3067,7 @@ if (NOT RISCV64) # TODO i#3544: Port tests to RISC-V 64 use_DynamoRIO_extension(client.drwrap-drreg-test.dll drwrap) use_DynamoRIO_extension(client.drwrap-drreg-test.dll drreg) use_DynamoRIO_extension(client.drwrap-drreg-test.dll drmgr) -endif (NOT RISCV64) + #endif (NOT RISCV64) if (AARCH64 AND NOT APPLE) # TODO i#5383: Port to Mac M1. # Create a fuzzing application for stress-testing via drstatecmp. @@ -6162,6 +6162,8 @@ if (RISCV64) code_api|client.app_args code_api|client.blackbox code_api|client.crashmsg + code_api|client.drwrap-test-callconv + code_api|client.drwrap-drreg-test code_api|client.execfault code_api|client.mangle_suspend code_api|client.null_instrument diff --git a/suite/tests/client-interface/drwrap-drreg-test.dll.c b/suite/tests/client-interface/drwrap-drreg-test.dll.c index b493bff8c7b..3583901854d 100644 --- a/suite/tests/client-interface/drwrap-drreg-test.dll.c +++ b/suite/tests/client-interface/drwrap-drreg-test.dll.c @@ -104,8 +104,8 @@ clean_call_rw(void) mc.flags = DR_MC_CONTROL | DR_MC_INTEGER; bool ok = dr_get_mcontext(drcontext, &mc); CHECK(ok, "dr_get_mcontext failed"); - CHECK(IF_X86_ELSE(mc.xdx, mc.r1) == 4, "app reg val not restored for clean call"); - IF_X86_ELSE(mc.xcx, mc.r2) = 3; + CHECK(IF_X86_ELSE(mc.xdx, IF_AARCHXX_ELSE(mc.r1, mc.a1)) == 4, "app reg val not restored for clean call"); + IF_X86_ELSE(mc.xcx, IF_AARCHXX_ELSE(mc.r2, mc.a2)) = 3; ok = dr_set_mcontext(drcontext, &mc); CHECK(ok, "dr_set_mcontext failed"); } @@ -121,9 +121,9 @@ clean_call_check_rw(reg_t reg1, reg_t reg2) mc.flags = DR_MC_CONTROL | DR_MC_INTEGER; bool ok = dr_get_mcontext(drcontext, &mc); CHECK(ok, "dr_get_mcontext failed"); - CHECK(IF_X86_ELSE(mc.xdx, mc.r1) == SENTINEL, + CHECK(IF_X86_ELSE(mc.xdx, IF_AARCHXX_ELSE(mc.r1, mc.a1)) == SENTINEL, "tool val1 in mc not restored after call"); - CHECK(IF_X86_ELSE(mc.xdi, mc.r4) == SENTINEL, + CHECK(IF_X86_ELSE(mc.xdi, IF_AARCHXX_ELSE(mc.r4, mc.a4)) == SENTINEL, "tool val2 in mc not restored after call"); } @@ -136,7 +136,7 @@ clean_call_multipath(void) mc.flags = DR_MC_CONTROL | DR_MC_INTEGER; bool ok = dr_get_mcontext(drcontext, &mc); CHECK(ok, "dr_get_mcontext failed"); - CHECK(IF_X86_ELSE(mc.xdx, mc.r1) == 4, "app reg val not restored for clean call"); + CHECK(IF_X86_ELSE(mc.xdx, IF_AARCHXX_ELSE(mc.r1, mc.a1)) == 4, "app reg val not restored for clean call"); #ifdef X86 /* This tests the drreg_statelessly_restore_app_value() respill which only * happens with aflags in xax. @@ -169,6 +169,10 @@ clobber_key_regs(void *drcontext, instrlist_t *bb, instr_t *inst) drreg_set_vector_entry(&allowed, DR_REG_XAX, true); drreg_set_vector_entry(&allowed, DR_REG_XDI, true); drreg_set_vector_entry(&allowed, DR_REG_XSI, true); +#elif defined(RISCV64) + drreg_set_vector_entry(&allowed, DR_REG_A0, true); + drreg_set_vector_entry(&allowed, DR_REG_A1, true); + drreg_set_vector_entry(&allowed, DR_REG_A2, true); #else drreg_set_vector_entry(&allowed, DR_REG_R0, true); drreg_set_vector_entry(&allowed, DR_REG_R1, true); @@ -218,6 +222,9 @@ insert_rw_call(void *drcontext, instrlist_t *bb, instr_t *inst) #ifdef X86 drreg_set_vector_entry(&allowed, DR_REG_XDX, true); drreg_set_vector_entry(&allowed, DR_REG_XDI, true); +#elif defined(RISCV64) + drreg_set_vector_entry(&allowed, DR_REG_A1, true); + drreg_set_vector_entry(&allowed, DR_REG_A4, true); #else drreg_set_vector_entry(&allowed, DR_REG_R1, true); drreg_set_vector_entry(&allowed, DR_REG_R4, true); @@ -267,6 +274,8 @@ insert_multipath_call(void *drcontext, instrlist_t *bb, instr_t *inst) /* Clobber the reg we check in clean_call_multipath(). */ #ifdef X86 drreg_set_vector_entry(&allowed, DR_REG_XDX, true); +#elif defined(RISCV64) + drreg_set_vector_entry(&allowed, DR_REG_A1, true); #else drreg_set_vector_entry(&allowed, DR_REG_R1, true); #endif @@ -285,7 +294,7 @@ insert_multipath_call(void *drcontext, instrlist_t *bb, instr_t *inst) /* The app executes twice and sets rcx/r0 to 0 for one of them. */ instrlist_meta_preinsert( bb, inst, - XINST_CREATE_cmp(drcontext, opnd_create_reg(IF_X86_ELSE(DR_REG_XCX, DR_REG_R0)), + XINST_CREATE_cmp(drcontext, opnd_create_reg(IF_X86_ELSE(DR_REG_XCX, IF_AARCHXX_ELSE(DR_REG_R0, DR_REG_A0))), OPND_CREATE_INT32(0))); instrlist_meta_preinsert( bb, inst, @@ -331,7 +340,11 @@ event_app_instruction(void *drcontext, void *tag, instrlist_t *bb, instr_t *inst /* Look for nop;nop;nop in reg_val_test() and 4 nops in multipath_test(). */ if (instr_is_app(inst)) { int *nop_count = (int *)user_data; +#if defined(RISCV64) + if (instr_is_nop(inst)) { +#else if (instr_get_opcode(inst) == OP_nop IF_ARM(|| instr_is_mov_nop(inst))) { +#endif ++(*nop_count); } else { if (*nop_count == 3) { From f18b2241393e0cfa012b23dbf5832eb6a83f81a1 Mon Sep 17 00:00:00 2001 From: Daniil Kutz Date: Tue, 2 Apr 2024 16:51:41 +0300 Subject: [PATCH 04/14] Port drwrap-callconv and drwrap-drreg tests to RISC-V --- core/ir/riscv64/instr_create_api.h.in | 14 ++++++++++++++ .../tests/client-interface/drwrap-drreg-test.dll.c | 13 ++++++++++++- .../client-interface/drwrap-test-callconv.dll.cpp | 6 +++++- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/core/ir/riscv64/instr_create_api.h.in b/core/ir/riscv64/instr_create_api.h.in index ba02e2495ce..11566056133 100644 --- a/core/ir/riscv64/instr_create_api.h.in +++ b/core/ir/riscv64/instr_create_api.h.in @@ -199,6 +199,20 @@ #define XINST_CREATE_jump_short(dc, t) \ INSTR_CREATE_jal(dc, opnd_create_reg(DR_REG_ZERO), t) +/** + * This platform-independent macro creates an instr_t for an conditional + * branch instruction. + * \param dc The void * dcontext used to allocate memory for the instr_t. + * \param t The opnd_t target operand for the instruction, which can be + * either a pc (opnd_create_pc)()) or an instr_t (opnd_create_instr()). + * \param s1 The opnd_t explicit first source operand for the instruction. + * \param s2 The opnd_t explicit second source operand for the instruction. + * Be sure to ensure that the limited reach of this short branch will reach + * the target (a pc operand is not suitable for most uses unless you know + * precisely where this instruction will be encoded). + */ +#define XINST_CREATE_beq(dc, t, s1, s2) INSTR_CREATE_beq(dc, t, s1, s2) + /** * This platform-independent macro creates an instr_t for an unconditional * branch instruction. diff --git a/suite/tests/client-interface/drwrap-drreg-test.dll.c b/suite/tests/client-interface/drwrap-drreg-test.dll.c index 3583901854d..65bd96c9180 100644 --- a/suite/tests/client-interface/drwrap-drreg-test.dll.c +++ b/suite/tests/client-interface/drwrap-drreg-test.dll.c @@ -80,7 +80,11 @@ module_load_event(void *drcontext, const module_data_t *mod, bool loaded) addr_two_args = (app_pc)dr_get_proc_address(mod->handle, "two_args"); CHECK(addr_two_args != NULL, "cannot find lib export"); +#if defined(RISCV64) + bool ok = drwrap_wrap_ex(addr_two_args, wrap_pre, wrap_post, 0, DRWRAP_CALLCONV_RISCV_LP64 | DRWRAP_REPLACE_RETADDR); +#else bool ok = drwrap_wrap(addr_two_args, wrap_pre, wrap_post); +#endif CHECK(ok, "wrap failed"); } } @@ -292,13 +296,20 @@ insert_multipath_call(void *drcontext, instrlist_t *bb, instr_t *inst) instr_t *skip_call = INSTR_CREATE_label(drcontext); /* The app executes twice and sets rcx/r0 to 0 for one of them. */ +#if defined(RISCV64) instrlist_meta_preinsert( bb, inst, - XINST_CREATE_cmp(drcontext, opnd_create_reg(IF_X86_ELSE(DR_REG_XCX, IF_AARCHXX_ELSE(DR_REG_R0, DR_REG_A0))), + XINST_CREATE_beq(drcontext, opnd_create_instr(skip_call), opnd_create_reg(DR_REG_A0), + OPND_CREATE_INT32(0))); +#else + instrlist_meta_preinsert( + bb, inst, + XINST_CREATE_cmp(drcontext, opnd_create_reg(IF_X86_ELSE(DR_REG_XCX, DR_REG_R0)), OPND_CREATE_INT32(0))); instrlist_meta_preinsert( bb, inst, XINST_CREATE_jump_cond(drcontext, DR_PRED_EQ, opnd_create_instr(skip_call))); +#endif dr_insert_clean_call_ex(drcontext, bb, inst, clean_call_multipath, DR_CLEANCALL_READS_APP_CONTEXT | DR_CLEANCALL_MULTIPATH, 0); instrlist_meta_preinsert(bb, inst, skip_call); diff --git a/suite/tests/client-interface/drwrap-test-callconv.dll.cpp b/suite/tests/client-interface/drwrap-test-callconv.dll.cpp index 16ef0dd529f..89e064b8ff4 100644 --- a/suite/tests/client-interface/drwrap-test-callconv.dll.cpp +++ b/suite/tests/client-interface/drwrap-test-callconv.dll.cpp @@ -48,7 +48,7 @@ # define PLATFORM_HAS_THISCALL 1 #endif -#if !defined(ARM) && !defined(X64) +#if !defined(ARM) && !defined(X64) && !defined(RISCV64) # define PLATFORM_HAS_FASTCALL 1 #endif @@ -190,6 +190,8 @@ dr_init(client_id_t id) #ifdef PLATFORM_HAS_THISCALL thiscall = DRWRAP_CALLCONV_THISCALL; +#elif defined(RISCV64) + thiscall = DRWRAP_CALLCONV_RISCV_LP64; #else thiscall = DRWRAP_CALLCONV_DEFAULT; #endif @@ -197,6 +199,8 @@ dr_init(client_id_t id) #ifdef PLATFORM_HAS_FASTCALL fastcall = DRWRAP_CALLCONV_FASTCALL; +#elif defined(RISCV64) + thiscall = DRWRAP_CALLCONV_RISCV_LP64; #else fastcall = DRWRAP_CALLCONV_DEFAULT; #endif From 3dbfc4cd4d19dbc2ab461009312167891e41db1b Mon Sep 17 00:00:00 2001 From: Daniil Kutz Date: Tue, 2 Apr 2024 20:48:03 +0300 Subject: [PATCH 05/14] Try to port drwrap-drreg to RISC-V --- core/ir/riscv64/instr_create_api.h.in | 14 -------- suite/tests/CMakeLists.txt | 33 ++++++++----------- .../drwrap-drreg-test.appdll.c | 22 +++++++++++++ .../client-interface/drwrap-drreg-test.dll.c | 2 +- 4 files changed, 37 insertions(+), 34 deletions(-) diff --git a/core/ir/riscv64/instr_create_api.h.in b/core/ir/riscv64/instr_create_api.h.in index 11566056133..ba02e2495ce 100644 --- a/core/ir/riscv64/instr_create_api.h.in +++ b/core/ir/riscv64/instr_create_api.h.in @@ -199,20 +199,6 @@ #define XINST_CREATE_jump_short(dc, t) \ INSTR_CREATE_jal(dc, opnd_create_reg(DR_REG_ZERO), t) -/** - * This platform-independent macro creates an instr_t for an conditional - * branch instruction. - * \param dc The void * dcontext used to allocate memory for the instr_t. - * \param t The opnd_t target operand for the instruction, which can be - * either a pc (opnd_create_pc)()) or an instr_t (opnd_create_instr()). - * \param s1 The opnd_t explicit first source operand for the instruction. - * \param s2 The opnd_t explicit second source operand for the instruction. - * Be sure to ensure that the limited reach of this short branch will reach - * the target (a pc operand is not suitable for most uses unless you know - * precisely where this instruction will be encoded). - */ -#define XINST_CREATE_beq(dc, t, s1, s2) INSTR_CREATE_beq(dc, t, s1, s2) - /** * This platform-independent macro creates an instr_t for an unconditional * branch instruction. diff --git a/suite/tests/CMakeLists.txt b/suite/tests/CMakeLists.txt index b32bbdee361..762fde711b7 100644 --- a/suite/tests/CMakeLists.txt +++ b/suite/tests/CMakeLists.txt @@ -3029,15 +3029,12 @@ if (X86 OR AARCH64) endif () endif () -#if (NOT RISCV64) - # TODO i#3544: Port tests to RISC-V 64 - tobuild_appdll(client.drwrap-test client-interface/drwrap-test.c) - get_target_path_for_execution(drwrap_libpath client.drwrap-test.appdll - "${location_suffix}") - tobuild_ci(client.drwrap-test client-interface/drwrap-test.c "" "" "${drwrap_libpath}") - use_DynamoRIO_extension(client.drwrap-test.dll drwrap) - tochcon(client.drwrap-test.appdll textrel_shlib_t) - #endif (NOT RISCV64) +tobuild_appdll(client.drwrap-test client-interface/drwrap-test.c) +get_target_path_for_execution(drwrap_libpath client.drwrap-test.appdll + "${location_suffix}") +tobuild_ci(client.drwrap-test client-interface/drwrap-test.c "" "" "${drwrap_libpath}") +use_DynamoRIO_extension(client.drwrap-test.dll drwrap) +tochcon(client.drwrap-test.appdll textrel_shlib_t) if (WIN32) # export from asm code @@ -3058,16 +3055,14 @@ if (NOT APPLE AND NOT RISCV64) # XXX i#1997: static DR not fully supported on Ma link_with_pthread(client.drwrap-test-detach) endif () -#if (NOT RISCV64) # TODO i#3544: Port tests to RISC-V 64 - tobuild_appdll(client.drwrap-drreg-test client-interface/drwrap-drreg-test.c) - get_target_path_for_execution(drwrap_drreg_libpath client.drwrap-drreg-test.appdll - "${location_suffix}") - tobuild_ci(client.drwrap-drreg-test client-interface/drwrap-drreg-test.c "" "" - "${drwrap_drreg_libpath}") - use_DynamoRIO_extension(client.drwrap-drreg-test.dll drwrap) - use_DynamoRIO_extension(client.drwrap-drreg-test.dll drreg) - use_DynamoRIO_extension(client.drwrap-drreg-test.dll drmgr) - #endif (NOT RISCV64) +tobuild_appdll(client.drwrap-drreg-test client-interface/drwrap-drreg-test.c) +get_target_path_for_execution(drwrap_drreg_libpath client.drwrap-drreg-test.appdll + "${location_suffix}") +tobuild_ci(client.drwrap-drreg-test client-interface/drwrap-drreg-test.c "" "" + "${drwrap_drreg_libpath}") +use_DynamoRIO_extension(client.drwrap-drreg-test.dll drwrap) +use_DynamoRIO_extension(client.drwrap-drreg-test.dll drreg) +use_DynamoRIO_extension(client.drwrap-drreg-test.dll drmgr) if (AARCH64 AND NOT APPLE) # TODO i#5383: Port to Mac M1. # Create a fuzzing application for stress-testing via drstatecmp. diff --git a/suite/tests/client-interface/drwrap-drreg-test.appdll.c b/suite/tests/client-interface/drwrap-drreg-test.appdll.c index 701c295068b..2f70ef1548b 100644 --- a/suite/tests/client-interface/drwrap-drreg-test.appdll.c +++ b/suite/tests/client-interface/drwrap-drreg-test.appdll.c @@ -117,6 +117,16 @@ GLOBAL_LABEL(FUNCNAME:) nop add r0, r1, r2 bx lr +# elif defined(RISCV64) + mov REG_A1, HEX(4) + /* The clean call writes to x7, replacing this value. */ + mov REG_A2, HEX(42) + /* The clean call is inserted after 3 nops. */ + nop + nop + nop + add REG_A0, REG_A1, REG_A2 + ret # endif END_FUNC(FUNCNAME) # undef FUNCNAME @@ -166,6 +176,18 @@ GLOBAL_LABEL(FUNCNAME:) nop add r0, r1, r2 bx lr +# elif defined(RISCV64) + mov A0, ARG1 /* Used to skip clean call. */ + mov A1, HEX(4) /* Read in clean call. */ + mov A2, HEX(0x42) + /* Aflags has special x86 behavior; we do not test it here. */ + /* The clean call is inserted after 4 nops. */ + nop + nop + nop + nop + add REG_A0, REG_A1, REG_A2 + ret # endif END_FUNC(FUNCNAME) # undef FUNCNAME diff --git a/suite/tests/client-interface/drwrap-drreg-test.dll.c b/suite/tests/client-interface/drwrap-drreg-test.dll.c index 65bd96c9180..a12ae351c12 100644 --- a/suite/tests/client-interface/drwrap-drreg-test.dll.c +++ b/suite/tests/client-interface/drwrap-drreg-test.dll.c @@ -299,7 +299,7 @@ insert_multipath_call(void *drcontext, instrlist_t *bb, instr_t *inst) #if defined(RISCV64) instrlist_meta_preinsert( bb, inst, - XINST_CREATE_beq(drcontext, opnd_create_instr(skip_call), opnd_create_reg(DR_REG_A0), + INSTR_CREATE_beq(drcontext, opnd_create_instr(skip_call), opnd_create_reg(DR_REG_A0), OPND_CREATE_INT32(0))); #else instrlist_meta_preinsert( From c0242bd1a63501ccc2b722677c4ac548fd871a51 Mon Sep 17 00:00:00 2001 From: Daniil Kutz Date: Tue, 2 Apr 2024 20:49:53 +0300 Subject: [PATCH 06/14] fix --- suite/tests/client-interface/drwrap-drreg-test.appdll.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/suite/tests/client-interface/drwrap-drreg-test.appdll.c b/suite/tests/client-interface/drwrap-drreg-test.appdll.c index 2f70ef1548b..f148647e448 100644 --- a/suite/tests/client-interface/drwrap-drreg-test.appdll.c +++ b/suite/tests/client-interface/drwrap-drreg-test.appdll.c @@ -177,9 +177,9 @@ GLOBAL_LABEL(FUNCNAME:) add r0, r1, r2 bx lr # elif defined(RISCV64) - mov A0, ARG1 /* Used to skip clean call. */ - mov A1, HEX(4) /* Read in clean call. */ - mov A2, HEX(0x42) + mov REG_A0, ARG1 /* Used to skip clean call. */ + mov REG_A1, HEX(4) /* Read in clean call. */ + mov REG_A2, HEX(42) /* Aflags has special x86 behavior; we do not test it here. */ /* The clean call is inserted after 4 nops. */ nop From 59add872b58dcc2f2a62c9fdc46977cf83d276ca Mon Sep 17 00:00:00 2001 From: Daniil Kutz Date: Wed, 3 Apr 2024 12:57:28 +0300 Subject: [PATCH 07/14] Fix style --- .../client-interface/drwrap-drreg-test.dll.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/suite/tests/client-interface/drwrap-drreg-test.dll.c b/suite/tests/client-interface/drwrap-drreg-test.dll.c index a12ae351c12..35d32178b08 100644 --- a/suite/tests/client-interface/drwrap-drreg-test.dll.c +++ b/suite/tests/client-interface/drwrap-drreg-test.dll.c @@ -81,7 +81,8 @@ module_load_event(void *drcontext, const module_data_t *mod, bool loaded) addr_two_args = (app_pc)dr_get_proc_address(mod->handle, "two_args"); CHECK(addr_two_args != NULL, "cannot find lib export"); #if defined(RISCV64) - bool ok = drwrap_wrap_ex(addr_two_args, wrap_pre, wrap_post, 0, DRWRAP_CALLCONV_RISCV_LP64 | DRWRAP_REPLACE_RETADDR); + bool ok = drwrap_wrap_ex(addr_two_args, wrap_pre, wrap_post, 0, + DRWRAP_CALLCONV_RISCV_LP64 | DRWRAP_REPLACE_RETADDR); #else bool ok = drwrap_wrap(addr_two_args, wrap_pre, wrap_post); #endif @@ -108,7 +109,8 @@ clean_call_rw(void) mc.flags = DR_MC_CONTROL | DR_MC_INTEGER; bool ok = dr_get_mcontext(drcontext, &mc); CHECK(ok, "dr_get_mcontext failed"); - CHECK(IF_X86_ELSE(mc.xdx, IF_AARCHXX_ELSE(mc.r1, mc.a1)) == 4, "app reg val not restored for clean call"); + CHECK(IF_X86_ELSE(mc.xdx, IF_AARCHXX_ELSE(mc.r1, mc.a1)) == 4, + "app reg val not restored for clean call"); IF_X86_ELSE(mc.xcx, IF_AARCHXX_ELSE(mc.r2, mc.a2)) = 3; ok = dr_set_mcontext(drcontext, &mc); CHECK(ok, "dr_set_mcontext failed"); @@ -140,7 +142,8 @@ clean_call_multipath(void) mc.flags = DR_MC_CONTROL | DR_MC_INTEGER; bool ok = dr_get_mcontext(drcontext, &mc); CHECK(ok, "dr_get_mcontext failed"); - CHECK(IF_X86_ELSE(mc.xdx, IF_AARCHXX_ELSE(mc.r1, mc.a1)) == 4, "app reg val not restored for clean call"); + CHECK(IF_X86_ELSE(mc.xdx, IF_AARCHXX_ELSE(mc.r1, mc.a1)) == 4, + "app reg val not restored for clean call"); #ifdef X86 /* This tests the drreg_statelessly_restore_app_value() respill which only * happens with aflags in xax. @@ -351,11 +354,7 @@ event_app_instruction(void *drcontext, void *tag, instrlist_t *bb, instr_t *inst /* Look for nop;nop;nop in reg_val_test() and 4 nops in multipath_test(). */ if (instr_is_app(inst)) { int *nop_count = (int *)user_data; -#if defined(RISCV64) - if (instr_is_nop(inst)) { -#else - if (instr_get_opcode(inst) == OP_nop IF_ARM(|| instr_is_mov_nop(inst))) { -#endif + if (instr_is_nop(inst) IF_ARM(|| instr_is_mov_nop(inst))) { ++(*nop_count); } else { if (*nop_count == 3) { From 33c117b38e814cd2d1a866bc50c6ee8782398f97 Mon Sep 17 00:00:00 2001 From: Daniil Kutz Date: Wed, 3 Apr 2024 13:05:14 +0300 Subject: [PATCH 08/14] Fix style --- suite/tests/client-interface/drwrap-drreg-test.dll.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/suite/tests/client-interface/drwrap-drreg-test.dll.c b/suite/tests/client-interface/drwrap-drreg-test.dll.c index 35d32178b08..e4567ba8e0c 100644 --- a/suite/tests/client-interface/drwrap-drreg-test.dll.c +++ b/suite/tests/client-interface/drwrap-drreg-test.dll.c @@ -300,10 +300,10 @@ insert_multipath_call(void *drcontext, instrlist_t *bb, instr_t *inst) instr_t *skip_call = INSTR_CREATE_label(drcontext); /* The app executes twice and sets rcx/r0 to 0 for one of them. */ #if defined(RISCV64) - instrlist_meta_preinsert( - bb, inst, - INSTR_CREATE_beq(drcontext, opnd_create_instr(skip_call), opnd_create_reg(DR_REG_A0), - OPND_CREATE_INT32(0))); + instrlist_meta_preinsert(bb, inst, + INSTR_CREATE_beq(drcontext, opnd_create_instr(skip_call), + opnd_create_reg(DR_REG_A0), + OPND_CREATE_INT32(0))); #else instrlist_meta_preinsert( bb, inst, From 613785acc8fa5c866600d85b3f90391604b77d17 Mon Sep 17 00:00:00 2001 From: Daniil Kutz Date: Wed, 3 Apr 2024 13:19:52 +0300 Subject: [PATCH 09/14] Fix bug --- suite/tests/client-interface/drwrap-test-callconv.dll.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/suite/tests/client-interface/drwrap-test-callconv.dll.cpp b/suite/tests/client-interface/drwrap-test-callconv.dll.cpp index 89e064b8ff4..e42de389b04 100644 --- a/suite/tests/client-interface/drwrap-test-callconv.dll.cpp +++ b/suite/tests/client-interface/drwrap-test-callconv.dll.cpp @@ -200,7 +200,7 @@ dr_init(client_id_t id) #ifdef PLATFORM_HAS_FASTCALL fastcall = DRWRAP_CALLCONV_FASTCALL; #elif defined(RISCV64) - thiscall = DRWRAP_CALLCONV_RISCV_LP64; + fastcall = DRWRAP_CALLCONV_RISCV_LP64; #else fastcall = DRWRAP_CALLCONV_DEFAULT; #endif From 1e96eea74e206d8ee67db19da673ccc759ccd5d5 Mon Sep 17 00:00:00 2001 From: Daniil Kutz Date: Mon, 5 Aug 2024 19:46:14 +0300 Subject: [PATCH 10/14] Fix CI --- suite/tests/CMakeLists.txt | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/suite/tests/CMakeLists.txt b/suite/tests/CMakeLists.txt index 762fde711b7..f07496406f1 100644 --- a/suite/tests/CMakeLists.txt +++ b/suite/tests/CMakeLists.txt @@ -3055,14 +3055,16 @@ if (NOT APPLE AND NOT RISCV64) # XXX i#1997: static DR not fully supported on Ma link_with_pthread(client.drwrap-test-detach) endif () -tobuild_appdll(client.drwrap-drreg-test client-interface/drwrap-drreg-test.c) -get_target_path_for_execution(drwrap_drreg_libpath client.drwrap-drreg-test.appdll - "${location_suffix}") -tobuild_ci(client.drwrap-drreg-test client-interface/drwrap-drreg-test.c "" "" - "${drwrap_drreg_libpath}") -use_DynamoRIO_extension(client.drwrap-drreg-test.dll drwrap) -use_DynamoRIO_extension(client.drwrap-drreg-test.dll drreg) -use_DynamoRIO_extension(client.drwrap-drreg-test.dll drmgr) +if (NOT RISCV64) # TODO i#3544: Port tests to RISC-V 64 + tobuild_appdll(client.drwrap-drreg-test client-interface/drwrap-drreg-test.c) + get_target_path_for_execution(drwrap_drreg_libpath client.drwrap-drreg-test.appdll + "${location_suffix}") + tobuild_ci(client.drwrap-drreg-test client-interface/drwrap-drreg-test.c "" "" + "${drwrap_drreg_libpath}") + use_DynamoRIO_extension(client.drwrap-drreg-test.dll drwrap) + use_DynamoRIO_extension(client.drwrap-drreg-test.dll drreg) + use_DynamoRIO_extension(client.drwrap-drreg-test.dll drmgr) +endif (NOT RISCV64) if (AARCH64 AND NOT APPLE) # TODO i#5383: Port to Mac M1. # Create a fuzzing application for stress-testing via drstatecmp. @@ -6158,7 +6160,6 @@ if (RISCV64) code_api|client.blackbox code_api|client.crashmsg code_api|client.drwrap-test-callconv - code_api|client.drwrap-drreg-test code_api|client.execfault code_api|client.mangle_suspend code_api|client.null_instrument From bc853cd0fe0c6278a598fa8d837b37ad479c2990 Mon Sep 17 00:00:00 2001 From: Daniil Kutz Date: Tue, 6 Aug 2024 13:34:11 +0300 Subject: [PATCH 11/14] Disable drwrap test --- suite/tests/CMakeLists.txt | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/suite/tests/CMakeLists.txt b/suite/tests/CMakeLists.txt index f07496406f1..7d5101c1548 100644 --- a/suite/tests/CMakeLists.txt +++ b/suite/tests/CMakeLists.txt @@ -3029,12 +3029,15 @@ if (X86 OR AARCH64) endif () endif () -tobuild_appdll(client.drwrap-test client-interface/drwrap-test.c) -get_target_path_for_execution(drwrap_libpath client.drwrap-test.appdll - "${location_suffix}") -tobuild_ci(client.drwrap-test client-interface/drwrap-test.c "" "" "${drwrap_libpath}") -use_DynamoRIO_extension(client.drwrap-test.dll drwrap) -tochcon(client.drwrap-test.appdll textrel_shlib_t) +if (NOT RISCV64) + # TODO i#3544: Port tests to RISC-V 64 + tobuild_appdll(client.drwrap-test client-interface/drwrap-test.c) + get_target_path_for_execution(drwrap_libpath client.drwrap-test.appdll + "${location_suffix}") + tobuild_ci(client.drwrap-test client-interface/drwrap-test.c "" "" "${drwrap_libpath}") + use_DynamoRIO_extension(client.drwrap-test.dll drwrap) + tochcon(client.drwrap-test.appdll textrel_shlib_t) +endif (NOT RISCV64) if (WIN32) # export from asm code From 2ca90ac08c1f3563699c9beab760893443f3bd7a Mon Sep 17 00:00:00 2001 From: Daniil Kutz Date: Thu, 8 Aug 2024 15:46:16 +0300 Subject: [PATCH 12/14] Set correct DRWRAP_CALLCONV_DEFAULT for RISCV64 --- ext/drwrap/drwrap.h | 3 +++ suite/tests/client-interface/drwrap-test-callconv.dll.cpp | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ext/drwrap/drwrap.h b/ext/drwrap/drwrap.h index a0448ef8f8e..8b801bd03b5 100644 --- a/ext/drwrap/drwrap.h +++ b/ext/drwrap/drwrap.h @@ -459,6 +459,9 @@ typedef enum { # ifdef AARCH64 /** Default calling convention for the platform. */ DRWRAP_CALLCONV_DEFAULT = DRWRAP_CALLCONV_AARCH64, +# elif defined(RISCV64) + /** Default calling convention for the platform. */ + DRWRAP_CALLCONV_DEFAULT = DRWRAP_CALLCONV_RISCV_LP64, # elif defined(UNIX) /* x64 */ /** Default calling convention for the platform. */ DRWRAP_CALLCONV_DEFAULT = DRWRAP_CALLCONV_AMD64, diff --git a/suite/tests/client-interface/drwrap-test-callconv.dll.cpp b/suite/tests/client-interface/drwrap-test-callconv.dll.cpp index e42de389b04..0cf756fb1bf 100644 --- a/suite/tests/client-interface/drwrap-test-callconv.dll.cpp +++ b/suite/tests/client-interface/drwrap-test-callconv.dll.cpp @@ -190,8 +190,6 @@ dr_init(client_id_t id) #ifdef PLATFORM_HAS_THISCALL thiscall = DRWRAP_CALLCONV_THISCALL; -#elif defined(RISCV64) - thiscall = DRWRAP_CALLCONV_RISCV_LP64; #else thiscall = DRWRAP_CALLCONV_DEFAULT; #endif @@ -199,8 +197,6 @@ dr_init(client_id_t id) #ifdef PLATFORM_HAS_FASTCALL fastcall = DRWRAP_CALLCONV_FASTCALL; -#elif defined(RISCV64) - fastcall = DRWRAP_CALLCONV_RISCV_LP64; #else fastcall = DRWRAP_CALLCONV_DEFAULT; #endif From cde5993125d450c52dfbccd44a354884dff3a5a1 Mon Sep 17 00:00:00 2001 From: Daniil Kutz Date: Thu, 8 Aug 2024 18:42:37 +0300 Subject: [PATCH 13/14] Remove DRWRAP_REPLACE_RETADDR from drwrap-drreg-test --- suite/tests/client-interface/drwrap-drreg-test.dll.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/suite/tests/client-interface/drwrap-drreg-test.dll.c b/suite/tests/client-interface/drwrap-drreg-test.dll.c index e4567ba8e0c..2a82cddf445 100644 --- a/suite/tests/client-interface/drwrap-drreg-test.dll.c +++ b/suite/tests/client-interface/drwrap-drreg-test.dll.c @@ -80,12 +80,7 @@ module_load_event(void *drcontext, const module_data_t *mod, bool loaded) addr_two_args = (app_pc)dr_get_proc_address(mod->handle, "two_args"); CHECK(addr_two_args != NULL, "cannot find lib export"); -#if defined(RISCV64) - bool ok = drwrap_wrap_ex(addr_two_args, wrap_pre, wrap_post, 0, - DRWRAP_CALLCONV_RISCV_LP64 | DRWRAP_REPLACE_RETADDR); -#else bool ok = drwrap_wrap(addr_two_args, wrap_pre, wrap_post); -#endif CHECK(ok, "wrap failed"); } } From 70a1a1e5d03ef8aa044bb02c9bec15c398f2a827 Mon Sep 17 00:00:00 2001 From: Daniil Kutz Date: Thu, 15 Aug 2024 15:58:20 +0300 Subject: [PATCH 14/14] Add docs for DRWRAP_REPLACE_RETADDR --- ext/drwrap/drwrap.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/drwrap/drwrap.h b/ext/drwrap/drwrap.h index 8b801bd03b5..7be45879730 100644 --- a/ext/drwrap/drwrap.h +++ b/ext/drwrap/drwrap.h @@ -421,8 +421,9 @@ typedef enum { * violation may be exposed to the client's dr_register_kernel_xfer_event() callback * if it inspects the mcontext PC on the stack; drwrap_get_retaddr_if_sentinel() * may be used to mitigate such cases. Use #DRWRAP_REPLACE_RETADDR at your own risk. + * Currently is not supported for RISC-V. */ - DRWRAP_REPLACE_RETADDR = 0x04, + DRWRAP_REPLACE_RETADDR = 0x04, /* TODO i#3544: support flag for RISC-V 64 */ } drwrap_wrap_flags_t; /* offset of drwrap_callconv_t in drwrap_wrap_flags_t */