1 //===------ utils/wasm2yaml.cpp - obj2yaml conversion tool ------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 #include "llvm/Object/COFF.h"
12 #include "llvm/ObjectYAML/WasmYAML.h"
13 #include "llvm/Support/ErrorHandling.h"
14 #include "llvm/Support/YAMLTraits.h"
17 using object::WasmSection
;
22 const object::WasmObjectFile
&Obj
;
25 WasmDumper(const object::WasmObjectFile
&O
) : Obj(O
) {}
27 ErrorOr
<WasmYAML::Object
*> dump();
29 std::unique_ptr
<WasmYAML::CustomSection
>
30 dumpCustomSection(const WasmSection
&WasmSec
);
35 static WasmYAML::Table
make_table(const wasm::WasmTable
&Table
) {
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
;
44 static WasmYAML::Limits
make_limits(const wasm::WasmLimits
&Limits
) {
46 L
.Flags
= Limits
.Flags
;
47 L
.Initial
= Limits
.Initial
;
48 L
.Maximum
= Limits
.Maximum
;
52 std::unique_ptr
<WasmYAML::CustomSection
>
53 WasmDumper::dumpCustomSection(const WasmSection
&WasmSec
) {
54 std::unique_ptr
<WasmYAML::CustomSection
> CustomSec
;
55 if (WasmSec
.Name
== "name") {
56 std::unique_ptr
<WasmYAML::NameSection
> NameSec
=
57 make_unique
<WasmYAML::NameSection
>();
58 for (const llvm::wasm::WasmFunctionName
&Func
: Obj
.debugNames()) {
59 WasmYAML::NameEntry NameEntry
;
60 NameEntry
.Name
= Func
.Name
;
61 NameEntry
.Index
= Func
.Index
;
62 NameSec
->FunctionNames
.push_back(NameEntry
);
64 CustomSec
= std::move(NameSec
);
65 } else if (WasmSec
.Name
== "linking") {
66 std::unique_ptr
<WasmYAML::LinkingSection
> LinkingSec
=
67 make_unique
<WasmYAML::LinkingSection
>();
68 LinkingSec
->Version
= Obj
.linkingData().Version
;
70 ArrayRef
<StringRef
> Comdats
= Obj
.linkingData().Comdats
;
71 for (StringRef ComdatName
: Comdats
)
72 LinkingSec
->Comdats
.emplace_back(WasmYAML::Comdat
{ComdatName
, {}});
73 for (auto &Func
: Obj
.functions()) {
74 if (Func
.Comdat
!= UINT32_MAX
) {
75 LinkingSec
->Comdats
[Func
.Comdat
].Entries
.emplace_back(
76 WasmYAML::ComdatEntry
{wasm::WASM_COMDAT_FUNCTION
, Func
.Index
});
80 uint32_t SegmentIndex
= 0;
81 for (const object::WasmSegment
&Segment
: Obj
.dataSegments()) {
82 if (!Segment
.Data
.Name
.empty()) {
83 WasmYAML::SegmentInfo SegmentInfo
;
84 SegmentInfo
.Name
= Segment
.Data
.Name
;
85 SegmentInfo
.Index
= SegmentIndex
;
86 SegmentInfo
.Alignment
= Segment
.Data
.Alignment
;
87 SegmentInfo
.Flags
= Segment
.Data
.Flags
;
88 LinkingSec
->SegmentInfos
.push_back(SegmentInfo
);
90 if (Segment
.Data
.Comdat
!= UINT32_MAX
) {
91 LinkingSec
->Comdats
[Segment
.Data
.Comdat
].Entries
.emplace_back(
92 WasmYAML::ComdatEntry
{wasm::WASM_COMDAT_DATA
, SegmentIndex
});
97 uint32_t SymbolIndex
= 0;
98 for (const wasm::WasmSymbolInfo
&Symbol
: Obj
.linkingData().SymbolTable
) {
99 WasmYAML::SymbolInfo Info
;
100 Info
.Index
= SymbolIndex
++;
101 Info
.Kind
= static_cast<uint32_t>(Symbol
.Kind
);
102 Info
.Name
= Symbol
.Name
;
103 Info
.Flags
= Symbol
.Flags
;
104 switch (Symbol
.Kind
) {
105 case wasm::WASM_SYMBOL_TYPE_DATA
:
106 Info
.DataRef
= Symbol
.DataRef
;
108 case wasm::WASM_SYMBOL_TYPE_FUNCTION
:
109 case wasm::WASM_SYMBOL_TYPE_GLOBAL
:
110 Info
.ElementIndex
= Symbol
.ElementIndex
;
112 case wasm::WASM_SYMBOL_TYPE_SECTION
:
113 Info
.ElementIndex
= Symbol
.ElementIndex
;
116 LinkingSec
->SymbolTable
.emplace_back(Info
);
119 for (const wasm::WasmInitFunc
&Func
: Obj
.linkingData().InitFunctions
) {
120 WasmYAML::InitFunction F
{Func
.Priority
, Func
.Symbol
};
121 LinkingSec
->InitFunctions
.emplace_back(F
);
124 CustomSec
= std::move(LinkingSec
);
126 CustomSec
= make_unique
<WasmYAML::CustomSection
>(WasmSec
.Name
);
128 CustomSec
->Payload
= yaml::BinaryRef(WasmSec
.Content
);
132 ErrorOr
<WasmYAML::Object
*> WasmDumper::dump() {
133 auto Y
= make_unique
<WasmYAML::Object
>();
136 Y
->Header
.Version
= Obj
.getHeader().Version
;
139 for (const auto &Sec
: Obj
.sections()) {
140 const WasmSection
&WasmSec
= Obj
.getWasmSection(Sec
);
141 std::unique_ptr
<WasmYAML::Section
> S
;
142 switch (WasmSec
.Type
) {
143 case wasm::WASM_SEC_CUSTOM
: {
144 if (WasmSec
.Name
.startswith("reloc.")) {
145 // Relocations are attached the sections they apply to rather than
146 // being represented as a custom section in the YAML output.
149 S
= dumpCustomSection(WasmSec
);
152 case wasm::WASM_SEC_TYPE
: {
153 auto TypeSec
= make_unique
<WasmYAML::TypeSection
>();
155 for (const auto &FunctionSig
: Obj
.types()) {
156 WasmYAML::Signature Sig
;
158 Sig
.ReturnType
= FunctionSig
.ReturnType
;
159 for (const auto &ParamType
: FunctionSig
.ParamTypes
)
160 Sig
.ParamTypes
.push_back(ParamType
);
161 TypeSec
->Signatures
.push_back(Sig
);
163 S
= std::move(TypeSec
);
166 case wasm::WASM_SEC_IMPORT
: {
167 auto ImportSec
= make_unique
<WasmYAML::ImportSection
>();
168 for (auto &Import
: Obj
.imports()) {
170 Im
.Module
= Import
.Module
;
171 Im
.Field
= Import
.Field
;
172 Im
.Kind
= Import
.Kind
;
174 case wasm::WASM_EXTERNAL_FUNCTION
:
175 Im
.SigIndex
= Import
.SigIndex
;
177 case wasm::WASM_EXTERNAL_GLOBAL
:
178 Im
.GlobalImport
.Type
= Import
.Global
.Type
;
179 Im
.GlobalImport
.Mutable
= Import
.Global
.Mutable
;
181 case wasm::WASM_EXTERNAL_TABLE
:
182 Im
.TableImport
= make_table(Import
.Table
);
184 case wasm::WASM_EXTERNAL_MEMORY
:
185 Im
.Memory
= make_limits(Import
.Memory
);
188 ImportSec
->Imports
.push_back(Im
);
190 S
= std::move(ImportSec
);
193 case wasm::WASM_SEC_FUNCTION
: {
194 auto FuncSec
= make_unique
<WasmYAML::FunctionSection
>();
195 for (const auto &Func
: Obj
.functionTypes()) {
196 FuncSec
->FunctionTypes
.push_back(Func
);
198 S
= std::move(FuncSec
);
201 case wasm::WASM_SEC_TABLE
: {
202 auto TableSec
= make_unique
<WasmYAML::TableSection
>();
203 for (const wasm::WasmTable
&Table
: Obj
.tables()) {
204 TableSec
->Tables
.push_back(make_table(Table
));
206 S
= std::move(TableSec
);
209 case wasm::WASM_SEC_MEMORY
: {
210 auto MemorySec
= make_unique
<WasmYAML::MemorySection
>();
211 for (const wasm::WasmLimits
&Memory
: Obj
.memories()) {
212 MemorySec
->Memories
.push_back(make_limits(Memory
));
214 S
= std::move(MemorySec
);
217 case wasm::WASM_SEC_GLOBAL
: {
218 auto GlobalSec
= make_unique
<WasmYAML::GlobalSection
>();
219 for (auto &Global
: Obj
.globals()) {
221 G
.Index
= Global
.Index
;
222 G
.Type
= Global
.Type
.Type
;
223 G
.Mutable
= Global
.Type
.Mutable
;
224 G
.InitExpr
= Global
.InitExpr
;
225 GlobalSec
->Globals
.push_back(G
);
227 S
= std::move(GlobalSec
);
230 case wasm::WASM_SEC_START
: {
231 auto StartSec
= make_unique
<WasmYAML::StartSection
>();
232 StartSec
->StartFunction
= Obj
.startFunction();
233 S
= std::move(StartSec
);
236 case wasm::WASM_SEC_EXPORT
: {
237 auto ExportSec
= make_unique
<WasmYAML::ExportSection
>();
238 for (auto &Export
: Obj
.exports()) {
240 Ex
.Name
= Export
.Name
;
241 Ex
.Kind
= Export
.Kind
;
242 Ex
.Index
= Export
.Index
;
243 ExportSec
->Exports
.push_back(Ex
);
245 S
= std::move(ExportSec
);
248 case wasm::WASM_SEC_ELEM
: {
249 auto ElemSec
= make_unique
<WasmYAML::ElemSection
>();
250 for (auto &Segment
: Obj
.elements()) {
251 WasmYAML::ElemSegment Seg
;
252 Seg
.TableIndex
= Segment
.TableIndex
;
253 Seg
.Offset
= Segment
.Offset
;
254 for (auto &Func
: Segment
.Functions
) {
255 Seg
.Functions
.push_back(Func
);
257 ElemSec
->Segments
.push_back(Seg
);
259 S
= std::move(ElemSec
);
262 case wasm::WASM_SEC_CODE
: {
263 auto CodeSec
= make_unique
<WasmYAML::CodeSection
>();
264 for (auto &Func
: Obj
.functions()) {
265 WasmYAML::Function Function
;
266 Function
.Index
= Func
.Index
;
267 for (auto &Local
: Func
.Locals
) {
268 WasmYAML::LocalDecl LocalDecl
;
269 LocalDecl
.Type
= Local
.Type
;
270 LocalDecl
.Count
= Local
.Count
;
271 Function
.Locals
.push_back(LocalDecl
);
273 Function
.Body
= yaml::BinaryRef(Func
.Body
);
274 CodeSec
->Functions
.push_back(Function
);
276 S
= std::move(CodeSec
);
279 case wasm::WASM_SEC_DATA
: {
280 auto DataSec
= make_unique
<WasmYAML::DataSection
>();
281 for (const object::WasmSegment
&Segment
: Obj
.dataSegments()) {
282 WasmYAML::DataSegment Seg
;
283 Seg
.SectionOffset
= Segment
.SectionOffset
;
284 Seg
.MemoryIndex
= Segment
.Data
.MemoryIndex
;
285 Seg
.Offset
= Segment
.Data
.Offset
;
286 Seg
.Content
= yaml::BinaryRef(Segment
.Data
.Content
);
287 DataSec
->Segments
.push_back(Seg
);
289 S
= std::move(DataSec
);
293 llvm_unreachable("Unknown section type");
296 for (const wasm::WasmRelocation
&Reloc
: WasmSec
.Relocations
) {
297 WasmYAML::Relocation R
;
299 R
.Index
= Reloc
.Index
;
300 R
.Offset
= Reloc
.Offset
;
301 R
.Addend
= Reloc
.Addend
;
302 S
->Relocations
.push_back(R
);
304 Y
->Sections
.push_back(std::move(S
));
310 std::error_code
wasm2yaml(raw_ostream
&Out
, const object::WasmObjectFile
&Obj
) {
311 WasmDumper
Dumper(Obj
);
312 ErrorOr
<WasmYAML::Object
*> YAMLOrErr
= Dumper
.dump();
313 if (std::error_code EC
= YAMLOrErr
.getError())
316 std::unique_ptr
<WasmYAML::Object
> YAML(YAMLOrErr
.get());
317 yaml::Output
Yout(Out
);
320 return std::error_code();