Guest User

Untitled

a guest
May 4th, 2023
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.00 KB | None | 0 0
  1. /*
  2.  
  3. Wasmtime failure repro.
  4.  
  5. Author: Steve Williams, Advance Software
  6.  
  7. Compiled as a console app, Windows, functions as expect.
  8. Compiled as a Windows app, fails.
  9.  
  10. */
  11.  
  12. #include <assert.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <wasm.h>
  16. #include <wasmtime.h>
  17.  
  18. static void exit_with_error(const char *message, wasmtime_error_t *error, wasm_trap_t *trap);
  19.  
  20. #define STRLEN(x) (sizeof(x)-1)
  21.  
  22. wasm_engine_t *__engine = NULL;
  23.  
  24. wasm_engine_t *Engine_Init(bool debug_mode)
  25. {
  26.     // Configuring engine to support generating of DWARF info.
  27.     // lldb can be used to debug program via GDB/JIT interface provided by wasmtime.
  28.     wasm_config_t* wasm_config = wasm_config_new();
  29.     wasmtime_config_debug_info_set(wasm_config, debug_mode);
  30.     __engine = wasm_engine_new_with_config(wasm_config);
  31.     return __engine;
  32. }
  33.  
  34.  
  35. int _export_init_fn = -1;
  36.  
  37.  
  38. #if INF_DEBUG_PROBE_STANDALONE
  39. #include <windows.h>
  40. #include <stdio.h>
  41.  
  42. void Logf(const char *format, ...)
  43. {
  44.    va_list arg_list;
  45.    va_start(arg_list, format);
  46.  
  47.    // Do the format once to get the length.
  48. #if defined _WIN32 || defined _WIN64 /// COMPILER(MSVC)
  49.     int len = _vscprintf(format, arg_list);
  50. #else
  51.     char ch;
  52.     int len = vsnprintf(&ch, 1, format, arg_list);
  53.  
  54.     // We need to call va_end() and then va_start() again here, as the
  55.     // contents of args is undefined after the call to vsnprintf
  56.     // according to http://man.cx/snprintf(3)
  57.  
  58.     // Not calling va_end/va_start here happens to work on lots of systems, but fails on some systems e.g. 64 bit Linux.
  59.     va_end(arg_list);
  60.     va_start(arg_list, format);
  61. #endif
  62.  
  63.    // Ensure we have enough room.
  64.    char *tmp = malloc(len+1);
  65.  
  66.     vsprintf(tmp, format, arg_list);
  67.  
  68.     va_end(arg_list);
  69.  
  70.    MessageBoxA(NULL, tmp, "repro", MB_OK);
  71.    free(tmp);
  72. }
  73. #else
  74. #define Logf printf
  75. #endif
  76.  
  77.  
  78. bool Analyze_Exports(wasm_module_t *module)
  79. {
  80.   // Extract export.
  81.   wasm_exporttype_vec_t export_types;
  82.  
  83.   wasm_module_exports(module, &export_types);
  84.  
  85.   if (export_types.size == 0)
  86.   {
  87.      Logf("Error : Module contains no exported functions.\n");
  88.      return false;
  89.   }
  90.  
  91.   // Scan for exports we're expecting.
  92.   for (auto i = 0; i < export_types.size; ++i)
  93.   {
  94.      const wasm_externtype_t *etype = wasm_exporttype_type(export_types.data[i]);
  95.  
  96.      if (wasm_externtype_kind(etype) == WASM_EXTERN_FUNC)
  97.      {
  98.        const wasm_externtype_t *type_info = wasm_exporttype_type(export_types.data[i]);
  99.  
  100.        if (wasm_externtype_kind(type_info) == WASM_EXTERN_FUNC)
  101.        {
  102.          const wasm_name_t *id = wasm_exporttype_name(export_types.data[i]);
  103.  
  104.          if (!strncmp("app_init", id->data, STRLEN("app_init")))
  105.          {
  106.             const wasm_functype_t* func_type = wasm_externtype_as_functype_const(type_info);
  107.  
  108.             // Check parameters ...
  109.             const wasm_valtype_vec_t *param_sig = wasm_functype_params(func_type);
  110.             bool param_match = false;
  111.  
  112.             if (param_sig->size == 1)
  113.             {
  114.                if (wasm_valtype_kind(param_sig->data[0]) == WASM_I32)
  115.                   param_match = true;
  116.             }
  117.  
  118.             // Check return sig ...
  119.             const wasm_valtype_vec_t *return_sig = wasm_functype_results(func_type);
  120.             bool return_sig_match = false;
  121.  
  122.             if (return_sig->size == 1)
  123.             {
  124.                if (wasm_valtype_kind(return_sig->data[0]) == WASM_I32)
  125.                   return_sig_match = true;
  126.             }
  127.  
  128.             if  (return_sig_match && param_match)
  129.                _export_init_fn = i;
  130.          }
  131.        }
  132.      }
  133.   }
  134.  
  135.   return _export_init_fn != -1;
  136. }
  137.  
  138. #define INF_WASM_VEC(x) { 1, &(x) }
  139.  
  140. int main()
  141. {
  142.   wasm_engine_t *engine = Engine_Init(true);
  143.  
  144.   FILE* file = fopen("..\\..\\examples\\repro\\wasm\\build_d\\app.wasm", "rb");
  145.   assert(file != NULL);
  146.   fseek(file, 0L, SEEK_END);
  147.   size_t file_size = ftell(file);
  148.   fseek(file, 0L, SEEK_SET);
  149.   wasm_byte_vec_t wasm;
  150.   wasm_byte_vec_new_uninitialized(&wasm, file_size);
  151.   assert(fread(wasm.data, file_size, 1, file) == 1);
  152.   fclose(file);
  153.   wasmtime_error_t *error = NULL;
  154.  
  155.   // Now that we've got our binary web assembly we can compile our module.
  156.   Logf("Loaded module ... size : %d\n", file_size);
  157.  
  158.   wasm_store_t *store  = wasm_store_new(__engine);
  159.  
  160.   if (!store)
  161.   {
  162.      Logf("No store");
  163.      return false;
  164.   }
  165.  
  166.   wasm_module_t *module = store ? wasm_module_new(store, &wasm) : NULL;
  167.  
  168.   if (!module)
  169.   {
  170.       Logf("wasm_module_new failed.\n");
  171.       exit(1);
  172.   }
  173.  
  174.   wasm_byte_vec_delete(&wasm);
  175.  
  176.   if (error)
  177.     exit_with_error("failed to compile module", error, NULL);
  178.  
  179.  
  180.   // With our callback function we can now instantiate the compiled module,
  181.   // giving us an instance we can then execute exports from. Note that
  182.   // instantiation can trap due to execution of the `app_init` function, so we need
  183.   // to handle that here too.
  184.   Logf("Instantiating module...\n");
  185.   wasm_trap_t *trap = NULL;
  186.  
  187.    wasm_extern_vec_t _imports = WASM_EMPTY_VEC;
  188.    wasm_instance_t *instance = wasm_instance_new(store, module, &_imports, &trap);
  189.  
  190.   if (error|| trap)
  191.     exit_with_error("failed to instantiate", error, trap);
  192.  
  193.    // Lookup our `run` export function
  194.    Logf("Extracting export...\n");
  195.  
  196.    bool ok = Analyze_Exports(module);
  197.  
  198.    if (!ok)
  199.    {
  200.       Logf("Exports not as expected.\n");
  201.       exit(1);
  202.    }
  203.  
  204.    wasm_extern_vec_t exports;
  205.    wasm_instance_exports(instance, &exports);
  206.    wasm_func_t* init_fn = wasm_extern_as_func(exports.data[_export_init_fn]);
  207.  
  208.    if (!init_fn)
  209.    {
  210.       Logf(stderr, "Export function not as expected.\n");
  211.       exit(1);
  212.    }
  213.  
  214.  
  215.    wasm_val_t in;
  216.    in.kind = WASM_I32;
  217.    in.of.i32 = 1;
  218.  
  219.    wasm_val_t out;
  220.    out.kind = WASM_I32;
  221.    out.of.i32 = 0;
  222.  
  223.  
  224.    const wasm_val_vec_t _in = INF_WASM_VEC(in);
  225.    wasm_val_vec_t      _out = INF_WASM_VEC(out);
  226.  
  227.    trap = wasm_func_call(init_fn, &_in, &_out);
  228.  
  229.    if (trap)
  230.    {
  231.       exit_with_error("Function call fail :", NULL, trap);      
  232.       exit(1);
  233.    }
  234.    
  235.  
  236.    Logf("Input: %d\nOutput: %d\n",  in.of.i32, out.of.i32);
  237.  
  238.    // TODO: Clean up
  239.  
  240.    wasm_engine_delete(engine);
  241.  
  242.    return 0;
  243. }
  244.  
  245. static void exit_with_error(const char *message, wasmtime_error_t *error, wasm_trap_t *trap) {
  246.   Logf(stderr, "error: %s\n", message);
  247.   wasm_byte_vec_t error_message;
  248.   if (error != NULL) {
  249.     wasmtime_error_message(error, &error_message);
  250.     wasmtime_error_delete(error);
  251.   } else {
  252.     wasm_trap_message(trap, &error_message);
  253.     wasm_trap_delete(trap);
  254.   }
  255.   Logf("%.*s\n", (int) error_message.size, error_message.data);
  256.   wasm_byte_vec_delete(&error_message);
  257.   exit(1);
  258. }
  259.  
  260.  
  261. #if INF_DEBUG_PROBE_STANDALONE
  262. #ifdef INF_DEBUG
  263. #pragma comment(lib, "..\\..\\..\\..\\target\\debug\\wasmtime.dll.lib")
  264. #else
  265. #pragma comment(lib, "..\\..\\..\\..\\target\\release\\wasmtime.dll.lib")
  266. #endif
  267. #include <windows.h>
  268. int  WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
  269. {
  270.    main();
  271.    return 0;
  272. }
  273. #endif
Advertisement
Add Comment
Please, Sign In to add comment