HRESULT STDMETHODCALLTYPE ReadExecutableAtRVA( DWORD relativeVirtualAddress, DWORD cbData, DWORD* pcbData, BYTE data[] ) { #ifdef PDBTOTIL if ( mem_reader != NULL ) { uint32 read; bool ok = mem_reader(m_load_address + relativeVirtualAddress, cbData, data, &read); if ( !ok ) return E_FAIL; *pcbData = read; return S_OK; } #endif #ifndef BUILDING_EFD #ifndef PDBTOTIL if ( get_many_bytes(m_load_address + relativeVirtualAddress, data, cbData) ) { *pcbData = cbData; return S_OK; } #endif #else qnotused(relativeVirtualAddress); qnotused(cbData); qnotused(pcbData); qnotused(data); #endif return S_FALSE; }
//---------------------------------------------------------------------- // функция оповещения static int notify(int msgnum,void *arg,...) { // Various messages: qnotused(arg); switch ( msgnum ) { // новый файл case IDP_NEWFILE: inf.mf = 0; // MSB last inf.nametype = NM_SHORT; segment_t *sptr = get_first_seg(); if ( sptr != NULL ) { if ( sptr->startEA-get_segm_base(sptr) == 0 ) { inf.beginEA = sptr->startEA; inf.startIP = 0; } } // основной сегмент - кодовый set_segm_class(get_first_seg(), "CODE"); break; // создание нового сегмента case IDP_NEWSEG: { segment_t *seg; seg=((segment_t *)arg); // установим регистры по умолчанию seg->defsr[rVds-ph.regFirstSreg] = 0; break; } } return 1; }
//-------------------------------------------------------------------------- // The plugin method - is not used for debugger plugins static void idaapi run(int arg) { #ifdef HAVE_PLUGIN_RUN plugin_run(arg); #else qnotused(arg); #endif }
//-------------------------------------------------------------------------- static bool idaapi compile( // Compile an expression const char *name, // in: name of the function which will // hold the compiled expression ea_t current_ea, // in: current address. if unknown then BADADDR const char *expr, // in: expression to compile char *errbuf, // out: error message if compilation fails size_t errbufsize) // in: size of the error buffer { // Returns: success qnotused(name); qnotused(current_ea); qnotused(expr); qnotused(errbuf); qnotused(errbufsize); // our toy interpreter doesn't support separate compilation/evaluation // some entry fields in ida won't be useable (bpt conditions, for example) qstrncpy(errbuf, "compilation error", errbufsize); return false; }
//-------------------------------------------------------------------------- // return lowcnd_t if its condition is not satisfied lowcnd_t *debmod_t::get_failed_lowcnd(thid_t tid, ea_t ea) { #ifndef ENABLE_LOWCNDS qnotused(tid); qnotused(ea); #else lowcnds_t::iterator p = cndmap.find(ea); if ( p != cndmap.end() ) { bool ok = true; idc_value_t rv; char name[32]; ::qsnprintf(name, sizeof(name), "__lc%a", ea); lowcnd_t &lc = p->second; lock_begin(); { idc_debmod = this; // is required by compiler/interpreter idc_thread = tid; // is required by interpreter if ( !lc.compiled ) { qstring func; func.sprnt("static %s() { return %s; }", name, lc.cndbody.begin()); ok = CompileLineEx(func.begin(), NULL, 0, NULL, true); if ( ok ) lc.compiled = true; } if ( ok ) ok = Run(name, 0, NULL, &rv, NULL, 0); } lock_end(); if ( !ok ) { report_idc_error(ea, get_qerrno(), get_error_data(0), get_error_string(0)); return NULL; } VarInt64(&rv); if ( rv.i64 == 0 ) return &lc; // condition is not satisfied, resume } #endif return NULL; }
//---------------------------------------------------------------------- static void swap_pef_export(pef_export_t &pe) { #if __MF__ qnotused(pe); #else pe.classAndName = swap32(pe.classAndName); pe.symbolValue = swap32(pe.symbolValue); pe.sectionIndex = swap16(pe.sectionIndex); #endif }
//-------------------------------------------------------------------------- int idaapi debmod_t::dbg_update_lowcnds( const lowcnd_t *lowcnds, int nlowcnds) { #ifndef ENABLE_LOWCNDS qnotused(lowcnds); qnotused(nlowcnds); return 0; #else for ( int i=0; i < nlowcnds; i++, lowcnds++ ) { ea_t ea = lowcnds->ea; if ( lowcnds->cndbody.empty() ) cndmap.erase(ea); else cndmap[ea] = *lowcnds; } return nlowcnds; #endif }
//---------------------------------------------------------------------- static void swap_pef_reloc_header(pef_reloc_header_t &prh) { #if __MF__ qnotused(prh); #else prh.sectionIndex = swap16(prh.sectionIndex); prh.reservedA = swap16(prh.reservedA); prh.relocCount = swap32(prh.relocCount); prh.firstRelocOffset = swap32(prh.firstRelocOffset); #endif }
//---------------------------------------------------------------------- static void swap_pef_library(pef_library_t &pil) { #if __MF__ qnotused(pil); #else pil.nameOffset = swap32(pil.nameOffset ); pil.oldImpVersion = swap32(pil.oldImpVersion ); pil.currentVersion = swap32(pil.currentVersion ); pil.importedSymbolCount = swap32(pil.importedSymbolCount); pil.firstImportedSymbol = swap32(pil.firstImportedSymbol); pil.reservedB = swap16(pil.reservedB ); #endif }
//---------------------------------------------------------------------- static void swap_pef_section(pef_section_t &ps) { #if __MF__ qnotused(ps); #else ps.nameOffset = swap32(ps.nameOffset ); ps.defaultAddress = swap32(ps.defaultAddress ); ps.totalSize = swap32(ps.totalSize ); ps.unpackedSize = swap32(ps.unpackedSize ); ps.packedSize = swap32(ps.packedSize ); ps.containerOffset = swap32(ps.containerOffset); #endif }
//---------------------------------------------------------------------- static void swap_pef(pef_t &pef) { #if __MF__ qnotused(pef); #else pef.formatVersion = swap32(pef.formatVersion); pef.dateTimeStamp = swap32(pef.dateTimeStamp); pef.oldDefVersion = swap32(pef.oldDefVersion); pef.oldImpVersion = swap32(pef.oldImpVersion); pef.currentVersion = swap32(pef.currentVersion); pef.reservedA = swap32(pef.reservedA); pef.sectionCount = swap16(pef.sectionCount); pef.instSectionCount = swap16(pef.instSectionCount); #endif }
//-------------------------------------------------------------------------- static bool idaapi calcexpr( // Compile and evaluate expression ea_t current_ea, // in: current address. if unknown then BADADDR const char *expr, // in: expression to evaluation idc_value_t *rv, // out: expression value char *errbuf, // out: error message if evaluation fails size_t errbufsize) // in: size of the error buffer { // Returns: success qnotused(current_ea); // we know to parse and decimal and hexadecimal numbers int radix = 10; const char *ptr = skipSpaces(expr); bool neg = false; if ( *ptr == '-' ) { neg = true; ptr = skipSpaces(ptr+1); } if ( *ptr == '0' && *(ptr+1) == 'x' ) { radix = 16; ptr += 2; } sval_t value = 0; while ( radix==10 ? isdigit(*ptr) : isxdigit(*ptr) ) { int d = *ptr <= '9' ? *ptr-'0' : tolower(*ptr)-'a'+10; value *= radix; value += d; ptr++; } if ( neg ) value = -value; ptr = skipSpaces(ptr); if ( *ptr != '\0' ) { msg("EVAL FAILED: %s\n", expr); qstrncpy(errbuf, "syntax error", errbufsize); return false; } // we have the result, store it in the return value rv->clear(); rv->num = value; msg("EVAL %d: %s\n", value, expr); return true; }
//---------------------------------------------------------------------- static void swap_pef_loader(pef_loader_t &pl) { #if __MF__ qnotused(pl); #else pl.mainSection = swap32(pl.mainSection ); pl.mainOffset = swap32(pl.mainOffset ); pl.initSection = swap32(pl.initSection ); pl.initOffset = swap32(pl.initOffset ); pl.termSection = swap32(pl.termSection ); pl.termOffset = swap32(pl.termOffset ); pl.importLibraryCount = swap32(pl.importLibraryCount ); pl.totalImportedSymbolCount = swap32(pl.totalImportedSymbolCount); pl.relocSectionCount = swap32(pl.relocSectionCount ); pl.relocInstrOffset = swap32(pl.relocInstrOffset ); pl.loaderStringsOffset = swap32(pl.loaderStringsOffset ); pl.exportHashOffset = swap32(pl.exportHashOffset ); pl.exportHashTablePower = swap32(pl.exportHashTablePower ); pl.exportedSymbolCount = swap32(pl.exportedSymbolCount ); #endif }
//-------------------------------------------------------------------------- static bool idaapi run( // Evaluate a previously compiled expression const char *name, // in: function to run int nargs, // in: number of input arguments const idc_value_t args[], // in: input arguments idc_value_t *result, // out: function result char *errbuf, // out: error message if evaluation fails size_t errbufsize) // in: size of the error buffer { // Returns: success qnotused(name); qnotused(nargs); qnotused(args); qnotused(result); qnotused(errbuf); qnotused(errbufsize); qstrncpy(errbuf, "evaluation error", errbufsize); return false; }
virtual void dbg_thread_exit(pid_t pid, thid_t tid, ea_t ea, int exit_code) {qnotused(pid); qnotused(tid); qnotused(ea); qnotused(exit_code); }
virtual void dbg_thread_start(pid_t pid, thid_t tid, ea_t ea) {qnotused(pid); qnotused(tid); qnotused(ea); }
virtual void dbg_process_detach(pid_t pid, thid_t tid, ea_t ea) {qnotused(pid); qnotused(tid); qnotused(ea); }
virtual void dbg_process_attach(pid_t pid, thid_t tid, ea_t ea, const char * modinfo_name, ea_t modinfo_base, asize_t modinfo_size) {qnotused(pid); qnotused(tid); qnotused(ea); qnotused(modinfo_name); qnotused(modinfo_base); qnotused(modinfo_size); }
int idaapi DBG_Callback(void *ud, int notification_code, va_list va) { // This hook gets called from the kernel. Ensure we hold the GIL. PYW_GIL_GET; class DBG_Hooks *proxy = (class DBG_Hooks *)ud; debug_event_t *event; int ret = 0; try { switch ( notification_code ) { // hookgenDBG:notifications case dbg_process_start: { const debug_event_t * event = va_arg(va, const debug_event_t *); proxy->dbg_process_start(event->pid, event->tid, event->ea, event->modinfo.name, event->modinfo.base, event->modinfo.size); } break; case dbg_process_exit: { const debug_event_t * event = va_arg(va, const debug_event_t *); proxy->dbg_process_exit(event->pid, event->tid, event->ea, event->exit_code); } break; case dbg_process_attach: { const debug_event_t * event = va_arg(va, const debug_event_t *); proxy->dbg_process_attach(event->pid, event->tid, event->ea, event->modinfo.name, event->modinfo.base, event->modinfo.size); } break; case dbg_process_detach: { const debug_event_t * event = va_arg(va, const debug_event_t *); proxy->dbg_process_detach(event->pid, event->tid, event->ea); } break; case dbg_thread_start: { const debug_event_t * event = va_arg(va, const debug_event_t *); proxy->dbg_thread_start(event->pid, event->tid, event->ea); } break; case dbg_thread_exit: { const debug_event_t * event = va_arg(va, const debug_event_t *); proxy->dbg_thread_exit(event->pid, event->tid, event->ea, event->exit_code); } break; case dbg_library_load: { const debug_event_t * event = va_arg(va, const debug_event_t *); proxy->dbg_library_load(event->pid, event->tid, event->ea, event->modinfo.name, event->modinfo.base, event->modinfo.size); } break; case dbg_library_unload: { const debug_event_t * event = va_arg(va, const debug_event_t *); proxy->dbg_library_unload(event->pid, event->tid, event->ea, event->info); } break; case dbg_information: { const debug_event_t * event = va_arg(va, const debug_event_t *); proxy->dbg_information(event->pid, event->tid, event->ea, event->info); } break; case dbg_exception: { const debug_event_t * event = va_arg(va, const debug_event_t *); int * warn = va_arg(va, int *); int _tmp = proxy->dbg_exception(event->pid, event->tid, event->ea, event->exc.code, event->exc.can_cont, event->exc.ea, event->exc.info); ret = DBG_Hooks::store_int(_tmp, event, warn); } break; case dbg_suspend_process: { const debug_event_t * event = va_arg(va, const debug_event_t *); qnotused(event); proxy->dbg_suspend_process(); } break; case dbg_bpt: { thid_t tid = va_arg(va, thid_t); ea_t bptea = va_arg(va, ea_t); int * warn = va_arg(va, int *); int _tmp = proxy->dbg_bpt(tid, bptea); ret = DBG_Hooks::store_int(_tmp, tid, bptea, warn); } break; case dbg_trace: { thid_t tid = va_arg(va, thid_t); ea_t ip = va_arg(va, ea_t); ret = proxy->dbg_trace(tid, ip); } break; case dbg_request_error: { ui_notification_t failed_command = ui_notification_t(va_arg(va, int)); dbg_notification_t failed_dbg_notification = dbg_notification_t(va_arg(va, int)); proxy->dbg_request_error((int) failed_command, (int) failed_dbg_notification); } break; case dbg_step_into: { const debug_event_t * event = va_arg(va, const debug_event_t *); qnotused(event); proxy->dbg_step_into(); } break; case dbg_step_over: { const debug_event_t * event = va_arg(va, const debug_event_t *); qnotused(event); proxy->dbg_step_over(); } break; case dbg_run_to: { const debug_event_t * event = va_arg(va, const debug_event_t *); proxy->dbg_run_to(event->pid, event->tid, event->ea); } break; case dbg_step_until_ret: { const debug_event_t * event = va_arg(va, const debug_event_t *); qnotused(event); proxy->dbg_step_until_ret(); } break; case dbg_bpt_changed: { int bptev_code = va_arg(va, int); bpt_t * bpt = va_arg(va, bpt_t *); proxy->dbg_bpt_changed(bptev_code, bpt); } break; } } catch (Swig::DirectorException &e) { msg("Exception in DBG Hook function: %s\n", e.getMessage()); if ( PyErr_Occurred() ) PyErr_Print(); } return ret; }
//-------------------------------------------------------------------------- static int idaapi callback( void * /*user_data*/, int notification_code, va_list va) { static int stage = 0; static bool is_dll; static char needed_file[QMAXPATH]; switch ( notification_code ) { case dbg_process_start: case dbg_process_attach: get_input_file_path(needed_file, sizeof(needed_file)); // no break case dbg_library_load: if ( stage == 0 ) { const debug_event_t *pev = va_arg(va, const debug_event_t *); if ( !strieq(pev->modinfo.name, needed_file) ) break; if ( notification_code == dbg_library_load ) is_dll = true; // remember the current module bounds if ( pev->modinfo.rebase_to != BADADDR ) curmod.startEA = pev->modinfo.rebase_to; else curmod.startEA = pev->modinfo.base; curmod.endEA = curmod.startEA + pev->modinfo.size; deb(IDA_DEBUG_PLUGIN, "UUNP: module space %a-%a\n", curmod.startEA, curmod.endEA); ++stage; } break; case dbg_library_unload: if ( stage != 0 && is_dll ) { const debug_event_t *pev = va_arg(va, const debug_event_t *); if ( curmod.startEA == pev->modinfo.base || curmod.startEA == pev->modinfo.rebase_to ) { deb(IDA_DEBUG_PLUGIN, "UUNP: unload unpacked module\n"); if ( stage > 2 ) enable_step_trace(false); stage = 0; curmod.startEA = 0; curmod.endEA = 0; _hide_wait_box(); } } break; case dbg_run_to: // Parameters: const debug_event_t *event dbg->stopped_at_debug_event(true); bp_gpa = get_name_ea(BADADDR, "kernel32_GetProcAddress"); #ifndef __X64__ if( (LONG)GetVersion() < 0 ) // win9x mode -- use thunk's { is_9x = true; win9x_resolve_gpa_thunk(); } #endif if ( bp_gpa == BADADDR ) { bring_debugger_to_front(); warning("Sorry, could not find kernel32.GetProcAddress"); FORCE_STOP: stage = 4; // last stage clear_requests_queue(); request_exit_process(); run_requests(); break; } else if( !my_add_bpt(bp_gpa) ) { bring_debugger_to_front(); warning("Sorry, can not set bpt to kernel32.GetProcAddress"); goto FORCE_STOP; } else { ++stage; set_wait_box("Waiting for a call to GetProcAddress()"); } continue_process(); break; case dbg_bpt: // A user defined breakpoint was reached. // Parameters: thid_t tid // ea_t breakpoint_ea // int *warn = -1 // Return (in *warn): // -1 - to display a breakpoint warning dialog // if the process is suspended. // 0 - to never display a breakpoint warning dialog. // 1 - to always display a breakpoint warning dialog. { thid_t tid = va_arg(va, thid_t); qnotused(tid); ea_t ea = va_arg(va, ea_t); //int *warn = va_arg(va, int*); if ( stage == 2 ) { if ( ea == bp_gpa ) { regval_t rv; if ( get_reg_val(REGNAME_ESP, &rv) ) { ea_t esp = ea_t(rv.ival); invalidate_dbgmem_contents(esp, 1024); ea_t gpa_caller = getPtr(esp); if ( !is_library_entry(gpa_caller) ) { ea_t nameaddr; if ( ptrSz == 4 ) { nameaddr = get_long(esp+8); } else { get_reg_val(REGNAME_ECX, &rv); nameaddr = ea_t(rv.ival); } invalidate_dbgmem_contents(nameaddr, 1024); char name[MAXSTR]; size_t len = get_max_ascii_length(nameaddr, ASCSTR_C, ALOPT_IGNHEADS); name[0] = '\0'; get_ascii_contents2(nameaddr, len, ASCSTR_C, name, sizeof(name)); if ( !ignore_win32_api(name) ) { deb(IDA_DEBUG_PLUGIN, "%a: found a call to GetProcAddress(%s)\n", gpa_caller, name); if ( !my_del_bpt(bp_gpa) || !my_add_bpt(gpa_caller) ) error("Can not modify breakpoint"); } } } } else if ( ea == bpt_ea ) { my_del_bpt(ea); if ( !is_library_entry(ea) ) { msg("Uunp: reached unpacker code at %a, switching to trace mode\n", ea); enable_step_trace(true); ++stage; uint64 eax; if ( get_reg_val(REGNAME_EAX, &eax) ) an_imported_func = ea_t(eax); set_wait_box("Waiting for the unpacker to finish"); } else { warning("%a: bpt in library code", ea); // how can it be? my_add_bpt(bp_gpa); } } // not our bpt? skip it else { // hide the wait box to allow others plugins to properly stop _hide_wait_box(); break; } } } // while continue_process() would work here too, request+run is more universal // because they do not ignore the request queue request_continue_process(); run_requests(); break; case dbg_trace: // A step occured (one instruction was executed). This event // notification is only generated if step tracing is enabled. // Parameter: none if ( stage == 3 ) { thid_t tid = va_arg(va, thid_t); qnotused(tid); ea_t ip = va_arg(va, ea_t); // ip reached the OEP range? if ( oep_area.contains(ip) ) { // stop the trace mode enable_step_trace(false); msg("Uunp: reached OEP %a\n", ip); set_wait_box("Reanalyzing the unpacked code"); // reanalyze the unpacked code do_unknown_range(oep_area.startEA, oep_area.size(), DOUNK_EXPAND); auto_make_code(ip); // plan to make code noUsed(oep_area.startEA, oep_area.endEA); // plan to reanalyze auto_mark_range(oep_area.startEA, oep_area.endEA, AU_FINAL); // plan to analyze move_entry(ip); // mark the program's entry point _hide_wait_box(); // inform the user bring_debugger_to_front(); if ( askyn_c(1, "HIDECANCEL\n" "The universal unpacker has finished its work.\n" "Do you want to take a memory snapshot and stop now?\n" "(you can do it yourself if you want)\n") > 0 ) { set_wait_box("Recreating the import table"); invalidate_dbgmem_config(); if ( is_9x ) find_thunked_imports(); create_impdir(); set_wait_box("Storing resources to 'resource.res'"); if ( resfile[0] != '\0' ) extract_resource(resfile); _hide_wait_box(); if ( take_memory_snapshot(true) ) goto FORCE_STOP; } suspend_process(); unhook_from_notification_point(HT_DBG, callback, NULL); } } break; case dbg_process_exit: { stage = 0; // stop the tracing _hide_wait_box(); unhook_from_notification_point(HT_DBG, callback, NULL); if ( success ) jumpto(inf.beginEA, -1); else tell_about_failure(); } break; case dbg_exception:// Parameters: const debug_event_t *event // int *warn = -1 // Return (in *warn): // -1 - to display an exception warning dialog // if the process is suspended. // 0 - to never display an exception warning dialog. // 1 - to always display an exception warning dialog. { // const debug_event_t *event = va_arg(va, const debug_event_t *); // int *warn = va_arg(va, int *); // FIXME: handle code which uses SEH to unpack itself if ( askyn_c(1, "AUTOHIDE DATABASE\n" "HIDECANCEL\n" "An exception occurred in the program.\n" "UUNP does not support exceptions yet.\n" "The execution has been suspended.\n" "Do you want to continue the unpacking?") <= 0 ) { _hide_wait_box(); stage = 0; enable_step_trace(false); // stop the trace mode suspend_process(); } else { continue_process(); } } break; case dbg_request_error: // An error occured during the processing of a request. // Parameters: ui_notification_t failed_command // dbg_notification_t failed_dbg_notification { ui_notification_t failed_cmd = va_arg(va, ui_notification_t); dbg_notification_t failed_dbg_notification = va_arg(va, dbg_notification_t); _hide_wait_box(); stage = 0; warning("dbg request error: command: %d notification: %d", failed_cmd, failed_dbg_notification); } break; } return 0; }
virtual void dbg_request_error(int failed_command, int failed_dbg_notification) {qnotused(failed_command); qnotused(failed_dbg_notification); }
virtual int dbg_trace(thid_t tid, ea_t ip) {qnotused(tid); qnotused(ip); return 0;}
virtual int dbg_bpt(thid_t tid, ea_t bptea) {qnotused(tid); qnotused(bptea); return 0;}
virtual void dbg_information(pid_t pid, thid_t tid, ea_t ea, const char * info) {qnotused(pid); qnotused(tid); qnotused(ea); qnotused(info); }
virtual void dbg_library_load(pid_t pid, thid_t tid, ea_t ea, const char * modinfo_name, ea_t modinfo_base, asize_t modinfo_size) {qnotused(pid); qnotused(tid); qnotused(ea); qnotused(modinfo_name); qnotused(modinfo_base); qnotused(modinfo_size); }
virtual void dbg_run_to(pid_t pid, thid_t tid, ea_t ea) {qnotused(pid); qnotused(tid); qnotused(ea); }
virtual void dbg_library_unload(pid_t pid, thid_t tid, ea_t ea, const char * info) {qnotused(pid); qnotused(tid); qnotused(ea); qnotused(info); }
virtual void dbg_bpt_changed(int bptev_code, bpt_t * bpt) {qnotused(bptev_code); qnotused(bpt); }
virtual int dbg_exception(pid_t pid, thid_t tid, ea_t ea, int exc_code, bool exc_can_cont, ea_t exc_ea, const char * exc_info) {qnotused(pid); qnotused(tid); qnotused(ea); qnotused(exc_code); qnotused(exc_can_cont); qnotused(exc_ea); qnotused(exc_info); return 0;}
//---------------------------------------------------------- main thread --- int idaapi win32_debmod_t::handle_ioctl( int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize) { qnotused(size); switch ( fn ) { case WIN32_IOCTL_RDMSR: QASSERT(30119, size == sizeof(uval_t)); { uint64 value; uval_t reg = *(uval_t *)buf; int code = rdmsr(reg, &value); if ( SUCCEEDED(code) ) { *poutbuf = qalloc(sizeof(value)); if ( *poutbuf != NULL ) { memcpy(*poutbuf, &value, sizeof(value)); *poutsize = sizeof(value); } } return code; } case WIN32_IOCTL_WRMSR: QASSERT(30120, size == sizeof(win32_wrmsr_t)); { win32_wrmsr_t &msr = *(win32_wrmsr_t *)buf; return wrmsr(msr.reg, msr.value); } #ifdef ENABLE_REMOTEPDB case WIN32_IOCTL_STARTPDB: QASSERT(30192, size >= sizeof(uint64)); { qstring errmsg; if ( pdbthread.is_running() ) { errmsg = "Only one PDB conversion at a time is supported!"; PDBERROR: *poutsize = errmsg.size(); *poutbuf = errmsg.extract(); return -2; } const uchar *ptr = (const uchar *)buf; const uchar *end = ptr + size; compiler_info_t cc; extract_memory(&ptr, end, &cc, sizeof(cc)); ea_t base_ea = extract_ea64(&ptr, end); const char *pdbfile = extract_str(&ptr, end); const char *dpath = extract_str(&ptr, end); const char *spath = extract_str(&ptr, end); if ( !pdbthread.do_convert(cc, base_ea, pdbfile, dpath, spath) ) { errmsg = "Error starting PDB conversion!"; goto PDBERROR; } return 0x1234; // dummy ID } case WIN32_IOCTL_DONEPDB: { qstring errmsg; if ( !pdbthread.is_running() ) { errmsg = "PDB conversion is not started!"; PDBERROR2: *poutsize = errmsg.size(); *poutbuf = errmsg.extract(); return -2; } const uchar *ptr = (const uchar *)buf; const uchar *end = ptr + size; uint32 id = extract_long(&ptr, end); if ( id != 0x1234 ) { errmsg = "Bad conversion ID"; goto PDBERROR2; } if ( pdbthread.is_waiting_req() ) { // we've got a read request, handle it now handle_pdb_request(); pdbthread.post_req_done(); } if ( pdbthread.is_done() ) { // done pdbthread.finalize(); *poutsize = pdbthread.tilfname.size(); *poutbuf = pdbthread.tilfname.extract(); return 2; } else { // not done yet return 1; } } case WIN32_IOCTL_RMFILE: { qstring errmsg; const uchar *ptr = (const uchar *)buf; const uchar *end = ptr + size; const char *filename = extract_str(&ptr, end); if ( filename == NULL ) { errmsg = "Filename missing"; PDBERROR3: *poutsize = errmsg.size(); *poutbuf = errmsg.extract(); return -2; } if ( unlink(filename) != 0 ) { errmsg = "Error deleting file"; goto PDBERROR3; } return 1; } #endif // REMOTEPDB default: break; } return 0; }