diff options
| author | ruki <[email protected]> | 2025-12-12 23:57:08 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2025-12-12 23:57:08 +0800 |
| commit | d131da854a1f2b62fd26237b95f55441b1ea3b75 (patch) | |
| tree | f7354bdd26056f765fb7a8ae8a98f3cd6160bde0 /core/src | |
| parent | c5a01a4d8de7e7775ed410486a46278f0817841e (diff) | |
improve deplibs for elf
Diffstat (limited to 'core/src')
| -rw-r--r-- | core/src/xmake/binutils/elf/deplibs.c | 216 | ||||
| -rw-r--r-- | core/src/xmake/binutils/elf/prefix.h | 2 |
2 files changed, 160 insertions, 58 deletions
diff --git a/core/src/xmake/binutils/elf/deplibs.c b/core/src/xmake/binutils/elf/deplibs.c index c79190634..6ee471af7 100644 --- a/core/src/xmake/binutils/elf/deplibs.c +++ b/core/src/xmake/binutils/elf/deplibs.c @@ -70,44 +70,94 @@ static tb_bool_t xm_binutils_elf_deplibs_32(tb_stream_ref_t istream, tb_hize_t b } } - // find .dynamic section - xm_elf32_section_t dynamic_section; - tb_bool_t found_dynamic = tb_false; + // find .dynamic section info + tb_uint32_t dynamic_offset = 0; + tb_uint32_t dynamic_size = 0; + tb_uint32_t strtab_offset = 0; - if (!tb_stream_seek(istream, base_offset + header.e_shoff)) { - return tb_false; - } + // try to find from section headers first + if (header.e_shoff != 0 && header.e_shnum > 0) { + if (tb_stream_seek(istream, base_offset + header.e_shoff)) { + for (tb_uint16_t i = 0; i < header.e_shnum; i++) { + xm_elf32_section_t section; + if (!tb_stream_bread(istream, (tb_byte_t*)§ion, sizeof(section))) { + break; + } - for (tb_uint16_t i = 0; i < header.e_shnum; i++) { - xm_elf32_section_t section; - if (!tb_stream_bread(istream, (tb_byte_t*)§ion, sizeof(section))) { - return tb_false; - } + if (section.sh_type == XM_ELF_SHT_DYNAMIC) { + dynamic_offset = section.sh_offset; + dynamic_size = section.sh_size; - if (section.sh_type == XM_ELF_SHT_DYNAMIC) { - dynamic_section = section; - found_dynamic = tb_true; - break; + // find string table via sh_link + xm_elf32_section_t strtab_section; + if (tb_stream_seek(istream, base_offset + header.e_shoff + section.sh_link * sizeof(xm_elf32_section_t)) && + tb_stream_bread(istream, (tb_byte_t*)&strtab_section, sizeof(strtab_section))) { + strtab_offset = strtab_section.sh_offset; + } + break; + } + } } } - if (!found_dynamic) { - return tb_true; // no dynamic section - } + // fallback to program headers if not found in sections + if ((dynamic_offset == 0 || strtab_offset == 0) && header.e_phoff != 0 && header.e_phnum > 0) { + if (tb_stream_seek(istream, base_offset + header.e_phoff)) { + for (tb_uint16_t i = 0; i < header.e_phnum; i++) { + xm_elf32_phdr_t phdr; + if (!tb_stream_bread(istream, (tb_byte_t*)&phdr, sizeof(phdr))) { + break; + } + if (phdr.p_type == XM_ELF_PT_DYNAMIC) { + dynamic_offset = phdr.p_offset; + dynamic_size = phdr.p_memsz; // usually p_filesz == p_memsz for dynamic + break; + } + } + } - // find string table for dynamic section - // sh_link of dynamic section contains the section header index of the string table - xm_elf32_section_t strtab_section; - if (!tb_stream_seek(istream, base_offset + header.e_shoff + dynamic_section.sh_link * sizeof(xm_elf32_section_t))) { - return tb_false; + if (dynamic_offset > 0 && dynamic_size > 0) { + // read dynamic entries to find strtab address + tb_uint32_t strtab_vaddr = 0; + tb_uint32_t count = dynamic_size / sizeof(xm_elf32_dynamic_t); + if (tb_stream_seek(istream, base_offset + dynamic_offset)) { + for (tb_uint32_t i = 0; i < count; i++) { + xm_elf32_dynamic_t dyn; + if (!tb_stream_bread(istream, (tb_byte_t*)&dyn, sizeof(dyn))) { + break; + } + if (dyn.d_tag == XM_ELF_DT_STRTAB) { + strtab_vaddr = dyn.d_un.d_val; + break; + } + } + } + + if (strtab_vaddr > 0) { + // map strtab vaddr to file offset using PT_LOAD + if (tb_stream_seek(istream, base_offset + header.e_phoff)) { + for (tb_uint16_t i = 0; i < header.e_phnum; i++) { + xm_elf32_phdr_t phdr; + if (!tb_stream_bread(istream, (tb_byte_t*)&phdr, sizeof(phdr))) { + break; + } + if (phdr.p_type == XM_ELF_PT_LOAD && strtab_vaddr >= phdr.p_vaddr && strtab_vaddr < phdr.p_vaddr + phdr.p_memsz) { + strtab_offset = phdr.p_offset + (strtab_vaddr - phdr.p_vaddr); + break; + } + } + } + } + } } - if (!tb_stream_bread(istream, (tb_byte_t*)&strtab_section, sizeof(strtab_section))) { - return tb_false; + + if (dynamic_offset == 0 || strtab_offset == 0) { + return tb_true; // no dynamic section or strtab found } // read dynamic entries - tb_uint32_t count = dynamic_section.sh_size / sizeof(xm_elf32_dynamic_t); - if (!tb_stream_seek(istream, base_offset + dynamic_section.sh_offset)) { + tb_uint32_t count = dynamic_size / sizeof(xm_elf32_dynamic_t); + if (!tb_stream_seek(istream, base_offset + dynamic_offset)) { return tb_false; } @@ -121,9 +171,9 @@ static tb_bool_t xm_binutils_elf_deplibs_32(tb_stream_ref_t istream, tb_hize_t b break; } - if (dyn.d_tag == XM_ELF_DT_NEEDED || dyn.d_tag == XM_ELF_DT_SONAME) { + if (dyn.d_tag == XM_ELF_DT_NEEDED || dyn.d_tag == XM_ELF_DT_SONAME || dyn.d_tag == XM_ELF_DT_AUXILIARY || dyn.d_tag == XM_ELF_DT_FILTER) { tb_char_t name[256]; - if (xm_binutils_elf_read_string(istream, base_offset + strtab_section.sh_offset, dyn.d_un.d_val, name, sizeof(name)) && name[0]) { + if (xm_binutils_elf_read_string(istream, base_offset + strtab_offset, dyn.d_un.d_val, name, sizeof(name)) && name[0]) { lua_pushinteger(lua, result_count + 1); lua_pushstring(lua, name); lua_settable(lua, -3); @@ -171,44 +221,94 @@ static tb_bool_t xm_binutils_elf_deplibs_64(tb_stream_ref_t istream, tb_hize_t b } } - // find .dynamic section - xm_elf64_section_t dynamic_section; - tb_bool_t found_dynamic = tb_false; + // find .dynamic section info + tb_uint64_t dynamic_offset = 0; + tb_uint64_t dynamic_size = 0; + tb_uint64_t strtab_offset = 0; - if (!tb_stream_seek(istream, base_offset + header.e_shoff)) { - return tb_false; - } + // try to find from section headers first + if (header.e_shoff != 0 && header.e_shnum > 0) { + if (tb_stream_seek(istream, base_offset + header.e_shoff)) { + for (tb_uint16_t i = 0; i < header.e_shnum; i++) { + xm_elf64_section_t section; + if (!tb_stream_bread(istream, (tb_byte_t*)§ion, sizeof(section))) { + break; + } - for (tb_uint16_t i = 0; i < header.e_shnum; i++) { - xm_elf64_section_t section; - if (!tb_stream_bread(istream, (tb_byte_t*)§ion, sizeof(section))) { - return tb_false; - } + if (section.sh_type == XM_ELF_SHT_DYNAMIC) { + dynamic_offset = section.sh_offset; + dynamic_size = section.sh_size; - if (section.sh_type == XM_ELF_SHT_DYNAMIC) { - dynamic_section = section; - found_dynamic = tb_true; - break; + // find string table via sh_link + xm_elf64_section_t strtab_section; + if (tb_stream_seek(istream, base_offset + header.e_shoff + section.sh_link * sizeof(xm_elf64_section_t)) && + tb_stream_bread(istream, (tb_byte_t*)&strtab_section, sizeof(strtab_section))) { + strtab_offset = strtab_section.sh_offset; + } + break; + } + } } } - if (!found_dynamic) { - return tb_true; // no dynamic section - } + // fallback to program headers if not found in sections + if ((dynamic_offset == 0 || strtab_offset == 0) && header.e_phoff != 0 && header.e_phnum > 0) { + if (tb_stream_seek(istream, base_offset + header.e_phoff)) { + for (tb_uint16_t i = 0; i < header.e_phnum; i++) { + xm_elf64_phdr_t phdr; + if (!tb_stream_bread(istream, (tb_byte_t*)&phdr, sizeof(phdr))) { + break; + } + if (phdr.p_type == XM_ELF_PT_DYNAMIC) { + dynamic_offset = phdr.p_offset; + dynamic_size = phdr.p_memsz; + break; + } + } + } - // find string table for dynamic section - // sh_link of dynamic section contains the section header index of the string table - xm_elf64_section_t strtab_section; - if (!tb_stream_seek(istream, base_offset + header.e_shoff + dynamic_section.sh_link * sizeof(xm_elf64_section_t))) { - return tb_false; + if (dynamic_offset > 0 && dynamic_size > 0) { + // read dynamic entries to find strtab address + tb_uint64_t strtab_vaddr = 0; + tb_uint32_t count = (tb_uint32_t)(dynamic_size / sizeof(xm_elf64_dynamic_t)); + if (tb_stream_seek(istream, base_offset + dynamic_offset)) { + for (tb_uint32_t i = 0; i < count; i++) { + xm_elf64_dynamic_t dyn; + if (!tb_stream_bread(istream, (tb_byte_t*)&dyn, sizeof(dyn))) { + break; + } + if (dyn.d_tag == XM_ELF_DT_STRTAB) { + strtab_vaddr = dyn.d_un.d_val; + break; + } + } + } + + if (strtab_vaddr > 0) { + // map strtab vaddr to file offset using PT_LOAD + if (tb_stream_seek(istream, base_offset + header.e_phoff)) { + for (tb_uint16_t i = 0; i < header.e_phnum; i++) { + xm_elf64_phdr_t phdr; + if (!tb_stream_bread(istream, (tb_byte_t*)&phdr, sizeof(phdr))) { + break; + } + if (phdr.p_type == XM_ELF_PT_LOAD && strtab_vaddr >= phdr.p_vaddr && strtab_vaddr < phdr.p_vaddr + phdr.p_memsz) { + strtab_offset = phdr.p_offset + (strtab_vaddr - phdr.p_vaddr); + break; + } + } + } + } + } } - if (!tb_stream_bread(istream, (tb_byte_t*)&strtab_section, sizeof(strtab_section))) { - return tb_false; + + if (dynamic_offset == 0 || strtab_offset == 0) { + return tb_true; // no dynamic section or strtab found } // read dynamic entries - tb_uint32_t count = (tb_uint32_t)(dynamic_section.sh_size / sizeof(xm_elf64_dynamic_t)); - if (!tb_stream_seek(istream, base_offset + dynamic_section.sh_offset)) { + tb_uint32_t count = (tb_uint32_t)(dynamic_size / sizeof(xm_elf64_dynamic_t)); + if (!tb_stream_seek(istream, base_offset + dynamic_offset)) { return tb_false; } @@ -222,9 +322,9 @@ static tb_bool_t xm_binutils_elf_deplibs_64(tb_stream_ref_t istream, tb_hize_t b break; } - if (dyn.d_tag == XM_ELF_DT_NEEDED || dyn.d_tag == XM_ELF_DT_SONAME) { + if (dyn.d_tag == XM_ELF_DT_NEEDED || dyn.d_tag == XM_ELF_DT_SONAME || dyn.d_tag == XM_ELF_DT_AUXILIARY || dyn.d_tag == XM_ELF_DT_FILTER) { tb_char_t name[256]; - if (xm_binutils_elf_read_string(istream, base_offset + strtab_section.sh_offset, (tb_uint32_t)dyn.d_un.d_val, name, sizeof(name)) && name[0]) { + if (xm_binutils_elf_read_string(istream, base_offset + strtab_offset, (tb_uint32_t)dyn.d_un.d_val, name, sizeof(name)) && name[0]) { lua_pushinteger(lua, result_count + 1); lua_pushstring(lua, name); lua_settable(lua, -3); diff --git a/core/src/xmake/binutils/elf/prefix.h b/core/src/xmake/binutils/elf/prefix.h index a967c5ce7..4e61c4741 100644 --- a/core/src/xmake/binutils/elf/prefix.h +++ b/core/src/xmake/binutils/elf/prefix.h @@ -60,6 +60,8 @@ #define XM_ELF_DT_STRTAB 5 #define XM_ELF_DT_STRSZ 10 #define XM_ELF_DT_SONAME 14 +#define XM_ELF_DT_AUXILIARY 0x7ffffffd +#define XM_ELF_DT_FILTER 0x7fffffff #define XM_ELF_SHF_ALLOC 0x2 #define XM_ELF_SHF_WRITE 0x1 |
