DebugChecksumsSubsection.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. //===- DebugChecksumsSubsection.cpp ---------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #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>
  20. using namespace llvm;
  21. using namespace llvm::codeview;
  22. struct FileChecksumEntryHeader {
  23. using ulittle32_t = support::ulittle32_t;
  24. ulittle32_t FileNameOffset; // Byte offset of filename in global string table.
  25. uint8_t ChecksumSize; // Number of bytes of checksum.
  26. uint8_t ChecksumKind; // FileChecksumKind
  27. // Checksum bytes follow.
  28. };
  29. Error VarStreamArrayExtractor<FileChecksumEntry>::
  30. operator()(BinaryStreamRef Stream, uint32_t &Len, FileChecksumEntry &Item) {
  31. BinaryStreamReader Reader(Stream);
  32. const FileChecksumEntryHeader *Header;
  33. if (auto EC = Reader.readObject(Header))
  34. return EC;
  35. Item.FileNameOffset = Header->FileNameOffset;
  36. Item.Kind = static_cast<FileChecksumKind>(Header->ChecksumKind);
  37. if (auto EC = Reader.readBytes(Item.Checksum, Header->ChecksumSize))
  38. return EC;
  39. Len = alignTo(Header->ChecksumSize + sizeof(FileChecksumEntryHeader), 4);
  40. return Error::success();
  41. }
  42. Error DebugChecksumsSubsectionRef::initialize(BinaryStreamReader Reader) {
  43. if (auto EC = Reader.readArray(Checksums, Reader.bytesRemaining()))
  44. return EC;
  45. return Error::success();
  46. }
  47. Error DebugChecksumsSubsectionRef::initialize(BinaryStreamRef Section) {
  48. BinaryStreamReader Reader(Section);
  49. return initialize(Reader);
  50. }
  51. DebugChecksumsSubsection::DebugChecksumsSubsection(
  52. DebugStringTableSubsection &Strings)
  53. : DebugSubsection(DebugSubsectionKind::FileChecksums), Strings(Strings) {}
  54. void DebugChecksumsSubsection::addChecksum(StringRef FileName,
  55. FileChecksumKind Kind,
  56. ArrayRef<uint8_t> Bytes) {
  57. FileChecksumEntry Entry;
  58. if (!Bytes.empty()) {
  59. uint8_t *Copy = Storage.Allocate<uint8_t>(Bytes.size());
  60. ::memcpy(Copy, Bytes.data(), Bytes.size());
  61. Entry.Checksum = ArrayRef(Copy, Bytes.size());
  62. }
  63. Entry.FileNameOffset = Strings.insert(FileName);
  64. Entry.Kind = Kind;
  65. Checksums.push_back(Entry);
  66. // This maps the offset of this string in the string table to the offset
  67. // of this checksum entry in the checksum buffer.
  68. OffsetMap[Entry.FileNameOffset] = SerializedSize;
  69. assert(SerializedSize % 4 == 0);
  70. uint32_t Len = alignTo(sizeof(FileChecksumEntryHeader) + Bytes.size(), 4);
  71. SerializedSize += Len;
  72. }
  73. uint32_t DebugChecksumsSubsection::calculateSerializedSize() const {
  74. return SerializedSize;
  75. }
  76. Error DebugChecksumsSubsection::commit(BinaryStreamWriter &Writer) const {
  77. for (const auto &FC : Checksums) {
  78. FileChecksumEntryHeader Header;
  79. Header.ChecksumKind = uint8_t(FC.Kind);
  80. Header.ChecksumSize = FC.Checksum.size();
  81. Header.FileNameOffset = FC.FileNameOffset;
  82. if (auto EC = Writer.writeObject(Header))
  83. return EC;
  84. if (auto EC = Writer.writeArray(ArrayRef(FC.Checksum)))
  85. return EC;
  86. if (auto EC = Writer.padToAlignment(4))
  87. return EC;
  88. }
  89. return Error::success();
  90. }
  91. uint32_t DebugChecksumsSubsection::mapChecksumOffset(StringRef FileName) const {
  92. uint32_t Offset = Strings.getIdForString(FileName);
  93. auto Iter = OffsetMap.find(Offset);
  94. assert(Iter != OffsetMap.end());
  95. return Iter->second;
  96. }