1a580b014SDimitry Andric //===- DebugChecksumsSubsection.cpp ---------------------------------------===// 289cb50c9SDimitry Andric // 389cb50c9SDimitry Andric // The LLVM Compiler Infrastructure 489cb50c9SDimitry Andric // 589cb50c9SDimitry Andric // This file is distributed under the University of Illinois Open Source 689cb50c9SDimitry Andric // License. See LICENSE.TXT for details. 789cb50c9SDimitry Andric // 889cb50c9SDimitry Andric //===----------------------------------------------------------------------===// 989cb50c9SDimitry Andric 1089cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" 11a580b014SDimitry Andric #include "llvm/ADT/ArrayRef.h" 12a580b014SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeView.h" 1389cb50c9SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" 1489cb50c9SDimitry Andric #include "llvm/Support/BinaryStreamReader.h" 15a580b014SDimitry Andric #include "llvm/Support/BinaryStreamWriter.h" 16a580b014SDimitry Andric #include "llvm/Support/Endian.h" 17a580b014SDimitry Andric #include "llvm/Support/Error.h" 18a580b014SDimitry Andric #include "llvm/Support/MathExtras.h" 19a580b014SDimitry Andric #include <cassert> 20a580b014SDimitry Andric #include <cstdint> 21a580b014SDimitry Andric #include <cstring> 2289cb50c9SDimitry Andric 2389cb50c9SDimitry Andric using namespace llvm; 2489cb50c9SDimitry Andric using namespace llvm::codeview; 2589cb50c9SDimitry Andric 2689cb50c9SDimitry Andric struct FileChecksumEntryHeader { 2789cb50c9SDimitry Andric using ulittle32_t = support::ulittle32_t; 2889cb50c9SDimitry Andric 2989cb50c9SDimitry Andric ulittle32_t FileNameOffset; // Byte offset of filename in global string table. 3089cb50c9SDimitry Andric uint8_t ChecksumSize; // Number of bytes of checksum. 3189cb50c9SDimitry Andric uint8_t ChecksumKind; // FileChecksumKind 3289cb50c9SDimitry Andric // Checksum bytes follow. 3389cb50c9SDimitry Andric }; 3489cb50c9SDimitry Andric 35a580b014SDimitry Andric Error VarStreamArrayExtractor<FileChecksumEntry>:: 36db17bf38SDimitry Andric operator()(BinaryStreamRef Stream, uint32_t &Len, FileChecksumEntry &Item) { 3789cb50c9SDimitry Andric BinaryStreamReader Reader(Stream); 3889cb50c9SDimitry Andric 3989cb50c9SDimitry Andric const FileChecksumEntryHeader *Header; 4089cb50c9SDimitry Andric if (auto EC = Reader.readObject(Header)) 4189cb50c9SDimitry Andric return EC; 4289cb50c9SDimitry Andric 4389cb50c9SDimitry Andric Item.FileNameOffset = Header->FileNameOffset; 4489cb50c9SDimitry Andric Item.Kind = static_cast<FileChecksumKind>(Header->ChecksumKind); 4589cb50c9SDimitry Andric if (auto EC = Reader.readBytes(Item.Checksum, Header->ChecksumSize)) 4689cb50c9SDimitry Andric return EC; 4789cb50c9SDimitry Andric 4889cb50c9SDimitry Andric Len = alignTo(Header->ChecksumSize + sizeof(FileChecksumEntryHeader), 4); 4989cb50c9SDimitry Andric return Error::success(); 5089cb50c9SDimitry Andric } 5189cb50c9SDimitry Andric 5289cb50c9SDimitry Andric Error DebugChecksumsSubsectionRef::initialize(BinaryStreamReader Reader) { 5389cb50c9SDimitry Andric if (auto EC = Reader.readArray(Checksums, Reader.bytesRemaining())) 5489cb50c9SDimitry Andric return EC; 5589cb50c9SDimitry Andric 5689cb50c9SDimitry Andric return Error::success(); 5789cb50c9SDimitry Andric } 58a580b014SDimitry Andric 5989cb50c9SDimitry Andric Error DebugChecksumsSubsectionRef::initialize(BinaryStreamRef Section) { 6089cb50c9SDimitry Andric BinaryStreamReader Reader(Section); 6189cb50c9SDimitry Andric return initialize(Reader); 6289cb50c9SDimitry Andric } 6389cb50c9SDimitry Andric 6489cb50c9SDimitry Andric DebugChecksumsSubsection::DebugChecksumsSubsection( 6589cb50c9SDimitry Andric DebugStringTableSubsection &Strings) 6689cb50c9SDimitry Andric : DebugSubsection(DebugSubsectionKind::FileChecksums), Strings(Strings) {} 6789cb50c9SDimitry Andric 6889cb50c9SDimitry Andric void DebugChecksumsSubsection::addChecksum(StringRef FileName, 6989cb50c9SDimitry Andric FileChecksumKind Kind, 7089cb50c9SDimitry Andric ArrayRef<uint8_t> Bytes) { 7189cb50c9SDimitry Andric FileChecksumEntry Entry; 7289cb50c9SDimitry Andric if (!Bytes.empty()) { 7389cb50c9SDimitry Andric uint8_t *Copy = Storage.Allocate<uint8_t>(Bytes.size()); 7489cb50c9SDimitry Andric ::memcpy(Copy, Bytes.data(), Bytes.size()); 7589cb50c9SDimitry Andric Entry.Checksum = makeArrayRef(Copy, Bytes.size()); 7689cb50c9SDimitry Andric } 7789cb50c9SDimitry Andric 7889cb50c9SDimitry Andric Entry.FileNameOffset = Strings.insert(FileName); 7989cb50c9SDimitry Andric Entry.Kind = Kind; 8089cb50c9SDimitry Andric Checksums.push_back(Entry); 8189cb50c9SDimitry Andric 8289cb50c9SDimitry Andric // This maps the offset of this string in the string table to the offset 8389cb50c9SDimitry Andric // of this checksum entry in the checksum buffer. 8489cb50c9SDimitry Andric OffsetMap[Entry.FileNameOffset] = SerializedSize; 8589cb50c9SDimitry Andric assert(SerializedSize % 4 == 0); 8689cb50c9SDimitry Andric 8789cb50c9SDimitry Andric uint32_t Len = alignTo(sizeof(FileChecksumEntryHeader) + Bytes.size(), 4); 8889cb50c9SDimitry Andric SerializedSize += Len; 8989cb50c9SDimitry Andric } 9089cb50c9SDimitry Andric 9189cb50c9SDimitry Andric uint32_t DebugChecksumsSubsection::calculateSerializedSize() const { 9289cb50c9SDimitry Andric return SerializedSize; 9389cb50c9SDimitry Andric } 9489cb50c9SDimitry Andric 9589cb50c9SDimitry Andric Error DebugChecksumsSubsection::commit(BinaryStreamWriter &Writer) const { 9689cb50c9SDimitry Andric for (const auto &FC : Checksums) { 9789cb50c9SDimitry Andric FileChecksumEntryHeader Header; 9889cb50c9SDimitry Andric Header.ChecksumKind = uint8_t(FC.Kind); 9989cb50c9SDimitry Andric Header.ChecksumSize = FC.Checksum.size(); 10089cb50c9SDimitry Andric Header.FileNameOffset = FC.FileNameOffset; 10189cb50c9SDimitry Andric if (auto EC = Writer.writeObject(Header)) 10289cb50c9SDimitry Andric return EC; 10389cb50c9SDimitry Andric if (auto EC = Writer.writeArray(makeArrayRef(FC.Checksum))) 10489cb50c9SDimitry Andric return EC; 10589cb50c9SDimitry Andric if (auto EC = Writer.padToAlignment(4)) 10689cb50c9SDimitry Andric return EC; 10789cb50c9SDimitry Andric } 10889cb50c9SDimitry Andric return Error::success(); 10989cb50c9SDimitry Andric } 11089cb50c9SDimitry Andric 11189cb50c9SDimitry Andric uint32_t DebugChecksumsSubsection::mapChecksumOffset(StringRef FileName) const { 11289cb50c9SDimitry Andric uint32_t Offset = Strings.getStringId(FileName); 11389cb50c9SDimitry Andric auto Iter = OffsetMap.find(Offset); 11489cb50c9SDimitry Andric assert(Iter != OffsetMap.end()); 11589cb50c9SDimitry Andric return Iter->second; 11689cb50c9SDimitry Andric } 117