int main(int argc, char *argv[]) { void *dcontext = dr_standalone_init(); test_all_opcodes(dcontext); #ifdef X64 /* FIXME: NYI */ #else test_disp_control(dcontext); test_indirect_cti(dcontext); test_cti_prefixes(dcontext); test_modrm16(dcontext); test_size_changes(dcontext); #endif test_nop_xchg(dcontext); print("all done\n"); return 0; }
int main(int argc, char *argv[]) { #ifdef STANDALONE_DECODER void *dcontext = GLOBAL_DCONTEXT; #else void *dcontext = dr_standalone_init(); /* simple test of deadlock_avoidance, etc. being disabled in standalone */ void *x = dr_mutex_create(); dr_mutex_lock(x); dr_mutex_unlock(x); dr_mutex_destroy(x); #endif test_all_opcodes_0(dcontext); #ifndef STANDALONE_DECODER /* speed up compilation */ test_all_opcodes_1(dcontext); test_all_opcodes_2(dcontext); test_all_opcodes_2_mm(dcontext); test_all_opcodes_3(dcontext); test_all_opcodes_3_avx(dcontext); test_all_opcodes_4(dcontext); #endif test_disp_control(dcontext); test_indirect_cti(dcontext); test_cti_prefixes(dcontext); #ifndef X64 test_modrm16(dcontext); #endif test_size_changes(dcontext); test_nop_xchg(dcontext); #ifdef X64 test_x86_mode(dcontext); test_x64_abs_addr(dcontext); test_x64_inc(dcontext); #endif test_regs(dcontext); test_instr_opnds(dcontext); test_strict_invalid(dcontext); print("all done\n"); return 0; }
int main(int argc, char *argv[]) { void *dcontext = dr_standalone_init(); /* i#1702: test that a cbr is outside the IT-block */ test_dr_insert_it_instrs_cbr(dcontext); /* i#1702: test that a cti terminates the IT-block */ test_dr_insert_it_instrs_cti(dcontext); return 0; }
int main(int argc, char *argv[]) { file_t f; void *drcontext = dr_standalone_init(); if (argc != 2) { dr_fprintf(STDERR, "Usage: %s <objfile>\n", argv[0]); return 1; } f = dr_open_file(argv[1], DR_FILE_READ | DR_FILE_ALLOW_LARGE); if (f == INVALID_FILE) { dr_fprintf(STDERR, "Error opening %s\n", argv[1]); return 1; } read_data(f, drcontext); dr_close_file(f); return 0; }
int main(int argc, char *argv[]) { version_info_t info; HMODULE hmod; void *drcontext = dr_standalone_init(); if (argc != 2) { printf("Usage: %s <dll to read>\n", argv[0]); return 1; } /* Don't use LOAD_LIBRARY_AS_DATAFILE, it doesn't layout the sections as we expect * use DONT_RESOLVE_DLL_REFERENCES instead */ hmod = LoadLibraryEx(argv[1], NULL, DONT_RESOLVE_DLL_REFERENCES); if (hmod == NULL) { printf("Can't find module %s\n", argv[1]); return 2; } /* Need to round off the loaded as data flag to get actual base */ if (!get_module_resource_version_info((app_pc)((uint)hmod & 0xfffffffe), &info)) { printf("Failed to read rsrc directory\n"); return 3; } printf("File Version = %04d.%04d.%04d.%04d, Product Version = %04d.%04d.%04d.%04d\n", info.file_version.version_parts.p1, info.file_version.version_parts.p2, info.file_version.version_parts.p3, info.file_version.version_parts.p4, info.product_version.version_parts.p1, info.product_version.version_parts.p2, info.product_version.version_parts.p3, info.product_version.version_parts.p4); if (info.original_filename != NULL) printf("Original File Name = \"%S\"\n", info.original_filename); if (info.company_name != NULL) printf("Company Name = \"%S\"\n", info.company_name); if (info.product_name != NULL) printf("Product Name = \"%S\"\n", info.product_name); return 0; }
bool drstrace_unit_test_syscall_init() { uint const_arrays_num; uint i = 0; dr_standalone_init(); if (drsym_init(0) != DRSYM_SUCCESS) return false; const_arrays_num = get_const_arrays_num(); hashtable_init(&nconsts_table, HASHTABLE_BITSIZE, HASH_STRING, false); while (i < const_arrays_num) { const_values_t *named_consts = const_struct_array[i]; bool res = hashtable_add(&nconsts_table, (void *) named_consts[0].const_name, (void *) named_consts); if (!res) return false; i++; } return true; }
int main(int argc, char *argv[]) { char *dll = NULL; int i; /* module + address per line */ char line[MAXIMUM_PATH*2]; size_t modoffs; /* options that can be local vars */ bool addr2sym = false; bool addr2sym_multi = false; bool sym2addr = false; bool enumerate = false; bool enumerate_all = false; bool search = false; bool searchall = false; for (i = 1; i < argc; i++) { if (_stricmp(argv[i], "-e") == 0) { if (i+1 >= argc) { PRINT_USAGE(argv[0]); return 1; } i++; dll = argv[i]; if ( #ifdef WINDOWS _access(dll, 4/*read*/) == -1 #else !dr_file_exists(dll) #endif ) { printf("ERROR: invalid path %s\n", dll); return 1; } } else if (_stricmp(argv[i], "-f") == 0) { show_func = true; } else if (_stricmp(argv[i], "-v") == 0) { verbose = true; } else if (_stricmp(argv[i], "-a") == 0 || _stricmp(argv[i], "-s") == 0) { if (i+1 >= argc) { PRINT_USAGE(argv[0]); return 1; } if (_stricmp(argv[i], "-a") == 0) addr2sym = true; else sym2addr = true; i++; /* rest of args read below */ break; } else if (_stricmp(argv[i], "-q") == 0) { addr2sym_multi = true; } else if (_stricmp(argv[i], "--enum") == 0) { enumerate = true; } else if (_stricmp(argv[i], "--list") == 0) { enumerate_all = true; } else if (_stricmp(argv[i], "--search") == 0) { search = true; } else if (_stricmp(argv[i], "--searchall") == 0) { search = true; searchall = true; } else { PRINT_USAGE(argv[0]); return 1; } } if (((sym2addr || addr2sym) && dll == NULL) || (addr2sym_multi && dll != NULL) || (!sym2addr && !addr2sym && !addr2sym_multi && !enumerate_all)) { PRINT_USAGE(argv[0]); return 1; } dr_standalone_init(); if (drsym_init(IF_WINDOWS_ELSE(NULL, 0)) != DRSYM_SUCCESS) { printf("ERROR: unable to initialize symbol library\n"); return 1; } if (!addr2sym_multi) { if (enumerate_all) enumerate_symbols(dll, NULL, search, searchall); else { /* kind of a hack: assumes i hasn't changed and that -s/-a is last option */ for (; i < argc; i++) { if (addr2sym) { if (sscanf(argv[i], "%x", (uint *)&modoffs) == 1) lookup_address(dll, modoffs); else printf("ERROR: unknown input %s\n", argv[i]); } else if (enumerate || search) enumerate_symbols(dll, argv[i], search, searchall); else lookup_symbol(dll, argv[i]); } } } else { while (!feof(stdin)) { char modpath[MAXIMUM_PATH]; if (fgets(line, sizeof(line), stdin) == NULL || /* when postprocess.pl closes the pipe, fgets is not * returning, so using an alternative eof code */ strcmp(line, ";exit\n") == 0) break; /* Ensure we support spaces in paths by using ; to split. * Since ; separates PATH, no Windows dll will have ; in its name. */ if (sscanf(line, "%"MAX_PATH_STR"[^;];%x", (char *)&modpath, (uint *)&modoffs) == 2) { lookup_address(modpath, modoffs); fflush(stdout); /* ensure flush in case piped */ } else if (verbose) printf("Error: unknown input %s\n", line); } } if (drsym_exit() != DRSYM_SUCCESS) printf("WARNING: error cleaning up symbol library\n"); return 0; }
int _tmain(int argc, TCHAR *targv[]) { char **argv; char *process = NULL; char *dr_root = NULL; char *drheapstat_root = NULL; char default_dr_root[MAXIMUM_PATH]; char default_drheapstat_root[MAXIMUM_PATH]; char client_path[MAXIMUM_PATH]; char client_ops[MAX_DR_CMDLINE]; size_t cliops_sofar = 0; /* for BUFPRINT to client_ops */ char dr_ops[MAX_DR_CMDLINE]; size_t drops_sofar = 0; /* for BUFPRINT to dr_ops */ ssize_t len; /* shared by all BUFPRINT */ char logdir[MAXIMUM_PATH]; bool have_logdir = false; bool use_root_for_logdir; #ifdef WINDOWS char *pidfile = NULL; #endif #ifndef MACOS /* XXX i#1286: implement nudge on MacOS */ process_id_t nudge_pid = 0; #endif bool use_dr_debug = false; bool use_drheapstat_debug = false; char *app_name; char full_app_name[MAXIMUM_PATH]; char **app_argv; int errcode; void *inject_data; int i; char *c; char buf[MAXIMUM_PATH]; process_id_t pid; bool exit0 = false; bool dr_logdir_specified = false; bool doubledash_present = false; drfront_status_t sc; bool res; #ifndef X64 bool is64, is32; #endif dr_standalone_init(); #if defined(WINDOWS) && !defined(_UNICODE) # error _UNICODE must be defined #else /* Convert to UTF-8 if necessary */ sc = drfront_convert_args((const TCHAR **)targv, &argv, argc); if (sc != DRFRONT_SUCCESS) fatal("failed to process args: %d\n", sc); #endif /* Default root: we assume this exe is <root>/bin/drheapstat.exe */ get_full_path(argv[0], buf, BUFFER_SIZE_ELEMENTS(buf)); c = buf + strlen(buf) - 1; while (*c != DIRSEP && *c != ALT_DIRSEP && c > buf) c--; _snprintf(c+1, BUFFER_SIZE_ELEMENTS(buf) - (c+1-buf), "../dynamorio"); NULL_TERMINATE_BUFFER(buf); get_absolute_path(buf, default_dr_root, BUFFER_SIZE_ELEMENTS(default_dr_root)); NULL_TERMINATE_BUFFER(default_dr_root); dr_root = default_dr_root; /* assuming we're in bin/ (mainly due to CPack NSIS limitations) */ _snprintf(c+1, BUFFER_SIZE_ELEMENTS(buf) - (c+1-buf), ".."); NULL_TERMINATE_BUFFER(buf); get_absolute_path(buf, default_drheapstat_root, BUFFER_SIZE_ELEMENTS(default_drheapstat_root)); NULL_TERMINATE_BUFFER(default_drheapstat_root); drheapstat_root = default_drheapstat_root; string_replace_character(drheapstat_root, ALT_DIRSEP, DIRSEP); /* canonicalize */ BUFPRINT(dr_ops, BUFFER_SIZE_ELEMENTS(dr_ops), drops_sofar, len, "%s ", DEFAULT_DR_OPS); client_ops[0] = '\0'; /* default logdir */ if (drfront_appdata_logdir(drheapstat_root, "Dr. Heapstat", &use_root_for_logdir, logdir, BUFFER_SIZE_ELEMENTS(logdir)) == DRFRONT_SUCCESS && !use_root_for_logdir) { if ((dr_create_dir(logdir) || dr_directory_exists(logdir)) && file_is_writable(logdir)) have_logdir = true; } if (!have_logdir) { _snprintf(logdir, BUFFER_SIZE_ELEMENTS(logdir), "%s%cdrheapstat%clogs", drheapstat_root, DIRSEP, DIRSEP); NULL_TERMINATE_BUFFER(logdir); if (!file_is_writable(logdir)) { _snprintf(logdir, BUFFER_SIZE_ELEMENTS(logdir), "%s%clogs", drheapstat_root, DIRSEP); NULL_TERMINATE_BUFFER(logdir); if (file_is_writable(logdir)) have_logdir = true; } else have_logdir = true; } else have_logdir = true; if (!have_logdir) { /* try logs in cur dir */ get_absolute_path("./logs", logdir, BUFFER_SIZE_ELEMENTS(logdir)); NULL_TERMINATE_BUFFER(logdir); if (!file_is_writable(logdir)) { /* try cur dir */ get_absolute_path(".", logdir, BUFFER_SIZE_ELEMENTS(logdir)); NULL_TERMINATE_BUFFER(logdir); } } /* parse command line */ /* FIXME PR 487993: use optionsx.h to construct this parsing code */ for (i=1; i<argc; i++) { if (strcmp(argv[i], "--") == 0) { doubledash_present = true; break; } } for (i=1; i<argc; i++) { /* note that we pass unknown args to client, until -- */ if (strcmp(argv[i], "--") == 0) { i++; break; } /* drag-and-drop does not include "--" so we try to identify the app. * we explicitly parse -logdir and -suppress, and all the other * client ops that take args take numbers so this should be safe. */ else if (argv[i][0] != '-' && !doubledash_present && ends_in_exe(argv[i])) { /* leave i alone: this is the app itself */ break; } else if (strcmp(argv[i], "-v") == 0) { verbose = true; continue; } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { print_usage(true/*full*/); exit(0); } else if (strcmp(argv[i], "-dr_debug") == 0) { use_dr_debug = true; continue; } else if (strcmp(argv[i], "-dr_release") == 0) { use_dr_debug = false; continue; } else if (strcmp(argv[i], "-debug") == 0) { use_drheapstat_debug = true; continue; } else if (strcmp(argv[i], "-release") == 0) { use_drheapstat_debug = false; continue; } else if (!strcmp(argv[i], "-version")) { #if defined(BUILD_NUMBER) && defined(VERSION_NUMBER) printf("Dr. Heapstat version %s -- build %d\n", VERSION_STRING, BUILD_NUMBER); #elif defined(BUILD_NUMBER) printf("Dr. Heapstat custom build %d -- %s\n", BUILD_NUMBER, __DATE__); #elif defined(VERSION_NUMBER) printf("Dr. Heapstat version %s -- custom build %s, %s\n", VERSION_STRING, __DATE__, __TIME__); #else printf("Dr. Heapstat custom build -- %s, %s\n", __DATE__, __TIME__); #endif exit(0); } else if (strcmp(argv[i], "-dr") == 0) { if (i >= argc - 1) usage("invalid arguments"); dr_root = argv[++i]; } else if (strcmp(argv[i], "-drheapstat") == 0) { if (i >= argc - 1) usage("invalid arguments"); drheapstat_root = argv[++i]; } else if (strcmp(argv[i], "-follow_children") == 0 || strcmp(argv[i], "-no_follow_children") == 0) { BUFPRINT(dr_ops, BUFFER_SIZE_ELEMENTS(dr_ops), drops_sofar, len, "%s ", argv[i]); } #ifndef MACOS /* XXX i#1286: implement nudge on MacOS */ else if (strcmp(argv[i], "-nudge") == 0) { if (i >= argc - 1) usage("invalid arguments"); nudge_pid = strtoul(argv[++i], NULL, 10); } #endif else if (strcmp(argv[i], "-dr_ops") == 0) { if (i >= argc - 1) usage("invalid arguments"); /* Slight risk of some other option containing "-logdir " but * -dr_ops is really only be used by Dr. Memory developers anyway. */ if (strstr(argv[i+1], "-logdir ") != NULL) dr_logdir_specified = true; BUFPRINT(dr_ops, BUFFER_SIZE_ELEMENTS(dr_ops), drops_sofar, len, "%s ", argv[++i]); } #ifdef WINDOWS else if (strcmp(argv[i], "-pid_file") == 0) { if (i >= argc - 1) usage("invalid arguments"); pidfile = argv[++i]; } #endif else if (strcmp(argv[i], "-logdir") == 0) { if (i >= argc - 1) usage("invalid arguments"); /* make absolute */ get_absolute_path(argv[++i], logdir, BUFFER_SIZE_ELEMENTS(logdir)); NULL_TERMINATE_BUFFER(logdir); /* added to client ops below */ } else if (strcmp(argv[i], "-exit0") == 0) { exit0 = true; } /* FIXME i#1653: add support for options the old perl frontend supported */ else { /* pass to client */ BUFPRINT(client_ops, BUFFER_SIZE_ELEMENTS(client_ops), cliops_sofar, len, "`%s` ", argv[i]); } } #ifndef MACOS /* XXX i#1286: implement nudge on MacOS */ if (nudge_pid != 0) { if (i < argc) usage("%s", "-nudge does not take an app to run"); /* could also complain about other client or app specific ops */ res = dr_nudge_pid(nudge_pid, CLIENT_ID, NUDGE_LEAK_SCAN, INFINITE); if (res != DR_SUCCESS) { fatal("error nudging %d%s", nudge_pid, (res == DR_NUDGE_PID_NOT_INJECTED) ? ": no such Dr. Heapstat process" : ""); assert(false); /* shouldn't get here */ } exit(0); } #endif if (i >= argc) usage("%s", "no app specified"); app_name = argv[i]; get_full_path(app_name, full_app_name, BUFFER_SIZE_ELEMENTS(full_app_name)); if (full_app_name[0] != '\0') app_name = full_app_name; info("targeting application: \"%s\"", app_name); /* XXX: See drmemory/frontend.c for notes about our argv processing. */ app_argv = &argv[i]; if (verbose) { int j; c = buf; for (j = 0; app_argv[j] != NULL; j++) { c += _snprintf(c, BUFFER_SIZE_ELEMENTS(buf) - (c - buf), "\"%s\" ", app_argv[j]); } NULL_TERMINATE_BUFFER(buf); assert(c - buf < BUFFER_SIZE_ELEMENTS(buf)); info("app cmdline: %s", buf); } #ifndef X64 /* XXX: See drmemory/frontend.c for notes about 64-bit support. */ if (drfront_is_64bit_app(app_name, &is64, &is32) == DRFRONT_SUCCESS && is64 && !is32) { fatal("This Dr. Heapstat release does not support 64-bit applications."); goto error; /* actually won't get here */ } #endif if (!file_is_readable(dr_root)) { fatal("invalid -dr %s", dr_root); goto error; /* actually won't get here */ } if (dr_root != default_dr_root) { /* Workaround for DRi#1082 where DR root path can't have ".." */ get_absolute_path(dr_root, default_dr_root, BUFFER_SIZE_ELEMENTS(default_dr_root)); NULL_TERMINATE_BUFFER(default_dr_root); dr_root = default_dr_root; } _snprintf(buf, BUFFER_SIZE_ELEMENTS(buf), "%s/"LIB_ARCH"/%s/%s", dr_root, use_dr_debug ? "debug" : "release", DR_LIB_NAME); NULL_TERMINATE_BUFFER(buf); if (!file_is_readable(buf)) { /* support debug build w/ integrated debug DR build and so no release */ if (!use_dr_debug) { _snprintf(buf, BUFFER_SIZE_ELEMENTS(buf), "%s/"LIB_ARCH"/%s/%s", dr_root, "debug", DR_LIB_NAME); NULL_TERMINATE_BUFFER(buf); if (!file_is_readable(buf)) { fatal("cannot find DynamoRIO library %s", buf); goto error; /* actually won't get here */ } warn("using debug DynamoRIO since release not found"); use_dr_debug = true; } } /* once we have 64-bit we'll need to address the NSIS "bin/" requirement */ _snprintf(client_path, BUFFER_SIZE_ELEMENTS(client_path), "%s%c"BIN_ARCH"%c%s%c%s", drheapstat_root, DIRSEP, DIRSEP, use_drheapstat_debug ? "debug" : "release", DIRSEP, DRHEAPSTAT_LIB_NAME); NULL_TERMINATE_BUFFER(client_path); if (!file_is_readable(client_path)) { if (!use_drheapstat_debug) { _snprintf(client_path, BUFFER_SIZE_ELEMENTS(client_path), "%s%c"BIN_ARCH"%c%s%c%s", drheapstat_root, DIRSEP, DIRSEP, "debug", DIRSEP, DRHEAPSTAT_LIB_NAME); NULL_TERMINATE_BUFFER(client_path); if (!file_is_readable(client_path)) { fatal("invalid -drheapstat_root: cannot find %s", client_path); goto error; /* actually won't get here */ } /* try to avoid warning for devs running from build dir */ _snprintf(buf, BUFFER_SIZE_ELEMENTS(client_path), "%s%cCMakeCache.txt", drheapstat_root, DIRSEP); NULL_TERMINATE_BUFFER(buf); if (!file_is_readable(buf)) warn("using debug Dr. Heapstat since release not found"); use_drheapstat_debug = true; } } drfront_string_replace_character(logdir, ALT_DIRSEP, DIRSEP); /* canonicalize */ if (!file_is_writable(logdir)) { fatal("invalid -logdir: cannot find/write %s", logdir); goto error; /* actually won't get here */ } info("logdir is \"%s\"", logdir); BUFPRINT(client_ops, BUFFER_SIZE_ELEMENTS(client_ops), cliops_sofar, len, "-logdir `%s` ", logdir); /* Put DR logs inside drheapstat logdir */ if (!dr_logdir_specified) { _snprintf(buf, BUFFER_SIZE_ELEMENTS(buf), "%s%cdynamorio", logdir, DIRSEP); NULL_TERMINATE_BUFFER(buf); if (!dr_directory_exists(buf)) { if (!dr_create_dir(buf)) { /* check again in case of a race */ if (!dr_directory_exists(buf)) { fatal("cannot create %s", buf); goto error; /* actually won't get here */ } } } BUFPRINT(dr_ops, BUFFER_SIZE_ELEMENTS(dr_ops), drops_sofar, len, "-logdir `%s` ", buf); } #ifdef UNIX errcode = dr_inject_prepare_to_exec(app_name, (const char **)app_argv, &inject_data); #else errcode = dr_inject_process_create(app_name, (const char **)app_argv, &inject_data); #endif /* Mismatch is just a warning */ if (errcode != 0 && errcode != WARN_IMAGE_MACHINE_TYPE_MISMATCH_EXE) { #ifdef WINDOWS int sofar = #endif _snprintf(buf, BUFFER_SIZE_ELEMENTS(buf), "failed to create process for \"%s\": ", app_name); #ifdef WINDOWS if (sofar > 0) { FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errcode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) buf + sofar, BUFFER_SIZE_ELEMENTS(buf) - sofar*sizeof(char), NULL); } NULL_TERMINATE_BUFFER(buf); #endif fatal("%s", buf); goto error; /* actually won't get here */ } pid = dr_inject_get_process_id(inject_data); #ifdef WINDOWS if (pidfile != NULL) write_pid_to_file(pidfile, pid); #endif process = dr_inject_get_image_name(inject_data); /* we don't care if this app is already registered for DR b/c our * this-pid config will override */ info("configuring %s pid=%d dr_ops=\"%s\"", process, pid, dr_ops); if (dr_register_process(process, pid, false/*local*/, dr_root, DR_MODE_CODE_MANIPULATION, use_dr_debug, DR_PLATFORM_DEFAULT, dr_ops) != DR_SUCCESS) { fatal("failed to register DynamoRIO configuration"); goto error; /* actually won't get here */ } info("configuring client \"%s\" ops=\"%s\"", client_path, client_ops); if (dr_register_client(process, pid, false/*local*/, DR_PLATFORM_DEFAULT, CLIENT_ID, 0, client_path, client_ops) != DR_SUCCESS) { fatal("failed to register DynamoRIO client configuration"); goto error; /* actually won't get here */ } if (!dr_inject_process_inject(inject_data, false/*!force*/, NULL)) { fatal("unable to inject"); goto error; /* actually won't get here */ } dr_inject_process_run(inject_data); #ifdef UNIX fatal("Failed to exec application"); #else info("waiting for app to exit..."); errcode = WaitForSingleObject(dr_inject_get_process_handle(inject_data), INFINITE); if (errcode != WAIT_OBJECT_0) info("failed to wait for app: %d\n", errcode); #endif errcode = dr_inject_process_exit(inject_data, false/*don't kill process*/); goto cleanup; error: dr_inject_process_exit(inject_data, false); errcode = 1; cleanup: sc = drfront_cleanup_args(argv, argc); if (sc != DRFRONT_SUCCESS) fatal("drfront_cleanup_args failed: %d\n", sc); return (exit0 ? 0 : errcode); }
int _tmain(int argc, TCHAR *targv[]) { int res = 1; char **argv; char dll[MAXIMUM_PATH]; int i; /* module + address per line */ char line[MAXIMUM_PATH*2]; size_t modoffs; /* options that can be local vars */ bool addr2sym = false; bool addr2sym_multi = false; bool sym2addr = false; bool enumerate = false; bool enumerate_all = false; bool search = false; bool searchall = false; bool enum_lines = false; #if defined(WINDOWS) && !defined(_UNICODE) # error _UNICODE must be defined #else /* Convert to UTF-8 if necessary */ if (drfront_convert_args((const TCHAR **)targv, &argv, argc) != DRFRONT_SUCCESS) { printf("ERROR: failed to process args\n"); return 1; } #endif for (i = 1; i < argc; i++) { if (_stricmp(argv[i], "-e") == 0) { bool is_readable; if (i+1 >= argc) { PRINT_USAGE(argv[0]); goto cleanup; } i++; if (drfront_get_absolute_path(argv[i], dll, BUFFER_SIZE_ELEMENTS(dll)) != DRFRONT_SUCCESS) { printf("ERROR: invalid path %s\n", argv[i]); goto cleanup; } if (drfront_access(dll, DRFRONT_READ, &is_readable) != DRFRONT_SUCCESS || !is_readable) { printf("ERROR: invalid path %s\n", argv[i]); goto cleanup; } } else if (_stricmp(argv[i], "-f") == 0) { show_func = true; } else if (_stricmp(argv[i], "-v") == 0) { verbose = true; } else if (_stricmp(argv[i], "-a") == 0 || _stricmp(argv[i], "-s") == 0) { if (i+1 >= argc) { PRINT_USAGE(argv[0]); goto cleanup; } if (_stricmp(argv[i], "-a") == 0) addr2sym = true; else sym2addr = true; i++; /* rest of args read below */ break; } else if (_stricmp(argv[i], "--lines") == 0) { enum_lines = true; } else if (_stricmp(argv[i], "-q") == 0) { addr2sym_multi = true; } else if (_stricmp(argv[i], "--enum") == 0) { enumerate = true; } else if (_stricmp(argv[i], "--list") == 0) { enumerate_all = true; } else if (_stricmp(argv[i], "--search") == 0) { search = true; } else if (_stricmp(argv[i], "--searchall") == 0) { search = true; searchall = true; } else { PRINT_USAGE(argv[0]); goto cleanup; } } if ((!addr2sym_multi && dll == NULL) || (addr2sym_multi && dll != NULL) || (!sym2addr && !addr2sym && !addr2sym_multi && !enumerate_all && !enum_lines)) { PRINT_USAGE(argv[0]); goto cleanup; } dr_standalone_init(); if (dll != NULL) { if (!check_architecture(dll, argv)) goto cleanup; } if (drsym_init(IF_WINDOWS_ELSE(NULL, 0)) != DRSYM_SUCCESS) { printf("ERROR: unable to initialize symbol library\n"); goto cleanup; } if (!addr2sym_multi) { if (enum_lines) enumerate_lines(dll); else if (enumerate_all) enumerate_symbols(dll, NULL, search, searchall); else { /* kind of a hack: assumes i hasn't changed and that -s/-a is last option */ for (; i < argc; i++) { if (addr2sym) { if (sscanf(argv[i], SIZE_FMT, &modoffs) == 1) symquery_lookup_address(dll, modoffs); else printf("ERROR: unknown input %s\n", argv[i]); } else if (enumerate || search) enumerate_symbols(dll, argv[i], search, searchall); else symquery_lookup_symbol(dll, argv[i]); } } } else { while (!feof(stdin)) { char modpath[MAXIMUM_PATH]; if (fgets(line, sizeof(line), stdin) == NULL || /* when postprocess.pl closes the pipe, fgets is not * returning, so using an alternative eof code */ strcmp(line, ";exit\n") == 0) break; /* Ensure we support spaces in paths by using ; to split. * Since ; separates PATH, no Windows dll will have ; in its name. */ if (sscanf(line, "%"MAX_PATH_STR"[^;];"SIZE_FMT, (char *)&modpath, &modoffs) == 2) { symquery_lookup_address(modpath, modoffs); fflush(stdout); /* ensure flush in case piped */ } else if (verbose) printf("Error: unknown input %s\n", line); } } if (drsym_exit() != DRSYM_SUCCESS) printf("WARNING: error cleaning up symbol library\n"); res = 0; cleanup: if (drfront_cleanup_args(argv, argc) != DRFRONT_SUCCESS) printf("WARNING: drfront_cleanup_args failed\n"); return res; }
int main(int argc, char *argv[]) { void *dcontext = dr_standalone_init(); int res; char *dll; bool forced = false; dr_set_isa_mode(dcontext, DR_ISA_IA32, NULL); for (res=1; res < argc; res++) { if (strcmp(argv[res], "-sysenter") == 0) { expect_sysenter = true; forced = true; } else if (strcmp(argv[res], "-int2e") == 0) { expect_int2e = true; forced = true; } else if (strcmp(argv[res], "-wow") == 0) { expect_wow = true; forced = true; } else if (strcmp(argv[res], "-x64") == 0) { expect_x64 = true; #ifdef X64 dr_set_isa_mode(dcontext, DR_ISA_AMD64, NULL); #else /* For 32-bit builds we hack a fix for -syscalls (see * decode_syscall_num()) but -Ki won't work. */ #endif forced = true; } else if (strcmp(argv[res], "-v") == 0) { verbose = true; } else if (strcmp(argv[res], "-exports") == 0) { list_exports = true; list_forwards = true; /* implied */ } else if (strcmp(argv[res], "-forwards") == 0) { list_forwards = true; } else if (strcmp(argv[res], "-Ki") == 0) { list_Ki = true; } else if (strcmp(argv[res], "-syscalls") == 0) { list_syscalls = true; } else if (strcmp(argv[res], "-ignore_Zw") == 0) { ignore_Zw = true; } else if (strcmp(argv[res], "-usercalls") == 0) { list_usercalls = true; } else if (argv[res][0] == '-') { usage(argv[0]); } else { break; } } if (res >= argc || (!list_syscalls && !list_Ki && !list_forwards && !verbose && !list_usercalls)) { usage(argv[0]); } dll = argv[res]; if (!forced && list_syscalls) { usage(argv[0]); } load_and_analyze(dcontext, dll); return 0; }
int main(int argc, char *argv[]) { byte *dll_1, *dll_2, *p1, *p2, *iat_start1, *iat_end1, *iat_start2, *iat_end2; bool has_iat = false; MEMORY_BASIC_INFORMATION info; void *drcontext = dr_standalone_init(); uint writable_pages = 0, reserved_pages = 0, IAT_pages = 0; uint matched_pages = 0, second_matched_pages = 0, unmatched_pages = 0; uint exact_match_pages = 0, exact_no_match_pages = 0; char reloc_file[MAX_PATH] = {0}, orig_file[MAX_PATH], *input_file; uint old_size = 0, new_size = 0; uint old_base = 0, new_base = 0x69000000; /* unlikely to collide */ /* user specified option defaults */ uint arg_offs = 1; bool use_second_pass = true; bool assume_header_match = true; uint second_pass_offset = 16; /* FIXME arbitrary, what's a good choice? */ bool assume_IAT_written = true; bool spin_for_debugger = false; if (argc < 2) return usage(argv[0]); while (argv[arg_offs][0] == '-') { if (strcmp(argv[arg_offs], "-vv") == 0) { vv = true; } else if (strcmp(argv[arg_offs], "-v") == 0) { v = true; } else if (strcmp(argv[arg_offs], "-no_second_pass") == 0) { use_second_pass = false; } else if (strcmp(argv[arg_offs], "-second_pass_offset") == 0) { if ((uint)argc <= arg_offs+1) return usage(argv[0]); second_pass_offset = atoi(argv[++arg_offs]); } else if (strcmp(argv[arg_offs], "-no_assume_IAT_written") == 0) { assume_IAT_written = false; } else if (strcmp(argv[arg_offs], "-spin_for_debugger") == 0) { spin_for_debugger = true; } else { return usage(argv[0]); } arg_offs++; } input_file = argv[arg_offs++]; if (arg_offs != argc) return usage(argv[0]); _snprintf(reloc_file, sizeof(reloc_file), "%s.reloc.dll", input_file); reloc_file[sizeof(reloc_file)-1] = '\0'; if (!CopyFile(input_file, reloc_file, FALSE)) { LPSTR msg = NULL; uint error = GetLastError(); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ALLOCATE_BUFFER, 0, GetLastError(), 0, msg, 0, NULL); VERBOSE_PRINT("Copy Error %d (0x%x) = %s\n", error, error, msg); return 1; } snprintf(orig_file, sizeof(orig_file), "%s.orig.dll", input_file); orig_file[sizeof(orig_file)-1] = '\0'; if (!CopyFile(input_file, orig_file, FALSE)) { LPSTR msg = NULL; uint error = GetLastError(); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ALLOCATE_BUFFER, 0, GetLastError(), 0, msg, 0, NULL); VERBOSE_PRINT("Copy Error %d (0x%x) = %s\n", error, error, msg); return 1; } if (ReBaseImage(reloc_file, "", TRUE, FALSE, FALSE, 0, &old_size, &old_base, &new_size, &new_base, 0)) { VERBOSE_PRINT("Rebased imsage \"%s\" from 0x%08x to 0x%08x\n" "Size changed from %d bytes to %d bytes\n", input_file, old_base, new_base, old_size, new_size); } else { LPSTR msg = NULL; uint error = GetLastError(); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ALLOCATE_BUFFER, 0, GetLastError(), 0, msg, 0, NULL); VERBOSE_PRINT("Rebase Error %d (0x%x) = %s\n", error, error, msg); return 1; } dll_1 = (byte *)ALIGN_BACKWARD(LoadLibraryExA(orig_file, NULL, DONT_RESOLVE_DLL_REFERENCES), PAGE_SIZE); p1 = dll_1; dll_2 = (byte *)ALIGN_BACKWARD(LoadLibraryExA(reloc_file, NULL, DONT_RESOLVE_DLL_REFERENCES), PAGE_SIZE); p2 = dll_2; VVERBOSE_PRINT("Loaded dll @ 0x%08x and 0x%08x\n", dll_1, dll_2); if (dll_1 == NULL || dll_2 == NULL) { VERBOSE_PRINT( "Error loading %s\n", input_file); return 1; } /* Handle the first page specially since I'm seeing problems with a handful of * dlls that aren't really getting rebased. mcupdate_GenuineIntel.dll for ex. * (which does have relocations etc.) not sure what's up, but it's only a couple of * dlls so will ignore them. If we really rebased the header should differ. */ if (memcmp(dll_1, dll_2, PAGE_SIZE) == 0) { printf("%s - ERROR during relocating\n", input_file); return 1; } else { exact_no_match_pages++; if (assume_header_match) /* We could modify the hash function to catch header pages. */ matched_pages++; else unmatched_pages++; } p1 += PAGE_SIZE; p2 += PAGE_SIZE; if (assume_IAT_written && get_IAT_section_bounds(dll_1, &iat_start1, &iat_end1)) { has_iat = true; ASSERT(get_IAT_section_bounds(dll_2, &iat_start2, &iat_end2) && iat_start1 - dll_1 == iat_start2 - dll_2 && iat_end1 - dll_1 == iat_end2 - dll_2); } while (dr_virtual_query(p1, &info, sizeof(info)) == sizeof(info) && info.State != MEM_FREE && info.AllocationBase == dll_1) { /* we only check read-only pages (assumption writable pages aren't shareable) */ ASSERT(p1 == info.BaseAddress); if (info.State != MEM_COMMIT) { reserved_pages += info.RegionSize / PAGE_SIZE; VVERBOSE_PRINT("skipping %d reserved pages\n", info.RegionSize / PAGE_SIZE); p1 += info.RegionSize; p2 += info.RegionSize; } else if (!prot_is_writable(info.Protect)) { uint i; for (i = 0; i < info.RegionSize / PAGE_SIZE; i++) { bool exact = false; if (assume_IAT_written && has_iat && iat_end1 > p1 && iat_start1 < p1 + PAGE_SIZE) { /* overlaps an IAT page */ IAT_pages++; p1 += PAGE_SIZE; p2 += PAGE_SIZE; continue; } if (memcmp(p1, p2, PAGE_SIZE) == 0) { VVERBOSE_PRINT("Page Exact Match\n"); exact_match_pages++; exact = true; } else { VVERBOSE_PRINT("Page Exact Mismatch\n"); exact_no_match_pages++; } if (compare_pages(drcontext, p1, p2, 0)) { VVERBOSE_PRINT("Matched page\n"); matched_pages++; } else { VVERBOSE_PRINT("Failed to match page\n"); if (use_second_pass && compare_pages(drcontext, p1, p2, second_pass_offset)) { second_matched_pages++; } else { unmatched_pages++; } ASSERT(!exact); } p1 += PAGE_SIZE; p2 += PAGE_SIZE; } } else { writable_pages += info.RegionSize / PAGE_SIZE; VVERBOSE_PRINT("skipping %d writable pages\n", info.RegionSize / PAGE_SIZE); p1 += info.RegionSize; p2 += info.RegionSize; } } VERBOSE_PRINT("%d exact match, %d not exact match\n%d hash_match, %d second_hash_match, %d hash_mismatch\n", exact_match_pages, exact_no_match_pages, matched_pages, second_matched_pages, unmatched_pages); printf("%s : %d pages - %d w %d res %d IAT = %d same %d differ : %d hash differ %d first hash differ : %d%% found, %d%% found first hash\n", input_file, writable_pages + reserved_pages + IAT_pages + exact_match_pages + exact_no_match_pages, writable_pages, reserved_pages, IAT_pages, exact_match_pages, exact_no_match_pages, unmatched_pages, unmatched_pages + second_matched_pages, (100 * (matched_pages + second_matched_pages - exact_match_pages))/exact_no_match_pages, (100 * (matched_pages - exact_match_pages))/exact_no_match_pages); while (spin_for_debugger) Sleep(1000); return 0; }
int main(int argc, char *argv[]) { void *dcontext = dr_standalone_init(); int res; char *dll; bool forced = false; #ifdef X64 set_x86_mode(dcontext, true/*x86*/); #endif for (res=1; res < argc; res++) { if (strcmp(argv[res], "-sysenter") == 0) { expect_sysenter = true; forced = true; } else if (strcmp(argv[res], "-int2e") == 0) { expect_int2e = true; forced = true; } else if (strcmp(argv[res], "-wow") == 0) { expect_wow = true; forced = true; } else if (strcmp(argv[res], "-x64") == 0) { expect_x64 = true; #ifdef X64 set_x86_mode(dcontext, false/*x64*/); #else /* For 32-bit builds we hack a fix for -syscalls (see * decode_syscall_num()) but -Ki won't work. */ #endif forced = true; } else if (strcmp(argv[res], "-v") == 0) { verbose = true; } else if (strcmp(argv[res], "-exports") == 0) { list_exports = true; list_forwards = true; /* implied */ } else if (strcmp(argv[res], "-forwards") == 0) { list_forwards = true; } else if (strcmp(argv[res], "-Ki") == 0) { list_Ki = true; } else if (strcmp(argv[res], "-syscalls") == 0) { list_syscalls = true; } else if (strcmp(argv[res], "-ignore_Zw") == 0) { ignore_Zw = true; } else if (argv[res][0] == '-') { usage(argv[0]); assert(false); /* not reached */ } else { break; } } if (res >= argc || (!list_syscalls && !list_Ki && !list_forwards && !verbose)) { usage(argv[0]); assert(false); /* not reached */ } dll = argv[res]; if (!forced && list_syscalls) { usage(argv[0]); assert(false); /* not reached */ } process_exports(dcontext, dll); return 0; }