static void at_not_taken(app_pc src, app_pc fall) { int app_errno; dr_mcontext_t mcontext; void *drcontext = dr_get_current_drcontext(); /* * Record the fact that we've seen the fallthrough case. */ elem_t *elem = lookup(table, src); ASSERT(elem != NULL); elem->state |= CBR_NOT_TAKEN; dr_fprintf(STDERR, "cbr not taken\n"); /* * Remove the bb from the cache so it will be re-built the next * time it is executed. Since the flush will remove the fragment * we're already in, redirect execution to the target. */ dr_flush_region(src, 1); dr_get_mcontext(drcontext, &mcontext, &app_errno); mcontext.xip = fall; dr_redirect_execution(&mcontext, app_errno); }
/** Records given fragment. */ void record_frag(void* ctx, instrlist_t* frag, frag_id_t id) { bool flushed; struct trace_buffer_t* tb; tb = dr_get_tls_field(ctx); tb_tlv_complete(tb); for(flushed = false; ; tb_flush(tb), flushed = true) { struct frag_t* frag_data; void* current; tb_tlv(tb, TYPE_FRAG); frag_data = tb->current; current = record_frag_instrs(ctx, frag, &frag_data->chunks, tb_end(tb)); if(current) { frag_data->id = id; tb->current = current; tb_tlv_complete(tb); tb_tlv(tb, TYPE_TRACE); break; } else { if(flushed) { dr_fprintf(STDERR, "fatal: not enough buffer space after flush\n"); dr_exit_process(1); } tb_tlv_cancel(tb); } } }
dr_emit_flags_t handle_bb(void* ctx, void* tag, instrlist_t* bb, bool for_trace, bool translating) { bool new_frag; bool instrument; #ifdef TRACE_DEBUG dr_fprintf(STDERR, "debug: handle_bb(tag=%p, for_trace=%u, translating=%u)\n", tag, for_trace, translating); #endif check_ctx(ctx, "handle_bb"); new_frag = true; instrument = true; if(for_trace) { // Traces are instrumented separately, we only need to increment counter. new_frag = false; instrument = false; } if(translating) { // Reuse existing fragment when translating. new_frag = false; } handle_frag(ctx, tag, bb, new_frag, instrument, 0); return DR_EMIT_DEFAULT; }
DR_EXPORT void dr_init(client_id_t id) { dr_set_client_name("DynamoRIO Sample Client 'instrcalls'", "http://dynamorio.org/issues"); my_id = id; /* make it easy to tell, by looking at log file, which client executed */ dr_log(NULL, LOG_ALL, 1, "Client 'instrcalls' initializing\n"); /* also give notification to stderr */ #ifdef SHOW_RESULTS if (dr_is_notify_on()) { # ifdef WINDOWS /* ask for best-effort printing to cmd window. must be called in dr_init(). */ dr_enable_console_printing(); # endif dr_fprintf(STDERR, "Client instrcalls is running\n"); } #endif dr_register_exit_event(event_exit); dr_register_bb_event(event_basic_block); dr_register_thread_init_event(event_thread_init); dr_register_thread_exit_event(event_thread_exit); #ifdef SHOW_SYMBOLS if (drsym_init(0) != DRSYM_SUCCESS) { dr_log(NULL, LOG_ALL, 1, "WARNING: unable to initialize symbol translation\n"); } #endif }
DR_EXPORT void dr_client_main(client_id_t id, int argc, const char *argv[]) { module_data_t *appmod; dr_set_client_name("DynamoRIO Sample Client 'modxfer_app2lib'", "http://dynamorio.org/issues"); appmod = dr_get_main_module(); DR_ASSERT(appmod != NULL); app_base = appmod->start; app_end = appmod->end; dr_free_module_data(appmod); /* register events */ dr_register_exit_event(event_exit); dr_register_bb_event(event_basic_block); /* make it easy to tell, by looking at log file, which client executed */ dr_log(NULL, LOG_ALL, 1, "Client 'modxfer_app2lib' initializing\n"); #ifdef SHOW_RESULTS /* also give notification to stderr */ if (dr_is_notify_on()) { # ifdef WINDOWS /* ask for best-effort printing to cmd window. must be called at init. */ dr_enable_console_printing(); # endif dr_fprintf(STDERR, "Client modxfer_app2lib is running\n"); } #endif }
DR_EXPORT void dr_init(client_id_t id) { dr_register_exit_event(event_exit); dr_register_trace_event(event_trace); /* this optimization is only worthwhile on the Pentium 4, where * an add of 1 is faster than an inc */ enable = (proc_get_family() == FAMILY_PENTIUM_4); /* make it easy to tell, by looking at log file, which client executed */ dr_log(NULL, LOG_ALL, 1, "Client 'inc2add' initializing\n"); #ifdef SHOW_RESULTS /* also give notification to stderr */ if (dr_is_notify_on()) { # ifdef WINDOWS /* ask for best-effort printing to cmd window. must be called in dr_init(). */ dr_enable_console_printing(); # endif dr_fprintf(STDERR, "Client inc2add is running\n"); } #endif /* initialize our global variables */ num_examined = 0; num_converted = 0; }
static void thread_exit_event2(void *drcontext) { inc_count_second(EVENT_THREAD_EXIT_2); if (!dr_unregister_thread_exit_event(thread_exit_event2)) dr_fprintf(STDERR, "unregister failed!\n"); }
static void delete_event1(void *dcontext, void *tag) { inc_count_first(EVENT_DELETE_1, EVENT_DELETE_2); if (!dr_unregister_delete_event(delete_event1)) dr_fprintf(STDERR, "unregister failed!\n"); }
static void bb_table_print(void *drcontext, per_thread_t *data) { ASSERT(data != NULL, "data must not be NULL"); if (data->log == INVALID_FILE) { ASSERT(false, "invalid log file"); return; } dr_fprintf(data->log, "BB Table: %u bbs\n", drtable_num_entries(data->bb_table)); if (TEST(DRCOVLIB_DUMP_AS_TEXT, options.flags)) { dr_fprintf(data->log, "module id, start, size:\n"); drtable_iterate(data->bb_table, data, bb_table_entry_print); } else drtable_dump_entries(data->bb_table, data->log); }
DR_EXPORT void dr_client_main(client_id_t id, int argc, const char *argv[]) { drreg_options_t ops = { sizeof(ops), 2 /*max slots needed*/, false }; dr_set_client_name("DynamoRIO Sample Client 'countcalls'", "http://dynamorio.org/issues"); if (!drmgr_init() || drreg_init(&ops) != DRREG_SUCCESS) DR_ASSERT(false); /* register events */ dr_register_exit_event(event_exit); drmgr_register_thread_init_event(event_thread_init); drmgr_register_thread_exit_event(event_thread_exit); drmgr_register_bb_instrumentation_event(NULL, event_instruction, NULL); tls_idx = drmgr_register_tls_field(); /* make it easy to tell, by looking at log file, which client executed */ dr_log(NULL, DR_LOG_ALL, 1, "Client 'countcalls' initializing\n"); #ifdef SHOW_RESULTS /* also give notification to stderr */ if (dr_is_notify_on()) { # ifdef WINDOWS /* ask for best-effort printing to cmd window. must be called at init. */ dr_enable_console_printing(); # endif dr_fprintf(STDERR, "Client countcalls is running\n"); } #endif }
static void wrap_pre_SSL_write(void *wrapcxt, OUT void **user_data) { /* int SSL_write(SSL *ssl, const void *buf, int num); * * ssize_t gnutls_record_send(gnutls_session_t session, * const void * data, size_t sizeofdata); */ void *ssl = (void *)drwrap_get_arg(wrapcxt, 0); unsigned char *buf = (unsigned char *)drwrap_get_arg(wrapcxt, 1); size_t sz = (size_t)drwrap_get_arg(wrapcxt, 2); /* By generating unique filenames (per SSL context), we are able to * simplify logging of SSL traffic (no file locking is required). */ char filename[MAXIMUM_PATH] = { 0 }; dr_snprintf(filename, BUFFER_SIZE_ELEMENTS(filename), "trace-%x.write", ssl); NULL_TERMINATE_BUFFER(filename); FILE *fp = fopen(filename, "ab+"); /* Error handling of logging operations isn't critical - in fact, we don't * even know what to do in such error conditions, so we simply return! */ if (!fp) { dr_fprintf(STDERR, "Couldn’t open the output file %s\n", filename); return; } /* We assume that SSL_write always succeeds and writes the whole buffer. */ fwrite(buf, 1, sz, fp); fclose(fp); }
static void event_exit(void) { dr_mutex_destroy(syslock); CHECK(checked_tls_from_cache, "failed to hit clean call"); CHECK(checked_cls_from_cache, "failed to hit clean call"); CHECK(checked_tls_write_from_cache, "failed to hit clean call"); CHECK(checked_cls_write_from_cache, "failed to hit clean call"); CHECK(one_time_exec == 1, "failed to execute one-time event"); if (!drmgr_unregister_bb_instrumentation_event(event_bb_analysis)) CHECK(false, "drmgr unregistration failed"); if (!drmgr_unregister_bb_instrumentation_ex_event(event_bb4_app2app, event_bb4_analysis, event_bb4_insert, event_bb4_instru2instru)) CHECK(false, "drmgr unregistration failed"); if (!drmgr_unregister_cls_field(event_thread_context_init, event_thread_context_exit, cls_idx)) CHECK(false, "drmgr unregistration failed"); drmgr_exit(); dr_fprintf(STDERR, "all done\n"); }
DR_EXPORT void dr_client_main(client_id_t id, int argc, const char *argv[]) { dr_set_client_name("DynamoRIO Sample Client 'inline'", "http://dynamorio.org/issues"); if (!drmgr_init()) DR_ASSERT(false); hashtable_init_ex(&head_table, HASH_BITS, HASH_INTPTR, false/*!strdup*/, false/*synchronization is external*/, free_trace_head_entry, NULL, NULL); dr_register_exit_event(event_exit); if (!drmgr_register_bb_instrumentation_event(event_analyze_bb, NULL, NULL)) DR_ASSERT(false); dr_register_delete_event(event_fragment_deleted); dr_register_end_trace_event(query_end_trace); /* Make it easy to tell from the log file which client executed. */ dr_log(NULL, DR_LOG_ALL, 1, "Client 'inline' initializing\n"); #ifdef SHOW_RESULTS /* also give notification to stderr */ if (dr_is_notify_on()) { # ifdef WINDOWS /* Ask for best-effort printing to cmd window. Must be called at init. */ dr_enable_console_printing(); # endif dr_fprintf(STDERR, "Client inline is running\n"); } #endif }
static void event_exit(void) { /* ensure our file was not closed by the app */ if (!dr_file_seek(file, 0, DR_SEEK_SET)) dr_fprintf(STDERR, "seek error in exit event\n"); dr_close_file(file); dr_fprintf(STDERR, "file separation check\n"); /* i#1213: test float i/o. * Technically we should save fpstate (for detach) but we're not bothering. */ dr_fprintf(STDERR, "float i/o test: %6.5g\n", 3.1415916); dr_fprintf(STDERR, "done\n"); }
/* * Hardware division instructions are unlikely to run in time * independent of the data, so we log both their parameters. */ static void log_div(uint n, uint d, const char *loc) { if (outfile == INVALID_FILE || logging_paused) return; dr_fprintf(outfile, "%s: divide %"PRIuMAX" / %"PRIuMAX"\n", loc, (uintmax_t)n, (uintmax_t)d); }
DR_EXPORT void dr_init(client_id_t id) { client_id = id; dr_fprintf(STDERR, "thank you for testing the client interface\n"); drmgr_init(); cls_idx = drmgr_register_cls_field(event_thread_context_init, event_thread_context_exit); ASSERT(cls_idx != -1); dr_register_nudge_event(event_nudge, id); dr_register_filter_syscall_event(event_filter_syscall); drmgr_register_pre_syscall_event(event_pre_syscall); drmgr_register_post_syscall_event(event_post_syscall); dr_register_exit_event(event_exit); #ifdef WINDOWS sysnum_CreateProcess = get_sysnum("NtCreateProcess"); ASSERT(sysnum_CreateProcess != -1); /* not asserting on these since added later */ sysnum_CreateProcessEx = get_sysnum("NtCreateProcessEx"); sysnum_CreateUserProcess = get_sysnum("NtCreateUserProcess"); sysnum_ResumeThread = get_sysnum("NtResumeThread"); ASSERT(sysnum_ResumeThread != -1); #endif }
static void module_load_event1(void *drcontext, const module_data_t *info, bool loaded) { inc_count_first(EVENT_MODULE_LOAD_1, EVENT_MODULE_LOAD_2); if (!dr_unregister_module_load_event(module_load_event1)) dr_fprintf(STDERR, "unregister failed!\n"); }
DR_EXPORT void dr_init(client_id_t id) { module_data_t *data; dr_fprintf(STDERR, "thank you for testing the client interface\n"); dr_register_bb_event(bb_event); data = dr_lookup_module_by_name("kernel32.dll"); if (data != NULL) { exit_proc_addr = (void *)dr_get_proc_address(data->handle, "ExitProcess"); if (exit_proc_addr == NULL) dr_fprintf(STDERR, "ERROR: unable to find kernel32!ExitProcess\n"); dr_free_module_data(data); } else { dr_fprintf(STDERR, "ERROR: unable to find ntdll.dll\n"); } }
static void module_unload_event2(void *drcontext, const module_data_t *info) { inc_count_second(EVENT_MODULE_UNLOAD_2); if (!dr_unregister_module_unload_event(module_unload_event2)) dr_fprintf(STDERR, "unregister failed!\n"); }
static void thread_init_event1(void *drcontext) { inc_count_first(EVENT_THREAD_INIT_1, EVENT_THREAD_INIT_2); if (!dr_unregister_thread_init_event(thread_init_event1)) dr_fprintf(STDERR, "unregister failed!\n"); }
static void post_syscall_event2(void *drcontext, int sysnum) { inc_count_second(EVENT_POST_SYSCALL_2); if (!dr_unregister_post_syscall_event(post_syscall_event2)) dr_fprintf(STDERR, "unregister failed!\n"); }
static void fork_init_event1(void *drcontext) { inc_count_first(EVENT_FORK_INIT_1, EVENT_FORK_INIT_2); if (!dr_unregister_fork_init_event(fork_init_event1)) dr_fprintf(STDERR, "unregister failed!\n"); }
static void decrement(void *tag) { elem_t *elem; elem = find(tag); if (elem == NULL) { dr_fprintf(STDERR, "ERROR removing "PFX"\n", tag); } else { elem->count--; if (elem->count == 0) { if (head == elem) { head = elem->next; } if (tail == elem) { tail = elem->prev; } if (elem->next) { elem->next->prev = elem->prev; } if (elem->prev) { elem->prev->next = elem->next; } dr_global_free(elem, sizeof(elem_t)); } } }
void tb_flush(struct trace_buffer_t* tb) { size_t size; int64 pos; size_t written; void* aligned_current; tb_tlv_complete(tb); // Align current position to block boundary. aligned_current = aligned_block(tb->current); memset(tb->current, 'X', aligned_current - tb->current); tb->current = aligned_current; size = tb->current - (void*)&tb->block; if(size == sizeof(struct block_t)) { // Nothing to do. return; } tb->block.length = (uint32_t)size; tb->block.crc32 = 0; tb->block.crc32 = crc32((char*)&tb->block, size); // Write data. dr_mutex_lock(tb->mutex); pos = dr_file_tell(tb->file); if(pos == -1) { dr_fprintf(STDERR, "fatal: dr_file_tell() failed\n"); dr_exit_process(1); } dr_fprintf(STDERR, "info: flushing tb=%p file-offset=%" PRId64 " size=%u" " tb-thread=0x%" PRIx64 " current-thread=0x%" PRIx64 "\n", tb, pos, (unsigned int)size, tb->block.thread_id, (uint64_t)dr_get_thread_id(dr_get_current_drcontext())); written = dr_write_file(tb->file, &tb->block, size); dr_mutex_unlock(tb->mutex); if(written != size) { dr_fprintf(STDERR, "fatal: dr_write_file() failed\n"); dr_exit_process(1); } // Reset position. tb->current = tb + 1; }
static void exit_event(void) { if (drfuzz_exit() != DRMF_SUCCESS) EXPECT(false, "drfuzz failed to exit"); dr_fprintf(STDERR, "TEST PASSED\n"); drmgr_exit(); }
static bool filter_syscall_event2(void *drcontext, int sysnum) { inc_count_second(EVENT_FILTER_SYSCALL_2); if (!dr_unregister_filter_syscall_event(filter_syscall_event2)) dr_fprintf(STDERR, "unregister failed!\n"); return true; }
static bool pre_syscall_event1(void *drcontext, int sysnum) { inc_count_first(EVENT_PRE_SYSCALL_1, EVENT_PRE_SYSCALL_2); if (!dr_unregister_pre_syscall_event(pre_syscall_event1)) dr_fprintf(STDERR, "unregister failed!\n"); return true; }
static dr_custom_trace_action_t end_trace_event2(void *dcontext, void *trace_tag, void *next_tag) { inc_count_second(EVENT_END_TRACE_2); if (!dr_unregister_end_trace_event(end_trace_event2)) dr_fprintf(STDERR, "unregister failed!\n"); return CUSTOM_TRACE_DR_DECIDES; }
static dr_emit_flags_t bb_event(void* drcontext, void* tag, instrlist_t* bb, bool for_trace, bool translating) { dr_fprintf(STDERR, "got BB event\n"); dr_insert_clean_call(drcontext, bb, instrlist_first(bb), (void *)unregister, false, 0); return DR_EMIT_DEFAULT; }
static dr_custom_trace_action_t end_trace_event1(void *dcontext, void *trace_tag, void *next_tag) { inc_count_first(EVENT_END_TRACE_1, EVENT_END_TRACE_2); if (!dr_unregister_end_trace_event(end_trace_event1)) dr_fprintf(STDERR, "unregister failed!\n"); return 0; }