diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/tools/wasm-link.cc | 564 |
1 files changed, 276 insertions, 288 deletions
diff --git a/src/tools/wasm-link.cc b/src/tools/wasm-link.cc index 471b90c5..87050754 100644 --- a/src/tools/wasm-link.cc +++ b/src/tools/wasm-link.cc @@ -44,15 +44,6 @@ static const char* s_outfile = "a.wasm"; static std::vector<std::string> s_infiles; static std::unique_ptr<FileStream> s_log_stream; -struct Context { - WABT_DISALLOW_COPY_AND_ASSIGN(Context); - Context() {} - - MemoryStream stream; - std::vector<std::unique_ptr<LinkerInputBinary>> inputs; - ssize_t current_section_payload_offset = 0; -}; - static void ParseOptions(int argc, char** argv) { OptionParser parser("wasm-link", s_description); @@ -123,11 +114,11 @@ bool LinkerInputBinary::IsValidFunctionIndex(Index index) { Index LinkerInputBinary::RelocateFuncIndex(Index function_index) { Index offset; if (!IsFunctionImport(function_index)) { - /* locally declared function call */ + // locally declared function call. offset = function_index_offset; LOG_DEBUG("func reloc %d + %d\n", function_index, offset); } else { - /* imported function call */ + // imported function call. FunctionImport* import = &function_imports[function_index]; if (!import->active) { function_index = import->foreign_index; @@ -158,7 +149,7 @@ Index LinkerInputBinary::RelocateGlobalIndex(Index global_index) { return global_index + offset; } -static void apply_relocation(Section* section, Reloc* r) { +static void ApplyRelocation(const Section* section, const Reloc* r) { LinkerInputBinary* binary = section->binary; uint8_t* section_data = &binary->data[section->offset]; size_t section_size = section->size; @@ -189,44 +180,83 @@ static void apply_relocation(Section* section, Reloc* r) { new_value); } -static void apply_relocations(Section* section) { +static void ApplyRelocations(const Section* section) { if (!section->relocations.size()) return; - LOG_DEBUG("apply_relocations: %s\n", GetSectionName(section->section_code)); - - /* Perform relocations in-place */ - for (Reloc& reloc: section->relocations) { - apply_relocation(section, &reloc); - } -} + LOG_DEBUG("ApplyRelocations: %s\n", GetSectionName(section->section_code)); + + // Perform relocations in-place. + for (const auto& reloc: section->relocations) { + ApplyRelocation(section, &reloc); + } +} + +class Linker { + public: + WABT_DISALLOW_COPY_AND_ASSIGN(Linker); + Linker() = default; + + void AppendBinary(LinkerInputBinary* binary) { inputs_.emplace_back(binary); } + Result PerformLink(); + + private: + typedef std::pair<Offset, Offset> Fixup; + Fixup WriteUnknownSize(); + void FixupSize(Fixup); + + void WriteSectionPayload(Section* sec); + void WriteTableSection(const SectionPtrVector& sections); + void WriteExportSection(); + void WriteElemSection(const SectionPtrVector& sections); + void WriteMemorySection(const SectionPtrVector& sections); + void WriteFunctionImport(const FunctionImport& import, Index offset); + void WriteGlobalImport(const GlobalImport& import); + void WriteImportSection(); + void WriteFunctionSection(const SectionPtrVector& sections, + Index total_count); + void WriteDataSegment(const DataSegment& segment, Address offset); + void WriteDataSection(const SectionPtrVector& sections, Index total_count); + void WriteNamesSection(); + void WriteRelocSection(BinarySection section_code, + const SectionPtrVector& sections); + bool WriteCombinedSection(BinarySection section_code, + const SectionPtrVector& sections); + void ResolveSymbols(); + void CalculateRelocOffsets(); + void WriteBinary(); + void DumpRelocOffsets(); + + MemoryStream stream_; + std::vector<std::unique_ptr<LinkerInputBinary>> inputs_; + ssize_t current_section_payload_offset_ = 0; +}; -static void write_section_payload(Context* ctx, Section* sec) { - assert(ctx->current_section_payload_offset != -1); +void Linker::WriteSectionPayload(Section* sec) { + assert(current_section_payload_offset_ != -1); sec->output_payload_offset = - ctx->stream.offset() - ctx->current_section_payload_offset; + stream_.offset() - current_section_payload_offset_; uint8_t* payload = &sec->binary->data[sec->payload_offset]; - ctx->stream.WriteData(payload, sec->payload_size, "section content"); + stream_.WriteData(payload, sec->payload_size, "section content"); } -#define WRITE_UNKNOWN_SIZE(STREAM) \ - { \ - Offset fixup_offset = (STREAM)->offset(); \ - WriteFixedU32Leb128(STREAM, 0, "unknown size"); \ - ctx->current_section_payload_offset = (STREAM)->offset(); \ - Offset start = (STREAM)->offset(); +Linker::Fixup Linker::WriteUnknownSize() { + Offset fixup_offset = stream_.offset(); + WriteFixedU32Leb128(&stream_, 0, "unknown size"); + current_section_payload_offset_ = stream_.offset(); + return std::make_pair(fixup_offset, current_section_payload_offset_); +} -#define FIXUP_SIZE(STREAM) \ - WriteFixedU32Leb128At(STREAM, fixup_offset, (STREAM)->offset() - start, \ - "fixup size"); \ - } +void Linker::FixupSize(Fixup fixup) { + WriteFixedU32Leb128At(&stream_, fixup.first, stream_.offset() - fixup.second, + "fixup size"); +} -static void write_table_section(Context* ctx, - const SectionPtrVector& sections) { - /* Total section size includes the element count leb128 which is - * always 1 in the current spec */ +void Linker::WriteTableSection(const SectionPtrVector& sections) { + // Total section size includes the element count leb128 which is always 1 in + // the current spec. Index table_count = 1; uint32_t flags = WABT_BINARY_LIMITS_HAS_MAX_FLAG; Index elem_count = 0; @@ -235,30 +265,28 @@ static void write_table_section(Context* ctx, elem_count += section->binary->table_elem_count; } - Stream* stream = &ctx->stream; - WRITE_UNKNOWN_SIZE(stream); - WriteU32Leb128(stream, table_count, "table count"); - WriteType(stream, Type::Anyfunc); - WriteU32Leb128(stream, flags, "table elem flags"); - WriteU32Leb128(stream, elem_count, "table initial length"); - WriteU32Leb128(stream, elem_count, "table max length"); - FIXUP_SIZE(stream); + auto fixup = WriteUnknownSize(); + WriteU32Leb128(&stream_, table_count, "table count"); + WriteType(&stream_, Type::Anyfunc); + WriteU32Leb128(&stream_, flags, "table elem flags"); + WriteU32Leb128(&stream_, elem_count, "table initial length"); + WriteU32Leb128(&stream_, elem_count, "table max length"); + FixupSize(fixup); } -static void write_export_section(Context* ctx) { +void Linker::WriteExportSection() { Index total_exports = 0; - for (const std::unique_ptr<LinkerInputBinary>& binary: ctx->inputs) { + for (const std::unique_ptr<LinkerInputBinary>& binary : inputs_) { total_exports += binary->exports.size(); } - Stream* stream = &ctx->stream; - WRITE_UNKNOWN_SIZE(stream); - WriteU32Leb128(stream, total_exports, "export count"); + auto fixup = WriteUnknownSize(); + WriteU32Leb128(&stream_, total_exports, "export count"); - for (const std::unique_ptr<LinkerInputBinary>& binary : ctx->inputs) { + for (const std::unique_ptr<LinkerInputBinary>& binary : inputs_) { for (const Export& export_ : binary->exports) { - WriteStr(stream, export_.name, "export name"); - stream->WriteU8Enum(export_.kind, "export kind"); + WriteStr(&stream_, export_.name, "export name"); + stream_.WriteU8Enum(export_.kind, "export kind"); Index index = export_.index; switch (export_.kind) { case ExternalKind::Func: @@ -269,121 +297,104 @@ static void write_export_section(Context* ctx) { static_cast<int>(export_.kind)); break; } - WriteU32Leb128(stream, index, "export index"); + WriteU32Leb128(&stream_, index, "export index"); } } - FIXUP_SIZE(stream); + + FixupSize(fixup); } -static void write_elem_section(Context* ctx, - const SectionPtrVector& sections) { - Stream* stream = &ctx->stream; - WRITE_UNKNOWN_SIZE(stream); +void Linker::WriteElemSection(const SectionPtrVector& sections) { + auto fixup = WriteUnknownSize(); Index total_elem_count = 0; for (Section* section : sections) { total_elem_count += section->binary->table_elem_count; } - WriteU32Leb128(stream, 1, "segment count"); - WriteU32Leb128(stream, 0, "table index"); - WriteOpcode(&ctx->stream, Opcode::I32Const); - WriteI32Leb128(&ctx->stream, 0, "elem init literal"); - WriteOpcode(&ctx->stream, Opcode::End); - WriteU32Leb128(stream, total_elem_count, "num elements"); + WriteU32Leb128(&stream_, 1, "segment count"); + WriteU32Leb128(&stream_, 0, "table index"); + WriteOpcode(&stream_, Opcode::I32Const); + WriteI32Leb128(&stream_, 0, "elem init literal"); + WriteOpcode(&stream_, Opcode::End); + WriteU32Leb128(&stream_, total_elem_count, "num elements"); - ctx->current_section_payload_offset = stream->offset(); + current_section_payload_offset_ = stream_.offset(); for (Section* section : sections) { - apply_relocations(section); - write_section_payload(ctx, section); + ApplyRelocations(section); + WriteSectionPayload(section); } - FIXUP_SIZE(stream); + FixupSize(fixup); } -static void write_memory_section(Context* ctx, - const SectionPtrVector& sections) { - Stream* stream = &ctx->stream; - WRITE_UNKNOWN_SIZE(stream); +void Linker::WriteMemorySection(const SectionPtrVector& sections) { + auto fixup = WriteUnknownSize(); - WriteU32Leb128(stream, 1, "memory count"); + WriteU32Leb128(&stream_, 1, "memory count"); Limits limits; ZeroMemory(limits); limits.has_max = true; - for (size_t i = 0; i < sections.size(); i++) { - Section* sec = sections[i]; - limits.initial += sec->data.memory_limits.initial; + for (Section* section: sections) { + limits.initial += section->data.memory_limits.initial; } limits.max = limits.initial; - WriteLimits(stream, &limits); + WriteLimits(&stream_, &limits); - FIXUP_SIZE(stream); + FixupSize(fixup); } -static void write_function_import(Context* ctx, - FunctionImport* import, - Index offset) { - WriteStr(&ctx->stream, import->module_name, "import module name"); - WriteStr(&ctx->stream, import->name, "import field name"); - ctx->stream.WriteU8Enum(ExternalKind::Func, "import kind"); - WriteU32Leb128(&ctx->stream, import->sig_index + offset, - "import signature index"); +void Linker::WriteFunctionImport(const FunctionImport& import, Index offset) { + WriteStr(&stream_, import.module_name, "import module name"); + WriteStr(&stream_, import.name, "import field name"); + stream_.WriteU8Enum(ExternalKind::Func, "import kind"); + WriteU32Leb128(&stream_, import.sig_index + offset, "import signature index"); } -static void write_global_import(Context* ctx, GlobalImport* import) { - WriteStr(&ctx->stream, import->module_name, "import module name"); - WriteStr(&ctx->stream, import->name, "import field name"); - ctx->stream.WriteU8Enum(ExternalKind::Global, "import kind"); - WriteType(&ctx->stream, import->type); - ctx->stream.WriteU8(import->mutable_, "global mutability"); +void Linker::WriteGlobalImport(const GlobalImport& import) { + WriteStr(&stream_, import.module_name, "import module name"); + WriteStr(&stream_, import.name, "import field name"); + stream_.WriteU8Enum(ExternalKind::Global, "import kind"); + WriteType(&stream_, import.type); + stream_.WriteU8(import.mutable_, "global mutability"); } -static void write_import_section(Context* ctx) { +void Linker::WriteImportSection() { Index num_imports = 0; - for (size_t i = 0; i < ctx->inputs.size(); i++) { - LinkerInputBinary* binary = ctx->inputs[i].get(); - std::vector<FunctionImport>& imports = binary->function_imports; - for (size_t j = 0; j < imports.size(); j++) { - FunctionImport* import = &imports[j]; - if (import->active) + for (const auto& binary: inputs_) { + for (const auto& import : binary->function_imports) { + if (import.active) num_imports++; } num_imports += binary->global_imports.size(); } - WRITE_UNKNOWN_SIZE(&ctx->stream); - WriteU32Leb128(&ctx->stream, num_imports, "num imports"); + auto fixup = WriteUnknownSize(); + WriteU32Leb128(&stream_, num_imports, "num imports"); - for (size_t i = 0; i < ctx->inputs.size(); i++) { - LinkerInputBinary* binary = ctx->inputs[i].get(); - std::vector<FunctionImport>& imports = binary->function_imports; - for (size_t j = 0; j < imports.size(); j++) { - FunctionImport* import = &imports[j]; - if (import->active) - write_function_import(ctx, import, binary->type_index_offset); + for (const auto& binary: inputs_) { + for (const auto& function_import : binary->function_imports) { + if (function_import.active) + WriteFunctionImport(function_import, binary->type_index_offset); } - std::vector<GlobalImport>& globals = binary->global_imports; - for (size_t j = 0; j < globals.size(); j++) { - write_global_import(ctx, &globals[j]); + for (const auto& global_import : binary->global_imports) { + WriteGlobalImport(global_import); } } - FIXUP_SIZE(&ctx->stream); + FixupSize(fixup); } -static void write_function_section(Context* ctx, - const SectionPtrVector& sections, - Index total_count) { - Stream* stream = &ctx->stream; - WRITE_UNKNOWN_SIZE(stream); +void Linker::WriteFunctionSection(const SectionPtrVector& sections, + Index total_count) { + auto fixup = WriteUnknownSize(); - WriteU32Leb128(stream, total_count, "function count"); + WriteU32Leb128(&stream_, total_count, "function count"); - for (size_t i = 0; i < sections.size(); i++) { - Section* sec = sections[i]; + for (Section* sec: sections) { Index count = sec->count; Offset input_offset = 0; Index sig_index = 0; @@ -392,47 +403,42 @@ static void write_function_section(Context* ctx, &sec->binary->data[sec->payload_offset + sec->payload_size]; while (count--) { input_offset += ReadU32Leb128(start + input_offset, end, &sig_index); - WriteU32Leb128(stream, sec->binary->RelocateTypeIndex(sig_index), "sig"); + WriteU32Leb128(&stream_, sec->binary->RelocateTypeIndex(sig_index), + "sig"); } } - FIXUP_SIZE(stream); + FixupSize(fixup); } -static void write_data_segment(Stream* stream, - const DataSegment& segment, - Address offset) { +void Linker::WriteDataSegment(const DataSegment& segment, Address offset) { assert(segment.memory_index == 0); - WriteU32Leb128(stream, segment.memory_index, "memory index"); - WriteOpcode(stream, Opcode::I32Const); - WriteU32Leb128(stream, segment.offset + offset, "offset"); - WriteOpcode(stream, Opcode::End); - WriteU32Leb128(stream, segment.size, "segment size"); - stream->WriteData(segment.data, segment.size, "segment data"); -} - -static void write_data_section(Context* ctx, - const SectionPtrVector& sections, - Index total_count) { - Stream* stream = &ctx->stream; - WRITE_UNKNOWN_SIZE(stream); - - WriteU32Leb128(stream, total_count, "data segment count"); - for (size_t i = 0; i < sections.size(); i++) { - Section* sec = sections[i]; - for (size_t j = 0; j < sec->data.data_segments->size(); j++) { - const DataSegment& segment = (*sec->data.data_segments)[j]; - write_data_segment(stream, segment, - sec->binary->memory_page_offset * WABT_PAGE_SIZE); + WriteU32Leb128(&stream_, segment.memory_index, "memory index"); + WriteOpcode(&stream_, Opcode::I32Const); + WriteU32Leb128(&stream_, segment.offset + offset, "offset"); + WriteOpcode(&stream_, Opcode::End); + WriteU32Leb128(&stream_, segment.size, "segment size"); + stream_.WriteData(segment.data, segment.size, "segment data"); +} + +void Linker::WriteDataSection(const SectionPtrVector& sections, + Index total_count) { + auto fixup = WriteUnknownSize(); + + WriteU32Leb128(&stream_, total_count, "data segment count"); + for (const Section* sec: sections) { + for (const auto& segment: *sec->data.data_segments) { + WriteDataSegment(segment, + sec->binary->memory_page_offset * WABT_PAGE_SIZE); } } - FIXUP_SIZE(stream); + FixupSize(fixup); } -static void write_names_section(Context* ctx) { +void Linker::WriteNamesSection() { Index total_count = 0; - for (const std::unique_ptr<LinkerInputBinary>& binary: ctx->inputs) { + for (const auto& binary : inputs_) { for (size_t i = 0; i < binary->debug_names.size(); i++) { if (binary->debug_names[i].empty()) continue; @@ -445,70 +451,65 @@ static void write_names_section(Context* ctx) { if (!total_count) return; - Stream* stream = &ctx->stream; - stream->WriteU8Enum(BinarySection::Custom, "section code"); - WRITE_UNKNOWN_SIZE(stream); - WriteStr(stream, "name", "custom section name"); + stream_.WriteU8Enum(BinarySection::Custom, "section code"); + auto fixup_section = WriteUnknownSize(); + WriteStr(&stream_, "name", "custom section name"); - stream->WriteU8Enum(NameSectionSubsection::Function, "subsection code"); - WRITE_UNKNOWN_SIZE(stream); - WriteU32Leb128(stream, total_count, "element count"); + stream_.WriteU8Enum(NameSectionSubsection::Function, "subsection code"); + auto fixup_subsection = WriteUnknownSize(); + WriteU32Leb128(&stream_, total_count, "element count"); - // Write import names - for (const std::unique_ptr<LinkerInputBinary>& binary: ctx->inputs) { + // Write import names. + for (const auto& binary : inputs_) { for (size_t i = 0; i < binary->debug_names.size(); i++) { if (binary->debug_names[i].empty() || !binary->IsFunctionImport(i)) continue; if (binary->IsInactiveFunctionImport(i)) continue; - WriteU32Leb128(stream, binary->RelocateFuncIndex(i), "function index"); - WriteStr(stream, binary->debug_names[i], "function name"); + WriteU32Leb128(&stream_, binary->RelocateFuncIndex(i), "function index"); + WriteStr(&stream_, binary->debug_names[i], "function name"); } } - // Write non-import names - for (const std::unique_ptr<LinkerInputBinary>& binary: ctx->inputs) { + // Write non-import names. + for (const auto& binary : inputs_) { for (size_t i = 0; i < binary->debug_names.size(); i++) { if (binary->debug_names[i].empty() || binary->IsFunctionImport(i)) continue; - WriteU32Leb128(stream, binary->RelocateFuncIndex(i), "function index"); - WriteStr(stream, binary->debug_names[i], "function name"); + WriteU32Leb128(&stream_, binary->RelocateFuncIndex(i), "function index"); + WriteStr(&stream_, binary->debug_names[i], "function name"); } } - FIXUP_SIZE(stream); - - FIXUP_SIZE(stream); + FixupSize(fixup_subsection); + FixupSize(fixup_section); } -static void write_reloc_section(Context* ctx, - BinarySection section_code, - const SectionPtrVector& sections) { +void Linker::WriteRelocSection(BinarySection section_code, + const SectionPtrVector& sections) { Index total_relocs = 0; - /* First pass to know total reloc count */ + // First pass to know total reloc count. for (Section* sec: sections) total_relocs += sec->relocations.size(); if (!total_relocs) return; - char section_name[128]; - snprintf(section_name, sizeof(section_name), "%s.%s", - WABT_BINARY_SECTION_RELOC, GetSectionName(section_code)); + std::string section_name = StringPrintf("%s.%s", WABT_BINARY_SECTION_RELOC, + GetSectionName(section_code)); - Stream* stream = &ctx->stream; - stream->WriteU8Enum(BinarySection::Custom, "section code"); - WRITE_UNKNOWN_SIZE(stream); - WriteStr(stream, section_name, "reloc section name"); - WriteU32Leb128Enum(&ctx->stream, section_code, "reloc section"); - WriteU32Leb128(&ctx->stream, total_relocs, "num relocs"); + stream_.WriteU8Enum(BinarySection::Custom, "section code"); + auto fixup = WriteUnknownSize(); + WriteStr(&stream_, section_name, "reloc section name"); + WriteU32Leb128Enum(&stream_, section_code, "reloc section"); + WriteU32Leb128(&stream_, total_relocs, "num relocs"); for (Section* sec: sections) { for (const Reloc& reloc: sec->relocations) { - WriteU32Leb128Enum(&ctx->stream, reloc.type, "reloc type"); + WriteU32Leb128Enum(&stream_, reloc.type, "reloc type"); Offset new_offset = reloc.offset + sec->output_payload_offset; - WriteU32Leb128(&ctx->stream, new_offset, "reloc offset"); + WriteU32Leb128(&stream_, new_offset, "reloc offset"); Index relocated_index; switch (reloc.type) { case RelocType::FuncIndexLEB: @@ -526,16 +527,15 @@ static void write_reloc_section(Context* ctx, GetRelocTypeName(reloc.type)); break; } - WriteU32Leb128(&ctx->stream, relocated_index, "reloc index"); + WriteU32Leb128(&stream_, relocated_index, "reloc index"); } } - FIXUP_SIZE(stream); + FixupSize(fixup); } -static bool write_combined_section(Context* ctx, - BinarySection section_code, - const SectionPtrVector& sections) { +bool Linker::WriteCombinedSection(BinarySection section_code, + const SectionPtrVector& sections) { if (!sections.size()) return false; @@ -547,49 +547,48 @@ static bool write_combined_section(Context* ctx, Index total_count = 0; Index total_size = 0; - /* Sum section size and element count */ - for (Section* sec: sections) { + // Sum section size and element count. + for (Section* sec : sections) { total_size += sec->payload_size; total_count += sec->count; } - ctx->stream.WriteU8Enum(section_code, "section code"); - ctx->current_section_payload_offset = -1; + stream_.WriteU8Enum(section_code, "section code"); + current_section_payload_offset_ = -1; switch (section_code) { case BinarySection::Import: - write_import_section(ctx); + WriteImportSection(); break; case BinarySection::Function: - write_function_section(ctx, sections, total_count); + WriteFunctionSection(sections, total_count); break; case BinarySection::Table: - write_table_section(ctx, sections); + WriteTableSection(sections); break; case BinarySection::Export: - write_export_section(ctx); + WriteExportSection(); break; case BinarySection::Elem: - write_elem_section(ctx, sections); + WriteElemSection(sections); break; case BinarySection::Memory: - write_memory_section(ctx, sections); + WriteMemorySection(sections); break; case BinarySection::Data: - write_data_section(ctx, sections, total_count); + WriteDataSection(sections, total_count); break; default: { - /* Total section size includes the element count leb128. */ + // Total section size includes the element count leb128. total_size += U32Leb128Length(total_count); - /* Write section to stream */ - Stream* stream = &ctx->stream; - WriteU32Leb128(stream, total_size, "section size"); - WriteU32Leb128(stream, total_count, "element count"); - ctx->current_section_payload_offset = ctx->stream.offset(); - for (Section* sec: sections) { - apply_relocations(sec); - write_section_payload(ctx, sec); + // Write section to stream. + WriteU32Leb128(&stream_, total_size, "section size"); + WriteU32Leb128(&stream_, total_count, "element count"); + current_section_payload_offset_ = stream_.offset(); + for (Section* sec : sections) { + ApplyRelocations(sec); + WriteSectionPayload(sec); } } } @@ -605,50 +604,44 @@ struct ExportInfo { LinkerInputBinary* binary; }; -static void resolve_symbols(Context* ctx) { - /* Create hashmap of all exported symbols from all inputs */ +void Linker::ResolveSymbols() { + // Create hashmap of all exported symbols from all inputs. BindingHash export_map; std::vector<ExportInfo> export_list; - for (size_t i = 0; i < ctx->inputs.size(); i++) { - LinkerInputBinary* binary = ctx->inputs[i].get(); - for (size_t j = 0; j < binary->exports.size(); j++) { - Export* export_ = &binary->exports[j]; - export_list.emplace_back(export_, binary); + for (const auto& binary: inputs_) { + for (auto& export_ : binary->exports) { + export_list.emplace_back(&export_, binary.get()); - /* TODO(sbc): Handle duplicate names */ - export_map.emplace(export_->name, Binding(export_list.size() - 1)); + // TODO(sbc): Handle duplicate names. + export_map.emplace(export_.name, Binding(export_list.size() - 1)); } } - /* - * Iterate through all imported functions resolving them against exported - * ones. - */ - for (size_t i = 0; i < ctx->inputs.size(); i++) { - LinkerInputBinary* binary = ctx->inputs[i].get(); - for (size_t j = 0; j < binary->function_imports.size(); j++) { - FunctionImport* import = &binary->function_imports[j]; - int export_index = export_map.FindIndex(import->name); - if (export_index == -1) { + // Iterate through all imported functions resolving them against exported + // ones. + for (auto& binary: inputs_) { + for (auto& import: binary->function_imports) { + Index export_index = export_map.FindIndex(import.name); + if (export_index == kInvalidIndex) { if (!s_relocatable) - WABT_FATAL("undefined symbol: %s\n", import->name.c_str()); + WABT_FATAL("undefined symbol: %s\n", import.name.c_str()); continue; } - /* We found the symbol exported by another module */ - ExportInfo* export_info = &export_list[export_index]; + // We found the symbol exported by another module. + const ExportInfo& export_info = export_list[export_index]; - /* TODO(sbc): verify the foriegn function has the correct signature */ - import->active = false; - import->foreign_binary = export_info->binary; - import->foreign_index = export_info->export_->index; + // TODO(sbc): verify the foriegn function has the correct signature. + import.active = false; + import.foreign_binary = export_info.binary; + import.foreign_index = export_info.export_->index; binary->active_function_imports--; } } } -static void calculate_reloc_offsets(Context* ctx) { +void Linker::CalculateRelocOffsets() { Index memory_page_offset = 0; Index type_count = 0; Index global_count = 0; @@ -656,11 +649,11 @@ static void calculate_reloc_offsets(Context* ctx) { Index table_elem_count = 0; Index total_function_imports = 0; Index total_global_imports = 0; - for (size_t i = 0; i < ctx->inputs.size(); i++) { - LinkerInputBinary* binary = ctx->inputs[i].get(); - /* The imported_function_index_offset is the sum of all the function - * imports from objects that precede this one. i.e. the current running - * total */ + + for (auto& binary : inputs_) { + // The imported_function_index_offset is the sum of all the function + // imports from objects that precede this one. i.e. the current running + // total. binary->imported_function_index_offset = total_function_imports; binary->imported_global_index_offset = total_global_imports; binary->memory_page_offset = memory_page_offset; @@ -671,7 +664,7 @@ static void calculate_reloc_offsets(Context* ctx) { delta++; } else { binary->function_imports[i].relocated_function_index = - total_function_imports + i - delta; + total_function_imports + i - delta; } } @@ -680,12 +673,10 @@ static void calculate_reloc_offsets(Context* ctx) { total_global_imports += binary->global_imports.size(); } - for (size_t i = 0; i < ctx->inputs.size(); i++) { - LinkerInputBinary* binary = ctx->inputs[i].get(); + for (auto& binary : inputs_) { binary->table_index_offset = table_elem_count; table_elem_count += binary->table_elem_count; - for (size_t j = 0; j < binary->sections.size(); j++) { - Section* sec = binary->sections[j].get(); + for (auto& sec : binary->sections) { switch (sec->section_code) { case BinarySection::Type: binary->type_index_offset = type_count; @@ -710,69 +701,66 @@ static void calculate_reloc_offsets(Context* ctx) { } } -static void write_binary(Context* ctx) { - /* Find all the sections of each type */ +void Linker::WriteBinary() { + // Find all the sections of each type. SectionPtrVector sections[kBinarySectionCount]; - for (size_t j = 0; j < ctx->inputs.size(); j++) { - LinkerInputBinary* binary = ctx->inputs[j].get(); - for (size_t i = 0; i < binary->sections.size(); i++) { - Section* s = binary->sections[i].get(); - SectionPtrVector& sec_list = sections[static_cast<int>(s->section_code)]; - sec_list.push_back(s); + for (auto& binary : inputs_) { + for (auto& sec : binary->sections) { + SectionPtrVector& sec_list = + sections[static_cast<int>(sec->section_code)]; + sec_list.push_back(sec.get()); } } - /* Write the final binary */ - ctx->stream.WriteU32(WABT_BINARY_MAGIC, "WABT_BINARY_MAGIC"); - ctx->stream.WriteU32(WABT_BINARY_VERSION, "WABT_BINARY_VERSION"); + // Write the final binary. + stream_.WriteU32(WABT_BINARY_MAGIC, "WABT_BINARY_MAGIC"); + stream_.WriteU32(WABT_BINARY_VERSION, "WABT_BINARY_VERSION"); - /* Write known sections first */ + // Write known sections first. for (size_t i = FIRST_KNOWN_SECTION; i < kBinarySectionCount; i++) { - write_combined_section(ctx, static_cast<BinarySection>(i), sections[i]); + WriteCombinedSection(static_cast<BinarySection>(i), sections[i]); } - write_names_section(ctx); + WriteNamesSection(); - /* Generate a new set of reloction sections */ + // Generate a new set of reloction sections. for (size_t i = FIRST_KNOWN_SECTION; i < kBinarySectionCount; i++) { - write_reloc_section(ctx, static_cast<BinarySection>(i), sections[i]); + WriteRelocSection(static_cast<BinarySection>(i), sections[i]); } } -static void dump_reloc_offsets(Context* ctx) { +void Linker::DumpRelocOffsets() { if (s_debug) { - for (size_t i = 0; i < ctx->inputs.size(); i++) { - LinkerInputBinary* binary = ctx->inputs[i].get(); + for (const auto& binary : inputs_) { LOG_DEBUG("Relocation info for: %s\n", binary->filename); - LOG_DEBUG(" - type index offset : %d\n", - binary->type_index_offset); + LOG_DEBUG(" - type index offset : %d\n", binary->type_index_offset); LOG_DEBUG(" - mem page offset : %d\n", - binary->memory_page_offset); + binary->memory_page_offset); LOG_DEBUG(" - function index offset : %d\n", - binary->function_index_offset); + binary->function_index_offset); LOG_DEBUG(" - global index offset : %d\n", - binary->global_index_offset); + binary->global_index_offset); LOG_DEBUG(" - imported function offset: %d\n", - binary->imported_function_index_offset); + binary->imported_function_index_offset); LOG_DEBUG(" - imported global offset : %d\n", - binary->imported_global_index_offset); + binary->imported_global_index_offset); } } } -static Result perform_link(Context* ctx) { +Result Linker::PerformLink() { if (s_debug) - ctx->stream.set_log_stream(s_log_stream.get()); + stream_.set_log_stream(s_log_stream.get()); LOG_DEBUG("writing file: %s\n", s_outfile); - calculate_reloc_offsets(ctx); - resolve_symbols(ctx); - calculate_reloc_offsets(ctx); - dump_reloc_offsets(ctx); - write_binary(ctx); + CalculateRelocOffsets(); + ResolveSymbols(); + CalculateRelocOffsets(); + DumpRelocOffsets(); + WriteBinary(); - if (Failed(ctx->stream.WriteToFile(s_outfile))) { + if (Failed(stream_.WriteToFile(s_outfile))) { WABT_FATAL("error writing linked output to file\n"); } @@ -782,30 +770,30 @@ static Result perform_link(Context* ctx) { int ProgramMain(int argc, char** argv) { InitStdio(); - Context context; + Linker linker; ParseOptions(argc, argv); Result result = Result::Ok; - for (size_t i = 0; i < s_infiles.size(); i++) { - const std::string& input_filename = s_infiles[i]; + for (const auto& input_filename: s_infiles) { LOG_DEBUG("reading file: %s\n", input_filename.c_str()); std::vector<uint8_t> file_data; result = ReadFile(input_filename.c_str(), &file_data); if (Failed(result)) return result != Result::Ok; - LinkerInputBinary* b = - new LinkerInputBinary(input_filename.c_str(), file_data); - context.inputs.emplace_back(b); + + auto binary = new LinkerInputBinary(input_filename.c_str(), file_data); + linker.AppendBinary(binary); + LinkOptions options = { NULL }; if (s_debug) options.log_stream = s_log_stream.get(); - result = ReadBinaryLinker(b, &options); + result = ReadBinaryLinker(binary, &options); if (Failed(result)) WABT_FATAL("error parsing file: %s\n", input_filename.c_str()); } - result = perform_link(&context); + result = linker.PerformLink(); return result != Result::Ok; } |