DWARFEmitter.cpp 40 KB

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