- make it compilable with gcc 4.0.2

- improvements in error reporting, fixes for actual linux
 - only include libltdl if necessary
master
Marc Wäckerlin 19 years ago
parent a36d124fcd
commit 853f93cf6a
  1. 152
      mrw/stacktrace.cpp

@ -8,61 +8,15 @@
@copy © Marc Wäckerlin @copy © Marc Wäckerlin
@license LGPL, see file <a href="license.html">COPYING</a> @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/stacktrace.hpp>
#include <mrw/exec.hpp> #include <mrw/exec.hpp>
#include <mrw/string.hpp> #include <mrw/string.hpp>
#include <mrw/list.hpp> #include <mrw/list.hpp>
#include <mrw/stdext.hpp> #include <mrw/stdext.hpp>
#include <mrw/dynamiclibrary.hpp> #ifndef NO_LTDL
# include <mrw/dynamiclibrary.hpp>
#endif
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -80,36 +34,28 @@
#include <execinfo.h> #include <execinfo.h>
#endif #endif
#include <bfd.h> #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> #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 { namespace mrw {
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -202,9 +148,10 @@ const mrw::StackTrace& mrw::StackTrace::print(std::ostream& os) const
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
mrw::StackTrace::CodePos mrw::StackTrace::translate(void* addr) mrw::StackTrace::CodePos mrw::StackTrace::translate(void* addr)
throw(std::bad_exception) { throw(std::bad_exception) {
#ifdef _REENTRANT #ifdef _MT
boost::recursive_mutex::scoped_lock lock(_mutex); boost::recursive_mutex::scoped_lock lock(_mutex);
#endif #endif
static const CodePos UNKNOWN(addr, "????", "????", 0);
assert(sizeof(bfd_vma)>=sizeof(void*)); assert(sizeof(bfd_vma)>=sizeof(void*));
bfd_vma vma_addr(reinterpret_cast<bfd_vma>(addr)); bfd_vma vma_addr(reinterpret_cast<bfd_vma>(addr));
std::map<Translator::key_type, std::string>::iterator 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 || if (it==_addrs.begin() || (--it)->first > vma_addr ||
_dic.find(it->second)==_dic.end() || _dic.find(it->second)==_dic.end() ||
_dic[it->second][it->first].first <= vma_addr) _dic[it->second][it->first].first <= vma_addr)
return CodePos(addr, "????", "????", 0); return UNKNOWN;
static const char* file(0); static const char* file(0);
static const char* function(0); static const char* function(0);
unsigned int line; unsigned int line;
@ -222,7 +169,7 @@ mrw::StackTrace::CodePos mrw::StackTrace::translate(void* addr)
_syms[it->second], _syms[it->second],
vma_addr - it->first, vma_addr - it->first,
&file, &function, &line)) &file, &function, &line))
return CodePos(addr, "????", "????", 0); return UNKNOWN;
return CodePos(addr, mrw::demangle(_bfd[it->second], function), return CodePos(addr, mrw::demangle(_bfd[it->second], function),
file?file:"????", line); 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) bool mrw::StackTrace::createSymtable(const std::string& fname, void* offs)
throw(std::bad_exception) { throw(std::bad_exception) {
#ifdef _REENTRANT #ifdef _MT
boost::recursive_mutex::scoped_lock lock(_mutex); boost::recursive_mutex::scoped_lock lock(_mutex);
#endif #endif
if (_dic.find(fname)!=_dic.end()) return true; // already loaded if (_dic.find(fname)!=_dic.end()) return true; // already loaded
try { 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 DynamicLibrary lib("libbfd");
static bfd*(*bfd_openr)(const char*, const char*) = static bfd*(*bfd_openr)(const char*, const char*) =
(bfd*(*)(const char*, const char*))lib.symbol("bfd_openr"); (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*) = (bfd*, void(*)(bfd*, asection*, void*), void*) =
(void(*)(bfd*, void(*)(bfd*, asection*, void*), void*)) (void(*)(bfd*, void(*)(bfd*, asection*, void*), void*))
lib.symbol("bfd_map_over_sections"); lib.symbol("bfd_map_over_sections");
#endif
if (fname=="") return createSymtable(filename()); if (fname=="") return createSymtable(filename());
AutoBfd abfd((*bfd_openr)(fname.c_str(), 0)); AutoBfd abfd((*bfd_openr)(fname.c_str(), 0));
long memsz(-1); 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))) !(bfd_get_file_flags(const_cast<bfd*>(static_cast<const bfd*>(abfd)))
&HAS_SYMS) || &HAS_SYMS) ||
(memsz=bfd_get_symtab_upper_bound (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; return false;
}
mrw::AutoPtr<asymbol*> syms(new asymbol*[memsz]); mrw::AutoPtr<asymbol*> syms(new asymbol*[memsz]);
if (bfd_canonicalize_symtab(const_cast<bfd*>(static_cast<const bfd*>(abfd)), 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; return false;
}
_bfd[fname] = abfd; _bfd[fname] = abfd;
_syms[fname] = syms; _syms[fname] = syms;
_dic[fname]; _dic[fname];
std::pair<std::string, void*> fileoffs = std::make_pair(fname, offs); std::pair<std::string, void*> fileoffs = std::make_pair(fname, offs);
(*bfd_map_over_sections)(_bfd[fname], buildSectionMap, &fileoffs); (*bfd_map_over_sections)(_bfd[fname], buildSectionMap, &fileoffs);
return true; 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 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) bool mrw::StackTrace::createSymtable(const mrw::StackTrace::BinFiles& files)
throw(std::bad_exception) { throw(std::bad_exception) {
#ifdef _REENTRANT #ifdef _MT
boost::recursive_mutex::scoped_lock lock(_mutex); boost::recursive_mutex::scoped_lock lock(_mutex);
#endif #endif
bool success(true); bool success(true);
@ -290,8 +257,12 @@ bool mrw::StackTrace::createSymtable(const mrw::StackTrace::BinFiles& files)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
int mrw::StackTrace::bfdClose(bfd* abfd) throw() { int mrw::StackTrace::bfdClose(bfd* abfd) throw() {
try { try {
#if NO_LTDL
static int(*bfd_close)(bfd*) = ::bfd_close;
#else
static DynamicLibrary lib(""); static DynamicLibrary lib("");
static int(*bfd_close)(bfd*) = (int(*)(bfd*))lib.symbol("bfd_close"); static int(*bfd_close)(bfd*) = (int(*)(bfd*))lib.symbol("bfd_close");
#endif
return (*bfd_close)(abfd); return (*bfd_close)(abfd);
} catch (...) { } catch (...) {
return -1; // dynamic library loading problems return -1; // dynamic library loading problems
@ -324,7 +295,11 @@ mrw::StackTrace::BinFiles mrw::StackTrace::filename()
range.resize(range.find_first_not_of("0123456789abcdefABCDEF")); range.resize(range.find_first_not_of("0123456789abcdefABCDEF"));
void* addr(0); void* addr(0);
range>>addr; 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 } catch (...) {} // ignore non matching lines
return res; return res;
} }
@ -365,6 +340,7 @@ std::map<mrw::StackTrace::Translator::key_type, std::string>
mrw::StackTrace::_addrs; mrw::StackTrace::_addrs;
std::map<std::string, mrw::StackTrace::AutoBfd> mrw::StackTrace::_bfd; std::map<std::string, mrw::StackTrace::AutoBfd> mrw::StackTrace::_bfd;
std::map<std::string, mrw::AutoPtr<asymbol*> > mrw::StackTrace::_syms; std::map<std::string, mrw::AutoPtr<asymbol*> > mrw::StackTrace::_syms;
#ifdef _REENTRANT #ifdef _MT
boost::recursive_mutex mrw::StackTrace::_mutex; boost::recursive_mutex mrw::StackTrace::_mutex;
#endif #endif
std::string mrw::StackTrace::_error;

Loading…
Cancel
Save