mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 12:43:36 +01:00
7e35d3e5e5
Summary: This adds support for the 'event section' specified in the exception handling proposal. (This was named 'exception section' first, but later renamed to 'event section' to take possibilities of other kinds of events into consideration. But currently we only store exception info in this section.) The event section is added between the global section and the export section. This is for ease of validation per request of the V8 team. This patch: - Creates the event symbol type, which is a weak symbol - Makes 'throw' instruction take the event symbol '__cpp_exception' - Adds relocation support for events - Adds WasmObjectWriter / WasmObjectFile (Reader) support - Adds obj2yaml / yaml2obj support - Adds '.eventtype' printing support Reviewers: dschuff, sbc100, aardappel Subscribers: jgravelle-google, sunfish, llvm-commits Differential Revision: https://reviews.llvm.org/D54096 llvm-svn: 346825
230 lines
7.1 KiB
C++
230 lines
7.1 KiB
C++
//===-- WasmDumper.cpp - Wasm-specific object file dumper -----------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the Wasm-specific dumper for llvm-readobj.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "Error.h"
|
|
#include "ObjDumper.h"
|
|
#include "llvm-readobj.h"
|
|
#include "llvm/Object/Wasm.h"
|
|
#include "llvm/Support/ScopedPrinter.h"
|
|
|
|
using namespace llvm;
|
|
using namespace object;
|
|
|
|
namespace {
|
|
|
|
static const EnumEntry<unsigned> WasmSymbolTypes[] = {
|
|
#define ENUM_ENTRY(X) \
|
|
{ #X, wasm::WASM_SYMBOL_TYPE_##X }
|
|
ENUM_ENTRY(FUNCTION), ENUM_ENTRY(DATA), ENUM_ENTRY(GLOBAL),
|
|
ENUM_ENTRY(SECTION), ENUM_ENTRY(EVENT),
|
|
#undef ENUM_ENTRY
|
|
};
|
|
|
|
static const EnumEntry<uint32_t> WasmSectionTypes[] = {
|
|
#define ENUM_ENTRY(X) \
|
|
{ #X, wasm::WASM_SEC_##X }
|
|
ENUM_ENTRY(CUSTOM), ENUM_ENTRY(TYPE), ENUM_ENTRY(IMPORT),
|
|
ENUM_ENTRY(FUNCTION), ENUM_ENTRY(TABLE), ENUM_ENTRY(MEMORY),
|
|
ENUM_ENTRY(GLOBAL), ENUM_ENTRY(EVENT), ENUM_ENTRY(EXPORT),
|
|
ENUM_ENTRY(START), ENUM_ENTRY(ELEM), ENUM_ENTRY(CODE),
|
|
ENUM_ENTRY(DATA),
|
|
#undef ENUM_ENTRY
|
|
};
|
|
|
|
class WasmDumper : public ObjDumper {
|
|
public:
|
|
WasmDumper(const WasmObjectFile *Obj, ScopedPrinter &Writer)
|
|
: ObjDumper(Writer), Obj(Obj) {}
|
|
|
|
void printFileHeaders() override;
|
|
void printSectionHeaders() override;
|
|
void printRelocations() override;
|
|
void printSymbols() override;
|
|
void printDynamicSymbols() override { llvm_unreachable("unimplemented"); }
|
|
void printUnwindInfo() override { llvm_unreachable("unimplemented"); }
|
|
void printStackMap() const override { llvm_unreachable("unimplemented"); }
|
|
|
|
protected:
|
|
void printSymbol(const SymbolRef &Sym);
|
|
void printRelocation(const SectionRef &Section, const RelocationRef &Reloc);
|
|
|
|
private:
|
|
const WasmObjectFile *Obj;
|
|
};
|
|
|
|
void WasmDumper::printFileHeaders() {
|
|
W.printHex("Version", Obj->getHeader().Version);
|
|
}
|
|
|
|
void WasmDumper::printRelocation(const SectionRef &Section,
|
|
const RelocationRef &Reloc) {
|
|
SmallString<64> RelocTypeName;
|
|
uint64_t RelocType = Reloc.getType();
|
|
Reloc.getTypeName(RelocTypeName);
|
|
const wasm::WasmRelocation &WasmReloc = Obj->getWasmRelocation(Reloc);
|
|
|
|
StringRef SymName;
|
|
symbol_iterator SI = Reloc.getSymbol();
|
|
if (SI != Obj->symbol_end())
|
|
SymName = error(SI->getName());
|
|
|
|
bool HasAddend = false;
|
|
switch (RelocType) {
|
|
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
|
|
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
|
|
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
|
|
case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
|
|
case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
|
|
HasAddend = true;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (opts::ExpandRelocs) {
|
|
DictScope Group(W, "Relocation");
|
|
W.printNumber("Type", RelocTypeName, RelocType);
|
|
W.printHex("Offset", Reloc.getOffset());
|
|
if (!SymName.empty())
|
|
W.printString("Symbol", SymName);
|
|
else
|
|
W.printHex("Index", WasmReloc.Index);
|
|
if (HasAddend)
|
|
W.printNumber("Addend", WasmReloc.Addend);
|
|
} else {
|
|
raw_ostream &OS = W.startLine();
|
|
OS << W.hex(Reloc.getOffset()) << " " << RelocTypeName << " ";
|
|
if (!SymName.empty())
|
|
OS << SymName;
|
|
else
|
|
OS << WasmReloc.Index;
|
|
if (HasAddend)
|
|
OS << " " << WasmReloc.Addend;
|
|
OS << "\n";
|
|
}
|
|
}
|
|
|
|
void WasmDumper::printRelocations() {
|
|
ListScope D(W, "Relocations");
|
|
|
|
int SectionNumber = 0;
|
|
for (const SectionRef &Section : Obj->sections()) {
|
|
bool PrintedGroup = false;
|
|
StringRef Name;
|
|
error(Section.getName(Name));
|
|
++SectionNumber;
|
|
|
|
for (const RelocationRef &Reloc : Section.relocations()) {
|
|
if (!PrintedGroup) {
|
|
W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n";
|
|
W.indent();
|
|
PrintedGroup = true;
|
|
}
|
|
|
|
printRelocation(Section, Reloc);
|
|
}
|
|
|
|
if (PrintedGroup) {
|
|
W.unindent();
|
|
W.startLine() << "}\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
void WasmDumper::printSymbols() {
|
|
ListScope Group(W, "Symbols");
|
|
|
|
for (const SymbolRef &Symbol : Obj->symbols())
|
|
printSymbol(Symbol);
|
|
}
|
|
|
|
void WasmDumper::printSectionHeaders() {
|
|
ListScope Group(W, "Sections");
|
|
for (const SectionRef &Section : Obj->sections()) {
|
|
const WasmSection &WasmSec = Obj->getWasmSection(Section);
|
|
DictScope SectionD(W, "Section");
|
|
W.printEnum("Type", WasmSec.Type, makeArrayRef(WasmSectionTypes));
|
|
W.printNumber("Size", static_cast<uint64_t>(WasmSec.Content.size()));
|
|
W.printNumber("Offset", WasmSec.Offset);
|
|
switch (WasmSec.Type) {
|
|
case wasm::WASM_SEC_CUSTOM:
|
|
W.printString("Name", WasmSec.Name);
|
|
if (WasmSec.Name == "linking") {
|
|
const wasm::WasmLinkingData &LinkingData = Obj->linkingData();
|
|
if (!LinkingData.InitFunctions.empty()) {
|
|
ListScope Group(W, "InitFunctions");
|
|
for (const wasm::WasmInitFunc &F : LinkingData.InitFunctions)
|
|
W.startLine() << F.Symbol << " (priority=" << F.Priority << ")\n";
|
|
}
|
|
}
|
|
break;
|
|
case wasm::WASM_SEC_DATA: {
|
|
ListScope Group(W, "Segments");
|
|
for (const WasmSegment &Segment : Obj->dataSegments()) {
|
|
const wasm::WasmDataSegment &Seg = Segment.Data;
|
|
DictScope Group(W, "Segment");
|
|
if (!Seg.Name.empty())
|
|
W.printString("Name", Seg.Name);
|
|
W.printNumber("Size", static_cast<uint64_t>(Seg.Content.size()));
|
|
if (Seg.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST)
|
|
W.printNumber("Offset", Seg.Offset.Value.Int32);
|
|
}
|
|
break;
|
|
}
|
|
case wasm::WASM_SEC_MEMORY:
|
|
ListScope Group(W, "Memories");
|
|
for (const wasm::WasmLimits &Memory : Obj->memories()) {
|
|
DictScope Group(W, "Memory");
|
|
W.printNumber("InitialPages", Memory.Initial);
|
|
if (Memory.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) {
|
|
W.printNumber("MaxPages", WasmSec.Offset);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (opts::SectionRelocations) {
|
|
ListScope D(W, "Relocations");
|
|
for (const RelocationRef &Reloc : Section.relocations())
|
|
printRelocation(Section, Reloc);
|
|
}
|
|
|
|
if (opts::SectionData) {
|
|
W.printBinaryBlock("SectionData", WasmSec.Content);
|
|
}
|
|
}
|
|
}
|
|
|
|
void WasmDumper::printSymbol(const SymbolRef &Sym) {
|
|
DictScope D(W, "Symbol");
|
|
WasmSymbol Symbol = Obj->getWasmSymbol(Sym.getRawDataRefImpl());
|
|
W.printString("Name", Symbol.Info.Name);
|
|
W.printEnum("Type", Symbol.Info.Kind, makeArrayRef(WasmSymbolTypes));
|
|
W.printHex("Flags", Symbol.Info.Flags);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
namespace llvm {
|
|
|
|
std::error_code createWasmDumper(const object::ObjectFile *Obj,
|
|
ScopedPrinter &Writer,
|
|
std::unique_ptr<ObjDumper> &Result) {
|
|
const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(Obj);
|
|
assert(WasmObj && "createWasmDumper called with non-wasm object");
|
|
|
|
Result.reset(new WasmDumper(WasmObj, Writer));
|
|
return readobj_error::success;
|
|
}
|
|
|
|
} // namespace llvm
|