void ntdll_redir_init(void) { uint i; ntdll_table = strhash_hash_create(GLOBAL_DCONTEXT, hashtable_num_bits(REDIRECT_NTDLL_NUM*2), 80 /* load factor: not perf-critical, plus static */, HASHTABLE_SHARED | HASHTABLE_PERSISTENT, NULL _IF_DEBUG("ntdll redirection table")); TABLE_RWLOCK(ntdll_table, write, lock); for (i = 0; i < REDIRECT_NTDLL_NUM; i++) { strhash_hash_add(GLOBAL_DCONTEXT, ntdll_table, redirect_ntdll[i].name, (void *) redirect_ntdll[i].func); } TABLE_RWLOCK(ntdll_table, write, unlock); if (get_os_version() >= WINDOWS_VERSION_7) { ntdll_win7_table = strhash_hash_create(GLOBAL_DCONTEXT, REDIRECT_NTDLL_WIN7_NUM*2, 80 /* load factor: not perf-critical, plus static */, HASHTABLE_SHARED | HASHTABLE_PERSISTENT, NULL _IF_DEBUG("ntdll win7 redirection table")); TABLE_RWLOCK(ntdll_win7_table, write, lock); for (i = 0; i < REDIRECT_NTDLL_WIN7_NUM; i++) { strhash_hash_add(GLOBAL_DCONTEXT, ntdll_win7_table, redirect_ntdll_win7[i].name, (void *) redirect_ntdll_win7[i].func); } TABLE_RWLOCK(ntdll_win7_table, write, unlock); } }
/* just like instr_encode but doesn't assert on reachability or predication failures */ byte * instr_encode_check_reachability(dcontext_t *dcontext, instr_t *instr, byte *pc, bool *has_instr_opnds /*OUT OPTIONAL*/) { return instr_encode_arch(dcontext, instr, pc, pc, true, has_instr_opnds _IF_DEBUG(false)); }
static void callee_info_table_init(void) { callee_info_table = generic_hash_create( GLOBAL_DCONTEXT, INIT_HTABLE_SIZE_CALLEE, 80 /* load factor: not perf-critical */, HASHTABLE_SHARED | HASHTABLE_PERSISTENT, (void (*)(dcontext_t *, void *))callee_info_free _IF_DEBUG("callee-info table")); }
void advapi32_redir_init(void) { uint i; advapi32_table = strhash_hash_create(GLOBAL_DCONTEXT, hashtable_num_bits(REDIRECT_ADVAPI32_NUM*2), 80 /* load factor: not perf-critical, plus static */, HASHTABLE_SHARED | HASHTABLE_PERSISTENT, NULL _IF_DEBUG("advapi32 redirection table")); TABLE_RWLOCK(advapi32_table, write, lock); for (i = 0; i < REDIRECT_ADVAPI32_NUM; i++) { strhash_hash_add(GLOBAL_DCONTEXT, advapi32_table, redirect_advapi32[i].name, (void *) redirect_advapi32[i].func); } TABLE_RWLOCK(advapi32_table, write, unlock); }
HEAP_TYPE_FREE(dcontext, entry, generic_entry_t, ACCT_OTHER, PROTECTED); } /* Wrapper routines to implement our generic_entry_t and free-func layer */ generic_table_t * generic_hash_create(dcontext_t *dcontext, uint bits, uint load_factor_percent, uint table_flags, void (*free_payload_func)(dcontext_t *, void *) _IF_DEBUG(const char *table_name)) { generic_table_t *table = HEAP_TYPE_ALLOC(dcontext, generic_table_t, ACCT_OTHER, PROTECTED); hashtable_generic_init(dcontext, table, bits, load_factor_percent, (hash_function_t)INTERNAL_OPTION(alt_hash_func), 0 /* hash_mask_offset */, table_flags _IF_DEBUG(table_name)); table->free_payload_func = free_payload_func; return table; } void generic_hash_clear(dcontext_t *dcontext, generic_table_t *htable) { hashtable_generic_clear(dcontext, htable); } void generic_hash_destroy(dcontext_t *dcontext, generic_table_t *htable) { /* FIXME: why doesn't hashtablex.h walk the table and call the free routine * in free() or in remove()? It only seems to do it for range_remove().
HEAP_TYPE_FREE(dcontext, entry, generic_entry_t, ACCT_OTHER, PROTECTED); } /* Wrapper routines to implement our generic_entry_t and free-func layer */ generic_table_t * generic_hash_create(dcontext_t *dcontext, uint bits, uint load_factor_percent, uint table_flags, void (*free_payload_func)(void*) _IF_DEBUG(const char *table_name)) { generic_table_t *table = HEAP_TYPE_ALLOC(dcontext, generic_table_t, ACCT_OTHER, PROTECTED); hashtable_generic_init(dcontext, table, bits, load_factor_percent, (hash_function_t)INTERNAL_OPTION(alt_hash_func), 0 /* hash_mask_offset */, table_flags _IF_DEBUG(table_name)); table->free_payload_func = free_payload_func; return table; } void generic_hash_clear(dcontext_t *dcontext, generic_table_t *htable) { hashtable_generic_clear(dcontext, htable); } void generic_hash_destroy(dcontext_t *dcontext, generic_table_t *htable) { /* FIXME: why doesn't hashtablex.h walk the table and call the free routine * in free() or in remove()? It only seems to do it for range_remove().
byte * instr_encode_to_copy(dcontext_t *dcontext, instr_t *instr, byte *copy_pc, byte *final_pc) { return instr_encode_arch(dcontext, instr, copy_pc, final_pc, true, NULL _IF_DEBUG(true)); }
/* completely ignores reachability and predication failures */ byte * instr_encode_ignore_reachability(dcontext_t *dcontext, instr_t *instr, byte *pc) { return instr_encode_arch(dcontext, instr, pc, pc, false, NULL _IF_DEBUG(false)); }
/* callback for dl_iterate_phdr() for adding existing modules to our lists */ static int dl_iterate_get_areas_cb(struct dl_phdr_info *info, size_t size, void *data) { int *count = (int *)data; uint i; /* see comments in dl_iterate_get_path_cb() */ app_pc modend; app_pc min_vaddr = module_vaddr_from_prog_header((app_pc)info->dlpi_phdr, info->dlpi_phnum, NULL, &modend); app_pc modbase = info->dlpi_addr + min_vaddr; size_t modsize = modend - min_vaddr; LOG(GLOBAL, LOG_VMAREAS, 2, "dl_iterate_get_areas_cb: addr=" PFX " hdrs=" PFX " base=" PFX " name=%s\n", info->dlpi_addr, info->dlpi_phdr, modbase, info->dlpi_name); ASSERT(info->dlpi_phnum == module_num_program_headers(modbase)); ASSERT(count != NULL); if (*count == 0) { /* since we don't get a name for the executable, for now we * assume that the first iter is the executable itself. * XXX: this seems to hold, but there's no guarantee: can we do better? */ executable_start = modbase; } #ifndef X64 if (modsize == PAGE_SIZE && info->dlpi_name[0] == '\0') { /* Candidate for VDSO. Xref PR 289138 on using AT_SYSINFO to locate. */ /* Xref VSYSCALL_PAGE_START_HARDCODED but later linuxes randomize */ char *soname; if (module_walk_program_headers(modbase, modsize, false, true, /* i#1589: ld.so relocated .dynamic */ NULL, NULL, NULL, &soname, NULL) && strncmp(soname, VSYSCALL_PAGE_SO_NAME, strlen(VSYSCALL_PAGE_SO_NAME)) == 0) { ASSERT(!dynamo_initialized); /* .data should be +w */ ASSERT(vsyscall_page_start == NULL); vsyscall_page_start = modbase; LOG(GLOBAL, LOG_VMAREAS, 1, "found vsyscall page @ " PFX "\n", vsyscall_page_start); } } #endif if (modbase != vsyscall_page_start) module_list_add(modbase, modsize, false, info->dlpi_name, 0 /*don't have inode*/); for (i = 0; i < info->dlpi_phnum; i++) { app_pc start, end; uint prot; size_t align; if (module_read_program_header(modbase, i, &start, &end, &prot, &align)) { start += info->dlpi_addr; end += info->dlpi_addr; LOG(GLOBAL, LOG_VMAREAS, 2, "\tsegment %d: " PFX "-" PFX " %s align=%d\n", i, start, end, memprot_string(prot), align); start = (app_pc)ALIGN_BACKWARD(start, PAGE_SIZE); end = (app_pc)ALIGN_FORWARD(end, PAGE_SIZE); LOG(GLOBAL, LOG_VMAREAS, 4, "find_executable_vm_areas: adding: " PFX "-" PFX " prot=%d\n", start, end, prot); all_memory_areas_lock(); update_all_memory_areas(start, end, prot, DR_MEMTYPE_IMAGE); all_memory_areas_unlock(); if (app_memory_allocation(NULL, start, end - start, prot, true /*image*/ _IF_DEBUG("ELF SO"))) (*count)++; } } return 0; /* keep iterating */ }