Эх сурвалжийг харах

Add the Windows COFF format support for AOT (#382)

Add the Windows COFF format support to wamr-compiler and iwasm can
load and excute it on Windows(X64) platform.

Signed-off-by: Wu Zhongmin <vwzm@live.com>
Signed-off-by: Xiaokang Qin <xiaokang.qxk@antgroup.com>

Co-authored-by: Wu Zhongmin <vwzm@live.com>
Xiaokang Qin 5 жил өмнө
parent
commit
728890103b

+ 10 - 3
core/iwasm/aot/aot_loader.c

@@ -156,6 +156,7 @@ GET_U64_FROM_ADDR(uint32 *addr)
 #define BIN_TYPE_ELF32B 1           /* 32-bit big endian */
 #define BIN_TYPE_ELF64L 2           /* 64-bit little endian */
 #define BIN_TYPE_ELF64B 3           /* 64-bit big endian */
+#define BIN_TYPE_COFF64 6           /* 64-bit little endian */
 
 /* Legal values for e_type (object file type). */
 #define E_TYPE_NONE     0           /* No file type */
@@ -174,6 +175,7 @@ GET_U64_FROM_ADDR(uint32 *addr)
 #define E_MACHINE_MIPS_X   51       /* Stanford MIPS-X */
 #define E_MACHINE_X86_64   62       /* AMD x86-64 architecture */
 #define E_MACHINE_XTENSA   94       /* Tensilica Xtensa Architecture */
+#define E_MACHINE_WIN_X86_64 0x8664 /* Windowx x86-64 architecture */
 
 /* Legal values for e_version */
 #define E_VERSION_CURRENT  1        /* Current version */
@@ -232,6 +234,7 @@ get_aot_file_target(AOTTargetInfo *target_info,
     char *machine_type = NULL;
     switch (target_info->e_machine) {
         case E_MACHINE_X86_64:
+        case E_MACHINE_WIN_X86_64:
             machine_type = "x86_64";
             break;
         case E_MACHINE_386:
@@ -973,7 +976,7 @@ load_object_data_sections(const uint8 **p_buf, const uint8 *buf_end,
             return false;
         }
 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
-#ifndef BH_PLATFORM_LINUX_SGX
+#if !defined(BH_PLATFORM_LINUX_SGX) && !defined(BH_PLATFORM_WINDOWS)
         /* address must be in the first 2 Gigabytes of
            the process address space */
         bh_assert((uintptr_t)data_sections[i].data < INT32_MAX);
@@ -1564,7 +1567,11 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end,
 
         if (!strcmp(group->section_name, ".rel.text")
             || !strcmp(group->section_name, ".rela.text")
-            || !strcmp(group->section_name, ".rela.literal")) {
+            || !strcmp(group->section_name, ".rela.literal")
+#ifdef BH_PLATFORM_WINDOWS
+            || !strcmp(group->section_name, ".text")
+#endif
+            ) {
             if (!do_text_relocation(module, group, error_buf, error_buf_size))
                 return false;
         }
@@ -1819,7 +1826,7 @@ create_sections(const uint8 *buf, uint32 size,
                         goto fail;
                     }
 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
-#ifndef BH_PLATFORM_LINUX_SGX
+#if !defined(BH_PLATFORM_LINUX_SGX) && !defined(BH_PLATFORM_WINDOWS)
                     /* address must be in the first 2 Gigabytes of
                        the process address space */
                     bh_assert((uintptr_t)aot_text < INT32_MAX);

+ 5 - 1
core/iwasm/aot/arch/aot_reloc_x86_64.c

@@ -11,6 +11,8 @@
 #define R_X86_64_32     10  /* Direct 32 bit zero extended */
 #define R_X86_64_32S    11  /* Direct 32 bit sign extended */
 
+#define IMAGE_REL_AMD64_REL32 4 /* The 32-bit relative address from the byte following the relocation. */
+
 void __divdi3();
 void __udivdi3();
 void __moddi3();
@@ -174,7 +176,9 @@ apply_relocation(AOTModule *module,
                               "Try using wamrc with --size-level=1 option.");
                 return false;
             }
-
+#ifdef BH_PLATFORM_WINDOWS
+            target_addr -= sizeof(int32);
+#endif
             *(int32*)(target_section_addr + reloc_offset) = (int32)target_addr;
             break;
         }

+ 59 - 8
core/iwasm/compilation/aot_emit_aot_file.c

@@ -1399,6 +1399,27 @@ aot_emit_relocation_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
     return true;
 }
 
