- make it compilable with gcc 4.0.2
- improvements in error reporting, fixes for actual linux - only include libltdl if necessary
This commit is contained in:
		@@ -8,61 +8,15 @@
 | 
			
		||||
    @copy © Marc Wäckerlin
 | 
			
		||||
    @license LGPL, see file <a href="license.html">COPYING</a>
 | 
			
		||||
 | 
			
		||||
    $Log$
 | 
			
		||||
    Revision 1.14  2005/03/11 23:22:58  marc
 | 
			
		||||
    It's multithreaded now, thanks to a boost mutex
 | 
			
		||||
 | 
			
		||||
    Revision 1.13  2005/02/28 07:28:37  marc
 | 
			
		||||
    typo
 | 
			
		||||
 | 
			
		||||
    Revision 1.12  2005/02/28 07:14:03  marc
 | 
			
		||||
    change in getting section size for SUN Solaris (old bfd.h)
 | 
			
		||||
 | 
			
		||||
    Revision 1.11  2005/02/18 15:48:56  marc
 | 
			
		||||
    Dynamic loading of libbfd, no more dependency on specific libbfd version!
 | 
			
		||||
 | 
			
		||||
    Revision 1.10  2005/01/28 07:51:24  marc
 | 
			
		||||
    improved and corrected trace formatting
 | 
			
		||||
 | 
			
		||||
    Revision 1.9  2005/01/07 00:34:38  marc
 | 
			
		||||
    some changes for solaris
 | 
			
		||||
 | 
			
		||||
    Revision 1.8  2004/12/20 13:22:25  marc
 | 
			
		||||
    mrw string now throws exceptions, catch needed
 | 
			
		||||
 | 
			
		||||
    Revision 1.7  2004/10/13 10:47:15  marc
 | 
			
		||||
    no more need for ldd in StackTrace, read from /proc/self/maps
 | 
			
		||||
 | 
			
		||||
    Revision 1.6  2004/10/11 15:58:51  marc
 | 
			
		||||
    First version with working support for shared libraries!
 | 
			
		||||
 | 
			
		||||
    Revision 1.5  2004/10/07 16:59:12  marc
 | 
			
		||||
    new method createSymtable that takes a list of arguments
 | 
			
		||||
     -> untested!
 | 
			
		||||
 | 
			
		||||
    Revision 1.4  2004/10/07 09:32:45  marc
 | 
			
		||||
    correction in parameter (const&)
 | 
			
		||||
 | 
			
		||||
    Revision 1.3  2004/08/28 16:21:25  marc
 | 
			
		||||
    mrw-c++-0.92 (mrw)
 | 
			
		||||
    - new file: version.cpp
 | 
			
		||||
    - new file header for all sources
 | 
			
		||||
    - work around warning in mrw::auto<T>
 | 
			
		||||
    - possibility to compile without log4cxx
 | 
			
		||||
    - work around bugs in demangle.h and libiberty.h
 | 
			
		||||
    - corrections in documentation
 | 
			
		||||
    - added simple tracing mechanism
 | 
			
		||||
    - more warnings
 | 
			
		||||
    - small corrections in Auto<>::Free and a new test for it
 | 
			
		||||
    - possibility to compile without stack trace
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
#include <mrw/stacktrace.hpp>
 | 
			
		||||
#include <mrw/exec.hpp>
 | 
			
		||||
#include <mrw/string.hpp>
 | 
			
		||||
#include <mrw/list.hpp>
 | 
			
		||||
#include <mrw/stdext.hpp>
 | 
			
		||||
#include <mrw/dynamiclibrary.hpp>
 | 
			
		||||
#ifndef NO_LTDL
 | 
			
		||||
# include <mrw/dynamiclibrary.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
@@ -80,36 +34,28 @@
 | 
			
		||||
#include <execinfo.h>
 | 
			
		||||
#endif
 | 
			
		||||
#include <bfd.h>
 | 
			
		||||
