mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2025-12-06 02:40:26 -08:00
debugger: add C backtrace for windows
Because that needs the DbgHelp library, an additional make
option has been defined for users, who don't want to link to this
library. Some msvc Makefile cleanup has also been done.
This commit is contained in:
parent
2279361383
commit
a3a44a0eeb
4 changed files with 107 additions and 19 deletions
|
|
@ -60,6 +60,8 @@ ECL_RT =
|
|||
ECL_DEFSYS =
|
||||
# Profiling
|
||||
ECL_PROFILE =
|
||||
# Use the DbgHelp.lib shared library to provide C Backtrace support
|
||||
ECL_USE_DBGHELP = $(ECL_DEBUG)
|
||||
|
||||
!if "$(YASM)" == ""
|
||||
!if "$(ECL_WIN64)" != ""
|
||||
|
|
@ -78,7 +80,9 @@ TAR_DIR = %CD%\ecl-$(ECL_VERSION)
|
|||
#
|
||||
|
||||
CC = cl
|
||||
LIBS = eclgc.lib eclgmp.lib user32.lib ws2_32.lib shell32.lib
|
||||
CLIBS = user32.lib ws2_32.lib shell32.lib
|
||||
STATICLIBS = eclgc.lib eclgmp.lib
|
||||
LIBS = $(STATICLIBS) $(CLIBS)
|
||||
RM = del
|
||||
RMDIR = rmdir /Q /S
|
||||
MKDIR = mkdir
|
||||
|
|
@ -123,6 +127,10 @@ SHARED_LDFLAGS = /LD
|
|||
GCFLAGS = nodebug=1
|
||||
!endif
|
||||
|
||||
!if "$(ECL_USE_DBGHELP)" != ""
|
||||
CLIBS = $(CLIBS) DbgHelp.lib
|
||||
!endif
|
||||
|
||||
CFLAGS = /EHsc /DGC_DLL /DGC_BUILD /nologo /D_CRT_SECURE_NO_DEPRECATE $(CFLAGS_CONFIG)
|
||||
LDFLAGS = /link /incremental:no /nologo /nodefaultlib:libcmt /nodefaultlib:libcmtd /nodefaultlib:libc /nodefaultlib:libcd $(LDFLAGS_CONFIG)
|
||||
|
||||
|
|
@ -263,9 +271,9 @@ compile.lsp: bare.lsp $(srcdir)/compile.lsp.in Makefile
|
|||
"@LDFLAGS@" "$(LDFLAGS)" \
|
||||
"@SHARED_LDFLAGS@" "$(SHARED_LDFLAGS)" \
|
||||
"@BUNDLE_LDFLAGS@" "$(SHARED_LDFLAGS)" \
|
||||
"@CLIBS@" "user32.lib ws2_32.lib shell32.lib" \
|
||||
"@STATICLIBS@" "eclgmp.lib eclgc.lib" \
|
||||
"@LIBS@" "user32.lib ws2_32.lib shell32.lib" \
|
||||
"@CLIBS@" "$(CLIBS)" \
|
||||
"@STATICLIBS@" "$(STATICLIBS)" \
|
||||
"@LIBS@" "$(LIBS)" \
|
||||
"@CORE_LIBS@" "" \
|
||||
"@FASL_LIBS@" "" \
|
||||
"@OBJEXT@" "obj" \
|
||||
|
|
@ -305,8 +313,8 @@ cmp/cmpdefs.lsp: $(srcdir)/cmp/cmpdefs.lsp Makefile
|
|||
"@LDFLAGS@" "$(LDFLAGS)" \
|
||||
"@SHARED_LDFLAGS@" "$(SHARED_LDFLAGS)" \
|
||||
"@BUNDLE_LDFLAGS@" "$(SHARED_LDFLAGS)" \
|
||||
"@CLIBS@" "user32.lib ws2_32.lib shell32.lib" \
|
||||
"@STATICLIBS@" "eclgmp.lib eclgc.lib" \
|
||||
"@CLIBS@" "$(CLIBS)" \
|
||||
"@STATICLIBS@" "$(STATICLIBS)" \
|
||||
"@OBJEXT@" "obj" \
|
||||
"@SHAREDPREFIX@" "" \
|
||||
"@SHAREDEXT@" "dll" \
|
||||
|
|
@ -340,6 +348,7 @@ eclmin.lib: eclgmp.lib eclgc.lib lsp/config.lsp
|
|||
$(MAKE) ECL_VERSION_NUMBER=$(ECL_VERSION_NUMBER) \
|
||||
ECL_THREADS=$(ECL_THREADS) ECL_UNICODE=$(ECL_UNICODE) \
|
||||
ECL_SSE=$(ECL_SSE) ECL_WIN64=$(ECL_WIN64) \
|
||||
ECL_USE_DBGHELP=$(ECL_USE_DBGHELP) \
|
||||
"ECL_CFLAGS=$(CFLAGS) -DGC_BUILD"
|
||||
cd ..
|
||||
eclgc.lib:
|
||||
|
|
@ -448,6 +457,7 @@ clean_ecl:
|
|||
-$(MAKE) ECL_VERSION_NUMBER=$(ECL_VERSION_NUMBER) \
|
||||
ECL_THREADS=$(ECL_THREADS) ECL_UNICODE=$(ECL_UNICODE) \
|
||||
ECL_SSE=$(ECL_SSE) ECL_WIN64=$(ECL_WIN64) \
|
||||
ECL_USE_DBGHELP=$(ECL_USE_DBGHELP) \
|
||||
"ECL_CFLAGS=$(CFLAGS) -DGC_BUILD" clean
|
||||
cd ..
|
||||
clean_lisp:
|
||||
|
|
|
|||
|
|
@ -35,6 +35,12 @@ ECL_SSE_FLAG=0
|
|||
ECL_SSE_OBJ=
|
||||
!endif
|
||||
|
||||
!if "$(ECL_USE_DBGHELP)" != ""
|
||||
ECL_USE_DBGHELP_FLAG=1
|
||||
!else
|
||||
ECL_USE_DBGHELP_FLAG=0
|
||||
!endif
|
||||
|
||||
# Programs used by "make":
|
||||
#
|
||||
TRUE_CC = cl
|
||||
|
|
@ -60,12 +66,14 @@ libdir=$(prefix)\lib\ecl
|
|||
# Files
|
||||
|
||||
HDIR = $(top_srcdir)\h
|
||||
HFILES = ..\ecl\config.h ..\ecl\atomic_ops.h $(HDIR)\ecl.h $(HDIR)\ecl-cmp.h\
|
||||
$(HDIR)\object.h $(HDIR)\cs.h $(HDIR)\stacks.h\
|
||||
$(HDIR)\external.h $(HDIR)\cons.h $(HDIR)\legacy.h\
|
||||
HFILES = ..\ecl\config.h ..\ecl\config-internal.h ..\ecl\atomic_ops.h \
|
||||
$(HDIR)\ecl.h $(HDIR)\ecl-cmp.h \
|
||||
$(HDIR)\object.h $(HDIR)\cs.h $(HDIR)\stacks.h \
|
||||
$(HDIR)\external.h $(HDIR)\cons.h $(HDIR)\legacy.h \
|
||||
$(HDIR)\number.h $(HDIR)\page.h \
|
||||
$(HDIR)\internal.h $(HDIR)\ecl-inl.h $(HDIR)\bytecodes.h \
|
||||
$(HDIR)\impl\math_dispatch.h
|
||||
$(HDIR)\impl\math_dispatch.h $(HDIR)\cache.h $(HDIR)\stack-resize.h \
|
||||
$(HDIR)\ecl-atomic-ops.h
|
||||
|
||||
OBJS = main.obj symbol.obj package.obj cons.obj list.obj\
|
||||
apply.obj eval.obj \
|
||||
|
|
@ -153,21 +161,23 @@ clean:
|
|||
|
||||
# Build rules
|
||||
|
||||
$(DPP): $(srcdir)/dpp.c $(srcdir)/symbols_list2.h ../ecl/config.h
|
||||
$(DPP): $(srcdir)/dpp.c $(srcdir)/symbols_list2.h ../ecl/config.h ../ecl/config-internal.h
|
||||
$(TRUE_CC) -I.. -I./ $(srcdir)/dpp.c -o $@
|
||||
$(HFILES): ../ecl/config.h.msvc6 Makefile
|
||||
$(HFILES): ../ecl/config.h.msvc6 ../ecl/config-internal.h.msvc6 Makefile
|
||||
-mkdir ..\ecl\impl
|
||||
cut.exe "@ECL_FPE_CODE@" "$(srcdir:\=/)/arch/$(ECL_FPE_CODE)" \
|
||||
"@ECL_VERSION_NUMBER@" "$(ECL_VERSION_NUMBER)" \
|
||||
"@ECL_THREADS@" "$(ECL_THREADS_FLAG)" \
|
||||
"@ECL_UNICODE@" "$(ECL_UNICODE_FLAG)" \
|
||||
"@ECL_SSE2@" "$(ECL_SSE_FLAG)" \
|
||||
"@ECL_USE_DBGHELP@" "$(ECL_USE_DBGHELP_FLAG)" \
|
||||
< ..\ecl\config.h.msvc6 > ..\ecl\config.h
|
||||
cut.exe "@ECL_FPE_CODE@" "$(srcdir:\=/)/arch/$(ECL_FPE_CODE)" \
|
||||
"@ECL_VERSION_NUMBER@" "$(ECL_VERSION_NUMBER)" \
|
||||
"@ECL_THREADS@" "$(ECL_THREADS_FLAG)" \
|
||||
"@ECL_UNICODE@" "$(ECL_UNICODE_FLAG)" \
|
||||
"@ECL_SSE2@" "$(ECL_SSE_FLAG)" \
|
||||
"@ECL_USE_DBGHELP@" "$(ECL_USE_DBGHELP_FLAG)" \
|
||||
< ..\ecl\config-internal.h.msvc6 > ..\ecl\config-internal.h
|
||||
xcopy /SYI $(top_srcdir)\h\*.h ..\ecl
|
||||
-mkdir ..\ecl\atomic_ops
|
||||
|
|
|
|||
|
|
@ -210,3 +210,8 @@
|
|||
# define ECL_MATHERR_CLEAR
|
||||
# define ECL_MATHERR_TEST
|
||||
#endif
|
||||
|
||||
#define ECL_WINDOWS_BACKTRACE @ECL_USE_DBGHELP@
|
||||
#if !ECL_WINDOWS_BACKTRACE
|
||||
#undef ECL_WINDOWS_BACKTRACE
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -14,53 +14,116 @@
|
|||
#include <stdlib.h>
|
||||
#include <ecl/ecl.h>
|
||||
|
||||
#if defined(HAVE_BACKTRACE) || defined(HAVE_BACKTRACE_SYMBOLS)
|
||||
#if defined(HAVE_BACKTRACE) && defined(HAVE_BACKTRACE_SYMBOLS)
|
||||
# include <execinfo.h>
|
||||
# define ECL_UNIX_BACKTRACE
|
||||
#endif
|
||||
|
||||
#if defined(ECL_WINDOWS_BACKTRACE)
|
||||
# include <windows.h>
|
||||
# include <DbgHelp.h>
|
||||
#endif
|
||||
|
||||
/* Max number of frames dumped by _ecl_dump_c_backtrace */
|
||||
#define MAX_BACKTRACE_SIZE 128
|
||||
/* Max length of symbols printed */
|
||||
#define MAX_SYMBOL_LENGTH 256
|
||||
|
||||
void
|
||||
_ecl_dump_c_backtrace()
|
||||
{
|
||||
#ifdef HAVE_BACKTRACE_SYMBOLS
|
||||
#if defined(ECL_UNIX_BACKTRACE) || defined(ECL_WINDOWS_BACKTRACE)
|
||||
{
|
||||
void **pointers = malloc(sizeof(void*) * MAX_BACKTRACE_SIZE);
|
||||
# if defined(ECL_UNIX_BACKTRACE)
|
||||
int nframes = backtrace(pointers, MAX_BACKTRACE_SIZE);
|
||||
char **names = backtrace_symbols(pointers, nframes);
|
||||
# elif defined(ECL_WINDOWS_BACKTRACE)
|
||||
HANDLE process = GetCurrentProcess();
|
||||
if (!SymInitialize(process, NULL, TRUE)) {
|
||||
return;
|
||||
}
|
||||
int nframes = CaptureStackBackTrace(0, MAX_BACKTRACE_SIZE, pointers, NULL);
|
||||
char buffer[sizeof(SYMBOL_INFO) + MAX_SYMBOL_LENGTH * sizeof(TCHAR)];
|
||||
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
|
||||
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
pSymbol->MaxNameLen = MAX_SYMBOL_LENGTH;
|
||||
# endif
|
||||
int i;
|
||||
fprintf(stderr, "\n;;; ECL C Backtrace\n");
|
||||
for (i = 0; i < nframes; i++) {
|
||||
# if defined(ECL_UNIX_BACKTRACE)
|
||||
fprintf(stderr, ";;; %s\n", names[i]);
|
||||
# elif defined(ECL_WINDOWS_BACKTRACE)
|
||||
DWORD64 displacement;
|
||||
if (SymFromAddr(process, (DWORD64) pointers[i], &displacement, pSymbol)) {
|
||||
fprintf(stderr, ";;; (%s+0x%llx) [0x%p]\n", pSymbol->Name, displacement, pointers[i]);
|
||||
} else {
|
||||
fprintf(stderr, ";;; (unknown) [0x%p]\n", pointers[i]);
|
||||
}
|
||||
# endif
|
||||
}
|
||||
fflush(stderr);
|
||||
free(names);
|
||||
free(pointers);
|
||||
# if defined(ECL_UNIX_BACKTRACE)
|
||||
free(names);
|
||||
# elif defined(ECL_WINDOWS_BACKTRACE)
|
||||
SymCleanup(process);
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
#endif /* defined(ECL_UNIX_BACKTRACE) || defined(ECL_WINDOWS_BACKTRACE) */
|
||||
}
|
||||
|
||||
cl_object
|
||||
si_dump_c_backtrace(cl_object size)
|
||||
{
|
||||
cl_env_ptr the_env = ecl_process_env();
|
||||
#ifdef HAVE_BACKTRACE_SYMBOLS
|
||||
#if defined(ECL_UNIX_BACKTRACE) || defined(ECL_WINDOWS_BACKTRACE)
|
||||
{
|
||||
cl_index nsize = ecl_to_unsigned_integer(size);
|
||||
void **pointers = malloc(sizeof(void*) * nsize);
|
||||
# if defined(ECL_UNIX_BACKTRACE)
|
||||
int nframes = backtrace(pointers, nsize);
|
||||
char **names = backtrace_symbols(pointers, nframes);
|
||||
# elif defined(ECL_WINDOWS_BACKTRACE)
|
||||
HANDLE process = GetCurrentProcess();
|
||||
if (!SymInitialize(process, NULL, TRUE)) {
|
||||
return;
|
||||
}
|
||||
int nframes = CaptureStackBackTrace(0, nsize, pointers, NULL);
|
||||
char buffer[sizeof(SYMBOL_INFO) + MAX_SYMBOL_LENGTH * sizeof(TCHAR)];
|
||||
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
|
||||
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
pSymbol->MaxNameLen = MAX_SYMBOL_LENGTH;
|
||||
# endif
|
||||
int i;
|
||||
cl_format(2, ECL_T, make_constant_base_string("~&C Backtrace:~%"));
|
||||
for (i = 0; i < nframes; i++) {
|
||||
# if defined(ECL_UNIX_BACKTRACE)
|
||||
cl_format(3, ECL_T, make_constant_base_string(" > ~a~%"),
|
||||
make_constant_base_string(names[i]));
|
||||
# elif defined(ECL_WINDOWS_BACKTRACE)
|
||||
DWORD64 displacement;
|
||||
if (SymFromAddr(process, (DWORD64) pointers[i], &displacement, pSymbol)) {
|
||||
cl_format(5, ECL_T, make_constant_base_string(" > (~a+0x~x) [0x~x]~%"),
|
||||
make_constant_base_string(pSymbol->Name),
|
||||
ecl_make_unsigned_integer(displacement),
|
||||
ecl_make_unsigned_integer((cl_index)pointers[i]));
|
||||
} else {
|
||||
cl_format(3, ECL_T, make_constant_base_string(" > (unknown) [0x~x]~%"),
|
||||
ecl_make_unsigned_integer((cl_index)pointers[i]));
|
||||
}
|
||||
# endif
|
||||
}
|
||||
free(names);
|
||||
free(pointers);
|
||||
# if defined(ECL_UNIX_BACKTRACE)
|
||||
free(names);
|
||||
# elif defined(ECL_WINDOWS_BACKTRACE)
|
||||
SymCleanup(process);
|
||||
# endif
|
||||
}
|
||||
ecl_return1(the_env, ECL_T);
|
||||
#else
|
||||
ecl_return1(the_env, ECL_NIL);
|
||||
#endif
|
||||
#endif /* defined(ECL_UNIX_BACKTRACE) || defined(ECL_WINDOWS_BACKTRACE) */
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue