mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-09 01:36:04 +00:00

The raw CodeView format references strings by "offsets", but it's confusing what table the offset refers to. In the case of line number information, it's an offset into a buffer of records, and an indirection is required to get another offset into a different table to find the final string. And in the case of checksum information, there is no indirection, and the offset refers directly to the location of the string in another buffer. This would be less confusing if we always just referred to the strings by their value, and have the library be smart enough to correctly resolve the offsets on its own from the right location. This patch makes that possible. When either reading or writing, all the user deals with are strings, and the library does the appropriate translations behind the scenes. llvm-svn: 302053
108 lines
3.6 KiB
C++
108 lines
3.6 KiB
C++
//===- 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/DebugInfo/CodeView/StringTable.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) {
|
|
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 ModuleDebugFileChecksumFragmentRef::initialize(
|
|
BinaryStreamReader Reader) {
|
|
if (auto EC = Reader.readArray(Checksums, Reader.bytesRemaining()))
|
|
return EC;
|
|
|
|
return Error::success();
|
|
}
|
|
|
|
ModuleDebugFileChecksumFragment::ModuleDebugFileChecksumFragment(
|
|
StringTable &Strings)
|
|
: ModuleDebugFragment(ModuleDebugFragmentKind::FileChecksums),
|
|
Strings(Strings) {}
|
|
|
|
void ModuleDebugFileChecksumFragment::addChecksum(StringRef FileName,
|
|
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 = Strings.insert(FileName);
|
|
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[Entry.FileNameOffset] = SerializedSize;
|
|
assert(SerializedSize % 4 == 0);
|
|
|
|
uint32_t Len = alignTo(sizeof(FileChecksumEntryHeader) + Bytes.size(), 4);
|
|
SerializedSize += Len;
|
|
}
|
|
|
|
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;
|
|
if (auto EC = Writer.padToAlignment(4))
|
|
return EC;
|
|
}
|
|
return Error::success();
|
|
}
|
|
|
|
uint32_t
|
|
ModuleDebugFileChecksumFragment::mapChecksumOffset(StringRef FileName) const {
|
|
uint32_t Offset = Strings.getStringId(FileName);
|
|
auto Iter = OffsetMap.find(Offset);
|
|
assert(Iter != OffsetMap.end());
|
|
return Iter->second;
|
|
}
|