DWARFDebugPubTable.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. //===- DWARFDebugPubTable.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/DWARF/DWARFDebugPubTable.h"
  9. #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
  10. #include "llvm/ADT/StringRef.h"
  11. #include "llvm/BinaryFormat/Dwarf.h"
  12. #include "llvm/Support/DataExtractor.h"
  13. #include "llvm/Support/Errc.h"
  14. #include "llvm/Support/Format.h"
  15. #include "llvm/Support/raw_ostream.h"
  16. #include <cstdint>
  17. using namespace llvm;
  18. using namespace dwarf;
  19. void DWARFDebugPubTable::extract(
  20. DWARFDataExtractor Data, bool GnuStyle,
  21. function_ref<void(Error)> RecoverableErrorHandler) {
  22. this->GnuStyle = GnuStyle;
  23. Sets.clear();
  24. uint64_t Offset = 0;
  25. while (Data.isValidOffset(Offset)) {
  26. uint64_t SetOffset = Offset;
  27. Sets.push_back({});
  28. Set &NewSet = Sets.back();
  29. DataExtractor::Cursor C(Offset);
  30. std::tie(NewSet.Length, NewSet.Format) = Data.getInitialLength(C);
  31. if (!C) {
  32. // Drop the newly added set because it does not contain anything useful
  33. // to dump.
  34. Sets.pop_back();
  35. RecoverableErrorHandler(createStringError(
  36. errc::invalid_argument,
  37. "name lookup table at offset 0x%" PRIx64 " parsing failed: %s",
  38. SetOffset, toString(C.takeError()).c_str()));
  39. return;
  40. }
  41. Offset = C.tell() + NewSet.Length;
  42. DWARFDataExtractor SetData(Data, Offset);
  43. const unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(NewSet.Format);
  44. NewSet.Version = SetData.getU16(C);
  45. NewSet.Offset = SetData.getRelocatedValue(C, OffsetSize);
  46. NewSet.Size = SetData.getUnsigned(C, OffsetSize);
  47. if (!C) {
  48. // Preserve the newly added set because at least some fields of the header
  49. // are read and can be dumped.
  50. RecoverableErrorHandler(
  51. createStringError(errc::invalid_argument,
  52. "name lookup table at offset 0x%" PRIx64
  53. " does not have a complete header: %s",
  54. SetOffset, toString(C.takeError()).c_str()));
  55. continue;
  56. }
  57. while (C) {
  58. uint64_t DieRef = SetData.getUnsigned(C, OffsetSize);
  59. if (DieRef == 0)
  60. break;
  61. uint8_t IndexEntryValue = GnuStyle ? SetData.getU8(C) : 0;
  62. StringRef Name = SetData.getCStrRef(C);
  63. if (C)
  64. NewSet.Entries.push_back(
  65. {DieRef, PubIndexEntryDescriptor(IndexEntryValue), Name});
  66. }
  67. if (!C) {
  68. RecoverableErrorHandler(createStringError(
  69. errc::invalid_argument,
  70. "name lookup table at offset 0x%" PRIx64 " parsing failed: %s",
  71. SetOffset, toString(C.takeError()).c_str()));
  72. continue;
  73. }
  74. if (C.tell() != Offset)
  75. RecoverableErrorHandler(createStringError(
  76. errc::invalid_argument,
  77. "name lookup table at offset 0x%" PRIx64
  78. " has a terminator at offset 0x%" PRIx64
  79. " before the expected end at 0x%" PRIx64,
  80. SetOffset, C.tell() - OffsetSize, Offset - OffsetSize));
  81. }
  82. }
  83. void DWARFDebugPubTable::dump(raw_ostream &OS) const {
  84. for (const Set &S : Sets) {
  85. int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(S.Format);
  86. OS << "length = " << format("0x%0*" PRIx64, OffsetDumpWidth, S.Length);
  87. OS << ", format = " << dwarf::FormatString(S.Format);
  88. OS << ", version = " << format("0x%04x", S.Version);
  89. OS << ", unit_offset = "
  90. << format("0x%0*" PRIx64, OffsetDumpWidth, S.Offset);
  91. OS << ", unit_size = " << format("0x%0*" PRIx64, OffsetDumpWidth, S.Size)
  92. << '\n';
  93. OS << (GnuStyle ? "Offset Linkage Kind Name\n"
  94. : "Offset Name\n");
  95. for (const Entry &E : S.Entries) {
  96. OS << format("0x%0*" PRIx64 " ", OffsetDumpWidth, E.SecOffset);
  97. if (GnuStyle) {
  98. StringRef EntryLinkage =
  99. GDBIndexEntryLinkageString(E.Descriptor.Linkage);
  100. StringRef EntryKind = dwarf::GDBIndexEntryKindString(E.Descriptor.Kind);
  101. OS << format("%-8s", EntryLinkage.data()) << ' '
  102. << format("%-8s", EntryKind.data()) << ' ';
  103. }
  104. OS << '\"' << E.Name << "\"\n";
  105. }
  106. }
  107. }