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#1551,i#1569,i#3544 Port sample 'cbr' to AARCHXX and RISCV64. #2

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/samples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,8 @@ add_sample_client(memtrace_simple "memtrace_simple.c;utils.c" "drmgr;drreg;druti
add_sample_client(memval_simple "memval_simple.c;utils.c" "drmgr;drreg;drutil;drx")
add_sample_client(instrace_simple "instrace_simple.c;utils.c" "drmgr;drreg;drx")
add_sample_client(opcode_count "opcode_count.cpp" "drmgr;drreg;drx;droption")
add_sample_client(cbr "cbr.c" "drmgr;drreg")
if (X86) # FIXME i#1551, i#1569, i#3544: port to ARM/AArch64/RISCV64
add_sample_client(cbr "cbr.c" "drmgr")
add_sample_client(countcalls "countcalls.c" "drmgr;drreg")
add_sample_client(inc2add "inc2add.c" "drmgr;drreg")
add_sample_client(memtrace_x86_binary "memtrace_x86.c;utils.c"
Expand Down
61 changes: 58 additions & 3 deletions api/samples/cbr.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@

#include "dr_api.h"
#include "drmgr.h"
#if defined(AARCHXX) || defined(RISCV64)
# include "drreg.h"
#endif

#define MINSERT instrlist_meta_preinsert

Expand All @@ -81,6 +84,11 @@
/* Possible cbr states */
typedef enum { CBR_NEITHER = 0x00, CBR_TAKEN = 0x01, CBR_NOT_TAKEN = 0x10 } cbr_state_t;

#if defined(AARCHXX) || defined(RISCV64)
drvector_t allowed_scratch; /* stolen register should not be reserved as scratch reg */
reg_id_t dr_reg_stolen;
#endif

/* Each bucket in the hash table is a list of the following elements.
* For each cbr, we store its address and its state.
*/
Expand Down Expand Up @@ -334,14 +342,49 @@ event_app_instruction(void *drcontext, void *tag, instrlist_t *bb, instr_t *inst
app_pc fall = (app_pc)decode_next_pc(drcontext, (byte *)src);
app_pc targ = instr_get_branch_target_pc(instr);

#if defined(AARCHXX) || defined(RISCV64)
/* For ARM and RISCV, if instr uses the stolen regs, we have to replace it with a
* scratch reg here, because instr will be set meta and can not be mangled later.
* We can not use drreg_get_app_value() as DR will refuse to load into the same
* reg returned by dr_get_stolen_reg(). See comment in drreg_get_app_value().
*/
if (instr_uses_reg(instr, dr_reg_stolen)) {
reg_id_t scratch_reg;
if (drreg_reserve_register(drcontext, bb, instr, &allowed_scratch,
&scratch_reg) != DRREG_SUCCESS) {
DR_ASSERT(false); /* cannot recover */
return DR_EMIT_DEFAULT;
}

dr_insert_get_stolen_reg_value(drcontext, bb, instr, scratch_reg);

for (int i = 0; i < instr_num_srcs(instr); i++) {
opnd_t src_opnd = instr_get_src(instr, i);
if (opnd_is_reg(src_opnd) && opnd_get_reg(src_opnd) == dr_reg_stolen) {
opnd_replace_reg(&src_opnd, dr_reg_stolen, scratch_reg);
instr_set_src(instr, i, src_opnd);
}
}

dr_insert_set_stolen_reg_value(drcontext, bb, instr_get_next(instr),
scratch_reg);

if (drreg_unreserve_register(drcontext, bb, instr_get_next(instr),
scratch_reg) != DRREG_SUCCESS) {
DR_ASSERT(false);
return DR_EMIT_DEFAULT;
}
}
#endif

/* Redirect the existing cbr to jump to a callout for
* the 'taken' case. We'll insert a 'not-taken'
* callout at the fallthrough address.
*/
instr_t *label = INSTR_CREATE_label(drcontext);
/* should be meta, and meta-instrs shouldn't have translations */
instr_set_meta_no_translation(instr);
/* it may not reach (in particular for x64) w/ our added clean call */
/* it may not reach w/ our added clean call */
if (instr_is_cti_short(instr)) {
/* if jecxz/loop we want to set the target of the long-taken
* so set instr to the return value
Expand Down Expand Up @@ -374,7 +417,8 @@ event_app_instruction(void *drcontext, void *tag, instrlist_t *bb, instr_t *inst
* well as Linux.
*/
instrlist_preinsert(
bb, NULL, INSTR_XL8(INSTR_CREATE_jmp(drcontext, opnd_create_pc(fall)), fall));
bb, NULL,
INSTR_XL8(XINST_CREATE_jump(drcontext, opnd_create_pc(fall)), fall));

/* label goes before the 'taken' callout */
MINSERT(bb, NULL, label);
Expand All @@ -392,7 +436,8 @@ event_app_instruction(void *drcontext, void *tag, instrlist_t *bb, instr_t *inst
* block (this should not be a meta-instruction).
*/
instrlist_preinsert(
bb, NULL, INSTR_XL8(INSTR_CREATE_jmp(drcontext, opnd_create_pc(targ)), targ));
bb, NULL,
INSTR_XL8(XINST_CREATE_jump(drcontext, opnd_create_pc(targ)), targ));
}
/* since our added instrumentation is not constant, we ask to store
* translations now
Expand Down Expand Up @@ -428,6 +473,9 @@ dr_exit(void)
#endif

delete_table(global_table);
#if defined(AARCHXX) || defined(RISCV64)
drvector_delete(&allowed_scratch);
#endif
drmgr_exit();
}

Expand All @@ -440,6 +488,13 @@ dr_client_main(client_id_t id, int argc, const char *argv[])
DR_ASSERT_MSG(false, "drmgr_init failed!");

global_table = new_table();

#if defined(AARCHXX) || defined(RISCV64)
drreg_init_and_fill_vector(&allowed_scratch, true);
dr_reg_stolen = dr_get_stolen_reg();
drreg_set_vector_entry(&allowed_scratch, dr_reg_stolen, false);
#endif

if (!drmgr_register_bb_instrumentation_event(NULL, event_app_instruction, NULL))
DR_ASSERT_MSG(false, "fail to register event_app_instruction!");
dr_register_exit_event(dr_exit);
Expand Down
6 changes: 2 additions & 4 deletions core/ir/riscv64/instr.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,10 +238,8 @@ instr_is_near_ubr(instr_t *instr)
bool
instr_is_cti_short(instr_t *instr)
{
/* The branch with smallest reach is direct branch, with range +/- 4 KiB.
* We have restricted MAX_FRAGMENT_SIZE on RISCV64 accordingly.
*/
return false;
int opc = instr_get_opcode(instr);
return (opc == OP_c_beqz || opc == OP_c_bnez);
}

bool
Expand Down
10 changes: 7 additions & 3 deletions core/ir/riscv64/ir_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,13 @@ remangle_short_rewrite(dcontext_t *dcontext, instr_t *instr, byte *pc, app_pc ta
instr_t *
convert_to_near_rel_arch(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr)
{
/* FIXME i#3544: Not implemented */
ASSERT_NOT_IMPLEMENTED(false);
return NULL;
int opc = instr_get_opcode(instr);
if (opc == OP_c_beqz)
instr_set_opcode(instr, OP_beq);
else if (opc == OP_c_bnez)
instr_set_opcode(instr, OP_bne);

return instr;
}

static int
Expand Down
Loading