| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 | 
							- /*=========================================================================
 
-   Library:   CTK
 
-   Copyright (c) German Cancer Research Center,
 
-     Division of Medical and Biological Informatics
 
-   Licensed under the Apache License, Version 2.0 (the "License");
 
-   you may not use this file except in compliance with the License.
 
-   You may obtain a copy of the License at
 
-       http://www.apache.org/licenses/LICENSE-2.0.txt
 
-   Unless required by applicable law or agreed to in writing, software
 
-   distributed under the License is distributed on an "AS IS" BASIS,
 
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
-   See the License for the specific language governing permissions and
 
-   limitations under the License.
 
- =========================================================================*/
 
- //
 
- // Code taken from http://thread.gmane.org/gmane.comp.lib.boost.devel/209982
 
- // and modified for CTK.
 
- //
 
- // Original Copyright (c) 2010 Artyom Beilis (Tonkikh)
 
- //
 
- // Distributed under the Boost Software License, Version 1.0.
 
- // (See http://www.boost.org/LICENSE_1_0.txt)
 
- //
 
- #include "ctkBackTrace.h"
 
- #include <QList>
 
- #include <vector>
 
- #if defined(__linux) || defined(__APPLE__) || defined(__sun)
 
- #define CTK_HAVE_EXECINFO
 
- #define CTK_HAVE_DLADDR
 
- #endif
 
- #if defined(__GNUC__)
 
- #define CTK_HAVE_ABI_CXA_DEMANGLE
 
- #endif
 
- #ifdef CTK_HAVE_EXECINFO
 
- #include <execinfo.h>
 
- #endif
 
- #ifdef CTK_HAVE_ABI_CXA_DEMANGLE
 
- #include <cxxabi.h>
 
- #endif
 
- #ifdef CTK_HAVE_DLADDR
 
- #include <dlfcn.h>
 
- #endif
 
- #include <stdlib.h>
 
- #include <sstream>
 
- #if defined(Q_CC_MSVC)
 
- #include <windows.h>
 
- #include <stdlib.h>
 
- #include <dbghelp.h>
 
- #endif
 
- // --------------------------------------------------------------------------
 
- size_t const ctkBackTrace::DefaultStackSize = 32;
 
- // --------------------------------------------------------------------------
 
- struct ctkBackTracePrivate
 
- {
 
-   std::vector<void *> Frames;
 
-   int trace(void** addresses, int size) const;
 
-   std::string getSymbol(void* address) const;
 
- };
 
- // --------------------------------------------------------------------------
 
- ctkBackTrace::ctkBackTrace(const ctkBackTrace& other)
 
-   : d(new ctkBackTracePrivate(*other.d.data()))
 
- {
 
- }
 
- ctkBackTrace::ctkBackTrace(size_t framesNumber)
 
-   : d(new ctkBackTracePrivate)
 
- {
 
-   if(framesNumber == 0)
 
-     return;
 
-   d->Frames.resize(framesNumber, 0);
 
-   int size = d->trace(&d->Frames.front(), framesNumber);
 
-   d->Frames.resize(size);
 
- }
 
- // --------------------------------------------------------------------------
 
- ctkBackTrace::~ctkBackTrace() throw()
 
- {
 
- }
 
- // --------------------------------------------------------------------------
 
- size_t ctkBackTrace::stackSize() const
 
- {
 
-   return d->Frames.size();
 
- }
 
- // --------------------------------------------------------------------------
 
- void* ctkBackTrace::returnAddress(unsigned frameNumber) const
 
- {
 
-   if(frameNumber < stackSize())
 
-     return d->Frames[frameNumber];
 
-   return 0;
 
- }
 
- // --------------------------------------------------------------------------
 
- QString ctkBackTrace::stackFrame(unsigned frameNumber) const
 
- {
 
-   if(frameNumber < d->Frames.size())
 
-     return QString::fromStdString(d->getSymbol(d->Frames[frameNumber]));
 
-   return QString();
 
- }
 
- // --------------------------------------------------------------------------
 
- QList<QString> ctkBackTrace::stackTrace() const
 
- {
 
-   QList<QString> trace;
 
-   if(d->Frames.empty())
 
-     return trace;
 
-   for (std::size_t i = 0; i < d->Frames.size(); ++i)
 
-   {
 
-     std::string s = d->getSymbol(d->Frames[i]);
 
-     if (!s.empty())
 
-     {
 
-       trace.push_back(QString::fromStdString(s));
 
-     }
 
-   }
 
-   return trace;
 
-   //std::ostringstream res;
 
-   //d->writeSymbols(&d->Frames.front(), d->Frames.size(), res, framePrefix.toStdString());
 
-   //return QString::fromStdString(res.str());
 
- }
 
- #if defined(CTK_HAVE_EXECINFO)
 
- // --------------------------------------------------------------------------
 
- int ctkBackTracePrivate::trace(void** array, int n) const
 
- {
 
-   return :: backtrace(array,n);
 
- }
 
- #elif defined(Q_CC_MSVC)
 
- // --------------------------------------------------------------------------
 
- int ctkBackTracePrivate::trace(void** array, int n) const
 
