123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 |
- //===------ utils/wasm2yaml.cpp - obj2yaml conversion tool ------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "obj2yaml.h"
- #include "llvm/Object/COFF.h"
- #include "llvm/ObjectYAML/WasmYAML.h"
- #include "llvm/Support/ErrorHandling.h"
- #include "llvm/Support/YAMLTraits.h"
- using namespace llvm;
- using object::WasmSection;
- namespace {
- class WasmDumper {
- const object::WasmObjectFile &Obj;
- public:
- WasmDumper(const object::WasmObjectFile &O) : Obj(O) {}
- ErrorOr<WasmYAML::Object *> dump();
- std::unique_ptr<WasmYAML::CustomSection>
- dumpCustomSection(const WasmSection &WasmSec);
- };
- } // namespace
- static WasmYAML::Limits makeLimits(const wasm::WasmLimits &Limits) {
- WasmYAML::Limits L;
- L.Flags = Limits.Flags;
- L.Minimum = Limits.Minimum;
- L.Maximum = Limits.Maximum;
- return L;
- }
- static WasmYAML::Table makeTable(uint32_t Index,
- const wasm::WasmTableType &Type) {
- WasmYAML::Table T;
- T.Index = Index;
- T.ElemType = Type.ElemType;
- T.TableLimits = makeLimits(Type.Limits);
- return T;
- }
- std::unique_ptr<WasmYAML::CustomSection>
- WasmDumper::dumpCustomSection(const WasmSection &WasmSec) {
- std::unique_ptr<WasmYAML::CustomSection> CustomSec;
- if (WasmSec.Name == "dylink" || WasmSec.Name == "dylink.0") {
- std::unique_ptr<WasmYAML::DylinkSection> DylinkSec =
- std::make_unique<WasmYAML::DylinkSection>();
- const wasm::WasmDylinkInfo& Info = Obj.dylinkInfo();
- DylinkSec->MemorySize = Info.MemorySize;
- DylinkSec->MemoryAlignment = Info.MemoryAlignment;
- DylinkSec->TableSize = Info.TableSize;
- DylinkSec->TableAlignment = Info.TableAlignment;
- DylinkSec->Needed = Info.Needed;
- for (const auto &Imp : Info.ImportInfo)
- DylinkSec->ImportInfo.push_back({Imp.Module, Imp.Field, Imp.Flags});
- for (const auto &Exp : Info.ExportInfo)
- DylinkSec->ExportInfo.push_back({Exp.Name, Exp.Flags});
- CustomSec = std::move(DylinkSec);
- } else if (WasmSec.Name == "name") {
- std::unique_ptr<WasmYAML::NameSection> NameSec =
- std::make_unique<WasmYAML::NameSection>();
- for (const llvm::wasm::WasmDebugName &Name : Obj.debugNames()) {
- WasmYAML::NameEntry NameEntry;
- NameEntry.Name = Name.Name;
- NameEntry.Index = Name.Index;
- if (Name.Type == llvm::wasm::NameType::FUNCTION) {
- NameSec->FunctionNames.push_back(NameEntry);
- } else if (Name.Type == llvm::wasm::NameType::GLOBAL) {
- NameSec->GlobalNames.push_back(NameEntry);
- } else {
- assert(Name.Type == llvm::wasm::NameType::DATA_SEGMENT);
- NameSec->DataSegmentNames.push_back(NameEntry);
- }
- }
- CustomSec = std::move(NameSec);
- } else if (WasmSec.Name == "linking") {
- std::unique_ptr<WasmYAML::LinkingSection> LinkingSec =
- std::make_unique<WasmYAML::LinkingSection>();
- LinkingSec->Version = Obj.linkingData().Version;
- ArrayRef<StringRef> Comdats = Obj.linkingData().Comdats;
- for (StringRef ComdatName : Comdats)
- LinkingSec->Comdats.emplace_back(WasmYAML::Comdat{ComdatName, {}});
- for (auto &Func : Obj.functions()) {
- if (Func.Comdat != UINT32_MAX) {
- LinkingSec->Comdats[Func.Comdat].Entries.emplace_back(
- WasmYAML::ComdatEntry{wasm::WASM_COMDAT_FUNCTION, Func.Index});
- }
- }
- uint32_t SegmentIndex = 0;
- for (const object::WasmSegment &Segment : Obj.dataSegments()) {
- if (!Segment.Data.Name.empty()) {
- WasmYAML::SegmentInfo SegmentInfo;
- SegmentInfo.Name = Segment.Data.Name;
- SegmentInfo.Index = SegmentIndex;
- SegmentInfo.Alignment = Segment.Data.Alignment;
- SegmentInfo.Flags = Segment.Data.LinkingFlags;
- LinkingSec->SegmentInfos.push_back(SegmentInfo);
- }
- if (Segment.Data.Comdat != UINT32_MAX) {
- LinkingSec->Comdats[Segment.Data.Comdat].Entries.emplace_back(
- WasmYAML::ComdatEntry{wasm::WASM_COMDAT_DATA, SegmentIndex});
- }
- SegmentIndex++;
- }
- uint32_t SectionIndex = 0;
- for (const auto &Sec : Obj.sections()) {
- const WasmSection &WasmSec = Obj.getWasmSection(Sec);
- if (WasmSec.Comdat != UINT32_MAX)
- LinkingSec->Comdats[WasmSec.Comdat].Entries.emplace_back(
- WasmYAML::ComdatEntry{wasm::WASM_COMDAT_SECTION, SectionIndex});
- SectionIndex++;
- }
- uint32_t SymbolIndex = 0;
- for (const wasm::WasmSymbolInfo &Symbol : Obj.linkingData().SymbolTable) {
- WasmYAML::SymbolInfo Info;
- Info.Index = SymbolIndex++;
- Info.Kind = static_cast<uint32_t>(Symbol.Kind);
- Info.Name = Symbol.Name;
- Info.Flags = Symbol.Flags;
- switch (Symbol.Kind) {
- case wasm::WASM_SYMBOL_TYPE_DATA:
- Info.DataRef = Symbol.DataRef;
- break;
- case wasm::WASM_SYMBOL_TYPE_FUNCTION:
- case wasm::WASM_SYMBOL_TYPE_GLOBAL:
- case wasm::WASM_SYMBOL_TYPE_TABLE:
- case wasm::WASM_SYMBOL_TYPE_TAG:
- Info.ElementIndex = Symbol.ElementIndex;
- break;
- case wasm::WASM_SYMBOL_TYPE_SECTION:
- Info.ElementIndex = Symbol.ElementIndex;
- break;
- }
- LinkingSec->SymbolTable.emplace_back(Info);
- }
- for (const wasm::WasmInitFunc &Func : Obj.linkingData().InitFunctions) {
- WasmYAML::InitFunction F{Func.Priority, Func.Symbol};
- LinkingSec->InitFunctions.emplace_back(F);
- }
- CustomSec = std::move(LinkingSec);
- } else if (WasmSec.Name == "producers") {
- std::unique_ptr<WasmYAML::ProducersSection> ProducersSec =
- std::make_unique<WasmYAML::ProducersSection>();
- const llvm::wasm::WasmProducerInfo &Info = Obj.getProducerInfo();
- for (auto &E : Info.Languages) {
- WasmYAML::ProducerEntry Producer;
- Producer.Name = E.first;
- Producer.Version = E.second;
- ProducersSec->Languages.push_back(Producer);
- }
- for (auto &E : Info.Tools) {
- WasmYAML::ProducerEntry Producer;
- Producer.Name = E.first;
- Producer.Version = E.second;
- ProducersSec->Tools.push_back(Producer);
- }
- for (auto &E : Info.SDKs) {
- WasmYAML::ProducerEntry Producer;
- Producer.Name = E.first;
- Producer.Version = E.second;
- ProducersSec->SDKs.push_back(Producer);
- }
- CustomSec = std::move(ProducersSec);
- } else if (WasmSec.Name == "target_features") {
- std::unique_ptr<WasmYAML::TargetFeaturesSection> TargetFeaturesSec =
- std::make_unique<WasmYAML::TargetFeaturesSection>();
- for (auto &E : Obj.getTargetFeatures()) {
- WasmYAML::FeatureEntry Feature;
- Feature.Prefix = E.Prefix;
- Feature.Name = E.Name;
- TargetFeaturesSec->Features.push_back(Feature);
- }
- CustomSec = std::move(TargetFeaturesSec);
- } else {
- CustomSec = std::make_unique<WasmYAML::CustomSection>(WasmSec.Name);
- }
- CustomSec->Payload = yaml::BinaryRef(WasmSec.Content);
- return CustomSec;
- }
- ErrorOr<WasmYAML::Object *> WasmDumper::dump() {
- auto Y = std::make_unique<WasmYAML::Object>();
- // Dump header
- Y->Header.Version = Obj.getHeader().Version;
- // Dump sections
- for (const auto &Sec : Obj.sections()) {
- const WasmSection &WasmSec = Obj.getWasmSection(Sec);
- std::unique_ptr<WasmYAML::Section> S;
- switch (WasmSec.Type) {
- case wasm::WASM_SEC_CUSTOM: {
- if (WasmSec.Name.startswith("reloc.")) {
- // Relocations are attached the sections they apply to rather than
- // being represented as a custom section in the YAML output.
- continue;
- }
- S = dumpCustomSection(WasmSec);
- break;
- }
- case wasm::WASM_SEC_TYPE: {
- auto TypeSec = std::make_unique<WasmYAML::TypeSection>();
- uint32_t Index = 0;
- for (const auto &FunctionSig : Obj.types()) {
- WasmYAML::Signature Sig;
- Sig.Index = Index++;
- for (const auto &ParamType : FunctionSig.Params)
- Sig.ParamTypes.emplace_back(static_cast<uint32_t>(ParamType));
- for (const auto &ReturnType : FunctionSig.Returns)
- Sig.ReturnTypes.emplace_back(static_cast<uint32_t>(ReturnType));
- TypeSec->Signatures.push_back(Sig);
- }
- S = std::move(TypeSec);
- break;
- }
- case wasm::WASM_SEC_IMPORT: {
- auto ImportSec = std::make_unique<WasmYAML::ImportSection>();
- for (auto &Import : Obj.imports()) {
- WasmYAML::Import Im;
- Im.Module = Import.Module;
- Im.Field = Import.Field;
- Im.Kind = Import.Kind;
- switch (Im.Kind) {
- case wasm::WASM_EXTERNAL_FUNCTION:
- Im.SigIndex = Import.SigIndex;
- break;
- case wasm::WASM_EXTERNAL_GLOBAL:
- Im.GlobalImport.Type = Import.Global.Type;
- Im.GlobalImport.Mutable = Import.Global.Mutable;
- break;
- case wasm::WASM_EXTERNAL_TAG:
- Im.SigIndex = Import.SigIndex;
- break;
- case wasm::WASM_EXTERNAL_TABLE:
- // FIXME: Currently we always output an index of 0 for any imported
- // table.
- Im.TableImport = makeTable(0, Import.Table);
- break;
- case wasm::WASM_EXTERNAL_MEMORY:
- Im.Memory = makeLimits(Import.Memory);
- break;
- }
- ImportSec->Imports.push_back(Im);
- }
- S = std::move(ImportSec);
- break;
- }
- case wasm::WASM_SEC_FUNCTION: {
- auto FuncSec = std::make_unique<WasmYAML::FunctionSection>();
- for (const auto &Func : Obj.functions()) {
- FuncSec->FunctionTypes.push_back(Func.SigIndex);
- }
- S = std::move(FuncSec);
- break;
- }
- case wasm::WASM_SEC_TABLE: {
- auto TableSec = std::make_unique<WasmYAML::TableSection>();
- for (const wasm::WasmTable &Table : Obj.tables()) {
- TableSec->Tables.push_back(makeTable(Table.Index, Table.Type));
- }
- S = std::move(TableSec);
- break;
- }
- case wasm::WASM_SEC_MEMORY: {
- auto MemorySec = std::make_unique<WasmYAML::MemorySection>();
- for (const wasm::WasmLimits &Memory : Obj.memories()) {
- MemorySec->Memories.push_back(makeLimits(Memory));
- }
- S = std::move(MemorySec);
- break;
- }
- case wasm::WASM_SEC_TAG: {
- auto TagSec = std::make_unique<WasmYAML::TagSection>();
- for (auto &Tag : Obj.tags()) {
- TagSec->TagTypes.push_back(Tag.SigIndex);
- }
- S = std::move(TagSec);
- break;
- }
- case wasm::WASM_SEC_GLOBAL: {
- auto GlobalSec = std::make_unique<WasmYAML::GlobalSection>();
- for (auto &Global : Obj.globals()) {
- WasmYAML::Global G;
- G.Index = Global.Index;
- G.Type = Global.Type.Type;
- G.Mutable = Global.Type.Mutable;
- G.InitExpr = Global.InitExpr;
- GlobalSec->Globals.push_back(G);
- }
- S = std::move(GlobalSec);
- break;
- }
- case wasm::WASM_SEC_START: {
- auto StartSec = std::make_unique<WasmYAML::StartSection>();
- StartSec->StartFunction = Obj.startFunction();
- S = std::move(StartSec);
- break;
- }
- case wasm::WASM_SEC_EXPORT: {
- auto ExportSec = std::make_unique<WasmYAML::ExportSection>();
- for (auto &Export : Obj.exports()) {
- WasmYAML::Export Ex;
- Ex.Name = Export.Name;
- Ex.Kind = Export.Kind;
- Ex.Index = Export.Index;
- ExportSec->Exports.push_back(Ex);
- }
- S = std::move(ExportSec);
- break;
- }
- case wasm::WASM_SEC_ELEM: {
- auto ElemSec = std::make_unique<WasmYAML::ElemSection>();
- for (auto &Segment : Obj.elements()) {
- WasmYAML::ElemSegment Seg;
- Seg.Flags = Segment.Flags;
- Seg.TableNumber = Segment.TableNumber;
- Seg.ElemKind = Segment.ElemKind;
- Seg.Offset = Segment.Offset;
- append_range(Seg.Functions, Segment.Functions);
- ElemSec->Segments.push_back(Seg);
- }
- S = std::move(ElemSec);
- break;
- }
- case wasm::WASM_SEC_CODE: {
- auto CodeSec = std::make_unique<WasmYAML::CodeSection>();
- for (auto &Func : Obj.functions()) {
- WasmYAML::Function Function;
- Function.Index = Func.Index;
- for (auto &Local : Func.Locals) {
- WasmYAML::LocalDecl LocalDecl;
- LocalDecl.Type = Local.Type;
- LocalDecl.Count = Local.Count;
- Function.Locals.push_back(LocalDecl);
- }
- Function.Body = yaml::BinaryRef(Func.Body);
- CodeSec->Functions.push_back(Function);
- }
- S = std::move(CodeSec);
- break;
- }
- case wasm::WASM_SEC_DATA: {
- auto DataSec = std::make_unique<WasmYAML::DataSection>();
- for (const object::WasmSegment &Segment : Obj.dataSegments()) {
- WasmYAML::DataSegment Seg;
- Seg.SectionOffset = Segment.SectionOffset;
- Seg.InitFlags = Segment.Data.InitFlags;
- Seg.MemoryIndex = Segment.Data.MemoryIndex;
- Seg.Offset = Segment.Data.Offset;
- Seg.Content = yaml::BinaryRef(Segment.Data.Content);
- DataSec->Segments.push_back(Seg);
- }
- S = std::move(DataSec);
- break;
- }
- case wasm::WASM_SEC_DATACOUNT: {
- auto DataCountSec = std::make_unique<WasmYAML::DataCountSection>();
- DataCountSec->Count = Obj.dataSegments().size();
- S = std::move(DataCountSec);
- break;
- }
- default:
- llvm_unreachable("Unknown section type");
- break;
- }
- for (const wasm::WasmRelocation &Reloc : WasmSec.Relocations) {
- WasmYAML::Relocation R;
- R.Type = Reloc.Type;
- R.Index = Reloc.Index;
- R.Offset = Reloc.Offset;
- R.Addend = Reloc.Addend;
- S->Relocations.push_back(R);
- }
- Y->Sections.push_back(std::move(S));
- }
- return Y.release();
- }
- std::error_code wasm2yaml(raw_ostream &Out, const object::WasmObjectFile &Obj) {
- WasmDumper Dumper(Obj);
- ErrorOr<WasmYAML::Object *> YAMLOrErr = Dumper.dump();
- if (std::error_code EC = YAMLOrErr.getError())
- return EC;
- std::unique_ptr<WasmYAML::Object> YAML(YAMLOrErr.get());
- yaml::Output Yout(Out);
- Yout << *YAML;
- return std::error_code();
- }
|