Author: mlytwyn
Date: Tue Dec 1 19:46:09 2015
New Revision: 39206
URL: http://svn.gna.org/viewcvs/gnustep?rev=39206&view=rev
Log:
Add backtrace output to logfile if logging to file enabled
Added:
libs/back/branches/gnustep_testplant_branch/Tools/Backtrace/
libs/back/branches/gnustep_testplant_branch/Tools/Backtrace/backtrace.c
libs/back/branches/gnustep_testplant_branch/Tools/Backtrace/makefile
libs/back/branches/gnustep_testplant_branch/Tools/Backtrace/test.c
Modified:
libs/back/branches/gnustep_testplant_branch/Tools/GNUmakefile.postamble
libs/back/branches/gnustep_testplant_branch/Tools/GNUmakefile.preamble
libs/back/branches/gnustep_testplant_branch/Tools/gpbs.m
Added: libs/back/branches/gnustep_testplant_branch/Tools/Backtrace/backtrace.c
URL:
http://svn.gna.org/viewcvs/gnustep/libs/back/branches/gnustep_testplant_branch/Tools/Backtrace/backtrace.c?rev=39206&view=auto
==============================================================================
--- libs/back/branches/gnustep_testplant_branch/Tools/Backtrace/backtrace.c
(added)
+++ libs/back/branches/gnustep_testplant_branch/Tools/Backtrace/backtrace.c
Tue Dec 1 19:46:09 2015
@@ -0,0 +1,382 @@
+/*
+ Copyright (c) 2010 ,
+ Cloud Wu . All rights reserved.
+
+ http://www.codingnow.com
+
+ Use, modification and distribution are subject to the "New BSD License"
+ as listed at <url: http://www.opensource.org/licenses/bsd-license.php >.
+
+ filename: backtrace.c
+
+ compiler: gcc 3.4.5 (mingw-win32)
+
+ build command: gcc -O2 -shared -Wall -o backtrace.dll backtrace.c -lbfd
-liberty -limagehlp
+
+ how to use: Call LoadLibraryA("backtrace.dll"); at beginning of your
program .
+
+ */
+
+#include <windows.h>
+#include <excpt.h>
+#include <imagehlp.h>
+
+// TO get bfd.h to load...
+#if !defined(PACKAGE)
+#define PACKAGE "Eggplant"
+#define ____PACKAGE_DEFINED
+#endif
+#if !defined(PACKAGE_VERSION)
+#define PACKAGE_VERSION "0.0.0"
+#define ____PACKAGE_VERSION_DEFINED
+#endif
+
+#include <bfd.h>
+
+#if defined(____PACKAGE_DEFINED)
+#undef PACKAGE
+#undef ____PACKAGE_DEFINED
+#endif
+#if defined(____PACKAGE_VERSION_DEFINED)
+#undef PACKAGE_VERSION
+#undef ____PACKAGE_VERSION_DEFINED
+#endif
+
+#include <psapi.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdbool.h>
+#include <time.h>
+
+#define BUFFER_MAX (16*1024)
+
+struct bfd_ctx {
+ bfd * handle;
+ asymbol ** symbol;
+};
+
+struct bfd_set {
+ char * name;
+ struct bfd_ctx * bc;
+ struct bfd_set *next;
+};
+
+struct find_info {
+ asymbol **symbol;
+ bfd_vma counter;
+ const char *file;
+ const char *func;
+ unsigned line;
+};
+
+struct output_buffer {
+ char * buf;
+ size_t sz;
+ size_t ptr;
+};
+
+static void
+output_init(struct output_buffer *ob, char * buf, size_t sz)
+{
+ ob->buf = buf;
+ ob->sz = sz;
+ ob->ptr = 0;
+ ob->buf[0] = '\0';
+}
+
+static void
+output_print(struct output_buffer *ob, const char * format, ...)
+{
+ if (ob->sz == ob->ptr)
+ return;
+ ob->buf[ob->ptr] = '\0';
+ va_list ap;
+ va_start(ap,format);
+ vsnprintf(ob->buf + ob->ptr , ob->sz - ob->ptr , format, ap);
+ va_end(ap);
+
+ ob->ptr = strlen(ob->buf + ob->ptr) + ob->ptr;
+}
+
+static void
+lookup_section(bfd *abfd, asection *sec, void *opaque_data)
+{
+ struct find_info *data = opaque_data;
+
+ if (data->func)
+ return;
+
+ if (!(bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
+ return;
+
+ bfd_vma vma = bfd_get_section_vma(abfd, sec);
+ if (data->counter < vma || vma + bfd_get_section_size(sec) <=
data->counter)
+ return;
+
+ bfd_find_nearest_line(abfd, sec, data->symbol, data->counter - vma,
&(data->file), &(data->func), &(data->line));
+}
+
+static void
+find(struct bfd_ctx * b, DWORD offset, const char **file, const char **func,
unsigned *line)
+{
+ struct find_info data;
+ data.func = NULL;
+ data.symbol = b->symbol;
+ data.counter = offset;
+ data.file = NULL;
+ data.func = NULL;
+ data.line = 0;
+
+ bfd_map_over_sections(b->handle, &lookup_section, &data);
+ if (file) {
+ *file = data.file;
+ }
+ if (func) {
+ *func = data.func;
+ }
+ if (line) {
+ *line = data.line;
+ }
+}
+
+static int
+init_bfd_ctx(struct bfd_ctx *bc, const char * procname, struct output_buffer
*ob)
+{
+ bc->handle = NULL;
+ bc->symbol = NULL;
+
+ bfd *b = bfd_openr(procname, 0);
+ if (!b) {
+ output_print(ob,"Failed to open bfd from (%s)\n" , procname);
+ return 1;
+ }
+
+ int r1 = bfd_check_format(b, bfd_object);
+ int r2 = bfd_check_format_matches(b, bfd_object, NULL);
+ int r3 = bfd_get_file_flags(b) & HAS_SYMS;
+
+ if (!(r1 && r2 && r3)) {
+ bfd_close(b);
+ output_print(ob,"Failed to init bfd from (%s)\n", procname);
+ return 1;
+ }
+
+ void *symbol_table;
+
+ unsigned dummy = 0;
+ if (bfd_read_minisymbols(b, FALSE, &symbol_table, &dummy) == 0) {
+ if (bfd_read_minisymbols(b, TRUE, &symbol_table, &dummy) < 0) {
+ free(symbol_table);
+ bfd_close(b);
+ output_print(ob,"Failed to read symbols from (%s)\n",
procname);
+ return 1;
+ }
+ }
+
+ bc->handle = b;
+ bc->symbol = symbol_table;
+
+ return 0;
+}
+
+static void
+close_bfd_ctx(struct bfd_ctx *bc)
+{
+ if (bc) {
+ if (bc->symbol) {
+ free(bc->symbol);
+ }
+ if (bc->handle) {
+ bfd_close(bc->handle);
+ }
+ }
+}
+
+static struct bfd_ctx *
+get_bc(struct output_buffer *ob , struct bfd_set *set , const char *procname)
+{
+ while(set->name) {
+ if (strcmp(set->name , procname) == 0) {
+ return set->bc;
+ }
+ set = set->next;
+ }
+ struct bfd_ctx bc;
+ if (init_bfd_ctx(&bc, procname , ob)) {
+ return NULL;
+ }
+ set->next = calloc(1, sizeof(*set));
+ set->bc = malloc(sizeof(struct bfd_ctx));
+ memcpy(set->bc, &bc, sizeof(bc));
+ set->name = strdup(procname);
+
+ return set->bc;
+}
+
+static void
+release_set(struct bfd_set *set)
+{
+ while(set) {
+ struct bfd_set * temp = set->next;
+ free(set->name);
+ close_bfd_ctx(set->bc);
+ free(set);
+ set = temp;
+ }
+}
+
+static void
+_backtrace(struct output_buffer *ob, struct bfd_set *set, int depth ,
LPCONTEXT context)
+{
+ char procname[MAX_PATH];
+ GetModuleFileNameA(NULL, procname, sizeof procname);
+
+ struct bfd_ctx *bc = NULL;
+
+ STACKFRAME frame;
+ memset(&frame,0,sizeof(frame));
+
+ frame.AddrPC.Offset = context->Eip;
+ frame.AddrPC.Mode = AddrModeFlat;
+ frame.AddrStack.Offset = context->Esp;
+ frame.AddrStack.Mode = AddrModeFlat;
+ frame.AddrFrame.Offset = context->Ebp;
+ frame.AddrFrame.Mode = AddrModeFlat;
+
+ HANDLE process = GetCurrentProcess();
+ HANDLE thread = GetCurrentThread();
+
+ char symbol_buffer[sizeof(IMAGEHLP_SYMBOL) + 255];
+ char module_name_raw[MAX_PATH];
+
+ while(StackWalk(IMAGE_FILE_MACHINE_I386,
+ process,
+ thread,
+ &frame,
+ context,
+ 0,
+ SymFunctionTableAccess,
+ SymGetModuleBase, 0)) {
+
+ --depth;
+ if (depth < 0)
+ break;
+
+ IMAGEHLP_SYMBOL *symbol = (IMAGEHLP_SYMBOL *)symbol_buffer;
+ symbol->SizeOfStruct = (sizeof *symbol) + 255;
+ symbol->MaxNameLength = 254;
+
+ DWORD module_base = SymGetModuleBase(process,
frame.AddrPC.Offset);
+
+ const char * module_name = "[unknown module]";
+ if (module_base &&
+ GetModuleFileNameA((HINSTANCE)module_base,
module_name_raw, MAX_PATH)) {
+ module_name = module_name_raw;
+ bc = get_bc(ob, set, module_name);
+ }
+
+ const char * file = NULL;
+ const char * func = NULL;
+ unsigned line = 0;
+
+ if (bc) {
+ find(bc,frame.AddrPC.Offset,&file,&func,&line);
+ }
+
+ if (file == NULL) {
+ DWORD dummy = 0;
+ if (SymGetSymFromAddr(process, frame.AddrPC.Offset,
&dummy, symbol)) {
+ file = symbol->Name;
+ }
+ else {
+ file = "[unknown file]";
+ }
+ }
+ if (func == NULL) {
+ output_print(ob,"0x%x : %s : %s \n",
+ frame.AddrPC.Offset,
+ module_name,
+ file);
+ }
+ else {
+ output_print(ob,"0x%x : %s : %s (%d) : in function (%s)
\n",
+ frame.AddrPC.Offset,
+ module_name,
+ file,
+ line,
+ func);
+ }
+ }
+}
+
+static char * g_output = NULL;
+static LPTOP_LEVEL_EXCEPTION_FILTER g_prev = NULL;
+
+static LONG WINAPI
+exception_filter(LPEXCEPTION_POINTERS info)
+{
+ struct output_buffer ob;
+ time_t *crashTime = calloc(1,sizeof(*crashTime));
+ char timeString[256];
+
+ output_init(&ob, g_output, BUFFER_MAX);
+ time(crashTime);
+ strftime(timeString, 256, "%Y-%m-%d %H:%M:%S", localtime(crashTime));
+
+ output_print(&ob,"\nCrash Backtrace: %s\n", timeString);
+
+ if (!SymInitialize(GetCurrentProcess(), 0, TRUE)) {
+ output_print(&ob,"\nFailed to init symbol context\n");
+ }
+ else {
+ bfd_init();
+ struct bfd_set *set = calloc(1,sizeof(*set));
+ _backtrace(&ob , set , 128 , info->ContextRecord);
+ release_set(set);
+
+ SymCleanup(GetCurrentProcess());
+ }
+
+ fputs(g_output , stderr);
+
+ exit(1);
+
+ return 0;
+}
+
+static void
+backtrace_register(void)
+{
+ if (g_output == NULL) {
+ g_output = malloc(BUFFER_MAX);
+ g_prev = SetUnhandledExceptionFilter(exception_filter);
+ }
+}
+
+static void
+backtrace_unregister(void)
+{
+ if (g_output) {
+ free(g_output);
+ SetUnhandledExceptionFilter(g_prev);
+ g_prev = NULL;
+ g_output = NULL;
+ }
+}
+
+BOOL WINAPI
+DllMain(HANDLE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
+{
+ switch (dwReason) {
+ case DLL_PROCESS_ATTACH:
+ backtrace_register();
+ break;
+ case DLL_PROCESS_DETACH:
+ backtrace_unregister();
+ break;
+ }
+ return TRUE;
+}
+
Added: libs/back/branches/gnustep_testplant_branch/Tools/Backtrace/makefile
URL:
http://svn.gna.org/viewcvs/gnustep/libs/back/branches/gnustep_testplant_branch/Tools/Backtrace/makefile?rev=39206&view=auto
==============================================================================
--- libs/back/branches/gnustep_testplant_branch/Tools/Backtrace/makefile
(added)
+++ libs/back/branches/gnustep_testplant_branch/Tools/Backtrace/makefile
Tue Dec 1 19:46:09 2015
@@ -0,0 +1,12 @@
+.PHONY: all clean
+
+all : backtrace.dll test.exe
+
+backtrace.dll : backtrace.c
+ gcc -O2 -shared -Wall -o $@ $^ -lbfd -lintl -liberty -limagehlp -lz
+
+test.exe : test.c
+ gcc -g -Wall -o $@ $^
+
+clean :
+ -rm -f backtrace.dll test.exe
Added: libs/back/branches/gnustep_testplant_branch/Tools/Backtrace/test.c
URL:
http://svn.gna.org/viewcvs/gnustep/libs/back/branches/gnustep_testplant_branch/Tools/Backtrace/test.c?rev=39206&view=auto
==============================================================================
--- libs/back/branches/gnustep_testplant_branch/Tools/Backtrace/test.c (added)
+++ libs/back/branches/gnustep_testplant_branch/Tools/Backtrace/test.c Tue Dec
1 19:46:09 2015
@@ -0,0 +1,23 @@
+#include <windows.h>
+
+static void
+foo()
+{
+ int *f=NULL;
+ *f = 0;
+}
+
+static void
+bar()
+{
+ foo();
+}
+
+int
+main()
+{
+ LoadLibraryA("backtrace.dll");
+ bar();
+
+ return 0;
+}
Modified:
libs/back/branches/gnustep_testplant_branch/Tools/GNUmakefile.postamble
URL:
http://svn.gna.org/viewcvs/gnustep/libs/back/branches/gnustep_testplant_branch/Tools/GNUmakefile.postamble?rev=39206&r1=39205&r2=39206&view=diff
==============================================================================
--- libs/back/branches/gnustep_testplant_branch/Tools/GNUmakefile.postamble
(original)
+++ libs/back/branches/gnustep_testplant_branch/Tools/GNUmakefile.postamble
Tue Dec 1 19:46:09 2015
@@ -32,6 +32,9 @@
$(LN_S) ../Source/xlib/XGCommonFont.m .
-$(RM) xdnd.c
$(LN_S) ../Source/x11/xdnd.c .
+ifeq ($(findstring mingw32, $(GNUSTEP_TARGET_OS)), mingw32)
+ (cd Backtrace; make; cd ..)
+endif
# Things to do after compiling
# after-all::
@@ -41,6 +44,9 @@
# Things to do after installing
after-install::
+ifeq ($(findstring mingw32, $(GNUSTEP_TARGET_OS)), mingw32)
+ $(INSTALL) backtrace/backtrace.dll $(GNUSTEP_TOOLS)
+endif
if [ ! -f $(GNUSTEP_DOC_MAN) ]; then \
$(MKDIRS) $(GNUSTEP_DOC_MAN); \
fi; \
@@ -60,6 +66,9 @@
# Things to do after uninstalling
after-uninstall::
+ifeq ($(findstring mingw32, $(GNUSTEP_TARGET_OS)), mingw32)
+ rm -f $(GNUSTEP_TOOLS)/backtrace.dll
+endif
for file in $(MAN1_PAGES) __done; do \
if [ $$file != __done ]; then \
rm -f $(GNUSTEP_DOC_MAN)/man1/$$file.gz; \
Modified: libs/back/branches/gnustep_testplant_branch/Tools/GNUmakefile.preamble
URL:
http://svn.gna.org/viewcvs/gnustep/libs/back/branches/gnustep_testplant_branch/Tools/GNUmakefile.preamble?rev=39206&r1=39205&r2=39206&view=diff
==============================================================================
--- libs/back/branches/gnustep_testplant_branch/Tools/GNUmakefile.preamble
(original)
+++ libs/back/branches/gnustep_testplant_branch/Tools/GNUmakefile.preamble
Tue Dec 1 19:46:09 2015
@@ -67,3 +67,10 @@
else
ADDITIONAL_TOOL_LIBS += -lgnustep-gui -lgnustep-back $(SYSTEM_LIBS)
endif
+
+ifeq ($(findstring mingw32, $(GNUSTEP_TARGET_OS)), mingw32)
+ADDITIONAL_LIB_DIRS += -L./Backtrace
+ADDITIONAL_TOOL_LIBS += -lbacktrace
+SUBPROJECTS = Backtrace
+endif
+
Modified: libs/back/branches/gnustep_testplant_branch/Tools/gpbs.m
URL:
http://svn.gna.org/viewcvs/gnustep/libs/back/branches/gnustep_testplant_branch/Tools/gpbs.m?rev=39206&r1=39205&r2=39206&view=diff
==============================================================================
--- libs/back/branches/gnustep_testplant_branch/Tools/gpbs.m (original)
+++ libs/back/branches/gnustep_testplant_branch/Tools/gpbs.m Tue Dec 1
19:46:09 2015
@@ -1235,6 +1235,7 @@
}
}
+#if 0 // TODO...
// Purge logfile to 3 max each...
NSArray *properties = [NSArray
arrayWithObjects:@"NSURLCreationDateKey", nil];
NSArray *logfiles = [filemgr contentsOfDirectoryAtURL:[NSURL
fileURLWithPath:filepath]
@@ -1265,6 +1266,7 @@
NSLog(@"%s:purging output log files: %@",
__PRETTY_FUNCTION__, outfiles);
}
}
+#endif
if ([filemgr fileExistsAtPath:filepath isDirectory:&isDir] &&
isDir)
{
@@ -1418,12 +1420,27 @@
}
}
}
+
+#if defined(__MINGW__)
+ if ([[NSUserDefaults standardUserDefaults]
boolForKey:@"GSGPBSLoggingEnabled"])
+ {
+ // Load backtrace library for mingw...
+ NSString *gpbstool = [NSString stringWithCString:argv[0]
encoding:NSASCIIStringEncoding];
+ NSString *gpbspath = [gpbstool stringByDeletingLastPathComponent];
+ NSString *backtrace = [gpbspath
stringByAppendingPathComponent:@"backtrace.dll"];
+
+ if (LoadLibraryA([backtrace cStringUsingEncoding:NSUTF8StringEncoding]) ==
0)
+ NSWarnMLog(@"error loading mingw backtrace library - status: %d",
GetLastError());
+ else
+ NSWarnMLog(@"Windows/mingw backtrace library loaded successfully");
+ }
+#endif
if (verbose)
{
NSLog(@"GNU pasteboard server startup.");
}
-
+
if ([[NSUserDefaults standardUserDefaults]
stringForKey: @"GSStartupNotification"])
{
_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs