From c9f88cef85f058cfb672dec6a38adf6d91b6a292 Mon Sep 17 00:00:00 2001 From: Hanlu Li Date: Fri, 24 Jul 2026 12:20:51 +0800 Subject: [PATCH] LATX, opt: Separate PE AOT caches by load address Use a versioned, type-qualified cache identity for AOT files and include the full segment address for PE and cache mappings. Apply that identity consistently to generation, locking, merging, publication, loading, and the in-memory library tree. Build cache paths with bounds checks, keep runtime segment state separate from the AOT file type, and release address-specific cache mappings when their segment is removed. Add focused coverage for identity namespacing, distinct and same-page PE addresses, independent state/type fields, and lib-tree removal. Keep the test target out of normal product builds. Signed-off-by: Hanlu Li --- meson.build | 14 ++ target/i386/latx/include/aot.h | 6 +- target/i386/latx/include/aot_lib.h | 4 +- target/i386/latx/include/segment.h | 4 + target/i386/latx/sbt/aot.c | 194 +++++++++++++----- target/i386/latx/sbt/aot_lib.c | 15 +- target/i386/latx/sbt/aot_merge.c | 8 +- target/i386/latx/sbt/segment.c | 39 ++++ .../latx/sbt/tests/aot-pe-load-address-test.c | 87 ++++++++ 9 files changed, 308 insertions(+), 63 deletions(-) create mode 100644 target/i386/latx/sbt/tests/aot-pe-load-address-test.c diff --git a/meson.build b/meson.build index 1df5f707a3..d7df014cf6 100644 --- a/meson.build +++ b/meson.build @@ -651,6 +651,20 @@ foreach target : target_dirs ] ) test('latx-aot-file-publish', aot_file_publish_test) + + aot_pe_load_address_test = executable( + 'test-latx-aot-pe-load-address', + files( + 'target/i386/latx/sbt/tests/aot-pe-load-address-test.c', + 'target/i386/latx/sbt/segment.c', + 'target/i386/latx/sbt/aot_lib.c' + ), + c_args: smc_reload_test_c_args, + dependencies: [glib], + include_directories: target_inc, + link_args: smc_reload_test_link_args + ) + test('latx-aot-pe-load-address', aot_pe_load_address_test) endif execs = [{ diff --git a/target/i386/latx/include/aot.h b/target/i386/latx/include/aot.h index 8c3353e806..c30fae93b6 100644 --- a/target/i386/latx/include/aot.h +++ b/target/i386/latx/include/aot.h @@ -293,7 +293,8 @@ extern seg_info **seg_info_vector; void mk_aot_dir(char * pathname); void dump_aot_buffer(aot_header *p_header); void dump_seg(aot_segment *p_segment, aot_header *p_header); -lib_info *aot_load(char *lib_name, void **curr_aot_buffer); +lib_info *aot_load(char *lib_name, char *aot_file_name, + void **curr_aot_buffer); void aot_tb_register(TranslationBlock *tb); void aot_do_tb_reloc(TranslationBlock *tb, struct aot_tb *stb, target_ulong seg_begin, target_ulong seg_end); @@ -339,7 +340,8 @@ extern aot_rel *aot_rel_table; extern aot_file_info *aot_buffer_all; extern int aot_buffer_all_num; -void get_aot_path(const char *lib_name, char *file_path); +int get_aot_path(const char *lib_name, char *file_path, + size_t file_path_size); char in_share_list(char *lib); char in_black_list(char *lib); char in_white_list(char *lib); diff --git a/target/i386/latx/include/aot_lib.h b/target/i386/latx/include/aot_lib.h index eac490e31e..5fb362f254 100644 --- a/target/i386/latx/include/aot_lib.h +++ b/target/i386/latx/include/aot_lib.h @@ -17,12 +17,14 @@ typedef struct lib_info { char *name; void *buffer; + size_t map_len; bool is_unmapped; } lib_info; void lib_tree_init(void); -lib_info *lib_tree_insert(char *name, void *buffer); +lib_info *lib_tree_insert(char *name, void *buffer, size_t map_len); +bool lib_tree_remove(char *name); gint get_lib_num(void); void do_lib_record(lib_info **lib_info_vector); diff --git a/target/i386/latx/include/segment.h b/target/i386/latx/include/segment.h index b58e704430..f4ae87b1c9 100644 --- a/target/i386/latx/include/segment.h +++ b/target/i386/latx/include/segment.h @@ -27,7 +27,9 @@ typedef struct seg_info { }; #define SEG_RUNNING 0x1 #define IS_ELF_SEG 0x2 +#define SEG_AOT_LOADED 0x4 uint8_t seg_flag; + uint8_t aot_file_type; } seg_info; typedef struct wine_sec_info { @@ -85,5 +87,7 @@ void segment_tree_remove(seg_info *val); bool segment_tree_winepe_lookup(target_ulong pc); gint get_segment_num(void); void do_segment_record(seg_info **seg_info_vector); +int segment_get_aot_file_name(const seg_info *seg, char *name, + size_t name_size); #endif diff --git a/target/i386/latx/sbt/aot.c b/target/i386/latx/sbt/aot.c index 3c36ec9a1c..e549d3770f 100644 --- a/target/i386/latx/sbt/aot.c +++ b/target/i386/latx/sbt/aot.c @@ -54,6 +54,7 @@ seg_info **seg_info_vector; static int seg_info_num; static int curr_lib_seg_num; static char *curr_lib_name; +static char curr_aot_file_name[PATH_MAX]; uintptr_t table_end_addr; /* Helper functions used to dump tbs in hash table to a vector */ static void do_tb_count(void *p, uint32_t hash, void *userp) @@ -613,25 +614,34 @@ static uint8_t *fill_ir1_buff(uint64_t ir1_table_offset, aot_tb *p_aot_tbs, return ir1_buffer; } -void get_aot_path(const char *lib_name, char *file_path) +int get_aot_path(const char *lib_name, char *file_path, + size_t file_path_size) { - assert(lib_name && file_path); - char *home = getenv("HOME"); - if (likely(home)) { - snprintf(file_path, PATH_MAX, "%s%s", home, "/.cache/latx/"); - } else { - snprintf(file_path, PATH_MAX, "%s", "/.cache/latx/"); - } - char temp[PATH_MAX]; - strcpy(temp, ""); - strcat(temp, lib_name); - for (int i = 0; i < strlen(temp); i++) { - if (temp[i] == '/') { - temp[i] = '+'; + const char *home; + char *escaped_name; + int len; + + if (!lib_name || !file_path || !file_path_size) { + return -EINVAL; + } + escaped_name = g_strdup(lib_name); + if (!escaped_name) { + return -ENOMEM; + } + for (char *p = escaped_name; *p; p++) { + if (*p == '/') { + *p = '+'; } } - strcat(file_path, temp); - strcat(file_path, ".aot2"); + home = getenv("HOME"); + len = snprintf(file_path, file_path_size, "%s/.cache/latx/%s.aot2", + home ? home : "", escaped_name); + g_free(escaped_name); + if (len < 0 || (size_t)len >= file_path_size) { + file_path[0] = '\0'; + return -ENAMETOOLONG; + } + return 0; } static long get_fileSize(FILE* file) @@ -657,7 +667,11 @@ static int write_aot_file(int *lockfd, aot_header *p_header, uint32_t *p_insn, size_t write_size; int fd; - get_aot_path(curr_lib_name, aot_file_path); + if (get_aot_path(curr_aot_file_name, aot_file_path, + PATH_MAX) < 0) { + qemu_log_mask(LAT_LOG_AOT, "AOT path is too long\n"); + return -1; + } if (aot_file_get_tmp_path(aot_file_path, tmp_file_path, sizeof(tmp_file_path)) < 0) { qemu_log_mask(LAT_LOG_AOT, "AOT temporary path is too long\n"); @@ -736,7 +750,8 @@ int do_generate_aot(int first_seg_in_lib, int end_seg_in_lib) return false; } - p_header->aot_file_type = get_file_type(curr_lib_name); + p_header->aot_file_type = + seg_info_vector[first_seg_in_lib]->aot_file_type; if (p_header->aot_file_type & (ELF_AOT_FILE | PE_AOT_FILE)) { struct stat statbuf; @@ -786,7 +801,7 @@ int do_generate_aot(int first_seg_in_lib, int end_seg_in_lib) uint8_t *p_ir1 = (uint8_t *)ROUND_UP(table_end_addr, 8); int ir1_size = 0; uint8_t *ir1_buffer = NULL; - if (!is_elf_file(curr_lib_name)) { + if (!(p_header->aot_file_type & ELF_AOT_FILE)) { ir1_buffer = fill_ir1_buff((void *)p_ir1 - (void *)p_header, p_aot_tbs, tb_table_end, &ir1_size); } @@ -830,8 +845,11 @@ char in_white_list(char *lib) return in_list(lib, lib_white_list); } -static int get_tb_num(char *lib_name, CPUState *cpu) { - get_aot_path(lib_name, aot_file_path); +static int get_tb_num(char *lib_name, char *aot_file_name, CPUState *cpu) +{ + if (get_aot_path(aot_file_name, aot_file_path, PATH_MAX) < 0) { + return 0; + } if (access(aot_file_path, 0) < 0) { return 0; } @@ -897,10 +915,10 @@ static int get_tb_num(char *lib_name, CPUState *cpu) { #define PROLIFERATION_RATE 10 static inline int need_gen_aot(CPUState *cpu, - char *lib_name, int *lockfd, uint32_t tb_count) + char *lib_name, char *aot_file_name, int *lockfd, uint32_t tb_count) { - lib_info *lib = lib_tree_lookup(lib_name); - int aim_tb_num = 0;; + lib_info *lib = lib_tree_lookup(aot_file_name); + int aim_tb_num = 0; if (lib) { aot_header *p_head = (aot_header *)lib->buffer; if (cpu->tcg_cflags & CF_PARALLEL) { @@ -909,13 +927,15 @@ static inline int need_gen_aot(CPUState *cpu, aim_tb_num = p_head->unparallel_tb_num; } } else { - aim_tb_num = get_tb_num(lib_name, cpu); + aim_tb_num = get_tb_num(lib_name, aot_file_name, cpu); } /* Too few tb number. */ if (tb_count * PROLIFERATION_RATE < aim_tb_num) { return -1; } - get_aot_path(curr_lib_name, aot_file_path); + if (get_aot_path(aot_file_name, aot_file_path, PATH_MAX) < 0) { + return -1; + } if (aot_file_get_lock_path(aot_file_path, aot_file_lock, PATH_MAX) < 0) { return -1; @@ -954,7 +974,11 @@ void pre_translate(int begin_id, int end_id, CPUState *cpu, qatomic_set(&tcg_ctx->tb_gen_ptr, tcg_ctx->tb_gen_buffer); clear_rel_table(); - get_aot_path(curr_lib_name, aot_file_path); + if (get_aot_path(curr_aot_file_name, aot_file_path, + PATH_MAX) < 0) { + tb_num = 0; + return; + } if (access(aot_file_path, 0) >= 0) { char tmp_file_path[PATH_MAX]; @@ -976,7 +1000,9 @@ static bool rename_aot_file(char *lib_name) char tmp_file_path[PATH_MAX]; int ret; - get_aot_path(lib_name, aot_file_path); + if (get_aot_path(lib_name, aot_file_path, PATH_MAX) < 0) { + return false; + } if (aot_file_get_tmp_path(aot_file_path, tmp_file_path, sizeof(tmp_file_path)) < 0) { return false; @@ -1006,9 +1032,18 @@ static inline void gen_aot_by_lib(int first_seg_id, int end_seg_id, int lockfd = -1; curr_lib_name = seg_info_vector[first_seg_id]->file_name; + if (segment_get_aot_file_name(seg_info_vector[first_seg_id], + curr_aot_file_name, + sizeof(curr_aot_file_name)) < 0) { + return; + } - if (need_gen_aot(cpu, curr_lib_name, &lockfd, tb_count) >= 0) { - get_aot_path(curr_lib_name, aot_file_path); + if (need_gen_aot(cpu, curr_lib_name, curr_aot_file_name, + &lockfd, tb_count) >= 0) { + if (get_aot_path(curr_aot_file_name, aot_file_path, + PATH_MAX) < 0) { + goto unlock; + } if (aot_file_get_tmp_path(aot_file_path, tmp_file_path, sizeof(tmp_file_path)) < 0) { goto unlock; @@ -1022,10 +1057,10 @@ static inline void gen_aot_by_lib(int first_seg_id, int end_seg_id, pre_translate(first_seg_id, end_seg_id, cpu, NULL); if (do_generate_aot(first_seg_id, end_seg_id)) { merge_result = - aot2_merge(curr_lib_name, first_seg_id, end_seg_id, cpu); + aot2_merge(curr_aot_file_name, first_seg_id, end_seg_id, cpu); if (merge_result == AOT_MERGE_NO_BASE || merge_result == AOT_MERGE_READY) { - generated_aot_file |= rename_aot_file(curr_lib_name); + generated_aot_file |= rename_aot_file(curr_aot_file_name); } else { unlink(tmp_file_path); } @@ -1044,7 +1079,9 @@ static void generate_aot_v2(CPUState *cpu) seg_info_vector[0]->first_tb_id + 1; for (int i = 1; i < seg_info_num; i++) { if (strcmp(seg_info_vector[i]->file_name, - seg_info_vector[first_seg_in_lib]->file_name)) { + seg_info_vector[first_seg_in_lib]->file_name) || + (seg_info_vector[first_seg_in_lib]->aot_file_type & + (PE_AOT_FILE | CACHE_AOT_FILE))) { gen_aot_by_lib(first_seg_in_lib, i, cpu, tb_count); first_seg_in_lib = i; tb_count = seg_info_vector[i]->last_tb_id @@ -1074,7 +1111,10 @@ void clear_rel_table(void) void aot_generate(CPUState *cpu) { char tmp_file[2] = "t"; - get_aot_path(tmp_file, aot_file_path); + if (get_aot_path(tmp_file, aot_file_path, PATH_MAX) < 0) { + qemu_log_mask(LAT_LOG_AOT, "AOT path is too long\n"); + return; + } int fd = open(aot_file_path, O_CREAT | O_RDONLY, 0777); /* make fd > 2. */ while(fd <= 2) { @@ -1205,19 +1245,23 @@ static void remove_curr_aot_file(int fd) time_t aot_st_ctime; -lib_info *aot_load(char *lib_name, void **curr_aot_buffer) +lib_info *aot_load(char *lib_name, char *aot_file_name, + void **curr_aot_buffer) { /* Get aot_file path and lock file. */ assert(lib_name); - get_aot_path(lib_name, aot_file_path); + if (get_aot_path(aot_file_name, aot_file_path, PATH_MAX) < 0) { + return NULL; + } if (access(aot_file_path, 0) < 0) { return NULL; } /* Open aot_file. */ - void *buffer; + void *buffer = MAP_FAILED; struct stat statbuf; lib_info *curr_lib_info = NULL; + size_t file_sz = 0; char aot_version[strlen(AOT_VERSION) + 1]; int fd = open(aot_file_path, O_RDONLY); FILE *pf = NULL; @@ -1227,7 +1271,7 @@ lib_info *aot_load(char *lib_name, void **curr_aot_buffer) pf = fdopen(fd, "r"); lsassert(pf && ("open aot file failed!")); fseek(pf, 0, SEEK_END); /* seek to end of file */ - size_t file_sz = ftell(pf); /* get current file pointer */ + file_sz = ftell(pf); /* get current file pointer */ /*check aot complete.*/ if (fseek(pf, -strlen(AOT_VERSION), SEEK_END) != 0 @@ -1243,7 +1287,7 @@ lib_info *aot_load(char *lib_name, void **curr_aot_buffer) /* Read aot file */ fseek(pf, 0, SEEK_SET); /* seek back to beginning of file */ buffer = mmap(NULL, file_sz, PROT_READ, MAP_SHARED, fd, 0); - if (buffer <= 0) { + if (buffer == MAP_FAILED) { qemu_log_mask(LAT_LOG_AOT, "aot file mmap error\n"); goto exit_aot_load; } @@ -1265,9 +1309,12 @@ lib_info *aot_load(char *lib_name, void **curr_aot_buffer) /* dump_aot_buffer(p_header); */ *curr_aot_buffer = buffer; - curr_lib_info = lib_tree_insert(lib_name, buffer); + curr_lib_info = lib_tree_insert(aot_file_name, buffer, file_sz); exit_aot_load: + if (!curr_lib_info && buffer != MAP_FAILED) { + munmap(buffer, file_sz); + } if (likely(pf)) { fclose(pf); } @@ -1556,27 +1603,45 @@ void aot_do_tb_reloc(TranslationBlock *tb, struct aot_tb *stb, } } -static aot_segment *get_segment(char *lib_name, uint64_t aot_offset, - abi_long start, abi_long end, void **curr_aot_buffer) +static aot_segment *get_segment(seg_info *seg, char *lib_name, + uint64_t aot_offset, abi_long start, abi_long end, + void **curr_aot_buffer) { + char aot_file_name[PATH_MAX]; aot_segment *p_segment; - lib_info *lib = lib_tree_lookup(lib_name); + lib_info *lib; + + if (segment_get_aot_file_name(seg, aot_file_name, + sizeof(aot_file_name)) < 0) { + return NULL; + } + lib = lib_tree_lookup(aot_file_name); if (lib == NULL) { *curr_aot_buffer = NULL; - lib = aot_load(lib_name, curr_aot_buffer); + lib = aot_load(lib_name, aot_file_name, curr_aot_buffer); } else if (!lib->is_unmapped){ *curr_aot_buffer = lib->buffer; + } else if (seg->aot_file_type & (PE_AOT_FILE | CACHE_AOT_FILE)) { + lib_tree_remove(aot_file_name); + *curr_aot_buffer = NULL; + return NULL; } if (*curr_aot_buffer == NULL) { return NULL; } p_segment = aot_find_segment(lib_name, aot_offset, *curr_aot_buffer); if (p_segment == NULL) { + if (seg->aot_file_type & (PE_AOT_FILE | CACHE_AOT_FILE)) { + lib_tree_remove(aot_file_name); + *curr_aot_buffer = NULL; + } return NULL; } - if (p_segment->aot_file_type & PE_AOT_FILE) { - if (p_segment->details.seg_begin != start) { - lib->is_unmapped = 1; + if (p_segment->aot_file_type & (PE_AOT_FILE | CACHE_AOT_FILE)) { + if (p_segment->details.seg_begin != start || + p_segment->details.seg_end != end) { + lib_tree_remove(aot_file_name); + *curr_aot_buffer = NULL; return NULL; } } @@ -1585,7 +1650,12 @@ static aot_segment *get_segment(char *lib_name, uint64_t aot_offset, && (start > p_segment->details.seg_begin)){ qemu_log_mask(LAT_LOG_AOT, "seg start h32 not zero\n"); assert(lib); - lib->is_unmapped = 1; + if (seg->aot_file_type & (PE_AOT_FILE | CACHE_AOT_FILE)) { + lib_tree_remove(aot_file_name); + *curr_aot_buffer = NULL; + } else { + lib->is_unmapped = 1; + } return NULL; } @@ -1628,9 +1698,13 @@ static void aot_guest_code_protect(target_ulong seg_begin, } } -void recover_aot_tb(char *lib_name, uint64_t aot_offset, abi_long start, +void recover_aot_tb(char *lib_name, uint64_t aot_offset, abi_long start, abi_long len) { + seg_info *seg; + void *curr_aot_buffer = NULL; + struct aot_segment *p_segment; + if (!option_load_aot) { return; } @@ -1641,11 +1715,21 @@ void recover_aot_tb(char *lib_name, uint64_t aot_offset, abi_long start, #endif return; } - /* First, we should identify whether this segment is in aot. */ - void *curr_aot_buffer = NULL; + seg = segment_tree_lookup2(start, start + len); + if (!seg) { + return; + } + if (strcmp(seg->file_name, lib_name)) { + return; + } + if ((seg->aot_file_type & (PE_AOT_FILE | CACHE_AOT_FILE)) && + (seg->seg_begin != start || seg->seg_end != start + len)) { + return; + } - struct aot_segment *p_segment = - get_segment(lib_name, aot_offset, start, start + len, &curr_aot_buffer); + /* First, we should identify whether this segment is in aot. */ + p_segment = get_segment(seg, lib_name, aot_offset, start, start + len, + &curr_aot_buffer); if (p_segment == NULL) { return; @@ -1658,10 +1742,10 @@ void recover_aot_tb(char *lib_name, uint64_t aot_offset, abi_long start, qemu_log_mask(LAT_LOG_AOT, "---------------------------------------------\n"); } - seg_info *seg = segment_tree_lookup2(start, start + len); - if (seg && (seg->seg_begin == start) && (seg->seg_end == start + len)) { + if ((seg->seg_begin == start) && (seg->seg_end == start + len)) { seg->buffer = curr_aot_buffer; seg->p_segment = p_segment; + seg->seg_flag |= SEG_AOT_LOADED; } if (p_segment->aot_file_type & ELF_AOT_FILE) { aot_guest_code_protect(start, start + len, p_segment, curr_aot_buffer); diff --git a/target/i386/latx/sbt/aot_lib.c b/target/i386/latx/sbt/aot_lib.c index f2a899f59a..c0e779040d 100644 --- a/target/i386/latx/sbt/aot_lib.c +++ b/target/i386/latx/sbt/aot_lib.c @@ -21,7 +21,9 @@ static void lib_delete(gconstpointer a) lsassert(oldkey); lsassert(oldkey->name); free(oldkey->name); - free(oldkey->buffer); + if (oldkey->buffer && oldkey->map_len) { + munmap(oldkey->buffer, oldkey->map_len); + } free(oldkey); } @@ -61,7 +63,7 @@ lib_info *lib_tree_lookup(char *name) { } -lib_info *lib_tree_insert(char *name, void *buffer) +lib_info *lib_tree_insert(char *name, void *buffer, size_t map_len) { lib_info *lib = (lib_info *)malloc(sizeof(lib_info)); if (lib == NULL) { @@ -77,12 +79,20 @@ lib_info *lib_tree_insert(char *name, void *buffer) strncpy(lib->name, name, strlen(name) + 1); lib->buffer = buffer; + lib->map_len = map_len; lib->is_unmapped = 0; /* Now insert this new lib into lib_tree */ g_tree_replace(lib_tree, lib, lib); return lib; } +bool lib_tree_remove(char *name) +{ + lib_info key = {.name = name}; + + return g_tree_remove(lib_tree, &key); +} + gint get_lib_num(void) { return g_tree_nnodes(lib_tree); @@ -98,4 +108,3 @@ void do_lib_record(lib_info **lib_info_vector) } #endif - diff --git a/target/i386/latx/sbt/aot_merge.c b/target/i386/latx/sbt/aot_merge.c index 521ec8364b..200dce7138 100644 --- a/target/i386/latx/sbt/aot_merge.c +++ b/target/i386/latx/sbt/aot_merge.c @@ -701,7 +701,9 @@ static AOTLoadResult aot_load_no_lock(char *lib_name) if (lib_name == NULL) { return -1; } - get_aot_path(lib_name, aot_file_path); + if (get_aot_path(lib_name, aot_file_path, PATH_MAX) < 0) { + return AOT_LOAD_ERROR; + } if (access(aot_file_path, 0) < 0) { return -1; } @@ -1034,7 +1036,9 @@ AOTMergeResult aot2_merge(char *curr_lib_name, int first_seg_id, AOTMergeResult result; AOTLoadResult load_result; - get_aot_path(curr_lib_name, aot_file_path); + if (get_aot_path(curr_lib_name, aot_file_path, PATH_MAX) < 0) { + return AOT_MERGE_ERROR; + } if (access(aot_file_path, F_OK) < 0) { return errno == ENOENT ? AOT_MERGE_NO_BASE : AOT_MERGE_ERROR; } diff --git a/target/i386/latx/sbt/segment.c b/target/i386/latx/sbt/segment.c index 9c83bace91..7bffd1aac9 100644 --- a/target/i386/latx/sbt/segment.c +++ b/target/i386/latx/sbt/segment.c @@ -16,10 +16,48 @@ #ifdef CONFIG_LATX_AOT static GTree *segment_tree; static GTree *wine_sec_tree; + +int segment_get_aot_file_name(const seg_info *seg, char *name, + size_t name_size) +{ + char *path_hash; + int len; + + if (!seg || !seg->file_name || !name || !name_size) { + return -EINVAL; + } + path_hash = g_compute_checksum_for_string(G_CHECKSUM_SHA256, + seg->file_name, -1); + if (!path_hash) { + return -ENOMEM; + } + if (seg->aot_file_type & (PE_AOT_FILE | CACHE_AOT_FILE)) { + len = snprintf(name, name_size, "v2-%02x-%s-%" PRIx64, + seg->aot_file_type, path_hash, + (uint64_t)seg->seg_begin); + } else { + len = snprintf(name, name_size, "v2-%02x-%s", + seg->aot_file_type, path_hash); + } + g_free(path_hash); + if (len < 0 || (size_t)len >= name_size) { + return -ENAMETOOLONG; + } + return 0; +} + static void seg_delete(gconstpointer a) { seg_info *oldkey = (seg_info *)a; + char aot_file_name[PATH_MAX]; + lsassert(oldkey); lsassert(oldkey->file_name); + if ((oldkey->seg_flag & SEG_AOT_LOADED) && oldkey->buffer && + (oldkey->aot_file_type & (PE_AOT_FILE | CACHE_AOT_FILE)) && + segment_get_aot_file_name(oldkey, aot_file_name, + sizeof(aot_file_name)) == 0) { + lib_tree_remove(aot_file_name); + } free(oldkey->file_name); free(oldkey); } @@ -155,6 +193,7 @@ void segment_tree_insert(char *name, target_ulong offset, target_ulong begin, seg->buffer = NULL; seg->p_segment = NULL; seg->seg_flag = 0; + seg->aot_file_type = get_file_type(name); if (is_elf_file(name)) { seg->seg_flag = IS_ELF_SEG; } diff --git a/target/i386/latx/sbt/tests/aot-pe-load-address-test.c b/target/i386/latx/sbt/tests/aot-pe-load-address-test.c new file mode 100644 index 0000000000..049cf5d815 --- /dev/null +++ b/target/i386/latx/sbt/tests/aot-pe-load-address-test.c @@ -0,0 +1,87 @@ +#include "qemu/osdep.h" + +#include "aot.h" +#include "aot_lib.h" +#include "segment.h" + +int qemu_loglevel; + +int qemu_log(const char *fmt G_GNUC_UNUSED, ...) +{ + return 0; +} + +void print_stack_trace(void) +{ +} + +static void get_cache_name(seg_info *seg, char *name) +{ + g_assert(segment_get_aot_file_name(seg, name, PATH_MAX) == 0); +} + +int main(void) +{ + char elf_name[] = "/tmp/libexample.so"; + char pe_name[] = "/tmp/example.dll"; + char colliding_name[] = "/tmp/example.dll-140000000"; + seg_info elf_seg = { + .file_name = elf_name, + .seg_begin = 0x400000, + .aot_file_type = ELF_AOT_FILE, + }; + seg_info pe_seg = { + .file_name = pe_name, + .seg_begin = 0x140000000, + .aot_file_type = PE_AOT_FILE, + }; + seg_info relocated_pe_seg = pe_seg; + seg_info same_page_pe_seg = pe_seg; + seg_info colliding_elf_seg = { + .file_name = colliding_name, + .seg_begin = 0x400000, + .aot_file_type = ELF_AOT_FILE, + }; + char elf_cache_name[PATH_MAX]; + char colliding_cache_name[PATH_MAX]; + char first_name[PATH_MAX]; + char second_name[PATH_MAX]; + size_t map_len = TARGET_PAGE_SIZE; + void *mapping; + + get_cache_name(&elf_seg, elf_cache_name); + get_cache_name(&pe_seg, first_name); + get_cache_name(&colliding_elf_seg, colliding_cache_name); + g_assert(g_str_has_prefix(elf_cache_name, "v2-01-")); + g_assert(g_str_has_prefix(first_name, "v2-02-")); + g_assert(g_str_has_suffix(first_name, "-140000000")); + g_assert(strcmp(first_name, colliding_cache_name) != 0); + + same_page_pe_seg.seg_begin += 0x80; + get_cache_name(&same_page_pe_seg, second_name); + g_assert(g_str_has_suffix(second_name, "-140000080")); + g_assert(strcmp(first_name, second_name) != 0); + + relocated_pe_seg.seg_begin = 0x180000000; + get_cache_name(&relocated_pe_seg, second_name); + g_assert(g_str_has_suffix(second_name, "-180000000")); + g_assert(strcmp(first_name, second_name) != 0); + + pe_seg.seg_flag = SEG_RUNNING; + g_assert(pe_seg.seg_flag & SEG_RUNNING); + g_assert(pe_seg.aot_file_type == PE_AOT_FILE); + + lib_tree_init(); + mapping = mmap(NULL, map_len, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + g_assert(mapping != MAP_FAILED); + g_assert(lib_tree_insert(first_name, mapping, map_len) != NULL); + g_assert(lib_tree_insert(second_name, NULL, 0) != NULL); + g_assert(get_lib_num() == 2); + g_assert(lib_tree_lookup(first_name) != lib_tree_lookup(second_name)); + g_assert(lib_tree_remove(first_name)); + g_assert(lib_tree_remove(second_name)); + g_assert(get_lib_num() == 0); + + return 0; +}