- {
 
-   if(n>=63)
 
-     n=62;
 
-   return RtlCaptureStackBackTrace(0, n, array, 0);
 
- }
 
- #else
 
- // --------------------------------------------------------------------------
 
- int ctkBackTracePrivate::trace(void** /*array*/, int /*n*/) const
 
- {
 
-   return 0;
 
- }
 
- #endif
 
- #if defined(CTK_HAVE_DLADDR) && defined(CTK_HAVE_ABI_CXA_DEMANGLE)
 
- // --------------------------------------------------------------------------
 
- std::string ctkBackTracePrivate::getSymbol(void* ptr) const
 
- {
 
-   if(!ptr)
 
-     return std::string();
 
-   std::ostringstream res;
 
-   res.imbue(std::locale::classic());
 
-   res << ptr << ": ";
 
-   Dl_info info = {0,0,0,0};
 
-   if(dladdr(ptr,&info) == 0)
 
-   {
 
-     res << "???";
 
-   }
 
-   else
 
-   {
 
-     if(info.dli_sname)
 
-     {
 
-       int status = 0;
 
-       char *demangled = abi::__cxa_demangle(info.dli_sname, 0, 0, &status);
 
-       if(demangled)
 
-       {
 
-         res << demangled;
 
-         free(demangled);
 
-       }
 
-       else
 
-       {
 
-         res << info.dli_sname;
 
-       }
 
-     }
 
-     else
 
-     {
 
-       res << "???";
 
-     }
 
-     unsigned offset = reinterpret_cast<char*>(ptr) - reinterpret_cast<char*>(info.dli_saddr);
 
-     res << std::hex <<" + 0x" << offset ;
 
-     if(info.dli_fname)
 
-       res << " in " << info.dli_fname;
 
-   }
 
-   return res.str();
 
- }
 
- #elif defined(CTK_HAVE_EXECINFO)
 
- // --------------------------------------------------------------------------
 
- std::string ctkBackTracePrivate::getSymbol(void *address) const
 
- {
 
-   char ** ptr = backtrace_symbols(&address, 1);
 
-   try
 
-   {
 
-     if(ptr == 0)
 
-       return std::string();
 
-     std::string res = ptr[0];
 
-     free(ptr);
 
-     ptr = 0;
 
-     return res;
 
-   }
 
-   catch(...)
 
-   {
 
-     free(ptr);
 
-     throw;
 
-   }
 
- }
 
- #elif defined(Q_CC_MSVC)
 
- // --------------------------------------------------------------------------
 
- namespace {
 
- HANDLE hProcess = 0;
 
- bool syms_ready = false;
 
- }
 
- // --------------------------------------------------------------------------
 
- namespace ctk {
 
- bool DebugSymInitialize()
 
- {
 
-   if(hProcess == 0)
 
-   {
 
-     hProcess = GetCurrentProcess();
 
-     SymSetOptions(SYMOPT_DEFERRED_LOADS);
 
-     if (SymInitialize(hProcess, NULL, TRUE))
 
-     {
 
-       syms_ready = true;
 
-     }
 
-   }
 
-   return syms_ready;
 
- }
 
- }
 
- // --------------------------------------------------------------------------
 
- std::string ctkBackTracePrivate::getSymbol(void* ptr) const
 
- {
 
-   if(ptr==0)
 
-     return std::string();
 
-   ctk::DebugSymInitialize();
 
-   std::ostringstream ss;
 
-   ss.imbue(std::locale::classic());
 
-   ss << ptr;
 
-   if(syms_ready)
 
-   {
 
-     DWORD64  dwDisplacement = 0;
 
-     DWORD64  dwAddress = (DWORD64)ptr;
 
-     std::vector<char> buffer(sizeof(SYMBOL_INFO) + MAX_SYM_NAME);
 
-     PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)&buffer.front();
 
-     pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
 
-     pSymbol->MaxNameLen = MAX_SYM_NAME;
 
-     if (SymFromAddr(hProcess, dwAddress, &dwDisplacement, pSymbol))
 
-     {
 
-       ss <<": " << pSymbol->Name << std::hex << " + 0x" << dwDisplacement;
 
-     }
 
-     else
 
-     {
 
-       ss << ": ???";
 
-     }
 
-     std::vector<char> moduleBuffer(sizeof(IMAGEHLP_MODULE64));
 
-     PIMAGEHLP_MODULE64 pModuleInfo = (PIMAGEHLP_MODULE64)&moduleBuffer.front();
 
-     pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
 
-     if (SymGetModuleInfo64(hProcess, pSymbol->ModBase, pModuleInfo))
 
-     {
 
-       ss << " in " << pModuleInfo->LoadedImageName;
 
-     }
 
-   }
 
-   return ss.str();
 
- }
 
- #else
 
- // --------------------------------------------------------------------------
 
- std::string ctkBackTracePrivate::getSymbol(void* ptr) const
 
- {
 
-   if(!ptr)
 
-     return std::string();
 
-   std::ostringstream res;
 
-   res.imbue(std::locale::classic());
 
-   res << ptr;
 
-   return res.str();
 
- }
 
- #endif
 
 
  |