summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/tools/wasm-link.cc564
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;
}