DWARFVerifier.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- DWARFVerifier.h ----------------------------------------------------===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
  14. #define LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
  15. #include "llvm/ADT/Optional.h"
  16. #include "llvm/DebugInfo/DIContext.h"
  17. #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
  18. #include "llvm/DebugInfo/DWARF/DWARFDie.h"
  19. #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
  20. #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
  21. #include <cstdint>
  22. #include <map>
  23. #include <set>
  24. namespace llvm {
  25. class raw_ostream;
  26. struct DWARFAddressRange;
  27. struct DWARFAttribute;
  28. class DWARFContext;
  29. class DWARFDataExtractor;
  30. class DWARFDebugAbbrev;
  31. class DataExtractor;
  32. struct DWARFSection;
  33. class DWARFUnit;
  34. /// A class that verifies DWARF debug information given a DWARF Context.
  35. class DWARFVerifier {
  36. public:
  37. /// A class that keeps the address range information for a single DIE.
  38. struct DieRangeInfo {
  39. DWARFDie Die;
  40. /// Sorted DWARFAddressRanges.
  41. std::vector<DWARFAddressRange> Ranges;
  42. /// Sorted DWARFAddressRangeInfo.
  43. std::set<DieRangeInfo> Children;
  44. DieRangeInfo() = default;
  45. DieRangeInfo(DWARFDie Die) : Die(Die) {}
  46. /// Used for unit testing.
  47. DieRangeInfo(std::vector<DWARFAddressRange> Ranges)
  48. : Ranges(std::move(Ranges)) {}
  49. typedef std::set<DieRangeInfo>::const_iterator die_range_info_iterator;
  50. /// Inserts the address range. If the range overlaps with an existing
  51. /// range, the range that it overlaps with will be returned and the two
  52. /// address ranges will be unioned together in "Ranges".
  53. ///
  54. /// This is used for finding overlapping ranges in the DW_AT_ranges
  55. /// attribute of a DIE. It is also used as a set of address ranges that
  56. /// children address ranges must all be contained in.
  57. Optional<DWARFAddressRange> insert(const DWARFAddressRange &R);
  58. /// Inserts the address range info. If any of its ranges overlaps with a
  59. /// range in an existing range info, the range info is *not* added and an
  60. /// iterator to the overlapping range info.
  61. ///
  62. /// This is used for finding overlapping children of the same DIE.
  63. die_range_info_iterator insert(const DieRangeInfo &RI);
  64. /// Return true if ranges in this object contains all ranges within RHS.
  65. bool contains(const DieRangeInfo &RHS) const;
  66. /// Return true if any range in this object intersects with any range in
  67. /// RHS.
  68. bool intersects(const DieRangeInfo &RHS) const;
  69. };
  70. private:
  71. raw_ostream &OS;
  72. DWARFContext &DCtx;
  73. DIDumpOptions DumpOpts;
  74. uint32_t NumDebugLineErrors = 0;
  75. // Used to relax some checks that do not currently work portably
  76. bool IsObjectFile;
  77. bool IsMachOObject;
  78. using ReferenceMap = std::map<uint64_t, std::set<uint64_t>>;
  79. raw_ostream &error() const;
  80. raw_ostream &warn() const;
  81. raw_ostream &note() const;
  82. raw_ostream &dump(const DWARFDie &Die, unsigned indent = 0) const;
  83. /// Verifies the abbreviations section.
  84. ///
  85. /// This function currently checks that:
  86. /// --No abbreviation declaration has more than one attributes with the same
  87. /// name.
  88. ///
  89. /// \param Abbrev Pointer to the abbreviations section we are verifying
  90. /// Abbrev can be a pointer to either .debug_abbrev or debug_abbrev.dwo.
  91. ///
  92. /// \returns The number of errors that occurred during verification.
  93. unsigned verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev);
  94. /// Verifies the header of a unit in a .debug_info or .debug_types section.
  95. ///
  96. /// This function currently checks for:
  97. /// - Unit is in 32-bit DWARF format. The function can be modified to
  98. /// support 64-bit format.
  99. /// - The DWARF version is valid
  100. /// - The unit type is valid (if unit is in version >=5)
  101. /// - The unit doesn't extend beyond the containing section
  102. /// - The address size is valid
  103. /// - The offset in the .debug_abbrev section is valid
  104. ///
  105. /// \param DebugInfoData The section data
  106. /// \param Offset A reference to the offset start of the unit. The offset will
  107. /// be updated to point to the next unit in the section
  108. /// \param UnitIndex The index of the unit to be verified
  109. /// \param UnitType A reference to the type of the unit
  110. /// \param isUnitDWARF64 A reference to a flag that shows whether the unit is
  111. /// in 64-bit format.
  112. ///
  113. /// \returns true if the header is verified successfully, false otherwise.
  114. bool verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
  115. uint64_t *Offset, unsigned UnitIndex, uint8_t &UnitType,
  116. bool &isUnitDWARF64);
  117. bool verifyName(const DWARFDie &Die);
  118. /// Verifies the header of a unit in a .debug_info or .debug_types section.
  119. ///
  120. /// This function currently verifies:
  121. /// - The debug info attributes.
  122. /// - The debug info form=s.
  123. /// - The presence of a root DIE.
  124. /// - That the root DIE is a unit DIE.
  125. /// - If a unit type is provided, that the unit DIE matches the unit type.
  126. /// - The DIE ranges.
  127. /// - That call site entries are only nested within subprograms with a
  128. /// DW_AT_call attribute.
  129. ///
  130. /// \param Unit The DWARF Unit to verify.
  131. ///
  132. /// \returns The number of errors that occurred during verification.
  133. unsigned verifyUnitContents(DWARFUnit &Unit,
  134. ReferenceMap &UnitLocalReferences,
  135. ReferenceMap &CrossUnitReferences);
  136. /// Verifies the unit headers and contents in a .debug_info or .debug_types
  137. /// section.
  138. ///
  139. /// \param S The DWARF Section to verify.
  140. /// \param SectionKind The object-file section kind that S comes from.
  141. ///
  142. /// \returns The number of errors that occurred during verification.
  143. unsigned verifyUnitSection(const DWARFSection &S);
  144. unsigned verifyUnits(const DWARFUnitVector &Units);
  145. /// Verifies that a call site entry is nested within a subprogram with a
  146. /// DW_AT_call attribute.
  147. ///
  148. /// \returns Number of errors that occurred during verification.
  149. unsigned verifyDebugInfoCallSite(const DWARFDie &Die);
  150. /// Verify that all Die ranges are valid.
  151. ///
  152. /// This function currently checks for:
  153. /// - cases in which lowPC >= highPC
  154. ///
  155. /// \returns Number of errors that occurred during verification.
  156. unsigned verifyDieRanges(const DWARFDie &Die, DieRangeInfo &ParentRI);
  157. /// Verifies the attribute's DWARF attribute and its value.
  158. ///
  159. /// This function currently checks for:
  160. /// - DW_AT_ranges values is a valid .debug_ranges offset
  161. /// - DW_AT_stmt_list is a valid .debug_line offset
  162. ///
  163. /// \param Die The DWARF DIE that owns the attribute value
  164. /// \param AttrValue The DWARF attribute value to check
  165. ///
  166. /// \returns NumErrors The number of errors occurred during verification of
  167. /// attributes' values in a unit
  168. unsigned verifyDebugInfoAttribute(const DWARFDie &Die,
  169. DWARFAttribute &AttrValue);
  170. /// Verifies the attribute's DWARF form.
  171. ///
  172. /// This function currently checks for:
  173. /// - All DW_FORM_ref values that are CU relative have valid CU offsets
  174. /// - All DW_FORM_ref_addr values have valid section offsets
  175. /// - All DW_FORM_strp values have valid .debug_str offsets
  176. ///
  177. /// \param Die The DWARF DIE that owns the attribute value
  178. /// \param AttrValue The DWARF attribute value to check
  179. ///
  180. /// \returns NumErrors The number of errors occurred during verification of
  181. /// attributes' forms in a unit
  182. unsigned verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue,
  183. ReferenceMap &UnitLocalReferences,
  184. ReferenceMap &CrossUnitReferences);
  185. /// Verifies the all valid references that were found when iterating through
  186. /// all of the DIE attributes.
  187. ///
  188. /// This function will verify that all references point to DIEs whose DIE
  189. /// offset matches. This helps to ensure if a DWARF link phase moved things
  190. /// around, that it doesn't create invalid references by failing to relocate
  191. /// CU relative and absolute references.
  192. ///
  193. /// \returns NumErrors The number of errors occurred during verification of
  194. /// references for the .debug_info and .debug_types sections
  195. unsigned verifyDebugInfoReferences(
  196. const ReferenceMap &,
  197. llvm::function_ref<DWARFUnit *(uint64_t)> GetUnitForDieOffset);
  198. /// Verify the DW_AT_stmt_list encoding and value and ensure that no
  199. /// compile units that have the same DW_AT_stmt_list value.
  200. void verifyDebugLineStmtOffsets();
  201. /// Verify that all of the rows in the line table are valid.
  202. ///
  203. /// This function currently checks for:
  204. /// - addresses within a sequence that decrease in value
  205. /// - invalid file indexes
  206. void verifyDebugLineRows();
  207. /// Verify that an Apple-style accelerator table is valid.
  208. ///
  209. /// This function currently checks that:
  210. /// - The fixed part of the header fits in the section
  211. /// - The size of the section is as large as what the header describes
  212. /// - There is at least one atom
  213. /// - The form for each atom is valid
  214. /// - The tag for each DIE in the table is valid
  215. /// - The buckets have a valid index, or they are empty
  216. /// - Each hashdata offset is valid
  217. /// - Each DIE is valid
  218. ///
  219. /// \param AccelSection pointer to the section containing the acceleration table
  220. /// \param StrData pointer to the string section
  221. /// \param SectionName the name of the table we're verifying
  222. ///
  223. /// \returns The number of errors occurred during verification
  224. unsigned verifyAppleAccelTable(const DWARFSection *AccelSection,
  225. DataExtractor *StrData,
  226. const char *SectionName);
  227. unsigned verifyDebugNamesCULists(const DWARFDebugNames &AccelTable);
  228. unsigned verifyNameIndexBuckets(const DWARFDebugNames::NameIndex &NI,
  229. const DataExtractor &StrData);
  230. unsigned verifyNameIndexAbbrevs(const DWARFDebugNames::NameIndex &NI);
  231. unsigned verifyNameIndexAttribute(const DWARFDebugNames::NameIndex &NI,
  232. const DWARFDebugNames::Abbrev &Abbr,
  233. DWARFDebugNames::AttributeEncoding AttrEnc);
  234. unsigned verifyNameIndexEntries(const DWARFDebugNames::NameIndex &NI,
  235. const DWARFDebugNames::NameTableEntry &NTE);
  236. unsigned verifyNameIndexCompleteness(const DWARFDie &Die,
  237. const DWARFDebugNames::NameIndex &NI);
  238. /// Verify that the DWARF v5 accelerator table is valid.
  239. ///
  240. /// This function currently checks that:
  241. /// - Headers individual Name Indices fit into the section and can be parsed.
  242. /// - Abbreviation tables can be parsed and contain valid index attributes
  243. /// with correct form encodings.
  244. /// - The CU lists reference existing compile units.
  245. /// - The buckets have a valid index, or they are empty.
  246. /// - All names are reachable via the hash table (they have the correct hash,
  247. /// and the hash is in the correct bucket).
  248. /// - Information in the index entries is complete (all required entries are
  249. /// present) and consistent with the debug_info section DIEs.
  250. ///
  251. /// \param AccelSection section containing the acceleration table
  252. /// \param StrData string section
  253. ///
  254. /// \returns The number of errors occurred during verification
  255. unsigned verifyDebugNames(const DWARFSection &AccelSection,
  256. const DataExtractor &StrData);
  257. public:
  258. DWARFVerifier(raw_ostream &S, DWARFContext &D,
  259. DIDumpOptions DumpOpts = DIDumpOptions::getForSingleDIE());
  260. /// Verify the information in any of the following sections, if available:
  261. /// .debug_abbrev, debug_abbrev.dwo
  262. ///
  263. /// Any errors are reported to the stream that was this object was
  264. /// constructed with.
  265. ///
  266. /// \returns true if .debug_abbrev and .debug_abbrev.dwo verify successfully,
  267. /// false otherwise.
  268. bool handleDebugAbbrev();
  269. /// Verify the information in the .debug_info and .debug_types sections.
  270. ///
  271. /// Any errors are reported to the stream that this object was
  272. /// constructed with.
  273. ///
  274. /// \returns true if all sections verify successfully, false otherwise.
  275. bool handleDebugInfo();
  276. /// Verify the information in the .debug_line section.
  277. ///
  278. /// Any errors are reported to the stream that was this object was
  279. /// constructed with.
  280. ///
  281. /// \returns true if the .debug_line verifies successfully, false otherwise.
  282. bool handleDebugLine();
  283. /// Verify the information in accelerator tables, if they exist.
  284. ///
  285. /// Any errors are reported to the stream that was this object was
  286. /// constructed with.
  287. ///
  288. /// \returns true if the existing Apple-style accelerator tables verify
  289. /// successfully, false otherwise.
  290. bool handleAccelTables();
  291. };
  292. static inline bool operator<(const DWARFVerifier::DieRangeInfo &LHS,
  293. const DWARFVerifier::DieRangeInfo &RHS) {
  294. return std::tie(LHS.Ranges, LHS.Die) < std::tie(RHS.Ranges, RHS.Die);
  295. }
  296. } // end namespace llvm
  297. #endif // LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
  298. #ifdef __GNUC__
  299. #pragma GCC diagnostic pop
  300. #endif