]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/llvm-readobj/WasmDumper.cpp
Merge ACPICA 20170929 (take 2).
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / llvm-readobj / WasmDumper.cpp
1 //===-- WasmDumper.cpp - Wasm-specific object file dumper -----------------===//
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 // This file implements the Wasm-specific dumper for llvm-readobj.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "Error.h"
15 #include "ObjDumper.h"
16 #include "llvm-readobj.h"
17 #include "llvm/Object/Wasm.h"
18 #include "llvm/Support/ScopedPrinter.h"
19
20 using namespace llvm;
21 using namespace object;
22
23 namespace {
24
25 static const EnumEntry<unsigned> WasmSymbolTypes[] = {
26 #define ENUM_ENTRY(X) { #X, static_cast<unsigned>(WasmSymbol::SymbolType::X) }
27   ENUM_ENTRY(FUNCTION_IMPORT),
28   ENUM_ENTRY(FUNCTION_EXPORT),
29   ENUM_ENTRY(GLOBAL_IMPORT),
30   ENUM_ENTRY(GLOBAL_EXPORT),
31   ENUM_ENTRY(DEBUG_FUNCTION_NAME),
32 #undef ENUM_ENTRY
33 };
34
35 static const EnumEntry<uint32_t> WasmSectionTypes[] = {
36 #define ENUM_ENTRY(X) { #X, wasm::WASM_SEC_##X }
37   ENUM_ENTRY(CUSTOM),
38   ENUM_ENTRY(TYPE),
39   ENUM_ENTRY(IMPORT),
40   ENUM_ENTRY(FUNCTION),
41   ENUM_ENTRY(TABLE),
42   ENUM_ENTRY(MEMORY),
43   ENUM_ENTRY(GLOBAL),
44   ENUM_ENTRY(EXPORT),
45   ENUM_ENTRY(START),
46   ENUM_ENTRY(ELEM),
47   ENUM_ENTRY(CODE),
48   ENUM_ENTRY(DATA),
49 #undef ENUM_ENTRY
50 };
51
52 class WasmDumper : public ObjDumper {
53 public:
54   WasmDumper(const WasmObjectFile *Obj, ScopedPrinter &Writer)
55       : ObjDumper(Writer), Obj(Obj) {}
56
57   void printFileHeaders() override;
58   void printSections() override;
59   void printRelocations() override;
60   void printSymbols() override;
61   void printDynamicSymbols() override { llvm_unreachable("unimplemented"); }
62   void printUnwindInfo() override { llvm_unreachable("unimplemented"); }
63   void printStackMap() const override { llvm_unreachable("unimplemented"); }
64
65 protected:
66   void printSymbol(const SymbolRef &Sym);
67   void printRelocation(const SectionRef &Section, const RelocationRef &Reloc);
68
69 private:
70   const WasmObjectFile *Obj;
71 };
72
73 void WasmDumper::printFileHeaders() {
74   W.printHex("Version", Obj->getHeader().Version);
75 }
76
77 void WasmDumper::printRelocation(const SectionRef &Section,
78                                  const RelocationRef &Reloc) {
79   SmallString<64> RelocTypeName;
80   uint64_t RelocType = Reloc.getType();
81   Reloc.getTypeName(RelocTypeName);
82   const wasm::WasmRelocation &WasmReloc = Obj->getWasmRelocation(Reloc);
83
84   bool HasAddend = false;
85   switch (RelocType) {
86   case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
87   case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
88   case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
89     HasAddend = true;
90     break;
91   default:
92     break;
93   }
94   if (opts::ExpandRelocs) {
95     DictScope Group(W, "Relocation");
96     W.printNumber("Type", RelocTypeName, RelocType);
97     W.printHex("Offset", Reloc.getOffset());
98     W.printHex("Index", WasmReloc.Index);
99     if (HasAddend)
100       W.printNumber("Addend", WasmReloc.Addend);
101   } else {
102     raw_ostream& OS = W.startLine();
103     OS << W.hex(Reloc.getOffset())
104        << " " << RelocTypeName << "[" << WasmReloc.Index << "]";
105     if (HasAddend)
106       OS << " " << WasmReloc.Addend;
107     OS << "\n";
108   }
109 }
110
111 void WasmDumper::printRelocations() {
112   ListScope D(W, "Relocations");
113
114   int SectionNumber = 0;
115   for (const SectionRef &Section : Obj->sections()) {
116     bool PrintedGroup = false;
117     StringRef Name;
118     error(Section.getName(Name));
119     ++SectionNumber;
120
121     for (const RelocationRef &Reloc : Section.relocations()) {
122       if (!PrintedGroup) {
123         W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n";
124         W.indent();
125         PrintedGroup = true;
126       }
127
128       printRelocation(Section, Reloc);
129     }
130
131     if (PrintedGroup) {
132       W.unindent();
133       W.startLine() << "}\n";
134     }
135   }
136 }
137
138 void WasmDumper::printSymbols() {
139   ListScope Group(W, "Symbols");
140
141   for (const SymbolRef &Symbol : Obj->symbols())
142     printSymbol(Symbol);
143 }
144
145 void WasmDumper::printSections() {
146   ListScope Group(W, "Sections");
147   for (const SectionRef &Section : Obj->sections()) {
148     const WasmSection &WasmSec = Obj->getWasmSection(Section);
149     DictScope SectionD(W, "Section");
150     W.printEnum("Type", WasmSec.Type, makeArrayRef(WasmSectionTypes));
151     W.printNumber("Size", (uint64_t)WasmSec.Content.size());
152     W.printNumber("Offset", WasmSec.Offset);
153     switch (WasmSec.Type) {
154     case wasm::WASM_SEC_CUSTOM:
155       W.printString("Name", WasmSec.Name);
156       if (WasmSec.Name == "linking") {
157         const wasm::WasmLinkingData &LinkingData = Obj->linkingData();
158         W.printNumber("DataSize", LinkingData.DataSize);
159         if (LinkingData.DataAlignment)
160           W.printNumber("DataAlignment", LinkingData.DataAlignment);
161       }
162       break;
163     case wasm::WASM_SEC_MEMORY:
164       ListScope Group(W, "Memories");
165       for (const wasm::WasmLimits &Memory : Obj->memories()) {
166         DictScope Group(W, "Memory");
167         W.printNumber("InitialPages", Memory.Initial);
168         if (Memory.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) {
169           W.printNumber("MaxPages", WasmSec.Offset);
170         }
171       }
172       break;
173     }
174
175     if (opts::SectionRelocations) {
176       ListScope D(W, "Relocations");
177       for (const RelocationRef &Reloc : Section.relocations())
178         printRelocation(Section, Reloc);
179     }
180
181     if (opts::SectionData) {
182       W.printBinaryBlock("SectionData", WasmSec.Content);
183     }
184   }
185 }
186
187 void WasmDumper::printSymbol(const SymbolRef &Sym) {
188   DictScope D(W, "Symbol");
189   WasmSymbol Symbol = Obj->getWasmSymbol(Sym.getRawDataRefImpl());
190   W.printString("Name", Symbol.Name);
191   W.printEnum("Type", static_cast<unsigned>(Symbol.Type), makeArrayRef(WasmSymbolTypes));
192   W.printHex("Flags", Symbol.Flags);
193 }
194
195 }
196
197 namespace llvm {
198
199 std::error_code createWasmDumper(const object::ObjectFile *Obj,
200                                  ScopedPrinter &Writer,
201                                  std::unique_ptr<ObjDumper> &Result) {
202   const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(Obj);
203   assert(WasmObj && "createWasmDumper called with non-wasm object");
204
205   Result.reset(new WasmDumper(WasmObj, Writer));
206   return readobj_error::success;
207 }
208
209 } // namespace llvm