/* ** indexer.cpp ** ** This file is part of mkxp. ** ** Copyright (C) 2013 - 2021 Amaryllis Kulla ** ** mkxp is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 2 of the License, or ** (at your option) any later version. ** ** mkxp is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with mkxp. If not, see . */ #include #include #include #include "wabt/binary-reader.h" #include "wabt/binary-reader-ir.h" #include "wabt/ir.h" int main(int argc, char **argv) { if (argc < 2) { std::cerr << "[indexer] error: at least one argument must be passed to this program" << std::endl; return 1; } // Read the input file into the vector `data` std::vector data; { std::ifstream f(argv[1], std::ios::binary); if (!f.is_open()) { std::cerr << "[indexer] error: could not open " << argv[1] << std::endl; return 2; } for (;;) { unsigned char c = f.get(); if (f.eof()) { break; } data.push_back(c); } } // Parse the data we read as a WebAssembly module wabt::Module wasm; { const wabt::ReadBinaryOptions options; wabt::Errors errors; const wabt::Result result = wabt::ReadBinaryIr(argv[1], data.data(), data.size(), options, &errors, &wasm); if (result != wabt::Result::Ok) { std::cerr << "[indexer] error: failed to parse " << argv[1] << std::endl; return 3; } } // Find the "asyncify_start_unwind" function const wabt::Func *func = nullptr; for (const wabt::Export *e : wasm.exports) { if (e->kind == wabt::ExternalKind::Func && e->name == "asyncify_start_unwind") { func = wasm.GetFunc(e->var); break; } } if (func == nullptr) { std::cerr << "[indexer] error: could not find asyncify_start_unwind function in " << argv[1] << std::endl; return 4; } // Print the indices of the variables set by the `global.set` instructions in this function // (There should be two `global.set` instructions corresponding to `__asyncify_state` and `__asyncify_data`) size_t num_global_sets = 0; for (const auto &e : func->exprs) { if (e.type() == wabt::ExprType::GlobalSet) { wabt::Index index = ((wabt::GlobalSetExpr &)e).var.index(); switch (++num_global_sets) { case 1: std::cout << "#define MKXPZ_SANDBOX_ASYNCIFY_STATE_INDEX " << index << std::endl; break; case 2: std::cout << "#define MKXPZ_SANDBOX_ASYNCIFY_DATA_INDEX " << index << std::endl; break; default: std::cerr << "[indexer] error: asyncify_start_unwind function in " << argv[1] << " contains more than two global.set instructions" << std::endl; return 5; } } } // Verify that there were exactly two `global.set` instructions in this function if (num_global_sets != 2) { std::cerr << "[indexer] error: asyncify_start_unwind function in " << argv[1] << " contains less than two global.set instructions" << std::endl; return 5; } return 0; }