📄 platform-win32.cc.svn-base
字号:
__debugbreak();}void OS::DebugBreak() { __debugbreak();}class Win32MemoryMappedFile : public OS::MemoryMappedFile { public: Win32MemoryMappedFile(HANDLE file, HANDLE file_mapping, void* memory) : file_(file), file_mapping_(file_mapping), memory_(memory) { } virtual ~Win32MemoryMappedFile(); virtual void* memory() { return memory_; } private: HANDLE file_; HANDLE file_mapping_; void* memory_;};OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, void* initial) { // Open a physical file HANDLE file = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL); if (file == NULL) return NULL; // Create a file mapping for the physical file HANDLE file_mapping = CreateFileMapping(file, NULL, PAGE_READWRITE, 0, static_cast<DWORD>(size), NULL); if (file_mapping == NULL) return NULL; // Map a view of the file into memory void* memory = MapViewOfFile(file_mapping, FILE_MAP_ALL_ACCESS, 0, 0, size); if (memory) memmove(memory, initial, size); return new Win32MemoryMappedFile(file, file_mapping, memory);}Win32MemoryMappedFile::~Win32MemoryMappedFile() { if (memory_ != NULL) UnmapViewOfFile(memory_); CloseHandle(file_mapping_); CloseHandle(file_);}// The following code loads functions defined in DbhHelp.h and TlHelp32.h// dynamically. This is to avoid beeing depending on dbghelp.dll and// tlhelp32.dll when running (the functions in tlhelp32.dll have been moved to// kernel32.dll at some point so loading functions defines in TlHelp32.h// dynamically might not be necessary any more - for some versions of Windows?).// Function pointers to functions dynamically loaded from dbghelp.dll.#define DBGHELP_FUNCTION_LIST(V) \ V(SymInitialize) \ V(SymGetOptions) \ V(SymSetOptions) \ V(SymGetSearchPath) \ V(SymLoadModule64) \ V(StackWalk64) \ V(SymGetSymFromAddr64) \ V(SymGetLineFromAddr64) \ V(SymFunctionTableAccess64) \ V(SymGetModuleBase64)// Function pointers to functions dynamically loaded from dbghelp.dll.#define TLHELP32_FUNCTION_LIST(V) \ V(CreateToolhelp32Snapshot) \ V(Module32FirstW) \ V(Module32NextW)// Define the decoration to use for the type and variable name used for// dynamically loaded DLL function..#define DLL_FUNC_TYPE(name) _##name##_#define DLL_FUNC_VAR(name) _##name// Define the type for each dynamically loaded DLL function. The function// definitions are copied from DbgHelp.h and TlHelp32.h. The IN and VOID macros// from the Windows include files are redefined here to have the function// definitions to be as close to the ones in the original .h files as possible.#ifndef IN#define IN#endif#ifndef VOID#define VOID void#endif// DbgHelp.h functions.typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymInitialize))(IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess);typedef DWORD (__stdcall *DLL_FUNC_TYPE(SymGetOptions))(VOID);typedef DWORD (__stdcall *DLL_FUNC_TYPE(SymSetOptions))(IN DWORD SymOptions);typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetSearchPath))( IN HANDLE hProcess, OUT PSTR SearchPath, IN DWORD SearchPathLength);typedef DWORD64 (__stdcall *DLL_FUNC_TYPE(SymLoadModule64))( IN HANDLE hProcess, IN HANDLE hFile, IN PSTR ImageName, IN PSTR ModuleName, IN DWORD64 BaseOfDll, IN DWORD SizeOfDll);typedef BOOL (__stdcall *DLL_FUNC_TYPE(StackWalk64))( DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetSymFromAddr64))( IN HANDLE hProcess, IN DWORD64 qwAddr, OUT PDWORD64 pdwDisplacement, OUT PIMAGEHLP_SYMBOL64 Symbol);typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetLineFromAddr64))( IN HANDLE hProcess, IN DWORD64 qwAddr, OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_LINE64 Line64);// DbgHelp.h typedefs. Implementation found in dbghelp.dll.typedef PVOID (__stdcall *DLL_FUNC_TYPE(SymFunctionTableAccess64))( HANDLE hProcess, DWORD64 AddrBase); // DbgHelp.h typedef PFUNCTION_TABLE_ACCESS_ROUTINE64typedef DWORD64 (__stdcall *DLL_FUNC_TYPE(SymGetModuleBase64))( HANDLE hProcess, DWORD64 AddrBase); // DbgHelp.h typedef PGET_MODULE_BASE_ROUTINE64// TlHelp32.h functions.typedef HANDLE (__stdcall *DLL_FUNC_TYPE(CreateToolhelp32Snapshot))( DWORD dwFlags, DWORD th32ProcessID);typedef BOOL (__stdcall *DLL_FUNC_TYPE(Module32FirstW))(HANDLE hSnapshot, LPMODULEENTRY32W lpme);typedef BOOL (__stdcall *DLL_FUNC_TYPE(Module32NextW))(HANDLE hSnapshot, LPMODULEENTRY32W lpme);#undef IN#undef VOID// Declare a variable for each dynamically loaded DLL function.#define DEF_DLL_FUNCTION(name) DLL_FUNC_TYPE(name) DLL_FUNC_VAR(name) = NULL;DBGHELP_FUNCTION_LIST(DEF_DLL_FUNCTION)TLHELP32_FUNCTION_LIST(DEF_DLL_FUNCTION)#undef DEF_DLL_FUNCTION// Load the functions. This function has a lot of "ugly" macros in order to// keep down code duplication.static bool LoadDbgHelpAndTlHelp32() { static bool dbghelp_loaded = false; if (dbghelp_loaded) return true; HMODULE module; // Load functions from the dbghelp.dll module. module = LoadLibrary(TEXT("dbghelp.dll")); if (module == NULL) { return false; }#define LOAD_DLL_FUNC(name) \ DLL_FUNC_VAR(name) = \ reinterpret_cast<DLL_FUNC_TYPE(name)>(GetProcAddress(module, #name));DBGHELP_FUNCTION_LIST(LOAD_DLL_FUNC)#undef LOAD_DLL_FUNC // Load functions from the kernel32.dll module (the TlHelp32.h function used // to be in tlhelp32.dll but are now moved to kernel32.dll). module = LoadLibrary(TEXT("kernel32.dll")); if (module == NULL) { return false; }#define LOAD_DLL_FUNC(name) \ DLL_FUNC_VAR(name) = \ reinterpret_cast<DLL_FUNC_TYPE(name)>(GetProcAddress(module, #name));TLHELP32_FUNCTION_LIST(LOAD_DLL_FUNC)#undef LOAD_DLL_FUNC // Check that all functions where loaded. bool result =#define DLL_FUNC_LOADED(name) (DLL_FUNC_VAR(name) != NULL) &&DBGHELP_FUNCTION_LIST(DLL_FUNC_LOADED)TLHELP32_FUNCTION_LIST(DLL_FUNC_LOADED)#undef DLL_FUNC_LOADED true; dbghelp_loaded = result; return result; // NOTE: The modules are never unloaded and will stay arround until the // application is closed.}// Load the symbols for generating stack traces.static bool LoadSymbols(HANDLE process_handle) { static bool symbols_loaded = false; if (symbols_loaded) return true; BOOL ok; // Initialize the symbol engine. ok = _SymInitialize(process_handle, // hProcess NULL, // UserSearchPath FALSE); // fInvadeProcess if (!ok) return false; DWORD options = _SymGetOptions(); options |= SYMOPT_LOAD_LINES; options |= SYMOPT_FAIL_CRITICAL_ERRORS; options = _SymSetOptions(options); char buf[OS::kStackWalkMaxNameLen] = {0}; ok = _SymGetSearchPath(process_handle, buf, OS::kStackWalkMaxNameLen); if (!ok) { int err = GetLastError(); PrintF("%d\n", err); return false; } HANDLE snapshot = _CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, // dwFlags GetCurrentProcessId()); // th32ProcessId if (snapshot == INVALID_HANDLE_VALUE) return false; MODULEENTRY32W module_entry; module_entry.dwSize = sizeof(module_entry); // Set the size of the structure. BOOL cont = _Module32FirstW(snapshot, &module_entry); while (cont) { DWORD64 base; // NOTE the SymLoadModule64 function has the peculiarity of accepting a // both unicode and ASCII strings even though the parameter is PSTR. base = _SymLoadModule64( process_handle, // hProcess 0, // hFile reinterpret_cast<PSTR>(module_entry.szExePath), // ImageName reinterpret_cast<PSTR>(module_entry.szModule), // ModuleName reinterpret_cast<DWORD64>(module_entry.modBaseAddr), // BaseOfDll module_entry.modBaseSize); // SizeOfDll if (base == 0) { int err = GetLastError(); if (err != ERROR_MOD_NOT_FOUND && err != ERROR_INVALID_HANDLE) return false; } LOG(SharedLibraryEvent( module_entry.szExePath, reinterpret_cast<unsigned int>(module_entry.modBaseAddr), reinterpret_cast<unsigned int>(module_entry.modBaseAddr + module_entry.modBaseSize))); cont = _Module32NextW(snapshot, &module_entry); } CloseHandle(snapshot); symbols_loaded = true; return true;}void OS::LogSharedLibraryAddresses() { // SharedLibraryEvents are logged when loading symbol information. // Only the shared libraries loaded at the time of the call to // LogSharedLibraryAddresses are logged. DLLs loaded after // initialization are not accounted for. if (!LoadDbgHelpAndTlHelp32()) return; HANDLE process_handle = GetCurrentProcess(); LoadSymbols(process_handle);}// Walk the stack using the facilities in dbghelp.dll and tlhelp32.dll// Switch off warning 4748 (/GS can not protect parameters and local variables// from local buffer overrun because optimizations are disabled in function) as// it is triggered by the use of inline assembler.#pragma warning(push)#pragma warning(disable : 4748)int OS::StackWalk(OS::StackFrame* frames, int frames_size) { BOOL ok; // Load the required functions from DLL's. if (!LoadDbgHelpAndTlHelp32()) return kStackWalkError; // Get the process and thread handles. HANDLE process_handle = GetCurrentProcess(); HANDLE thread_handle = GetCurrentThread(); // Read the symbols. if (!LoadSymbols(process_handle)) return kStackWalkError; // Capture current context. CONTEXT context; memset(&context, 0, sizeof(context)); context.ContextFlags = CONTEXT_CONTROL; context.ContextFlags = CONTEXT_CONTROL; __asm call x __asm x: pop eax __asm mov context.Eip, eax __asm mov context.Ebp, ebp __asm mov context.Esp, esp // NOTE: At some point, we could use RtlCaptureContext(&context) to // capture the context instead of inline assembler. However it is // only available on XP, Vista, Server 2003 and Server 2008 which // might not be sufficient. // Initialize the stack walking STACKFRAME64 stack_frame; memset(&stack_frame, 0, sizeof(stack_frame)); stack_frame.AddrPC.Offset = context.Eip; stack_frame.AddrPC.Mode = AddrModeFlat; stack_frame.AddrFrame.Offset = context.Ebp; stack_frame.AddrFrame.Mode = AddrModeFlat; stack_frame.AddrStack.Offset = context.Esp; stack_frame.AddrStack.Mode = AddrModeFlat; int frames_count = 0; // Collect stack frames. while (frames_count < frames_size) { ok = _StackWalk64( IMAGE_FILE_MACHINE_I386, // MachineType process_handle, // hProcess thread_handle, // hThread &stack_frame, // StackFrame &context, // ContextRecord NULL, // ReadMemoryRoutine _SymFunctionTableAccess64, // FunctionTableAccessRoutine _SymGetModuleBase64, // GetModuleBaseRoutine NULL); // TranslateAddress if (!ok) break; // Store the address. ASSERT((stack_frame.AddrPC.Offset >> 32) == 0); // 32-bit address. frames[frames_count].address = reinterpret_cast<void*>(stack_frame.AddrPC.Offset); // Try to locate a symbol for this frame. DWORD64 symbol_displacement; IMAGEHLP_SYMBOL64* symbol = NULL; symbol = NewArray<IMAGEHLP_SYMBOL64>(kStackWalkMaxNameLen); if (!symbol) return kStackWalkError; // Out of memory. memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64) + kStackWalkMaxNameLen); symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); symbol->MaxNameLength = kStackWalkMaxNameLen; ok = _SymGetSymFromAddr64(process_handle, // hProcess stack_frame.AddrPC.Offset, // Address &symbol_displacement, // Displacement symbol); // Symbol if (ok) { // Try to locate more source information for the symbol. IMAGEHLP_LINE64 Line; memset(&Line, 0, sizeof(Line)); Line.SizeOfStruct = sizeof(Line); DWORD line_displacement; ok = _SymGetLineFromAddr64( process_handle, // hProcess stack_frame.AddrPC.Offset, // dwAddr &line_displacement, // pdwDisplacement &Line); // Line // Format a text representation of the frame based on the information // available. if (ok) { SNPrintF(MutableCStrVector(frames[frames_count].text, kStackWalkMaxTextLen), "%s %s:%d:%d", symbol->Name, Line.FileName, Line.LineNumber, line_displacement); } else { SNPrintF(MutableCStrVector(frames[frames_count].text, kStackWalkMaxTextLen), "%s", symbol->Name); } // Make sure line termination is in place. frames[frames_count].text[kStackWalkMaxTextLen - 1] = '\0'; } else { // No text representation of this frame frames[frames_count].text[0] = '\0'; // Continue if we are just missing a module (for non C/C++ frames a // module will never be found). int err = GetLastError(); if (err != ERROR_MOD_NOT_FOUND) { DeleteArray(symbol); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -