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