summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorruki <[email protected]>2025-12-14 23:10:20 +0800
committerruki <[email protected]>2025-12-14 23:10:20 +0800
commit3a9dd63237efbe9e49ee026bc882c03c8622d722 (patch)
tree219e678ba5219ab7b12e393963680f16cf14b72f /core/src
parentcdfc65c451343242c4d007483da1ad4a6ba7fe84 (diff)
fix elf deplibs
Diffstat (limited to 'core/src')
-rw-r--r--core/src/xmake/binutils/elf/deplibs.c187
-rw-r--r--core/src/xmake/binutils/elf/prefix.h2
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