From e66b41427faf90ae5d86452b59d5ff59442ebb87 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Tue, 25 Jun 2024 11:47:23 +0900 Subject: [PATCH] aot_resolve_target_info: Avoid in-place modification of e_type (#3564) * I believe that LLVM MemoryBuffer interface is supposed to be read-only and it's allowed to use eg. read-only mmap of the underlying file. It isn't appropriate to modify the view at all. * in case of WASM_ENABLE_DEBUG_AOT, the whole buffer is written as the text section of the aot file. the modified e_type would confuse dwarf consumers. note that, even when we are using XIP, the debug info usually contains relocations. for example, llvm-dwarfdump doesn't seem to perform relocations on .debug_info section for ET_CORE (== 4 == our E_TYPE_XIP) objects. --- core/iwasm/compilation/aot_emit_aot_file.c | 41 +++++++++++++--------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/core/iwasm/compilation/aot_emit_aot_file.c b/core/iwasm/compilation/aot_emit_aot_file.c index 2d2e54be..e05f83b0 100644 --- a/core/iwasm/compilation/aot_emit_aot_file.c +++ b/core/iwasm/compilation/aot_emit_aot_file.c @@ -3038,15 +3038,18 @@ typedef struct elf64_rela { elf64_sxword r_addend; } elf64_rela; -#define SET_TARGET_INFO(f, v, type, little) \ - do { \ - type tmp = elf_header->v; \ - if ((little && !is_little_endian()) \ - || (!little && is_little_endian())) \ - exchange_##type((uint8 *)&tmp); \ - obj_data->target_info.f = tmp; \ +#define SET_TARGET_INFO_VALUE(f, val, type, little) \ + do { \ + type tmp = val; \ + if ((little && !is_little_endian()) \ + || (!little && is_little_endian())) \ + exchange_##type((uint8 *)&tmp); \ + obj_data->target_info.f = tmp; \ } while (0) +#define SET_TARGET_INFO_FIELD(f, v, type, little) \ + SET_TARGET_INFO_VALUE(f, elf_header->v, type, little) + static bool aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data) { @@ -3096,6 +3099,7 @@ aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data) || bin_type == LLVMBinaryTypeELF32B) { struct elf32_ehdr *elf_header; bool is_little_bin = bin_type == LLVMBinaryTypeELF32L; + uint16 e_type; if (!elf_buf || elf_size < sizeof(struct elf32_ehdr)) { aot_set_last_error("invalid elf32 buffer."); @@ -3103,20 +3107,22 @@ aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data) } elf_header = (struct elf32_ehdr *)elf_buf; + e_type = elf_header->e_type; /* Emit eXecute In Place file type while in indirect mode */ if (comp_ctx->is_indirect_mode) - elf_header->e_type = E_TYPE_XIP; + e_type = E_TYPE_XIP; - SET_TARGET_INFO(e_type, e_type, uint16, is_little_bin); - SET_TARGET_INFO(e_machine, e_machine, uint16, is_little_bin); - SET_TARGET_INFO(e_version, e_version, uint32, is_little_bin); - SET_TARGET_INFO(e_flags, e_flags, uint32, is_little_bin); + SET_TARGET_INFO_VALUE(e_type, e_type, uint16, is_little_bin); + SET_TARGET_INFO_FIELD(e_machine, e_machine, uint16, is_little_bin); + SET_TARGET_INFO_FIELD(e_version, e_version, uint32, is_little_bin); + SET_TARGET_INFO_FIELD(e_flags, e_flags, uint32, is_little_bin); } else if (bin_type == LLVMBinaryTypeELF64L || bin_type == LLVMBinaryTypeELF64B) { struct elf64_ehdr *elf_header; bool is_little_bin = bin_type == LLVMBinaryTypeELF64L; + uint16 e_type; if (!elf_buf || elf_size < sizeof(struct elf64_ehdr)) { aot_set_last_error("invalid elf64 buffer."); @@ -3124,15 +3130,16 @@ aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data) } elf_header = (struct elf64_ehdr *)elf_buf; + e_type = elf_header->e_type; /* Emit eXecute In Place file type while in indirect mode */ if (comp_ctx->is_indirect_mode) - elf_header->e_type = E_TYPE_XIP; + e_type = E_TYPE_XIP; - SET_TARGET_INFO(e_type, e_type, uint16, is_little_bin); - SET_TARGET_INFO(e_machine, e_machine, uint16, is_little_bin); - SET_TARGET_INFO(e_version, e_version, uint32, is_little_bin); - SET_TARGET_INFO(e_flags, e_flags, uint32, is_little_bin); + SET_TARGET_INFO_VALUE(e_type, e_type, uint16, is_little_bin); + SET_TARGET_INFO_FIELD(e_machine, e_machine, uint16, is_little_bin); + SET_TARGET_INFO_FIELD(e_version, e_version, uint32, is_little_bin); + SET_TARGET_INFO_FIELD(e_flags, e_flags, uint32, is_little_bin); } else if (bin_type == LLVMBinaryTypeMachO32L || bin_type == LLVMBinaryTypeMachO32B) {