forked from OSchip/llvm-project
[WebAssembly] Add support for weak symbols in the binary format
This also introduces the updated format for the "linking" section which can represent extra symbol information. See: https://github.com/WebAssembly/tool-conventions/pull/10 Differential Revision: https://reviews.llvm.org/D34019 llvm-svn: 305769
This commit is contained in:
parent
47a78a2502
commit
b7787fd076
|
@ -176,6 +176,11 @@ enum class ValType {
|
|||
// Linking metadata kinds.
|
||||
enum : unsigned {
|
||||
WASM_STACK_POINTER = 0x1,
|
||||
WASM_SYMBOL_INFO = 0x2,
|
||||
};
|
||||
|
||||
enum : unsigned {
|
||||
WASM_SYMBOL_FLAG_WEAK = 0x1,
|
||||
};
|
||||
|
||||
#define WASM_RELOC(name, value) name = value,
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace llvm {
|
|||
class MCSymbolWasm : public MCSymbol {
|
||||
private:
|
||||
bool IsFunction = false;
|
||||
bool IsWeak = false;
|
||||
std::string ModuleName;
|
||||
SmallVector<wasm::ValType, 1> Returns;
|
||||
SmallVector<wasm::ValType, 4> Params;
|
||||
|
@ -39,6 +40,9 @@ public:
|
|||
bool isFunction() const { return IsFunction; }
|
||||
void setIsFunction(bool isFunc) { IsFunction = isFunc; }
|
||||
|
||||
bool isWeak() const { return IsWeak; }
|
||||
void setWeak(bool isWeak) { IsWeak = isWeak; }
|
||||
|
||||
const StringRef getModuleName() const { return ModuleName; }
|
||||
|
||||
const SmallVector<wasm::ValType, 1> &getReturns() const { return Returns; }
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/BinaryFormat/Wasm.h"
|
||||
#include "llvm/Object/Binary.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
|
@ -48,7 +49,24 @@ public:
|
|||
StringRef Name;
|
||||
SymbolType Type;
|
||||
uint32_t Section;
|
||||
uint32_t Flags = 0;
|
||||
|
||||
// Index into the imports, exports or functions array of the object depending
|
||||
// on the type
|
||||
uint32_t ElementIndex;
|
||||
|
||||
bool isWeak() const {
|
||||
return Flags & wasm::WASM_SYMBOL_FLAG_WEAK;
|
||||
}
|
||||
|
||||
void print(raw_ostream &Out) const {
|
||||
Out << "Name=" << Name << ", Type=" << static_cast<int>(Type)
|
||||
<< ", Flags=" << Flags;
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
||||
LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
|
||||
#endif
|
||||
};
|
||||
|
||||
class WasmSection {
|
||||
|
@ -63,6 +81,7 @@ public:
|
|||
};
|
||||
|
||||
class WasmObjectFile : public ObjectFile {
|
||||
|
||||
public:
|
||||
WasmObjectFile(MemoryBufferRef Object, Error &Err);
|
||||
|
||||
|
@ -176,6 +195,7 @@ private:
|
|||
|
||||
// Custom section types
|
||||
Error parseNameSection(const uint8_t *Ptr, const uint8_t *End);
|
||||
Error parseLinkingSection(const uint8_t *Ptr, const uint8_t *End);
|
||||
Error parseRelocSection(StringRef Name, const uint8_t *Ptr,
|
||||
const uint8_t *End);
|
||||
|
||||
|
@ -190,13 +210,22 @@ private:
|
|||
std::vector<wasm::WasmExport> Exports;
|
||||
std::vector<wasm::WasmElemSegment> ElemSegments;
|
||||
std::vector<wasm::WasmDataSegment> DataSegments;
|
||||
std::vector<WasmSymbol> Symbols;
|
||||
std::vector<wasm::WasmFunction> Functions;
|
||||
std::vector<WasmSymbol> Symbols;
|
||||
ArrayRef<uint8_t> CodeSection;
|
||||
uint32_t StartFunction = -1;
|
||||
|
||||
StringMap<uint32_t> SymbolMap;
|
||||
};
|
||||
|
||||
} // end namespace object
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS,
|
||||
const object::WasmSymbol &Sym) {
|
||||
Sym.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_OBJECT_WASM_H
|
||||
|
|
|
@ -112,8 +112,13 @@ struct Signature {
|
|||
ValueType ReturnType;
|
||||
};
|
||||
|
||||
struct SymbolInfo {
|
||||
StringRef Name;
|
||||
uint32_t Flags;
|
||||
};
|
||||
|
||||
struct Section {
|
||||
Section(SectionType SecType) : Type(SecType) {}
|
||||
explicit Section(SectionType SecType) : Type(SecType) {}
|
||||
virtual ~Section();
|
||||
|
||||
SectionType Type;
|
||||
|
@ -121,20 +126,36 @@ struct Section {
|
|||
};
|
||||
|
||||
struct CustomSection : Section {
|
||||
CustomSection() : Section(wasm::WASM_SEC_CUSTOM) {}
|
||||
explicit CustomSection(StringRef Name)
|
||||
: Section(wasm::WASM_SEC_CUSTOM), Name(Name) {}
|
||||
static bool classof(const Section *S) {
|
||||
return S->Type == wasm::WASM_SEC_CUSTOM;
|
||||
}
|
||||
|
||||
StringRef Name;
|
||||
yaml::BinaryRef Payload;
|
||||
};
|
||||
|
||||
struct NameSection : CustomSection {
|
||||
NameSection() : CustomSection("name") {}
|
||||
static bool classof(const Section *S) {
|
||||
auto C = dyn_cast<CustomSection>(S);
|
||||
return C && C->Name == "name";
|
||||
}
|
||||
|
||||
// The follow is used by the "name" custom section.
|
||||
// TODO(sbc): Add support for more then just functions names. The wasm
|
||||
// name section can support multiple sub-sections.
|
||||
std::vector<NameEntry> FunctionNames;
|
||||
};
|
||||
|
||||
struct LinkingSection : CustomSection {
|
||||
LinkingSection() : CustomSection("linking") {}
|
||||
static bool classof(const Section *S) {
|
||||
auto C = dyn_cast<CustomSection>(S);
|
||||
return C && C->Name == "linking";
|
||||
}
|
||||
|
||||
std::vector<SymbolInfo> SymbolInfos;
|
||||
};
|
||||
|
||||
struct TypeSection : Section {
|
||||
TypeSection() : Section(wasm::WASM_SEC_TYPE) {}
|
||||
static bool classof(const Section *S) {
|
||||
|
@ -256,6 +277,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Function)
|
|||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::LocalDecl)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Relocation)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::NameEntry)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SymbolInfo)
|
||||
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t)
|
||||
|
||||
namespace llvm {
|
||||
|
@ -329,6 +351,10 @@ template <> struct MappingTraits<WasmYAML::ElemSegment> {
|
|||
static void mapping(IO &IO, WasmYAML::ElemSegment &Segment);
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<WasmYAML::SymbolInfo> {
|
||||
static void mapping(IO &IO, WasmYAML::SymbolInfo &Info);
|
||||
};
|
||||
|
||||
template <> struct ScalarEnumerationTraits<WasmYAML::ValueType> {
|
||||
static void enumeration(IO &IO, WasmYAML::ValueType &Type);
|
||||
};
|
||||
|
|
|
@ -98,18 +98,30 @@ bool MCWasmStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
|
|||
case MCSA_WeakDefAutoPrivate:
|
||||
case MCSA_Invalid:
|
||||
case MCSA_IndirectSymbol:
|
||||
case MCSA_Hidden:
|
||||
return false;
|
||||
|
||||
case MCSA_Weak:
|
||||
case MCSA_WeakReference:
|
||||
Symbol->setWeak(true);
|
||||
Symbol->setExternal(true);
|
||||
break;
|
||||
|
||||
case MCSA_Global:
|
||||
Symbol->setExternal(true);
|
||||
break;
|
||||
|
||||
case MCSA_ELF_TypeFunction:
|
||||
Symbol->setIsFunction(true);
|
||||
break;
|
||||
|
||||
case MCSA_ELF_TypeObject:
|
||||
Symbol->setIsFunction(false);
|
||||
break;
|
||||
|
||||
default:
|
||||
// unrecognized directive
|
||||
llvm_unreachable("unexpected MCSymbolAttr");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -156,9 +156,18 @@ struct WasmRelocationEntry {
|
|||
Out << "Off=" << Offset << ", Sym=" << Symbol << ", Addend=" << Addend
|
||||
<< ", Type=" << Type << ", FixupSection=" << FixupSection;
|
||||
}
|
||||
void dump() const { print(errs()); }
|
||||
|
||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
||||
LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
|
||||
#endif
|
||||
};
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS,
|
||||
const WasmRelocationEntry &Rel) {
|
||||
Rel.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
class WasmObjectWriter : public MCObjectWriter {
|
||||
/// Helper struct for containing some precomputed information on symbols.
|
||||
struct WasmSymbolData {
|
||||
|
@ -229,6 +238,11 @@ private:
|
|||
|
||||
void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
|
||||
|
||||
void writeString(const StringRef Str) {
|
||||
encodeULEB128(Str.size(), getStream());
|
||||
writeBytes(Str);
|
||||
}
|
||||
|
||||
void writeValueType(wasm::ValType Ty) {
|
||||
encodeSLEB128(int32_t(Ty), getStream());
|
||||
}
|
||||
|
@ -250,7 +264,8 @@ private:
|
|||
uint32_t NumFuncImports);
|
||||
void writeCodeRelocSection();
|
||||
void writeDataRelocSection(uint64_t DataSectionHeaderSize);
|
||||
void writeLinkingMetaDataSection(bool HasStackPointer,
|
||||
void writeLinkingMetaDataSection(ArrayRef<StringRef> WeakSymbols,
|
||||
bool HasStackPointer,
|
||||
uint32_t StackPointerGlobal);
|
||||
|
||||
void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
|
||||
|
@ -282,6 +297,7 @@ void WasmObjectWriter::startSection(SectionBookkeeping &Section,
|
|||
assert((Name != nullptr) == (SectionId == wasm::WASM_SEC_CUSTOM) &&
|
||||
"Only custom sections can have names");
|
||||
|
||||
DEBUG(dbgs() << "startSection " << SectionId << ": " << Name << "\n");
|
||||
encodeULEB128(SectionId, getStream());
|
||||
|
||||
Section.SizeOffset = getStream().tell();
|
||||
|
@ -295,8 +311,8 @@ void WasmObjectWriter::startSection(SectionBookkeeping &Section,
|
|||
|
||||
// Custom sections in wasm also have a string identifier.
|
||||
if (SectionId == wasm::WASM_SEC_CUSTOM) {
|
||||
encodeULEB128(strlen(Name), getStream());
|
||||
writeBytes(Name);
|
||||
assert(Name);
|
||||
writeString(StringRef(Name));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,6 +323,7 @@ void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
|
|||
if (uint32_t(Size) != Size)
|
||||
report_fatal_error("section size does not fit in a uint32_t");
|
||||
|
||||
DEBUG(dbgs() << "endSection size=" << Size << "\n");
|
||||
unsigned Padding = PaddingFor5ByteULEB128(Size);
|
||||
|
||||
// Write the final section size to the payload_len field, which follows
|
||||
|
@ -411,6 +428,7 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
|
|||
unsigned Type = getRelocType(Target, Fixup);
|
||||
|
||||
WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
|
||||
DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
|
||||
|
||||
if (FixupSection.hasInstructions())
|
||||
CodeRelocations.push_back(Rec);
|
||||
|
@ -455,7 +473,7 @@ static uint32_t ProvisionalValue(const WasmRelocationEntry &RelEntry) {
|
|||
const MCSymbolWasm *Sym = RelEntry.Symbol;
|
||||
|
||||
// For undefined symbols, use a hopefully invalid value.
|
||||
if (!Sym->isDefined(false))
|
||||
if (!Sym->isDefined(/*SetUsed=*/false))
|
||||
return UINT32_MAX;
|
||||
|
||||
MCSectionWasm &Section =
|
||||
|
@ -473,17 +491,23 @@ uint32_t WasmObjectWriter::getRelocationIndexValue(
|
|||
switch (RelEntry.Type) {
|
||||
case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
|
||||
case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
|
||||
assert(IndirectSymbolIndices.count(RelEntry.Symbol));
|
||||
if (!IndirectSymbolIndices.count(RelEntry.Symbol))
|
||||
report_fatal_error("symbol not found table index space:" +
|
||||
RelEntry.Symbol->getName());
|
||||
return IndirectSymbolIndices[RelEntry.Symbol];
|
||||
case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
|
||||
case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
|
||||
case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
|
||||
case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
|
||||
case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
|
||||
assert(SymbolIndices.count(RelEntry.Symbol));
|
||||
if (!SymbolIndices.count(RelEntry.Symbol))
|
||||
report_fatal_error("symbol not found function/global index space:" +
|
||||
RelEntry.Symbol->getName());
|
||||
return SymbolIndices[RelEntry.Symbol];
|
||||
case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
|
||||
assert(TypeIndices.count(RelEntry.Symbol));
|
||||
if (!TypeIndices.count(RelEntry.Symbol))
|
||||
report_fatal_error("symbol not found in type index space:" +
|
||||
RelEntry.Symbol->getName());
|
||||
return TypeIndices[RelEntry.Symbol];
|
||||
default:
|
||||
llvm_unreachable("invalid relocation type");
|
||||
|
@ -500,6 +524,7 @@ void WasmObjectWriter::applyRelocations(
|
|||
RelEntry.FixupSection->getSectionOffset() +
|
||||
RelEntry.Offset;
|
||||
|
||||
DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
|
||||
switch (RelEntry.Type) {
|
||||
case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
|
||||
case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
|
||||
|
@ -577,6 +602,7 @@ void WasmObjectWriter::writeTypeSection(
|
|||
endSection(Section);
|
||||
}
|
||||
|
||||
|
||||
void WasmObjectWriter::writeImportSection(
|
||||
const SmallVector<WasmImport, 4> &Imports) {
|
||||
if (Imports.empty())
|
||||
|
@ -587,13 +613,8 @@ void WasmObjectWriter::writeImportSection(
|
|||
|
||||
encodeULEB128(Imports.size(), getStream());
|
||||
for (const WasmImport &Import : Imports) {
|
||||
StringRef ModuleName = Import.ModuleName;
|
||||
encodeULEB128(ModuleName.size(), getStream());
|
||||
writeBytes(ModuleName);
|
||||
|
||||
StringRef FieldName = Import.FieldName;
|
||||
encodeULEB128(FieldName.size(), getStream());
|
||||
writeBytes(FieldName);
|
||||
writeString(Import.ModuleName);
|
||||
writeString(Import.FieldName);
|
||||
|
||||
encodeULEB128(Import.Kind, getStream());
|
||||
|
||||
|
@ -701,11 +722,8 @@ void WasmObjectWriter::writeExportSection(
|
|||
|
||||
encodeULEB128(Exports.size(), getStream());
|
||||
for (const WasmExport &Export : Exports) {
|
||||
encodeULEB128(Export.FieldName.size(), getStream());
|
||||
writeBytes(Export.FieldName);
|
||||
|
||||
writeString(Export.FieldName);
|
||||
encodeSLEB128(Export.Kind, getStream());
|
||||
|
||||
encodeULEB128(Export.Index, getStream());
|
||||
}
|
||||
|
||||
|
@ -750,15 +768,6 @@ void WasmObjectWriter::writeCodeSection(
|
|||
MCSectionWasm &FuncSection =
|
||||
static_cast<MCSectionWasm &>(Func.Sym->getSection());
|
||||
|
||||
if (Func.Sym->isVariable())
|
||||
report_fatal_error("weak symbols not supported yet");
|
||||
|
||||
if (Func.Sym->getOffset() != 0)
|
||||
report_fatal_error("function sections must contain one function each");
|
||||
|
||||
if (!Func.Sym->getSize())
|
||||
report_fatal_error("function symbols must have a size set with .size");
|
||||
|
||||
int64_t Size = 0;
|
||||
if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout))
|
||||
report_fatal_error(".size expression must be evaluatable");
|
||||
|
@ -819,15 +828,13 @@ void WasmObjectWriter::writeNameSection(
|
|||
for (const WasmImport &Import : Imports) {
|
||||
if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
|
||||
encodeULEB128(Index, getStream());
|
||||
encodeULEB128(Import.FieldName.size(), getStream());
|
||||
writeBytes(Import.FieldName);
|
||||
writeString(Import.FieldName);
|
||||
++Index;
|
||||
}
|
||||
}
|
||||
for (const WasmFunction &Func : Functions) {
|
||||
encodeULEB128(Index, getStream());
|
||||
encodeULEB128(Func.Sym->getName().size(), getStream());
|
||||
writeBytes(Func.Sym->getName());
|
||||
writeString(Func.Sym->getName());
|
||||
++Index;
|
||||
}
|
||||
|
||||
|
@ -872,22 +879,37 @@ void WasmObjectWriter::writeDataRelocSection(uint64_t DataSectionHeaderSize) {
|
|||
}
|
||||
|
||||
void WasmObjectWriter::writeLinkingMetaDataSection(
|
||||
bool HasStackPointer, uint32_t StackPointerGlobal) {
|
||||
if (!HasStackPointer)
|
||||
ArrayRef<StringRef> WeakSymbols, bool HasStackPointer,
|
||||
uint32_t StackPointerGlobal) {
|
||||
if (!HasStackPointer && WeakSymbols.empty())
|
||||
return;
|
||||
|
||||
SectionBookkeeping Section;
|
||||
startSection(Section, wasm::WASM_SEC_CUSTOM, "linking");
|
||||
SectionBookkeeping SubSection;
|
||||
|
||||
encodeULEB128(1, getStream()); // count
|
||||
if (HasStackPointer) {
|
||||
startSection(SubSection, wasm::WASM_STACK_POINTER);
|
||||
encodeULEB128(StackPointerGlobal, getStream()); // id
|
||||
endSection(SubSection);
|
||||
}
|
||||
|
||||
encodeULEB128(wasm::WASM_STACK_POINTER, getStream()); // type
|
||||
encodeULEB128(StackPointerGlobal, getStream()); // id
|
||||
if (WeakSymbols.size() != 0) {
|
||||
startSection(SubSection, wasm::WASM_SYMBOL_INFO);
|
||||
encodeULEB128(WeakSymbols.size(), getStream());
|
||||
for (const StringRef Export: WeakSymbols) {
|
||||
writeString(Export);
|
||||
encodeULEB128(wasm::WASM_SYMBOL_FLAG_WEAK, getStream());
|
||||
}
|
||||
endSection(SubSection);
|
||||
}
|
||||
|
||||
endSection(Section);
|
||||
}
|
||||
|
||||
void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout) {
|
||||
DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");
|
||||
MCContext &Ctx = Asm.getContext();
|
||||
wasm::ValType PtrType = is64Bit() ? wasm::ValType::I64 : wasm::ValType::I32;
|
||||
|
||||
|
@ -898,6 +920,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
|||
SmallVector<WasmGlobal, 4> Globals;
|
||||
SmallVector<WasmImport, 4> Imports;
|
||||
SmallVector<WasmExport, 4> Exports;
|
||||
SmallVector<StringRef, 4> WeakSymbols;
|
||||
SmallPtrSet<const MCSymbolWasm *, 4> IsAddressTaken;
|
||||
unsigned NumFuncImports = 0;
|
||||
unsigned NumGlobalImports = 0;
|
||||
|
@ -906,7 +929,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
|||
bool HasStackPointer = false;
|
||||
|
||||
// Populate the IsAddressTaken set.
|
||||
for (WasmRelocationEntry RelEntry : CodeRelocations) {
|
||||
for (const WasmRelocationEntry &RelEntry : CodeRelocations) {
|
||||
switch (RelEntry.Type) {
|
||||
case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
|
||||
case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
|
||||
|
@ -916,7 +939,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
|||
break;
|
||||
}
|
||||
}
|
||||
for (WasmRelocationEntry RelEntry : DataRelocations) {
|
||||
for (const WasmRelocationEntry &RelEntry : DataRelocations) {
|
||||
switch (RelEntry.Type) {
|
||||
case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
|
||||
case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
|
||||
|
@ -1045,14 +1068,32 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
|||
StackPointerGlobal = NumGlobalImports + *(const int32_t *)Contents.data();
|
||||
}
|
||||
|
||||
// Handle defined symbols.
|
||||
// Handle regular defined and undefined symbols.
|
||||
for (const MCSymbol &S : Asm.symbols()) {
|
||||
// Ignore unnamed temporary symbols, which aren't ever exported, imported,
|
||||
// or used in relocations.
|
||||
if (S.isTemporary() && S.getName().empty())
|
||||
continue;
|
||||
|
||||
// Variable references (weak references) are handled in a second pass
|
||||
if (S.isVariable())
|
||||
continue;
|
||||
|
||||
const auto &WS = static_cast<const MCSymbolWasm &>(S);
|
||||
DEBUG(dbgs() << "MCSymbol: '" << S << "'"
|
||||
<< " isDefined=" << S.isDefined() << " isExternal="
|
||||
<< S.isExternal() << " isTemporary=" << S.isTemporary()
|
||||
<< " isFunction=" << WS.isFunction()
|
||||
<< " isWeak=" << WS.isWeak()
|
||||
<< " isVariable=" << WS.isVariable() << "\n");
|
||||
|
||||
if (WS.isWeak())
|
||||
WeakSymbols.push_back(WS.getName());
|
||||
|
||||
unsigned Index;
|
||||
|
||||
//<< " function=" << S.isFunction()
|
||||
|
||||
if (WS.isFunction()) {
|
||||
// Prepare the function's type, if we haven't seen it yet.
|
||||
WasmFunctionType F;
|
||||
|
@ -1066,6 +1107,14 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
|||
int32_t Type = Pair.first->second;
|
||||
|
||||
if (WS.isDefined(/*SetUsed=*/false)) {
|
||||
if (WS.getOffset() != 0)
|
||||
report_fatal_error(
|
||||
"function sections must contain one function each");
|
||||
|
||||
if (WS.getSize() == 0)
|
||||
report_fatal_error(
|
||||
"function symbols must have a size set with .size");
|
||||
|
||||
// A definition. Take the next available index.
|
||||
Index = NumFuncImports + Functions.size();
|
||||
|
||||
|
@ -1076,6 +1125,9 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
|||
SymbolIndices[&WS] = Index;
|
||||
Functions.push_back(Func);
|
||||
} else {
|
||||
// Should be no such thing as weak undefined symbol
|
||||
assert(!WS.isVariable());
|
||||
|
||||
// An import; the index was assigned above.
|
||||
Index = SymbolIndices.find(&WS)->second;
|
||||
}
|
||||
|
@ -1089,7 +1141,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
|||
if (WS.isTemporary() && !WS.getSize())
|
||||
continue;
|
||||
|
||||
if (WS.isDefined(false)) {
|
||||
if (WS.isDefined(/*SetUsed=*/false)) {
|
||||
if (WS.getOffset() != 0)
|
||||
report_fatal_error("data sections must contain one variable each: " +
|
||||
WS.getName());
|
||||
|
@ -1154,21 +1206,46 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
|||
}
|
||||
|
||||
// If the symbol is visible outside this translation unit, export it.
|
||||
if (WS.isExternal()) {
|
||||
assert(WS.isDefined(false));
|
||||
if (WS.isExternal() && WS.isDefined(/*SetUsed=*/false)) {
|
||||
WasmExport Export;
|
||||
Export.FieldName = WS.getName();
|
||||
Export.Index = Index;
|
||||
|
||||
if (WS.isFunction())
|
||||
Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
|
||||
else
|
||||
Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
|
||||
|
||||
Exports.push_back(Export);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle weak aliases
|
||||
for (const MCSymbol &S : Asm.symbols()) {
|
||||
if (!S.isVariable())
|
||||
continue;
|
||||
assert(S.isExternal());
|
||||
assert(S.isDefined(/*SetUsed=*/false));
|
||||
|
||||
const auto &WS = static_cast<const MCSymbolWasm &>(S);
|
||||
|
||||
// Find the target symbol of this weak alias
|
||||
const MCExpr *Expr = WS.getVariableValue();
|
||||
auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr);
|
||||
const MCSymbolWasm *ResolvedSym = cast<MCSymbolWasm>(&Inner->getSymbol());
|
||||
uint32_t Index = SymbolIndices.find(ResolvedSym)->second;
|
||||
DEBUG(dbgs() << "Weak alias: '" << WS << "' -> '" << ResolvedSym << "' = " << Index << "\n");
|
||||
SymbolIndices[&WS] = Index;
|
||||
|
||||
WasmExport Export;
|
||||
Export.FieldName = WS.getName();
|
||||
Export.Index = Index;
|
||||
if (WS.isFunction())
|
||||
Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
|
||||
else
|
||||
Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
|
||||
WeakSymbols.push_back(Export.FieldName);
|
||||
Exports.push_back(Export);
|
||||
}
|
||||
|
||||
// Add types for indirect function calls.
|
||||
for (const WasmRelocationEntry &Fixup : CodeRelocations) {
|
||||
if (Fixup.Type != wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB)
|
||||
|
@ -1202,7 +1279,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
|||
writeNameSection(Functions, Imports, NumFuncImports);
|
||||
writeCodeRelocSection();
|
||||
writeDataRelocSection(DataSectionHeaderSize);
|
||||
writeLinkingMetaDataSection(HasStackPointer, StackPointerGlobal);
|
||||
writeLinkingMetaDataSection(WeakSymbols, HasStackPointer, StackPointerGlobal);
|
||||
|
||||
// TODO: Translate the .comment section to the output.
|
||||
// TODO: Translate debug sections to the output.
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include <cstring>
|
||||
#include <system_error>
|
||||
|
||||
#define DEBUG_TYPE "wasm-object"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace object;
|
||||
|
||||
|
@ -256,6 +258,7 @@ Error WasmObjectFile::parseNameSection(const uint8_t *Ptr, const uint8_t *End) {
|
|||
while (Ptr < End) {
|
||||
uint8_t Type = readVarint7(Ptr);
|
||||
uint32_t Size = readVaruint32(Ptr);
|
||||
const uint8_t *SubSectionEnd = Ptr + Size;
|
||||
switch (Type) {
|
||||
case wasm::WASM_NAMES_FUNCTION: {
|
||||
uint32_t Count = readVaruint32(Ptr);
|
||||
|
@ -275,6 +278,9 @@ Error WasmObjectFile::parseNameSection(const uint8_t *Ptr, const uint8_t *End) {
|
|||
Ptr += Size;
|
||||
break;
|
||||
}
|
||||
if (Ptr != SubSectionEnd)
|
||||
return make_error<GenericBinaryError>("Name sub-section ended prematurely",
|
||||
object_error::parse_failed);
|
||||
}
|
||||
|
||||
if (Ptr != End)
|
||||
|
@ -283,6 +289,50 @@ Error WasmObjectFile::parseNameSection(const uint8_t *Ptr, const uint8_t *End) {
|
|||
return Error::success();
|
||||
}
|
||||
|
||||
Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
|
||||
const uint8_t *End) {
|
||||
while (Ptr < End) {
|
||||
uint8_t Type = readVarint7(Ptr);
|
||||
uint32_t Size = readVaruint32(Ptr);
|
||||
const uint8_t *SubSectionEnd = Ptr + Size;
|
||||
switch (Type) {
|
||||
case wasm::WASM_SYMBOL_INFO: {
|
||||
uint32_t Count = readVaruint32(Ptr);
|
||||
while (Count--) {
|
||||
StringRef Symbol = readString(Ptr);
|
||||
DEBUG(dbgs() << "reading syminfo: " << Symbol << "\n");
|
||||
uint32_t Flags = readVaruint32(Ptr);
|
||||
auto iter = SymbolMap.find(Symbol);
|
||||
if (iter == SymbolMap.end()) {
|
||||
return make_error<GenericBinaryError>(
|
||||
"Invalid symbol name in linking section",
|
||||
object_error::parse_failed);
|
||||
}
|
||||
uint32_t SymIndex = iter->second;
|
||||
assert(SymIndex < Symbols.size());
|
||||
Symbols[SymIndex].Flags = Flags;
|
||||
DEBUG(dbgs() << "Set symbol flags index:"
|
||||
<< SymIndex << " name:"
|
||||
<< Symbols[SymIndex].Name << " exptected:"
|
||||
<< Symbol << " flags: " << Flags << "\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case wasm::WASM_STACK_POINTER:
|
||||
default:
|
||||
Ptr += Size;
|
||||
break;
|
||||
}
|
||||
if (Ptr != SubSectionEnd)
|
||||
return make_error<GenericBinaryError>(
|
||||
"Linking sub-section ended prematurely", object_error::parse_failed);
|
||||
}
|
||||
if (Ptr != End)
|
||||
return make_error<GenericBinaryError>("Linking section ended prematurely",
|
||||
object_error::parse_failed);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
WasmSection* WasmObjectFile::findCustomSectionByName(StringRef Name) {
|
||||
for (WasmSection& Section : Sections) {
|
||||
if (Section.Type == wasm::WASM_SEC_CUSTOM && Section.Name == Name)
|
||||
|
@ -351,6 +401,9 @@ Error WasmObjectFile::parseCustomSection(WasmSection &Sec,
|
|||
if (Sec.Name == "name") {
|
||||
if (Error Err = parseNameSection(Ptr, End))
|
||||
return Err;
|
||||
} else if (Sec.Name == "linking") {
|
||||
if (Error Err = parseLinkingSection(Ptr, End))
|
||||
return Err;
|
||||
} else if (Sec.Name.startswith("reloc.")) {
|
||||
if (Error Err = parseRelocSection(Sec.Name, Ptr, End))
|
||||
return Err;
|
||||
|
@ -402,14 +455,20 @@ Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End)
|
|||
switch (Im.Kind) {
|
||||
case wasm::WASM_EXTERNAL_FUNCTION:
|
||||
Im.SigIndex = readVaruint32(Ptr);
|
||||
SymbolMap.try_emplace(Im.Field, Symbols.size());
|
||||
Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::FUNCTION_IMPORT,
|
||||
Sections.size(), i);
|
||||
DEBUG(dbgs() << "Adding import: " << Symbols.back()
|
||||
<< " sym index:" << Symbols.size() << "\n");
|
||||
break;
|
||||
case wasm::WASM_EXTERNAL_GLOBAL:
|
||||
Im.Global.Type = readVarint7(Ptr);
|
||||
Im.Global.Mutable = readVaruint1(Ptr);
|
||||
SymbolMap.try_emplace(Im.Field, Symbols.size());
|
||||
Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT,
|
||||
Sections.size(), i);
|
||||
DEBUG(dbgs() << "Adding import: " << Symbols.back()
|
||||
<< " sym index:" << Symbols.size() << "\n");
|
||||
break;
|
||||
case wasm::WASM_EXTERNAL_MEMORY:
|
||||
Im.Memory = readLimits(Ptr);
|
||||
|
@ -498,15 +557,20 @@ Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End)
|
|||
Ex.Name = readString(Ptr);
|
||||
Ex.Kind = readUint8(Ptr);
|
||||
Ex.Index = readVaruint32(Ptr);
|
||||
Exports.push_back(Ex);
|
||||
switch (Ex.Kind) {
|
||||
case wasm::WASM_EXTERNAL_FUNCTION:
|
||||
SymbolMap.try_emplace(Ex.Name, Symbols.size());
|
||||
Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::FUNCTION_EXPORT,
|
||||
Sections.size(), i);
|
||||
DEBUG(dbgs() << "Adding export: " << Symbols.back()
|
||||
<< " sym index:" << Symbols.size() << "\n");
|
||||
break;
|
||||
case wasm::WASM_EXTERNAL_GLOBAL:
|
||||
SymbolMap.try_emplace(Ex.Name, Symbols.size());
|
||||
Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::GLOBAL_EXPORT,
|
||||
Sections.size(), i);
|
||||
DEBUG(dbgs() << "Adding export: " << Symbols.back()
|
||||
<< " sym index:" << Symbols.size() << "\n");
|
||||
break;
|
||||
case wasm::WASM_EXTERNAL_MEMORY:
|
||||
case wasm::WASM_EXTERNAL_TABLE:
|
||||
|
@ -515,6 +579,7 @@ Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End)
|
|||
return make_error<GenericBinaryError>(
|
||||
"Unexpected export kind", object_error::parse_failed);
|
||||
}
|
||||
Exports.push_back(Ex);
|
||||
}
|
||||
if (Ptr != End)
|
||||
return make_error<GenericBinaryError>("Export section ended prematurely",
|
||||
|
@ -622,6 +687,10 @@ uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
|
|||
uint32_t Result = SymbolRef::SF_None;
|
||||
const WasmSymbol &Sym = getWasmSymbol(Symb);
|
||||
|
||||
DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
|
||||
if (Sym.Flags & wasm::WASM_SYMBOL_FLAG_WEAK)
|
||||
Result |= SymbolRef::SF_Weak;
|
||||
|
||||
switch (Sym.Type) {
|
||||
case WasmSymbol::SymbolType::FUNCTION_IMPORT:
|
||||
Result |= SymbolRef::SF_Undefined | SymbolRef::SF_Executable;
|
||||
|
@ -631,6 +700,7 @@ uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
|
|||
break;
|
||||
case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
|
||||
Result |= SymbolRef::SF_Executable;
|
||||
Result |= SymbolRef::SF_FormatSpecific;
|
||||
break;
|
||||
case WasmSymbol::SymbolType::GLOBAL_IMPORT:
|
||||
Result |= SymbolRef::SF_Undefined;
|
||||
|
@ -664,8 +734,7 @@ const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
|
|||
}
|
||||
|
||||
Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
|
||||
const WasmSymbol &Sym = getWasmSymbol(Symb);
|
||||
return Sym.Name;
|
||||
return getWasmSymbol(Symb).Name;
|
||||
}
|
||||
|
||||
Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
|
||||
|
@ -673,8 +742,17 @@ Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
|
|||
}
|
||||
|
||||
uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
|
||||
const WasmSymbol &Sym = getWasmSymbol(Symb);
|
||||
return Sym.ElementIndex;
|
||||
const WasmSymbol& Sym = getWasmSymbol(Symb);
|
||||
switch (Sym.Type) {
|
||||
case WasmSymbol::SymbolType::FUNCTION_IMPORT:
|
||||
case WasmSymbol::SymbolType::GLOBAL_IMPORT:
|
||||
return 0;
|
||||
case WasmSymbol::SymbolType::FUNCTION_EXPORT:
|
||||
case WasmSymbol::SymbolType::GLOBAL_EXPORT:
|
||||
return Exports[Sym.ElementIndex].Index;
|
||||
case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
|
||||
return Sym.ElementIndex;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
|
||||
|
|
|
@ -47,14 +47,22 @@ static void commonSectionMapping(IO &IO, WasmYAML::Section &Section) {
|
|||
IO.mapOptional("Relocations", Section.Relocations);
|
||||
}
|
||||
|
||||
static void sectionMapping(IO &IO, WasmYAML::NameSection &Section) {
|
||||
commonSectionMapping(IO, Section);
|
||||
IO.mapRequired("Name", Section.Name);
|
||||
IO.mapOptional("FunctionNames", Section.FunctionNames);
|
||||
}
|
||||
|
||||
static void sectionMapping(IO &IO, WasmYAML::LinkingSection &Section) {
|
||||
commonSectionMapping(IO, Section);
|
||||
IO.mapRequired("Name", Section.Name);
|
||||
IO.mapRequired("SymbolInfo", Section.SymbolInfos);
|
||||
}
|
||||
|
||||
static void sectionMapping(IO &IO, WasmYAML::CustomSection &Section) {
|
||||
commonSectionMapping(IO, Section);
|
||||
IO.mapRequired("Name", Section.Name);
|
||||
if (Section.Name == "name") {
|
||||
IO.mapOptional("FunctionNames", Section.FunctionNames);
|
||||
} else {
|
||||
IO.mapRequired("Payload", Section.Payload);
|
||||
}
|
||||
IO.mapRequired("Payload", Section.Payload);
|
||||
}
|
||||
|
||||
static void sectionMapping(IO &IO, WasmYAML::TypeSection &Section) {
|
||||
|
@ -121,11 +129,29 @@ void MappingTraits<std::unique_ptr<WasmYAML::Section>>::mapping(
|
|||
IO.mapRequired("Type", SectionType);
|
||||
|
||||
switch (SectionType) {
|
||||
case wasm::WASM_SEC_CUSTOM:
|
||||
if (!IO.outputting())
|
||||
Section.reset(new WasmYAML::CustomSection());
|
||||
sectionMapping(IO, *cast<WasmYAML::CustomSection>(Section.get()));
|
||||
case wasm::WASM_SEC_CUSTOM: {
|
||||
StringRef SectionName;
|
||||
if (IO.outputting()) {
|
||||
auto CustomSection = cast<WasmYAML::CustomSection>(Section.get());
|
||||
SectionName = CustomSection->Name;
|
||||
} else {
|
||||
IO.mapRequired("Name", SectionName);
|
||||
}
|
||||
if (SectionName == "linking") {
|
||||
if (!IO.outputting())
|
||||
Section.reset(new WasmYAML::LinkingSection());
|
||||
sectionMapping(IO, *cast<WasmYAML::LinkingSection>(Section.get()));
|
||||
} else if (SectionName == "name") {
|
||||
if (!IO.outputting())
|
||||
Section.reset(new WasmYAML::NameSection());
|
||||
sectionMapping(IO, *cast<WasmYAML::NameSection>(Section.get()));
|
||||
} else {
|
||||
if (!IO.outputting())
|
||||
Section.reset(new WasmYAML::CustomSection(SectionName));
|
||||
sectionMapping(IO, *cast<WasmYAML::CustomSection>(Section.get()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case wasm::WASM_SEC_TYPE:
|
||||
if (!IO.outputting())
|
||||
Section.reset(new WasmYAML::TypeSection());
|
||||
|
@ -321,6 +347,12 @@ void MappingTraits<WasmYAML::DataSegment>::mapping(
|
|||
IO.mapRequired("Content", Segment.Content);
|
||||
}
|
||||
|
||||
void MappingTraits<WasmYAML::SymbolInfo>::mapping(IO &IO,
|
||||
WasmYAML::SymbolInfo &Info) {
|
||||
IO.mapRequired("Name", Info.Name);
|
||||
IO.mapRequired("Flags", Info.Flags);
|
||||
}
|
||||
|
||||
void ScalarEnumerationTraits<WasmYAML::ValueType>::enumeration(
|
||||
IO &IO, WasmYAML::ValueType &Type) {
|
||||
#define ECase(X) IO.enumCase(Type, #X, wasm::WASM_TYPE_##X);
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
# RUN: yaml2obj %s | obj2yaml | FileCheck %s
|
||||
--- !WASM
|
||||
FileHeader:
|
||||
Version: 0x00000001
|
||||
Sections:
|
||||
- Type: EXPORT
|
||||
Exports:
|
||||
- Name: function_export
|
||||
Kind: FUNCTION
|
||||
Index: 1
|
||||
- Name: global_export
|
||||
Kind: GLOBAL
|
||||
Index: 2
|
||||
- Type: CUSTOM
|
||||
Name: linking
|
||||
SymbolInfo:
|
||||
- Name: function_export
|
||||
Flags: 1
|
||||
- Name: global_export
|
||||
Flags: 1
|
||||
...
|
||||
# CHECK: --- !WASM
|
||||
# CHECK: FileHeader:
|
||||
# CHECK: Version: 0x00000001
|
||||
# CHECK: Sections:
|
||||
# CHECK: - Type: EXPORT
|
||||
# CHECK: Exports:
|
||||
# CHECK: - Name: function_export
|
||||
# CHECK: Kind: FUNCTION
|
||||
# CHECK: Index: 1
|
||||
# CHECK: - Name: global_export
|
||||
# CHECK: Kind: GLOBAL
|
||||
# CHECK: Index: 2
|
||||
# CHECK: - Type: CUSTOM
|
||||
# CHECK: Name: linking
|
||||
# CHECK: SymbolInfo:
|
||||
# CHECK: - Name: function_export
|
||||
# CHECK: Flags: 1
|
||||
# CHECK: - Name: global_export
|
||||
# CHECK: Flags: 1
|
|
@ -1,5 +1,8 @@
|
|||
# RUN: yaml2obj < %s | llvm-nm - | FileCheck %s
|
||||
|
||||
# That wasm exports of functions and globals are displayed as global data and
|
||||
# code symbols.
|
||||
|
||||
--- !WASM
|
||||
FileHeader:
|
||||
Version: 0x00000001
|
||||
|
@ -13,10 +16,10 @@ Sections:
|
|||
Exports:
|
||||
- Name: foo
|
||||
Kind: FUNCTION
|
||||
Index: 0x00000000
|
||||
Index: 0x00000004
|
||||
- Name: bar
|
||||
Kind: GLOBAL
|
||||
Index: 0x00000000
|
||||
Index: 0x00000002
|
||||
|
||||
# CHECK: 00000001 D bar
|
||||
# CHECK: 00000000 T foo
|
||||
# CHECK: 00000002 D bar
|
||||
# CHECK: 00000004 T foo
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
# RUN: yaml2obj < %s | llvm-nm - | FileCheck %s
|
||||
|
||||
# That wasm exports of functions and globals are displayed as global data and
|
||||
# code symbols.
|
||||
|
||||
--- !WASM
|
||||
FileHeader:
|
||||
Version: 0x00000001
|
||||
Sections:
|
||||
- Type: TYPE
|
||||
Signatures:
|
||||
- ReturnType: I32
|
||||
ParamTypes:
|
||||
- I32
|
||||
- Type: IMPORT
|
||||
Imports:
|
||||
- Module: env
|
||||
Field: weak_import_func
|
||||
Kind: FUNCTION
|
||||
SigIndex: 0
|
||||
- Module: env
|
||||
Field: weak_import_data
|
||||
Kind: GLOBAL
|
||||
GlobalType: I32
|
||||
GlobalMutable: false
|
||||
- Type: EXPORT
|
||||
Exports:
|
||||
- Name: weak_global_func
|
||||
Kind: FUNCTION
|
||||
Index: 0x00000004
|
||||
- Name: weak_global_data
|
||||
Kind: GLOBAL
|
||||
Index: 0x00000002
|
||||
- Type: CUSTOM
|
||||
Name: linking
|
||||
SymbolInfo:
|
||||
- Name: weak_global_func
|
||||
Flags: 1
|
||||
- Name: weak_global_data
|
||||
Flags: 1
|
||||
- Name: weak_import_func
|
||||
Flags: 1
|
||||
- Name: weak_import_data
|
||||
Flags: 1
|
||||
|
||||
# CHECK: 00000002 W weak_global_data
|
||||
# CHECK: 00000004 W weak_global_func
|
||||
# CHECK: w weak_import_data
|
||||
# CHECK: w weak_import_func
|
|
@ -14,6 +14,7 @@
|
|||
#include "llvm/Support/YAMLTraits.h"
|
||||
|
||||
using namespace llvm;
|
||||
using object::WasmSection;
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -22,10 +23,16 @@ class WasmDumper {
|
|||
|
||||
public:
|
||||
WasmDumper(const object::WasmObjectFile &O) : Obj(O) {}
|
||||
|
||||
ErrorOr<WasmYAML::Object *> dump();
|
||||
|
||||
std::unique_ptr<WasmYAML::CustomSection>
|
||||
dumpCustomSection(const WasmSection &WasmSec);
|
||||
};
|
||||
|
||||
WasmYAML::Table make_table(const wasm::WasmTable &Table) {
|
||||
} // namespace
|
||||
|
||||
static WasmYAML::Table make_table(const wasm::WasmTable &Table) {
|
||||
WasmYAML::Table T;
|
||||
T.ElemType = Table.ElemType;
|
||||
T.TableLimits.Flags = Table.Limits.Flags;
|
||||
|
@ -34,7 +41,7 @@ WasmYAML::Table make_table(const wasm::WasmTable &Table) {
|
|||
return T;
|
||||
}
|
||||
|
||||
WasmYAML::Limits make_limits(const wasm::WasmLimits &Limits) {
|
||||
static WasmYAML::Limits make_limits(const wasm::WasmLimits &Limits) {
|
||||
WasmYAML::Limits L;
|
||||
L.Flags = Limits.Flags;
|
||||
L.Initial = Limits.Initial;
|
||||
|
@ -42,6 +49,42 @@ WasmYAML::Limits make_limits(const wasm::WasmLimits &Limits) {
|
|||
return L;
|
||||
}
|
||||
|
||||
std::unique_ptr<WasmYAML::CustomSection> WasmDumper::dumpCustomSection(const WasmSection &WasmSec) {
|
||||
std::unique_ptr<WasmYAML::CustomSection> CustomSec;
|
||||
if (WasmSec.Name == "name") {
|
||||
std::unique_ptr<WasmYAML::NameSection> NameSec = make_unique<WasmYAML::NameSection>();
|
||||
for (const object::SymbolRef& Sym: Obj.symbols()) {
|
||||
uint32_t Flags = Sym.getFlags();
|
||||
// Skip over symbols that come from imports or exports
|
||||
if (Flags &
|
||||
(object::SymbolRef::SF_Global | object::SymbolRef::SF_Undefined))
|
||||
continue;
|
||||
Expected<StringRef> NameOrError = Sym.getName();
|
||||
if (!NameOrError)
|
||||
continue;
|
||||
WasmYAML::NameEntry NameEntry;
|
||||
NameEntry.Name = *NameOrError;
|
||||
NameEntry.Index = Sym.getValue();
|
||||
NameSec->FunctionNames.push_back(NameEntry);
|
||||
}
|
||||
CustomSec = std::move(NameSec);
|
||||
} else if (WasmSec.Name == "linking") {
|
||||
std::unique_ptr<WasmYAML::LinkingSection> LinkingSec = make_unique<WasmYAML::LinkingSection>();
|
||||
for (const object::SymbolRef& Sym: Obj.symbols()) {
|
||||
const object::WasmSymbol Symbol = Obj.getWasmSymbol(Sym);
|
||||
if (Symbol.Flags != 0) {
|
||||
WasmYAML::SymbolInfo Info = { Symbol.Name, Symbol.Flags };
|
||||
LinkingSec->SymbolInfos.push_back(Info);
|
||||
}
|
||||
}
|
||||
CustomSec = std::move(LinkingSec);
|
||||
} else {
|
||||
CustomSec = make_unique<WasmYAML::CustomSection>(WasmSec.Name);
|
||||
}
|
||||
CustomSec->Payload = yaml::BinaryRef(WasmSec.Content);
|
||||
return CustomSec;
|
||||
}
|
||||
|
||||
ErrorOr<WasmYAML::Object *> WasmDumper::dump() {
|
||||
auto Y = make_unique<WasmYAML::Object>();
|
||||
|
||||
|
@ -50,7 +93,7 @@ ErrorOr<WasmYAML::Object *> WasmDumper::dump() {
|
|||
|
||||
// Dump sections
|
||||
for (const auto &Sec : Obj.sections()) {
|
||||
const object::WasmSection &WasmSec = Obj.getWasmSection(Sec);
|
||||
const WasmSection &WasmSec = Obj.getWasmSection(Sec);
|
||||
std::unique_ptr<WasmYAML::Section> S;
|
||||
switch (WasmSec.Type) {
|
||||
case wasm::WASM_SEC_CUSTOM: {
|
||||
|
@ -59,27 +102,7 @@ ErrorOr<WasmYAML::Object *> WasmDumper::dump() {
|
|||
// being represented as a custom section in the YAML output.
|
||||
continue;
|
||||
}
|
||||
auto CustomSec = make_unique<WasmYAML::CustomSection>();
|
||||
CustomSec->Name = WasmSec.Name;
|
||||
if (CustomSec->Name == "name") {
|
||||
for (const object::SymbolRef& Sym: Obj.symbols()) {
|
||||
uint32_t Flags = Sym.getFlags();
|
||||
// Skip over symbols that come from imports or exports
|
||||
if (Flags &
|
||||
(object::SymbolRef::SF_Global | object::SymbolRef::SF_Undefined))
|
||||
continue;
|
||||
Expected<StringRef> NameOrError = Sym.getName();
|
||||
if (!NameOrError)
|
||||
continue;
|
||||
WasmYAML::NameEntry NameEntry;
|
||||
NameEntry.Name = *NameOrError;
|
||||
NameEntry.Index = Sym.getValue();
|
||||
CustomSec->FunctionNames.push_back(NameEntry);
|
||||
}
|
||||
} else {
|
||||
CustomSec->Payload = yaml::BinaryRef(WasmSec.Content);
|
||||
}
|
||||
S = std::move(CustomSec);
|
||||
S = dumpCustomSection(WasmSec);
|
||||
break;
|
||||
}
|
||||
case wasm::WASM_SEC_TYPE: {
|
||||
|
@ -237,8 +260,6 @@ ErrorOr<WasmYAML::Object *> WasmDumper::dump() {
|
|||
return Y.release();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::error_code wasm2yaml(raw_ostream &Out, const object::WasmObjectFile &Obj) {
|
||||
WasmDumper Dumper(Obj);
|
||||
ErrorOr<WasmYAML::Object *> YAMLOrErr = Dumper.dump();
|
||||
|
|
|
@ -26,8 +26,9 @@ class WasmWriter {
|
|||
public:
|
||||
WasmWriter(WasmYAML::Object &Obj) : Obj(Obj) {}
|
||||
int writeWasm(raw_ostream &OS);
|
||||
|
||||
private:
|
||||
int writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec);
|
||||
int writeNameSection(raw_ostream &OS, WasmYAML::CustomSection &Section);
|
||||
|
||||
int writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
|
||||
int writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
|
||||
|
@ -42,7 +43,9 @@ public:
|
|||
int writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
|
||||
int writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
|
||||
|
||||
private:
|
||||
// Custom section types
|
||||
int writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
|
||||
int writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
|
||||
WasmYAML::Object &Obj;
|
||||
};
|
||||
|
||||
|
@ -107,12 +110,30 @@ static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int WasmWriter::writeNameSection(raw_ostream &OS,
|
||||
WasmYAML::CustomSection &Section) {
|
||||
int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section) {
|
||||
writeStringRef(Section.Name, OS);
|
||||
if (Section.SymbolInfos.size()) {
|
||||
encodeULEB128(wasm::WASM_SYMBOL_INFO, OS);
|
||||
std::string OutString;
|
||||
raw_string_ostream StringStream(OutString);
|
||||
|
||||
encodeULEB128(Section.SymbolInfos.size(), StringStream);
|
||||
for (const WasmYAML::SymbolInfo &Info : Section.SymbolInfos) {
|
||||
writeStringRef(Info.Name, StringStream);
|
||||
encodeULEB128(Info.Flags, StringStream);
|
||||
}
|
||||
|
||||
StringStream.flush();
|
||||
encodeULEB128(OutString.size(), OS);
|
||||
OS << OutString;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section) {
|
||||
writeStringRef(Section.Name, OS);
|
||||
if (Section.FunctionNames.size()) {
|
||||
encodeULEB128(wasm::WASM_NAMES_FUNCTION, OS);
|
||||
|
||||
std::string OutString;
|
||||
raw_string_ostream StringStream(OutString);
|
||||
|
||||
|
@ -131,8 +152,12 @@ int WasmWriter::writeNameSection(raw_ostream &OS,
|
|||
|
||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||
WasmYAML::CustomSection &Section) {
|
||||
if (Section.Name == "name") {
|
||||
writeNameSection(OS, Section);
|
||||
if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
|
||||
if (auto Err = writeSectionContent(OS, *S))
|
||||
return Err;
|
||||
} else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
|
||||
if (auto Err = writeSectionContent(OS, *S))
|
||||
return Err;
|
||||
} else {
|
||||
Section.Payload.writeAsBinary(OS);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue