How to create BBs?

49 views
Skip to first unread message

Mohammad Ewais

unread,
Apr 20, 2022, 6:57:31 PM4/20/22
to DynamoRIO Users
Hi,

I am trying to skip a function call based on some condition. Ideally, I would use drwrap_skip_call to skip it, but since this is having issues currently, I am trying my own workaround.

To skip the call, when my instrumentation hits the first BB in the target function,  I want to explicitly check for some condition (in my TLS region) then based on it return or continue with the original BB.

In short, this is what I tried:
1. Use R11 as the TLS address (no reserving needed, caller saved and unused)
2. CMP TLS->condition against a value
3. Jcc over the next step
4. Return
5. Original BB, ending with Jcc

This fails because of DR's constraints on BB jumps, so instead I would like to split it to 3 BBs. The first containing steps 1, 2, and 3. The second containing 4. And the third containing the original values. 

So, instead, I tried the following:

if (bb is beginning of func)
{
    static bool first_step = false;
    static bool second_step = false;
    instr_t* first = instrlist_first(bb);
    if (!first_step)
    {
        // Get TLS. Use R11 for the TLS, this is the beginning of the function so definitely not used.
        // Flags don't matter either
        reg_id_t tls_reg = DR_REG_R11;
        drmgr_insert_read_tls_field(drctx, tls_index, bb, first, tls_reg);
        // Test
        opnd_t check_opnd = opnd_create_base_disp(tls_reg, DR_REG_NULL, 0,
                                                  offsetof(TLSInfo, skip_fn), OPSZ_1);
        instr_t* tmp = INSTR_CREATE_cmp(drctx, check_opnd, opnd_create_immed_uint(1, OPSZ_1));
        instr_set_translation(tmp, instr_get_app_pc(first) - 1);
        instrlist_meta_preinsert(bb, first, tmp);
        // conditional jump to original bb if not skip
        tmp = INSTR_CREATE_jcc(drctx, OP_jne, opnd_create_pc(instr_get_app_pc(first)));
        instr_set_translation(tmp, instr_get_app_pc(first) - 1);
        instrlist_preinsert(bb, first, tmp);
        // Remove the rest of the BB
        for (instr_t* inst = first; inst != nullptr; )
        {
            instr_t* next_inst = instr_get_next(inst);
            instrlist_remove(bb, inst);
            inst = next_inst;
        }
        // end first step
        first_step = true;
        return DR_EMIT_DEFAULT;
    }
    else if (!second_step)
    {
        // Ret
        instr_t* ret = INSTR_CREATE_ret(drctx);
        instr_set_translation(ret, instr_get_app_pc(first)-1);
        instrlist_preinsert(bb, first, ret);
        // Remove the rest of the BB
        for (instr_t* inst = first; inst != nullptr; )
        {
            instr_t* next_inst = instr_get_next(inst);
            instrlist_remove(bb, inst);
            inst = next_inst;
        }
        // end second step
        second_step = true;
    }
}


This obviously fails. It would make all three BBs share the same tag and thus would cause looping issues with step #3 (BB1 loops for a while first, then BB2 runs instead in a trace, BB3 never hits). So, my question is how to create new BBs without sharing the tag with the original? How to avoid this behavior?

Derek Bruening

unread,
Apr 20, 2022, 11:42:15 PM4/20/22
to Mohammad Ewais, DynamoRIO Users
On Wed, Apr 20, 2022 at 6:57 PM Mohammad Ewais <mohammad...@gmail.com> wrote:
Hi,

I am trying to skip a function call based on some condition. Ideally, I would use drwrap_skip_call to skip it, but since this is having issues currently, I am trying my own workaround.

--
You received this message because you are subscribed to the Google Groups "DynamoRIO Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dynamorio-use...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dynamorio-users/b020acec-e54d-45b1-8086-b12a3fd7b6b4n%40googlegroups.com.

Mohammad Ewais

unread,
Apr 21, 2022, 12:26:29 AM4/21/22
to DynamoRIO Users
I'll give it a try.

But for now, in general, is there a way to create BBs with custom tags? or is the only way to create them off of existing BBs?

Derek Bruening

unread,
Apr 21, 2022, 9:53:23 AM4/21/22
to Mohammad Ewais, DynamoRIO Users
For two blocks for the same app entry point, one way is pointed out in this thread: include the first instr of the bb in the first block and have the 2nd block use the 2nd instr as the tag (assuming 1st instr is not a conditional branch), resulting in two different tags.  A hackier scheme is also proposed as Option C at https://github.com/DynamoRIO/dynamorio/issues/4948#issuecomment-1064249371.

For having the return in the same block: drwrap_skip_call emulates the stack adjustment and then uses dr_redirect_execution.  Or dr_redirect_native_target can be used to accomplish an app control transfer without an app instruction.

Xref similar issues with proposed features for calling app code: https://github.com/DynamoRIO/dynamorio/issues/497, https://github.com/DynamoRIO/dynamorio/issues/758.

If a synthetic tag approach is taken: it needs to point at real code in memory; even if initially filled in with something like dr_prepopulate_cache and translations set to be stored instead of recreated, cache capacity or consistency may result in  rebuilding the block and DR will go decode from there.


Reply all
Reply to author
Forward
0 new messages