diff --git a/mrw/stacktrace.cpp b/mrw/stacktrace.cpp index 24f1979..493ed4a 100644 --- a/mrw/stacktrace.cpp +++ b/mrw/stacktrace.cpp @@ -8,61 +8,15 @@ @copy © Marc Wäckerlin @license LGPL, see file COPYING - $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 - - 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 #include #include #include #include -#include +#ifndef NO_LTDL +# include +#endif #include #include #include @@ -80,36 +34,28 @@ #include #endif #include -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 -# 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 +#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 +#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(addr)); std::map::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(static_cast(abfd))) &HAS_SYMS) || (memsz=bfd_get_symtab_upper_bound - (const_cast(static_cast(abfd))))<0) + (const_cast(static_cast(abfd))))<0) { + _error = "cannot map bfd symbols - 'bfd_get_file_flags' failed " + "for file: \""+fname+'"'; return false; + } mrw::AutoPtr syms(new asymbol*[memsz]); if (bfd_canonicalize_symtab(const_cast(static_cast(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 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<0) + res< mrw::StackTrace::_addrs; std::map mrw::StackTrace::_bfd; std::map > mrw::StackTrace::_syms; -#ifdef _REENTRANT +#ifdef _MT boost::recursive_mutex mrw::StackTrace::_mutex; #endif +std::string mrw::StackTrace::_error;