bytecodealliance / wasm-micro-runtime

WebAssembly Micro Runtime (WAMR)
Apache License 2.0
4.94k stars 623 forks source link

Run AOT failed on windows #2235

Open luciouskami opened 1 year ago

luciouskami commented 1 year ago

Os:windows 10 wamrc_ver:latest x86 toolchain:emcc llvm_ver:15.X

    add_ldflags({"-s WASM=1", "-s STANDALONE_WASM","-s EXPORTED_FUNCTIONS=['_main']", "-s NODEJS_CATCH_EXIT=0", "-s NODEJS_CATCH_REJECTION=0"})
    set_optimize("fastest")
#include <iostream>

int main()
{

    std::cout<<"Hello, world!\n";
    return 0;

}

cmooand:wamrc --target-abi=msvc --target=i386 -o test.aot test.wasm


Create AoT compiler with:
  target:        i386
  target cpu:
  target triple: i386-pc-windows-msvc
  cpu features:
  opt level:     3
  size level:    1
  output format: AoT file
Compile success, file test.aot was generated.

iwasm.exe test.aot
Load relocation section failed: invalid relocation type 20.
wenyongh commented 1 year ago

Hi, the relocations for Windows x86-32 haven't been implemented yet, I tried to enable the relocation type 20 as you mentioned, see win_x86_32.zip, could you have a try?

luciouskami commented 1 year ago

test.zip

Hi, the relocations for Windows x86-32 haven't been implemented yet, I tried to enable the relocation type 20 as you mentioned, see win_x86_32.zip, could you have a try?

Hi I've tried,but failed. toolchain:msvc-2022-x86 emcc

add_ldflags({"-s WASM=1", "-s STANDALONE_WASM","-s EXPORTED_FUNCTIONS=['_main']", "-s NODEJS_CATCH_EXIT=0", "-s NODEJS_CATCH_REJECTION=0"})

test.cpp:


#include <stdio.h>
#include <chrono>
#include <iostream>
#include <filesystem>
#include <time.h>
#include "3rd/fmt/include/fmt/core.h"

extern "C" 
{

    //use for loop 
    int add(int a, int b) {
    return a + b;
    }

    int main() {

    // std::cout << "hello fmt"<<fmt::format("{} {}", "hello", "world!");
    std::cout << "hello world!\n";
    std::string s = fmt::format("fmt: {} {}.", "hello", "world");
    fmt::print("fmt Hello, world!\n");
    std::cout << s<<"\n";

    const auto v_start_time = std::chrono::high_resolution_clock::now();
    uint64_t a = 0;
    for (uint64_t i = 0; i < 20000000000; i++) {
        a += add(i, i + 1);
    }

    auto v_end_time = std::chrono::high_resolution_clock::now();
    auto cost_time = std::chrono::duration_cast<std::chrono::milliseconds>(v_end_time - v_start_time).count();
    std::cout << "a:" << a <<"add time: " <<cost_time << std::endl;

    return 0;

    }
}

runlog:


AOT module load failed: resolve symbol _aot_func#384 failed
wenyongh commented 1 year ago

It seems that the function symbol generated in Windows 32bit starts with '_', could you modify the aot_loader.c:

diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c
index 5345fb2d..9a431d02 100644
--- a/core/iwasm/aot/aot_loader.c
+++ b/core/iwasm/aot/aot_loader.c
@@ -1947,6 +1947,19 @@ do_text_relocation(AOTModule *module, AOTRelocationGroup *group,
             }
             symbol_addr = module->func_ptrs[func_index];
         }
+#if defined(BH_PLATFORM_WINDOWS) && defined(BUILD_TARGET_X86_32)
+        else if (!strncmp(symbol, "_" AOT_FUNC_PREFIX,
+                          strlen("_" AOT_FUNC_PREFIX))) {
+            p = symbol + strlen("_" AOT_FUNC_PREFIX);
+            if (*p == '\0'
+                || (func_index = (uint32)atoi(p)) > module->func_count) {
+                set_error_buf_v(error_buf, error_buf_size, "invalid symbol %s",
+                                symbol);
+                goto check_symbol_fail;
+            }
+            symbol_addr = module->func_ptrs[func_index];
+        }
+#endif
         else if (!strcmp(symbol, ".text")) {
             symbol_addr = module->code;
         }
