DebugSubsectionRecord.cpp 3.4 KB

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