no more need for ldd in StackTrace, read from /proc/self/maps

master
Marc Wäckerlin 20 years ago
parent 6bc3bcc755
commit 8d5c98e8c0
  1. 40
      mrw/stacktrace.cpp
  2. 61
      mrw/stacktrace.hpp

@ -9,6 +9,9 @@
@license LGPL, see file <a href="license.html">COPYING</a> @license LGPL, see file <a href="license.html">COPYING</a>
$Log$ $Log$
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 Revision 1.6 2004/10/11 15:58:51 marc
First version with working support for shared libraries! First version with working support for shared libraries!
@ -45,6 +48,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <assert.h> #include <assert.h>
#include <math.h> #include <math.h>
#include <fstream>
#include <algorithm> #include <algorithm>
#include <list> #include <list>
#if defined(__solaris__) #if defined(__solaris__)
@ -237,10 +241,10 @@ bool mrw::StackTrace::createSymtable(const mrw::StackTrace::BinFiles& files)
mrw::StackTrace::BinFiles mrw::StackTrace::filename() mrw::StackTrace::BinFiles mrw::StackTrace::filename()
throw(std::bad_exception) { throw(std::bad_exception) {
mrw::StackTrace::BinFiles res; mrw::StackTrace::BinFiles res;
std::string s;
s<<"/proc/"<<getpid();
# if defined(__solaris__) # if defined(__solaris__)
{ {
std::string s;
s<<"/proc/"<<getpid();
AutoFile fd(open(s.str(), O_RDONLY)); AutoFile fd(open(s.str(), O_RDONLY));
prpsinfo_t status; prpsinfo_t status;
if (fd==-1 || ioctl(fd, PIOCPSINFO, &status)==-1) return res; if (fd==-1 || ioctl(fd, PIOCPSINFO, &status)==-1) return res;
@ -249,26 +253,18 @@ mrw::StackTrace::BinFiles mrw::StackTrace::filename()
} }
# elif defined(__linux__) # elif defined(__linux__)
{ {
res<<BinFiles::value_type(s<<"/exe", 0); res<<BinFiles::value_type("/proc/self/exe", 0);
try { std::ifstream is("/proc/self/maps");
mrw::Exec ldd = (mrw::Cmd("/usr/bin/ldd"), s).execute(); std::string s;
for (std::string lddres(ldd.result()); std::string range, perm, x1, x2, size, lib;
lddres.size(); while (getline(is, s)) {
lddres.erase(0, min(lddres.find('\n')+1, std::string::npos))) { range = perm = x1 = x2 = size = lib = "????";
std::string line(lddres.substr(0, lddres.find('\n'))); s>>range>>perm>>x1>>x2>>size>>lib;
std::string::size_type pos = line.find(" => "); range.resize(range.find_first_not_of("0123456789abcdefABCDEF"));
if (pos<std::string::npos) { void* addr(0);
pos += 4; range>>addr;
std::string file = line.substr(pos, (pos=line.find(' ', pos)-pos)); if (lib.size() && addr>0) res<<BinFiles::value_type(lib, addr);
std::stringstream addr;
addr<<line.substr(++(pos=line.find('(', pos)),
line.find(')', pos)-pos);
void* address(0);
addr>>address;
if (file.size()) res<<BinFiles::value_type(file, address);
}
} }
} catch (mrw::ExecutionFailedExc&) {}
return res; return res;
} }
# else # else
@ -276,7 +272,7 @@ mrw::StackTrace::BinFiles mrw::StackTrace::filename()
# warning "Don't know how to get executable file name in your system!" # warning "Don't know how to get executable file name in your system!"
# warning "Impossible to get function names in stack trace!" # warning "Impossible to get function names in stack trace!"
# warning "Give the path to the executable to StackTrace::createSymtable!" # warning "Give the path to the executable to StackTrace::createSymtable!"
abort(); return res; // empty
} }
# endif # endif
} }

