wasm2yaml.cpp 14 KB

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