Path: blob/main/contrib/llvm-project/llvm/tools/llvm-readobj/WasmDumper.cpp
35231 views
//===-- WasmDumper.cpp - Wasm-specific object file dumper -----------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the Wasm-specific dumper for llvm-readobj.9//10//===----------------------------------------------------------------------===//1112#include "ObjDumper.h"13#include "llvm-readobj.h"14#include "llvm/Object/Wasm.h"15#include "llvm/Support/ScopedPrinter.h"1617using namespace llvm;18using namespace object;1920namespace {2122const EnumEntry<unsigned> WasmSymbolTypes[] = {23#define ENUM_ENTRY(X) \24{ #X, wasm::WASM_SYMBOL_TYPE_##X }25ENUM_ENTRY(FUNCTION), ENUM_ENTRY(DATA), ENUM_ENTRY(GLOBAL),26ENUM_ENTRY(SECTION), ENUM_ENTRY(TAG), ENUM_ENTRY(TABLE),27#undef ENUM_ENTRY28};2930const EnumEntry<uint32_t> WasmSectionTypes[] = {31#define ENUM_ENTRY(X) \32{ #X, wasm::WASM_SEC_##X }33ENUM_ENTRY(CUSTOM), ENUM_ENTRY(TYPE), ENUM_ENTRY(IMPORT),34ENUM_ENTRY(FUNCTION), ENUM_ENTRY(TABLE), ENUM_ENTRY(MEMORY),35ENUM_ENTRY(GLOBAL), ENUM_ENTRY(TAG), ENUM_ENTRY(EXPORT),36ENUM_ENTRY(START), ENUM_ENTRY(ELEM), ENUM_ENTRY(CODE),37ENUM_ENTRY(DATA), ENUM_ENTRY(DATACOUNT),38#undef ENUM_ENTRY39};4041const EnumEntry<unsigned> WasmSymbolFlags[] = {42#define ENUM_ENTRY(X) \43{ #X, wasm::WASM_SYMBOL_##X }44ENUM_ENTRY(BINDING_GLOBAL),45ENUM_ENTRY(BINDING_WEAK),46ENUM_ENTRY(BINDING_LOCAL),47ENUM_ENTRY(VISIBILITY_DEFAULT),48ENUM_ENTRY(VISIBILITY_HIDDEN),49ENUM_ENTRY(UNDEFINED),50ENUM_ENTRY(EXPORTED),51ENUM_ENTRY(EXPLICIT_NAME),52ENUM_ENTRY(NO_STRIP),53#undef ENUM_ENTRY54};5556class WasmDumper : public ObjDumper {57public:58WasmDumper(const WasmObjectFile *Obj, ScopedPrinter &Writer)59: ObjDumper(Writer, Obj->getFileName()), Obj(Obj) {}6061void printFileHeaders() override;62void printSectionHeaders() override;63void printRelocations() override;64void printUnwindInfo() override { llvm_unreachable("unimplemented"); }65void printStackMap() const override { llvm_unreachable("unimplemented"); }6667protected:68void printSymbol(const SymbolRef &Sym);69void printRelocation(const SectionRef &Section, const RelocationRef &Reloc);7071private:72void printSymbols(bool ExtraSymInfo) override;73void printDynamicSymbols() override { llvm_unreachable("unimplemented"); }7475const WasmObjectFile *Obj;76};7778void WasmDumper::printFileHeaders() {79W.printHex("Version", Obj->getHeader().Version);80}8182void WasmDumper::printRelocation(const SectionRef &Section,83const RelocationRef &Reloc) {84SmallString<64> RelocTypeName;85uint64_t RelocType = Reloc.getType();86Reloc.getTypeName(RelocTypeName);87const wasm::WasmRelocation &WasmReloc = Obj->getWasmRelocation(Reloc);8889StringRef SymName;90symbol_iterator SI = Reloc.getSymbol();91if (SI != Obj->symbol_end())92SymName = unwrapOrError(Obj->getFileName(), SI->getName());9394bool HasAddend = wasm::relocTypeHasAddend(static_cast<uint32_t>(RelocType));9596if (opts::ExpandRelocs) {97DictScope Group(W, "Relocation");98W.printNumber("Type", RelocTypeName, RelocType);99W.printHex("Offset", Reloc.getOffset());100if (!SymName.empty())101W.printString("Symbol", SymName);102else103W.printHex("Index", WasmReloc.Index);104if (HasAddend)105W.printNumber("Addend", WasmReloc.Addend);106} else {107raw_ostream &OS = W.startLine();108OS << W.hex(Reloc.getOffset()) << " " << RelocTypeName << " ";109if (!SymName.empty())110OS << SymName;111else112OS << WasmReloc.Index;113if (HasAddend)114OS << " " << WasmReloc.Addend;115OS << "\n";116}117}118119void WasmDumper::printRelocations() {120ListScope D(W, "Relocations");121122int SectionNumber = 0;123for (const SectionRef &Section : Obj->sections()) {124bool PrintedGroup = false;125StringRef Name = unwrapOrError(Obj->getFileName(), Section.getName());126127++SectionNumber;128129for (const RelocationRef &Reloc : Section.relocations()) {130if (!PrintedGroup) {131W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n";132W.indent();133PrintedGroup = true;134}135136printRelocation(Section, Reloc);137}138139if (PrintedGroup) {140W.unindent();141W.startLine() << "}\n";142}143}144}145146void WasmDumper::printSymbols(bool /*ExtraSymInfo*/) {147ListScope Group(W, "Symbols");148149for (const SymbolRef &Symbol : Obj->symbols())150printSymbol(Symbol);151}152153void WasmDumper::printSectionHeaders() {154ListScope Group(W, "Sections");155for (const SectionRef &Section : Obj->sections()) {156const WasmSection &WasmSec = Obj->getWasmSection(Section);157DictScope SectionD(W, "Section");158W.printEnum("Type", WasmSec.Type, ArrayRef(WasmSectionTypes));159W.printNumber("Size", static_cast<uint64_t>(WasmSec.Content.size()));160W.printNumber("Offset", WasmSec.Offset);161switch (WasmSec.Type) {162case wasm::WASM_SEC_CUSTOM:163W.printString("Name", WasmSec.Name);164if (WasmSec.Name == "linking") {165const wasm::WasmLinkingData &LinkingData = Obj->linkingData();166if (!LinkingData.InitFunctions.empty()) {167ListScope Group(W, "InitFunctions");168for (const wasm::WasmInitFunc &F : LinkingData.InitFunctions)169W.startLine() << F.Symbol << " (priority=" << F.Priority << ")\n";170}171}172break;173case wasm::WASM_SEC_DATA: {174ListScope Group(W, "Segments");175for (const WasmSegment &Segment : Obj->dataSegments()) {176const wasm::WasmDataSegment &Seg = Segment.Data;177DictScope Group(W, "Segment");178if (!Seg.Name.empty())179W.printString("Name", Seg.Name);180W.printNumber("Size", static_cast<uint64_t>(Seg.Content.size()));181if (Seg.Offset.Extended)182llvm_unreachable("extended const exprs not supported");183else if (Seg.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST)184W.printNumber("Offset", Seg.Offset.Inst.Value.Int32);185else if (Seg.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST)186W.printNumber("Offset", Seg.Offset.Inst.Value.Int64);187else if (Seg.Offset.Inst.Opcode == wasm::WASM_OPCODE_GLOBAL_GET) {188ListScope Group(W, "Offset");189W.printNumber("Global", Seg.Offset.Inst.Value.Global);190} else191llvm_unreachable("unknown init expr opcode");192}193break;194}195case wasm::WASM_SEC_MEMORY:196ListScope Group(W, "Memories");197for (const wasm::WasmLimits &Memory : Obj->memories()) {198DictScope Group(W, "Memory");199W.printNumber("MinPages", Memory.Minimum);200if (Memory.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) {201W.printNumber("MaxPages", WasmSec.Offset);202}203}204break;205}206207if (opts::SectionRelocations) {208ListScope D(W, "Relocations");209for (const RelocationRef &Reloc : Section.relocations())210printRelocation(Section, Reloc);211}212213if (opts::SectionData) {214W.printBinaryBlock("SectionData", WasmSec.Content);215}216}217}218219void WasmDumper::printSymbol(const SymbolRef &Sym) {220DictScope D(W, "Symbol");221WasmSymbol Symbol = Obj->getWasmSymbol(Sym.getRawDataRefImpl());222W.printString("Name", Symbol.Info.Name);223W.printEnum("Type", Symbol.Info.Kind, ArrayRef(WasmSymbolTypes));224W.printFlags("Flags", Symbol.Info.Flags, ArrayRef(WasmSymbolFlags));225226if (Symbol.Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) {227if (Symbol.Info.ImportName) {228W.printString("ImportName", *Symbol.Info.ImportName);229}230if (Symbol.Info.ImportModule) {231W.printString("ImportModule", *Symbol.Info.ImportModule);232}233}234if (Symbol.Info.Kind != wasm::WASM_SYMBOL_TYPE_DATA) {235W.printHex("ElementIndex", Symbol.Info.ElementIndex);236} else if (!(Symbol.Info.Flags & wasm::WASM_SYMBOL_UNDEFINED)) {237W.printHex("Offset", Symbol.Info.DataRef.Offset);238W.printHex("Segment", Symbol.Info.DataRef.Segment);239W.printHex("Size", Symbol.Info.DataRef.Size);240}241}242243} // namespace244245namespace llvm {246247std::unique_ptr<ObjDumper> createWasmDumper(const object::WasmObjectFile &Obj,248ScopedPrinter &Writer) {249return std::make_unique<WasmDumper>(&Obj, Writer);250}251252} // namespace llvm253254255