Fixed problem in DeviceSettings::strParam, returned wrong string
[avr-sim.git] / src / Exception.cpp
blobab1db17607b05b94a39c8ac8ec202925fd270664
1 /*
2 * avr-sim: An atmel AVR simulator
3 * Copyright (C) 2008 Tom Haber
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "Exception.h"
20 #include <iostream>
22 #ifdef __GNUC__
23 # include <execinfo.h>
24 # include <malloc.h>
25 # define GNU_SOURCE
26 # include <dlfcn.h>
27 # include <cxxabi.h>
28 #endif
30 #ifdef _WIN32
31 # include <SymbolResolve.h>
32 #endif
34 #ifdef _DEBUG
35 # ifndef DEBUG
36 # define DEBUG
37 # endif
38 #endif
40 namespace util {
41 LowLevelException::LowLevelException() {
42 msg = "";
43 fillInStackTrace();
46 LowLevelException::~LowLevelException() {
50 LowLevelException::LowLevelException(const LowLevelException & ex) {
51 #if ! defined(DISABLESTACKTRACE)
52 msg = ex.msg;
53 trace = ex.trace;
54 for(short i = 0; i < trace; ++i) {
55 callersAddr[i] = ex.callersAddr[i];
57 #endif
60 #if defined(_MSC_VER) && defined(_M_IX86) && ! defined(DISABLESTACKTRACE)
61 static void *getCaller(int index) {
62 void *caller = 0;
63 __asm
65 mov ebx, ebp
66 mov ecx, index
67 inc ecx
68 xor eax, eax
69 Exception_getCaller_next:
70 mov eax, [ebx+4]
71 mov ebx, [ebx]
72 dec ecx
73 jnz Exception_getCaller_next
74 mov caller, eax
77 return caller;
79 #endif
81 /**
82 Creates the stacktrace buffer.
84 void LowLevelException::fillInStackTrace() {
85 #if ! defined(DISABLESTACKTRACE)
86 #if defined(_MSC_VER) && defined(_M_IX86)
87 trace = 1;
88 void *addr;
89 do {
90 addr = getCaller(trace);
91 callersAddr[trace++] = addr;
92 } while( (addr != 0) && (trace < MAXTRACESIZE) );
93 #elif defined(__GNUC__)
94 trace = backtrace(callersAddr, MAXTRACESIZE);
95 #else
96 trace = 0;
97 #endif
98 #endif
101 void LowLevelException::printStackTrace() const {
102 printStackTrace( std::cout );
106 Prints this Exception and its backtrace to the
107 standard error stream. This method prints a stack trace
108 for this exception on the error output stream
109 The first line of output contains the result of the getMessage()
110 method for this object. Remaining lines represent
111 a list of the function calls that are currently active
113 void LowLevelException::printStackTrace(std::ostream & str) const {
114 #if ! defined(DISABLESTACKTRACE)
115 #if defined(_MSC_VER) && defined(_M_IX86)
116 for(unsigned short i = 2; i < trace; ++i) {
117 str << '(' << (trace - i) << ") "
118 << " [" << std::hex << callersAddr[i] << std::dec << "]: ";
120 #ifndef NO_DBGHELP
121 DWORD64 addr = DWORD64(callersAddr[i]);
122 PSYMBOL_INFO sym = SymbolResolve::getSymbolFromAddress( addr );
123 str << ((sym != 0) ? sym->Name : "???") << std::endl;
125 IMAGEHLP_LINE64 *im = SymbolResolve::getSourceFromAddress( addr );
126 if( im != 0 )
127 str << "\t" << im->FileName << ":" << im->LineNumber << std::endl;
128 #else
129 str << "???" << std::endl;
130 #endif
132 #elif defined(__GNUC__)
133 Dl_info info;
134 for(unsigned short i = 2; i < trace; ++i) {
135 str << '(' << (trace - i) << ") ";
136 if( (dladdr(callersAddr[i], &info) != 0) && (info.dli_sname != 0) ) {
137 const char *name =__cxxabiv1::__cxa_demangle(info.dli_sname, 0, 0, 0);
138 if( name != 0 ) {
139 str << name;
140 free( (void *)name );
141 } else {
142 str << info.dli_sname;
146 str << " [" << std::hex << callersAddr[i] << std::dec << ']' << std::endl;
149 /* backtrace_symbols might be more portable but does not do name
150 demangling.
152 #endif
153 #endif