#include <folly/debugging/symbolizer/ElfCache.h>
#include <signal.h>
#include <folly/ScopeGuard.h>
#include <folly/portability/Config.h>
#include <folly/portability/SysMman.h>
#if FOLLY_HAVE_ELF
namespace folly {
namespace symbolizer {
SignalSafeElfCache::Path::Path(
char const* const data,
std::size_t const size,
reentrant_allocator<char> const& alloc) noexcept
: data_{alloc} {
data_.reserve(size + 1);
data_.insert(data_.end(), data, data + size);
data_.insert(data_.end(), '\0');
}
std::shared_ptr<ElfFile> SignalSafeElfCache::getFile(StringPiece p) {
struct cmp {
bool operator()(Entry const& a, StringPiece b) const noexcept {
return a.path < b;
}
bool operator()(StringPiece a, Entry const& b) const noexcept {
return a < b.path;
}
};
sigset_t newsigs;
sigfillset(&newsigs);
sigset_t oldsigs;
sigemptyset(&oldsigs);
sigprocmask(SIG_SETMASK, &newsigs, &oldsigs);
SCOPE_EXIT {
sigprocmask(SIG_SETMASK, &oldsigs, nullptr);
};
if (!state_) {
state_.emplace();
}
auto pos = state_->map.find(p, cmp{});
if (pos == state_->map.end()) {
state_->list.emplace_front(p, state_->alloc);
pos = state_->map.insert(state_->list.front()).first;
}
if (!pos->init) {
int r = pos->file->openAndFollow(pos->path.c_str());
pos->init = r == ElfFile::kSuccess;
}
if (!pos->init) {
return nullptr;
}
return pos->file;
}
std::shared_ptr<ElfFile> ElfCache::getFile(StringPiece p) {
std::lock_guard<std::mutex> lock(mutex_);
auto pos = files_.find(p);
if (pos != files_.end()) {
auto& entry = pos->second;
return filePtr(entry);
}
auto entry = std::make_shared<Entry>();
entry->path = p.str();
auto& path = entry->path;
int r = entry->file.openAndFollow(path.c_str());
if (r != ElfFile::kSuccess) {
return nullptr;
}
pos = files_.emplace(path, std::move(entry)).first;
return filePtr(pos->second);
}
std::shared_ptr<ElfFile> ElfCache::filePtr(const std::shared_ptr<Entry>& e) {
return std::shared_ptr<ElfFile>(e, &e->file);
}
}
}
#endif