diff options
| author | ruki <[email protected]> | 2025-12-14 23:10:20 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2025-12-14 23:10:20 +0800 |
| commit | 3a9dd63237efbe9e49ee026bc882c03c8622d722 (patch) | |
| tree | 219e678ba5219ab7b12e393963680f16cf14b72f /core/src | |
| parent | cdfc65c451343242c4d007483da1ad4a6ba7fe84 (diff) | |
fix elf deplibs
Diffstat (limited to 'core/src')
| -rw-r--r-- | core/src/xmake/binutils/elf/deplibs.c | 187 | ||||
| -rw-r--r-- | core/src/xmake/binutils/elf/prefix.h | 2 |
2 files changed, 161 insertions, 28 deletions
diff --git a/core/src/xmake/binutils/elf/deplibs.c b/core/src/xmake/binutils/elf/deplibs.c index 39c5625ed..2b58902ef 100644 --- a/core/src/xmake/binutils/elf/deplibs.c +++ b/core/src/xmake/binutils/elf/deplibs.c @@ -34,6 +34,89 @@ * private implementation */ + +static tb_bool_t xm_binutils_elf_check_path(tb_char_t const* path, tb_char_t const* name, tb_char_t* output, tb_size_t output_size) { + tb_char_t fullpath[TB_PATH_MAXN]; + tb_snprintf(fullpath, sizeof(fullpath), "%s/%s", path, name); + if (tb_file_info(fullpath, tb_null)) { + if (output) { + tb_strlcpy(output, fullpath, output_size); + } + return tb_true; + } + return tb_false; +} + +static tb_void_t xm_binutils_elf_resolve_path(tb_char_t const* name, tb_char_t const* rpath, tb_char_t const* binary_dir, tb_char_t* output, tb_size_t output_size) { + + // absolute path? + if (tb_path_is_absolute(name)) { + tb_strlcpy(output, name, output_size); + return; + } + + // try rpath/runpath + if (rpath && binary_dir) { + tb_char_t const* p = rpath; + tb_char_t const* e = tb_null; + while (*p) { + e = tb_strchr(p, ':'); + tb_size_t n = e ? (tb_size_t)(e - p) : tb_strlen(p); + if (n > 0) { + tb_char_t path[TB_PATH_MAXN]; + tb_char_t expanded_path[TB_PATH_MAXN]; + tb_strncpy(path, p, n); + path[n] = '\0'; + + // replace $ORIGIN + tb_char_t* origin = tb_strstr(path, "$ORIGIN"); + if (origin) { + tb_long_t len = tb_snprintf(expanded_path, sizeof(expanded_path), "%.*s%s%s", (tb_int_t)(origin - path), path, binary_dir, origin + 7); + if (len >= 0) { + if (xm_binutils_elf_check_path(expanded_path, name, output, output_size)) { + return; + } + } + } else { + if (xm_binutils_elf_check_path(path, name, output, output_size)) { + return; + } + } + } + if (e) p = e + 1; + else break; + } + } + + // try system paths + static tb_char_t const* s_sys_paths[] = { + "/lib", + "/usr/lib", + "/lib64", + "/usr/lib64", + "/usr/local/lib", + "/usr/local/lib64", + "/lib/x86_64-linux-gnu", // Debian/Ubuntu + "/usr/lib/x86_64-linux-gnu", + "/lib/i386-linux-gnu", + "/usr/lib/i386-linux-gnu", + "/lib/aarch64-linux-gnu", + "/usr/lib/aarch64-linux-gnu", + "/lib/arm-linux-gnueabihf", + "/usr/lib/arm-linux-gnueabihf", + tb_null + }; + + for (tb_char_t const** sys_path = s_sys_paths; *sys_path; sys_path++) { + if (xm_binutils_elf_check_path(*sys_path, name, output, output_size)) { + return; + } + } + + // not found, return original name + tb_strlcpy(output, name, output_size); +} + static tb_bool_t xm_binutils_elf_deplibs_32(tb_stream_ref_t istream, tb_hize_t base_offset, lua_State *lua) { tb_assert_and_check_return_val(istream && lua, tb_false); @@ -161,25 +244,49 @@ static tb_bool_t xm_binutils_elf_deplibs_32(tb_stream_ref_t istream, tb_hize_t b return tb_false; } - 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))) { - return tb_false; + tb_char_t rpath[8192] = {0}; + tb_char_t runpath[8192] = {0}; + tb_vector_ref_t needed_libs = tb_vector_init(0, tb_element_str(tb_true)); + if (needed_libs) { + 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_NULL) { + break; + } + + 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_read_string(istream, base_offset + strtab_offset + dyn.d_un.d_val, name, sizeof(name)) && name[0]) { + tb_vector_insert_tail(needed_libs, name); + } + } else if (dyn.d_tag == XM_ELF_DT_RPATH) { + xm_binutils_read_string(istream, base_offset + strtab_offset + dyn.d_un.d_val, rpath, sizeof(rpath)); + } else if (dyn.d_tag == XM_ELF_DT_RUNPATH) { + xm_binutils_read_string(istream, base_offset + strtab_offset + dyn.d_un.d_val, runpath, sizeof(runpath)); + } } - if (dyn.d_tag == XM_ELF_DT_NULL) { - break; + // get binary directory + tb_char_t const* binary_path = tb_null; + tb_char_t binary_dir[TB_PATH_MAXN] = {0}; + if (tb_stream_ctrl(istream, TB_STREAM_CTRL_GET_PATH, &binary_path) && binary_path) { + tb_path_directory(binary_path, binary_dir, sizeof(binary_dir)); } - 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_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); - result_count++; - } + // resolve and push paths + tb_for_all (tb_char_t const*, name, needed_libs) { + tb_char_t fullpath[TB_PATH_MAXN]; + xm_binutils_elf_resolve_path(name, runpath[0]? runpath : rpath, binary_dir[0]? binary_dir : tb_null, fullpath, sizeof(fullpath)); + lua_pushinteger(lua, result_count + 1); + lua_pushstring(lua, fullpath); + lua_settable(lua, -3); + result_count++; } + tb_vector_exit(needed_libs); } return tb_true; @@ -312,25 +419,49 @@ static tb_bool_t xm_binutils_elf_deplibs_64(tb_stream_ref_t istream, tb_hize_t b return tb_false; } - 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))) { - return tb_false; + tb_char_t rpath[8192] = {0}; + tb_char_t runpath[8192] = {0}; + tb_vector_ref_t needed_libs = tb_vector_init(0, tb_element_str(tb_true)); + if (needed_libs) { + 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_NULL) { + break; + } + + 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_read_string(istream, base_offset + strtab_offset + (tb_uint32_t)dyn.d_un.d_val, name, sizeof(name)) && name[0]) { + tb_vector_insert_tail(needed_libs, name); + } + } else if (dyn.d_tag == XM_ELF_DT_RPATH) { + xm_binutils_read_string(istream, base_offset + strtab_offset + (tb_uint32_t)dyn.d_un.d_val, rpath, sizeof(rpath)); + } else if (dyn.d_tag == XM_ELF_DT_RUNPATH) { + xm_binutils_read_string(istream, base_offset + strtab_offset + (tb_uint32_t)dyn.d_un.d_val, runpath, sizeof(runpath)); + } } - if (dyn.d_tag == XM_ELF_DT_NULL) { - break; + // get binary directory + tb_char_t const* binary_path = tb_null; + tb_char_t binary_dir[TB_PATH_MAXN] = {0}; + if (tb_stream_ctrl(istream, TB_STREAM_CTRL_GET_PATH, &binary_path) && binary_path) { + tb_path_directory(binary_path, binary_dir, sizeof(binary_dir)); } - 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_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); - result_count++; - } + // resolve and push paths + tb_for_all (tb_char_t const*, name, needed_libs) { + tb_char_t fullpath[TB_PATH_MAXN]; + xm_binutils_elf_resolve_path(name, runpath[0]? runpath : rpath, binary_dir[0]? binary_dir : tb_null, fullpath, sizeof(fullpath)); + lua_pushinteger(lua, result_count + 1); + lua_pushstring(lua, fullpath); + lua_settable(lua, -3); + result_count++; } + tb_vector_exit(needed_libs); } return tb_true; diff --git a/core/src/xmake/binutils/elf/prefix.h b/core/src/xmake/binutils/elf/prefix.h index caf5ef1e3..c3876fd9f 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_RPATH 15 +#define XM_ELF_DT_RUNPATH 29 #define XM_ELF_DT_AUXILIARY 0x7ffffffd #define XM_ELF_DT_FILTER 0x7fffffff |
