static enum dbg_start minidump_do_reload(struct tgt_process_minidump_data* data) { ULONG size; MINIDUMP_DIRECTORY* dir; void* stream; DWORD pid = 1; /* by default */ HANDLE hProc = (HANDLE)0x900DBAAD; int i; MINIDUMP_MODULE_LIST* mml; MINIDUMP_MODULE* mm; MINIDUMP_STRING* mds; char exec_name[1024]; char name[1024]; unsigned len; /* fetch PID */ if (MiniDumpReadDumpStream(data->mapping, MiscInfoStream, &dir, &stream, &size)) { MINIDUMP_MISC_INFO* mmi = (MINIDUMP_MISC_INFO*)stream; if (mmi->Flags1 & MINIDUMP_MISC1_PROCESS_ID) pid = mmi->ProcessId; } /* fetch executable name (it's normally the first one in module list) */ strcpy(exec_name, "<minidump-exec>"); /* default */ if (MiniDumpReadDumpStream(data->mapping, ModuleListStream, &dir, &stream, &size)) { mml = (MINIDUMP_MODULE_LIST*)stream; if (mml->NumberOfModules) { char* ptr; mm = &mml->Modules[0]; mds = (MINIDUMP_STRING*)((char*)data->mapping + mm->ModuleNameRva); len = WideCharToMultiByte(CP_ACP, 0, mds->Buffer, mds->Length / sizeof(WCHAR), name, sizeof(name) - 1, NULL, NULL); name[len] = 0; for (ptr = name + len - 1; ptr >= name; ptr--) { if (*ptr == '/' || *ptr == '\\') { strcpy(exec_name, ptr + 1); break; } } if (ptr < name) strcpy(exec_name, name); } } if (MiniDumpReadDumpStream(data->mapping, SystemInfoStream, &dir, &stream, &size)) { MINIDUMP_SYSTEM_INFO* msi = (MINIDUMP_SYSTEM_INFO*)stream; const char *str; char tmp[128]; dbg_printf("WineDbg starting on minidump on pid %lu\n", pid); switch (msi->ProcessorArchitecture) { case PROCESSOR_ARCHITECTURE_UNKNOWN: str = "Unknown"; break; case PROCESSOR_ARCHITECTURE_INTEL: strcpy(tmp, "Intel "); switch (msi->ProcessorLevel) { case 3: str = "80386"; break; case 4: str = "80486"; break; case 5: str = "Pentium"; break; case 6: str = "Pentium Pro/II"; break; default: str = "???"; break; } strcat(tmp, str); if (msi->ProcessorLevel == 3 || msi->ProcessorLevel == 4) { if (HIWORD(msi->ProcessorRevision) == 0xFF) sprintf(tmp + strlen(tmp), "-%c%d", 'A' + HIBYTE(LOWORD(msi->ProcessorRevision)), LOBYTE(LOWORD(msi->ProcessorRevision))); else sprintf(tmp + strlen(tmp), "-%c%d", 'A' + HIWORD(msi->ProcessorRevision), LOWORD(msi->ProcessorRevision)); } else sprintf(tmp + strlen(tmp), "-%d.%d", HIWORD(msi->ProcessorRevision), LOWORD(msi->ProcessorRevision)); str = tmp; break; case PROCESSOR_ARCHITECTURE_MIPS: str = "Mips"; break; case PROCESSOR_ARCHITECTURE_ALPHA: str = "Alpha"; break; case PROCESSOR_ARCHITECTURE_PPC: str = "PowerPC"; break; default: str = "???"; break; } dbg_printf(" %s was running on #%d %s CPU%s", exec_name, msi->u.s.NumberOfProcessors, str, msi->u.s.NumberOfProcessors < 2 ? "" : "s"); switch (msi->MajorVersion) { case 3: switch (msi->MinorVersion) { case 51: str = "NT 3.51"; break; default: str = "3-????"; break; } break; case 4: switch (msi->MinorVersion) { case 0: str = (msi->PlatformId == VER_PLATFORM_WIN32_NT) ? "NT 4.0" : "95"; break; case 10: str = "98"; break; case 90: str = "ME"; break; default: str = "5-????"; break; } break; case 5: switch (msi->MinorVersion) { case 0: str = "2000"; break; case 1: str = "XP"; break; case 2: str = "Server 2003"; break; default: str = "5-????"; break; } break; default: str = "???"; break; } dbg_printf(" on Windows %s (%lu)\n", str, msi->BuildNumber); /* FIXME CSD: msi->CSDVersionRva */ } dbg_curr_process = dbg_add_process(&be_process_minidump_io, pid, hProc); dbg_curr_pid = pid; dbg_curr_process->pio_data = data; dbg_set_process_name(dbg_curr_process, exec_name); SymInitialize(hProc, NULL, FALSE); if (MiniDumpReadDumpStream(data->mapping, ThreadListStream, &dir, &stream, &size)) { MINIDUMP_THREAD_LIST* mtl = (MINIDUMP_THREAD_LIST*)stream; MINIDUMP_THREAD* mt = &mtl->Threads[0]; dbg_add_thread(dbg_curr_process, mt->ThreadId, NULL, (void*)(DWORD_PTR)mt->Teb); } /* first load ELF modules, then do the PE ones */ if (MiniDumpReadDumpStream(data->mapping, Wine_ElfModuleListStream, &dir, &stream, &size)) { char buffer[MAX_PATH]; mml = (MINIDUMP_MODULE_LIST*)stream; for (i = 0, mm = &mml->Modules[0]; i < mml->NumberOfModules; i++, mm++) { mds = (MINIDUMP_STRING*)((char*)data->mapping + mm->ModuleNameRva); len = WideCharToMultiByte(CP_ACP, 0, mds->Buffer, mds->Length / sizeof(WCHAR), name, sizeof(name) - 1, NULL, NULL); name[len] = 0; if (SymFindFileInPath(hProc, NULL, name, (void*)(DWORD_PTR)mm->CheckSum, 0, 0, SSRVOPT_DWORD, buffer, validate_file, NULL)) SymLoadModule(hProc, NULL, buffer, NULL, mm->BaseOfImage, mm->SizeOfImage); else SymLoadModuleEx(hProc, NULL, name, NULL, mm->BaseOfImage, mm->SizeOfImage, NULL, SLMFLAG_VIRTUAL); } } if (MiniDumpReadDumpStream(data->mapping, ModuleListStream, &dir, &stream, &size)) { mml = (MINIDUMP_MODULE_LIST*)stream; for (i = 0, mm = &mml->Modules[0]; i < mml->NumberOfModules; i++, mm++) { mds = (MINIDUMP_STRING*)((char*)data->mapping + mm->ModuleNameRva); len = WideCharToMultiByte(CP_ACP, 0, mds->Buffer, mds->Length / sizeof(WCHAR), name, sizeof(name) - 1, NULL, NULL); name[len] = 0; SymLoadModule(hProc, NULL, name, NULL, mm->BaseOfImage, mm->SizeOfImage); } } if (MiniDumpReadDumpStream(data->mapping, ExceptionStream, &dir, &stream, &size)) { MINIDUMP_EXCEPTION_STREAM* mes = (MINIDUMP_EXCEPTION_STREAM*)stream; if ((dbg_curr_thread = dbg_get_thread(dbg_curr_process, mes->ThreadId))) { ADDRESS64 addr; dbg_curr_tid = mes->ThreadId; dbg_curr_thread->in_exception = TRUE; dbg_curr_thread->excpt_record.ExceptionCode = mes->ExceptionRecord.ExceptionCode; dbg_curr_thread->excpt_record.ExceptionFlags = mes->ExceptionRecord.ExceptionFlags; dbg_curr_thread->excpt_record.ExceptionRecord = (void*)(DWORD_PTR)mes->ExceptionRecord.ExceptionRecord; dbg_curr_thread->excpt_record.ExceptionAddress = (void*)(DWORD_PTR)mes->ExceptionRecord.ExceptionAddress; dbg_curr_thread->excpt_record.NumberParameters = mes->ExceptionRecord.NumberParameters; for (i = 0; i < dbg_curr_thread->excpt_record.NumberParameters; i++) { dbg_curr_thread->excpt_record.ExceptionInformation[i] = mes->ExceptionRecord.ExceptionInformation[i]; } memcpy(&dbg_context, (char*)data->mapping + mes->ThreadContext.Rva, min(sizeof(dbg_context), mes->ThreadContext.DataSize)); memory_get_current_pc(&addr); stack_fetch_frames(); be_cpu->print_context(dbg_curr_thread->handle, &dbg_context, 0); stack_info(); be_cpu->print_segment_info(dbg_curr_thread->handle, &dbg_context); stack_backtrace(mes->ThreadId); source_list_from_addr(&addr, 0); } } return start_ok; }
void *client(void *arg) { CLI *c=arg; #ifdef DEBUG_STACK_SIZE stack_info(1); /* initialize */ #endif log(LOG_DEBUG, "%s started", c->opt->servname); #ifndef USE_WIN32 if(c->opt->option.remote && c->opt->option.program) c->local_rfd.fd=c->local_wfd.fd=connect_local(c); /* connect and exec options specified together */ /* spawn local program instead of stdio */ #endif c->remote_fd.fd=-1; c->ssl=NULL; cleanup(c, do_client(c)); #ifdef USE_FORK if(!c->opt->option.remote) /* 'exec' specified */ exec_status(); /* null SIGCHLD handler was used */ #else enter_critical_section(CRIT_CLIENTS); /* for multi-cpu machines */ log(LOG_DEBUG, "%s finished (%d left)", c->opt->servname, --num_clients); leave_critical_section(CRIT_CLIENTS); #endif free(c); #ifdef DEBUG_STACK_SIZE stack_info(0); /* display computed value */ #endif return NULL; }
void *client_thread(void *arg) { CLI *c = arg; #ifdef DEBUG_STACK_SIZE stack_info(1); #endif client_main(c); #ifdef DEBUG_STACK_SIZE stack_info(0); #endif str_stats(); str_cleanup(); return NULL; }
void *client(void *arg) { CLI *c=arg; #ifdef DEBUG_STACK_SIZE stack_info(1); /* initialize */ #endif s_log(LOG_DEBUG, "%s started", c->opt->servname); if(alloc_fd(c->local_rfd.fd)) return NULL; if(c->local_wfd.fd!=c->local_rfd.fd) if(alloc_fd(c->local_wfd.fd)) return NULL; #ifndef USE_WIN32 if(c->opt->option.remote && c->opt->option.program) c->local_rfd.fd=c->local_wfd.fd=connect_local(c); /* connect and exec options specified together */ /* spawn local program instead of stdio */ #endif c->remote_fd.fd=-1; c->ssl=NULL; cleanup(c, do_client(c)); #ifdef USE_FORK if(!c->opt->option.remote) /* 'exec' specified */ child_status(); /* null SIGCHLD handler was used */ #else enter_critical_section(CRIT_CLIENTS); /* for multi-cpu machines */ s_log(LOG_DEBUG, "%s finished (%d left)", c->opt->servname, --num_clients); leave_critical_section(CRIT_CLIENTS); #endif free(c); #ifdef DEBUG_STACK_SIZE stack_info(0); /* display computed value */ #endif #ifdef USE_WIN32 _endthread(); #endif #ifdef USE_UCONTEXT s_log(LOG_DEBUG, "Context %ld closed", ready_head->id); s_poll_wait(NULL, 0); /* wait on poll() */ s_log(LOG_ERR, "INTERNAL ERROR: failed to drop context"); #endif return NULL; }
void *client_thread(void *arg) { CLI *c=arg; #ifdef DEBUG_STACK_SIZE stack_info(1); /* initialize */ #endif client_main(c); #ifdef DEBUG_STACK_SIZE stack_info(0); /* display computed value */ #endif str_stats(); str_cleanup(); /* s_log() is not allowed after str_cleanup() */ #if defined(USE_WIN32) && !defined(_WIN32_WCE) _endthread(); #endif #ifdef USE_UCONTEXT s_poll_wait(NULL, 0, 0); /* wait on poll() */ #endif return NULL; }
void *client(void *arg) { CLI *c=arg; #ifdef DEBUG_STACK_SIZE stack_info(1); /* initialize */ #endif s_log(LOG_DEBUG, "Service %s started", c->opt->servname); if(c->opt->option.remote && c->opt->option.program) { /* connect and exec options specified together */ /* -> spawn a local program instead of stdio */ while((c->local_rfd.fd=c->local_wfd.fd=connect_local(c))>=0) { run_client(c); if(!c->opt->option.retry) break; sleep(1); /* FIXME: not a good idea in ucontext threading */ str_stats(); str_cleanup(); } } else run_client(c); /* str_free() cannot be used here, because corresponding calloc() is called from a different thread */ free(c); #ifdef DEBUG_STACK_SIZE stack_info(0); /* display computed value */ #endif #ifdef USE_UCONTEXT s_log(LOG_DEBUG, "Context %ld closed", ready_head->id); #endif str_stats(); str_cleanup(); /* s_log() is not allowed after str_cleanup() */ #if defined(USE_WIN32) && !defined(_WIN32_WCE) _endthread(); #endif #ifdef USE_UCONTEXT s_poll_wait(NULL, 0, 0); /* wait on poll() */ #endif return NULL; }
void column_attach(Area *a, Frame *f) { Frame *first; int nframe, dy, h; f->colr = a->r; if(a->sel) { stack_info(a->sel, &first, nil, &dy, &nframe); h = dy / (nframe+1); f->colr.max.y = f->colr.min.y + h; stack_scale(first, dy - h); } column_insert(a, f, a->sel); column_arrange(a, false); }
void column_detach(Frame *f) { Frame *first; Area *a; int dy; a = f->area; stack_info(f, &first, nil, &dy, nil); if(first && first == f) first = f->anext; column_remove(f); if(a->frame) { if(first) stack_scale(first, dy); column_arrange(a, false); }else if(a->view->areas[a->screen]->next) area_destroy(a); }
RuntimeIC::RuntimeIC(void* func_addr, int num_slots, int slot_size) : eh_frame(RUNTIMEICS_OMIT_FRAME_PTR) { static StatCounter sc("runtime_ics_num"); sc.log(); if (ENABLE_RUNTIME_ICS) { assert(SCRATCH_BYTES >= 0); assert(SCRATCH_BYTES < 0x80); // This would break both the instruction encoding and the dwarf encoding assert(SCRATCH_BYTES % 8 == 0); #if RUNTIMEICS_OMIT_FRAME_PTR /* * prologue: * sub $0x28, %rsp # 48 83 ec 28 * * epilogue: * add $0x28, %rsp # 48 83 c4 28 * retq # c3 * */ static const int PROLOGUE_SIZE = 4; static const int EPILOGUE_SIZE = 5; assert(SCRATCH_BYTES % 16 == 8); #else /* * The prologue looks like: * push %rbp # 55 * mov %rsp, %rbp # 48 89 e5 * sub $0x30, %rsp # 48 83 ec 30 * * The epilogue is: * add $0x30, %rsp # 48 83 c4 30 * pop %rbp # 5d * retq # c3 */ static const int PROLOGUE_SIZE = 8; static const int EPILOGUE_SIZE = 6; assert(SCRATCH_BYTES % 16 == 0); #endif static const int CALL_SIZE = 13; int patchable_size = num_slots * slot_size; #ifdef NVALGRIND int total_size = PROLOGUE_SIZE + patchable_size + CALL_SIZE + EPILOGUE_SIZE; addr = malloc(total_size); #else total_size = PROLOGUE_SIZE + patchable_size + CALL_SIZE + EPILOGUE_SIZE; addr = mmap(NULL, (total_size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); RELEASE_ASSERT(addr != MAP_FAILED, ""); #endif // printf("Allocated runtime IC at %p\n", addr); std::unique_ptr<ICSetupInfo> setup_info( ICSetupInfo::initialize(true, num_slots, slot_size, ICSetupInfo::Generic, NULL)); uint8_t* pp_start = (uint8_t*)addr + PROLOGUE_SIZE; uint8_t* pp_end = pp_start + patchable_size + CALL_SIZE; SpillMap _spill_map; PatchpointInitializationInfo initialization_info = initializePatchpoint3(func_addr, pp_start, pp_end, 0 /* scratch_offset */, 0 /* scratch_size */, std::unordered_set<int>(), _spill_map); assert(_spill_map.size() == 0); assert(initialization_info.slowpath_start == pp_start + patchable_size); assert(initialization_info.slowpath_rtn_addr == pp_end); assert(initialization_info.continue_addr == pp_end); StackInfo stack_info(SCRATCH_BYTES, 0); icinfo = registerCompiledPatchpoint(pp_start, pp_start + patchable_size, pp_end, pp_end, setup_info.get(), stack_info, std::unordered_set<int>()); assembler::Assembler prologue_assem((uint8_t*)addr, PROLOGUE_SIZE); #if RUNTIMEICS_OMIT_FRAME_PTR // If SCRATCH_BYTES is 8 or less, we could use more compact instruction encodings // (push instead of sub), but it doesn't seem worth it for now. prologue_assem.sub(assembler::Immediate(SCRATCH_BYTES), assembler::RSP); #else prologue_assem.push(assembler::RBP); prologue_assem.mov(assembler::RSP, assembler::RBP); prologue_assem.sub(assembler::Immediate(SCRATCH_BYTES), assembler::RSP); #endif assert(!prologue_assem.hasFailed()); assert(prologue_assem.isExactlyFull()); assembler::Assembler epilogue_assem(pp_end, EPILOGUE_SIZE); #if RUNTIMEICS_OMIT_FRAME_PTR epilogue_assem.add(assembler::Immediate(SCRATCH_BYTES), assembler::RSP); #else epilogue_assem.add(assembler::Immediate(SCRATCH_BYTES), assembler::RSP); epilogue_assem.pop(assembler::RBP); #endif epilogue_assem.retq(); assert(!epilogue_assem.hasFailed()); assert(epilogue_assem.isExactlyFull()); // TODO: ideally would be more intelligent about allocation strategies. // The code sections should be together and the eh sections together eh_frame.writeAndRegister(addr, total_size); } else { addr = func_addr; } }
RuntimeIC::RuntimeIC(void* func_addr, int total_size) { static StatCounter sc("num_runtime_ics"); sc.log(); if (ENABLE_RUNTIME_ICS) { assert(SCRATCH_BYTES >= 0); assert(SCRATCH_BYTES < 0x80); // This would break both the instruction encoding and the dwarf encoding assert(SCRATCH_BYTES % 8 == 0); #if RUNTIMEICS_OMIT_FRAME_PTR /* * prologue: * sub $0x28, %rsp # 48 83 ec 28 * * epilogue: * add $0x28, %rsp # 48 83 c4 28 * retq # c3 * */ static const int PROLOGUE_SIZE = 4; static const int EPILOGUE_SIZE = 5; assert(SCRATCH_BYTES % 16 == 8); #else /* * The prologue looks like: * push %rbp # 55 * mov %rsp, %rbp # 48 89 e5 * sub $0x30, %rsp # 48 83 ec 30 * * The epilogue is: * add $0x30, %rsp # 48 83 c4 30 * pop %rbp # 5d * retq # c3 */ static const int PROLOGUE_SIZE = 8; static const int EPILOGUE_SIZE = 6; assert(SCRATCH_BYTES % 16 == 0); #endif static const int CALL_SIZE = 13; int total_code_size = total_size - EH_FRAME_SIZE; int patchable_size = total_code_size - (PROLOGUE_SIZE + CALL_SIZE + EPILOGUE_SIZE); int total_size = total_code_size + EH_FRAME_SIZE; assert(total_size == 512 && "we currently only have a 512 byte block memory manager"); addr = memory_manager_512b.alloc(); // the memory block contains the EH frame directly followed by the generated machine code. void* eh_frame_addr = addr; addr = (char*)addr + EH_FRAME_SIZE; // printf("Allocated runtime IC at %p\n", addr); std::unique_ptr<ICSetupInfo> setup_info(ICSetupInfo::initialize(true, patchable_size, ICSetupInfo::Generic)); uint8_t* pp_start = (uint8_t*)addr + PROLOGUE_SIZE; uint8_t* pp_end = pp_start + patchable_size + CALL_SIZE; SpillMap _spill_map; PatchpointInitializationInfo initialization_info = initializePatchpoint3( func_addr, pp_start, pp_end, 0 /* scratch_offset */, 0 /* scratch_size */, LiveOutSet(), _spill_map); assert(_spill_map.size() == 0); assert(initialization_info.slowpath_start == pp_start + patchable_size); assert(initialization_info.slowpath_rtn_addr == pp_end); assert(initialization_info.continue_addr == pp_end); StackInfo stack_info(SCRATCH_BYTES, 0); icinfo = registerCompiledPatchpoint(pp_start, pp_start + patchable_size, pp_end, pp_end, setup_info.get(), stack_info, LiveOutSet()); assembler::Assembler prologue_assem((uint8_t*)addr, PROLOGUE_SIZE); #if RUNTIMEICS_OMIT_FRAME_PTR // If SCRATCH_BYTES is 8 or less, we could use more compact instruction encodings // (push instead of sub), but it doesn't seem worth it for now. prologue_assem.sub(assembler::Immediate(SCRATCH_BYTES), assembler::RSP); #else prologue_assem.push(assembler::RBP); prologue_assem.mov(assembler::RSP, assembler::RBP); prologue_assem.sub(assembler::Immediate(SCRATCH_BYTES), assembler::RSP); #endif assert(!prologue_assem.hasFailed()); assert(prologue_assem.isExactlyFull()); assembler::Assembler epilogue_assem(pp_end, EPILOGUE_SIZE); #if RUNTIMEICS_OMIT_FRAME_PTR epilogue_assem.add(assembler::Immediate(SCRATCH_BYTES), assembler::RSP); #else epilogue_assem.add(assembler::Immediate(SCRATCH_BYTES), assembler::RSP); epilogue_assem.pop(assembler::RBP); #endif epilogue_assem.retq(); assert(!epilogue_assem.hasFailed()); assert(epilogue_assem.isExactlyFull()); if (RUNTIMEICS_OMIT_FRAME_PTR) memcpy(eh_frame_addr, _eh_frame_template_ofp, _eh_frame_template_ofp_size); else memcpy(eh_frame_addr, _eh_frame_template_fp, _eh_frame_template_fp_size); register_eh_frame.updateAndRegisterFrameFromTemplate((uint64_t)addr, total_code_size, (uint64_t)eh_frame_addr, EH_FRAME_SIZE); } else { addr = func_addr; } }
/*********************************************************************** * dbg_exception_prolog * * Examine exception and decide if interactive mode is entered(return TRUE) * or exception is silently continued(return FALSE) * is_debug means the exception is a breakpoint or single step exception */ static unsigned dbg_exception_prolog(BOOL is_debug, BOOL first_chance, const EXCEPTION_RECORD* rec) { ADDRESS64 addr; BOOL is_break; char hexbuf[MAX_OFFSET_TO_STR_LEN]; memory_get_current_pc(&addr); break_suspend_execution(); dbg_curr_thread->excpt_record = *rec; dbg_curr_thread->in_exception = TRUE; if (!is_debug) { switch (addr.Mode) { case AddrModeFlat: dbg_printf(" in 32-bit code (%s)", memory_offset_to_string(hexbuf, addr.Offset, 0)); break; case AddrModeReal: dbg_printf(" in vm86 code (%04x:%04x)", addr.Segment, (unsigned) addr.Offset); break; case AddrMode1616: dbg_printf(" in 16-bit code (%04x:%04x)", addr.Segment, (unsigned) addr.Offset); break; case AddrMode1632: dbg_printf(" in 32-bit code (%04x:%08lx)", addr.Segment, (unsigned long) addr.Offset); break; default: dbg_printf(" bad address"); } dbg_printf(".\n"); } /* this will resynchronize builtin dbghelp's internal ELF module list */ SymLoadModule(dbg_curr_process->handle, 0, 0, 0, 0, 0); if (is_debug) break_adjust_pc(&addr, rec->ExceptionCode, first_chance, &is_break); /* * Do a quiet backtrace so that we have an idea of what the situation * is WRT the source files. */ stack_fetch_frames(); if (is_debug && !is_break && break_should_continue(&addr, rec->ExceptionCode)) return FALSE; if (addr.Mode != dbg_curr_thread->addr_mode) { const char* name = NULL; switch (addr.Mode) { case AddrMode1616: name = "16 bit"; break; case AddrMode1632: name = "32 bit"; break; case AddrModeReal: name = "vm86"; break; case AddrModeFlat: name = "32 bit"; break; } dbg_printf("In %s mode.\n", name); dbg_curr_thread->addr_mode = addr.Mode; } display_print(); if (!is_debug) { /* This is a real crash, dump some info */ be_cpu->print_context(dbg_curr_thread->handle, &dbg_context, 0); stack_info(); be_cpu->print_segment_info(dbg_curr_thread->handle, &dbg_context); stack_backtrace(dbg_curr_tid); } else { static char* last_name; static char* last_file; char buffer[sizeof(SYMBOL_INFO) + 256]; SYMBOL_INFO* si = (SYMBOL_INFO*)buffer; void* lin = memory_to_linear_addr(&addr); DWORD64 disp64; IMAGEHLP_LINE il; DWORD disp; si->SizeOfStruct = sizeof(*si); si->MaxNameLen = 256; il.SizeOfStruct = sizeof(il); if (SymFromAddr(dbg_curr_process->handle, (DWORD_PTR)lin, &disp64, si) && SymGetLineFromAddr(dbg_curr_process->handle, (DWORD_PTR)lin, &disp, &il)) { if ((!last_name || strcmp(last_name, si->Name)) || (!last_file || strcmp(last_file, il.FileName))) { HeapFree(GetProcessHeap(), 0, last_name); HeapFree(GetProcessHeap(), 0, last_file); last_name = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(si->Name) + 1), si->Name); last_file = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(il.FileName) + 1), il.FileName); dbg_printf("%s () at %s:%u\n", last_name, last_file, il.LineNumber); } } } if (!is_debug || is_break || dbg_curr_thread->exec_mode == dbg_exec_step_over_insn || dbg_curr_thread->exec_mode == dbg_exec_step_into_insn) { ADDRESS64 tmp = addr; /* Show where we crashed */ memory_disasm_one_insn(&tmp); } source_list_from_addr(&addr, 0); return TRUE; }
void JitFragmentWriter::_emitPPCall(RewriterVar* result, void* func_addr, const RewriterVar::SmallVector& args, int num_slots, int slot_size) { assembler::Register r = allocReg(assembler::R11); if (args.size() > 6) { // only 6 args can get passed in registers. assert(args.size() <= 6 + JitCodeBlock::num_stack_args); for (int i = 6; i < args.size(); ++i) { assembler::Register reg = args[i]->getInReg(Location::any(), true); assembler->mov(reg, assembler::Indirect(assembler::RSP, sizeof(void*) * (i - 6))); } RewriterVar::SmallVector reg_args(args.begin(), args.begin() + 6); assert(reg_args.size() == 6); _setupCall(false, reg_args, RewriterVar::SmallVector()); } else _setupCall(false, args, RewriterVar::SmallVector()); if (failed) return; // make sure setupCall doesn't use R11 assert(vars_by_location.count(assembler::R11) == 0); int pp_size = slot_size * num_slots; // make space for patchpoint uint8_t* pp_start = rewrite->getSlotStart() + assembler->bytesWritten(); constexpr int call_size = 16; assembler->skipBytes(pp_size + call_size); uint8_t* pp_end = rewrite->getSlotStart() + assembler->bytesWritten(); assert(assembler->hasFailed() || (pp_start + pp_size + call_size == pp_end)); std::unique_ptr<ICSetupInfo> setup_info( ICSetupInfo::initialize(true, num_slots, slot_size, ICSetupInfo::Generic, NULL)); // calculate available scratch space int pp_scratch_size = 0; int pp_scratch_location = rewrite->getScratchRspOffset() + rewrite->getScratchSize(); for (int i = rewrite->getScratchSize() - 8; i >= 0; i -= 8) { Location l(Location::Scratch, i); if (vars_by_location.count(l)) break; pp_scratch_size += 8; pp_scratch_location -= 8; } for (RewriterVar* arg : args) { arg->bumpUse(); } assertConsistent(); StackInfo stack_info(pp_scratch_size, pp_scratch_location); pp_infos.emplace_back(PPInfo{ func_addr, pp_start, pp_end, std::move(setup_info), stack_info }); assert(vars_by_location.count(assembler::RAX) == 0); result->initializeInReg(assembler::RAX); assertConsistent(); result->releaseIfNoUses(); }