DWARFDebugRnglists.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. //===- DWARFDebugRnglists.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/DWARFDebugRnglists.h"
  9. #include "llvm/BinaryFormat/Dwarf.h"
  10. #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
  11. #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
  12. #include "llvm/Support/Errc.h"
  13. #include "llvm/Support/Error.h"
  14. #include "llvm/Support/Format.h"
  15. #include "llvm/Support/raw_ostream.h"
  16. using namespace llvm;
  17. Error RangeListEntry::extract(DWARFDataExtractor Data, uint64_t *OffsetPtr) {
  18. Offset = *OffsetPtr;
  19. SectionIndex = -1ULL;
  20. // The caller should guarantee that we have at least 1 byte available, so
  21. // we just assert instead of revalidate.
  22. assert(*OffsetPtr < Data.size() &&
  23. "not enough space to extract a rangelist encoding");
  24. uint8_t Encoding = Data.getU8(OffsetPtr);
  25. DataExtractor::Cursor C(*OffsetPtr);
  26. switch (Encoding) {
  27. case dwarf::DW_RLE_end_of_list:
  28. Value0 = Value1 = 0;
  29. break;
  30. // TODO: Support other encodings.
  31. case dwarf::DW_RLE_base_addressx: {
  32. Value0 = Data.getULEB128(C);
  33. break;
  34. }
  35. case dwarf::DW_RLE_startx_endx:
  36. Value0 = Data.getULEB128(C);
  37. Value1 = Data.getULEB128(C);
  38. break;
  39. case dwarf::DW_RLE_startx_length: {
  40. Value0 = Data.getULEB128(C);
  41. Value1 = Data.getULEB128(C);
  42. break;
  43. }
  44. case dwarf::DW_RLE_offset_pair: {
  45. Value0 = Data.getULEB128(C);
  46. Value1 = Data.getULEB128(C);
  47. break;
  48. }
  49. case dwarf::DW_RLE_base_address: {
  50. Value0 = Data.getRelocatedAddress(C, &SectionIndex);
  51. break;
  52. }
  53. case dwarf::DW_RLE_start_end: {
  54. Value0 = Data.getRelocatedAddress(C, &SectionIndex);
  55. Value1 = Data.getRelocatedAddress(C);
  56. break;
  57. }
  58. case dwarf::DW_RLE_start_length: {
  59. Value0 = Data.getRelocatedAddress(C, &SectionIndex);
  60. Value1 = Data.getULEB128(C);
  61. break;
  62. }
  63. default:
  64. consumeError(C.takeError());
  65. return createStringError(errc::not_supported,
  66. "unknown rnglists encoding 0x%" PRIx32
  67. " at offset 0x%" PRIx64,
  68. uint32_t(Encoding), Offset);
  69. }
  70. if (!C) {
  71. consumeError(C.takeError());
  72. return createStringError(
  73. errc::invalid_argument,
  74. "read past end of table when reading %s encoding at offset 0x%" PRIx64,
  75. dwarf::RLEString(Encoding).data(), Offset);
  76. }
  77. *OffsetPtr = C.tell();
  78. EntryKind = Encoding;
  79. return Error::success();
  80. }
  81. DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(
  82. llvm::Optional<object::SectionedAddress> BaseAddr, DWARFUnit &U) const {
  83. return getAbsoluteRanges(
  84. BaseAddr, U.getAddressByteSize(),
  85. [&](uint32_t Index) { return U.getAddrOffsetSectionItem(Index); });
  86. }
  87. DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges(
  88. Optional<object::SectionedAddress> BaseAddr, uint8_t AddressByteSize,
  89. function_ref<Optional<object::SectionedAddress>(uint32_t)>
  90. LookupPooledAddress) const {
  91. DWARFAddressRangesVector Res;
  92. uint64_t Tombstone = dwarf::computeTombstoneAddress(AddressByteSize);
  93. for (const RangeListEntry &RLE : Entries) {
  94. if (RLE.EntryKind == dwarf::DW_RLE_end_of_list)
  95. break;
  96. if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) {
  97. BaseAddr = LookupPooledAddress(RLE.Value0);
  98. if (!BaseAddr)
  99. BaseAddr = {RLE.Value0, -1ULL};
  100. continue;
  101. }
  102. if (RLE.EntryKind == dwarf::DW_RLE_base_address) {
  103. BaseAddr = {RLE.Value0, RLE.SectionIndex};
  104. continue;
  105. }
  106. DWARFAddressRange E;
  107. E.SectionIndex = RLE.SectionIndex;
  108. if (BaseAddr && E.SectionIndex == -1ULL)
  109. E.SectionIndex = BaseAddr->SectionIndex;
  110. switch (RLE.EntryKind) {
  111. case dwarf::DW_RLE_offset_pair:
  112. E.LowPC = RLE.Value0;
  113. if (E.LowPC == Tombstone)
  114. continue;
  115. E.HighPC = RLE.Value1;
  116. if (BaseAddr) {
  117. if (BaseAddr->Address == Tombstone)
  118. continue;
  119. E.LowPC += BaseAddr->Address;
  120. E.HighPC += BaseAddr->Address;
  121. }
  122. break;
  123. case dwarf::DW_RLE_start_end:
  124. E.LowPC = RLE.Value0;
  125. E.HighPC = RLE.Value1;
  126. break;
  127. case dwarf::DW_RLE_start_length:
  128. E.LowPC = RLE.Value0;
  129. E.HighPC = E.LowPC + RLE.Value1;
  130. break;
  131. case dwarf::DW_RLE_startx_length: {
  132. auto Start = LookupPooledAddress(RLE.Value0);
  133. if (!Start)
  134. Start = {0, -1ULL};
  135. E.SectionIndex = Start->SectionIndex;
  136. E.LowPC = Start->Address;
  137. E.HighPC = E.LowPC + RLE.Value1;
  138. break;
  139. }
  140. case dwarf::DW_RLE_startx_endx: {
  141. auto Start = LookupPooledAddress(RLE.Value0);
  142. if (!Start)
  143. Start = {0, -1ULL};
  144. auto End = LookupPooledAddress(RLE.Value1);
  145. if (!End)
  146. End = {0, -1ULL};
  147. // FIXME: Some error handling if Start.SectionIndex != End.SectionIndex
  148. E.SectionIndex = Start->SectionIndex;
  149. E.LowPC = Start->Address;
  150. E.HighPC = End->Address;
  151. break;
  152. }
  153. default:
  154. // Unsupported encodings should have been reported during extraction,
  155. // so we should not run into any here.
  156. llvm_unreachable("Unsupported range list encoding");
  157. }
  158. if (E.LowPC == Tombstone)
  159. continue;
  160. Res.push_back(E);
  161. }
  162. return Res;
  163. }
  164. void RangeListEntry::dump(
  165. raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
  166. uint64_t &CurrentBase, DIDumpOptions DumpOpts,
  167. llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)>
  168. LookupPooledAddress) const {
  169. auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry,
  170. uint8_t AddrSize, DIDumpOptions DumpOpts) {
  171. if (DumpOpts.Verbose) {
  172. DumpOpts.DisplayRawContents = true;
  173. DWARFAddressRange(Entry.Value0, Entry.Value1)
  174. .dump(OS, AddrSize, DumpOpts);
  175. OS << " => ";
  176. }
  177. };
  178. if (DumpOpts.Verbose) {
  179. // Print the section offset in verbose mode.
  180. OS << format("0x%8.8" PRIx64 ":", Offset);
  181. auto EncodingString = dwarf::RangeListEncodingString(EntryKind);
  182. // Unsupported encodings should have been reported during parsing.
  183. assert(!EncodingString.empty() && "Unknown range entry encoding");
  184. OS << format(" [%s%*c", EncodingString.data(),
  185. MaxEncodingStringLength - EncodingString.size() + 1, ']');
  186. if (EntryKind != dwarf::DW_RLE_end_of_list)
  187. OS << ": ";
  188. }
  189. uint64_t Tombstone = dwarf::computeTombstoneAddress(AddrSize);
  190. switch (EntryKind) {
  191. case dwarf::DW_RLE_end_of_list:
  192. OS << (DumpOpts.Verbose ? "" : "<End of list>");
  193. break;
  194. case dwarf::DW_RLE_base_addressx: {
  195. if (auto SA = LookupPooledAddress(Value0))
  196. CurrentBase = SA->Address;
  197. else
  198. CurrentBase = Value0;
  199. if (!DumpOpts.Verbose)
  200. return;
  201. DWARFFormValue::dumpAddress(OS << ' ', AddrSize, Value0);
  202. break;
  203. }
  204. case dwarf::DW_RLE_base_address:
  205. // In non-verbose mode we do not print anything for this entry.
  206. CurrentBase = Value0;
  207. if (!DumpOpts.Verbose)
  208. return;
  209. DWARFFormValue::dumpAddress(OS << ' ', AddrSize, Value0);
  210. break;
  211. case dwarf::DW_RLE_start_length:
  212. PrintRawEntry(OS, *this, AddrSize, DumpOpts);
  213. DWARFAddressRange(Value0, Value0 + Value1).dump(OS, AddrSize, DumpOpts);
  214. break;
  215. case dwarf::DW_RLE_offset_pair:
  216. PrintRawEntry(OS, *this, AddrSize, DumpOpts);
  217. if (CurrentBase != Tombstone)
  218. DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase)
  219. .dump(OS, AddrSize, DumpOpts);
  220. else
  221. OS << "dead code";
  222. break;
  223. case dwarf::DW_RLE_start_end:
  224. DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts);
  225. break;
  226. case dwarf::DW_RLE_startx_length: {
  227. PrintRawEntry(OS, *this, AddrSize, DumpOpts);
  228. uint64_t Start = 0;
  229. if (auto SA = LookupPooledAddress(Value0))
  230. Start = SA->Address;
  231. DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts);
  232. break;
  233. }
  234. case dwarf::DW_RLE_startx_endx: {
  235. PrintRawEntry(OS, *this, AddrSize, DumpOpts);
  236. uint64_t Start = 0;
  237. if (auto SA = LookupPooledAddress(Value0))
  238. Start = SA->Address;
  239. uint64_t End = 0;
  240. if (auto SA = LookupPooledAddress(Value1))
  241. End = SA->Address;
  242. DWARFAddressRange(Start, End).dump(OS, AddrSize, DumpOpts);
  243. break;
  244. }
  245. default:
  246. llvm_unreachable("Unsupported range list encoding");
  247. }
  248. OS << "\n";
  249. }