DWARFEmitter.cpp 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081
  1. //===- DWARFEmitter - Convert YAML to DWARF binary data -------------------===//
  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. ///
  9. /// \file
  10. /// The DWARF component of yaml2obj. Provided as library code for tests.
  11. ///
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/ObjectYAML/DWARFEmitter.h"
  14. #include "llvm/ADT/ArrayRef.h"
  15. #include "llvm/ADT/StringMap.h"
  16. #include "llvm/ADT/StringRef.h"
  17. #include "llvm/ADT/StringSwitch.h"
  18. #include "llvm/BinaryFormat/Dwarf.h"
  19. #include "llvm/ObjectYAML/DWARFYAML.h"
  20. #include "llvm/Support/Errc.h"
  21. #include "llvm/Support/Error.h"
  22. #include "llvm/Support/Host.h"
  23. #include "llvm/Support/LEB128.h"
  24. #include "llvm/Support/MathExtras.h"
  25. #include "llvm/Support/MemoryBuffer.h"
  26. #include "llvm/Support/SourceMgr.h"
  27. #include "llvm/Support/SwapByteOrder.h"
  28. #include "llvm/Support/YAMLTraits.h"
  29. #include "llvm/Support/raw_ostream.h"
  30. #include <algorithm>
  31. #include <cassert>
  32. #include <cstddef>
  33. #include <cstdint>
  34. #include <memory>
  35. #include <optional>
  36. #include <string>
  37. #include <vector>
  38. using namespace llvm;
  39. template <typename T>
  40. static void writeInteger(T Integer, raw_ostream &OS, bool IsLittleEndian) {
  41. if (IsLittleEndian != sys::IsLittleEndianHost)
  42. sys::swapByteOrder(Integer);
  43. OS.write(reinterpret_cast<char *>(&Integer), sizeof(T));
  44. }
  45. static Error writeVariableSizedInteger(uint64_t Integer, size_t Size,
  46. raw_ostream &OS, bool IsLittleEndian) {
  47. if (8 == Size)
  48. writeInteger((uint64_t)Integer, OS, IsLittleEndian);
  49. else if (4 == Size)
  50. writeInteger((uint32_t)Integer, OS, IsLittleEndian);
  51. else if (2 == Size)
  52. writeInteger((uint16_t)Integer, OS, IsLittleEndian);
  53. else if (1 == Size)
  54. writeInteger((uint8_t)Integer, OS, IsLittleEndian);
  55. else
  56. return createStringError(errc::not_supported,
  57. "invalid integer write size: %zu", Size);
  58. return Error::success();
  59. }
  60. static void ZeroFillBytes(raw_ostream &OS, size_t Size) {
  61. std::vector<uint8_t> FillData(Size, 0);
  62. OS.write(reinterpret_cast<char *>(FillData.data()), Size);
  63. }
  64. static void writeInitialLength(const dwarf::DwarfFormat Format,
  65. const uint64_t Length, raw_ostream &OS,
  66. bool IsLittleEndian) {
  67. bool IsDWARF64 = Format == dwarf::DWARF64;
  68. if (IsDWARF64)
  69. cantFail(writeVariableSizedInteger(dwarf::DW_LENGTH_DWARF64, 4, OS,
  70. IsLittleEndian));
  71. cantFail(
  72. writeVariableSizedInteger(Length, IsDWARF64 ? 8 : 4, OS, IsLittleEndian));
  73. }
  74. static void writeDWARFOffset(uint64_t Offset, dwarf::DwarfFormat Format,
  75. raw_ostream &OS, bool IsLittleEndian) {
  76. cantFail(writeVariableSizedInteger(Offset, Format == dwarf::DWARF64 ? 8 : 4,
  77. OS, IsLittleEndian));
  78. }
  79. Error DWARFYAML::emitDebugStr(raw_ostream &OS, const DWARFYAML::Data &DI) {
  80. for (StringRef Str : *DI.DebugStrings) {
  81. OS.write(Str.data(), Str.size());
  82. OS.write('\0');
  83. }
  84. return Error::success();
  85. }
  86. StringRef DWARFYAML::Data::getAbbrevTableContentByIndex(uint64_t Index) const {
  87. assert(Index < DebugAbbrev.size() &&
  88. "Index should be less than the size of DebugAbbrev array");
  89. auto It = AbbrevTableContents.find(Index);
  90. if (It != AbbrevTableContents.cend())
  91. return It->second;
  92. std::string AbbrevTableBuffer;
  93. raw_string_ostream OS(AbbrevTableBuffer);
  94. uint64_t AbbrevCode = 0;
  95. for (const DWARFYAML::Abbrev &AbbrevDecl : DebugAbbrev[Index].Table) {
  96. AbbrevCode = AbbrevDecl.Code ? (uint64_t)*AbbrevDecl.Code : AbbrevCode + 1;
  97. encodeULEB128(AbbrevCode, OS);
  98. encodeULEB128(AbbrevDecl.Tag, OS);
  99. OS.write(AbbrevDecl.Children);
  100. for (const auto &Attr : AbbrevDecl.Attributes) {
  101. encodeULEB128(Attr.Attribute, OS);
  102. encodeULEB128(Attr.Form, OS);
  103. if (Attr.Form == dwarf::DW_FORM_implicit_const)
  104. encodeSLEB128(Attr.Value, OS);
  105. }
  106. encodeULEB128(0, OS);
  107. encodeULEB128(0, OS);
  108. }
  109. // The abbreviations for a given compilation unit end with an entry
  110. // consisting of a 0 byte for the abbreviation code.
  111. OS.write_zeros(1);
  112. AbbrevTableContents.insert({Index, AbbrevTableBuffer});
  113. return AbbrevTableContents[Index];
  114. }
  115. Error DWARFYAML::emitDebugAbbrev(raw_ostream &OS, const DWARFYAML::Data &DI) {
  116. for (uint64_t I = 0; I < DI.DebugAbbrev.size(); ++I) {
  117. StringRef AbbrevTableContent = DI.getAbbrevTableContentByIndex(I);
  118. OS.write(AbbrevTableContent.data(), AbbrevTableContent.size());
  119. }
  120. return Error::success();
  121. }
  122. Error DWARFYAML::emitDebugAranges(raw_ostream &OS, const DWARFYAML::Data &DI) {
  123. assert(DI.DebugAranges && "unexpected emitDebugAranges() call");
  124. for (const auto &Range : *DI.DebugAranges) {
  125. uint8_t AddrSize;
  126. if (Range.AddrSize)
  127. AddrSize = *Range.AddrSize;
  128. else
  129. AddrSize = DI.Is64BitAddrSize ? 8 : 4;
  130. uint64_t Length = 4; // sizeof(version) 2 + sizeof(address_size) 1 +
  131. // sizeof(segment_selector_size) 1
  132. Length +=
  133. Range.Format == dwarf::DWARF64 ? 8 : 4; // sizeof(debug_info_offset)
  134. const uint64_t HeaderLength =
  135. Length + (Range.Format == dwarf::DWARF64
  136. ? 12
  137. : 4); // sizeof(unit_header) = 12 (DWARF64) or 4 (DWARF32)
  138. const uint64_t PaddedHeaderLength = alignTo(HeaderLength, AddrSize * 2);
  139. if (Range.Length) {
  140. Length = *Range.Length;
  141. } else {
  142. Length += PaddedHeaderLength - HeaderLength;
  143. Length += AddrSize * 2 * (Range.Descriptors.size() + 1);
  144. }
  145. writeInitialLength(Range.Format, Length, OS, DI.IsLittleEndian);
  146. writeInteger((uint16_t)Range.Version, OS, DI.IsLittleEndian);
  147. writeDWARFOffset(Range.CuOffset, Range.Format, OS, DI.IsLittleEndian);
  148. writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
  149. writeInteger((uint8_t)Range.SegSize, OS, DI.IsLittleEndian);
  150. ZeroFillBytes(OS, PaddedHeaderLength - HeaderLength);
  151. for (const auto &Descriptor : Range.Descriptors) {
  152. if (Error Err = writeVariableSizedInteger(Descriptor.Address, AddrSize,
  153. OS, DI.IsLittleEndian))
  154. return createStringError(errc::not_supported,
  155. "unable to write debug_aranges address: %s",
  156. toString(std::move(Err)).c_str());
  157. cantFail(writeVariableSizedInteger(Descriptor.Length, AddrSize, OS,
  158. DI.IsLittleEndian));
  159. }
  160. ZeroFillBytes(OS, AddrSize * 2);
  161. }
  162. return Error::success();
  163. }
  164. Error DWARFYAML::emitDebugRanges(raw_ostream &OS, const DWARFYAML::Data &DI) {
  165. const size_t RangesOffset = OS.tell();
  166. uint64_t EntryIndex = 0;
  167. for (const auto &DebugRanges : *DI.DebugRanges) {
  168. const size_t CurrOffset = OS.tell() - RangesOffset;
  169. if (DebugRanges.Offset && (uint64_t)*DebugRanges.Offset < CurrOffset)
  170. return createStringError(errc::invalid_argument,
  171. "'Offset' for 'debug_ranges' with index " +
  172. Twine(EntryIndex) +
  173. " must be greater than or equal to the "
  174. "number of bytes written already (0x" +
  175. Twine::utohexstr(CurrOffset) + ")");
  176. if (DebugRanges.Offset)
  177. ZeroFillBytes(OS, *DebugRanges.Offset - CurrOffset);
  178. uint8_t AddrSize;
  179. if (DebugRanges.AddrSize)
  180. AddrSize = *DebugRanges.AddrSize;
  181. else
  182. AddrSize = DI.Is64BitAddrSize ? 8 : 4;
  183. for (const auto &Entry : DebugRanges.Entries) {
  184. if (Error Err = writeVariableSizedInteger(Entry.LowOffset, AddrSize, OS,
  185. DI.IsLittleEndian))
  186. return createStringError(
  187. errc::not_supported,
  188. "unable to write debug_ranges address offset: %s",
  189. toString(std::move(Err)).c_str());
  190. cantFail(writeVariableSizedInteger(Entry.HighOffset, AddrSize, OS,
  191. DI.IsLittleEndian));
  192. }
  193. ZeroFillBytes(OS, AddrSize * 2);
  194. ++EntryIndex;
  195. }
  196. return Error::success();
  197. }
  198. static Error emitPubSection(raw_ostream &OS, const DWARFYAML::PubSection &Sect,
  199. bool IsLittleEndian, bool IsGNUPubSec = false) {
  200. writeInitialLength(Sect.Format, Sect.Length, OS, IsLittleEndian);
  201. writeInteger((uint16_t)Sect.Version, OS, IsLittleEndian);
  202. writeInteger((uint32_t)Sect.UnitOffset, OS, IsLittleEndian);
  203. writeInteger((uint32_t)Sect.UnitSize, OS, IsLittleEndian);
  204. for (const auto &Entry : Sect.Entries) {
  205. writeInteger((uint32_t)Entry.DieOffset, OS, IsLittleEndian);
  206. if (IsGNUPubSec)
  207. writeInteger((uint8_t)Entry.Descriptor, OS, IsLittleEndian);
  208. OS.write(Entry.Name.data(), Entry.Name.size());
  209. OS.write('\0');
  210. }
  211. return Error::success();
  212. }
  213. Error DWARFYAML::emitDebugPubnames(raw_ostream &OS, const Data &DI) {
  214. assert(DI.PubNames && "unexpected emitDebugPubnames() call");
  215. return emitPubSection(OS, *DI.PubNames, DI.IsLittleEndian);
  216. }
  217. Error DWARFYAML::emitDebugPubtypes(raw_ostream &OS, const Data &DI) {
  218. assert(DI.PubTypes && "unexpected emitDebugPubtypes() call");
  219. return emitPubSection(OS, *DI.PubTypes, DI.IsLittleEndian);
  220. }
  221. Error DWARFYAML::emitDebugGNUPubnames(raw_ostream &OS, const Data &DI) {
  222. assert(DI.GNUPubNames && "unexpected emitDebugGNUPubnames() call");
  223. return emitPubSection(OS, *DI.GNUPubNames, DI.IsLittleEndian,
  224. /*IsGNUStyle=*/true);
  225. }
  226. Error DWARFYAML::emitDebugGNUPubtypes(raw_ostream &OS, const Data &DI) {
  227. assert(DI.GNUPubTypes && "unexpected emitDebugGNUPubtypes() call");
  228. return emitPubSection(OS, *DI.GNUPubTypes, DI.IsLittleEndian,
  229. /*IsGNUStyle=*/true);
  230. }
  231. static Expected<uint64_t> writeDIE(const DWARFYAML::Data &DI, uint64_t CUIndex,
  232. uint64_t AbbrevTableID,
  233. const dwarf::FormParams &Params,
  234. const DWARFYAML::Entry &Entry,
  235. raw_ostream &OS, bool IsLittleEndian) {
  236. uint64_t EntryBegin = OS.tell();
  237. encodeULEB128(Entry.AbbrCode, OS);
  238. uint32_t AbbrCode = Entry.AbbrCode;
  239. if (AbbrCode == 0 || Entry.Values.empty())
  240. return OS.tell() - EntryBegin;
  241. Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr =
  242. DI.getAbbrevTableInfoByID(AbbrevTableID);
  243. if (!AbbrevTableInfoOrErr)
  244. return createStringError(errc::invalid_argument,
  245. toString(AbbrevTableInfoOrErr.takeError()) +
  246. " for compilation unit with index " +
  247. utostr(CUIndex));
  248. ArrayRef<DWARFYAML::Abbrev> AbbrevDecls(
  249. DI.DebugAbbrev[AbbrevTableInfoOrErr->Index].Table);
  250. if (AbbrCode > AbbrevDecls.size())
  251. return createStringError(
  252. errc::invalid_argument,
  253. "abbrev code must be less than or equal to the number of "
  254. "entries in abbreviation table");
  255. const DWARFYAML::Abbrev &Abbrev = AbbrevDecls[AbbrCode - 1];
  256. auto FormVal = Entry.Values.begin();
  257. auto AbbrForm = Abbrev.Attributes.begin();
  258. for (; FormVal != Entry.Values.end() && AbbrForm != Abbrev.Attributes.end();
  259. ++FormVal, ++AbbrForm) {
  260. dwarf::Form Form = AbbrForm->Form;
  261. bool Indirect;
  262. do {
  263. Indirect = false;
  264. switch (Form) {
  265. case dwarf::DW_FORM_addr:
  266. // TODO: Test this error.
  267. if (Error Err = writeVariableSizedInteger(
  268. FormVal->Value, Params.AddrSize, OS, IsLittleEndian))
  269. return std::move(Err);
  270. break;
  271. case dwarf::DW_FORM_ref_addr:
  272. // TODO: Test this error.
  273. if (Error Err = writeVariableSizedInteger(FormVal->Value,
  274. Params.getRefAddrByteSize(),
  275. OS, IsLittleEndian))
  276. return std::move(Err);
  277. break;
  278. case dwarf::DW_FORM_exprloc:
  279. case dwarf::DW_FORM_block:
  280. encodeULEB128(FormVal->BlockData.size(), OS);
  281. OS.write((const char *)FormVal->BlockData.data(),
  282. FormVal->BlockData.size());
  283. break;
  284. case dwarf::DW_FORM_block1: {
  285. writeInteger((uint8_t)FormVal->BlockData.size(), OS, IsLittleEndian);
  286. OS.write((const char *)FormVal->BlockData.data(),
  287. FormVal->BlockData.size());
  288. break;
  289. }
  290. case dwarf::DW_FORM_block2: {
  291. writeInteger((uint16_t)FormVal->BlockData.size(), OS, IsLittleEndian);
  292. OS.write((const char *)FormVal->BlockData.data(),
  293. FormVal->BlockData.size());
  294. break;
  295. }
  296. case dwarf::DW_FORM_block4: {
  297. writeInteger((uint32_t)FormVal->BlockData.size(), OS, IsLittleEndian);
  298. OS.write((const char *)FormVal->BlockData.data(),
  299. FormVal->BlockData.size());
  300. break;
  301. }
  302. case dwarf::DW_FORM_strx:
  303. case dwarf::DW_FORM_addrx:
  304. case dwarf::DW_FORM_rnglistx:
  305. case dwarf::DW_FORM_loclistx:
  306. case dwarf::DW_FORM_udata:
  307. case dwarf::DW_FORM_ref_udata:
  308. case dwarf::DW_FORM_GNU_addr_index:
  309. case dwarf::DW_FORM_GNU_str_index:
  310. encodeULEB128(FormVal->Value, OS);
  311. break;
  312. case dwarf::DW_FORM_data1:
  313. case dwarf::DW_FORM_ref1:
  314. case dwarf::DW_FORM_flag:
  315. case dwarf::DW_FORM_strx1:
  316. case dwarf::DW_FORM_addrx1:
  317. writeInteger((uint8_t)FormVal->Value, OS, IsLittleEndian);
  318. break;
  319. case dwarf::DW_FORM_data2:
  320. case dwarf::DW_FORM_ref2:
  321. case dwarf::DW_FORM_strx2:
  322. case dwarf::DW_FORM_addrx2:
  323. writeInteger((uint16_t)FormVal->Value, OS, IsLittleEndian);
  324. break;
  325. case dwarf::DW_FORM_data4:
  326. case dwarf::DW_FORM_ref4:
  327. case dwarf::DW_FORM_ref_sup4:
  328. case dwarf::DW_FORM_strx4:
  329. case dwarf::DW_FORM_addrx4:
  330. writeInteger((uint32_t)FormVal->Value, OS, IsLittleEndian);
  331. break;
  332. case dwarf::DW_FORM_data8:
  333. case dwarf::DW_FORM_ref8:
  334. case dwarf::DW_FORM_ref_sup8:
  335. case dwarf::DW_FORM_ref_sig8:
  336. writeInteger((uint64_t)FormVal->Value, OS, IsLittleEndian);
  337. break;
  338. case dwarf::DW_FORM_sdata:
  339. encodeSLEB128(FormVal->Value, OS);
  340. break;
  341. case dwarf::DW_FORM_string:
  342. OS.write(FormVal->CStr.data(), FormVal->CStr.size());
  343. OS.write('\0');
  344. break;
  345. case dwarf::DW_FORM_indirect:
  346. encodeULEB128(FormVal->Value, OS);
  347. Indirect = true;
  348. Form = static_cast<dwarf::Form>((uint64_t)FormVal->Value);
  349. ++FormVal;
  350. break;
  351. case dwarf::DW_FORM_strp:
  352. case dwarf::DW_FORM_sec_offset:
  353. case dwarf::DW_FORM_GNU_ref_alt:
  354. case dwarf::DW_FORM_GNU_strp_alt:
  355. case dwarf::DW_FORM_line_strp:
  356. case dwarf::DW_FORM_strp_sup:
  357. cantFail(writeVariableSizedInteger(FormVal->Value,
  358. Params.getDwarfOffsetByteSize(), OS,
  359. IsLittleEndian));
  360. break;
  361. default:
  362. break;
  363. }
  364. } while (Indirect);
  365. }
  366. return OS.tell() - EntryBegin;
  367. }
  368. Error DWARFYAML::emitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) {
  369. for (uint64_t I = 0; I < DI.CompileUnits.size(); ++I) {
  370. const DWARFYAML::Unit &Unit = DI.CompileUnits[I];
  371. uint8_t AddrSize;
  372. if (Unit.AddrSize)
  373. AddrSize = *Unit.AddrSize;
  374. else
  375. AddrSize = DI.Is64BitAddrSize ? 8 : 4;
  376. dwarf::FormParams Params = {Unit.Version, AddrSize, Unit.Format};
  377. uint64_t Length = 3; // sizeof(version) + sizeof(address_size)
  378. Length += Unit.Version >= 5 ? 1 : 0; // sizeof(unit_type)
  379. Length += Params.getDwarfOffsetByteSize(); // sizeof(debug_abbrev_offset)
  380. // Since the length of the current compilation unit is undetermined yet, we
  381. // firstly write the content of the compilation unit to a buffer to
  382. // calculate it and then serialize the buffer content to the actual output
  383. // stream.
  384. std::string EntryBuffer;
  385. raw_string_ostream EntryBufferOS(EntryBuffer);
  386. uint64_t AbbrevTableID = Unit.AbbrevTableID.value_or(I);
  387. for (const DWARFYAML::Entry &Entry : Unit.Entries) {
  388. if (Expected<uint64_t> EntryLength =
  389. writeDIE(DI, I, AbbrevTableID, Params, Entry, EntryBufferOS,
  390. DI.IsLittleEndian))
  391. Length += *EntryLength;
  392. else
  393. return EntryLength.takeError();
  394. }
  395. // If the length is specified in the YAML description, we use it instead of
  396. // the actual length.
  397. if (Unit.Length)
  398. Length = *Unit.Length;
  399. writeInitialLength(Unit.Format, Length, OS, DI.IsLittleEndian);
  400. writeInteger((uint16_t)Unit.Version, OS, DI.IsLittleEndian);
  401. uint64_t AbbrevTableOffset = 0;
  402. if (Unit.AbbrOffset) {
  403. AbbrevTableOffset = *Unit.AbbrOffset;
  404. } else {
  405. if (Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr =
  406. DI.getAbbrevTableInfoByID(AbbrevTableID)) {
  407. AbbrevTableOffset = AbbrevTableInfoOrErr->Offset;
  408. } else {
  409. // The current compilation unit may not have DIEs and it will not be
  410. // able to find the associated abbrev table. We consume the error and
  411. // assign 0 to the debug_abbrev_offset in such circumstances.
  412. consumeError(AbbrevTableInfoOrErr.takeError());
  413. }
  414. }
  415. if (Unit.Version >= 5) {
  416. writeInteger((uint8_t)Unit.Type, OS, DI.IsLittleEndian);
  417. writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
  418. writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian);
  419. } else {
  420. writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian);
  421. writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
  422. }
  423. OS.write(EntryBuffer.data(), EntryBuffer.size());
  424. }
  425. return Error::success();
  426. }
  427. static void emitFileEntry(raw_ostream &OS, const DWARFYAML::File &File) {
  428. OS.write(File.Name.data(), File.Name.size());
  429. OS.write('\0');
  430. encodeULEB128(File.DirIdx, OS);
  431. encodeULEB128(File.ModTime, OS);
  432. encodeULEB128(File.Length, OS);
  433. }
  434. static void writeExtendedOpcode(const DWARFYAML::LineTableOpcode &Op,
  435. uint8_t AddrSize, bool IsLittleEndian,
  436. raw_ostream &OS) {
  437. // The first byte of extended opcodes is a zero byte. The next bytes are an
  438. // ULEB128 integer giving the number of bytes in the instruction itself (does
  439. // not include the first zero byte or the size). We serialize the instruction
  440. // itself into the OpBuffer and then write the size of the buffer and the
  441. // buffer to the real output stream.
  442. std::string OpBuffer;
  443. raw_string_ostream OpBufferOS(OpBuffer);
  444. writeInteger((uint8_t)Op.SubOpcode, OpBufferOS, IsLittleEndian);
  445. switch (Op.SubOpcode) {
  446. case dwarf::DW_LNE_set_address:
  447. cantFail(writeVariableSizedInteger(Op.Data, AddrSize, OpBufferOS,
  448. IsLittleEndian));
  449. break;
  450. case dwarf::DW_LNE_define_file:
  451. emitFileEntry(OpBufferOS, Op.FileEntry);
  452. break;
  453. case dwarf::DW_LNE_set_discriminator:
  454. encodeULEB128(Op.Data, OpBufferOS);
  455. break;
  456. case dwarf::DW_LNE_end_sequence:
  457. break;
  458. default:
  459. for (auto OpByte : Op.UnknownOpcodeData)
  460. writeInteger((uint8_t)OpByte, OpBufferOS, IsLittleEndian);
  461. }
  462. uint64_t ExtLen = Op.ExtLen.value_or(OpBuffer.size());
  463. encodeULEB128(ExtLen, OS);
  464. OS.write(OpBuffer.data(), OpBuffer.size());
  465. }
  466. static void writeLineTableOpcode(const DWARFYAML::LineTableOpcode &Op,
  467. uint8_t OpcodeBase, uint8_t AddrSize,
  468. raw_ostream &OS, bool IsLittleEndian) {
  469. writeInteger((uint8_t)Op.Opcode, OS, IsLittleEndian);
  470. if (Op.Opcode == 0) {
  471. writeExtendedOpcode(Op, AddrSize, IsLittleEndian, OS);
  472. } else if (Op.Opcode < OpcodeBase) {
  473. switch (Op.Opcode) {
  474. case dwarf::DW_LNS_copy:
  475. case dwarf::DW_LNS_negate_stmt:
  476. case dwarf::DW_LNS_set_basic_block:
  477. case dwarf::DW_LNS_const_add_pc:
  478. case dwarf::DW_LNS_set_prologue_end:
  479. case dwarf::DW_LNS_set_epilogue_begin:
  480. break;
  481. case dwarf::DW_LNS_advance_pc:
  482. case dwarf::DW_LNS_set_file:
  483. case dwarf::DW_LNS_set_column:
  484. case dwarf::DW_LNS_set_isa:
  485. encodeULEB128(Op.Data, OS);
  486. break;
  487. case dwarf::DW_LNS_advance_line:
  488. encodeSLEB128(Op.SData, OS);
  489. break;
  490. case dwarf::DW_LNS_fixed_advance_pc:
  491. writeInteger((uint16_t)Op.Data, OS, IsLittleEndian);
  492. break;
  493. default:
  494. for (auto OpData : Op.StandardOpcodeData) {
  495. encodeULEB128(OpData, OS);
  496. }
  497. }
  498. }
  499. }
  500. static std::vector<uint8_t>
  501. getStandardOpcodeLengths(uint16_t Version, std::optional<uint8_t> OpcodeBase) {
  502. // If the opcode_base field isn't specified, we returns the
  503. // standard_opcode_lengths array according to the version by default.
  504. std::vector<uint8_t> StandardOpcodeLengths{0, 1, 1, 1, 1, 0,
  505. 0, 0, 1, 0, 0, 1};
  506. if (Version == 2) {
  507. // DWARF v2 uses the same first 9 standard opcodes as v3-5.
  508. StandardOpcodeLengths.resize(9);
  509. } else if (OpcodeBase) {
  510. StandardOpcodeLengths.resize(*OpcodeBase > 0 ? *OpcodeBase - 1 : 0, 0);
  511. }
  512. return StandardOpcodeLengths;
  513. }
  514. Error DWARFYAML::emitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) {
  515. for (const DWARFYAML::LineTable &LineTable : DI.DebugLines) {
  516. // Buffer holds the bytes following the header_length (or prologue_length in
  517. // DWARFv2) field to the end of the line number program itself.
  518. std::string Buffer;
  519. raw_string_ostream BufferOS(Buffer);
  520. writeInteger(LineTable.MinInstLength, BufferOS, DI.IsLittleEndian);
  521. // TODO: Add support for emitting DWARFv5 line table.
  522. if (LineTable.Version >= 4)
  523. writeInteger(LineTable.MaxOpsPerInst, BufferOS, DI.IsLittleEndian);
  524. writeInteger(LineTable.DefaultIsStmt, BufferOS, DI.IsLittleEndian);
  525. writeInteger(LineTable.LineBase, BufferOS, DI.IsLittleEndian);
  526. writeInteger(LineTable.LineRange, BufferOS, DI.IsLittleEndian);
  527. std::vector<uint8_t> StandardOpcodeLengths =
  528. LineTable.StandardOpcodeLengths.value_or(
  529. getStandardOpcodeLengths(LineTable.Version, LineTable.OpcodeBase));
  530. uint8_t OpcodeBase = LineTable.OpcodeBase
  531. ? *LineTable.OpcodeBase
  532. : StandardOpcodeLengths.size() + 1;
  533. writeInteger(OpcodeBase, BufferOS, DI.IsLittleEndian);
  534. for (uint8_t OpcodeLength : StandardOpcodeLengths)
  535. writeInteger(OpcodeLength, BufferOS, DI.IsLittleEndian);
  536. for (StringRef IncludeDir : LineTable.IncludeDirs) {
  537. BufferOS.write(IncludeDir.data(), IncludeDir.size());
  538. BufferOS.write('\0');
  539. }
  540. BufferOS.write('\0');
  541. for (const DWARFYAML::File &File : LineTable.Files)
  542. emitFileEntry(BufferOS, File);
  543. BufferOS.write('\0');
  544. uint64_t HeaderLength =
  545. LineTable.PrologueLength ? *LineTable.PrologueLength : Buffer.size();
  546. for (const DWARFYAML::LineTableOpcode &Op : LineTable.Opcodes)
  547. writeLineTableOpcode(Op, OpcodeBase, DI.Is64BitAddrSize ? 8 : 4, BufferOS,
  548. DI.IsLittleEndian);
  549. uint64_t Length;
  550. if (LineTable.Length) {
  551. Length = *LineTable.Length;
  552. } else {
  553. Length = 2; // sizeof(version)
  554. Length +=
  555. (LineTable.Format == dwarf::DWARF64 ? 8 : 4); // sizeof(header_length)
  556. Length += Buffer.size();
  557. }
  558. writeInitialLength(LineTable.Format, Length, OS, DI.IsLittleEndian);
  559. writeInteger(LineTable.Version, OS, DI.IsLittleEndian);
  560. writeDWARFOffset(HeaderLength, LineTable.Format, OS, DI.IsLittleEndian);
  561. OS.write(Buffer.data(), Buffer.size());
  562. }
  563. return Error::success();
  564. }
  565. Error DWARFYAML::emitDebugAddr(raw_ostream &OS, const Data &DI) {
  566. for (const AddrTableEntry &TableEntry : *DI.DebugAddr) {
  567. uint8_t AddrSize;
  568. if (TableEntry.AddrSize)
  569. AddrSize = *TableEntry.AddrSize;
  570. else
  571. AddrSize = DI.Is64BitAddrSize ? 8 : 4;
  572. uint64_t Length;
  573. if (TableEntry.Length)
  574. Length = (uint64_t)*TableEntry.Length;
  575. else
  576. // 2 (version) + 1 (address_size) + 1 (segment_selector_size) = 4
  577. Length = 4 + (AddrSize + TableEntry.SegSelectorSize) *
  578. TableEntry.SegAddrPairs.size();
  579. writeInitialLength(TableEntry.Format, Length, OS, DI.IsLittleEndian);
  580. writeInteger((uint16_t)TableEntry.Version, OS, DI.IsLittleEndian);
  581. writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
  582. writeInteger((uint8_t)TableEntry.SegSelectorSize, OS, DI.IsLittleEndian);
  583. for (const SegAddrPair &Pair : TableEntry.SegAddrPairs) {
  584. if (TableEntry.SegSelectorSize != yaml::Hex8{0})
  585. if (Error Err = writeVariableSizedInteger(Pair.Segment,
  586. TableEntry.SegSelectorSize,
  587. OS, DI.IsLittleEndian))
  588. return createStringError(errc::not_supported,
  589. "unable to write debug_addr segment: %s",
  590. toString(std::move(Err)).c_str());
  591. if (AddrSize != 0)
  592. if (Error Err = writeVariableSizedInteger(Pair.Address, AddrSize, OS,
  593. DI.IsLittleEndian))
  594. return createStringError(errc::not_supported,
  595. "unable to write debug_addr address: %s",
  596. toString(std::move(Err)).c_str());
  597. }
  598. }
  599. return Error::success();
  600. }
  601. Error DWARFYAML::emitDebugStrOffsets(raw_ostream &OS, const Data &DI) {
  602. assert(DI.DebugStrOffsets && "unexpected emitDebugStrOffsets() call");
  603. for (const DWARFYAML::StringOffsetsTable &Table : *DI.DebugStrOffsets) {
  604. uint64_t Length;
  605. if (Table.Length)
  606. Length = *Table.Length;
  607. else
  608. // sizeof(version) + sizeof(padding) = 4
  609. Length =
  610. 4 + Table.Offsets.size() * (Table.Format == dwarf::DWARF64 ? 8 : 4);
  611. writeInitialLength(Table.Format, Length, OS, DI.IsLittleEndian);
  612. writeInteger((uint16_t)Table.Version, OS, DI.IsLittleEndian);
  613. writeInteger((uint16_t)Table.Padding, OS, DI.IsLittleEndian);
  614. for (uint64_t Offset : Table.Offsets)
  615. writeDWARFOffset(Offset, Table.Format, OS, DI.IsLittleEndian);
  616. }
  617. return Error::success();
  618. }
  619. static Error checkOperandCount(StringRef EncodingString,
  620. ArrayRef<yaml::Hex64> Values,
  621. uint64_t ExpectedOperands) {
  622. if (Values.size() != ExpectedOperands)
  623. return createStringError(
  624. errc::invalid_argument,
  625. "invalid number (%zu) of operands for the operator: %s, %" PRIu64
  626. " expected",
  627. Values.size(), EncodingString.str().c_str(), ExpectedOperands);
  628. return Error::success();
  629. }
  630. static Error writeListEntryAddress(StringRef EncodingName, raw_ostream &OS,
  631. uint64_t Addr, uint8_t AddrSize,
  632. bool IsLittleEndian) {
  633. if (Error Err = writeVariableSizedInteger(Addr, AddrSize, OS, IsLittleEndian))
  634. return createStringError(errc::invalid_argument,
  635. "unable to write address for the operator %s: %s",
  636. EncodingName.str().c_str(),
  637. toString(std::move(Err)).c_str());
  638. return Error::success();
  639. }
  640. static Expected<uint64_t>
  641. writeDWARFExpression(raw_ostream &OS,
  642. const DWARFYAML::DWARFOperation &Operation,
  643. uint8_t AddrSize, bool IsLittleEndian) {
  644. auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
  645. return checkOperandCount(dwarf::OperationEncodingString(Operation.Operator),
  646. Operation.Values, ExpectedOperands);
  647. };
  648. uint64_t ExpressionBegin = OS.tell();
  649. writeInteger((uint8_t)Operation.Operator, OS, IsLittleEndian);
  650. switch (Operation.Operator) {
  651. case dwarf::DW_OP_consts:
  652. if (Error Err = CheckOperands(1))
  653. return std::move(Err);
  654. encodeSLEB128(Operation.Values[0], OS);
  655. break;
  656. case dwarf::DW_OP_stack_value:
  657. if (Error Err = CheckOperands(0))
  658. return std::move(Err);
  659. break;
  660. default:
  661. StringRef EncodingStr = dwarf::OperationEncodingString(Operation.Operator);
  662. return createStringError(errc::not_supported,
  663. "DWARF expression: " +
  664. (EncodingStr.empty()
  665. ? "0x" + utohexstr(Operation.Operator)
  666. : EncodingStr) +
  667. " is not supported");
  668. }
  669. return OS.tell() - ExpressionBegin;
  670. }
  671. static Expected<uint64_t> writeListEntry(raw_ostream &OS,
  672. const DWARFYAML::RnglistEntry &Entry,
  673. uint8_t AddrSize,
  674. bool IsLittleEndian) {
  675. uint64_t BeginOffset = OS.tell();
  676. writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);
  677. StringRef EncodingName = dwarf::RangeListEncodingString(Entry.Operator);
  678. auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
  679. return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);
  680. };
  681. auto WriteAddress = [&](uint64_t Addr) -> Error {
  682. return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,
  683. IsLittleEndian);
  684. };
  685. switch (Entry.Operator) {
  686. case dwarf::DW_RLE_end_of_list:
  687. if (Error Err = CheckOperands(0))
  688. return std::move(Err);
  689. break;
  690. case dwarf::DW_RLE_base_addressx:
  691. if (Error Err = CheckOperands(1))
  692. return std::move(Err);
  693. encodeULEB128(Entry.Values[0], OS);
  694. break;
  695. case dwarf::DW_RLE_startx_endx:
  696. case dwarf::DW_RLE_startx_length:
  697. case dwarf::DW_RLE_offset_pair:
  698. if (Error Err = CheckOperands(2))
  699. return std::move(Err);
  700. encodeULEB128(Entry.Values[0], OS);
  701. encodeULEB128(Entry.Values[1], OS);
  702. break;
  703. case dwarf::DW_RLE_base_address:
  704. if (Error Err = CheckOperands(1))
  705. return std::move(Err);
  706. if (Error Err = WriteAddress(Entry.Values[0]))
  707. return std::move(Err);
  708. break;
  709. case dwarf::DW_RLE_start_end:
  710. if (Error Err = CheckOperands(2))
  711. return std::move(Err);
  712. if (Error Err = WriteAddress(Entry.Values[0]))
  713. return std::move(Err);
  714. cantFail(WriteAddress(Entry.Values[1]));
  715. break;
  716. case dwarf::DW_RLE_start_length:
  717. if (Error Err = CheckOperands(2))
  718. return std::move(Err);
  719. if (Error Err = WriteAddress(Entry.Values[0]))
  720. return std::move(Err);
  721. encodeULEB128(Entry.Values[1], OS);
  722. break;
  723. }
  724. return OS.tell() - BeginOffset;
  725. }
  726. static Expected<uint64_t> writeListEntry(raw_ostream &OS,
  727. const DWARFYAML::LoclistEntry &Entry,
  728. uint8_t AddrSize,
  729. bool IsLittleEndian) {
  730. uint64_t BeginOffset = OS.tell();
  731. writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);
  732. StringRef EncodingName = dwarf::LocListEncodingString(Entry.Operator);
  733. auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
  734. return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);
  735. };
  736. auto WriteAddress = [&](uint64_t Addr) -> Error {
  737. return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,
  738. IsLittleEndian);
  739. };
  740. auto WriteDWARFOperations = [&]() -> Error {
  741. std::string OpBuffer;
  742. raw_string_ostream OpBufferOS(OpBuffer);
  743. uint64_t DescriptionsLength = 0;
  744. for (const DWARFYAML::DWARFOperation &Op : Entry.Descriptions) {
  745. if (Expected<uint64_t> OpSize =
  746. writeDWARFExpression(OpBufferOS, Op, AddrSize, IsLittleEndian))
  747. DescriptionsLength += *OpSize;
  748. else
  749. return OpSize.takeError();
  750. }
  751. if (Entry.DescriptionsLength)
  752. DescriptionsLength = *Entry.DescriptionsLength;
  753. else
  754. DescriptionsLength = OpBuffer.size();
  755. encodeULEB128(DescriptionsLength, OS);
  756. OS.write(OpBuffer.data(), OpBuffer.size());
  757. return Error::success();
  758. };
  759. switch (Entry.Operator) {
  760. case dwarf::DW_LLE_end_of_list:
  761. if (Error Err = CheckOperands(0))
  762. return std::move(Err);
  763. break;
  764. case dwarf::DW_LLE_base_addressx:
  765. if (Error Err = CheckOperands(1))
  766. return std::move(Err);
  767. encodeULEB128(Entry.Values[0], OS);
  768. break;
  769. case dwarf::DW_LLE_startx_endx:
  770. case dwarf::DW_LLE_startx_length:
  771. case dwarf::DW_LLE_offset_pair:
  772. if (Error Err = CheckOperands(2))
  773. return std::move(Err);
  774. encodeULEB128(Entry.Values[0], OS);
  775. encodeULEB128(Entry.Values[1], OS);
  776. if (Error Err = WriteDWARFOperations())
  777. return std::move(Err);
  778. break;
  779. case dwarf::DW_LLE_default_location:
  780. if (Error Err = CheckOperands(0))
  781. return std::move(Err);
  782. if (Error Err = WriteDWARFOperations())
  783. return std::move(Err);
  784. break;
  785. case dwarf::DW_LLE_base_address:
  786. if (Error Err = CheckOperands(1))
  787. return std::move(Err);
  788. if (Error Err = WriteAddress(Entry.Values[0]))
  789. return std::move(Err);
  790. break;
  791. case dwarf::DW_LLE_start_end:
  792. if (Error Err = CheckOperands(2))
  793. return std::move(Err);
  794. if (Error Err = WriteAddress(Entry.Values[0]))
  795. return std::move(Err);
  796. cantFail(WriteAddress(Entry.Values[1]));
  797. if (Error Err = WriteDWARFOperations())
  798. return std::move(Err);
  799. break;
  800. case dwarf::DW_LLE_start_length:
  801. if (Error Err = CheckOperands(2))
  802. return std::move(Err);
  803. if (Error Err = WriteAddress(Entry.Values[0]))
  804. return std::move(Err);
  805. encodeULEB128(Entry.Values[1], OS);
  806. if (Error Err = WriteDWARFOperations())
  807. return std::move(Err);
  808. break;
  809. }
  810. return OS.tell() - BeginOffset;
  811. }
  812. template <typename EntryType>
  813. static Error writeDWARFLists(raw_ostream &OS,
  814. ArrayRef<DWARFYAML::ListTable<EntryType>> Tables,
  815. bool IsLittleEndian, bool Is64BitAddrSize) {
  816. for (const DWARFYAML::ListTable<EntryType> &Table : Tables) {
  817. // sizeof(version) + sizeof(address_size) + sizeof(segment_selector_size) +
  818. // sizeof(offset_entry_count) = 8
  819. uint64_t Length = 8;
  820. uint8_t AddrSize;
  821. if (Table.AddrSize)
  822. AddrSize = *Table.AddrSize;
  823. else
  824. AddrSize = Is64BitAddrSize ? 8 : 4;
  825. // Since the length of the current range/location lists entry is
  826. // undetermined yet, we firstly write the content of the range/location
  827. // lists to a buffer to calculate the length and then serialize the buffer
  828. // content to the actual output stream.
  829. std::string ListBuffer;
  830. raw_string_ostream ListBufferOS(ListBuffer);
  831. // Offsets holds offsets for each range/location list. The i-th element is
  832. // the offset from the beginning of the first range/location list to the
  833. // location of the i-th range list.
  834. std::vector<uint64_t> Offsets;
  835. for (const DWARFYAML::ListEntries<EntryType> &List : Table.Lists) {
  836. Offsets.push_back(ListBufferOS.tell());
  837. if (List.Content) {
  838. List.Content->writeAsBinary(ListBufferOS, UINT64_MAX);
  839. Length += List.Content->binary_size();
  840. } else if (List.Entries) {
  841. for (const EntryType &Entry : *List.Entries) {
  842. Expected<uint64_t> EntrySize =
  843. writeListEntry(ListBufferOS, Entry, AddrSize, IsLittleEndian);
  844. if (!EntrySize)
  845. return EntrySize.takeError();
  846. Length += *EntrySize;
  847. }
  848. }
  849. }
  850. // If the offset_entry_count field isn't specified, yaml2obj will infer it
  851. // from the 'Offsets' field in the YAML description. If the 'Offsets' field
  852. // isn't specified either, yaml2obj will infer it from the auto-generated
  853. // offsets.
  854. uint32_t OffsetEntryCount;
  855. if (Table.OffsetEntryCount)
  856. OffsetEntryCount = *Table.OffsetEntryCount;
  857. else
  858. OffsetEntryCount = Table.Offsets ? Table.Offsets->size() : Offsets.size();
  859. uint64_t OffsetsSize =
  860. OffsetEntryCount * (Table.Format == dwarf::DWARF64 ? 8 : 4);
  861. Length += OffsetsSize;
  862. // If the length is specified in the YAML description, we use it instead of
  863. // the actual length.
  864. if (Table.Length)
  865. Length = *Table.Length;
  866. writeInitialLength(Table.Format, Length, OS, IsLittleEndian);
  867. writeInteger((uint16_t)Table.Version, OS, IsLittleEndian);
  868. writeInteger((uint8_t)AddrSize, OS, IsLittleEndian);
  869. writeInteger((uint8_t)Table.SegSelectorSize, OS, IsLittleEndian);
  870. writeInteger((uint32_t)OffsetEntryCount, OS, IsLittleEndian);
  871. auto EmitOffsets = [&](ArrayRef<uint64_t> Offsets, uint64_t OffsetsSize) {
  872. for (uint64_t Offset : Offsets)
  873. writeDWARFOffset(OffsetsSize + Offset, Table.Format, OS,
  874. IsLittleEndian);
  875. };
  876. if (Table.Offsets)
  877. EmitOffsets(ArrayRef<uint64_t>((const uint64_t *)Table.Offsets->data(),
  878. Table.Offsets->size()),
  879. 0);
  880. else if (OffsetEntryCount != 0)
  881. EmitOffsets(Offsets, OffsetsSize);
  882. OS.write(ListBuffer.data(), ListBuffer.size());
  883. }
  884. return Error::success();
  885. }
  886. Error DWARFYAML::emitDebugRnglists(raw_ostream &OS, const Data &DI) {
  887. assert(DI.DebugRnglists && "unexpected emitDebugRnglists() call");
  888. return writeDWARFLists<DWARFYAML::RnglistEntry>(
  889. OS, *DI.DebugRnglists, DI.IsLittleEndian, DI.Is64BitAddrSize);
  890. }
  891. Error DWARFYAML::emitDebugLoclists(raw_ostream &OS, const Data &DI) {
  892. assert(DI.DebugLoclists && "unexpected emitDebugRnglists() call");
  893. return writeDWARFLists<DWARFYAML::LoclistEntry>(
  894. OS, *DI.DebugLoclists, DI.IsLittleEndian, DI.Is64BitAddrSize);
  895. }
  896. std::function<Error(raw_ostream &, const DWARFYAML::Data &)>
  897. DWARFYAML::getDWARFEmitterByName(StringRef SecName) {
  898. auto EmitFunc =
  899. StringSwitch<
  900. std::function<Error(raw_ostream &, const DWARFYAML::Data &)>>(SecName)
  901. .Case("debug_abbrev", DWARFYAML::emitDebugAbbrev)
  902. .Case("debug_addr", DWARFYAML::emitDebugAddr)
  903. .Case("debug_aranges", DWARFYAML::emitDebugAranges)
  904. .Case("debug_gnu_pubnames", DWARFYAML::emitDebugGNUPubnames)
  905. .Case("debug_gnu_pubtypes", DWARFYAML::emitDebugGNUPubtypes)
  906. .Case("debug_info", DWARFYAML::emitDebugInfo)
  907. .Case("debug_line", DWARFYAML::emitDebugLine)
  908. .Case("debug_loclists", DWARFYAML::emitDebugLoclists)
  909. .Case("debug_pubnames", DWARFYAML::emitDebugPubnames)
  910. .Case("debug_pubtypes", DWARFYAML::emitDebugPubtypes)
  911. .Case("debug_ranges", DWARFYAML::emitDebugRanges)
  912. .Case("debug_rnglists", DWARFYAML::emitDebugRnglists)
  913. .Case("debug_str", DWARFYAML::emitDebugStr)
  914. .Case("debug_str_offsets", DWARFYAML::emitDebugStrOffsets)
  915. .Default([&](raw_ostream &, const DWARFYAML::Data &) {
  916. return createStringError(errc::not_supported,
  917. SecName + " is not supported");
  918. });
  919. return EmitFunc;
  920. }
  921. static Error
  922. emitDebugSectionImpl(const DWARFYAML::Data &DI, StringRef Sec,
  923. StringMap<std::unique_ptr<MemoryBuffer>> &OutputBuffers) {
  924. std::string Data;
  925. raw_string_ostream DebugInfoStream(Data);
  926. auto EmitFunc = DWARFYAML::getDWARFEmitterByName(Sec);
  927. if (Error Err = EmitFunc(DebugInfoStream, DI))
  928. return Err;
  929. DebugInfoStream.flush();
  930. if (!Data.empty())
  931. OutputBuffers[Sec] = MemoryBuffer::getMemBufferCopy(Data);
  932. return Error::success();
  933. }
  934. Expected<StringMap<std::unique_ptr<MemoryBuffer>>>
  935. DWARFYAML::emitDebugSections(StringRef YAMLString, bool IsLittleEndian,
  936. bool Is64BitAddrSize) {
  937. auto CollectDiagnostic = [](const SMDiagnostic &Diag, void *DiagContext) {
  938. *static_cast<SMDiagnostic *>(DiagContext) = Diag;
  939. };
  940. SMDiagnostic GeneratedDiag;
  941. yaml::Input YIn(YAMLString, /*Ctxt=*/nullptr, CollectDiagnostic,
  942. &GeneratedDiag);
  943. DWARFYAML::Data DI;
  944. DI.IsLittleEndian = IsLittleEndian;
  945. DI.Is64BitAddrSize = Is64BitAddrSize;
  946. YIn >> DI;
  947. if (YIn.error())
  948. return createStringError(YIn.error(), GeneratedDiag.getMessage());
  949. StringMap<std::unique_ptr<MemoryBuffer>> DebugSections;
  950. Error Err = Error::success();
  951. for (StringRef SecName : DI.getNonEmptySectionNames())
  952. Err = joinErrors(std::move(Err),
  953. emitDebugSectionImpl(DI, SecName, DebugSections));
  954. if (Err)
  955. return std::move(Err);
  956. return std::move(DebugSections);
  957. }