00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "TMemStatBacktrace.h"
00012
00013
00014 #include <cstdlib>
00015
00016 #ifndef __CINT__
00017 #if !defined(__APPLE__) || defined(MAC_OS_X_VERSION_10_5)
00018 #include <execinfo.h>
00019 #endif
00020 #include <cxxabi.h>
00021 #endif
00022
00023 #include <dlfcn.h>
00024
00025 #include "TString.h"
00026
00027 #if defined(R__GNU) && (defined(R__LINUX) || defined(R__HURD) || (defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_5)))
00028 #define SUPPORTS_MEMSTAT
00029 #endif
00030
00031
00032
00033 void *g_global_stack_end = NULL;
00034
00035 #if defined(SUPPORTS_MEMSTAT)
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #define G__builtin_return_address(N) \
00047 ((__builtin_frame_address(N) == NULL) || \
00048 (__builtin_frame_address(N) >= g_global_stack_end) || \
00049 (__builtin_frame_address(N) < __builtin_frame_address(0))) ? \
00050 NULL : __builtin_return_address(N)
00051
00052
00053
00054 #define _RET_ADDR(x) case x: return G__builtin_return_address(x);
00055
00056 #endif
00057
00058 namespace memstat {
00059
00060
00061
00062 static void *return_address(int _frame)
00063 {
00064
00065
00066 #if defined(SUPPORTS_MEMSTAT)
00067 switch(_frame) {
00068 _RET_ADDR(0);
00069 _RET_ADDR(1);
00070 _RET_ADDR(2);
00071 _RET_ADDR(3);
00072 _RET_ADDR(4);
00073 _RET_ADDR(5);
00074 _RET_ADDR(6);
00075 _RET_ADDR(7);
00076 _RET_ADDR(8);
00077 _RET_ADDR(9);
00078 _RET_ADDR(10);
00079 _RET_ADDR(11);
00080 _RET_ADDR(12);
00081 _RET_ADDR(13);
00082 _RET_ADDR(14);
00083 _RET_ADDR(15);
00084 _RET_ADDR(16);
00085 _RET_ADDR(17);
00086 _RET_ADDR(18);
00087 _RET_ADDR(19);
00088 _RET_ADDR(20);
00089 _RET_ADDR(21);
00090 _RET_ADDR(22);
00091 _RET_ADDR(23);
00092 _RET_ADDR(24);
00093 _RET_ADDR(25);
00094 _RET_ADDR(26);
00095 _RET_ADDR(27);
00096 _RET_ADDR(28);
00097 _RET_ADDR(29);
00098 _RET_ADDR(30);
00099 _RET_ADDR(31);
00100 _RET_ADDR(32);
00101 _RET_ADDR(33);
00102 _RET_ADDR(34);
00103 _RET_ADDR(35);
00104 default:
00105 return 0;
00106 }
00107 #else
00108 if(_frame) { }
00109 return 0;
00110 #endif
00111 }
00112
00113
00114 size_t builtin_return_address(void **_container, size_t _limit)
00115 {
00116 size_t i(0);
00117 void *addr;
00118 for(i = 0; (i < _limit) && (addr = return_address(i)); ++i)
00119 _container[i] = addr;
00120
00121 return i;
00122 }
00123
00124 size_t getBacktrace(void **_trace, size_t _size, Bool_t _bUseGNUBuiltinBacktrace)
00125 {
00126
00127
00128
00129
00130
00131
00132
00133 #if defined(SUPPORTS_MEMSTAT)
00134 if(_bUseGNUBuiltinBacktrace) {
00135
00136 return builtin_return_address(_trace, _size);
00137 }
00138 return backtrace(_trace, _size);
00139 #else
00140 if(_trace || _size || _bUseGNUBuiltinBacktrace) { }
00141 return 0;
00142 #endif
00143 }
00144
00145
00146 int getSymbols(void *_pAddr,
00147 TString &, TString &_strLib, TString &_strSymbol)
00148 {
00149
00150
00151 #if defined(SUPPORTS_MEMSTAT)
00152 Dl_info info;
00153 if(0 == dladdr(_pAddr, &info)) {
00154 return -1;
00155 }
00156 if(NULL != info.dli_sname) {
00157 int status(0);
00158 char *ch = abi::__cxa_demangle(info.dli_sname, 0, 0, &status);
00159
00160 _strSymbol = (0 == status) ? ch : info.dli_sname;
00161
00162
00163 free(ch);
00164 }
00165 if(NULL != info.dli_fname)
00166 _strLib = info.dli_fname;
00167 #else
00168 if(!_pAddr) {
00169 _strLib = "";
00170 _strSymbol = "";
00171 }
00172 #endif
00173 return 0;
00174 }
00175
00176
00177 void getSymbolFullInfo(void *_pAddr, TString *_retInfo, const char *const _separator)
00178 {
00179
00180 if(!_retInfo)
00181 return;
00182
00183 #if defined(SUPPORTS_MEMSTAT)
00184 TString strInfo;
00185 TString strLib;
00186 TString strFun;
00187 int res = getSymbols(_pAddr, strInfo, strLib, strFun);
00188 if(0 != res)
00189 return;
00190
00191 *_retInfo += strInfo;
00192 *_retInfo += _separator;
00193 *_retInfo += strLib;
00194 *_retInfo += _separator;
00195 *_retInfo += strFun;
00196 #else
00197 if(_pAddr || _separator) { }
00198 #endif
00199 }
00200
00201
00202 void demangle(char *_codeInfo, TString &_str)
00203 {
00204
00205
00206 #if defined(SUPPORTS_MEMSTAT)
00207 int status = 0;
00208 char *ch = abi::__cxa_demangle(_codeInfo, 0, 0, &status);
00209 if(ch) {
00210 _str = ch;
00211 free(ch);
00212 } else {
00213 _str = "unknown";
00214 }
00215 #else
00216 if(!_codeInfo) {
00217 _str = "";
00218 }
00219 #endif
00220 }
00221
00222 }