From b96281fa3f212f06467277dc8e7e6a27d10a16d8 Mon Sep 17 00:00:00 2001 From: usualtreee <1340399194@qq.com> Date: Wed, 21 Oct 2026 20:56:53 +0800 Subject: [PATCH 1/3] [dlmodule] fix: uninitialized globals in relocatable modules Fix the loader of relocatable (ET_REL) dynamic modules so that uninitialized global variables get their own storage and correct addresses: 1. Advance the allocation pointer after loading a BSS (SHT_NOBITS) section, so multiple NOBITS sections no longer overlap in memory. 2. Relocate section symbols with section_load_addr - sec_sh_addr + sym->st_value, matching how text symbols are already handled. 3. Allocate a common block for SHN_COMMON symbols (tentative definitions of global variables) and relocate every reference to it instead of silently skipping them. 4. Build the module symbol table from .symtab for ET_REL modules so that dlsym() can resolve the module's global functions. Verified on bsp/qemu-vexpress-a9 with CONFIG_RT_USING_MODULE=y: before the fix an ET_REL module fails dlsym(), after the fix its globals get correct non-overlapping addresses and round-trip reads/writes succeed, and ET_DYN (-shared) modules are unaffected. Refs: #5705 --- components/libc/posix/libdl/dlelf.c | 155 ++++++++++++++++++++++++++-- components/libc/posix/libdl/dlelf.h | 1 + 2 files changed, 147 insertions(+), 9 deletions(-) diff --git a/components/libc/posix/libdl/dlelf.c b/components/libc/posix/libdl/dlelf.c index 6490b3263395..0c18fa9042b4 100644 --- a/components/libc/posix/libdl/dlelf.c +++ b/components/libc/posix/libdl/dlelf.c @@ -300,6 +300,48 @@ rt_err_t dlmodule_load_shared_object(struct rt_dlmodule* module, void *module_pt return RT_EOK; } +/** + * @brief Compute the size of the common block of a symbol table, and + * optionally the offset of one specific SHN_COMMON symbol inside it. + * + * SHN_COMMON symbols are tentative definitions of uninitialized global + * variables. The loader must allocate storage for them just like a static + * linker does: every common symbol is aligned to its st_value alignment + * requirement and occupies st_size bytes, packed one after another. + * + * @param symtab pointer to the symbol table + * @param nsym number of symbols in the table + * @param target symbol whose offset is wanted, or RT_NULL to get the total + * size of the common block + * @return offset of target in the common block, or the total size of the + * block when target is RT_NULL + */ +static rt_ubase_t dlmodule_common_block(Elf_Sym *symtab, rt_ubase_t nsym, + Elf_Sym *target) +{ + rt_ubase_t i, offset = 0; + + for (i = 0; i < nsym; i++) + { + if (symtab[i].st_shndx != SHN_COMMON) + { + continue; + } + + /* st_value of a SHN_COMMON symbol holds its alignment requirement */ + offset = RT_ALIGN(offset, symtab[i].st_value > 1 ? symtab[i].st_value : 1); + + if (target == &symtab[i]) + { + return offset; + } + + offset += symtab[i].st_size; + } + + return offset; +} + /** * @brief Load a relocatable file into memory. * @@ -319,7 +361,7 @@ rt_err_t dlmodule_load_shared_object(struct rt_dlmodule* module, void *module_pt */ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module_ptr) { - rt_ubase_t index, rodata_addr = 0, bss_addr = 0, data_addr = 0; + rt_ubase_t index, rodata_addr = 0, bss_addr = 0, data_addr = 0, common_addr = 0; rt_ubase_t module_addr = 0, module_size = 0; rt_uint8_t *ptr, *strtab, *shstrab; @@ -349,6 +391,23 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module } } + /* account for common symbols (uninitialized global variables) */ + for (index = 0; index < elf_module->e_shnum; index++) + { + Elf_Sym *symtab; + rt_ubase_t nsym; + + if (shdr[index].sh_type != SHT_SYMTAB) + { + continue; + } + + symtab = (Elf_Sym *)((rt_uint8_t *)elf_module + shdr[index].sh_offset); + nsym = (rt_ubase_t)(shdr[index].sh_size / sizeof(Elf_Sym)); + module_size += RT_ALIGN(dlmodule_common_block(symtab, nsym, RT_NULL), + sizeof(rt_ubase_t)); + } + /* no text, data and bss on image */ if (module_size == 0) return RT_NULL; @@ -410,9 +469,14 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module rt_memset(ptr, 0, shdr[index].sh_size); bss_addr = (rt_ubase_t)ptr; LOG_D("load bss 0x%x, size %d", ptr, shdr[index].sh_size); + ptr += shdr[index].sh_size; } } + /* the common block (uninitialized global variables) starts right after + * the loaded sections; it was zeroed together with the module space */ + common_addr = (rt_ubase_t)ptr; + /* set module entry */ module->entry_addr = (rt_dlmodule_entry_func_t)((rt_uint8_t *)module->mem_space + elf_module->e_entry - module_addr); @@ -459,29 +523,48 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module { Elf_Addr addr = 0; - if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) || - (ELF_ST_TYPE(sym->st_info) == STT_OBJECT)) + if (sym->st_shndx == SHN_COMMON) { + /* relocate common symbol (uninitialized global variable): + * SHN_COMMON is not a real section index, so it must be + * handled before the section-name checks below */ + LOG_D("common symbol"); + addr = (Elf_Addr)(common_addr + dlmodule_common_block( + symtab, + (rt_ubase_t)(shdr[shdr[index].sh_link].sh_size / sizeof(Elf_Sym)), + sym)); + dlmodule_relocate(module, rel, addr); + } + else if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) || + (ELF_ST_TYPE(sym->st_info) == STT_OBJECT)) + { + Elf_Addr sec_sh_addr = shdr[sym->st_shndx].sh_addr; if (rt_strncmp((const char *)(shstrab + - shdr[sym->st_shndx].sh_name), ELF_RODATA, 8) == 0) + shdr[sym->st_shndx].sh_name), + ELF_RODATA, 8) == 0) { /* relocate rodata section */ LOG_D("rodata"); - addr = (Elf_Addr)(rodata_addr + sym->st_value); + addr = (Elf_Addr)(rodata_addr - sec_sh_addr + sym->st_value); } - else if (rt_strncmp((const char *) - (shstrab + shdr[sym->st_shndx].sh_name), ELF_BSS, 5) == 0) + else if (rt_strncmp((const char *)(shstrab + shdr[sym->st_shndx].sh_name), ELF_BSS, 5) == 0) { /* relocate bss section */ LOG_D("bss"); - addr = (Elf_Addr)bss_addr + sym->st_value; + addr = (Elf_Addr)(bss_addr - sec_sh_addr + sym->st_value); + } + else if (rt_strncmp((const char *)(shstrab + shdr[sym->st_shndx].sh_name), ".common", 7) == 0) + { + /* relocate common section (uninitialized globals) */ + LOG_D("common"); + addr = (Elf_Addr)(bss_addr - sec_sh_addr + sym->st_value); } else if (rt_strncmp((const char *)(shstrab + shdr[sym->st_shndx].sh_name), ELF_DATA, 6) == 0) { /* relocate data section */ LOG_D("data"); - addr = (Elf_Addr)data_addr + sym->st_value; + addr = (Elf_Addr)(data_addr - sec_sh_addr + sym->st_value); } if (addr != 0) dlmodule_relocate(module, rel, addr); @@ -533,5 +616,59 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module } } + /* construct the module symbol table from .symtab so that lookups such as + * dlsym() can resolve the module's global functions */ + shstrab = (rt_uint8_t *)module_ptr + shdr[elf_module->e_shstrndx].sh_offset; + for (index = 0; index < elf_module->e_shnum; index++) + { + if ((shdr[index].sh_type == SHT_SYMTAB) && + (rt_strcmp((const char *)(shstrab + shdr[index].sh_name), ELF_SYMTAB) == 0)) + { + break; + } + } + + if (index != elf_module->e_shnum) + { + Elf_Sym *symtab; + rt_ubase_t i, count = 0; + + symtab = (Elf_Sym *)((rt_uint8_t *)module_ptr + shdr[index].sh_offset); + strtab = (rt_uint8_t *)module_ptr + shdr[shdr[index].sh_link].sh_offset; + + for (i = 0; i < shdr[index].sh_size / sizeof(Elf_Sym); i++) + { + if ((ELF_ST_BIND(symtab[i].st_info) == STB_GLOBAL) && + (ELF_ST_TYPE(symtab[i].st_info) == STT_FUNC)) + { + count++; + } + } + + module->symtab = (struct rt_module_symtab *)rt_malloc(count * sizeof(struct rt_module_symtab)); + module->nsym = count; + for (i = 0, count = 0; i < shdr[index].sh_size / sizeof(Elf_Sym); i++) + { + rt_size_t length; + + if ((ELF_ST_BIND(symtab[i].st_info) != STB_GLOBAL) || + (ELF_ST_TYPE(symtab[i].st_info) != STT_FUNC)) + { + continue; + } + + length = rt_strlen((const char *)(strtab + symtab[i].st_name)) + 1; + + module->symtab[count].addr = + (void *)((rt_uint8_t *)module->mem_space - module_addr + symtab[i].st_value); + module->symtab[count].name = rt_malloc(length); + rt_memset((void *)module->symtab[count].name, 0, length); + rt_memcpy((void *)module->symtab[count].name, + strtab + symtab[i].st_name, + length); + count++; + } + } + return RT_EOK; } diff --git a/components/libc/posix/libdl/dlelf.h b/components/libc/posix/libdl/dlelf.h index 6b03271034f3..15d4ddba601b 100644 --- a/components/libc/posix/libdl/dlelf.h +++ b/components/libc/posix/libdl/dlelf.h @@ -202,6 +202,7 @@ typedef struct #define STT_HIPROC 15 #define STN_UNDEF 0 /* undefined */ +#define SHN_COMMON 0xfff2 /* common symbols (uninitialized globals) */ #define ELF_ST_BIND(info) ((info) >> 4) #define ELF_ST_TYPE(info) ((info) & 0xf) From 5d6e93f93353d88cb83c9b3d1310932dfbd32946 Mon Sep 17 00:00:00 2001 From: usualtreee <1340399194@qq.com> Date: Mon, 26 Oct 2026 17:01:54 +0800 Subject: [PATCH 2/3] [dlmodule] fix: align COMMON and harden ET_REL exports Reserve COMMON alignment padding and check symbol-table allocations. Use per-section load addresses for exported functions and exclude undefined symbols. --- components/libc/posix/libdl/dlelf.c | 95 ++++++++++++++++++++++------- components/libc/posix/libdl/dlelf.h | 1 + 2 files changed, 75 insertions(+), 21 deletions(-) diff --git a/components/libc/posix/libdl/dlelf.c b/components/libc/posix/libdl/dlelf.c index 0c18fa9042b4..5b11f151a0c2 100644 --- a/components/libc/posix/libdl/dlelf.c +++ b/components/libc/posix/libdl/dlelf.c @@ -362,7 +362,8 @@ static rt_ubase_t dlmodule_common_block(Elf_Sym *symtab, rt_ubase_t nsym, rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module_ptr) { rt_ubase_t index, rodata_addr = 0, bss_addr = 0, data_addr = 0, common_addr = 0; - rt_ubase_t module_addr = 0, module_size = 0; + rt_ubase_t module_addr = 0, module_size = 0, common_align = 1; + rt_ubase_t *section_load_addr = RT_NULL; rt_uint8_t *ptr, *strtab, *shstrab; /* get the ELF image size */ @@ -395,7 +396,7 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module for (index = 0; index < elf_module->e_shnum; index++) { Elf_Sym *symtab; - rt_ubase_t nsym; + rt_ubase_t i, nsym; if (shdr[index].sh_type != SHT_SYMTAB) { @@ -404,10 +405,25 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module symtab = (Elf_Sym *)((rt_uint8_t *)elf_module + shdr[index].sh_offset); nsym = (rt_ubase_t)(shdr[index].sh_size / sizeof(Elf_Sym)); + for (i = 0; i < nsym; i++) + { + if ((symtab[i].st_shndx == SHN_COMMON) && + (symtab[i].st_value > common_align)) + { + common_align = symtab[i].st_value; + } + } module_size += RT_ALIGN(dlmodule_common_block(symtab, nsym, RT_NULL), sizeof(rt_ubase_t)); } + /* The actual base is known only after allocation. Reserve the worst-case + * padding needed to align the common block after all sections are loaded. */ + if (common_align > 1) + { + module_size += common_align - 1; + } + /* no text, data and bss on image */ if (module_size == 0) return RT_NULL; @@ -422,6 +438,14 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module } module->mem_size = module_size; + section_load_addr = rt_calloc(elf_module->e_shnum, + sizeof(*section_load_addr)); + if (section_load_addr == RT_NULL) + { + LOG_E("Module: allocate section address table failed.\n"); + return -RT_ENOMEM; + } + /* zero all space */ ptr = module->mem_space; rt_memset(ptr, 0, module_size); @@ -432,6 +456,7 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module /* load text section */ if (IS_PROG(shdr[index]) && IS_AX(shdr[index])) { + section_load_addr[index] = (rt_ubase_t)ptr; rt_memcpy(ptr, (rt_uint8_t *)elf_module + shdr[index].sh_offset, shdr[index].sh_size); @@ -442,6 +467,7 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module /* load rodata section */ if (IS_PROG(shdr[index]) && IS_ALLOC(shdr[index])) { + section_load_addr[index] = (rt_ubase_t)ptr; rt_memcpy(ptr, (rt_uint8_t *)elf_module + shdr[index].sh_offset, shdr[index].sh_size); @@ -454,6 +480,7 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module /* load data section */ if (IS_PROG(shdr[index]) && IS_AW(shdr[index])) { + section_load_addr[index] = (rt_ubase_t)ptr; rt_memcpy(ptr, (rt_uint8_t *)elf_module + shdr[index].sh_offset, shdr[index].sh_size); @@ -466,6 +493,7 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module /* load bss section */ if (IS_NOPROG(shdr[index]) && IS_AW(shdr[index])) { + section_load_addr[index] = (rt_ubase_t)ptr; rt_memset(ptr, 0, shdr[index].sh_size); bss_addr = (rt_ubase_t)ptr; LOG_D("load bss 0x%x, size %d", ptr, shdr[index].sh_size); @@ -475,7 +503,7 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module /* the common block (uninitialized global variables) starts right after * the loaded sections; it was zeroed together with the module space */ - common_addr = (rt_ubase_t)ptr; + common_addr = RT_ALIGN((rt_ubase_t)ptr, common_align); /* set module entry */ module->entry_addr = (rt_dlmodule_entry_func_t)((rt_uint8_t *)module->mem_space + elf_module->e_entry - module_addr); @@ -639,36 +667,61 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module for (i = 0; i < shdr[index].sh_size / sizeof(Elf_Sym); i++) { if ((ELF_ST_BIND(symtab[i].st_info) == STB_GLOBAL) && - (ELF_ST_TYPE(symtab[i].st_info) == STT_FUNC)) + (ELF_ST_TYPE(symtab[i].st_info) == STT_FUNC) && + (symtab[i].st_shndx != SHN_UNDEF) && + (symtab[i].st_shndx < elf_module->e_shnum) && + (section_load_addr[symtab[i].st_shndx] != 0)) { count++; } } - module->symtab = (struct rt_module_symtab *)rt_malloc(count * sizeof(struct rt_module_symtab)); - module->nsym = count; - for (i = 0, count = 0; i < shdr[index].sh_size / sizeof(Elf_Sym); i++) + module->nsym = 0; + if (count > 0) { - rt_size_t length; - - if ((ELF_ST_BIND(symtab[i].st_info) != STB_GLOBAL) || - (ELF_ST_TYPE(symtab[i].st_info) != STT_FUNC)) + module->symtab = (struct rt_module_symtab *)rt_malloc( + count * sizeof(struct rt_module_symtab)); + if (module->symtab == RT_NULL) { - continue; + LOG_E("Module: allocate symbol table failed.\n"); + rt_free(section_load_addr); + return -RT_ENOMEM; } - length = rt_strlen((const char *)(strtab + symtab[i].st_name)) + 1; + for (i = 0; i < shdr[index].sh_size / sizeof(Elf_Sym); i++) + { + rt_size_t length; - module->symtab[count].addr = - (void *)((rt_uint8_t *)module->mem_space - module_addr + symtab[i].st_value); - module->symtab[count].name = rt_malloc(length); - rt_memset((void *)module->symtab[count].name, 0, length); - rt_memcpy((void *)module->symtab[count].name, - strtab + symtab[i].st_name, - length); - count++; + if ((ELF_ST_BIND(symtab[i].st_info) != STB_GLOBAL) || + (ELF_ST_TYPE(symtab[i].st_info) != STT_FUNC) || + (symtab[i].st_shndx == SHN_UNDEF) || + (symtab[i].st_shndx >= elf_module->e_shnum) || + (section_load_addr[symtab[i].st_shndx] == 0)) + { + continue; + } + + length = rt_strlen((const char *)(strtab + symtab[i].st_name)) + 1; + + module->symtab[module->nsym].addr = + (void *)(section_load_addr[symtab[i].st_shndx] - + shdr[symtab[i].st_shndx].sh_addr + symtab[i].st_value); + module->symtab[module->nsym].name = rt_malloc(length); + if (module->symtab[module->nsym].name == RT_NULL) + { + LOG_E("Module: allocate symbol name failed.\n"); + rt_free(section_load_addr); + return -RT_ENOMEM; + } + rt_memset((void *)module->symtab[module->nsym].name, 0, length); + rt_memcpy((void *)module->symtab[module->nsym].name, + strtab + symtab[i].st_name, + length); + module->nsym++; + } } } + rt_free(section_load_addr); return RT_EOK; } diff --git a/components/libc/posix/libdl/dlelf.h b/components/libc/posix/libdl/dlelf.h index 15d4ddba601b..e5acaf7f5719 100644 --- a/components/libc/posix/libdl/dlelf.h +++ b/components/libc/posix/libdl/dlelf.h @@ -202,6 +202,7 @@ typedef struct #define STT_HIPROC 15 #define STN_UNDEF 0 /* undefined */ +#define SHN_UNDEF 0x0000 /* undefined section */ #define SHN_COMMON 0xfff2 /* common symbols (uninitialized globals) */ #define ELF_ST_BIND(info) ((info) >> 4) From 6880fad537fa8a3b9186ed26070ebff7a7ba367f Mon Sep 17 00:00:00 2001 From: usualtreee <1340399194@qq.com> Date: Wed, 28 Oct 2026 15:48:37 +0800 Subject: [PATCH 3/3] [dlmodule] fix ET_REL relocation target handling Convert relocation offsets to module-relative addresses using the target section's load address. Use per-section load addresses for defined symbols and ET_REL exports without subtracting sh_addr. Skip relocations whose target sections were not loaded, such as debug sections. Verified with 12 host scenarios using ASan/UBSan and seven modules on qemu-vexpress-a9, including COMMON references in data, multiple NOBITS sections, nonzero sh_addr, and -g debug relocations. --- components/libc/posix/libdl/dlelf.c | 87 +++++++++++------------------ 1 file changed, 33 insertions(+), 54 deletions(-) diff --git a/components/libc/posix/libdl/dlelf.c b/components/libc/posix/libdl/dlelf.c index 5b11f151a0c2..e7ceaf1cef28 100644 --- a/components/libc/posix/libdl/dlelf.c +++ b/components/libc/posix/libdl/dlelf.c @@ -361,7 +361,7 @@ static rt_ubase_t dlmodule_common_block(Elf_Sym *symtab, rt_ubase_t nsym, */ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module_ptr) { - rt_ubase_t index, rodata_addr = 0, bss_addr = 0, data_addr = 0, common_addr = 0; + rt_ubase_t index, common_addr = 0; rt_ubase_t module_addr = 0, module_size = 0, common_align = 1; rt_ubase_t *section_load_addr = RT_NULL; rt_uint8_t *ptr, *strtab, *shstrab; @@ -471,9 +471,7 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module rt_memcpy(ptr, (rt_uint8_t *)elf_module + shdr[index].sh_offset, shdr[index].sh_size); - rodata_addr = (rt_ubase_t)ptr; - LOG_D("load rodata 0x%x, size %d, rodata 0x%x", ptr, - shdr[index].sh_size, *(rt_ubase_t *)rodata_addr); + LOG_D("load rodata 0x%x, size %d", ptr, shdr[index].sh_size); ptr += shdr[index].sh_size; } @@ -484,9 +482,7 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module rt_memcpy(ptr, (rt_uint8_t *)elf_module + shdr[index].sh_offset, shdr[index].sh_size); - data_addr = (rt_ubase_t)ptr; - LOG_D("load data 0x%x, size %d, data 0x%x", ptr, - shdr[index].sh_size, *(rt_ubase_t *)data_addr); + LOG_D("load data 0x%x, size %d", ptr, shdr[index].sh_size); ptr += shdr[index].sh_size; } @@ -495,7 +491,6 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module { section_load_addr[index] = (rt_ubase_t)ptr; rt_memset(ptr, 0, shdr[index].sh_size); - bss_addr = (rt_ubase_t)ptr; LOG_D("load bss 0x%x, size %d", ptr, shdr[index].sh_size); ptr += shdr[index].sh_size; } @@ -523,6 +518,12 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module continue; #endif + /* Only relocate sections that were loaded into module memory. */ + if ((shdr[index].sh_info >= elf_module->e_shnum) || + (section_load_addr[shdr[index].sh_info] == 0)) + { + continue; + } /* get relocate item */ rel = (Elf_Rel *)((rt_uint8_t *)module_ptr + shdr[index].sh_offset); @@ -544,6 +545,12 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module #elif (defined(__aarch64__) || defined(__x86_64__) || (__riscv_xlen == 64)) Elf_Sym *sym = &symtab[ELF64_R_SYM(rel->r_info)]; #endif + Elf_Rel target_rel = *rel; + + /* r_offset is relative to the section being relocated. Convert it + * to the module-relative offset expected by the arch relocator. */ + target_rel.r_offset += section_load_addr[shdr[index].sh_info] - + (rt_ubase_t)module->mem_space; LOG_D("relocate symbol: %s", strtab + sym->st_name); @@ -553,62 +560,34 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module if (sym->st_shndx == SHN_COMMON) { - /* relocate common symbol (uninitialized global variable): - * SHN_COMMON is not a real section index, so it must be - * handled before the section-name checks below */ + /* SHN_COMMON is not a real section index. */ LOG_D("common symbol"); addr = (Elf_Addr)(common_addr + dlmodule_common_block( symtab, (rt_ubase_t)(shdr[shdr[index].sh_link].sh_size / sizeof(Elf_Sym)), sym)); - dlmodule_relocate(module, rel, addr); } - else if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) || - (ELF_ST_TYPE(sym->st_info) == STT_OBJECT)) + else if (((ELF_ST_TYPE(sym->st_info) == STT_SECTION) || + (ELF_ST_TYPE(sym->st_info) == STT_OBJECT) || + (ELF_ST_TYPE(sym->st_info) == STT_FUNC)) && + (sym->st_shndx < elf_module->e_shnum) && + (section_load_addr[sym->st_shndx] != 0)) { - Elf_Addr sec_sh_addr = shdr[sym->st_shndx].sh_addr; - if (rt_strncmp((const char *)(shstrab + - shdr[sym->st_shndx].sh_name), - ELF_RODATA, 8) == 0) - { - /* relocate rodata section */ - LOG_D("rodata"); - addr = (Elf_Addr)(rodata_addr - sec_sh_addr + sym->st_value); - } - else if (rt_strncmp((const char *)(shstrab + shdr[sym->st_shndx].sh_name), ELF_BSS, 5) == 0) - { - /* relocate bss section */ - LOG_D("bss"); - addr = (Elf_Addr)(bss_addr - sec_sh_addr + sym->st_value); - } - else if (rt_strncmp((const char *)(shstrab + shdr[sym->st_shndx].sh_name), ".common", 7) == 0) - { - /* relocate common section (uninitialized globals) */ - LOG_D("common"); - addr = (Elf_Addr)(bss_addr - sec_sh_addr + sym->st_value); - } - else if (rt_strncmp((const char *)(shstrab + shdr[sym->st_shndx].sh_name), - ELF_DATA, 6) == 0) - { - /* relocate data section */ - LOG_D("data"); - addr = (Elf_Addr)(data_addr - sec_sh_addr + sym->st_value); - } - - if (addr != 0) dlmodule_relocate(module, rel, addr); + /* For ET_REL, st_value is already the offset within the + * symbol's section; sh_addr must not be subtracted. */ + addr = (Elf_Addr)(section_load_addr[sym->st_shndx] + + sym->st_value); } - else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC) - { - addr = (Elf_Addr)((rt_uint8_t *) module->mem_space - module_addr + sym->st_value); - /* relocate function */ - dlmodule_relocate(module, rel, addr); + if (addr != 0) + { + dlmodule_relocate(module, &target_rel, addr); } } else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC) { /* relocate function */ - dlmodule_relocate(module, rel, + dlmodule_relocate(module, &target_rel, (Elf_Addr)((rt_uint8_t *) module->mem_space - module_addr @@ -626,7 +605,7 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module addr = dlmodule_symbol_find((const char *)(strtab + sym->st_name)); if (addr != (Elf_Addr)RT_NULL) { - dlmodule_relocate(module, rel, addr); + dlmodule_relocate(module, &target_rel, addr); LOG_D("symbol addr 0x%x", addr); } else @@ -636,7 +615,7 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module else { addr = (Elf_Addr)((rt_uint8_t *) module->mem_space - module_addr + sym->st_value); - dlmodule_relocate(module, rel, addr); + dlmodule_relocate(module, &target_rel, addr); } } @@ -704,8 +683,8 @@ rt_err_t dlmodule_load_relocated_object(struct rt_dlmodule* module, void *module length = rt_strlen((const char *)(strtab + symtab[i].st_name)) + 1; module->symtab[module->nsym].addr = - (void *)(section_load_addr[symtab[i].st_shndx] - - shdr[symtab[i].st_shndx].sh_addr + symtab[i].st_value); + (void *)(section_load_addr[symtab[i].st_shndx] + + symtab[i].st_value); module->symtab[module->nsym].name = rt_malloc(length); if (module->symtab[module->nsym].name == RT_NULL) {