diff options
author | Zachary Turner <zturner@google.com> | 2017-04-27 16:12:16 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2017-04-27 16:12:16 +0000 |
commit | c37cb0c6a5c266f102c130bfe1daaa25329cb997 (patch) | |
tree | 48cd2b14c7b818b9b1a6eec14ae4518ee2dc195d /llvm/lib/DebugInfo | |
parent | e5094474187a9b748589aa709c3e1e172d42e87f (diff) | |
download | bcm5719-llvm-c37cb0c6a5c266f102c130bfe1daaa25329cb997.tar.gz bcm5719-llvm-c37cb0c6a5c266f102c130bfe1daaa25329cb997.zip |
[CodeView] Isolate Debug Info Fragments into standalone classes.
Previously parsing of these were all grouped together into a
single master class that could parse any type of debug info
fragment.
With writing forthcoming, the complexity of each individual
fragment is enough to warrant them having their own classes so
that reading and writing of each fragment type can be grouped
together, but isolated from the code for reading and writing
other fragment types.
In doing so, I found a place where parsing code was duplicated
for the FileChecksums fragment, across llvm-readobj and the
CodeView library, and one of the implementations had a bug.
Now that the codepaths are merged, the bug is resolved.
Differential Revision: https://reviews.llvm.org/D32547
llvm-svn: 301557
Diffstat (limited to 'llvm/lib/DebugInfo')
8 files changed, 200 insertions, 120 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt index 5dae51eedd1..7655f6c651e 100644 --- a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt @@ -7,8 +7,12 @@ add_llvm_library(LLVMDebugInfoCodeView EnumTables.cpp Formatters.cpp Line.cpp + ModuleDebugFileChecksumFragment.cpp ModuleDebugFragment.cpp + ModuleDebugFragmentRecord.cpp ModuleDebugFragmentVisitor.cpp + ModuleDebugLineFragment.cpp + ModuleDebugUnknownFragment.cpp RecordSerialization.cpp SymbolRecordMapping.cpp SymbolDumper.cpp diff --git a/llvm/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp b/llvm/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp new file mode 100644 index 00000000000..3f234adc1c2 --- /dev/null +++ b/llvm/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp @@ -0,0 +1,49 @@ +//===- ModuleDebugFileChecksumFragment.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/ModuleDebugFileChecksumFragment.h" + +#include "llvm/DebugInfo/CodeView/CodeViewError.h" +#include "llvm/Support/BinaryStreamReader.h" + +using namespace llvm; +using namespace llvm::codeview; + +struct FileChecksumEntryHeader { + using ulittle32_t = support::ulittle32_t; + + ulittle32_t FileNameOffset; // Byte offset of filename in global string table. + uint8_t ChecksumSize; // Number of bytes of checksum. + uint8_t ChecksumKind; // FileChecksumKind + // Checksum bytes follow. +}; + +Error llvm::VarStreamArrayExtractor<FileChecksumEntry>::extract( + BinaryStreamRef Stream, uint32_t &Len, FileChecksumEntry &Item, void *Ctx) { + BinaryStreamReader Reader(Stream); + + const FileChecksumEntryHeader *Header; + if (auto EC = Reader.readObject(Header)) + return EC; + + Item.FileNameOffset = Header->FileNameOffset; + Item.Kind = static_cast<FileChecksumKind>(Header->ChecksumKind); + if (auto EC = Reader.readBytes(Item.Checksum, Header->ChecksumSize)) + return EC; + + Len = alignTo(Header->ChecksumSize + sizeof(FileChecksumEntryHeader), 4); + return Error::success(); +} + +Error ModuleDebugFileChecksumFragment::initialize(BinaryStreamReader Reader) { + if (auto EC = Reader.readArray(Checksums, Reader.bytesRemaining())) + return EC; + + return Error::success(); +} diff --git a/llvm/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp b/llvm/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp index 1329f8cc8f6..a3327b06b98 100644 --- a/llvm/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp +++ b/llvm/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp @@ -1,5 +1,4 @@ -//===- ModuleDebugFragment.cpp --------------------------------------*- C++ -//-*-===// +//===- ModuleDebugFragment.cpp -----------------------------------*- C++-*-===// // // The LLVM Compiler Infrastructure // @@ -10,37 +9,6 @@ #include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" -#include "llvm/Support/BinaryStreamReader.h" - -using namespace llvm; using namespace llvm::codeview; -ModuleDebugFragment::ModuleDebugFragment() - : Kind(ModuleDebugFragmentKind::None) {} - -ModuleDebugFragment::ModuleDebugFragment(ModuleDebugFragmentKind Kind, - BinaryStreamRef Data) - : Kind(Kind), Data(Data) {} - -Error ModuleDebugFragment::initialize(BinaryStreamRef Stream, - ModuleDebugFragment &Info) { - const ModuleDebugFragmentHeader *Header; - BinaryStreamReader Reader(Stream); - if (auto EC = Reader.readObject(Header)) - return EC; - - ModuleDebugFragmentKind Kind = - static_cast<ModuleDebugFragmentKind>(uint32_t(Header->Kind)); - if (auto EC = Reader.readStreamRef(Info.Data, Header->Length)) - return EC; - Info.Kind = Kind; - return Error::success(); -} - -uint32_t ModuleDebugFragment::getRecordLength() const { - return sizeof(ModuleDebugFragmentHeader) + Data.getLength(); -} - -ModuleDebugFragmentKind ModuleDebugFragment::kind() const { return Kind; } - -BinaryStreamRef ModuleDebugFragment::getRecordData() const { return Data; } +ModuleDebugFragment::~ModuleDebugFragment() {} diff --git a/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp b/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp new file mode 100644 index 00000000000..20c06e9bebe --- /dev/null +++ b/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp @@ -0,0 +1,47 @@ +//===- ModuleDebugFragmentRecord.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/ModuleDebugFragmentRecord.h" + +#include "llvm/Support/BinaryStreamReader.h" + +using namespace llvm; +using namespace llvm::codeview; + +ModuleDebugFragmentRecord::ModuleDebugFragmentRecord() + : Kind(ModuleDebugFragmentKind::None) {} + +ModuleDebugFragmentRecord::ModuleDebugFragmentRecord( + ModuleDebugFragmentKind Kind, BinaryStreamRef Data) + : Kind(Kind), Data(Data) {} + +Error ModuleDebugFragmentRecord::initialize(BinaryStreamRef Stream, + ModuleDebugFragmentRecord &Info) { + const ModuleDebugFragmentHeader *Header; + BinaryStreamReader Reader(Stream); + if (auto EC = Reader.readObject(Header)) + return EC; + + ModuleDebugFragmentKind Kind = + static_cast<ModuleDebugFragmentKind>(uint32_t(Header->Kind)); + if (auto EC = Reader.readStreamRef(Info.Data, Header->Length)) + return EC; + Info.Kind = Kind; + return Error::success(); +} + +uint32_t ModuleDebugFragmentRecord::getRecordLength() const { + return sizeof(ModuleDebugFragmentHeader) + Data.getLength(); +} + +ModuleDebugFragmentKind ModuleDebugFragmentRecord::kind() const { return Kind; } + +BinaryStreamRef ModuleDebugFragmentRecord::getRecordData() const { + return Data; +} diff --git a/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp b/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp index 37cd887d783..53dc922a649 100644 --- a/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp +++ b/llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp @@ -8,99 +8,36 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h" + +#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/BinaryStreamRef.h" using namespace llvm; using namespace llvm::codeview; -Error ModuleDebugFragmentVisitor::visitSymbols(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::Symbols, Data); -} -Error ModuleDebugFragmentVisitor::visitLines(BinaryStreamRef Data, - const LineFragmentHeader *Header, - const LineInfoArray &Lines) { - return visitUnknown(ModuleDebugFragmentKind::Lines, Data); -} -Error ModuleDebugFragmentVisitor::visitStringTable(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::StringTable, Data); -} -Error ModuleDebugFragmentVisitor::visitFileChecksums( - BinaryStreamRef Data, const FileChecksumArray &Checksums) { - return visitUnknown(ModuleDebugFragmentKind::FileChecksums, Data); -} -Error ModuleDebugFragmentVisitor::visitFrameData(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::FrameData, Data); -} -Error ModuleDebugFragmentVisitor::visitInlineeLines(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::InlineeLines, Data); -} -Error ModuleDebugFragmentVisitor::visitCrossScopeImports(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::CrossScopeExports, Data); -} -Error ModuleDebugFragmentVisitor::visitCrossScopeExports(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::CrossScopeImports, Data); -} -Error ModuleDebugFragmentVisitor::visitILLines(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::ILLines, Data); -} -Error ModuleDebugFragmentVisitor::visitFuncMDTokenMap(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::FuncMDTokenMap, Data); -} -Error ModuleDebugFragmentVisitor::visitTypeMDTokenMap(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::TypeMDTokenMap, Data); -} -Error ModuleDebugFragmentVisitor::visitMergedAssemblyInput( - BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::MergedAssemblyInput, Data); -} -Error ModuleDebugFragmentVisitor::visitCoffSymbolRVA(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::CoffSymbolRVA, Data); -} - -Error llvm::codeview::visitModuleDebugFragment(const ModuleDebugFragment &R, - ModuleDebugFragmentVisitor &V) { +Error llvm::codeview::visitModuleDebugFragment( + const ModuleDebugFragmentRecord &R, ModuleDebugFragmentVisitor &V) { + BinaryStreamReader Reader(R.getRecordData()); switch (R.kind()) { - case ModuleDebugFragmentKind::Symbols: - return V.visitSymbols(R.getRecordData()); case ModuleDebugFragmentKind::Lines: { - BinaryStreamReader Reader(R.getRecordData()); - const LineFragmentHeader *Header; - if (auto EC = Reader.readObject(Header)) + ModuleDebugLineFragment Fragment; + if (auto EC = Fragment.initialize(Reader)) return EC; - LineInfoArray LineInfos; - if (auto EC = Reader.readArray(LineInfos, Reader.bytesRemaining(), Header)) - return EC; - return V.visitLines(R.getRecordData(), Header, LineInfos); + + return V.visitLines(Fragment); } - case ModuleDebugFragmentKind::StringTable: - return V.visitStringTable(R.getRecordData()); case ModuleDebugFragmentKind::FileChecksums: { - BinaryStreamReader Reader(R.getRecordData()); - FileChecksumArray Checksums; - if (auto EC = Reader.readArray(Checksums, Reader.bytesRemaining())) + ModuleDebugFileChecksumFragment Fragment; + if (auto EC = Fragment.initialize(Reader)) return EC; - return V.visitFileChecksums(R.getRecordData(), Checksums); + + return V.visitFileChecksums(Fragment); + } + default: { + ModuleDebugUnknownFragment Fragment(R.kind(), R.getRecordData()); + return V.visitUnknown(Fragment); } - case ModuleDebugFragmentKind::FrameData: - return V.visitFrameData(R.getRecordData()); - case ModuleDebugFragmentKind::InlineeLines: - return V.visitInlineeLines(R.getRecordData()); - case ModuleDebugFragmentKind::CrossScopeImports: - return V.visitCrossScopeImports(R.getRecordData()); - case ModuleDebugFragmentKind::CrossScopeExports: - return V.visitCrossScopeExports(R.getRecordData()); - case ModuleDebugFragmentKind::ILLines: - return V.visitILLines(R.getRecordData()); - case ModuleDebugFragmentKind::FuncMDTokenMap: - return V.visitFuncMDTokenMap(R.getRecordData()); - case ModuleDebugFragmentKind::TypeMDTokenMap: - return V.visitTypeMDTokenMap(R.getRecordData()); - case ModuleDebugFragmentKind::MergedAssemblyInput: - return V.visitMergedAssemblyInput(R.getRecordData()); - case ModuleDebugFragmentKind::CoffSymbolRVA: - return V.visitCoffSymbolRVA(R.getRecordData()); - default: - return V.visitUnknown(R.kind(), R.getRecordData()); } } diff --git a/llvm/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp b/llvm/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp new file mode 100644 index 00000000000..1b840890560 --- /dev/null +++ b/llvm/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp @@ -0,0 +1,63 @@ +//===- ModuleDebugLineFragment.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/ModuleDebugLineFragment.h" + +#include "llvm/DebugInfo/CodeView/CodeViewError.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.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 & uint32_t(LineFlags::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(); +} + +ModuleDebugLineFragment::ModuleDebugLineFragment() + : ModuleDebugFragment(ModuleDebugFragmentKind::Lines) {} + +Error ModuleDebugLineFragment::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(); +} diff --git a/llvm/lib/DebugInfo/CodeView/ModuleDebugUnknownFragment.cpp b/llvm/lib/DebugInfo/CodeView/ModuleDebugUnknownFragment.cpp new file mode 100644 index 00000000000..9fd2cb8ed3e --- /dev/null +++ b/llvm/lib/DebugInfo/CodeView/ModuleDebugUnknownFragment.cpp @@ -0,0 +1,10 @@ +//===- ModuleDebugUnknownFragment.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/ModuleDebugUnknownFragment.h"
\ No newline at end of file diff --git a/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp b/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp index 8caa4b85772..56e415a3d54 100644 --- a/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp @@ -21,6 +21,7 @@ #include <cstdint> using namespace llvm; +using namespace llvm::codeview; using namespace llvm::msf; using namespace llvm::pdb; @@ -54,7 +55,8 @@ Error ModuleDebugStream::reload() { return EC; BinaryStreamReader LineReader(C13LinesSubstream); - if (auto EC = LineReader.readArray(LineInfo, LineReader.bytesRemaining())) + if (auto EC = + LineReader.readArray(LinesAndChecksums, LineReader.bytesRemaining())) return EC; uint32_t GlobalRefsSize; @@ -77,13 +79,13 @@ ModuleDebugStream::symbols(bool *HadError) const { return make_range(SymbolsSubstream.begin(HadError), SymbolsSubstream.end()); } -iterator_range<codeview::ModuleDebugFragmentArray::Iterator> -ModuleDebugStream::lines(bool *HadError) const { - return make_range(LineInfo.begin(HadError), LineInfo.end()); +llvm::iterator_range<ModuleDebugStream::LinesAndChecksumsIterator> +ModuleDebugStream::linesAndChecksums() const { + return make_range(LinesAndChecksums.begin(), LinesAndChecksums.end()); } bool ModuleDebugStream::hasLineInfo() const { - return C13LinesSubstream.getLength() > 0 || LinesSubstream.getLength() > 0; + return C13LinesSubstream.getLength() > 0; } Error ModuleDebugStream::commit() { return Error::success(); } |