llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp
Zachary Turner 68ca30aa36 [CodeView] Support remaining debug subsection types
This adds support for Symbols, StringTable, and FrameData subsection
types.  Even though these subsections rarely if ever appear in a PDB
file (they are usually in object files), there's no theoretical reason
why they *couldn't* appear in a PDB.  The real issue though is that in
order to add support for dumping and writing them (which will be useful
for object files), we need a way to test them.  And since there is no
support for reading and writing them to / from object files yet, making
PDB support them is the best way to both add support for the underlying
format and add support for tests at the same time.  Later, when we go
to add support for reading / writing them from object files, we'll need
only minimal changes in the underlying read/write code.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305037 91177308-0d34-0410-b5e6-96231b3b80d8
2017-06-09 00:28:08 +00:00

97 lines
3.4 KiB
C++

//===- DebugSubsectionRecord.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/DebugSubsectionRecord.h"
#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
#include "llvm/Support/BinaryStreamReader.h"
using namespace llvm;
using namespace llvm::codeview;
DebugSubsectionRecord::DebugSubsectionRecord()
: Container(CodeViewContainer::ObjectFile),
Kind(DebugSubsectionKind::None) {}
DebugSubsectionRecord::DebugSubsectionRecord(DebugSubsectionKind Kind,
BinaryStreamRef Data,
CodeViewContainer Container)
: Container(Container), Kind(Kind), Data(Data) {}
Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream,
DebugSubsectionRecord &Info,
CodeViewContainer Container) {
const DebugSubsectionHeader *Header;
BinaryStreamReader Reader(Stream);
if (auto EC = Reader.readObject(Header))
return EC;
DebugSubsectionKind Kind =
static_cast<DebugSubsectionKind>(uint32_t(Header->Kind));
switch (Kind) {
case DebugSubsectionKind::FileChecksums:
case DebugSubsectionKind::Lines:
case DebugSubsectionKind::InlineeLines:
case DebugSubsectionKind::CrossScopeExports:
case DebugSubsectionKind::CrossScopeImports:
case DebugSubsectionKind::Symbols:
case DebugSubsectionKind::StringTable:
case DebugSubsectionKind::FrameData:
break;
default:
llvm_unreachable("Unexpected debug fragment kind!");
}
if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))
return EC;
Info.Container = Container;
Info.Kind = Kind;
return Error::success();
}
uint32_t DebugSubsectionRecord::getRecordLength() const {
return sizeof(DebugSubsectionHeader) + Data.getLength();
}
DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; }
BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; }
DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
std::unique_ptr<DebugSubsection> Subsection, CodeViewContainer Container)
: Subsection(std::move(Subsection)), Container(Container) {}
uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() {
// The length of the entire subsection is always padded to 4 bytes, regardless
// of the container kind.
uint32_t Size = sizeof(DebugSubsectionHeader) +
alignTo(Subsection->calculateSerializedSize(), 4);
return Size;
}
Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const {
assert(Writer.getOffset() % alignOf(Container) == 0 &&
"Debug Subsection not properly aligned");
DebugSubsectionHeader Header;
Header.Kind = uint32_t(Subsection->kind());
// The value written into the Header's Length field is only padded to the
// container's alignment
Header.Length =
alignTo(Subsection->calculateSerializedSize(), alignOf(Container));
if (auto EC = Writer.writeObject(Header))
return EC;
if (auto EC = Subsection->commit(Writer))
return EC;
if (auto EC = Writer.padToAlignment(4))
return EC;
return Error::success();
}