Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i#3544 RV64: Implement return address handling for post wrappers #6736

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

apach301
Copy link
Contributor

@apach301 apach301 commented Mar 27, 2024

Substitute value of return address register to enable post wrappers.

Partially enables drwrap-test for RISC-V:

  1. Add drwrap-test-callconv test to pipeline
  2. Partially supported drwrap-drreg-test: check for pre/post wrappers passes,
    but checks for clean_call and restore registers functionality are failing.

Issue: #3544

Copy link
Contributor

@ksco ksco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose this is covered by some tests, do these tests work now? If yes, maybe state that in the PR description and enable it in the RUN_ON_QEMU label for RISC-V so it can be checked by the CI.

@apach301
Copy link
Contributor Author

apach301 commented Mar 28, 2024

I suppose this is covered by some tests, do these tests work now? If yes, maybe state that in the PR description and enable it in the RUN_ON_QEMU label for RISC-V so it can be checked by the CI.

I tested it only on my DR client. I don't familiar with DynamoRIO test system, and all I found is

if (NOT RISCV64)
and
if (NOT RISCV64) # TODO i#3544: Port tests to RISC-V 64
that are disabling drwrap tests on RISC-V. Is it sufficient to just remove the guards to enable these tests?

Also, as much as I understand, the one failing test (ci-aarchxx) isn't related to these changes, and is failing on current master.

@ksco
Copy link
Contributor

ksco commented Mar 28, 2024

Yes, remove the guards should be enough for CMake to build the test, then add the test name into suite/tests/CMakeLists.txt#L6152 and run ctest -L RUNS_ON_QEMU see if the test passes.

@apach301
Copy link
Contributor Author

Yes, remove the guards should be enough for CMake to build the test, then add the test name into suite/tests/CMakeLists.txt#L6152 and run ctest -L RUNS_ON_QEMU see if the test passes.

The tests couldn't be compiled currently for RISCV64: it needs a platform-depend fixes in suite/tests/client-interface/drwrap-drreg-test.dll.c, which requires implementing some functions in core/ir/riscv64/instr_create_api.h.in.

@ksco
Copy link
Contributor

ksco commented Mar 29, 2024

I suppose you’re referring to XINST_CREATE_cmp() and XINST_CREATE_jmp_cond? There won’t be such thing on RISC-V since we don’t have eflags. You can use INSTR_CREATE_beq() to rewrite this part for RISC-V.

@apach301
Copy link
Contributor Author

apach301 commented Apr 2, 2024

I suppose you’re referring to XINST_CREATE_cmp() and XINST_CREATE_jmp_cond? There won’t be such thing on RISC-V since we don’t have eflags. You can use INSTR_CREATE_beq() to rewrite this part for RISC-V.

Finally being able to compile and run tests. Test drwrap-callconv seems to work, but with drwrap-drreg things more complicated. The part with pre/post wrappers passes, the part with drreg save/restore registers fails.

Moreover, for riscv default callconv is not working, it requires explicitly setup DRWRAP_CALLCONV_RISCV_LP64 | DRWRAP_REPLACE_RETADDR flags

core/ir/riscv64/instr_create_api.h.in Outdated Show resolved Hide resolved
core/arch/asm_defines.asm Show resolved Hide resolved
core/arch/asm_defines.asm Show resolved Hide resolved
@ksco ksco requested a review from derekbruening April 2, 2024 17:13
@@ -331,7 +351,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(). */
Copy link
Contributor

@ksco ksco Apr 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reg_val_test() and multipath_test() are assembly functions and they are currently not ported to RISC-V, maybe add a TODO here if this is a future work.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrote assemblies, but it fails on assertion that check reg value restore functionality. I don't know whether it implemented, in this PR I supported only post-wrappers.

if (instr_get_opcode(inst) == OP_nop IF_ARM(|| instr_is_mov_nop(inst))) {
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@derekbruening Why don't we use if (instr_is_nop(inst)) { here for all architectures?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably originally because this is recognizing a specific opcode we control in the app and we don't want a broad check that recognizes other nop variants (on x86 there are several encoding variants of different sizes all considered nops). The tradeoff of a possible false positive pattern recognition might be outweighed by simpler cross-arch code so probably ok to change it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

suite/tests/CMakeLists.txt Outdated Show resolved Hide resolved
suite/tests/CMakeLists.txt Outdated Show resolved Hide resolved
@@ -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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Line too long. This should fail the clang-format check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@@ -104,8 +108,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");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Line too long. This should fail the clang-format check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@ksco
Copy link
Contributor

ksco commented Apr 3, 2024

Please don't do force push, see: https://dynamorio.org/page_code_reviews.html.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants