brintos

brintos / llvm-project-archived public Read only

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