extern "C" {
 | 
			
		||||
 | 
			
		||||
  /// @bug redefined in libiberty.h
 | 
			
		||||
# define HAVE_DECL_BASENAME 1
 | 
			
		||||
  /// @bug redefined in libiberty.h
 | 
			
		||||
# define HAVE_DECL_ASPRINTF 1
 | 
			
		||||
  /// @bug redefined in libiberty.h
 | 
			
		||||
# define HAVE_DECL_VASPRINTF 1
 | 
			
		||||
/** @bug
 | 
			
		||||
 | 
			
		||||
       - in file file: /usr/include/demangle.h
 | 
			
		||||
       - of package:   binutils-2.15.90.0.1.1-31
 | 
			
		||||
 | 
			
		||||
      Someone unfortunately abused the C++ keyword @c typename as
 | 
			
		||||
      variable name to @c cplus_demangle_fill_builtin_type, so I have
 | 
			
		||||
      to work around it.
 | 
			
		||||
  */      
 | 
			
		||||
# define typename anotherNameThatsNotAKeyword
 | 
			
		||||
#   include <demangle.h>
 | 
			
		||||
# undef typename
 | 
			
		||||
//   // copied from demangle.h because of compiler warnings in libliberty.h
 | 
			
		||||
//   // (... throws different exception)
 | 
			
		||||
// #define DMGL_PARAMS	 (1 << 0)	/* Include function args */
 | 
			
		||||
// #define DMGL_ANSI	 (1 << 1)	/* Include const, volatile, etc */
 | 
			
		||||
//   /// @bug demangle.h includes libiberty.h which throws different
 | 
			
		||||
//   ///      exceptions for the same functions than other standard libraries,
 | 
			
		||||
//   ///      so I can't include demangle.h!
 | 
			
		||||
// extern char * cplus_demangle(const char *, int);
 | 
			
		||||
}
 | 
			
		||||
#include <iomanip>
 | 
			
		||||
#if HAVE_DEMANGLE_H
 | 
			
		||||
/* the defines work around wrong definitions in libiberty.h */
 | 
			
		||||
#define HAVE_DECL_BASENAME 1
 | 
			
		||||
#define HAVE_DECL_FFS 1
 | 
			
		||||
#define HAVE_DECL_ASPRINTF 1
 | 
			
		||||
#define HAVE_DECL_VASPRINTF 1
 | 
			
		||||
#define HAVE_DECL_SNPRINTF 1
 | 
			
		||||
#define HAVE_DECL_VSNPRINTF 1
 | 
			
		||||
#define HAVE_DECL_STRVERSCMP 1
 | 
			
		||||
# include <demangle.h>
 | 
			
		||||
#else
 | 
			
		||||
# define DMGL_PARAMS	 (1 << 0)	/* Include function args */
 | 
			
		||||
# define DMGL_ANSI	 (1 << 1)	/* Include const, volatile, etc */
 | 
			
		||||
  extern "C" {
 | 
			
		||||
    extern char * cplus_demangle(const char *, int);
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if (__GNUC__==3 && __GNUC_MINOR__<4 || __GNUC__<3) && _REENTRANT && !_MT
 | 
			
		||||
#define _MT
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace mrw {
 | 
			
		||||
  //----------------------------------------------------------------------------
 | 
			
		||||
@@ -202,9 +148,10 @@ const mrw::StackTrace& mrw::StackTrace::print(std::ostream& os) const
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
mrw::StackTrace::CodePos mrw::StackTrace::translate(void* addr)
 | 
			
		||||
  throw(std::bad_exception) {
 | 
			
		||||
#ifdef _REENTRANT
 | 
			
		||||
#ifdef _MT
 | 
			
		||||
  boost::recursive_mutex::scoped_lock lock(_mutex);
 | 
			
		||||
#endif
 | 
			
		||||
  static const CodePos UNKNOWN(addr, "????", "????", 0);
 | 
			
		||||
  assert(sizeof(bfd_vma)>=sizeof(void*));
 | 
			
		||||
  bfd_vma vma_addr(reinterpret_cast<bfd_vma>(addr));
 | 
			
		||||
  std::map<Translator::key_type, std::string>::iterator
 | 
			
		||||
@@ -212,7 +159,7 @@ mrw::StackTrace::CodePos mrw::StackTrace::translate(void* addr)
 | 
			
		||||
  if (it==_addrs.begin() || (--it)->first > vma_addr ||
 | 
			
		||||
      _dic.find(it->second)==_dic.end() ||
 | 
			
		||||
      _dic[it->second][it->first].first <= vma_addr)
 | 
			
		||||
    return CodePos(addr, "????", "????", 0);
 | 
			
		||||
    return UNKNOWN;
 | 
			
		||||
  static const char* file(0);
 | 
			
		||||
  static const char* function(0);
 | 
			
		||||
  unsigned int line;
 | 
			
		||||
@@ -222,7 +169,7 @@ mrw::StackTrace::CodePos mrw::StackTrace::translate(void* addr)
 | 
			
		||||
       _syms[it->second],
 | 
			
		||||
       vma_addr - it->first,
 | 
			
		||||
       &file, &function, &line))
 | 
			
		||||
    return CodePos(addr, "????", "????", 0);
 | 
			
		||||
    return UNKNOWN;
 | 
			
		||||
  return CodePos(addr, mrw::demangle(_bfd[it->second], function),
 | 
			
		||||
                 file?file:"????", line);
 | 
			
		||||
}
 | 
			
		||||
