mirror of
https://github.com/RPCSX/llvm.git
synced 2025-05-13 19:06:05 +00:00
[CodeView] Write CodeView line information.
Differential Revision: https://reviews.llvm.org/D32716 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301882 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2cc0b076e8
commit
4c78c0e348
@ -11,7 +11,9 @@
|
|||||||
#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFILECHECKSUMFRAGMENT_H
|
#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFILECHECKSUMFRAGMENT_H
|
||||||
|
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
|
#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
|
||||||
|
#include "llvm/Support/Allocator.h"
|
||||||
#include "llvm/Support/BinaryStreamArray.h"
|
#include "llvm/Support/BinaryStreamArray.h"
|
||||||
#include "llvm/Support/BinaryStreamReader.h"
|
#include "llvm/Support/BinaryStreamReader.h"
|
||||||
#include "llvm/Support/Endian.h"
|
#include "llvm/Support/Endian.h"
|
||||||
@ -61,6 +63,28 @@ public:
|
|||||||
private:
|
private:
|
||||||
FileChecksumArray Checksums;
|
FileChecksumArray Checksums;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ModuleDebugFileChecksumFragment final : public ModuleDebugFragment {
|
||||||
|
public:
|
||||||
|
ModuleDebugFileChecksumFragment();
|
||||||
|
|
||||||
|
static bool classof(const ModuleDebugFragment *S) {
|
||||||
|
return S->kind() == ModuleDebugFragmentKind::FileChecksums;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addChecksum(uint32_t StringTableOffset, FileChecksumKind Kind,
|
||||||
|
ArrayRef<uint8_t> Bytes);
|
||||||
|
|
||||||
|
uint32_t calculateSerializedLength() override;
|
||||||
|
Error commit(BinaryStreamWriter &Writer) override;
|
||||||
|
uint32_t mapChecksumOffset(uint32_t StringTableOffset) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
DenseMap<uint32_t, uint32_t> OffsetMap;
|
||||||
|
uint32_t SerializedSize = 0;
|
||||||
|
llvm::BumpPtrAllocator Storage;
|
||||||
|
std::vector<FileChecksumEntry> Checksums;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENT_H
|
#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENT_H
|
||||||
|
|
||||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||||
|
#include "llvm/Support/BinaryStreamWriter.h"
|
||||||
#include "llvm/Support/Casting.h"
|
#include "llvm/Support/Casting.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
@ -27,6 +28,20 @@ protected:
|
|||||||
ModuleDebugFragmentKind Kind;
|
ModuleDebugFragmentKind Kind;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ModuleDebugFragment {
|
||||||
|
public:
|
||||||
|
explicit ModuleDebugFragment(ModuleDebugFragmentKind Kind) : Kind(Kind) {}
|
||||||
|
virtual ~ModuleDebugFragment();
|
||||||
|
|
||||||
|
ModuleDebugFragmentKind kind() const { return Kind; }
|
||||||
|
|
||||||
|
virtual Error commit(BinaryStreamWriter &Writer) = 0;
|
||||||
|
virtual uint32_t calculateSerializedLength() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ModuleDebugFragmentKind Kind;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace codeview
|
} // namespace codeview
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
|
||||||
|
@ -13,12 +13,15 @@
|
|||||||
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||||||
#include "llvm/Support/BinaryStreamArray.h"
|
#include "llvm/Support/BinaryStreamArray.h"
|
||||||
#include "llvm/Support/BinaryStreamRef.h"
|
#include "llvm/Support/BinaryStreamRef.h"
|
||||||
|
#include "llvm/Support/BinaryStreamWriter.h"
|
||||||
#include "llvm/Support/Endian.h"
|
#include "llvm/Support/Endian.h"
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace codeview {
|
namespace codeview {
|
||||||
|
|
||||||
|
class ModuleDebugFragment;
|
||||||
|
|
||||||
// Corresponds to the `CV_DebugSSubsectionHeader_t` structure.
|
// Corresponds to the `CV_DebugSSubsectionHeader_t` structure.
|
||||||
struct ModuleDebugFragmentHeader {
|
struct ModuleDebugFragmentHeader {
|
||||||
support::ulittle32_t Kind; // codeview::ModuleDebugFragmentKind enum
|
support::ulittle32_t Kind; // codeview::ModuleDebugFragmentKind enum
|
||||||
@ -32,6 +35,7 @@ public:
|
|||||||
|
|
||||||
static Error initialize(BinaryStreamRef Stream,
|
static Error initialize(BinaryStreamRef Stream,
|
||||||
ModuleDebugFragmentRecord &Info);
|
ModuleDebugFragmentRecord &Info);
|
||||||
|
|
||||||
uint32_t getRecordLength() const;
|
uint32_t getRecordLength() const;
|
||||||
ModuleDebugFragmentKind kind() const;
|
ModuleDebugFragmentKind kind() const;
|
||||||
BinaryStreamRef getRecordData() const;
|
BinaryStreamRef getRecordData() const;
|
||||||
@ -41,6 +45,18 @@ private:
|
|||||||
BinaryStreamRef Data;
|
BinaryStreamRef Data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ModuleDebugFragmentRecordBuilder {
|
||||||
|
public:
|
||||||
|
ModuleDebugFragmentRecordBuilder(ModuleDebugFragmentKind Kind,
|
||||||
|
ModuleDebugFragment &Frag);
|
||||||
|
uint32_t calculateSerializedLength();
|
||||||
|
Error commit(BinaryStreamWriter &Writer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ModuleDebugFragmentKind Kind;
|
||||||
|
ModuleDebugFragment &Frag;
|
||||||
|
};
|
||||||
|
|
||||||
typedef VarStreamArray<ModuleDebugFragmentRecord> ModuleDebugFragmentArray;
|
typedef VarStreamArray<ModuleDebugFragmentRecord> ModuleDebugFragmentArray;
|
||||||
|
|
||||||
} // namespace codeview
|
} // namespace codeview
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#ifndef LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGLINEFRAGMENT_H
|
#ifndef LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGLINEFRAGMENT_H
|
||||||
#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGLINEFRAGMENT_H
|
#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGLINEFRAGMENT_H
|
||||||
|
|
||||||
|
#include "llvm/DebugInfo/CodeView/Line.h"
|
||||||
#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
|
#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
|
||||||
#include "llvm/Support/BinaryStreamArray.h"
|
#include "llvm/Support/BinaryStreamArray.h"
|
||||||
#include "llvm/Support/BinaryStreamReader.h"
|
#include "llvm/Support/BinaryStreamReader.h"
|
||||||
@ -28,7 +29,10 @@ struct LineFragmentHeader {
|
|||||||
|
|
||||||
// Corresponds to the `CV_DebugSLinesFileBlockHeader_t` structure.
|
// Corresponds to the `CV_DebugSLinesFileBlockHeader_t` structure.
|
||||||
struct LineBlockFragmentHeader {
|
struct LineBlockFragmentHeader {
|
||||||
support::ulittle32_t NameIndex; // Index in DBI name buffer of filename.
|
support::ulittle32_t NameIndex; // Offset of FileChecksum entry in File
|
||||||
|
// checksums buffer. The checksum entry then
|
||||||
|
// contains another offset into the string
|
||||||
|
// table of the actual name.
|
||||||
support::ulittle32_t NumLines; // Number of lines
|
support::ulittle32_t NumLines; // Number of lines
|
||||||
support::ulittle32_t BlockSize; // Code size of block, in bytes.
|
support::ulittle32_t BlockSize; // Code size of block, in bytes.
|
||||||
// The following two variable length arrays appear immediately after the
|
// The following two variable length arrays appear immediately after the
|
||||||
@ -88,6 +92,45 @@ private:
|
|||||||
const LineFragmentHeader *Header = nullptr;
|
const LineFragmentHeader *Header = nullptr;
|
||||||
LineInfoArray LinesAndColumns;
|
LineInfoArray LinesAndColumns;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ModuleDebugLineFragment final : public ModuleDebugFragment {
|
||||||
|
struct Block {
|
||||||
|
Block(uint32_t ChecksumBufferOffset)
|
||||||
|
: ChecksumBufferOffset(ChecksumBufferOffset) {}
|
||||||
|
|
||||||
|
uint32_t ChecksumBufferOffset;
|
||||||
|
std::vector<LineNumberEntry> Lines;
|
||||||
|
std::vector<ColumnNumberEntry> Columns;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
ModuleDebugLineFragment();
|
||||||
|
|
||||||
|
static bool classof(const ModuleDebugFragment *S) {
|
||||||
|
return S->kind() == ModuleDebugFragmentKind::Lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
void createBlock(uint32_t ChecksumBufferOffset);
|
||||||
|
void addLineInfo(uint32_t Offset, const LineInfo &Line);
|
||||||
|
void addLineAndColumnInfo(uint32_t Offset, const LineInfo &Line,
|
||||||
|
uint32_t ColStart, uint32_t ColEnd);
|
||||||
|
|
||||||
|
uint32_t calculateSerializedLength() override;
|
||||||
|
Error commit(BinaryStreamWriter &Writer) override;
|
||||||
|
|
||||||
|
void setRelocationAddress(uint16_t Segment, uint16_t Offset);
|
||||||
|
void setCodeSize(uint32_t Size);
|
||||||
|
void setFlags(LineFlags Flags);
|
||||||
|
|
||||||
|
bool hasColumnInfo() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint16_t RelocOffset = 0;
|
||||||
|
uint16_t RelocSegment = 0;
|
||||||
|
uint32_t CodeSize = 0;
|
||||||
|
LineFlags Flags = LF_None;
|
||||||
|
std::vector<Block> Blocks;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ public:
|
|||||||
StringRef getTypeName(TypeIndex Index) const;
|
StringRef getTypeName(TypeIndex Index) const;
|
||||||
|
|
||||||
const CVType &getTypeRecord(TypeIndex Index) const;
|
const CVType &getTypeRecord(TypeIndex Index) const;
|
||||||
|
CVType &getTypeRecord(TypeIndex Index);
|
||||||
|
|
||||||
bool containsTypeIndex(TypeIndex Index) const;
|
bool containsTypeIndex(TypeIndex Index) const;
|
||||||
|
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
#define LLVM_DEBUGINFO_PDB_RAW_DBIMODULEDESCRIPTORBUILDER_H
|
#define LLVM_DEBUGINFO_PDB_RAW_DBIMODULEDESCRIPTORBUILDER_H
|
||||||
|
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
|
||||||
|
#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
|
||||||
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
|
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
|
||||||
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
|
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
@ -21,6 +23,10 @@
|
|||||||
namespace llvm {
|
namespace llvm {
|
||||||
class BinaryStreamWriter;
|
class BinaryStreamWriter;
|
||||||
|
|
||||||
|
namespace codeview {
|
||||||
|
class ModuleDebugFragmentRecordBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
namespace msf {
|
namespace msf {
|
||||||
class MSFBuilder;
|
class MSFBuilder;
|
||||||
struct MSFLayout;
|
struct MSFLayout;
|
||||||
@ -33,6 +39,7 @@ class DbiModuleDescriptorBuilder {
|
|||||||
public:
|
public:
|
||||||
DbiModuleDescriptorBuilder(StringRef ModuleName, uint32_t ModIndex,
|
DbiModuleDescriptorBuilder(StringRef ModuleName, uint32_t ModIndex,
|
||||||
msf::MSFBuilder &Msf);
|
msf::MSFBuilder &Msf);
|
||||||
|
~DbiModuleDescriptorBuilder();
|
||||||
|
|
||||||
DbiModuleDescriptorBuilder(const DbiModuleDescriptorBuilder &) = delete;
|
DbiModuleDescriptorBuilder(const DbiModuleDescriptorBuilder &) = delete;
|
||||||
DbiModuleDescriptorBuilder &
|
DbiModuleDescriptorBuilder &
|
||||||
@ -41,6 +48,11 @@ public:
|
|||||||
void setObjFileName(StringRef Name);
|
void setObjFileName(StringRef Name);
|
||||||
void addSymbol(codeview::CVSymbol Symbol);
|
void addSymbol(codeview::CVSymbol Symbol);
|
||||||
|
|
||||||
|
void
|
||||||
|
addC13LineFragment(std::unique_ptr<codeview::ModuleDebugLineFragment> Lines);
|
||||||
|
void setC13FileChecksums(
|
||||||
|
std::unique_ptr<codeview::ModuleDebugFileChecksumFragment> Checksums);
|
||||||
|
|
||||||
uint16_t getStreamIndex() const;
|
uint16_t getStreamIndex() const;
|
||||||
StringRef getModuleName() const { return ModuleName; }
|
StringRef getModuleName() const { return ModuleName; }
|
||||||
StringRef getObjFileName() const { return ObjFileName; }
|
StringRef getObjFileName() const { return ObjFileName; }
|
||||||
@ -58,6 +70,8 @@ public:
|
|||||||
WritableBinaryStreamRef MsfBuffer);
|
WritableBinaryStreamRef MsfBuffer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
uint32_t calculateC13DebugInfoSize() const;
|
||||||
|
|
||||||
void addSourceFile(StringRef Path);
|
void addSourceFile(StringRef Path);
|
||||||
msf::MSFBuilder &MSF;
|
msf::MSFBuilder &MSF;
|
||||||
|
|
||||||
@ -66,6 +80,12 @@ private:
|
|||||||
std::string ObjFileName;
|
std::string ObjFileName;
|
||||||
std::vector<std::string> SourceFiles;
|
std::vector<std::string> SourceFiles;
|
||||||
std::vector<codeview::CVSymbol> Symbols;
|
std::vector<codeview::CVSymbol> Symbols;
|
||||||
|
std::vector<std::unique_ptr<codeview::ModuleDebugLineFragment>> LineInfo;
|
||||||
|
std::unique_ptr<codeview::ModuleDebugFileChecksumFragment> ChecksumInfo;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<codeview::ModuleDebugFragmentRecordBuilder>>
|
||||||
|
C13Builders;
|
||||||
|
|
||||||
ModuleInfoHeader Layout;
|
ModuleInfoHeader Layout;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@ public:
|
|||||||
|
|
||||||
Expected<DbiModuleDescriptorBuilder &> addModuleInfo(StringRef ModuleName);
|
Expected<DbiModuleDescriptorBuilder &> addModuleInfo(StringRef ModuleName);
|
||||||
Error addModuleSourceFile(StringRef Module, StringRef File);
|
Error addModuleSourceFile(StringRef Module, StringRef File);
|
||||||
|
Expected<uint32_t> getSourceFileNameIndex(StringRef FileName);
|
||||||
|
|
||||||
Error finalizeMsfLayout();
|
Error finalizeMsfLayout();
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ public:
|
|||||||
// If string S does not exist in the string table, insert it.
|
// If string S does not exist in the string table, insert it.
|
||||||
// Returns the ID for S.
|
// Returns the ID for S.
|
||||||
uint32_t insert(StringRef S);
|
uint32_t insert(StringRef S);
|
||||||
|
uint32_t getStringIndex(StringRef S);
|
||||||
|
|
||||||
uint32_t finalize();
|
uint32_t finalize();
|
||||||
Error commit(BinaryStreamWriter &Writer) const;
|
Error commit(BinaryStreamWriter &Writer) const;
|
||||||
|
@ -48,3 +48,50 @@ Error ModuleDebugFileChecksumFragmentRef::initialize(
|
|||||||
|
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModuleDebugFileChecksumFragment::ModuleDebugFileChecksumFragment()
|
||||||
|
: ModuleDebugFragment(ModuleDebugFragmentKind::FileChecksums) {}
|
||||||
|
|
||||||
|
void ModuleDebugFileChecksumFragment::addChecksum(uint32_t StringTableOffset,
|
||||||
|
FileChecksumKind Kind,
|
||||||
|
ArrayRef<uint8_t> Bytes) {
|
||||||
|
FileChecksumEntry Entry;
|
||||||
|
if (!Bytes.empty()) {
|
||||||
|
uint8_t *Copy = Storage.Allocate<uint8_t>(Bytes.size());
|
||||||
|
::memcpy(Copy, Bytes.data(), Bytes.size());
|
||||||
|
Entry.Checksum = makeArrayRef(Copy, Bytes.size());
|
||||||
|
}
|
||||||
|
Entry.FileNameOffset = StringTableOffset;
|
||||||
|
Entry.Kind = Kind;
|
||||||
|
Checksums.push_back(Entry);
|
||||||
|
|
||||||
|
// This maps the offset of this string in the string table to the offset
|
||||||
|
// of this checksum entry in the checksum buffer.
|
||||||
|
OffsetMap[StringTableOffset] = SerializedSize;
|
||||||
|
SerializedSize += sizeof(FileChecksumEntryHeader) + Bytes.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ModuleDebugFileChecksumFragment::calculateSerializedLength() {
|
||||||
|
return SerializedSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error ModuleDebugFileChecksumFragment::commit(BinaryStreamWriter &Writer) {
|
||||||
|
for (const auto &FC : Checksums) {
|
||||||
|
FileChecksumEntryHeader Header;
|
||||||
|
Header.ChecksumKind = uint8_t(FC.Kind);
|
||||||
|
Header.ChecksumSize = FC.Checksum.size();
|
||||||
|
Header.FileNameOffset = FC.FileNameOffset;
|
||||||
|
if (auto EC = Writer.writeObject(Header))
|
||||||
|
return EC;
|
||||||
|
if (auto EC = Writer.writeArray(makeArrayRef(FC.Checksum)))
|
||||||
|
return EC;
|
||||||
|
}
|
||||||
|
return Error::success();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ModuleDebugFileChecksumFragment::mapChecksumOffset(
|
||||||
|
uint32_t StringTableOffset) const {
|
||||||
|
auto Iter = OffsetMap.find(StringTableOffset);
|
||||||
|
assert(Iter != OffsetMap.end());
|
||||||
|
return Iter->second;
|
||||||
|
}
|
||||||
|
@ -12,3 +12,5 @@
|
|||||||
using namespace llvm::codeview;
|
using namespace llvm::codeview;
|
||||||
|
|
||||||
ModuleDebugFragmentRef::~ModuleDebugFragmentRef() {}
|
ModuleDebugFragmentRef::~ModuleDebugFragmentRef() {}
|
||||||
|
|
||||||
|
ModuleDebugFragment::~ModuleDebugFragment() {}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h"
|
#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h"
|
||||||
|
#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
|
||||||
|
|
||||||
#include "llvm/Support/BinaryStreamReader.h"
|
#include "llvm/Support/BinaryStreamReader.h"
|
||||||
|
|
||||||
@ -30,6 +31,13 @@ Error ModuleDebugFragmentRecord::initialize(BinaryStreamRef Stream,
|
|||||||
|
|
||||||
ModuleDebugFragmentKind Kind =
|
ModuleDebugFragmentKind Kind =
|
||||||
static_cast<ModuleDebugFragmentKind>(uint32_t(Header->Kind));
|
static_cast<ModuleDebugFragmentKind>(uint32_t(Header->Kind));
|
||||||
|
switch (Kind) {
|
||||||
|
case ModuleDebugFragmentKind::FileChecksums:
|
||||||
|
case ModuleDebugFragmentKind::Lines:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
llvm_unreachable("Unexpected debug fragment kind!");
|
||||||
|
}
|
||||||
if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))
|
if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))
|
||||||
return EC;
|
return EC;
|
||||||
Info.Kind = Kind;
|
Info.Kind = Kind;
|
||||||
@ -37,7 +45,9 @@ Error ModuleDebugFragmentRecord::initialize(BinaryStreamRef Stream,
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ModuleDebugFragmentRecord::getRecordLength() const {
|
uint32_t ModuleDebugFragmentRecord::getRecordLength() const {
|
||||||
return sizeof(ModuleDebugFragmentHeader) + Data.getLength();
|
uint32_t Result = sizeof(ModuleDebugFragmentHeader) + Data.getLength();
|
||||||
|
assert(Result % 4 == 0);
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleDebugFragmentKind ModuleDebugFragmentRecord::kind() const { return Kind; }
|
ModuleDebugFragmentKind ModuleDebugFragmentRecord::kind() const { return Kind; }
|
||||||
@ -45,3 +55,29 @@ ModuleDebugFragmentKind ModuleDebugFragmentRecord::kind() const { return Kind; }
|
|||||||
BinaryStreamRef ModuleDebugFragmentRecord::getRecordData() const {
|
BinaryStreamRef ModuleDebugFragmentRecord::getRecordData() const {
|
||||||
return Data;
|
return Data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModuleDebugFragmentRecordBuilder::ModuleDebugFragmentRecordBuilder(
|
||||||
|
ModuleDebugFragmentKind Kind, ModuleDebugFragment &Frag)
|
||||||
|
: Kind(Kind), Frag(Frag) {}
|
||||||
|
|
||||||
|
uint32_t ModuleDebugFragmentRecordBuilder::calculateSerializedLength() {
|
||||||
|
uint32_t Size = sizeof(ModuleDebugFragmentHeader) +
|
||||||
|
alignTo(Frag.calculateSerializedLength(), 4);
|
||||||
|
return Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error ModuleDebugFragmentRecordBuilder::commit(BinaryStreamWriter &Writer) {
|
||||||
|
ModuleDebugFragmentHeader Header;
|
||||||
|
Header.Kind = uint32_t(Kind);
|
||||||
|
Header.Length =
|
||||||
|
calculateSerializedLength() - sizeof(ModuleDebugFragmentHeader);
|
||||||
|
|
||||||
|
if (auto EC = Writer.writeObject(Header))
|
||||||
|
return EC;
|
||||||
|
if (auto EC = Frag.commit(Writer))
|
||||||
|
return EC;
|
||||||
|
if (auto EC = Writer.padToAlignment(4))
|
||||||
|
return EC;
|
||||||
|
|
||||||
|
return Error::success();
|
||||||
|
}
|
||||||
|
@ -64,3 +64,92 @@ Error ModuleDebugLineFragmentRef::initialize(BinaryStreamReader Reader) {
|
|||||||
bool ModuleDebugLineFragmentRef::hasColumnInfo() const {
|
bool ModuleDebugLineFragmentRef::hasColumnInfo() const {
|
||||||
return !!(Header->Flags & LF_HaveColumns);
|
return !!(Header->Flags & LF_HaveColumns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModuleDebugLineFragment::ModuleDebugLineFragment()
|
||||||
|
: ModuleDebugFragment(ModuleDebugFragmentKind::Lines) {}
|
||||||
|
|
||||||
|
void ModuleDebugLineFragment::createBlock(uint32_t ChecksumBufferOffset) {
|
||||||
|
Blocks.emplace_back(ChecksumBufferOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModuleDebugLineFragment::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 ModuleDebugLineFragment::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 ModuleDebugLineFragment::commit(BinaryStreamWriter &Writer) {
|
||||||
|
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 ModuleDebugLineFragment::calculateSerializedLength() {
|
||||||
|
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 ModuleDebugLineFragment::setRelocationAddress(uint16_t Segment,
|
||||||
|
uint16_t Offset) {
|
||||||
|
RelocOffset = Offset;
|
||||||
|
RelocSegment = Segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModuleDebugLineFragment::setCodeSize(uint32_t Size) { CodeSize = Size; }
|
||||||
|
|
||||||
|
void ModuleDebugLineFragment::setFlags(LineFlags Flags) { this->Flags = Flags; }
|
||||||
|
|
||||||
|
bool ModuleDebugLineFragment::hasColumnInfo() const {
|
||||||
|
return Flags & LF_HaveColumns;
|
||||||
|
}
|
||||||
|
@ -110,6 +110,10 @@ const CVType &TypeDatabase::getTypeRecord(TypeIndex Index) const {
|
|||||||
return TypeRecords[Index.getIndex() - TypeIndex::FirstNonSimpleIndex];
|
return TypeRecords[Index.getIndex() - TypeIndex::FirstNonSimpleIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CVType &TypeDatabase::getTypeRecord(TypeIndex Index) {
|
||||||
|
return TypeRecords[Index.getIndex() - TypeIndex::FirstNonSimpleIndex];
|
||||||
|
}
|
||||||
|
|
||||||
bool TypeDatabase::containsTypeIndex(TypeIndex Index) const {
|
bool TypeDatabase::containsTypeIndex(TypeIndex Index) const {
|
||||||
uint32_t I = Index.getIndex() - TypeIndex::FirstNonSimpleIndex;
|
uint32_t I = Index.getIndex() - TypeIndex::FirstNonSimpleIndex;
|
||||||
return I < CVUDTNames.size();
|
return I < CVUDTNames.size();
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
|
#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
|
||||||
|
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
|
#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h"
|
||||||
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
|
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
|
||||||
#include "llvm/DebugInfo/MSF/MSFCommon.h"
|
#include "llvm/DebugInfo/MSF/MSFCommon.h"
|
||||||
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
|
||||||
@ -35,11 +36,12 @@ template <> struct BinaryItemTraits<CVSymbol> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize) {
|
static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize,
|
||||||
|
uint32_t C13Size) {
|
||||||
uint32_t Size = sizeof(uint32_t); // Signature
|
uint32_t Size = sizeof(uint32_t); // Signature
|
||||||
Size += SymbolByteSize; // Symbol Data
|
Size += SymbolByteSize; // Symbol Data
|
||||||
Size += 0; // TODO: Layout.LineBytes
|
Size += 0; // TODO: Layout.C11Bytes
|
||||||
Size += 0; // TODO: Layout.C13Bytes
|
Size += C13Size; // C13 Debug Info Size
|
||||||
Size += sizeof(uint32_t); // GlobalRefs substream size (always 0)
|
Size += sizeof(uint32_t); // GlobalRefs substream size (always 0)
|
||||||
Size += 0; // GlobalRefs substream bytes
|
Size += 0; // GlobalRefs substream bytes
|
||||||
return Size;
|
return Size;
|
||||||
@ -52,6 +54,8 @@ DbiModuleDescriptorBuilder::DbiModuleDescriptorBuilder(StringRef ModuleName,
|
|||||||
Layout.Mod = ModIndex;
|
Layout.Mod = ModIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DbiModuleDescriptorBuilder::~DbiModuleDescriptorBuilder() {}
|
||||||
|
|
||||||
uint16_t DbiModuleDescriptorBuilder::getStreamIndex() const {
|
uint16_t DbiModuleDescriptorBuilder::getStreamIndex() const {
|
||||||
return Layout.ModDiStream;
|
return Layout.ModDiStream;
|
||||||
}
|
}
|
||||||
@ -69,6 +73,15 @@ void DbiModuleDescriptorBuilder::addSourceFile(StringRef Path) {
|
|||||||
SourceFiles.push_back(Path);
|
SourceFiles.push_back(Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t DbiModuleDescriptorBuilder::calculateC13DebugInfoSize() const {
|
||||||
|
uint32_t Result = 0;
|
||||||
|
for (const auto &Builder : C13Builders) {
|
||||||
|
assert(Builder && "Empty C13 Fragment Builder!");
|
||||||
|
Result += Builder->calculateSerializedLength();
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t DbiModuleDescriptorBuilder::calculateSerializedLength() const {
|
uint32_t DbiModuleDescriptorBuilder::calculateSerializedLength() const {
|
||||||
uint32_t L = sizeof(Layout);
|
uint32_t L = sizeof(Layout);
|
||||||
uint32_t M = ModuleName.size() + 1;
|
uint32_t M = ModuleName.size() + 1;
|
||||||
@ -80,7 +93,7 @@ void DbiModuleDescriptorBuilder::finalize() {
|
|||||||
Layout.FileNameOffs = 0; // TODO: Fix this
|
Layout.FileNameOffs = 0; // TODO: Fix this
|
||||||
Layout.Flags = 0; // TODO: Fix this
|
Layout.Flags = 0; // TODO: Fix this
|
||||||
Layout.C11Bytes = 0;
|
Layout.C11Bytes = 0;
|
||||||
Layout.C13Bytes = 0;
|
Layout.C13Bytes = calculateC13DebugInfoSize();
|
||||||
(void)Layout.Mod; // Set in constructor
|
(void)Layout.Mod; // Set in constructor
|
||||||
(void)Layout.ModDiStream; // Set in finalizeMsfLayout
|
(void)Layout.ModDiStream; // Set in finalizeMsfLayout
|
||||||
Layout.NumFiles = SourceFiles.size();
|
Layout.NumFiles = SourceFiles.size();
|
||||||
@ -94,7 +107,9 @@ void DbiModuleDescriptorBuilder::finalize() {
|
|||||||
|
|
||||||
Error DbiModuleDescriptorBuilder::finalizeMsfLayout() {
|
Error DbiModuleDescriptorBuilder::finalizeMsfLayout() {
|
||||||
this->Layout.ModDiStream = kInvalidStreamIndex;
|
this->Layout.ModDiStream = kInvalidStreamIndex;
|
||||||
auto ExpectedSN = MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize));
|
uint32_t C13Size = calculateC13DebugInfoSize();
|
||||||
|
auto ExpectedSN =
|
||||||
|
MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize, C13Size));
|
||||||
if (!ExpectedSN)
|
if (!ExpectedSN)
|
||||||
return ExpectedSN.takeError();
|
return ExpectedSN.takeError();
|
||||||
Layout.ModDiStream = *ExpectedSN;
|
Layout.ModDiStream = *ExpectedSN;
|
||||||
@ -130,7 +145,13 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter,
|
|||||||
if (auto EC = SymbolWriter.writeStreamRef(RecordsRef))
|
if (auto EC = SymbolWriter.writeStreamRef(RecordsRef))
|
||||||
return EC;
|
return EC;
|
||||||
// TODO: Write C11 Line data
|
// TODO: Write C11 Line data
|
||||||
// TODO: Write C13 Line data
|
|
||||||
|
for (const auto &Builder : C13Builders) {
|
||||||
|
assert(Builder && "Empty C13 Fragment Builder!");
|
||||||
|
if (auto EC = Builder->commit(SymbolWriter))
|
||||||
|
return EC;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Figure out what GlobalRefs substream actually is and populate it.
|
// TODO: Figure out what GlobalRefs substream actually is and populate it.
|
||||||
if (auto EC = SymbolWriter.writeInteger<uint32_t>(0))
|
if (auto EC = SymbolWriter.writeInteger<uint32_t>(0))
|
||||||
return EC;
|
return EC;
|
||||||
@ -139,3 +160,29 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter,
|
|||||||
}
|
}
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DbiModuleDescriptorBuilder::addC13LineFragment(
|
||||||
|
std::unique_ptr<ModuleDebugLineFragment> Lines) {
|
||||||
|
ModuleDebugLineFragment &Frag = *Lines;
|
||||||
|
|
||||||
|
// File Checksums have to come first, so push an empty entry on if this
|
||||||
|
// is the first.
|
||||||
|
if (C13Builders.empty())
|
||||||
|
C13Builders.push_back(nullptr);
|
||||||
|
|
||||||
|
this->LineInfo.push_back(std::move(Lines));
|
||||||
|
C13Builders.push_back(
|
||||||
|
llvm::make_unique<ModuleDebugFragmentRecordBuilder>(Frag.kind(), Frag));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DbiModuleDescriptorBuilder::setC13FileChecksums(
|
||||||
|
std::unique_ptr<ModuleDebugFileChecksumFragment> Checksums) {
|
||||||
|
assert(!ChecksumInfo && "Can't have more than one checksum info!");
|
||||||
|
|
||||||
|
if (C13Builders.empty())
|
||||||
|
C13Builders.push_back(nullptr);
|
||||||
|
|
||||||
|
ChecksumInfo = std::move(Checksums);
|
||||||
|
C13Builders[0] = llvm::make_unique<ModuleDebugFragmentRecordBuilder>(
|
||||||
|
ChecksumInfo->kind(), *ChecksumInfo);
|
||||||
|
}
|
||||||
|
@ -101,6 +101,14 @@ Error DbiStreamBuilder::addModuleSourceFile(StringRef Module, StringRef File) {
|
|||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expected<uint32_t> DbiStreamBuilder::getSourceFileNameIndex(StringRef File) {
|
||||||
|
auto NameIter = SourceFileNames.find(File);
|
||||||
|
if (NameIter == SourceFileNames.end())
|
||||||
|
return make_error<RawError>(raw_error_code::no_entry,
|
||||||
|
"The specified source file was not found");
|
||||||
|
return NameIter->getValue();
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t DbiStreamBuilder::calculateModiSubstreamSize() const {
|
uint32_t DbiStreamBuilder::calculateModiSubstreamSize() const {
|
||||||
uint32_t Size = 0;
|
uint32_t Size = 0;
|
||||||
for (const auto &M : ModiList)
|
for (const auto &M : ModiList)
|
||||||
|
@ -29,6 +29,12 @@ uint32_t StringTableBuilder::insert(StringRef S) {
|
|||||||
return P.first->second;
|
return P.first->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t StringTableBuilder::getStringIndex(StringRef S) {
|
||||||
|
auto Iter = Strings.find(S);
|
||||||
|
assert(Iter != Strings.end());
|
||||||
|
return Iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t computeBucketCount(uint32_t NumStrings) {
|
static uint32_t computeBucketCount(uint32_t NumStrings) {
|
||||||
// The /names stream is basically an on-disk open-addressing hash table.
|
// The /names stream is basically an on-disk open-addressing hash table.
|
||||||
// Hash collisions are resolved by linear probing. We cannot make
|
// Hash collisions are resolved by linear probing. We cannot make
|
||||||
|
38
test/DebugInfo/PDB/Inputs/simple-line-info.yaml
Normal file
38
test/DebugInfo/PDB/Inputs/simple-line-info.yaml
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
StringTable:
|
||||||
|
- 'junk_a'
|
||||||
|
- 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
|
||||||
|
- 'junk_b'
|
||||||
|
DbiStream:
|
||||||
|
Modules:
|
||||||
|
- Module: 'd:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj'
|
||||||
|
ObjFile: 'd:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj'
|
||||||
|
SourceFiles:
|
||||||
|
- 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
|
||||||
|
LineInfo:
|
||||||
|
Checksums:
|
||||||
|
- FileName: 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
|
||||||
|
Kind: MD5
|
||||||
|
Checksum: A0A5BD0D3ECD93FC29D19DE826FBF4BC
|
||||||
|
Lines:
|
||||||
|
- CodeSize: 10
|
||||||
|
Flags: [ ]
|
||||||
|
RelocOffset: 16
|
||||||
|
RelocSegment: 1
|
||||||
|
Blocks:
|
||||||
|
- FileName: 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
|
||||||
|
Lines:
|
||||||
|
- Offset: 0
|
||||||
|
LineStart: 5
|
||||||
|
IsStatement: true
|
||||||
|
EndDelta: 0
|
||||||
|
- Offset: 3
|
||||||
|
LineStart: 6
|
||||||
|
IsStatement: true
|
||||||
|
EndDelta: 0
|
||||||
|
- Offset: 8
|
||||||
|
LineStart: 7
|
||||||
|
IsStatement: true
|
||||||
|
EndDelta: 0
|
||||||
|
Columns:
|
||||||
|
...
|
@ -495,11 +495,11 @@
|
|||||||
; EMPTY-NEXT: }
|
; EMPTY-NEXT: }
|
||||||
; EMPTY-NEXT: }
|
; EMPTY-NEXT: }
|
||||||
; EMPTY-NEXT: Lines {
|
; EMPTY-NEXT: Lines {
|
||||||
; EMPTY-NEXT: LineFragment {
|
; EMPTY-NEXT: Block {
|
||||||
; EMPTY-NEXT: RelocSegment: 1
|
; EMPTY-NEXT: RelocSegment: 1
|
||||||
; EMPTY-NEXT: RelocOffset: 16
|
; EMPTY-NEXT: RelocOffset: 16
|
||||||
; EMPTY-NEXT: CodeSize: 10
|
; EMPTY-NEXT: CodeSize: 10
|
||||||
; EMPTY-NEXT: HasColumns: 0
|
; EMPTY-NEXT: HasColumns: No
|
||||||
; EMPTY-NEXT: Lines {
|
; EMPTY-NEXT: Lines {
|
||||||
; EMPTY-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
|
; EMPTY-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
|
||||||
; EMPTY-NEXT: Line {
|
; EMPTY-NEXT: Line {
|
||||||
|
52
test/DebugInfo/PDB/pdbdump-yaml-lineinfo-write.test
Normal file
52
test/DebugInfo/PDB/pdbdump-yaml-lineinfo-write.test
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
; This testcase verifies that we can produce a PDB with line
|
||||||
|
; information. It does this by describing some line information
|
||||||
|
; manually in YAML, creating a PDB out of it, then dumping then
|
||||||
|
; line information from the resulting PDB.
|
||||||
|
|
||||||
|
; RUN: llvm-pdbdump yaml2pdb -pdb=%t.pdb %p/Inputs/simple-line-info.yaml
|
||||||
|
; RUN: llvm-pdbdump raw -line-info %t.pdb | FileCheck -check-prefix=LINES %s
|
||||||
|
|
||||||
|
LINES: Modules [
|
||||||
|
LINES-NEXT: {
|
||||||
|
LINES-NEXT: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
|
||||||
|
LINES: LineInfo [
|
||||||
|
LINES-NEXT: FileChecksums {
|
||||||
|
LINES-NEXT: Checksum {
|
||||||
|
LINES-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
|
||||||
|
LINES-NEXT: Kind: MD5 (0x1)
|
||||||
|
LINES-NEXT: Checksum (
|
||||||
|
LINES-NEXT: 0000: A0A5BD0D 3ECD93FC 29D19DE8 26FBF4BC |....>...)...&...|
|
||||||
|
LINES-NEXT: )
|
||||||
|
LINES-NEXT: }
|
||||||
|
LINES-NEXT: }
|
||||||
|
LINES-NEXT: Lines {
|
||||||
|
LINES-NEXT: Block {
|
||||||
|
LINES-NEXT: RelocSegment: 1
|
||||||
|
LINES-NEXT: RelocOffset: 16
|
||||||
|
LINES-NEXT: CodeSize: 10
|
||||||
|
LINES-NEXT: HasColumns: No
|
||||||
|
LINES-NEXT: Lines {
|
||||||
|
LINES-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
|
||||||
|
LINES-NEXT: Line {
|
||||||
|
LINES-NEXT: Offset: 0
|
||||||
|
LINES-NEXT: LineNumberStart: 5
|
||||||
|
LINES-NEXT: EndDelta: 0
|
||||||
|
LINES-NEXT: IsStatement: Yes
|
||||||
|
LINES-NEXT: }
|
||||||
|
LINES-NEXT: Line {
|
||||||
|
LINES-NEXT: Offset: 3
|
||||||
|
LINES-NEXT: LineNumberStart: 6
|
||||||
|
LINES-NEXT: EndDelta: 0
|
||||||
|
LINES-NEXT: IsStatement: Yes
|
||||||
|
LINES-NEXT: }
|
||||||
|
LINES-NEXT: Line {
|
||||||
|
LINES-NEXT: Offset: 8
|
||||||
|
LINES-NEXT: LineNumberStart: 7
|
||||||
|
LINES-NEXT: EndDelta: 0
|
||||||
|
LINES-NEXT: IsStatement: Yes
|
||||||
|
LINES-NEXT: }
|
||||||
|
LINES-NEXT: }
|
||||||
|
LINES-NEXT: }
|
||||||
|
LINES-NEXT: }
|
||||||
|
LINES-NEXT: ]
|
||||||
|
LINES-NEXT: }
|
@ -89,11 +89,11 @@ public:
|
|||||||
DictScope DD(P, "Lines");
|
DictScope DD(P, "Lines");
|
||||||
|
|
||||||
for (const auto &Fragment : Lines) {
|
for (const auto &Fragment : Lines) {
|
||||||
DictScope DDD(P, "LineFragment");
|
DictScope DDD(P, "Block");
|
||||||
P.printNumber("RelocSegment", Fragment.header()->RelocSegment);
|
P.printNumber("RelocSegment", Fragment.header()->RelocSegment);
|
||||||
P.printNumber("RelocOffset", Fragment.header()->RelocOffset);
|
P.printNumber("RelocOffset", Fragment.header()->RelocOffset);
|
||||||
P.printNumber("CodeSize", Fragment.header()->CodeSize);
|
P.printNumber("CodeSize", Fragment.header()->CodeSize);
|
||||||
P.printNumber("HasColumns", Fragment.hasColumnInfo());
|
P.printBoolean("HasColumns", Fragment.hasColumnInfo());
|
||||||
|
|
||||||
for (const auto &L : Fragment) {
|
for (const auto &L : Fragment) {
|
||||||
DictScope DDDD(P, "Lines");
|
DictScope DDDD(P, "Lines");
|
||||||
@ -557,6 +557,7 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
|
|||||||
|
|
||||||
bool IsSilentDatabaseBuild = !DumpRecordBytes && !DumpRecords && !DumpTpiHash;
|
bool IsSilentDatabaseBuild = !DumpRecordBytes && !DumpRecords && !DumpTpiHash;
|
||||||
if (IsSilentDatabaseBuild) {
|
if (IsSilentDatabaseBuild) {
|
||||||
|
outs().flush();
|
||||||
errs() << "Building Type Information For " << Label << "\n";
|
errs() << "Building Type Information For " << Label << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,8 +286,7 @@ Error YAMLOutputStyle::dumpDbiStream() {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto ModStreamData = msf::MappedBlockStream::createIndexedStream(
|
auto ModStreamData = msf::MappedBlockStream::createIndexedStream(
|
||||||
File.getMsfLayout(), File.getMsfBuffer(),
|
File.getMsfLayout(), File.getMsfBuffer(), ModiStream);
|
||||||
MI.Info.getModuleStreamIndex());
|
|
||||||
|
|
||||||
pdb::ModuleDebugStreamRef ModS(MI.Info, std::move(ModStreamData));
|
pdb::ModuleDebugStreamRef ModS(MI.Info, std::move(ModStreamData));
|
||||||
if (auto EC = ModS.reload())
|
if (auto EC = ModS.reload())
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/BitVector.h"
|
#include "llvm/ADT/BitVector.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
#include "llvm/Config/config.h"
|
#include "llvm/Config/config.h"
|
||||||
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
|
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
|
||||||
@ -491,6 +492,67 @@ static void yamlToPdb(StringRef Path) {
|
|||||||
for (auto Symbol : ModiStream.Symbols)
|
for (auto Symbol : ModiStream.Symbols)
|
||||||
ModiBuilder.addSymbol(Symbol.Record);
|
ModiBuilder.addSymbol(Symbol.Record);
|
||||||
}
|
}
|
||||||
|
if (MI.FileLineInfo.hasValue()) {
|
||||||
|
const auto &FLI = *MI.FileLineInfo;
|
||||||
|
|
||||||
|
// File Checksums must be emitted before line information, because line
|
||||||
|
// info records use offsets into the checksum buffer to reference a file's
|
||||||
|
// source file name.
|
||||||
|
auto Checksums = llvm::make_unique<ModuleDebugFileChecksumFragment>();
|
||||||
|
auto &ChecksumRef = *Checksums;
|
||||||
|
if (!FLI.FileChecksums.empty()) {
|
||||||
|
auto &Strings = Builder.getStringTableBuilder();
|
||||||
|
for (auto &FC : FLI.FileChecksums) {
|
||||||
|
uint32_t STOffset = Strings.getStringIndex(FC.FileName);
|
||||||
|
Checksums->addChecksum(STOffset, FC.Kind, FC.ChecksumBytes.Bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ModiBuilder.setC13FileChecksums(std::move(Checksums));
|
||||||
|
|
||||||
|
for (const auto &Fragment : FLI.LineFragments) {
|
||||||
|
auto Lines = llvm::make_unique<ModuleDebugLineFragment>();
|
||||||
|
Lines->setCodeSize(Fragment.CodeSize);
|
||||||
|
Lines->setRelocationAddress(Fragment.RelocSegment,
|
||||||
|
Fragment.RelocOffset);
|
||||||
|
Lines->setFlags(Fragment.Flags);
|
||||||
|
for (const auto &LC : Fragment.Blocks) {
|
||||||
|
// FIXME: StringTable / StringTableBuilder should really be in
|
||||||
|
// DebugInfoCodeView. This would allow us to construct the
|
||||||
|
// ModuleDebugLineFragment with a reference to the string table,
|
||||||
|
// and we could just pass strings around rather than having to
|
||||||
|
// remember how to calculate the right offset.
|
||||||
|
auto &Strings = Builder.getStringTableBuilder();
|
||||||
|
// The offset in the line info record is the offset of the checksum
|
||||||
|
// entry for the corresponding file. That entry then contains an
|
||||||
|
// offset into the global string table of the file name. So to
|
||||||
|
// compute the proper offset to write into the line info record, we
|
||||||
|
// must first get its offset in the global string table, then ask the
|
||||||
|
// checksum builder to find the offset in its serialized buffer that
|
||||||
|
// it mapped that filename string table offset to.
|
||||||
|
uint32_t StringOffset = Strings.getStringIndex(LC.FileName);
|
||||||
|
uint32_t ChecksumOffset = ChecksumRef.mapChecksumOffset(StringOffset);
|
||||||
|
|
||||||
|
Lines->createBlock(ChecksumOffset);
|
||||||
|
if (Lines->hasColumnInfo()) {
|
||||||
|
for (const auto &Item : zip(LC.Lines, LC.Columns)) {
|
||||||
|
auto &L = std::get<0>(Item);
|
||||||
|
auto &C = std::get<1>(Item);
|
||||||
|
uint32_t LE = L.LineStart + L.EndDelta;
|
||||||
|
Lines->addLineAndColumnInfo(
|
||||||
|
L.Offset, LineInfo(L.LineStart, LE, L.IsStatement),
|
||||||
|
C.StartColumn, C.EndColumn);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const auto &L : LC.Lines) {
|
||||||
|
uint32_t LE = L.LineStart + L.EndDelta;
|
||||||
|
Lines->addLineInfo(L.Offset,
|
||||||
|
LineInfo(L.LineStart, LE, L.IsStatement));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ModiBuilder.addC13LineFragment(std::move(Lines));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &TpiBuilder = Builder.getTpiBuilder();
|
auto &TpiBuilder = Builder.getTpiBuilder();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user