warn when trying to encode an instrlist with labels without a second pass
Created by: toshipiazza
When creating a code cache with dr_nonheap_alloc
that has a jump, I find that all jumps to labels are replaced with an infinite loop because the jump's operand points to itself.
void
insert_jmp(void *drcontext, instrlist_t *ilist, instr_t *where)
{
instr_t *label = INSTR_CREATE_label(drcontext);
instrlist_meta_preinsert(ilist, where, XINST_CREATE_jump
(drcontext,
opnd_create_instr(label)));
instrlist_meta_preinsert(ilist, where, label);
}
static void *
code_cache_init(void *drcontext)
{
void *code_cache = dr_nonheap_alloc(dr_page_size(), DR_MEMPROT_READ |
DR_MEMPROT_WRITE |
DR_MEMPROT_EXEC);
instrlist_t *ilist = instrlist_create(drcontext);
instr_t *where = INSTR_CREATE_ret(drcontext);
instrlist_meta_append(ilist, where);
/* jumping to this label causes an infinite loop */
insert_jmp(drcontext, ilist, where);
instrlist_encode(drcontext, ilist, code_cache, false);
instrlist_clear_and_destroy(drcontext, ilist);
return code_cache;
}
static dr_emit_flags_t
event_basic_block(void *drcontext, void *tag, instrlist_t *bb,
bool for_trace, bool translating)
{
instr_t *where = instrlist_first(bb);
/* jumping to this label works... */
insert_jmp(drcontext, bb, where);
dr_insert_clean_call(drcontext, bb, where, code_cache_init(drcontext), false, 0);
return DR_EMIT_DEFAULT;
}
This is similar to what we do in the memtrace_x86
sample, however we use an absolute jump as opposed to a clean call in that sample.
I would like to use a clean call here, but if this behavior is intended I will instead use dr_prepare_for_call
followed by the absolute jump.