DWARFVerifier.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  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/DebugInfo/DIContext.h"
  16. #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
  17. #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
  18. #include "llvm/DebugInfo/DWARF/DWARFDie.h"
  19. #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
  20. #include <cstdint>
  21. #include <map>
  22. #include <set>
  23. namespace llvm {
  24. class raw_ostream;
  25. struct DWARFAddressRange;
  26. class DWARFUnit;
  27. class DWARFUnitVector;
  28. struct DWARFAttribute;
  29. class DWARFContext;
  30. class DWARFDataExtractor;
  31. class DWARFDebugAbbrev;
  32. class DataExtractor;
  33. struct DWARFSection;
  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. std::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. ///
  141. /// \returns The number of errors that occurred during verification.
  142. unsigned verifyUnitSection(const DWARFSection &S);
  143. unsigned verifyUnits(const DWARFUnitVector &Units);
  144. unsigned verifyIndexes(const DWARFObject &DObj);
  145. unsigned verifyIndex(StringRef Name, DWARFSectionKind SectionKind,
  146. StringRef Index);
  147. /// Verifies that a call site entry is nested within a subprogram with a
  148. /// DW_AT_call attribute.
  149. ///
  150. /// \returns Number of errors that occurred during verification.
  151. unsigned verifyDebugInfoCallSite(const DWARFDie &Die);
  152. /// Verify that all Die ranges are valid.
  153. ///
  154. /// This function currently checks for:
  155. /// - cases in which lowPC >= highPC
  156. ///
  157. /// \returns Number of errors that occurred during verification.
  158. unsigned verifyDieRanges(const DWARFDie &Die, DieRangeInfo &ParentRI);
  159. /// Verifies the attribute's DWARF attribute and its value.
  160. ///
  161. /// This function currently checks for:
  162. /// - DW_AT_ranges values is a valid .debug_ranges offset
  163. /// - DW_AT_stmt_list is a valid .debug_line offset
  164. ///
  165. /// \param Die The DWARF DIE that owns the attribute value
  166. /// \param AttrValue The DWARF attribute value to check
  167. ///
  168. /// \returns NumErrors The number of errors occurred during verification of
  169. /// attributes' values in a unit
  170. unsigned verifyDebugInfoAttribute(const DWARFDie &Die,
  171. DWARFAttribute &AttrValue);
  172. /// Verifies the attribute's DWARF form.
  173. ///
  174. /// This function currently checks for:
  175. /// - All DW_FORM_ref values that are CU relative have valid CU offsets
  176. /// - All DW_FORM_ref_addr values have valid section offsets
  177. /// - All DW_FORM_strp values have valid .debug_str offsets
  178. ///
  179. /// \param Die The DWARF DIE that owns the attribute value
  180. /// \param AttrValue The DWARF attribute value to check
  181. ///
  182. /// \returns NumErrors The number of errors occurred during verification of
  183. /// attributes' forms in a unit
  184. unsigned verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue,
  185. ReferenceMap &UnitLocalReferences,
  186. ReferenceMap &CrossUnitReferences);
  187. /// Verifies the all valid references that were found when iterating through
  188. /// all of the DIE attributes.
  189. ///
  190. /// This function will verify that all references point to DIEs whose DIE
  191. /// offset matches. This helps to ensure if a DWARF link phase moved things
  192. /// around, that it doesn't create invalid references by failing to relocate
  193. /// CU relative and absolute references.
  194. ///
  195. /// \returns NumErrors The number of errors occurred during verification of
  196. /// references for the .debug_info and .debug_types sections
  197. unsigned verifyDebugInfoReferences(
  198. const ReferenceMap &,
  199. llvm::function_ref<DWARFUnit *(uint64_t)> GetUnitForDieOffset);
  200. /// Verify the DW_AT_stmt_list encoding and value and ensure that no
  201. /// compile units that have the same DW_AT_stmt_list value.
  202. void verifyDebugLineStmtOffsets();
  203. /// Verify that all of the rows in the line table are valid.
  204. ///
  205. /// This function currently checks for:
  206. /// - addresses within a sequence that decrease in value
  207. /// - invalid file indexes
  208. void verifyDebugLineRows();
  209. /// Verify that an Apple-style accelerator table is valid.
  210. ///
  211. /// This function currently checks that:
  212. /// - The fixed part of the header fits in the section
  213. /// - The size of the section is as large as what the header describes
  214. /// - There is at least one atom
  215. /// - The form for each atom is valid
  216. /// - The tag for each DIE in the table is valid
  217. /// - The buckets have a valid index, or they are empty
  218. /// - Each hashdata offset is valid
  219. /// - Each DIE is valid
  220. ///
  221. /// \param AccelSection pointer to the section containing the acceleration table
  222. /// \param StrData pointer to the string section
  223. /// \param SectionName the name of the table we're verifying
  224. ///
  225. /// \returns The number of errors occurred during verification
  226. unsigned verifyAppleAccelTable(const DWARFSection *AccelSection,
  227. DataExtractor *StrData,
  228. const char *SectionName);
  229. unsigned verifyDebugNamesCULists(const DWARFDebugNames &AccelTable);
  230. unsigned verifyNameIndexBuckets(const DWARFDebugNames::NameIndex &NI,
  231. const DataExtractor &StrData);
  232. unsigned verifyNameIndexAbbrevs(const DWARFDebugNames::NameIndex &NI);
  233. unsigned verifyNameIndexAttribute(const DWARFDebugNames::NameIndex &NI,
  234. const DWARFDebugNames::Abbrev &Abbr,
  235. DWARFDebugNames::AttributeEncoding AttrEnc);
  236. unsigned verifyNameIndexEntries(const DWARFDebugNames::NameIndex &NI,
  237. const DWARFDebugNames::NameTableEntry &NTE);
  238. unsigned verifyNameIndexCompleteness(const DWARFDie &Die,
  239. const DWARFDebugNames::NameIndex &NI);
  240. /// Verify that the DWARF v5 accelerator table is valid.
  241. ///
  242. /// This function currently checks that:
  243. /// - Headers individual Name Indices fit into the section and can be parsed.
  244. /// - Abbreviation tables can be parsed and contain valid index attributes
  245. /// with correct form encodings.
  246. /// - The CU lists reference existing compile units.
  247. /// - The buckets have a valid index, or they are empty.
  248. /// - All names are reachable via the hash table (they have the correct hash,
  249. /// and the hash is in the correct bucket).
  250. /// - Information in the index entries is complete (all required entries are
  251. /// present) and consistent with the debug_info section DIEs.
  252. ///
  253. /// \param AccelSection section containing the acceleration table
  254. /// \param StrData string section
  255. ///
  256. /// \returns The number of errors occurred during verification
  257. unsigned verifyDebugNames(const DWARFSection &AccelSection,
  258. const DataExtractor &StrData);
  259. public:
  260. DWARFVerifier(raw_ostream &S, DWARFContext &D,
  261. DIDumpOptions DumpOpts = DIDumpOptions::getForSingleDIE());
  262. /// Verify the information in any of the following sections, if available:
  263. /// .debug_abbrev, debug_abbrev.dwo
  264. ///
  265. /// Any errors are reported to the stream that was this object was
  266. /// constructed with.
  267. ///
  268. /// \returns true if .debug_abbrev and .debug_abbrev.dwo verify successfully,
  269. /// false otherwise.
  270. bool handleDebugAbbrev();
  271. /// Verify the information in the .debug_info and .debug_types sections.
  272. ///
  273. /// Any errors are reported to the stream that this object was
  274. /// constructed with.
  275. ///
  276. /// \returns true if all sections verify successfully, false otherwise.
  277. bool handleDebugInfo();
  278. /// Verify the information in the .debug_cu_index section.
  279. ///
  280. /// Any errors are reported to the stream that was this object was
  281. /// constructed with.
  282. ///
  283. /// \returns true if the .debug_cu_index verifies successfully, false
  284. /// otherwise.
  285. bool handleDebugCUIndex();
  286. /// Verify the information in the .debug_tu_index section.
  287. ///
  288. /// Any errors are reported to the stream that was this object was
  289. /// constructed with.
  290. ///
  291. /// \returns true if the .debug_tu_index verifies successfully, false
  292. /// otherwise.
  293. bool handleDebugTUIndex();
  294. /// Verify the information in the .debug_line section.
  295. ///
  296. /// Any errors are reported to the stream that was this object was
  297. /// constructed with.
  298. ///
  299. /// \returns true if the .debug_line verifies successfully, false otherwise.
  300. bool handleDebugLine();
  301. /// Verify the information in accelerator tables, if they exist.
  302. ///
  303. /// Any errors are reported to the stream that was this object was
  304. /// constructed with.
  305. ///
  306. /// \returns true if the existing Apple-style accelerator tables verify
  307. /// successfully, false otherwise.
  308. bool handleAccelTables();
  309. };
  310. static inline bool operator<(const DWARFVerifier::DieRangeInfo &LHS,
  311. const DWARFVerifier::DieRangeInfo &RHS) {
  312. return std::tie(LHS.Ranges, LHS.Die) < std::tie(RHS.Ranges, RHS.Die);
  313. }
  314. } // end namespace llvm
  315. #endif // LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
  316. #ifdef __GNUC__
  317. #pragma GCC diagnostic pop
  318. #endif