summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorruki <[email protected]>2025-12-12 23:57:08 +0800
committerruki <[email protected]>2025-12-12 23:57:08 +0800
commitd131da854a1f2b62fd26237b95f55441b1ea3b75 (patch)
treef7354bdd26056f765fb7a8ae8a98f3cd6160bde0 /core/src
parentc5a01a4d8de7e7775ed410486a46278f0817841e (diff)
improve deplibs for elf
Diffstat (limited to 'core/src')
-rw-r--r--core/src/xmake/binutils/elf/deplibs.c216
-rw-r--r--core/src/xmake/binutils/elf/prefix.h2
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*)&section, 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*)&section, 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*)&section, 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*)&section, 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