#pragma once
#include <variant>
#include <folly/Function.h>
#include <folly/Range.h>
#include <folly/experimental/symbolizer/Elf.h>
#include <folly/experimental/symbolizer/ElfCache.h>
#if FOLLY_HAVE_DWARF && FOLLY_HAVE_ELF
#include <dwarf.h>
namespace folly {
namespace symbolizer {
const uint32_t kMaxInlineLocationInfoPerFrame = 20;
const uint32_t kMaxAbbreviationEntries = 1000;
struct DebugSections {
const ElfFile* elf;
folly::StringPiece debugCuIndex;
folly::StringPiece debugAbbrev;
folly::StringPiece debugAddr;
folly::StringPiece debugAranges;
folly::StringPiece debugInfo;
folly::StringPiece debugLine;
folly::StringPiece debugLineStr;
folly::StringPiece debugLoclists;
folly::StringPiece debugRanges;
folly::StringPiece debugRnglists;
folly::StringPiece debugStr;
folly::StringPiece debugStrOffsets;
};
struct DIEAbbreviation {
uint64_t code = 0;
uint64_t tag = 0;
bool hasChildren = false;
folly::StringPiece attributes;
};
struct CompilationUnit {
DebugSections debugSections;
bool is64Bit = false;
uint8_t version = 0;
uint8_t unitType = DW_UT_compile;
uint8_t addrSize = 0;
uint32_t offset = 0;
uint32_t size = 0;
uint32_t firstDie = 0;
folly::Optional<uint64_t> abbrevOffset;
folly::StringPiece compDir = ".";
folly::Optional<uint64_t> addrBase;
folly::Optional<uint64_t> rangesBase;
folly::Optional<uint64_t> loclistsBase;
folly::Optional<uint64_t> rnglistsBase;
folly::Optional<uint64_t> strOffsetsBase;
folly::Optional<folly::StringPiece> dwoName;
folly::Optional<uint64_t> dwoId;
folly::Range<DIEAbbreviation*> abbrCache;
};
struct CompilationUnits {
CompilationUnit mainCompilationUnit;
folly::Optional<CompilationUnit> splitCU;
CompilationUnit& defaultCompilationUnit() {
if (splitCU.hasValue()) {
return *splitCU;
}
return mainCompilationUnit;
}
};
struct Die {
bool is64Bit = false;
uint8_t attrOffset = 0;
uint32_t offset = 0;
uint64_t code = 0;
DIEAbbreviation abbr;
};
struct AttributeSpec {
uint64_t name = 0;
uint64_t form = 0;
int64_t implicitConst = 0;
explicit operator bool() const { return name != 0 || form != 0; }
};
struct Attribute {
AttributeSpec spec;
const Die& die;
std::variant<uint64_t, folly::StringPiece> attrValue;
};
folly::StringPiece getElfSection(const ElfFile* elf, const char* name);
template <class T>
typename std::enable_if<
std::is_standard_layout<T>::value && std::is_trivial<T>::value,
T>::type
read(folly::StringPiece& sp) {
FOLLY_SAFE_CHECK(sp.size() >= sizeof(T), "underflow");
T x;
memcpy(&x, sp.data(), sizeof(T));
sp.advance(sizeof(T));
return x;
}
template <size_t N>
uint64_t readU64(folly::StringPiece& sp);
uint64_t readULEB(folly::StringPiece& sp, uint8_t& shift, uint8_t& val);
uint64_t readULEB(folly::StringPiece& sp);
int64_t readSLEB(folly::StringPiece& sp);
uint64_t readOffset(folly::StringPiece& sp, bool is64Bit);
folly::StringPiece readBytes(folly::StringPiece& sp, uint64_t len);
AttributeSpec readAttributeSpec(folly::StringPiece& sp);
bool readAbbreviation(folly::StringPiece& section, DIEAbbreviation& abbr);
folly::StringPiece readNullTerminated(folly::StringPiece& sp);
folly::StringPiece getStringFromStringSection(
folly::StringPiece str, uint64_t offset);
CompilationUnits getCompilationUnits(
ElfCacheBase* elfCache,
const DebugSections& debugSections,
uint64_t offset,
bool requireSplitDwarf = false);
Die getDieAtOffset(const CompilationUnit& cu, uint64_t offset);
Attribute readAttribute(
const CompilationUnit& cu,
const Die& die,
AttributeSpec spec,
folly::StringPiece& info);
size_t forEachAttribute(
const CompilationUnit& cu,
const Die& die,
folly::FunctionRef<bool(const Attribute&)> f);
template <class T>
folly::Optional<T> getAttribute(
const CompilationUnit& cu, const Die& die, uint64_t attrName) {
folly::Optional<T> result;
forEachAttribute(cu, die, [&](const Attribute& attr) {
if (attr.spec.name == attrName) {
result = std::get<T>(attr.attrValue);
return false;
}
return true;
});
return result;
}
folly::StringPiece getFunctionNameFromDie(
const CompilationUnit& srcu, const Die& die);
folly::StringPiece getFunctionName(
const CompilationUnit& srcu, uint64_t dieOffset);
Die findDefinitionDie(const CompilationUnit& cu, const Die& die);
}
}
#endif