Home | History | Annotate | Download | only in obj2yaml
      1 //===------ utils/wasm2yaml.cpp - obj2yaml conversion tool ------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "obj2yaml.h"
     11 #include "llvm/Object/COFF.h"
     12 #include "llvm/ObjectYAML/WasmYAML.h"
     13 #include "llvm/Support/ErrorHandling.h"
     14 #include "llvm/Support/YAMLTraits.h"
     15 
     16 using namespace llvm;
     17 using object::WasmSection;
     18 
     19 namespace {
     20 
     21 class WasmDumper {
     22   const object::WasmObjectFile &Obj;
     23 
     24 public:
     25   WasmDumper(const object::WasmObjectFile &O) : Obj(O) {}
     26 
     27   ErrorOr<WasmYAML::Object *> dump();
     28 
     29   std::unique_ptr<WasmYAML::CustomSection>
     30   dumpCustomSection(const WasmSection &WasmSec);
     31 };
     32 
     33 } // namespace
     34 
     35 static WasmYAML::Table make_table(const wasm::WasmTable &Table) {
     36   WasmYAML::Table T;
     37   T.ElemType = Table.ElemType;
     38   T.TableLimits.Flags = Table.Limits.Flags;
     39   T.TableLimits.Initial = Table.Limits.Initial;
     40   T.TableLimits.Maximum = Table.Limits.Maximum;
     41   return T;
     42 }
     43 
     44 static WasmYAML::Limits make_limits(const wasm::WasmLimits &Limits) {
     45   WasmYAML::Limits L;
     46   L.Flags = Limits.Flags;
     47   L.Initial = Limits.Initial;
     48   L.Maximum = Limits.Maximum;
     49   return L;
     50 }
     51 
     52 std::unique_ptr<WasmYAML::CustomSection> WasmDumper::dumpCustomSection(const WasmSection &WasmSec) {
     53   std::unique_ptr<WasmYAML::CustomSection> CustomSec;
     54   if (WasmSec.Name == "name") {
     55     std::unique_ptr<WasmYAML::NameSection> NameSec = make_unique<WasmYAML::NameSection>();
     56     for (const llvm::wasm::WasmFunctionName &Func: Obj.debugNames()) {
     57       WasmYAML::NameEntry NameEntry;
     58       NameEntry.Name = Func.Name;
     59       NameEntry.Index = Func.Index;
     60       NameSec->FunctionNames.push_back(NameEntry);
     61     }
     62     CustomSec = std::move(NameSec);
     63   } else if (WasmSec.Name == "linking") {
     64     std::unique_ptr<WasmYAML::LinkingSection> LinkingSec = make_unique<WasmYAML::LinkingSection>();
     65     LinkingSec->Version = Obj.linkingData().Version;
     66 
     67     ArrayRef<StringRef> Comdats = Obj.linkingData().Comdats;
     68     for (StringRef ComdatName : Comdats)
     69       LinkingSec->Comdats.emplace_back(WasmYAML::Comdat{ComdatName, {}});
     70     for (auto &Func : Obj.functions()) {
     71       if (Func.Comdat != UINT32_MAX) {
     72         LinkingSec->Comdats[Func.Comdat].Entries.emplace_back(
     73                 WasmYAML::ComdatEntry{wasm::WASM_COMDAT_FUNCTION, Func.Index});
     74       }
     75     }
     76 
     77     uint32_t SegmentIndex = 0;
     78     for (const object::WasmSegment &Segment : Obj.dataSegments()) {
     79       if (!Segment.Data.Name.empty()) {
     80         WasmYAML::SegmentInfo SegmentInfo;
     81         SegmentInfo.Name = Segment.Data.Name;
     82         SegmentInfo.Index = SegmentIndex;
     83         SegmentInfo.Alignment = Segment.Data.Alignment;
     84         SegmentInfo.Flags = Segment.Data.Flags;
     85         LinkingSec->SegmentInfos.push_back(SegmentInfo);
     86       }
     87       if (Segment.Data.Comdat != UINT32_MAX) {
     88         LinkingSec->Comdats[Segment.Data.Comdat].Entries.emplace_back(
     89             WasmYAML::ComdatEntry{wasm::WASM_COMDAT_DATA, SegmentIndex});
     90       }
     91       SegmentIndex++;
     92     }
     93 
     94     uint32_t SymbolIndex = 0;
     95     for (const wasm::WasmSymbolInfo &Symbol : Obj.linkingData().SymbolTable) {
     96       WasmYAML::SymbolInfo Info;
     97       Info.Index = SymbolIndex++;
     98       Info.Kind = static_cast<uint32_t>(Symbol.Kind);
     99       Info.Name = Symbol.Name;
    100       Info.Flags = Symbol.Flags;
    101       switch (Symbol.Kind) {
    102       case wasm::WASM_SYMBOL_TYPE_DATA:
    103         Info.DataRef = Symbol.DataRef;
    104         break;
    105       case wasm::WASM_SYMBOL_TYPE_FUNCTION:
    106       case wasm::WASM_SYMBOL_TYPE_GLOBAL:
    107         Info.ElementIndex = Symbol.ElementIndex;
    108         break;
    109       case wasm::WASM_SYMBOL_TYPE_SECTION:
    110         Info.ElementIndex = Symbol.ElementIndex;
    111         break;
    112       }
    113       LinkingSec->SymbolTable.emplace_back(Info);
    114     }
    115 
    116     for (const wasm::WasmInitFunc &Func : Obj.linkingData().InitFunctions) {
    117       WasmYAML::InitFunction F{Func.Priority, Func.Symbol};
    118       LinkingSec->InitFunctions.emplace_back(F);
    119     }
    120 
    121     CustomSec = std::move(LinkingSec);
    122   } else {
    123     CustomSec = make_unique<WasmYAML::CustomSection>(WasmSec.Name);
    124   }
    125   CustomSec->Payload = yaml::BinaryRef(WasmSec.Content);
    126   return CustomSec;
    127 }
    128 
    129 ErrorOr<WasmYAML::Object *> WasmDumper::dump() {
    130   auto Y = make_unique<WasmYAML::Object>();
    131 
    132   // Dump header
    133   Y->Header.Version = Obj.getHeader().Version;
    134 
    135   // Dump sections
    136   for (const auto &Sec : Obj.sections()) {
    137     const WasmSection &WasmSec = Obj.getWasmSection(Sec);
    138     std::unique_ptr<WasmYAML::Section> S;
    139     switch (WasmSec.Type) {
    140     case wasm::WASM_SEC_CUSTOM: {
    141       if (WasmSec.Name.startswith("reloc.")) {
    142         // Relocations are attached the sections they apply to rather than
    143         // being represented as a custom section in the YAML output.
    144         continue;
    145       }
    146       S = dumpCustomSection(WasmSec);
    147       break;
    148     }
    149     case wasm::WASM_SEC_TYPE: {
    150       auto TypeSec = make_unique<WasmYAML::TypeSection>();
    151       uint32_t Index = 0;
    152       for (const auto &FunctionSig : Obj.types()) {
    153         WasmYAML::Signature Sig;
    154         Sig.Index = Index++;
    155         Sig.ReturnType = FunctionSig.ReturnType;
    156         for (const auto &ParamType : FunctionSig.ParamTypes)
    157           Sig.ParamTypes.push_back(ParamType);
    158         TypeSec->Signatures.push_back(Sig);
    159       }
    160       S = std::move(TypeSec);
    161       break;
    162     }
    163     case wasm::WASM_SEC_IMPORT: {
    164       auto ImportSec = make_unique<WasmYAML::ImportSection>();
    165       for (auto &Import : Obj.imports()) {
    166         WasmYAML::Import Im;
    167         Im.Module = Import.Module;
    168         Im.Field = Import.Field;
    169         Im.Kind = Import.Kind;
    170         switch (Im.Kind) {
    171         case wasm::WASM_EXTERNAL_FUNCTION:
    172           Im.SigIndex = Import.SigIndex;
    173           break;
    174         case wasm::WASM_EXTERNAL_GLOBAL:
    175           Im.GlobalImport.Type = Import.Global.Type;
    176           Im.GlobalImport.Mutable = Import.Global.Mutable;
    177           break;
    178         case wasm::WASM_EXTERNAL_TABLE:
    179           Im.TableImport = make_table(Import.Table);
    180           break;
    181         case wasm::WASM_EXTERNAL_MEMORY:
    182           Im.Memory = make_limits(Import.Memory);
    183           break;
    184         }
    185         ImportSec->Imports.push_back(Im);
    186       }
    187       S = std::move(ImportSec);
    188       break;
    189     }
    190     case wasm::WASM_SEC_FUNCTION: {
    191       auto FuncSec = make_unique<WasmYAML::FunctionSection>();
    192       for (const auto &Func : Obj.functionTypes()) {
    193         FuncSec->FunctionTypes.push_back(Func);
    194       }
    195       S = std::move(FuncSec);
    196       break;
    197     }
    198     case wasm::WASM_SEC_TABLE: {
    199       auto TableSec = make_unique<WasmYAML::TableSection>();
    200       for (const wasm::WasmTable &Table : Obj.tables()) {
    201         TableSec->Tables.push_back(make_table(Table));
    202       }
    203       S = std::move(TableSec);
    204       break;
    205     }
    206     case wasm::WASM_SEC_MEMORY: {
    207       auto MemorySec = make_unique<WasmYAML::MemorySection>();
    208       for (const wasm::WasmLimits &Memory : Obj.memories()) {
    209         MemorySec->Memories.push_back(make_limits(Memory));
    210       }
    211       S = std::move(MemorySec);
    212       break;
    213     }
    214     case wasm::WASM_SEC_GLOBAL: {
    215       auto GlobalSec = make_unique<WasmYAML::GlobalSection>();
    216       for (auto &Global : Obj.globals()) {
    217         WasmYAML::Global G;
    218         G.Index = Global.Index;
    219         G.Type = Global.Type.Type;
    220         G.Mutable = Global.Type.Mutable;
    221         G.InitExpr = Global.InitExpr;
    222         GlobalSec->Globals.push_back(G);
    223       }
    224       S = std::move(GlobalSec);
    225       break;
    226     }
    227     case wasm::WASM_SEC_START: {
    228       auto StartSec = make_unique<WasmYAML::StartSection>();
    229       StartSec->StartFunction = Obj.startFunction();
    230       S = std::move(StartSec);
    231       break;
    232     }
    233     case wasm::WASM_SEC_EXPORT: {
    234       auto ExportSec = make_unique<WasmYAML::ExportSection>();
    235       for (auto &Export : Obj.exports()) {
    236         WasmYAML::Export Ex;
    237         Ex.Name = Export.Name;
    238         Ex.Kind = Export.Kind;
    239         Ex.Index = Export.Index;
    240         ExportSec->Exports.push_back(Ex);
    241       }
    242       S = std::move(ExportSec);
    243       break;
    244     }
    245     case wasm::WASM_SEC_ELEM: {
    246       auto ElemSec = make_unique<WasmYAML::ElemSection>();
    247       for (auto &Segment : Obj.elements()) {
    248         WasmYAML::ElemSegment Seg;
    249         Seg.TableIndex = Segment.TableIndex;
    250         Seg.Offset = Segment.Offset;
    251         for (auto &Func : Segment.Functions) {
    252           Seg.Functions.push_back(Func);
    253         }
    254         ElemSec->Segments.push_back(Seg);
    255       }
    256       S = std::move(ElemSec);
    257       break;
    258     }
    259     case wasm::WASM_SEC_CODE: {
    260       auto CodeSec = make_unique<WasmYAML::CodeSection>();
    261       for (auto &Func : Obj.functions()) {
    262         WasmYAML::Function Function;
    263         Function.Index = Func.Index;
    264         for (auto &Local : Func.Locals) {
    265           WasmYAML::LocalDecl LocalDecl;
    266           LocalDecl.Type = Local.Type;
    267           LocalDecl.Count = Local.Count;
    268           Function.Locals.push_back(LocalDecl);
    269         }
    270         Function.Body = yaml::BinaryRef(Func.Body);
    271         CodeSec->Functions.push_back(Function);
    272       }
    273       S = std::move(CodeSec);
    274       break;
    275     }
    276     case wasm::WASM_SEC_DATA: {
    277       auto DataSec = make_unique<WasmYAML::DataSection>();
    278       for (const object::WasmSegment &Segment : Obj.dataSegments()) {
    279         WasmYAML::DataSegment Seg;
    280         Seg.SectionOffset = Segment.SectionOffset;
    281         Seg.MemoryIndex = Segment.Data.MemoryIndex;
    282         Seg.Offset = Segment.Data.Offset;
    283         Seg.Content = yaml::BinaryRef(Segment.Data.Content);
    284         DataSec->Segments.push_back(Seg);
    285       }
    286       S = std::move(DataSec);
    287       break;
    288     }
    289     default:
    290       llvm_unreachable("Unknown section type");
    291       break;
    292     }
    293     for (const wasm::WasmRelocation &Reloc: WasmSec.Relocations) {
    294       WasmYAML::Relocation R;
    295       R.Type = Reloc.Type;
    296       R.Index = Reloc.Index;
    297       R.Offset = Reloc.Offset;
    298       R.Addend = Reloc.Addend;
    299       S->Relocations.push_back(R);
    300     }
    301     Y->Sections.push_back(std::move(S));
    302   }
    303 
    304   return Y.release();
    305 }
    306 
    307 std::error_code wasm2yaml(raw_ostream &Out, const object::WasmObjectFile &Obj) {
    308   WasmDumper Dumper(Obj);
    309   ErrorOr<WasmYAML::Object *> YAMLOrErr = Dumper.dump();
    310   if (std::error_code EC = YAMLOrErr.getError())
    311     return EC;
    312 
    313   std::unique_ptr<WasmYAML::Object> YAML(YAMLOrErr.get());
    314   yaml::Output Yout(Out);
    315   Yout << *YAML;
    316 
    317   return std::error_code();
    318 }
    319