summaryrefslogtreecommitdiff
path: root/COFF/PDB.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'COFF/PDB.cpp')
-rw-r--r--COFF/PDB.cpp426
1 files changed, 294 insertions, 132 deletions
diff --git a/COFF/PDB.cpp b/COFF/PDB.cpp
index 508f59e3af1fd..89462da934546 100644
--- a/COFF/PDB.cpp
+++ b/COFF/PDB.cpp
@@ -14,28 +14,29 @@
#include "SymbolTable.h"
#include "Symbols.h"
#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
-#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
-#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/MSF/MSFCommon.h"
+#include "llvm/DebugInfo/PDB/GenericError.h"
#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
-#include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
+#include "llvm/DebugInfo/PDB/PDB.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/Endian.h"
@@ -53,8 +54,81 @@ using llvm::object::coff_section;
static ExitOnError ExitOnErr;
+namespace {
+/// Map from type index and item index in a type server PDB to the
+/// corresponding index in the destination PDB.
+struct CVIndexMap {
+ SmallVector<TypeIndex, 0> TPIMap;
+ SmallVector<TypeIndex, 0> IPIMap;
+ bool IsTypeServerMap = false;
+};
+
+class PDBLinker {
+public:
+ PDBLinker(SymbolTable *Symtab)
+ : Alloc(), Symtab(Symtab), Builder(Alloc), TypeTable(Alloc),
+ IDTable(Alloc) {}
+
+ /// Emit the basic PDB structure: initial streams, headers, etc.
+ void initialize(const llvm::codeview::DebugInfo *DI);
+
+ /// Link CodeView from each object file in the symbol table into the PDB.
+ void addObjectsToPDB();
+
+ /// Link CodeView from a single object file into the PDB.
+ void addObjectFile(ObjectFile *File);
+
+ /// Produce a mapping from the type and item indices used in the object
+ /// file to those in the destination PDB.
+ ///
+ /// If the object file uses a type server PDB (compiled with /Zi), merge TPI
+ /// and IPI from the type server PDB and return a map for it. Each unique type
+ /// server PDB is merged at most once, so this may return an existing index
+ /// mapping.
+ ///
+ /// If the object does not use a type server PDB (compiled with /Z7), we merge
+ /// all the type and item records from the .debug$S stream and fill in the
+ /// caller-provided ObjectIndexMap.
+ const CVIndexMap &mergeDebugT(ObjectFile *File, CVIndexMap &ObjectIndexMap);
+
+ const CVIndexMap &maybeMergeTypeServerPDB(ObjectFile *File,
+ TypeServer2Record &TS);
+
+ /// Add the section map and section contributions to the PDB.
+ void addSections(ArrayRef<uint8_t> SectionTable);
+
+ /// Write the PDB to disk.
+ void commit();
+
+private:
+ BumpPtrAllocator Alloc;
+
+ SymbolTable *Symtab;
+
+ pdb::PDBFileBuilder Builder;
+
+ /// Type records that will go into the PDB TPI stream.
+ TypeTableBuilder TypeTable;
+
+ /// Item records that will go into the PDB IPI stream.
+ TypeTableBuilder IDTable;
+
+ /// PDBs use a single global string table for filenames in the file checksum
+ /// table.
+ DebugStringTableSubsection PDBStrTab;
+
+ llvm::SmallString<128> NativePath;
+
+ std::vector<pdb::SecMapEntry> SectionMap;
+
+ /// Type index mappings of type server PDBs that we've loaded so far.
+ std::map<GUID, CVIndexMap> TypeServerIndexMappings;
+};
+}
+
// Returns a list of all SectionChunks.
-static void addSectionContribs(SymbolTable *Symtab, pdb::DbiStreamBuilder &DbiBuilder) {
+static void addSectionContribs(SymbolTable *Symtab,
+ pdb::DbiStreamBuilder &DbiBuilder) {
for (Chunk *C : Symtab->getChunks())
if (auto *SC = dyn_cast<SectionChunk>(C))
DbiBuilder.addSectionContrib(SC->File->ModuleDBI, SC->Header);
@@ -96,24 +170,115 @@ static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder,
});
}
-static void mergeDebugT(ObjectFile *File,
- TypeTableBuilder &IDTable,
- TypeTableBuilder &TypeTable,
- SmallVectorImpl<TypeIndex> &TypeIndexMap,
- pdb::PDBTypeServerHandler &Handler) {
+static Optional<TypeServer2Record>
+maybeReadTypeServerRecord(CVTypeArray &Types) {
+ auto I = Types.begin();
+ if (I == Types.end())
+ return None;
+ const CVType &Type = *I;
+ if (Type.kind() != LF_TYPESERVER2)
+ return None;
+ TypeServer2Record TS;
+ if (auto EC = TypeDeserializer::deserializeAs(const_cast<CVType &>(Type), TS))
+ fatal(EC, "error reading type server record");
+ return std::move(TS);
+}
+
+const CVIndexMap &PDBLinker::mergeDebugT(ObjectFile *File,
+ CVIndexMap &ObjectIndexMap) {
ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
if (Data.empty())
- return;
+ return ObjectIndexMap;
BinaryByteStream Stream(Data, support::little);
CVTypeArray Types;
BinaryStreamReader Reader(Stream);
- Handler.addSearchPath(sys::path::parent_path(File->getName()));
if (auto EC = Reader.readArray(Types, Reader.getLength()))
fatal(EC, "Reader::readArray failed");
+
+ // Look through type servers. If we've already seen this type server, don't
+ // merge any type information.
+ if (Optional<TypeServer2Record> TS = maybeReadTypeServerRecord(Types))
+ return maybeMergeTypeServerPDB(File, *TS);
+
+ // This is a /Z7 object. Fill in the temporary, caller-provided
+ // ObjectIndexMap.
if (auto Err = mergeTypeAndIdRecords(IDTable, TypeTable,
- TypeIndexMap, &Handler, Types))
- fatal(Err, "codeview::mergeTypeStreams failed");
+ ObjectIndexMap.TPIMap, Types))
+ fatal(Err, "codeview::mergeTypeAndIdRecords failed");
+ return ObjectIndexMap;
+}
+
+static Expected<std::unique_ptr<pdb::NativeSession>>
+tryToLoadPDB(const GUID &GuidFromObj, StringRef TSPath) {
+ std::unique_ptr<pdb::IPDBSession> ThisSession;
+ if (auto EC =
+ pdb::loadDataForPDB(pdb::PDB_ReaderType::Native, TSPath, ThisSession))
+ return std::move(EC);
+
+ std::unique_ptr<pdb::NativeSession> NS(
+ static_cast<pdb::NativeSession *>(ThisSession.release()));
+ pdb::PDBFile &File = NS->getPDBFile();
+ auto ExpectedInfo = File.getPDBInfoStream();
+ // All PDB Files should have an Info stream.
+ if (!ExpectedInfo)
+ return ExpectedInfo.takeError();
+
+ // Just because a file with a matching name was found and it was an actual
+ // PDB file doesn't mean it matches. For it to match the InfoStream's GUID
+ // must match the GUID specified in the TypeServer2 record.
+ if (ExpectedInfo->getGuid() != GuidFromObj)
+ return make_error<pdb::GenericError>(
+ pdb::generic_error_code::type_server_not_found, TSPath);
+
+ return std::move(NS);
+}
+
+const CVIndexMap &PDBLinker::maybeMergeTypeServerPDB(ObjectFile *File,
+ TypeServer2Record &TS) {
+ // First, check if we already loaded a PDB with this GUID. Return the type
+ // index mapping if we have it.
+ auto Insertion = TypeServerIndexMappings.insert({TS.getGuid(), CVIndexMap()});
+ CVIndexMap &IndexMap = Insertion.first->second;
+ if (!Insertion.second)
+ return IndexMap;
+
+ // Mark this map as a type server map.
+ IndexMap.IsTypeServerMap = true;
+
+ // Check for a PDB at:
+ // 1. The given file path
+ // 2. Next to the object file or archive file
+ auto ExpectedSession = tryToLoadPDB(TS.getGuid(), TS.getName());
+ if (!ExpectedSession) {
+ consumeError(ExpectedSession.takeError());
+ StringRef LocalPath =
+ !File->ParentName.empty() ? File->ParentName : File->getName();
+ SmallString<128> Path = sys::path::parent_path(LocalPath);
+ sys::path::append(
+ Path, sys::path::filename(TS.getName(), sys::path::Style::windows));
+ ExpectedSession = tryToLoadPDB(TS.getGuid(), Path);
+ }
+ if (auto E = ExpectedSession.takeError())
+ fatal(E, "Type server PDB was not found");
+
+ // Merge TPI first, because the IPI stream will reference type indices.
+ auto ExpectedTpi = (*ExpectedSession)->getPDBFile().getPDBTpiStream();
+ if (auto E = ExpectedTpi.takeError())
+ fatal(E, "Type server does not have TPI stream");
+ if (auto Err = mergeTypeRecords(TypeTable, IndexMap.TPIMap,
+ ExpectedTpi->typeArray()))
+ fatal(Err, "codeview::mergeTypeRecords failed");
+
+ // Merge IPI.
+ auto ExpectedIpi = (*ExpectedSession)->getPDBFile().getPDBIpiStream();
+ if (auto E = ExpectedIpi.takeError())
+ fatal(E, "Type server does not have TPI stream");
+ if (auto Err = mergeIdRecords(IDTable, IndexMap.TPIMap, IndexMap.IPIMap,
+ ExpectedIpi->typeArray()))
+ fatal(Err, "codeview::mergeIdRecords failed");
+
+ return IndexMap;
}
static bool remapTypeIndex(TypeIndex &TI, ArrayRef<TypeIndex> TypeIndexMap) {
@@ -127,16 +292,22 @@ static bool remapTypeIndex(TypeIndex &TI, ArrayRef<TypeIndex> TypeIndexMap) {
static void remapTypesInSymbolRecord(ObjectFile *File,
MutableArrayRef<uint8_t> Contents,
- ArrayRef<TypeIndex> TypeIndexMap,
+ const CVIndexMap &IndexMap,
ArrayRef<TiReference> TypeRefs) {
for (const TiReference &Ref : TypeRefs) {
unsigned ByteSize = Ref.Count * sizeof(TypeIndex);
if (Contents.size() < Ref.Offset + ByteSize)
fatal("symbol record too short");
+
+ // This can be an item index or a type index. Choose the appropriate map.
+ ArrayRef<TypeIndex> TypeOrItemMap = IndexMap.TPIMap;
+ if (Ref.Kind == TiRefKind::IndexRef && IndexMap.IsTypeServerMap)
+ TypeOrItemMap = IndexMap.IPIMap;
+
MutableArrayRef<TypeIndex> TIs(
reinterpret_cast<TypeIndex *>(Contents.data() + Ref.Offset), Ref.Count);
for (TypeIndex &TI : TIs) {
- if (!remapTypeIndex(TI, TypeIndexMap)) {
+ if (!remapTypeIndex(TI, TypeOrItemMap)) {
TI = TypeIndex(SimpleTypeKind::NotTranslated);
log("ignoring symbol record in " + File->getName() +
" with bad type index 0x" + utohexstr(TI.getIndex()));
@@ -241,7 +412,7 @@ static void scopeStackClose(SmallVectorImpl<SymbolScope> &Stack,
}
static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjectFile *File,
- ArrayRef<TypeIndex> TypeIndexMap,
+ const CVIndexMap &IndexMap,
BinaryStreamRef SymData) {
// FIXME: Improve error recovery by warning and skipping records when
// possible.
@@ -264,7 +435,7 @@ static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjectFile *File,
// Re-map all the type index references.
MutableArrayRef<uint8_t> Contents =
NewData.drop_front(sizeof(RecordPrefix));
- remapTypesInSymbolRecord(File, Contents, TypeIndexMap, TypeRefs);
+ remapTypesInSymbolRecord(File, Contents, IndexMap, TypeRefs);
// Fill in "Parent" and "End" fields by maintaining a stack of scopes.
CVSymbol NewSym(Sym.kind(), NewData);
@@ -289,110 +460,105 @@ static ArrayRef<uint8_t> relocateDebugChunk(BumpPtrAllocator &Alloc,
".debug$S");
}
-// Add all object files to the PDB. Merge .debug$T sections into IpiData and
-// TpiData.
-static void addObjectsToPDB(BumpPtrAllocator &Alloc, SymbolTable *Symtab,
- pdb::PDBFileBuilder &Builder,
- TypeTableBuilder &TypeTable,
- TypeTableBuilder &IDTable) {
- // Follow type servers. If the same type server is encountered more than
- // once for this instance of `PDBTypeServerHandler` (for example if many
- // object files reference the same TypeServer), the types from the
- // TypeServer will only be visited once.
- pdb::PDBTypeServerHandler Handler;
-
- // PDBs use a single global string table for filenames in the file checksum
- // table.
- auto PDBStrTab = std::make_shared<DebugStringTableSubsection>();
-
- // Visit all .debug$T sections to add them to Builder.
- for (ObjectFile *File : Symtab->ObjectFiles) {
- // Add a module descriptor for every object file. We need to put an absolute
- // path to the object into the PDB. If this is a plain object, we make its
- // path absolute. If it's an object in an archive, we make the archive path
- // absolute.
- bool InArchive = !File->ParentName.empty();
- SmallString<128> Path = InArchive ? File->ParentName : File->getName();
- sys::fs::make_absolute(Path);
- sys::path::native(Path, llvm::sys::path::Style::windows);
- StringRef Name = InArchive ? File->getName() : StringRef(Path);
-
- File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name));
- File->ModuleDBI->setObjFileName(Path);
-
- // Before we can process symbol substreams from .debug$S, we need to process
- // type information, file checksums, and the string table. Add type info to
- // the PDB first, so that we can get the map from object file type and item
- // indices to PDB type and item indices.
- SmallVector<TypeIndex, 128> TypeIndexMap;
- mergeDebugT(File, IDTable, TypeTable, TypeIndexMap, Handler);
-
- // Now do all line info.
- for (SectionChunk *DebugChunk : File->getDebugChunks()) {
- if (!DebugChunk->isLive() || DebugChunk->getSectionName() != ".debug$S")
- continue;
+void PDBLinker::addObjectFile(ObjectFile *File) {
+ // Add a module descriptor for every object file. We need to put an absolute
+ // path to the object into the PDB. If this is a plain object, we make its
+ // path absolute. If it's an object in an archive, we make the archive path
+ // absolute.
+ bool InArchive = !File->ParentName.empty();
+ SmallString<128> Path = InArchive ? File->ParentName : File->getName();
+ sys::fs::make_absolute(Path);
+ sys::path::native(Path, sys::path::Style::windows);
+ StringRef Name = InArchive ? File->getName() : StringRef(Path);
+
+ File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name));
+ File->ModuleDBI->setObjFileName(Path);
+
+ // Before we can process symbol substreams from .debug$S, we need to process
+ // type information, file checksums, and the string table. Add type info to
+ // the PDB first, so that we can get the map from object file type and item
+ // indices to PDB type and item indices.
+ CVIndexMap ObjectIndexMap;
+ const CVIndexMap &IndexMap = mergeDebugT(File, ObjectIndexMap);
+
+ // Now do all live .debug$S sections.
+ for (SectionChunk *DebugChunk : File->getDebugChunks()) {
+ if (!DebugChunk->isLive() || DebugChunk->getSectionName() != ".debug$S")
+ continue;
- ArrayRef<uint8_t> RelocatedDebugContents =
- relocateDebugChunk(Alloc, DebugChunk);
- if (RelocatedDebugContents.empty())
- continue;
+ ArrayRef<uint8_t> RelocatedDebugContents =
+ relocateDebugChunk(Alloc, DebugChunk);
+ if (RelocatedDebugContents.empty())
+ continue;
- DebugSubsectionArray Subsections;
- BinaryStreamReader Reader(RelocatedDebugContents, support::little);
- ExitOnErr(Reader.readArray(Subsections, RelocatedDebugContents.size()));
-
- DebugStringTableSubsectionRef CVStrTab;
- DebugChecksumsSubsectionRef Checksums;
- for (const DebugSubsectionRecord &SS : Subsections) {
- switch (SS.kind()) {
- case DebugSubsectionKind::StringTable:
- ExitOnErr(CVStrTab.initialize(SS.getRecordData()));
- break;
- case DebugSubsectionKind::FileChecksums:
- ExitOnErr(Checksums.initialize(SS.getRecordData()));
- break;
- case DebugSubsectionKind::Lines:
- // We can add the relocated line table directly to the PDB without
- // modification because the file checksum offsets will stay the same.
- File->ModuleDBI->addDebugSubsection(SS);
- break;
- case DebugSubsectionKind::Symbols:
- mergeSymbolRecords(Alloc, File, TypeIndexMap, SS.getRecordData());
- break;
- default:
- // FIXME: Process the rest of the subsections.
- break;
- }
+ DebugSubsectionArray Subsections;
+ BinaryStreamReader Reader(RelocatedDebugContents, support::little);
+ ExitOnErr(Reader.readArray(Subsections, RelocatedDebugContents.size()));
+
+ DebugStringTableSubsectionRef CVStrTab;
+ DebugChecksumsSubsectionRef Checksums;
+ for (const DebugSubsectionRecord &SS : Subsections) {
+ switch (SS.kind()) {
+ case DebugSubsectionKind::StringTable:
+ ExitOnErr(CVStrTab.initialize(SS.getRecordData()));
+ break;
+ case DebugSubsectionKind::FileChecksums:
+ ExitOnErr(Checksums.initialize(SS.getRecordData()));
+ break;
+ case DebugSubsectionKind::Lines:
+ // We can add the relocated line table directly to the PDB without
+ // modification because the file checksum offsets will stay the same.
+ File->ModuleDBI->addDebugSubsection(SS);
+ break;
+ case DebugSubsectionKind::Symbols:
+ mergeSymbolRecords(Alloc, File, IndexMap, SS.getRecordData());
+ break;
+ default:
+ // FIXME: Process the rest of the subsections.
+ break;
}
+ }
- if (Checksums.valid()) {
- // Make a new file checksum table that refers to offsets in the PDB-wide
- // string table. Generally the string table subsection appears after the
- // checksum table, so we have to do this after looping over all the
- // subsections.
- if (!CVStrTab.valid())
- fatal(".debug$S sections must have both a string table subsection "
- "and a checksum subsection table or neither");
- auto NewChecksums =
- make_unique<DebugChecksumsSubsection>(*PDBStrTab);
- for (FileChecksumEntry &FC : Checksums) {
- StringRef FileName = ExitOnErr(CVStrTab.getString(FC.FileNameOffset));
- ExitOnErr(Builder.getDbiBuilder().addModuleSourceFile(
- *File->ModuleDBI, FileName));
- NewChecksums->addChecksum(FileName, FC.Kind, FC.Checksum);
- }
- File->ModuleDBI->addDebugSubsection(std::move(NewChecksums));
+ if (Checksums.valid()) {
+ // Make a new file checksum table that refers to offsets in the PDB-wide
+ // string table. Generally the string table subsection appears after the
+ // checksum table, so we have to do this after looping over all the
+ // subsections.
+ if (!CVStrTab.valid())
+ fatal(".debug$S sections must have both a string table subsection "
+ "and a checksum subsection table or neither");
+ auto NewChecksums = make_unique<DebugChecksumsSubsection>(PDBStrTab);
+ for (FileChecksumEntry &FC : Checksums) {
+ StringRef FileName = ExitOnErr(CVStrTab.getString(FC.FileNameOffset));
+ ExitOnErr(Builder.getDbiBuilder().addModuleSourceFile(*File->ModuleDBI,
+ FileName));
+ NewChecksums->addChecksum(FileName, FC.Kind, FC.Checksum);
}
+ File->ModuleDBI->addDebugSubsection(std::move(NewChecksums));
}
}
+}
+
+// Add all object files to the PDB. Merge .debug$T sections into IpiData and
+// TpiData.
+void PDBLinker::addObjectsToPDB() {
+ for (ObjectFile *File : Symtab->ObjectFiles)
+ addObjectFile(File);
- Builder.getStringTableBuilder().setStrings(*PDBStrTab);
+ Builder.getStringTableBuilder().setStrings(PDBStrTab);
// Construct TPI stream contents.
addTypeInfo(Builder.getTpiBuilder(), TypeTable);
// Construct IPI stream contents.
addTypeInfo(Builder.getIpiBuilder(), IDTable);
+
+ // Add public and symbol records stream.
+
+ // For now we don't actually write any thing useful to the publics stream, but
+ // the act of "getting" it also creates it lazily so that we write an empty
+ // stream.
+ (void)Builder.getPublicsBuilder();
}
static void addLinkerModuleSymbols(StringRef Path,
@@ -423,7 +589,7 @@ static void addLinkerModuleSymbols(StringRef Path,
std::string ArgStr = llvm::join(Args, " ");
EBS.Fields.push_back("cwd");
SmallString<64> cwd;
- llvm::sys::fs::current_path(cwd);
+ sys::fs::current_path(cwd);
EBS.Fields.push_back(cwd);
EBS.Fields.push_back("exe");
EBS.Fields.push_back(Config->Argv[0]);
@@ -442,8 +608,14 @@ static void addLinkerModuleSymbols(StringRef Path,
// Creates a PDB file.
void coff::createPDB(SymbolTable *Symtab, ArrayRef<uint8_t> SectionTable,
const llvm::codeview::DebugInfo *DI) {
- BumpPtrAllocator Alloc;
- pdb::PDBFileBuilder Builder(Alloc);
+ PDBLinker PDB(Symtab);
+ PDB.initialize(DI);
+ PDB.addObjectsToPDB();
+ PDB.addSections(SectionTable);
+ PDB.commit();
+}
+
+void PDBLinker::initialize(const llvm::codeview::DebugInfo *DI) {
ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize
// Create streams in MSF for predefined streams, namely
@@ -455,12 +627,7 @@ void coff::createPDB(SymbolTable *Symtab, ArrayRef<uint8_t> SectionTable,
auto &InfoBuilder = Builder.getInfoBuilder();
InfoBuilder.setAge(DI ? DI->PDB70.Age : 0);
- llvm::SmallString<128> NativePath(Config->PDBPath.begin(),
- Config->PDBPath.end());
- llvm::sys::fs::make_absolute(NativePath);
- llvm::sys::path::native(NativePath, llvm::sys::path::Style::windows);
-
- pdb::PDB_UniqueId uuid{};
+ GUID uuid{};
if (DI)
memcpy(&uuid, &DI->PDB70.Signature, sizeof(uuid));
InfoBuilder.setGuid(uuid);
@@ -471,32 +638,25 @@ void coff::createPDB(SymbolTable *Symtab, ArrayRef<uint8_t> SectionTable,
pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
DbiBuilder.setVersionHeader(pdb::PdbDbiV70);
ExitOnErr(DbiBuilder.addDbgStream(pdb::DbgHeaderType::NewFPO, {}));
+}
- // It's not entirely clear what this is, but the * Linker * module uses it.
- uint32_t PdbFilePathNI = DbiBuilder.addECName(NativePath);
-
- TypeTableBuilder TypeTable(BAlloc);
- TypeTableBuilder IDTable(BAlloc);
- addObjectsToPDB(Alloc, Symtab, Builder, TypeTable, IDTable);
-
- // Add public and symbol records stream.
-
- // For now we don't actually write any thing useful to the publics stream, but
- // the act of "getting" it also creates it lazily so that we write an empty
- // stream.
- (void)Builder.getPublicsBuilder();
-
+void PDBLinker::addSections(ArrayRef<uint8_t> SectionTable) {
// Add Section Contributions.
+ pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
addSectionContribs(Symtab, DbiBuilder);
// Add Section Map stream.
ArrayRef<object::coff_section> Sections = {
(const object::coff_section *)SectionTable.data(),
SectionTable.size() / sizeof(object::coff_section)};
- std::vector<pdb::SecMapEntry> SectionMap =
- pdb::DbiStreamBuilder::createSectionMap(Sections);
+ SectionMap = pdb::DbiStreamBuilder::createSectionMap(Sections);
DbiBuilder.setSectionMap(SectionMap);
+ // It's not entirely clear what this is, but the * Linker * module uses it.
+ NativePath = Config->PDBPath;
+ sys::fs::make_absolute(NativePath);
+ sys::path::native(NativePath, sys::path::Style::windows);
+ uint32_t PdbFilePathNI = DbiBuilder.addECName(NativePath);
auto &LinkerModule = ExitOnErr(DbiBuilder.addModuleInfo("* Linker *"));
LinkerModule.setPdbFilePathNI(PdbFilePathNI);
addLinkerModuleSymbols(NativePath, LinkerModule, Alloc);
@@ -504,7 +664,9 @@ void coff::createPDB(SymbolTable *Symtab, ArrayRef<uint8_t> SectionTable,
// Add COFF section header stream.
ExitOnErr(
DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable));
+}
+void PDBLinker::commit() {
// Write to a file.
ExitOnErr(Builder.commit(Config->PDBPath));
}