dwarf2yaml.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. //===------ dwarf2yaml.cpp - obj2yaml conversion tool -----------*- C++ -*-===//
  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/BinaryFormat/Dwarf.h"
  9. #include "llvm/DebugInfo/DWARF/DWARFContext.h"
  10. #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
  11. #include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"
  12. #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
  13. #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
  14. #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
  15. #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
  16. #include "llvm/DebugInfo/DWARF/DWARFSection.h"
  17. #include "llvm/ObjectYAML/DWARFYAML.h"
  18. #include <algorithm>
  19. #include <optional>
  20. using namespace llvm;
  21. void dumpDebugAbbrev(DWARFContext &DCtx, DWARFYAML::Data &Y) {
  22. auto AbbrevSetPtr = DCtx.getDebugAbbrev();
  23. if (AbbrevSetPtr) {
  24. uint64_t AbbrevTableID = 0;
  25. for (auto AbbrvDeclSet : *AbbrevSetPtr) {
  26. Y.DebugAbbrev.emplace_back();
  27. Y.DebugAbbrev.back().ID = AbbrevTableID++;
  28. for (auto AbbrvDecl : AbbrvDeclSet.second) {
  29. DWARFYAML::Abbrev Abbrv;
  30. Abbrv.Code = AbbrvDecl.getCode();
  31. Abbrv.Tag = AbbrvDecl.getTag();
  32. Abbrv.Children = AbbrvDecl.hasChildren() ? dwarf::DW_CHILDREN_yes
  33. : dwarf::DW_CHILDREN_no;
  34. for (auto Attribute : AbbrvDecl.attributes()) {
  35. DWARFYAML::AttributeAbbrev AttAbrv;
  36. AttAbrv.Attribute = Attribute.Attr;
  37. AttAbrv.Form = Attribute.Form;
  38. if (AttAbrv.Form == dwarf::DW_FORM_implicit_const)
  39. AttAbrv.Value = Attribute.getImplicitConstValue();
  40. Abbrv.Attributes.push_back(AttAbrv);
  41. }
  42. Y.DebugAbbrev.back().Table.push_back(Abbrv);
  43. }
  44. }
  45. }
  46. }
  47. Error dumpDebugAddr(DWARFContext &DCtx, DWARFYAML::Data &Y) {
  48. DWARFDebugAddrTable AddrTable;
  49. DWARFDataExtractor AddrData(DCtx.getDWARFObj(),
  50. DCtx.getDWARFObj().getAddrSection(),
  51. DCtx.isLittleEndian(), /*AddressSize=*/0);
  52. std::vector<DWARFYAML::AddrTableEntry> AddrTables;
  53. uint64_t Offset = 0;
  54. while (AddrData.isValidOffset(Offset)) {
  55. // We ignore any errors that don't prevent parsing the section, since we can
  56. // still represent such sections.
  57. if (Error Err = AddrTable.extractV5(AddrData, &Offset, /*CUAddrSize=*/0,
  58. consumeError))
  59. return Err;
  60. AddrTables.emplace_back();
  61. for (uint64_t Addr : AddrTable.getAddressEntries()) {
  62. // Currently, the parser doesn't support parsing an address table with non
  63. // linear addresses (segment_selector_size != 0). The segment selectors
  64. // are specified to be zero.
  65. AddrTables.back().SegAddrPairs.push_back(
  66. {/*SegmentSelector=*/0, /*Address=*/Addr});
  67. }
  68. AddrTables.back().Format = AddrTable.getFormat();
  69. AddrTables.back().Length = AddrTable.getLength();
  70. AddrTables.back().Version = AddrTable.getVersion();
  71. AddrTables.back().AddrSize = AddrTable.getAddressSize();
  72. AddrTables.back().SegSelectorSize = AddrTable.getSegmentSelectorSize();
  73. }
  74. Y.DebugAddr = std::move(AddrTables);
  75. return Error::success();
  76. }
  77. Error dumpDebugStrings(DWARFContext &DCtx, DWARFYAML::Data &Y) {
  78. DataExtractor StrData = DCtx.getStringExtractor();
  79. uint64_t Offset = 0;
  80. std::vector<StringRef> DebugStr;
  81. Error Err = Error::success();
  82. while (StrData.isValidOffset(Offset)) {
  83. const char *CStr = StrData.getCStr(&Offset, &Err);
  84. if (Err)
  85. return Err;
  86. DebugStr.push_back(CStr);
  87. }
  88. Y.DebugStrings = DebugStr;
  89. return Err;
  90. }
  91. Error dumpDebugARanges(DWARFContext &DCtx, DWARFYAML::Data &Y) {
  92. DWARFDataExtractor ArangesData(DCtx.getDWARFObj().getArangesSection(),
  93. DCtx.isLittleEndian(), 0);
  94. uint64_t Offset = 0;
  95. DWARFDebugArangeSet Set;
  96. std::vector<DWARFYAML::ARange> DebugAranges;
  97. // We ignore any errors that don't prevent parsing the section, since we can
  98. // still represent such sections. These errors are recorded via the
  99. // WarningHandler parameter of Set.extract().
  100. auto DiscardError = [](Error Err) { consumeError(std::move(Err)); };
  101. while (ArangesData.isValidOffset(Offset)) {
  102. if (Error E = Set.extract(ArangesData, &Offset, DiscardError))
  103. return E;
  104. DWARFYAML::ARange Range;
  105. Range.Format = Set.getHeader().Format;
  106. Range.Length = Set.getHeader().Length;
  107. Range.Version = Set.getHeader().Version;
  108. Range.CuOffset = Set.getHeader().CuOffset;
  109. Range.AddrSize = Set.getHeader().AddrSize;
  110. Range.SegSize = Set.getHeader().SegSize;
  111. for (auto Descriptor : Set.descriptors()) {
  112. DWARFYAML::ARangeDescriptor Desc;
  113. Desc.Address = Descriptor.Address;
  114. Desc.Length = Descriptor.Length;
  115. Range.Descriptors.push_back(Desc);
  116. }
  117. DebugAranges.push_back(Range);
  118. }
  119. Y.DebugAranges = DebugAranges;
  120. return ErrorSuccess();
  121. }
  122. Error dumpDebugRanges(DWARFContext &DCtx, DWARFYAML::Data &Y) {
  123. // We are assuming all address byte sizes will be consistent across all
  124. // compile units.
  125. uint8_t AddrSize = 0;
  126. for (const auto &CU : DCtx.compile_units()) {
  127. const uint8_t CUAddrSize = CU->getAddressByteSize();
  128. if (AddrSize == 0)
  129. AddrSize = CUAddrSize;
  130. else if (CUAddrSize != AddrSize)
  131. return createStringError(std::errc::invalid_argument,
  132. "address sizes vary in different compile units");
  133. }
  134. DWARFDataExtractor Data(DCtx.getDWARFObj().getRangesSection().Data,
  135. DCtx.isLittleEndian(), AddrSize);
  136. uint64_t Offset = 0;
  137. DWARFDebugRangeList DwarfRanges;
  138. std::vector<DWARFYAML::Ranges> DebugRanges;
  139. while (Data.isValidOffset(Offset)) {
  140. DWARFYAML::Ranges YamlRanges;
  141. YamlRanges.Offset = Offset;
  142. YamlRanges.AddrSize = AddrSize;
  143. if (Error E = DwarfRanges.extract(Data, &Offset))
  144. return E;
  145. for (const auto &RLE : DwarfRanges.getEntries())
  146. YamlRanges.Entries.push_back({RLE.StartAddress, RLE.EndAddress});
  147. DebugRanges.push_back(std::move(YamlRanges));
  148. }
  149. Y.DebugRanges = DebugRanges;
  150. return ErrorSuccess();
  151. }
  152. static std::optional<DWARFYAML::PubSection>
  153. dumpPubSection(const DWARFContext &DCtx, const DWARFSection &Section,
  154. bool IsGNUStyle) {
  155. DWARFYAML::PubSection Y;
  156. DWARFDataExtractor PubSectionData(DCtx.getDWARFObj(), Section,
  157. DCtx.isLittleEndian(), 0);
  158. DWARFDebugPubTable Table;
  159. // We ignore any errors that don't prevent parsing the section, since we can
  160. // still represent such sections.
  161. Table.extract(PubSectionData, IsGNUStyle,
  162. [](Error Err) { consumeError(std::move(Err)); });
  163. ArrayRef<DWARFDebugPubTable::Set> Sets = Table.getData();
  164. if (Sets.empty())
  165. return std::nullopt;
  166. // FIXME: Currently, obj2yaml only supports dumping the first pubtable.
  167. Y.Format = Sets[0].Format;
  168. Y.Length = Sets[0].Length;
  169. Y.Version = Sets[0].Version;
  170. Y.UnitOffset = Sets[0].Offset;
  171. Y.UnitSize = Sets[0].Size;
  172. for (const DWARFDebugPubTable::Entry &E : Sets[0].Entries)
  173. Y.Entries.push_back(DWARFYAML::PubEntry{(uint32_t)E.SecOffset,
  174. E.Descriptor.toBits(), E.Name});
  175. return Y;
  176. }
  177. void dumpDebugPubSections(DWARFContext &DCtx, DWARFYAML::Data &Y) {
  178. const DWARFObject &D = DCtx.getDWARFObj();
  179. Y.PubNames =
  180. dumpPubSection(DCtx, D.getPubnamesSection(), /*IsGNUStyle=*/false);
  181. Y.PubTypes =
  182. dumpPubSection(DCtx, D.getPubtypesSection(), /*IsGNUStyle=*/false);
  183. // TODO: Test dumping .debug_gnu_pubnames section.
  184. Y.GNUPubNames =
  185. dumpPubSection(DCtx, D.getGnuPubnamesSection(), /*IsGNUStyle=*/true);
  186. // TODO: Test dumping .debug_gnu_pubtypes section.
  187. Y.GNUPubTypes =
  188. dumpPubSection(DCtx, D.getGnuPubtypesSection(), /*IsGNUStyle=*/true);
  189. }
  190. void dumpDebugInfo(DWARFContext &DCtx, DWARFYAML::Data &Y) {
  191. for (const auto &CU : DCtx.compile_units()) {
  192. DWARFYAML::Unit NewUnit;
  193. NewUnit.Format = CU->getFormat();
  194. NewUnit.Length = CU->getLength();
  195. NewUnit.Version = CU->getVersion();
  196. if (NewUnit.Version >= 5)
  197. NewUnit.Type = (dwarf::UnitType)CU->getUnitType();
  198. const DWARFDebugAbbrev *DebugAbbrev = DCtx.getDebugAbbrev();
  199. NewUnit.AbbrevTableID = std::distance(
  200. DebugAbbrev->begin(),
  201. llvm::find_if(
  202. *DebugAbbrev,
  203. [&](const std::pair<uint64_t, DWARFAbbreviationDeclarationSet> &P) {
  204. return P.first == CU->getAbbreviations()->getOffset();
  205. }));
  206. NewUnit.AbbrOffset = CU->getAbbreviations()->getOffset();
  207. NewUnit.AddrSize = CU->getAddressByteSize();
  208. for (auto DIE : CU->dies()) {
  209. DWARFYAML::Entry NewEntry;
  210. DataExtractor EntryData = CU->getDebugInfoExtractor();
  211. uint64_t offset = DIE.getOffset();
  212. assert(EntryData.isValidOffset(offset) && "Invalid DIE Offset");
  213. if (!EntryData.isValidOffset(offset))
  214. continue;
  215. NewEntry.AbbrCode = EntryData.getULEB128(&offset);
  216. auto AbbrevDecl = DIE.getAbbreviationDeclarationPtr();
  217. if (AbbrevDecl) {
  218. for (const auto &AttrSpec : AbbrevDecl->attributes()) {
  219. DWARFYAML::FormValue NewValue;
  220. NewValue.Value = 0xDEADBEEFDEADBEEF;
  221. DWARFDie DIEWrapper(CU.get(), &DIE);
  222. auto FormValue = DIEWrapper.find(AttrSpec.Attr);
  223. if (!FormValue)
  224. return;
  225. auto Form = FormValue->getForm();
  226. bool indirect = false;
  227. do {
  228. indirect = false;
  229. switch (Form) {
  230. case dwarf::DW_FORM_addr:
  231. case dwarf::DW_FORM_GNU_addr_index:
  232. if (auto Val = FormValue->getAsAddress())
  233. NewValue.Value = *Val;
  234. break;
  235. case dwarf::DW_FORM_ref_addr:
  236. case dwarf::DW_FORM_ref1:
  237. case dwarf::DW_FORM_ref2:
  238. case dwarf::DW_FORM_ref4:
  239. case dwarf::DW_FORM_ref8:
  240. case dwarf::DW_FORM_ref_udata:
  241. case dwarf::DW_FORM_ref_sig8:
  242. if (auto Val = FormValue->getAsReferenceUVal())
  243. NewValue.Value = *Val;
  244. break;
  245. case dwarf::DW_FORM_exprloc:
  246. case dwarf::DW_FORM_block:
  247. case dwarf::DW_FORM_block1:
  248. case dwarf::DW_FORM_block2:
  249. case dwarf::DW_FORM_block4:
  250. if (auto Val = FormValue->getAsBlock()) {
  251. auto BlockData = *Val;
  252. std::copy(BlockData.begin(), BlockData.end(),
  253. std::back_inserter(NewValue.BlockData));
  254. }
  255. NewValue.Value = NewValue.BlockData.size();
  256. break;
  257. case dwarf::DW_FORM_data1:
  258. case dwarf::DW_FORM_flag:
  259. case dwarf::DW_FORM_data2:
  260. case dwarf::DW_FORM_data4:
  261. case dwarf::DW_FORM_data8:
  262. case dwarf::DW_FORM_sdata:
  263. case dwarf::DW_FORM_udata:
  264. case dwarf::DW_FORM_ref_sup4:
  265. case dwarf::DW_FORM_ref_sup8:
  266. if (auto Val = FormValue->getAsUnsignedConstant())
  267. NewValue.Value = *Val;
  268. break;
  269. case dwarf::DW_FORM_string:
  270. if (auto Val = dwarf::toString(FormValue))
  271. NewValue.CStr = *Val;
  272. break;
  273. case dwarf::DW_FORM_indirect:
  274. indirect = true;
  275. if (auto Val = FormValue->getAsUnsignedConstant()) {
  276. NewValue.Value = *Val;
  277. NewEntry.Values.push_back(NewValue);
  278. Form = static_cast<dwarf::Form>(*Val);
  279. }
  280. break;
  281. case dwarf::DW_FORM_strp:
  282. case dwarf::DW_FORM_sec_offset:
  283. case dwarf::DW_FORM_GNU_ref_alt:
  284. case dwarf::DW_FORM_GNU_strp_alt:
  285. case dwarf::DW_FORM_line_strp:
  286. case dwarf::DW_FORM_strp_sup:
  287. case dwarf::DW_FORM_GNU_str_index:
  288. case dwarf::DW_FORM_strx:
  289. if (auto Val = FormValue->getAsCStringOffset())
  290. NewValue.Value = *Val;
  291. break;
  292. case dwarf::DW_FORM_flag_present:
  293. NewValue.Value = 1;
  294. break;
  295. default:
  296. break;
  297. }
  298. } while (indirect);
  299. NewEntry.Values.push_back(NewValue);
  300. }
  301. }
  302. NewUnit.Entries.push_back(NewEntry);
  303. }
  304. Y.CompileUnits.push_back(NewUnit);
  305. }
  306. }
  307. bool dumpFileEntry(DataExtractor &Data, uint64_t &Offset,
  308. DWARFYAML::File &File) {
  309. File.Name = Data.getCStr(&Offset);
  310. if (File.Name.empty())
  311. return false;
  312. File.DirIdx = Data.getULEB128(&Offset);
  313. File.ModTime = Data.getULEB128(&Offset);
  314. File.Length = Data.getULEB128(&Offset);
  315. return true;
  316. }
  317. void dumpDebugLines(DWARFContext &DCtx, DWARFYAML::Data &Y) {
  318. for (const auto &CU : DCtx.compile_units()) {
  319. auto CUDIE = CU->getUnitDIE();
  320. if (!CUDIE)
  321. continue;
  322. if (auto StmtOffset =
  323. dwarf::toSectionOffset(CUDIE.find(dwarf::DW_AT_stmt_list))) {
  324. DWARFYAML::LineTable DebugLines;
  325. DataExtractor LineData(DCtx.getDWARFObj().getLineSection().Data,
  326. DCtx.isLittleEndian(), CU->getAddressByteSize());
  327. uint64_t Offset = *StmtOffset;
  328. uint64_t LengthOrDWARF64Prefix = LineData.getU32(&Offset);
  329. if (LengthOrDWARF64Prefix == dwarf::DW_LENGTH_DWARF64) {
  330. DebugLines.Format = dwarf::DWARF64;
  331. DebugLines.Length = LineData.getU64(&Offset);
  332. } else {
  333. DebugLines.Format = dwarf::DWARF32;
  334. DebugLines.Length = LengthOrDWARF64Prefix;
  335. }
  336. assert(DebugLines.Length);
  337. uint64_t LineTableLength = *DebugLines.Length;
  338. uint64_t SizeOfPrologueLength =
  339. DebugLines.Format == dwarf::DWARF64 ? 8 : 4;
  340. DebugLines.Version = LineData.getU16(&Offset);
  341. DebugLines.PrologueLength =
  342. LineData.getUnsigned(&Offset, SizeOfPrologueLength);
  343. assert(DebugLines.PrologueLength);
  344. const uint64_t EndPrologue = *DebugLines.PrologueLength + Offset;
  345. DebugLines.MinInstLength = LineData.getU8(&Offset);
  346. if (DebugLines.Version >= 4)
  347. DebugLines.MaxOpsPerInst = LineData.getU8(&Offset);
  348. DebugLines.DefaultIsStmt = LineData.getU8(&Offset);
  349. DebugLines.LineBase = LineData.getU8(&Offset);
  350. DebugLines.LineRange = LineData.getU8(&Offset);
  351. DebugLines.OpcodeBase = LineData.getU8(&Offset);
  352. DebugLines.StandardOpcodeLengths.emplace();
  353. for (uint8_t i = 1; i < DebugLines.OpcodeBase; ++i)
  354. DebugLines.StandardOpcodeLengths->push_back(LineData.getU8(&Offset));
  355. while (Offset < EndPrologue) {
  356. StringRef Dir = LineData.getCStr(&Offset);
  357. if (!Dir.empty())
  358. DebugLines.IncludeDirs.push_back(Dir);
  359. else
  360. break;
  361. }
  362. while (Offset < EndPrologue) {
  363. DWARFYAML::File TmpFile;
  364. if (dumpFileEntry(LineData, Offset, TmpFile))
  365. DebugLines.Files.push_back(TmpFile);
  366. else
  367. break;
  368. }
  369. const uint64_t LineEnd =
  370. LineTableLength + *StmtOffset + SizeOfPrologueLength;
  371. while (Offset < LineEnd) {
  372. DWARFYAML::LineTableOpcode NewOp = {};
  373. NewOp.Opcode = (dwarf::LineNumberOps)LineData.getU8(&Offset);
  374. if (NewOp.Opcode == 0) {
  375. auto StartExt = Offset;
  376. NewOp.ExtLen = LineData.getULEB128(&Offset);
  377. NewOp.SubOpcode =
  378. (dwarf::LineNumberExtendedOps)LineData.getU8(&Offset);
  379. switch (NewOp.SubOpcode) {
  380. case dwarf::DW_LNE_set_address:
  381. case dwarf::DW_LNE_set_discriminator:
  382. NewOp.Data = LineData.getAddress(&Offset);
  383. break;
  384. case dwarf::DW_LNE_define_file:
  385. dumpFileEntry(LineData, Offset, NewOp.FileEntry);
  386. break;
  387. case dwarf::DW_LNE_end_sequence:
  388. break;
  389. default:
  390. while (Offset < StartExt + *NewOp.ExtLen)
  391. NewOp.UnknownOpcodeData.push_back(LineData.getU8(&Offset));
  392. }
  393. } else if (NewOp.Opcode < *DebugLines.OpcodeBase) {
  394. switch (NewOp.Opcode) {
  395. case dwarf::DW_LNS_copy:
  396. case dwarf::DW_LNS_negate_stmt:
  397. case dwarf::DW_LNS_set_basic_block:
  398. case dwarf::DW_LNS_const_add_pc:
  399. case dwarf::DW_LNS_set_prologue_end:
  400. case dwarf::DW_LNS_set_epilogue_begin:
  401. break;
  402. case dwarf::DW_LNS_advance_pc:
  403. case dwarf::DW_LNS_set_file:
  404. case dwarf::DW_LNS_set_column:
  405. case dwarf::DW_LNS_set_isa:
  406. NewOp.Data = LineData.getULEB128(&Offset);
  407. break;
  408. case dwarf::DW_LNS_advance_line:
  409. NewOp.SData = LineData.getSLEB128(&Offset);
  410. break;
  411. case dwarf::DW_LNS_fixed_advance_pc:
  412. NewOp.Data = LineData.getU16(&Offset);
  413. break;
  414. default:
  415. for (uint8_t i = 0;
  416. i < (*DebugLines.StandardOpcodeLengths)[NewOp.Opcode - 1]; ++i)
  417. NewOp.StandardOpcodeData.push_back(LineData.getULEB128(&Offset));
  418. }
  419. }
  420. DebugLines.Opcodes.push_back(NewOp);
  421. }
  422. Y.DebugLines.push_back(DebugLines);
  423. }
  424. }
  425. }