TMemStatBacktrace.cxx

Go to the documentation of this file.
00001 // @(#)root/memstat:$Id: TMemStatBacktrace.cxx 36987 2010-11-26 18:29:44Z anar $
00002 // Author: Anar Manafov (A.Manafov@gsi.de) 2010-03-02
00003 
00004 /*************************************************************************
00005 * Copyright (C) 1995-2010, Rene Brun and Fons Rademakers.               *
00006 * All rights reserved.                                                  *
00007 *                                                                       *
00008 * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010 *************************************************************************/
00011 #include "TMemStatBacktrace.h"
00012 
00013 // STD
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 // ROOT
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 // This is a global variable set at MSManager init time.
00032 // It marks the highest used stack address.
00033 void *g_global_stack_end = NULL;
00034 
00035 #if defined(SUPPORTS_MEMSTAT)
00036 // Comment from Anar:
00037 // HACK: there is an ugly bug in gcc (Bug#8743): http://gcc.gnu.org/bugzilla/show_bug.cgi?id=8743
00038 // "receiving result from __builtin_return_address() beyond stack top causes segfault"
00039 // NOTE that __builtin_return_address should only be used with a non-zero argument for
00040 // debugging purposes. So we use it on our risk.
00041 // A workaround:
00042 // This means the address is out of range.  Note that for the
00043 // toplevel we see a frame pointer with value NULL which clearly is out of range.
00044 // NOTE 2: With gcc 4.1, some optimization levels (e.g., -O, -Os, -O2) have started to imply -fomit-frame-pointer.
00045 // One should use GCC builtin function with -fno-omit-frame-pointer option.
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 // __builtin_return_address(0) yields the address to which the current
00052 // function will return.  __builtin_return_address(1) yields the address to
00053 // which the caller will return, and so on up the stack.
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       // we have a limit on the depth = 35
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       // Get the backtrace
00127       // _trace - array of pointers
00128       // _size - maximal deepness of stack information
00129       // _bUseGNUBuiltinBacktrace - whether to use gcc builtin backtrace or C library one.
00130       // The builtin version is much faster, but very sensitive and in some conditions could fail to return a proper result.
00131       // return value =  min(stack deepness, dsize)
00132 
00133 #if defined(SUPPORTS_MEMSTAT)
00134       if(_bUseGNUBuiltinBacktrace) {
00135          // Initialize the stack end variable.
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 &/*_strInfo*/, TString &_strLib, TString &_strSymbol)
00148    {
00149       // get the name of the function and library
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          // it's our responsibility to free that pointer
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       // demangle symbols
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 }

Generated on Tue Jul 5 14:44:00 2011 for ROOT_528-00b_version by  doxygen 1.5.1