root/trunk/backtrace_assert/debugging.d

Revision 710, 2.9 kB (checked in by BCS, 2 years ago)

comment

Line 
1 module debugging;
2
3 /+++++++++++++++++++++++++++
4 This has some not exactly ideal bits:
5
6 -it won't work nicely unless you link with gcc and add the -rdynamic flag.
7 -accessing some of the posix stuff fubared my link (unresolved ModuleInfos) so
8  I had to add the prototypes directly (yuck)
9 -it uses the c function dprintf that on some system does what I want (print to
10  a low level file stream) and on some system does something totally different.
11 -it has the expected executable name and the location of addr2line hard coded
12
13 +/
14
15 import core.exception;
16
17 import core.stdc.errno;
18 import std.cstream;
19 import std.stdio;
20 import std.string;
21
22 import core.stdc.stdio;
23 import core.sys.posix.sys.wait;
24
25 //import core.sys.posix.fcntl;   // O_CREAT  O_TRUNC O_WRONLY open
26 //import core.sys.posix.unistd;  // fork dup2
27 extern(C)
28 {
29     /// these are in core.sys.posix.* but for some reason importing them breaks the build
30     enum O_CREAT        = 0100;
31     enum O_TRUNC        = 01000;
32     enum O_WRONLY       = 01;
33
34     int open(in char*, int, ...);
35     int fork();
36     int dup2(int, int);
37
38     int backtrace (void **__array, int __size) ;
39     extern char **backtrace_symbols (void **__array, int __size) ;
40     void backtrace_symbols_fd (void **__array, int __size,  int __fd) ;
41 }
42
43 // used to print directly to a file descriptor
44 version(linux) extern(C) int dprintf(int fd, const char *format, ...);
45 else static assert(false, "system not know to support dprintf");
46
47 enum nameOfExec = "btree";
48 enum nameOfAddr2line = "/usr/bin/addr2line";
49 pragma(msg, "Getting line numbers from a file named '"~nameOfExec~"' and passing them to '"~nameOfAddr2line~"'");
50
51 void DumpMessage(string test, string message, string file = __FILE__, int line = __LINE__)
52 {
53     derr.writef("StackTrace: %s:%d \'%s\' failed: %s\n", file, line, test, message);
54    
55     int dmp = open("dmplog", O_WRONLY|O_TRUNC|O_CREAT, 0666);
56     if(-1 == dmp) { writef("Log file failed %d\n", errno); return; }
57
58     dprintf(dmp,"StackTrace: %s:%d \'%s\' failed: %s\n------------------\n".ptr, file.ptr, line, test.ptr, message.ptr);
59     void* buffer[200];
60     int i = backtrace(buffer.ptr, buffer.length);
61    
62     if(0 == fork())
63     {
64         // child
65         string[] env = [null];
66
67         int count = 6-3+i;
68         auto argv = new string[count];
69         argv[0] = nameOfAddr2line;
70         argv[1] = "--exe=" ~ nameOfExec;
71         argv[2] = "-f";
72         argv[3] = "-C";
73         argv[4] = "-s";
74         argv[$-1] = null;
75
76         for(int j = 1; j < i-2; j++) argv[j + 4] = format("%x\0", cast(int)buffer[j]);
77
78         // fork/exec to addr2line
79         dup2(dmp, 1);
80         std.process.execve(argv[0], argv, env);
81         core.stdc.stdlib.abort();
82     }
83     else
84     {
85         wait(null);
86     }
87
88     dprintf(dmp, "-------------\n".ptr);
89     backtrace_symbols_fd(&buffer[1],i-3,dmp);
90 }
91
92 static this()
93 {
94     setAssertHandler(
95         function void(string file, int line, string msg)
96         {
97             DumpMessage("Assert", msg, file, line);
98             throw new AssertError( msg, file, line );
99         });
100 }
Note: See TracBrowser for help on using the browser.