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

wamrc: Fix windows relocation to `aot_func_internal#n` (#2474)

AOT relocation to aot_func_internal#n is generated by wamrc --bounds-checks=1.
Resolve the issue by applying the relocation in the compilation stage by wamrc and
don't generate these relocations in the AOT file.

Fixes #2471.
Wenyong Huang 2 жил өмнө
parent
commit
6716c23dd1

+ 3 - 0
core/iwasm/aot/arch/aot_reloc_x86_32.c

@@ -164,6 +164,9 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr,
                 (uint32)((uintptr_t)symbol_addr + (intptr_t)reloc_addend
                          - (uintptr_t)(target_section_addr
                                        + (uint32)reloc_offset)
+#if defined(BH_PLATFORM_WINDOWS)
+                         - sizeof(int32)
+#endif
                          + value); /* S + A - P */
             break;
         }

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

@@ -242,7 +242,7 @@ apply_relocation(AOTModule *module, uint8 *target_section_addr,
                      - (uintptr_t)(target_section_addr + reloc_offset));
             }
             else {
-                target_addr = (intptr_t) /* L + A - P */
+                target_addr = (intptr_t) /* S + A - P */
                     ((uintptr_t)symbol_addr + reloc_addend
                      - (uintptr_t)(target_section_addr + reloc_offset));
             }

+ 138 - 6
core/iwasm/compilation/aot_emit_aot_file.c

@@ -93,7 +93,10 @@ check_utf8_str(const uint8 *str, uint32 len)
 /* Internal function in object file */
 typedef struct AOTObjectFunc {
     char *func_name;
+    /* text offset of aot_func#n */
     uint64 text_offset;
+    /* text offset of aot_func_internal#n */
+    uint64 text_offset_of_aot_func_internal;
 } AOTObjectFunc;
 
 /* Symbol table list node */
@@ -637,13 +640,33 @@ get_relocation_size(AOTRelocation *relocation, bool is_32bin)
 }
 
 static uint32
