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