summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/binary-reader-linker.cc301
-rw-r--r--src/binary-reader-linker.h40
-rw-r--r--src/tools/wasm-link.cc849
-rw-r--r--src/tools/wast2json.cc2
-rw-r--r--src/tools/wat2wasm.cc2
-rw-r--r--src/wasm-link.h135
6 files changed, 2 insertions, 1327 deletions
diff --git a/src/binary-reader-linker.cc b/src/binary-reader-linker.cc
deleted file mode 100644
index a0c63882..00000000
--- a/src/binary-reader-linker.cc
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright 2017 WebAssembly Community Group participants
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/binary-reader-linker.h"
-
-#include <vector>
-
-#include "src/binary-reader-nop.h"
-#include "src/wasm-link.h"
-
-#define RELOC_SIZE 5
-
-namespace wabt {
-namespace link {
-
-namespace {
-
-class BinaryReaderLinker : public BinaryReaderNop {
- public:
- explicit BinaryReaderLinker(LinkerInputBinary* binary);
-
- Result BeginSection(BinarySection section_type, Offset size) override;
-
- Result OnImportFunc(Index import_index,
- string_view module_name,
- string_view field_name,
- Index func_index,
- Index sig_index) override;
- Result OnImportGlobal(Index import_index,
- string_view module_name,
- string_view field_name,
- Index global_index,
- Type type,
- bool mutable_) override;
- Result OnImportMemory(Index import_index,
- string_view module_name,
- string_view field_name,
- Index memory_index,
- const Limits* page_limits) override;
-
- Result OnFunctionCount(Index count) override;
-
- Result OnTable(Index index,
- Type elem_type,
- const Limits* elem_limits) override;
-
- Result OnMemory(Index index, const Limits* limits) override;
-
- Result OnExport(Index index,
- ExternalKind kind,
- Index item_index,
- string_view name) override;
-
- Result OnElemSegmentFunctionIndexCount(Index index,
- Index count) override;
-
- Result BeginDataSegment(Index index, Index memory_index) override;
- Result OnDataSegmentData(Index index,
- const void* data,
- Address size) override;
-
- Result BeginNamesSection(Offset size) override;
-
- Result OnFunctionName(Index function_index,
- string_view function_name) override;
-
- Result OnRelocCount(Index count,
- BinarySection section_code,
- string_view section_name) override;
- Result OnReloc(RelocType type,
- Offset offset,
- Index index,
- uint32_t addend) override;
-
- Result OnInitExprI32ConstExpr(Index index, uint32_t value) override;
-
- private:
- LinkerInputBinary* binary_;
-
- Section* reloc_section_ = nullptr;
- Section* current_section_ = nullptr;
-};
-
-BinaryReaderLinker::BinaryReaderLinker(LinkerInputBinary* binary)
- : binary_(binary) {}
-
-Result BinaryReaderLinker::OnRelocCount(Index count,
- BinarySection section_code,
- string_view section_name) {
- if (section_code == BinarySection::Custom) {
- WABT_FATAL("relocation for custom sections not yet supported\n");
- }
-
- for (const std::unique_ptr<Section>& section : binary_->sections) {
- if (section->section_code != section_code) {
- continue;
- }
- reloc_section_ = section.get();
- return Result::Ok;
- }
-
- WABT_FATAL("section not found: %d\n", static_cast<int>(section_code));
- return Result::Error;
-}
-
-Result BinaryReaderLinker::OnReloc(RelocType type,
- Offset offset,
- Index index,
- uint32_t addend) {
- if (offset + RELOC_SIZE > reloc_section_->size) {
- WABT_FATAL("invalid relocation offset: %#" PRIoffset "\n", offset);
- }
-
- reloc_section_->relocations.emplace_back(type, offset, index, addend);
-
- return Result::Ok;
-}
-
-Result BinaryReaderLinker::OnImportFunc(Index import_index,
- string_view module_name,
- string_view field_name,
- Index global_index,
- Index sig_index) {
- binary_->function_imports.emplace_back();
- FunctionImport* import = &binary_->function_imports.back();
- import->module_name = module_name.to_string();
- import->name = field_name.to_string();
- import->sig_index = sig_index;
- import->active = true;
- binary_->active_function_imports++;
- return Result::Ok;
-}
-
-Result BinaryReaderLinker::OnImportGlobal(Index import_index,
- string_view module_name,
- string_view field_name,
- Index global_index,
- Type type,
- bool mutable_) {
- binary_->global_imports.emplace_back();
- GlobalImport* import = &binary_->global_imports.back();
- import->module_name = module_name.to_string();
- import->name = field_name.to_string();
- import->type = type;
- import->mutable_ = mutable_;
- binary_->active_global_imports++;
- return Result::Ok;
-}
-
-Result BinaryReaderLinker::OnImportMemory(Index import_index,
- string_view module_name,
- string_view field_name,
- Index memory_index,
- const Limits* page_limits) {
- WABT_FATAL("Linker does not support imported memories");
- return Result::Error;
-}
-
-Result BinaryReaderLinker::OnFunctionCount(Index count) {
- binary_->function_count = count;
- return Result::Ok;
-}
-
-Result BinaryReaderLinker::BeginSection(BinarySection section_code,
- Offset size) {
- Section* sec = new Section();
- binary_->sections.emplace_back(sec);
- current_section_ = sec;
- sec->section_code = section_code;
- sec->size = size;
- sec->offset = state->offset;
- sec->binary = binary_;
-
- if (sec->section_code != BinarySection::Custom &&
- sec->section_code != BinarySection::Start) {
- const uint8_t* start = &binary_->data[sec->offset];
- // Must point to one-past-the-end, but we can't dereference end().
- const uint8_t* end = &binary_->data.back() + 1;
- size_t bytes_read = ReadU32Leb128(start, end, &sec->count);
- if (bytes_read == 0) {
- WABT_FATAL("error reading section element count\n");
- }
- sec->payload_offset = sec->offset + bytes_read;
- sec->payload_size = sec->size - bytes_read;
- }
- return Result::Ok;
-}
-
-Result BinaryReaderLinker::OnTable(Index index,
- Type elem_type,
- const Limits* elem_limits) {
- if (elem_limits->has_max && (elem_limits->max != elem_limits->initial)) {
- WABT_FATAL("Tables with max != initial not supported by wabt-link\n");
- }
-
- binary_->table_elem_count = elem_limits->initial;
- return Result::Ok;
-}
-
-Result BinaryReaderLinker::OnElemSegmentFunctionIndexCount(Index index,
- Index count) {
- Section* sec = current_section_;
-
- /* Modify the payload to include only the actual function indexes */
- size_t delta = state->offset - sec->payload_offset;
- sec->payload_offset += delta;
- sec->payload_size -= delta;
- return Result::Ok;
-}
-
-Result BinaryReaderLinker::OnMemory(Index index, const Limits* page_limits) {
- Section* sec = current_section_;
- sec->data.initial = page_limits->initial;
- binary_->memory_page_count = page_limits->initial;
- return Result::Ok;
-}
-
-Result BinaryReaderLinker::BeginDataSegment(Index index, Index memory_index) {
- Section* sec = current_section_;
- if (!sec->data.data_segments) {
- sec->data.data_segments = new std::vector<DataSegment>();
- }
- sec->data.data_segments->emplace_back();
- DataSegment& segment = sec->data.data_segments->back();
- segment.memory_index = memory_index;
- return Result::Ok;
-}
-
-Result BinaryReaderLinker::OnInitExprI32ConstExpr(Index index, uint32_t value) {
- Section* sec = current_section_;
- if (sec->section_code != BinarySection::Data) {
- return Result::Ok;
- }
- DataSegment& segment = sec->data.data_segments->back();
- segment.offset = value;
- return Result::Ok;
-}
-
-Result BinaryReaderLinker::OnDataSegmentData(Index index,
- const void* src_data,
- Address size) {
- Section* sec = current_section_;
- DataSegment& segment = sec->data.data_segments->back();
- segment.data = static_cast<const uint8_t*>(src_data);
- segment.size = size;
- return Result::Ok;
-}
-
-Result BinaryReaderLinker::OnExport(Index index,
- ExternalKind kind,
- Index item_index,
- string_view name) {
- if (kind == ExternalKind::Memory) {
- WABT_FATAL("Linker does not support exported memories");
- }
- binary_->exports.emplace_back();
- Export* export_ = &binary_->exports.back();
- export_->name = name.to_string();
- export_->kind = kind;
- export_->index = item_index;
- return Result::Ok;
-}
-
-Result BinaryReaderLinker::BeginNamesSection(Offset size) {
- binary_->debug_names.resize(binary_->function_count +
- binary_->function_imports.size());
- return Result::Ok;
-}
-
-Result BinaryReaderLinker::OnFunctionName(Index index, string_view name) {
- binary_->debug_names[index] = name.to_string();
- return Result::Ok;
-}
-
-} // end anonymous namespace
-
-Result ReadBinaryLinker(LinkerInputBinary* input_info, LinkOptions* options) {
- BinaryReaderLinker reader(input_info);
-
- ReadBinaryOptions read_options;
- read_options.read_debug_names = true;
- read_options.log_stream = options->log_stream;
- return ReadBinary(input_info->data.data(), input_info->data.size(),
- &reader, &read_options);
-}
-
-} // namespace link
-} // namespace wabt
diff --git a/src/binary-reader-linker.h b/src/binary-reader-linker.h
deleted file mode 100644
index 79b43878..00000000
--- a/src/binary-reader-linker.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2017 WebAssembly Community Group participants
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WABT_BINARY_READER_LINKER_H_
-#define WABT_BINARY_READER_LINKER_H_
-
-#include "src/common.h"
-#include "src/stream.h"
-
-namespace wabt {
-
-class Stream;
-
-namespace link {
-
-class LinkerInputBinary;
-
-struct LinkOptions {
- Stream* log_stream;
-};
-
-Result ReadBinaryLinker(LinkerInputBinary* input_info, LinkOptions* options);
-
-} // namespace link
-} // namespace wabt
-
-#endif /* WABT_BINARY_READER_LINKER_H_ */
diff --git a/src/tools/wasm-link.cc b/src/tools/wasm-link.cc
deleted file mode 100644
index cafa0d23..00000000
--- a/src/tools/wasm-link.cc
+++ /dev/null
@@ -1,849 +0,0 @@
-/*
- * Copyright 2016 WebAssembly Community Group participants
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "src/wasm-link.h"
-
-#include <memory>
-#include <vector>
-
-#include "src/binary-reader.h"
-#include "src/binding-hash.h"
-#include "src/binary-writer.h"
-#include "src/leb128.h"
-#include "src/option-parser.h"
-#include "src/stream.h"
-#include "src/binary-reader-linker.h"
-
-#define FIRST_KNOWN_SECTION static_cast<size_t>(BinarySection::Type)
-#define LOG_DEBUG(fmt, ...) if (s_debug) s_log_stream->Writef(fmt, __VA_ARGS__);
-
-using namespace wabt;
-using namespace wabt::link;
-
-static const char s_description[] =
-R"( link one or more wasm binary modules into a single binary module.
- $ wasm-link m1.wasm m2.wasm -o out.wasm
-)";
-
-static bool s_debug;
-static bool s_relocatable;
-static const char* s_outfile = "a.wasm";
-static std::vector<std::string> s_infiles;
-static std::unique_ptr<FileStream> s_log_stream;
-
-static void ParseOptions(int argc, char** argv) {
- OptionParser parser("wasm-link", s_description);
-
- parser.AddOption("debug",
- "Log extra information when reading and writing wasm files",
- []() {
- s_debug = true;
- s_log_stream = FileStream::CreateStdout();
- });
- parser.AddOption('o', "output", "FILE", "Output wasm binary file",
- [](const char* argument) { s_outfile = argument; });
- parser.AddOption('r', "relocatable", "Output a relocatable object file",
- []() { s_relocatable = true; });
- parser.AddHelpOption();
-
- parser.AddArgument(
- "filename", OptionParser::ArgumentCount::OneOrMore,
- [](const std::string& argument) { s_infiles.emplace_back(argument); });
-
- parser.Parse(argc, argv);
-}
-
-Section::Section()
- : binary(nullptr),
- section_code(BinarySection::Invalid),
- size(0),
- offset(0),
- payload_size(0),
- payload_offset(0),
- count(0),
- output_payload_offset(0) {
- ZeroMemory(data);
-}
-
-Section::~Section() {
- if (section_code == BinarySection::Data) {
- delete data.data_segments;
- }
-}
-
-LinkerInputBinary::LinkerInputBinary(const char* filename,
- const std::vector<uint8_t>& data)
- : filename(filename),
- data(data),
- active_function_imports(0),
- active_global_imports(0),
- type_index_offset(0),
- function_index_offset(0),
- imported_function_index_offset(0),
- table_index_offset(0),
- memory_page_count(0),
- memory_page_offset(0),
- table_elem_count(0) {}
-
-bool LinkerInputBinary::IsFunctionImport(Index index) {
- assert(IsValidFunctionIndex(index));
- return index < function_imports.size();
-}
-
-bool LinkerInputBinary::IsInactiveFunctionImport(Index index){
- return IsFunctionImport(index) && !function_imports[index].active;
-}
-
-bool LinkerInputBinary::IsValidFunctionIndex(Index index) {
- return index < function_imports.size() + function_count;
-}
-
-Index LinkerInputBinary::RelocateFuncIndex(Index function_index) {
- Index offset;
- if (!IsFunctionImport(function_index)) {
- // locally declared function call.
- offset = function_index_offset;
- LOG_DEBUG("func reloc %d + %d\n", function_index, offset);
- } else {
- // imported function call.
- FunctionImport* import = &function_imports[function_index];
- if (!import->active) {
- function_index = import->foreign_index;
- offset = import->foreign_binary->function_index_offset;
- LOG_DEBUG("reloc for disabled import. new index = %d + %d\n",
- function_index, offset);
- } else {
- Index new_index = import->relocated_function_index;
- LOG_DEBUG("reloc for active import. old index = %d, new index = %d\n",
- function_index, new_index);
- return new_index;
- }
- }
- return function_index + offset;
-}
-
-Index LinkerInputBinary::RelocateTypeIndex(Index type_index) {
- return type_index + type_index_offset;
-}
-
-Index LinkerInputBinary::RelocateGlobalIndex(Index global_index) {
- Index offset;
- if (global_index >= global_imports.size()) {
- offset = global_index_offset;
- } else {
- offset = imported_global_index_offset;
- }
- return global_index + offset;
-}
-
-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;
-
- Index cur_value = 0, new_value = 0;
- ReadU32Leb128(section_data + r->offset, section_data + section_size,
- &cur_value);
-
- switch (r->type) {
- case RelocType::FuncIndexLEB:
- new_value = binary->RelocateFuncIndex(cur_value);
- break;
- case RelocType::TypeIndexLEB:
- new_value = binary->RelocateTypeIndex(cur_value);
- break;
- case RelocType::TableIndexSLEB:
- new_value = cur_value + binary->table_index_offset;
- break;
- case RelocType::GlobalIndexLEB:
- new_value = binary->RelocateGlobalIndex(cur_value);
- break;
- case RelocType::TableIndexI32:
- case RelocType::MemoryAddressLEB:
- case RelocType::MemoryAddressSLEB:
- case RelocType::MemoryAddressI32:
- WABT_FATAL("unhandled relocation type: %s\n", GetRelocTypeName(r->type));
- }
-
- WriteFixedU32Leb128Raw(section_data + r->offset, section_data + section_size,
- new_value);
-}
-
-static void ApplyRelocations(const Section* section) {
- if (!section->relocations.size()) {
- return;
- }
-
- LOG_DEBUG("ApplyRelocations: %s\n", GetSectionName(section->section_code));
-
- // Perform relocations in-place.
- for (const Reloc& 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 WriteLinkingSection(uint32_t data_size, uint32_t data_alignment);
- 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;
-};
-
-void Linker::WriteSectionPayload(Section* sec) {
- assert(current_section_payload_offset_ != -1);
-
- sec->output_payload_offset =
- stream_.offset() - current_section_payload_offset_;
-
- uint8_t* payload = &sec->binary->data[sec->payload_offset];
- stream_.WriteData(payload, sec->payload_size, "section content");
-}
-
-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_);
-}
-
-void Linker::FixupSize(Fixup fixup) {
- WriteFixedU32Leb128At(&stream_, fixup.first, stream_.offset() - fixup.second,
- "fixup size");
-}
-
-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;
-
- for (Section* section: sections) {
- elem_count += section->binary->table_elem_count;
- }
-
- Fixup 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);
-}
-
-void Linker::WriteExportSection() {
- Index total_exports = 0;
- for (const std::unique_ptr<LinkerInputBinary>& binary : inputs_) {
- total_exports += binary->exports.size();
- }
-
- Fixup fixup = WriteUnknownSize();
- WriteU32Leb128(&stream_, total_exports, "export count");
-
- 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");
- Index index = export_.index;
- switch (export_.kind) {
- case ExternalKind::Func:
- index = binary->RelocateFuncIndex(index);
- break;
- default:
- WABT_FATAL("unsupport export type: %d\n",
- static_cast<int>(export_.kind));
- break;
- }
- WriteU32Leb128(&stream_, index, "export index");
- }
- }
-
- FixupSize(fixup);
-}
-
-void Linker::WriteElemSection(const SectionPtrVector& sections) {
- Fixup 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(&stream_, Opcode::I32Const);
- WriteS32Leb128(&stream_, 0U, "elem init literal");
- WriteOpcode(&stream_, Opcode::End);
- WriteU32Leb128(&stream_, total_elem_count, "num elements");
-
- current_section_payload_offset_ = stream_.offset();
-
- for (Section* section : sections) {
- ApplyRelocations(section);
- WriteSectionPayload(section);
- }
-
- FixupSize(fixup);
-}
-
-void Linker::WriteMemorySection(const SectionPtrVector& sections) {
- Fixup fixup = WriteUnknownSize();
-
- WriteU32Leb128(&stream_, 1, "memory count");
-
- Limits limits;
- limits.has_max = true;
- for (Section* section: sections) {
- limits.initial += section->data.initial;
- }
- limits.max = limits.initial;
- WriteLimits(&stream_, &limits);
-
- FixupSize(fixup);
-}
-
-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");
-}
-
-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");
-}
-
-void Linker::WriteImportSection() {
- Index num_imports = 0;
- for (const std::unique_ptr<LinkerInputBinary>& binary: inputs_) {
- for (const FunctionImport& import : binary->function_imports) {
- if (import.active) {
- num_imports++;
- }
- }
- num_imports += binary->global_imports.size();
- }
-
- Fixup fixup = WriteUnknownSize();
- WriteU32Leb128(&stream_, num_imports, "num imports");
-
- for (const std::unique_ptr<LinkerInputBinary>& binary: inputs_) {
- for (const FunctionImport& function_import : binary->function_imports) {
- if (function_import.active) {
- WriteFunctionImport(function_import, binary->type_index_offset);
- }
- }
-
- for (const GlobalImport& global_import : binary->global_imports) {
- WriteGlobalImport(global_import);
- }
- }
-
- FixupSize(fixup);
-}
-
-void Linker::WriteFunctionSection(const SectionPtrVector& sections,
- Index total_count) {
- Fixup fixup = WriteUnknownSize();
-
- WriteU32Leb128(&stream_, total_count, "function count");
-
- for (Section* sec: sections) {
- Index count = sec->count;
- Offset input_offset = 0;
- Index sig_index = 0;
- const uint8_t* start = &sec->binary->data[sec->payload_offset];
- const uint8_t* end =
- &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");
- }
- }
-
- FixupSize(fixup);
-}
-
-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");
-}
-
-void Linker::WriteDataSection(const SectionPtrVector& sections,
- Index total_count) {
- Fixup fixup = WriteUnknownSize();
-
- WriteU32Leb128(&stream_, total_count, "data segment count");
- for (const Section* sec: sections) {
- for (const DataSegment& segment: *sec->data.data_segments) {
- WriteDataSegment(segment,
- sec->binary->memory_page_offset * WABT_PAGE_SIZE);
- }
- }
-
- FixupSize(fixup);
-}
-
-void Linker::WriteNamesSection() {
- Index total_count = 0;
- for (const std::unique_ptr<LinkerInputBinary>& binary : inputs_) {
- for (size_t i = 0; i < binary->debug_names.size(); i++) {
- if (binary->debug_names[i].empty()) {
- continue;
- }
- if (binary->IsInactiveFunctionImport(i)) {
- continue;
- }
- total_count++;
- }
- }
-
- if (!total_count) {
- return;
- }
-
- stream_.WriteU8Enum(BinarySection::Custom, "section code");
- Fixup fixup_section = WriteUnknownSize();
- WriteStr(&stream_, "name", "custom section name");
-
- stream_.WriteU8Enum(NameSectionSubsection::Function, "subsection code");
- Fixup fixup_subsection = WriteUnknownSize();
- WriteU32Leb128(&stream_, total_count, "element count");
-
- // Write import names.
- for (const std::unique_ptr<LinkerInputBinary>& 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");
- }
- }
-
- // Write non-import names.
- for (const std::unique_ptr<LinkerInputBinary>& 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");
- }
- }
-
- FixupSize(fixup_subsection);
- FixupSize(fixup_section);
-}
-
-void Linker::WriteLinkingSection(uint32_t data_size, uint32_t data_alignment) {
- stream_.WriteU8Enum(BinarySection::Custom, "section code");
- Fixup fixup = WriteUnknownSize();
-
- WriteStr(&stream_, "linking", "linking section name");
-
- if (data_size) {
- WriteU32Leb128(&stream_, LinkingEntryType::DataSize, "subsection code");
- Fixup fixup_subsection = WriteUnknownSize();
- WriteU32Leb128(&stream_, data_size, "data size");
- FixupSize(fixup_subsection);
- }
-
- FixupSize(fixup);
-}
-
-void Linker::WriteRelocSection(BinarySection section_code,
- const SectionPtrVector& sections) {
- Index total_relocs = 0;
-
- // First pass to know total reloc count.
- for (Section* sec: sections)
- total_relocs += sec->relocations.size();
-
- if (!total_relocs) {
- return;
- }
-
- std::string section_name = StringPrintf("%s.%s", WABT_BINARY_SECTION_RELOC,
- GetSectionName(section_code));
-
- stream_.WriteU8Enum(BinarySection::Custom, "section code");
- Fixup fixup = WriteUnknownSize();
- WriteStr(&stream_, section_name, "reloc section name");
- WriteU32Leb128(&stream_, section_code, "reloc section");
- WriteU32Leb128(&stream_, total_relocs, "num relocs");
-
- for (Section* sec: sections) {
- for (const Reloc& reloc: sec->relocations) {
- WriteU32Leb128(&stream_, reloc.type, "reloc type");
- Offset new_offset = reloc.offset + sec->output_payload_offset;
- WriteU32Leb128(&stream_, new_offset, "reloc offset");
- Index relocated_index = 0;
- switch (reloc.type) {
- case RelocType::FuncIndexLEB:
- relocated_index = sec->binary->RelocateFuncIndex(reloc.index);
- break;
- case RelocType::TypeIndexLEB:
- relocated_index = sec->binary->RelocateTypeIndex(reloc.index);
- break;
- case RelocType::GlobalIndexLEB:
- relocated_index = sec->binary->RelocateGlobalIndex(reloc.index);
- break;
- case RelocType::MemoryAddressLEB:
- case RelocType::MemoryAddressSLEB:
- case RelocType::MemoryAddressI32:
- case RelocType::TableIndexSLEB:
- case RelocType::TableIndexI32:
- WABT_FATAL("Unhandled reloc type: %s\n",
- GetRelocTypeName(reloc.type));
- }
- WriteU32Leb128(&stream_, relocated_index, "reloc index");
- }
- }
-
- FixupSize(fixup);
-}
-
-bool Linker::WriteCombinedSection(BinarySection section_code,
- const SectionPtrVector& sections) {
- if (!sections.size()) {
- return false;
- }
-
- if (section_code == BinarySection::Start && sections.size() > 1) {
- WABT_FATAL("Don't know how to combine sections of type: %s\n",
- GetSectionName(section_code));
- }
-
- Index total_count = 0;
- Index total_size = 0;
-
- // Sum section size and element count.
- for (Section* sec : sections) {
- total_size += sec->payload_size;
- total_count += sec->count;
- }
-
- stream_.WriteU8Enum(section_code, "section code");
- current_section_payload_offset_ = -1;
-
- switch (section_code) {
- case BinarySection::Import:
- WriteImportSection();
- break;
- case BinarySection::Function:
- WriteFunctionSection(sections, total_count);
- break;
- case BinarySection::Table:
- WriteTableSection(sections);
- break;
- case BinarySection::Export:
- WriteExportSection();
- break;
- case BinarySection::Elem:
- WriteElemSection(sections);
- break;
- case BinarySection::Memory:
- WriteMemorySection(sections);
- break;
- case BinarySection::Data:
- WriteDataSection(sections, total_count);
- break;
- default: {
- // Total section size includes the element count leb128.
- total_size += U32Leb128Length(total_count);
-
- // 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);
- }
- }
- }
-
- return true;
-}
-
-struct ExportInfo {
- ExportInfo(const Export* export_, LinkerInputBinary* binary)
- : export_(export_), binary(binary) {}
-
- const Export* export_;
- LinkerInputBinary* binary;
-};
-
-void Linker::ResolveSymbols() {
- // Create hashmap of all exported symbols from all inputs.
- BindingHash export_map;
- std::vector<ExportInfo> export_list;
-
- for (const std::unique_ptr<LinkerInputBinary>& binary: inputs_) {
- for (const Export& 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));
- }
- }
-
- // Iterate through all imported functions resolving them against exported
- // ones.
- for (std::unique_ptr<LinkerInputBinary>& binary: inputs_) {
- for (FunctionImport& 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());
- }
- continue;
- }
-
- // 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;
- binary->active_function_imports--;
- }
- }
-}
-
-void Linker::CalculateRelocOffsets() {
- Index memory_page_offset = 0;
- Index type_count = 0;
- Index global_count = 0;
- Index function_count = 0;
- Index table_elem_count = 0;
- Index total_function_imports = 0;
- Index total_global_imports = 0;
-
- for (std::unique_ptr<LinkerInputBinary>& 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;
-
- size_t delta = 0;
- for (size_t i = 0; i < binary->function_imports.size(); i++) {
- if (!binary->function_imports[i].active) {
- delta++;
- } else {
- binary->function_imports[i].relocated_function_index =
- total_function_imports + i - delta;
- }
- }
-
- memory_page_offset += binary->memory_page_count;
- total_function_imports += binary->active_function_imports;
- total_global_imports += binary->global_imports.size();
- }
-
- for (std::unique_ptr<LinkerInputBinary>& binary : inputs_) {
- binary->table_index_offset = table_elem_count;
- table_elem_count += binary->table_elem_count;
- for (std::unique_ptr<Section>& sec : binary->sections) {
- switch (sec->section_code) {
- case BinarySection::Type:
- binary->type_index_offset = type_count;
- type_count += sec->count;
- break;
- case BinarySection::Global:
- binary->global_index_offset = total_global_imports -
- sec->binary->global_imports.size() +
- global_count;
- global_count += sec->count;
- break;
- case BinarySection::Function:
- binary->function_index_offset = total_function_imports -
- sec->binary->function_imports.size() +
- function_count;
- function_count += sec->count;
- break;
- default:
- break;
- }
- }
- }
-}
-
-void Linker::WriteBinary() {
- // Find all the sections of each type.
- SectionPtrVector sections[kBinarySectionCount];
-
- for (std::unique_ptr<LinkerInputBinary>& binary : inputs_) {
- for (std::unique_ptr<Section>& sec : binary->sections) {
- SectionPtrVector& sec_list =
- sections[static_cast<int>(sec->section_code)];
- sec_list.push_back(sec.get());
- }
- }
-
- // Write the final binary.
- stream_.WriteU32(WABT_BINARY_MAGIC, "WABT_BINARY_MAGIC");
- stream_.WriteU32(WABT_BINARY_VERSION, "WABT_BINARY_VERSION");
-
- // Write known sections first.
- for (size_t i = FIRST_KNOWN_SECTION; i < kBinarySectionCount; i++) {
- WriteCombinedSection(static_cast<BinarySection>(i), sections[i]);
- }
-
- WriteNamesSection();
-
- /* Generate a new set of reloction sections */
- if (s_relocatable) {
- WriteLinkingSection(0, 0);
- for (size_t i = FIRST_KNOWN_SECTION; i < kBinarySectionCount; i++) {
- WriteRelocSection(static_cast<BinarySection>(i), sections[i]);
- }
- }
-}
-
-void Linker::DumpRelocOffsets() {
- if (s_debug) {
- for (const std::unique_ptr<LinkerInputBinary>& binary : inputs_) {
- LOG_DEBUG("Relocation info for: %s\n", binary->filename);
- LOG_DEBUG(" - type index offset : %d\n", binary->type_index_offset);
- LOG_DEBUG(" - mem page offset : %d\n",
- binary->memory_page_offset);
- LOG_DEBUG(" - function index offset : %d\n",
- binary->function_index_offset);
- LOG_DEBUG(" - global index offset : %d\n",
- binary->global_index_offset);
- LOG_DEBUG(" - imported function offset: %d\n",
- binary->imported_function_index_offset);
- LOG_DEBUG(" - imported global offset : %d\n",
- binary->imported_global_index_offset);
- }
- }
-}
-
-Result Linker::PerformLink() {
- if (s_debug) {
- stream_.set_log_stream(s_log_stream.get());
- }
-
- LOG_DEBUG("writing file: %s\n", s_outfile);
- CalculateRelocOffsets();
- ResolveSymbols();
- CalculateRelocOffsets();
- DumpRelocOffsets();
- WriteBinary();
-
- if (Failed(stream_.WriteToFile(s_outfile))) {
- WABT_FATAL("error writing linked output to file\n");
- }
-
- return Result::Ok;
-}
-
-int ProgramMain(int argc, char** argv) {
- InitStdio();
-
- Linker linker;
-
- printf(R"(
-******************************************************************
-WARNING: wasm-link is deprecated. Where possible, use lld instead.
-******************************************************************
-)");
-
- ParseOptions(argc, argv);
-
- Result result = Result::Ok;
- for (const std::string& 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;
- }
-
- 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(binary, &options);
- if (Failed(result)) {
- WABT_FATAL("error parsing file: %s\n", input_filename.c_str());
- }
- }
-
- result = linker.PerformLink();
- return result != Result::Ok;
-}
-
-int main(int argc, char** argv) {
- WABT_TRY
- return ProgramMain(argc, argv);
- WABT_CATCH_BAD_ALLOC_AND_EXIT
-}
diff --git a/src/tools/wast2json.cc b/src/tools/wast2json.cc
index 21c62f9d..aa200136 100644
--- a/src/tools/wast2json.cc
+++ b/src/tools/wast2json.cc
@@ -73,7 +73,7 @@ static void ParseOptions(int argc, char* argv[]) {
[](const char* argument) { s_outfile = argument; });
parser.AddOption(
'r', "relocatable",
- "Create a relocatable wasm binary (suitable for linking with wasm-link)",
+ "Create a relocatable wasm binary (suitable for linking with e.g. lld)",
[]() { s_write_binary_options.relocatable = true; });
parser.AddOption(
"no-canonicalize-leb128s",
diff --git a/src/tools/wat2wasm.cc b/src/tools/wat2wasm.cc
index 2f376e63..0268011f 100644
--- a/src/tools/wat2wasm.cc
+++ b/src/tools/wat2wasm.cc
@@ -82,7 +82,7 @@ static void ParseOptions(int argc, char* argv[]) {
[](const char* argument) { s_outfile = argument; });
parser.AddOption(
'r', "relocatable",
- "Create a relocatable wasm binary (suitable for linking with wasm-link)",
+ "Create a relocatable wasm binary (suitable for linking with e.g. lld)",
[]() { s_write_binary_options.relocatable = true; });
parser.AddOption(
"no-canonicalize-leb128s",
diff --git a/src/wasm-link.h b/src/wasm-link.h
deleted file mode 100644
index f3467cee..00000000
--- a/src/wasm-link.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright 2017 WebAssembly Community Group participants
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WABT_LINK_H_
-#define WABT_LINK_H_
-
-#include <memory>
-#include <vector>
-
-#include "src/binary.h"
-#include "src/common.h"
-
-namespace wabt {
-namespace link {
-
-class LinkerInputBinary;
-
-struct FunctionImport {
- std::string module_name;
- std::string name;
- Index sig_index;
- bool active; /* Is this import present in the linked binary */
- Index relocated_function_index;
- LinkerInputBinary* foreign_binary;
- Index foreign_index;
-};
-
-struct GlobalImport {
- std::string module_name;
- std::string name;
- Type type;
- bool mutable_;
-};
-
-struct DataSegment {
- Index memory_index;
- Address offset;
- const uint8_t* data;
- size_t size;
-};
-
-struct Export {
- ExternalKind kind;
- std::string name;
- Index index;
-};
-
-struct Section {
- WABT_DISALLOW_COPY_AND_ASSIGN(Section);
- Section();
- ~Section();
-
- /* The binary to which this section belongs */
- LinkerInputBinary* binary;
- std::vector<Reloc> relocations; /* The relocations for this section */
-
- BinarySection section_code;
- size_t size;
- size_t offset;
-
- size_t payload_size;
- size_t payload_offset;
-
- /* For known sections, the count of the number of elements in the section */
- Index count;
-
- union {
- /* DATA section data */
- std::vector<DataSegment>* data_segments;
- /* MEMORY section data */
- uint64_t initial;
- } data;
-
- /* The offset at which this section appears within the combined output
- * section. */
- size_t output_payload_offset;
-};
-
-typedef std::vector<Section*> SectionPtrVector;
-
-class LinkerInputBinary {
- public:
- WABT_DISALLOW_COPY_AND_ASSIGN(LinkerInputBinary);
- LinkerInputBinary(const char* filename, const std::vector<uint8_t>& data);
-
- Index RelocateFuncIndex(Index findex);
- Index RelocateTypeIndex(Index index);
- Index RelocateGlobalIndex(Index index);
-
- bool IsValidFunctionIndex(Index index);
- bool IsFunctionImport(Index index);
- bool IsInactiveFunctionImport(Index index);
-
- const char* filename;
- std::vector<uint8_t> data;
- std::vector<std::unique_ptr<Section>> sections;
- std::vector<Export> exports;
-
- std::vector<FunctionImport> function_imports;
- Index active_function_imports;
- std::vector<GlobalImport> global_imports;
- Index active_global_imports;
-
- Index type_index_offset;
- Index function_index_offset;
- Index imported_function_index_offset;
- Index global_index_offset;
- Index imported_global_index_offset;
- Index table_index_offset;
- Index memory_page_count;
- Index memory_page_offset;
-
- Index table_elem_count = 0;
- Index function_count = 0;
-
- std::vector<std::string> debug_names;
-};
-
-} // namespace link
-} // namespace wabt
-
-#endif /* WABT_LINK_H_ */