Expand special names in DT_NEEDED names too (for #4682)

This commit is contained in:
ptitSeb committed 2026-11-07 11:26:50 +01:00
1 parent 70cdfdb2c2
commit 37f5e4b7b0
4 files changed
+116 -71

No files matched your search

+83 -71
View File
@@ -1138,6 +1138,81 @@ $PLATFORM – Expands to the processor type of the current machine (see the
uname(1) man page description of the -i option). For more details of this token
expansion, see “System Specific Shared Objects”
*/
char* ExpandNeededLibs(elfheader_t* h, char* rpath)
{
if(!rpath || !h) return rpath;
char* rpathref = rpath;
while(strstr(rpath, "$$ORIGIN")) {
char* origin = box_strdup(h->path);
char* p = strrchr(origin, '/');
if(p) *p = '\0'; // remove file name to have only full path, without last '/'
char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("$$ORIGIN")+strlen(origin)+1);
p = strstr(rpath, "$$ORIGIN");
memcpy(tmp, rpath, p-rpath);
strcat(tmp, origin);
strcat(tmp, p+strlen("$$ORIGIN"));
if(rpath!=rpathref)
box_free(rpath);
rpath = tmp;
box_free(origin);
}
while(strstr(rpath, "$ORIGIN")) {
char* origin = box_strdup(h->path);
char* p = strrchr(origin, '/');
if(p) *p = '\0'; // remove file name to have only full path, without last '/'
char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("$ORIGIN")+strlen(origin)+1);
p = strstr(rpath, "$ORIGIN");
memcpy(tmp, rpath, p-rpath);
strcat(tmp, origin);
strcat(tmp, p+strlen("$ORIGIN"));
if(rpath!=rpathref)
box_free(rpath);
rpath = tmp;
box_free(origin);
}
while(strstr(rpath, "${ORIGIN}")) {
char* origin = box_strdup(h->path);
char* p = strrchr(origin, '/');
if(p) *p = '\0'; // remove file name to have only full path, without last '/'
char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("${ORIGIN}")+strlen(origin)+1);
p = strstr(rpath, "${ORIGIN}");
memcpy(tmp, rpath, p-rpath);
strcat(tmp, origin);
strcat(tmp, p+strlen("${ORIGIN}"));
if(rpath!=rpathref)
box_free(rpath);
rpath = tmp;
box_free(origin);
if(!FileExist(rpath, 0) && strstr(rpath, "/../../")) {
tmp = (char*)box_calloc(1, strlen(rpath)+1);
strcpy(tmp, rpath);
// check if one "/.." could be removed for the folder to exist
char* p = strstr(tmp, "/../../");
memmove(p, p+3, strlen(p+3)+1);
if(FileExist(tmp, 0)) {
if(rpath!=rpathref)
box_free(rpath);
rpath = tmp;
} else
box_free(tmp);
}
}
while(strstr(rpath, "${PLATFORM}")) {
char* platform = box_strdup("x86_64");
char* p = strrchr(platform, '/');
if(p) *p = '\0'; // remove file name to have only full path, without last '/'
char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("${PLATFORM}")+strlen(platform)+1);
p = strstr(rpath, "${PLATFORM}");
memcpy(tmp, rpath, p-rpath);
strcat(tmp, platform);
strcat(tmp, p+strlen("${PLATFORM}"));
if(rpath!=rpathref)
box_free(rpath);
rpath = tmp;
box_free(platform);
}
return rpath;
}
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, int deepbind, box64context_t *box64, x64emu_t* emu)
{
if(h->needed) // already done
@@ -1150,75 +1225,7 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, int de
if(tag==DT_RPATH || tag==DT_RUNPATH) {
char *rpathref = h->DynStrTab+h->delta+(box64_is32bits?h->Dynamic._32[i].d_un.d_val:h->Dynamic._64[i].d_un.d_val);
char* rpath = rpathref;
while(strstr(rpath, "$$ORIGIN")) {
char* origin = box_strdup(h->path);
char* p = strrchr(origin, '/');
if(p) *p = '\0'; // remove file name to have only full path, without last '/'
char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("$$ORIGIN")+strlen(origin)+1);
p = strstr(rpath, "$$ORIGIN");
memcpy(tmp, rpath, p-rpath);
strcat(tmp, origin);
strcat(tmp, p+strlen("$$ORIGIN"));
if(rpath!=rpathref)
box_free(rpath);
rpath = tmp;
box_free(origin);
}
while(strstr(rpath, "$ORIGIN")) {
char* origin = box_strdup(h->path);
char* p = strrchr(origin, '/');
if(p) *p = '\0'; // remove file name to have only full path, without last '/'
char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("$ORIGIN")+strlen(origin)+1);
p = strstr(rpath, "$ORIGIN");
memcpy(tmp, rpath, p-rpath);
strcat(tmp, origin);
strcat(tmp, p+strlen("$ORIGIN"));
if(rpath!=rpathref)
box_free(rpath);
rpath = tmp;
box_free(origin);
}
while(strstr(rpath, "${ORIGIN}")) {
char* origin = box_strdup(h->path);
char* p = strrchr(origin, '/');
if(p) *p = '\0'; // remove file name to have only full path, without last '/'
char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("${ORIGIN}")+strlen(origin)+1);
p = strstr(rpath, "${ORIGIN}");
memcpy(tmp, rpath, p-rpath);
strcat(tmp, origin);
strcat(tmp, p+strlen("${ORIGIN}"));
if(rpath!=rpathref)
box_free(rpath);
rpath = tmp;
box_free(origin);
if(!FileExist(rpath, 0) && strstr(rpath, "/../../")) {
tmp = (char*)box_calloc(1, strlen(rpath)+1);
strcpy(tmp, rpath);
// check if one "/.." could be removed for the folder to exist
char* p = strstr(tmp, "/../../");
memmove(p, p+3, strlen(p+3)+1);
if(FileExist(tmp, 0)) {
if(rpath!=rpathref)
box_free(rpath);
rpath = tmp;
} else
box_free(tmp);
}
}
while(strstr(rpath, "${PLATFORM}")) {
char* platform = box_strdup("x86_64");
char* p = strrchr(platform, '/');
if(p) *p = '\0'; // remove file name to have only full path, without last '/'
char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("${PLATFORM}")+strlen(platform)+1);
p = strstr(rpath, "${PLATFORM}");
memcpy(tmp, rpath, p-rpath);
strcat(tmp, platform);
strcat(tmp, p+strlen("${PLATFORM}"));
if(rpath!=rpathref)
box_free(rpath);
rpath = tmp;
box_free(platform);
}
rpath = ExpandNeededLibs(h, rpath);
if(strchr(rpath, '$')) {
printf_log(LOG_INFO, "Warning, RPATH with $ variable not supported yet (%s)\n", rpath);
} else {
@@ -1255,8 +1262,13 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, int de
my_context->neededlibs = h->needed;
int j=0;
for (size_t i=0; i<h->numDynamic; ++i)
if((box64_is32bits?h->Dynamic._32[i].d_tag:h->Dynamic._64[i].d_tag)==DT_NEEDED)
h->needed->names[j++] = h->DynStrTab+h->delta+(box64_is32bits?h->Dynamic._32[i].d_un.d_val:h->Dynamic._64[i].d_un.d_val);
if((box64_is32bits?h->Dynamic._32[i].d_tag:h->Dynamic._64[i].d_tag)==DT_NEEDED) {
char* path = h->DynStrTab+h->delta+(box64_is32bits?h->Dynamic._32[i].d_un.d_val:h->Dynamic._64[i].d_un.d_val);
char* newpath = ExpandNeededLibs(h, path);
if(path!=newpath)
path = add1nsname(h->needed, newpath);
h->needed->names[j++] = path;
}
#ifndef ANDROID
if(box64_is32bits && strstr(h->name, "lsteamclient.dll.so"))
h->needed->names[j++] = "libgcc_s.so.1";
+3
View File
@@ -79,6 +79,8 @@ typedef struct needed_libs_s {
library_t** libs;
path_collection_t* rpath;
int nb_done;
char** nonstaticnames;
int ns_size;
} needed_libs_t;
void free_neededlib(needed_libs_t* needed);
@@ -88,6 +90,7 @@ void add1_neededlib(needed_libs_t* needed);
void add1lib_neededlib(needed_libs_t* needed, library_t* lib, const char* name);
void add1lib_neededlib_name(needed_libs_t* needed, library_t* lib, const char* name);
void add1libref_neededlib(needed_libs_t* needed, library_t* lib);
char* add1nsname(needed_libs_t* needed, char* nsname);
typedef struct base_segment_s {
uintptr_t base;
+1
View File
@@ -54,6 +54,7 @@ uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h);
uintptr_t GetLastByte(elfheader_t* h);
void AddSymbols(lib_t *maplib, elfheader_t* h);
int NeededLibs(elfheader_t* h);
char* ExpandNeededLibs(elfheader_t* h, char* rpath);
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, int deepbind, box64context_t *box64, x64emu_t* emu);
needed_libs_t* GetELfNeededLibs(elfheader_t* h);
uintptr_t GetElfInit(elfheader_t* h);
+29
View File
@@ -1323,6 +1323,13 @@ void free_neededlib(needed_libs_t* needed)
FreeCollection(needed->rpath);
box_free(needed->rpath);
}
if(needed->nonstaticnames) {
for(int i=0; i<needed->ns_size; ++i)
box_free(needed->nonstaticnames[i]);
box_free(needed->nonstaticnames);
needed->ns_size = 0;
needed->nonstaticnames = NULL;
}
box_free(needed);
}
void add1_neededlib(needed_libs_t* needed)
@@ -1406,8 +1413,30 @@ needed_libs_t* copy_neededlib(needed_libs_t* needed)
ret->names = (char**)box_calloc(ret->cap, sizeof(char*));
memcpy(ret->libs, needed->libs, ret->size*sizeof(library_t*));
memcpy(ret->names, needed->names, ret->size*sizeof(char*));
if(needed->nonstaticnames) {
ret->ns_size = needed->ns_size;
ret->nonstaticnames = (char**)box_malloc(ret->ns_size*sizeof(char*));
for(int i=0; i<ret->ns_size; ++i)
ret->nonstaticnames[i] = box_strdup(needed->nonstaticnames[i]);
}
return ret;
}
char* add1nsname(needed_libs_t* needed, char* nsname)
{
if(!needed->ns_size) {
needed->ns_size = 1;
needed->nonstaticnames = (char**)box_malloc(needed->ns_size*sizeof(char*));
needed->nonstaticnames[0] = nsname;
return needed->nonstaticnames[0];
}
for(int i=0; i<needed->ns_size; ++i)
if(!strcmp(needed->nonstaticnames[i], nsname))
return needed->nonstaticnames[i];
int i = needed->ns_size++;
needed->nonstaticnames = (char**)box_realloc(needed->nonstaticnames, (i+1)*sizeof(char*));
needed->nonstaticnames[i] = nsname;
return needed->nonstaticnames[i];
}
void setNeededLibs(library_t* lib, int n, ...)
{