-get_relocations_size(AOTRelocation *relocations, uint32 relocation_count,
+get_relocations_size(AOTObjectData *obj_data,
+                     AOTRelocationGroup *relocation_group,
+                     AOTRelocation *relocations, uint32 relocation_count,
                      bool is_32bin)
 {
     AOTRelocation *relocation = relocations;
     uint32 size = 0, i;
 
     for (i = 0; i < relocation_count; i++, relocation++) {
+        /* ignore the relocations to aot_func_internal#n in text section
+           for windows platform since they will be applied in
+           aot_emit_text_section */
+        if (!strcmp(relocation_group->section_name, ".text")
+            && !strncmp(relocation->symbol_name, AOT_FUNC_INTERNAL_PREFIX,
+                        strlen(AOT_FUNC_INTERNAL_PREFIX))
+            && ((!strncmp(obj_data->comp_ctx->target_arch, "x86_64", 6)
+                 /* Windows AOT_COFF64_BIN_TYPE */
+                 && obj_data->target_info.bin_type == 6
+                 /* IMAGE_REL_AMD64_REL32 in windows x86_64 */
+                 && relocation->relocation_type == 4)
+                || (!strncmp(obj_data->comp_ctx->target_arch, "i386", 4)
+                    /* Windows AOT_COFF32_BIN_TYPE */
+                    && obj_data->target_info.bin_type == 4
+                    /* IMAGE_REL_I386_REL32 in windows x86_32 */
+                    && relocation->relocation_type == 20))) {
+            continue;
+        }
         size = align_uint(size, 4);
         size += get_relocation_size(relocation, is_32bin);
     }
@@ -651,19 +674,22 @@ get_relocations_size(AOTRelocation *relocations, uint32 relocation_count,
 }
 
 static uint32
-get_relocation_group_size(AOTRelocationGroup *relocation_group, bool is_32bin)
+get_relocation_group_size(AOTObjectData *obj_data,
+                          AOTRelocationGroup *relocation_group, bool is_32bin)
 {
     uint32 size = 0;
     /* section name index + relocation count + relocations */
     size += (uint32)sizeof(uint32);
     size += (uint32)sizeof(uint32);
-    size += get_relocations_size(relocation_group->relocations,
+    size += get_relocations_size(obj_data, relocation_group,
+                                 relocation_group->relocations,
                                  relocation_group->relocation_count, is_32bin);
     return size;
 }
 
 static uint32
-get_relocation_groups_size(AOTRelocationGroup *relocation_groups,
+get_relocation_groups_size(AOTObjectData *obj_data,
+                           AOTRelocationGroup *relocation_groups,
                            uint32 relocation_group_count, bool is_32bin)
 {
     AOTRelocationGroup *relocation_group = relocation_groups;
@@ -671,7 +697,7 @@ get_relocation_groups_size(AOTRelocationGroup *relocation_groups,
 
     for (i = 0; i < relocation_group_count; i++, relocation_group++) {
         size = align_uint(size, 4);
-        size += get_relocation_group_size(relocation_group, is_32bin);
+        size += get_relocation_group_size(obj_data, relocation_group, is_32bin);
     }
     return size;
 }
@@ -864,7 +890,7 @@ get_relocation_section_size(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
 
     /* relocation group count + symbol_table + relocation groups */
     return (uint32)sizeof(uint32) + symbol_table_size
-           + get_relocation_groups_size(relocation_groups,
+           + get_relocation_groups_size(obj_data, relocation_groups,
                                         relocation_group_count,
                                         is_32bit_binary(obj_data));
 }
@@ -1734,6 +1760,10 @@ aot_emit_text_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
     uint32 section_size = get_text_section_size(obj_data);
     uint32 offset = *p_offset;
     uint8 placeholder = 0;
+    AOTRelocationGroup *relocation_group;
+    AOTRelocation *relocation;
+    uint32 i, j, relocation_count;
+    uint8 *text;
 
     *p_offset = offset = align_uint(offset, 4);
 
@@ -1747,6 +1777,8 @@ aot_emit_text_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
             EMIT_BUF(&placeholder, 1);
     }
 
+    text = buf + offset;
+
     if (obj_data->text_size > 0) {
         EMIT_BUF(obj_data->text, obj_data->text_size);
         while (offset & 3)
@@ -1768,6 +1800,67 @@ aot_emit_text_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
         return false;
     }
 
+    /* apply relocations to aot_func_internal#n in text section for
+       windows platform */
+    if ((!strncmp(obj_data->comp_ctx->target_arch, "x86_64", 6)
+         /* Windows AOT_COFF64_BIN_TYPE */
+         && obj_data->target_info.bin_type == 6)
+        || (!strncmp(obj_data->comp_ctx->target_arch, "i386", 4)
+            /* Windows AOT_COFF32_BIN_TYPE */
+            && obj_data->target_info.bin_type == 4)) {
+        relocation_group = obj_data->relocation_groups;
+        for (i = 0; i < obj_data->relocation_group_count;
+             i++, relocation_group++) {
+            /* relocation in text section */
+            if (!strcmp(relocation_group->section_name, ".text")) {
+                relocation = relocation_group->relocations;
+                relocation_count = relocation_group->relocation_count;
+                for (j = 0; j < relocation_count; j++) {
+                    /* relocation to aot_func_internal#n */
+                    if (str_starts_with(relocation->symbol_name,
+                                        AOT_FUNC_INTERNAL_PREFIX)
+                        && ((obj_data->target_info.bin_type
+                                 == 6 /* AOT_COFF64_BIN_TYPE */
+                             && relocation->relocation_type
+                                    == 4 /* IMAGE_REL_AMD64_REL32 */)
+                            || (obj_data->target_info.bin_type
+                                    == 4 /* AOT_COFF32_BIN_TYPE */
+                                && obj_data->target_info.bin_type
+                                       == 20 /* IMAGE_REL_I386_REL32 */))) {
+                        uint32 func_idx =
+                            atoi(relocation->symbol_name
+                                 + strlen(AOT_FUNC_INTERNAL_PREFIX));
+                        uint64 text_offset, reloc_offset, reloc_addend;
+
+                        bh_assert(func_idx < obj_data->func_count);
+
+                        text_offset = obj_data->funcs[func_idx]
+                                          .text_offset_of_aot_func_internal;
+                        reloc_offset = relocation->relocation_offset;
+                        reloc_addend = relocation->relocation_addend;
+                        /* S + A - P */
+                        *(uint32 *)(text + reloc_offset) =
+                            (uint32)(text_offset + reloc_addend - reloc_offset
+                                     - 4);
+
+                        /* remove current relocation as it has been applied */
+                        if (j < relocation_count - 1) {
+                            uint32 move_size =
+                                (uint32)(sizeof(AOTRelocation)
+                                         * (relocation_count - 1 - j));
+                            bh_memmove_s(relocation, move_size, relocation + 1,
+                                         move_size);
+                        }
+                        relocation_group->relocation_count--;
+                    }
+                    else {
+                        relocation++;
+                    }
+                }
+            }
+        }
+    }
+
     *p_offset = offset;
 
     return true;
@@ -2773,6 +2866,7 @@ aot_resolve_functions(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
     while (!LLVMObjectFileIsSymbolIteratorAtEnd(obj_data->binary, sym_itr)) {
         if ((name = (char *)LLVMGetSymbolName(sym_itr))
             && str_starts_with(name, prefix)) {
+            /* symbol aot_func#n */
             func_index = (uint32)atoi(name + strlen(prefix));
             if (func_index < obj_data->func_count) {
                 LLVMSectionIteratorRef contain_section;
@@ -2807,6 +2901,44 @@ aot_resolve_functions(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
                 }
             }
         }
+        else if ((name = (char *)LLVMGetSymbolName(sym_itr))
+                 && str_starts_with(name, AOT_FUNC_INTERNAL_PREFIX)) {
+            /* symbol aot_func_internal#n */
+            func_index = (uint32)atoi(name + strlen(AOT_FUNC_INTERNAL_PREFIX));
+            if (func_index < obj_data->func_count) {
+                LLVMSectionIteratorRef contain_section;
+                char *contain_section_name;
+
+                func = obj_data->funcs + func_index;
+
+                if (!(contain_section = LLVMObjectFileCopySectionIterator(
+                          obj_data->binary))) {
+                    aot_set_last_error("llvm get section iterator failed.");
+                    LLVMDisposeSymbolIterator(sym_itr);
+                    return false;
+                }
+                LLVMMoveToContainingSection(contain_section, sym_itr);
+                contain_section_name =
+                    (char *)LLVMGetSectionName(contain_section);
+                LLVMDisposeSectionIterator(contain_section);
+
+                if (!strcmp(contain_section_name, ".text.unlikely.")) {
+                    func->text_offset_of_aot_func_internal =
+                        align_uint(obj_data->text_size, 4)
+                        + LLVMGetSymbolAddress(sym_itr);
+                }
+                else if (!strcmp(contain_section_name, ".text.hot.")) {
+                    func->text_offset_of_aot_func_internal =
+                        align_uint(obj_data->text_size, 4)
+                        + align_uint(obj_data->text_unlikely_size, 4)
+                        + LLVMGetSymbolAddress(sym_itr);
+                }
+                else {
+                    func->text_offset_of_aot_func_internal =
+                        LLVMGetSymbolAddress(sym_itr);
+                }
+            }
+        }
         LLVMMoveToNextSymbol(sym_itr);
     }
     LLVMDisposeSymbolIterator(sym_itr);