Bug fix: check if vm exists
[avr-sim.git] / Exception.cpp
bloba01e6fafcc6add6639cec6a75724dcf1d85c82a7
1 #include "Exception.h"
2 #include <iostream>
4 #ifdef LINUX
5 # include <execinfo.h>
6 # include <malloc.h>
7 # define GNU_SOURCE
8 # include <dlfcn.h>
9 # include <cxxabi.h>
10 #endif
12 #ifdef WIN32
13 # include <SymbolResolve.h>
14 #endif
16 #ifdef _DEBUG
17 # ifndef DEBUG
18 # define DEBUG
19 # endif
20 #endif
22 namespace util {
23 LowLevelException::LowLevelException() {
24 msg = "";
25 fillInStackTrace();
28 LowLevelException::~LowLevelException() {
32 LowLevelException::LowLevelException(const LowLevelException & ex) {
33 #if ! defined(DISABLESTACKTRACE)
34 msg = ex.msg;
35 trace = ex.trace;
36 for(short i = 0; i < trace; ++i) {
37 callersAddr[i] = ex.callersAddr[i];
39 #endif
42 #if defined(_MSC_VER) && defined(_M_IX86) && ! defined(DISABLESTACKTRACE)
43 static void *getCaller(int index) {
44 void *caller = 0;
45 __asm
47 mov ebx, ebp
48 mov ecx, index
49 inc ecx
50 xor eax, eax
51 Exception_getCaller_next:
52 mov eax, [ebx+4]
53 mov ebx, [ebx]
54 dec ecx
55 jnz Exception_getCaller_next
56 mov caller, eax
59 return caller;
61 #endif
63 /**
64 Creates the stacktrace buffer.
66 void LowLevelException::fillInStackTrace() {
67 #if ! defined(DISABLESTACKTRACE)
68 #if defined(_MSC_VER) && defined(_M_IX86)
69 trace = 1;
70 void *addr;
71 do {
72 addr = getCaller(trace);
73 callersAddr[trace++] = addr;
74 } while( (addr != 0) && (trace < MAXTRACESIZE) );
75 #elif defined(LINUX)
76 trace = backtrace(callersAddr, MAXTRACESIZE);
77 #else
78 trace = 0;
79 #endif
80 #endif
83 void LowLevelException::printStackTrace() const {
84 printStackTrace( std::cout );
87 /**
88 Prints this Exception and its backtrace to the
89 standard error stream. This method prints a stack trace
90 for this exception on the error output stream
91 The first line of output contains the result of the getMessage()
92 method for this object. Remaining lines represent
93 a list of the function calls that are currently active
95 void LowLevelException::printStackTrace(std::ostream & str) const {
96 #if ! defined(DISABLESTACKTRACE)
97 #if defined(_MSC_VER) && defined(_M_IX86)
98 for(unsigned short i = 2; i < trace; ++i) {
99 str << '(' << (trace - i) << ") "
100 << " [" << std::hex << callersAddr[i] << std::dec << "]: ";
102 #ifndef NO_DBGHELP
103 DWORD64 addr = DWORD64(callersAddr[i]);
104 PSYMBOL_INFO sym = SymbolResolve::getSymbolFromAddress( addr );
105 str << ((sym != 0) ? sym->Name : "???") << std::endl;
107 IMAGEHLP_LINE64 *im = SymbolResolve::getSourceFromAddress( addr );
108 if( im != 0 )
109 str << "\t" << im->FileName << ":" << im->LineNumber << std::endl;
110 #else
111 str << "???" << std::endl;
112 #endif
114 #elif defined(LINUX)
115 Dl_info info;
116 for(unsigned short i = 2; i < trace; ++i) {
117 str << '(' << (trace - i) << ") ";
118 if( (dladdr(callersAddr[i], &info) != 0) && (info.dli_sname != 0) ) {
119 const char *name =__cxxabiv1::__cxa_demangle(info.dli_sname, 0, 0, 0);
120 if( name != 0 ) {
121 str << name;
122 free( (void *)name );
123 } else {
124 str << info.dli_sname;
128 str << " [" << std::hex << callersAddr[i] << std::dec << ']' << std::endl;
131 /* backtrace_symbols might be more portable but does not do name
132 demangling.
134 #endif
135 #endif