Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/tools/llvm-readobj/WasmDumper.cpp
35231 views
1
//===-- WasmDumper.cpp - Wasm-specific object file dumper -----------------===//
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
//
9
// This file implements the Wasm-specific dumper for llvm-readobj.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "ObjDumper.h"
14
#include "llvm-readobj.h"
15
#include "llvm/Object/Wasm.h"
16
#include "llvm/Support/ScopedPrinter.h"
17
18
using namespace llvm;
19
using namespace object;
20
21
namespace {
22
23
const EnumEntry<unsigned> WasmSymbolTypes[] = {
24
#define ENUM_ENTRY(X) \
25
{ #X, wasm::WASM_SYMBOL_TYPE_##X }
26
ENUM_ENTRY(FUNCTION), ENUM_ENTRY(DATA), ENUM_ENTRY(GLOBAL),
27
ENUM_ENTRY(SECTION), ENUM_ENTRY(TAG), ENUM_ENTRY(TABLE),
28
#undef ENUM_ENTRY
29
};
30
31
const EnumEntry<uint32_t> WasmSectionTypes[] = {
32
#define ENUM_ENTRY(X) \
33
{ #X, wasm::WASM_SEC_##X }
34
ENUM_ENTRY(CUSTOM), ENUM_ENTRY(TYPE), ENUM_ENTRY(IMPORT),
35
ENUM_ENTRY(FUNCTION), ENUM_ENTRY(TABLE), ENUM_ENTRY(MEMORY),
36
ENUM_ENTRY(GLOBAL), ENUM_ENTRY(TAG), ENUM_ENTRY(EXPORT),
37
ENUM_ENTRY(START), ENUM_ENTRY(ELEM), ENUM_ENTRY(CODE),
38
ENUM_ENTRY(DATA), ENUM_ENTRY(DATACOUNT),
39
#undef ENUM_ENTRY
40
};
41
42
const EnumEntry<unsigned> WasmSymbolFlags[] = {
43
#define ENUM_ENTRY(X) \
44
{ #X, wasm::WASM_SYMBOL_##X }
45
ENUM_ENTRY(BINDING_GLOBAL),
46
ENUM_ENTRY(BINDING_WEAK),
47
ENUM_ENTRY(BINDING_LOCAL),
48
ENUM_ENTRY(VISIBILITY_DEFAULT),
49
ENUM_ENTRY(VISIBILITY_HIDDEN),
50
ENUM_ENTRY(UNDEFINED),
51
ENUM_ENTRY(EXPORTED),
52
ENUM_ENTRY(EXPLICIT_NAME),
53
ENUM_ENTRY(NO_STRIP),
54
#undef ENUM_ENTRY
55
};
56
57
class WasmDumper : public ObjDumper {
58
public:
59
WasmDumper(const WasmObjectFile *Obj, ScopedPrinter &Writer)
60
: ObjDumper(Writer, Obj->getFileName()), Obj(Obj) {}
61
62
void printFileHeaders() override;
63
void printSectionHeaders() override;
64
void printRelocations() override;
65
void printUnwindInfo() override { llvm_unreachable("unimplemented"); }
66
void printStackMap() const override { llvm_unreachable("unimplemented"); }
67
68
protected:
69
void printSymbol(const SymbolRef &Sym);
70
void printRelocation(const SectionRef &Section, const RelocationRef &Reloc);
71
72
private:
73
void printSymbols(bool ExtraSymInfo) override;
74
void printDynamicSymbols() override { llvm_unreachable("unimplemented"); }
75
76
const WasmObjectFile *Obj;
77
};
78
79
void WasmDumper::printFileHeaders() {
80
W.printHex("Version", Obj->getHeader().Version);
81
}
82
83
void WasmDumper::printRelocation(const SectionRef &Section,
84
const RelocationRef &Reloc) {
85
SmallString<64> RelocTypeName;
86
uint64_t RelocType = Reloc.getType();
87
Reloc.getTypeName(RelocTypeName);
88
const wasm::WasmRelocation &WasmReloc = Obj->getWasmRelocation(Reloc);
89
90
StringRef SymName;
91
symbol_iterator SI = Reloc.getSymbol();
92
if (SI != Obj->symbol_end())
93
SymName = unwrapOrError(Obj->getFileName(), SI->getName());
94
95
bool HasAddend = wasm::relocTypeHasAddend(static_cast<uint32_t>(RelocType));
96
97
if (opts::ExpandRelocs) {
98
DictScope Group(W, "Relocation");
99
W.printNumber("Type", RelocTypeName, RelocType);
100
W.printHex("Offset", Reloc.getOffset());
101
if (!SymName.empty())
102
W.printString("Symbol", SymName);
103
else
104
W.printHex("Index", WasmReloc.Index);
105
if (HasAddend)
106
W.printNumber("Addend", WasmReloc.Addend);
107
} else {
108
raw_ostream &OS = W.startLine();
109
OS << W.hex(Reloc.getOffset()) << " " << RelocTypeName << " ";
110
if (!SymName.empty())
111
OS << SymName;
112
else
113
OS << WasmReloc.Index;
114
if (HasAddend)
115
OS << " " << WasmReloc.Addend;
116
OS << "\n";
117
}
118
}
119
120
void WasmDumper::printRelocations() {
121
ListScope D(W, "Relocations");
122
123
int SectionNumber = 0;
124
for (const SectionRef &Section : Obj->sections()) {
125
bool PrintedGroup = false;
126
StringRef Name = unwrapOrError(Obj->getFileName(), Section.getName());
127
128
++SectionNumber;
129
130
for (const RelocationRef &Reloc : Section.relocations()) {
131
if (!PrintedGroup) {
132
W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n";
133
W.indent();
134
PrintedGroup = true;
135
}
136
137
printRelocation(Section, Reloc);
138
}
139
140
if (PrintedGroup) {
141
W.unindent();
142
W.startLine() << "}\n";
143
}
144
}
145
}
146
147
void WasmDumper::printSymbols(bool /*ExtraSymInfo*/) {
148
ListScope Group(W, "Symbols");
149
150
for (const SymbolRef &Symbol : Obj->symbols())
151
printSymbol(Symbol);
152
}
153
154
void WasmDumper::printSectionHeaders() {
155
ListScope Group(W, "Sections");
156
for (const SectionRef &Section : Obj->sections()) {
157
const WasmSection &WasmSec = Obj->getWasmSection(Section);
158
DictScope SectionD(W, "Section");
159
W.printEnum("Type", WasmSec.Type, ArrayRef(WasmSectionTypes));
160
W.printNumber("Size", static_cast<uint64_t>(WasmSec.Content.size()));
161
W.printNumber("Offset", WasmSec.Offset);
162
switch (WasmSec.Type) {
163
case wasm::WASM_SEC_CUSTOM:
164
W.printString("Name", WasmSec.Name);
165
if (WasmSec.Name == "linking") {
166
const wasm::WasmLinkingData &LinkingData = Obj->linkingData();
167
if (!LinkingData.InitFunctions.empty()) {
168
ListScope Group(W, "InitFunctions");
169
for (const wasm::WasmInitFunc &F : LinkingData.InitFunctions)
170
W.startLine() << F.Symbol << " (priority=" << F.Priority << ")\n";
171
}
172
}
173
break;
174
case wasm::WASM_SEC_DATA: {
175
ListScope Group(W, "Segments");
176
for (const WasmSegment &Segment : Obj->dataSegments()) {
177
const wasm::WasmDataSegment &Seg = Segment.Data;
178
DictScope Group(W, "Segment");
179
if (!Seg.Name.empty())
180
W.printString("Name", Seg.Name);
181
W.printNumber("Size", static_cast<uint64_t>(Seg.Content.size()));
182
if (Seg.Offset.Extended)
183
llvm_unreachable("extended const exprs not supported");
184
else if (Seg.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST)
185
W.printNumber("Offset", Seg.Offset.Inst.Value.Int32);
186
else if (Seg.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST)
187
W.printNumber("Offset", Seg.Offset.Inst.Value.Int64);
188
else if (Seg.Offset.Inst.Opcode == wasm::WASM_OPCODE_GLOBAL_GET) {
189
ListScope Group(W, "Offset");
190
W.printNumber("Global", Seg.Offset.Inst.Value.Global);
191
} else
192
llvm_unreachable("unknown init expr opcode");
193
}
194
break;
195
}
196
case wasm::WASM_SEC_MEMORY:
197
ListScope Group(W, "Memories");
198
for (const wasm::WasmLimits &Memory : Obj->memories()) {
199
DictScope Group(W, "Memory");
200
W.printNumber("MinPages", Memory.Minimum);
201
if (Memory.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) {
202
W.printNumber("MaxPages", WasmSec.Offset);
203
}
204
}
205
break;
206
}
207
208
if (opts::SectionRelocations) {
209
ListScope D(W, "Relocations");
210
for (const RelocationRef &Reloc : Section.relocations())
211
printRelocation(Section, Reloc);
212
}
213
214
if (opts::SectionData) {
215
W.printBinaryBlock("SectionData", WasmSec.Content);
216
}
217
}
218
}
219
220
void WasmDumper::printSymbol(const SymbolRef &Sym) {
221
DictScope D(W, "Symbol");
222
WasmSymbol Symbol = Obj->getWasmSymbol(Sym.getRawDataRefImpl());
223
W.printString("Name", Symbol.Info.Name);
224
W.printEnum("Type", Symbol.Info.Kind, ArrayRef(WasmSymbolTypes));
225
W.printFlags("Flags", Symbol.Info.Flags, ArrayRef(WasmSymbolFlags));
226
227
if (Symbol.Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) {
228
if (Symbol.Info.ImportName) {
229
W.printString("ImportName", *Symbol.Info.ImportName);
230
}
231
if (Symbol.Info.ImportModule) {
232
W.printString("ImportModule", *Symbol.Info.ImportModule);
233
}
234
}
235
if (Symbol.Info.Kind != wasm::WASM_SYMBOL_TYPE_DATA) {
236
W.printHex("ElementIndex", Symbol.Info.ElementIndex);
237
} else if (!(Symbol.Info.Flags & wasm::WASM_SYMBOL_UNDEFINED)) {
238
W.printHex("Offset", Symbol.Info.DataRef.Offset);
239
W.printHex("Segment", Symbol.Info.DataRef.Segment);
240
W.printHex("Size", Symbol.Info.DataRef.Size);
241
}
242
}
243
244
} // namespace
245
246
namespace llvm {
247
248
std::unique_ptr<ObjDumper> createWasmDumper(const object::WasmObjectFile &Obj,
249
ScopedPrinter &Writer) {
250
return std::make_unique<WasmDumper>(&Obj, Writer);
251
}
252
253
} // namespace llvm
254
255