30#define DEBUG_TYPE "DWARFReader"
32void LVDWARFReader::processOneAttribute(
const DWARFDie &Die,
42 auto GetAsUnsignedConstant = [&]() -> int64_t {
54 auto GetBoundValue = [&AttrSpec](
const DWARFFormValue &FormValue) -> int64_t {
56 case dwarf::DW_FORM_ref_addr:
57 case dwarf::DW_FORM_ref1:
58 case dwarf::DW_FORM_ref2:
59 case dwarf::DW_FORM_ref4:
60 case dwarf::DW_FORM_ref8:
61 case dwarf::DW_FORM_ref_udata:
62 case dwarf::DW_FORM_ref_sig8:
64 case dwarf::DW_FORM_data1:
65 case dwarf::DW_FORM_flag:
66 case dwarf::DW_FORM_data2:
67 case dwarf::DW_FORM_data4:
68 case dwarf::DW_FORM_data8:
69 case dwarf::DW_FORM_udata:
70 case dwarf::DW_FORM_ref_sup4:
71 case dwarf::DW_FORM_ref_sup8:
73 case dwarf::DW_FORM_sdata:
75 case dwarf::DW_FORM_implicit_const:
87 switch (AttrSpec.
Attr) {
88 case dwarf::DW_AT_accessibility:
91 case dwarf::DW_AT_artificial:
94 case dwarf::DW_AT_bit_size:
97 case dwarf::DW_AT_byte_size:
100 case dwarf::DW_AT_call_file:
102 ? GetAsUnsignedConstant() + 1
103 : GetAsUnsignedConstant());
105 case dwarf::DW_AT_call_line:
108 case dwarf::DW_AT_comp_dir:
111 case dwarf::DW_AT_const_value:
120 if (FormValue.
getForm() == dwarf::DW_FORM_sdata) {
121 std::stringstream Stream;
134 case dwarf::DW_AT_count:
137 case dwarf::DW_AT_decl_line:
140 case dwarf::DW_AT_decl_file:
142 ? GetAsUnsignedConstant() + 1
143 : GetAsUnsignedConstant());
145 case dwarf::DW_AT_enum_class:
146 if (GetFlag(FormValue))
149 case dwarf::DW_AT_external:
150 if (GetFlag(FormValue))
153 case dwarf::DW_AT_GNU_discriminator:
156 case dwarf::DW_AT_inline:
159 case dwarf::DW_AT_lower_bound:
162 case dwarf::DW_AT_name:
165 case dwarf::DW_AT_GNU_template_name:
168 case dwarf::DW_AT_linkage_name:
169 case dwarf::DW_AT_MIPS_linkage_name:
172 case dwarf::DW_AT_producer:
173 if (
options().getAttributeProducer())
176 case dwarf::DW_AT_language:
177 if (
options().getAttributeLanguage())
181 case dwarf::DW_AT_upper_bound:
184 case dwarf::DW_AT_virtuality:
188 case dwarf::DW_AT_abstract_origin:
189 case dwarf::DW_AT_call_origin:
190 case dwarf::DW_AT_extension:
191 case dwarf::DW_AT_import:
192 case dwarf::DW_AT_specification:
193 case dwarf::DW_AT_type:
194 updateReference(AttrSpec.
Attr, FormValue);
197 case dwarf::DW_AT_low_pc:
198 if (
options().getGeneralCollectRanges()) {
204 CurrentLowPC = *
Value;
207 if (U->getAddrOffsetSectionItem(UValue)) {
229 case dwarf::DW_AT_high_pc:
230 if (
options().getGeneralCollectRanges()) {
232 if (std::optional<uint64_t> Address = FormValue.
getAsAddress())
234 CurrentHighPC = *Address;
253 case dwarf::DW_AT_ranges:
254 if (RangesDataAvailable &&
options().getGeneralCollectRanges()) {
257 if (FormValue.
getForm() == dwarf::DW_FORM_rnglistx)
262 GetRanges(FormValue, U);
263 if (!RangesOrError) {
266 dbgs() <<
format(
"error decoding address ranges = ",
295 case dwarf::DW_AT_data_member_location:
296 if (
options().getAttributeAnyLocation())
297 processLocationMember(AttrSpec.
Attr, FormValue, Die, OffsetOnEntry);
301 case dwarf::DW_AT_location:
302 case dwarf::DW_AT_string_length:
303 case dwarf::DW_AT_use_location:
305 processLocationList(AttrSpec.
Attr, FormValue, Die, OffsetOnEntry);
308 case dwarf::DW_AT_call_data_value:
309 case dwarf::DW_AT_call_value:
310 case dwarf::DW_AT_GNU_call_site_data_value:
311 case dwarf::DW_AT_GNU_call_site_value:
313 processLocationList(AttrSpec.
Attr, FormValue, Die, OffsetOnEntry,
322LVScope *LVDWARFReader::processOneDie(
const DWARFDie &InputDIE,
LVScope *Parent,
323 DWARFDie &SkeletonDie) {
328 const DWARFDie &DIE = SkeletonDie.
isValid() ? SkeletonDie : InputDIE;
329 DWARFDataExtractor DebugInfoData =
337 CurrentEndOffset = 0;
372 for (LVElement *Target :
Reference.References)
374 for (LVElement *Target :
Reference.Types)
391 auto ProcessAttributes = [&](
const DWARFDie &TheDIE,
392 DWARFDataExtractor &DebugData) {
393 CurrentEndOffset =
Offset;
394 uint32_t abbrCode = DebugData.getULEB128(&CurrentEndOffset);
396 if (
const DWARFAbbreviationDeclaration *AbbrevDecl =
399 for (
const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec :
400 AbbrevDecl->attributes())
401 processOneAttribute(TheDIE, &CurrentEndOffset, AttrSpec);
405 ProcessAttributes(DIE, DebugInfoData);
410 DWARFDataExtractor DebugInfoData =
414 ProcessAttributes(InputDIE, DebugInfoData);
423 if (FoundLowPC && FoundHighPC) {
427 if ((
options().getAttributePublics() ||
428 options().getPrintAnyLine()) &&
443 std::optional<DWARFFormValue> LinkageDIE =
445 if (LinkageDIE.has_value()) {
472 CurrentHighPC > CurrentLowPC
479 if (Parent->getIsAggregate())
490 Parent->setIsTemplate();
495void LVDWARFReader::traverseDieAndChildren(DWARFDie &DIE,
LVScope *Parent,
496 DWARFDie &SkeletonDie) {
498 LVScope *
Scope = processOneDie(DIE, Parent, SkeletonDie);
506 traverseDieAndChildren(Child, Scope, DummyDie);
516void LVDWARFReader::processLocationGaps() {
517 if (
options().getAttributeAnyLocation())
518 for (LVSymbol *Symbol : SymbolsWithLocations)
519 Symbol->fillLocationGaps();
522void LVDWARFReader::createLineAndFileRecords(
523 const DWARFDebugLine::LineTable *
Lines) {
528 if (!Lines->Prologue.FileNames.empty())
529 for (
const DWARFDebugLine::FileNameEntry &Entry :
530 Lines->Prologue.FileNames) {
531 std::string Directory;
532 if (Lines->getDirectoryForEntry(Entry, Directory))
534 if (Directory.empty())
535 Directory = std::string(
CompileUnit->getCompilationDirectory());
538 raw_string_ostream(
String) << Directory <<
"/" <<
File;
543 bool IncrementIndex = Lines->Prologue.getVersion() >= 5;
546 if (
options().getPrintLines() && Lines->Rows.size())
547 for (
const DWARFDebugLine::Row &Row : Lines->Rows) {
552 LVLineDebug *
Line = createLineDebug();
557 CompileUnit->getFilename(IncrementIndex ? Row.File + 1 : Row.File));
558 Line->setLineNumber(Row.Line);
559 if (Row.Discriminator)
560 Line->setDiscriminator(Row.Discriminator);
562 Line->setIsNewStatement();
564 Line->setIsBasicBlock();
566 Line->setIsEndSequence();
567 if (Row.EpilogueBegin)
568 Line->setIsEpilogueBegin();
570 Line->setIsPrologueEnd();
573 <<
" Line: " <<
Line->lineNumberAsString(
true)
585 if (Opcode == dwarf::DW_OP_regval_type)
591 auto *MCRegInfo =
MRI.get();
595 if (std::optional<MCRegister> LLVMRegNum =
596 MCRegInfo->getLLVMRegNum(DwarfRegNum, IsEH))
597 if (
const char *
RegName = MCRegInfo->getName(*LLVMRegNum))
608 W.startLine() <<
"\n";
609 W.printString(
"File", Obj.getFileName().str());
622 "Could not create DWARF information: %s",
625 if (
Error Err = loadTargetInfo(Obj))
634 DwarfContext->getNumCompileUnits() ? DwarfContext->compile_units()
635 : DwarfContext->dwo_compile_units();
636 for (
const std::unique_ptr<DWARFUnit> &
CU : CompileUnits) {
694 auto DeduceIncrementFileIndex = [&]() ->
bool {
695 if (
CU->getVersion() < 5)
700 CU->getContext().getLineTableForUnit(
CU.get())) {
702 if (LT->hasFileAtIndex(0) && LT->hasFileAtIndex(1)) {
704 LT->Prologue.getFileNameEntry(0);
706 LT->Prologue.getFileNameEntry(1);
712 std::string FileZero;
715 LT->getFileNameByIndex(
718 LT->getFileNameByIndex(
721 return FileZero != FileOne;
729 IncrementFileIndex = DeduceIncrementFileIndex();
734 std::optional<const char *> DWOFileName =
735 CU->getVersion() >= 5
738 StringRef From(DWOFileName.value_or(
""));
747 DWOAlternativeLocation);
759 RangesDataAvailable =
764 traverseDieAndChildren(CUDie,
Root, SkeletonDie);
766 createLineAndFileRecords(DwarfContext->getLineTableForUnit(
CU.get()));
776 ScopesWithRanges->
sort();
779 processLocationGaps();
782 ScopesWithRanges->
clear();
783 SymbolsWithLocations.clear();
795 bool CallSiteLocation) {
812 U->getFormParams().Format);
825 if (FormValue.
getForm() == dwarf::DW_FORM_loclistx) {
826 std::optional<uint64_t> LoclistOffset = U->getLoclistOffset(
Offset);
832 if (std::optional<SectionedAddress> BA =
U->getBaseAddress())
837 auto ProcessLocationEntry = [&](
const DWARFLocationEntry &
Entry) {
838 if (
Entry.Kind == dwarf::DW_LLE_base_address) {
842 if (
Entry.Kind == dwarf::DW_LLE_offset_pair) {
845 DWARFAddressRange
Range{LowPC, HighPC,
Entry.SectionIndex};
848 DWARFLocationExpression Loc{
Range,
Entry.Loc};
849 DWARFDataExtractor
Data(Loc.
Expr, IsLittleEndian,
850 U->getAddressByteSize());
851 DWARFExpression Expression(
Data,
U->getAddressByteSize());
859 ProcessLocationExpression(Expression);
862 Error E =
U->getLocationTable().visitLocationList(
863 &
Offset, [&](
const DWARFLocationEntry &
E) {
864 ProcessLocationEntry(
E);
873 const DWARFFormValue &FormValue,
875 uint64_t OffsetOnEntry) {
883 processLocationList(Attr, FormValue, Die, OffsetOnEntry);
888 const DWARFFormValue &FormValue) {
901 LVElement *
Target = getElementForOffset(
903 Attr == dwarf::DW_AT_import || Attr == dwarf::DW_AT_type);
905 if (FormValue.
getForm() == dwarf::DW_FORM_ref_addr) {
908 Target->setIsGlobalReference();
910 removeGlobalOffset(
Offset);
924 case dwarf::DW_AT_abstract_origin:
925 case dwarf::DW_AT_call_origin:
929 case dwarf::DW_AT_extension:
933 case dwarf::DW_AT_specification:
937 case dwarf::DW_AT_import:
938 case dwarf::DW_AT_type:
951 if (!
Entry.Element) {
953 Entry.Types.insert(Element);
955 Entry.References.insert(Element);
957 return Entry.Element;
963 Triple
TT = Obj.makeTriple();
966 Expected<SubtargetFeatures> Features = Obj.getFeatures();
967 SubtargetFeatures FeaturesValue;
970 FeaturesValue = SubtargetFeatures();
972 FeaturesValue = *Features;
975 if (
auto OptCPU = Obj.tryGetCPUName())
981void LVDWARFReader::mapRangeAddress(
const ObjectFile &Obj) {
982 for (
auto Iter = Obj.symbol_begin(); Iter != Obj.symbol_end(); ++Iter) {
983 const SymbolRef &
Symbol = *Iter;
985 Expected<SymbolRef::Type> TypeOrErr =
Symbol.getType();
1001 bool IsSTAB =
false;
1003 DataRefImpl SymDRI =
Symbol.getRawDataRefImpl();
1011 Expected<section_iterator> IterOrErr =
Symbol.getSection();
1017 if (Section == Obj.section_end())
1021 Expected<uint64_t> AddressOrErr =
Symbol.getAddress();
1022 if (!AddressOrErr) {
1026 uint64_t
Address = *AddressOrErr;
1030 Expected<StringRef> NameOrErr =
Symbol.getName();
1038 Expected<uint32_t> FlagsOrErr =
Symbol.getFlags();
1043 uint32_t
Flags = *FlagsOrErr;
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
mir Rename Register Operands
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...
DWARFUnitVector::compile_unit_range compile_unit_range
bool isLittleEndian() const
static std::unique_ptr< DWARFContext > create(const object::ObjectFile &Obj, ProcessDebugRelocations RelocAction=ProcessDebugRelocations::Process, const LoadedObjectInfo *L=nullptr, std::string DWPName="", std::function< void(Error)> RecoverableErrorHandler=WithColor::defaultErrorHandler, std::function< void(Error)> WarningHandler=WithColor::defaultWarningHandler, bool ThreadSafe=false)
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
uint64_t getOffset() const
Get the absolute offset into the debug info or types section.
LLVM_ABI std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
DWARFUnit * getDwarfUnit() const
LLVM_ABI DWARFDie getSibling() const
Get the sibling of this DIE object.
LLVM_ABI std::optional< DWARFFormValue > findRecursively(ArrayRef< dwarf::Attribute > Attrs) const
Extract the first value of any attribute in Attrs from this DIE and recurse into any DW_AT_specificat...
const DWARFAbbreviationDeclaration * getAbbreviationDeclarationPtr() const
Get the abbreviation declaration for this DIE.
LLVM_ABI DWARFDie getFirstChild() const
Get the first child of this DIE object.
dwarf::Tag getTag() const
This class represents an Operation in the Expression.
DWARFDataExtractor getDebugInfoExtractor() const
uint64_t getOffset() const
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
reference get()
Returns a reference to the stored T value.
Class representing an expression and its matching format.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
StringRef - Represent a constant reference to a string, i.e.
LLVM_ABI std::string getString() const
Returns features as a string.
LLVM Value Representation.
Stores all information relating to a compile unit, be it in its original instance in the object file ...
LVSectionIndex updateSymbolTable(LVScope *Function)
LVSectionIndex getSectionIndex(LVScope *Scope) override
Error loadGenericTargetInfo(StringRef TheTriple, StringRef TheFeatures, StringRef TheCPU)
void addToSymbolTable(StringRef Name, LVScope *Function, LVSectionIndex SectionIndex=0)
void processLines(LVLines *DebugLines, LVSectionIndex SectionIndex)
void mapVirtualAddress(const object::ObjectFile &Obj)
std::unique_ptr< const MCRegisterInfo > MRI
Error createInstructions()
LVAddress WasmCodeSectionOffset
LVAddress getTombstoneAddress() const
void setCUHighAddress(LVAddress Address)
void setTombstoneAddress(LVAddress Address)
void print(raw_ostream &OS) const
std::string getRegisterName(LVSmall Opcode, ArrayRef< uint64_t > Operands) override
void sortScopes() override
void setCUBaseAddress(LVAddress Address)
Error createScopes() override
virtual void setCount(int64_t Value)
virtual void setCallLineNumber(uint32_t Number)
virtual void setBitSize(uint32_t Size)
virtual void setLinkageName(StringRef LinkageName)
virtual void setProducer(StringRef ProducerName)
virtual void setUpperBound(int64_t Value)
virtual void setDiscriminator(uint32_t Value)
virtual void setLowerBound(int64_t Value)
virtual void setValue(StringRef Value)
void setInlineCode(uint32_t Code)
void setName(StringRef ElementName) override
virtual bool isCompileUnit() const
void setAccessibilityCode(uint32_t Access)
void setVirtualityCode(uint32_t Virtuality)
void setFilenameIndex(size_t Index)
virtual void setSourceLanguage(LVSourceLanguage SL)
virtual void setCallFilenameIndex(size_t Index)
void setLineNumber(uint32_t Number)
LVRange * getSectionRanges(LVSectionIndex SectionIndex)
void addCompileUnitOffset(LVOffset Offset, LVScopeCompileUnit *CompileUnit)
std::vector< LVAddressRange > CurrentRanges
std::string FileFormatName
std::string createAlternativePath(StringRef From)
LVElement * CurrentElement
LVElement * createElement(dwarf::Tag Tag)
StringRef getFilename() const
LVScopeCompileUnit * CompileUnit
LVSectionIndex DotTextSectionIndex
void addSectionRange(LVSectionIndex SectionIndex, LVScope *Scope)
virtual Error createScopes()
void addElement(LVElement *Element)
void addObject(LVLocation *Location)
void addLocation(dwarf::Attribute Attr, LVAddress LowPC, LVAddress HighPC, LVUnsigned SectionOffset, uint64_t LocDescOffset, bool CallSiteLocation=false)
void addLocationOperands(LVSmall Opcode, ArrayRef< uint64_t > Operands)
MachO::nlist getSymbolTableEntry(DataRefImpl DRI) const
MachO::nlist_64 getSymbol64TableEntry(DataRefImpl DRI) const
bool is64Bit() const override
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
std::string & str()
Returns the string's reference.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
StringRef toStringRef(const std::optional< DWARFFormValue > &V, StringRef Default={})
Take an optional DWARFFormValue and try to extract a string value from it.
uint64_t computeTombstoneAddress(uint8_t AddressByteSize)
Scope
Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...
FormattedNumber hexValue(uint64_t N, unsigned Width=HEX_WIDTH, bool Upper=false)
std::string hexString(uint64_t Value, size_t Width=HEX_WIDTH)
constexpr unsigned int DWARF_CHAR_BIT
LLVM_ABI std::string transformPath(StringRef Path)
std::pair< LVAddress, LVAddress > LVAddressRange
constexpr bool UpdateHighAddress
DWARFAbbreviationDeclaration::AttributeSpec AttributeSpec
content_iterator< SectionRef > section_iterator
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
DWARFExpression::Operation Op
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
void toHex(ArrayRef< uint8_t > Input, bool LowerCase, SmallVectorImpl< char > &Output)
Convert buffer Input to its hexadecimal representation. The returned string is double the size of Inp...
LLVM_ABI bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS, DIDumpOptions DumpOpts, uint8_t Opcode, ArrayRef< uint64_t > Operands)
Pretty print a register opcode and operands.
void consumeError(Error Err)
Consume a Error without doing anything.
StringRef toStringRef(bool B)
Construct a string ref from a boolean.
std::vector< DWARFAddressRange > DWARFAddressRangesVector
DWARFAddressRangesVector - represents a set of absolute address ranges.
Container for dump options that control which debug information will be dumped.
std::function< llvm::StringRef(uint64_t DwarfRegNum, bool IsEH)> GetNameForDWARFReg
bool isImplicitConst() const
int64_t getImplicitConstValue() const
static LLVM_ABI bool mayHaveLocationList(dwarf::Attribute Attr)
Identify DWARF attributes that may contain a pointer to a location list.
static LLVM_ABI bool mayHaveLocationExpr(dwarf::Attribute Attr)
Identifies DWARF attributes that may contain a reference to a DWARF expression.
SmallVector< uint8_t, 4 > Expr
The expression itself.
static const uint64_t UndefSection
A source language supported by any of the debug info representations.