Ejemplo n.º 1
0
static void
event_thread_init(void *drcontext)
{
    per_thread_t *data = dr_thread_alloc(drcontext, sizeof(*data));
    memset(data->cache, 0, sizeof(data->cache));
    drmgr_set_tls_field(drcontext, tls_idx, data);
}
Ejemplo n.º 2
0
static void
event_thread_init(void *drcontext)
{
    per_thread_t *data = dr_thread_alloc(drcontext, sizeof(per_thread_t));
    DR_ASSERT(data != NULL);
    drmgr_set_tls_field(drcontext, tls_idx, data);

    /* Keep seg_base in a per-thread data structure so we can get the TLS
     * slot and find where the pointer points to in the buffer.
     */
    data->seg_base = dr_get_dr_segment_base(tls_seg);
    data->buf_base =
        dr_raw_mem_alloc(MEM_BUF_SIZE, DR_MEMPROT_READ | DR_MEMPROT_WRITE, NULL);
    DR_ASSERT(data->seg_base != NULL && data->buf_base != NULL);
    /* put buf_base to TLS as starting buf_ptr */
    BUF_PTR(data->seg_base) = data->buf_base;

    data->num_refs = 0;

    /* We're going to dump our data to a per-thread file.
     * On Windows we need an absolute path so we place it in
     * the same directory as our library. We could also pass
     * in a path as a client argument.
     */
    data->log =
        log_file_open(client_id, drcontext, NULL /* using client lib path */, "memtrace",
#ifndef WINDOWS
                      DR_FILE_CLOSE_ON_FORK |
#endif
                          DR_FILE_ALLOW_LARGE);
    data->logf = log_stream_from_file(data->log);
    fprintf(data->logf, "Format: <data address>: <data size>, <(r)ead/(w)rite/opcode>\n");
}
Ejemplo n.º 3
0
static void
event_thread_init(void *drcontext)
{
    per_thread_t *data;

    /* allocate thread private data */
    data = dr_thread_alloc(drcontext, sizeof(per_thread_t));
    drmgr_set_tls_field(drcontext, tls_index, data);
    data->buf_base = dr_thread_alloc(drcontext, MEM_BUF_SIZE);
    data->buf_ptr  = data->buf_base;
    /* set buf_end to be negative of address of buffer end for the lea later */
    data->buf_end  = -(ptr_int_t)(data->buf_base + MEM_BUF_SIZE);
    data->num_refs = 0;

    /* We're going to dump our data to a per-thread file.
     * On Windows we need an absolute path so we place it in
     * the same directory as our library. We could also pass
     * in a path as a client argument.
     */
    data->log = log_file_open(client_id, drcontext, NULL /* using client lib path */,
                              "instrace",
#ifndef WINDOWS
                              DR_FILE_CLOSE_ON_FORK |
#endif
                              DR_FILE_ALLOW_LARGE);
#ifdef OUTPUT_TEXT
    data->logf = log_stream_from_file(data->log);
    fprintf(data->logf, "Format: <instr address>,<opcode>\n");
#endif
}
Ejemplo n.º 4
0
static void
event_thread_init(void *drcontext)
{
    if (main_thread == 0)
        main_thread = dr_get_thread_id(drcontext);
    drmgr_set_tls_field(drcontext, tls_idx,
                        (void *)(ptr_int_t)dr_get_thread_id(drcontext));
}
Ejemplo n.º 5
0
/* callbacks for threads */
void <client_name>_thread_init(void *drcontext){
	per_thread_t * data;

	DEBUG_PRINT("%s - initializing thread %d\n", ins_pass_name, dr_get_thread_id(drcontext));
	data = dr_thread_alloc(drcontext, sizeof(per_thread_t));
	drmgr_set_tls_field(drcontext, tls_index, data);

}
Ejemplo n.º 6
0
static void thread_init_event(void *drcontext)
{
	struct per_thread_journal_state *new_jstate;

	new_jstate = xzalloc(sizeof(*new_jstate));

	drmgr_set_tls_field(drcontext, tls_idx, new_jstate);
}
Ejemplo n.º 7
0
static void
thread_init(void *dcontext)
{
    fuzz_pass_context_t *fp = thread_alloc(dcontext, sizeof(fuzz_pass_context_t),
                                           HEAPSTAT_MISC);
    memset(fp, 0, sizeof(fuzz_pass_context_t));
    fp->dcontext = dcontext;
    fp->thread_state = create_fault_state(dcontext);
    drmgr_set_tls_field(dcontext, tls_idx_fuzzer, (void *) fp);
}
Ejemplo n.º 8
0
static void
check_tls_write_from_cache(void)
{
    void *drcontext = dr_get_current_drcontext();
    CHECK(drmgr_get_tls_field(drcontext, tls_idx) == (void *) MAGIC_NUMBER_FROM_CACHE,
          "cls write from cache incorrect");
    /* now restore */
    drmgr_set_tls_field(drcontext, tls_idx,
                        (void *)(ptr_int_t)dr_get_thread_id(drcontext));
    checked_tls_write_from_cache = true;
}
Ejemplo n.º 9
0
static void
wrap_unwindtest_pre(void *wrapcxt, OUT void **user_data)
{
    if (drwrap_get_func(wrapcxt) != addr_longdone) {
        void *drcontext = dr_get_current_drcontext();
        ptr_uint_t val = (ptr_uint_t) drmgr_get_tls_field(drcontext, tls_idx);
        dr_fprintf(STDERR, "  <pre-long%d>\n", val);
        /* increment per level of regular calls on way up */
        val++;
        drmgr_set_tls_field(drcontext, tls_idx, (void *)val);
    }
}
Ejemplo n.º 10
0
static void
event_thread_init(void *drcontext)
{
    /* create an instance of our data structure for this thread */
    per_thread_t *data = (per_thread_t *)dr_thread_alloc(drcontext, sizeof(per_thread_t));
    /* store it in the slot provided in the drcontext */
    drmgr_set_tls_field(drcontext, tls_idx, data);
    data->num_direct_calls = 0;
    data->num_indirect_calls = 0;
    data->num_returns = 0;
    dr_log(drcontext, DR_LOG_ALL, 1, "countcalls: set up for thread " TIDFMT "\n",
           dr_get_thread_id(drcontext));
}
Ejemplo n.º 11
0
static void
module_unload_event(void *drcontext, const module_data_t *mod)
{
    if (strstr(dr_module_preferred_name(mod),
               "client.drwrap-test.appdll.") != NULL) {
        bool ok;
        ok = drwrap_replace(addr_replace, NULL, true);
        CHECK(ok, "un-replace failed");
        ok = drwrap_replace_native(addr_replace2, NULL, true, 0, NULL, true);
        CHECK(ok, "un-replace_native failed");
        ok = drwrap_replace_native(addr_replace_callsite, NULL, false, 0, NULL, true);
        CHECK(ok, "un-replace_native failed");

        unwrap_addr(addr_skip_flags, "skip_flags", mod, true, false);
        unwrap_addr(addr_level0, "level0", mod, true, true);
        unwrap_addr(addr_level1, "level1", mod, true, true);
        unwrap_addr(addr_level2, "level2", mod, true, true);
        unwrap_addr(addr_tailcall, "makes_tailcall", mod, true, true);
        unwrap_addr(addr_preonly, "preonly", mod, true, false);
        /* skipme, postonly, and runlots were already unwrapped */

        /* test longjmp */
        unwrap_unwindtest_addr(addr_long0, "long0", mod);
        unwrap_unwindtest_addr(addr_long1, "long1", mod);
        unwrap_unwindtest_addr(addr_long2, "long2", mod);
        unwrap_unwindtest_addr(addr_long3, "long3", mod);
        unwrap_unwindtest_addr(addr_longdone, "longdone", mod);
        drmgr_set_tls_field(drcontext, tls_idx, (void *)(ptr_uint_t)0);
#ifdef WINDOWS
        /* test SEH */
        if (load_count == 1) {
            ok = drwrap_unwrap(addr_long0, wrap_unwindtest_seh_pre,
                               wrap_unwindtest_seh_post);
            CHECK(ok, "unwrap failed");
            ok = drwrap_unwrap(addr_long1, wrap_unwindtest_seh_pre,
                               wrap_unwindtest_seh_post);
            CHECK(ok, "unwrap failed");
            ok = drwrap_unwrap(addr_long2, wrap_unwindtest_seh_pre,
                               wrap_unwindtest_seh_post);
            CHECK(ok, "unwrap failed");
            ok = drwrap_unwrap(addr_long3, wrap_unwindtest_seh_pre,
                               wrap_unwindtest_seh_post);
            CHECK(ok, "unwrap failed");
            ok = drwrap_unwrap(addr_longdone, wrap_unwindtest_seh_pre,
                               wrap_unwindtest_seh_post);
        }
        CHECK(ok, "unwrap failed");
#endif
    }
}
Ejemplo n.º 12
0
static void
event_thread_init(void *drcontext)
{
    if (main_thread == 0)
        main_thread = dr_get_thread_id(drcontext);
    drmgr_set_tls_field(drcontext, tls_idx,
                        (void *)(ptr_int_t)dr_get_thread_id(drcontext));
    if (!in_event_thread_init) {
        dr_mutex_lock(threadlock);
        if (!in_event_thread_init) {
            dr_fprintf(STDERR, "in event_thread_init\n");
            in_event_thread_init = true;
        }
        dr_mutex_unlock(threadlock);
    }
}
Ejemplo n.º 13
0
static void
wrap_unwindtest_post(void *wrapcxt, void *user_data)
{
    void *drcontext = dr_get_current_drcontext();
    ptr_uint_t val = (ptr_uint_t) drmgr_get_tls_field(drcontext, tls_idx);
    if (drwrap_get_func(wrapcxt) == addr_longdone) {
        /* ensure our post-calls were all called and we got back to 0 */
        CHECK(val == 0, "post-calls were bypassed");
    } else {
        /* decrement on way down */
        val--;
        dr_fprintf(STDERR, "  <post-long%d%s>\n", val,
                   wrapcxt == NULL ? " abnormal" : "");
        drmgr_set_tls_field(drcontext, tls_idx, (void *)val);
    }
}
Ejemplo n.º 14
0
static void
event_thread_init(void *drcontext)
{
    per_thread_t *data;
    static volatile int thread_count;

    if (options.native_until_thread > 0) {
        int local_count = dr_atomic_add32_return_sum(&thread_count, 1);
        NOTIFY(1, "@@@@@@@@@@@@@ new thread #%d "TIDFMT"\n",
               local_count, dr_get_thread_id(drcontext));
        if (go_native && local_count == options.native_until_thread) {
            void **drcontexts = NULL;
            uint num_threads, i;
            go_native = false;
            NOTIFY(1, "thread "TIDFMT" suspending all threads\n",
                   dr_get_thread_id(drcontext));
            if (dr_suspend_all_other_threads_ex(&drcontexts, &num_threads, NULL,
                                                DR_SUSPEND_NATIVE)) {
                NOTIFY(1, "suspended %d threads\n", num_threads);
                for (i = 0; i < num_threads; i++) {
                    if (dr_is_thread_native(drcontexts[i])) {
                        NOTIFY(2, "\txxx taking over thread #%d "TIDFMT"\n",
                               i, dr_get_thread_id(drcontexts[i]));
                        dr_retakeover_suspended_native_thread(drcontexts[i]);
                    } else {
                        NOTIFY(2, "\tthread #%d "TIDFMT" under DR\n",
                               i, dr_get_thread_id(drcontexts[i]));
                    }
                }
                if (!dr_resume_all_other_threads(drcontexts, num_threads)) {
                    ASSERT(false, "failed to resume threads");
                }
            } else {
                ASSERT(false, "failed to suspend threads");
            }
        }

    }
    /* allocate thread private data for per-thread cache */
    if (drcov_per_thread)
        data = thread_data_create(drcontext);
    else
        data = thread_data_copy(drcontext);
    drmgr_set_tls_field(drcontext, tls_idx, data);
}
Ejemplo n.º 15
0
static void
event_thread_init(void *drcontext)
{
    per_thread_t *data = dr_thread_alloc(drcontext, sizeof(per_thread_t));
    DR_ASSERT(data != NULL);
    data->reg_addr = DR_REG_NULL;
    drmgr_set_tls_field(drcontext, tls_idx, data);

    /* We're going to dump our data to a per-thread file.
     * On Windows we need an absolute path so we place it in
     * the same directory as our library. We could also pass
     * in a path as a client argument.
     */
    data->log =
        log_file_open(client_id, drcontext, NULL /* using client lib path */, "memval",
#ifndef WINDOWS
                      DR_FILE_CLOSE_ON_FORK |
#endif
                          DR_FILE_ALLOW_LARGE);
    data->logf = log_stream_from_file(data->log);
}
Ejemplo n.º 16
0
/* callbacks for threads */
void funcwrap_thread_init(void *drcontext){
	
	per_thread_t * data;
	char logfilename[MAX_STRING_LENGTH];
	char thread_id[MAX_STRING_LENGTH];

	DEBUG_PRINT("%s - initializing thread %d\n", ins_pass_name, dr_get_thread_id(drcontext));
	
	data = dr_thread_alloc(drcontext, sizeof(per_thread_t));
	if (log_mode){
		dr_snprintf(thread_id, MAX_STRING_LENGTH, "%d", dr_get_thread_id(drcontext));
		populate_conv_filename(logfilename, logdir, ins_pass_name, thread_id);
		data->logfile = dr_open_file(logfilename, DR_FILE_WRITE_OVERWRITE);
	}

	

	data->filter_func = false;
	data->nesting = 0;
	drmgr_set_tls_field(drcontext, tls_index, data);

	DEBUG_PRINT("%s - initializing thread done %d\n", ins_pass_name, dr_get_thread_id(drcontext));

}
Ejemplo n.º 17
0
void memtrace_thread_init(void *drcontext)
{
    char logfilename[MAX_STRING_LENGTH];
	char outfilename[MAX_STRING_LENGTH];
	char thread_id[MAX_STRING_LENGTH];
	char extra_info[MAX_STRING_LENGTH];

    char *dirsep;
    int len;
    per_thread_t *data;

	uint * stack_base;
	uint * deallocation_stack;

	int i = 0;

	DEBUG_PRINT("%s - initializing thread %d\n", ins_pass_name, dr_get_thread_id(drcontext));

    /* allocate thread private data */
    data = dr_thread_alloc(drcontext, sizeof(per_thread_t));
    drmgr_set_tls_field(drcontext, tls_index, data);
    data->buf_base = dr_thread_alloc(drcontext, MEM_BUF_SIZE);
    data->buf_ptr  = data->buf_base;
    /* set buf_end to be negative of address of buffer end for the lea later */
    data->buf_end  = -(ptr_int_t)(data->buf_base + MEM_BUF_SIZE);
    data->num_refs = 0;

    /* We're going to dump our data to a per-thread file.
     * On Windows we need an absolute path so we place it in
     * the same directory as our library. We could also pass
     * in a path and retrieve with dr_get_options().
     */

	dr_snprintf(thread_id, MAX_STRING_LENGTH, "%d", dr_get_thread_id(drcontext));

	if (log_mode){
		populate_conv_filename(logfilename, logdir, ins_pass_name, thread_id);
		data->logfile = dr_open_file(logfilename, DR_FILE_WRITE_OVERWRITE | DR_FILE_ALLOW_LARGE);
	}



	dr_snprintf(extra_info, MAX_STRING_LENGTH, "%s_%s", client_arg->extra_info, thread_id);

	populate_conv_filename(outfilename, client_arg->output_folder, ins_pass_name, extra_info);
	data->outfile = dr_open_file(outfilename, DR_FILE_WRITE_OVERWRITE | DR_FILE_ALLOW_LARGE);
	DR_ASSERT(data->outfile != INVALID_FILE);

	/* this is done for 32 bit applications */
	deallocation_stack = &data->stack_limit;
	stack_base = &data->stack_base;

	__asm{
			mov EAX, FS : [0x04]
			mov EBX, stack_base
			mov[EBX], EAX
			mov EAX, FS : [0xE0C]
			mov EBX, deallocation_stack
			mov[EBX], EAX
	}

	DEBUG_PRINT("%s - stack boundaries - %x,%x\n", ins_pass_name, data->stack_base, data->stack_limit);

	DEBUG_PRINT("%s - initializing thread done %d\n", ins_pass_name, dr_get_thread_id(drcontext));

}
Ejemplo n.º 18
0
void instrace_thread_init(void *drcontext)
{
    char outfilename[MAX_STRING_LENGTH];
	char logfilename[MAX_STRING_LENGTH];
	char thread_id[MAX_STRING_LENGTH];
	char extra_info[MAX_STRING_LENGTH];

    char *dirsep;
    int len;
    per_thread_t *data;
	char * mode;

	uint * stack_base;
	uint * deallocation_stack;

	DEBUG_PRINT("%s - initializing thread %d\n", ins_pass_name, dr_get_thread_id(drcontext));

    /* allocate thread private data */
    data = dr_thread_alloc(drcontext, sizeof(per_thread_t));
    drmgr_set_tls_field(drcontext, tls_index, data);
    data->buf_base = dr_thread_alloc(drcontext, INSTR_BUF_SIZE);
    data->buf_ptr  = data->buf_base;
    /* set buf_end to be negative of address of buffer end for the lea later */
	data->buf_end  = -(ptr_int_t)(data->buf_base + INSTR_BUF_SIZE);
    data->num_refs = 0;

    /* We're going to dump our data to a per-thread file.
     * On Windows we need an absolute path so we place it in
     * the same directory as our library. We could also pass
     * in a path and retrieve with dr_get_options().
     */
	dr_snprintf(thread_id, MAX_STRING_LENGTH, "%d", dr_get_thread_id(drcontext));
	if (log_mode){
		populate_conv_filename(logfilename, logdir, ins_pass_name, thread_id);
		data->logfile = dr_open_file(logfilename, DR_FILE_WRITE_OVERWRITE | DR_FILE_ALLOW_LARGE);
	}

	/* instrace types */
	if (client_arg->instrace_mode == OPERAND_TRACE){
		mode = "opnd";
	}
	else if (client_arg->instrace_mode == OPCODE_TRACE){
		mode = "opcode";
	}
	else if (client_arg->instrace_mode == DISASSEMBLY_TRACE){
		mode = "disasm";
	}
	else if (client_arg->instrace_mode == INS_DISASM_TRACE){
		mode = "asm_instr";
	}
	else{
		mode = "instr";
	}
	
	

	dr_snprintf(extra_info, MAX_STRING_LENGTH, "%s_%s_%s", client_arg->extra_info, mode, thread_id);

	populate_conv_filename(outfilename, client_arg->output_folder, ins_pass_name, extra_info);
	data->outfile = dr_open_file(outfilename, DR_FILE_WRITE_OVERWRITE | DR_FILE_ALLOW_LARGE);
	DR_ASSERT(data->outfile != INVALID_FILE);

	DEBUG_PRINT("%s - thread id : %d, new thread logging at - %s\n",ins_pass_name, dr_get_thread_id(drcontext),logfilename);

	data->static_array = (instr_t **)dr_thread_alloc(drcontext,sizeof(instr_t *)*client_arg->static_info_size);
	data->static_array_size = client_arg->static_info_size;
	data->static_ptr = 0;

	data->output_array = (output_t *)dr_thread_alloc(drcontext,OUTPUT_BUF_SIZE);

	deallocation_stack = &data->deallocation_stack;
	stack_base = &data->stack_base;

	__asm{
		mov EAX, FS : [0x04]
		mov EBX, stack_base
		mov [EBX], EAX
		mov EAX, FS : [0xE0C]
		mov EBX, deallocation_stack
		mov [EBX], EAX
	}

	DEBUG_PRINT("%s - thread %d stack information - stack_base %x stack_reserve %x\n", ins_pass_name,
		dr_get_thread_id(drcontext), data->stack_base, data->deallocation_stack);

	DEBUG_PRINT("%s - initializing thread done %d\n", ins_pass_name, dr_get_thread_id(drcontext));


}
Ejemplo n.º 19
0
static void
module_load_event(void *drcontext, const module_data_t *mod, bool loaded)
{
    if (strstr(dr_module_preferred_name(mod),
               "client.drwrap-test.appdll.") != NULL) {
        bool ok;
        instr_t inst;
        app_pc init_pc, pc, next_pc;

        load_count++;
        if (load_count == 2) {
            /* test no-frills */
            drwrap_set_global_flags(DRWRAP_NO_FRILLS);
        }

        addr_replace = (app_pc) dr_get_proc_address(mod->handle, "replaceme");
        CHECK(addr_replace != NULL, "cannot find lib export");
        ok = drwrap_replace(addr_replace, (app_pc) replacewith, false);
        CHECK(ok, "replace failed");

        addr_replace2 = (app_pc) dr_get_proc_address(mod->handle, "replaceme2");
        CHECK(addr_replace2 != NULL, "cannot find lib export");
        ok = drwrap_replace_native(addr_replace2, (app_pc) replacewith2, true/*at entry*/,
                                   0, (void *)(ptr_int_t)DRWRAP_NATIVE_PARAM, false);
        CHECK(ok, "replace_native failed");

        init_pc = (app_pc) dr_get_proc_address(mod->handle, "replace_callsite");
        CHECK(init_pc != NULL, "cannot find lib export");
        /* Find callsite: we assume we'll linearly hit a ret.  We take final call
         * to skip any PIC call.
         */
        instr_init(drcontext, &inst);
        pc = init_pc;
        do {
            instr_reset(drcontext, &inst);
            next_pc = decode(drcontext, pc, &inst);
            if (!instr_valid(&inst))
                break;
            /* if initial jmp, follow it to handle ILT-indirection */
            if (pc == init_pc && instr_is_ubr(&inst))
                next_pc = opnd_get_pc(instr_get_target(&inst));
            else if (instr_is_call(&inst))
                addr_replace_callsite = pc;
            pc = next_pc;
        } while (instr_valid(&inst) && !instr_is_return(&inst));
        CHECK(addr_replace_callsite != NULL, "cannot find lib export");
        ok = drwrap_replace_native(addr_replace_callsite, (app_pc) replace_callsite,
                                   false/*!at entry*/, 0,
                                   (void *)(ptr_int_t)DRWRAP_NATIVE_PARAM, false);
        CHECK(ok, "replace_native failed");
        instr_free(drcontext, &inst);

        wrap_addr(&addr_level0, "level0", mod, true, true);
        wrap_addr(&addr_level1, "level1", mod, true, true);
        wrap_addr(&addr_level2, "level2", mod, true, true);
        wrap_addr(&addr_tailcall, "makes_tailcall", mod, true, true);
        wrap_addr(&addr_skipme, "skipme", mod, true, true);
        wrap_addr(&addr_repeat, "repeatme", mod, true, true);
        wrap_addr(&addr_preonly, "preonly", mod, true, false);
        wrap_addr(&addr_postonly, "postonly", mod, false, true);
        wrap_addr(&addr_runlots, "runlots", mod, false, true);

        /* test longjmp */
        wrap_unwindtest_addr(&addr_long0, "long0", mod);
        wrap_unwindtest_addr(&addr_long1, "long1", mod);
        wrap_unwindtest_addr(&addr_long2, "long2", mod);
        wrap_unwindtest_addr(&addr_long3, "long3", mod);
        wrap_unwindtest_addr(&addr_longdone, "longdone", mod);
        drmgr_set_tls_field(drcontext, tls_idx, (void *)(ptr_uint_t)0);
#ifdef WINDOWS
        /* test SEH */
        /* we can't do this test for no-frills b/c only one wrap per addr */
        if (load_count == 1) {
            ok = drwrap_wrap_ex(addr_long0, wrap_unwindtest_seh_pre,
                                wrap_unwindtest_seh_post,
                                NULL, DRWRAP_UNWIND_ON_EXCEPTION);
            CHECK(ok, "wrap failed");
            ok = drwrap_wrap_ex(addr_long1, wrap_unwindtest_seh_pre,
                                wrap_unwindtest_seh_post,
                                NULL, DRWRAP_UNWIND_ON_EXCEPTION);
            CHECK(ok, "wrap failed");
            ok = drwrap_wrap_ex(addr_long2, wrap_unwindtest_seh_pre,
                                wrap_unwindtest_seh_post,
                                NULL, DRWRAP_UNWIND_ON_EXCEPTION);
            CHECK(ok, "wrap failed");
            ok = drwrap_wrap_ex(addr_long3, wrap_unwindtest_seh_pre,
                                wrap_unwindtest_seh_post,
                                NULL, DRWRAP_UNWIND_ON_EXCEPTION);
            CHECK(ok, "wrap failed");
            ok = drwrap_wrap_ex(addr_longdone, wrap_unwindtest_seh_pre,
                                wrap_unwindtest_seh_post,
                                NULL, DRWRAP_UNWIND_ON_EXCEPTION);
            CHECK(ok, "wrap failed");
        }
#endif
        /* test leaner wrapping */
        if (load_count == 2)
            drwrap_set_global_flags(DRWRAP_NO_FRILLS | DRWRAP_FAST_CLEANCALLS);
        wrap_addr(&addr_skip_flags, "skip_flags", mod, true, false);
    }
}