![]() |
User Manual, Developers Guide and API Documentation |
![]() |
00001 /******************************************************************************* 00002 * This file is part of openWNS (open Wireless Network Simulator) 00003 * _____________________________________________________________________________ 00004 * 00005 * Copyright (C) 2004-2007 00006 * Chair of Communication Networks (ComNets) 00007 * Kopernikusstr. 16, D-52074 Aachen, Germany 00008 * phone: ++49-241-80-27910, 00009 * fax: ++49-241-80-22242 00010 * email: info@openwns.org 00011 * www: http://www.openwns.org 00012 * _____________________________________________________________________________ 00013 * 00014 * openWNS is free software; you can redistribute it and/or modify it under the 00015 * terms of the GNU Lesser General Public License version 2 as published by the 00016 * Free Software Foundation; 00017 * 00018 * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY 00019 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 00020 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00021 * details. 00022 * 00023 * You should have received a copy of the GNU Lesser General Public License 00024 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00025 * 00026 ******************************************************************************/ 00027 00028 #include <WNS/Backtrace.hpp> 00029 #include <WNS/demangle.hpp> 00030 #include <iomanip> 00031 #include <cmath> 00032 00033 // to get the __GLIBC__ macro set (if glibc available) 00034 #include <features.h> 00035 00036 #ifdef __GLIBC__ 00037 #include <execinfo.h> 00038 #include <cstdlib> 00039 #endif // __GLIBC__ 00040 00041 #include <sstream> 00042 00043 using namespace wns; 00044 00045 Backtrace::Backtrace() : 00046 backtrace_() 00047 { 00048 } 00049 00050 Backtrace::~Backtrace() 00051 { 00052 clear(); 00053 } 00054 00055 void 00056 Backtrace::snapshot() 00057 { 00058 clear(); 00059 #ifdef __GLIBC__ 00060 const int arraySize = 1000; 00061 void* array[arraySize]; 00062 size_t size; 00063 char** strings; 00064 00065 size = backtrace (array, arraySize); 00066 strings = backtrace_symbols (array, size); 00067 00068 for (size_t ii = 0; ii < size; ++ii) 00069 { 00070 backtrace_.push_back(strings[ii]); 00071 } 00072 00073 free (strings); 00074 #endif // __GLIBC__ 00075 } 00076 00077 void 00078 Backtrace::clear() 00079 { 00080 backtrace_.clear(); 00081 } 00082 00083 wns::Backtrace::FunctionCalls 00084 Backtrace::getFunctionCalls() const 00085 { 00086 FunctionCalls functionCalls; 00087 00088 for(Lines::const_iterator itr = backtrace_.begin(); 00089 itr != backtrace_.end(); 00090 ++itr) 00091 { 00092 functionCalls.push_back(FunctionCall(*itr)); 00093 } 00094 00095 return functionCalls; 00096 } 00097 00098 std::string 00099 Backtrace::doToString() const 00100 { 00101 // get function calls and stream reverse 00102 FunctionCalls functionCalls = getFunctionCalls(); 00103 size_t stackSize = functionCalls.size(); 00104 size_t frame = stackSize; 00105 int width = static_cast<int>(std::ceil(std::log10(stackSize))); 00106 std::stringstream tmp; 00107 tmp << "Backtrace (most recent call last, stack size: " << stackSize << "):\n"; 00108 if (stackSize == 0) 00109 { 00110 tmp << " No backtrace available.\n" 00111 << " Backtrace is currently only available on systems with glibc, sorry.\n"; 00112 return tmp.str(); 00113 } 00114 // Marc Schinnenburg <marc@schinnenburg.com> 10.12.2007 00115 // The itr should be const_reverse_iterator, but gcc 3.4.4 cannot find the 00116 // operator==() or operator!=() for that :} 00117 for(FunctionCalls::reverse_iterator itr = functionCalls.rbegin(); 00118 itr != functionCalls.rend(); 00119 ++itr) 00120 { 00121 tmp << " " << std::setw(width) << frame << ") " << itr->getName() << "\n"; 00122 --frame; 00123 } 00124 return tmp.str(); 00125 } 00126 00127 00128 00129 Backtrace::FunctionCall::FunctionCall(std::string line) : 00130 origin_("unknown"), 00131 name_("unknown"), 00132 offset_("unknown"), 00133 returnAddress_("unknown") 00134 { 00135 00136 // the line typically looks like this: 00137 // ./openwns(_ZN3wns3WNS13SignalHandler11catchSignalEi+0xfc) [0x8068870] 00138 size_t openBrace = line.find("("); 00139 size_t plus = line.find("+"); 00140 size_t closeBrace = line.find(")"); 00141 size_t openSquareBrace = line.find("["); 00142 size_t closeSquareBrace = line.find("]"); 00143 00144 if (openBrace != std::string::npos) 00145 { 00146 // the stuff in front of "(" is the origin 00147 origin_ = line.substr(0, openBrace); 00148 00149 if (closeBrace != std::string::npos && plus != std::string::npos) 00150 { 00151 // the stuff from "(" to "+" is the function name 00152 { 00153 std::string symbol = line.substr(openBrace+1, plus-openBrace-1); 00154 name_ = wns::demangle(symbol); 00155 } 00156 // the stuff from "+" to ")" is the offset 00157 offset_ = line.substr(plus+1, closeBrace-plus-1); 00158 } 00159 } 00160 00161 if (openSquareBrace != std::string::npos && closeSquareBrace != std::string::npos) 00162 { 00163 // between "[" and "]" we find the return address 00164 returnAddress_ = line.substr(openSquareBrace+1, closeSquareBrace-plus-1); 00165 } 00166 } 00167 00168 std::string 00169 Backtrace::FunctionCall::getOrigin() const 00170 { 00171 return origin_; 00172 } 00173 00174 std::string 00175 Backtrace::FunctionCall::getName() const 00176 { 00177 return name_; 00178 } 00179 00180 std::string 00181 Backtrace::FunctionCall::getOffset() const 00182 { 00183 return offset_; 00184 } 00185 00186 std::string 00187 Backtrace::FunctionCall::getReturnAddress() const 00188 { 00189 return returnAddress_; 00190 }
1.5.5