luciouskami commented 1 year ago

It seems that the function symbol generated in Windows 32bit starts with '_', could you modify the aot_loader.c:

diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c
index 5345fb2d..9a431d02 100644
--- a/core/iwasm/aot/aot_loader.c
+++ b/core/iwasm/aot/aot_loader.c
@@ -1947,6 +1947,19 @@ do_text_relocation(AOTModule *module, AOTRelocationGroup *group,
             }
             symbol_addr = module->func_ptrs[func_index];
         }
+#if defined(BH_PLATFORM_WINDOWS) && defined(BUILD_TARGET_X86_32)
+        else if (!strncmp(symbol, "_" AOT_FUNC_PREFIX,
+                          strlen("_" AOT_FUNC_PREFIX))) {
+            p = symbol + strlen("_" AOT_FUNC_PREFIX);
+            if (*p == '\0'
+                || (func_index = (uint32)atoi(p)) > module->func_count) {
+                set_error_buf_v(error_buf, error_buf_size, "invalid symbol %s",
+                                symbol);
+                goto check_symbol_fail;
+            }
+            symbol_addr = module->func_ptrs[func_index];
+        }
+#endif
         else if (!strcmp(symbol, ".text")) {
             symbol_addr = module->code;
         }

Sorry,my bad.emcc's toolchain is clang,not msvc.

runlog:

AOT module load failed: resolve symbol __aulldiv failed
wenyongh commented 1 year ago

Seems that __aulldiv is a compiler-rt function, could you try declaring it in aot_reloc_x86_32.c and then REG_SYM it:

https://github.com/bytecodealliance/wasm-micro-runtime/blob/main/core/iwasm/aot/arch/aot_reloc_x86_32.c#L52-L55


void __aulldiv();

static SymbolMap target_sym_map[] = {
    ...
    REG_SYM(__aulldiv),
};
luciouskami commented 1 year ago

Seems that __aulldiv is a compiler-rt function, could you try declaring it in aot_reloc_x86_32.c and then REG_SYM it:

https://github.com/bytecodealliance/wasm-micro-runtime/blob/main/core/iwasm/aot/arch/aot_reloc_x86_32.c#L52-L55

void __aulldiv();

static SymbolMap target_sym_map[] = {
    ...
    REG_SYM(__aulldiv),
};

ok.

static uint64
__aulldiv(uint64 a, uint64 b)
{
    return a / b;
}
#endif

/* clang-format off */
static SymbolMap target_sym_map[] = {
    REG_COMMON_SYMBOLS
    /* compiler-rt symbols that come from compiler(e.g. gcc) */
    REG_SYM(__divdi3),
    REG_SYM(__udivdi3),
    REG_SYM(__moddi3),
    REG_SYM(__umoddi3),
    REG_SYM(__aulldiv)
};

runlog:

Load relocation section failed: invalid relocation type 6.

I'm confused about that,why the type changed

wenyongh commented 1 year ago

