diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-05-30 17:37:31 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-05-30 17:37:31 +0000 | 
| commit | ee2f195dd3e40f49698ca4dc2666ec09c770e80d (patch) | |
| tree | 66fa9a69e5789356dfe844991e64bac9222f3a35 /lib/DebugInfo/CodeView/DebugLinesSubsection.cpp | |
| parent | ab44ce3d598882e51a25eb82eb7ae6308de85ae6 (diff) | |
Notes
Diffstat (limited to 'lib/DebugInfo/CodeView/DebugLinesSubsection.cpp')
| -rw-r--r-- | lib/DebugInfo/CodeView/DebugLinesSubsection.cpp | 159 | 
1 files changed, 159 insertions, 0 deletions
diff --git a/lib/DebugInfo/CodeView/DebugLinesSubsection.cpp b/lib/DebugInfo/CodeView/DebugLinesSubsection.cpp new file mode 100644 index 000000000000..2fce06ca2a17 --- /dev/null +++ b/lib/DebugInfo/CodeView/DebugLinesSubsection.cpp @@ -0,0 +1,159 @@ +//===- DebugLinesSubsection.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/DebugLinesSubsection.h" + +#include "llvm/DebugInfo/CodeView/CodeViewError.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" + +using namespace llvm; +using namespace llvm::codeview; + +Error LineColumnExtractor::extract(BinaryStreamRef Stream, uint32_t &Len, +                                   LineColumnEntry &Item, +                                   const LineFragmentHeader *Header) { +  using namespace codeview; +  const LineBlockFragmentHeader *BlockHeader; +  BinaryStreamReader Reader(Stream); +  if (auto EC = Reader.readObject(BlockHeader)) +    return EC; +  bool HasColumn = Header->Flags & uint16_t(LF_HaveColumns); +  uint32_t LineInfoSize = +      BlockHeader->NumLines * +      (sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0)); +  if (BlockHeader->BlockSize < sizeof(LineBlockFragmentHeader)) +    return make_error<CodeViewError>(cv_error_code::corrupt_record, +                                     "Invalid line block record size"); +  uint32_t Size = BlockHeader->BlockSize - sizeof(LineBlockFragmentHeader); +  if (LineInfoSize > Size) +    return make_error<CodeViewError>(cv_error_code::corrupt_record, +                                     "Invalid line block record size"); +  // The value recorded in BlockHeader->BlockSize includes the size of +  // LineBlockFragmentHeader. +  Len = BlockHeader->BlockSize; +  Item.NameIndex = BlockHeader->NameIndex; +  if (auto EC = Reader.readArray(Item.LineNumbers, BlockHeader->NumLines)) +    return EC; +  if (HasColumn) { +    if (auto EC = Reader.readArray(Item.Columns, BlockHeader->NumLines)) +      return EC; +  } +  return Error::success(); +} + +DebugLinesSubsectionRef::DebugLinesSubsectionRef() +    : DebugSubsectionRef(DebugSubsectionKind::Lines) {} + +Error DebugLinesSubsectionRef::initialize(BinaryStreamReader Reader) { +  if (auto EC = Reader.readObject(Header)) +    return EC; + +  if (auto EC = +          Reader.readArray(LinesAndColumns, Reader.bytesRemaining(), Header)) +    return EC; + +  return Error::success(); +} + +bool DebugLinesSubsectionRef::hasColumnInfo() const { +  return !!(Header->Flags & LF_HaveColumns); +} + +DebugLinesSubsection::DebugLinesSubsection(DebugChecksumsSubsection &Checksums, +                                           DebugStringTableSubsection &Strings) +    : DebugSubsection(DebugSubsectionKind::Lines), Checksums(Checksums) {} + +void DebugLinesSubsection::createBlock(StringRef FileName) { +  uint32_t Offset = Checksums.mapChecksumOffset(FileName); + +  Blocks.emplace_back(Offset); +} + +void DebugLinesSubsection::addLineInfo(uint32_t Offset, const LineInfo &Line) { +  Block &B = Blocks.back(); +  LineNumberEntry LNE; +  LNE.Flags = Line.getRawData(); +  LNE.Offset = Offset; +  B.Lines.push_back(LNE); +} + +void DebugLinesSubsection::addLineAndColumnInfo(uint32_t Offset, +                                                const LineInfo &Line, +                                                uint32_t ColStart, +                                                uint32_t ColEnd) { +  Block &B = Blocks.back(); +  assert(B.Lines.size() == B.Columns.size()); + +  addLineInfo(Offset, Line); +  ColumnNumberEntry CNE; +  CNE.StartColumn = ColStart; +  CNE.EndColumn = ColEnd; +  B.Columns.push_back(CNE); +} + +Error DebugLinesSubsection::commit(BinaryStreamWriter &Writer) const { +  LineFragmentHeader Header; +  Header.CodeSize = CodeSize; +  Header.Flags = hasColumnInfo() ? LF_HaveColumns : 0; +  Header.RelocOffset = RelocOffset; +  Header.RelocSegment = RelocSegment; + +  if (auto EC = Writer.writeObject(Header)) +    return EC; + +  for (const auto &B : Blocks) { +    LineBlockFragmentHeader BlockHeader; +    assert(B.Lines.size() == B.Columns.size() || B.Columns.empty()); + +    BlockHeader.NumLines = B.Lines.size(); +    BlockHeader.BlockSize = sizeof(LineBlockFragmentHeader); +    BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(LineNumberEntry); +    if (hasColumnInfo()) +      BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(ColumnNumberEntry); +    BlockHeader.NameIndex = B.ChecksumBufferOffset; +    if (auto EC = Writer.writeObject(BlockHeader)) +      return EC; + +    if (auto EC = Writer.writeArray(makeArrayRef(B.Lines))) +      return EC; + +    if (hasColumnInfo()) { +      if (auto EC = Writer.writeArray(makeArrayRef(B.Columns))) +        return EC; +    } +  } +  return Error::success(); +} + +uint32_t DebugLinesSubsection::calculateSerializedSize() const { +  uint32_t Size = sizeof(LineFragmentHeader); +  for (const auto &B : Blocks) { +    Size += sizeof(LineBlockFragmentHeader); +    Size += B.Lines.size() * sizeof(LineNumberEntry); +    if (hasColumnInfo()) +      Size += B.Columns.size() * sizeof(ColumnNumberEntry); +  } +  return Size; +} + +void DebugLinesSubsection::setRelocationAddress(uint16_t Segment, +                                                uint16_t Offset) { +  RelocOffset = Offset; +  RelocSegment = Segment; +} + +void DebugLinesSubsection::setCodeSize(uint32_t Size) { CodeSize = Size; } + +void DebugLinesSubsection::setFlags(LineFlags Flags) { this->Flags = Flags; } + +bool DebugLinesSubsection::hasColumnInfo() const { +  return Flags & LF_HaveColumns; +}  | 
