1*6b6b8c4fSAdrian McCarthy //===- DbiStreamBuilder.cpp - PDB Dbi Stream Creation -----------*- C++ -*-===// 2*6b6b8c4fSAdrian McCarthy // 3*6b6b8c4fSAdrian McCarthy // The LLVM Compiler Infrastructure 4*6b6b8c4fSAdrian McCarthy // 5*6b6b8c4fSAdrian McCarthy // This file is distributed under the University of Illinois Open Source 6*6b6b8c4fSAdrian McCarthy // License. See LICENSE.TXT for details. 7*6b6b8c4fSAdrian McCarthy // 8*6b6b8c4fSAdrian McCarthy //===----------------------------------------------------------------------===// 9*6b6b8c4fSAdrian McCarthy 10*6b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" 11*6b6b8c4fSAdrian McCarthy 12*6b6b8c4fSAdrian McCarthy #include "llvm/ADT/ArrayRef.h" 13*6b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/MSF/MSFBuilder.h" 14*6b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/MSF/MappedBlockStream.h" 15*6b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/MSF/StreamWriter.h" 16*6b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/DbiStream.h" 17*6b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/RawError.h" 18*6b6b8c4fSAdrian McCarthy #include "llvm/Object/COFF.h" 19*6b6b8c4fSAdrian McCarthy #include "llvm/Support/COFF.h" 20*6b6b8c4fSAdrian McCarthy 21*6b6b8c4fSAdrian McCarthy using namespace llvm; 22*6b6b8c4fSAdrian McCarthy using namespace llvm::codeview; 23*6b6b8c4fSAdrian McCarthy using namespace llvm::msf; 24*6b6b8c4fSAdrian McCarthy using namespace llvm::pdb; 25*6b6b8c4fSAdrian McCarthy 26*6b6b8c4fSAdrian McCarthy namespace { 27*6b6b8c4fSAdrian McCarthy class ModiSubstreamBuilder {}; 28*6b6b8c4fSAdrian McCarthy } 29*6b6b8c4fSAdrian McCarthy 30*6b6b8c4fSAdrian McCarthy DbiStreamBuilder::DbiStreamBuilder(msf::MSFBuilder &Msf) 31*6b6b8c4fSAdrian McCarthy : Msf(Msf), Allocator(Msf.getAllocator()), Age(1), BuildNumber(0), 32*6b6b8c4fSAdrian McCarthy PdbDllVersion(0), PdbDllRbld(0), Flags(0), MachineType(PDB_Machine::x86), 33*6b6b8c4fSAdrian McCarthy Header(nullptr), DbgStreams((int)DbgHeaderType::Max) {} 34*6b6b8c4fSAdrian McCarthy 35*6b6b8c4fSAdrian McCarthy void DbiStreamBuilder::setVersionHeader(PdbRaw_DbiVer V) { VerHeader = V; } 36*6b6b8c4fSAdrian McCarthy 37*6b6b8c4fSAdrian McCarthy void DbiStreamBuilder::setAge(uint32_t A) { Age = A; } 38*6b6b8c4fSAdrian McCarthy 39*6b6b8c4fSAdrian McCarthy void DbiStreamBuilder::setBuildNumber(uint16_t B) { BuildNumber = B; } 40*6b6b8c4fSAdrian McCarthy 41*6b6b8c4fSAdrian McCarthy void DbiStreamBuilder::setPdbDllVersion(uint16_t V) { PdbDllVersion = V; } 42*6b6b8c4fSAdrian McCarthy 43*6b6b8c4fSAdrian McCarthy void DbiStreamBuilder::setPdbDllRbld(uint16_t R) { PdbDllRbld = R; } 44*6b6b8c4fSAdrian McCarthy 45*6b6b8c4fSAdrian McCarthy void DbiStreamBuilder::setFlags(uint16_t F) { Flags = F; } 46*6b6b8c4fSAdrian McCarthy 47*6b6b8c4fSAdrian McCarthy void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; } 48*6b6b8c4fSAdrian McCarthy 49*6b6b8c4fSAdrian McCarthy void DbiStreamBuilder::setSectionContribs(ArrayRef<SectionContrib> Arr) { 50*6b6b8c4fSAdrian McCarthy SectionContribs = Arr; 51*6b6b8c4fSAdrian McCarthy } 52*6b6b8c4fSAdrian McCarthy 53*6b6b8c4fSAdrian McCarthy void DbiStreamBuilder::setSectionMap(ArrayRef<SecMapEntry> SecMap) { 54*6b6b8c4fSAdrian McCarthy SectionMap = SecMap; 55*6b6b8c4fSAdrian McCarthy } 56*6b6b8c4fSAdrian McCarthy 57*6b6b8c4fSAdrian McCarthy Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type, 58*6b6b8c4fSAdrian McCarthy ArrayRef<uint8_t> Data) { 59*6b6b8c4fSAdrian McCarthy if (DbgStreams[(int)Type].StreamNumber) 60*6b6b8c4fSAdrian McCarthy return make_error<RawError>(raw_error_code::duplicate_entry, 61*6b6b8c4fSAdrian McCarthy "The specified stream type already exists"); 62*6b6b8c4fSAdrian McCarthy auto ExpectedIndex = Msf.addStream(Data.size()); 63*6b6b8c4fSAdrian McCarthy if (!ExpectedIndex) 64*6b6b8c4fSAdrian McCarthy return ExpectedIndex.takeError(); 65*6b6b8c4fSAdrian McCarthy uint32_t Index = std::move(*ExpectedIndex); 66*6b6b8c4fSAdrian McCarthy DbgStreams[(int)Type].Data = Data; 67*6b6b8c4fSAdrian McCarthy DbgStreams[(int)Type].StreamNumber = Index; 68*6b6b8c4fSAdrian McCarthy return Error::success(); 69*6b6b8c4fSAdrian McCarthy } 70*6b6b8c4fSAdrian McCarthy 71*6b6b8c4fSAdrian McCarthy uint32_t DbiStreamBuilder::calculateSerializedLength() const { 72*6b6b8c4fSAdrian McCarthy // For now we only support serializing the header. 73*6b6b8c4fSAdrian McCarthy return sizeof(DbiStreamHeader) + calculateFileInfoSubstreamSize() + 74*6b6b8c4fSAdrian McCarthy calculateModiSubstreamSize() + calculateSectionContribsStreamSize() + 75*6b6b8c4fSAdrian McCarthy calculateSectionMapStreamSize() + calculateDbgStreamsSize(); 76*6b6b8c4fSAdrian McCarthy } 77*6b6b8c4fSAdrian McCarthy 78*6b6b8c4fSAdrian McCarthy Error DbiStreamBuilder::addModuleInfo(StringRef ObjFile, StringRef Module) { 79*6b6b8c4fSAdrian McCarthy auto Entry = llvm::make_unique<ModuleInfo>(); 80*6b6b8c4fSAdrian McCarthy ModuleInfo *M = Entry.get(); 81*6b6b8c4fSAdrian McCarthy Entry->Mod = Module; 82*6b6b8c4fSAdrian McCarthy Entry->Obj = ObjFile; 83*6b6b8c4fSAdrian McCarthy auto Result = ModuleInfos.insert(std::make_pair(Module, std::move(Entry))); 84*6b6b8c4fSAdrian McCarthy if (!Result.second) 85*6b6b8c4fSAdrian McCarthy return make_error<RawError>(raw_error_code::duplicate_entry, 86*6b6b8c4fSAdrian McCarthy "The specified module already exists"); 87*6b6b8c4fSAdrian McCarthy ModuleInfoList.push_back(M); 88*6b6b8c4fSAdrian McCarthy return Error::success(); 89*6b6b8c4fSAdrian McCarthy } 90*6b6b8c4fSAdrian McCarthy 91*6b6b8c4fSAdrian McCarthy Error DbiStreamBuilder::addModuleSourceFile(StringRef Module, StringRef File) { 92*6b6b8c4fSAdrian McCarthy auto ModIter = ModuleInfos.find(Module); 93*6b6b8c4fSAdrian McCarthy if (ModIter == ModuleInfos.end()) 94*6b6b8c4fSAdrian McCarthy return make_error<RawError>(raw_error_code::no_entry, 95*6b6b8c4fSAdrian McCarthy "The specified module was not found"); 96*6b6b8c4fSAdrian McCarthy uint32_t Index = SourceFileNames.size(); 97*6b6b8c4fSAdrian McCarthy SourceFileNames.insert(std::make_pair(File, Index)); 98*6b6b8c4fSAdrian McCarthy auto &ModEntry = *ModIter; 99*6b6b8c4fSAdrian McCarthy ModEntry.second->SourceFiles.push_back(File); 100*6b6b8c4fSAdrian McCarthy return Error::success(); 101*6b6b8c4fSAdrian McCarthy } 102*6b6b8c4fSAdrian McCarthy 103*6b6b8c4fSAdrian McCarthy uint32_t DbiStreamBuilder::calculateModiSubstreamSize() const { 104*6b6b8c4fSAdrian McCarthy uint32_t Size = 0; 105*6b6b8c4fSAdrian McCarthy for (const auto &M : ModuleInfoList) { 106*6b6b8c4fSAdrian McCarthy Size += sizeof(ModuleInfoHeader); 107*6b6b8c4fSAdrian McCarthy Size += M->Mod.size() + 1; 108*6b6b8c4fSAdrian McCarthy Size += M->Obj.size() + 1; 109*6b6b8c4fSAdrian McCarthy } 110*6b6b8c4fSAdrian McCarthy return alignTo(Size, sizeof(uint32_t)); 111*6b6b8c4fSAdrian McCarthy } 112*6b6b8c4fSAdrian McCarthy 113*6b6b8c4fSAdrian McCarthy uint32_t DbiStreamBuilder::calculateSectionContribsStreamSize() const { 114*6b6b8c4fSAdrian McCarthy if (SectionContribs.empty()) 115*6b6b8c4fSAdrian McCarthy return 0; 116*6b6b8c4fSAdrian McCarthy return sizeof(enum PdbRaw_DbiSecContribVer) + 117*6b6b8c4fSAdrian McCarthy sizeof(SectionContribs[0]) * SectionContribs.size(); 118*6b6b8c4fSAdrian McCarthy } 119*6b6b8c4fSAdrian McCarthy 120*6b6b8c4fSAdrian McCarthy uint32_t DbiStreamBuilder::calculateSectionMapStreamSize() const { 121*6b6b8c4fSAdrian McCarthy if (SectionMap.empty()) 122*6b6b8c4fSAdrian McCarthy return 0; 123*6b6b8c4fSAdrian McCarthy return sizeof(SecMapHeader) + sizeof(SecMapEntry) * SectionMap.size(); 124*6b6b8c4fSAdrian McCarthy } 125*6b6b8c4fSAdrian McCarthy 126*6b6b8c4fSAdrian McCarthy uint32_t DbiStreamBuilder::calculateFileInfoSubstreamSize() const { 127*6b6b8c4fSAdrian McCarthy uint32_t Size = 0; 128*6b6b8c4fSAdrian McCarthy Size += sizeof(ulittle16_t); // NumModules 129*6b6b8c4fSAdrian McCarthy Size += sizeof(ulittle16_t); // NumSourceFiles 130*6b6b8c4fSAdrian McCarthy Size += ModuleInfoList.size() * sizeof(ulittle16_t); // ModIndices 131*6b6b8c4fSAdrian McCarthy Size += ModuleInfoList.size() * sizeof(ulittle16_t); // ModFileCounts 132*6b6b8c4fSAdrian McCarthy uint32_t NumFileInfos = 0; 133*6b6b8c4fSAdrian McCarthy for (const auto &M : ModuleInfoList) 134*6b6b8c4fSAdrian McCarthy NumFileInfos += M->SourceFiles.size(); 135*6b6b8c4fSAdrian McCarthy Size += NumFileInfos * sizeof(ulittle32_t); // FileNameOffsets 136*6b6b8c4fSAdrian McCarthy Size += calculateNamesBufferSize(); 137*6b6b8c4fSAdrian McCarthy return alignTo(Size, sizeof(uint32_t)); 138*6b6b8c4fSAdrian McCarthy } 139*6b6b8c4fSAdrian McCarthy 140*6b6b8c4fSAdrian McCarthy uint32_t DbiStreamBuilder::calculateNamesBufferSize() const { 141*6b6b8c4fSAdrian McCarthy uint32_t Size = 0; 142*6b6b8c4fSAdrian McCarthy for (const auto &F : SourceFileNames) { 143*6b6b8c4fSAdrian McCarthy Size += F.getKeyLength() + 1; // Names[I]; 144*6b6b8c4fSAdrian McCarthy } 145*6b6b8c4fSAdrian McCarthy return Size; 146*6b6b8c4fSAdrian McCarthy } 147*6b6b8c4fSAdrian McCarthy 148*6b6b8c4fSAdrian McCarthy uint32_t DbiStreamBuilder::calculateDbgStreamsSize() const { 149*6b6b8c4fSAdrian McCarthy return DbgStreams.size() * sizeof(uint16_t); 150*6b6b8c4fSAdrian McCarthy } 151*6b6b8c4fSAdrian McCarthy 152*6b6b8c4fSAdrian McCarthy Error DbiStreamBuilder::generateModiSubstream() { 153*6b6b8c4fSAdrian McCarthy uint32_t Size = calculateModiSubstreamSize(); 154*6b6b8c4fSAdrian McCarthy auto Data = Allocator.Allocate<uint8_t>(Size); 155*6b6b8c4fSAdrian McCarthy 156*6b6b8c4fSAdrian McCarthy ModInfoBuffer = MutableByteStream(MutableArrayRef<uint8_t>(Data, Size)); 157*6b6b8c4fSAdrian McCarthy 158*6b6b8c4fSAdrian McCarthy StreamWriter ModiWriter(ModInfoBuffer); 159*6b6b8c4fSAdrian McCarthy for (const auto &M : ModuleInfoList) { 160*6b6b8c4fSAdrian McCarthy ModuleInfoHeader Layout = {}; 161*6b6b8c4fSAdrian McCarthy Layout.ModDiStream = kInvalidStreamIndex; 162*6b6b8c4fSAdrian McCarthy Layout.NumFiles = M->SourceFiles.size(); 163*6b6b8c4fSAdrian McCarthy if (auto EC = ModiWriter.writeObject(Layout)) 164*6b6b8c4fSAdrian McCarthy return EC; 165*6b6b8c4fSAdrian McCarthy if (auto EC = ModiWriter.writeZeroString(M->Mod)) 166*6b6b8c4fSAdrian McCarthy return EC; 167*6b6b8c4fSAdrian McCarthy if (auto EC = ModiWriter.writeZeroString(M->Obj)) 168*6b6b8c4fSAdrian McCarthy return EC; 169*6b6b8c4fSAdrian McCarthy } 170*6b6b8c4fSAdrian McCarthy if (ModiWriter.bytesRemaining() > sizeof(uint32_t)) 171*6b6b8c4fSAdrian McCarthy return make_error<RawError>(raw_error_code::invalid_format, 172*6b6b8c4fSAdrian McCarthy "Unexpected bytes in Modi Stream Data"); 173*6b6b8c4fSAdrian McCarthy return Error::success(); 174*6b6b8c4fSAdrian McCarthy } 175*6b6b8c4fSAdrian McCarthy 176*6b6b8c4fSAdrian McCarthy Error DbiStreamBuilder::generateFileInfoSubstream() { 177*6b6b8c4fSAdrian McCarthy uint32_t Size = calculateFileInfoSubstreamSize(); 178*6b6b8c4fSAdrian McCarthy uint32_t NameSize = calculateNamesBufferSize(); 179*6b6b8c4fSAdrian McCarthy auto Data = Allocator.Allocate<uint8_t>(Size); 180*6b6b8c4fSAdrian McCarthy uint32_t NamesOffset = Size - NameSize; 181*6b6b8c4fSAdrian McCarthy 182*6b6b8c4fSAdrian McCarthy FileInfoBuffer = MutableByteStream(MutableArrayRef<uint8_t>(Data, Size)); 183*6b6b8c4fSAdrian McCarthy 184*6b6b8c4fSAdrian McCarthy WritableStreamRef MetadataBuffer = 185*6b6b8c4fSAdrian McCarthy WritableStreamRef(FileInfoBuffer).keep_front(NamesOffset); 186*6b6b8c4fSAdrian McCarthy StreamWriter MetadataWriter(MetadataBuffer); 187*6b6b8c4fSAdrian McCarthy 188*6b6b8c4fSAdrian McCarthy uint16_t ModiCount = std::min<uint32_t>(UINT16_MAX, ModuleInfos.size()); 189*6b6b8c4fSAdrian McCarthy uint16_t FileCount = std::min<uint32_t>(UINT16_MAX, SourceFileNames.size()); 190*6b6b8c4fSAdrian McCarthy if (auto EC = MetadataWriter.writeInteger(ModiCount)) // NumModules 191*6b6b8c4fSAdrian McCarthy return EC; 192*6b6b8c4fSAdrian McCarthy if (auto EC = MetadataWriter.writeInteger(FileCount)) // NumSourceFiles 193*6b6b8c4fSAdrian McCarthy return EC; 194*6b6b8c4fSAdrian McCarthy for (uint16_t I = 0; I < ModiCount; ++I) { 195*6b6b8c4fSAdrian McCarthy if (auto EC = MetadataWriter.writeInteger(I)) // Mod Indices 196*6b6b8c4fSAdrian McCarthy return EC; 197*6b6b8c4fSAdrian McCarthy } 198*6b6b8c4fSAdrian McCarthy for (const auto MI : ModuleInfoList) { 199*6b6b8c4fSAdrian McCarthy FileCount = static_cast<uint16_t>(MI->SourceFiles.size()); 200*6b6b8c4fSAdrian McCarthy if (auto EC = MetadataWriter.writeInteger(FileCount)) // Mod File Counts 201*6b6b8c4fSAdrian McCarthy return EC; 202*6b6b8c4fSAdrian McCarthy } 203*6b6b8c4fSAdrian McCarthy 204*6b6b8c4fSAdrian McCarthy // Before writing the FileNameOffsets array, write the NamesBuffer array. 205*6b6b8c4fSAdrian McCarthy // A side effect of this is that this will actually compute the various 206*6b6b8c4fSAdrian McCarthy // file name offsets, so we can then go back and write the FileNameOffsets 207*6b6b8c4fSAdrian McCarthy // array to the other substream. 208*6b6b8c4fSAdrian McCarthy NamesBuffer = WritableStreamRef(FileInfoBuffer).drop_front(NamesOffset); 209*6b6b8c4fSAdrian McCarthy StreamWriter NameBufferWriter(NamesBuffer); 210*6b6b8c4fSAdrian McCarthy for (auto &Name : SourceFileNames) { 211*6b6b8c4fSAdrian McCarthy Name.second = NameBufferWriter.getOffset(); 212*6b6b8c4fSAdrian McCarthy if (auto EC = NameBufferWriter.writeZeroString(Name.getKey())) 213*6b6b8c4fSAdrian McCarthy return EC; 214*6b6b8c4fSAdrian McCarthy } 215*6b6b8c4fSAdrian McCarthy 216*6b6b8c4fSAdrian McCarthy for (const auto MI : ModuleInfoList) { 217*6b6b8c4fSAdrian McCarthy for (StringRef Name : MI->SourceFiles) { 218*6b6b8c4fSAdrian McCarthy auto Result = SourceFileNames.find(Name); 219*6b6b8c4fSAdrian McCarthy if (Result == SourceFileNames.end()) 220*6b6b8c4fSAdrian McCarthy return make_error<RawError>(raw_error_code::no_entry, 221*6b6b8c4fSAdrian McCarthy "The source file was not found."); 222*6b6b8c4fSAdrian McCarthy if (auto EC = MetadataWriter.writeInteger(Result->second)) 223*6b6b8c4fSAdrian McCarthy return EC; 224*6b6b8c4fSAdrian McCarthy } 225*6b6b8c4fSAdrian McCarthy } 226*6b6b8c4fSAdrian McCarthy 227*6b6b8c4fSAdrian McCarthy if (NameBufferWriter.bytesRemaining() > 0) 228*6b6b8c4fSAdrian McCarthy return make_error<RawError>(raw_error_code::invalid_format, 229*6b6b8c4fSAdrian McCarthy "The names buffer contained unexpected data."); 230*6b6b8c4fSAdrian McCarthy 231*6b6b8c4fSAdrian McCarthy if (MetadataWriter.bytesRemaining() > sizeof(uint32_t)) 232*6b6b8c4fSAdrian McCarthy return make_error<RawError>( 233*6b6b8c4fSAdrian McCarthy raw_error_code::invalid_format, 234*6b6b8c4fSAdrian McCarthy "The metadata buffer contained unexpected data."); 235*6b6b8c4fSAdrian McCarthy 236*6b6b8c4fSAdrian McCarthy return Error::success(); 237*6b6b8c4fSAdrian McCarthy } 238*6b6b8c4fSAdrian McCarthy 239*6b6b8c4fSAdrian McCarthy Error DbiStreamBuilder::finalize() { 240*6b6b8c4fSAdrian McCarthy if (Header) 241*6b6b8c4fSAdrian McCarthy return Error::success(); 242*6b6b8c4fSAdrian McCarthy 243*6b6b8c4fSAdrian McCarthy DbiStreamHeader *H = Allocator.Allocate<DbiStreamHeader>(); 244*6b6b8c4fSAdrian McCarthy 245*6b6b8c4fSAdrian McCarthy if (auto EC = generateModiSubstream()) 246*6b6b8c4fSAdrian McCarthy return EC; 247*6b6b8c4fSAdrian McCarthy if (auto EC = generateFileInfoSubstream()) 248*6b6b8c4fSAdrian McCarthy return EC; 249*6b6b8c4fSAdrian McCarthy 250*6b6b8c4fSAdrian McCarthy H->VersionHeader = *VerHeader; 251*6b6b8c4fSAdrian McCarthy H->VersionSignature = -1; 252*6b6b8c4fSAdrian McCarthy H->Age = Age; 253*6b6b8c4fSAdrian McCarthy H->BuildNumber = BuildNumber; 254*6b6b8c4fSAdrian McCarthy H->Flags = Flags; 255*6b6b8c4fSAdrian McCarthy H->PdbDllRbld = PdbDllRbld; 256*6b6b8c4fSAdrian McCarthy H->PdbDllVersion = PdbDllVersion; 257*6b6b8c4fSAdrian McCarthy H->MachineType = static_cast<uint16_t>(MachineType); 258*6b6b8c4fSAdrian McCarthy 259*6b6b8c4fSAdrian McCarthy H->ECSubstreamSize = 0; 260*6b6b8c4fSAdrian McCarthy H->FileInfoSize = FileInfoBuffer.getLength(); 261*6b6b8c4fSAdrian McCarthy H->ModiSubstreamSize = ModInfoBuffer.getLength(); 262*6b6b8c4fSAdrian McCarthy H->OptionalDbgHdrSize = DbgStreams.size() * sizeof(uint16_t); 263*6b6b8c4fSAdrian McCarthy H->SecContrSubstreamSize = calculateSectionContribsStreamSize(); 264*6b6b8c4fSAdrian McCarthy H->SectionMapSize = calculateSectionMapStreamSize(); 265*6b6b8c4fSAdrian McCarthy H->TypeServerSize = 0; 266*6b6b8c4fSAdrian McCarthy H->SymRecordStreamIndex = kInvalidStreamIndex; 267*6b6b8c4fSAdrian McCarthy H->PublicSymbolStreamIndex = kInvalidStreamIndex; 268*6b6b8c4fSAdrian McCarthy H->MFCTypeServerIndex = kInvalidStreamIndex; 269*6b6b8c4fSAdrian McCarthy H->GlobalSymbolStreamIndex = kInvalidStreamIndex; 270*6b6b8c4fSAdrian McCarthy 271*6b6b8c4fSAdrian McCarthy Header = H; 272*6b6b8c4fSAdrian McCarthy return Error::success(); 273*6b6b8c4fSAdrian McCarthy } 274*6b6b8c4fSAdrian McCarthy 275*6b6b8c4fSAdrian McCarthy Error DbiStreamBuilder::finalizeMsfLayout() { 276*6b6b8c4fSAdrian McCarthy uint32_t Length = calculateSerializedLength(); 277*6b6b8c4fSAdrian McCarthy if (auto EC = Msf.setStreamSize(StreamDBI, Length)) 278*6b6b8c4fSAdrian McCarthy return EC; 279*6b6b8c4fSAdrian McCarthy return Error::success(); 280*6b6b8c4fSAdrian McCarthy } 281*6b6b8c4fSAdrian McCarthy 282*6b6b8c4fSAdrian McCarthy static uint16_t toSecMapFlags(uint32_t Flags) { 283*6b6b8c4fSAdrian McCarthy uint16_t Ret = 0; 284*6b6b8c4fSAdrian McCarthy if (Flags & COFF::IMAGE_SCN_MEM_READ) 285*6b6b8c4fSAdrian McCarthy Ret |= static_cast<uint16_t>(OMFSegDescFlags::Read); 286*6b6b8c4fSAdrian McCarthy if (Flags & COFF::IMAGE_SCN_MEM_WRITE) 287*6b6b8c4fSAdrian McCarthy Ret |= static_cast<uint16_t>(OMFSegDescFlags::Write); 288*6b6b8c4fSAdrian McCarthy if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE) 289*6b6b8c4fSAdrian McCarthy Ret |= static_cast<uint16_t>(OMFSegDescFlags::Execute); 290*6b6b8c4fSAdrian McCarthy if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE) 291*6b6b8c4fSAdrian McCarthy Ret |= static_cast<uint16_t>(OMFSegDescFlags::Execute); 292*6b6b8c4fSAdrian McCarthy if (!(Flags & COFF::IMAGE_SCN_MEM_16BIT)) 293*6b6b8c4fSAdrian McCarthy Ret |= static_cast<uint16_t>(OMFSegDescFlags::AddressIs32Bit); 294*6b6b8c4fSAdrian McCarthy 295*6b6b8c4fSAdrian McCarthy // This seems always 1. 296*6b6b8c4fSAdrian McCarthy Ret |= static_cast<uint16_t>(OMFSegDescFlags::IsSelector); 297*6b6b8c4fSAdrian McCarthy 298*6b6b8c4fSAdrian McCarthy return Ret; 299*6b6b8c4fSAdrian McCarthy } 300*6b6b8c4fSAdrian McCarthy 301*6b6b8c4fSAdrian McCarthy // A utility function to create Section Contributions 302*6b6b8c4fSAdrian McCarthy // for a given input sections. 303*6b6b8c4fSAdrian McCarthy std::vector<SectionContrib> DbiStreamBuilder::createSectionContribs( 304*6b6b8c4fSAdrian McCarthy ArrayRef<object::coff_section> SecHdrs) { 305*6b6b8c4fSAdrian McCarthy std::vector<SectionContrib> Ret; 306*6b6b8c4fSAdrian McCarthy 307*6b6b8c4fSAdrian McCarthy // Create a SectionContrib for each input section. 308*6b6b8c4fSAdrian McCarthy for (auto &Sec : SecHdrs) { 309*6b6b8c4fSAdrian McCarthy Ret.emplace_back(); 310*6b6b8c4fSAdrian McCarthy auto &Entry = Ret.back(); 311*6b6b8c4fSAdrian McCarthy memset(&Entry, 0, sizeof(Entry)); 312*6b6b8c4fSAdrian McCarthy 313*6b6b8c4fSAdrian McCarthy Entry.Off = Sec.PointerToRawData; 314*6b6b8c4fSAdrian McCarthy Entry.Size = Sec.SizeOfRawData; 315*6b6b8c4fSAdrian McCarthy Entry.Characteristics = Sec.Characteristics; 316*6b6b8c4fSAdrian McCarthy } 317*6b6b8c4fSAdrian McCarthy return Ret; 318*6b6b8c4fSAdrian McCarthy } 319*6b6b8c4fSAdrian McCarthy 320*6b6b8c4fSAdrian McCarthy // A utility function to create a Section Map for a given list of COFF sections. 321*6b6b8c4fSAdrian McCarthy // 322*6b6b8c4fSAdrian McCarthy // A Section Map seem to be a copy of a COFF section list in other format. 323*6b6b8c4fSAdrian McCarthy // I don't know why a PDB file contains both a COFF section header and 324*6b6b8c4fSAdrian McCarthy // a Section Map, but it seems it must be present in a PDB. 325*6b6b8c4fSAdrian McCarthy std::vector<SecMapEntry> DbiStreamBuilder::createSectionMap( 326*6b6b8c4fSAdrian McCarthy ArrayRef<llvm::object::coff_section> SecHdrs) { 327*6b6b8c4fSAdrian McCarthy std::vector<SecMapEntry> Ret; 328*6b6b8c4fSAdrian McCarthy int Idx = 0; 329*6b6b8c4fSAdrian McCarthy 330*6b6b8c4fSAdrian McCarthy auto Add = [&]() -> SecMapEntry & { 331*6b6b8c4fSAdrian McCarthy Ret.emplace_back(); 332*6b6b8c4fSAdrian McCarthy auto &Entry = Ret.back(); 333*6b6b8c4fSAdrian McCarthy memset(&Entry, 0, sizeof(Entry)); 334*6b6b8c4fSAdrian McCarthy 335*6b6b8c4fSAdrian McCarthy Entry.Frame = Idx + 1; 336*6b6b8c4fSAdrian McCarthy 337*6b6b8c4fSAdrian McCarthy // We don't know the meaning of these fields yet. 338*6b6b8c4fSAdrian McCarthy Entry.SecName = UINT16_MAX; 339*6b6b8c4fSAdrian McCarthy Entry.ClassName = UINT16_MAX; 340*6b6b8c4fSAdrian McCarthy 341*6b6b8c4fSAdrian McCarthy return Entry; 342*6b6b8c4fSAdrian McCarthy }; 343*6b6b8c4fSAdrian McCarthy 344*6b6b8c4fSAdrian McCarthy for (auto &Hdr : SecHdrs) { 345*6b6b8c4fSAdrian McCarthy auto &Entry = Add(); 346*6b6b8c4fSAdrian McCarthy Entry.Flags = toSecMapFlags(Hdr.Characteristics); 347*6b6b8c4fSAdrian McCarthy Entry.SecByteLength = Hdr.VirtualSize; 348*6b6b8c4fSAdrian McCarthy ++Idx; 349*6b6b8c4fSAdrian McCarthy } 350*6b6b8c4fSAdrian McCarthy 351*6b6b8c4fSAdrian McCarthy // The last entry is for absolute symbols. 352*6b6b8c4fSAdrian McCarthy auto &Entry = Add(); 353*6b6b8c4fSAdrian McCarthy Entry.Flags = static_cast<uint16_t>(OMFSegDescFlags::AddressIs32Bit) | 354*6b6b8c4fSAdrian McCarthy static_cast<uint16_t>(OMFSegDescFlags::IsAbsoluteAddress); 355*6b6b8c4fSAdrian McCarthy Entry.SecByteLength = UINT32_MAX; 356*6b6b8c4fSAdrian McCarthy 357*6b6b8c4fSAdrian McCarthy return Ret; 358*6b6b8c4fSAdrian McCarthy } 359*6b6b8c4fSAdrian McCarthy 360*6b6b8c4fSAdrian McCarthy Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout, 361*6b6b8c4fSAdrian McCarthy const msf::WritableStream &Buffer) { 362*6b6b8c4fSAdrian McCarthy if (auto EC = finalize()) 363*6b6b8c4fSAdrian McCarthy return EC; 364*6b6b8c4fSAdrian McCarthy 365*6b6b8c4fSAdrian McCarthy auto InfoS = 366*6b6b8c4fSAdrian McCarthy WritableMappedBlockStream::createIndexedStream(Layout, Buffer, StreamDBI); 367*6b6b8c4fSAdrian McCarthy 368*6b6b8c4fSAdrian McCarthy StreamWriter Writer(*InfoS); 369*6b6b8c4fSAdrian McCarthy if (auto EC = Writer.writeObject(*Header)) 370*6b6b8c4fSAdrian McCarthy return EC; 371*6b6b8c4fSAdrian McCarthy 372*6b6b8c4fSAdrian McCarthy if (auto EC = Writer.writeStreamRef(ModInfoBuffer)) 373*6b6b8c4fSAdrian McCarthy return EC; 374*6b6b8c4fSAdrian McCarthy 375*6b6b8c4fSAdrian McCarthy if (!SectionContribs.empty()) { 376*6b6b8c4fSAdrian McCarthy if (auto EC = Writer.writeEnum(DbiSecContribVer60)) 377*6b6b8c4fSAdrian McCarthy return EC; 378*6b6b8c4fSAdrian McCarthy if (auto EC = Writer.writeArray(SectionContribs)) 379*6b6b8c4fSAdrian McCarthy return EC; 380*6b6b8c4fSAdrian McCarthy } 381*6b6b8c4fSAdrian McCarthy 382*6b6b8c4fSAdrian McCarthy if (!SectionMap.empty()) { 383*6b6b8c4fSAdrian McCarthy ulittle16_t Size = static_cast<ulittle16_t>(SectionMap.size()); 384*6b6b8c4fSAdrian McCarthy SecMapHeader SMHeader = {Size, Size}; 385*6b6b8c4fSAdrian McCarthy if (auto EC = Writer.writeObject(SMHeader)) 386*6b6b8c4fSAdrian McCarthy return EC; 387*6b6b8c4fSAdrian McCarthy if (auto EC = Writer.writeArray(SectionMap)) 388*6b6b8c4fSAdrian McCarthy return EC; 389*6b6b8c4fSAdrian McCarthy } 390*6b6b8c4fSAdrian McCarthy 391*6b6b8c4fSAdrian McCarthy if (auto EC = Writer.writeStreamRef(FileInfoBuffer)) 392*6b6b8c4fSAdrian McCarthy return EC; 393*6b6b8c4fSAdrian McCarthy 394*6b6b8c4fSAdrian McCarthy for (auto &Stream : DbgStreams) 395*6b6b8c4fSAdrian McCarthy if (auto EC = Writer.writeInteger(Stream.StreamNumber)) 396*6b6b8c4fSAdrian McCarthy return EC; 397*6b6b8c4fSAdrian McCarthy 398*6b6b8c4fSAdrian McCarthy for (auto &Stream : DbgStreams) { 399*6b6b8c4fSAdrian McCarthy if (Stream.StreamNumber == kInvalidStreamIndex) 400*6b6b8c4fSAdrian McCarthy continue; 401*6b6b8c4fSAdrian McCarthy auto WritableStream = WritableMappedBlockStream::createIndexedStream( 402*6b6b8c4fSAdrian McCarthy Layout, Buffer, Stream.StreamNumber); 403*6b6b8c4fSAdrian McCarthy StreamWriter DbgStreamWriter(*WritableStream); 404*6b6b8c4fSAdrian McCarthy if (auto EC = DbgStreamWriter.writeArray(Stream.Data)) 405*6b6b8c4fSAdrian McCarthy return EC; 406*6b6b8c4fSAdrian McCarthy } 407*6b6b8c4fSAdrian McCarthy 408*6b6b8c4fSAdrian McCarthy if (Writer.bytesRemaining() > 0) 409*6b6b8c4fSAdrian McCarthy return make_error<RawError>(raw_error_code::invalid_format, 410*6b6b8c4fSAdrian McCarthy "Unexpected bytes found in DBI Stream"); 411*6b6b8c4fSAdrian McCarthy return Error::success(); 412*6b6b8c4fSAdrian McCarthy } 413