+typedef uint32 U32;
+typedef int32  I32;
+typedef uint16 U16;
+typedef uint8  U8;
+
+struct coff_hdr {
+    U16 u16Machine;
+    U16 u16NumSections;
+    U32 u32DateTimeStamp;
+    U32 u32SymTblPtr;
+    U32 u32NumSymbols;
+    U16 u16PeHdrSize;
+    U16 u16Characs;
+};
+
+#define IMAGE_FILE_MACHINE_AMD64  0x8664
+#define IMAGE_FILE_MACHINE_I386   0x014c
+#define IMAGE_FILE_MACHINE_IA64   0x0200
+
+#define AOT_COFF_BIN_TYPE 6
+
 #define EI_NIDENT 16
 
 typedef uint32  elf32_word;
@@ -1487,7 +1508,8 @@ aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
     const uint8 *elf_buf = (uint8 *)LLVMGetBufferStart(obj_data->mem_buf);
     uint32 elf_size = (uint32)LLVMGetBufferSize(obj_data->mem_buf);
 
-    if (bin_type != LLVMBinaryTypeELF32L
+    if (bin_type != LLVMBinaryTypeCOFF
+        && bin_type != LLVMBinaryTypeELF32L
         && bin_type != LLVMBinaryTypeELF32B
         && bin_type != LLVMBinaryTypeELF64L
         && bin_type != LLVMBinaryTypeELF64B
@@ -1501,7 +1523,23 @@ aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
 
     obj_data->target_info.bin_type = bin_type - LLVMBinaryTypeELF32L;
 
-    if (bin_type == LLVMBinaryTypeELF32L
+    if (bin_type == LLVMBinaryTypeCOFF) {
+        struct coff_hdr  * coff_header;
+
+        if (!elf_buf || elf_size < sizeof(struct coff_hdr)) {
+            aot_set_last_error("invalid coff_hdr buffer.");
+            return false;
+        }
+        coff_header = (struct coff_hdr *)elf_buf;
+        obj_data->target_info.e_type = 1;
+        obj_data->target_info.e_machine = coff_header->u16Machine;
+        obj_data->target_info.e_version = 1;
+        obj_data->target_info.e_flags = 0;
+
+        if (coff_header->u16Machine == IMAGE_FILE_MACHINE_AMD64)
+            obj_data->target_info.bin_type = AOT_COFF_BIN_TYPE;
+    }
+    else if (bin_type == LLVMBinaryTypeELF32L
         || bin_type == LLVMBinaryTypeELF32B) {
         struct elf32_ehdr *elf_header;
         bool is_little_bin = bin_type == LLVMBinaryTypeELF32L;
@@ -1847,7 +1885,7 @@ fail:
 }
 
 static bool
-is_relocation_section(char *section_name)
+is_relocation_section_name(char *section_name)
 {
     return (!strcmp(section_name, ".rela.text")
             || !strcmp(section_name, ".rel.text")
@@ -1864,20 +1902,33 @@ is_relocation_section(char *section_name)
                         strlen(".rel.rodata.cst")));
 }
 
+static bool
+is_relocation_section(LLVMSectionIteratorRef sec_itr)
+{
+    uint32 count = 0;
+    char *name = (char *)LLVMGetSectionName(sec_itr);
+    if (name) {
+        if (is_relocation_section_name(name))
+            return true;
+        else if (!strncmp(name, ".text", strlen(".text"))
+                 && get_relocations_count(sec_itr, &count) && count > 0)
+            return true;
+    }
+    return false;
+}
+
 static bool
 get_relocation_groups_count(AOTObjectData *obj_data, uint32 *p_count)
 {
     uint32 count = 0;
     LLVMSectionIteratorRef sec_itr;
-    char *name;
 
     if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) {
         aot_set_last_error("llvm get section iterator failed.");
         return false;
     }
     while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
-        if ((name = (char *)LLVMGetSectionName(sec_itr))
-            && is_relocation_section(name)) {
+        if (is_relocation_section(sec_itr)) {
             count++;
         }
         LLVMMoveToNextSection(sec_itr);
@@ -1918,8 +1969,8 @@ aot_resolve_object_relocation_groups(AOTObjectData *obj_data)
         return false;
     }
     while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
-        if ((name = (char *)LLVMGetSectionName(sec_itr))
-            && is_relocation_section(name)) {
+        if (is_relocation_section(sec_itr)) {
+            name = (char *)LLVMGetSectionName(sec_itr);
             relocation_group->section_name = name;
             if (!aot_resolve_object_relocation_group(
                     obj_data,

+ 3 - 0
core/shared/platform/windows/win_memmap.c

@@ -19,6 +19,9 @@ void * os_mmap(void *hint, size_t size, int prot, int flags)
         /* integer overflow */
         return NULL;
 
+    if (request_size == 0)
+        request_size = page_size;
+
     if (prot & MMAP_PROT_EXEC) {
         if (prot & MMAP_PROT_WRITE)
             flProtect = PAGE_EXECUTE_READWRITE;