提交 458017c3 编写于 作者: B Bart Wyatt

progress on correct memory assumptions

上级 8d321000
......@@ -37,13 +37,13 @@ struct interpreter_interface : ModuleInstance::ExternalInterface {
void init(Module& wasm, ModuleInstance& instance) override {
FC_ASSERT(wasm.memory.initial * wasm::Memory::kPageSize <= wasm_constraints::maximum_linear_memory);
// initialize the linear memory
memset(memory.data, 0, wasm.memory.initial * Memory::kPageSize);
for(size_t i = 0; i < wasm.memory.segments.size(); i++ ) {
const auto& segment = wasm.memory.segments.at(i);
char *base = memory.data + (i * Memory::kPageSize);
Address offset = ConstantExpressionRunner<TrivialGlobalManager>(instance.globals).visit(segment.offset).value.geti32();
char *base = memory.data + offset;
FC_ASSERT(offset + segment.data.size() <= wasm_constraints::maximum_linear_memory);
memcpy(base, segment.data.data(), segment.data.size());
if (segment.data.size() < Memory::kPageSize) {
memset(base + segment.data.size(), 0, Memory::kPageSize - segment.data.size());
}
}
table.resize(wasm.table.initial);
......@@ -54,6 +54,8 @@ struct interpreter_interface : ModuleInstance::ExternalInterface {
table[offset + i] = segment.data[i];
}
}
sbrk_bytes = wasm.memory.initial * Memory::kPageSize;
}
Literal callImport(Import *import, LiteralList &args) override
......@@ -120,6 +122,11 @@ struct interpreter_interface : ModuleInstance::ExternalInterface {
}
}
void growMemory(Address, Address) override
{
FC_THROW_EXCEPTION(wasm_execution_error, "grow memory is not supported");
}
int8_t load8s(Address addr) override { return load_memory<int8_t>(addr); }
uint8_t load8u(Address addr) override { return load_memory<uint8_t>(addr); }
int16_t load16s(Address addr) override { return load_memory<int16_t>(addr); }
......@@ -168,28 +175,21 @@ struct info {
info( const entry& binaryen )
{
int num_segments = binaryen.module->memory.segments.size();
default_sbrk_bytes = num_segments * Memory::kPageSize;
mem_images.reserve(num_segments);
for(const auto& segment : binaryen.module->memory.segments ) {
const char* start = segment.data.data();
const char* high_watermark = start + segment.data.size();
default_sbrk_bytes = binaryen.interface->sbrk_bytes;
const char* start = binaryen.interface->memory.data;
const char* high_watermark = start + (binaryen.module->memory.initial * Memory::kPageSize);
while (high_watermark > start) {
if (*high_watermark) {
break;
}
high_watermark--;
}
if (high_watermark > start) {
mem_images.emplace_back(start, high_watermark);
} else {
mem_images.emplace_back();
}
}
mem_image.resize(high_watermark - start);
memcpy(mem_image.data(), start, high_watermark - start);
}
// a clean image of the memory used to sanitize things on checkin
vector<vector<char>> mem_images;
vector<char> mem_image;
uint32_t default_sbrk_bytes;
};
......
......@@ -36,6 +36,11 @@ namespace eosio { namespace chain {
FC_ASSERT( !"error parsing wast", "${msg}", ("msg",ss.get()) );
}
for(auto sectionIt = module.userSections.begin();sectionIt != module.userSections.end();++sectionIt)
{
if(sectionIt->name == "name") { module.userSections.erase(sectionIt); break; }
}
try
{
// Serialize the WebAssembly module.
......
......@@ -46,31 +46,32 @@ int entry::sbrk(int num_bytes) {
}
void entry::reset(const info& base_info) {
for (size_t i = 0; i < base_info.mem_images.size(); i++) {
const auto& image = base_info.mem_images.at(i);
char *base = interface->memory.data + (i * Memory::kPageSize);
const auto& image = base_info.mem_image;
char *base = interface->memory.data;
memcpy(base, image.data(), image.size());
}
if (interface->sbrk_bytes > base_info.default_sbrk_bytes) {
memset(interface->memory.data + base_info.default_sbrk_bytes, 0, interface->sbrk_bytes - base_info.default_sbrk_bytes);
if (interface->sbrk_bytes > image.size()) {
memset(interface->memory.data + image.size(), 0, interface->sbrk_bytes - image.size());
}
interface->sbrk_bytes = base_info.default_sbrk_bytes;
}
entry entry::build(const char* wasm_binary, size_t wasm_binary_size) {
try {
vector<char> code(wasm_binary, wasm_binary + wasm_binary_size);
unique_ptr<Module> module;
unique_ptr<Module> module(new Module());
WasmBinaryBuilder builder(*module, code, false);
builder.read();
unique_ptr<interpreter_interface> interface;
unique_ptr<interpreter_interface> interface(new interpreter_interface());
unique_ptr<ModuleInstance> instance(new ModuleInstance(*module.get(), interface.get()));
//TODO: validate
return entry(move(module), move(interface), move(instance));
} catch (const ParseException &e) {
FC_THROW_EXCEPTION(wasm_execution_error, "Error building interpreter: ${s}", ("s", e.text));
}
};
entry::entry(unique_ptr<Module>&& module, unique_ptr<interpreter_interface>&& interface, unique_ptr<ModuleInstance>&& instance)
......
#include <boost/test/unit_test.hpp>
#include <eosio/testing/tester.hpp>
#include <eosio/chain/asset.hpp>
#include <eosio/chain/wast_to_wasm.hpp>
#include <eosio/chain/contracts/types.hpp>
#include <eosio/chain/contracts/eos_contract.hpp>
#include <eosio/chain/contracts/contract_table_objects.hpp>
......@@ -239,48 +240,7 @@ namespace eosio { namespace testing {
} FC_CAPTURE_AND_RETHROW( (account)(perm)(auth)(parent) ) }
void tester::set_code( account_name account, const char* wast ) try {
const auto assemble = [](const char* wast) -> vector<unsigned char> {
using namespace IR;
using namespace WAST;
using namespace WASM;
using namespace Serialization;
Module module;
vector<Error> parse_errors;
parseModule(wast, fc::const_strlen(wast), module, parse_errors);
if (!parse_errors.empty()) {
fc::exception parse_exception(
FC_LOG_MESSAGE(warn, "Failed to parse WAST"),
fc::std_exception_code,
"wast_parse_error",
"Failed to parse WAST"
);
for (const auto& err: parse_errors) {
parse_exception.append_log( FC_LOG_MESSAGE(error, ":${desc}: ${message}", ("desc", err.locus.describe())("message", err.message.c_str()) ) );
parse_exception.append_log( FC_LOG_MESSAGE(error, string(err.locus.column(8), ' ') + "^" ));
}
throw parse_exception;
}
try {
// Serialize the WebAssembly module.
ArrayOutputStream stream;
serialize(stream,module);
return stream.getBytes();
} catch(const FatalSerializationException& ex) {
fc::exception serialize_exception (
FC_LOG_MESSAGE(warn, "Failed to serialize wasm: ${message}", ("message", ex.message)),
fc::std_exception_code,
"wasm_serialization_error",
"Failed to serialize WASM"
);
throw serialize_exception;
}
};
auto wasm = assemble(wast);
auto wasm = wast_to_wasm(wast);
signed_transaction trx;
trx.actions.emplace_back( vector<permission_level>{{account,config::active_name}},
......
......@@ -73,6 +73,7 @@ Options:
#include <eosio/utilities/key_conversion.hpp>
#include <eosio/chain/config.hpp>
#include <eosio/chain/wast_to_wasm.hpp>
#include <eosio/chain_plugin/chain_plugin.hpp>
#include <boost/range/algorithm/find_if.hpp>
#include <boost/range/algorithm/sort.hpp>
......@@ -172,38 +173,6 @@ inline std::vector<name> sort_names( const std::vector<name>& names ) {
return results;
}
vector<uint8_t> assemble_wast( const std::string& wast ) {
IR::Module module;
std::vector<WAST::Error> parseErrors;
WAST::parseModule(wast.c_str(),wast.size(),module,parseErrors);
if(parseErrors.size())
{
// Print any parse errors;
std::cerr << localized("Error parsing WebAssembly text file:") << std::endl;
for(auto& error : parseErrors)
{
std::cerr << ":" << error.locus.describe() << ": " << error.message.c_str() << std::endl;
std::cerr << error.locus.sourceLine << std::endl;
std::cerr << std::setw(error.locus.column(8)) << "^" << std::endl;
}
FC_THROW_EXCEPTION( explained_exception, "wast parse error" );
}
try
{
// Serialize the WebAssembly module.
Serialization::ArrayOutputStream stream;
WASM::serialize(stream,module);
return stream.getBytes();
}
catch(Serialization::FatalSerializationException exception)
{
std::cerr << localized("Error serializing WebAssembly binary file:") << std::endl;
std::cerr << exception.message << std::endl;
FC_THROW_EXCEPTION( explained_exception, "wasm serialize error");
}
}
auto tx_expiration = fc::seconds(30);
bool tx_force_unique = false;
void add_standard_transaction_options(CLI::App* cmd) {
......@@ -717,7 +686,7 @@ int main( int argc, char** argv ) {
}
else {
std::cout << localized("Assembling WASM...") << std::endl;
wasm = assemble_wast(wast);
wasm = wast_to_wasm(wast);
}
contracts::setcode handler;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册