@ -9,6 +9,9 @@
@license LGPL, see file <a href="license.html">COPYING</a> @license LGPL, see file <a href="license.html">COPYING</a>
$Log$ $Log$
Revision 1.9 2004/10/13 10:47:15 marc
no more need for ldd in StackTrace, read from /proc/self/maps
Revision 1.8 2004/10/11 16:49:32 marc Revision 1.8 2004/10/11 16:49:32 marc
Better comment for new shared library feature Better comment for new shared library feature
@ -90,7 +93,6 @@ namespace mrw {
- either a GNU glibc bases system (LINUX), or the GNU gcc compiler - either a GNU glibc bases system (LINUX), or the GNU gcc compiler
- a system with ELF binaries (LINUX, Solaris, ...) - a system with ELF binaries (LINUX, Solaris, ...)
- debug information, compile option @c -g - debug information, compile option @c -g
- it must be linked with @c -libery and @c -lbfd
*/ */
//@{ //@{
@ -108,10 +110,8 @@ namespace mrw {
once, before evaluating the first stack trace.Best place is the once, before evaluating the first stack trace.Best place is the
first line of the @c main function. first line of the @c main function.
@note This class requires libbfd an libiberty. Debug information @note Debug information is required for compiling. You nee the
is required for compiling. You nee the compile option @c -g, or compile option @c -g, or even better @c -ggdb3.
even better @c -ggdb3. To link, you need @c -lmrw, @c -lbfd and
@c -liberty.
@note The stack trace is known to work perfectly on Linux and @note The stack trace is known to work perfectly on Linux and
Solaris both with GNU gcc compiler. But it should work with the Solaris both with GNU gcc compiler. But it should work with the
@ -145,17 +145,43 @@ namespace mrw {
Unfortunately it is not possible to extract the source file name Unfortunately it is not possible to extract the source file name
and line number information if the executable was not compiled and line number information if the executable was not compiled
with debug option @c -g. But what's worse, it is not possible to with debug option @c -g.
ger symbolic information from libraries linked to the
executable. Perhaps it could be possible, if I'd add a
possibility to read and evaluate these libraries, but that's for
a future release. (Now, 10/08/2004, I am working on it)
@todo Add support to read debugging information from libraries
that are linked to the executable. (soon)
@todo Add support for alternative symbol evaluation using @c @todo Add support for alternative symbol evaluation using @c
backtrace_symbols. backtrace_symbols.
@bug File and line is wrong where the exception is thrown. On
Address [0x4007830b] file and line is wrong, the file should be
/privat/home/marc/pro/mrw-c++/mrw/exception.cpp. File and line
are always wrong at the line where the exception is
instanciated. Why?!? (Could it be, because there is a string
created inline? The trace always shows basic_string.h.)
@code
UNEXPECTED EXCEPTION: ----------------------------
---------- Reason:
mrw::Exec: command execution failed
failed command was: "/bin/false"
error was: "execution failed"
---------- Stack:
1[0x8049b71] ../sysdeps/i386/elf/start.S:105 _start
[0x4022f92b] ????:0 __libc_start_main
[0x8049c96] /usr/include/g++/bits/basic_string.h:249 main
[0x40054668] ????:0 CppUnit::TextUi::TestRunner::run(std::string, bool, bool, bool)
[0x40054747] ????:0 CppUnit::TextUi::TestRunner::runTestByName(std::string, bool)
[0x400543ec] ????:0 CppUnit::TextUi::TestRunner::runTest(CppUnit::Test*, bool)
[0x4005525b] ????:0 CppUnit::TestSuite::run(CppUnit::TestResult*)
[0x4005525b] ????:0 CppUnit::TestSuite::run(CppUnit::TestResult*)
[0x4005525b] ????:0 CppUnit::TestSuite::run(CppUnit::TestResult*)
[0x4004aa06] ????:0 CppUnit::TestCase::run(CppUnit::TestResult*)
[0x804b164] /usr/include/cppunit/TestCaller.h:166 CppUnit::TestCaller<ExecTest, std::bad_exception>::runTest()
[0x804b299] /usr/include/g++/bits/stl_alloc.h:652 ExecTest::unexpectedExc()
[0x40078bda] /privat/home/marc/pro/mrw-c++/mrw/exec.cpp:77 mrw::Cmd::execute(bool) const
[0x4007830b] /usr/include/g++/bits/basic_string.h:249 mrw::Exec::execute(bool)
[0x40077941] /privat/home/marc/pro/mrw-c++/mrw/exec.cpp:38 mrw::ExecutionFailedExc::ExecutionFailedExc(std::string const&, std::string const&)
[0x400769d4] /privat/home/marc/pro/mrw-c++/mrw/exception.cpp:41 mrw::exception::exception()
[0x4007cbc5] /privat/home/marc/pro/mrw-c++/mrw/stacktrace.cpp:118 mrw::StackTrace::StackTrace()
-------------------------------------------------
@endcode
*/ */
class StackTrace { class StackTrace {
public: public:
@ -193,11 +219,10 @@ namespace mrw {
/** @brief read the symbol table from the executable file or a /** @brief read the symbol table from the executable file or a
shared library shared library
On Solaris and Linux, the name of the executable is On Solaris and Linux, the executable is automatically
automatically detected through the @c /dev/proc file detected through the @c /proc file system. Only on Linux the
system. Only on Linux the shared libraries are detected shared libraries are detected through @c /proc/self/maps. So
through a call to @c ldd. So you may leave the parameter you may leave the parameter empty on these systems.
empty on these systems.
@param fname The file name of the executable or a shared @param fname The file name of the executable or a shared
library. On Linux and Solaris, this can be evaluated library. On Linux and Solaris, this can be evaluated

Loading…
Cancel
Save