/* Annotation handler to initialize a client context (associated with an app thread) */ static void init_context(uint id, const char *label, uint initial_mode) { context_t *context; dr_mutex_lock(context_lock); PRINTF("Initialize context %d '%s' in mode %d", id, label, initial_mode); context = get_context(id); if (context == NULL) { uint label_length = (uint) (sizeof(char) * strlen(label)) + 1; context = dr_global_alloc(sizeof(context_t)); context->id = id; context->label = dr_global_alloc(label_length); context->mode = initial_mode; context->mode_history = dr_global_alloc(MAX_MODE_HISTORY * sizeof(uint)); context->mode_history[0] = initial_mode; context->mode_history_index = 1; memcpy(context->label, label, label_length); context->next = NULL; if (context_list->head == NULL) { context_list->head = context_list->tail = context; } else { context_list->tail->next = context; context_list->tail = context; } } dr_mutex_unlock(context_lock); }
/* Parse CL options and register DR event handlers and annotation handlers */ DR_EXPORT void dr_client_main(client_id_t id, int argc, const char *argv[]) { context_lock = dr_mutex_create(); write_lock = dr_mutex_create(); # ifdef WINDOWS dr_enable_console_printing(); # endif client_id = id; /* XXX: should use droption */ if (argc > 1 && strcmp(argv[1], "full-decode") == 0) { PRINTF("Init annotation test client with full decoding"); dr_register_bb_event(empty_bb_event); } else if (argc > 1 && strlen(argv[1]) >= 8 && strncmp(argv[1], "truncate", 8) == 0) { bb_truncation_length = (argv[1][9] - '0'); /* format is "truncate@n" (0<n<10) */ ASSERT(bb_truncation_length < 10 && bb_truncation_length > 0); PRINTF("Init annotation test client with bb truncation"); dr_register_bb_event(bb_event_truncate); } else { PRINTF("Init annotation test client with fast decoding"); } context_list = dr_global_alloc(sizeof(context_list_t)); memset(context_list, 0, sizeof(context_list_t)); #if !(defined (WINDOWS) && defined (X64)) mem_defines = dr_global_alloc(sizeof(mem_defines_t)); memset(mem_defines, 0, sizeof(mem_defines_t)); #endif dr_register_exit_event(event_exit); register_call("test_annotation_init_mode", (void *) init_mode, 1); register_call("test_annotation_init_context", (void *) init_context, 3); register_call("test_annotation_get_mode", (void *) get_mode, 1); register_call("test_annotation_set_mode", (void *) set_mode, 2); #if !(defined (WINDOWS) && defined (X64)) register_call("test_annotation_rotate_valgrind_handler", (void *) rotate_valgrind_handler, 1); #endif register_call("test_annotation_eight_args", (void *) test_eight_args_v1, 8); register_call("test_annotation_eight_args", (void *) test_eight_args_v2, 8); /* Test removing the last handler */ dr_annotation_unregister_call("test_annotation_eight_args", test_eight_args_v1); register_call("test_annotation_nine_args", (void *) test_nine_args_v1, 9); register_call("test_annotation_nine_args", (void *) test_nine_args_v2, 9); /* Test removing the first handler */ dr_annotation_unregister_call("test_annotation_nine_args", test_nine_args_v2); /* Test multiple handlers */ register_call("test_annotation_ten_args", (void *) test_ten_args_v1, 10); register_call("test_annotation_ten_args", (void *) test_ten_args_v2, 10); dr_annotation_register_return("test_annotation_get_client_version", (void *) "2.2.8"); }
/* adds an address to the linear list with addresses */ static bbinfo_t * add_bb_to_list (bbinfo_t * bb_list, unsigned int addr, bool extra_info, uint size){ DR_ASSERT(size > bb_list[0].start_addr); bb_list[0].start_addr++; //first element of the start address will have the length bb_list[bb_list[0].start_addr].start_addr = addr; bb_list[bb_list[0].start_addr].freq = 0; bb_list[bb_list[0].start_addr].printable = true; if(extra_info){ //initialize from and to bbs bb_list[bb_list[0].start_addr].from_bbs = (call_bb_info_t *)dr_global_alloc(sizeof(call_bb_info_t)*MAX_TARGETS); bb_list[bb_list[0].start_addr].from_bbs[0].start_addr = 0; bb_list[bb_list[0].start_addr].to_bbs = (call_bb_info_t *)dr_global_alloc(sizeof(call_bb_info_t)*MAX_TARGETS); bb_list[bb_list[0].start_addr].to_bbs[0].start_addr = 0; //initialize call target bb_list[bb_list[0].start_addr].called_from = (call_target_info_t *)dr_global_alloc(sizeof(call_target_info_t)*MAX_TARGETS); bb_list[bb_list[0].start_addr].called_from[0].bb_addr = 0; //initialize called tos bb_list[bb_list[0].start_addr].called_to = (call_target_info_t *)dr_global_alloc(sizeof(call_target_info_t)*MAX_TARGETS); bb_list[bb_list[0].start_addr].called_to[0].bb_addr = 0; bb_list[bb_list[0].start_addr].func = NULL; bb_list[bb_list[0].start_addr].func_addr = 0; } return &bb_list[bb_list[0].start_addr]; }
static void increment(void *tag) { elem_t *elem; elem = find(tag); if (elem != NULL) { elem->count++; } else { elem = dr_global_alloc(sizeof(elem_t)); elem->tag = tag; elem->count = 1; elem->next = NULL; elem->prev = NULL; if (head == NULL) { head = elem; tail = elem; } else { tail->next = elem; elem->prev = tail; tail = elem; } } }
static void * hash_alloc(size_t size) { if (alloc_func != NULL) return (*alloc_func)(size); else return dr_global_alloc(size); }
/* gets a new element */ static module_t * new_elem (char * name, unsigned int list_length){ module_t * elem = (module_t *)dr_global_alloc(sizeof(module_t)); elem->module = (char *)dr_global_alloc(sizeof(char)*MAX_STRING_LENGTH); strncpy(elem->module,name,MAX_STRING_LENGTH); elem->bbs = (bbinfo_t *)dr_global_alloc(sizeof(bbinfo_t)*list_length); elem->bbs[0].start_addr = 0; // this is there for storing the length elem->size_bbs = list_length; elem->next = NULL; return elem; }
module_table_t * module_table_create() { module_table_t *table = dr_global_alloc(sizeof(*table)); memset(table->cache, 0, sizeof(table->cache)); drvector_init(&table->vector, 16, false, module_table_entry_free); return table; }
/** Allocates storage for wrapper context. */ static struct wrap* alloc_wrap() { struct wrap* wrap = ( struct wrap* )dr_global_alloc( sizeof( struct wrap ) ); if( wrap == NULL ) { dr_printf( "Failed to allocate memory for struct wrap\n" ); exit( 1 ); } return wrap; }
static list_t *new_list() { list_t *list = (list_t *)dr_global_alloc(sizeof(list_t)); list->head = NULL; list->tail = NULL; return list; }
/** Allocates, initializes and registers a new tag_info structure. * Must be called with tags_lock held. */ struct tag_info_t* tag_info_new(void* tag) { struct tag_info_t* tag_info = dr_global_alloc(sizeof(struct tag_info_t)); tag_info->id = 0; tag_info->counter = 0; memset(&tag_info->instr_info, 0, sizeof(struct instr_info_t)); hashtable_add(&tags, tag, tag_info); return tag_info; }
static bool parse_commandline_args(const char * args) { client_arg = (client_arg_t *)dr_global_alloc(sizeof(client_arg_t)); if (dr_sscanf(args, "%s", &client_arg->filter_filename) != 1){ return false; } return true; }
static void drvector_increase_size(drvector_t *vec, uint newcap) { void **newarray = dr_global_alloc(newcap * sizeof(void *)); if (vec->array != NULL) { memcpy(newarray, vec->array, vec->entries * sizeof(void *)); dr_global_free(vec->array, vec->capacity * sizeof(void *)); } vec->array = newarray; vec->capacity = newcap; }
static char * get_mem_dump_filename(app_pc base_pc, uint size, uint write, uint other_info){ char other_details[MAX_STRING_LENGTH]; char * filename = dr_global_alloc(sizeof(char) * MAX_STRING_LENGTH); dr_snprintf(other_details, MAX_STRING_LENGTH, "%x_%d_%d_%d", base_pc, size, write, other_info); populate_conv_filename(filename, client_arg->output_folder, ins_pass_name, other_details); return filename; }
static bool parse_commandline_args (const char * args) { client_arg = (client_arg_t *)dr_global_alloc(sizeof(client_arg_t)); if(dr_sscanf(args,"%s %d %s %s",&client_arg->filter_filename, &client_arg->filter_mode, &client_arg->output_folder, &client_arg->extra_info)!=4){ return false; } return true; }
static trace_head_entry_t * create_trace_head_entry(void *tag) { trace_head_entry_t *e = (trace_head_entry_t *) dr_global_alloc(sizeof(*e)); e->tag = tag; e->end_next = 0; e->size = 0; e->has_ret = false; e->is_trace_head = false; e->refcount = 1; return e; }
hash_table_t new_table() { int i; hash_table_t table = (hash_table_t)dr_global_alloc (sizeof(list_t *) * HASH_TABLE_SIZE); for (i=0; i<HASH_TABLE_SIZE; i++) { table[i] = NULL; } return table; }
static elem_t *new_elem(app_pc addr, cbr_state_t state) { elem_t *elem = (elem_t *)dr_global_alloc(sizeof(elem_t)); ASSERT(elem != NULL); elem->next = NULL; elem->addr = addr; elem->state = state; return elem; }
/* * Record the allocation of some memory. (Common code between malloc * and realloc.) */ static void allocated(void *ptr, size_t size) { if (outfile == INVALID_FILE) return; /* no need to track allocations outside a logging interval */ struct allocation *alloc = dr_global_alloc(sizeof(struct allocation)); alloc->start = (uintptr_t)ptr; alloc->size = size; alloc->index = next_alloc_index++; alloc->prev = alloc_ends->prev; alloc->next = alloc_ends; alloc->prev->next = alloc->next->prev = alloc; }
static void event_module_load(void *drcontext, const module_data_t *data, bool loaded) { module_entry_t *entry = NULL; module_data_t *mod; int i; /* Some apps repeatedly unload and reload the same module, * so we will try to re-use the old one. */ ASSERT(data != NULL, "data must not be NULL"); drvector_lock(&module_table.vector); /* Assuming most recently loaded entries are most likely to be unloaded, * we iterate the module table in a backward way for better performance. */ for (i = module_table.vector.entries-1; i >= 0; i--) { entry = drvector_get_entry(&module_table.vector, i); mod = entry->data; if (entry->unload && /* If the same module is re-loaded at the same address, * we will try to use the existing entry. */ mod->start == data->start && mod->end == data->end && mod->entry_point == data->entry_point && #ifdef WINDOWS mod->checksum == data->checksum && mod->timestamp == data->timestamp && #endif /* If a module w/ no name (there are some) is loaded, we will * keep making new entries. */ dr_module_preferred_name(data) != NULL && dr_module_preferred_name(mod) != NULL && strcmp(dr_module_preferred_name(data), dr_module_preferred_name(mod)) == 0) { entry->unload = false; break; } entry = NULL; } if (entry == NULL) { entry = dr_global_alloc(sizeof(*entry)); entry->id = module_table.vector.entries; entry->unload = false; entry->data = dr_copy_module_data(data); drvector_append(&module_table.vector, entry); } drvector_unlock(&module_table.vector); global_module_cache_add(module_table.cache, entry); }
/* WARNING i#262: if you use the cmake binary package, ctest is built * without a GNU_STACK section, which causes the linux kernel to set * the READ_IMPLIES_EXEC personality flag, which is propagated to * children and causes all mmaps to be +x, breaking all these tests * that check for mmapped memory to be +rw or +r! */ static void global_test(void) { char *array; uint prot; dr_fprintf(STDERR, " testing global memory alloc..."); array = dr_global_alloc(SIZE); write_array(array); dr_query_memory((const byte *)array, NULL, NULL, &prot); if (prot != get_os_mem_prot(DR_MEMPROT_READ|DR_MEMPROT_WRITE)) dr_fprintf(STDERR, "[error: prot %d doesn't match rw] ", prot); dr_global_free(array, SIZE); dr_fprintf(STDERR, "success\n"); }
bool drvector_init(drvector_t *vec, uint initial_capacity, bool synch, void (*free_data_func)(void*)) { if (vec == NULL) return false; vec->array = dr_global_alloc(initial_capacity * sizeof(void*)); vec->entries = 0; vec->capacity = initial_capacity; vec->synch = synch; vec->lock = dr_mutex_create(); vec->free_data_func = free_data_func; return true; }
static void do_mem_dump(file_t file, uint base_pc,uint size){ uint read; bool ok; byte * mem_values = dr_global_alloc(sizeof(byte) * size); ssize_t written; ok = dr_safe_read(base_pc, size, mem_values, &read); DR_ASSERT(ok); written = dr_write_file(file, mem_values, size); DEBUG_PRINT("read %d from %x of size %d and written %d\n", read, base_pc, size, written); dr_global_free(mem_values, sizeof(byte) * size); }
static bool drmgr_generic_event_add(generic_event_entry_t **list, void *rwlock, void (*func)(void)) { generic_event_entry_t *e; if (func == NULL) return false; dr_rwlock_write_lock(rwlock); e = (generic_event_entry_t *) dr_global_alloc(sizeof(*e)); e->cb.generic_cb = func; e->next = *list; *list = e; dr_rwlock_write_unlock(rwlock); return true; }
drcovlib_status_t drmodtrack_dump(file_t log) { drcovlib_status_t res; size_t size = 200 + module_table.vector.entries * (MAXIMUM_PATH + 40); char *buf; do { buf = dr_global_alloc(size); res = drmodtrack_dump_buf(buf, size); if (res == DRCOVLIB_SUCCESS) dr_write_file(log, buf, strlen(buf)); dr_global_free(buf, size); size *= 2; } while (res == DRCOVLIB_ERROR_BUF_TOO_SMALL); return res; }
/* Caller must hold htable_mutex if drcontext == NULL. */ static trace_head_entry_t * add_trace_head_entry(void *drcontext, void *tag) { trace_head_entry_t **table = htable; trace_head_entry_t *e; uint hindex; e = (trace_head_entry_t *) dr_global_alloc(sizeof(trace_head_entry_t)); e->tag = tag; e->end_next = 0; e->size = 0; e->has_ret = false; e->is_trace_head = false; hindex = (uint) HASH_FUNC_BITS((ptr_uint_t)tag, HASH_BITS); e->next = table[hindex]; table[hindex] = e; return e; }
static void read_table() { file_t file; bool read_entry = true; file = dr_open_file(table_def_file_name, DR_FILE_READ); if (file == INVALID_FILE) { DISPLAY_FUNC(NAME" error opening config file \"%s\"\n", table_def_file_name); return; } VVDISPLAY_FUNC(NAME" reading config file: \"%s\"\n", table_def_file_name); do { table_entry_t *entry = (table_entry_t *)dr_global_alloc(sizeof(table_entry_t)); if (dr_read_file(file, &entry->value, sizeof(table_value_t)) != sizeof(table_value_t)) { /* end of file */ read_entry = false; dr_global_free(entry, sizeof(table_entry_t)); } else { int i; /* insert NULL termination for module name (including space padding) */ for (i = sizeof(entry->value.module_name) - 1; i >= 0 && entry->value.module_name[i] == ' '; i--) { entry->value.module_name[i] = '\0'; } /* just in case */ entry->value.module_name[sizeof(entry->value.module_name)-1] = '\0'; /* add to the table */ entry->next = table; table = entry; VVDISPLAY_FUNC(NAME" read entry for module=\"%s\" to_stack=%s to_heap=%s " "transfer_to_here=%s\n", entry->value.module_name, (entry->value.allow_to_stack == 'y' || entry->value.allow_to_stack == 'Y') ? "yes" : "no", (entry->value.allow_to_heap == 'y' || entry->value.allow_to_heap == 'Y') ? "yes" : "no", (entry->value.allow_to_here == 'y' || entry->value.allow_to_here == 'Y') ? "yes" : "no"); } } while (read_entry); VVDISPLAY_FUNC(NAME" done reading config file."); }
static void wrap_pre_SSL_read(void *wrapcxt, OUT void **user_data) { struct SSL_read_data *sd; /* int SSL_read(SSL *ssl, void *buf, int num); * * ssize_t gnutls_record_recv(gnutls_session_t session, * void * data, size_t sizeofdata); */ sd = dr_global_alloc(sizeof(struct SSL_read_data)); sd->read_buffer = (unsigned char *)drwrap_get_arg(wrapcxt, 1); sd->ssl = (void *)drwrap_get_arg(wrapcxt, 0); *user_data = (void *)sd; }
/* Library offset has to be computed before the probe library is loaded * into memory. Reading it from the map file is one of the easiest ways to * do it. */ unsigned int get_symbol_offset_from_map(const char *map_file, const char *symbol) { const char *pref_addr_str = "Preferred load address is "; unsigned int pref_base, sym_addr, offset = 0xdeadc0de; ssize_t file_sz; file_t fd = INVALID_FILE; char *buf, *temp; fd = dr_open_file(map_file, DR_FILE_READ); if (fd == INVALID_FILE) goto _get_module_offset_exit; /* This seems to be the easiest way to get the size of the file. */ if (!dr_file_seek(fd, 0, DR_SEEK_END)) goto _get_module_offset_exit; file_sz = (ssize_t) dr_file_tell(fd); if (file_sz <= 0) goto _get_module_offset_exit; if (!dr_file_seek(fd, 0, DR_SEEK_SET)) goto _get_module_offset_exit; /* Read the whole file. */ buf = dr_global_alloc(file_sz + 1); if (buf == NULL) goto _get_module_offset_exit; dr_read_file(fd, buf, file_sz); buf[file_sz] = '\0'; /* Locate preferred base & symbol address. */ temp = strstr(buf, pref_addr_str); if (temp != NULL) { pref_base = strtoul(temp + strlen(pref_addr_str), NULL, 16); temp = strstr(buf, symbol); if (temp != NULL) sym_addr = strtoul(temp + strlen(symbol), NULL, 16); offset = sym_addr - pref_base; } dr_global_free(buf, file_sz + 1); _get_module_offset_exit: if (fd != INVALID_FILE) dr_close_file(fd); return offset; }
static inline void ordered_lock(ipc_channel_t *channel, uint tid) { dr_mutex_lock(channel->queue_lock); ticket_queue_t *q = &channel->ticket_queue; if (q->locked) { ticket_node_t *node = dr_global_alloc(sizeof(ticket_node_t)); if (node == NULL) DR_ABORT_MSG("Failed to allocate ticket node\n"); node->next = NULL; node->dr_event = dr_event_create(); node->waiting = true; node->thread_id = tid; DR_ASSERT(q->tail->next == NULL); q->tail = q->tail->next = node; SGL_DEBUG("Sleeping Thread :%d\n", tid); dr_mutex_unlock(channel->queue_lock); /* MDL20170425 TODO(soonish) * how likely is it that we'll miss a wakeup here? */ while (node->waiting) dr_event_wait(node->dr_event); dr_mutex_lock(channel->queue_lock); q->head->next = node->next; if (q->tail == node) q->tail = q->head; dr_event_destroy(node->dr_event); dr_global_free(node, sizeof(ticket_node_t)); SGL_DEBUG("Awakened Thread :%d\n", tid); } else { q->locked = true; } dr_mutex_unlock(channel->queue_lock); }
static per_thread_t * thread_data_create(void *drcontext) { per_thread_t *data; if (drcontext == NULL) { ASSERT(!drcov_per_thread, "drcov_per_thread should not be set"); data = dr_global_alloc(sizeof(*data)); } else { ASSERT(drcov_per_thread, "drcov_per_thread should be set"); data = dr_thread_alloc(drcontext, sizeof(*data)); } /* XXX: can we assume bb create event is serialized, * if so, no lock is required for bb_table operation. */ data->bb_table = bb_table_create(drcontext == NULL ? true : false); log_file_create(drcontext, data); return data; }