diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:32:52 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:32:52 +0000 | 
| commit | 08bbd35a80bf7765fe0d3043f9eb5a2f2786b649 (patch) | |
| tree | 80108f0f128657f8623f8f66ad9735b4d88e7b47 /lib/DebugInfo | |
| parent | 7c7aba6e5fef47a01a136be655b0a92cfd7090f6 (diff) | |
Notes
Diffstat (limited to 'lib/DebugInfo')
38 files changed, 810 insertions, 853 deletions
| diff --git a/lib/DebugInfo/CodeView/CMakeLists.txt b/lib/DebugInfo/CodeView/CMakeLists.txt index f916695a84392..b94bb0c80c793 100644 --- a/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/lib/DebugInfo/CodeView/CMakeLists.txt @@ -24,11 +24,10 @@ add_llvm_library(LLVMDebugInfoCodeView    SymbolRecordMapping.cpp    SymbolDumper.cpp    SymbolSerializer.cpp -  TypeDatabase.cpp -  TypeDatabaseVisitor.cpp    TypeDumpVisitor.cpp    TypeIndex.cpp    TypeIndexDiscovery.cpp +  TypeName.cpp    TypeRecordMapping.cpp    TypeSerializer.cpp    TypeStreamMerger.cpp diff --git a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/lib/DebugInfo/CodeView/CVTypeVisitor.cpp index f0debd9e97023..22f166a2335d6 100644 --- a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp +++ b/lib/DebugInfo/CodeView/CVTypeVisitor.cpp @@ -12,8 +12,6 @@  #include "llvm/ADT/TinyPtrVector.h"  #include "llvm/DebugInfo/CodeView/CodeViewError.h"  #include "llvm/DebugInfo/CodeView/TypeCollection.h" -#include "llvm/DebugInfo/CodeView/TypeDatabase.h" -#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"  #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"  #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"  #include "llvm/DebugInfo/CodeView/TypeServerHandler.h" diff --git a/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp b/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp index 334c5e002bbca..d69eca018e0c1 100644 --- a/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp +++ b/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp @@ -53,12 +53,16 @@ DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(      std::shared_ptr<DebugSubsection> Subsection, CodeViewContainer Container)      : Subsection(std::move(Subsection)), Container(Container) {} +DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder( +    const DebugSubsectionRecord &Contents, CodeViewContainer Container) +    : Contents(Contents), Container(Container) {} +  uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() { -  // The length of the entire subsection is always padded to 4 bytes, regardless -  // of the container kind. -  uint32_t Size = sizeof(DebugSubsectionHeader) + -                  alignTo(Subsection->calculateSerializedSize(), 4); -  return Size; +  uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize() +                                 : Contents.getRecordData().getLength(); +  // The length of the entire subsection is always padded to 4 bytes, +  // regardless of the container kind. +  return sizeof(DebugSubsectionHeader) + alignTo(DataSize, 4);  }  Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const { @@ -66,16 +70,22 @@ Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const {           "Debug Subsection not properly aligned");    DebugSubsectionHeader Header; -  Header.Kind = uint32_t(Subsection->kind()); +  Header.Kind = uint32_t(Subsection ? Subsection->kind() : Contents.kind());    // The value written into the Header's Length field is only padded to the    // container's alignment -  Header.Length = -      alignTo(Subsection->calculateSerializedSize(), alignOf(Container)); +  uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize() +                                 : Contents.getRecordData().getLength(); +  Header.Length = alignTo(DataSize, alignOf(Container));    if (auto EC = Writer.writeObject(Header))      return EC; -  if (auto EC = Subsection->commit(Writer)) -    return EC; +  if (Subsection) { +    if (auto EC = Subsection->commit(Writer)) +      return EC; +  } else { +    if (auto EC = Writer.writeStreamRef(Contents.getRecordData())) +      return EC; +  }    if (auto EC = Writer.padToAlignment(4))      return EC; diff --git a/lib/DebugInfo/CodeView/EnumTables.cpp b/lib/DebugInfo/CodeView/EnumTables.cpp index 01d8ccf2d31e8..ec00af28395e5 100644 --- a/lib/DebugInfo/CodeView/EnumTables.cpp +++ b/lib/DebugInfo/CodeView/EnumTables.cpp @@ -82,6 +82,13 @@ static const EnumEntry<uint16_t> RegisterNames[] = {      CV_ENUM_CLASS_ENT(RegisterId, R15),  }; +static const EnumEntry<uint32_t> PublicSymFlagNames[] = { +    CV_ENUM_CLASS_ENT(PublicSymFlags, Code), +    CV_ENUM_CLASS_ENT(PublicSymFlags, Function), +    CV_ENUM_CLASS_ENT(PublicSymFlags, Managed), +    CV_ENUM_CLASS_ENT(PublicSymFlags, MSIL), +}; +  static const EnumEntry<uint8_t> ProcSymFlagNames[] = {      CV_ENUM_CLASS_ENT(ProcSymFlags, HasFP),      CV_ENUM_CLASS_ENT(ProcSymFlags, HasIRET), @@ -338,6 +345,9 @@ ArrayRef<EnumEntry<uint16_t>> getRegisterNames() {    return makeArrayRef(RegisterNames);  } +ArrayRef<EnumEntry<uint32_t>> getPublicSymFlagNames() { +  return makeArrayRef(PublicSymFlagNames); +}  ArrayRef<EnumEntry<uint8_t>> getProcSymFlagNames() {    return makeArrayRef(ProcSymFlagNames);  } diff --git a/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp b/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp index 39eb4099ce9e6..20f7e72c3af39 100644 --- a/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp +++ b/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp @@ -11,7 +11,7 @@  #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"  #include "llvm/DebugInfo/CodeView/CodeViewError.h" -#include "llvm/DebugInfo/CodeView/TypeDatabase.h" +#include "llvm/DebugInfo/CodeView/TypeName.h"  #include "llvm/DebugInfo/CodeView/TypeServerHandler.h"  #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" @@ -31,15 +31,13 @@ LazyRandomTypeCollection::LazyRandomTypeCollection(uint32_t RecordCountHint)  LazyRandomTypeCollection::LazyRandomTypeCollection(      const CVTypeArray &Types, uint32_t RecordCountHint,      PartialOffsetArray PartialOffsets) -    : Database(RecordCountHint), Types(Types), DatabaseVisitor(Database), -      PartialOffsets(PartialOffsets) { -  KnownOffsets.resize(Database.capacity()); +    : NameStorage(Allocator), Types(Types), PartialOffsets(PartialOffsets) { +  Records.resize(RecordCountHint);  }  LazyRandomTypeCollection::LazyRandomTypeCollection(ArrayRef<uint8_t> Data,                                                     uint32_t RecordCountHint)      : LazyRandomTypeCollection(RecordCountHint) { -  reset(Data);  }  LazyRandomTypeCollection::LazyRandomTypeCollection(StringRef Data, @@ -52,50 +50,88 @@ LazyRandomTypeCollection::LazyRandomTypeCollection(const CVTypeArray &Types,                                                     uint32_t NumRecords)      : LazyRandomTypeCollection(Types, NumRecords, PartialOffsetArray()) {} -void LazyRandomTypeCollection::reset(StringRef Data) { -  reset(makeArrayRef(Data.bytes_begin(), Data.bytes_end())); -} - -void LazyRandomTypeCollection::reset(ArrayRef<uint8_t> Data) { +void LazyRandomTypeCollection::reset(StringRef Data, uint32_t RecordCountHint) { +  Count = 0;    PartialOffsets = PartialOffsetArray();    BinaryStreamReader Reader(Data, support::little);    error(Reader.readArray(Types, Reader.getLength())); -  KnownOffsets.resize(Database.capacity()); +  // Clear and then resize, to make sure existing data gets destroyed. +  Records.clear(); +  Records.resize(RecordCountHint); +} + +void LazyRandomTypeCollection::reset(ArrayRef<uint8_t> Data, +                                     uint32_t RecordCountHint) { +  reset(toStringRef(Data), RecordCountHint); +} + +uint32_t LazyRandomTypeCollection::getOffsetOfType(TypeIndex Index) { +  error(ensureTypeExists(Index)); +  assert(contains(Index)); + +  return Records[Index.toArrayIndex()].Offset;  }  CVType LazyRandomTypeCollection::getType(TypeIndex Index) {    error(ensureTypeExists(Index)); -  return Database.getTypeRecord(Index); +  assert(contains(Index)); + +  return Records[Index.toArrayIndex()].Type;  }  StringRef LazyRandomTypeCollection::getTypeName(TypeIndex Index) { -  if (!Index.isSimple()) { -    // Try to make sure the type exists.  Even if it doesn't though, it may be -    // because we're dumping a symbol stream with no corresponding type stream -    // present, in which case we still want to be able to print <unknown UDT> -    // for the type names. -    consumeError(ensureTypeExists(Index)); +  if (Index.isNoneType() || Index.isSimple()) +    return TypeIndex::simpleTypeName(Index); + +  // Try to make sure the type exists.  Even if it doesn't though, it may be +  // because we're dumping a symbol stream with no corresponding type stream +  // present, in which case we still want to be able to print <unknown UDT> +  // for the type names. +  if (auto EC = ensureTypeExists(Index)) { +    consumeError(std::move(EC)); +    return "<unknown UDT>";    } -  return Database.getTypeName(Index); +  uint32_t I = Index.toArrayIndex(); +  ensureCapacityFor(Index); +  if (Records[I].Name.data() == nullptr) { +    StringRef Result = NameStorage.save(computeTypeName(*this, Index)); +    Records[I].Name = Result; +  } +  return Records[I].Name;  }  bool LazyRandomTypeCollection::contains(TypeIndex Index) { -  return Database.contains(Index); +  if (Records.size() <= Index.toArrayIndex()) +    return false; +  if (!Records[Index.toArrayIndex()].Type.valid()) +    return false; +  return true;  } -uint32_t LazyRandomTypeCollection::size() { return Database.size(); } +uint32_t LazyRandomTypeCollection::size() { return Count; } -uint32_t LazyRandomTypeCollection::capacity() { return Database.capacity(); } +uint32_t LazyRandomTypeCollection::capacity() { return Records.size(); }  Error LazyRandomTypeCollection::ensureTypeExists(TypeIndex TI) { -  if (!Database.contains(TI)) { -    if (auto EC = visitRangeForType(TI)) -      return EC; -  } -  return Error::success(); +  if (contains(TI)) +    return Error::success(); + +  return visitRangeForType(TI); +} + +void LazyRandomTypeCollection::ensureCapacityFor(TypeIndex Index) { +  uint32_t MinSize = Index.toArrayIndex() + 1; + +  if (MinSize <= capacity()) +    return; + +  uint32_t NewCapacity = MinSize * 3 / 2; + +  assert(NewCapacity > capacity()); +  Records.resize(NewCapacity);  }  Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) { @@ -111,7 +147,7 @@ Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) {    auto Prev = std::prev(Next);    TypeIndex TIB = Prev->Type; -  if (Database.contains(TIB)) { +  if (contains(TIB)) {      // They've asked us to fetch a type index, but the entry we found in the      // partial offsets array has already been visited.  Since we visit an entire      // block every time, that means this record should have been previously @@ -122,13 +158,12 @@ Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) {    TypeIndex TIE;    if (Next == PartialOffsets.end()) { -    TIE = TypeIndex::fromArrayIndex(Database.capacity()); +    TIE = TypeIndex::fromArrayIndex(capacity());    } else {      TIE = Next->Type;    } -  if (auto EC = visitRange(TIB, Prev->Offset, TIE)) -    return EC; +  visitRange(TIB, Prev->Offset, TIE);    return Error::success();  } @@ -157,34 +192,31 @@ Error LazyRandomTypeCollection::fullScanForType(TypeIndex TI) {    assert(PartialOffsets.empty());    TypeIndex CurrentTI = TypeIndex::fromArrayIndex(0); -  uint32_t Offset = 0;    auto Begin = Types.begin(); -  if (!Database.empty()) { +  if (Count > 0) {      // In the case of type streams which we don't know the number of records of,      // it's possible to search for a type index triggering a full scan, but then      // later additional records are added since we didn't know how many there      // would be until we did a full visitation, then you try to access the new      // type triggering another full scan.  To avoid this, we assume that if the -    // database has some records, this must be what's going on.  So we ask the -    // database for the largest type index less than the one we're searching for -    // and only do the forward scan from there. -    auto Prev = Database.largestTypeIndexLessThan(TI); -    assert(Prev.hasValue() && "Empty database with valid types?"); -    Offset = KnownOffsets[Prev->toArrayIndex()]; -    CurrentTI = *Prev; -    ++CurrentTI; +    // database has some records, this must be what's going on.  We can also +    // assume that this index must be larger than the largest type index we've +    // visited, so we start from there and scan forward. +    uint32_t Offset = Records[LargestTypeIndex.toArrayIndex()].Offset; +    CurrentTI = LargestTypeIndex + 1;      Begin = Types.at(Offset);      ++Begin; -    Offset = Begin.offset();    }    auto End = Types.end();    while (Begin != End) { -    if (auto EC = visitOneRecord(CurrentTI, Offset, *Begin)) -      return EC; - -    Offset += Begin.getRecordLength(); +    ensureCapacityFor(CurrentTI); +    LargestTypeIndex = std::max(LargestTypeIndex, CurrentTI); +    auto Idx = CurrentTI.toArrayIndex(); +    Records[Idx].Type = *Begin; +    Records[Idx].Offset = Begin.offset(); +    ++Count;      ++Begin;      ++CurrentTI;    } @@ -194,36 +226,19 @@ Error LazyRandomTypeCollection::fullScanForType(TypeIndex TI) {    return Error::success();  } -Error LazyRandomTypeCollection::visitRange(TypeIndex Begin, -                                           uint32_t BeginOffset, -                                           TypeIndex End) { - +void LazyRandomTypeCollection::visitRange(TypeIndex Begin, uint32_t BeginOffset, +                                          TypeIndex End) {    auto RI = Types.at(BeginOffset);    assert(RI != Types.end()); +  ensureCapacityFor(End);    while (Begin != End) { -    if (auto EC = visitOneRecord(Begin, BeginOffset, *RI)) -      return EC; - -    BeginOffset += RI.getRecordLength(); +    LargestTypeIndex = std::max(LargestTypeIndex, Begin); +    auto Idx = Begin.toArrayIndex(); +    Records[Idx].Type = *RI; +    Records[Idx].Offset = RI.offset(); +    ++Count;      ++Begin;      ++RI;    } - -  return Error::success(); -} - -Error LazyRandomTypeCollection::visitOneRecord(TypeIndex TI, uint32_t Offset, -                                               CVType &Record) { -  assert(!Database.contains(TI)); -  if (auto EC = codeview::visitTypeRecord(Record, TI, DatabaseVisitor)) -    return EC; -  // Keep the KnownOffsets array the same size as the Database's capacity. Since -  // we don't always know how many records are in the type stream, we need to be -  // prepared for the database growing and receicing a type index that can't fit -  // in our current buffer. -  if (KnownOffsets.size() < Database.capacity()) -    KnownOffsets.resize(Database.capacity()); -  KnownOffsets[TI.toArrayIndex()] = Offset; -  return Error::success();  } diff --git a/lib/DebugInfo/CodeView/SymbolDumper.cpp b/lib/DebugInfo/CodeView/SymbolDumper.cpp index 36abafc079edb..b9fa9b6a6ad7e 100644 --- a/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ b/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -524,7 +524,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,  Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, PublicSym32 &Public) {    DictScope S(W, "PublicSym"); -  printTypeIndex("Type", Public.Index); +  W.printFlags("Flags", uint32_t(Public.Flags), getPublicSymFlagNames());    W.printNumber("Seg", Public.Segment);    W.printNumber("Off", Public.Offset);    W.printString("Name", Public.Name); diff --git a/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp b/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp index d731dc1b0a372..923837a45d9fc 100644 --- a/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp +++ b/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp @@ -361,7 +361,7 @@ Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,  Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,                                              PublicSym32 &Public) { -  error(IO.mapInteger(Public.Index)); +  error(IO.mapEnum(Public.Flags));    error(IO.mapInteger(Public.Offset));    error(IO.mapInteger(Public.Segment));    error(IO.mapStringZ(Public.Name)); diff --git a/lib/DebugInfo/CodeView/TypeDatabase.cpp b/lib/DebugInfo/CodeView/TypeDatabase.cpp deleted file mode 100644 index 08f848b36a9d5..0000000000000 --- a/lib/DebugInfo/CodeView/TypeDatabase.cpp +++ /dev/null @@ -1,146 +0,0 @@ -//===- TypeDatabase.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/TypeDatabase.h" - -using namespace llvm; -using namespace llvm::codeview; - -TypeDatabase::TypeDatabase(uint32_t Capacity) : TypeNameStorage(Allocator) { -  CVUDTNames.resize(Capacity); -  TypeRecords.resize(Capacity); -  ValidRecords.resize(Capacity); -} - -TypeIndex TypeDatabase::appendType(StringRef Name, const CVType &Data) { -  LargestTypeIndex = getAppendIndex(); -  if (LargestTypeIndex.toArrayIndex() >= capacity()) -    grow(); -  recordType(Name, LargestTypeIndex, Data); -  return LargestTypeIndex; -} - -void TypeDatabase::recordType(StringRef Name, TypeIndex Index, -                              const CVType &Data) { -  LargestTypeIndex = empty() ? Index : std::max(Index, LargestTypeIndex); - -  if (LargestTypeIndex.toArrayIndex() >= capacity()) -    grow(Index); - -  uint32_t AI = Index.toArrayIndex(); - -  assert(!contains(Index)); -  assert(AI < capacity()); - -  CVUDTNames[AI] = Name; -  TypeRecords[AI] = Data; -  ValidRecords.set(AI); -  ++Count; -} - -/// Saves the name in a StringSet and creates a stable StringRef. -StringRef TypeDatabase::saveTypeName(StringRef TypeName) { -  return TypeNameStorage.save(TypeName); -} - -StringRef TypeDatabase::getTypeName(TypeIndex Index) const { -  if (Index.isNoneType() || Index.isSimple()) -    return TypeIndex::simpleTypeName(Index); - -  if (contains(Index)) -    return CVUDTNames[Index.toArrayIndex()]; - -  return "<unknown UDT>"; -} - -const CVType &TypeDatabase::getTypeRecord(TypeIndex Index) const { -  assert(contains(Index)); -  return TypeRecords[Index.toArrayIndex()]; -} - -CVType &TypeDatabase::getTypeRecord(TypeIndex Index) { -  assert(contains(Index)); -  return TypeRecords[Index.toArrayIndex()]; -} - -bool TypeDatabase::contains(TypeIndex Index) const { -  uint32_t AI = Index.toArrayIndex(); -  if (AI >= capacity()) -    return false; - -  return ValidRecords.test(AI); -} - -uint32_t TypeDatabase::size() const { return Count; } - -uint32_t TypeDatabase::capacity() const { return TypeRecords.size(); } - -CVType TypeDatabase::getType(TypeIndex Index) { return getTypeRecord(Index); } - -StringRef TypeDatabase::getTypeName(TypeIndex Index) { -  return static_cast<const TypeDatabase *>(this)->getTypeName(Index); -} - -bool TypeDatabase::contains(TypeIndex Index) { -  return static_cast<const TypeDatabase *>(this)->contains(Index); -} - -uint32_t TypeDatabase::size() { -  return static_cast<const TypeDatabase *>(this)->size(); -} - -uint32_t TypeDatabase::capacity() { -  return static_cast<const TypeDatabase *>(this)->capacity(); -} - -void TypeDatabase::grow() { grow(LargestTypeIndex + 1); } - -void TypeDatabase::grow(TypeIndex NewIndex) { -  uint32_t NewSize = NewIndex.toArrayIndex() + 1; - -  if (NewSize <= capacity()) -    return; - -  uint32_t NewCapacity = NewSize * 3 / 2; - -  TypeRecords.resize(NewCapacity); -  CVUDTNames.resize(NewCapacity); -  ValidRecords.resize(NewCapacity); -} - -bool TypeDatabase::empty() const { return size() == 0; } - -Optional<TypeIndex> TypeDatabase::largestTypeIndexLessThan(TypeIndex TI) const { -  uint32_t AI = TI.toArrayIndex(); -  int N = ValidRecords.find_prev(AI); -  if (N == -1) -    return None; -  return TypeIndex::fromArrayIndex(N); -} - -TypeIndex TypeDatabase::getAppendIndex() const { -  if (empty()) -    return TypeIndex::fromArrayIndex(0); - -  return LargestTypeIndex + 1; -} - -Optional<TypeIndex> TypeDatabase::getFirst() { -  int N = ValidRecords.find_first(); -  if (N == -1) -    return None; -  return TypeIndex::fromArrayIndex(N); -} - -Optional<TypeIndex> TypeDatabase::getNext(TypeIndex Prev) { -  int N = ValidRecords.find_next(Prev.toArrayIndex()); -  if (N == -1) -    return None; -  return TypeIndex::fromArrayIndex(N); -} diff --git a/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp b/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp deleted file mode 100644 index 8d97f8b1cb401..0000000000000 --- a/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp +++ /dev/null @@ -1,330 +0,0 @@ -//===- TypeDatabaseVisitor.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/TypeDatabaseVisitor.h" - -#include "llvm/ADT/SmallString.h" - -using namespace llvm; - -using namespace llvm::codeview; - -Error TypeDatabaseVisitor::visitTypeBegin(CVType &Record) { -  assert(!IsInFieldList); -  // Reset Name to the empty string. If the visitor sets it, we know it. -  Name = ""; - -  if (Record.Type == LF_FIELDLIST) { -    // Record that we're in a field list so that members do not get assigned -    // type indices. -    IsInFieldList = true; -  } -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) { -  if (auto EC = visitTypeBegin(Record)) -    return EC; - -  CurrentTypeIndex = Index; -  return Error::success(); -} - -StringRef TypeDatabaseVisitor::getTypeName(TypeIndex Index) const { -  return TypeDB->getTypeName(Index); -} - -StringRef TypeDatabaseVisitor::saveTypeName(StringRef Name) { -  return TypeDB->saveTypeName(Name); -} - -Error TypeDatabaseVisitor::visitTypeEnd(CVType &CVR) { -  if (CVR.Type == LF_FIELDLIST) { -    assert(IsInFieldList); -    IsInFieldList = false; -  } -  assert(!IsInFieldList); - -  // Record every type that is not a field list member, even if Name is empty. -  // CVUDTNames is indexed by type index, and must have one entry for every -  // type.  Field list members are not recorded, and are only referenced by -  // their containing field list record. -  if (CurrentTypeIndex) -    TypeDB->recordType(Name, *CurrentTypeIndex, CVR); -  else -    TypeDB->appendType(Name, CVR); - -  CurrentTypeIndex.reset(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitMemberBegin(CVMemberRecord &Record) { -  assert(IsInFieldList); -  // Reset Name to the empty string. If the visitor sets it, we know it. -  Name = ""; -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitMemberEnd(CVMemberRecord &Record) { -  assert(IsInFieldList); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, -                                            FieldListRecord &FieldList) { -  Name = "<field list>"; -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVRecord<TypeLeafKind> &CVR, -                                            StringIdRecord &String) { -  // Put this in the database so it gets printed with LF_UDT_SRC_LINE. -  Name = String.getString(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ArgListRecord &Args) { -  auto Indices = Args.getIndices(); -  uint32_t Size = Indices.size(); -  SmallString<256> TypeName("("); -  for (uint32_t I = 0; I < Size; ++I) { -    StringRef ArgTypeName = getTypeName(Indices[I]); -    TypeName.append(ArgTypeName); -    if (I + 1 != Size) -      TypeName.append(", "); -  } -  TypeName.push_back(')'); -  Name = saveTypeName(TypeName); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, -                                            StringListRecord &Strings) { -  auto Indices = Strings.getIndices(); -  uint32_t Size = Indices.size(); -  SmallString<256> TypeName("\""); -  for (uint32_t I = 0; I < Size; ++I) { -    StringRef ArgTypeName = getTypeName(Indices[I]); -    TypeName.append(ArgTypeName); -    if (I + 1 != Size) -      TypeName.append("\" \""); -  } -  TypeName.push_back('\"'); -  Name = saveTypeName(TypeName); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ClassRecord &Class) { -  Name = Class.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, UnionRecord &Union) { -  Name = Union.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) { -  Name = Enum.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ArrayRecord &AT) { -  Name = AT.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) { -  Name = VFT.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, -                                            MemberFuncIdRecord &Id) { -  Name = Id.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, -                                            ProcedureRecord &Proc) { -  StringRef ReturnTypeName = getTypeName(Proc.getReturnType()); -  StringRef ArgListTypeName = getTypeName(Proc.getArgumentList()); -  SmallString<256> TypeName(ReturnTypeName); -  TypeName.push_back(' '); -  TypeName.append(ArgListTypeName); -  Name = saveTypeName(TypeName); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, -                                            MemberFunctionRecord &MF) { -  StringRef ReturnTypeName = getTypeName(MF.getReturnType()); -  StringRef ClassTypeName = getTypeName(MF.getClassType()); -  StringRef ArgListTypeName = getTypeName(MF.getArgumentList()); -  SmallString<256> TypeName(ReturnTypeName); -  TypeName.push_back(' '); -  TypeName.append(ClassTypeName); -  TypeName.append("::"); -  TypeName.append(ArgListTypeName); -  Name = saveTypeName(TypeName); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) { -  Name = Func.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, -                                            TypeServer2Record &TS) { -  Name = TS.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) { - -  if (Ptr.isPointerToMember()) { -    const MemberPointerInfo &MI = Ptr.getMemberInfo(); - -    StringRef PointeeName = getTypeName(Ptr.getReferentType()); -    StringRef ClassName = getTypeName(MI.getContainingType()); -    SmallString<256> TypeName(PointeeName); -    TypeName.push_back(' '); -    TypeName.append(ClassName); -    TypeName.append("::*"); -    Name = saveTypeName(TypeName); -  } else { -    SmallString<256> TypeName; -    if (Ptr.isConst()) -      TypeName.append("const "); -    if (Ptr.isVolatile()) -      TypeName.append("volatile "); -    if (Ptr.isUnaligned()) -      TypeName.append("__unaligned "); - -    TypeName.append(getTypeName(Ptr.getReferentType())); - -    if (Ptr.getMode() == PointerMode::LValueReference) -      TypeName.append("&"); -    else if (Ptr.getMode() == PointerMode::RValueReference) -      TypeName.append("&&"); -    else if (Ptr.getMode() == PointerMode::Pointer) -      TypeName.append("*"); - -    if (!TypeName.empty()) -      Name = saveTypeName(TypeName); -  } -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) { -  uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers()); - -  StringRef ModifiedName = getTypeName(Mod.getModifiedType()); -  SmallString<256> TypeName; -  if (Mods & uint16_t(ModifierOptions::Const)) -    TypeName.append("const "); -  if (Mods & uint16_t(ModifierOptions::Volatile)) -    TypeName.append("volatile "); -  if (Mods & uint16_t(ModifierOptions::Unaligned)) -    TypeName.append("__unaligned "); -  TypeName.append(ModifiedName); -  Name = saveTypeName(TypeName); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, -                                            VFTableShapeRecord &Shape) { -  Name = -      saveTypeName("<vftable " + utostr(Shape.getEntryCount()) + " methods>"); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            NestedTypeRecord &Nested) { -  Name = Nested.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            OneMethodRecord &Method) { -  Name = Method.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            OverloadedMethodRecord &Method) { -  Name = Method.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            DataMemberRecord &Field) { -  Name = Field.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            StaticDataMemberRecord &Field) { -  Name = Field.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            EnumeratorRecord &Enum) { -  Name = Enum.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            BaseClassRecord &Base) { -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            VirtualBaseClassRecord &VBase) { -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            ListContinuationRecord &Cont) { -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord( -    CVType &CVR, UdtModSourceLineRecord &ModSourceLine) { -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, -                                            UdtSourceLineRecord &SourceLine) { -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) { -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord( -    CVType &CVR, MethodOverloadListRecord &Overloads) { -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) { -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, LabelRecord &R) { -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            VFPtrRecord &VFP) { -  return Error::success(); -} diff --git a/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp b/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp index 04b0384d81902..5899667050151 100644 --- a/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp +++ b/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp @@ -13,8 +13,6 @@  #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"  #include "llvm/DebugInfo/CodeView/Formatters.h"  #include "llvm/DebugInfo/CodeView/TypeCollection.h" -#include "llvm/DebugInfo/CodeView/TypeDatabase.h" -#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"  #include "llvm/DebugInfo/CodeView/TypeIndex.h"  #include "llvm/DebugInfo/CodeView/TypeRecord.h"  #include "llvm/Support/BinaryByteStream.h" diff --git a/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp b/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp index 8704cea607867..1226d5be3f3c4 100644 --- a/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp +++ b/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp @@ -357,6 +357,82 @@ static void discoverTypeIndices(ArrayRef<uint8_t> Content, TypeLeafKind Kind,    }  } +static bool discoverTypeIndices(ArrayRef<uint8_t> Content, SymbolKind Kind, +                                SmallVectorImpl<TiReference> &Refs) { +  uint32_t Count; +  // FIXME: In the future it would be nice if we could avoid hardcoding these +  // values.  One idea is to define some structures representing these types +  // that would allow the use of offsetof(). +  switch (Kind) { +  case SymbolKind::S_GPROC32: +  case SymbolKind::S_LPROC32: +  case SymbolKind::S_GPROC32_ID: +  case SymbolKind::S_LPROC32_ID: +  case SymbolKind::S_LPROC32_DPC: +  case SymbolKind::S_LPROC32_DPC_ID: +    Refs.push_back({TiRefKind::IndexRef, 24, 1}); // LF_FUNC_ID +    break; +  case SymbolKind::S_UDT: +    Refs.push_back({TiRefKind::TypeRef, 0, 1}); // UDT +    break; +  case SymbolKind::S_GDATA32: +  case SymbolKind::S_LDATA32: +    Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type +    break; +  case SymbolKind::S_BUILDINFO: +    Refs.push_back({TiRefKind::IndexRef, 0, 1}); // Compile flags +    break; +  case SymbolKind::S_LOCAL: +    Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type +    break; +  case SymbolKind::S_CONSTANT: +    Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type +    break; +  case SymbolKind::S_REGREL32: +    Refs.push_back({TiRefKind::TypeRef, 4, 1}); // Type +    break; +  case SymbolKind::S_CALLSITEINFO: +    Refs.push_back({TiRefKind::TypeRef, 8, 1}); // Call signature +    break; +  case SymbolKind::S_CALLERS: +  case SymbolKind::S_CALLEES: +    // The record is a count followed by an array of type indices. +    Count = *reinterpret_cast<const ulittle32_t *>(Content.data()); +    Refs.push_back({TiRefKind::IndexRef, 4, Count}); // Callees +    break; +  case SymbolKind::S_INLINESITE: +    Refs.push_back({TiRefKind::IndexRef, 8, 1}); // ID of inlinee +    break; + +  // Defranges don't have types, just registers and code offsets. +  case SymbolKind::S_DEFRANGE_REGISTER: +  case SymbolKind::S_DEFRANGE_REGISTER_REL: +  case SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL: +  case SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE: +  case SymbolKind::S_DEFRANGE_SUBFIELD_REGISTER: +  case SymbolKind::S_DEFRANGE_SUBFIELD: +    break; + +  // No type refernces. +  case SymbolKind::S_LABEL32: +  case SymbolKind::S_OBJNAME: +  case SymbolKind::S_COMPILE: +  case SymbolKind::S_COMPILE2: +  case SymbolKind::S_COMPILE3: +  case SymbolKind::S_BLOCK32: +  case SymbolKind::S_FRAMEPROC: +    break; +  // Scope ending symbols. +  case SymbolKind::S_END: +  case SymbolKind::S_INLINESITE_END: +  case SymbolKind::S_PROC_ID_END: +    break; +  default: +    return false; // Unknown symbol. +  } +  return true; +} +  void llvm::codeview::discoverTypeIndices(const CVType &Type,                                           SmallVectorImpl<TiReference> &Refs) {    ::discoverTypeIndices(Type.content(), Type.kind(), Refs); @@ -369,3 +445,9 @@ void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData,    TypeLeafKind K = static_cast<TypeLeafKind>(uint16_t(P->RecordKind));    ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K, Refs);  } + +bool llvm::codeview::discoverTypeIndices(const CVSymbol &Sym, +                                         SmallVectorImpl<TiReference> &Refs) { +  SymbolKind K = Sym.kind(); +  return ::discoverTypeIndices(Sym.content(), K, Refs); +} diff --git a/lib/DebugInfo/CodeView/TypeName.cpp b/lib/DebugInfo/CodeView/TypeName.cpp new file mode 100644 index 0000000000000..2eb8b81862f3c --- /dev/null +++ b/lib/DebugInfo/CodeView/TypeName.cpp @@ -0,0 +1,243 @@ +//===- TypeName.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/TypeName.h" + +#include "llvm/ADT/SmallString.h" +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" +#include "llvm/Support/FormatVariadic.h" + +using namespace llvm; +using namespace llvm::codeview; + +namespace { +class TypeNameComputer : public TypeVisitorCallbacks { +  /// The type collection.  Used to calculate names of nested types. +  TypeCollection &Types; +  TypeIndex CurrentTypeIndex = TypeIndex::None(); + +  /// Name of the current type. Only valid before visitTypeEnd. +  SmallString<256> Name; + +public: +  explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {} + +  StringRef name() const { return Name; } + +  /// Paired begin/end actions for all types. Receives all record data, +  /// including the fixed-length record prefix. +  Error visitTypeBegin(CVType &Record) override; +  Error visitTypeBegin(CVType &Record, TypeIndex Index) override; +  Error visitTypeEnd(CVType &Record) override; + +#define TYPE_RECORD(EnumName, EnumVal, Name)                                   \ +  Error visitKnownRecord(CVType &CVR, Name##Record &Record) override; +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD(EnumName, EnumVal, Name) +#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" +}; +} // namespace + +Error TypeNameComputer::visitTypeBegin(CVType &Record) { +  llvm_unreachable("Must call visitTypeBegin with a TypeIndex!"); +  return Error::success(); +} + +Error TypeNameComputer::visitTypeBegin(CVType &Record, TypeIndex Index) { +  // Reset Name to the empty string. If the visitor sets it, we know it. +  Name = ""; +  CurrentTypeIndex = Index; +  return Error::success(); +} + +Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); } + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, +                                         FieldListRecord &FieldList) { +  Name = "<field list>"; +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVRecord<TypeLeafKind> &CVR, +                                         StringIdRecord &String) { +  Name = String.getString(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArgListRecord &Args) { +  auto Indices = Args.getIndices(); +  uint32_t Size = Indices.size(); +  Name = "("; +  for (uint32_t I = 0; I < Size; ++I) { +    assert(Indices[I] < CurrentTypeIndex); + +    Name.append(Types.getTypeName(Indices[I])); +    if (I + 1 != Size) +      Name.append(", "); +  } +  Name.push_back(')'); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, +                                         StringListRecord &Strings) { +  auto Indices = Strings.getIndices(); +  uint32_t Size = Indices.size(); +  Name = "\""; +  for (uint32_t I = 0; I < Size; ++I) { +    Name.append(Types.getTypeName(Indices[I])); +    if (I + 1 != Size) +      Name.append("\" \""); +  } +  Name.push_back('\"'); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, ClassRecord &Class) { +  Name = Class.getName(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, UnionRecord &Union) { +  Name = Union.getName(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, EnumRecord &Enum) { +  Name = Enum.getName(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArrayRecord &AT) { +  Name = AT.getName(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) { +  Name = VFT.getName(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) { +  Name = Id.getName(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) { +  StringRef Ret = Types.getTypeName(Proc.getReturnType()); +  StringRef Params = Types.getTypeName(Proc.getArgumentList()); +  Name = formatv("{0} {1}", Ret, Params).sstr<256>(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, +                                         MemberFunctionRecord &MF) { +  StringRef Ret = Types.getTypeName(MF.getReturnType()); +  StringRef Class = Types.getTypeName(MF.getClassType()); +  StringRef Params = Types.getTypeName(MF.getArgumentList()); +  Name = formatv("{0} {1}::{2}", Ret, Class, Params).sstr<256>(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) { +  Name = Func.getName(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) { +  Name = TS.getName(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) { + +  if (Ptr.isPointerToMember()) { +    const MemberPointerInfo &MI = Ptr.getMemberInfo(); + +    StringRef Pointee = Types.getTypeName(Ptr.getReferentType()); +    StringRef Class = Types.getTypeName(MI.getContainingType()); +    Name = formatv("{0} {1}::*", Pointee, Class); +  } else { +    if (Ptr.isConst()) +      Name.append("const "); +    if (Ptr.isVolatile()) +      Name.append("volatile "); +    if (Ptr.isUnaligned()) +      Name.append("__unaligned "); + +    Name.append(Types.getTypeName(Ptr.getReferentType())); + +    if (Ptr.getMode() == PointerMode::LValueReference) +      Name.append("&"); +    else if (Ptr.getMode() == PointerMode::RValueReference) +      Name.append("&&"); +    else if (Ptr.getMode() == PointerMode::Pointer) +      Name.append("*"); +  } +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) { +  uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers()); + +  SmallString<256> TypeName; +  if (Mods & uint16_t(ModifierOptions::Const)) +    Name.append("const "); +  if (Mods & uint16_t(ModifierOptions::Volatile)) +    Name.append("volatile "); +  if (Mods & uint16_t(ModifierOptions::Unaligned)) +    Name.append("__unaligned "); +  Name.append(Types.getTypeName(Mod.getModifiedType())); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, +                                         VFTableShapeRecord &Shape) { +  Name = formatv("<vftable {0} methods>", Shape.getEntryCount()); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord( +    CVType &CVR, UdtModSourceLineRecord &ModSourceLine) { +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, +                                         UdtSourceLineRecord &SourceLine) { +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) { +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, +                                         MethodOverloadListRecord &Overloads) { +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) { +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, LabelRecord &R) { +  return Error::success(); +} + +std::string llvm::codeview::computeTypeName(TypeCollection &Types, +                                            TypeIndex Index) { +  TypeNameComputer Computer(Types); +  CVType Record = Types.getType(Index); +  if (auto EC = visitTypeRecord(Record, Index, Computer)) { +    consumeError(std::move(EC)); +    return "<unknown UDT>"; +  } +  return Computer.name(); +} diff --git a/lib/DebugInfo/CodeView/TypeTableCollection.cpp b/lib/DebugInfo/CodeView/TypeTableCollection.cpp index 8d974d522f283..4eca5aeaa0ae3 100644 --- a/lib/DebugInfo/CodeView/TypeTableCollection.cpp +++ b/lib/DebugInfo/CodeView/TypeTableCollection.cpp @@ -10,7 +10,7 @@  #include "llvm/DebugInfo/CodeView/TypeTableCollection.h"  #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" -#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeName.h"  #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"  #include "llvm/Support/BinaryByteStream.h"  #include "llvm/Support/BinaryStreamReader.h" @@ -18,14 +18,10 @@  using namespace llvm;  using namespace llvm::codeview; -static void error(Error &&EC) { -  assert(!static_cast<bool>(EC)); -  if (EC) -    consumeError(std::move(EC)); -} -  TypeTableCollection::TypeTableCollection(ArrayRef<ArrayRef<uint8_t>> Records) -    : Records(Records), Database(Records.size()) {} +    : NameStorage(Allocator), Records(Records) { +  Names.resize(Records.size()); +}  Optional<TypeIndex> TypeTableCollection::getFirst() {    if (empty()) @@ -34,50 +30,38 @@ Optional<TypeIndex> TypeTableCollection::getFirst() {  }  Optional<TypeIndex> TypeTableCollection::getNext(TypeIndex Prev) { +  assert(contains(Prev));    ++Prev; -  assert(Prev.toArrayIndex() <= size());    if (Prev.toArrayIndex() == size())      return None;    return Prev;  } -void TypeTableCollection::ensureTypeExists(TypeIndex Index) { -  assert(hasCapacityFor(Index)); - -  if (Database.contains(Index)) -    return; - -  BinaryByteStream Bytes(Records[Index.toArrayIndex()], support::little); - -  CVType Type; -  uint32_t Len; -  VarStreamArrayExtractor<CVType> Extract; -  error(Extract(Bytes, Len, Type)); - -  TypeDatabaseVisitor DBV(Database); -  error(codeview::visitTypeRecord(Type, Index, DBV)); -  assert(Database.contains(Index)); -} -  CVType TypeTableCollection::getType(TypeIndex Index) { -  ensureTypeExists(Index); -  return Database.getTypeRecord(Index); +  assert(Index.toArrayIndex() < Records.size()); +  ArrayRef<uint8_t> Bytes = Records[Index.toArrayIndex()]; +  const RecordPrefix *Prefix = +      reinterpret_cast<const RecordPrefix *>(Bytes.data()); +  TypeLeafKind Kind = static_cast<TypeLeafKind>(uint16_t(Prefix->RecordKind)); +  return CVType(Kind, Bytes);  }  StringRef TypeTableCollection::getTypeName(TypeIndex Index) { -  if (!Index.isSimple()) -    ensureTypeExists(Index); -  return Database.getTypeName(Index); +  if (Index.isNoneType() || Index.isSimple()) +    return TypeIndex::simpleTypeName(Index); + +  uint32_t I = Index.toArrayIndex(); +  if (Names[I].data() == nullptr) { +    StringRef Result = NameStorage.save(computeTypeName(*this, Index)); +    Names[I] = Result; +  } +  return Names[I];  }  bool TypeTableCollection::contains(TypeIndex Index) { -  return Database.contains(Index); +  return Index.toArrayIndex() <= size();  }  uint32_t TypeTableCollection::size() { return Records.size(); }  uint32_t TypeTableCollection::capacity() { return Records.size(); } - -bool TypeTableCollection::hasCapacityFor(TypeIndex Index) const { -  return Index.toArrayIndex() < Records.size(); -} diff --git a/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp b/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp index 57eac91f8c192..bb475a669efb2 100644 --- a/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp +++ b/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp @@ -65,46 +65,52 @@ DWARFAbbreviationDeclaration::extract(DataExtractor Data,      if (A && F) {        Optional<int64_t> V;        bool IsImplicitConst = (F == DW_FORM_implicit_const); -      if (IsImplicitConst) +      if (IsImplicitConst) {          V = Data.getSLEB128(OffsetPtr); -      else if (auto Size = DWARFFormValue::getFixedByteSize(F)) -        V = *Size; -      AttributeSpecs.push_back(AttributeSpec(A, F, V)); -      if (IsImplicitConst) +        AttributeSpecs.push_back(AttributeSpec(A, F, V));          continue; +      }        // If this abbrevation still has a fixed byte size, then update the        // FixedAttributeSize as needed. -      if (FixedAttributeSize) { -        if (V) -          FixedAttributeSize->NumBytes += *V; -        else { -          switch (F) { -          case DW_FORM_addr: -            ++FixedAttributeSize->NumAddrs; -            break; - -          case DW_FORM_ref_addr: -            ++FixedAttributeSize->NumRefAddrs; -            break; - -          case DW_FORM_strp: -          case DW_FORM_GNU_ref_alt: -          case DW_FORM_GNU_strp_alt: -          case DW_FORM_line_strp: -          case DW_FORM_sec_offset: -          case DW_FORM_strp_sup: -            ++FixedAttributeSize->NumDwarfOffsets; -            break; - -          default: -            // Indicate we no longer have a fixed byte size for this -            // abbreviation by clearing the FixedAttributeSize optional value -            // so it doesn't have a value. -            FixedAttributeSize.reset(); -            break; -          } +      switch (F) { +      case DW_FORM_addr: +        if (FixedAttributeSize) +          ++FixedAttributeSize->NumAddrs; +        break; + +      case DW_FORM_ref_addr: +        if (FixedAttributeSize) +          ++FixedAttributeSize->NumRefAddrs; +        break; + +      case DW_FORM_strp: +      case DW_FORM_GNU_ref_alt: +      case DW_FORM_GNU_strp_alt: +      case DW_FORM_line_strp: +      case DW_FORM_sec_offset: +      case DW_FORM_strp_sup: +        if (FixedAttributeSize) +          ++FixedAttributeSize->NumDwarfOffsets; +        break; + +      default: +        // The form has a byte size that doesn't depend on Params. +        // If it's a fixed size, keep track of it. +        if (auto Size = +                DWARFFormValue::getFixedByteSize(F, DWARFFormParams())) { +          V = *Size; +          if (FixedAttributeSize) +            FixedAttributeSize->NumBytes += *V; +          break;          } +        // Indicate we no longer have a fixed byte size for this +        // abbreviation by clearing the FixedAttributeSize optional value +        // so it doesn't have a value. +        FixedAttributeSize.reset(); +        break;        } +      // Record this attribute and its fixed size if it has one. +      AttributeSpecs.push_back(AttributeSpec(A, F, V));      } else if (A == 0 && F == 0) {        // We successfully reached the end of this abbreviation declaration        // since both attribute and form are zero. @@ -186,7 +192,8 @@ Optional<DWARFFormValue> DWARFAbbreviationDeclaration::getAttributeValue(      if (auto FixedSize = Spec.getByteSize(U))        Offset += *FixedSize;      else -      DWARFFormValue::skipValue(Spec.Form, DebugInfoData, &Offset, &U); +      DWARFFormValue::skipValue(Spec.Form, DebugInfoData, &Offset, +                                U.getFormParams());      ++AttrIndex;    }    return None; @@ -211,7 +218,8 @@ Optional<int64_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize(    if (ByteSizeOrValue)      return ByteSizeOrValue;    Optional<int64_t> S; -  auto FixedByteSize = DWARFFormValue::getFixedByteSize(Form, &U); +  auto FixedByteSize = +      DWARFFormValue::getFixedByteSize(Form, U.getFormParams());    if (FixedByteSize)      S = *FixedByteSize;    return S; diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp index 9bafcde57f0ae..3814794617503 100644 --- a/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -13,6 +13,7 @@  #include "llvm/ADT/SmallVector.h"  #include "llvm/ADT/StringRef.h"  #include "llvm/ADT/StringSwitch.h" +#include "llvm/BinaryFormat/Dwarf.h"  #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"  #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"  #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" @@ -36,7 +37,6 @@  #include "llvm/Object/RelocVisitor.h"  #include "llvm/Support/Casting.h"  #include "llvm/Support/DataExtractor.h" -#include "llvm/Support/Debug.h"  #include "llvm/Support/Error.h"  #include "llvm/Support/Format.h"  #include "llvm/Support/MemoryBuffer.h" @@ -44,8 +44,8 @@  #include <algorithm>  #include <cstdint>  #include <map> -#include <set>  #include <string> +#include <tuple>  #include <utility>  #include <vector> @@ -55,9 +55,9 @@ using namespace object;  #define DEBUG_TYPE "dwarf" -typedef DWARFDebugLine::LineTable DWARFLineTable; -typedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind; -typedef DILineInfoSpecifier::FunctionNameKind FunctionNameKind; +using DWARFLineTable = DWARFDebugLine::LineTable; +using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind; +using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind;  uint64_t llvm::getRelocatedValue(const DataExtractor &Data, uint32_t Size,                                   uint32_t *Off, const RelocAddrMap *Relocs, @@ -201,8 +201,7 @@ static void dumpStringOffsetsSection(raw_ostream &OS, StringRef SectionName,    }  } -void DWARFContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts){ - +void DWARFContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {    DIDumpType DumpType = DumpOpts.DumpType;    bool DumpEH = DumpOpts.DumpEH;    bool SummarizeTypes = DumpOpts.SummarizeTypes; @@ -1068,7 +1067,7 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,          errs() << "error: failed to compute relocation: " << Name << "\n";          continue;        } -      llvm::RelocAddrEntry Rel = {SymInfoOrErr->SectionIndex, Val}; +      RelocAddrEntry Rel = {SymInfoOrErr->SectionIndex, Val};        Map->insert({Reloc.getOffset(), Rel});      }    } diff --git a/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp index cf9fec2b3254c..475cf25b781b4 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -8,7 +8,6 @@  //===----------------------------------------------------------------------===//  #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" -  #include "llvm/ADT/ArrayRef.h"  #include "llvm/ADT/DenseMap.h"  #include "llvm/ADT/Optional.h" @@ -71,7 +70,7 @@ protected:    /// An entry may contain CFI instructions. An instruction consists of an    /// opcode and an optional sequence of operands. -  typedef std::vector<uint64_t> Operands; +  using Operands = std::vector<uint64_t>;    struct Instruction {      Instruction(uint8_t Opcode)        : Opcode(Opcode) @@ -518,14 +517,13 @@ static uint64_t readPointer(const DataExtractor &Data, uint32_t &Offset,  // 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); +static void LLVM_ATTRIBUTE_NORETURN ReportError(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) { @@ -590,13 +588,15 @@ void DWARFDebugFrame::parse(DataExtractor Data) {          for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) {            switch (AugmentationString[i]) {              default: -              ReportError("Unknown augmentation character in entry at %lx"); +              ReportError(StartOffset, +                          "Unknown augmentation character in entry at %lx");              case 'L':                LSDAPointerEncoding = Data.getU8(&Offset);                break;              case 'P': {                if (Personality) -                ReportError("Duplicate personality in entry at %lx"); +                ReportError(StartOffset, +                            "Duplicate personality in entry at %lx");                PersonalityEncoding = Data.getU8(&Offset);                Personality = readPointer(Data, Offset, *PersonalityEncoding);                break; @@ -606,7 +606,8 @@ void DWARFDebugFrame::parse(DataExtractor Data) {                break;              case 'z':                if (i) -                ReportError("'z' must be the first character at %lx"); +                ReportError(StartOffset, +                            "'z' must be the first character at %lx");                // Parse the augmentation length first.  We only parse it if                // the string contains a 'z'.                AugmentationLength = Data.getULEB128(&Offset); @@ -618,7 +619,7 @@ void DWARFDebugFrame::parse(DataExtractor Data) {          if (AugmentationLength.hasValue()) {            if (Offset != EndAugmentationOffset) -            ReportError("Parsing augmentation data at %lx failed"); +            ReportError(StartOffset, "Parsing augmentation data at %lx failed");            AugmentationData = Data.getData().slice(StartAugmentationOffset,                                                    EndAugmentationOffset); @@ -645,7 +646,8 @@ void DWARFDebugFrame::parse(DataExtractor Data) {        if (IsEH) {          // The address size is encoded in the CIE we reference.          if (!Cie) -          ReportError("Parsing FDE data at %lx failed due to missing CIE"); +          ReportError(StartOffset, +                      "Parsing FDE data at %lx failed due to missing CIE");          InitialLocation = readPointer(Data, Offset,                                        Cie->getFDEPointerEncoding()); @@ -665,7 +667,7 @@ void DWARFDebugFrame::parse(DataExtractor Data) {              readPointer(Data, Offset, Cie->getLSDAPointerEncoding());            if (Offset != EndAugmentationOffset) -            ReportError("Parsing augmentation data at %lx failed"); +            ReportError(StartOffset, "Parsing augmentation data at %lx failed");          }        } else {          InitialLocation = Data.getAddress(&Offset); @@ -680,7 +682,7 @@ void DWARFDebugFrame::parse(DataExtractor Data) {      Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);      if (Offset != EndStructureOffset) -      ReportError("Parsing entry instructions at %lx failed"); +      ReportError(StartOffset, "Parsing entry instructions at %lx failed");    }  } diff --git a/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp index dbcc64fc0832f..1551974b822ac 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp @@ -59,7 +59,7 @@ bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U, uint32_t *OffsetPtr,        // Attribute byte size if fixed, just add the size to the offset.        *OffsetPtr += *FixedSize;      } else if (!DWARFFormValue::skipValue(AttrSpec.Form, DebugInfoData, -                                          OffsetPtr, &U)) { +                                          OffsetPtr, U.getFormParams())) {        // We failed to skip this attribute's value, restore the original offset        // and return the failure status.        *OffsetPtr = Offset; diff --git a/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/lib/DebugInfo/DWARF/DWARFDebugLine.cpp index cda3e75fbc3e7..ad5647f3e03d8 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -9,6 +9,8 @@  #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"  #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h"  #include "llvm/BinaryFormat/Dwarf.h"  #include "llvm/DebugInfo/DWARF/DWARFContext.h"  #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" @@ -26,23 +28,27 @@  using namespace llvm;  using namespace dwarf; -typedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind; +using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind; +  namespace { +  struct ContentDescriptor {    dwarf::LineNumberEntryFormat Type;    dwarf::Form Form;  }; -typedef SmallVector<ContentDescriptor, 4> ContentDescriptors; + +using ContentDescriptors = SmallVector<ContentDescriptor, 4>; +  } // end anonmyous namespace  DWARFDebugLine::Prologue::Prologue() { clear(); }  void DWARFDebugLine::Prologue::clear() { -  TotalLength = Version = PrologueLength = 0; -  AddressSize = SegSelectorSize = 0; +  TotalLength = PrologueLength = 0; +  SegSelectorSize = 0;    MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0;    OpcodeBase = 0; -  IsDWARF64 = false; +  FormParams = DWARFFormParams({0, 0, DWARF32});    StandardOpcodeLengths.clear();    IncludeDirectories.clear();    FileNames.clear(); @@ -51,12 +57,13 @@ void DWARFDebugLine::Prologue::clear() {  void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const {    OS << "Line table prologue:\n"       << format("    total_length: 0x%8.8" PRIx64 "\n", TotalLength) -     << format("         version: %u\n", Version) -     << format(Version >= 5 ? "    address_size: %u\n" : "", AddressSize) -     << format(Version >= 5 ? " seg_select_size: %u\n" : "", SegSelectorSize) -     << format(" prologue_length: 0x%8.8" PRIx64 "\n", PrologueLength) +     << format("         version: %u\n", getVersion()); +  if (getVersion() >= 5) +    OS << format("    address_size: %u\n", getAddressSize()) +       << format(" seg_select_size: %u\n", SegSelectorSize); +  OS << format(" prologue_length: 0x%8.8" PRIx64 "\n", PrologueLength)       << format(" min_inst_length: %u\n", MinInstLength) -     << format(Version >= 4 ? "max_ops_per_inst: %u\n" : "", MaxOpsPerInst) +     << format(getVersion() >= 4 ? "max_ops_per_inst: %u\n" : "", MaxOpsPerInst)       << format(" default_is_stmt: %u\n", DefaultIsStmt)       << format("       line_base: %i\n", LineBase)       << format("      line_range: %u\n", LineRange) @@ -137,6 +144,7 @@ parseV5EntryFormat(DataExtractor DebugLineData, uint32_t *OffsetPtr,  static bool  parseV5DirFileTables(DataExtractor DebugLineData, uint32_t *OffsetPtr,                       uint64_t EndPrologueOffset, +                     const DWARFFormParams &FormParams,                       std::vector<StringRef> &IncludeDirectories,                       std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {    // Get the directory entry description. @@ -159,7 +167,7 @@ parseV5DirFileTables(DataExtractor DebugLineData, uint32_t *OffsetPtr,          IncludeDirectories.push_back(Value.getAsCString().getValue());          break;        default: -        if (!Value.skipValue(DebugLineData, OffsetPtr, nullptr)) +        if (!Value.skipValue(DebugLineData, OffsetPtr, FormParams))            return false;        }      } @@ -211,24 +219,26 @@ bool DWARFDebugLine::Prologue::parse(DataExtractor DebugLineData,    clear();    TotalLength = DebugLineData.getU32(OffsetPtr);    if (TotalLength == UINT32_MAX) { -    IsDWARF64 = true; +    FormParams.Format = dwarf::DWARF64;      TotalLength = DebugLineData.getU64(OffsetPtr); -  } else if (TotalLength > 0xffffff00) { +  } else if (TotalLength >= 0xffffff00) {      return false;    } -  Version = DebugLineData.getU16(OffsetPtr); -  if (Version < 2) +  FormParams.Version = DebugLineData.getU16(OffsetPtr); +  if (getVersion() < 2)      return false; -  if (Version >= 5) { -    AddressSize = DebugLineData.getU8(OffsetPtr); +  if (getVersion() >= 5) { +    FormParams.AddrSize = DebugLineData.getU8(OffsetPtr); +    assert(getAddressSize() == DebugLineData.getAddressSize() && +           "Line table header and data extractor disagree");      SegSelectorSize = DebugLineData.getU8(OffsetPtr);    }    PrologueLength = DebugLineData.getUnsigned(OffsetPtr, sizeofPrologueLength());    const uint64_t EndPrologueOffset = PrologueLength + *OffsetPtr;    MinInstLength = DebugLineData.getU8(OffsetPtr); -  if (Version >= 4) +  if (getVersion() >= 4)      MaxOpsPerInst = DebugLineData.getU8(OffsetPtr);    DefaultIsStmt = DebugLineData.getU8(OffsetPtr);    LineBase = DebugLineData.getU8(OffsetPtr); @@ -241,9 +251,9 @@ bool DWARFDebugLine::Prologue::parse(DataExtractor DebugLineData,      StandardOpcodeLengths.push_back(OpLen);    } -  if (Version >= 5) { +  if (getVersion() >= 5) {      if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset, -                              IncludeDirectories, FileNames)) { +                              getFormParams(), IncludeDirectories, FileNames)) {        fprintf(stderr,                "warning: parsing line table prologue at 0x%8.8" PRIx64                " found an invalid directory or file table description at" @@ -333,7 +343,7 @@ void DWARFDebugLine::LineTable::clear() {  }  DWARFDebugLine::ParsingState::ParsingState(struct LineTable *LT) -    : LineTable(LT), RowNumber(0) { +    : LineTable(LT) {    resetRowAndSequence();  } diff --git a/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/lib/DebugInfo/DWARF/DWARFFormValue.cpp index ed1f5f46dcfb8..861114bde1f2b 100644 --- a/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -59,48 +59,13 @@ static const DWARFFormValue::FormClass DWARF4FormClasses[] = {      DWARFFormValue::FC_Flag,          // 0x19 DW_FORM_flag_present  }; -namespace { - -/// A helper class that can be used in DWARFFormValue.cpp functions that need -/// to know the byte size of DW_FORM values that vary in size depending on the -/// DWARF version, address byte size, or DWARF32 or DWARF64. -class FormSizeHelper { -  uint16_t Version; -  uint8_t AddrSize; -  llvm::dwarf::DwarfFormat Format; - -public: -  FormSizeHelper(uint16_t V, uint8_t A, llvm::dwarf::DwarfFormat F) -      : Version(V), AddrSize(A), Format(F) {} - -  uint8_t getAddressByteSize() const { return AddrSize; } - -  uint8_t getRefAddrByteSize() const { -    if (Version == 2) -      return AddrSize; -    return getDwarfOffsetByteSize(); -  } - -  uint8_t getDwarfOffsetByteSize() const { -    switch (Format) { -    case dwarf::DwarfFormat::DWARF32: -      return 4; -    case dwarf::DwarfFormat::DWARF64: -      return 8; -    } -    llvm_unreachable("Invalid Format value"); -  } -}; - -} // end anonymous namespace - -template <class T> -static Optional<uint8_t> getFixedByteSize(dwarf::Form Form, const T *U) { +Optional<uint8_t> +DWARFFormValue::getFixedByteSize(dwarf::Form Form, +                                 const DWARFFormParams Params) {    switch (Form) {    case DW_FORM_addr: -    if (U) -      return U->getAddressByteSize(); -    return None; +    assert(Params.Version && Params.AddrSize && "Invalid Params for form"); +    return Params.AddrSize;    case DW_FORM_block:          // ULEB128 length L followed by L bytes.    case DW_FORM_block1:         // 1 byte length L followed by L bytes. @@ -121,9 +86,8 @@ static Optional<uint8_t> getFixedByteSize(dwarf::Form Form, const T *U) {      return None;    case DW_FORM_ref_addr: -    if (U) -      return U->getRefAddrByteSize(); -    return None; +    assert(Params.Version && Params.AddrSize && "Invalid Params for form"); +    return Params.getRefAddrByteSize();    case DW_FORM_flag:    case DW_FORM_data1: @@ -138,6 +102,9 @@ static Optional<uint8_t> getFixedByteSize(dwarf::Form Form, const T *U) {    case DW_FORM_addrx2:      return 2; +  case DW_FORM_strx3: +    return 3; +    case DW_FORM_data4:    case DW_FORM_ref4:    case DW_FORM_ref_sup4: @@ -151,9 +118,8 @@ static Optional<uint8_t> getFixedByteSize(dwarf::Form Form, const T *U) {    case DW_FORM_line_strp:    case DW_FORM_sec_offset:    case DW_FORM_strp_sup: -    if (U) -      return U->getDwarfOffsetByteSize(); -    return None; +    assert(Params.Version && Params.AddrSize && "Invalid Params for form"); +    return Params.getDwarfOffsetByteSize();    case DW_FORM_data8:    case DW_FORM_ref8: @@ -178,9 +144,9 @@ static Optional<uint8_t> getFixedByteSize(dwarf::Form Form, const T *U) {    return None;  } -template <class T> -static bool skipFormValue(dwarf::Form Form, const DataExtractor &DebugInfoData, -                          uint32_t *OffsetPtr, const T *U) { +bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData, +                               uint32_t *OffsetPtr, +                               const DWARFFormParams Params) {    bool Indirect = false;    do {      switch (Form) { @@ -240,7 +206,8 @@ static bool skipFormValue(dwarf::Form Form, const DataExtractor &DebugInfoData,      case DW_FORM_line_strp:      case DW_FORM_GNU_ref_alt:      case DW_FORM_GNU_strp_alt: -      if (Optional<uint8_t> FixedSize = ::getFixedByteSize(Form, U)) { +      if (Optional<uint8_t> FixedSize = +              DWARFFormValue::getFixedByteSize(Form, Params)) {          *OffsetPtr += *FixedSize;          return true;        } @@ -274,19 +241,6 @@ static bool skipFormValue(dwarf::Form Form, const DataExtractor &DebugInfoData,    return true;  } -Optional<uint8_t> DWARFFormValue::getFixedByteSize(dwarf::Form Form, -                                                   const DWARFUnit *U) { -  return ::getFixedByteSize(Form, U); -} - -Optional<uint8_t> -DWARFFormValue::getFixedByteSize(dwarf::Form Form, uint16_t Version, -                                 uint8_t AddrSize, -                                 llvm::dwarf::DwarfFormat Format) { -  FormSizeHelper FSH(Version, AddrSize, Format); -  return ::getFixedByteSize(Form, &FSH); -} -  bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {    // First, check DWARF4 form classes.    if (Form < makeArrayRef(DWARF4FormClasses).size() && @@ -302,6 +256,10 @@ bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {    case DW_FORM_GNU_str_index:    case DW_FORM_GNU_strp_alt:    case DW_FORM_strx: +  case DW_FORM_strx1: +  case DW_FORM_strx2: +  case DW_FORM_strx3: +  case DW_FORM_strx4:      return (FC == FC_String);    case DW_FORM_implicit_const:      return (FC == FC_Constant); @@ -368,6 +326,9 @@ bool DWARFFormValue::extractValue(const DataExtractor &Data,      case DW_FORM_addrx2:        Value.uval = Data.getU16(OffsetPtr);        break; +    case DW_FORM_strx3: +      Value.uval = Data.getU24(OffsetPtr); +      break;      case DW_FORM_data4:      case DW_FORM_ref4:      case DW_FORM_ref_sup4: @@ -438,24 +399,6 @@ bool DWARFFormValue::extractValue(const DataExtractor &Data,    return true;  } -bool DWARFFormValue::skipValue(DataExtractor DebugInfoData, uint32_t *OffsetPtr, -                               const DWARFUnit *U) const { -  return DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, U); -} - -bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData, -                               uint32_t *OffsetPtr, const DWARFUnit *U) { -  return skipFormValue(Form, DebugInfoData, OffsetPtr, U); -} - -bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData, -                               uint32_t *OffsetPtr, uint16_t Version, -                               uint8_t AddrSize, -                               llvm::dwarf::DwarfFormat Format) { -  FormSizeHelper FSH(Version, AddrSize, Format); -  return skipFormValue(Form, DebugInfoData, OffsetPtr, &FSH); -} -  void DWARFFormValue::dump(raw_ostream &OS) const {    uint64_t UValue = Value.uval;    bool CURelativeOffset = false; @@ -545,6 +488,10 @@ void DWARFFormValue::dump(raw_ostream &OS) const {      dumpString(OS);      break;    case DW_FORM_strx: +  case DW_FORM_strx1: +  case DW_FORM_strx2: +  case DW_FORM_strx3: +  case DW_FORM_strx4:    case DW_FORM_GNU_str_index:      OS << format(" indexed (%8.8x) string = ", (uint32_t)UValue);      dumpString(OS); @@ -623,7 +570,9 @@ Optional<const char *> DWARFFormValue::getAsCString() const {    if (Form == DW_FORM_GNU_strp_alt || U == nullptr)      return None;    uint32_t Offset = Value.uval; -  if (Form == DW_FORM_GNU_str_index || Form == DW_FORM_strx) { +  if (Form == DW_FORM_GNU_str_index || Form == DW_FORM_strx || +      Form == DW_FORM_strx1 || Form == DW_FORM_strx2 || Form == DW_FORM_strx3 || +      Form == DW_FORM_strx4) {      uint64_t StrOffset;      if (!U->getStringOffsetSectionItem(Offset, StrOffset))        return None; diff --git a/lib/DebugInfo/DWARF/DWARFUnit.cpp b/lib/DebugInfo/DWARF/DWARFUnit.cpp index 09e6a292e5fe1..fd9c7c2b1d46c 100644 --- a/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -1,4 +1,4 @@ -//===-- DWARFUnit.cpp -----------------------------------------------------===// +//===- DWARFUnit.cpp ------------------------------------------------------===//  //  //                     The LLVM Compiler Infrastructure  // @@ -8,7 +8,6 @@  //===----------------------------------------------------------------------===//  #include "llvm/DebugInfo/DWARF/DWARFUnit.h" -#include "llvm/ADT/STLExtras.h"  #include "llvm/ADT/SmallString.h"  #include "llvm/ADT/StringRef.h"  #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" @@ -17,8 +16,6 @@  #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"  #include "llvm/DebugInfo/DWARF/DWARFDie.h"  #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Support/Casting.h"  #include "llvm/Support/DataExtractor.h"  #include "llvm/Support/Path.h"  #include <algorithm> @@ -26,6 +23,7 @@  #include <cstddef>  #include <cstdint>  #include <cstdio> +#include <utility>  #include <vector>  using namespace llvm; @@ -55,8 +53,8 @@ DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section,                       const DWARFUnitIndex::Entry *IndexEntry)      : Context(DC), InfoSection(Section), Abbrev(DA), RangeSection(RS),        LineSection(LS), StringSection(SS), StringOffsetSection(SOS), -      StringOffsetSectionBase(0), AddrOffsetSection(AOS), isLittleEndian(LE), -      isDWO(IsDWO), UnitSection(UnitSection), IndexEntry(IndexEntry) { +      AddrOffsetSection(AOS), isLittleEndian(LE), isDWO(IsDWO), +      UnitSection(UnitSection), IndexEntry(IndexEntry) {    clear();  } @@ -64,11 +62,13 @@ DWARFUnit::~DWARFUnit() = default;  bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index,                                                  uint64_t &Result) const { -  uint32_t Offset = AddrOffsetSectionBase + Index * AddrSize; -  if (AddrOffsetSection->Data.size() < Offset + AddrSize) +  uint32_t Offset = AddrOffsetSectionBase + Index * getAddressByteSize(); +  if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize())      return false; -  DataExtractor DA(AddrOffsetSection->Data, isLittleEndian, AddrSize); -  Result = getRelocatedValue(DA, AddrSize, &Offset, &AddrOffsetSection->Relocs); +  DataExtractor DA(AddrOffsetSection->Data, isLittleEndian, +                   getAddressByteSize()); +  Result = getRelocatedValue(DA, getAddressByteSize(), &Offset, +                             &AddrOffsetSection->Relocs);    return true;  } @@ -94,15 +94,17 @@ uint64_t DWARFUnit::getStringOffsetSectionRelocation(uint32_t Index) const {  bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) {    Length = debug_info.getU32(offset_ptr); -  Version = debug_info.getU16(offset_ptr); +  // FIXME: Support DWARF64. +  FormParams.Format = DWARF32; +  FormParams.Version = debug_info.getU16(offset_ptr);    uint64_t AbbrOffset; -  if (Version >= 5) { +  if (FormParams.Version >= 5) {      UnitType = debug_info.getU8(offset_ptr); -    AddrSize = debug_info.getU8(offset_ptr); +    FormParams.AddrSize = debug_info.getU8(offset_ptr);      AbbrOffset = debug_info.getU32(offset_ptr);    } else {      AbbrOffset = debug_info.getU32(offset_ptr); -    AddrSize = debug_info.getU8(offset_ptr); +    FormParams.AddrSize = debug_info.getU8(offset_ptr);    }    if (IndexEntry) {      if (AbbrOffset) @@ -117,14 +119,14 @@ bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) {    }    bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1); -  bool VersionOK = DWARFContext::isSupportedVersion(Version); -  bool AddrSizeOK = AddrSize == 4 || AddrSize == 8; +  bool VersionOK = DWARFContext::isSupportedVersion(getVersion()); +  bool AddrSizeOK = getAddressByteSize() == 4 || getAddressByteSize() == 8;    if (!LengthOK || !VersionOK || !AddrSizeOK)      return false;    // Keep track of the highest DWARF version we encounter across all units. -  Context.setMaxVersionIfGreater(Version); +  Context.setMaxVersionIfGreater(getVersion());    Abbrevs = Abbrev->getAbbreviationDeclarationSet(AbbrOffset);    return Abbrevs != nullptr; @@ -150,7 +152,8 @@ bool DWARFUnit::extractRangeList(uint32_t RangeListOffset,                                          DWARFDebugRangeList &RangeList) const {    // Require that compile unit is extracted.    assert(!DieArray.empty()); -  DataExtractor RangesData(RangeSection->Data, isLittleEndian, AddrSize); +  DataExtractor RangesData(RangeSection->Data, isLittleEndian, +                           getAddressByteSize());    uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;    return RangeList.extract(RangesData, &ActualRangeListOffset,                             RangeSection->Relocs); @@ -159,9 +162,8 @@ bool DWARFUnit::extractRangeList(uint32_t RangeListOffset,  void DWARFUnit::clear() {    Offset = 0;    Length = 0; -  Version = 0;    Abbrevs = nullptr; -  AddrSize = 0; +  FormParams = DWARFFormParams({0, 0, DWARF32});    BaseAddr = 0;    RangeSectionBase = 0;    AddrOffsetSectionBase = 0; diff --git a/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/lib/DebugInfo/DWARF/DWARFVerifier.cpp index a6240fb60143c..41907e5705637 100644 --- a/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -279,7 +279,6 @@ bool DWARFVerifier::handleDebugLine() {  bool DWARFVerifier::handleAppleNames() {    NumAppleNamesErrors = 0; -  OS << "Verifying .apple_names...\n";    DataExtractor AppleNamesSection(DCtx.getAppleNamesSection().Data,                                    DCtx.isLittleEndian(), 0); @@ -288,10 +287,11 @@ bool DWARFVerifier::handleAppleNames() {                                     DCtx.getAppleNamesSection().Relocs);    if (!AppleNames.extract()) { -    OS << "error: cannot extract .apple_names accelerator table\n"; -    return false; +    return true;    } +  OS << "Verifying .apple_names...\n"; +    // Verify that all buckets have a valid hash index or are empty    uint32_t NumBuckets = AppleNames.getNumBuckets();    uint32_t NumHashes = AppleNames.getNumHashes(); diff --git a/lib/DebugInfo/MSF/MSFBuilder.cpp b/lib/DebugInfo/MSF/MSFBuilder.cpp index 5b1b5d8dc4d55..0f4f785abf55a 100644 --- a/lib/DebugInfo/MSF/MSFBuilder.cpp +++ b/lib/DebugInfo/MSF/MSFBuilder.cpp @@ -1,3 +1,4 @@ +//===- MSFBuilder.cpp -----------------------------------------------------===//  //  //                     The LLVM Compiler Infrastructure  // @@ -6,22 +7,30 @@  //  //===----------------------------------------------------------------------===// +#include "llvm/ADT/ArrayRef.h"  #include "llvm/DebugInfo/MSF/MSFBuilder.h"  #include "llvm/DebugInfo/MSF/MSFError.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <cstring> +#include <memory> +#include <utility> +#include <vector>  using namespace llvm;  using namespace llvm::msf;  using namespace llvm::support; -namespace { -const uint32_t kSuperBlockBlock = 0; -const uint32_t kFreePageMap0Block = 1; -const uint32_t kFreePageMap1Block = 2; -const uint32_t kNumReservedPages = 3; +static const uint32_t kSuperBlockBlock = 0; +static const uint32_t kFreePageMap0Block = 1; +static const uint32_t kFreePageMap1Block = 2; +static const uint32_t kNumReservedPages = 3; -const uint32_t kDefaultFreePageMap = kFreePageMap0Block; -const uint32_t kDefaultBlockMapAddr = kNumReservedPages; -} +static const uint32_t kDefaultFreePageMap = kFreePageMap0Block; +static const uint32_t kDefaultBlockMapAddr = kNumReservedPages;  MSFBuilder::MSFBuilder(uint32_t BlockSize, uint32_t MinBlockCount, bool CanGrow,                         BumpPtrAllocator &Allocator) @@ -263,7 +272,7 @@ Expected<MSFLayout> MSFBuilder::build() {    // The stream sizes should be re-allocated as a stable pointer and the stream    // map should have each of its entries allocated as a separate stable pointer. -  if (StreamData.size() > 0) { +  if (!StreamData.empty()) {      ulittle32_t *Sizes = Allocator.Allocate<ulittle32_t>(StreamData.size());      L.StreamSizes = ArrayRef<ulittle32_t>(Sizes, StreamData.size());      L.StreamMap.resize(StreamData.size()); diff --git a/lib/DebugInfo/MSF/MSFCommon.cpp b/lib/DebugInfo/MSF/MSFCommon.cpp index fdab7884646ec..1facf5efb4bbb 100644 --- a/lib/DebugInfo/MSF/MSFCommon.cpp +++ b/lib/DebugInfo/MSF/MSFCommon.cpp @@ -1,4 +1,4 @@ -//===- MSFCommon.cpp - Common types and functions for MSF files -*- C++ -*-===// +//===- MSFCommon.cpp - Common types and functions for MSF files -----------===//  //  //                     The LLVM Compiler Infrastructure  // @@ -9,6 +9,10 @@  #include "llvm/DebugInfo/MSF/MSFCommon.h"  #include "llvm/DebugInfo/MSF/MSFError.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <cstring>  using namespace llvm;  using namespace llvm::msf; diff --git a/lib/DebugInfo/MSF/MappedBlockStream.cpp b/lib/DebugInfo/MSF/MappedBlockStream.cpp index faf2442bc94bb..e45f4ae0ed940 100644 --- a/lib/DebugInfo/MSF/MappedBlockStream.cpp +++ b/lib/DebugInfo/MSF/MappedBlockStream.cpp @@ -8,23 +8,33 @@  //===----------------------------------------------------------------------===//  #include "llvm/DebugInfo/MSF/MappedBlockStream.h" - -#include "llvm/DebugInfo/MSF/IMSFFile.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h"  #include "llvm/DebugInfo/MSF/MSFCommon.h"  #include "llvm/DebugInfo/MSF/MSFStreamLayout.h" -#include "llvm/Support/BinaryStreamError.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MathExtras.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <cstring> +#include <utility> +#include <vector>  using namespace llvm;  using namespace llvm::msf;  namespace { +  template <typename Base> class MappedBlockStreamImpl : public Base {  public:    template <typename... Args>    MappedBlockStreamImpl(Args &&... Params)        : Base(std::forward<Args>(Params)...) {}  }; -} + +} // end anonymous namespace  static void initializeFpmStreamLayout(const MSFLayout &Layout,                                        MSFStreamLayout &FpmLayout) { @@ -39,7 +49,8 @@ static void initializeFpmStreamLayout(const MSFLayout &Layout,    FpmLayout.Length = msf::getFullFpmByteSize(Layout);  } -typedef std::pair<uint32_t, uint32_t> Interval; +using Interval = std::pair<uint32_t, uint32_t>; +  static Interval intersect(const Interval &I1, const Interval &I2) {    return std::make_pair(std::max(I1.first, I2.first),                          std::min(I1.second, I2.second)); @@ -214,7 +225,7 @@ bool MappedBlockStream::tryReadContiguously(uint32_t Offset, uint32_t Size,    uint32_t OffsetInBlock = Offset % BlockSize;    uint32_t BytesFromFirstBlock = std::min(Size, BlockSize - OffsetInBlock);    uint32_t NumAdditionalBlocks = -      llvm::alignTo(Size - BytesFromFirstBlock, BlockSize) / BlockSize; +      alignTo(Size - BytesFromFirstBlock, BlockSize) / BlockSize;    uint32_t RequiredContiguousBlocks = NumAdditionalBlocks + 1;    uint32_t E = StreamLayout.Blocks[BlockNum]; diff --git a/lib/DebugInfo/PDB/DIA/DIASession.cpp b/lib/DebugInfo/PDB/DIA/DIASession.cpp index ef47b92b4f2f3..ef9390cda3127 100644 --- a/lib/DebugInfo/PDB/DIA/DIASession.cpp +++ b/lib/DebugInfo/PDB/DIA/DIASession.cpp @@ -151,7 +151,7 @@ void DIASession::setLoadAddress(uint64_t Address) {    Session->put_loadAddress(Address);  } -std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() const { +std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() {    CComPtr<IDiaSymbol> GlobalScope;    if (S_OK != Session->get_globalScope(&GlobalScope))      return nullptr; diff --git a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp index 81a9d3eeec619..745dd742aadc3 100644 --- a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp @@ -51,6 +51,7 @@ DbiModuleDescriptorBuilder::DbiModuleDescriptorBuilder(StringRef ModuleName,                                                         uint32_t ModIndex,                                                         msf::MSFBuilder &Msf)      : MSF(Msf), ModuleName(ModuleName) { +  ::memset(&Layout, 0, sizeof(Layout));    Layout.Mod = ModIndex;  } @@ -102,6 +103,7 @@ template <typename T> struct Foo {  template <typename T> Foo<T> makeFoo(T &&t) { return Foo<T>(std::move(t)); }  void DbiModuleDescriptorBuilder::finalize() { +  Layout.SC.ModuleIndex = Layout.Mod;    Layout.FileNameOffs = 0; // TODO: Fix this    Layout.Flags = 0;        // TODO: Fix this    Layout.C11Bytes = 0; @@ -182,3 +184,9 @@ void DbiModuleDescriptorBuilder::addDebugSubsection(    C13Builders.push_back(llvm::make_unique<DebugSubsectionRecordBuilder>(        std::move(Subsection), CodeViewContainer::Pdb));  } + +void DbiModuleDescriptorBuilder::addDebugSubsection( +    const DebugSubsectionRecord &SubsectionContents) { +  C13Builders.push_back(llvm::make_unique<DebugSubsectionRecordBuilder>( +      SubsectionContents, CodeViewContainer::Pdb)); +} diff --git a/lib/DebugInfo/PDB/Native/DbiStream.cpp b/lib/DebugInfo/PDB/Native/DbiStream.cpp index 24322d942facc..a1f0671dec3e6 100644 --- a/lib/DebugInfo/PDB/Native/DbiStream.cpp +++ b/lib/DebugInfo/PDB/Native/DbiStream.cpp @@ -99,29 +99,27 @@ Error DbiStream::reload() {      return make_error<RawError>(raw_error_code::corrupt_file,                                  "DBI type server substream not aligned."); -  BinaryStreamRef ModInfoSubstream; -  BinaryStreamRef FileInfoSubstream; -  if (auto EC = -          Reader.readStreamRef(ModInfoSubstream, Header->ModiSubstreamSize)) +  if (auto EC = Reader.readSubstream(ModiSubstream, Header->ModiSubstreamSize))      return EC; -  if (auto EC = Reader.readStreamRef(SecContrSubstream, +  if (auto EC = Reader.readSubstream(SecContrSubstream,                                       Header->SecContrSubstreamSize))      return EC; -  if (auto EC = Reader.readStreamRef(SecMapSubstream, Header->SectionMapSize)) +  if (auto EC = Reader.readSubstream(SecMapSubstream, Header->SectionMapSize))      return EC; -  if (auto EC = Reader.readStreamRef(FileInfoSubstream, Header->FileInfoSize)) +  if (auto EC = Reader.readSubstream(FileInfoSubstream, Header->FileInfoSize))      return EC;    if (auto EC = -          Reader.readStreamRef(TypeServerMapSubstream, Header->TypeServerSize)) +          Reader.readSubstream(TypeServerMapSubstream, Header->TypeServerSize))      return EC; -  if (auto EC = Reader.readStreamRef(ECSubstream, Header->ECSubstreamSize)) +  if (auto EC = Reader.readSubstream(ECSubstream, Header->ECSubstreamSize))      return EC;    if (auto EC = Reader.readArray(            DbgStreams, Header->OptionalDbgHdrSize / sizeof(ulittle16_t)))      return EC; -  if (auto EC = Modules.initialize(ModInfoSubstream, FileInfoSubstream)) +  if (auto EC = Modules.initialize(ModiSubstream.StreamData, +                                   FileInfoSubstream.StreamData))      return EC;    if (auto EC = initializeSectionContributionData()) @@ -137,8 +135,8 @@ Error DbiStream::reload() {      return make_error<RawError>(raw_error_code::corrupt_file,                                  "Found unexpected bytes in DBI Stream."); -  if (ECSubstream.getLength() > 0) { -    BinaryStreamReader ECReader(ECSubstream); +  if (!ECSubstream.empty()) { +    BinaryStreamReader ECReader(ECSubstream.StreamData);      if (auto EC = ECNames.reload(ECReader))        return EC;    } @@ -228,10 +226,10 @@ void DbiStream::visitSectionContributions(  }  Error DbiStream::initializeSectionContributionData() { -  if (SecContrSubstream.getLength() == 0) +  if (SecContrSubstream.empty())      return Error::success(); -  BinaryStreamReader SCReader(SecContrSubstream); +  BinaryStreamReader SCReader(SecContrSubstream.StreamData);    if (auto EC = SCReader.readEnum(SectionContribVersion))      return EC; @@ -302,11 +300,33 @@ Error DbiStream::initializeFpoRecords() {    return Error::success();  } +BinarySubstreamRef DbiStream::getSectionContributionData() const { +  return SecContrSubstream; +} + +BinarySubstreamRef DbiStream::getSecMapSubstreamData() const { +  return SecMapSubstream; +} + +BinarySubstreamRef DbiStream::getModiSubstreamData() const { +  return ModiSubstream; +} + +BinarySubstreamRef DbiStream::getFileInfoSubstreamData() const { +  return FileInfoSubstream; +} + +BinarySubstreamRef DbiStream::getTypeServerMapSubstreamData() const { +  return TypeServerMapSubstream; +} + +BinarySubstreamRef DbiStream::getECSubstreamData() const { return ECSubstream; } +  Error DbiStream::initializeSectionMapData() { -  if (SecMapSubstream.getLength() == 0) +  if (SecMapSubstream.empty())      return Error::success(); -  BinaryStreamReader SMReader(SecMapSubstream); +  BinaryStreamReader SMReader(SecMapSubstream.StreamData);    const SecMapHeader *Header;    if (auto EC = SMReader.readObject(Header))      return EC; diff --git a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp index e7304b444f23f..aad247ea185f2 100644 --- a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp @@ -90,10 +90,14 @@ Error DbiStreamBuilder::addModuleSourceFile(StringRef Module, StringRef File) {    if (ModIter == ModiMap.end())      return make_error<RawError>(raw_error_code::no_entry,                                  "The specified module was not found"); +  return addModuleSourceFile(*ModIter->second, File); +} + +Error DbiStreamBuilder::addModuleSourceFile(DbiModuleDescriptorBuilder &Module, +                                            StringRef File) {    uint32_t Index = SourceFileNames.size();    SourceFileNames.insert(std::make_pair(File, Index)); -  auto &ModEntry = *ModIter; -  ModEntry.second->addSourceFile(File); +  Module.addSourceFile(File);    return Error::success();  } @@ -233,6 +237,7 @@ Error DbiStreamBuilder::finalize() {      return EC;    DbiStreamHeader *H = Allocator.Allocate<DbiStreamHeader>(); +  ::memset(H, 0, sizeof(DbiStreamHeader));    H->VersionHeader = *VerHeader;    H->VersionSignature = -1;    H->Age = Age; diff --git a/lib/DebugInfo/PDB/Native/InfoStream.cpp b/lib/DebugInfo/PDB/Native/InfoStream.cpp index a3979d480bf45..21b66b3e7bcff 100644 --- a/lib/DebugInfo/PDB/Native/InfoStream.cpp +++ b/lib/DebugInfo/PDB/Native/InfoStream.cpp @@ -57,6 +57,10 @@ Error InfoStream::reload() {    uint32_t NewOffset = Reader.getOffset();    NamedStreamMapByteSize = NewOffset - Offset; +  Reader.setOffset(Offset); +  if (auto EC = Reader.readSubstream(SubNamedStreams, NamedStreamMapByteSize)) +    return EC; +    bool Stop = false;    while (!Stop && !Reader.empty()) {      PdbRaw_FeatureSig Sig; @@ -129,3 +133,7 @@ ArrayRef<PdbRaw_FeatureSig> InfoStream::getFeatureSignatures() const {  const NamedStreamMap &InfoStream::getNamedStreams() const {    return NamedStreams;  } + +BinarySubstreamRef InfoStream::getNamedStreamsBuffer() const { +  return SubNamedStreams; +} diff --git a/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp b/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp index 4186f2eb6ba01..83c56574a16e5 100644 --- a/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp +++ b/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp @@ -47,15 +47,19 @@ Error ModuleDebugStreamRef::reload() {    if (auto EC = Reader.readInteger(Signature))      return EC; -  if (auto EC = Reader.readArray(SymbolsSubstream, SymbolSize - 4)) +  if (auto EC = Reader.readSubstream(SymbolsSubstream, SymbolSize - 4))      return EC; - -  if (auto EC = Reader.readStreamRef(C11LinesSubstream, C11Size)) +  if (auto EC = Reader.readSubstream(C11LinesSubstream, C11Size)) +    return EC; +  if (auto EC = Reader.readSubstream(C13LinesSubstream, C13Size))      return EC; -  if (auto EC = Reader.readStreamRef(C13LinesSubstream, C13Size)) + +  BinaryStreamReader SymbolReader(SymbolsSubstream.StreamData); +  if (auto EC = +          SymbolReader.readArray(SymbolArray, SymbolReader.bytesRemaining()))      return EC; -  BinaryStreamReader SubsectionsReader(C13LinesSubstream); +  BinaryStreamReader SubsectionsReader(C13LinesSubstream.StreamData);    if (auto EC = SubsectionsReader.readArray(Subsections,                                              SubsectionsReader.bytesRemaining()))      return EC; @@ -63,7 +67,7 @@ Error ModuleDebugStreamRef::reload() {    uint32_t GlobalRefsSize;    if (auto EC = Reader.readInteger(GlobalRefsSize))      return EC; -  if (auto EC = Reader.readStreamRef(GlobalRefsSubstream, GlobalRefsSize)) +  if (auto EC = Reader.readSubstream(GlobalRefsSubstream, GlobalRefsSize))      return EC;    if (Reader.bytesRemaining() > 0)      return make_error<RawError>(raw_error_code::corrupt_file, @@ -72,9 +76,25 @@ Error ModuleDebugStreamRef::reload() {    return Error::success();  } +BinarySubstreamRef ModuleDebugStreamRef::getSymbolsSubstream() const { +  return SymbolsSubstream; +} + +BinarySubstreamRef ModuleDebugStreamRef::getC11LinesSubstream() const { +  return C11LinesSubstream; +} + +BinarySubstreamRef ModuleDebugStreamRef::getC13LinesSubstream() const { +  return C13LinesSubstream; +} + +BinarySubstreamRef ModuleDebugStreamRef::getGlobalRefsSubstream() const { +  return GlobalRefsSubstream; +} +  iterator_range<codeview::CVSymbolArray::Iterator>  ModuleDebugStreamRef::symbols(bool *HadError) const { -  return make_range(SymbolsSubstream.begin(HadError), SymbolsSubstream.end()); +  return make_range(SymbolArray.begin(HadError), SymbolArray.end());  }  llvm::iterator_range<ModuleDebugStreamRef::DebugSubsectionIterator> @@ -83,7 +103,7 @@ ModuleDebugStreamRef::subsections() const {  }  bool ModuleDebugStreamRef::hasDebugSubsections() const { -  return C13LinesSubstream.getLength() > 0; +  return !C13LinesSubstream.empty();  }  Error ModuleDebugStreamRef::commit() { return Error::success(); } diff --git a/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp b/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp index c7ba32b82bc6b..4f90cd9cd8ac0 100644 --- a/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp +++ b/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp @@ -23,6 +23,14 @@  using namespace llvm;  using namespace llvm::pdb; +// FIXME: This shouldn't be necessary, but if we insert the strings in any +// other order, cvdump cannot read the generated name map.  This suggests that +// we may be using the wrong hash function.  A closer inspection of the cvdump +// source code may reveal something, but for now this at least makes us work, +// even if only by accident. +static constexpr const char *OrderedStreamNames[] = {"/LinkInfo", "/names", +                                                     "/src/headerblock"}; +  NamedStreamMap::NamedStreamMap() = default;  Error NamedStreamMap::load(BinaryStreamReader &Stream) { @@ -73,9 +81,10 @@ Error NamedStreamMap::commit(BinaryStreamWriter &Writer) const {    if (auto EC = Writer.writeInteger(FinalizedInfo->StringDataBytes))      return EC; -  // Now all of the string data itself. -  for (const auto &Item : Mapping) { -    if (auto EC = Writer.writeCString(Item.getKey())) +  for (const auto &Name : OrderedStreamNames) { +    auto Item = Mapping.find(Name); +    assert(Item != Mapping.end()); +    if (auto EC = Writer.writeCString(Item->getKey()))        return EC;    } @@ -93,9 +102,12 @@ uint32_t NamedStreamMap::finalize() {    // Build the finalized hash table.    FinalizedHashTable.clear();    FinalizedInfo.emplace(); -  for (const auto &Item : Mapping) { -    FinalizedHashTable.set(FinalizedInfo->StringDataBytes, Item.getValue()); -    FinalizedInfo->StringDataBytes += Item.getKeyLength() + 1; + +  for (const auto &Name : OrderedStreamNames) { +    auto Item = Mapping.find(Name); +    assert(Item != Mapping.end()); +    FinalizedHashTable.set(FinalizedInfo->StringDataBytes, Item->getValue()); +    FinalizedInfo->StringDataBytes += Item->getKeyLength() + 1;    }    // Number of bytes of string data. diff --git a/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp index 77f832582f824..180c169ec209c 100644 --- a/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp +++ b/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp @@ -9,17 +9,24 @@  #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" +#include "llvm/ADT/STLExtras.h" +  namespace llvm {  namespace pdb {  NativeCompilandSymbol::NativeCompilandSymbol(NativeSession &Session, +                                             uint32_t SymbolId,                                               DbiModuleDescriptor MI) -    : NativeRawSymbol(Session), Module(MI) {} +    : NativeRawSymbol(Session, SymbolId), Module(MI) {}  PDB_SymType NativeCompilandSymbol::getSymTag() const {    return PDB_SymType::Compiland;  } +std::unique_ptr<NativeRawSymbol> NativeCompilandSymbol::clone() const { +  return llvm::make_unique<NativeCompilandSymbol>(Session, SymbolId, Module); +} +  bool NativeCompilandSymbol::isEditAndContinueEnabled() const {    return Module.hasECInfo();  } diff --git a/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp b/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp index 97319fd77d117..c23120041164a 100644 --- a/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp +++ b/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp @@ -34,7 +34,7 @@ NativeEnumModules::getChildAtIndex(uint32_t Index) const {      return nullptr;    return std::unique_ptr<PDBSymbol>(new PDBSymbolCompiland(        Session, std::unique_ptr<IPDBRawSymbol>(new NativeCompilandSymbol( -                   Session, Modules.getModuleDescriptor(Index))))); +                   Session, 0, Modules.getModuleDescriptor(Index)))));  }  std::unique_ptr<PDBSymbol> NativeEnumModules::getNext() { diff --git a/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp index bb52560be167a..6206155b9fb64 100644 --- a/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp +++ b/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp @@ -9,6 +9,7 @@  #include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h" +#include "llvm/ADT/STLExtras.h"  #include "llvm/DebugInfo/PDB/Native/DbiStream.h"  #include "llvm/DebugInfo/PDB/Native/InfoStream.h"  #include "llvm/DebugInfo/PDB/Native/NativeEnumModules.h" @@ -17,8 +18,12 @@  namespace llvm {  namespace pdb { -NativeExeSymbol::NativeExeSymbol(NativeSession &Session) -    : NativeRawSymbol(Session), File(Session.getPDBFile()) {} +NativeExeSymbol::NativeExeSymbol(NativeSession &Session, uint32_t SymbolId) +    : NativeRawSymbol(Session, SymbolId), File(Session.getPDBFile()) {} + +std::unique_ptr<NativeRawSymbol> NativeExeSymbol::clone() const { +  return llvm::make_unique<NativeExeSymbol>(Session, SymbolId); +}  std::unique_ptr<IPDBEnumSymbols>  NativeExeSymbol::findChildren(PDB_SymType Type) const { diff --git a/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp index 70968d4330b07..ed6db63edbabf 100644 --- a/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp +++ b/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp @@ -22,8 +22,8 @@  using namespace llvm;  using namespace llvm::pdb; -NativeRawSymbol::NativeRawSymbol(NativeSession &PDBSession) -  : Session(PDBSession) {} +NativeRawSymbol::NativeRawSymbol(NativeSession &PDBSession, uint32_t SymbolId) +    : Session(PDBSession), SymbolId(SymbolId) {}  void NativeRawSymbol::dump(raw_ostream &OS, int Indent) const {} @@ -253,9 +253,7 @@ uint32_t NativeRawSymbol::getSubTypeId() const {  std::string NativeRawSymbol::getSymbolsFileName() const { return ""; } -uint32_t NativeRawSymbol::getSymIndexId() const { -  return 0; -} +uint32_t NativeRawSymbol::getSymIndexId() const { return SymbolId; }  uint32_t NativeRawSymbol::getTargetOffset() const {    return 0; diff --git a/lib/DebugInfo/PDB/Native/NativeSession.cpp b/lib/DebugInfo/PDB/Native/NativeSession.cpp index 7e6843bceb7db..3ab381e76e628 100644 --- a/lib/DebugInfo/PDB/Native/NativeSession.cpp +++ b/lib/DebugInfo/PDB/Native/NativeSession.cpp @@ -70,12 +70,11 @@ uint64_t NativeSession::getLoadAddress() const { return 0; }  void NativeSession::setLoadAddress(uint64_t Address) {} -std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() const { -  auto RawSymbol = -      llvm::make_unique<NativeExeSymbol>(const_cast<NativeSession &>(*this)); +std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() { +  auto RawSymbol = llvm::make_unique<NativeExeSymbol>(*this, 0);    auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol)));    std::unique_ptr<PDBSymbolExe> ExeSymbol( -    static_cast<PDBSymbolExe *>(PdbSymbol.release())); +      static_cast<PDBSymbolExe *>(PdbSymbol.release()));    return ExeSymbol;  } diff --git a/lib/DebugInfo/PDB/Native/PDBFile.cpp b/lib/DebugInfo/PDB/Native/PDBFile.cpp index a9597cdf4c4d3..4f6ebb0cb3428 100644 --- a/lib/DebugInfo/PDB/Native/PDBFile.cpp +++ b/lib/DebugInfo/PDB/Native/PDBFile.cpp @@ -230,6 +230,14 @@ ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() const {    return ContainerLayout.DirectoryBlocks;  } +MSFStreamLayout PDBFile::getStreamLayout(uint32_t StreamIdx) const { +  MSFStreamLayout Result; +  auto Blocks = getStreamBlockList(StreamIdx); +  Result.Blocks.assign(Blocks.begin(), Blocks.end()); +  Result.Length = getStreamByteSize(StreamIdx); +  return Result; +} +  Expected<GlobalsStream &> PDBFile::getPDBGlobalsStream() {    if (!Globals) {      auto DbiS = getPDBDbiStream(); diff --git a/lib/DebugInfo/PDB/Native/TpiStream.cpp b/lib/DebugInfo/PDB/Native/TpiStream.cpp index 67c803d3124ec..f917ef91f6396 100644 --- a/lib/DebugInfo/PDB/Native/TpiStream.cpp +++ b/lib/DebugInfo/PDB/Native/TpiStream.cpp @@ -66,7 +66,13 @@ Error TpiStream::reload() {                                  "TPI Stream Invalid number of hash buckets.");    // The actual type records themselves come from this stream -  if (auto EC = Reader.readArray(TypeRecords, Header->TypeRecordBytes)) +  if (auto EC = +          Reader.readSubstream(TypeRecordsSubstream, Header->TypeRecordBytes)) +    return EC; + +  BinaryStreamReader RecordReader(TypeRecordsSubstream.StreamData); +  if (auto EC = +          RecordReader.readArray(TypeRecords, TypeRecordsSubstream.size()))      return EC;    // Hash indices, hash values, etc come from the hash stream. @@ -135,6 +141,10 @@ uint16_t TpiStream::getTypeHashStreamAuxIndex() const {  uint32_t TpiStream::getNumHashBuckets() const { return Header->NumHashBuckets; }  uint32_t TpiStream::getHashKeySize() const { return Header->HashKeySize; } +BinarySubstreamRef TpiStream::getTypeRecordsSubstream() const { +  return TypeRecordsSubstream; +} +  FixedStreamArray<support::ulittle32_t> TpiStream::getHashValues() const {    return HashValues;  } | 
