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
Gnustep-cvs@gna.org
https://mail.gna.org/listinfo/gnustep-cvs

Reply via email to