diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-16 21:03:24 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-16 21:03:24 +0000 |
commit | 7c7aba6e5fef47a01a136be655b0a92cfd7090f6 (patch) | |
tree | 99ec531924f6078534b100ab9d7696abce848099 /lib/DebugInfo | |
parent | 7ab83427af0f77b59941ceba41d509d7d097b065 (diff) |
Notes
Diffstat (limited to 'lib/DebugInfo')
24 files changed, 272 insertions, 392 deletions
diff --git a/lib/DebugInfo/CodeView/CMakeLists.txt b/lib/DebugInfo/CodeView/CMakeLists.txt index 2f9e8981b698a..f916695a84392 100644 --- a/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/lib/DebugInfo/CodeView/CMakeLists.txt @@ -20,6 +20,7 @@ add_llvm_library(LLVMDebugInfoCodeView LazyRandomTypeCollection.cpp Line.cpp RecordSerialization.cpp + StringsAndChecksums.cpp SymbolRecordMapping.cpp SymbolDumper.cpp SymbolSerializer.cpp @@ -32,7 +33,7 @@ add_llvm_library(LLVMDebugInfoCodeView TypeSerializer.cpp TypeStreamMerger.cpp TypeTableCollection.cpp - + ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/CodeView ) diff --git a/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp b/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp index 6e647c4b976b5..de02525270c45 100644 --- a/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp +++ b/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp @@ -58,6 +58,10 @@ Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const { uint32_t Begin = Writer.getOffset(); uint32_t End = Begin + StringSize; + // Write a null string at the beginning. + if (auto EC = Writer.writeCString(StringRef())) + return EC; + for (auto &Pair : Strings) { StringRef S = Pair.getKey(); uint32_t Offset = Begin + Pair.getValue(); @@ -68,6 +72,7 @@ Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const { } Writer.setOffset(End); + assert((End - Begin) == StringSize); return Error::success(); } diff --git a/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp b/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp index e9124e68fe821..334c5e002bbca 100644 --- a/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp +++ b/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp @@ -50,7 +50,7 @@ DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; } BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; } DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder( - std::unique_ptr<DebugSubsection> Subsection, CodeViewContainer Container) + std::shared_ptr<DebugSubsection> Subsection, CodeViewContainer Container) : Subsection(std::move(Subsection)), Container(Container) {} uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() { diff --git a/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp b/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp index 8550107741ce7..9b824333369be 100644 --- a/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp +++ b/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp @@ -26,40 +26,9 @@ using namespace llvm; using namespace llvm::codeview; -DebugSubsectionState::DebugSubsectionState() {} - -DebugSubsectionState::DebugSubsectionState( - const DebugStringTableSubsectionRef &Strings) - : Strings(&Strings) {} - -DebugSubsectionState::DebugSubsectionState( - const DebugStringTableSubsectionRef &Strings, - const DebugChecksumsSubsectionRef &Checksums) - : Strings(&Strings), Checksums(&Checksums) {} - -void DebugSubsectionState::initializeStrings(const DebugSubsectionRecord &SR) { - assert(SR.kind() == DebugSubsectionKind::StringTable); - assert(!Strings && "Found a string table even though we already have one!"); - - OwnedStrings = llvm::make_unique<DebugStringTableSubsectionRef>(); - consumeError(OwnedStrings->initialize(SR.getRecordData())); - Strings = OwnedStrings.get(); -} - -void DebugSubsectionState::initializeChecksums( - const DebugSubsectionRecord &FCR) { - assert(FCR.kind() == DebugSubsectionKind::FileChecksums); - if (Checksums) - return; - - OwnedChecksums = llvm::make_unique<DebugChecksumsSubsectionRef>(); - consumeError(OwnedChecksums->initialize(FCR.getRecordData())); - Checksums = OwnedChecksums.get(); -} - -Error llvm::codeview::visitDebugSubsection(const DebugSubsectionRecord &R, - DebugSubsectionVisitor &V, - const DebugSubsectionState &State) { +Error llvm::codeview::visitDebugSubsection( + const DebugSubsectionRecord &R, DebugSubsectionVisitor &V, + const StringsAndChecksumsRef &State) { BinaryStreamReader Reader(R.getRecordData()); switch (R.kind()) { case DebugSubsectionKind::Lines: { diff --git a/lib/DebugInfo/CodeView/StringsAndChecksums.cpp b/lib/DebugInfo/CodeView/StringsAndChecksums.cpp new file mode 100644 index 0000000000000..928bf8c94f735 --- /dev/null +++ b/lib/DebugInfo/CodeView/StringsAndChecksums.cpp @@ -0,0 +1,55 @@ +//===- StringsAndChecksums.cpp ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" + +using namespace llvm; +using namespace llvm::codeview; + +StringsAndChecksumsRef::StringsAndChecksumsRef() {} + +StringsAndChecksumsRef::StringsAndChecksumsRef( + const DebugStringTableSubsectionRef &Strings) + : Strings(&Strings) {} + +StringsAndChecksumsRef::StringsAndChecksumsRef( + const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &Checksums) + : Strings(&Strings), Checksums(&Checksums) {} + +void StringsAndChecksumsRef::initializeStrings( + const DebugSubsectionRecord &SR) { + assert(SR.kind() == DebugSubsectionKind::StringTable); + assert(!Strings && "Found a string table even though we already have one!"); + + OwnedStrings = llvm::make_unique<DebugStringTableSubsectionRef>(); + consumeError(OwnedStrings->initialize(SR.getRecordData())); + Strings = OwnedStrings.get(); +} + +void StringsAndChecksumsRef::setChecksums( + const DebugChecksumsSubsectionRef &CS) { + OwnedChecksums = llvm::make_unique<DebugChecksumsSubsectionRef>(); + *OwnedChecksums = CS; + Checksums = OwnedChecksums.get(); +} + +void StringsAndChecksumsRef::initializeChecksums( + const DebugSubsectionRecord &FCR) { + assert(FCR.kind() == DebugSubsectionKind::FileChecksums); + if (Checksums) + return; + + OwnedChecksums = llvm::make_unique<DebugChecksumsSubsectionRef>(); + consumeError(OwnedChecksums->initialize(FCR.getRecordData())); + Checksums = OwnedChecksums.get(); +} diff --git a/lib/DebugInfo/CodeView/SymbolDumper.cpp b/lib/DebugInfo/CodeView/SymbolDumper.cpp index 66045933ce9b5..36abafc079edb 100644 --- a/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ b/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -212,7 +212,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, FileStaticSym &FileStatic) { DictScope S(W, "FileStatic"); - W.printNumber("Index", FileStatic.Index); + printTypeIndex("Index", FileStatic.Index); W.printNumber("ModFilenameOffset", FileStatic.ModFilenameOffset); W.printFlags("Flags", uint16_t(FileStatic.Flags), getLocalFlagNames()); W.printString("Name", FileStatic.Name); @@ -516,7 +516,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, RegisterSym &Register) { DictScope S(W, "RegisterSym"); - W.printNumber("Type", Register.Index); + printTypeIndex("Type", Register.Index); W.printEnum("Seg", uint16_t(Register.Register), getRegisterNames()); W.printString("Name", Register.Name); return Error::success(); @@ -524,7 +524,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, PublicSym32 &Public) { DictScope S(W, "PublicSym"); - W.printNumber("Type", Public.Index); + printTypeIndex("Type", Public.Index); W.printNumber("Seg", Public.Segment); W.printNumber("Off", Public.Offset); W.printString("Name", Public.Name); @@ -631,7 +631,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, W.printHex("Offset", RegRel.Offset); printTypeIndex("Type", RegRel.Type); - W.printHex("Register", RegRel.Register); + W.printEnum("Register", uint16_t(RegRel.Register), getRegisterNames()); W.printString("VarName", RegRel.Name); return Error::success(); } diff --git a/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp b/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp index ea46841a70f63..d731dc1b0a372 100644 --- a/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp +++ b/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp @@ -307,7 +307,7 @@ Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, error(IO.mapInteger(FrameCookie.CodeOffset)); error(IO.mapInteger(FrameCookie.Register)); - error(IO.mapInteger(FrameCookie.CookieKind)); + error(IO.mapEnum(FrameCookie.CookieKind)); error(IO.mapInteger(FrameCookie.Flags)); return Error::success(); @@ -439,7 +439,7 @@ Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, error(IO.mapInteger(RegRel.Offset)); error(IO.mapInteger(RegRel.Type)); - error(IO.mapInteger(RegRel.Register)); + error(IO.mapEnum(RegRel.Register)); error(IO.mapStringZ(RegRel.Name)); return Error::success(); diff --git a/lib/DebugInfo/CodeView/TypeDatabase.cpp b/lib/DebugInfo/CodeView/TypeDatabase.cpp index af05d2dc294be..08f848b36a9d5 100644 --- a/lib/DebugInfo/CodeView/TypeDatabase.cpp +++ b/lib/DebugInfo/CodeView/TypeDatabase.cpp @@ -12,59 +12,6 @@ using namespace llvm; using namespace llvm::codeview; -namespace { -struct SimpleTypeEntry { - StringRef Name; - SimpleTypeKind Kind; -}; -} - -/// The names here all end in "*". If the simple type is a pointer type, we -/// return the whole name. Otherwise we lop off the last character in our -/// StringRef. -static const SimpleTypeEntry SimpleTypeNames[] = { - {"void*", SimpleTypeKind::Void}, - {"<not translated>*", SimpleTypeKind::NotTranslated}, - {"HRESULT*", SimpleTypeKind::HResult}, - {"signed char*", SimpleTypeKind::SignedCharacter}, - {"unsigned char*", SimpleTypeKind::UnsignedCharacter}, - {"char*", SimpleTypeKind::NarrowCharacter}, - {"wchar_t*", SimpleTypeKind::WideCharacter}, - {"char16_t*", SimpleTypeKind::Character16}, - {"char32_t*", SimpleTypeKind::Character32}, - {"__int8*", SimpleTypeKind::SByte}, - {"unsigned __int8*", SimpleTypeKind::Byte}, - {"short*", SimpleTypeKind::Int16Short}, - {"unsigned short*", SimpleTypeKind::UInt16Short}, - {"__int16*", SimpleTypeKind::Int16}, - {"unsigned __int16*", SimpleTypeKind::UInt16}, - {"long*", SimpleTypeKind::Int32Long}, - {"unsigned long*", SimpleTypeKind::UInt32Long}, - {"int*", SimpleTypeKind::Int32}, - {"unsigned*", SimpleTypeKind::UInt32}, - {"__int64*", SimpleTypeKind::Int64Quad}, - {"unsigned __int64*", SimpleTypeKind::UInt64Quad}, - {"__int64*", SimpleTypeKind::Int64}, - {"unsigned __int64*", SimpleTypeKind::UInt64}, - {"__int128*", SimpleTypeKind::Int128}, - {"unsigned __int128*", SimpleTypeKind::UInt128}, - {"__half*", SimpleTypeKind::Float16}, - {"float*", SimpleTypeKind::Float32}, - {"float*", SimpleTypeKind::Float32PartialPrecision}, - {"__float48*", SimpleTypeKind::Float48}, - {"double*", SimpleTypeKind::Float64}, - {"long double*", SimpleTypeKind::Float80}, - {"__float128*", SimpleTypeKind::Float128}, - {"_Complex float*", SimpleTypeKind::Complex32}, - {"_Complex double*", SimpleTypeKind::Complex64}, - {"_Complex long double*", SimpleTypeKind::Complex80}, - {"_Complex __float128*", SimpleTypeKind::Complex128}, - {"bool*", SimpleTypeKind::Boolean8}, - {"__bool16*", SimpleTypeKind::Boolean16}, - {"__bool32*", SimpleTypeKind::Boolean32}, - {"__bool64*", SimpleTypeKind::Boolean64}, -}; - TypeDatabase::TypeDatabase(uint32_t Capacity) : TypeNameStorage(Allocator) { CVUDTNames.resize(Capacity); TypeRecords.resize(Capacity); @@ -103,22 +50,8 @@ StringRef TypeDatabase::saveTypeName(StringRef TypeName) { } StringRef TypeDatabase::getTypeName(TypeIndex Index) const { - if (Index.isNoneType()) - return "<no type>"; - - if (Index.isSimple()) { - // This is a simple type. - for (const auto &SimpleTypeName : SimpleTypeNames) { - if (SimpleTypeName.Kind == Index.getSimpleKind()) { - if (Index.getSimpleMode() == SimpleTypeMode::Direct) - return SimpleTypeName.Name.drop_back(1); - // Otherwise, this is a pointer type. We gloss over the distinction - // between near, far, 64, 32, etc, and just give a pointer type. - return SimpleTypeName.Name; - } - } - return "<unknown simple type>"; - } + if (Index.isNoneType() || Index.isSimple()) + return TypeIndex::simpleTypeName(Index); if (contains(Index)) return CVUDTNames[Index.toArrayIndex()]; diff --git a/lib/DebugInfo/CodeView/TypeIndex.cpp b/lib/DebugInfo/CodeView/TypeIndex.cpp index 20ba6470cd5be..24fe5fcb28d4f 100644 --- a/lib/DebugInfo/CodeView/TypeIndex.cpp +++ b/lib/DebugInfo/CodeView/TypeIndex.cpp @@ -15,11 +15,88 @@ using namespace llvm; using namespace llvm::codeview; +namespace { +struct SimpleTypeEntry { + StringRef Name; + SimpleTypeKind Kind; +}; + +/// The names here all end in "*". If the simple type is a pointer type, we +/// return the whole name. Otherwise we lop off the last character in our +/// StringRef. +static const SimpleTypeEntry SimpleTypeNames[] = { + {"void*", SimpleTypeKind::Void}, + {"<not translated>*", SimpleTypeKind::NotTranslated}, + {"HRESULT*", SimpleTypeKind::HResult}, + {"signed char*", SimpleTypeKind::SignedCharacter}, + {"unsigned char*", SimpleTypeKind::UnsignedCharacter}, + {"char*", SimpleTypeKind::NarrowCharacter}, + {"wchar_t*", SimpleTypeKind::WideCharacter}, + {"char16_t*", SimpleTypeKind::Character16}, + {"char32_t*", SimpleTypeKind::Character32}, + {"__int8*", SimpleTypeKind::SByte}, + {"unsigned __int8*", SimpleTypeKind::Byte}, + {"short*", SimpleTypeKind::Int16Short}, + {"unsigned short*", SimpleTypeKind::UInt16Short}, + {"__int16*", SimpleTypeKind::Int16}, + {"unsigned __int16*", SimpleTypeKind::UInt16}, + {"long*", SimpleTypeKind::Int32Long}, + {"unsigned long*", SimpleTypeKind::UInt32Long}, + {"int*", SimpleTypeKind::Int32}, + {"unsigned*", SimpleTypeKind::UInt32}, + {"__int64*", SimpleTypeKind::Int64Quad}, + {"unsigned __int64*", SimpleTypeKind::UInt64Quad}, + {"__int64*", SimpleTypeKind::Int64}, + {"unsigned __int64*", SimpleTypeKind::UInt64}, + {"__int128*", SimpleTypeKind::Int128}, + {"unsigned __int128*", SimpleTypeKind::UInt128}, + {"__half*", SimpleTypeKind::Float16}, + {"float*", SimpleTypeKind::Float32}, + {"float*", SimpleTypeKind::Float32PartialPrecision}, + {"__float48*", SimpleTypeKind::Float48}, + {"double*", SimpleTypeKind::Float64}, + {"long double*", SimpleTypeKind::Float80}, + {"__float128*", SimpleTypeKind::Float128}, + {"_Complex float*", SimpleTypeKind::Complex32}, + {"_Complex double*", SimpleTypeKind::Complex64}, + {"_Complex long double*", SimpleTypeKind::Complex80}, + {"_Complex __float128*", SimpleTypeKind::Complex128}, + {"bool*", SimpleTypeKind::Boolean8}, + {"__bool16*", SimpleTypeKind::Boolean16}, + {"__bool32*", SimpleTypeKind::Boolean32}, + {"__bool64*", SimpleTypeKind::Boolean64}, +}; +} // namespace + +StringRef TypeIndex::simpleTypeName(TypeIndex TI) { + assert(TI.isNoneType() || TI.isSimple()); + + if (TI.isNoneType()) + return "<no type>"; + + // This is a simple type. + for (const auto &SimpleTypeName : SimpleTypeNames) { + if (SimpleTypeName.Kind == TI.getSimpleKind()) { + if (TI.getSimpleMode() == SimpleTypeMode::Direct) + return SimpleTypeName.Name.drop_back(1); + // Otherwise, this is a pointer type. We gloss over the distinction + // between near, far, 64, 32, etc, and just give a pointer type. + return SimpleTypeName.Name; + } + } + return "<unknown simple type>"; +} + void llvm::codeview::printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, TypeIndex TI, TypeCollection &Types) { StringRef TypeName; - if (!TI.isNoneType()) - TypeName = Types.getTypeName(TI); + if (!TI.isNoneType()) { + if (TI.isSimple()) + TypeName = TypeIndex::simpleTypeName(TI); + else + TypeName = Types.getTypeName(TI); + } + if (!TypeName.empty()) Printer.printHex(FieldName, TypeName, TI.getIndex()); else diff --git a/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp b/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp index 11e2e215303c1..8704cea607867 100644 --- a/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp +++ b/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp @@ -34,7 +34,7 @@ static inline PointerMode getPointerMode(uint32_t Attrs) { static inline bool isMemberPointer(uint32_t Attrs) { PointerMode Mode = getPointerMode(Attrs); return Mode == PointerMode::PointerToDataMember || - Mode == PointerMode::PointerToDataMember; + Mode == PointerMode::PointerToMemberFunction; } static inline uint32_t getEncodedIntegerLength(ArrayRef<uint8_t> Data) { diff --git a/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp index 97b52f0fbdd6c..87009bf1b6a1d 100644 --- a/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp +++ b/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp @@ -55,6 +55,13 @@ bool DWARFAcceleratorTable::extract() { return true; } +uint32_t DWARFAcceleratorTable::getNumBuckets() { return Hdr.NumBuckets; } +uint32_t DWARFAcceleratorTable::getNumHashes() { return Hdr.NumHashes; } +uint32_t DWARFAcceleratorTable::getSizeHdr() { return sizeof(Hdr); } +uint32_t DWARFAcceleratorTable::getHeaderDataLength() { + return Hdr.HeaderDataLength; +} + LLVM_DUMP_METHOD void DWARFAcceleratorTable::dump(raw_ostream &OS) const { // Dump the header. OS << "Magic = " << format("0x%08x", Hdr.Magic) << '\n' diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp index 42ab48808f9a4..9bafcde57f0ae 100644 --- a/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -425,248 +425,6 @@ DWARFDie DWARFContext::getDIEForOffset(uint32_t Offset) { return DWARFDie(); } -namespace { - -class Verifier { - raw_ostream &OS; - DWARFContext &DCtx; -public: - Verifier(raw_ostream &S, DWARFContext &D) : OS(S), DCtx(D) {} - - bool HandleDebugInfo() { - bool Success = true; - // 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; - - OS << "Verifying .debug_info...\n"; - for (const auto &CU : DCtx.compile_units()) { - unsigned NumDies = CU->getNumDIEs(); - for (unsigned I = 0; I < NumDies; ++I) { - auto Die = CU->getDIEAtIndex(I); - const auto Tag = Die.getTag(); - if (Tag == DW_TAG_null) - continue; - for (auto AttrValue : Die.attributes()) { - const auto Attr = AttrValue.Attr; - const auto Form = AttrValue.Value.getForm(); - switch (Attr) { - case DW_AT_ranges: - // Make sure the offset in the DW_AT_ranges attribute is valid. - if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) { - if (*SectionOffset >= DCtx.getRangeSection().Data.size()) { - Success = false; - OS << "error: DW_AT_ranges offset is beyond .debug_ranges " - "bounds:\n"; - Die.dump(OS, 0); - OS << "\n"; - } - } else { - Success = false; - OS << "error: DIE has invalid DW_AT_ranges encoding:\n"; - Die.dump(OS, 0); - OS << "\n"; - } - break; - case DW_AT_stmt_list: - // Make sure the offset in the DW_AT_stmt_list attribute is valid. - if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) { - if (*SectionOffset >= DCtx.getLineSection().Data.size()) { - Success = false; - OS << "error: DW_AT_stmt_list offset is beyond .debug_line " - "bounds: " - << format("0x%08" PRIx32, *SectionOffset) << "\n"; - CU->getUnitDIE().dump(OS, 0); - OS << "\n"; - } - } else { - Success = false; - OS << "error: DIE has invalid DW_AT_stmt_list encoding:\n"; - Die.dump(OS, 0); - OS << "\n"; - } - break; - - default: - break; - } - switch (Form) { - case DW_FORM_ref1: - case DW_FORM_ref2: - case DW_FORM_ref4: - case DW_FORM_ref8: - case DW_FORM_ref_udata: { - // Verify all CU relative references are valid CU offsets. - Optional<uint64_t> RefVal = AttrValue.Value.getAsReference(); - assert(RefVal); - if (RefVal) { - auto DieCU = Die.getDwarfUnit(); - auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset(); - auto CUOffset = AttrValue.Value.getRawUValue(); - if (CUOffset >= CUSize) { - Success = false; - OS << "error: " << FormEncodingString(Form) << " CU offset " - << format("0x%08" PRIx32, CUOffset) - << " is invalid (must be less than CU size of " - << format("0x%08" PRIx32, CUSize) << "):\n"; - Die.dump(OS, 0); - OS << "\n"; - } else { - // Valid reference, but we will verify it points to an actual - // DIE later. - ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset()); - } - } - break; - } - case DW_FORM_ref_addr: { - // Verify all absolute DIE references have valid offsets in the - // .debug_info section. - Optional<uint64_t> RefVal = AttrValue.Value.getAsReference(); - assert(RefVal); - if (RefVal) { - if(*RefVal >= DCtx.getInfoSection().Data.size()) { - Success = false; - OS << "error: DW_FORM_ref_addr offset beyond .debug_info " - "bounds:\n"; - Die.dump(OS, 0); - OS << "\n"; - } else { - // Valid reference, but we will verify it points to an actual - // DIE later. - ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset()); - } - } - break; - } - case DW_FORM_strp: { - auto SecOffset = AttrValue.Value.getAsSectionOffset(); - assert(SecOffset); // DW_FORM_strp is a section offset. - if (SecOffset && *SecOffset >= DCtx.getStringSection().size()) { - Success = false; - OS << "error: DW_FORM_strp offset beyond .debug_str bounds:\n"; - Die.dump(OS, 0); - OS << "\n"; - } - break; - } - default: - break; - } - } - } - } - - // Take all references and make sure they point to an actual DIE by - // getting the DIE by offset and emitting an error - OS << "Verifying .debug_info references...\n"; - for (auto Pair: ReferenceToDIEOffsets) { - auto Die = DCtx.getDIEForOffset(Pair.first); - if (Die) - continue; - Success = false; - OS << "error: invalid DIE reference " << format("0x%08" PRIx64, Pair.first) - << ". Offset is in between DIEs:\n"; - for (auto Offset: Pair.second) { - auto ReferencingDie = DCtx.getDIEForOffset(Offset); - ReferencingDie.dump(OS, 0); - OS << "\n"; - } - OS << "\n"; - } - return Success; - } - - bool HandleDebugLine() { - std::map<uint64_t, DWARFDie> StmtListToDie; - bool Success = true; - OS << "Verifying .debug_line...\n"; - for (const auto &CU : DCtx.compile_units()) { - uint32_t LineTableOffset = 0; - auto CUDie = CU->getUnitDIE(); - auto StmtFormValue = CUDie.find(DW_AT_stmt_list); - if (!StmtFormValue) { - // No line table for this compile unit. - continue; - } - // Get the attribute value as a section offset. No need to produce an - // error here if the encoding isn't correct because we validate this in - // the .debug_info verifier. - if (auto StmtSectionOffset = toSectionOffset(StmtFormValue)) { - LineTableOffset = *StmtSectionOffset; - if (LineTableOffset >= DCtx.getLineSection().Data.size()) { - // Make sure we don't get a valid line table back if the offset - // is wrong. - assert(DCtx.getLineTableForUnit(CU.get()) == nullptr); - // Skip this line table as it isn't valid. No need to create an error - // here because we validate this in the .debug_info verifier. - continue; - } else { - auto Iter = StmtListToDie.find(LineTableOffset); - if (Iter != StmtListToDie.end()) { - Success = false; - OS << "error: two compile unit DIEs, " - << format("0x%08" PRIx32, Iter->second.getOffset()) << " and " - << format("0x%08" PRIx32, CUDie.getOffset()) - << ", have the same DW_AT_stmt_list section offset:\n"; - Iter->second.dump(OS, 0); - CUDie.dump(OS, 0); - OS << '\n'; - // Already verified this line table before, no need to do it again. - continue; - } - StmtListToDie[LineTableOffset] = CUDie; - } - } - auto LineTable = DCtx.getLineTableForUnit(CU.get()); - if (!LineTable) { - Success = false; - OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset) - << "] was not able to be parsed for CU:\n"; - CUDie.dump(OS, 0); - OS << '\n'; - continue; - } - uint32_t MaxFileIndex = LineTable->Prologue.FileNames.size(); - uint64_t PrevAddress = 0; - uint32_t RowIndex = 0; - for (const auto &Row : LineTable->Rows) { - if (Row.Address < PrevAddress) { - Success = false; - OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset) - << "] row[" << RowIndex - << "] decreases in address from previous row:\n"; - - DWARFDebugLine::Row::dumpTableHeader(OS); - if (RowIndex > 0) - LineTable->Rows[RowIndex - 1].dump(OS); - Row.dump(OS); - OS << '\n'; - } - - if (Row.File > MaxFileIndex) { - Success = false; - OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset) - << "][" << RowIndex << "] has invalid file index " << Row.File - << " (valid values are [1," << MaxFileIndex << "]):\n"; - DWARFDebugLine::Row::dumpTableHeader(OS); - Row.dump(OS); - OS << '\n'; - } - if (Row.EndSequence) - PrevAddress = 0; - else - PrevAddress = Row.Address; - ++RowIndex; - } - } - return Success; - } -}; - -} // anonymous namespace - bool DWARFContext::verify(raw_ostream &OS, DIDumpType DumpType) { bool Success = true; DWARFVerifier verifier(OS, *this); @@ -678,8 +436,13 @@ bool DWARFContext::verify(raw_ostream &OS, DIDumpType DumpType) { if (!verifier.handleDebugLine()) Success = false; } + if (DumpType == DIDT_All || DumpType == DIDT_AppleNames) { + if (!verifier.handleAppleNames()) + Success = false; + } return Success; } + const DWARFUnitIndex &DWARFContext::getCUIndex() { if (CUIndex) return *CUIndex; @@ -1250,7 +1013,7 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj, continue; RelSecName = RelSecName.substr( - RelSecName.find_first_not_of("._")); // Skip . and _ prefixes. + RelSecName.find_first_not_of("._z")); // Skip . and _ prefixes. // TODO: Add support for relocations in other sections as needed. // Record relocations for the debug_info and debug_line sections. diff --git a/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp index e6e007896cc85..cf9fec2b3254c 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -514,6 +514,20 @@ static uint64_t readPointer(const DataExtractor &Data, uint32_t &Offset, } } +// This is a workaround for old compilers which do not allow +// noreturn attribute usage in lambdas. Once the support for those +// compilers are phased out, we can remove this and return back to +// a ReportError lambda: [StartOffset](const char *ErrorMsg). +#define ReportError(ErrorMsg) ReportErrorImpl(StartOffset,ErrorMsg) +static void LLVM_ATTRIBUTE_NORETURN +ReportErrorImpl(uint32_t StartOffset, const char *ErrorMsg) { + std::string Str; + raw_string_ostream OS(Str); + OS << format(ErrorMsg, StartOffset); + OS.flush(); + report_fatal_error(Str); +} + void DWARFDebugFrame::parse(DataExtractor Data) { uint32_t Offset = 0; DenseMap<uint32_t, CIE *> CIEs; @@ -521,14 +535,6 @@ void DWARFDebugFrame::parse(DataExtractor Data) { while (Data.isValidOffset(Offset)) { uint32_t StartOffset = Offset; - auto ReportError = [StartOffset](const char *ErrorMsg) { - std::string Str; - raw_string_ostream OS(Str); - OS << format(ErrorMsg, StartOffset); - OS.flush(); - report_fatal_error(Str); - }; - bool IsDWARF64 = false; uint64_t Length = Data.getU32(&Offset); uint64_t Id; @@ -585,7 +591,6 @@ void DWARFDebugFrame::parse(DataExtractor Data) { switch (AugmentationString[i]) { default: ReportError("Unknown augmentation character in entry at %lx"); - llvm_unreachable("ReportError should not return."); case 'L': LSDAPointerEncoding = Data.getU8(&Offset); break; diff --git a/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/lib/DebugInfo/DWARF/DWARFVerifier.cpp index 8a544296f65cb..a6240fb60143c 100644 --- a/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -14,6 +14,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h" +#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" #include "llvm/Support/raw_ostream.h" #include <map> #include <set> @@ -275,3 +276,36 @@ bool DWARFVerifier::handleDebugLine() { verifyDebugLineRows(); return NumDebugLineErrors == 0; } + +bool DWARFVerifier::handleAppleNames() { + NumAppleNamesErrors = 0; + OS << "Verifying .apple_names...\n"; + + DataExtractor AppleNamesSection(DCtx.getAppleNamesSection().Data, + DCtx.isLittleEndian(), 0); + DataExtractor StrData(DCtx.getStringSection(), DCtx.isLittleEndian(), 0); + DWARFAcceleratorTable AppleNames(AppleNamesSection, StrData, + DCtx.getAppleNamesSection().Relocs); + + if (!AppleNames.extract()) { + OS << "error: cannot extract .apple_names accelerator table\n"; + return false; + } + + // Verify that all buckets have a valid hash index or are empty + uint32_t NumBuckets = AppleNames.getNumBuckets(); + uint32_t NumHashes = AppleNames.getNumHashes(); + + uint32_t BucketsOffset = + AppleNames.getSizeHdr() + AppleNames.getHeaderDataLength(); + + for (uint32_t BucketIdx = 0; BucketIdx < NumBuckets; ++BucketIdx) { + uint32_t HashIdx = AppleNamesSection.getU32(&BucketsOffset); + if (HashIdx >= NumHashes && HashIdx != UINT32_MAX) { + OS << format("error: Bucket[%d] has invalid hash index: [%d]\n", + BucketIdx, HashIdx); + ++NumAppleNamesErrors; + } + } + return NumAppleNamesErrors == 0; +} diff --git a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp index 396dffaa68b1b..81a9d3eeec619 100644 --- a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp @@ -177,7 +177,7 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter, } void DbiModuleDescriptorBuilder::addDebugSubsection( - std::unique_ptr<DebugSubsection> Subsection) { + std::shared_ptr<DebugSubsection> Subsection) { assert(Subsection); C13Builders.push_back(llvm::make_unique<DebugSubsectionRecordBuilder>( std::move(Subsection), CodeViewContainer::Pdb)); diff --git a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp index 355c7b57f4d14..e7304b444f23f 100644 --- a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp @@ -45,10 +45,6 @@ void DbiStreamBuilder::setFlags(uint16_t F) { Flags = F; } void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; } -void DbiStreamBuilder::setSectionContribs(ArrayRef<SectionContrib> Arr) { - SectionContribs = Arr; -} - void DbiStreamBuilder::setSectionMap(ArrayRef<SecMapEntry> SecMap) { SectionMap = SecMap; } @@ -293,23 +289,17 @@ static uint16_t toSecMapFlags(uint32_t Flags) { return Ret; } -// A utility function to create Section Contributions -// for a given input sections. -std::vector<SectionContrib> DbiStreamBuilder::createSectionContribs( - ArrayRef<object::coff_section> SecHdrs) { - std::vector<SectionContrib> Ret; - - // Create a SectionContrib for each input section. - for (auto &Sec : SecHdrs) { - Ret.emplace_back(); - auto &Entry = Ret.back(); - memset(&Entry, 0, sizeof(Entry)); - - Entry.Off = Sec.PointerToRawData; - Entry.Size = Sec.SizeOfRawData; - Entry.Characteristics = Sec.Characteristics; - } - return Ret; +void DbiStreamBuilder::addSectionContrib(DbiModuleDescriptorBuilder *ModuleDbi, + const object::coff_section *SecHdr) { + SectionContrib SC; + memset(&SC, 0, sizeof(SC)); + SC.ISect = (uint16_t)~0U; // This represents nil. + SC.Off = SecHdr->PointerToRawData; + SC.Size = SecHdr->SizeOfRawData; + SC.Characteristics = SecHdr->Characteristics; + // Use the module index in the module dbi stream or nil (-1). + SC.Imod = ModuleDbi ? ModuleDbi->getModuleIndex() : (uint16_t)~0U; + SectionContribs.emplace_back(SC); } // A utility function to create a Section Map for a given list of COFF sections. @@ -372,7 +362,7 @@ Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout, if (!SectionContribs.empty()) { if (auto EC = Writer.writeEnum(DbiSecContribVer60)) return EC; - if (auto EC = Writer.writeArray(SectionContribs)) + if (auto EC = Writer.writeArray(makeArrayRef(SectionContribs))) return EC; } diff --git a/lib/DebugInfo/PDB/Native/InfoStream.cpp b/lib/DebugInfo/PDB/Native/InfoStream.cpp index 7c6069652da6a..a3979d480bf45 100644 --- a/lib/DebugInfo/PDB/Native/InfoStream.cpp +++ b/lib/DebugInfo/PDB/Native/InfoStream.cpp @@ -102,6 +102,10 @@ InfoStream::named_streams() const { return NamedStreams.entries(); } +bool InfoStream::containsIdStream() const { + return !!(Features & PdbFeatureContainsIdStream); +} + PdbRaw_ImplVer InfoStream::getVersion() const { return static_cast<PdbRaw_ImplVer>(Version); } diff --git a/lib/DebugInfo/PDB/Native/PDBFile.cpp b/lib/DebugInfo/PDB/Native/PDBFile.cpp index 1254e23c73ebf..a9597cdf4c4d3 100644 --- a/lib/DebugInfo/PDB/Native/PDBFile.cpp +++ b/lib/DebugInfo/PDB/Native/PDBFile.cpp @@ -363,6 +363,16 @@ Expected<PDBStringTable &> PDBFile::getStringTable() { return *Strings; } +uint32_t PDBFile::getPointerSize() { + auto DbiS = getPDBDbiStream(); + if (!DbiS) + return 0; + PDB_Machine Machine = DbiS->getMachineType(); + if (Machine == PDB_Machine::Amd64) + return 8; + return 4; +} + bool PDBFile::hasPDBDbiStream() const { return StreamDBI < getNumStreams(); } bool PDBFile::hasPDBGlobalsStream() { diff --git a/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp index 2c6465e6fb2a8..12b0c3b36c1dd 100644 --- a/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp @@ -80,6 +80,16 @@ Error PDBFileBuilder::addNamedStream(StringRef Name, uint32_t Size) { } Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() { + + if (Ipi && Ipi->getRecordCount() > 0) { + // In theory newer PDBs always have an ID stream, but by saying that we're + // only going to *really* have an ID stream if there is at least one ID + // record, we leave open the opportunity to test older PDBs such as those + // that don't have an ID stream. + auto &Info = getInfoBuilder(); + Info.addFeature(PdbRaw_FeatureSig::VC140); + } + uint32_t StringsLen = Strings.calculateSerializedSize(); if (auto EC = addNamedStream("/names", StringsLen)) diff --git a/lib/DebugInfo/PDB/Native/PDBStringTable.cpp b/lib/DebugInfo/PDB/Native/PDBStringTable.cpp index 6013c342cf025..f9f8ac219d357 100644 --- a/lib/DebugInfo/PDB/Native/PDBStringTable.cpp +++ b/lib/DebugInfo/PDB/Native/PDBStringTable.cpp @@ -56,7 +56,8 @@ Error PDBStringTable::readStrings(BinaryStreamReader &Reader) { return Error::success(); } -codeview::DebugStringTableSubsectionRef PDBStringTable::getStringTable() const { +const codeview::DebugStringTableSubsectionRef & +PDBStringTable::getStringTable() const { return Strings; } diff --git a/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp b/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp index a472181a4895c..90acfadd311ff 100644 --- a/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp @@ -52,6 +52,11 @@ uint32_t PDBStringTableBuilder::calculateSerializedSize() const { return Size; } +void PDBStringTableBuilder::setStrings( + const codeview::DebugStringTableSubsection &Strings) { + this->Strings = Strings; +} + Error PDBStringTableBuilder::writeHeader(BinaryStreamWriter &Writer) const { // Write a header PDBStringTableHeader H; diff --git a/lib/DebugInfo/PDB/Native/PublicsStream.cpp b/lib/DebugInfo/PDB/Native/PublicsStream.cpp index 091ac67035dc6..8f3474b9ce190 100644 --- a/lib/DebugInfo/PDB/Native/PublicsStream.cpp +++ b/lib/DebugInfo/PDB/Native/PublicsStream.cpp @@ -130,4 +130,13 @@ PublicsStream::getSymbols(bool *HadError) const { return SS.getSymbols(HadError); } +Expected<const codeview::CVSymbolArray &> +PublicsStream::getSymbolArray() const { + auto SymbolS = Pdb.getPDBSymbolStream(); + if (!SymbolS) + return SymbolS.takeError(); + + return SymbolS->getSymbolArray(); +} + Error PublicsStream::commit() { return Error::success(); } diff --git a/lib/DebugInfo/PDB/Native/TpiHashing.cpp b/lib/DebugInfo/PDB/Native/TpiHashing.cpp index 16904a5a27ed3..91b8d648fcf9d 100644 --- a/lib/DebugInfo/PDB/Native/TpiHashing.cpp +++ b/lib/DebugInfo/PDB/Native/TpiHashing.cpp @@ -9,6 +9,7 @@ #include "llvm/DebugInfo/PDB/Native/TpiHashing.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/PDB/Native/Hash.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" diff --git a/lib/DebugInfo/PDB/UDTLayout.cpp b/lib/DebugInfo/PDB/UDTLayout.cpp index aacefae80c3a2..da353cb6977ce 100644 --- a/lib/DebugInfo/PDB/UDTLayout.cpp +++ b/lib/DebugInfo/PDB/UDTLayout.cpp @@ -181,13 +181,14 @@ void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) { if (Data->getDataKind() == PDB_DataKind::Member) Members.push_back(std::move(Data)); else - Other.push_back(std::move(Child)); + Other.push_back(std::move(Data)); } else if (auto VT = unique_dyn_cast<PDBSymbolTypeVTable>(Child)) VTables.push_back(std::move(VT)); else if (auto Func = unique_dyn_cast<PDBSymbolFunc>(Child)) Funcs.push_back(std::move(Func)); - else + else { Other.push_back(std::move(Child)); + } } // We don't want to have any re-allocations in the list of bases, so make |