Commit e018a713 authored by Kenny Yu's avatar Kenny Yu Committed by Facebook GitHub Bot

symbolizer: Allow Symbolizer to take a path to binary

Summary:
Previously by default, `Symbolizer` would always use the current process's
binary by looking at `/proc/self/exe`. This change allows passing a
different binary name to `Symbolizer` so that we can reuse this library
to look up symbol information of a different process that is executed
from a different binary.

Reviewed By: Gownta

Differential Revision: D33558166

fbshipit-source-id: 12c6ae3aa8c5d88caaef7933edb2c69bc896d75b
parent 515b5b68
......@@ -124,8 +124,13 @@ bool Symbolizer::isAvailable() {
}
Symbolizer::Symbolizer(
ElfCacheBase* cache, LocationInfoMode mode, size_t symbolCacheSize)
: cache_(cache ? cache : defaultElfCache()), mode_(mode) {
ElfCacheBase* cache,
LocationInfoMode mode,
size_t symbolCacheSize,
std::string exePath)
: cache_(cache ? cache : defaultElfCache()),
mode_(mode),
exePath_(std::move(exePath)) {
if (symbolCacheSize > 0) {
symbolCache_.emplace(folly::in_place, symbolCacheSize);
}
......@@ -149,7 +154,7 @@ size_t Symbolizer::symbolize(
char selfPath[PATH_MAX + 8];
ssize_t selfSize;
if ((selfSize = readlink("/proc/self/exe", selfPath, PATH_MAX + 1)) == -1) {
if ((selfSize = readlink(exePath_.c_str(), selfPath, PATH_MAX + 1)) == -1) {
// Something has gone terribly wrong.
return 0;
}
......
......@@ -106,7 +106,8 @@ class Symbolizer {
explicit Symbolizer(
ElfCacheBase* cache,
LocationInfoMode mode = kDefaultLocationInfoMode,
size_t symbolCacheSize = 0);
size_t symbolCacheSize = 0,
std::string exePath = "/proc/self/exe");
/**
* Symbolize given addresses and return the number of @frames filled:
......@@ -150,6 +151,7 @@ class Symbolizer {
private:
ElfCacheBase* const cache_;
const LocationInfoMode mode_;
const std::string exePath_;
// SymbolCache contains mapping between an address and its frames. The first
// frame is the normal function call, and the following are stacked inline
......
......@@ -16,11 +16,13 @@
#include <folly/experimental/symbolizer/Symbolizer.h>
#include <signal.h>
#include <array>
#include <cstdlib>
#include <folly/Demangle.h>
#include <folly/Range.h>
#include <folly/ScopeGuard.h>
#include <folly/String.h>
#include <folly/experimental/symbolizer/ElfCache.h>
#include <folly/experimental/symbolizer/SymbolizedFrame.h>
......@@ -28,6 +30,8 @@
#include <folly/experimental/symbolizer/test/SymbolizerTestUtils.h>
#include <folly/portability/Filesystem.h>
#include <folly/portability/GTest.h>
#include <folly/portability/Unistd.h>
#include <folly/synchronization/Baton.h>
#include <folly/test/TestUtils.h>
#if FOLLY_HAVE_ELF && FOLLY_HAVE_DWARF
......@@ -66,6 +70,47 @@ TEST(Symbolizer, Single) {
EXPECT_EQ("SymbolizerTest.cpp", basename.str());
}
TEST(Symbolizer, SingleCustomExePath) {
SKIP_IF(!Symbolizer::isAvailable());
auto pid = ::fork();
if (pid == -1) {
SKIP("fork failed");
} else if (pid == 0) {
// child process waits forever, parent will kill
folly::Baton<> baton;
baton.wait();
} else {
// parent process
// kill the child process on cleanup
auto guard = folly::makeGuard([pid] {
auto error = ::kill(pid, SIGKILL);
ASSERT_EQ(0, error);
});
// path to executable for child binary
auto exePath = folly::to<std::string>("/proc/", pid, "/exe");
// It looks like we could only use .debug_aranges with "-g2", with
// "-g1 -gdwarf-aranges", the code has to fallback to line-tables to
// get the file name.
Symbolizer symbolizer(
nullptr, LocationInfoMode::FULL, 0, std::move(exePath));
SymbolizedFrame a;
ASSERT_TRUE(symbolizer.symbolize(reinterpret_cast<uintptr_t>(foo), a));
EXPECT_EQ("folly::symbolizer::test::foo()", folly::demangle(a.name));
auto path = a.location.file.toString();
folly::StringPiece basename(path);
auto pos = basename.rfind('/');
if (pos != folly::StringPiece::npos) {
basename.advance(pos + 1);
}
EXPECT_EQ("SymbolizerTest.cpp", basename.str());
}
}
// Test stack frames...
class ElfCacheTest : public testing::Test {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment