Skip to content

Commit abbbd05

Browse files
authored
[ELF] Clean up native symbol resolving stuff (#3469)
1 parent 70bb817 commit abbbd05

File tree

3 files changed

+33
-72
lines changed

3 files changed

+33
-72
lines changed

src/elfs/elfhacks.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,8 @@ int eh_find_sym_hash(eh_obj_t *obj, const char *name, eh_sym_t *sym)
312312

313313
while ((sym->sym == NULL) &&
314314
(chain[idx] != STN_UNDEF)) {
315+
if (chain[idx] >= obj->hash[1] /* nchain */) /* some ELF file contains broken chain! */
316+
break;
315317
esym = &obj->symtab[chain[idx]];
316318

317319
if (esym->st_name) {

src/elfs/elfloader.c

Lines changed: 28 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <link.h>
1111
#include <unistd.h>
1212
#include <errno.h>
13+
#include <fnmatch.h>
1314
#ifndef _DLFCN_H
1415
#include <dlfcn.h>
1516
#endif
@@ -38,6 +39,7 @@
3839
#include "symbols.h"
3940
#include "cleanup.h"
4041
#include "globalsymbols.h"
42+
#include "elfhacks.h"
4143
#ifdef DYNAREC
4244
#include "dynablock.h"
4345
#endif
@@ -1940,72 +1942,60 @@ int NeededLibs(elfheader_t* h)
19401942

19411943
typedef struct search_symbol_s{
19421944
const char* name;
1943-
void* addr;
1944-
void* lib;
1945+
void* addr;
19451946
} search_symbol_t;
1946-
int dl_iterate_phdr_findsymbol(struct dl_phdr_info* info, size_t size, void* data)
1947+
1948+
int dl_iterate_phdr_findsymbol(eh_obj_t* obj, search_symbol_t* s)
19471949
{
1948-
search_symbol_t* s = (search_symbol_t*)data;
1950+
// special case for dlsym -- it's not a versionned symbol in libMangoHud_shim.so.
1951+
if (!fnmatch("*libMangoHud_shim.so*", obj->name, 0) && !strcmp(s->name, "dlsym")) {
1952+
eh_find_sym(obj, "dlsym", &s->addr);
1953+
eh_destroy_obj(obj);
1954+
return !!s->addr;
1955+
}
19491956

1950-
for(int j = 0; j<info->dlpi_phnum; ++j) {
1951-
if (info->dlpi_phdr[j].p_type == PT_DYNAMIC) {
1952-
ElfW(Sym)* sym = NULL;
1953-
ElfW(Word) sym_cnt = 0;
1957+
for (int j = 0; j < obj->phnum; ++j) {
1958+
if (obj->phdr[j].p_type == PT_DYNAMIC) {
19541959
ElfW(Verdef)* verdef = NULL;
19551960
ElfW(Word) verdef_cnt = 0;
1956-
char *strtab = NULL;
1957-
ElfW(Dyn)* dyn = (ElfW(Dyn)*)(info->dlpi_addr + info->dlpi_phdr[j].p_vaddr); //Dynamic Section
1961+
char* strtab = NULL;
1962+
ElfW(Dyn)* dyn = (ElfW(Dyn)*)(obj->addr + obj->phdr[j].p_vaddr);
19581963
// grab the needed info
1959-
while(dyn->d_tag != DT_NULL) {
1960-
switch(dyn->d_tag) {
1964+
while (dyn->d_tag != DT_NULL) {
1965+
switch (dyn->d_tag) {
19611966
case DT_STRTAB:
1962-
strtab = (char *)(dyn->d_un.d_ptr);
1967+
strtab = (char*)(dyn->d_un.d_ptr);
19631968
break;
19641969
case DT_VERDEF:
1965-
verdef = (ElfW(Verdef)*)(info->dlpi_addr + dyn->d_un.d_ptr);
1970+
verdef = (ElfW(Verdef)*)(obj->addr + dyn->d_un.d_ptr);
19661971
break;
19671972
case DT_VERDEFNUM:
19681973
verdef_cnt = dyn->d_un.d_val;
19691974
break;
19701975
}
19711976
++dyn;
19721977
}
1973-
if(strtab && verdef && verdef_cnt) {
1974-
if((uintptr_t)strtab < (uintptr_t)info->dlpi_addr) // this test is need for linux-vdso on PI and some other OS (looks like a bug to me)
1975-
strtab=(char*)((uintptr_t)strtab + info->dlpi_addr);
1976-
// Look fr all defined versions now
1977-
ElfW(Verdef)* v = verdef;
1978-
while(v) {
1979-
ElfW(Verdaux)* vda = (ElfW(Verdaux)*)(((uintptr_t)v) + v->vd_aux);
1980-
if(v->vd_version>0 && !v->vd_flags)
1981-
for(int i=0; i<v->vd_cnt; ++i) {
1982-
const char* vername = (strtab+vda->vda_name);
1983-
if(vername && vername[0] && (s->addr = dlvsym(s->lib, s->name, vername))) {
1984-
printf_log(/*LOG_DEBUG*/LOG_INFO, "Found symbol with version %s, value = %p\n", vername, s->addr);
1985-
return 1; // stop searching
1986-
}
1987-
vda = (ElfW(Verdaux)*)(((uintptr_t)vda) + vda->vda_next);
1988-
}
1989-
v = v->vd_next?(ElfW(Verdef)*)((uintptr_t)v + v->vd_next):NULL;
1978+
1979+
if (strtab && verdef && verdef_cnt) {
1980+
eh_find_sym(obj, s->name, &s->addr);
1981+
if (s->addr) {
1982+
eh_destroy_obj(obj);
1983+
return 1;
19901984
}
19911985
}
19921986
}
19931987
}
1988+
1989+
eh_destroy_obj(obj);
19941990
return 0;
19951991
}
19961992

19971993
void* GetNativeSymbolUnversioned(void* lib, const char* name)
19981994
{
1999-
// try to find "name" in loaded elf, whithout checking for the symbol version (like dlsym, but no version check)
20001995
search_symbol_t s;
20011996
s.name = name;
20021997
s.addr = NULL;
2003-
if(lib)
2004-
s.lib = lib;
2005-
else
2006-
s.lib = my_context->box64lib;
2007-
printf_log(LOG_INFO, "Look for %s in loaded elfs\n", name);
2008-
dl_iterate_phdr(dl_iterate_phdr_findsymbol, &s);
1998+
eh_iterate_obj((eh_iterate_obj_callback_func)dl_iterate_phdr_findsymbol, &s);
20091999
return s.addr;
20102000
}
20112001

src/libtools/libdl.c

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -62,38 +62,9 @@ static void*(*real_dlopen)(const char*, int) = NULL;
6262
static int (*real_dlclose)(void*) = NULL;
6363
static void* (*real_dlsym)(void*, const char*) = NULL;
6464

65-
static void get_real_dlsym(void)
66-
{
67-
eh_obj_t libdl;
68-
int ret;
69-
70-
const char* libs[] = {
71-
"*libMangoHud_shim.so*",
72-
#if defined(__GLIBC__)
73-
"*libdl.so*",
74-
#endif
75-
"*libc.so*",
76-
"*libc.*.so*",
77-
"*ld-musl-*.so*",
78-
};
79-
80-
for (size_t i = 0; i < sizeof(libs) / sizeof(*libs); i++) {
81-
ret = eh_find_obj(&libdl, libs[i]);
82-
if (ret) {
83-
continue;
84-
}
85-
eh_find_sym(&libdl, "dlsym", (void**)&real_dlsym);
86-
eh_destroy_obj(&libdl);
87-
if (real_dlsym) break;
88-
}
89-
}
90-
91-
9265
EXPORT void* dlopen(const char* path, int flags)
9366
{
94-
if(!real_dlopen) {
95-
real_dlopen = GetNativeSymbolUnversioned(RTLD_NEXT, "dlopen");
96-
}
67+
if (!real_dlopen) real_dlopen = GetNativeSymbolUnversioned(RTLD_NEXT, "dlopen");
9768

9869
// will look only for libs loaded with full path (and only on 64bits for now)
9970
if(path && strchr(path, '/') && (/*(box64_is32bits && FileIsX86ELF(path)) ||*/ (!box64_is32bits && FileIsX64ELF(path)))) {
@@ -120,9 +91,7 @@ EXPORT void* dlopen(const char* path, int flags)
12091

12192
EXPORT int dlclose(void* handle)
12293
{
123-
if (!real_dlclose) {
124-
real_dlclose = GetNativeSymbolUnversioned(RTLD_NEXT, "dlclose");
125-
}
94+
if (!real_dlclose) real_dlclose = GetNativeSymbolUnversioned(RTLD_NEXT, "dlclose");
12695

12796
if((uintptr_t)handle>=HOOKLIB && (uintptr_t)handle<HOOKLIB+hooked_size) {
12897
uint32_t i = (uintptr_t)handle-HOOKLIB;
@@ -137,7 +106,7 @@ EXPORT int dlclose(void* handle)
137106

138107
EXPORT void* dlsym(void* handle, const char* symbol)
139108
{
140-
if (!real_dlsym) get_real_dlsym();
109+
if (!real_dlsym) real_dlsym = GetNativeSymbolUnversioned(RTLD_NEXT, "dlsym");
141110

142111
if((uintptr_t)handle>=HOOKLIB && (uintptr_t)handle<HOOKLIB+hooked_size) {
143112
uint32_t i = (uintptr_t)handle-HOOKLIB;

0 commit comments

Comments
 (0)