Skip to content

Commit

Permalink
i#1569 AArch64: Implement clean call.
Browse files Browse the repository at this point in the history
Clean call analysis (analyze_clean_call) is not yet implemented.

Review-URL: https://codereview.appspot.com/302150043
  • Loading branch information
Kevin Zhou authored and egrimley-arm committed Jul 19, 2016
1 parent 6279847 commit d039d22
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 26 deletions.
4 changes: 3 additions & 1 deletion core/arch/aarch64/clean_call_opt.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ bool
analyze_clean_call(dcontext_t *dcontext, clean_call_info_t *cci, instr_t *where,
void *callee, bool save_fpstate, uint num_args, opnd_t *args)
{
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */
/* FIXME i#1569: NYI on AArch64 */
ASSERT_NOT_IMPLEMENTED(INTERNAL_OPTION(opt_cleancall) == 0);
clean_call_info_init(cci, callee, save_fpstate, num_args);
return false;
}

Expand Down
6 changes: 4 additions & 2 deletions core/arch/aarch64/instr_create.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,10 @@
opnd_add_flags((sht), DR_OPND_IS_SHIFT), (sha))
#define INSTR_CREATE_b(dc, pc) \
instr_create_0dst_1src((dc), OP_b, (pc))
#define INSTR_CREATE_br(dc, Xn) \
instr_create_0dst_1src((dc), OP_br, (Xn))
#define INSTR_CREATE_br(dc, xn) \
instr_create_0dst_1src((dc), OP_br, (xn))
#define INSTR_CREATE_blr(dc, xn) \
instr_create_0dst_1src((dc), OP_blr, (xn))
#define INSTR_CREATE_brk(dc, imm) \
instr_create_0dst_1src((dc), OP_brk, (imm))
#define INSTR_CREATE_cbnz(dc, pc, reg) \
Expand Down
20 changes: 5 additions & 15 deletions core/arch/aarchxx/mangle.c
Original file line number Diff line number Diff line change
Expand Up @@ -539,16 +539,12 @@ insert_parameter_preparation(dcontext_t *dcontext, instrlist_t *ilist, instr_t *
} else if (opnd_is_reg(args[i])) {
ASSERT_NOT_IMPLEMENTED(opnd_get_size(args[i]) == OPSZ_PTR);
if (opnd_get_reg(args[i]) == DR_REG_XSP) {
#ifdef AARCH64
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */
#else
instr_t *loc = instr_get_next(mark);
PRE(ilist, loc, instr_create_save_to_tls
(dcontext, regparms[i], TLS_REG0_SLOT));
insert_get_mcontext_base(dcontext, ilist, loc, regparms[i]);
PRE(ilist, loc, instr_create_restore_from_dc_via_reg
(dcontext, regparms[i], regparms[i], XSP_OFFSET));
#endif
} else if (opnd_get_reg(args[i]) != regparms[i]) {
POST(ilist, mark, XINST_CREATE_move(dcontext,
opnd_create_reg(regparms[i]),
Expand Down Expand Up @@ -582,18 +578,12 @@ insert_reachable_cti(dcontext_t *dcontext, instrlist_t *ilist, instr_t *where,
opnd_create_reg(scratch), ilist, where, NULL, NULL);
/* even if a call and not a jmp, we can skip this if it doesn't return */
if (!jmp && returns) {
#ifdef AARCH64
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1569 */
#else
PRE(ilist, where, INSTR_CREATE_blx_ind(dcontext, opnd_create_reg(scratch)));
#endif
PRE(ilist, where,
IF_AARCH64_ELSE(INSTR_CREATE_blr, INSTR_CREATE_blx_ind)
(dcontext, opnd_create_reg(scratch)));
} else {
#ifdef AARCH64
PRE(ilist, where, INSTR_CREATE_xx(dcontext, 0xd61f0000 | /* br x(scratch) */
(scratch - DR_REG_X0) << 5));
#else
PRE(ilist, where, INSTR_CREATE_bx(dcontext, opnd_create_reg(scratch)));
#endif
PRE(ilist, where,
XINST_CREATE_jump_reg(dcontext, opnd_create_reg(scratch)));
}
return false /* an ind branch */;
}
Expand Down
113 changes: 105 additions & 8 deletions core/arch/mangle_shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,12 +165,30 @@ prepare_for_clean_call(dcontext_t *dcontext, clean_call_info_t *cci,
if (SCRATCH_ALWAYS_TLS()) {
PRE(ilist, instr, instr_create_save_to_tls
(dcontext, SCRATCH_REG0, TLS_REG0_SLOT));

insert_get_mcontext_base(dcontext, ilist, instr, SCRATCH_REG0);

#ifdef AARCH64
/* We need an addtional scratch register for saving the SP.
* TLS_REG1_SLOT is not safe since it may be used by clients.
* Instead we save it to dcontext.mcontext.x0, which is not
* used by dr_save_reg (see definition of SPILL_SLOT_MC_REG).
*/
PRE(ilist, instr,
XINST_CREATE_store(dcontext,
OPND_CREATE_MEMPTR(SCRATCH_REG0, 0),
opnd_create_reg(SCRATCH_REG1)));
PRE(ilist, instr,
XINST_CREATE_move(dcontext, opnd_create_reg(SCRATCH_REG1),
opnd_create_reg(DR_REG_XSP)));
PRE(ilist, instr,
XINST_CREATE_store(dcontext,
opnd_create_dcontext_field_via_reg_sz
(dcontext, SCRATCH_REG0,
XSP_OFFSET, OPSZ_PTR),
opnd_create_reg(SCRATCH_REG1)));
#else
PRE(ilist, instr, instr_create_save_to_dc_via_reg
(dcontext, SCRATCH_REG0, REG_XSP, XSP_OFFSET));

(dcontext, SCRATCH_REG0, REG_XSP, XSP_OFFSET));
#endif
/* DSTACK_OFFSET isn't within the upcontext so if it's separate this won't
* work right. FIXME - the dcontext accessing routines are a mess of shared
* vs. no shared support, separate context vs. no separate context support etc. */
Expand All @@ -189,14 +207,30 @@ prepare_for_clean_call(dcontext_t *dcontext, clean_call_info_t *cci,
REG_XAX/*dc*/, REG_XSP/*scratch*/, true/*to priv*/);
}
#endif
#ifdef AARCH64
PRE(ilist, instr,
XINST_CREATE_load(dcontext,
opnd_create_reg(SCRATCH_REG1),
opnd_create_dcontext_field_via_reg_sz
(dcontext, SCRATCH_REG0,
DSTACK_OFFSET, OPSZ_PTR)));
PRE(ilist, instr,
XINST_CREATE_move(dcontext, opnd_create_reg(DR_REG_XSP),
opnd_create_reg(SCRATCH_REG1)));
/* Restore scratch_reg from dcontext.mcontext.x0. */
PRE(ilist, instr,
XINST_CREATE_load(dcontext, opnd_create_reg(SCRATCH_REG1),
OPND_CREATE_MEMPTR(SCRATCH_REG0, 0)));
#else
PRE(ilist, instr, instr_create_restore_from_dc_via_reg
(dcontext, SCRATCH_REG0, REG_XSP, DSTACK_OFFSET));

/* restore xax before pushing the context on the dstack */
#endif
/* Restore SCRATCH_REG0 before pushing the context on the dstack. */
PRE(ilist, instr, instr_create_restore_from_tls
(dcontext, SCRATCH_REG0, TLS_REG0_SLOT));
}
else {
IF_AARCH64(ASSERT_NOT_REACHED());
PRE(ilist, instr, instr_create_save_to_dcontext(dcontext, REG_XSP, XSP_OFFSET));
#ifdef WINDOWS
if (!cci->out_of_line_swap) {
Expand Down Expand Up @@ -316,13 +350,36 @@ cleanup_after_clean_call(dcontext_t *dcontext, clean_call_info_t *cci,
}
#endif

#ifdef AARCH64
/* TLS_REG1_SLOT is not safe since it may be used by clients.
* We save it to dcontext.mcontext.x0.
*/
PRE(ilist, instr,
XINST_CREATE_store(dcontext,
OPND_CREATE_MEMPTR(SCRATCH_REG0, 0),
opnd_create_reg(SCRATCH_REG1)));
PRE(ilist, instr,
XINST_CREATE_load(dcontext,
opnd_create_reg(SCRATCH_REG1),
opnd_create_dcontext_field_via_reg_sz
(dcontext, SCRATCH_REG0,
XSP_OFFSET, OPSZ_PTR)));
PRE(ilist, instr,
XINST_CREATE_move(dcontext, opnd_create_reg(DR_REG_XSP),
opnd_create_reg(SCRATCH_REG1)));
/* Restore scratch_reg from dcontext.mcontext.x0. */
PRE(ilist, instr,
XINST_CREATE_load(dcontext, opnd_create_reg(SCRATCH_REG1),
OPND_CREATE_MEMPTR(SCRATCH_REG0, 0)));
#else
PRE(ilist, instr, instr_create_restore_from_dc_via_reg
(dcontext, SCRATCH_REG0, REG_XSP, XSP_OFFSET));

(dcontext, SCRATCH_REG0, REG_XSP, XSP_OFFSET));
#endif
PRE(ilist, instr, instr_create_restore_from_tls
(dcontext, SCRATCH_REG0, TLS_REG0_SLOT));
}
else {
IF_AARCH64(ASSERT_NOT_REACHED());
#ifdef WINDOWS
if (!cci->out_of_line_swap) {
preinsert_swap_peb(dcontext, ilist, instr, !SCRATCH_ALWAYS_TLS(),
Expand Down Expand Up @@ -365,10 +422,30 @@ insert_meta_call_vargs(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr,
* which specifies that the caller must save xax (and xcx and xdx)
*/
insert_get_mcontext_base(dcontext, ilist, instr, SCRATCH_REG0);
# ifdef AARCH64
/* TLS_REG1_SLOT is not safe since it may be used by clients.
* We save it to dcontext.mcontext.x0.
*/
PRE(ilist, instr,
XINST_CREATE_store(dcontext,
OPND_CREATE_MEMPTR(SCRATCH_REG0, 0),
opnd_create_reg(SCRATCH_REG1)));
instrlist_insert_mov_immed_ptrsz(dcontext, (ptr_int_t)WHERE_CLEAN_CALLEE,
opnd_create_reg(SCRATCH_REG1),
ilist, instr, NULL, NULL);
PRE(ilist, instr,
instr_create_save_to_dc_via_reg(dcontext, SCRATCH_REG0, SCRATCH_REG1,
WHEREAMI_OFFSET));
/* Restore scratch_reg from dcontext.mcontext.x0. */
PRE(ilist, instr,
XINST_CREATE_load(dcontext, opnd_create_reg(SCRATCH_REG1),
OPND_CREATE_MEMPTR(SCRATCH_REG0, 0)));
# else
PRE(ilist, instr,
instr_create_save_immed_to_dc_via_reg(dcontext, SCRATCH_REG0,
WHEREAMI_OFFSET,
(uint) WHERE_CLEAN_CALLEE, OPSZ_4));
# endif
} else {
PRE(ilist, instr, XINST_CREATE_store(dcontext,
opnd_create_dcontext_field(dcontext, WHEREAMI_OFFSET),
Expand Down Expand Up @@ -410,9 +487,29 @@ insert_meta_call_vargs(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr,
if (SCRATCH_ALWAYS_TLS()) {
/* SCRATCH_REG0 is dead here: restore of the app stack will clobber xax */
insert_get_mcontext_base(dcontext, ilist, instr, SCRATCH_REG0);
# ifdef AARCH64
/* TLS_REG1_SLOT is not safe since it may be used by clients.
* We save it to dcontext.mcontext.x0.
*/
PRE(ilist, instr,
XINST_CREATE_store(dcontext,
OPND_CREATE_MEMPTR(SCRATCH_REG0, 0),
opnd_create_reg(SCRATCH_REG1)));
instrlist_insert_mov_immed_ptrsz(dcontext, (ptr_int_t)whereami,
opnd_create_reg(SCRATCH_REG1),
ilist, instr, NULL, NULL);
PRE(ilist, instr,
instr_create_save_to_dc_via_reg(dcontext, SCRATCH_REG0, SCRATCH_REG1,
WHEREAMI_OFFSET));
/* Restore scratch_reg from dcontext.mcontext.x0. */
PRE(ilist, instr,
XINST_CREATE_load(dcontext, opnd_create_reg(SCRATCH_REG1),
OPND_CREATE_MEMPTR(SCRATCH_REG0, 0)));
# else
PRE(ilist, instr,
instr_create_save_immed_to_dc_via_reg(dcontext, SCRATCH_REG0,
WHEREAMI_OFFSET, whereami, OPSZ_4));
# endif
} else {
PRE(ilist, instr, XINST_CREATE_store(dcontext,
opnd_create_dcontext_field(dcontext, WHEREAMI_OFFSET),
Expand Down
1 change: 1 addition & 0 deletions core/lib/instrument.c
Original file line number Diff line number Diff line change
Expand Up @@ -5321,6 +5321,7 @@ static const reg_id_t SPILL_SLOT_MC_REG[NUM_SPILL_SLOTS - NUM_TLS_SPILL_SLOTS] =
# endif
REG_XDI, REG_XSI, REG_XBP, REG_XDX, REG_XCX, REG_XBX
#elif defined(AARCHXX)
/* DR_REG_R0 is not used here. See prepare_for_clean_call. */
DR_REG_R6, DR_REG_R5, DR_REG_R4, DR_REG_R3, DR_REG_R2, DR_REG_R1
#endif /* X86/ARM */
};
Expand Down

0 comments on commit d039d22

Please sign in to comment.