DebugSubsectionRecord.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. //===- DebugSubsectionRecord.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/DebugSubsectionRecord.h"
  9. #include "llvm/DebugInfo/CodeView/CodeView.h"
  10. #include "llvm/DebugInfo/CodeView/DebugSubsection.h"
  11. #include "llvm/Support/BinaryStreamReader.h"
  12. #include "llvm/Support/BinaryStreamWriter.h"
  13. #include "llvm/Support/Error.h"
  14. #include "llvm/Support/MathExtras.h"
  15. #include <cassert>
  16. #include <cstdint>
  17. using namespace llvm;
  18. using namespace llvm::codeview;
  19. DebugSubsectionRecord::DebugSubsectionRecord() = default;
  20. DebugSubsectionRecord::DebugSubsectionRecord(DebugSubsectionKind Kind,
  21. BinaryStreamRef Data)
  22. : Kind(Kind), Data(Data) {}
  23. Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream,
  24. DebugSubsectionRecord &Info) {
  25. const DebugSubsectionHeader *Header;
  26. BinaryStreamReader Reader(Stream);
  27. if (auto EC = Reader.readObject(Header))
  28. return EC;
  29. DebugSubsectionKind Kind =
  30. static_cast<DebugSubsectionKind>(uint32_t(Header->Kind));
  31. if (auto EC = Reader.readStreamRef(Info.Data, Header->Length))
  32. return EC;
  33. Info.Kind = Kind;
  34. return Error::success();
  35. }
  36. uint32_t DebugSubsectionRecord::getRecordLength() const {
  37. return sizeof(DebugSubsectionHeader) + Data.getLength();
  38. }
  39. DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; }
  40. BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; }
  41. DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
  42. std::shared_ptr<DebugSubsection> Subsection)
  43. : Subsection(std::move(Subsection)) {}
  44. DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
  45. const DebugSubsectionRecord &Contents)
  46. : Contents(Contents) {}
  47. uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() const {
  48. uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()
  49. : Contents.getRecordData().getLength();
  50. // The length of the entire subsection is always padded to 4 bytes,
  51. // regardless of the container kind.
  52. return sizeof(DebugSubsectionHeader) + alignTo(DataSize, 4);
  53. }
  54. Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer,
  55. CodeViewContainer Container) const {
  56. assert(Writer.getOffset() % alignOf(Container) == 0 &&
  57. "Debug Subsection not properly aligned");
  58. DebugSubsectionHeader Header;
  59. Header.Kind = uint32_t(Subsection ? Subsection->kind() : Contents.kind());
  60. // The value written into the Header's Length field is only padded to the
  61. // container's alignment
  62. uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize()
  63. : Contents.getRecordData().getLength();
  64. Header.Length = alignTo(DataSize, alignOf(Container));
  65. if (auto EC = Writer.writeObject(Header))
  66. return EC;
  67. if (Subsection) {
  68. if (auto EC = Subsection->commit(Writer))
  69. return EC;
  70. } else {
  71. if (auto EC = Writer.writeStreamRef(Contents.getRecordData()))
  72. return EC;
  73. }
  74. if (auto EC = Writer.padToAlignment(4))
  75. return EC;
  76. return Error::success();
  77. }