wasm2yaml.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. //===------ utils/wasm2yaml.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 "obj2yaml.h"
  9. #include "llvm/Object/COFF.h"
  10. #include "llvm/ObjectYAML/WasmYAML.h"
  11. #include "llvm/Support/ErrorHandling.h"
  12. #include "llvm/Support/YAMLTraits.h"
  13. using namespace llvm;
  14. using object::WasmSection;
  15. namespace {
  16. class WasmDumper {
  17. const object::WasmObjectFile &Obj;
  18. public:
  19. WasmDumper(const object::WasmObjectFile &O) : Obj(O) {}
  20. ErrorOr<WasmYAML::Object *> dump();
  21. std::unique_ptr<WasmYAML::CustomSection>
  22. dumpCustomSection(const WasmSection &WasmSec);
  23. };
  24. } // namespace
  25. static WasmYAML::Limits makeLimits(const wasm::WasmLimits &Limits) {
  26. WasmYAML::Limits L;
  27. L.Flags = Limits.Flags;
  28. L.Minimum = Limits.Minimum;
  29. L.Maximum = Limits.Maximum;
  30. return L;
  31. }
  32. static WasmYAML::Table makeTable(uint32_t Index,
  33. const wasm::WasmTableType &Type) {
  34. WasmYAML::Table T;
  35. T.Index = Index;
  36. T.ElemType = Type.ElemType;
  37. T.TableLimits = makeLimits(Type.Limits);
  38. return T;
  39. }
  40. std::unique_ptr<WasmYAML::CustomSection>
  41. WasmDumper::dumpCustomSection(const WasmSection &WasmSec) {
  42. std::unique_ptr<WasmYAML::CustomSection> CustomSec;
  43. if (WasmSec.Name == "dylink" || WasmSec.Name == "dylink.0") {
  44. std::unique_ptr<WasmYAML::DylinkSection> DylinkSec =
  45. std::make_unique<WasmYAML::DylinkSection>();
  46. const wasm::WasmDylinkInfo& Info = Obj.dylinkInfo();
  47. DylinkSec->MemorySize = Info.MemorySize;
  48. DylinkSec->MemoryAlignment = Info.MemoryAlignment;
  49. DylinkSec->TableSize = Info.TableSize;
  50. DylinkSec->TableAlignment = Info.TableAlignment;
  51. DylinkSec->Needed = Info.Needed;
  52. for (const auto &Imp : Info.ImportInfo)
  53. DylinkSec->ImportInfo.push_back({Imp.Module, Imp.Field, Imp.Flags});
  54. for (const auto &Exp : Info.ExportInfo)
  55. DylinkSec->ExportInfo.push_back({Exp.Name, Exp.Flags});
  56. CustomSec = std::move(DylinkSec);
  57. } else if (WasmSec.Name == "name") {
  58. std::unique_ptr<WasmYAML::NameSection> NameSec =
  59. std::make_unique<WasmYAML::NameSection>();
  60. for (const llvm::wasm::WasmDebugName &Name : Obj.debugNames()) {
  61. WasmYAML::NameEntry NameEntry;
  62. NameEntry.Name = Name.Name;
  63. NameEntry.Index = Name.Index;
  64. if (Name.Type == llvm::wasm::NameType::FUNCTION) {
  65. NameSec->FunctionNames.push_back(NameEntry);
  66. } else if (Name.Type == llvm::wasm::NameType::GLOBAL) {
  67. NameSec->GlobalNames.push_back(NameEntry);
  68. } else {
  69. assert(Name.Type == llvm::wasm::NameType::DATA_SEGMENT);
  70. NameSec->DataSegmentNames.push_back(NameEntry);
  71. }
  72. }
  73. CustomSec = std::move(NameSec);
  74. } else if (WasmSec.Name == "linking") {
  75. std::unique_ptr<WasmYAML::LinkingSection> LinkingSec =
  76. std::make_unique<WasmYAML::LinkingSection>();
  77. LinkingSec->Version = Obj.linkingData().Version;
  78. ArrayRef<StringRef> Comdats = Obj.linkingData().Comdats;
  79. for (StringRef ComdatName : Comdats)
  80. LinkingSec->Comdats.emplace_back(WasmYAML::Comdat{ComdatName, {}});
  81. for (auto &Func : Obj.functions()) {
  82. if (Func.Comdat != UINT32_MAX) {
  83. LinkingSec->Comdats[Func.Comdat].Entries.emplace_back(
  84. WasmYAML::ComdatEntry{wasm::WASM_COMDAT_FUNCTION, Func.Index});
  85. }
  86. }
  87. uint32_t SegmentIndex = 0;
  88. for (const object::WasmSegment &Segment : Obj.dataSegments()) {
  89. if (!Segment.Data.Name.empty()) {
  90. WasmYAML::SegmentInfo SegmentInfo;
  91. SegmentInfo.Name = Segment.Data.Name;
  92. SegmentInfo.Index = SegmentIndex;
  93. SegmentInfo.Alignment = Segment.Data.Alignment;
  94. SegmentInfo.Flags = Segment.Data.LinkingFlags;
  95. LinkingSec->SegmentInfos.push_back(SegmentInfo);
  96. }
  97. if (Segment.Data.Comdat != UINT32_MAX) {
  98. LinkingSec->Comdats[Segment.Data.Comdat].Entries.emplace_back(
  99. WasmYAML::ComdatEntry{wasm::WASM_COMDAT_DATA, SegmentIndex});
  100. }
  101. SegmentIndex++;
  102. }
  103. uint32_t SectionIndex = 0;
  104. for (const auto &Sec : Obj.sections()) {
  105. const WasmSection &WasmSec = Obj.getWasmSection(Sec);
  106. if (WasmSec.Comdat != UINT32_MAX)
  107. LinkingSec->Comdats[WasmSec.Comdat].Entries.emplace_back(
  108. WasmYAML::ComdatEntry{wasm::WASM_COMDAT_SECTION, SectionIndex});
  109. SectionIndex++;
  110. }
  111. uint32_t SymbolIndex = 0;
  112. for (const wasm::WasmSymbolInfo &Symbol : Obj.linkingData().SymbolTable) {
  113. WasmYAML::SymbolInfo Info;
  114. Info.Index = SymbolIndex++;
  115. Info.Kind = static_cast<uint32_t>(Symbol.Kind);
  116. Info.Name = Symbol.Name;
  117. Info.Flags = Symbol.Flags;
  118. switch (Symbol.Kind) {
  119. case wasm::WASM_SYMBOL_TYPE_DATA:
  120. Info.DataRef = Symbol.DataRef;
  121. break;
  122. case wasm::WASM_SYMBOL_TYPE_FUNCTION:
  123. case wasm::WASM_SYMBOL_TYPE_GLOBAL:
  124. case wasm::WASM_SYMBOL_TYPE_TABLE:
  125. case wasm::WASM_SYMBOL_TYPE_TAG:
  126. Info.ElementIndex = Symbol.ElementIndex;
  127. break;
  128. case wasm::WASM_SYMBOL_TYPE_SECTION:
  129. Info.ElementIndex = Symbol.ElementIndex;
  130. break;
  131. }
  132. LinkingSec->SymbolTable.emplace_back(Info);
  133. }
  134. for (const wasm::WasmInitFunc &Func : Obj.linkingData().InitFunctions) {
  135. WasmYAML::InitFunction F{Func.Priority, Func.Symbol};
  136. LinkingSec->InitFunctions.emplace_back(F);
  137. }
  138. CustomSec = std::move(LinkingSec);
  139. } else if (WasmSec.Name == "producers") {
  140. std::unique_ptr<WasmYAML::ProducersSection> ProducersSec =
  141. std::make_unique<WasmYAML::ProducersSection>();
  142. const llvm::wasm::WasmProducerInfo &Info = Obj.getProducerInfo();
  143. for (auto &E : Info.Languages) {
  144. WasmYAML::ProducerEntry Producer;
  145. Producer.Name = E.first;
  146. Producer.Version = E.second;
  147. ProducersSec->Languages.push_back(Producer);
  148. }
  149. for (auto &E : Info.Tools) {
  150. WasmYAML::ProducerEntry Producer;
  151. Producer.Name = E.first;
  152. Producer.Version = E.second;
  153. ProducersSec->Tools.push_back(Producer);
  154. }
  155. for (auto &E : Info.SDKs) {
  156. WasmYAML::ProducerEntry Producer;
  157. Producer.Name = E.first;
  158. Producer.Version = E.second;
  159. ProducersSec->SDKs.push_back(Producer);
  160. }
  161. CustomSec = std::move(ProducersSec);
  162. } else if (WasmSec.Name == "target_features") {
  163. std::unique_ptr<WasmYAML::TargetFeaturesSection> TargetFeaturesSec =
  164. std::make_unique<WasmYAML::TargetFeaturesSection>();
  165. for (auto &E : Obj.getTargetFeatures()) {
  166. WasmYAML::FeatureEntry Feature;
  167. Feature.Prefix = E.Prefix;
  168. Feature.Name = E.Name;
  169. TargetFeaturesSec->Features.push_back(Feature);
  170. }
  171. CustomSec = std::move(TargetFeaturesSec);
  172. } else {
  173. CustomSec = std::make_unique<WasmYAML::CustomSection>(WasmSec.Name);
  174. }
  175. CustomSec->Payload = yaml::BinaryRef(WasmSec.Content);
  176. return CustomSec;
  177. }
  178. ErrorOr<WasmYAML::Object *> WasmDumper::dump() {
  179. auto Y = std::make_unique<WasmYAML::Object>();
  180. // Dump header
  181. Y->Header.Version = Obj.getHeader().Version;
  182. // Dump sections
  183. for (const auto &Sec : Obj.sections()) {
  184. const WasmSection &WasmSec = Obj.getWasmSection(Sec);
  185. std::unique_ptr<WasmYAML::Section> S;
  186. switch (WasmSec.Type) {
  187. case wasm::WASM_SEC_CUSTOM: {
  188. if (WasmSec.Name.startswith("reloc.")) {
  189. // Relocations are attached the sections they apply to rather than
  190. // being represented as a custom section in the YAML output.
  191. continue;
  192. }
  193. S = dumpCustomSection(WasmSec);
  194. break;
  195. }
  196. case wasm::WASM_SEC_TYPE: {
  197. auto TypeSec = std::make_unique<WasmYAML::TypeSection>();
  198. uint32_t Index = 0;
  199. for (const auto &FunctionSig : Obj.types()) {
  200. WasmYAML::Signature Sig;
  201. Sig.Index = Index++;
  202. for (const auto &ParamType : FunctionSig.Params)
  203. Sig.ParamTypes.emplace_back(static_cast<uint32_t>(ParamType));
  204. for (const auto &ReturnType : FunctionSig.Returns)
  205. Sig.ReturnTypes.emplace_back(static_cast<uint32_t>(ReturnType));
  206. TypeSec->Signatures.push_back(Sig);
  207. }
  208. S = std::move(TypeSec);
  209. break;
  210. }
  211. case wasm::WASM_SEC_IMPORT: {
  212. auto ImportSec = std::make_unique<WasmYAML::ImportSection>();
  213. for (auto &Import : Obj.imports()) {
  214. WasmYAML::Import Im;
  215. Im.Module = Import.Module;
  216. Im.Field = Import.Field;
  217. Im.Kind = Import.Kind;
  218. switch (Im.Kind) {
  219. case wasm::WASM_EXTERNAL_FUNCTION:
  220. Im.SigIndex = Import.SigIndex;
  221. break;
  222. case wasm::WASM_EXTERNAL_GLOBAL:
  223. Im.GlobalImport.Type = Import.Global.Type;
  224. Im.GlobalImport.Mutable = Import.Global.Mutable;
  225. break;
  226. case wasm::WASM_EXTERNAL_TAG:
  227. Im.SigIndex = Import.SigIndex;
  228. break;
  229. case wasm::WASM_EXTERNAL_TABLE:
  230. // FIXME: Currently we always output an index of 0 for any imported
  231. // table.
  232. Im.TableImport = makeTable(0, Import.Table);
  233. break;
  234. case wasm::WASM_EXTERNAL_MEMORY:
  235. Im.Memory = makeLimits(Import.Memory);
  236. break;
  237. }
  238. ImportSec->Imports.push_back(Im);
  239. }
  240. S = std::move(ImportSec);
  241. break;
  242. }
  243. case wasm::WASM_SEC_FUNCTION: {
  244. auto FuncSec = std::make_unique<WasmYAML::FunctionSection>();
  245. for (const auto &Func : Obj.functions()) {
  246. FuncSec->FunctionTypes.push_back(Func.SigIndex);
  247. }
  248. S = std::move(FuncSec);
  249. break;
  250. }
  251. case wasm::WASM_SEC_TABLE: {
  252. auto TableSec = std::make_unique<WasmYAML::TableSection>();
  253. for (const wasm::WasmTable &Table : Obj.tables()) {
  254. TableSec->Tables.push_back(makeTable(Table.Index, Table.Type));
  255. }
  256. S = std::move(TableSec);
  257. break;
  258. }
  259. case wasm::WASM_SEC_MEMORY: {
  260. auto MemorySec = std::make_unique<WasmYAML::MemorySection>();
  261. for (const wasm::WasmLimits &Memory : Obj.memories()) {
  262. MemorySec->Memories.push_back(makeLimits(Memory));
  263. }
  264. S = std::move(MemorySec);
  265. break;
  266. }
  267. case wasm::WASM_SEC_TAG: {
  268. auto TagSec = std::make_unique<WasmYAML::TagSection>();
  269. for (auto &Tag : Obj.tags()) {
  270. TagSec->TagTypes.push_back(Tag.SigIndex);
  271. }
  272. S = std::move(TagSec);
  273. break;
  274. }
  275. case wasm::WASM_SEC_GLOBAL: {
  276. auto GlobalSec = std::make_unique<WasmYAML::GlobalSection>();
  277. for (auto &Global : Obj.globals()) {
  278. WasmYAML::Global G;
  279. G.Index = Global.Index;
  280. G.Type = Global.Type.Type;
  281. G.Mutable = Global.Type.Mutable;
  282. G.InitExpr = Global.InitExpr;
  283. GlobalSec->Globals.push_back(G);
  284. }
  285. S = std::move(GlobalSec);
  286. break;
  287. }
  288. case wasm::WASM_SEC_START: {
  289. auto StartSec = std::make_unique<WasmYAML::StartSection>();
  290. StartSec->StartFunction = Obj.startFunction();
  291. S = std::move(StartSec);
  292. break;
  293. }
  294. case wasm::WASM_SEC_EXPORT: {
  295. auto ExportSec = std::make_unique<WasmYAML::ExportSection>();
  296. for (auto &Export : Obj.exports()) {
  297. WasmYAML::Export Ex;
  298. Ex.Name = Export.Name;
  299. Ex.Kind = Export.Kind;
  300. Ex.Index = Export.Index;
  301. ExportSec->Exports.push_back(Ex);
  302. }
  303. S = std::move(ExportSec);
  304. break;
  305. }
  306. case wasm::WASM_SEC_ELEM: {
  307. auto ElemSec = std::make_unique<WasmYAML::ElemSection>();
  308. for (auto &Segment : Obj.elements()) {
  309. WasmYAML::ElemSegment Seg;
  310. Seg.Flags = Segment.Flags;
  311. Seg.TableNumber = Segment.TableNumber;
  312. Seg.ElemKind = Segment.ElemKind;
  313. Seg.Offset = Segment.Offset;
  314. append_range(Seg.Functions, Segment.Functions);
  315. ElemSec->Segments.push_back(Seg);
  316. }
  317. S = std::move(ElemSec);
  318. break;
  319. }
  320. case wasm::WASM_SEC_CODE: {
  321. auto CodeSec = std::make_unique<WasmYAML::CodeSection>();
  322. for (auto &Func : Obj.functions()) {
  323. WasmYAML::Function Function;
  324. Function.Index = Func.Index;
  325. for (auto &Local : Func.Locals) {
  326. WasmYAML::LocalDecl LocalDecl;
  327. LocalDecl.Type = Local.Type;
  328. LocalDecl.Count = Local.Count;
  329. Function.Locals.push_back(LocalDecl);
  330. }
  331. Function.Body = yaml::BinaryRef(Func.Body);
  332. CodeSec->Functions.push_back(Function);
  333. }
  334. S = std::move(CodeSec);
  335. break;
  336. }
  337. case wasm::WASM_SEC_DATA: {
  338. auto DataSec = std::make_unique<WasmYAML::DataSection>();
  339. for (const object::WasmSegment &Segment : Obj.dataSegments()) {
  340. WasmYAML::DataSegment Seg;
  341. Seg.SectionOffset = Segment.SectionOffset;
  342. Seg.InitFlags = Segment.Data.InitFlags;
  343. Seg.MemoryIndex = Segment.Data.MemoryIndex;
  344. Seg.Offset = Segment.Data.Offset;
  345. Seg.Content = yaml::BinaryRef(Segment.Data.Content);
  346. DataSec->Segments.push_back(Seg);
  347. }
  348. S = std::move(DataSec);
  349. break;
  350. }
  351. case wasm::WASM_SEC_DATACOUNT: {
  352. auto DataCountSec = std::make_unique<WasmYAML::DataCountSection>();
  353. DataCountSec->Count = Obj.dataSegments().size();
  354. S = std::move(DataCountSec);
  355. break;
  356. }
  357. default:
  358. llvm_unreachable("Unknown section type");
  359. break;
  360. }
  361. for (const wasm::WasmRelocation &Reloc : WasmSec.Relocations) {
  362. WasmYAML::Relocation R;
  363. R.Type = Reloc.Type;
  364. R.Index = Reloc.Index;
  365. R.Offset = Reloc.Offset;
  366. R.Addend = Reloc.Addend;
  367. S->Relocations.push_back(R);
  368. }
  369. Y->Sections.push_back(std::move(S));
  370. }
  371. return Y.release();
  372. }
  373. std::error_code wasm2yaml(raw_ostream &Out, const object::WasmObjectFile &Obj) {
  374. WasmDumper Dumper(Obj);
  375. ErrorOr<WasmYAML::Object *> YAMLOrErr = Dumper.dump();
  376. if (std::error_code EC = YAMLOrErr.getError())
  377. return EC;
  378. std::unique_ptr<WasmYAML::Object> YAML(YAMLOrErr.get());
  379. yaml::Output Yout(Out);
  380. Yout << *YAML;
  381. return std::error_code();
  382. }