mirror of
https://github.com/QuasarApp/backward-cpp.git
synced 2025-04-29 20:04:32 +00:00
Handle executable being deleted or replaced by directly opening
`/proc/self/exe` rather than file it links to. Fixes issue #146.
This commit is contained in:
parent
79e7738e1f
commit
1ecbdc6491
94
backward.hpp
94
backward.hpp
@ -811,32 +811,58 @@ private:
|
||||
|
||||
#ifdef BACKWARD_SYSTEM_LINUX
|
||||
|
||||
static std::string get_argv0() {
|
||||
std::string argv0;
|
||||
std::getline(std::ifstream("/proc/self/cmdline"), argv0, '\0');
|
||||
return argv0;
|
||||
}
|
||||
|
||||
static std::string read_symlink(std::string const &symlink_path) {
|
||||
std::string path;
|
||||
path.resize(100);
|
||||
|
||||
while (true) {
|
||||
ssize_t len =
|
||||
::readlink(symlink_path.c_str(), &*path.begin(), path.size());
|
||||
if (len < 0) {
|
||||
return "";
|
||||
}
|
||||
if (static_cast<size_t>(len) == path.size()) {
|
||||
path.resize(path.size() * 2);
|
||||
class TraceResolverLinuxBase
|
||||
: public TraceResolverImplBase {
|
||||
public:
|
||||
TraceResolverLinuxBase()
|
||||
: argv0_(get_argv0()), exec_path_(read_symlink("/proc/self/exe")) {
|
||||
}
|
||||
std::string resolve_exec_path(Dl_info &symbol_info) const {
|
||||
// mutates symbol_info.dli_fname to be filename to open and returns filename to display
|
||||
if(symbol_info.dli_fname == argv0_) {
|
||||
// dladdr returns argv[0] in dli_fname for symbols contained in
|
||||
// the main executable, which is not a valid path if the
|
||||
// executable was found by a search of the PATH environment
|
||||
// variable; In that case, we actually open /proc/self/exe, which
|
||||
// is always the actual executable (even if it was deleted/replaced!)
|
||||
// but display the path that /proc/self/exe links to.
|
||||
symbol_info.dli_fname = "/proc/self/exe";
|
||||
return exec_path_;
|
||||
} else {
|
||||
path.resize(static_cast<std::string::size_type>(len));
|
||||
break;
|
||||
return symbol_info.dli_fname;
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::string argv0_;
|
||||
std::string exec_path_;
|
||||
|
||||
return path;
|
||||
}
|
||||
static std::string get_argv0() {
|
||||
std::string argv0;
|
||||
std::getline(std::ifstream("/proc/self/cmdline"), argv0, '\0');
|
||||
return argv0;
|
||||
}
|
||||
|
||||
static std::string read_symlink(std::string const &symlink_path) {
|
||||
std::string path;
|
||||
path.resize(100);
|
||||
|
||||
while (true) {
|
||||
ssize_t len =
|
||||
::readlink(symlink_path.c_str(), &*path.begin(), path.size());
|
||||
if (len < 0) {
|
||||
return "";
|
||||
}
|
||||
if (static_cast<size_t>(len) == path.size()) {
|
||||
path.resize(path.size() * 2);
|
||||
} else {
|
||||
path.resize(static_cast<std::string::size_type>(len));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename STACKTRACE_TAG> class TraceResolverLinuxImpl;
|
||||
|
||||
@ -844,7 +870,7 @@ template <typename STACKTRACE_TAG> class TraceResolverLinuxImpl;
|
||||
|
||||
template <>
|
||||
class TraceResolverLinuxImpl<trace_resolver_tag::backtrace_symbol>
|
||||
: public TraceResolverImplBase {
|
||||
: public TraceResolverLinuxBase {
|
||||
public:
|
||||
template <class ST> void load_stacktrace(ST &st) {
|
||||
using namespace details;
|
||||
@ -887,7 +913,7 @@ private:
|
||||
|
||||
template <>
|
||||
class TraceResolverLinuxImpl<trace_resolver_tag::libbfd>
|
||||
: public TraceResolverImplBase {
|
||||
: public TraceResolverLinuxBase {
|
||||
public:
|
||||
TraceResolverLinuxImpl() : _bfd_loaded(false) {}
|
||||
|
||||
@ -903,12 +929,6 @@ public:
|
||||
return trace; // dat broken trace...
|
||||
}
|
||||
|
||||
std::string tmp;
|
||||
if (symbol_info.dli_fname == get_argv0()) {
|
||||
tmp = read_symlink("/proc/self/exe");
|
||||
symbol_info.dli_fname = tmp.c_str();
|
||||
}
|
||||
|
||||
// Now we get in symbol_info:
|
||||
// .dli_fname:
|
||||
// pathname of the shared object that contains the address.
|
||||
@ -928,7 +948,7 @@ public:
|
||||
return trace;
|
||||
}
|
||||
|
||||
trace.object_filename = symbol_info.dli_fname;
|
||||
trace.object_filename = resolve_exec_path(symbol_info);
|
||||
bfd_fileobject &fobj = load_object_with_bfd(symbol_info.dli_fname);
|
||||
if (!fobj.handle) {
|
||||
return trace; // sad, we couldn't load the object :(
|
||||
@ -1257,7 +1277,7 @@ private:
|
||||
|
||||
template <>
|
||||
class TraceResolverLinuxImpl<trace_resolver_tag::libdw>
|
||||
: public TraceResolverImplBase {
|
||||
: public TraceResolverLinuxBase {
|
||||
public:
|
||||
TraceResolverLinuxImpl() : _dwfl_handle_initialized(false) {}
|
||||
|
||||
@ -1586,7 +1606,7 @@ private:
|
||||
|
||||
template <>
|
||||
class TraceResolverLinuxImpl<trace_resolver_tag::libdwarf>
|
||||
: public TraceResolverImplBase {
|
||||
: public TraceResolverLinuxBase {
|
||||
public:
|
||||
TraceResolverLinuxImpl() : _dwarf_loaded(false) {}
|
||||
|
||||
@ -1613,12 +1633,6 @@ public:
|
||||
return trace; // dat broken trace...
|
||||
}
|
||||
|
||||
std::string tmp;
|
||||
if (symbol_info.dli_fname == get_argv0()) {
|
||||
tmp = read_symlink("/proc/self/exe");
|
||||
symbol_info.dli_fname = tmp.c_str();
|
||||
}
|
||||
|
||||
// Now we get in symbol_info:
|
||||
// .dli_fname:
|
||||
// pathname of the shared object that contains the address.
|
||||
@ -1645,7 +1659,7 @@ public:
|
||||
return trace;
|
||||
}
|
||||
|
||||
trace.object_filename = symbol_info.dli_fname;
|
||||
trace.object_filename = resolve_exec_path(symbol_info);
|
||||
dwarf_fileobject &fobj = load_object_with_dwarf(symbol_info.dli_fname);
|
||||
if (!fobj.dwarf_handle) {
|
||||
return trace; // sad, we couldn't load the object :(
|
||||
|
Loading…
x
Reference in New Issue
Block a user