1*0b57cec5SDimitry Andric //===- DebugInlineeLinesSubsection.cpp ------------------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" 10*0b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 11*0b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeView.h" 12*0b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" 13*0b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamReader.h" 14*0b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamWriter.h" 15*0b57cec5SDimitry Andric #include "llvm/Support/Endian.h" 16*0b57cec5SDimitry Andric #include "llvm/Support/Error.h" 17*0b57cec5SDimitry Andric #include <cassert> 18*0b57cec5SDimitry Andric #include <cstdint> 19*0b57cec5SDimitry Andric 20*0b57cec5SDimitry Andric using namespace llvm; 21*0b57cec5SDimitry Andric using namespace llvm::codeview; 22*0b57cec5SDimitry Andric 23*0b57cec5SDimitry Andric Error VarStreamArrayExtractor<InlineeSourceLine>:: 24*0b57cec5SDimitry Andric operator()(BinaryStreamRef Stream, uint32_t &Len, InlineeSourceLine &Item) { 25*0b57cec5SDimitry Andric BinaryStreamReader Reader(Stream); 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric if (auto EC = Reader.readObject(Item.Header)) 28*0b57cec5SDimitry Andric return EC; 29*0b57cec5SDimitry Andric 30*0b57cec5SDimitry Andric if (HasExtraFiles) { 31*0b57cec5SDimitry Andric uint32_t ExtraFileCount; 32*0b57cec5SDimitry Andric if (auto EC = Reader.readInteger(ExtraFileCount)) 33*0b57cec5SDimitry Andric return EC; 34*0b57cec5SDimitry Andric if (auto EC = Reader.readArray(Item.ExtraFiles, ExtraFileCount)) 35*0b57cec5SDimitry Andric return EC; 36*0b57cec5SDimitry Andric } 37*0b57cec5SDimitry Andric 38*0b57cec5SDimitry Andric Len = Reader.getOffset(); 39*0b57cec5SDimitry Andric return Error::success(); 40*0b57cec5SDimitry Andric } 41*0b57cec5SDimitry Andric 42*0b57cec5SDimitry Andric DebugInlineeLinesSubsectionRef::DebugInlineeLinesSubsectionRef() 43*0b57cec5SDimitry Andric : DebugSubsectionRef(DebugSubsectionKind::InlineeLines) {} 44*0b57cec5SDimitry Andric 45*0b57cec5SDimitry Andric Error DebugInlineeLinesSubsectionRef::initialize(BinaryStreamReader Reader) { 46*0b57cec5SDimitry Andric if (auto EC = Reader.readEnum(Signature)) 47*0b57cec5SDimitry Andric return EC; 48*0b57cec5SDimitry Andric 49*0b57cec5SDimitry Andric Lines.getExtractor().HasExtraFiles = hasExtraFiles(); 50*0b57cec5SDimitry Andric if (auto EC = Reader.readArray(Lines, Reader.bytesRemaining())) 51*0b57cec5SDimitry Andric return EC; 52*0b57cec5SDimitry Andric 53*0b57cec5SDimitry Andric assert(Reader.bytesRemaining() == 0); 54*0b57cec5SDimitry Andric return Error::success(); 55*0b57cec5SDimitry Andric } 56*0b57cec5SDimitry Andric 57*0b57cec5SDimitry Andric bool DebugInlineeLinesSubsectionRef::hasExtraFiles() const { 58*0b57cec5SDimitry Andric return Signature == InlineeLinesSignature::ExtraFiles; 59*0b57cec5SDimitry Andric } 60*0b57cec5SDimitry Andric 61*0b57cec5SDimitry Andric DebugInlineeLinesSubsection::DebugInlineeLinesSubsection( 62*0b57cec5SDimitry Andric DebugChecksumsSubsection &Checksums, bool HasExtraFiles) 63*0b57cec5SDimitry Andric : DebugSubsection(DebugSubsectionKind::InlineeLines), Checksums(Checksums), 64*0b57cec5SDimitry Andric HasExtraFiles(HasExtraFiles) {} 65*0b57cec5SDimitry Andric 66*0b57cec5SDimitry Andric uint32_t DebugInlineeLinesSubsection::calculateSerializedSize() const { 67*0b57cec5SDimitry Andric // 4 bytes for the signature 68*0b57cec5SDimitry Andric uint32_t Size = sizeof(InlineeLinesSignature); 69*0b57cec5SDimitry Andric 70*0b57cec5SDimitry Andric // one header for each entry. 71*0b57cec5SDimitry Andric Size += Entries.size() * sizeof(InlineeSourceLineHeader); 72*0b57cec5SDimitry Andric if (HasExtraFiles) { 73*0b57cec5SDimitry Andric // If extra files are enabled, one count for each entry. 74*0b57cec5SDimitry Andric Size += Entries.size() * sizeof(uint32_t); 75*0b57cec5SDimitry Andric 76*0b57cec5SDimitry Andric // And one file id for each file. 77*0b57cec5SDimitry Andric Size += ExtraFileCount * sizeof(uint32_t); 78*0b57cec5SDimitry Andric } 79*0b57cec5SDimitry Andric assert(Size % 4 == 0); 80*0b57cec5SDimitry Andric return Size; 81*0b57cec5SDimitry Andric } 82*0b57cec5SDimitry Andric 83*0b57cec5SDimitry Andric Error DebugInlineeLinesSubsection::commit(BinaryStreamWriter &Writer) const { 84*0b57cec5SDimitry Andric InlineeLinesSignature Sig = InlineeLinesSignature::Normal; 85*0b57cec5SDimitry Andric if (HasExtraFiles) 86*0b57cec5SDimitry Andric Sig = InlineeLinesSignature::ExtraFiles; 87*0b57cec5SDimitry Andric 88*0b57cec5SDimitry Andric if (auto EC = Writer.writeEnum(Sig)) 89*0b57cec5SDimitry Andric return EC; 90*0b57cec5SDimitry Andric 91*0b57cec5SDimitry Andric for (const auto &E : Entries) { 92*0b57cec5SDimitry Andric if (auto EC = Writer.writeObject(E.Header)) 93*0b57cec5SDimitry Andric return EC; 94*0b57cec5SDimitry Andric 95*0b57cec5SDimitry Andric if (!HasExtraFiles) 96*0b57cec5SDimitry Andric continue; 97*0b57cec5SDimitry Andric 98*0b57cec5SDimitry Andric if (auto EC = Writer.writeInteger<uint32_t>(E.ExtraFiles.size())) 99*0b57cec5SDimitry Andric return EC; 100*0b57cec5SDimitry Andric if (auto EC = Writer.writeArray(makeArrayRef(E.ExtraFiles))) 101*0b57cec5SDimitry Andric return EC; 102*0b57cec5SDimitry Andric } 103*0b57cec5SDimitry Andric 104*0b57cec5SDimitry Andric return Error::success(); 105*0b57cec5SDimitry Andric } 106*0b57cec5SDimitry Andric 107*0b57cec5SDimitry Andric void DebugInlineeLinesSubsection::addExtraFile(StringRef FileName) { 108*0b57cec5SDimitry Andric uint32_t Offset = Checksums.mapChecksumOffset(FileName); 109*0b57cec5SDimitry Andric 110*0b57cec5SDimitry Andric auto &Entry = Entries.back(); 111*0b57cec5SDimitry Andric Entry.ExtraFiles.push_back(ulittle32_t(Offset)); 112*0b57cec5SDimitry Andric ++ExtraFileCount; 113*0b57cec5SDimitry Andric } 114*0b57cec5SDimitry Andric 115*0b57cec5SDimitry Andric void DebugInlineeLinesSubsection::addInlineSite(TypeIndex FuncId, 116*0b57cec5SDimitry Andric StringRef FileName, 117*0b57cec5SDimitry Andric uint32_t SourceLine) { 118*0b57cec5SDimitry Andric uint32_t Offset = Checksums.mapChecksumOffset(FileName); 119*0b57cec5SDimitry Andric 120*0b57cec5SDimitry Andric Entries.emplace_back(); 121*0b57cec5SDimitry Andric auto &Entry = Entries.back(); 122*0b57cec5SDimitry Andric Entry.Header.FileID = Offset; 123*0b57cec5SDimitry Andric Entry.Header.SourceLineNum = SourceLine; 124*0b57cec5SDimitry Andric Entry.Header.Inlinee = FuncId; 125*0b57cec5SDimitry Andric } 126