Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/CodeView/DebugChecksumsSubsection.cpp
35271 views
//===- DebugChecksumsSubsection.cpp ---------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"9#include "llvm/ADT/ArrayRef.h"10#include "llvm/DebugInfo/CodeView/CodeView.h"11#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"12#include "llvm/Support/BinaryStreamReader.h"13#include "llvm/Support/BinaryStreamWriter.h"14#include "llvm/Support/Endian.h"15#include "llvm/Support/Error.h"16#include "llvm/Support/MathExtras.h"17#include <cassert>18#include <cstdint>19#include <cstring>2021using namespace llvm;22using namespace llvm::codeview;2324struct FileChecksumEntryHeader {25using ulittle32_t = support::ulittle32_t;2627ulittle32_t FileNameOffset; // Byte offset of filename in global string table.28uint8_t ChecksumSize; // Number of bytes of checksum.29uint8_t ChecksumKind; // FileChecksumKind30// Checksum bytes follow.31};3233Error VarStreamArrayExtractor<FileChecksumEntry>::34operator()(BinaryStreamRef Stream, uint32_t &Len, FileChecksumEntry &Item) {35BinaryStreamReader Reader(Stream);3637const FileChecksumEntryHeader *Header;38if (auto EC = Reader.readObject(Header))39return EC;4041Item.FileNameOffset = Header->FileNameOffset;42Item.Kind = static_cast<FileChecksumKind>(Header->ChecksumKind);43if (auto EC = Reader.readBytes(Item.Checksum, Header->ChecksumSize))44return EC;4546Len = alignTo(Header->ChecksumSize + sizeof(FileChecksumEntryHeader), 4);47return Error::success();48}4950Error DebugChecksumsSubsectionRef::initialize(BinaryStreamReader Reader) {51if (auto EC = Reader.readArray(Checksums, Reader.bytesRemaining()))52return EC;5354return Error::success();55}5657Error DebugChecksumsSubsectionRef::initialize(BinaryStreamRef Section) {58BinaryStreamReader Reader(Section);59return initialize(Reader);60}6162DebugChecksumsSubsection::DebugChecksumsSubsection(63DebugStringTableSubsection &Strings)64: DebugSubsection(DebugSubsectionKind::FileChecksums), Strings(Strings) {}6566void DebugChecksumsSubsection::addChecksum(StringRef FileName,67FileChecksumKind Kind,68ArrayRef<uint8_t> Bytes) {69FileChecksumEntry Entry;70if (!Bytes.empty()) {71uint8_t *Copy = Storage.Allocate<uint8_t>(Bytes.size());72::memcpy(Copy, Bytes.data(), Bytes.size());73Entry.Checksum = ArrayRef(Copy, Bytes.size());74}7576Entry.FileNameOffset = Strings.insert(FileName);77Entry.Kind = Kind;78Checksums.push_back(Entry);7980// This maps the offset of this string in the string table to the offset81// of this checksum entry in the checksum buffer.82OffsetMap[Entry.FileNameOffset] = SerializedSize;83assert(SerializedSize % 4 == 0);8485uint32_t Len = alignTo(sizeof(FileChecksumEntryHeader) + Bytes.size(), 4);86SerializedSize += Len;87}8889uint32_t DebugChecksumsSubsection::calculateSerializedSize() const {90return SerializedSize;91}9293Error DebugChecksumsSubsection::commit(BinaryStreamWriter &Writer) const {94for (const auto &FC : Checksums) {95FileChecksumEntryHeader Header;96Header.ChecksumKind = uint8_t(FC.Kind);97Header.ChecksumSize = FC.Checksum.size();98Header.FileNameOffset = FC.FileNameOffset;99if (auto EC = Writer.writeObject(Header))100return EC;101if (auto EC = Writer.writeArray(ArrayRef(FC.Checksum)))102return EC;103if (auto EC = Writer.padToAlignment(4))104return EC;105}106return Error::success();107}108109uint32_t DebugChecksumsSubsection::mapChecksumOffset(StringRef FileName) const {110uint32_t Offset = Strings.getIdForString(FileName);111auto Iter = OffsetMap.find(Offset);112assert(Iter != OffsetMap.end());113return Iter->second;114}115116117