diff options
author | Andy Wingo <wingo@igalia.com> | 2020-10-01 17:30:58 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-01 08:30:58 -0700 |
commit | ee87440dedb4335d5ca8ec25e86b36c27a5b3368 (patch) | |
tree | 522ec9766d5da42fd8b8ba6efa0c6e74fc370748 | |
parent | cd63243c5b3b2fa938f365edab30139f74549b51 (diff) | |
download | wabt-ee87440dedb4335d5ca8ec25e86b36c27a5b3368.tar.gz wabt-ee87440dedb4335d5ca8ec25e86b36c27a5b3368.tar.bz2 wabt-ee87440dedb4335d5ca8ec25e86b36c27a5b3368.zip |
Add --relocatable support for tables (#1549) (#1549)
We add relocations for table numbers on each place where we reify a
table number (call_indirect, table.get, table.set...), but only if
reference types are enabled.
Also, fix symbol table generation with unnamed definitions, to allow for
relocating references to anonymous functions or tables.
As tests, add variants of the relocations and symbol-tables dump tests,
with and without all features enabled. Enabling reference types causes
relocs to be emitted. We also add --details to the relocations dump
tests, so that we can see the target symbols for the relocations.
-rw-r--r-- | src/binary-reader-ir.cc | 19 | ||||
-rw-r--r-- | src/binary-reader-logging.cc | 10 | ||||
-rw-r--r-- | src/binary-reader-logging.h | 4 | ||||
-rw-r--r-- | src/binary-reader-nop.h | 6 | ||||
-rw-r--r-- | src/binary-reader-objdump.cc | 42 | ||||
-rw-r--r-- | src/binary-reader-objdump.h | 1 | ||||
-rw-r--r-- | src/binary-reader.cc | 7 | ||||
-rw-r--r-- | src/binary-reader.h | 4 | ||||
-rw-r--r-- | src/binary-writer.cc | 107 | ||||
-rw-r--r-- | src/common.cc | 1 | ||||
-rw-r--r-- | src/common.h | 6 | ||||
-rw-r--r-- | test/dump/relocations-all-features.txt | 90 | ||||
-rw-r--r-- | test/dump/relocations.txt | 46 | ||||
-rw-r--r-- | test/dump/symbol-tables-all-features.txt | 74 | ||||
-rw-r--r-- | test/dump/symbol-tables.txt | 50 |
15 files changed, 418 insertions, 49 deletions
diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc index 3678438e..58636e88 100644 --- a/src/binary-reader-ir.cc +++ b/src/binary-reader-ir.cc @@ -260,6 +260,8 @@ class BinaryReaderIR : public BinaryReaderNop { Index section_index) override; Result OnEventSymbol(Index index, uint32_t flags, string_view name, Index event_index) override; + Result OnTableSymbol(Index index, uint32_t flags, string_view name, + Index table_index) override; private: Location GetLocation() const; @@ -1349,6 +1351,23 @@ Result BinaryReaderIR::OnEventSymbol(Index index, uint32_t flags, return Result::Ok; } +Result BinaryReaderIR::OnTableSymbol(Index index, uint32_t flags, + string_view name, Index table_index) { + if (name.empty()) { + return Result::Ok; + } + if (table_index >= module_->tables.size()) { + PrintError("invalid table index: %" PRIindex, table_index); + return Result::Error; + } + Table* table = module_->tables[table_index]; + std::string dollar_name = + GetUniqueName(&module_->table_bindings, MakeDollarName(name)); + table->name = dollar_name; + module_->table_bindings.emplace(dollar_name, Binding(table_index)); + return Result::Ok; +} + } // end anonymous namespace Result ReadBinaryIr(const char* filename, diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc index b74dcf43..9c83a049 100644 --- a/src/binary-reader-logging.cc +++ b/src/binary-reader-logging.cc @@ -603,6 +603,16 @@ Result BinaryReaderLogging::OnEventSymbol(Index index, return reader_->OnEventSymbol(index, flags, name, event_index); } +Result BinaryReaderLogging::OnTableSymbol(Index index, + uint32_t flags, + string_view name, + Index table_index) { + LOGF("OnTableSymbol(name: " PRIstringview " flags: 0x%x index: %" PRIindex + ")\n", + WABT_PRINTF_STRING_VIEW_ARG(name), flags, table_index); + return reader_->OnTableSymbol(index, flags, name, table_index); +} + Result BinaryReaderLogging::OnSegmentInfo(Index index, string_view name, Address alignment, diff --git a/src/binary-reader-logging.h b/src/binary-reader-logging.h index a461572b..5936dad6 100644 --- a/src/binary-reader-logging.h +++ b/src/binary-reader-logging.h @@ -327,6 +327,10 @@ class BinaryReaderLogging : public BinaryReaderDelegate { uint32_t flags, string_view name, Index event_index) override; + Result OnTableSymbol(Index index, + uint32_t flags, + string_view name, + Index event_index) override; Result OnSegmentInfoCount(Index count) override; Result OnSegmentInfo(Index index, string_view name, diff --git a/src/binary-reader-nop.h b/src/binary-reader-nop.h index 492687bd..b49883b9 100644 --- a/src/binary-reader-nop.h +++ b/src/binary-reader-nop.h @@ -472,6 +472,12 @@ class BinaryReaderNop : public BinaryReaderDelegate { Index event_index) override { return Result::Ok; } + Result OnTableSymbol(Index index, + uint32_t flags, + string_view name, + Index table_index) override { + return Result::Ok; + } Result OnSegmentInfoCount(Index count) override { return Result::Ok; } Result OnSegmentInfo(Index index, string_view name, diff --git a/src/binary-reader-objdump.cc b/src/binary-reader-objdump.cc index 649358d6..0d3d1188 100644 --- a/src/binary-reader-objdump.cc +++ b/src/binary-reader-objdump.cc @@ -58,6 +58,7 @@ class BinaryReaderObjdumpBase : public BinaryReaderNop { string_view GetEventName(Index index) const; string_view GetSymbolName(Index index) const; string_view GetSegmentName(Index index) const; + string_view GetTableName(Index index) const; void PrintRelocation(const Reloc& reloc, Offset offset) const; Offset GetSectionStart(BinarySection section_code) const { return section_starts_[static_cast<size_t>(section_code)]; @@ -152,6 +153,10 @@ string_view BinaryReaderObjdumpBase::GetSegmentName(Index index) const { return objdump_state_->segment_names.Get(index); } +string_view BinaryReaderObjdumpBase::GetTableName(Index index) const { + return objdump_state_->table_names.Get(index); +} + string_view BinaryReaderObjdumpBase::GetSymbolName(Index symbol_index) const { if (symbol_index >= objdump_state_->symtab.size()) return "<illegal_symbol_index>"; @@ -167,6 +172,8 @@ string_view BinaryReaderObjdumpBase::GetSymbolName(Index symbol_index) const { return GetSectionName(sym.index); case SymbolType::Event: return GetEventName(sym.index); + case SymbolType::Table: + return GetTableName(sym.index); } WABT_UNREACHABLE; } @@ -283,6 +290,18 @@ class BinaryReaderObjdumpPrepass : public BinaryReaderObjdumpBase { return Result::Ok; } + Result OnTableSymbol(Index index, + uint32_t flags, + string_view name, + Index table_index) override { + if (!name.empty()) { + SetTableName(table_index, name); + } + objdump_state_->symtab[index] = {SymbolType::Table, name.to_string(), + table_index}; + return Result::Ok; + } + Result OnImportFunc(Index import_index, string_view module_name, string_view field_name, @@ -351,6 +370,7 @@ class BinaryReaderObjdumpPrepass : public BinaryReaderObjdumpBase { void SetFunctionName(Index index, string_view name); void SetGlobalName(Index index, string_view name); void SetEventName(Index index, string_view name); + void SetTableName(Index index, string_view name); void SetSegmentName(Index index, string_view name); }; @@ -367,6 +387,10 @@ void BinaryReaderObjdumpPrepass::SetEventName(Index index, string_view name) { objdump_state_->event_names.Set(index, name); } +void BinaryReaderObjdumpPrepass::SetTableName(Index index, string_view name) { + objdump_state_->table_names.Set(index, name); +} + void BinaryReaderObjdumpPrepass::SetSegmentName(Index index, string_view name) { objdump_state_->segment_names.Set(index, name); } @@ -891,6 +915,10 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase { uint32_t flags, string_view name, Index event_index) override; + Result OnTableSymbol(Index index, + uint32_t flags, + string_view name, + Index table_index) override; Result OnSegmentInfoCount(Index count) override; Result OnSegmentInfo(Index index, string_view name, @@ -1781,11 +1809,23 @@ Result BinaryReaderObjdump::OnEventSymbol(Index index, if (name.empty()) { name = GetEventName(event_index); } - PrintDetails(" - [%d] E <" PRIstringview "> event=%" PRIindex, index, + PrintDetails(" - %d: E <" PRIstringview "> event=%" PRIindex, index, WABT_PRINTF_STRING_VIEW_ARG(name), event_index); return PrintSymbolFlags(flags); } +Result BinaryReaderObjdump::OnTableSymbol(Index index, + uint32_t flags, + string_view name, + Index table_index) { + if (name.empty()) { + name = GetTableName(table_index); + } + PrintDetails(" - %d: T <" PRIstringview "> table=%" PRIindex, index, + WABT_PRINTF_STRING_VIEW_ARG(name), table_index); + return PrintSymbolFlags(flags); +} + Result BinaryReaderObjdump::OnSegmentInfoCount(Index count) { PrintDetails(" - segment info [count=%d]\n", count); return Result::Ok; diff --git a/src/binary-reader-objdump.h b/src/binary-reader-objdump.h index b1e24f81..b2874dac 100644 --- a/src/binary-reader-objdump.h +++ b/src/binary-reader-objdump.h @@ -73,6 +73,7 @@ struct ObjdumpState { ObjdumpNames section_names; ObjdumpNames event_names; ObjdumpNames segment_names; + ObjdumpNames table_names; std::vector<ObjdumpSymbol> symtab; }; diff --git a/src/binary-reader.cc b/src/binary-reader.cc index a28a0ad9..e44b8ca7 100644 --- a/src/binary-reader.cc +++ b/src/binary-reader.cc @@ -1784,6 +1784,7 @@ Result BinaryReader::ReadRelocSection(Offset section_size) { case RelocType::GlobalIndexI32: case RelocType::EventIndexLEB: case RelocType::TableIndexRelSLEB: + case RelocType::TableNumberLEB: break; default: @@ -1854,7 +1855,8 @@ Result BinaryReader::ReadLinkingSection(Offset section_size) { switch (sym_type) { case SymbolType::Function: case SymbolType::Global: - case SymbolType::Event: { + case SymbolType::Event: + case SymbolType::Table: { uint32_t index = 0; CHECK_RESULT(ReadU32Leb128(&index, "index")); if ((flags & WABT_SYMBOL_FLAG_UNDEFINED) == 0 || @@ -1870,6 +1872,9 @@ Result BinaryReader::ReadLinkingSection(Offset section_size) { case SymbolType::Event: CALLBACK(OnEventSymbol, i, flags, name, index); break; + case SymbolType::Table: + CALLBACK(OnTableSymbol, i, flags, name, index); + break; default: WABT_UNREACHABLE; } diff --git a/src/binary-reader.h b/src/binary-reader.h index 1c3fcf12..8e5e3dd6 100644 --- a/src/binary-reader.h +++ b/src/binary-reader.h @@ -401,6 +401,10 @@ class BinaryReaderDelegate { uint32_t flags, string_view name, Index event_index) = 0; + virtual Result OnTableSymbol(Index index, + uint32_t flags, + string_view name, + Index table_index) = 0; virtual Result OnSegmentInfoCount(Index count) = 0; virtual Result OnSegmentInfo(Index index, string_view name, diff --git a/src/binary-writer.cc b/src/binary-writer.cc index c628b108..b5732533 100644 --- a/src/binary-writer.cc +++ b/src/binary-writer.cc @@ -122,6 +122,10 @@ class Symbol { static const SymbolType type = SymbolType::Event; Index index; }; + struct Table { + static const SymbolType type = SymbolType::Table; + Index index; + }; private: SymbolType type_; @@ -133,6 +137,7 @@ class Symbol { Global global_; Section section_; Event event_; + Table table_; }; public: @@ -146,6 +151,8 @@ class Symbol { : type_(Section::type), name_(name), flags_(flags), section_(s) {} Symbol(const string_view& name, uint8_t flags, const Event& e) : type_(Event::type), name_(name), flags_(flags), event_(e) {} + Symbol(const string_view& name, uint8_t flags, const Table& t) + : type_(Table::type), name_(name), flags_(flags), table_(t) {} SymbolType type() const { return type_; } const string_view& name() const { return name_; } @@ -168,6 +175,7 @@ class Symbol { bool IsGlobal() const { return type() == Global::type; } bool IsSection() const { return type() == Section::type; } bool IsEvent() const { return type() == Event::type; } + bool IsTable() const { return type() == Table::type; } const Function& AsFunction() const { assert(IsFunction()); @@ -189,6 +197,10 @@ class Symbol { assert(IsEvent()); return event_; } + const Table& AsTable() const { + assert(IsTable()); + return table_; + } }; class SymbolTable { @@ -197,6 +209,7 @@ class SymbolTable { std::vector<Symbol> symbols_; std::vector<Index> functions_; + std::vector<Index> tables_; std::vector<Index> globals_; std::set<string_view> seen_names_; @@ -222,17 +235,17 @@ class SymbolTable { // name fabricated by wabt. name = string_view(); } else { - // Functions defined in this module without a name don't go in the symbol - // table. if (name.empty()) { - return Result::Ok; + // Definitions without a name are local. + flags |= uint8_t(SymbolBinding::Local); + flags |= uint8_t(SymbolVisibility::Hidden); + } else { + // Otherwise, strip the dollar off the name; a definition $foo is + // available for linking as "foo". + assert(name[0] == '$'); + name.remove_prefix(1); } - // Otherwise, strip the dollar off the name; a function $foo is available - // for linking as "foo". - assert(name[0] == '$'); - name.remove_prefix(1); - if (exported) { CHECK_RESULT(EnsureUnique(name)); flags |= uint8_t(SymbolVisibility::Hidden); @@ -248,6 +261,13 @@ class SymbolTable { return Result::Ok; }; + Index SymbolIndex(const std::vector<Index>& table, Index index) const { + // For well-formed modules, an index into (e.g.) functions_ will always be + // within bounds; the out-of-bounds case here is just to allow --relocatable + // to write known-invalid modules. + return index < table.size() ? table[index] : kInvalidIndex; + } + public: SymbolTable() {} @@ -276,8 +296,8 @@ class SymbolTable { } } - // We currently only create symbol table entries for function and global - // symbols. + // We currently only create symbol table entries for function, table, and + // global symbols. for (size_t i = 0; i < module->funcs.size(); ++i) { const Func* func = module->funcs[i]; bool imported = i < module->num_func_imports; @@ -286,6 +306,14 @@ class SymbolTable { Symbol::Function{Index(i)})); } + for (size_t i = 0; i < module->tables.size(); ++i) { + const Table* table = module->tables[i]; + bool imported = i < module->num_table_imports; + bool exported = exported_tables.count(i); + CHECK_RESULT(AddSymbol(&tables_, table->name, imported, exported, + Symbol::Table{Index(i)})); + } + for (size_t i = 0; i < module->globals.size(); ++i) { const Global* global = module->globals[i]; bool imported = i < module->num_global_imports; @@ -298,8 +326,15 @@ class SymbolTable { } const std::vector<Symbol>& symbols() const { return symbols_; } - Index FunctionSymbolIndex(Index index) const { return functions_[index]; } - Index GlobalSymbolIndex(Index index) const { return globals_[index]; } + Index FunctionSymbolIndex(Index index) const { + return SymbolIndex(functions_, index); + } + Index TableSymbolIndex(Index index) const { + return SymbolIndex(tables_, index); + } + Index GlobalSymbolIndex(Index index) const { + return SymbolIndex(globals_, index); + } }; class BinaryWriter { @@ -336,6 +371,7 @@ class BinaryWriter { void WriteS32Leb128WithReloc(int32_t value, const char* desc, RelocType reloc_type); + void WriteTableNumberWithReloc(Index table_number, const char* desc); template <typename T> void WriteLoadStoreExpr(const Func* func, const Expr* expr, const char* desc); void WriteExpr(const Func* func, const Expr* expr); @@ -513,6 +549,8 @@ Index BinaryWriter::GetSymbolIndex(RelocType reloc_type, Index index) { switch (reloc_type) { case RelocType::FuncIndexLEB: return symtab_.FunctionSymbolIndex(index); + case RelocType::TableNumberLEB: + return symtab_.TableSymbolIndex(index); case RelocType::GlobalIndexLEB: return symtab_.GlobalSymbolIndex(index); case RelocType::TypeIndexLEB: @@ -537,6 +575,12 @@ void BinaryWriter::AddReloc(RelocType reloc_type, Index index) { // Add a new relocation to the curent reloc section size_t offset = stream_->offset() - last_section_payload_offset_; Index symbol_index = GetSymbolIndex(reloc_type, index); + if (symbol_index == kInvalidIndex) { + // The file is invalid, for example a reference to function 42 where only 10 + // functions are defined. The user must have already passed --no-check, so + // no extra warning here is needed. + return; + } current_reloc_section_->relocations.emplace_back(reloc_type, offset, symbol_index); } @@ -563,6 +607,18 @@ void BinaryWriter::WriteS32Leb128WithReloc(int32_t value, } } +void BinaryWriter::WriteTableNumberWithReloc(Index value, + const char* desc) { + // Unless reference types are enabled, all references to tables refer to table + // 0, so no relocs need be emitted when making relocatable binaries. + if (options_.relocatable && options_.features.reference_types_enabled()) { + AddReloc(RelocType::TableNumberLEB, value); + WriteFixedS32Leb128(stream_, value, desc); + } else { + WriteS32Leb128(stream_, value, desc); + } +} + Index BinaryWriter::GetLocalIndex(const Func* func, const Var& var) { // func can be nullptr when using local.get/local.set/local.tee in an // init_expr. @@ -674,7 +730,7 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { module_->GetTableIndex(cast<CallIndirectExpr>(expr)->table); WriteOpcode(stream_, Opcode::CallIndirect); WriteU32Leb128WithReloc(sig_index, "signature index", RelocType::TypeIndexLEB); - WriteU32Leb128(stream_, table_index, "table index"); + WriteTableNumberWithReloc(table_index, "table index"); break; } case ExprType::ReturnCallIndirect: { @@ -684,7 +740,7 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { module_->GetTableIndex(cast<ReturnCallIndirectExpr>(expr)->table); WriteOpcode(stream_, Opcode::ReturnCallIndirect); WriteU32Leb128WithReloc(sig_index, "signature index", RelocType::TypeIndexLEB); - WriteU32Leb128(stream_, table_index, "table index"); + WriteTableNumberWithReloc(table_index, "table index"); break; } case ExprType::Compare: @@ -815,8 +871,8 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { Index dst = module_->GetTableIndex(copy_expr->dst_table); Index src = module_->GetTableIndex(copy_expr->src_table); WriteOpcode(stream_, Opcode::TableCopy); - WriteU32Leb128(stream_, dst, "table.copy dst_table"); - WriteU32Leb128(stream_, src, "table.copy src_table"); + WriteTableNumberWithReloc(dst, "table.copy dst_table"); + WriteTableNumberWithReloc(src, "table.copy src_table"); break; } case ExprType::ElemDrop: { @@ -833,42 +889,42 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) { module_->GetElemSegmentIndex(init_expr->segment_index); WriteOpcode(stream_, Opcode::TableInit); WriteU32Leb128(stream_, segment_index, "table.init segment"); - WriteU32Leb128(stream_, table_index, "table.init table"); + WriteTableNumberWithReloc(table_index, "table.init table"); break; } case ExprType::TableGet: { Index index = module_->GetTableIndex(cast<TableGetExpr>(expr)->var); WriteOpcode(stream_, Opcode::TableGet); - WriteU32Leb128(stream_, index, "table.get table index"); + WriteTableNumberWithReloc(index, "table.get table index"); break; } case ExprType::TableSet: { Index index = module_->GetTableIndex(cast<TableSetExpr>(expr)->var); WriteOpcode(stream_, Opcode::TableSet); - WriteU32Leb128(stream_, index, "table.set table index"); + WriteTableNumberWithReloc(index, "table.set table index"); break; } case ExprType::TableGrow: { Index index = module_->GetTableIndex(cast<TableGrowExpr>(expr)->var); WriteOpcode(stream_, Opcode::TableGrow); - WriteU32Leb128(stream_, index, "table.grow table index"); + WriteTableNumberWithReloc(index, "table.grow table index"); break; } case ExprType::TableSize: { Index index = module_->GetTableIndex(cast<TableSizeExpr>(expr)->var); WriteOpcode(stream_, Opcode::TableSize); - WriteU32Leb128(stream_, index, "table.size table index"); + WriteTableNumberWithReloc(index, "table.size table index"); break; } case ExprType::TableFill: { Index index = module_->GetTableIndex(cast<TableFillExpr>(expr)->var); WriteOpcode(stream_, Opcode::TableFill); - WriteU32Leb128(stream_, index, "table.fill table index"); + WriteTableNumberWithReloc(index, "table.fill table index"); break; } case ExprType::RefFunc: { @@ -1042,6 +1098,7 @@ void BinaryWriter::WriteRelocSection(const RelocSection* reloc_section) { case RelocType::GlobalIndexLEB: case RelocType::EventIndexLEB: case RelocType::TableIndexRelSLEB: + case RelocType::TableNumberLEB: break; default: fprintf(stderr, "warning: unsupported relocation type: %s\n", @@ -1094,6 +1151,12 @@ void BinaryWriter::WriteLinkingSection() { WriteStr(stream_, sym.name(), "event name", PrintChars::Yes); } break; + case SymbolType::Table: + WriteU32Leb128(stream_, sym.AsTable().index, "table index"); + if (sym.defined() || sym.explicit_name()) { + WriteStr(stream_, sym.name(), "table name", PrintChars::Yes); + } + break; } } EndSubsection(); diff --git a/src/common.cc b/src/common.cc index 875f71ae..0de9cf93 100644 --- a/src/common.cc +++ b/src/common.cc @@ -53,6 +53,7 @@ const char* g_reloc_type_name[] = { "R_WASM_MEMORY_ADDR_LEB64", "R_WASM_MEMORY_ADDR_SLEB64", "R_WASM_MEMORY_ADDR_I64", "R_WASM_MEMORY_ADDR_REL_SLEB64", "R_WASM_TABLE_INDEX_SLEB64", "R_WASM_TABLE_INDEX_I64", + "R_WASM_TABLE_NUMBER_LEB", }; WABT_STATIC_ASSERT(WABT_ARRAY_SIZE(g_reloc_type_name) == kRelocTypeCount); diff --git a/src/common.h b/src/common.h index 40f79f49..d900619d 100644 --- a/src/common.h +++ b/src/common.h @@ -294,9 +294,10 @@ enum class RelocType { MemoryAddressRelSLEB64 = 17, // Memory64: Like MemoryAddressRelSLEB TableIndexSLEB64 = 18, // Memory64: Like TableIndexSLEB TableIndexI64 = 19, // Memory64: Like TableIndexI32 + TableNumberLEB = 20, // e.g. Immediate of table.get First = FuncIndexLEB, - Last = TableIndexI64, + Last = TableNumberLEB, }; static const int kRelocTypeCount = WABT_ENUM_COUNT(RelocType); @@ -322,6 +323,7 @@ enum class SymbolType { Global = 2, Section = 3, Event = 4, + Table = 5, }; enum class ComdatType { @@ -422,6 +424,8 @@ static WABT_INLINE const char* GetSymbolTypeName(SymbolType type) { return "section"; case SymbolType::Event: return "event"; + case SymbolType::Table: + return "table"; default: return "<error_symbol_type>"; } diff --git a/test/dump/relocations-all-features.txt b/test/dump/relocations-all-features.txt new file mode 100644 index 00000000..19f940a4 --- /dev/null +++ b/test/dump/relocations-all-features.txt @@ -0,0 +1,90 @@ +;;; TOOL: run-objdump +;;; ARGS0: -r --enable-all +;;; ARGS1: --headers --details +(module + (type $t (func (param i32))) + (import "__extern" "foo" (func (param i32) (result i32))) + (import "__extern" "bar" (func (param i32) (param i32) (result i32))) + (global $g i32 (i32.const 0)) + (func $f (param i32) (result i32) + get_global 0 + call 2 + call 0 + i32.const 1234 + i32.const 0 + call_indirect (param i32) (param i32) (result i32)) + (export "f" (func $f)) + (table anyfunc (elem 1))) +(;; STDOUT ;;; + +relocations-all-features.wasm: file format wasm 0x1 + +Sections: + + Type start=0x0000000a end=0x0000001a (size=0x00000010) count: 3 + Import start=0x0000001c end=0x0000003b (size=0x0000001f) count: 2 + Function start=0x0000003d end=0x0000003f (size=0x00000002) count: 1 + Table start=0x00000041 end=0x00000046 (size=0x00000005) count: 1 + Global start=0x00000048 end=0x0000004e (size=0x00000006) count: 1 + Export start=0x00000050 end=0x00000055 (size=0x00000005) count: 1 + Elem start=0x00000057 end=0x0000005e (size=0x00000007) count: 1 + Code start=0x00000060 end=0x00000086 (size=0x00000026) count: 1 + Custom start=0x00000088 end=0x000000a9 (size=0x00000021) "linking" + Custom start=0x000000ab end=0x000000c7 (size=0x0000001c) "reloc.Code" + +Section Details: + +Type[3]: + - type[0] (i32) -> nil + - type[1] (i32) -> i32 + - type[2] (i32, i32) -> i32 +Import[2]: + - func[0] sig=1 <__extern.foo> <- __extern.foo + - func[1] sig=2 <__extern.bar> <- __extern.bar +Function[1]: + - func[2] sig=1 <f> +Table[1]: + - table[0] type=funcref initial=1 max=1 +Global[1]: + - global[0] i32 mutable=0 <g> - init i32=0 +Export[1]: + - func[2] <f> -> "f" +Elem[1]: + - segment[0] flags=0 table=0 count=1 - init i32=0 + - elem[0] = func[1] <__extern.bar> +Code[1]: + - func[2] size=36 <f> +Custom: + - name: "linking" + - symbol table [count=5] + - 0: F <__extern.foo> func=0 undefined binding=global vis=default + - 1: F <__extern.bar> func=1 undefined binding=global vis=default + - 2: F <f> func=2 exported no_strip binding=global vis=hidden + - 3: T <> table=0 binding=local vis=hidden + - 4: G <g> global=0 binding=global vis=default +Custom: + - name: "reloc.Code" + - relocations for section: 7 (Code) [5] + - R_WASM_GLOBAL_INDEX_LEB offset=0x000004(file=0x000064) symbol=4 <g> + - R_WASM_FUNCTION_INDEX_LEB offset=0x00000a(file=0x00006a) symbol=2 <f> + - R_WASM_FUNCTION_INDEX_LEB offset=0x000010(file=0x000070) symbol=0 <__extern.foo> + - R_WASM_TYPE_INDEX_LEB offset=0x00001b(file=0x00007b) type=2 + - R_WASM_TABLE_NUMBER_LEB offset=0x000020(file=0x000080) symbol=3 <> + +Code Disassembly: + +000062 func[2] <f>: + 000063: 23 80 80 80 80 00 | global.get 0 <g> + 000064: R_WASM_GLOBAL_INDEX_LEB 4 <g> + 000069: 10 82 80 80 80 00 | call 2 <f> + 00006a: R_WASM_FUNCTION_INDEX_LEB 2 <f> + 00006f: 10 80 80 80 80 00 | call 0 <__extern.foo> + 000070: R_WASM_FUNCTION_INDEX_LEB 0 <__extern.foo> + 000075: 41 d2 09 | i32.const 1234 + 000078: 41 00 | i32.const 0 + 00007a: 11 82 80 80 80 00 80 80 80 | call_indirect 2 0 + 000083: 80 00 | + 00007b: R_WASM_TYPE_INDEX_LEB 2 + 000085: 0b | end + 000080: R_WASM_TABLE_NUMBER_LEB 3 <> +;;; STDOUT ;;) diff --git a/test/dump/relocations.txt b/test/dump/relocations.txt index d856413a..1fb5e708 100644 --- a/test/dump/relocations.txt +++ b/test/dump/relocations.txt @@ -1,6 +1,6 @@ ;;; TOOL: run-objdump ;;; ARGS0: -r -;;; ARGS1: --headers +;;; ARGS1: --headers --details (module (type $t (func (param i32))) (import "__extern" "foo" (func (param i32) (result i32))) @@ -29,14 +29,52 @@ Sections: Export start=0x00000050 end=0x00000055 (size=0x00000005) count: 1 Elem start=0x00000057 end=0x0000005e (size=0x00000007) count: 1 Code start=0x00000060 end=0x00000082 (size=0x00000022) count: 1 - Custom start=0x00000084 end=0x000000a1 (size=0x0000001d) "linking" - Custom start=0x000000a3 end=0x000000bc (size=0x00000019) "reloc.Code" + Custom start=0x00000084 end=0x000000a5 (size=0x00000021) "linking" + Custom start=0x000000a7 end=0x000000c0 (size=0x00000019) "reloc.Code" + +Section Details: + +Type[3]: + - type[0] (i32) -> nil + - type[1] (i32) -> i32 + - type[2] (i32, i32) -> i32 +Import[2]: + - func[0] sig=1 <__extern.foo> <- __extern.foo + - func[1] sig=2 <__extern.bar> <- __extern.bar +Function[1]: + - func[2] sig=1 <f> +Table[1]: + - table[0] type=funcref initial=1 max=1 +Global[1]: + - global[0] i32 mutable=0 <g> - init i32=0 +Export[1]: + - func[2] <f> -> "f" +Elem[1]: + - segment[0] flags=0 table=0 count=1 - init i32=0 + - elem[0] = func[1] <__extern.bar> +Code[1]: + - func[2] size=32 <f> +Custom: + - name: "linking" + - symbol table [count=5] + - 0: F <__extern.foo> func=0 undefined binding=global vis=default + - 1: F <__extern.bar> func=1 undefined binding=global vis=default + - 2: F <f> func=2 exported no_strip binding=global vis=hidden + - 3: T <> table=0 binding=local vis=hidden + - 4: G <g> global=0 binding=global vis=default +Custom: + - name: "reloc.Code" + - relocations for section: 7 (Code) [4] + - R_WASM_GLOBAL_INDEX_LEB offset=0x000004(file=0x000064) symbol=4 <g> + - R_WASM_FUNCTION_INDEX_LEB offset=0x00000a(file=0x00006a) symbol=2 <f> + - R_WASM_FUNCTION_INDEX_LEB offset=0x000010(file=0x000070) symbol=0 <__extern.foo> + - R_WASM_TYPE_INDEX_LEB offset=0x00001b(file=0x00007b) type=2 Code Disassembly: 000062 func[2] <f>: 000063: 23 80 80 80 80 00 | global.get 0 <g> - 000064: R_WASM_GLOBAL_INDEX_LEB 3 <g> + 000064: R_WASM_GLOBAL_INDEX_LEB 4 <g> 000069: 10 82 80 80 80 00 | call 2 <f> 00006a: R_WASM_FUNCTION_INDEX_LEB 2 <f> 00006f: 10 80 80 80 80 00 | call 0 <__extern.foo> diff --git a/test/dump/symbol-tables-all-features.txt b/test/dump/symbol-tables-all-features.txt new file mode 100644 index 00000000..562c62a2 --- /dev/null +++ b/test/dump/symbol-tables-all-features.txt @@ -0,0 +1,74 @@ +;;; TOOL: run-objdump +;;; ARGS0: -r --enable-all +;;; ARGS1: -x +(module + (type (;0;) (func)) + (import "env" "b" (func (;0;) (type 0))) + (func $a (type 0) + call 0) + (func (type 0) + call 0) + (func $b (type 0) + (call_indirect (type 0) (i32.const 0)) + call 0) + (export "a" (func $a)) + (table $t 0 funcref)) +(;; STDOUT ;;; + +symbol-tables-all-features.wasm: file format wasm 0x1 + +Section Details: + +Type[1]: + - type[0] () -> nil +Import[1]: + - func[0] sig=0 <env.b> <- env.b +Function[3]: + - func[1] sig=0 <a> + - func[2] sig=0 + - func[3] sig=0 <b> +Table[1]: + - table[0] type=funcref initial=0 +Export[1]: + - func[1] <a> -> "a" +Code[3]: + - func[1] size=8 <a> + - func[2] size=8 + - func[3] size=21 <b> +Custom: + - name: "linking" + - symbol table [count=5] + - 0: F <env.b> func=0 undefined binding=global vis=default + - 1: F <a> func=1 exported no_strip binding=global vis=hidden + - 2: F <> func=2 binding=local vis=hidden + - 3: F <b> func=3 binding=global vis=default + - 4: T <t> table=0 binding=global vis=default +Custom: + - name: "reloc.Code" + - relocations for section: 5 (Code) [5] + - R_WASM_FUNCTION_INDEX_LEB offset=0x000004(file=0x000032) symbol=0 <env.b> + - R_WASM_FUNCTION_INDEX_LEB offset=0x00000d(file=0x00003b) symbol=0 <env.b> + - R_WASM_TYPE_INDEX_LEB offset=0x000018(file=0x000046) type=0 + - R_WASM_TABLE_NUMBER_LEB offset=0x00001d(file=0x00004b) symbol=4 <t> + - R_WASM_FUNCTION_INDEX_LEB offset=0x000023(file=0x000051) symbol=0 <env.b> + +Code Disassembly: + +000030 func[1] <a>: + 000031: 10 80 80 80 80 00 | call 0 <env.b> + 000032: R_WASM_FUNCTION_INDEX_LEB 0 <env.b> + 000037: 0b | end +000039 func[2]: + 00003a: 10 80 80 80 80 00 | call 0 <env.b> + 00003b: R_WASM_FUNCTION_INDEX_LEB 0 <env.b> + 000040: 0b | end +000042 func[3] <b>: + 000043: 41 00 | i32.const 0 + 000045: 11 80 80 80 80 00 80 80 80 | call_indirect 0 0 + 00004e: 80 00 | + 000046: R_WASM_TYPE_INDEX_LEB 0 + 000050: 10 80 80 80 80 00 | call 0 <env.b> + 00004b: R_WASM_TABLE_NUMBER_LEB 4 <t> + 000056: 0b | end + 000051: R_WASM_FUNCTION_INDEX_LEB 0 <env.b> +;;; STDOUT ;;) diff --git a/test/dump/symbol-tables.txt b/test/dump/symbol-tables.txt index 26385d4f..7d6555e2 100644 --- a/test/dump/symbol-tables.txt +++ b/test/dump/symbol-tables.txt @@ -9,8 +9,10 @@ (func (type 0) call 0) (func $b (type 0) + (call_indirect (type 0) (i32.const 0)) call 0) - (export "a" (func $a))) + (export "a" (func $a)) + (table $t 0 funcref)) (;; STDOUT ;;; symbol-tables.wasm: file format wasm 0x1 @@ -25,37 +27,45 @@ Function[3]: - func[1] sig=0 <a> - func[2] sig=0 - func[3] sig=0 <b> +Table[1]: + - table[0] type=funcref initial=0 Export[1]: - func[1] <a> -> "a" Code[3]: - func[1] size=8 <a> - func[2] size=8 - - func[3] size=8 <b> + - func[3] size=17 <b> Custom: - name: "linking" - - symbol table [count=3] + - symbol table [count=5] - 0: F <env.b> func=0 undefined binding=global vis=default - 1: F <a> func=1 exported no_strip binding=global vis=hidden - - 2: F <b> func=3 binding=global vis=default + - 2: F <> func=2 binding=local vis=hidden + - 3: F <b> func=3 binding=global vis=default + - 4: T <t> table=0 binding=global vis=default Custom: - name: "reloc.Code" - - relocations for section: 4 (Code) [3] - - R_WASM_FUNCTION_INDEX_LEB offset=0x000004(file=0x00002c) symbol=0 <env.b> - - R_WASM_FUNCTION_INDEX_LEB offset=0x00000d(file=0x000035) symbol=0 <env.b> - - R_WASM_FUNCTION_INDEX_LEB offset=0x000016(file=0x00003e) symbol=0 <env.b> + - relocations for section: 5 (Code) [4] + - R_WASM_FUNCTION_INDEX_LEB offset=0x000004(file=0x000032) symbol=0 <env.b> + - R_WASM_FUNCTION_INDEX_LEB offset=0x00000d(file=0x00003b) symbol=0 <env.b> + - R_WASM_TYPE_INDEX_LEB offset=0x000018(file=0x000046) type=0 + - R_WASM_FUNCTION_INDEX_LEB offset=0x00001f(file=0x00004d) symbol=0 <env.b> Code Disassembly: -00002a func[1] <a>: - 00002b: 10 80 80 80 80 00 | call 0 <env.b> - 00002c: R_WASM_FUNCTION_INDEX_LEB 0 <env.b> - 000031: 0b | end -000033 func[2]: - 000034: 10 80 80 80 80 00 | call 0 <env.b> - 000035: R_WASM_FUNCTION_INDEX_LEB 0 <env.b> - 00003a: 0b | end -00003c func[3] <b>: - 00003d: 10 80 80 80 80 00 | call 0 <env.b> - 00003e: R_WASM_FUNCTION_INDEX_LEB 0 <env.b> - 000043: 0b | end +000030 func[1] <a>: + 000031: 10 80 80 80 80 00 | call 0 <env.b> + 000032: R_WASM_FUNCTION_INDEX_LEB 0 <env.b> + 000037: 0b | end +000039 func[2]: + 00003a: 10 80 80 80 80 00 | call 0 <env.b> + 00003b: R_WASM_FUNCTION_INDEX_LEB 0 <env.b> + 000040: 0b | end +000042 func[3] <b>: + 000043: 41 00 | i32.const 0 + 000045: 11 80 80 80 80 00 00 | call_indirect 0 0 + 000046: R_WASM_TYPE_INDEX_LEB 0 + 00004c: 10 80 80 80 80 00 | call 0 <env.b> + 00004d: R_WASM_FUNCTION_INDEX_LEB 0 <env.b> + 000052: 0b | end ;;; STDOUT ;;) |