In aot_reloc_x86_32.c, try adding #define IMAGE_REL_I386_REL32 6 and then:

     switch (reloc_type) {
+#if !defined(BH_PLATFORM_WINDOWS)
         case R_386_32:
+#else
+        case IMAGE_REL_I386_DIR32:
+#endif
luciouskami commented 1 year ago
case IMAGE_REL_I386_DIR32:
apply_relocation(AOTModule *module, uint8 *target_section_addr,
                 uint32 target_section_size, uint64 reloc_offset,
                 int64 reloc_addend, uint32 reloc_type, void *symbol_addr,
                 int32 symbol_index, char *error_buf, uint32 error_buf_size)
{
    switch (reloc_type) {
#if !defined(BH_PLATFORM_WINDOWS)
        case R_386_32:
#else
        case IMAGE_REL_I386_DIR32:
        {
            intptr_t value;

            CHECK_RELOC_OFFSET(sizeof(void *));
            value = *(intptr_t *)(target_section_addr + (uint32)reloc_offset);
            *(uintptr_t *)(target_section_addr + reloc_offset) =
                (uintptr_t)symbol_addr + (intptr_t)reloc_addend
                + value; /* S + A */
            break;
        }

#endif

#if !defined(BH_PLATFORM_WINDOWS)
        /*
         * Handle R_386_PLT32 like R_386_PC32 since it should be able to reach
         * any 32 bit address
         */
        case R_386_PLT32:
        case R_386_PC32:
#else
        case IMAGE_REL_I386_REL32:
#endif
        {
            int32 value;

            CHECK_RELOC_OFFSET(sizeof(void *));
            value = *(int32 *)(target_section_addr + (uint32)reloc_offset);
            *(uint32 *)(target_section_addr + (uint32)reloc_offset) =
                (uint32)((uintptr_t)symbol_addr + (intptr_t)reloc_addend
                         - (uintptr_t)(target_section_addr
                                       + (uint32)reloc_offset)
                         + value); /* S + A - P */
            break;
        }

and

    REG_SYM(__aulldiv),
    REG_SYM(__alldiv),
    REG_SYM(__allrem)

If define IMAGE_REL_I386_REL32 6, which would be 20 ? tried,then exit without output nor log

another:

define IMAGE_REL_I386_REL32 6

apply_relocation(AOTModule *module, uint8 *target_section_addr,
                 uint32 target_section_size, uint64 reloc_offset,
                 int64 reloc_addend, uint32 reloc_type, void *symbol_addr,
                 int32 symbol_index, char *error_buf, uint32 error_buf_size)
{
    switch (reloc_type) {
#if !defined(BH_PLATFORM_WINDOWS)
        case R_386_32:
#else
        case IMAGE_REL_I386_DIR32:
#endif
        {
            intptr_t value;

            CHECK_RELOC_OFFSET(sizeof(void *));
            value = *(intptr_t *)(target_section_addr + (uint32)reloc_offset);
            *(uintptr_t *)(target_section_addr + reloc_offset) =
                (uintptr_t)symbol_addr + (intptr_t)reloc_addend
                + value; /* S + A */
            break;
        }

#if !defined(BH_PLATFORM_WINDOWS)
        /*
         * Handle R_386_PLT32 like R_386_PC32 since it should be able to reach
         * any 32 bit address
         */
        case R_386_PLT32:
        case R_386_PC32:
#else
        //case IMAGE_REL_I386_REL32:
#endif
        //{
        //    int32 value;

        //    CHECK_RELOC_OFFSET(sizeof(void *));
        //    value = *(int32 *)(target_section_addr + (uint32)reloc_offset);
        //    *(uint32 *)(target_section_addr + (uint32)reloc_offset) =
        //        (uint32)((uintptr_t)symbol_addr + (intptr_t)reloc_addend
        //                 - (uintptr_t)(target_section_addr
        //                               + (uint32)reloc_offset)
        //                 + value); /* S + A - P */
        //    break;
        //}

runlog:

Load relocation section failed: invalid relocation type 20.
wenyongh commented 1 year ago

Hi, refer to below link for Windows x86-32 relocations: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#intel-386-processors

It seems the implementation of the two relocation types should be like: IMAGE_REL_I386_REL32 (=20): refer to the patch win_x86_32.zip IMAGE_REL_I386_DIR32 (=6): refer to the patch:

     switch (reloc_type) {
+#if !defined(BH_PLATFORM_WINDOWS)
         case R_386_32:
+#else
+        case IMAGE_REL_I386_DIR32:
+#endif
wenyongh commented 1 year ago

@Waitforomething2023 Thanks for reporting the issues, I uploaded PR #2285 to fix them, could you help check whether there is anything missing? Thanks.