AbstractMachine.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. /*
  2. * Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibWasm/AbstractMachine/AbstractMachine.h>
  7. #include <LibWasm/AbstractMachine/BytecodeInterpreter.h>
  8. #include <LibWasm/AbstractMachine/Configuration.h>
  9. #include <LibWasm/AbstractMachine/Interpreter.h>
  10. #include <LibWasm/AbstractMachine/Validator.h>
  11. #include <LibWasm/Types.h>
  12. namespace Wasm {
  13. Optional<FunctionAddress> Store::allocate(ModuleInstance& module, Module::Function const& function)
  14. {
  15. FunctionAddress address { m_functions.size() };
  16. if (function.type().value() > module.types().size())
  17. return {};
  18. auto& type = module.types()[function.type().value()];
  19. m_functions.empend(WasmFunction { type, module, function });
  20. return address;
  21. }
  22. Optional<FunctionAddress> Store::allocate(HostFunction&& function)
  23. {
  24. FunctionAddress address { m_functions.size() };
  25. m_functions.empend(HostFunction { move(function) });
  26. return address;
  27. }
  28. Optional<TableAddress> Store::allocate(TableType const& type)
  29. {
  30. TableAddress address { m_tables.size() };
  31. Vector<Optional<Reference>> elements;
  32. elements.resize(type.limits().min());
  33. m_tables.empend(TableInstance { type, move(elements) });
  34. return address;
  35. }
  36. Optional<MemoryAddress> Store::allocate(MemoryType const& type)
  37. {
  38. MemoryAddress address { m_memories.size() };
  39. m_memories.empend(MemoryInstance { type });
  40. return address;
  41. }
  42. Optional<GlobalAddress> Store::allocate(GlobalType const& type, Value value)
  43. {
  44. GlobalAddress address { m_globals.size() };
  45. m_globals.append(GlobalInstance { move(value), type.is_mutable() });
  46. return address;
  47. }
  48. Optional<ElementAddress> Store::allocate(ValueType const& type, Vector<Reference> references)
  49. {
  50. ElementAddress address { m_elements.size() };
  51. m_elements.append(ElementInstance { type, move(references) });
  52. return address;
  53. }
  54. FunctionInstance* Store::get(FunctionAddress address)
  55. {
  56. auto value = address.value();
  57. if (m_functions.size() <= value)
  58. return nullptr;
  59. return &m_functions[value];
  60. }
  61. TableInstance* Store::get(TableAddress address)
  62. {
  63. auto value = address.value();
  64. if (m_tables.size() <= value)
  65. return nullptr;
  66. return &m_tables[value];
  67. }
  68. MemoryInstance* Store::get(MemoryAddress address)
  69. {
  70. auto value = address.value();
  71. if (m_memories.size() <= value)
  72. return nullptr;
  73. return &m_memories[value];
  74. }
  75. GlobalInstance* Store::get(GlobalAddress address)
  76. {
  77. auto value = address.value();
  78. if (m_globals.size() <= value)
  79. return nullptr;
  80. return &m_globals[value];
  81. }
  82. ElementInstance* Store::get(ElementAddress address)
  83. {
  84. auto value = address.value();
  85. if (m_elements.size() <= value)
  86. return nullptr;
  87. return &m_elements[value];
  88. }
  89. ErrorOr<void, ValidationError> AbstractMachine::validate(Module& module)
  90. {
  91. if (module.validation_status() != Module::ValidationStatus::Unchecked) {
  92. if (module.validation_status() == Module::ValidationStatus::Valid)
  93. return {};
  94. return ValidationError { module.validation_error() };
  95. }
  96. auto result = Validator {}.validate(module);
  97. if (result.is_error()) {
  98. module.set_validation_error(result.error().error_string);
  99. return result.release_error();
  100. }
  101. return {};
  102. }
  103. InstantiationResult AbstractMachine::instantiate(Module const& module, Vector<ExternValue> externs)
  104. {
  105. if (auto result = validate(const_cast<Module&>(module)); result.is_error())
  106. return InstantiationError { String::formatted("Validation failed: {}", result.error()) };
  107. auto main_module_instance_pointer = make<ModuleInstance>();
  108. auto& main_module_instance = *main_module_instance_pointer;
  109. Optional<InstantiationResult> instantiation_result;
  110. module.for_each_section_of_type<TypeSection>([&](TypeSection const& section) {
  111. main_module_instance.types() = section.types();
  112. });
  113. Vector<Value> global_values;
  114. Vector<Vector<Reference>> elements;
  115. ModuleInstance auxiliary_instance;
  116. // FIXME: Check that imports/extern match
  117. for (auto& entry : externs) {
  118. if (auto* ptr = entry.get_pointer<GlobalAddress>())
  119. auxiliary_instance.globals().append(*ptr);
  120. }
  121. BytecodeInterpreter interpreter;
  122. module.for_each_section_of_type<GlobalSection>([&](auto& global_section) {
  123. for (auto& entry : global_section.entries()) {
  124. Configuration config { m_store };
  125. if (m_should_limit_instruction_count)
  126. config.enable_instruction_count_limit();
  127. config.set_frame(Frame {
  128. auxiliary_instance,
  129. Vector<Value> {},
  130. entry.expression(),
  131. 1,
  132. });
  133. auto result = config.execute(interpreter);
  134. if (result.is_trap())
  135. instantiation_result = InstantiationError { String::formatted("Global value construction trapped: {}", result.trap().reason) };
  136. else
  137. global_values.append(result.values().first());
  138. }
  139. });
  140. if (instantiation_result.has_value())
  141. return instantiation_result.release_value();
  142. if (auto result = allocate_all_initial_phase(module, main_module_instance, externs, global_values); result.has_value())
  143. return result.release_value();
  144. module.for_each_section_of_type<ElementSection>([&](ElementSection const& section) {
  145. for (auto& segment : section.segments()) {
  146. Vector<Reference> references;
  147. for (auto& entry : segment.init) {
  148. Configuration config { m_store };
  149. if (m_should_limit_instruction_count)
  150. config.enable_instruction_count_limit();
  151. config.set_frame(Frame {
  152. main_module_instance,
  153. Vector<Value> {},
  154. entry,
  155. entry.instructions().size(),
  156. });
  157. auto result = config.execute(interpreter);
  158. if (result.is_trap()) {
  159. instantiation_result = InstantiationError { String::formatted("Element construction trapped: {}", result.trap().reason) };
  160. return IterationDecision::Continue;
  161. }
  162. for (auto& value : result.values()) {
  163. if (!value.type().is_reference()) {
  164. instantiation_result = InstantiationError { "Evaluated element entry is not a reference" };
  165. return IterationDecision::Continue;
  166. }
  167. auto reference = value.to<Reference>();
  168. if (!reference.has_value()) {
  169. instantiation_result = InstantiationError { "Evaluated element entry does not contain a reference" };
  170. return IterationDecision::Continue;
  171. }
  172. // FIXME: type-check the reference.
  173. references.prepend(reference.release_value());
  174. }
  175. }
  176. elements.append(move(references));
  177. }
  178. return IterationDecision::Continue;
  179. });
  180. if (instantiation_result.has_value())
  181. return instantiation_result.release_value();
  182. if (auto result = allocate_all_final_phase(module, main_module_instance, elements); result.has_value())
  183. return result.release_value();
  184. module.for_each_section_of_type<ElementSection>([&](ElementSection const& section) {
  185. size_t index = 0;
  186. for (auto& segment : section.segments()) {
  187. auto current_index = index;
  188. ++index;
  189. auto active_ptr = segment.mode.get_pointer<ElementSection::Active>();
  190. if (!active_ptr)
  191. continue;
  192. if (active_ptr->index.value() != 0) {
  193. instantiation_result = InstantiationError { "Non-zero table referenced by active element segment" };
  194. return IterationDecision::Break;
  195. }
  196. Configuration config { m_store };
  197. if (m_should_limit_instruction_count)
  198. config.enable_instruction_count_limit();
  199. config.set_frame(Frame {
  200. main_module_instance,
  201. Vector<Value> {},
  202. active_ptr->expression,
  203. 1,
  204. });
  205. auto result = config.execute(interpreter);
  206. if (result.is_trap()) {
  207. instantiation_result = InstantiationError { String::formatted("Element section initialisation trapped: {}", result.trap().reason) };
  208. return IterationDecision::Break;
  209. }
  210. auto d = result.values().first().to<i32>();
  211. if (!d.has_value()) {
  212. instantiation_result = InstantiationError { "Element section initialisation returned invalid table initial offset" };
  213. return IterationDecision::Break;
  214. }
  215. if (main_module_instance.tables().size() < 1) {
  216. instantiation_result = InstantiationError { "Element section initialisation references nonexistent table" };
  217. return IterationDecision::Break;
  218. }
  219. auto table_instance = m_store.get(main_module_instance.tables()[0]);
  220. if (current_index >= main_module_instance.elements().size()) {
  221. instantiation_result = InstantiationError { "Invalid element referenced by active element segment" };
  222. return IterationDecision::Break;
  223. }
  224. auto elem_instance = m_store.get(main_module_instance.elements()[current_index]);
  225. if (!table_instance || !elem_instance) {
  226. instantiation_result = InstantiationError { "Invalid element referenced by active element segment" };
  227. return IterationDecision::Break;
  228. }
  229. auto total_required_size = elem_instance->references().size() + d.value();
  230. if (table_instance->type().limits().max().value_or(total_required_size) < total_required_size) {
  231. instantiation_result = InstantiationError { "Table limit overflow in active element segment" };
  232. return IterationDecision::Break;
  233. }
  234. if (table_instance->elements().size() < total_required_size)
  235. table_instance->elements().resize(total_required_size);
  236. size_t i = 0;
  237. for (auto it = elem_instance->references().begin(); it < elem_instance->references().end(); ++i, ++it) {
  238. table_instance->elements()[i + d.value()] = *it;
  239. }
  240. }
  241. return IterationDecision::Continue;
  242. });
  243. if (instantiation_result.has_value())
  244. return instantiation_result.release_value();
  245. module.for_each_section_of_type<DataSection>([&](DataSection const& data_section) {
  246. for (auto& segment : data_section.data()) {
  247. segment.value().visit(
  248. [&](DataSection::Data::Active const& data) {
  249. Configuration config { m_store };
  250. if (m_should_limit_instruction_count)
  251. config.enable_instruction_count_limit();
  252. config.set_frame(Frame {
  253. main_module_instance,
  254. Vector<Value> {},
  255. data.offset,
  256. 1,
  257. });
  258. auto result = config.execute(interpreter);
  259. if (result.is_trap()) {
  260. instantiation_result = InstantiationError { String::formatted("Data section initialisation trapped: {}", result.trap().reason) };
  261. return;
  262. }
  263. size_t offset = 0;
  264. result.values().first().value().visit(
  265. [&](auto const& value) { offset = value; },
  266. [&](Reference const&) { instantiation_result = InstantiationError { "Data segment offset returned a reference" }; });
  267. if (instantiation_result.has_value() && instantiation_result->is_error())
  268. return;
  269. if (main_module_instance.memories().size() <= data.index.value()) {
  270. instantiation_result = InstantiationError {
  271. String::formatted("Data segment referenced out-of-bounds memory ({}) of max {} entries",
  272. data.index.value(), main_module_instance.memories().size())
  273. };
  274. return;
  275. }
  276. if (data.init.is_empty())
  277. return;
  278. auto address = main_module_instance.memories()[data.index.value()];
  279. if (auto instance = m_store.get(address)) {
  280. if (auto max = instance->type().limits().max(); max.has_value()) {
  281. if (*max < data.init.size() + offset) {
  282. instantiation_result = InstantiationError {
  283. String::formatted("Data segment attempted to write to out-of-bounds memory ({}) of max {} bytes",
  284. data.init.size() + offset, instance->type().limits().max().value())
  285. };
  286. return;
  287. }
  288. }
  289. if (instance->size() < data.init.size() + offset)
  290. instance->grow(data.init.size() + offset - instance->size());
  291. instance->data().overwrite(offset, data.init.data(), data.init.size());
  292. }
  293. },
  294. [&](DataSection::Data::Passive const&) {
  295. // FIXME: What do we do here?
  296. });
  297. }
  298. });
  299. module.for_each_section_of_type<StartSection>([&](StartSection const& section) {
  300. auto& functions = main_module_instance.functions();
  301. auto index = section.function().index();
  302. if (functions.size() <= index.value()) {
  303. instantiation_result = InstantiationError { String::formatted("Start section function referenced invalid index {} of max {} entries", index.value(), functions.size()) };
  304. return;
  305. }
  306. invoke(functions[index.value()], {});
  307. });
  308. if (instantiation_result.has_value())
  309. return instantiation_result.release_value();
  310. return InstantiationResult { move(main_module_instance_pointer) };
  311. }
  312. Optional<InstantiationError> AbstractMachine::allocate_all_initial_phase(Module const& module, ModuleInstance& module_instance, Vector<ExternValue>& externs, Vector<Value>& global_values)
  313. {
  314. Optional<InstantiationError> result;
  315. for (auto& entry : externs) {
  316. entry.visit(
  317. [&](FunctionAddress const& address) { module_instance.functions().append(address); },
  318. [&](TableAddress const& address) { module_instance.tables().append(address); },
  319. [&](MemoryAddress const& address) { module_instance.memories().append(address); },
  320. [&](GlobalAddress const& address) { module_instance.globals().append(address); });
  321. }
  322. // FIXME: What if this fails?
  323. for (auto& func : module.functions()) {
  324. auto address = m_store.allocate(module_instance, func);
  325. VERIFY(address.has_value());
  326. module_instance.functions().append(*address);
  327. }
  328. module.for_each_section_of_type<TableSection>([&](TableSection const& section) {
  329. for (auto& table : section.tables()) {
  330. auto table_address = m_store.allocate(table.type());
  331. VERIFY(table_address.has_value());
  332. module_instance.tables().append(*table_address);
  333. }
  334. });
  335. module.for_each_section_of_type<MemorySection>([&](MemorySection const& section) {
  336. for (auto& memory : section.memories()) {
  337. auto memory_address = m_store.allocate(memory.type());
  338. VERIFY(memory_address.has_value());
  339. module_instance.memories().append(*memory_address);
  340. }
  341. });
  342. module.for_each_section_of_type<GlobalSection>([&](GlobalSection const& section) {
  343. size_t index = 0;
  344. for (auto& entry : section.entries()) {
  345. auto address = m_store.allocate(entry.type(), move(global_values[index]));
  346. VERIFY(address.has_value());
  347. module_instance.globals().append(*address);
  348. index++;
  349. }
  350. });
  351. module.for_each_section_of_type<ExportSection>([&](ExportSection const& section) {
  352. for (auto& entry : section.entries()) {
  353. Variant<FunctionAddress, TableAddress, MemoryAddress, GlobalAddress, Empty> address {};
  354. entry.description().visit(
  355. [&](FunctionIndex const& index) {
  356. if (module_instance.functions().size() > index.value())
  357. address = FunctionAddress { module_instance.functions()[index.value()] };
  358. else
  359. dbgln("Failed to export '{}', the exported address ({}) was out of bounds (min: 0, max: {})", entry.name(), index.value(), module_instance.functions().size());
  360. },
  361. [&](TableIndex const& index) {
  362. if (module_instance.tables().size() > index.value())
  363. address = TableAddress { module_instance.tables()[index.value()] };
  364. else
  365. dbgln("Failed to export '{}', the exported address ({}) was out of bounds (min: 0, max: {})", entry.name(), index.value(), module_instance.tables().size());
  366. },
  367. [&](MemoryIndex const& index) {
  368. if (module_instance.memories().size() > index.value())
  369. address = MemoryAddress { module_instance.memories()[index.value()] };
  370. else
  371. dbgln("Failed to export '{}', the exported address ({}) was out of bounds (min: 0, max: {})", entry.name(), index.value(), module_instance.memories().size());
  372. },
  373. [&](GlobalIndex const& index) {
  374. if (module_instance.globals().size() > index.value())
  375. address = GlobalAddress { module_instance.globals()[index.value()] };
  376. else
  377. dbgln("Failed to export '{}', the exported address ({}) was out of bounds (min: 0, max: {})", entry.name(), index.value(), module_instance.globals().size());
  378. });
  379. if (address.has<Empty>()) {
  380. result = InstantiationError { "An export could not be resolved" };
  381. continue;
  382. }
  383. module_instance.exports().append(ExportInstance {
  384. entry.name(),
  385. move(address).downcast<FunctionAddress, TableAddress, MemoryAddress, GlobalAddress>(),
  386. });
  387. }
  388. });
  389. return result;
  390. }
  391. Optional<InstantiationError> AbstractMachine::allocate_all_final_phase(Module const& module, ModuleInstance& module_instance, Vector<Vector<Reference>>& elements)
  392. {
  393. module.for_each_section_of_type<ElementSection>([&](ElementSection const& section) {
  394. size_t index = 0;
  395. for (auto& segment : section.segments()) {
  396. auto address = m_store.allocate(segment.type, move(elements[index]));
  397. VERIFY(address.has_value());
  398. module_instance.elements().append(*address);
  399. index++;
  400. }
  401. });
  402. return {};
  403. }
  404. Result AbstractMachine::invoke(FunctionAddress address, Vector<Value> arguments)
  405. {
  406. BytecodeInterpreter interpreter;
  407. return invoke(interpreter, address, move(arguments));
  408. }
  409. Result AbstractMachine::invoke(Interpreter& interpreter, FunctionAddress address, Vector<Value> arguments)
  410. {
  411. Configuration configuration { m_store };
  412. if (m_should_limit_instruction_count)
  413. configuration.enable_instruction_count_limit();
  414. return configuration.call(interpreter, address, move(arguments));
  415. }
  416. void Linker::link(ModuleInstance const& instance)
  417. {
  418. populate();
  419. if (m_unresolved_imports.is_empty())
  420. return;
  421. HashTable<Name> resolved_imports;
  422. for (auto& import_ : m_unresolved_imports) {
  423. auto it = instance.exports().find_if([&](auto& export_) { return export_.name() == import_.name; });
  424. if (!it.is_end()) {
  425. resolved_imports.set(import_);
  426. m_resolved_imports.set(import_, it->value());
  427. }
  428. }
  429. for (auto& entry : resolved_imports)
  430. m_unresolved_imports.remove(entry);
  431. }
  432. void Linker::link(HashMap<Linker::Name, ExternValue> const& exports)
  433. {
  434. populate();
  435. if (m_unresolved_imports.is_empty())
  436. return;
  437. if (exports.is_empty())
  438. return;
  439. HashTable<Name> resolved_imports;
  440. for (auto& import_ : m_unresolved_imports) {
  441. auto export_ = exports.get(import_);
  442. if (export_.has_value()) {
  443. resolved_imports.set(import_);
  444. m_resolved_imports.set(import_, export_.value());
  445. }
  446. }
  447. for (auto& entry : resolved_imports)
  448. m_unresolved_imports.remove(entry);
  449. }
  450. AK::Result<Vector<ExternValue>, LinkError> Linker::finish()
  451. {
  452. populate();
  453. if (!m_unresolved_imports.is_empty()) {
  454. if (!m_error.has_value())
  455. m_error = LinkError {};
  456. for (auto& entry : m_unresolved_imports)
  457. m_error->missing_imports.append(entry.name);
  458. return *m_error;
  459. }
  460. if (m_error.has_value())
  461. return *m_error;
  462. // Result must be in the same order as the module imports
  463. Vector<ExternValue> exports;
  464. exports.ensure_capacity(m_ordered_imports.size());
  465. for (auto& import_ : m_ordered_imports)
  466. exports.unchecked_append(*m_resolved_imports.get(import_));
  467. return exports;
  468. }
  469. void Linker::populate()
  470. {
  471. if (!m_ordered_imports.is_empty())
  472. return;
  473. // There better be at most one import section!
  474. bool already_seen_an_import_section = false;
  475. m_module.for_each_section_of_type<ImportSection>([&](ImportSection const& section) {
  476. if (already_seen_an_import_section) {
  477. if (!m_error.has_value())
  478. m_error = LinkError {};
  479. m_error->other_errors.append(LinkError::InvalidImportedModule);
  480. return;
  481. }
  482. already_seen_an_import_section = true;
  483. for (auto& import_ : section.imports()) {
  484. m_ordered_imports.append({ import_.module(), import_.name(), import_.description() });
  485. m_unresolved_imports.set(m_ordered_imports.last());
  486. }
  487. });
  488. }
  489. }