@@ -230,11 +177,22 @@ mrw::StackTrace::CodePos mrw::StackTrace::translate(void* addr)
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
bool mrw::StackTrace::createSymtable(const std::string& fname, void* offs)
 | 
			
		||||
    throw(std::bad_exception) {
 | 
			
		||||
#ifdef _REENTRANT
 | 
			
		||||
#ifdef _MT
 | 
			
		||||
  boost::recursive_mutex::scoped_lock lock(_mutex);
 | 
			
		||||
#endif
 | 
			
		||||
  if (_dic.find(fname)!=_dic.end()) return true; // already loaded
 | 
			
		||||
  try {
 | 
			
		||||
#if NO_LTDL
 | 
			
		||||
    static bfd*(*bfd_openr)(const char*, const char*) =
 | 
			
		||||
      ::bfd_openr;
 | 
			
		||||
    static bfd_boolean(*bfd_check_format)(bfd*, bfd_format) =
 | 
			
		||||
      ::bfd_check_format;
 | 
			
		||||
    static bfd_boolean(*bfd_check_format_matches)(bfd*, bfd_format, char***) =
 | 
			
		||||
      ::bfd_check_format_matches;
 | 
			
		||||
    static void(*bfd_map_over_sections)
 | 
			
		||||
      (bfd*, void(*)(bfd*, asection*, void*), void*) =
 | 
			
		||||
      ::bfd_map_over_sections;
 | 
			
		||||
#else
 | 
			
		||||
    static DynamicLibrary lib("libbfd");
 | 
			
		||||
    static bfd*(*bfd_openr)(const char*, const char*) =
 | 
			
		||||
      (bfd*(*)(const char*, const char*))lib.symbol("bfd_openr");
 | 
			
		||||
@@ -247,6 +205,7 @@ bool mrw::StackTrace::createSymtable(const std::string& fname, void* offs)
 | 
			
		||||
      (bfd*, void(*)(bfd*, asection*, void*), void*) =
 | 
			
		||||
      (void(*)(bfd*, void(*)(bfd*, asection*, void*), void*))
 | 
			
		||||
      lib.symbol("bfd_map_over_sections");
 | 
			
		||||
#endif
 | 
			
		||||
    if (fname=="") return createSymtable(filename());
 | 
			
		||||
    AutoBfd abfd((*bfd_openr)(fname.c_str(), 0));
 | 
			
		||||
    long memsz(-1);
 | 
			
		||||
@@ -256,19 +215,27 @@ bool mrw::StackTrace::createSymtable(const std::string& fname, void* offs)
 | 
			
		||||
        !(bfd_get_file_flags(const_cast<bfd*>(static_cast<const bfd*>(abfd)))
 | 
			
		||||
          &HAS_SYMS) ||
 | 
			
		||||
        (memsz=bfd_get_symtab_upper_bound
 | 
			
		||||
         (const_cast<bfd*>(static_cast<const bfd*>(abfd))))<0)
 | 
			
		||||
         (const_cast<bfd*>(static_cast<const bfd*>(abfd))))<0) {
 | 
			
		||||
      _error = "cannot map bfd symbols - 'bfd_get_file_flags' failed "
 | 
			
		||||
        "for file: \""+fname+'"';
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    mrw::AutoPtr<asymbol*> syms(new asymbol*[memsz]);
 | 
			
		||||
    if (bfd_canonicalize_symtab(const_cast<bfd*>(static_cast<const bfd*>(abfd)),
 | 
			
		||||
                                syms)<0)
 | 
			
		||||
                                syms)<0) {
 | 
			
		||||
      _error = "cannot map bfd symbols - 'bfd_canonicalize_symtab' failed"
 | 
			
		||||
        "for file: \""+fname+'"';
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    _bfd[fname] = abfd;
 | 
			
		||||
    _syms[fname] = syms;
 | 
			
		||||
    _dic[fname];
 | 
			
		||||
    std::pair<std::string, void*> fileoffs = std::make_pair(fname, offs);
 | 
			
		||||
    (*bfd_map_over_sections)(_bfd[fname], buildSectionMap, &fileoffs);
 | 
			
		||||
    return true;
 | 
			
		||||
  } catch (...) {
 | 
			
		||||
  } catch (const std::exception& x) {
 | 
			
		||||
    _error = std::string("exception received: \"")+x.what()+"\", "
 | 
			
		||||
      "while processing file: \""+fname+'"';
 | 
			
		||||
    return false; // shared library for bfd not found or similar
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -276,7 +243,7 @@ bool mrw::StackTrace::createSymtable(const std::string& fname, void* offs)
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
bool mrw::StackTrace::createSymtable(const mrw::StackTrace::BinFiles& files)
 | 
			
		||||
  throw(std::bad_exception) {
 | 
			
		||||
#ifdef _REENTRANT
 | 
			
		||||
#ifdef _MT
 | 
			
		||||
  boost::recursive_mutex::scoped_lock lock(_mutex);
 | 
			
		||||
#endif
 | 
			
		||||
  bool success(true);
 | 
			
		||||
@@ -290,8 +257,12 @@ bool mrw::StackTrace::createSymtable(const mrw::StackTrace::BinFiles& files)
 | 
			
		||||
//----------------------------------------------------------------------------
 | 
			
		||||
int mrw::StackTrace::bfdClose(bfd* abfd) throw() {
 | 
			
		||||
  try {
 | 
			
		||||
#if NO_LTDL
 | 
			
		||||
    static int(*bfd_close)(bfd*) = ::bfd_close;
 | 
			
		||||
#else
 | 
			
		||||
    static DynamicLibrary lib("");
 | 
			
		||||
    static int(*bfd_close)(bfd*) = (int(*)(bfd*))lib.symbol("bfd_close");
 | 
			
		||||
#endif
 | 
			
		||||
    return (*bfd_close)(abfd);
 | 
			
		||||
  } catch (...) {
 | 
			
		||||
    return -1; // dynamic library loading problems
 | 
			
		||||
@@ -324,7 +295,11 @@ mrw::StackTrace::BinFiles mrw::StackTrace::filename()
 | 
			
		||||
      range.resize(range.find_first_not_of("0123456789abcdefABCDEF"));
 | 
			
		||||
      void* addr(0);
 | 
			
		||||
      range>>addr;
 | 
			
		||||
      if (lib.size() && addr>0) res<<BinFiles::value_type(lib, addr);
 | 
			
		||||
      // added check: no names in brackets: [lib], because there are
 | 
			
		||||
      // [heap], [stack] and [vdso] that cannot be loaded
 | 
			
		||||
      // question: should only files with ending '.so' be loaded?
 | 
			
		||||
      if (lib.size() && lib[0]!='[' && lib[lib.size()-1]!=']' && addr>0)
 | 
			
		||||
        res<<BinFiles::value_type(lib, addr);
 | 
			
		||||
    } catch (...) {} // ignore non matching lines
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
@@ -365,6 +340,7 @@ std::map<mrw::StackTrace::Translator::key_type, std::string>
 | 
			
		||||
  mrw::StackTrace::_addrs;
 | 
			
		||||
std::map<std::string, mrw::StackTrace::AutoBfd> mrw::StackTrace::_bfd;
 | 
			
		||||
std::map<std::string, mrw::AutoPtr<asymbol*> > mrw::StackTrace::_syms;
 | 
			
		||||
#ifdef _REENTRANT
 | 
			
		||||
#ifdef _MT
 | 
			
		||||
boost::recursive_mutex mrw::StackTrace::_mutex;
 | 
			
		||||
#endif
 | 
			
		||||
std::string mrw::StackTrace::_error;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user