22 using namespace dwarf;
23 using namespace object;
25 #define DEBUG_TYPE "dwarf"
32 bool LittleEndian,
bool GnuStyle) {
33 OS <<
"\n." << Name <<
" contents:\n";
37 OS <<
"length = " <<
format(
"0x%08x", pubNames.
getU32(&offset));
38 OS <<
" version = " <<
format(
"0x%04x", pubNames.
getU16(&offset));
39 OS <<
" unit_offset = " <<
format(
"0x%08x", pubNames.
getU32(&offset));
40 OS <<
" unit_size = " <<
format(
"0x%08x", pubNames.
getU32(&offset)) <<
'\n';
42 OS <<
"Offset Linkage Kind Name\n";
44 OS <<
"Offset Name\n";
46 while (offset < Data.
size()) {
47 uint32_t dieRef = pubNames.
getU32(&offset);
50 OS <<
format(
"0x%8.8x ", dieRef);
57 OS <<
'\"' << pubNames.
getCStr(&offset) <<
"\"\n";
67 OS <<
"\n." << Name <<
" contents:\n";
76 OS <<
".debug_abbrev contents:\n";
77 getDebugAbbrev()->dump(OS);
82 OS <<
"\n.debug_abbrev.dwo contents:\n";
87 OS <<
"\n.debug_info contents:\n";
88 for (
const auto &CU : compile_units())
93 getNumDWOCompileUnits()) {
94 OS <<
"\n.debug_info.dwo contents:\n";
95 for (
const auto &DWOCU : dwo_compile_units())
100 OS <<
"\n.debug_types contents:\n";
101 for (
const auto &TUS : type_unit_sections())
102 for (
const auto &TU : TUS)
107 getNumDWOTypeUnits()) {
108 OS <<
"\n.debug_types.dwo contents:\n";
109 for (
const auto &DWOTUS : dwo_type_unit_sections())
110 for (
const auto &DWOTU : DWOTUS)
115 OS <<
"\n.debug_loc contents:\n";
116 getDebugLoc()->dump(OS);
120 OS <<
"\n.debug_loc.dwo contents:\n";
121 getDebugLocDWO()->dump(OS);
125 OS <<
"\n.debug_frame contents:\n";
126 getDebugFrame()->dump(OS);
131 OS <<
"\n.debug_aranges contents:\n";
132 DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0);
134 while (set.
extract(arangesData, &offset))
138 uint8_t savedAddressByteSize = 0;
140 OS <<
"\n.debug_line contents:\n";
141 for (
const auto &CU : compile_units()) {
142 savedAddressByteSize = CU->getAddressByteSize();
143 const auto *CUDIE = CU->getUnitDIE();
144 if (CUDIE ==
nullptr)
146 unsigned stmtOffset = CUDIE->getAttributeValueAsSectionOffset(
148 if (stmtOffset != -1U) {
150 savedAddressByteSize);
152 LineTable.
parse(lineData, &getLineSection().Relocs, &stmtOffset);
159 OS <<
"\n.debug_line.dwo contents:\n";
160 unsigned stmtOffset = 0;
162 savedAddressByteSize);
171 OS <<
"\n.debug_str contents:\n";
172 DataExtractor strData(getStringSection(), isLittleEndian(), 0);
174 uint32_t strOffset = 0;
175 while (
const char *s = strData.
getCStr(&offset)) {
176 OS <<
format(
"0x%8.8x: \"%s\"\n", strOffset, s);
182 !getStringDWOSection().empty()) {
183 OS <<
"\n.debug_str.dwo contents:\n";
184 DataExtractor strDWOData(getStringDWOSection(), isLittleEndian(), 0);
186 uint32_t strDWOOffset = 0;
187 while (
const char *s = strDWOData.
getCStr(&offset)) {
188 OS <<
format(
"0x%8.8x: \"%s\"\n", strDWOOffset, s);
189 strDWOOffset = offset;
194 OS <<
"\n.debug_ranges contents:\n";
199 DataExtractor rangesData(getRangeSection(), isLittleEndian(),
200 savedAddressByteSize);
203 while (rangeList.
extract(rangesData, &offset))
209 isLittleEndian(),
false);
213 isLittleEndian(),
false);
217 isLittleEndian(),
true );
221 isLittleEndian(),
true );
224 !getStringOffsetDWOSection().empty()) {
225 OS <<
"\n.debug_str_offsets.dwo contents:\n";
226 DataExtractor strOffsetExt(getStringOffsetDWOSection(), isLittleEndian(),
229 uint64_t
size = getStringOffsetDWOSection().size();
230 while (offset < size) {
231 OS <<
format(
"0x%8.8x: ", offset);
238 getStringSection(), isLittleEndian());
242 getStringSection(), isLittleEndian());
246 getStringSection(), isLittleEndian());
250 getStringSection(), isLittleEndian());
257 DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0);
260 Abbrev->extract(abbrData);
266 return AbbrevDWO.get();
268 DataExtractor abbrData(getAbbrevDWOSection(), isLittleEndian(), 0);
270 AbbrevDWO->extract(abbrData);
271 return AbbrevDWO.get();
281 if (getNumCompileUnits())
282 Loc->parse(LocData, getCompileUnitAtIndex(0)->getAddressByteSize());
292 LocDWO->parse(LocData);
298 return Aranges.get();
302 return Aranges.get();
307 return DebugFrame.get();
318 DataExtractor debugFrameData(getDebugFrameSection(), isLittleEndian(),
321 DebugFrame->parse(debugFrameData);
322 return DebugFrame.get();
330 if (UnitDIE ==
nullptr)
332 unsigned stmtOffset =
334 if (stmtOffset == -1U)
344 return Line->getOrParseLineTable(lineData, stmtOffset);
347 void DWARFContext::parseCompileUnits() {
348 CUs.parse(*
this, getInfoSection());
351 void DWARFContext::parseTypeUnits() {
354 for (
const auto &
I : getTypesSections()) {
356 TUs.back().parse(*
this,
I.second);
360 void DWARFContext::parseDWOCompileUnits() {
361 DWOCUs.parseDWO(*
this, getInfoDWOSection());
364 void DWARFContext::parseDWOTypeUnits() {
367 for (
const auto &
I : getTypesDWOSections()) {
368 DWOTUs.emplace_back();
369 DWOTUs.back().parseDWO(*
this,
I.second);
375 return CUs.getUnitForOffset(Offset);
380 uint32_t CUOffset = getDebugAranges()->findAddress(Address);
382 return getCompileUnitForOffset(CUOffset);
387 std::string &FunctionName) {
395 if (InlinedChain.
DIEs.size() == 0)
398 if (
const char *
Name =
430 std::string FunctionName =
"<invalid>";
438 Lines.
push_back(std::make_pair(Address, Result));
445 std::vector<uint32_t> RowVector;
449 for (uint32_t RowIndex : RowVector) {
476 if (InlinedChain.
DIEs.size() == 0) {
481 LineTable = getLineTableForUnit(CU);
490 uint32_t CallFile = 0, CallLine = 0, CallColumn = 0;
491 for (uint32_t i = 0, n = InlinedChain.
DIEs.size(); i != n; i++) {
495 if (
const char *
Name =
502 LineTable = getLineTableForUnit(CU);
513 Frame.
Line = CallLine;
514 Frame.
Column = CallColumn;
528 uint64_t &OriginalSize) {
536 OriginalSize = extractor.
getU64(&Offset);
539 data = data.
substr(Offset);
545 : IsLittleEndian(Obj.isLittleEndian()),
546 AddressSize(Obj.getBytesInAddress()) {
554 bool IsVirtual =
Section.isVirtual();
569 uint64_t OriginalSize;
573 UncompressedSections.resize(UncompressedSections.size() + 1);
576 UncompressedSections.pop_back();
581 data = UncompressedSections.back();
586 .Case(
"debug_info", &InfoSection.
Data)
587 .
Case(
"debug_abbrev", &AbbrevSection)
588 .
Case(
"debug_loc", &LocSection.
Data)
589 .
Case(
"debug_line", &LineSection.
Data)
590 .
Case(
"debug_aranges", &ARangeSection)
591 .
Case(
"debug_frame", &DebugFrameSection)
592 .
Case(
"debug_str", &StringSection)
593 .
Case(
"debug_ranges", &RangeSection)
594 .
Case(
"debug_pubnames", &PubNamesSection)
595 .
Case(
"debug_pubtypes", &PubTypesSection)
596 .
Case(
"debug_gnu_pubnames", &GnuPubNamesSection)
597 .
Case(
"debug_gnu_pubtypes", &GnuPubTypesSection)
598 .
Case(
"debug_info.dwo", &InfoDWOSection.
Data)
599 .
Case(
"debug_abbrev.dwo", &AbbrevDWOSection)
600 .
Case(
"debug_loc.dwo", &LocDWOSection.
Data)
601 .
Case(
"debug_line.dwo", &LineDWOSection.
Data)
602 .
Case(
"debug_str.dwo", &StringDWOSection)
603 .
Case(
"debug_str_offsets.dwo", &StringOffsetDWOSection)
604 .
Case(
"debug_addr", &AddrSection)
605 .
Case(
"apple_names", &AppleNamesSection.
Data)
606 .
Case(
"apple_types", &AppleTypesSection.
Data)
607 .
Case(
"apple_namespaces", &AppleNamespacesSection.
Data)
608 .
Case(
"apple_namespac", &AppleNamespacesSection.
Data)
609 .
Case(
"apple_objc", &AppleObjCSection.
Data)
614 if (name ==
"debug_ranges") {
616 RangeDWOSection = data;
618 }
else if (name ==
"debug_types") {
621 TypesSections[
Section].Data = data;
622 }
else if (name ==
"debug_types.dwo") {
623 TypesDWOSections[
Section].Data = data;
632 RelocatedSection->getName(RelSecName);
640 RelSecName = RelSecName.
substr(
646 .Case(
"debug_info", &InfoSection.
Relocs)
648 .
Case(
"debug_info.dwo", &InfoDWOSection.
Relocs)
650 .
Case(
"apple_names", &AppleNamesSection.
Relocs)
651 .
Case(
"apple_types", &AppleTypesSection.
Relocs)
652 .
Case(
"apple_namespaces", &AppleNamespacesSection.
Relocs)
653 .
Case(
"apple_namespac", &AppleNamespacesSection.
Relocs)
659 if (RelSecName ==
"debug_types")
660 Map = &TypesSections[*RelocatedSection].Relocs;
661 else if (RelSecName ==
"debug_types.dwo")
662 Map = &TypesDWOSections[*RelocatedSection].Relocs;
668 uint64_t
SectionSize = RelocatedSection->getSize();
670 uint64_t Address = Reloc.getOffset();
671 uint64_t
Type = Reloc.getType();
672 uint64_t SymAddr = 0;
673 uint64_t SectionLoadAddress = 0;
681 if (std::error_code EC = SymAddrOrErr.
getError()) {
682 errs() <<
"error: failed to compute symbol address: "
683 << EC.message() <<
'\n';
686 SymAddr = *SymAddrOrErr;
689 }
else if (
auto *MObj = dyn_cast<MachOObjectFile>(&Obj)) {
693 RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl());
694 SymAddr = RSec->getAddress();
706 RSec->getName(SecName);
708 if (SectionLoadAddress != 0)
709 SymAddr += SectionLoadAddress - RSec->getAddress();
716 Reloc.getTypeName(Name);
717 errs() <<
"error: failed to compute relocation: "
722 if (Address + R.Width > SectionSize) {
723 errs() <<
"error: " << R.Width <<
"-byte relocation starting "
724 << Address <<
" bytes into section " << name <<
" which is "
725 << SectionSize <<
" bytes long.\n";
729 errs() <<
"error: can't handle a relocation of more than 8 bytes at "
734 <<
" at " <<
format(
"%p", Address)
735 <<
" with width " <<
format(
"%d", R.Width)
737 Map->
insert(std::make_pair(Address, std::make_pair(R.Width, R.Value)));
743 void DWARFContextInMemory::anchor() { }
RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t Value=0)
void push_back(const T &Elt)
std::error_code getError() const
Represents either an error or a value T.
const DWARFDebugFrame * getDebugFrame()
Get a pointer to the parsed frame information object.
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
A parsed .debug_frame section.
size_t size() const
size - Get the string size.
const DWARFDebugLocDWO * getDebugLocDWO()
Get a pointer to the parsed DebugLoc object.
const DWARFDebugLoc * getDebugLoc()
Get a pointer to the parsed DebugLoc object.
const char * getSubroutineName(const DWARFUnit *U, DINameKind Kind) const
If a DIE represents a subprogram (or inlined subroutine), returns its mangled name (or short name...
virtual bool getLoadedSectionContents(StringRef Name, StringRef &Data) const
If conveniently available, return the content of the given Section.
static bool getFunctionNameForAddress(DWARFCompileUnit *CU, uint64_t Address, FunctionNameKind Kind, std::string &FunctionName)
bool getFileNameByIndex(uint64_t FileIndex, const char *CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, std::string &Result) const
StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
This class is the base class for all object file types.
void addFrame(const DILineInfo &Frame)
const DWARFDebugAbbrev * getDebugAbbrevDWO()
Get a pointer to the parsed dwo abbreviations object.
DINameKind
A DINameKind is passed to name search methods to specify a preference regarding the type of name reso...
void generate(DWARFContext *CTX)
StringSwitch & Case(const char(&S)[N], const T &Value)
virtual uint64_t getSectionLoadAddress(StringRef Name) const =0
Obtain the Load Address of a section by Name.
static void dumpAccelSection(raw_ostream &OS, StringRef Name, const DWARFSection &Section, StringRef StringSection, bool LittleEndian)
DILineInfo - a format-neutral container for source line information.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
const char * GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage)
void dump(raw_ostream &OS, DIDumpType DumpType=DIDT_All) override
const char * getCompilationDir()
This is a value type class that represents a single relocation in the list of relocations in the obje...
Decsribes an entry of the various gnu_pub* debug sections.
const DWARFDebugAranges * getDebugAranges()
Get a pointer to the parsed DebugAranges object.
DWARFDebugInfoEntryInlinedChain getInlinedChainForAddress(uint64_t Address)
getInlinedChainForAddress - fetches inlined chain for a given address.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
const DWARFDebugAbbrev * getDebugAbbrev()
Get a pointer to the parsed DebugAbbrev object.
bool extract(DataExtractor data, uint32_t *offset_ptr)
SmallVector< DWARFDebugInfoEntryMinimal, 4 > DIEs
format_object< Ts...> format(const char *Fmt, const Ts &...Vals)
These are helper functions used to produce formatted output.
A switch()-like statement whose cases are string literals.
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
void dump(raw_ostream &OS) const
DWARFDebugInfoEntryMinimal - A DIE with only the minimum required data.
The instances of the Type class are immutable: once they are created, they are never changed...
DILineInfoSpecifier - controls which fields of DILineInfo container should be filled with data...
DIInliningInfo - a format-neutral container for inlined code description.
DIDumpType
Selects which debug sections get dumped.
DILineInfo getLineInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier=DILineInfoSpecifier()) override
static void dumpPubSection(raw_ostream &OS, StringRef Name, StringRef Data, bool LittleEndian, bool GnuStyle)
bool parse(DataExtractor debug_line_data, uint32_t *offset_ptr)
void dump(raw_ostream &OS) const
bool parse(DataExtractor debug_line_data, const RelocAddrMap *RMap, uint32_t *offset_ptr)
Parse prologue and all rows.
section_iterator_range sections() const
bool lookupAddressRange(uint64_t address, uint64_t size, std::vector< uint32_t > &result) const
size_t find_first_not_of(char C, size_t From=0) const
Find the first character in the string that is not C or npos if not found.
void dump(raw_ostream &OS) const
basic_symbol_iterator symbol_end() const
DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind
bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
static bool consumeCompressedDebugSectionHeader(StringRef &data, uint64_t &OriginalSize)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
DIInliningInfo getInliningInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier=DILineInfoSpecifier()) override
bool extract(DataExtractor data, uint32_t *offset_ptr)
uint64_t getAttributeValueAsSectionOffset(const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const
R Default(const T &Value) const
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
An inferface for inquiring the load address of a loaded object file to be used by the DIContext imple...
void getCallerFrame(const DWARFUnit *U, uint32_t &CallFile, uint32_t &CallLine, uint32_t &CallColumn) const
Retrieves values of DW_AT_call_file, DW_AT_call_line and DW_AT_call_column from DIE (or zeroes if the...
DWARFDebugLine::LineTable DWARFLineTable
DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size, DILineInfoSpecifier Specifier=DILineInfoSpecifier()) override
DILineInfoSpecifier::FunctionNameKind FunctionNameKind
const char * GDBIndexEntryKindString(GDBIndexEntryKind Kind)
Status uncompress(StringRef InputBuffer, SmallVectorImpl< char > &UncompressedBuffer, size_t UncompressedSize)
virtual section_iterator section_end() const =0
void dump(raw_ostream &OS) const
DWARFContextInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L=nullptr)
bool getFileLineInfoForAddress(uint64_t Address, const char *CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, DILineInfo &Result) const
uint8_t getAddressByteSize() const
const ARM::ArchExtKind Kind
const DWARFDebugLine::LineTable * getLineTableForUnit(DWARFUnit *cu)
Get a pointer to a parsed line table corresponding to a compile unit.
This class implements an extremely fast bulk output stream that can only output to a stream...
const DWARFDebugInfoEntryMinimal * getUnitDIE(bool ExtractUnitDIEOnly=true)
StringRef - Represent a constant reference to a string, i.e.
ErrorOr< uint64_t > getAddress() const
Returns the symbol virtual address (i.e.
std::error_code getSection(section_iterator &Result) const
Get section this symbol is defined in reference to.
This is a value type class that represents a single section in the list of sections in the object fil...
Base class for object file relocation visitors.
DWARFDebugInfoEntryInlinedChain - represents a chain of inlined_subroutine DIEs, (possibly ending wit...