MCPcopy Create free account
hub / github.com/bombela/backward-cpp / TraceResolverLinuxBase

Class TraceResolverLinuxBase

backward.hpp:1252–1310  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1250#ifdef BACKWARD_SYSTEM_LINUX
1251
1252class TraceResolverLinuxBase : public TraceResolverImplBase {
1253public:
1254 TraceResolverLinuxBase()
1255 : argv0_(get_argv0()), exec_path_(read_symlink("/proc/self/exe")) {}
1256 std::string resolve_exec_path(Dl_info &symbol_info) const {
1257 // mutates symbol_info.dli_fname to be filename to open and returns filename
1258 // to display
1259 if (symbol_info.dli_fname == argv0_) {
1260 // dladdr returns argv[0] in dli_fname for symbols contained in
1261 // the main executable, which is not a valid path if the
1262 // executable was found by a search of the PATH environment
1263 // variable; In that case, we actually open /proc/self/exe, which
1264 // is always the actual executable (even if it was deleted/replaced!)
1265 // but display the path that /proc/self/exe links to.
1266 // However, this right away reduces probability of successful symbol
1267 // resolution, because libbfd may try to find *.debug files in the
1268 // same dir, in case symbols are stripped. As a result, it may try
1269 // to find a file /proc/self/<exe_name>.debug, which obviously does
1270 // not exist. /proc/self/exe is a last resort. First load attempt
1271 // should go for the original executable file path.
1272 symbol_info.dli_fname = "/proc/self/exe";
1273 return exec_path_;
1274 } else {
1275 return symbol_info.dli_fname;
1276 }
1277 }
1278
1279private:
1280 std::string argv0_;
1281 std::string exec_path_;
1282
1283 static std::string get_argv0() {
1284 std::string argv0;
1285 std::ifstream ifs("/proc/self/cmdline");
1286 std::getline(ifs, argv0, '\0');
1287 return argv0;
1288 }
1289
1290 static std::string read_symlink(std::string const &symlink_path) {
1291 std::string path;
1292 path.resize(100);
1293
1294 while (true) {
1295 ssize_t len =
1296 ::readlink(symlink_path.c_str(), &*path.begin(), path.size());
1297 if (len < 0) {
1298 return "";
1299 }
1300 if (static_cast<size_t>(len) == path.size()) {
1301 path.resize(path.size() * 2);
1302 } else {
1303 path.resize(static_cast<std::string::size_type>(len));
1304 break;
1305 }
1306 }
1307
1308 return path;
1309 }

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected