Stacktraces with dwarf symbols #280

Open
icex2 wants to merge 4 commits from icex2/stacktraces-with-dwarf-syms into development
17 changed files with 410 additions and 88 deletions
+1 -3
View File
@@ -25,7 +25,7 @@ toolchain_64 := x86_64-w64-mingw32-
gitrev := $(shell git rev-parse HEAD)
cppflags := -I src -I src/main -I src/test -DGITREV=$(gitrev)
cflags := -O2 -pipe -ffunction-sections -fdata-sections \
cflags := -g -O2 -pipe -ffunction-sections -fdata-sections \
-Wall -std=c99 -DPSAPI_VERSION=1
cflags_release := -Werror
ldflags := -Wl,--gc-sections -static-libgcc
@@ -240,7 +240,6 @@ $$(dll_$1_$2_$3) $$(implib_$1_$2_$3): $$(obj_$1_$2_$3) $$(abslib_$1_$2_$3) \
$(V)$$(toolchain_$1)gcc -shared \
-o $$(dll_$1_$2_$3) -Wl,--out-implib,$$(implib_$1_$2_$3) \
-Wl,--start-group $$^ -Wl,--end-group $$(ldflags_$3)
$(V)$$(toolchain_$1)strip $$(dll_$1_$2_$3)
$(V)$$(toolchain_$1)ranlib $$(implib_$1_$2_$3)
endef
@@ -257,7 +256,6 @@ $$(exe_$1_$2_$3): $$(obj_$1_$2_$3) $$(abslib_$1_$2_$3) $$(absdpl_$1_$2_$3) \
| $$(bindir_$1_$2)
$(V)echo ... $$@
$(V)$$(toolchain_$1)gcc -o $$@ $$^ $$(ldflags_$3)
$(V)$$(toolchain_$1)strip $$@
endef
+8
View File
@@ -257,6 +257,7 @@ $(zipdir)/iidx-09-to-12.zip: \
build/bin/indep-32/iidxio.dll \
build/bin/indep-32/vefxio.dll \
build/bin/indep-32/inject.exe \
dist/dwarfstack/32/dwarfstack.dll \
dist/iidx/config.bat \
dist/iidx/gamestart-09.bat \
dist/iidx/gamestart-10.bat \
@@ -282,6 +283,7 @@ $(zipdir)/iidx-13.zip: \
build/bin/indep-32/iidxio.dll \
build/bin/indep-32/vefxio.dll \
build/bin/indep-32/inject.exe \
dist/dwarfstack/32/dwarfstack.dll \
dist/iidx/config.bat \
dist/iidx/gamestart-13.bat \
dist/iidx/iidxhook-13.conf \
@@ -298,6 +300,7 @@ $(zipdir)/iidx-14-to-17.zip: \
build/bin/indep-32/iidxio.dll \
build/bin/indep-32/vefxio.dll \
build/bin/indep-32/inject.exe \
dist/dwarfstack/32/dwarfstack.dll \
dist/iidx/config.bat \
dist/iidx/gamestart-14.bat \
dist/iidx/gamestart-15.bat \
@@ -485,6 +488,7 @@ $(zipdir)/jb-01.zip: \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/jbio.dll \
dist/dwarfstack/32/dwarfstack.dll \
dist/jb/config.bat \
dist/jb/gamestart-01.bat \
dist/jb/jbhook-01.conf \
@@ -499,6 +503,7 @@ $(zipdir)/jb-02.zip: \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
build/bin/indep-32/jbio.dll \
dist/dwarfstack/32/dwarfstack.dll \
dist/jb/config.bat \
dist/jb/gamestart-02.bat \
dist/jb/jbhook-02.conf \
@@ -659,6 +664,7 @@ $(zipdir)/ddr-12-us.zip: \
build/bin/indep-32/ddrio-smx.dll \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/geninput.dll \
dist/dwarfstack/32/dwarfstack.dll \
dist/ddr/config.bat \
dist/ddr/gamestart-12-us.bat \
dist/ddr/gamestart-12-eu.bat \
@@ -776,6 +782,7 @@ $(zipdir)/popn-15-to-18.zip: \
build/bin/indep-32/eamio.dll \
build/bin/indep-32/popnio.dll \
build/bin/indep-32/ezusb2-popn-shim.dll \
dist/dwarfstack/32/dwarfstack.dll \
dist/popn/config.bat \
dist/popn/gamestart-15.bat \
dist/popn/gamestart-16.bat \
@@ -807,6 +814,7 @@ $(BUILDDIR)/tests.zip: \
build/bin/indep-32/iidxhook-util-config-gfx-test.exe \
build/bin/indep-32/iidxhook-util-config-misc-test.exe \
build/bin/indep-32/iidxhook-util-config-sec-test.exe \
dist/dwarfstack/32/dwarfstack.dll \
build/bin/indep-32/inject.exe \
build/bin/indep-32/security-id-test.exe \
build/bin/indep-32/security-mcode-test.exe \
Binary file not shown.
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
Version/release: https://github.com/ssbssa/dwarfstack/releases/tag/2.2
+162
View File
@@ -0,0 +1,162 @@
/*
* Copyright (C) 2013-2019 Hannes Domani
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __DWARFSTACK_H__
#define __DWARFSTACK_H__
#include <stdint.h>
#if defined(DWST_STATIC)
#define EXPORT
#elif defined(DWST_SHARED)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C" {
#endif
// dwstCallback(): callback function
// addr: stack address
// filename: source file location
// lineno: line number
// funcname: function name
// context: user-provided pointer (callbackContext)
// columnno: column number
typedef void dwstCallback(
uint64_t addr,const char *filename,int lineno,const char *funcname,
void *context,int columnno );
typedef void dwstCallbackW(
uint64_t addr,const wchar_t *filename,int lineno,const char *funcname,
void *context,int columnno );
// special values for lineno:
// DWST_BASE_ADDR: inform about the used image base address
// (important in case it's not the same as the preferred image base address)
// addr: used image base address
// filename: executable location
#define DWST_BASE_ADDR 0
// DWST_NO_DBG_SYM: no debug information available
// addr: stack address
// filename: executable location
#define DWST_NO_DBG_SYM -1
// DWST_NO_SRC_FILE: no source file information available
// addr: stack address
// filename: executable location
#define DWST_NO_SRC_FILE -2
// DWST_NOT_FOUND: no information available (invalid address?)
// addr: stack address
// filename: executable location
#define DWST_NOT_FOUND -3
// dwstOfFile(): stack information of file
// name: executable location
// imageBase: used image base address
// addr: stack addresses
// count: number of addresses
// callbackFunc: callback function
// callbackContext: user-provided pointer (context)
// (for example see examples/addr2line/)
EXPORT int dwstOfFile(
const char *name,uint64_t imageBase,
uint64_t *addr,int count,
dwstCallback *callbackFunc,void *callbackContext );
EXPORT int dwstOfFileW(
const wchar_t *name,uint64_t imageBase,
uint64_t *addr,int count,
dwstCallbackW *callbackFunc,void *callbackContext );
// dwstOfProcess(): stack information of current process
// addr: stack addresses
// count: number of addresses
// callbackFunc: callback function
// callbackContext: user-provided pointer (context)
EXPORT int dwstOfProcess(
uintptr_t *addr,int count,
dwstCallback *callbackFunc,void *callbackContext );
EXPORT int dwstOfProcessW(
uintptr_t *addr,int count,
dwstCallbackW *callbackFunc,void *callbackContext );
// dwstOfLocation(): stack information of current location
// callbackFunc: callback function
// callbackContext: user-provided pointer (context)
// (for example see examples/location/)
EXPORT int dwstOfLocation(
dwstCallback *callbackFunc,void *callbackContext );
EXPORT int dwstOfLocationW(
dwstCallbackW *callbackFunc,void *callbackContext );
// dwstOfException(): stack information of exception
// context: ContextRecord of exception
// callbackFunc: callback function
// callbackContext: user-provided pointer (context)
// (for example see examples/exception/)
EXPORT int dwstOfException(
void *context,
dwstCallback *callbackFunc,void *callbackContext );
EXPORT int dwstOfExceptionW(
void *context,
dwstCallbackW *callbackFunc,void *callbackContext );
// dwstExceptionDialog(): show dialog on unhandled exception
// extraInfo: extra information shown in dialog
// (for example see examples/exception-dialog/)
EXPORT void dwstExceptionDialog(
const char *extraInfo );
EXPORT void dwstExceptionDialogW(
const wchar_t *extraInfo );
#ifndef DWST_STATIC
// dwstDemangle(): demangle gcc style c++ symbols
// mangled: mangled name
// demangled: demangled name
// length: size of demangled buffer
EXPORT size_t dwstDemangle(
const char *mangled,
char *demangled,size_t length );
#endif
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,13 @@
LIBRARY dwarfstack
EXPORTS
dwstOfFile @ 441
dwstOfFileW @ 443
dwstOfProcess @ 446
dwstOfProcessW @ 448
dwstOfLocation @ 444
dwstOfLocationW @ 445
dwstOfException @ 438
dwstOfExceptionW @ 440
dwstExceptionDialog @ 436
dwstExceptionDialogW @ 437
@@ -0,0 +1,13 @@
LIBRARY dwarfstack
EXPORTS
dwstOfFile @ 441
dwstOfFileW @ 443
dwstOfProcess @ 446
dwstOfProcessW @ 448
dwstOfLocation @ 444
dwstOfLocationW @ 445
dwstOfException @ 438
dwstOfExceptionW @ 440
dwstExceptionDialog @ 436
dwstExceptionDialogW @ 437
+3
View File
@@ -1,11 +1,14 @@
exes += inject
imps += dwarfstack
ldflags_inject := \
-mconsole \
-lpsapi \
-ldbghelp \
libs_inject := \
util \
dwarfstack \
src_inject := \
main.c \
+2 -2
View File
@@ -11,10 +11,10 @@
#include "inject/debugger.h"
#include "inject/logger.h"
#include "util/debug.h"
#include "util/log.h"
#include "util/mem.h"
#include "util/proc.h"
#include "util/signal.h"
#include "util/str.h"
#define MM_ALLOCATION_GRANULARITY 0x10000
@@ -271,7 +271,7 @@ static uint32_t debugger_loop()
"EXCEPTION_DEBUG_EVENT(pid %ld, tid %ld): x%s 0x%p",
de.dwProcessId,
de.dwThreadId,
signal_exception_code_to_str(
debug_exception_code_to_str(
de.u.Exception.ExceptionRecord.ExceptionCode),
de.u.Exception.ExceptionRecord.ExceptionAddress);
+2
View File
@@ -16,6 +16,7 @@
#include "inject/version.h"
#include "util/cmdline.h"
#include "util/debug.h"
#include "util/log.h"
#include "util/mem.h"
#include "util/os.h"
@@ -166,6 +167,7 @@ int main(int argc, char **argv)
os_version_log();
debug_init();
signal_exception_handler_init();
// Cleanup remote process on CTRL+C
signal_register_shutdown_handler(signal_shutdown_handler);
+1
View File
@@ -5,6 +5,7 @@ src_util := \
cmdline.c \
crc.c \
crypto.c \
debug.c \
fs.c \
hex.c \
iobuf.c \
+184
View File
@@ -0,0 +1,184 @@
#define LOG_MODULE "util-debug"
#include <windows.h>
#include <stdio.h>
#include "imports/dwarfstack.h"
#include "util/debug.h"
#include "util/log.h"
#define EX_DESC(name) \
case EXCEPTION_##name: \
desc = " (" #name ")"; \
break
static void _debug_stacktrace_printer(
uint64_t addr,
const char *filename,
int lineno,
const char *funcname,
void *context,
int columnno)
{
int *count;
const char *delim;
void *ptr;
char buffer[512];
char *buffer_ptr;
count = context;
delim = strrchr(filename, '/');
if (delim) {
filename = delim + 1;
}
delim = strrchr(filename, '\\');
if (delim) {
filename = delim + 1;
}
ptr = (void *) (uintptr_t) addr;
switch (lineno) {
case DWST_BASE_ADDR:
log_exception_handler("base address: 0x%p (%s)", ptr, filename);
break;
case DWST_NOT_FOUND:
case DWST_NO_DBG_SYM:
case DWST_NO_SRC_FILE:
log_exception_handler(
" stack %02d: 0x%p (%s)", (*count)++, ptr, filename);
break;
default:
buffer_ptr = buffer;
memset(buffer, 0, sizeof(buffer));
if (ptr) {
buffer_ptr += sprintf(
buffer_ptr, " stack %02d: 0x%p", (*count)++, ptr);
} else {
buffer_ptr += sprintf(
buffer_ptr,
" %*s",
(int) sizeof(void *) * 2,
"");
}
buffer_ptr += sprintf(buffer_ptr, " (%s:%d", filename, lineno);
if (columnno > 0) {
buffer_ptr += sprintf(buffer_ptr, ":%d", columnno);
}
buffer_ptr += sprintf(buffer_ptr, ")");
if (funcname) {
buffer_ptr += sprintf(buffer_ptr, " [%s]", funcname);
}
log_exception_handler(buffer);
break;
}
}
static LONG WINAPI _debug_unhandled_exception_filter(LPEXCEPTION_POINTERS ep)
{
DWORD code;
const char *desc;
ULONG_PTR flag;
ULONG_PTR addr;
int count;
log_exception_handler(
"==========================================================");
log_exception_handler(
"The application has crashed due to an unhandled exception!");
code = ep->ExceptionRecord->ExceptionCode;
desc = debug_exception_code_to_str(code);
log_exception_handler("code: 0x%08lX", code);
log_exception_handler("desc: %s", desc);
if (code == EXCEPTION_ACCESS_VIOLATION &&
ep->ExceptionRecord->NumberParameters == 2) {
flag = ep->ExceptionRecord->ExceptionInformation[0];
addr = ep->ExceptionRecord->ExceptionInformation[1];
log_exception_handler(
"%s violation at 0x%p",
flag == 8 ? "data execution prevention" :
(flag ? "write access" : "read access"),
(void *) addr);
}
log_exception_handler("stacktrace:");
count = 0;
dwstOfException(ep->ContextRecord, &_debug_stacktrace_printer, &count);
return EXCEPTION_EXECUTE_HANDLER;
}
void debug_init()
{
SetUnhandledExceptionFilter(_debug_unhandled_exception_filter);
log_info("Initialized");
}
void debug_print_stacktrace()
{
int count;
count = 0;
log_exception_handler(
"==========================================================");
log_exception_handler("Debug stacktrace");
dwstOfLocation(&_debug_stacktrace_printer, &count);
}
const char *debug_exception_code_to_str(DWORD code)
{
const char *desc = "";
switch (code) {
EX_DESC(ACCESS_VIOLATION);
EX_DESC(ARRAY_BOUNDS_EXCEEDED);
EX_DESC(BREAKPOINT);
EX_DESC(DATATYPE_MISALIGNMENT);
EX_DESC(FLT_DENORMAL_OPERAND);
EX_DESC(FLT_DIVIDE_BY_ZERO);
EX_DESC(FLT_INEXACT_RESULT);
EX_DESC(FLT_INVALID_OPERATION);
EX_DESC(FLT_OVERFLOW);
EX_DESC(FLT_STACK_CHECK);
EX_DESC(FLT_UNDERFLOW);
EX_DESC(ILLEGAL_INSTRUCTION);
EX_DESC(IN_PAGE_ERROR);
EX_DESC(INT_DIVIDE_BY_ZERO);
EX_DESC(INT_OVERFLOW);
EX_DESC(INVALID_DISPOSITION);
EX_DESC(NONCONTINUABLE_EXCEPTION);
EX_DESC(PRIV_INSTRUCTION);
EX_DESC(SINGLE_STEP);
EX_DESC(STACK_OVERFLOW);
case DBG_CONTROL_C:
return "DBG_CONTROL_C";
default:
log_warning("Unknown exception code: %lX", code);
return "Unknown";
}
return desc;
}
+10
View File
@@ -0,0 +1,10 @@
#ifndef UTIL_DEBUG_H
#define UTIL_DEBUG_H
#include <windows.h>
void debug_init();
void debug_print_stacktrace();
const char *debug_exception_code_to_str(DWORD code);
#endif
+9
View File
@@ -64,6 +64,15 @@ static void log_builtin_format(
}
}
void log_exception_handler(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
log_builtin_format(LOG_LEVEL_FATAL, LOG_MODULE, fmt, ap);
va_end(ap);
}
void log_assert_body(const char *file, int line, const char *function)
{
log_impl_fatal("assert", "%s:%d: function `%s'", file, line, function);
+1
View File
@@ -66,6 +66,7 @@ enum log_level {
LOG_LEVEL_MISC = 3,
};
void log_exception_handler(const char *fmt, ...);
void log_assert_body(const char *file, int line, const char *function);
void log_to_external(
log_formatter_t misc,
-83
View File
@@ -1,5 +1,4 @@
#include <unistd.h>
#include <windows.h>
#include "util/hex.h"
#include "util/log.h"
@@ -45,40 +44,9 @@ static BOOL WINAPI console_ctrl_handler(DWORD dwCtrlType)
return FALSE;
}
static LONG WINAPI
unhandled_exception_filter(struct _EXCEPTION_POINTERS *ExceptionInfo)
{
// no exception info provided
if (ExceptionInfo != NULL) {
struct _EXCEPTION_RECORD *ExceptionRecord =
ExceptionInfo->ExceptionRecord;
log_warning(
"Exception raised: %s",
signal_exception_code_to_str(ExceptionRecord->ExceptionCode));
struct _EXCEPTION_RECORD *record_cause =
ExceptionRecord->ExceptionRecord;
while (record_cause != NULL) {
log_warning(
"Caused by: %s",
signal_exception_code_to_str(record_cause->ExceptionCode));
record_cause = record_cause->ExceptionRecord;
}
// TODO print stacktrace
log_fatal("End exception handler");
}
return EXCEPTION_CONTINUE_SEARCH;
}
void signal_exception_handler_init()
{
SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
SetUnhandledExceptionFilter(unhandled_exception_filter);
log_info("Initialized");
}
@@ -88,55 +56,4 @@ void signal_register_shutdown_handler(signal_shutdown_handler_t handler)
shutdown_handler = handler;
log_misc("Registered shutdown handler");
}
const char *signal_exception_code_to_str(DWORD code)
{
switch (code) {
case EXCEPTION_ACCESS_VIOLATION:
return "EXCEPTION_ACCESS_VIOLATION";
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
case EXCEPTION_BREAKPOINT:
return "EXCEPTION_BREAKPOINT";
case EXCEPTION_DATATYPE_MISALIGNMENT:
return "EXCEPTION_DATATYPE_MISALIGNMENT";
case EXCEPTION_FLT_DENORMAL_OPERAND:
return "EXCEPTION_FLT_DENORMAL_OPERAND";
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
return "EXCEPTION_FLT_DIVIDE_BY_ZERO";
case EXCEPTION_FLT_INEXACT_RESULT:
return "EXCEPTION_FLT_INEXACT_RESULT";
case EXCEPTION_FLT_INVALID_OPERATION:
return "EXCEPTION_FLT_INVALID_OPERATION";
case EXCEPTION_FLT_OVERFLOW:
return "EXCEPTION_FLT_OVERFLOW";
case EXCEPTION_FLT_STACK_CHECK:
return "EXCEPTION_FLT_STACK_CHECK";
case EXCEPTION_FLT_UNDERFLOW:
return "EXCEPTION_FLT_UNDERFLOW";
case EXCEPTION_ILLEGAL_INSTRUCTION:
return "EXCEPTION_ILLEGAL_INSTRUCTION";
case EXCEPTION_IN_PAGE_ERROR:
return "EXCEPTION_IN_PAGE_ERROR";
case EXCEPTION_INT_DIVIDE_BY_ZERO:
return "EXCEPTION_INT_DIVIDE_BY_ZERO";
case EXCEPTION_INT_OVERFLOW:
return "EXCEPTION_INT_OVERFLOW";
case EXCEPTION_INVALID_DISPOSITION:
return "EXCEPTION_INVALID_DISPOSITION";
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
return "EXCEPTION_NONCONTINUABLE_EXCEPTION";
case EXCEPTION_PRIV_INSTRUCTION:
return "EXCEPTION_PRIV_INSTRUCTION";
case EXCEPTION_SINGLE_STEP:
return "EXCEPTION_SINGLE_STEP";
case EXCEPTION_STACK_OVERFLOW:
return "EXCEPTION_STACK_OVERFLOW";
case DBG_CONTROL_C:
return "DBG_CONTROL_C";
default:
log_warning("Unknown exception code: %lX", code);
return "Unknown";
}
}