diff options
Diffstat (limited to 'src/osd/modules/diagnostics/diagnostics_win32.cpp')
-rw-r--r-- | src/osd/modules/diagnostics/diagnostics_win32.cpp | 126 |
1 files changed, 95 insertions, 31 deletions
diff --git a/src/osd/modules/diagnostics/diagnostics_win32.cpp b/src/osd/modules/diagnostics/diagnostics_win32.cpp index 677cd93bff7..660d4d91682 100644 --- a/src/osd/modules/diagnostics/diagnostics_win32.cpp +++ b/src/osd/modules/diagnostics/diagnostics_win32.cpp @@ -9,12 +9,13 @@ #include "emu.h" #include "diagnostics_module.h" +#include "corestr.h" + #if defined(OSD_WINDOWS) || defined(SDLMAME_WIN32) // standard windows headers #include <windows.h> -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) #include <debugger.h> #include <psapi.h> @@ -99,7 +100,7 @@ private: void scan_cache_for_address(uintptr_t address); void format_symbol(const char *name, uint32_t displacement, const char *filename = nullptr, int linenumber = 0); - static uintptr_t get_text_section_base(); + static uintptr_t get_text_section_base(ULONG &size); struct cache_entry { @@ -115,8 +116,9 @@ private: std::string m_symfile; std::string m_buffer; HANDLE m_process; - uintptr_t m_last_base; - uintptr_t m_text_base; + uintptr_t m_last_base; + uintptr_t m_text_base; + ULONG m_text_size; osd::dynamic_module::ptr m_dbghelp_dll; @@ -167,8 +169,8 @@ bool stack_walker::s_initialized = false; // stack_walker - constructor //------------------------------------------------- -stack_walker::stack_walker() - : m_process(GetCurrentProcess()), +stack_walker::stack_walker() : + m_process(GetCurrentProcess()), m_thread(GetCurrentThread()), m_first(true) { @@ -214,14 +216,18 @@ bool stack_walker::reset() m_stackframe.AddrStack.Mode = AddrModeFlat; // pull architecture-specific fields from the context -#ifdef PTR64 +#if defined(__x86_64__) || defined(_M_X64) m_stackframe.AddrPC.Offset = m_context.Rip; m_stackframe.AddrFrame.Offset = m_context.Rsp; m_stackframe.AddrStack.Offset = m_context.Rsp; -#else +#elif defined(__i386__) || defined(_M_IX86) m_stackframe.AddrPC.Offset = m_context.Eip; m_stackframe.AddrFrame.Offset = m_context.Ebp; m_stackframe.AddrStack.Offset = m_context.Esp; +#elif defined(__aarch64__) || defined(_M_ARM64) + m_stackframe.AddrPC.Offset = m_context.Pc; + m_stackframe.AddrFrame.Offset = m_context.Fp; + m_stackframe.AddrStack.Offset = m_context.Sp; #endif return true; } @@ -240,14 +246,18 @@ void stack_walker::reset(CONTEXT &initial, HANDLE thread) m_stackframe.AddrStack.Mode = AddrModeFlat; // pull architecture-specific fields from the context -#ifdef PTR64 +#if defined(__x86_64__) || defined(_M_X64) m_stackframe.AddrPC.Offset = m_context.Rip; m_stackframe.AddrFrame.Offset = m_context.Rsp; m_stackframe.AddrStack.Offset = m_context.Rsp; -#else +#elif defined(__i386__) || defined(_M_IX86) m_stackframe.AddrPC.Offset = m_context.Eip; m_stackframe.AddrFrame.Offset = m_context.Ebp; m_stackframe.AddrStack.Offset = m_context.Esp; +#elif defined(__aarch64__) || defined(_M_ARM64) + m_stackframe.AddrPC.Offset = m_context.Pc; + m_stackframe.AddrFrame.Offset = m_context.Fp; + m_stackframe.AddrStack.Offset = m_context.Sp; #endif } @@ -261,10 +271,14 @@ bool stack_walker::unwind() // if we were able to initialize, then we have everything we need if (s_initialized) { -#ifdef PTR64 +#if defined(__x86_64__) || defined(_M_X64) return (*m_stack_walk_64)(IMAGE_FILE_MACHINE_AMD64, m_process, m_thread, &m_stackframe, &m_context, nullptr, *m_sym_function_table_access_64, *m_sym_get_module_base_64, nullptr); -#else +#elif defined(__i386__) || defined(_M_IX86) return (*m_stack_walk_64)(IMAGE_FILE_MACHINE_I386, m_process, m_thread, &m_stackframe, &m_context, nullptr, *m_sym_function_table_access_64, *m_sym_get_module_base_64, nullptr); +#elif defined(__aarch64__) || defined(_M_ARM64) + return (*m_stack_walk_64)(IMAGE_FILE_MACHINE_ARM64, m_process, m_thread, &m_stackframe, &m_context, nullptr, *m_sym_function_table_access_64, *m_sym_get_module_base_64, nullptr); +#else + return false; #endif } @@ -287,8 +301,8 @@ bool stack_walker::unwind() // symbol_manager - constructor //------------------------------------------------- -symbol_manager::symbol_manager(const char *argv0) - : m_mapfile(argv0), +symbol_manager::symbol_manager(const char *argv0) : + m_mapfile(argv0), m_symfile(argv0), m_process(GetCurrentProcess()), m_last_base(0), @@ -298,7 +312,7 @@ symbol_manager::symbol_manager(const char *argv0) // compute the name of the mapfile int extoffs = m_mapfile.find_last_of('.'); if (extoffs != -1) - m_mapfile.substr(0, extoffs); + m_mapfile = m_mapfile.substr(0, extoffs); m_mapfile.append(".map"); // and the name of the symfile @@ -308,7 +322,7 @@ symbol_manager::symbol_manager(const char *argv0) m_symfile.append(".sym"); // figure out the base of the .text section - m_text_base = get_text_section_base(); + m_text_base = get_text_section_base(m_text_size); #endif // expand the buffer to be decently large up front @@ -377,6 +391,10 @@ bool symbol_manager::query_system_for_address(uintptr_t address) info.MaxNameLen = sizeof(info_buffer) - sizeof(info); if ((*m_sym_from_addr)(m_process, address, &displacement, &info)) { + // if the address is within our image, but the symbol is at or below the text base, it's useless (lld produces these) + if (info.Address <= m_text_base && address > m_text_base && address < m_text_base + m_text_size) + return false; + // try to get source info as well; again we are returned an ANSI string IMAGEHLP_LINE64 lineinfo = { sizeof(lineinfo) }; DWORD linedisp; @@ -503,6 +521,9 @@ bool symbol_manager::parse_sym_line(const char *line, uintptr_t &address, std::s // first look for a (ty) entry const char *type = strstr(line, "(ty 20)"); if (type == nullptr) + type = strstr(line, "(ty 20)"); + + if (type == nullptr) return false; // scan forward in the line to find the address @@ -529,7 +550,7 @@ bool symbol_manager::parse_sym_line(const char *line, uintptr_t &address, std::s chptr++; // extract the symbol name - strtrimspace(symbol.assign(chptr)); + symbol.assign(strtrimspace(chptr)); return (symbol.length() > 0); } } @@ -569,7 +590,7 @@ bool symbol_manager::parse_map_line(const char *line, uintptr_t &address, std::s chptr++; // extract the symbol name - strtrimspace(symbol.assign(chptr)); + symbol.assign(strtrimspace(chptr)); return (symbol.length() > 0); } #endif @@ -602,7 +623,7 @@ void symbol_manager::format_symbol(const char *name, uint32_t displacement, cons // of the .text section //------------------------------------------------- -uintptr_t symbol_manager::get_text_section_base() +uintptr_t symbol_manager::get_text_section_base(ULONG &size) { osd::dynamic_module::ptr m_dbghelp_dll = osd::dynamic_module::open({ "dbghelp.dll" }); @@ -610,7 +631,7 @@ uintptr_t symbol_manager::get_text_section_base() ImageNtHeader_fn image_nt_header = m_dbghelp_dll->bind<ImageNtHeader_fn>("ImageNtHeader"); // start with the image base - PVOID base = reinterpret_cast<PVOID>(GetModuleHandleUni()); + auto base = reinterpret_cast<PVOID>(GetModuleHandleUni()); assert(base != nullptr); // make sure we have the functions we need @@ -623,10 +644,14 @@ uintptr_t symbol_manager::get_text_section_base() // look ourself up (assuming we are in the .text section) PIMAGE_SECTION_HEADER section = (*image_rva_to_section)(headers, base, reinterpret_cast<uintptr_t>(get_text_section_base) - reinterpret_cast<uintptr_t>(base)); if (section != nullptr) + { + size = section->SizeOfRawData; return reinterpret_cast<uintptr_t>(base) + section->VirtualAddress; + } } // fallback to returning the image base (wrong) + size = 0; return reinterpret_cast<uintptr_t>(base); } @@ -640,8 +665,8 @@ uintptr_t symbol_manager::get_text_section_base() // sampling_profiler - constructor //------------------------------------------------- -sampling_profiler::sampling_profiler(uint32_t max_seconds, uint8_t stack_depth = 0) - : m_target_thread(nullptr), +sampling_profiler::sampling_profiler(uint32_t max_seconds, uint8_t stack_depth = 0) : + m_target_thread(nullptr), m_thread(nullptr), m_thread_id(0), m_thread_exit(false), @@ -663,7 +688,7 @@ sampling_profiler::~sampling_profiler() } -//------------------------------------------------- +////------------------------------------------------- // start - begin gathering profiling information //------------------------------------------------- @@ -712,8 +737,8 @@ void sampling_profiler::stop() int CLIB_DECL sampling_profiler::compare_address(const void *item1, const void *item2) { - const uintptr_t *entry1 = reinterpret_cast<const uintptr_t *>(item1); - const uintptr_t *entry2 = reinterpret_cast<const uintptr_t *>(item2); + const auto *entry1 = reinterpret_cast<const uintptr_t *>(item1); + const auto *entry2 = reinterpret_cast<const uintptr_t *>(item2); int mincount = std::min(entry1[0], entry2[0]); // sort in order of: bucket, caller, caller's caller, etc. @@ -733,8 +758,8 @@ int CLIB_DECL sampling_profiler::compare_address(const void *item1, const void * int CLIB_DECL sampling_profiler::compare_frequency(const void *item1, const void *item2) { - const uintptr_t *entry1 = reinterpret_cast<const uintptr_t *>(item1); - const uintptr_t *entry2 = reinterpret_cast<const uintptr_t *>(item2); + const auto *entry1 = reinterpret_cast<const uintptr_t *>(item1); + const auto *entry2 = reinterpret_cast<const uintptr_t *>(item2); // sort by frequency, then by address if (entry1[0] != entry2[0]) @@ -984,7 +1009,7 @@ private: // print the state of the CPU fprintf(stderr, "-----------------------------------------------------\n"); -#ifdef PTR64 +#if defined(__x86_64__) || defined(_M_X64) fprintf(stderr, "RAX=%p RBX=%p RCX=%p RDX=%p\n", (void *)info->ContextRecord->Rax, (void *)info->ContextRecord->Rbx, @@ -1005,7 +1030,7 @@ private: (void *)info->ContextRecord->R13, (void *)info->ContextRecord->R14, (void *)info->ContextRecord->R15); -#else +#elif defined(__i386__) || defined(_M_IX86) fprintf(stderr, "EAX=%p EBX=%p ECX=%p EDX=%p\n", (void *)info->ContextRecord->Eax, (void *)info->ContextRecord->Ebx, @@ -1016,6 +1041,47 @@ private: (void *)info->ContextRecord->Edi, (void *)info->ContextRecord->Ebp, (void *)info->ContextRecord->Esp); +#elif defined(__aarch64__) || defined(_M_ARM64) + fprintf(stderr, " X0=%p X1=%p X2=%p X3=%p\n", + (void *)info->ContextRecord->X0, + (void *)info->ContextRecord->X1, + (void *)info->ContextRecord->X2, + (void *)info->ContextRecord->X3); + fprintf(stderr, " X4=%p X5=%p X6=%p X7=%p\n", + (void *)info->ContextRecord->X4, + (void *)info->ContextRecord->X5, + (void *)info->ContextRecord->X6, + (void *)info->ContextRecord->X7); + fprintf(stderr, " X8=%p X9=%p X10=%p X11=%p\n", + (void *)info->ContextRecord->X8, + (void *)info->ContextRecord->X9, + (void *)info->ContextRecord->X10, + (void *)info->ContextRecord->X11); + fprintf(stderr, "X12=%p X13=%p X14=%p X15=%p\n", + (void *)info->ContextRecord->X12, + (void *)info->ContextRecord->X13, + (void *)info->ContextRecord->X14, + (void *)info->ContextRecord->X15); + fprintf(stderr, "X16=%p X17=%p X18=%p X19=%p\n", + (void *)info->ContextRecord->X16, + (void *)info->ContextRecord->X17, + (void *)info->ContextRecord->X18, + (void *)info->ContextRecord->X19); + fprintf(stderr, "X20=%p X21=%p X22=%p X23=%p\n", + (void *)info->ContextRecord->X20, + (void *)info->ContextRecord->X21, + (void *)info->ContextRecord->X22, + (void *)info->ContextRecord->X23); + fprintf(stderr, "X24=%p X25=%p X26=%p X27=%p\n", + (void *)info->ContextRecord->X24, + (void *)info->ContextRecord->X25, + (void *)info->ContextRecord->X26, + (void *)info->ContextRecord->X27); + fprintf(stderr, "X28=%p FP=%p LR=%p SP=%p\n", + (void *)info->ContextRecord->X28, + (void *)info->ContextRecord->Fp, + (void *)info->ContextRecord->Lr, + (void *)info->ContextRecord->Sp); #endif // reprint the actual exception address @@ -1087,6 +1153,4 @@ diagnostics_module * diagnostics_module::get_instance() return &s_instance; } -#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - #endif |