diff options
Diffstat (limited to 'include/llvm/DebugInfo')
50 files changed, 1653 insertions, 415 deletions
diff --git a/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h b/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h index 7d20bb0a7bde..7538cb2c2548 100644 --- a/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h +++ b/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h @@ -11,7 +11,6 @@ #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" #include "llvm/Support/Error.h" namespace llvm { @@ -31,9 +30,6 @@ enum VisitorDataSource { Error visitTypeRecord(CVType &Record, TypeIndex Index, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source = VDS_BytesPresent); -Error visitTypeRecord(CVType &Record, TypeIndex Index, - TypeVisitorCallbackPipeline &Callbacks, - VisitorDataSource Source = VDS_BytesPresent); Error visitTypeRecord(CVType &Record, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source = VDS_BytesPresent); diff --git a/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h b/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h index 00fb0cf4cc90..60829a51dc25 100644 --- a/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h +++ b/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h @@ -33,6 +33,9 @@ public: virtual void EmitIntValue(uint64_t Value, unsigned Size) = 0; virtual void EmitBinaryData(StringRef Data) = 0; virtual void AddComment(const Twine &T) = 0; + virtual void AddRawComment(const Twine &T) = 0; + virtual bool isVerboseAsm() = 0; + virtual std::string getTypeName(TypeIndex TI) = 0; virtual ~CodeViewRecordStreamer() = default; }; @@ -206,6 +209,11 @@ public: return 0; } + void emitRawComment(const Twine &T) { + if (isStreaming() && Streamer->isVerboseAsm()) + Streamer->AddRawComment(T); + } + private: void emitEncodedSignedInteger(const int64_t &Value, const Twine &Comment = ""); @@ -225,9 +233,10 @@ private: } void emitComment(const Twine &Comment) { - if (isStreaming()) { + if (isStreaming() && Streamer->isVerboseAsm()) { Twine TComment(Comment); - Streamer->AddComment(TComment); + if (!TComment.isTriviallyEmpty()) + Streamer->AddComment(TComment); } } diff --git a/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def b/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def index 9767e49c44f5..ed5c143818e6 100644 --- a/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def +++ b/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def @@ -366,8 +366,134 @@ CV_REGISTER(AMD64_K7, 765) #endif // defined(CV_REGISTERS_ALL) || defined(CV_REGISTERS_X86) +#if defined(CV_REGISTERS_ALL) || defined(CV_REGISTERS_ARM) + +// ARM registers + +CV_REGISTER(ARM_NOREG, 0) + +// General purpose 32-bit integer regisers + +CV_REGISTER(ARM_R0, 10) +CV_REGISTER(ARM_R1, 11) +CV_REGISTER(ARM_R2, 12) +CV_REGISTER(ARM_R3, 13) +CV_REGISTER(ARM_R4, 14) +CV_REGISTER(ARM_R5, 15) +CV_REGISTER(ARM_R6, 16) +CV_REGISTER(ARM_R7, 17) +CV_REGISTER(ARM_R8, 18) +CV_REGISTER(ARM_R9, 19) +CV_REGISTER(ARM_R10, 20) +CV_REGISTER(ARM_R11, 21) +CV_REGISTER(ARM_R12, 22) +CV_REGISTER(ARM_SP, 23) +CV_REGISTER(ARM_LR, 24) +CV_REGISTER(ARM_PC, 25) + +// Status register + +CV_REGISTER(ARM_CPSR, 25) + +// ARM VFPv1 registers + +CV_REGISTER(ARM_FPSCR, 40) +CV_REGISTER(ARM_FPEXC, 41) + +// ARM VFPv3/NEON registers + +CV_REGISTER(ARM_FS32, 200) +CV_REGISTER(ARM_FS33, 201) +CV_REGISTER(ARM_FS34, 202) +CV_REGISTER(ARM_FS35, 203) +CV_REGISTER(ARM_FS36, 204) +CV_REGISTER(ARM_FS37, 205) +CV_REGISTER(ARM_FS38, 206) +CV_REGISTER(ARM_FS39, 207) +CV_REGISTER(ARM_FS40, 208) +CV_REGISTER(ARM_FS41, 209) +CV_REGISTER(ARM_FS42, 210) +CV_REGISTER(ARM_FS43, 211) +CV_REGISTER(ARM_FS44, 212) +CV_REGISTER(ARM_FS45, 213) +CV_REGISTER(ARM_FS46, 214) +CV_REGISTER(ARM_FS47, 215) +CV_REGISTER(ARM_FS48, 216) +CV_REGISTER(ARM_FS49, 217) +CV_REGISTER(ARM_FS50, 218) +CV_REGISTER(ARM_FS51, 219) +CV_REGISTER(ARM_FS52, 220) +CV_REGISTER(ARM_FS53, 221) +CV_REGISTER(ARM_FS54, 222) +CV_REGISTER(ARM_FS55, 223) +CV_REGISTER(ARM_FS56, 224) +CV_REGISTER(ARM_FS57, 225) +CV_REGISTER(ARM_FS58, 226) +CV_REGISTER(ARM_FS59, 227) +CV_REGISTER(ARM_FS60, 228) +CV_REGISTER(ARM_FS61, 229) +CV_REGISTER(ARM_FS62, 230) +CV_REGISTER(ARM_FS63, 231) + +CV_REGISTER(ARM_ND0, 300) +CV_REGISTER(ARM_ND1, 301) +CV_REGISTER(ARM_ND2, 302) +CV_REGISTER(ARM_ND3, 303) +CV_REGISTER(ARM_ND4, 304) +CV_REGISTER(ARM_ND5, 305) +CV_REGISTER(ARM_ND6, 306) +CV_REGISTER(ARM_ND7, 307) +CV_REGISTER(ARM_ND8, 308) +CV_REGISTER(ARM_ND9, 309) +CV_REGISTER(ARM_ND10, 310) +CV_REGISTER(ARM_ND11, 311) +CV_REGISTER(ARM_ND12, 312) +CV_REGISTER(ARM_ND13, 313) +CV_REGISTER(ARM_ND14, 314) +CV_REGISTER(ARM_ND15, 315) +CV_REGISTER(ARM_ND16, 316) +CV_REGISTER(ARM_ND17, 317) +CV_REGISTER(ARM_ND18, 318) +CV_REGISTER(ARM_ND19, 319) +CV_REGISTER(ARM_ND20, 320) +CV_REGISTER(ARM_ND21, 321) +CV_REGISTER(ARM_ND22, 322) +CV_REGISTER(ARM_ND23, 323) +CV_REGISTER(ARM_ND24, 324) +CV_REGISTER(ARM_ND25, 325) +CV_REGISTER(ARM_ND26, 326) +CV_REGISTER(ARM_ND27, 327) +CV_REGISTER(ARM_ND28, 328) +CV_REGISTER(ARM_ND29, 329) +CV_REGISTER(ARM_ND30, 330) +CV_REGISTER(ARM_ND31, 331) + +CV_REGISTER(ARM_NQ0, 400) +CV_REGISTER(ARM_NQ1, 401) +CV_REGISTER(ARM_NQ2, 402) +CV_REGISTER(ARM_NQ3, 403) +CV_REGISTER(ARM_NQ4, 404) +CV_REGISTER(ARM_NQ5, 405) +CV_REGISTER(ARM_NQ6, 406) +CV_REGISTER(ARM_NQ7, 407) +CV_REGISTER(ARM_NQ8, 408) +CV_REGISTER(ARM_NQ9, 409) +CV_REGISTER(ARM_NQ10, 410) +CV_REGISTER(ARM_NQ11, 411) +CV_REGISTER(ARM_NQ12, 412) +CV_REGISTER(ARM_NQ13, 413) +CV_REGISTER(ARM_NQ14, 414) +CV_REGISTER(ARM_NQ15, 415) + +#endif // defined(CV_REGISTERS_ALL) || defined(CV_REGISTERS_ARM) + #if defined(CV_REGISTERS_ALL) || defined(CV_REGISTERS_ARM64) +// arm64intr.h from MSVC defines ARM64_FPSR, which conflicts with +// these declarations. +#pragma push_macro("ARM64_FPSR") +#undef ARM64_FPSR + // ARM64 registers CV_REGISTER(ARM64_NOREG, 0) @@ -556,4 +682,6 @@ CV_REGISTER(ARM64_Q31, 211) CV_REGISTER(ARM64_FPSR, 220) +#pragma pop_macro("ARM64_FPSR") + #endif // defined(CV_REGISTERS_ALL) || defined(CV_REGISTERS_ARM64) diff --git a/include/llvm/DebugInfo/CodeView/EnumTables.h b/include/llvm/DebugInfo/CodeView/EnumTables.h index ed126ed9e2ff..270cd4b8330c 100644 --- a/include/llvm/DebugInfo/CodeView/EnumTables.h +++ b/include/llvm/DebugInfo/CodeView/EnumTables.h @@ -37,6 +37,17 @@ ArrayRef<EnumEntry<uint8_t>> getThunkOrdinalNames(); ArrayRef<EnumEntry<uint16_t>> getTrampolineNames(); ArrayRef<EnumEntry<COFF::SectionCharacteristics>> getImageSectionCharacteristicNames(); +ArrayRef<EnumEntry<uint16_t>> getClassOptionNames(); +ArrayRef<EnumEntry<uint8_t>> getMemberAccessNames(); +ArrayRef<EnumEntry<uint16_t>> getMethodOptionNames(); +ArrayRef<EnumEntry<uint16_t>> getMemberKindNames(); +ArrayRef<EnumEntry<uint8_t>> getPtrKindNames(); +ArrayRef<EnumEntry<uint8_t>> getPtrModeNames(); +ArrayRef<EnumEntry<uint16_t>> getPtrMemberRepNames(); +ArrayRef<EnumEntry<uint16_t>> getTypeModifierNames(); +ArrayRef<EnumEntry<uint8_t>> getCallingConventions(); +ArrayRef<EnumEntry<uint8_t>> getFunctionOptionEnum(); +ArrayRef<EnumEntry<uint16_t>> getLabelTypeEnum(); } // end namespace codeview } // end namespace llvm diff --git a/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h b/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h index 62761cb87c81..108abb291498 100644 --- a/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h +++ b/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h @@ -62,7 +62,7 @@ public: Error visitSymbolBegin(CVSymbol &Record) override { assert(!Mapping && "Already in a symbol mapping!"); - Mapping = llvm::make_unique<MappingInfo>(Record.content(), Container); + Mapping = std::make_unique<MappingInfo>(Record.content(), Container); return Mapping->Mapping.visitSymbolBegin(Record); } Error visitSymbolEnd(CVSymbol &Record) override { diff --git a/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/include/llvm/DebugInfo/CodeView/SymbolRecord.h index 5e9a7432b9b6..1aafa3ca9f1d 100644 --- a/include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ b/include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -73,17 +73,17 @@ public: Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset) : SymbolRecord(Kind), RecordOffset(RecordOffset) {} - uint32_t Parent; - uint32_t End; - uint32_t Next; - uint32_t Offset; - uint16_t Segment; - uint16_t Length; + uint32_t Parent = 0; + uint32_t End = 0; + uint32_t Next = 0; + uint32_t Offset = 0; + uint16_t Segment = 0; + uint16_t Length = 0; ThunkOrdinal Thunk; StringRef Name; ArrayRef<uint8_t> VariantData; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_TRAMPOLINE @@ -94,13 +94,13 @@ public: : SymbolRecord(Kind), RecordOffset(RecordOffset) {} TrampolineType Type; - uint16_t Size; - uint32_t ThunkOffset; - uint32_t TargetOffset; - uint16_t ThunkSection; - uint16_t TargetSection; + uint16_t Size = 0; + uint32_t ThunkOffset = 0; + uint32_t TargetOffset = 0; + uint16_t ThunkSection = 0; + uint16_t TargetSection = 0; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_SECTION @@ -110,14 +110,14 @@ public: SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset) : SymbolRecord(Kind), RecordOffset(RecordOffset) {} - uint16_t SectionNumber; - uint8_t Alignment; - uint32_t Rva; - uint32_t Length; - uint32_t Characteristics; + uint16_t SectionNumber = 0; + uint8_t Alignment = 0; + uint32_t Rva = 0; + uint32_t Length = 0; + uint32_t Characteristics = 0; StringRef Name; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_COFFGROUP @@ -127,13 +127,13 @@ public: CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset) : SymbolRecord(Kind), RecordOffset(RecordOffset) {} - uint32_t Size; - uint32_t Characteristics; - uint32_t Offset; - uint16_t Segment; + uint32_t Size = 0; + uint32_t Characteristics = 0; + uint32_t Offset = 0; + uint16_t Segment = 0; StringRef Name; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; class ScopeEndSym : public SymbolRecord { @@ -142,7 +142,7 @@ public: ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset) : SymbolRecord(Kind), RecordOffset(RecordOffset) {} - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; class CallerSym : public SymbolRecord { @@ -153,7 +153,7 @@ public: std::vector<TypeIndex> Indices; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; struct DecodedAnnotation { @@ -333,7 +333,7 @@ private: class InlineSiteSym : public SymbolRecord { public: explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} - InlineSiteSym(uint32_t RecordOffset) + explicit InlineSiteSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::InlineSiteSym), RecordOffset(RecordOffset) {} @@ -342,12 +342,12 @@ public: BinaryAnnotationIterator()); } - uint32_t Parent; - uint32_t End; + uint32_t Parent = 0; + uint32_t End = 0; TypeIndex Inlinee; std::vector<uint8_t> AnnotationData; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_PUB32 @@ -371,7 +371,7 @@ public: class RegisterSym : public SymbolRecord { public: explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} - RegisterSym(uint32_t RecordOffset) + explicit RegisterSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::RegisterSym), RecordOffset(RecordOffset) {} @@ -379,7 +379,7 @@ public: RegisterId Register; StringRef Name; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_PROCREF, S_LPROCREF @@ -390,13 +390,13 @@ public: : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset) { } - uint32_t SumName; - uint32_t SymOffset; - uint16_t Module; + uint32_t SumName = 0; + uint32_t SymOffset = 0; + uint16_t Module = 0; StringRef Name; uint16_t modi() const { return Module - 1; } - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_LOCAL @@ -410,7 +410,7 @@ public: LocalSymFlags Flags; StringRef Name; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; struct LocalVariableAddrRange { @@ -440,11 +440,11 @@ public: return RecordOffset + RelocationOffset; } - uint32_t Program; + uint32_t Program = 0; LocalVariableAddrRange Range; std::vector<LocalVariableAddrGap> Gaps; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_DEFRANGE_SUBFIELD @@ -453,7 +453,7 @@ class DefRangeSubfieldSym : public SymbolRecord { public: explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} - DefRangeSubfieldSym(uint32_t RecordOffset) + explicit DefRangeSubfieldSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym), RecordOffset(RecordOffset) {} @@ -461,58 +461,62 @@ public: return RecordOffset + RelocationOffset; } - uint32_t Program; - uint16_t OffsetInParent; + uint32_t Program = 0; + uint16_t OffsetInParent = 0; LocalVariableAddrRange Range; std::vector<LocalVariableAddrGap> Gaps; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; +}; + +struct DefRangeRegisterHeader { + ulittle16_t Register; + ulittle16_t MayHaveNoName; }; // S_DEFRANGE_REGISTER class DefRangeRegisterSym : public SymbolRecord { public: - struct Header { - ulittle16_t Register; - ulittle16_t MayHaveNoName; - }; - explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} - DefRangeRegisterSym(uint32_t RecordOffset) + explicit DefRangeRegisterSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym), RecordOffset(RecordOffset) {} - uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); } + uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeRegisterHeader); } - Header Hdr; + DefRangeRegisterHeader Hdr; LocalVariableAddrRange Range; std::vector<LocalVariableAddrGap> Gaps; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; +}; + +struct DefRangeSubfieldRegisterHeader { + ulittle16_t Register; + ulittle16_t MayHaveNoName; + ulittle32_t OffsetInParent; }; // S_DEFRANGE_SUBFIELD_REGISTER class DefRangeSubfieldRegisterSym : public SymbolRecord { public: - struct Header { - ulittle16_t Register; - ulittle16_t MayHaveNoName; - ulittle32_t OffsetInParent; - }; - explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} - DefRangeSubfieldRegisterSym(uint32_t RecordOffset) + explicit DefRangeSubfieldRegisterSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym), RecordOffset(RecordOffset) {} - uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); } + uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeSubfieldRegisterHeader); } - Header Hdr; + DefRangeSubfieldRegisterHeader Hdr; LocalVariableAddrRange Range; std::vector<LocalVariableAddrGap> Gaps; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; +}; + +struct DefRangeFramePointerRelHeader { + little32_t Offset; }; // S_DEFRANGE_FRAMEPOINTER_REL @@ -522,7 +526,7 @@ class DefRangeFramePointerRelSym : public SymbolRecord { public: explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} - DefRangeFramePointerRelSym(uint32_t RecordOffset) + explicit DefRangeFramePointerRelSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym), RecordOffset(RecordOffset) {} @@ -530,22 +534,22 @@ public: return RecordOffset + RelocationOffset; } - int32_t Offset; + DefRangeFramePointerRelHeader Hdr; LocalVariableAddrRange Range; std::vector<LocalVariableAddrGap> Gaps; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; +}; + +struct DefRangeRegisterRelHeader { + ulittle16_t Register; + ulittle16_t Flags; + little32_t BasePointerOffset; }; // S_DEFRANGE_REGISTER_REL class DefRangeRegisterRelSym : public SymbolRecord { public: - struct Header { - ulittle16_t Register; - ulittle16_t Flags; - little32_t BasePointerOffset; - }; - explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} explicit DefRangeRegisterRelSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym), @@ -563,13 +567,13 @@ public: bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; } uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; } - uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); } + uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeRegisterRelHeader); } - Header Hdr; + DefRangeRegisterRelHeader Hdr; LocalVariableAddrRange Range; std::vector<LocalVariableAddrGap> Gaps; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE @@ -581,9 +585,9 @@ public: : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym), RecordOffset(RecordOffset) {} - int32_t Offset; + int32_t Offset = 0; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_BLOCK32 @@ -599,14 +603,14 @@ public: return RecordOffset + RelocationOffset; } - uint32_t Parent; - uint32_t End; - uint32_t CodeSize; - uint32_t CodeOffset; - uint16_t Segment; + uint32_t Parent = 0; + uint32_t End = 0; + uint32_t CodeSize = 0; + uint32_t CodeOffset = 0; + uint16_t Segment = 0; StringRef Name; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_LABEL32 @@ -622,12 +626,12 @@ public: return RecordOffset + RelocationOffset; } - uint32_t CodeOffset; - uint16_t Segment; + uint32_t CodeOffset = 0; + uint16_t Segment = 0; ProcSymFlags Flags; StringRef Name; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_OBJNAME @@ -635,82 +639,82 @@ class ObjNameSym : public SymbolRecord { public: explicit ObjNameSym() : SymbolRecord(SymbolRecordKind::ObjNameSym) {} explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} - ObjNameSym(uint32_t RecordOffset) + explicit ObjNameSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset) { } - uint32_t Signature; + uint32_t Signature = 0; StringRef Name; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_ENVBLOCK class EnvBlockSym : public SymbolRecord { public: explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} - EnvBlockSym(uint32_t RecordOffset) + explicit EnvBlockSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::EnvBlockSym), RecordOffset(RecordOffset) {} std::vector<StringRef> Fields; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_EXPORT class ExportSym : public SymbolRecord { public: explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} - ExportSym(uint32_t RecordOffset) + explicit ExportSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset) {} - uint16_t Ordinal; + uint16_t Ordinal = 0; ExportFlags Flags; StringRef Name; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_FILESTATIC class FileStaticSym : public SymbolRecord { public: explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} - FileStaticSym(uint32_t RecordOffset) + explicit FileStaticSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::FileStaticSym), RecordOffset(RecordOffset) {} TypeIndex Index; - uint32_t ModFilenameOffset; + uint32_t ModFilenameOffset = 0; LocalSymFlags Flags; StringRef Name; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_COMPILE2 class Compile2Sym : public SymbolRecord { public: explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} - Compile2Sym(uint32_t RecordOffset) + explicit Compile2Sym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::Compile2Sym), RecordOffset(RecordOffset) {} CompileSym2Flags Flags; CPUType Machine; - uint16_t VersionFrontendMajor; - uint16_t VersionFrontendMinor; - uint16_t VersionFrontendBuild; - uint16_t VersionBackendMajor; - uint16_t VersionBackendMinor; - uint16_t VersionBackendBuild; + uint16_t VersionFrontendMajor = 0; + uint16_t VersionFrontendMinor = 0; + uint16_t VersionFrontendBuild = 0; + uint16_t VersionBackendMajor = 0; + uint16_t VersionBackendMinor = 0; + uint16_t VersionBackendBuild = 0; StringRef Version; std::vector<StringRef> ExtraStrings; uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; } uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; } - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_COMPILE3 @@ -718,20 +722,20 @@ class Compile3Sym : public SymbolRecord { public: Compile3Sym() : SymbolRecord(SymbolRecordKind::Compile3Sym) {} explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} - Compile3Sym(uint32_t RecordOffset) + explicit Compile3Sym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::Compile3Sym), RecordOffset(RecordOffset) {} CompileSym3Flags Flags; CPUType Machine; - uint16_t VersionFrontendMajor; - uint16_t VersionFrontendMinor; - uint16_t VersionFrontendBuild; - uint16_t VersionFrontendQFE; - uint16_t VersionBackendMajor; - uint16_t VersionBackendMinor; - uint16_t VersionBackendBuild; - uint16_t VersionBackendQFE; + uint16_t VersionFrontendMajor = 0; + uint16_t VersionFrontendMinor = 0; + uint16_t VersionFrontendBuild = 0; + uint16_t VersionFrontendQFE = 0; + uint16_t VersionBackendMajor = 0; + uint16_t VersionBackendMinor = 0; + uint16_t VersionBackendBuild = 0; + uint16_t VersionBackendQFE = 0; StringRef Version; void setLanguage(SourceLanguage Lang) { @@ -750,7 +754,7 @@ public: (getFlags() & (CompileSym3Flags::PGO | CompileSym3Flags::LTCG)); } - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_FRAMEPROC @@ -761,12 +765,12 @@ public: : SymbolRecord(SymbolRecordKind::FrameProcSym), RecordOffset(RecordOffset) {} - uint32_t TotalFrameBytes; - uint32_t PaddingFrameBytes; - uint32_t OffsetToPadding; - uint32_t BytesOfCalleeSavedRegisters; - uint32_t OffsetOfExceptionHandler; - uint16_t SectionIdOfExceptionHandler; + uint32_t TotalFrameBytes = 0; + uint32_t PaddingFrameBytes = 0; + uint32_t OffsetToPadding = 0; + uint32_t BytesOfCalleeSavedRegisters = 0; + uint32_t OffsetOfExceptionHandler = 0; + uint16_t SectionIdOfExceptionHandler = 0; FrameProcedureOptions Flags; /// Extract the register this frame uses to refer to local variables. @@ -781,7 +785,7 @@ public: EncodedFramePtrReg((uint32_t(Flags) >> 16U) & 0x3U), CPU); } - uint32_t RecordOffset; + uint32_t RecordOffset = 0; private: }; @@ -799,11 +803,11 @@ public: return RecordOffset + RelocationOffset; } - uint32_t CodeOffset; - uint16_t Segment; + uint32_t CodeOffset = 0; + uint16_t Segment = 0; TypeIndex Type; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_HEAPALLOCSITE @@ -820,12 +824,12 @@ public: return RecordOffset + RelocationOffset; } - uint32_t CodeOffset; - uint16_t Segment; - uint16_t CallInstructionSize; + uint32_t CodeOffset = 0; + uint16_t Segment = 0; + uint16_t CallInstructionSize = 0; TypeIndex Type; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_FRAMECOOKIE @@ -841,12 +845,12 @@ public: return RecordOffset + RelocationOffset; } - uint32_t CodeOffset; - uint16_t Register; + uint32_t CodeOffset = 0; + uint16_t Register = 0; FrameCookieKind CookieKind; - uint8_t Flags; + uint8_t Flags = 0; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_UDT, S_COBOLUDT @@ -859,20 +863,20 @@ public: TypeIndex Type; StringRef Name; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_BUILDINFO class BuildInfoSym : public SymbolRecord { public: explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} - BuildInfoSym(uint32_t RecordOffset) + explicit BuildInfoSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::BuildInfoSym), RecordOffset(RecordOffset) {} TypeIndex BuildId; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_BPREL32 @@ -883,11 +887,11 @@ public: : SymbolRecord(SymbolRecordKind::BPRelativeSym), RecordOffset(RecordOffset) {} - int32_t Offset; + int32_t Offset = 0; TypeIndex Type; StringRef Name; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_REGREL32 @@ -898,19 +902,19 @@ public: : SymbolRecord(SymbolRecordKind::RegRelativeSym), RecordOffset(RecordOffset) {} - uint32_t Offset; + uint32_t Offset = 0; TypeIndex Type; RegisterId Register; StringRef Name; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_CONSTANT, S_MANCONSTANT class ConstantSym : public SymbolRecord { public: explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} - ConstantSym(uint32_t RecordOffset) + explicit ConstantSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::ConstantSym), RecordOffset(RecordOffset) {} @@ -918,7 +922,7 @@ public: APSInt Value; StringRef Name; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA @@ -927,7 +931,7 @@ class DataSym : public SymbolRecord { public: explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} - DataSym(uint32_t RecordOffset) + explicit DataSym(uint32_t RecordOffset) : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset) {} uint32_t getRelocationOffset() const { @@ -935,11 +939,11 @@ public: } TypeIndex Type; - uint32_t DataOffset; - uint16_t Segment; + uint32_t DataOffset = 0; + uint16_t Segment = 0; StringRef Name; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_LTHREAD32, S_GTHREAD32 @@ -957,11 +961,11 @@ public: } TypeIndex Type; - uint32_t DataOffset; - uint16_t Segment; + uint32_t DataOffset = 0; + uint16_t Segment = 0; StringRef Name; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_UNAMESPACE @@ -974,7 +978,7 @@ public: StringRef Name; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; // S_ANNOTATION @@ -989,7 +993,7 @@ public: uint16_t Segment = 0; std::vector<StringRef> Strings; - uint32_t RecordOffset; + uint32_t RecordOffset = 0; }; using CVSymbol = CVRecord<SymbolKind>; diff --git a/include/llvm/DebugInfo/CodeView/TypeDeserializer.h b/include/llvm/DebugInfo/CodeView/TypeDeserializer.h index 081de32dd02c..2b17f5ccb13b 100644 --- a/include/llvm/DebugInfo/CodeView/TypeDeserializer.h +++ b/include/llvm/DebugInfo/CodeView/TypeDeserializer.h @@ -66,7 +66,7 @@ public: Error visitTypeBegin(CVType &Record) override { assert(!Mapping && "Already in a type mapping!"); - Mapping = llvm::make_unique<MappingInfo>(Record.content()); + Mapping = std::make_unique<MappingInfo>(Record.content()); return Mapping->Mapping.visitTypeBegin(Record); } diff --git a/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h b/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h index 4c309c10ff0c..c6044d5138a8 100644 --- a/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h +++ b/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h @@ -10,6 +10,7 @@ #define LLVM_DEBUGINFO_CODEVIEW_TYPERECORDMAPPING_H #include "llvm/ADT/Optional.h" +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" #include "llvm/Support/Error.h" diff --git a/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h b/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h index 169715be2d52..fb0b579d6a06 100644 --- a/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h +++ b/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h @@ -82,11 +82,6 @@ public: Pipeline.push_back(&Callbacks); } - void addCallbackToPipelineFront(TypeVisitorCallbacks &Callbacks) { - auto CallBackItr = Pipeline.begin(); - Pipeline.insert(CallBackItr, &Callbacks); - } - #define TYPE_RECORD(EnumName, EnumVal, Name) \ Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \ return visitKnownRecordImpl(CVR, Record); \ diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h index d2a5318179eb..fbebfe634b63 100644 --- a/include/llvm/DebugInfo/DIContext.h +++ b/include/llvm/DebugInfo/DIContext.h @@ -28,6 +28,10 @@ namespace llvm { /// A format-neutral container for source line information. struct DILineInfo { + // DILineInfo contains "<invalid>" for function/filename it cannot fetch. + static constexpr const char *const BadString = "<invalid>"; + // Use "??" instead of "<invalid>" to make our output closer to addr2line. + static constexpr const char *const Addr2LineBadString = "??"; std::string FileName; std::string FunctionName; Optional<StringRef> Source; @@ -38,7 +42,7 @@ struct DILineInfo { // DWARF-specific. uint32_t Discriminator = 0; - DILineInfo() : FileName("<invalid>"), FunctionName("<invalid>") {} + DILineInfo() : FileName(BadString), FunctionName(BadString) {} bool operator==(const DILineInfo &RHS) const { return Line == RHS.Line && Column == RHS.Column && @@ -61,9 +65,9 @@ struct DILineInfo { void dump(raw_ostream &OS) { OS << "Line info: "; - if (FileName != "<invalid>") + if (FileName != BadString) OS << "file '" << FileName << "', "; - if (FunctionName != "<invalid>") + if (FunctionName != BadString) OS << "function '" << FunctionName << "', "; OS << "line " << Line << ", "; OS << "column " << Column << ", "; @@ -109,7 +113,7 @@ struct DIGlobal { uint64_t Start = 0; uint64_t Size = 0; - DIGlobal() : Name("<invalid>") {} + DIGlobal() : Name(DILineInfo::BadString) {} }; struct DILocal { @@ -289,7 +293,7 @@ public: LoadedObjectInfoHelper(Ts &&... Args) : Base(std::forward<Ts>(Args)...) {} std::unique_ptr<llvm::LoadedObjectInfo> clone() const override { - return llvm::make_unique<Derived>(static_cast<const Derived &>(*this)); + return std::make_unique<Derived>(static_cast<const Derived &>(*this)); } }; diff --git a/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h index ccf2891c2e21..39ae53c4e7fe 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h +++ b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h @@ -130,11 +130,11 @@ public: /// \param Attr DWARF attribute to search for. /// \param U the DWARFUnit the contains the DIE. /// \returns Optional DWARF form value if the attribute was extracted. - Optional<DWARFFormValue> getAttributeValue(const uint32_t DIEOffset, + Optional<DWARFFormValue> getAttributeValue(const uint64_t DIEOffset, const dwarf::Attribute Attr, const DWARFUnit &U) const; - bool extract(DataExtractor Data, uint32_t* OffsetPtr); + bool extract(DataExtractor Data, uint64_t* OffsetPtr); void dump(raw_ostream &OS) const; // Return an optional byte size of all attribute data in this abbreviation diff --git a/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h index 303375703d2e..c9042e593260 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h +++ b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h @@ -96,7 +96,7 @@ class AppleAcceleratorTable : public DWARFAcceleratorTable { using AtomType = uint16_t; using Form = dwarf::Form; - uint32_t DIEOffsetBase; + uint64_t DIEOffsetBase; SmallVector<std::pair<AtomType, Form>, 3> Atoms; Optional<uint64_t> extractOffset(Optional<DWARFFormValue> Value) const; @@ -109,7 +109,7 @@ class AppleAcceleratorTable : public DWARFAcceleratorTable { /// Returns true if we should continue scanning for entries or false if we've /// reached the last (sentinel) entry of encountered a parsing error. bool dumpName(ScopedPrinter &W, SmallVectorImpl<DWARFFormValue> &AtomForms, - uint32_t *DataOffset) const; + uint64_t *DataOffset) const; public: /// Apple-specific implementation of an Accelerator Entry. @@ -119,7 +119,7 @@ public: Entry(const HeaderData &Data); Entry() = default; - void extract(const AppleAcceleratorTable &AccelTable, uint32_t *Offset); + void extract(const AppleAcceleratorTable &AccelTable, uint64_t *Offset); public: Optional<uint64_t> getCUOffset() const override; @@ -143,7 +143,7 @@ public: class ValueIterator : public std::iterator<std::input_iterator_tag, Entry> { const AppleAcceleratorTable *AccelTable = nullptr; Entry Current; ///< The current entry. - unsigned DataOffset = 0; ///< Offset into the section. + uint64_t DataOffset = 0; ///< Offset into the section. unsigned Data = 0; ///< Current data entry. unsigned NumData = 0; ///< Number of data entries. @@ -151,7 +151,7 @@ public: void Next(); public: /// Construct a new iterator for the entries at \p DataOffset. - ValueIterator(const AppleAcceleratorTable &AccelTable, unsigned DataOffset); + ValueIterator(const AppleAcceleratorTable &AccelTable, uint64_t DataOffset); /// End marker. ValueIterator() = default; @@ -193,7 +193,7 @@ public: /// DieOffset is the offset into the .debug_info section for the DIE /// related to the input hash data offset. /// DieTag is the tag of the DIE - std::pair<uint32_t, dwarf::Tag> readAtoms(uint32_t &HashDataOffset); + std::pair<uint64_t, dwarf::Tag> readAtoms(uint64_t *HashDataOffset); void dump(raw_ostream &OS) const override; /// Look up all entries in the accelerator table matching \c Key. @@ -245,7 +245,7 @@ public: struct Header : public HeaderPOD { SmallString<8> AugmentationString; - Error extract(const DWARFDataExtractor &AS, uint32_t *Offset); + Error extract(const DWARFDataExtractor &AS, uint64_t *Offset); void dump(ScopedPrinter &W) const; }; @@ -354,12 +354,12 @@ public: DataExtractor StrData; uint32_t Index; - uint32_t StringOffset; - uint32_t EntryOffset; + uint64_t StringOffset; + uint64_t EntryOffset; public: NameTableEntry(const DataExtractor &StrData, uint32_t Index, - uint32_t StringOffset, uint32_t EntryOffset) + uint64_t StringOffset, uint64_t EntryOffset) : StrData(StrData), Index(Index), StringOffset(StringOffset), EntryOffset(EntryOffset) {} @@ -367,17 +367,17 @@ public: uint32_t getIndex() const { return Index; } /// Returns the offset of the name of the described entities. - uint32_t getStringOffset() const { return StringOffset; } + uint64_t getStringOffset() const { return StringOffset; } /// Return the string referenced by this name table entry or nullptr if the /// string offset is not valid. const char *getString() const { - uint32_t Off = StringOffset; + uint64_t Off = StringOffset; return StrData.getCStr(&Off); } /// Returns the offset of the first Entry in the list. - uint32_t getEntryOffset() const { return EntryOffset; } + uint64_t getEntryOffset() const { return EntryOffset; } }; /// Represents a single accelerator table within the DWARF v5 .debug_names @@ -389,40 +389,40 @@ public: // Base of the whole unit and of various important tables, as offsets from // the start of the section. - uint32_t Base; - uint32_t CUsBase; - uint32_t BucketsBase; - uint32_t HashesBase; - uint32_t StringOffsetsBase; - uint32_t EntryOffsetsBase; - uint32_t EntriesBase; + uint64_t Base; + uint64_t CUsBase; + uint64_t BucketsBase; + uint64_t HashesBase; + uint64_t StringOffsetsBase; + uint64_t EntryOffsetsBase; + uint64_t EntriesBase; void dumpCUs(ScopedPrinter &W) const; void dumpLocalTUs(ScopedPrinter &W) const; void dumpForeignTUs(ScopedPrinter &W) const; void dumpAbbreviations(ScopedPrinter &W) const; - bool dumpEntry(ScopedPrinter &W, uint32_t *Offset) const; + bool dumpEntry(ScopedPrinter &W, uint64_t *Offset) const; void dumpName(ScopedPrinter &W, const NameTableEntry &NTE, Optional<uint32_t> Hash) const; void dumpBucket(ScopedPrinter &W, uint32_t Bucket) const; - Expected<AttributeEncoding> extractAttributeEncoding(uint32_t *Offset); + Expected<AttributeEncoding> extractAttributeEncoding(uint64_t *Offset); Expected<std::vector<AttributeEncoding>> - extractAttributeEncodings(uint32_t *Offset); + extractAttributeEncodings(uint64_t *Offset); - Expected<Abbrev> extractAbbrev(uint32_t *Offset); + Expected<Abbrev> extractAbbrev(uint64_t *Offset); public: - NameIndex(const DWARFDebugNames &Section, uint32_t Base) + NameIndex(const DWARFDebugNames &Section, uint64_t Base) : Section(Section), Base(Base) {} /// Reads offset of compilation unit CU. CU is 0-based. - uint32_t getCUOffset(uint32_t CU) const; + uint64_t getCUOffset(uint32_t CU) const; uint32_t getCUCount() const { return Hdr.CompUnitCount; } /// Reads offset of local type unit TU, TU is 0-based. - uint32_t getLocalTUOffset(uint32_t TU) const; + uint64_t getLocalTUOffset(uint32_t TU) const; uint32_t getLocalTUCount() const { return Hdr.LocalTypeUnitCount; } /// Reads signature of foreign type unit TU. TU is 0-based. @@ -451,7 +451,7 @@ public: return Abbrevs; } - Expected<Entry> getEntry(uint32_t *Offset) const; + Expected<Entry> getEntry(uint64_t *Offset) const; /// Look up all entries in this Name Index matching \c Key. iterator_range<ValueIterator> equal_range(StringRef Key) const; @@ -460,8 +460,8 @@ public: NameIterator end() const { return NameIterator(this, getNameCount() + 1); } Error extract(); - uint32_t getUnitOffset() const { return Base; } - uint32_t getNextUnitOffset() const { return Base + 4 + Hdr.UnitLength; } + uint64_t getUnitOffset() const { return Base; } + uint64_t getNextUnitOffset() const { return Base + 4 + Hdr.UnitLength; } void dump(ScopedPrinter &W) const; friend class DWARFDebugNames; @@ -479,12 +479,12 @@ public: bool IsLocal; Optional<Entry> CurrentEntry; - unsigned DataOffset = 0; ///< Offset into the section. + uint64_t DataOffset = 0; ///< Offset into the section. std::string Key; ///< The Key we are searching for. Optional<uint32_t> Hash; ///< Hash of Key, if it has been computed. bool getEntryAtCurrentOffset(); - Optional<uint32_t> findEntryOffsetInCurrentIndex(); + Optional<uint64_t> findEntryOffsetInCurrentIndex(); bool findInCurrentIndex(); void searchFromStartOfCurrentIndex(); void next(); @@ -572,7 +572,7 @@ public: private: SmallVector<NameIndex, 0> NameIndices; - DenseMap<uint32_t, const NameIndex *> CUToNameIndex; + DenseMap<uint64_t, const NameIndex *> CUToNameIndex; public: DWARFDebugNames(const DWARFDataExtractor &AccelSection, @@ -591,7 +591,7 @@ public: /// Return the Name Index covering the compile unit at CUOffset, or nullptr if /// there is no Name Index covering that unit. - const NameIndex *getCUNameIndex(uint32_t CUOffset); + const NameIndex *getCUNameIndex(uint64_t CUOffset); }; } // end namespace llvm diff --git a/include/llvm/DebugInfo/DWARF/DWARFAttribute.h b/include/llvm/DebugInfo/DWARF/DWARFAttribute.h index c8ad19ad6bf6..dfc778346dbe 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFAttribute.h +++ b/include/llvm/DebugInfo/DWARF/DWARFAttribute.h @@ -23,7 +23,7 @@ namespace llvm { /// attributes in a DWARFDie. struct DWARFAttribute { /// The debug info/types offset for this attribute. - uint32_t Offset = 0; + uint64_t Offset = 0; /// The debug info/types section byte size of the data for this attribute. uint32_t ByteSize = 0; /// The attribute enumeration of this attribute. diff --git a/include/llvm/DebugInfo/DWARF/DWARFContext.h b/include/llvm/DebugInfo/DWARF/DWARFContext.h index 23cf21c3523f..fae163622edb 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ b/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -225,10 +225,10 @@ public: DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash); /// Return the compile unit that includes an offset (relative to .debug_info). - DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset); + DWARFCompileUnit *getCompileUnitForOffset(uint64_t Offset); /// Get a DIE given an exact offset. - DWARFDie getDIEForOffset(uint32_t Offset); + DWARFDie getDIEForOffset(uint64_t Offset); unsigned getMaxVersion() { // Ensure info units have been parsed to discover MaxVersion @@ -301,10 +301,10 @@ public: std::function<void(Error)> RecoverableErrorCallback); DataExtractor getStringExtractor() const { - return DataExtractor(DObj->getStringSection(), false, 0); + return DataExtractor(DObj->getStrSection(), false, 0); } DataExtractor getLineStringExtractor() const { - return DataExtractor(DObj->getLineStringSection(), false, 0); + return DataExtractor(DObj->getLineStrSection(), false, 0); } /// Wraps the returned DIEs for a given address. diff --git a/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h b/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h index 7c2a159b71fa..980724c525d2 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h @@ -35,20 +35,25 @@ public: /// Extracts a value and applies a relocation to the result if /// one exists for the given offset. - uint64_t getRelocatedValue(uint32_t Size, uint32_t *Off, - uint64_t *SectionIndex = nullptr) const; + uint64_t getRelocatedValue(uint32_t Size, uint64_t *Off, + uint64_t *SectionIndex = nullptr, + Error *Err = nullptr) const; /// Extracts an address-sized value and applies a relocation to the result if /// one exists for the given offset. - uint64_t getRelocatedAddress(uint32_t *Off, uint64_t *SecIx = nullptr) const { + uint64_t getRelocatedAddress(uint64_t *Off, uint64_t *SecIx = nullptr) const { return getRelocatedValue(getAddressSize(), Off, SecIx); } + uint64_t getRelocatedAddress(Cursor &C, uint64_t *SecIx = nullptr) const { + return getRelocatedValue(getAddressSize(), &getOffset(C), SecIx, + &getError(C)); + } /// Extracts a DWARF-encoded pointer in \p Offset using \p Encoding. /// There is a DWARF encoding that uses a PC-relative adjustment. /// For these values, \p AbsPosOffset is used to fix them, which should /// reflect the absolute address of this pointer. - Optional<uint64_t> getEncodedPointer(uint32_t *Offset, uint8_t Encoding, + Optional<uint64_t> getEncodedPointer(uint64_t *Offset, uint8_t Encoding, uint64_t AbsPosOffset = 0) const; size_t size() const { return Section == nullptr ? 0 : Section->Data.size(); } diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h b/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h index 28fd8484b4a9..1398e16252a9 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h @@ -20,7 +20,7 @@ namespace llvm { class raw_ostream; class DWARFAbbreviationDeclarationSet { - uint32_t Offset; + uint64_t Offset; /// Code of the first abbreviation, if all abbreviations in the set have /// consecutive codes. UINT32_MAX otherwise. uint32_t FirstAbbrCode; @@ -32,9 +32,9 @@ class DWARFAbbreviationDeclarationSet { public: DWARFAbbreviationDeclarationSet(); - uint32_t getOffset() const { return Offset; } + uint64_t getOffset() const { return Offset; } void dump(raw_ostream &OS) const; - bool extract(DataExtractor Data, uint32_t *OffsetPtr); + bool extract(DataExtractor Data, uint64_t *OffsetPtr); const DWARFAbbreviationDeclaration * getAbbreviationDeclaration(uint32_t AbbrCode) const; diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h b/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h index a98bf282fe7c..4539b9c9d581 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h @@ -45,7 +45,7 @@ public: private: dwarf::DwarfFormat Format; - uint32_t HeaderOffset; + uint64_t HeaderOffset; Header HeaderData; uint32_t DataSize = 0; std::vector<uint64_t> Addrs; @@ -54,11 +54,11 @@ public: void clear(); /// Extract an entire table, including all addresses. - Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr, + Error extract(DWARFDataExtractor Data, uint64_t *OffsetPtr, uint16_t Version, uint8_t AddrSize, std::function<void(Error)> WarnCallback); - uint32_t getHeaderOffset() const { return HeaderOffset; } + uint64_t getHeaderOffset() const { return HeaderOffset; } uint8_t getAddrSize() const { return HeaderData.AddrSize; } void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const; diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h b/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h index 5b6c578bc3bf..ebe4ad6e24dd 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h @@ -49,7 +49,7 @@ private: using DescriptorColl = std::vector<Descriptor>; using desc_iterator_range = iterator_range<DescriptorColl::const_iterator>; - uint32_t Offset; + uint64_t Offset; Header HeaderData; DescriptorColl ArangeDescriptors; @@ -57,7 +57,7 @@ public: DWARFDebugArangeSet() { clear(); } void clear(); - bool extract(DataExtractor data, uint32_t *offset_ptr); + bool extract(DataExtractor data, uint64_t *offset_ptr); void dump(raw_ostream &OS) const; uint32_t getCompileUnitDIEOffset() const { return HeaderData.CuOffset; } diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h b/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h index 03223fbc80a9..172f1d2c9dbe 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h @@ -28,7 +28,7 @@ private: void extract(DataExtractor DebugArangesData); /// Call appendRange multiple times and then call construct. - void appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC); + void appendRange(uint64_t CUOffset, uint64_t LowPC, uint64_t HighPC); void construct(); struct Range { @@ -60,10 +60,10 @@ private: struct RangeEndpoint { uint64_t Address; - uint32_t CUOffset; + uint64_t CUOffset; bool IsRangeStart; - RangeEndpoint(uint64_t Address, uint32_t CUOffset, bool IsRangeStart) + RangeEndpoint(uint64_t Address, uint64_t CUOffset, bool IsRangeStart) : Address(Address), CUOffset(CUOffset), IsRangeStart(IsRangeStart) {} bool operator<(const RangeEndpoint &Other) const { @@ -76,7 +76,7 @@ private: std::vector<RangeEndpoint> Endpoints; RangeColl Aranges; - DenseSet<uint32_t> ParsedCUOffsets; + DenseSet<uint64_t> ParsedCUOffsets; }; } // end namespace llvm diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h index d960f4bc9b1c..c6539df0d756 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h @@ -69,7 +69,7 @@ public: /// starting at *Offset and ending at EndOffset. *Offset is updated /// to EndOffset upon successful parsing, or indicates the offset /// where a problem occurred in case an error is returned. - Error parse(DataExtractor Data, uint32_t *Offset, uint32_t EndOffset); + Error parse(DWARFDataExtractor Data, uint64_t *Offset, uint64_t EndOffset); void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, unsigned IndentLevel = 1) const; diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h b/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h index f50063b24370..ded960337ec6 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h @@ -22,7 +22,7 @@ class DWARFUnit; /// DWARFDebugInfoEntry - A DIE with only the minimum required data. class DWARFDebugInfoEntry { /// Offset within the .debug_info of the start of this entry. - uint32_t Offset = 0; + uint64_t Offset = 0; /// The integer depth of this DIE within the compile unit DIEs where the /// compile/type unit DIE has a depth of zero. @@ -36,14 +36,14 @@ public: /// Extracts a debug info entry, which is a child of a given unit, /// starting at a given offset. If DIE can't be extracted, returns false and /// doesn't change OffsetPtr. - bool extractFast(const DWARFUnit &U, uint32_t *OffsetPtr); + bool extractFast(const DWARFUnit &U, uint64_t *OffsetPtr); /// High performance extraction should use this call. - bool extractFast(const DWARFUnit &U, uint32_t *OffsetPtr, - const DWARFDataExtractor &DebugInfoData, uint32_t UEndOffset, + bool extractFast(const DWARFUnit &U, uint64_t *OffsetPtr, + const DWARFDataExtractor &DebugInfoData, uint64_t UEndOffset, uint32_t Depth); - uint32_t getOffset() const { return Offset; } + uint64_t getOffset() const { return Offset; } uint32_t getDepth() const { return Depth; } dwarf::Tag getTag() const { diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h index e7425c192373..c2be8304ad84 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -18,6 +18,7 @@ #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" #include "llvm/Support/MD5.h" +#include "llvm/Support/Path.h" #include <cstdint> #include <map> #include <string> @@ -128,13 +129,15 @@ public: bool hasFileAtIndex(uint64_t FileIndex) const; - bool getFileNameByIndex(uint64_t FileIndex, StringRef CompDir, - DILineInfoSpecifier::FileLineInfoKind Kind, - std::string &Result) const; + bool + getFileNameByIndex(uint64_t FileIndex, StringRef CompDir, + DILineInfoSpecifier::FileLineInfoKind Kind, + std::string &Result, + sys::path::Style Style = sys::path::Style::native) const; void clear(); void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const; - Error parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, + Error parse(const DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr, const DWARFContext &Ctx, const DWARFUnit *U = nullptr); }; @@ -278,7 +281,7 @@ public: /// Parse prologue and all rows. Error parse( - DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, + DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr, const DWARFContext &Ctx, const DWARFUnit *U, std::function<void(Error)> RecoverableErrorCallback, raw_ostream *OS = nullptr); @@ -305,9 +308,9 @@ public: std::vector<uint32_t> &Result) const; }; - const LineTable *getLineTable(uint32_t Offset) const; + const LineTable *getLineTable(uint64_t Offset) const; Expected<const LineTable *> getOrParseLineTable( - DWARFDataExtractor &DebugLineData, uint32_t Offset, + DWARFDataExtractor &DebugLineData, uint64_t Offset, const DWARFContext &Ctx, const DWARFUnit *U, std::function<void(Error)> RecoverableErrorCallback); @@ -350,17 +353,17 @@ public: bool done() const { return Done; } /// Get the offset the parser has reached. - uint32_t getOffset() const { return Offset; } + uint64_t getOffset() const { return Offset; } private: - DWARFUnit *prepareToParse(uint32_t Offset); - void moveToNextTable(uint32_t OldOffset, const Prologue &P); + DWARFUnit *prepareToParse(uint64_t Offset); + void moveToNextTable(uint64_t OldOffset, const Prologue &P); LineToUnitMap LineToUnit; DWARFDataExtractor &DebugLineData; const DWARFContext &Context; - uint32_t Offset = 0; + uint64_t Offset = 0; bool Done = false; }; @@ -377,7 +380,7 @@ private: struct Sequence Sequence; }; - using LineTableMapTy = std::map<uint32_t, LineTable>; + using LineTableMapTy = std::map<uint64_t, LineTable>; using LineTableIter = LineTableMapTy::iterator; using LineTableConstIter = LineTableMapTy::const_iterator; diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h index cced6048e811..c79d98e34f6e 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h @@ -11,6 +11,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include <cstdint> @@ -29,19 +30,20 @@ public: /// The ending address of the instruction range. uint64_t End; /// The location of the variable within the specified range. - SmallVector<char, 4> Loc; + SmallVector<uint8_t, 4> Loc; }; /// A list of locations that contain one variable. struct LocationList { /// The beginning offset where this location list is stored in the debug_loc /// section. - unsigned Offset; + uint64_t Offset; /// All the locations in which the variable is stored. SmallVector<Entry, 2> Entries; /// Dump this list on OS. - void dump(raw_ostream &OS, bool IsLittleEndian, unsigned AddressSize, - const MCRegisterInfo *MRI, DWARFUnit *U, uint64_t BaseAddress, + void dump(raw_ostream &OS, uint64_t BaseAddress, bool IsLittleEndian, + unsigned AddressSize, const MCRegisterInfo *MRI, DWARFUnit *U, + DIDumpOptions DumpOpts, unsigned Indent) const; }; @@ -58,7 +60,7 @@ private: public: /// Print the location lists found within the debug_loc section. - void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo, + void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo, DIDumpOptions DumpOpts, Optional<uint64_t> Offset) const; /// Parse the debug_loc section accessible via the 'data' parameter using the @@ -68,25 +70,29 @@ public: /// Return the location list at the given offset or nullptr. LocationList const *getLocationListAtOffset(uint64_t Offset) const; - Optional<LocationList> parseOneLocationList(DWARFDataExtractor Data, - uint32_t *Offset); + Expected<LocationList> + parseOneLocationList(const DWARFDataExtractor &Data, uint64_t *Offset); }; class DWARFDebugLoclists { public: struct Entry { uint8_t Kind; + uint64_t Offset; uint64_t Value0; uint64_t Value1; - SmallVector<char, 4> Loc; + SmallVector<uint8_t, 4> Loc; + void dump(raw_ostream &OS, uint64_t &BaseAddr, bool IsLittleEndian, + unsigned AddressSize, const MCRegisterInfo *MRI, DWARFUnit *U, + DIDumpOptions DumpOpts, unsigned Indent, size_t MaxEncodingStringLength) const; }; struct LocationList { - unsigned Offset; + uint64_t Offset; SmallVector<Entry, 2> Entries; void dump(raw_ostream &OS, uint64_t BaseAddr, bool IsLittleEndian, unsigned AddressSize, const MCRegisterInfo *RegInfo, - DWARFUnit *U, unsigned Indent) const; + DWARFUnit *U, DIDumpOptions DumpOpts, unsigned Indent) const; }; private: @@ -99,15 +105,16 @@ private: bool IsLittleEndian; public: - void parse(DataExtractor data, unsigned Version); + void parse(DataExtractor data, uint64_t Offset, uint64_t EndOffset, uint16_t Version); void dump(raw_ostream &OS, uint64_t BaseAddr, const MCRegisterInfo *RegInfo, - Optional<uint64_t> Offset) const; + DIDumpOptions DumpOpts, Optional<uint64_t> Offset) const; /// Return the location list at the given offset or nullptr. LocationList const *getLocationListAtOffset(uint64_t Offset) const; - static Optional<LocationList> - parseOneLocationList(DataExtractor Data, unsigned *Offset, unsigned Version); + static Expected<LocationList> parseOneLocationList(const DataExtractor &Data, + uint64_t *Offset, + unsigned Version); }; } // end namespace llvm diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h b/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h index 99e91ca90319..ae57306b90e1 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h @@ -25,7 +25,7 @@ class DWARFDebugPubTable { public: struct Entry { /// Section offset from the beginning of the compilation unit. - uint32_t SecOffset; + uint64_t SecOffset; /// An entry of the various gnu_pub* debug sections. dwarf::PubIndexEntryDescriptor Descriptor; @@ -50,7 +50,7 @@ public: /// The offset from the beginning of the .debug_info section of the /// compilation unit header referenced by the set. - uint32_t Offset; + uint64_t Offset; /// The size in bytes of the contents of the .debug_info section generated /// to represent that compilation unit. diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h index a66f60292343..2f72c642a2d5 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h @@ -53,14 +53,13 @@ public: assert(AddressSize == 4 || AddressSize == 8); if (AddressSize == 4) return StartAddress == -1U; - else - return StartAddress == -1ULL; + return StartAddress == -1ULL; } }; private: /// Offset in .debug_ranges section. - uint32_t Offset; + uint64_t Offset; uint8_t AddressSize; std::vector<RangeListEntry> Entries; @@ -69,7 +68,7 @@ public: void clear(); void dump(raw_ostream &OS) const; - Error extract(const DWARFDataExtractor &data, uint32_t *offset_ptr); + Error extract(const DWARFDataExtractor &data, uint64_t *offset_ptr); const std::vector<RangeListEntry> &getEntries() { return Entries; } /// getAbsoluteRanges - Returns absolute address ranges defined by this range diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h b/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h index 167ddde3ec3d..952c41e188c7 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h @@ -34,7 +34,7 @@ struct RangeListEntry : public DWARFListEntryBase { uint64_t Value0; uint64_t Value1; - Error extract(DWARFDataExtractor Data, uint32_t End, uint32_t *OffsetPtr); + Error extract(DWARFDataExtractor Data, uint64_t End, uint64_t *OffsetPtr); void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, uint64_t &CurrentBase, DIDumpOptions DumpOpts, llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)> diff --git a/include/llvm/DebugInfo/DWARF/DWARFDie.h b/include/llvm/DebugInfo/DWARF/DWARFDie.h index 21e68f983bb3..f7f08b4a499d 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDie.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -63,7 +63,7 @@ public: /// Get the absolute offset into the debug info or types section. /// /// \returns the DIE offset or -1U if invalid. - uint32_t getOffset() const { + uint64_t getOffset() const { assert(isValid() && "must check validity prior to calling"); return Die->getOffset(); } diff --git a/include/llvm/DebugInfo/DWARF/DWARFExpression.h b/include/llvm/DebugInfo/DWARF/DWARFExpression.h index f066dd58d606..456d9df957ad 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFExpression.h +++ b/include/llvm/DebugInfo/DWARF/DWARFExpression.h @@ -77,18 +77,18 @@ public: uint8_t Opcode; ///< The Op Opcode, DW_OP_<something>. Description Desc; bool Error; - uint32_t EndOffset; + uint64_t EndOffset; uint64_t Operands[2]; - uint32_t OperandEndOffsets[2]; + uint64_t OperandEndOffsets[2]; public: Description &getDescription() { return Desc; } uint8_t getCode() { return Opcode; } uint64_t getRawOperand(unsigned Idx) { return Operands[Idx]; } - uint32_t getOperandEndOffset(unsigned Idx) { return OperandEndOffsets[Idx]; } - uint32_t getEndOffset() { return EndOffset; } + uint64_t getOperandEndOffset(unsigned Idx) { return OperandEndOffsets[Idx]; } + uint64_t getEndOffset() { return EndOffset; } bool extract(DataExtractor Data, uint16_t Version, uint8_t AddressSize, - uint32_t Offset); + uint64_t Offset); bool isError() { return Error; } bool print(raw_ostream &OS, const DWARFExpression *Expr, const MCRegisterInfo *RegInfo, DWARFUnit *U, bool isEH); @@ -101,9 +101,9 @@ public: Operation> { friend class DWARFExpression; const DWARFExpression *Expr; - uint32_t Offset; + uint64_t Offset; Operation Op; - iterator(const DWARFExpression *Expr, uint32_t Offset) + iterator(const DWARFExpression *Expr, uint64_t Offset) : Expr(Expr), Offset(Offset) { Op.Error = Offset >= Expr->Data.getData().size() || diff --git a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h index 731e71ed9eae..6fec6fcb6b34 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -70,7 +70,7 @@ public: static DWARFFormValue createFromBlockValue(dwarf::Form F, ArrayRef<uint8_t> D); static DWARFFormValue createFromUnit(dwarf::Form F, const DWARFUnit *Unit, - uint32_t *OffsetPtr); + uint64_t *OffsetPtr); dwarf::Form getForm() const { return Form; } uint64_t getRawUValue() const { return Value.uval; } @@ -87,12 +87,12 @@ public: /// in \p FormParams is needed to interpret some forms. The optional /// \p Context and \p Unit allows extracting information if the form refers /// to other sections (e.g., .debug_str). - bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr, + bool extractValue(const DWARFDataExtractor &Data, uint64_t *OffsetPtr, dwarf::FormParams FormParams, const DWARFContext *Context = nullptr, const DWARFUnit *Unit = nullptr); - bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr, + bool extractValue(const DWARFDataExtractor &Data, uint64_t *OffsetPtr, dwarf::FormParams FormParams, const DWARFUnit *U) { return extractValue(Data, OffsetPtr, FormParams, nullptr, U); } @@ -128,7 +128,7 @@ public: /// \param OffsetPtr A reference to the offset that will be updated. /// \param Params DWARF parameters to help interpret forms. /// \returns true on success, false if the form was not skipped. - bool skipValue(DataExtractor DebugInfoData, uint32_t *OffsetPtr, + bool skipValue(DataExtractor DebugInfoData, uint64_t *OffsetPtr, const dwarf::FormParams Params) const { return DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, Params); } @@ -144,7 +144,7 @@ public: /// \param FormParams DWARF parameters to help interpret forms. /// \returns true on success, false if the form was not skipped. static bool skipValue(dwarf::Form Form, DataExtractor DebugInfoData, - uint32_t *OffsetPtr, + uint64_t *OffsetPtr, const dwarf::FormParams FormParams); private: diff --git a/include/llvm/DebugInfo/DWARF/DWARFListTable.h b/include/llvm/DebugInfo/DWARF/DWARFListTable.h index a1ea69b040f0..496fdb2477f9 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFListTable.h +++ b/include/llvm/DebugInfo/DWARF/DWARFListTable.h @@ -26,7 +26,7 @@ namespace llvm { /// entries. struct DWARFListEntryBase { /// The offset at which the entry is located in the section. - uint32_t Offset; + uint64_t Offset; /// The DWARF encoding (DW_RLE_* or DW_LLE_*). uint8_t EntryKind; /// The index of the section this entry belongs to. @@ -46,8 +46,8 @@ public: const ListEntries &getEntries() const { return Entries; } bool empty() const { return Entries.empty(); } void clear() { Entries.clear(); } - Error extract(DWARFDataExtractor Data, uint32_t HeaderOffset, uint32_t End, - uint32_t *OffsetPtr, StringRef SectionName, + Error extract(DWARFDataExtractor Data, uint64_t HeaderOffset, uint64_t End, + uint64_t *OffsetPtr, StringRef SectionName, StringRef ListStringName); }; @@ -57,7 +57,7 @@ class DWARFListTableHeader { struct Header { /// The total length of the entries for this table, not including the length /// field itself. - uint32_t Length = 0; + uint64_t Length = 0; /// The DWARF version number. uint16_t Version; /// The size in bytes of an address on the target architecture. For @@ -75,12 +75,12 @@ class DWARFListTableHeader { /// The offset table, which contains offsets to the individual list entries. /// It is used by forms such as DW_FORM_rnglistx. /// FIXME: Generate the table and use the appropriate forms. - std::vector<uint32_t> Offsets; + std::vector<uint64_t> Offsets; /// The table's format, either DWARF32 or DWARF64. dwarf::DwarfFormat Format; /// The offset at which the header (and hence the table) is located within /// its section. - uint32_t HeaderOffset; + uint64_t HeaderOffset; /// The name of the section the list is located in. StringRef SectionName; /// A characterization of the list for dumping purposes, e.g. "range" or @@ -95,28 +95,40 @@ public: HeaderData = {}; Offsets.clear(); } - uint32_t getHeaderOffset() const { return HeaderOffset; } + uint64_t getHeaderOffset() const { return HeaderOffset; } uint8_t getAddrSize() const { return HeaderData.AddrSize; } - uint32_t getLength() const { return HeaderData.Length; } + uint64_t getLength() const { return HeaderData.Length; } uint16_t getVersion() const { return HeaderData.Version; } StringRef getSectionName() const { return SectionName; } StringRef getListTypeString() const { return ListTypeString; } dwarf::DwarfFormat getFormat() const { return Format; } + /// Return the size of the table header including the length but not including + /// the offsets. + static uint8_t getHeaderSize(dwarf::DwarfFormat Format) { + switch (Format) { + case dwarf::DwarfFormat::DWARF32: + return 12; + case dwarf::DwarfFormat::DWARF64: + return 20; + } + llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64"); + } + void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const; - Optional<uint32_t> getOffsetEntry(uint32_t Index) const { + Optional<uint64_t> getOffsetEntry(uint32_t Index) const { if (Index < Offsets.size()) return Offsets[Index]; return None; } /// Extract the table header and the array of offsets. - Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr); + Error extract(DWARFDataExtractor Data, uint64_t *OffsetPtr); /// Returns the length of the table, including the length field, or 0 if the /// length has not been determined (e.g. because the table has not yet been /// parsed, or there was a problem in parsing). - uint32_t length() const; + uint64_t length() const; }; /// A class representing a table of lists as specified in the DWARF v5 @@ -128,7 +140,7 @@ template <typename DWARFListType> class DWARFListTableBase { DWARFListTableHeader Header; /// A mapping between file offsets and lists. It is used to find a particular /// list based on an offset (obtained from DW_AT_ranges, for example). - std::map<uint32_t, DWARFListType> ListMap; + std::map<uint64_t, DWARFListType> ListMap; /// This string is displayed as a heading before the list is dumped /// (e.g. "ranges:"). StringRef HeaderString; @@ -144,17 +156,18 @@ public: ListMap.clear(); } /// Extract the table header and the array of offsets. - Error extractHeaderAndOffsets(DWARFDataExtractor Data, uint32_t *OffsetPtr) { + Error extractHeaderAndOffsets(DWARFDataExtractor Data, uint64_t *OffsetPtr) { return Header.extract(Data, OffsetPtr); } /// Extract an entire table, including all list entries. - Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr); + Error extract(DWARFDataExtractor Data, uint64_t *OffsetPtr); /// Look up a list based on a given offset. Extract it and enter it into the /// list map if necessary. - Expected<DWARFListType> findList(DWARFDataExtractor Data, uint32_t Offset); + Expected<DWARFListType> findList(DWARFDataExtractor Data, uint64_t Offset); - uint32_t getHeaderOffset() const { return Header.getHeaderOffset(); } + uint64_t getHeaderOffset() const { return Header.getHeaderOffset(); } uint8_t getAddrSize() const { return Header.getAddrSize(); } + dwarf::DwarfFormat getFormat() const { return Header.getFormat(); } void dump(raw_ostream &OS, llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)> @@ -162,37 +175,31 @@ public: DIDumpOptions DumpOpts = {}) const; /// Return the contents of the offset entry designated by a given index. - Optional<uint32_t> getOffsetEntry(uint32_t Index) const { + Optional<uint64_t> getOffsetEntry(uint32_t Index) const { return Header.getOffsetEntry(Index); } /// Return the size of the table header including the length but not including /// the offsets. This is dependent on the table format, which is unambiguously /// derived from parsing the table. uint8_t getHeaderSize() const { - switch (Header.getFormat()) { - case dwarf::DwarfFormat::DWARF32: - return 12; - case dwarf::DwarfFormat::DWARF64: - return 20; - } - llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64"); + return DWARFListTableHeader::getHeaderSize(getFormat()); } - uint32_t length() { return Header.length(); } + uint64_t length() { return Header.length(); } }; template <typename DWARFListType> Error DWARFListTableBase<DWARFListType>::extract(DWARFDataExtractor Data, - uint32_t *OffsetPtr) { + uint64_t *OffsetPtr) { clear(); if (Error E = extractHeaderAndOffsets(Data, OffsetPtr)) return E; Data.setAddressSize(Header.getAddrSize()); - uint32_t End = getHeaderOffset() + Header.length(); + uint64_t End = getHeaderOffset() + Header.length(); while (*OffsetPtr < End) { DWARFListType CurrentList; - uint32_t Off = *OffsetPtr; + uint64_t Off = *OffsetPtr; if (Error E = CurrentList.extract(Data, getHeaderOffset(), End, OffsetPtr, Header.getSectionName(), Header.getListTypeString())) @@ -208,13 +215,13 @@ Error DWARFListTableBase<DWARFListType>::extract(DWARFDataExtractor Data, template <typename ListEntryType> Error DWARFListType<ListEntryType>::extract(DWARFDataExtractor Data, - uint32_t HeaderOffset, uint32_t End, - uint32_t *OffsetPtr, + uint64_t HeaderOffset, uint64_t End, + uint64_t *OffsetPtr, StringRef SectionName, StringRef ListTypeString) { if (*OffsetPtr < HeaderOffset || *OffsetPtr >= End) return createStringError(errc::invalid_argument, - "invalid %s list offset 0x%" PRIx32, + "invalid %s list offset 0x%" PRIx64, ListTypeString.data(), *OffsetPtr); Entries.clear(); while (*OffsetPtr < End) { @@ -227,7 +234,7 @@ Error DWARFListType<ListEntryType>::extract(DWARFDataExtractor Data, } return createStringError(errc::illegal_byte_sequence, "no end of list marker detected at end of %s table " - "starting at offset 0x%" PRIx32, + "starting at offset 0x%" PRIx64, SectionName.data(), HeaderOffset); } @@ -261,15 +268,15 @@ void DWARFListTableBase<DWARFListType>::dump( template <typename DWARFListType> Expected<DWARFListType> DWARFListTableBase<DWARFListType>::findList(DWARFDataExtractor Data, - uint32_t Offset) { + uint64_t Offset) { auto Entry = ListMap.find(Offset); if (Entry != ListMap.end()) return Entry->second; // Extract the list from the section and enter it into the list map. DWARFListType List; - uint32_t End = getHeaderOffset() + Header.length(); - uint32_t StartingOffset = Offset; + uint64_t End = getHeaderOffset() + Header.length(); + uint64_t StartingOffset = Offset; if (Error E = List.extract(Data, getHeaderOffset(), End, &Offset, Header.getSectionName(), Header.getListTypeString())) diff --git a/include/llvm/DebugInfo/DWARF/DWARFObject.h b/include/llvm/DebugInfo/DWARF/DWARFObject.h index 1bba74a25d0e..88fe3f434edc 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFObject.h +++ b/include/llvm/DebugInfo/DWARF/DWARFObject.h @@ -39,20 +39,20 @@ public: virtual StringRef getAbbrevSection() const { return ""; } virtual const DWARFSection &getLocSection() const { return Dummy; } virtual const DWARFSection &getLoclistsSection() const { return Dummy; } - virtual StringRef getARangeSection() const { return ""; } - virtual StringRef getDebugFrameSection() const { return ""; } - virtual StringRef getEHFrameSection() const { return ""; } + virtual StringRef getArangesSection() const { return ""; } + virtual const DWARFSection &getFrameSection() const { return Dummy; } + virtual const DWARFSection &getEHFrameSection() const { return Dummy; } virtual const DWARFSection &getLineSection() const { return Dummy; } - virtual StringRef getLineStringSection() const { return ""; } - virtual StringRef getStringSection() const { return ""; } - virtual const DWARFSection &getRangeSection() const { return Dummy; } + virtual StringRef getLineStrSection() const { return ""; } + virtual StringRef getStrSection() const { return ""; } + virtual const DWARFSection &getRangesSection() const { return Dummy; } virtual const DWARFSection &getRnglistsSection() const { return Dummy; } virtual StringRef getMacinfoSection() const { return ""; } - virtual const DWARFSection &getPubNamesSection() const { return Dummy; } - virtual const DWARFSection &getPubTypesSection() const { return Dummy; } - virtual const DWARFSection &getGnuPubNamesSection() const { return Dummy; } - virtual const DWARFSection &getGnuPubTypesSection() const { return Dummy; } - virtual const DWARFSection &getStringOffsetSection() const { return Dummy; } + virtual const DWARFSection &getPubnamesSection() const { return Dummy; } + virtual const DWARFSection &getPubtypesSection() const { return Dummy; } + virtual const DWARFSection &getGnuPubnamesSection() const { return Dummy; } + virtual const DWARFSection &getGnuPubtypesSection() const { return Dummy; } + virtual const DWARFSection &getStrOffsetsSection() const { return Dummy; } virtual void forEachInfoDWOSections(function_ref<void(const DWARFSection &)> F) const {} virtual void @@ -60,11 +60,11 @@ public: virtual StringRef getAbbrevDWOSection() const { return ""; } virtual const DWARFSection &getLineDWOSection() const { return Dummy; } virtual const DWARFSection &getLocDWOSection() const { return Dummy; } - virtual StringRef getStringDWOSection() const { return ""; } - virtual const DWARFSection &getStringOffsetDWOSection() const { + virtual StringRef getStrDWOSection() const { return ""; } + virtual const DWARFSection &getStrOffsetsDWOSection() const { return Dummy; } - virtual const DWARFSection &getRangeDWOSection() const { return Dummy; } + virtual const DWARFSection &getRangesDWOSection() const { return Dummy; } virtual const DWARFSection &getRnglistsDWOSection() const { return Dummy; } virtual const DWARFSection &getAddrSection() const { return Dummy; } virtual const DWARFSection &getAppleNamesSection() const { return Dummy; } @@ -72,7 +72,7 @@ public: virtual const DWARFSection &getAppleNamespacesSection() const { return Dummy; } - virtual const DWARFSection &getDebugNamesSection() const { return Dummy; } + virtual const DWARFSection &getNamesSection() const { return Dummy; } virtual const DWARFSection &getAppleObjCSection() const { return Dummy; } virtual StringRef getCUIndexSection() const { return ""; } virtual StringRef getGdbIndexSection() const { return ""; } diff --git a/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h index 90d89375fd35..c95bdcbd8a43 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h +++ b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h @@ -34,7 +34,7 @@ public: LS, LE, IsDWO, UnitVector) {} uint64_t getTypeHash() const { return getHeader().getTypeHash(); } - uint32_t getTypeOffset() const { return getHeader().getTypeOffset(); } + uint64_t getTypeOffset() const { return getHeader().getTypeOffset(); } void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override; // Enable LLVM-style RTTI. diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h index f9f90db31890..51de114a3506 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -45,7 +45,7 @@ class DWARFUnit; /// parse the header before deciding what specific kind of unit to construct. class DWARFUnitHeader { // Offset within section. - uint32_t Offset = 0; + uint64_t Offset = 0; // Version, address size, and DWARF format. dwarf::FormParams FormParams; uint64_t Length = 0; @@ -56,7 +56,7 @@ class DWARFUnitHeader { // For type units only. uint64_t TypeHash = 0; - uint32_t TypeOffset = 0; + uint64_t TypeOffset = 0; // For v5 split or skeleton compile units only. Optional<uint64_t> DWOId; @@ -70,10 +70,10 @@ class DWARFUnitHeader { public: /// Parse a unit header from \p debug_info starting at \p offset_ptr. bool extract(DWARFContext &Context, const DWARFDataExtractor &debug_info, - uint32_t *offset_ptr, DWARFSectionKind Kind = DW_SECT_INFO, + uint64_t *offset_ptr, DWARFSectionKind Kind = DW_SECT_INFO, const DWARFUnitIndex *Index = nullptr, const DWARFUnitIndex::Entry *Entry = nullptr); - uint32_t getOffset() const { return Offset; } + uint64_t getOffset() const { return Offset; } const dwarf::FormParams &getFormParams() const { return FormParams; } uint16_t getVersion() const { return FormParams.Version; } dwarf::DwarfFormat getFormat() const { return FormParams.Format; } @@ -91,16 +91,17 @@ public: } const DWARFUnitIndex::Entry *getIndexEntry() const { return IndexEntry; } uint64_t getTypeHash() const { return TypeHash; } - uint32_t getTypeOffset() const { return TypeOffset; } + uint64_t getTypeOffset() const { return TypeOffset; } uint8_t getUnitType() const { return UnitType; } bool isTypeUnit() const { return UnitType == dwarf::DW_UT_type || UnitType == dwarf::DW_UT_split_type; } uint8_t getSize() const { return Size; } - uint32_t getNextUnitOffset() const { - return Offset + Length + - (FormParams.Format == llvm::dwarf::DwarfFormat::DWARF64 ? 4 : 0) + - FormParams.getDwarfOffsetByteSize(); + uint8_t getUnitLengthFieldByteSize() const { + return dwarf::getUnitLengthFieldByteSize(FormParams.Format); + } + uint64_t getNextUnitOffset() const { + return Offset + Length + getUnitLengthFieldByteSize(); } }; @@ -110,7 +111,7 @@ const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context, /// Describe a collection of units. Intended to hold all units either from /// .debug_info and .debug_types, or from .debug_info.dwo and .debug_types.dwo. class DWARFUnitVector final : public SmallVector<std::unique_ptr<DWARFUnit>, 1> { - std::function<std::unique_ptr<DWARFUnit>(uint32_t, DWARFSectionKind, + std::function<std::unique_ptr<DWARFUnit>(uint64_t, DWARFSectionKind, const DWARFSection *, const DWARFUnitIndex::Entry *)> Parser; @@ -121,7 +122,7 @@ public: using iterator = typename UnitVector::iterator; using iterator_range = llvm::iterator_range<typename UnitVector::iterator>; - DWARFUnit *getUnitForOffset(uint32_t Offset) const; + DWARFUnit *getUnitForOffset(uint64_t Offset) const; DWARFUnit *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E); /// Read units from a .debug_info or .debug_types section. Calls made @@ -197,7 +198,7 @@ class DWARFUnit { DWARFUnitHeader Header; const DWARFDebugAbbrev *Abbrev; const DWARFSection *RangeSection; - uint32_t RangeSectionBase; + uint64_t RangeSectionBase; /// We either keep track of the location list section or its data, depending /// on whether we are handling a split DWARF section or not. union { @@ -275,7 +276,7 @@ public: const DWARFSection &getInfoSection() const { return InfoSection; } const DWARFSection *getLocSection() const { return LocSection; } StringRef getLocSectionData() const { return LocSectionData; } - uint32_t getOffset() const { return Header.getOffset(); } + uint64_t getOffset() const { return Header.getOffset(); } const dwarf::FormParams &getFormParams() const { return Header.getFormParams(); } @@ -285,10 +286,10 @@ public: uint8_t getDwarfOffsetByteSize() const { return Header.getDwarfOffsetByteSize(); } - uint32_t getLength() const { return Header.getLength(); } + uint64_t getLength() const { return Header.getLength(); } uint8_t getUnitType() const { return Header.getUnitType(); } bool isTypeUnit() const { return Header.isTypeUnit(); } - uint32_t getNextUnitOffset() const { return Header.getNextUnitOffset(); } + uint64_t getNextUnitOffset() const { return Header.getNextUnitOffset(); } const DWARFSection &getLineSection() const { return LineSection; } StringRef getStringSection() const { return StringSection; } const DWARFSection &getStringOffsetSection() const { @@ -303,7 +304,7 @@ public: /// Recursively update address to Die map. void updateAddressDieMap(DWARFDie Die); - void setRangesSection(const DWARFSection *RS, uint32_t Base) { + void setRangesSection(const DWARFSection *RS, uint64_t Base) { RangeSection = RS; RangeSectionBase = Base; } @@ -322,7 +323,7 @@ public: /// .debug_ranges section. If the extraction is unsuccessful, an error /// is returned. Successful extraction requires that the compile unit /// has already been extracted. - Error extractRangeList(uint32_t RangeListOffset, + Error extractRangeList(uint64_t RangeListOffset, DWARFDebugRangeList &RangeList) const; void clear(); @@ -405,7 +406,7 @@ public: /// Return a vector of address ranges resulting from a (possibly encoded) /// range list starting at a given offset in the appropriate ranges section. - Expected<DWARFAddressRangesVector> findRnglistFromOffset(uint32_t Offset); + Expected<DWARFAddressRangesVector> findRnglistFromOffset(uint64_t Offset); /// Return a vector of address ranges retrieved from an encoded range /// list whose offset is found via a table lookup given an index (DWARF v5 @@ -415,7 +416,7 @@ public: /// Return a rangelist's offset based on an index. The index designates /// an entry in the rangelist table's offset array and is supplied by /// DW_FORM_rnglistx. - Optional<uint32_t> getRnglistOffset(uint32_t Index) { + Optional<uint64_t> getRnglistOffset(uint32_t Index) { if (RngListTable) return RngListTable->getOffsetEntry(Index); return None; @@ -470,7 +471,7 @@ public: /// unit's DIE vector. /// /// The unit needs to have its DIEs extracted for this method to work. - DWARFDie getDIEForOffset(uint32_t Offset) { + DWARFDie getDIEForOffset(uint64_t Offset) { extractDIEsIfNeeded(false); assert(!DieArray.empty()); auto It = @@ -495,15 +496,19 @@ public: } virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0; + + Error tryExtractDIEsIfNeeded(bool CUDieOnly); + private: /// Size in bytes of the .debug_info data associated with this compile unit. size_t getDebugInfoSize() const { - return Header.getLength() + 4 - getHeaderSize(); + return Header.getLength() + Header.getUnitLengthFieldByteSize() - + getHeaderSize(); } /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it - /// hasn't already been done. Returns the number of DIEs parsed at this call. - size_t extractDIEsIfNeeded(bool CUDieOnly); + /// hasn't already been done + void extractDIEsIfNeeded(bool CUDieOnly); /// extractDIEsToVector - Appends all parsed DIEs to a vector. void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs, diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h b/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h index fc8c707c512e..684103aac2fc 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h +++ b/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h @@ -37,7 +37,7 @@ class DWARFUnitIndex { uint32_t NumUnits; uint32_t NumBuckets = 0; - bool parse(DataExtractor IndexData, uint32_t *OffsetPtr); + bool parse(DataExtractor IndexData, uint64_t *OffsetPtr); void dump(raw_ostream &OS) const; }; diff --git a/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/include/llvm/DebugInfo/DWARF/DWARFVerifier.h index f1268f220272..a4a3a11d441b 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFVerifier.h +++ b/include/llvm/DebugInfo/DWARF/DWARFVerifier.h @@ -94,7 +94,7 @@ private: /// A map that tracks all references (converted absolute references) so we /// can verify each reference points to a valid DIE and not an offset that /// lies between to valid DIEs. - std::map<uint64_t, std::set<uint32_t>> ReferenceToDIEOffsets; + std::map<uint64_t, std::set<uint64_t>> ReferenceToDIEOffsets; uint32_t NumDebugLineErrors = 0; // Used to relax some checks that do not currently work portably bool IsObjectFile; @@ -138,7 +138,7 @@ private: /// /// \returns true if the header is verified successfully, false otherwise. bool verifyUnitHeader(const DWARFDataExtractor DebugInfoData, - uint32_t *Offset, unsigned UnitIndex, uint8_t &UnitType, + uint64_t *Offset, unsigned UnitIndex, uint8_t &UnitType, bool &isUnitDWARF64); /// Verifies the header of a unit in a .debug_info or .debug_types section. diff --git a/include/llvm/DebugInfo/GSYM/FileEntry.h b/include/llvm/DebugInfo/GSYM/FileEntry.h index 228b4efa0656..49e7fc9c4291 100644 --- a/include/llvm/DebugInfo/GSYM/FileEntry.h +++ b/include/llvm/DebugInfo/GSYM/FileEntry.h @@ -1,9 +1,8 @@ //===- FileEntry.h ----------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/GSYM/FileWriter.h b/include/llvm/DebugInfo/GSYM/FileWriter.h new file mode 100644 index 000000000000..cd568765a4f2 --- /dev/null +++ b/include/llvm/DebugInfo/GSYM/FileWriter.h @@ -0,0 +1,124 @@ +//===- FileWriter.h ---------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_GSYM_FILEWRITER_H +#define LLVM_DEBUGINFO_GSYM_FILEWRITER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/Endian.h" + +#include <stddef.h> +#include <stdint.h> +#include <sys/types.h> + +namespace llvm { +class raw_pwrite_stream; + +namespace gsym { + +/// A simplified binary data writer class that doesn't require targets, target +/// definitions, architectures, or require any other optional compile time +/// libraries to be enabled via the build process. This class needs the ability +/// to seek to different spots in the binary stream that is produces to fixup +/// offsets and sizes. +class FileWriter { + llvm::raw_pwrite_stream &OS; + llvm::support::endianness ByteOrder; +public: + FileWriter(llvm::raw_pwrite_stream &S, llvm::support::endianness B) + : OS(S), ByteOrder(B) {} + ~FileWriter(); + /// Write a single uint8_t value into the stream at the current file + /// position. + /// + /// \param Value The value to write into the stream. + void writeU8(uint8_t Value); + + /// Write a single uint16_t value into the stream at the current file + /// position. The value will be byte swapped if needed to match the byte + /// order specified during construction. + /// + /// \param Value The value to write into the stream. + void writeU16(uint16_t Value); + + /// Write a single uint32_t value into the stream at the current file + /// position. The value will be byte swapped if needed to match the byte + /// order specified during construction. + /// + /// \param Value The value to write into the stream. + void writeU32(uint32_t Value); + + /// Write a single uint64_t value into the stream at the current file + /// position. The value will be byte swapped if needed to match the byte + /// order specified during construction. + /// + /// \param Value The value to write into the stream. + void writeU64(uint64_t Value); + + /// Write the value into the stream encoded using signed LEB128 at the + /// current file position. + /// + /// \param Value The value to write into the stream. + void writeSLEB(int64_t Value); + + /// Write the value into the stream encoded using unsigned LEB128 at the + /// current file position. + /// + /// \param Value The value to write into the stream. + void writeULEB(uint64_t Value); + + /// Write an array of uint8_t values into the stream at the current file + /// position. + /// + /// \param Data An array of values to write into the stream. + void writeData(llvm::ArrayRef<uint8_t> Data); + + /// Write a NULL terminated C string into the stream at the current file + /// position. The entire contents of Str will be written into the steam at + /// the current file position and then an extra NULL termation byte will be + /// written. It is up to the user to ensure that Str doesn't contain any NULL + /// characters unless the additional NULL characters are desired. + /// + /// \param Str The value to write into the stream. + void writeNullTerminated(llvm::StringRef Str); + + /// Fixup a uint32_t value at the specified offset in the stream. This + /// function will save the current file position, seek to the specified + /// offset, overwrite the data using Value, and then restore the file + /// position to the previous file position. + /// + /// \param Value The value to write into the stream. + /// \param Offset The offset at which to write the Value within the stream. + void fixup32(uint32_t Value, uint64_t Offset); + + /// Pad with zeroes at the current file position until the current file + /// position matches the specified alignment. + /// + /// \param Align An integer speciying the desired alignment. This does not + /// need to be a power of two. + void alignTo(size_t Align); + + /// Return the current offset within the file. + /// + /// \return The unsigned offset from the start of the file of the current + /// file position. + uint64_t tell(); + + llvm::raw_pwrite_stream &get_stream() { + return OS; + } + +private: + FileWriter(const FileWriter &rhs) = delete; + void operator=(const FileWriter &rhs) = delete; +}; + +} // namespace gsym +} // namespace llvm + +#endif // #ifndef LLVM_DEBUGINFO_GSYM_FILEWRITER_H diff --git a/include/llvm/DebugInfo/GSYM/FunctionInfo.h b/include/llvm/DebugInfo/GSYM/FunctionInfo.h index eedb1e638fd1..63e18bb2ecd5 100644 --- a/include/llvm/DebugInfo/GSYM/FunctionInfo.h +++ b/include/llvm/DebugInfo/GSYM/FunctionInfo.h @@ -1,17 +1,17 @@ //===- FunctionInfo.h -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_DEBUGINFO_GSYM_FUNCTIONINFO_H #define LLVM_DEBUGINFO_GSYM_FUNCTIONINFO_H +#include "llvm/ADT/Optional.h" #include "llvm/DebugInfo/GSYM/InlineInfo.h" -#include "llvm/DebugInfo/GSYM/LineEntry.h" +#include "llvm/DebugInfo/GSYM/LineTable.h" #include "llvm/DebugInfo/GSYM/Range.h" #include "llvm/DebugInfo/GSYM/StringTable.h" #include <tuple> @@ -21,41 +21,125 @@ namespace llvm { class raw_ostream; namespace gsym { -/// Function information in GSYM files encodes information for one -/// contiguous address range. The name of the function is encoded as -/// a string table offset and allows multiple functions with the same -/// name to share the name string in the string table. Line tables are -/// stored in a sorted vector of gsym::LineEntry objects and are split -/// into line tables for each function. If a function has a discontiguous -/// range, it will be split into two gsym::FunctionInfo objects. If the -/// function has inline functions, the information will be encoded in -/// the "Inline" member, see gsym::InlineInfo for more information. +/// Function information in GSYM files encodes information for one contiguous +/// address range. If a function has discontiguous address ranges, they will +/// need to be encoded using multiple FunctionInfo objects. +/// +/// ENCODING +/// +/// The function information gets the function start address as an argument +/// to the FunctionInfo::decode(...) function. This information is calculated +/// from the GSYM header and an address offset from the GSYM address offsets +/// table. The encoded FunctionInfo information must be alinged to a 4 byte +/// boundary. +/// +/// The encoded data for a FunctionInfo starts with fixed data that all +/// function info objects have: +/// +/// ENCODING NAME DESCRIPTION +/// ========= =========== ==================================================== +/// uint32_t Size The size in bytes of this function. +/// uint32_t Name The string table offset of the function name. +/// +/// The optional data in a FunctionInfo object follows this fixed information +/// and consists of a stream of tuples that consist of: +/// +/// ENCODING NAME DESCRIPTION +/// ========= =========== ==================================================== +/// uint32_t InfoType An "InfoType" enumeration that describes the type +/// of optional data that is encoded. +/// uint32_t InfoLength The size in bytes of the encoded data that +/// immediately follows this length if this value is +/// greater than zero. +/// uint8_t[] InfoData Encoded bytes that represent the data for the +/// "InfoType". These bytes are only present if +/// "InfoLength" is greater than zero. +/// +/// The "InfoType" is an enumeration: +/// +/// enum InfoType { +/// EndOfList = 0u, +/// LineTableInfo = 1u, +/// InlineInfo = 2u +/// }; +/// +/// This stream of tuples is terminated by a "InfoType" whose value is +/// InfoType::EndOfList and a zero for "InfoLength". This signifies the end of +/// the optional information list. This format allows us to add new optional +/// information data to a FunctionInfo object over time and allows older +/// clients to still parse the format and skip over any data that they don't +/// understand or want to parse. +/// +/// So the function information encoding essientially looks like: +/// +/// struct { +/// uint32_t Size; +/// uint32_t Name; +/// struct { +/// uint32_t InfoType; +/// uint32_t InfoLength; +/// uint8_t InfoData[InfoLength]; +/// }[N]; +/// } +/// +/// Where "N" is the number of tuples. struct FunctionInfo { AddressRange Range; uint32_t Name; ///< String table offset in the string table. - std::vector<gsym::LineEntry> Lines; - InlineInfo Inline; + llvm::Optional<LineTable> OptLineTable; + llvm::Optional<InlineInfo> Inline; FunctionInfo(uint64_t Addr = 0, uint64_t Size = 0, uint32_t N = 0) : Range(Addr, Addr + Size), Name(N) {} + /// Query if a FunctionInfo has rich debug info. + /// + /// \returns A bool that indicates if this object has something else than + /// range and name. When converting information from a symbol table and from + /// debug info, we might end up with multiple FunctionInfo objects for the + /// same range and we need to be able to tell which one is the better object + /// to use. bool hasRichInfo() const { - /// Returns whether we have something else than range and name. When - /// converting information from a symbol table and from debug info, we - /// might end up with multiple FunctionInfo objects for the same range - /// and we need to be able to tell which one is the better object to use. - return !Lines.empty() || Inline.isValid(); + return OptLineTable.hasValue() || Inline.hasValue(); } + /// Query if a FunctionInfo object is valid. + /// + /// Address and size can be zero and there can be no line entries for a + /// symbol so the only indication this entry is valid is if the name is + /// not zero. This can happen when extracting information from symbol + /// tables that do not encode symbol sizes. In that case only the + /// address and name will be filled in. + /// + /// \returns A boolean indicating if this FunctionInfo is valid. bool isValid() const { - /// Address and size can be zero and there can be no line entries for a - /// symbol so the only indication this entry is valid is if the name is - /// not zero. This can happen when extracting information from symbol - /// tables that do not encode symbol sizes. In that case only the - /// address and name will be filled in. return Name != 0; } + /// Decode an object from a binary data stream. + /// + /// \param Data The binary stream to read the data from. This object must + /// have the data for the object starting at offset zero. The data + /// can contain more data than needed. + /// + /// \param BaseAddr The FunctionInfo's start address and will be used as the + /// base address when decoding any contained information like the line table + /// and the inline info. + /// + /// \returns An FunctionInfo or an error describing the issue that was + /// encountered during decoding. + static llvm::Expected<FunctionInfo> decode(DataExtractor &Data, + uint64_t BaseAddr); + + /// Encode this object into FileWriter stream. + /// + /// \param O The binary stream to write the data to at the current file + /// position. + /// + /// \returns An error object that indicates failure or the offset of the + /// function info that was successfully written into the stream. + llvm::Expected<uint64_t> encode(FileWriter &O) const; + uint64_t startAddress() const { return Range.Start; } uint64_t endAddress() const { return Range.End; } uint64_t size() const { return Range.size(); } @@ -66,14 +150,14 @@ struct FunctionInfo { void clear() { Range = {0, 0}; Name = 0; - Lines.clear(); - Inline.clear(); + OptLineTable = None; + Inline = None; } }; inline bool operator==(const FunctionInfo &LHS, const FunctionInfo &RHS) { return LHS.Range == RHS.Range && LHS.Name == RHS.Name && - LHS.Lines == RHS.Lines && LHS.Inline == RHS.Inline; + LHS.OptLineTable == RHS.OptLineTable && LHS.Inline == RHS.Inline; } inline bool operator!=(const FunctionInfo &LHS, const FunctionInfo &RHS) { return !(LHS == RHS); @@ -89,14 +173,10 @@ inline bool operator<(const FunctionInfo &LHS, const FunctionInfo &RHS) { return LHS.Range < RHS.Range; // Then sort by inline - if (LHS.Inline.isValid() != RHS.Inline.isValid()) - return RHS.Inline.isValid(); - - // If the number of lines is the same, then compare line table entries - if (LHS.Lines.size() == RHS.Lines.size()) - return LHS.Lines < RHS.Lines; - // Then sort by number of line table entries (more is better) - return LHS.Lines.size() < RHS.Lines.size(); + if (LHS.Inline.hasValue() != RHS.Inline.hasValue()) + return RHS.Inline.hasValue(); + + return LHS.OptLineTable < RHS.OptLineTable; } raw_ostream &operator<<(raw_ostream &OS, const FunctionInfo &R); diff --git a/include/llvm/DebugInfo/GSYM/GsymCreator.h b/include/llvm/DebugInfo/GSYM/GsymCreator.h new file mode 100644 index 000000000000..12c8187132ba --- /dev/null +++ b/include/llvm/DebugInfo/GSYM/GsymCreator.h @@ -0,0 +1,229 @@ +//===- GsymCreator.h --------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_GSYM_GSYMCREATOR_H +#define LLVM_DEBUGINFO_GSYM_GSYMCREATOR_H + +#include <functional> +#include <memory> +#include <mutex> +#include <string> +#include <thread> + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/GSYM/FileEntry.h" +#include "llvm/DebugInfo/GSYM/FunctionInfo.h" +#include "llvm/DebugInfo/GSYM/Range.h" +#include "llvm/MC/StringTableBuilder.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/Path.h" + +namespace llvm { + +namespace gsym { +class FileWriter; + +/// GsymCreator is used to emit GSYM data to a stand alone file or section +/// within a file. +/// +/// The GsymCreator is designed to be used in 3 stages: +/// - Create FunctionInfo objects and add them +/// - Finalize the GsymCreator object +/// - Save to file or section +/// +/// The first stage involves creating FunctionInfo objects from another source +/// of information like compiler debug info metadata, DWARF or Breakpad files. +/// Any strings in the FunctionInfo or contained information, like InlineInfo +/// or LineTable objects, should get the string table offsets by calling +/// GsymCreator::insertString(...). Any file indexes that are needed should be +/// obtained by calling GsymCreator::insertFile(...). All of the function calls +/// in GsymCreator are thread safe. This allows multiple threads to create and +/// add FunctionInfo objects while parsing debug information. +/// +/// Once all of the FunctionInfo objects have been added, the +/// GsymCreator::finalize(...) must be called prior to saving. This function +/// will sort the FunctionInfo objects, finalize the string table, and do any +/// other passes on the information needed to prepare the information to be +/// saved. +/// +/// Once the object has been finalized, it can be saved to a file or section. +/// +/// ENCODING +/// +/// GSYM files are designed to be memory mapped into a process as shared, read +/// only data, and used as is. +/// +/// The GSYM file format when in a stand alone file consists of: +/// - Header +/// - Address Table +/// - Function Info Offsets +/// - File Table +/// - String Table +/// - Function Info Data +/// +/// HEADER +/// +/// The header is fully described in "llvm/DebugInfo/GSYM/Header.h". +/// +/// ADDRESS TABLE +/// +/// The address table immediately follows the header in the file and consists +/// of Header.NumAddresses address offsets. These offsets are sorted and can be +/// binary searched for efficient lookups. Addresses in the address table are +/// stored as offsets from a 64 bit base address found in Header.BaseAddress. +/// This allows the address table to contain 8, 16, or 32 offsets. This allows +/// the address table to not require full 64 bit addresses for each address. +/// The resulting GSYM size is smaller and causes fewer pages to be touched +/// during address lookups when the address table is smaller. The size of the +/// address offsets in the address table is specified in the header in +/// Header.AddrOffSize. The first offset in the address table is alinged to +/// Header.AddrOffSize alignement to ensure efficient access when loaded into +/// memory. +/// +/// FUNCTION INFO OFFSETS TABLE +/// +/// The function info offsets table immediately follows the address table and +/// consists of Header.NumAddresses 32 bit file offsets: one for each address +/// in the address table. This data is algined to a 4 byte boundary. The +/// offsets in this table are the relative offsets from the start offset of the +/// GSYM header and point to the function info data for each address in the +/// address table. Keeping this data separate from the address table helps to +/// reduce the number of pages that are touched when address lookups occur on a +/// GSYM file. +/// +/// FILE TABLE +/// +/// The file table immediately follows the function info offsets table. The +/// encoding of the FileTable is: +/// +/// struct FileTable { +/// uint32_t Count; +/// FileEntry Files[]; +/// }; +/// +/// The file table starts with a 32 bit count of the number of files that are +/// used in all of the function info, followed by that number of FileEntry +/// structures. The file table is aligned to a 4 byte boundary, Each file in +/// the file table is represented with a FileEntry structure. +/// See "llvm/DebugInfo/GSYM/FileEntry.h" for details. +/// +/// STRING TABLE +/// +/// The string table follows the file table in stand alone GSYM files and +/// contains all strings for everything contained in the GSYM file. Any string +/// data should be added to the string table and any references to strings +/// inside GSYM information must be stored as 32 bit string table offsets into +/// this string table. The string table always starts with an empty string at +/// offset zero and is followed by any strings needed by the GSYM information. +/// The start of the string table is not aligned to any boundary. +/// +/// FUNCTION INFO DATA +/// +/// The function info data is the payload that contains information about the +/// address that is being looked up. It contains all of the encoded +/// FunctionInfo objects. Each encoded FunctionInfo's data is pointed to by an +/// entry in the Function Info Offsets Table. For details on the exact encoding +/// of FunctionInfo objects, see "llvm/DebugInfo/GSYM/FunctionInfo.h". +class GsymCreator { + // Private member variables require Mutex protections + mutable std::recursive_mutex Mutex; + std::vector<FunctionInfo> Funcs; + StringTableBuilder StrTab; + DenseMap<llvm::gsym::FileEntry, uint32_t> FileEntryToIndex; + std::vector<llvm::gsym::FileEntry> Files; + std::vector<uint8_t> UUID; + bool Finalized = false; + +public: + + GsymCreator(); + + /// Save a GSYM file to a stand alone file. + /// + /// \param Path The file path to save the GSYM file to. + /// \param ByteOrder The endianness to use when saving the file. + /// \returns An error object that indicates success or failure of the save. + llvm::Error save(StringRef Path, llvm::support::endianness ByteOrder) const; + + /// Encode a GSYM into the file writer stream at the current position. + /// + /// \param O The stream to save the binary data to + /// \returns An error object that indicates success or failure of the save. + llvm::Error encode(FileWriter &O) const; + + /// Insert a string into the GSYM string table. + /// + /// All strings used by GSYM files must be uniqued by adding them to this + /// string pool and using the returned offset for any string values. + /// + /// \param S The string to insert into the string table. + /// \returns The unique 32 bit offset into the string table. + uint32_t insertString(StringRef S); + + /// Insert a file into this GSYM creator. + /// + /// Inserts a file by adding a FileEntry into the "Files" member variable if + /// the file has not already been added. The file path is split into + /// directory and filename which are both added to the string table. This + /// allows paths to be stored efficiently by reusing the directories that are + /// common between multiple files. + /// + /// \param Path The path to the file to insert. + /// \param Style The path style for the "Path" parameter. + /// \returns The unique file index for the inserted file. + uint32_t insertFile(StringRef Path, + sys::path::Style Style = sys::path::Style::native); + + /// Add a function info to this GSYM creator. + /// + /// All information in the FunctionInfo object must use the + /// GsymCreator::insertString(...) function when creating string table + /// offsets for names and other strings. + /// + /// \param FI The function info object to emplace into our functions list. + void addFunctionInfo(FunctionInfo &&FI); + + /// Finalize the data in the GSYM creator prior to saving the data out. + /// + /// Finalize must be called after all FunctionInfo objects have been added + /// and before GsymCreator::save() is called. + /// + /// \param OS Output stream to report duplicate function infos, overlapping + /// function infos, and function infos that were merged or removed. + /// \returns An error object that indicates success or failure of the + /// finalize. + llvm::Error finalize(llvm::raw_ostream &OS); + + /// Set the UUID value. + /// + /// \param UUIDBytes The new UUID bytes. + void setUUID(llvm::ArrayRef<uint8_t> UUIDBytes) { + UUID.assign(UUIDBytes.begin(), UUIDBytes.end()); + } + + /// Thread safe iteration over all function infos. + /// + /// \param Callback A callback function that will get called with each + /// FunctionInfo. If the callback returns false, stop iterating. + void forEachFunctionInfo( + std::function<bool(FunctionInfo &)> const &Callback); + + /// Thread safe const iteration over all function infos. + /// + /// \param Callback A callback function that will get called with each + /// FunctionInfo. If the callback returns false, stop iterating. + void forEachFunctionInfo( + std::function<bool(const FunctionInfo &)> const &Callback) const; + +}; + +} // namespace gsym +} // namespace llvm + +#endif // #ifndef LLVM_DEBUGINFO_GSYM_GSYMCREATOR_H diff --git a/include/llvm/DebugInfo/GSYM/GsymReader.h b/include/llvm/DebugInfo/GSYM/GsymReader.h new file mode 100644 index 000000000000..113bcee9c9a3 --- /dev/null +++ b/include/llvm/DebugInfo/GSYM/GsymReader.h @@ -0,0 +1,228 @@ +//===- GsymReader.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_GSYM_GSYMREADER_H +#define LLVM_DEBUGINFO_GSYM_GSYMREADER_H + + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/GSYM/FileEntry.h" +#include "llvm/DebugInfo/GSYM/FunctionInfo.h" +#include "llvm/DebugInfo/GSYM/Header.h" +#include "llvm/DebugInfo/GSYM/LineEntry.h" +#include "llvm/DebugInfo/GSYM/StringTable.h" +#include "llvm/Support/DataExtractor.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorOr.h" + +#include <inttypes.h> +#include <memory> +#include <stdint.h> +#include <string> +#include <vector> + +namespace llvm { +class MemoryBuffer; +class raw_ostream; + +namespace gsym { + +/// GsymReader is used to read GSYM data from a file or buffer. +/// +/// This class is optimized for very quick lookups when the endianness matches +/// the host system. The Header, address table, address info offsets, and file +/// table is designed to be mmap'ed as read only into memory and used without +/// any parsing needed. If the endianness doesn't match, we swap these objects +/// and tables into GsymReader::SwappedData and then point our header and +/// ArrayRefs to this swapped internal data. +/// +/// GsymReader objects must use one of the static functions to create an +/// instance: GsymReader::openFile(...) and GsymReader::copyBuffer(...). + +class GsymReader { + GsymReader(std::unique_ptr<MemoryBuffer> Buffer); + llvm::Error parse(); + + std::unique_ptr<MemoryBuffer> MemBuffer; + StringRef GsymBytes; + llvm::support::endianness Endian; + const Header *Hdr = nullptr; + ArrayRef<uint8_t> AddrOffsets; + ArrayRef<uint32_t> AddrInfoOffsets; + ArrayRef<FileEntry> Files; + StringTable StrTab; + /// When the GSYM file's endianness doesn't match the host system then + /// we must decode all data structures that need to be swapped into + /// local storage and set point the ArrayRef objects above to these swapped + /// copies. + struct SwappedData { + Header Hdr; + std::vector<uint8_t> AddrOffsets; + std::vector<uint32_t> AddrInfoOffsets; + std::vector<FileEntry> Files; + }; + std::unique_ptr<SwappedData> Swap; + +public: + GsymReader(GsymReader &&RHS); + ~GsymReader(); + + /// Construct a GsymReader from a file on disk. + /// + /// \param Path The file path the GSYM file to read. + /// \returns An expected GsymReader that contains the object or an error + /// object that indicates reason for failing to read the GSYM. + static llvm::Expected<GsymReader> openFile(StringRef Path); + + /// Construct a GsymReader from a buffer. + /// + /// \param Bytes A set of bytes that will be copied and owned by the + /// returned object on success. + /// \returns An expected GsymReader that contains the object or an error + /// object that indicates reason for failing to read the GSYM. + static llvm::Expected<GsymReader> copyBuffer(StringRef Bytes); + + /// Access the GSYM header. + /// \returns A native endian version of the GSYM header. + const Header &getHeader() const; + + /// Get the full function info for an address. + /// + /// \param Addr A virtual address from the orignal object file to lookup. + /// \returns An expected FunctionInfo that contains the function info object + /// or an error object that indicates reason for failing to lookup the + /// address, + llvm::Expected<FunctionInfo> getFunctionInfo(uint64_t Addr) const; + + /// Get a string from the string table. + /// + /// \param Offset The string table offset for the string to retrieve. + /// \returns The string from the strin table. + StringRef getString(uint32_t Offset) const { return StrTab[Offset]; } + +protected: + /// Gets an address from the address table. + /// + /// Addresses are stored as offsets frrom the gsym::Header::BaseAddress. + /// + /// \param Index A index into the address table. + /// \returns A resolved virtual address for adddress in the address table + /// or llvm::None if Index is out of bounds. + Optional<uint64_t> getAddress(size_t Index) const; + + /// Get the a file entry for the suppplied file index. + /// + /// Used to convert any file indexes in the FunctionInfo data back into + /// files. This function can be used for iteration, but is more commonly used + /// for random access when doing lookups. + /// + /// \param Index An index into the file table. + /// \returns An optional FileInfo that will be valid if the file index is + /// valid, or llvm::None if the file index is out of bounds, + Optional<FileEntry> getFile(uint32_t Index) const { + if (Index < Files.size()) + return Files[Index]; + return llvm::None; + } + + /// Get an appropriate address info offsets array. + /// + /// The address table in the GSYM file is stored as array of 1, 2, 4 or 8 + /// byte offsets from the The gsym::Header::BaseAddress. The table is stored + /// internally as a array of bytes that are in the correct endianness. When + /// we access this table we must get an array that matches those sizes. This + /// templatized helper function is used when accessing address offsets in the + /// AddrOffsets member variable. + /// + /// \returns An ArrayRef of an appropriate address offset size. + template <class T> ArrayRef<T> + getAddrOffsets() const { + return ArrayRef<T>(reinterpret_cast<const T *>(AddrOffsets.data()), + AddrOffsets.size()/sizeof(T)); + } + + /// Get an appropriate address from the address table. + /// + /// The address table in the GSYM file is stored as array of 1, 2, 4 or 8 + /// byte address offsets from the The gsym::Header::BaseAddress. The table is + /// stored internally as a array of bytes that are in the correct endianness. + /// In order to extract an address from the address table we must access the + /// address offset using the correct size and then add it to the BaseAddress + /// in the header. + /// + /// \param Index An index into the AddrOffsets array. + /// \returns An virtual address that matches the original object file for the + /// address as the specified index, or llvm::None if Index is out of bounds. + template <class T> Optional<uint64_t> + addressForIndex(size_t Index) const { + ArrayRef<T> AIO = getAddrOffsets<T>(); + if (Index < AIO.size()) + return AIO[Index] + Hdr->BaseAddress; + return llvm::None; + } + /// Lookup an address offset in the AddrOffsets table. + /// + /// Given an address offset, look it up using a binary search of the + /// AddrOffsets table. + /// + /// \param AddrOffset An address offset, that has already been computed by + /// subtracting the gsym::Header::BaseAddress. + /// \returns The matching address offset index. This index will be used to + /// extract the FunctionInfo data's offset from the AddrInfoOffsets array. + template <class T> + uint64_t getAddressOffsetIndex(const uint64_t AddrOffset) const { + ArrayRef<T> AIO = getAddrOffsets<T>(); + const auto Begin = AIO.begin(); + const auto End = AIO.end(); + auto Iter = std::lower_bound(Begin, End, AddrOffset); + if (Iter == End || AddrOffset < *Iter) + --Iter; + return std::distance(Begin, Iter); + } + + /// Create a GSYM from a memory buffer. + /// + /// Called by both openFile() and copyBuffer(), this function does all of the + /// work of parsing the GSYM file and returning an error. + /// + /// \param MemBuffer A memory buffer that will transfer ownership into the + /// GsymReader. + /// \returns An expected GsymReader that contains the object or an error + /// object that indicates reason for failing to read the GSYM. + static llvm::Expected<llvm::gsym::GsymReader> + create(std::unique_ptr<MemoryBuffer> &MemBuffer); + + + /// Given an address, find the address index. + /// + /// Binary search the address table and find the matching address index. + /// + /// \param Addr A virtual address that matches the original object file + /// to lookup. + /// \returns An index into the address table. This index can be used to + /// extract the FunctionInfo data's offset from the AddrInfoOffsets array. + /// Returns an error if the address isn't in the GSYM with details of why. + Expected<uint64_t> getAddressIndex(const uint64_t Addr) const; + + /// Given an address index, get the offset for the FunctionInfo. + /// + /// Looking up an address is done by finding the corresponding address + /// index for the address. This index is then used to get the offset of the + /// FunctionInfo data that we will decode using this function. + /// + /// \param Index An index into the address table. + /// \returns An optional GSYM data offset for the offset of the FunctionInfo + /// that needs to be decoded. + Optional<uint64_t> getAddressInfoOffset(size_t Index) const; +}; + +} // namespace gsym +} // namespace llvm + +#endif // #ifndef LLVM_DEBUGINFO_GSYM_GSYMREADER_H diff --git a/include/llvm/DebugInfo/GSYM/Header.h b/include/llvm/DebugInfo/GSYM/Header.h new file mode 100644 index 000000000000..6652c59c97a6 --- /dev/null +++ b/include/llvm/DebugInfo/GSYM/Header.h @@ -0,0 +1,129 @@ +//===- Header.h -------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_GSYM_HEADER_H +#define LLVM_DEBUGINFO_GSYM_HEADER_H + +#include "llvm/Support/Error.h" + +#include <cstddef> +#include <cstdint> + +namespace llvm { +class raw_ostream; +class DataExtractor; + +namespace gsym { +class FileWriter; + +constexpr uint32_t GSYM_MAGIC = 0x4753594d; // 'GSYM' +constexpr uint32_t GSYM_CIGAM = 0x4d595347; // 'MYSG' +constexpr uint32_t GSYM_VERSION = 1; +constexpr size_t GSYM_MAX_UUID_SIZE = 20; + +/// The GSYM header. +/// +/// The GSYM header is found at the start of a stand alone GSYM file, or as +/// the first bytes in a section when GSYM is contained in a section of an +/// executable file (ELF, mach-o, COFF). +/// +/// The structure is encoded exactly as it appears in the structure definition +/// with no gaps between members. Alignment should not change from system to +/// system as the members were laid out so that they shouldn't align +/// differently on different architectures. +/// +/// When endianness of the system loading a GSYM file matches, the file can +/// be mmap'ed in and a pointer to the header can be cast to the first bytes +/// of the file (stand alone GSYM file) or section data (GSYM in a section). +/// When endianness is swapped, the Header::decode() function should be used to +/// decode the header. +struct Header { + /// The magic bytes should be set to GSYM_MAGIC. This helps detect if a file + /// is a GSYM file by scanning the first 4 bytes of a file or section. + /// This value might appear byte swapped + uint32_t Magic; + /// The version can number determines how the header is decoded and how each + /// InfoType in FunctionInfo is encoded/decoded. As version numbers increase, + /// "Magic" and "Version" members should always appear at offset zero and 4 + /// respectively to ensure clients figure out if they can parse the format. + uint16_t Version; + /// The size in bytes of each address offset in the address offsets table. + uint8_t AddrOffSize; + /// The size in bytes of the UUID encoded in the "UUID" member. + uint8_t UUIDSize; + /// The 64 bit base address that all address offsets in the address offsets + /// table are relative to. Storing a full 64 bit address allows our address + /// offsets table to be smaller on disk. + uint64_t BaseAddress; + /// The number of addresses stored in the address offsets table. + uint32_t NumAddresses; + /// The file relative offset of the start of the string table for strings + /// contained in the GSYM file. If the GSYM in contained in a stand alone + /// file this will be the file offset of the start of the string table. If + /// the GSYM is contained in a section within an executable file, this can + /// be the offset of the first string used in the GSYM file and can possibly + /// span one or more executable string tables. This allows the strings to + /// share string tables in an ELF or mach-o file. + uint32_t StrtabOffset; + /// The size in bytes of the string table. For a stand alone GSYM file, this + /// will be the exact size in bytes of the string table. When the GSYM data + /// is in a section within an executable file, this size can span one or more + /// sections that contains strings. This allows any strings that are already + /// stored in the executable file to be re-used, and any extra strings could + /// be added to another string table and the string table offset and size + /// can be set to span all needed string tables. + uint32_t StrtabSize; + /// The UUID of the original executable file. This is stored to allow + /// matching a GSYM file to an executable file when symbolication is + /// required. Only the first "UUIDSize" bytes of the UUID are valid. Any + /// bytes in the UUID value that appear after the first UUIDSize bytes should + /// be set to zero. + uint8_t UUID[GSYM_MAX_UUID_SIZE]; + + /// Check if a header is valid and return an error if anything is wrong. + /// + /// This function can be used prior to encoding a header to ensure it is + /// valid, or after decoding a header to ensure it is valid and supported. + /// + /// Check a correctly byte swapped header for errors: + /// - check magic value + /// - check that version number is supported + /// - check that the address offset size is supported + /// - check that the UUID size is valid + /// + /// \returns An error if anything is wrong in the header, or Error::success() + /// if there are no errors. + llvm::Error checkForError() const; + + /// Decode an object from a binary data stream. + /// + /// \param Data The binary stream to read the data from. This object must + /// have the data for the object starting at offset zero. The data + /// can contain more data than needed. + /// + /// \returns A Header or an error describing the issue that was + /// encountered during decoding. + static llvm::Expected<Header> decode(DataExtractor &Data); + + /// Encode this object into FileWriter stream. + /// + /// \param O The binary stream to write the data to at the current file + /// position. + /// + /// \returns An error object that indicates success or failure of the + /// encoding process. + llvm::Error encode(FileWriter &O) const; +}; + +bool operator==(const Header &LHS, const Header &RHS); +raw_ostream &operator<<(raw_ostream &OS, const llvm::gsym::Header &H); + +} // namespace gsym +} // namespace llvm + +#endif // #ifndef LLVM_DEBUGINFO_GSYM_HEADER_H diff --git a/include/llvm/DebugInfo/GSYM/InlineInfo.h b/include/llvm/DebugInfo/GSYM/InlineInfo.h index 222430622932..48fd9a7c1308 100644 --- a/include/llvm/DebugInfo/GSYM/InlineInfo.h +++ b/include/llvm/DebugInfo/GSYM/InlineInfo.h @@ -1,9 +1,8 @@ //===- InlineInfo.h ---------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -12,6 +11,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/DebugInfo/GSYM/Range.h" +#include "llvm/Support/Error.h" #include <stdint.h> #include <vector> @@ -31,6 +31,30 @@ namespace gsym { /// Any clients that encode information will need to ensure the ranges are /// all contined correctly or lookups could fail. Add ranges in these objects /// must be contained in the top level FunctionInfo address ranges as well. +/// +/// ENCODING +/// +/// When saved to disk, the inline info encodes all ranges to be relative to +/// a parent address range. This will be the FunctionInfo's start address if +/// the InlineInfo is directly contained in a FunctionInfo, or a the start +/// address of the containing parent InlineInfo's first "Ranges" member. This +/// allows address ranges to be efficiently encoded using ULEB128 encodings as +/// we encode the offset and size of each range instead of full addresses. This +/// also makes any encoded addresses easy to relocate as we just need to +/// relocate the FunctionInfo's start address. +/// +/// - The AddressRanges member "Ranges" is encoded using an approriate base +/// address as described above. +/// - UINT8 boolean value that specifies if the InlineInfo object has children. +/// - UINT32 string table offset that points to the name of the inline +/// function. +/// - ULEB128 integer that specifies the file of the call site that called +/// this function. +/// - ULEB128 integer that specifies the source line of the call site that +/// called this function. +/// - if this object has children, enocode each child InlineInfo using the +/// the first address range's start address as the base address. +/// struct InlineInfo { uint32_t Name; ///< String table offset in the string table. @@ -62,6 +86,37 @@ struct InlineInfo { /// \returns optional vector of InlineInfo objects that describe the /// inline call stack for a given address, false otherwise. llvm::Optional<InlineArray> getInlineStack(uint64_t Addr) const; + + /// Decode an InlineInfo object from a binary data stream. + /// + /// \param Data The binary stream to read the data from. This object must + /// have the data for the InlineInfo object starting at offset zero. The data + /// can contain more data than needed. + /// + /// \param BaseAddr The base address to use when decoding all address ranges. + /// This will be the FunctionInfo's start address if this object is directly + /// contained in a FunctionInfo object, or the start address of the first + /// address range in an InlineInfo object of this object is a child of + /// another InlineInfo object. + /// \returns An InlineInfo or an error describing the issue that was + /// encountered during decoding. + static llvm::Expected<InlineInfo> decode(DataExtractor &Data, + uint64_t BaseAddr); + + /// Encode this InlineInfo object into FileWriter stream. + /// + /// \param O The binary stream to write the data to at the current file + /// position. + /// + /// \param BaseAddr The base address to use when encoding all address ranges. + /// This will be the FunctionInfo's start address if this object is directly + /// contained in a FunctionInfo object, or the start address of the first + /// address range in an InlineInfo object of this object is a child of + /// another InlineInfo object. + /// + /// \returns An error object that indicates success or failure or the + /// encoding process. + llvm::Error encode(FileWriter &O, uint64_t BaseAddr) const; }; inline bool operator==(const InlineInfo &LHS, const InlineInfo &RHS) { diff --git a/include/llvm/DebugInfo/GSYM/LineEntry.h b/include/llvm/DebugInfo/GSYM/LineEntry.h index 6b9380940bd3..aac7c48e067e 100644 --- a/include/llvm/DebugInfo/GSYM/LineEntry.h +++ b/include/llvm/DebugInfo/GSYM/LineEntry.h @@ -1,9 +1,8 @@ //===- LineEntry.h ----------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/GSYM/LineTable.h b/include/llvm/DebugInfo/GSYM/LineTable.h new file mode 100644 index 000000000000..3cdbccb08ced --- /dev/null +++ b/include/llvm/DebugInfo/GSYM/LineTable.h @@ -0,0 +1,198 @@ +//===- LineTable.h ----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_GSYM_LINETABLE_H +#define LLVM_DEBUGINFO_GSYM_LINETABLE_H + +#include "llvm/DebugInfo/GSYM/LineEntry.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <vector> + +namespace llvm { +namespace gsym { + +struct FunctionInfo; +class FileWriter; + +/// LineTable class contains deserialized versions of line tables for each +/// function's address ranges. +/// +/// When saved to disk, the line table is encoded using a modified version of +/// the DWARF line tables that only tracks address to source file and line. +/// +/// ENCODING +/// +/// The line table starts with a small prolog that contains the following +/// values: +/// +/// ENCODING NAME DESCRIPTION +/// ======== =========== ==================================================== +/// SLEB MinDelta The min line delta for special opcodes that advance +/// the address and line number. +/// SLEB MaxDelta The max line delta for single byte opcodes that +/// advance the address and line number. +/// ULEB FirstLine The value of the first source line number to +/// initialize the LineEntry with. +/// +/// Once these prolog items are read, we initialize a LineEntry struct with +/// the start address of the function from the FunctionInfo's address range, +/// a default file index of 1, and the line number set to "FirstLine" from +/// the prolog above: +/// +/// LineEntry Row(BaseAddr, 1, FirstLine); +/// +/// The line table state machine is now initialized and ready to be parsed. +/// The stream that follows this encodes the line entries in a compact +/// form. Some opcodes cause "Row" to be modified and some opcodes may also +/// push "Row" onto the end of the "LineTable.Lines" vector. The end result +/// is a vector of LineEntry structs that is sorted in ascending address +/// order. +/// +/// NORMAL OPCODES +/// +/// The opcodes 0 through 3 are normal in opcodes. Their encoding and +/// descriptions are listed below: +/// +/// ENCODING ENUMERATION VALUE DESCRIPTION +/// ======== ================ ===== ======================================== +/// LTOC_EndSequence 0x00 Parsing is done. +/// ULEB LTOC_SetFile 0x01 Row.File = ULEB +/// ULEB LTOC_AdvancePC 0x02 Row.Addr += ULEB, push "Row". +/// SLEB LTOC_AdvanceLine 0x03 Row.Line += SLEB +/// LTOC_FirstSpecial 0x04 First special opcode (see SPECIAL +/// OPCODES below). +/// +/// SPECIAL OPCODES +/// +/// Opcodes LTOC_FirstSpecial through 255 are special opcodes that always +/// increment both the Row.Addr and Row.Line and push "Row" onto the +/// LineEntry.Lines array. They do this by using some of the bits to +/// increment/decrement the source line number, and some of the bits to +/// increment the address. Line numbers can go up or down when making line +/// tables, where addresses always only increase since line tables are sorted +/// by address. +/// +/// In order to calculate the amount to increment the line and address for +/// these special opcodes, we calculate the number of values reserved for the +/// line increment/decrement using the "MinDelta" and "MaxDelta" from the +/// prolog: +/// +/// const int64_t LineRange = MaxDelta - MinDelta + 1; +/// +/// Then we can adjust the opcode to not include any of the normal opcodes: +/// +/// const uint8_t AdjustedOp = Opcode - LTOC_FirstSpecial; +/// +/// And we can calculate the line offset, and address offset: +/// +/// const int64_t LineDelta = MinDelta + (AdjustedOp % LineRange); +/// const uint64_t AddrDelta = (AdjustedOp / LineRange); +/// +/// And use these to modify our "Row": +/// +/// Row.Line += LineDelta; +/// Row.Addr += AddrDelta; +/// +/// And push a row onto the line table: +/// +/// Lines.push_back(Row); +/// +/// This is verify similar to the way that DWARF encodes its line tables. The +/// only difference is the DWARF line tables have more normal opcodes and the +/// "Row" contains more members, like source column number, bools for end of +/// prologue, beginnging of epilogue, is statement and many others. There are +/// also more complex rules that happen for the extra normal opcodes. By +/// leaving these extra opcodes out, we leave more bits for the special +/// opcodes that allows us to encode line tables in fewer bytes than standard +/// DWARF encodings. +/// +/// Opcodes that will push "Row" onto the LineEntry.Lines include the +/// LTOC_AdvancePC opcode and all special opcodes. All other opcodes +/// only modify the current "Row", or cause the line table to end. +class LineTable { + typedef std::vector<gsym::LineEntry> Collection; + Collection Lines; ///< All line entries in the line table. +public: + static LineEntry lookup(DataExtractor &Data, uint64_t BaseAddr, + uint64_t Addr); + + /// Decode an LineTable object from a binary data stream. + /// + /// \param Data The binary stream to read the data from. This object must + /// have the data for the LineTable object starting at offset zero. The data + /// can contain more data than needed. + /// + /// \param BaseAddr The base address to use when decoding the line table. + /// This will be the FunctionInfo's start address and will be used to + /// initialize the line table row prior to parsing any opcodes. + /// + /// \returns An LineTable or an error describing the issue that was + /// encountered during decoding. + static llvm::Expected<LineTable> decode(DataExtractor &Data, + uint64_t BaseAddr); + /// Encode this LineTable object into FileWriter stream. + /// + /// \param O The binary stream to write the data to at the current file + /// position. + /// + /// \param BaseAddr The base address to use when decoding the line table. + /// This will be the FunctionInfo's start address. + /// + /// \returns An error object that indicates success or failure or the + /// encoding process. + llvm::Error encode(FileWriter &O, uint64_t BaseAddr) const; + bool empty() const { return Lines.empty(); } + void clear() { Lines.clear(); } + void push(const LineEntry &LE) { + Lines.push_back(LE); + } + size_t isValid() const { + return !Lines.empty(); + } + size_t size() const { + return Lines.size(); + } + LineEntry &get(size_t i) { + assert(i < Lines.size()); + return Lines[i]; + } + const LineEntry &get(size_t i) const { + assert(i < Lines.size()); + return Lines[i]; + } + LineEntry &operator[](size_t i) { + return get(i); + } + const LineEntry &operator[](size_t i) const { + return get(i); + } + bool operator==(const LineTable &RHS) const { + return Lines == RHS.Lines; + } + bool operator!=(const LineTable &RHS) const { + return Lines != RHS.Lines; + } + bool operator<(const LineTable &RHS) const { + const auto LHSSize = Lines.size(); + const auto RHSSize = RHS.Lines.size(); + if (LHSSize == RHSSize) + return Lines < RHS.Lines; + return LHSSize < RHSSize; + } + Collection::const_iterator begin() const { return Lines.begin(); } + Collection::const_iterator end() const { return Lines.end(); } + +}; + +raw_ostream &operator<<(raw_ostream &OS, const gsym::LineTable <); + +} // namespace gsym +} // namespace llvm + +#endif // #ifndef LLVM_DEBUGINFO_GSYM_LINETABLE_H diff --git a/include/llvm/DebugInfo/GSYM/Range.h b/include/llvm/DebugInfo/GSYM/Range.h index 772ff244c5b7..37cfec713f26 100644 --- a/include/llvm/DebugInfo/GSYM/Range.h +++ b/include/llvm/DebugInfo/GSYM/Range.h @@ -1,9 +1,8 @@ -//===- AddressRange.h -------------------------------------------*- C++ -*-===// +//===- Range.h --------------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -21,10 +20,13 @@ #define HEX64(v) llvm::format_hex(v, 18) namespace llvm { +class DataExtractor; class raw_ostream; namespace gsym { +class FileWriter; + /// A class that represents an address range. The range is specified using /// a start and an end address. struct AddressRange { @@ -47,6 +49,18 @@ struct AddressRange { bool operator<(const AddressRange &R) const { return std::make_pair(Start, End) < std::make_pair(R.Start, R.End); } + /// AddressRange objects are encoded and decoded to be relative to a base + /// address. This will be the FunctionInfo's start address if the AddressRange + /// is directly contained in a FunctionInfo, or a base address of the + /// containing parent AddressRange or AddressRanges. This allows address + /// ranges to be efficiently encoded using ULEB128 encodings as we encode the + /// offset and size of each range instead of full addresses. This also makes + /// encoded addresses easy to relocate as we just need to relocate one base + /// address. + /// @{ + void decode(DataExtractor &Data, uint64_t BaseAddr, uint64_t &Offset); + void encode(FileWriter &O, uint64_t BaseAddr) const; + /// @} }; raw_ostream &operator<<(raw_ostream &OS, const AddressRange &R); @@ -66,6 +80,7 @@ public: void clear() { Ranges.clear(); } bool empty() const { return Ranges.empty(); } bool contains(uint64_t Addr) const; + bool contains(AddressRange Range) const; void insert(AddressRange Range); size_t size() const { return Ranges.size(); } bool operator==(const AddressRanges &RHS) const { @@ -77,6 +92,14 @@ public: } Collection::const_iterator begin() const { return Ranges.begin(); } Collection::const_iterator end() const { return Ranges.end(); } + + /// Address ranges are decoded and encoded to be relative to a base address. + /// See the AddressRange comment for the encode and decode methods for full + /// details. + /// @{ + void decode(DataExtractor &Data, uint64_t BaseAddr, uint64_t &Offset); + void encode(FileWriter &O, uint64_t BaseAddr) const; + /// @} }; raw_ostream &operator<<(raw_ostream &OS, const AddressRanges &AR); diff --git a/include/llvm/DebugInfo/GSYM/StringTable.h b/include/llvm/DebugInfo/GSYM/StringTable.h index 0001b8b82743..a96ae5899da3 100644 --- a/include/llvm/DebugInfo/GSYM/StringTable.h +++ b/include/llvm/DebugInfo/GSYM/StringTable.h @@ -1,9 +1,8 @@ //===- StringTable.h --------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/include/llvm/DebugInfo/PDB/GenericError.h b/include/llvm/DebugInfo/PDB/GenericError.h index ec85d92d2a92..af93be931b8e 100644 --- a/include/llvm/DebugInfo/PDB/GenericError.h +++ b/include/llvm/DebugInfo/PDB/GenericError.h @@ -20,7 +20,7 @@ enum class pdb_error_code { dia_sdk_not_present, dia_failed_loading, signature_out_of_date, - external_cmdline_ref, + no_matching_pch, unspecified, }; } // namespace pdb diff --git a/include/llvm/DebugInfo/PDB/Native/SymbolCache.h b/include/llvm/DebugInfo/PDB/Native/SymbolCache.h index 0b15ab474f71..4adf3b394c2e 100644 --- a/include/llvm/DebugInfo/PDB/Native/SymbolCache.h +++ b/include/llvm/DebugInfo/PDB/Native/SymbolCache.h @@ -87,7 +87,7 @@ public: // Initial construction must not access the cache, since it must be done // atomically. - auto Result = llvm::make_unique<ConcreteSymbolT>( + auto Result = std::make_unique<ConcreteSymbolT>( Session, Id, std::forward<Args>(ConstructorArgs)...); Result->SymbolId = Id; diff --git a/include/llvm/DebugInfo/PDB/PDBSymbol.h b/include/llvm/DebugInfo/PDB/PDBSymbol.h index d9004a8894d9..0d95a2467556 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbol.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbol.h @@ -131,7 +131,7 @@ public: auto BaseIter = RawSymbol->findChildren(T::Tag); if (!BaseIter) return nullptr; - return llvm::make_unique<ConcreteSymbolEnumerator<T>>(std::move(BaseIter)); + return std::make_unique<ConcreteSymbolEnumerator<T>>(std::move(BaseIter)); } std::unique_ptr<IPDBEnumSymbols> findAllChildren(PDB_SymType Type) const; std::unique_ptr<IPDBEnumSymbols> findAllChildren() const; diff --git a/include/llvm/DebugInfo/Symbolize/Symbolize.h b/include/llvm/DebugInfo/Symbolize/Symbolize.h index d3da28ca0b7b..11599fc1797d 100644 --- a/include/llvm/DebugInfo/Symbolize/Symbolize.h +++ b/include/llvm/DebugInfo/Symbolize/Symbolize.h @@ -39,6 +39,7 @@ public: bool UseSymbolTable = true; bool Demangle = true; bool RelativeAddresses = false; + bool UntagAddresses = false; std::string DefaultArch; std::vector<std::string> DsymHints; std::string FallbackDebugPath; |