mkxp-z/libretro/indexer.cpp

104 lines
3.7 KiB
C++

/*
** indexer.cpp
**
** This file is part of mkxp.
**
** Copyright (C) 2013 - 2021 Amaryllis Kulla <ancurio@mapleshrine.eu>
**
** 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 <http://www.gnu.org/licenses/>.
*/
#include <fstream>
#include <iostream>
#include <vector>
#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<uint8_t> data;
{
std::ifstream f(argv[1]);
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;
}