Advertisement
Guest User

Untitled

a guest
May 5th, 2023
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.91 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. #define WASM_ARRAY_LEN(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
  78.  
  79. inline  wasm_functype_t* wasm_functype_new_4_1(wasm_valtype_t* p1, wasm_valtype_t* p2, wasm_valtype_t* p3,  
  80.                                                        wasm_valtype_t* p4, wasm_valtype_t* r)
  81. {
  82.   wasm_valtype_t* ps[4] = {p1, p2, p3, p4};
  83.   wasm_valtype_t* rs[1] = {r};
  84.   wasm_valtype_vec_t params, results;
  85.   wasm_valtype_vec_new(&params, WASM_ARRAY_LEN(ps), ps);
  86.   wasm_valtype_vec_new(&results, WASM_ARRAY_LEN(rs), rs);
  87.   return wasm_functype_new(&params, &results);
  88. }
  89.  
  90. wasm_functype_t *__ft_i32_out_i32 = NULL;
  91. wasm_functype_t *__ft_i32_i32_out_i32 = NULL;
  92. wasm_functype_t *__ft_i32_i32_i32_i32_out_i32 = NULL;
  93. wasm_functype_t *__ft_i32_i64_i32_i32_out_i32 = NULL;
  94.  
  95.  
  96. void Function_Types_Init()
  97. {
  98.     wasm_valtype_t* val_i32 =  wasm_valtype_new(WASM_I32);
  99.     wasm_valtype_t* val_i64 =  wasm_valtype_new(WASM_I64);
  100.  
  101.     // Binding function signatures ...
  102.     __ft_i32_out_i32  = wasm_functype_new_1_1(val_i32, val_i32);
  103. #if 0
  104.     __ft_i32_i32_out_i32 = wasm_functype_new_2_1(val_i32, val_i32, val_i32);
  105.     __ft_i32_i32_i32_i32_out_i32 = wasm_functype_new_4_1(val_i32, val_i32, val_i32, val_i32, val_i32);
  106.     __ft_i32_i64_i32_i32_out_i32  = wasm_functype_new_4_1(val_i32, val_i64, val_i32, val_i32, val_i32);
  107. #endif
  108.  
  109.     wasm_valtype_delete(val_i32);
  110.     wasm_valtype_delete(val_i64);
  111. }
  112.  
  113.  
  114. bool Analyze_Exports(wasm_module_t *module)
  115. {
  116.   // Extract export.
  117.   wasm_exporttype_vec_t export_types;
  118.  
  119.   wasm_module_exports(module, &export_types);
  120.  
  121.   if (export_types.size == 0)
  122.   {
  123.      Logf("Error : Module contains no exported functions.\n");
  124.      return false;
  125.   }
  126.  
  127.   // Scan for exports we're expecting.
  128.   for (auto i = 0; i < export_types.size; ++i)
  129.   {
  130.      const wasm_externtype_t *etype = wasm_exporttype_type(export_types.data[i]);
  131.  
  132.      if (wasm_externtype_kind(etype) == WASM_EXTERN_FUNC)
  133.      {
  134.        const wasm_externtype_t *type_info = wasm_exporttype_type(export_types.data[i]);
  135.  
  136.        if (wasm_externtype_kind(type_info) == WASM_EXTERN_FUNC)
  137.        {
  138.          const wasm_name_t *id = wasm_exporttype_name(export_types.data[i]);
  139.  
  140.          if (!strncmp("app_init", id->data, STRLEN("app_init")))
  141.          {
  142.             const wasm_functype_t* func_type = wasm_externtype_as_functype_const(type_info);
  143.  
  144.             // Check parameters ...
  145.             const wasm_valtype_vec_t *param_sig = wasm_functype_params(func_type);
  146.             bool param_match = false;
  147.  
  148.             if (param_sig->size == 1)
  149.             {
  150.                if (wasm_valtype_kind(param_sig->data[0]) == WASM_I32)
  151.                   param_match = true;
  152.             }
  153.  
  154.             // Check return sig ...
  155.             const wasm_valtype_vec_t *return_sig = wasm_functype_results(func_type);
  156.             bool return_sig_match = false;
  157.  
  158.             if (return_sig->size == 1)
  159.             {
  160.                if (wasm_valtype_kind(return_sig->data[0]) == WASM_I32)
  161.                   return_sig_match = true;
  162.             }
  163.  
  164.             if  (return_sig_match && param_match)
  165.                _export_init_fn = i;
  166.          }
  167.        }
  168.      }
  169.   }
  170.  
  171.   return _export_init_fn != -1;
  172. }
  173.  
  174. #define INF_WASM_VEC(x) { 1, &(x) }
  175.  
  176. int main()
  177. {
  178.   wasm_engine_t *engine = Engine_Init(true);
  179.  
  180. #ifdef INFINITY_PLUGIN_EXPORTS
  181.    const char *filename = "z:\\dev\\wasm\\wasmtime\\examples\\repro\\wasm\\build_d\\app.wasm";
  182. #else
  183.    const char *filename = ".\\examples\\repro\\wasm\\build_d\\app.wasm";
  184. #endif
  185.  
  186.   FILE* file = fopen(filename, "rb");
  187.  
  188.   if (!file)
  189.   {
  190.      Logf("Couldn't open wasm binary");
  191.      exit(0);
  192.   }
  193.  
  194.   fseek(file, 0L, SEEK_END);
  195.   size_t file_size = ftell(file);
  196.   fseek(file, 0L, SEEK_SET);
  197.   wasm_byte_vec_t wasm;
  198.   wasm_byte_vec_new_uninitialized(&wasm, file_size);
  199.   size_t count = fread(wasm.data, 1, file_size, file);
  200.   fclose(file);
  201.  
  202.   if (count != file_size)
  203.   {
  204.      Logf("Couldn't read wasm binary");
  205.      exit(0);
  206.   }
  207.  
  208.   wasmtime_error_t *error = NULL;
  209.  
  210.   // Now that we've got our binary web assembly we can compile our module.
  211.   Logf("Loaded module ... size : %zu\n", file_size);
  212.  
  213.   Logf("data[1] : %x\n", wasm.data[1]);
  214.  
  215.   wasm_store_t *store  = wasm_store_new(__engine);
  216.  
  217.   if (!store)
  218.   {
  219.      Logf("No store");
  220.      return false;
  221.   }
  222.  
  223.   wasm_module_t *module = store ? wasm_module_new(store, &wasm) : NULL;
  224.  
  225.   if (!module)
  226.   {
  227.       Logf("wasm_module_new failed.\n");
  228.       exit(1);
  229.   }
  230.  
  231.   wasm_byte_vec_delete(&wasm);
  232.  
  233.   if (error)
  234.     exit_with_error("failed to compile module", error, NULL);
  235.  
  236.   Logf("FT[a].\n");
  237.   Function_Types_Init();
  238.   Logf("FT[b].\n");
  239.  
  240.  
  241.   // With our callback function we can now instantiate the compiled module,
  242.   // giving us an instance we can then execute exports from. Note that
  243.   // instantiation can trap due to execution of the `app_init` function, so we need
  244.   // to handle that here too.
  245.   Logf("Instantiating module...\n");
  246.   wasm_trap_t *trap = NULL;
  247.  
  248.    wasm_extern_vec_t _imports = WASM_EMPTY_VEC;
  249.    wasm_instance_t *instance = wasm_instance_new(store, module, &_imports, &trap);
  250.  
  251.   if (error|| trap)
  252.     exit_with_error("failed to instantiate", error, trap);
  253.  
  254.    // Lookup our `run` export function
  255.    Logf("Extracting export...\n");
  256.  
  257.    bool ok = Analyze_Exports(module);
  258.  
  259.    if (!ok)
  260.    {
  261.       Logf("Exports not as expected.\n");
  262.       exit(1);
  263.    }
  264.  
  265.    wasm_extern_vec_t exports;
  266.    wasm_instance_exports(instance, &exports);
  267.    wasm_func_t* init_fn = wasm_extern_as_func(exports.data[_export_init_fn]);
  268.  
  269.    if (!init_fn)
  270.    {
  271.       Logf("Export function not as expected.\n");
  272.       exit(1);
  273.    }
  274.  
  275.  
  276.    wasm_val_t in;
  277.    in.kind = WASM_I32;
  278.    in.of.i32 = 1;
  279.  
  280.    wasm_val_t out;
  281.    out.kind = WASM_I32;
  282.    out.of.i32 = 0;
  283.  
  284.  
  285.    const wasm_val_vec_t _in = INF_WASM_VEC(in);
  286.    wasm_val_vec_t      _out = INF_WASM_VEC(out);
  287.  
  288.    trap = wasm_func_call(init_fn, &_in, &_out);
  289.  
  290.    if (trap)
  291.    {
  292.       exit_with_error("Function call fail :", NULL, trap);      
  293.       exit(1);
  294.    }
  295.    
  296.    if (out.of.i32 != (in.of.i32 + 1))
  297.       Logf("Incorrect result or test program has changed.");
  298.  
  299.    Logf("Input: %d\nOutput: %d\n",  in.of.i32, out.of.i32);
  300.  
  301.    // TODO: Clean up
  302.  
  303.    wasm_engine_delete(engine);
  304.  
  305.    return 0;
  306. }
  307.  
  308. static void exit_with_error(const char *message, wasmtime_error_t *error, wasm_trap_t *trap) {
  309.   Logf("Error: %s\n", message);
  310.   wasm_byte_vec_t error_message;
  311.   if (error) {
  312.     wasmtime_error_message(error, &error_message);
  313.     wasmtime_error_delete(error);
  314.   } else {
  315.     wasm_trap_message(trap, &error_message);
  316.     wasm_trap_delete(trap);
  317.   }
  318.   Logf("%.*s\n", (int) error_message.size, error_message.data);
  319.   wasm_byte_vec_delete(&error_message);
  320.   exit(1);
  321. }
  322.  
  323.  
  324. #if INF_DEBUG_PROBE_STANDALONE
  325. #ifdef INF_DEBUG
  326. #pragma comment(lib, "..\\..\\..\\..\\target\\debug\\wasmtime.dll.lib")
  327. #else
  328. #pragma comment(lib, "..\\..\\..\\..\\target\\release\\wasmtime.dll.lib")
  329. #endif
  330. #include <windows.h>
  331. int  WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
  332. {
  333.    main();
  334.    return 0;
  335. }
  336. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement