19 #include <type_traits> 23 #if __has_include(<libdwarf/dwarf.h>) 24 #include <libdwarf/dwarf.h> 30 namespace symbolizer {
49 memcpy(&x, sp.
data(),
sizeof(
T));
59 val = read<uint8_t>(sp);
60 r |= ((
uint64_t)(val & 0x7f) << shift);
69 return readULEB(sp, shift, val);
76 uint64_t r = readULEB(sp, shift, val);
78 if (shift < 64 && (val & 0x40)) {
79 r |= -(1ULL << shift);
87 return is64Bit ? read<uint64_t>(sp) : read<uint32_t>(sp);
100 const char* p =
static_cast<const char*
>(memchr(sp.
data(), 0, sp.
size()));
109 size_t remainder = (sp.
data() -
start) % alignment;
112 sp.
advance(alignment - remainder);
171 : baseDir_(baseDir), subDir_(subDir), file_(file) {
181 if (
file_[0] ==
'/') {
203 bool needsSlash =
false;
225 size_t totalSize = 0;
226 bool needsSlash =
false;
230 size_t toCopy =
std::min(sp.size(), bufSize - 1);
231 memcpy(buf, sp.data(), toCopy);
235 totalSize += sp.size();
258 assert(totalSize ==
size());
263 size_t initialSize = dest.size();
264 dest.reserve(initialSize +
size());
269 if (!dest.empty() && dest.back() !=
'/') {
275 if (!dest.empty() && dest.back() !=
'/') {
280 assert(dest.size() == initialSize +
size());
293 auto initialLength = read<uint32_t>(chunk);
294 is64Bit_ = (initialLength == (
uint32_t)-1);
295 auto length = is64Bit_ ? read<uint64_t>(chunk) : initialLength;
307 #ifdef SHF_COMPRESSED 308 if (elfSection->sh_flags & SHF_COMPRESSED) {
335 abbr.
code = readULEB(section);
336 if (abbr.
code == 0) {
341 abbr.
tag = readULEB(section);
344 abbr.
hasChildren = (read<uint8_t>(section) != DW_CHILDREN_no);
347 const char* attributeBegin = section.
data();
351 if (attr.name == 0 && attr.form == 0) {
361 return {readULEB(sp), readULEB(sp)};
372 if (abbr.
code == code) {
383 bool is64Bit)
const {
386 return read<uintptr_t>(sp);
388 return readBytes(sp, read<uint8_t>(sp));
390 return readBytes(sp, read<uint16_t>(sp));
392 return readBytes(sp, read<uint32_t>(sp));
394 case DW_FORM_exprloc:
395 return readBytes(sp, readULEB(sp));
398 return read<uint8_t>(sp);
401 return read<uint16_t>(sp);
404 return read<uint32_t>(sp);
407 return read<uint64_t>(sp);
411 case DW_FORM_ref_udata:
414 return read<uint8_t>(sp);
415 case DW_FORM_flag_present:
417 case DW_FORM_sec_offset:
418 case DW_FORM_ref_addr:
419 return readOffset(sp, is64Bit);
421 return readNullTerminated(sp);
424 case DW_FORM_indirect:
435 return readNullTerminated(sp);
446 Section arangesSection(aranges);
448 while (arangesSection.
next(chunk)) {
449 auto version = read<uint16_t>(chunk);
452 offset = readOffset(chunk, arangesSection.
is64Bit());
453 auto addressSize = read<uint8_t>(chunk);
455 auto segmentSize = read<uint8_t>(chunk);
461 skipPadding(chunk, aranges.
data(), 2 *
sizeof(uintptr_t));
463 auto start = read<uintptr_t>(chunk);
464 auto length = read<uintptr_t>(chunk);
466 if (
start == 0 && length == 0) {
471 if (address >=
start && address <
start + length) {
502 Section debugInfoSection(infoEntry);
506 auto version = read<uint16_t>(chunk);
509 auto addressSize = read<uint8_t>(chunk);
516 auto code = readULEB(chunk);
520 abbr.tag == DW_TAG_compile_unit,
"expecting compile unit entry");
525 bool foundLineOffset =
false;
534 if (attr.
name == 0 && attr.
form == 0) {
539 case DW_AT_stmt_list:
542 lineOffset = boost::get<uint64_t>(
val);
543 foundLineOffset =
true;
547 compilationDirectory = boost::get<folly::StringPiece>(
val);
551 mainFileName = boost::get<folly::StringPiece>(
val);
556 if (!mainFileName.
empty()) {
558 locationInfo.
mainFile =
Path(compilationDirectory,
"", mainFileName);
561 if (!foundLineOffset) {
566 lineSection.
advance(lineOffset);
623 : compilationDirectory_(compilationDirectory) {
651 headerLength <=
data_.
size(),
"invalid line number VM header length");
657 uint8_t maxOpsPerInstruction = read<uint8_t>(header);
666 header.advance(opcodeBase_ - 1);
672 const char* tmp = header.
data();
674 while (!(sp = readNullTerminated(header)).
empty()) {
704 for (; index; --index) {
715 for (; index; --index) {
733 for (; index; --index) {
734 dir = readNullTerminated(includeDirectories);
760 while (!program.
empty()) {
761 auto opcode = read<uint8_t>(program);
777 auto length = readULEB(program);
780 read<uint8_t>(program);
783 if (opcode == DW_LNE_define_file) {
786 "invalid empty file in DW_LNE_define_file");
799 auto opcode = read<uint8_t>(program);
825 case DW_LNS_advance_pc:
828 case DW_LNS_advance_line:
829 line_ += readSLEB(program);
831 case DW_LNS_set_file:
832 file_ = readULEB(program);
834 case DW_LNS_set_column:
837 case DW_LNS_negate_stmt:
840 case DW_LNS_set_basic_block:
843 case DW_LNS_const_add_pc:
846 case DW_LNS_fixed_advance_pc:
847 address_ += read<uint16_t>(program);
849 case DW_LNS_set_prologue_end:
855 case DW_LNS_set_epilogue_begin:
865 isa_ = readULEB(program);
879 auto length = readULEB(program);
882 auto extendedOpcode = read<uint8_t>(program);
885 switch (extendedOpcode) {
886 case DW_LNE_end_sequence:
888 case DW_LNE_set_address:
889 address_ = read<uintptr_t>(program);
891 case DW_LNE_define_file:
896 case DW_LNE_set_discriminator:
927 while (!program.
empty()) {
928 bool seqEnd = !
next(program);
930 if (state == START) {
932 state =
address_ <= target ? LOW_SEQ : HIGH_SEQ;
936 if (state == LOW_SEQ) {
DIEAbbreviation getAbbreviation(uint64_t code, uint64_t offset) const
folly::StringPiece subDir_
bool next(folly::StringPiece &chunk)
Dwarf(const ElfFile *elf)
folly::StringPiece attributes
bool nextDefineFile(folly::StringPiece &program, FileName &fn) const
bool findAddress(uintptr_t address, LocationInfo &info, LocationInfoMode mode) const
bool getSection(const char *name, folly::StringPiece *section) const
bool next(folly::StringPiece &program)
size_t includeDirectoryCount_
static DIEAbbreviation::Attribute readAttribute(folly::StringPiece &sp)
LineNumberVM(folly::StringPiece data, folly::StringPiece compilationDirectory)
void advance(size_type n)
void append(std::unique_ptr< IOBuf > &buf, StringPiece str)
constexpr size_type size() const
folly::StringPiece getStringFromStringSection(uint64_t offset) const
folly::StringPiece getSectionBody(const ElfShdr §ion) const
—— Concurrent Priority Queue Implementation ——
folly::Optional< PskKeyExchangeMode > mode
bool removeSuffix(const const_range_type &suffix)
const uint8_t * standardOpcodeLengths_
constexpr bool empty() const
State
See Core for details.
constexpr auto empty(C const &c) -> decltype(c.empty())
folly::StringPiece strings_
boost::variant< uint64_t, folly::StringPiece > AttributeValue
size_t read(T &out, folly::io::Cursor &cursor)
folly::StringPiece getIncludeDirectory(uint64_t index) const
constexpr Iter data() const
constexpr auto data(C &c) -> decltype(c.data())
void assign(Iter start, Iter end)
folly::StringPiece includeDirectories_
const ElfShdr * getSectionByName(const char *name) const
folly::StringPiece abbrev_
size_t toBuffer(char *buf, size_t bufSize) const
static const char *const value
bool removePrefix(const const_range_type &prefix)
#define FOLLY_SAFE_CHECK(expr, msg)
constexpr Iter end() const
FileName getFileName(uint64_t index) const
folly::StringPiece aranges_
constexpr Iter begin() const
folly::StringPiece fileNames_
void swap(exception_wrapper &a, exception_wrapper &b) noexcept
bool findAddress(uintptr_t address, Path &file, uint64_t &line)
bool startsWith(const const_range_type &other) const
folly::StringPiece baseDir_
StepResult step(folly::StringPiece &program)
void swap(SwapTrackingAlloc< T > &, SwapTrackingAlloc< T > &)
bool endsWith(const const_range_type &other) const
Range< const char * > StringPiece
static bool readAbbreviation(folly::StringPiece &sp, DIEAbbreviation &abbr)
AttributeValue readAttributeValue(folly::StringPiece &sp, uint64_t form, bool is64Bit) const
bool findLocation(uintptr_t address, StringPiece &infoEntry, LocationInfo &info) const
static bool findDebugInfoOffset(uintptr_t address, StringPiece aranges, uint64_t &offset)
static bool readFileName(folly::StringPiece &sp, FileName &fn)
std::string toString() const
folly::StringPiece relativeName
void reset(Iter start, size_type size)
folly::StringPiece compilationDirectory_