summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/diagnostics/diagnostics_win32.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/modules/diagnostics/diagnostics_win32.cpp')
-rw-r--r--src/osd/modules/diagnostics/diagnostics_win32.cpp126
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