00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <string>
00023 #include <vector>
00024
00025 #include "TString.h"
00026
00027 #if defined(R__MACOSX)
00028 #if defined(MAC_OS_X_VERSION_10_5)
00029 #include <malloc/malloc.h>
00030 #include <execinfo.h>
00031 #endif
00032 #else
00033 #include <malloc.h>
00034 #include <execinfo.h>
00035 #endif
00036 #include <cxxabi.h>
00037
00038 #include "TMemStatDepend.h"
00039
00040 #if defined(R__GNU) && (defined(R__LINUX) || defined(R__HURD)) && !defined(__alpha__)
00041 #define SUPPORTS_MEMSTAT
00042 #endif
00043
00044
00045
00046 void *g_global_stack_end = NULL;
00047
00048 #if defined(SUPPORTS_MEMSTAT)
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 #define G__builtin_return_address(N) \
00060 ((__builtin_frame_address(N) == NULL) || \
00061 (__builtin_frame_address(N) >= g_global_stack_end) || \
00062 (__builtin_frame_address(N) < __builtin_frame_address(0))) ? \
00063 NULL : __builtin_return_address(N)
00064
00065
00066
00067 #define _RET_ADDR(x) case x: return G__builtin_return_address(x);
00068
00069 #endif
00070
00071 using namespace std;
00072
00073 ClassImp(TMemStatDepend)
00074
00075
00076
00077 static void *return_address(int _frame)
00078 {
00079
00080
00081 #if defined(SUPPORTS_MEMSTAT)
00082 switch (_frame) {
00083 _RET_ADDR(0);_RET_ADDR(1);_RET_ADDR(2);_RET_ADDR(3);_RET_ADDR(4);_RET_ADDR(5);_RET_ADDR(6);_RET_ADDR(7);
00084 _RET_ADDR(8);_RET_ADDR(9);_RET_ADDR(10);_RET_ADDR(11);_RET_ADDR(12);_RET_ADDR(13);_RET_ADDR(14);
00085 _RET_ADDR(15);_RET_ADDR(16);_RET_ADDR(17);_RET_ADDR(18);_RET_ADDR(19);_RET_ADDR(20);_RET_ADDR(21);
00086 _RET_ADDR(22);_RET_ADDR(23);_RET_ADDR(24);_RET_ADDR(25);_RET_ADDR(26);_RET_ADDR(27);_RET_ADDR(28);
00087 _RET_ADDR(29);_RET_ADDR(30);_RET_ADDR(31);_RET_ADDR(32);_RET_ADDR(33);_RET_ADDR(34);_RET_ADDR(35);
00088 default:
00089 return 0;
00090 }
00091 #else
00092 if (_frame) { }
00093 return 0;
00094 #endif
00095 }
00096
00097
00098 size_t builtin_return_address(void **_Container, size_t _limit)
00099 {
00100 size_t i(0);
00101 void *addr;
00102 for (i = 0; (i < _limit) && (addr = return_address(i)); ++i)
00103 _Container[i] = addr;
00104 return i;
00105 }
00106
00107
00108 TMemStatDepend::MallocHookFunc_t TMemStatDepend::GetMallocHook()
00109 {
00110
00111
00112 #if defined(SUPPORTS_MEMSTAT)
00113 return __malloc_hook;
00114 #else
00115 return 0;
00116 #endif
00117 }
00118
00119
00120 TMemStatDepend::FreeHookFunc_t TMemStatDepend::GetFreeHook()
00121 {
00122
00123
00124 #if defined(SUPPORTS_MEMSTAT)
00125 return __free_hook;
00126 #else
00127 return 0;
00128 #endif
00129 }
00130
00131
00132 void TMemStatDepend::SetMallocHook(MallocHookFunc_t p)
00133 {
00134
00135
00136 #if defined(SUPPORTS_MEMSTAT)
00137 __malloc_hook = p;
00138 #else
00139 if (p) { }
00140 #endif
00141 }
00142
00143
00144 void TMemStatDepend::SetFreeHook(FreeHookFunc_t p)
00145 {
00146
00147
00148 #if defined(SUPPORTS_MEMSTAT)
00149 __free_hook = p;
00150 #else
00151 if (p) { }
00152 #endif
00153 }
00154
00155
00156 size_t TMemStatDepend::Backtrace(void **trace, size_t dsize, Bool_t _bUseGNUBuildinBacktrace)
00157 {
00158
00159
00160
00161
00162
00163 if ( _bUseGNUBuildinBacktrace )
00164 {
00165 #if defined(SUPPORTS_MEMSTAT)
00166
00167 return builtin_return_address(trace, dsize);
00168 #else
00169 if (trace || dsize) { }
00170 return 0;
00171 #endif
00172 }
00173 #if defined(R__MACOSX)
00174 #if defined(MAC_OS_X_VERSION_10_5)
00175 return backtrace(trace, dsize);
00176 #else
00177 if (trace || dsize) { }
00178 return 0;
00179 #endif
00180 #else
00181 return backtrace(trace, dsize);
00182 #endif
00183 }
00184
00185
00186 char** TMemStatDepend::BacktraceSymbols(void **trace, size_t size)
00187 {
00188
00189
00190 #if defined(SUPPORTS_MEMSTAT)
00191 return backtrace_symbols(trace, size);
00192 #else
00193 if (trace || size) { }
00194 #endif
00195 return 0;
00196 }
00197
00198
00199 void TMemStatDepend::GetSymbols(void *_pFunction,
00200 TString &_strInfo, TString &_strLib, TString &_strFun, TString &)
00201 {
00202
00203
00204 #if defined(SUPPORTS_MEMSTAT)
00205 char ** code = backtrace_symbols(&_pFunction, 1);
00206 if (!code || !code[0])
00207 return;
00208 const string codeInfo(code[0]);
00209
00210 free(code);
00211
00212
00213 _strInfo = codeInfo.c_str();
00214
00215
00216 const string::size_type pos_begin = codeInfo.find_first_of("( [");
00217 if (string::npos == pos_begin) {
00218 _strLib = codeInfo;
00219 return;
00220 }
00221 _strLib = codeInfo.substr(0, pos_begin);
00222
00223
00224 string::size_type pos_end = codeInfo.find('+', pos_begin);
00225 if (string::npos == pos_end) {
00226 pos_end = codeInfo.find(')', pos_begin);
00227 if (string::npos == pos_end)
00228 return;
00229 }
00230 const string func(codeInfo.substr(pos_begin + 1, pos_end - pos_begin - 1));
00231
00232
00233 int status(0);
00234 char *ch = abi::__cxa_demangle(func.c_str(), 0, 0, &status);
00235 if (!ch)
00236 return;
00237 _strFun = (!status) ? ch : func.c_str();
00238
00239 free(ch);
00240 #else
00241 if (!_pFunction) { _strInfo = ""; _strLib = ""; _strFun = ""; }
00242 #endif
00243 }
00244
00245
00246 void TMemStatDepend::Demangle(char *codeInfo, TString &str)
00247 {
00248
00249
00250 #if defined(SUPPORTS_MEMSTAT)
00251 int status = 0;
00252 char *ch = abi::__cxa_demangle(codeInfo, 0, 0, &status);
00253 if (ch) {
00254 str = ch;
00255 free(ch);
00256 } else {
00257 str = "unknown";
00258 }
00259 #else
00260 if (!codeInfo) { str = ""; }
00261 #endif
00262 }