[ELFLOADER] Improved handling of dlopen local lib (helps Half-Life, Garry's Mod, and probably many other)

This commit is contained in:
ptitSeb 2023-08-26 16:26:30 +02:00
parent 7ae3200c6f
commit 399b2c7f8a
10 changed files with 146 additions and 50 deletions

View File

@ -872,20 +872,25 @@ add_test(NAME idiv COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref20.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
add_test(NAME multiple_dlopen COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test21 -D TEST_OUTPUT=tmpfile21.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref21.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
foreach(file ${extension_tests})
get_filename_component(testname "${file}" NAME_WE)
add_test(NAME "${testname}" COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/extensions/${testname} -D TEST_OUTPUT=tmpfile-${testname}.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/extensions/${testname}.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake)
endforeach()
endforeach()
add_test(NAME sse_optimized COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test17_o2 -D TEST_OUTPUT=tmpfile17_o2.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref17_o2.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(sse_optimized PROPERTIES ENVIRONMENT "BOX86_DYNAREC_FASTNAN=0;BOX86_DYNAREC_FASTROUND=0")
set_tests_properties(sse_optimized PROPERTIES ENVIRONMENT "BOX86_DYNAREC_FASTNAN=0;BOX86_DYNAREC_FASTROUND=0")
endif(BOX86LIB)

View File

@ -59,6 +59,7 @@ typedef struct needed_libs_s {
int size;
char** names;
library_t** libs;
int nb_done;
} needed_libs_t;
void free_neededlib(needed_libs_t* needed);

View File

@ -37,6 +37,7 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername, const char* defver);
void MapLibRemoveLib(lib_t* maplib, library_t* lib);
void MapLibPrependLib(lib_t* maplib, library_t* lib, library_t* ref);
const char* GetMaplibDefaultVersion(lib_t *maplib, lib_t *local_maplib, int isweak, const char* symname);

View File

@ -41,7 +41,7 @@ void FreeLibrarian(lib_t **maplib, x86emu_t *emu)
/*if((*maplib)->ownlibs && (*maplib)->libsz) {
for(int i=0; i<(*maplib)->libsz; ++i) {
printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
printf_dump(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
DecRefCount(&(*maplib)->libraries[i], emu);
}
}*/
@ -105,6 +105,28 @@ void MapLibAddLib(lib_t* maplib, library_t* lib)
++maplib->libsz;
}
void MapLibPrependLib(lib_t* maplib, library_t* lib, library_t* ref)
{
if(libraryInMapLib(maplib, lib))
return;
if (maplib->libsz == maplib->libcap) {
maplib->libcap += 8;
maplib->libraries = (library_t**)box_realloc(maplib->libraries, maplib->libcap*sizeof(library_t*));
}
// find insersion point
int point = ref?maplib->libsz:0;
if(ref)
for(int i=0; i<maplib->libsz; ++i)
if(maplib->libraries[i]==ref) {
point = i;
i = maplib->libsz;
}
if(point<maplib->libsz)
memmove(&maplib->libraries[point+1], &maplib->libraries[point], sizeof(library_t*)*(maplib->libsz-point));
maplib->libraries[point] = lib;
++maplib->libsz;
}
static void MapLibAddMapLib(lib_t* dest, library_t* lib_src, lib_t* src)
{
if(!src)
@ -180,29 +202,26 @@ int isLibLocal(library_t* lib)
static int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int n, elfheader_t* verneeded, box86context_t* box86, x86emu_t* emu)
{
const char* path = needed->names[n];
printf_log(LOG_DEBUG, "Trying to add \"%s\" to maplib%s\n", path, local?" (local)":"");
printf_dump(LOG_DEBUG, "Trying to add \"%s\" to maplib%s\n", path, local?" (local)":"");
// first check if lib is already loaded
library_t *lib = getLib(my_context->maplib, path);
if(lib) {
IncRefCount(lib, emu); // increment cntref
needed->libs[n] = lib;
printf_log(LOG_DEBUG, "Already present in maplib => success\n");
printf_dump(LOG_DEBUG, "Already present in maplib => success\n");
return 0;
}
// check also in the local loaded lib
lib = getLib(my_context->local_maplib, path);
if(lib) {
printf_log(LOG_DEBUG, "Already present in local_maplib => success\n");
printf_dump(LOG_DEBUG, "Already present in local_maplib => success\n");
needed->libs[n] = lib;
IncRefCount(lib, emu); // increment cntref
if(local) {
// add lib to maplib...
if(maplib) {
if(lib->maplib) {
MapLibAddMapLib(maplib, lib, lib->maplib);
}
if(!libraryInMapLib(maplib, lib))
MapLibAddLib(maplib, lib);
MapLibPrependLib(maplib, lib, NULL); // todo: Also insert libs needed by lib, after lib? But current lib->maplib is probably not the solution
if(maplib->ownlibs)
MapLibRemoveMapLib(my_context->local_maplib, maplib);
}
@ -215,7 +234,7 @@ static int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int
// load a new one
needed->libs[n] = lib = NewLibrary(path, box86, verneeded);
if(!lib) {
printf_log(LOG_DEBUG, "Faillure to create lib => fail\n");
printf_dump(LOG_DEBUG, "Faillure to create lib => fail\n");
return 1; //Error
}
@ -224,8 +243,6 @@ static int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int
MapLibAddLib(my_context->local_maplib, lib);
if(maplib) {
MapLibAddLib(maplib, lib);
if(!lib->maplib)
lib->maplib = maplib;
} else {
lib->maplib = NewLibrarian(box86, 0);
MapLibAddLib(lib->maplib, lib);
@ -238,7 +255,7 @@ static int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int
maplib = (local)?lib->maplib:my_context->maplib;
if(AddSymbolsLibrary(maplib, lib, emu)) { // also add needed libs
printf_log(LOG_DEBUG, "Failure to Add lib => fail\n");
printf_dump(LOG_DEBUG, "Failure to Add lib => fail\n");
return 1;
}
@ -247,7 +264,7 @@ static int AddNeededLib_add(lib_t* maplib, int local, needed_libs_t* needed, int
linkmap_t *lm = addLinkMapLib(lib);
if(!lm) {
// Crashed already
printf_log(LOG_DEBUG, "Failure to add lib linkmap\n");
printf_dump(LOG_DEBUG, "Failure to add lib linkmap\n");
return 1;
}
lm->l_addr = (Elf32_Addr)GetElfDelta(lib->e.elf);
@ -271,8 +288,8 @@ int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, elf
} else {
// it's an emulated lib,
// load dependancies and launch init sequence
if(LoadNeededLibs(mainelf, maplib, 0, bindnow, box86, emu)) {
printf_log(LOG_DEBUG, "Failure to Add dependant lib => fail\n");
if(LoadNeededLibs(mainelf, maplib, local, bindnow, box86, emu)) {
printf_dump(LOG_DEBUG, "Failure to Add dependant lib => fail\n");
return 1;
}
// some special case, where dependancies may not be correct
@ -297,12 +314,12 @@ int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, elf
// finalize the lib
if(FinalizeLibrary(lib, local?maplib:NULL, bindnow, emu)) {
printf_log(LOG_DEBUG, "Failure to finalizing lib => fail\n");
printf_dump(LOG_DEBUG, "Failure to finalizing lib => fail\n");
return 1;
}
}
// success
printf_log(LOG_DEBUG, "Created lib and added to maplib => success\n");
printf_dump(LOG_DEBUG, "Created lib and added to maplib => success\n");
return 0;
}
@ -351,20 +368,20 @@ void RemoveNeededLib(lib_t* maplib, int local, needed_libs_t* needed, box86conte
return;
for(int i=0; i<needed->size; ++i) {
if(box86_log>=LOG_DEBUG && needed->libs[i])
printf_log(LOG_DEBUG, "Will remove after failed init %s\n", needed->names[i]);
printf_dump(LOG_DEBUG, "Will remove after failed init %s\n", needed->names[i]);
AddNeededLib_remove(maplib, local, &needed->libs[i], box86, emu);
}
}
library_t* GetLibMapLib(lib_t* maplib, const char* name)
{
printf_log(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name);
printf_dump(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name);
return getLib(maplib, name);
}
library_t* GetLibInternal(const char* name)
{
printf_log(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name);
printf_dump(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name);
library_t* lib = getLib(my_context->maplib, name);
if(!lib) lib = getLib(my_context->local_maplib, name);
return lib;
@ -388,6 +405,20 @@ static int isLocal(elfheader_t* self, library_t* l)
return 0;
}
static void CheckNeededLibs(needed_libs_t* needed)
{
while(needed->nb_done<needed->size) {
library_t* lib = needed->libs[needed->nb_done++];
if(lib) {
int n = GetNeededLibsN(lib);
char** names = GetNeededLibsNames(lib);
for (int i=0; i<n; ++i) {
add1lib_neededlib(needed, GetNeededLib(lib, i), names[i]);
}
}
}
}
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, const char* globdefver, const char* weakdefver)
{
assert(self); // need self for this one
@ -450,13 +481,17 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin
if(my_context->preload)
for(int i=0; i<my_context->preload->size; ++i)
if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->preload->libs[i]), globdefver))
if(*start)
if(*start) {
return 1;
}
// search non-weak symbol, from older to newer (first GLOBAL object wins, starting with self)
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, globdefver))
if(*start)
if(*start) {
return 1;
// TODO: create a temporary map to search lib only 1 time, and in order of needed...
}
// This kind-of create a map to search lib only 1 time, and in order of needed...
if(my_context->neededlibs)
CheckNeededLibs(my_context->neededlibs);
// search in needed libs from neededlibs first, in order
if(my_context->neededlibs)
for(int i=0; i<my_context->neededlibs->size; ++i)
@ -468,8 +503,9 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin
if(maplib) {
if(self && self!=my_context->elfs[0] && self!=(void*)1)
if(GetSymbolStartEnd(GetMapSymbols(self), name, start, end, version, vername, 1, globdefver))
if(*start)
if(*start) {
return 1;
}
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), globdefver))
if(*start) {
@ -482,8 +518,17 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin
int ok = 0;
// GetSymbolStartEnd should not change start/end if symbol is not found
if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, weakdefver))
if(*start)
if(*start) {
ok = 1;
}
// search in needed libs from neededlibs first, in order
if(my_context->neededlibs)
for(int i=0; i<my_context->neededlibs->size; ++i)
if(GetLibWeakSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i]), weakdefver))
if(*start) {
return 1;
}
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), weakdefver))
@ -542,7 +587,9 @@ static int GetGlobalWeakSymbolStartEnd_internal(lib_t *maplib, const char* name,
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, globdefver))
if(*start)
return 1;
// TODO: create a temporary map to search lib only 1 time, and in order of needed...
// This kind-of create a map to search lib only 1 time, and in order of needed...
if(my_context->neededlibs)
CheckNeededLibs(my_context->neededlibs);
// search in needed libs from neededlibs first, in order
if(my_context->neededlibs)
for(int i=0; i<my_context->neededlibs->size; ++i)

View File

@ -209,7 +209,7 @@ static void initWrappedLib(library_t *lib, box86context_t* context) {
printf_log(LOG_NONE, "Error initializing native %s (last dlerror is %s)\n", lib->name, error_str);
return; // non blocker...
}
printf_log(LOG_INFO, "Using native(wrapped) %s\n", lib->name);
printf_dump(LOG_INFO, "Using native(wrapped) %s\n", lib->name);
lib->fini = wrappedlibs[i].fini;
lib->getglobal = WrappedLib_GetGlobal;
lib->getweak = WrappedLib_GetWeak;
@ -225,13 +225,13 @@ static void initWrappedLib(library_t *lib, box86context_t* context) {
linkmap_t *lm = addLinkMapLib(lib);
if(!lm) {
// Crashed already
printf_log(LOG_DEBUG, "Failure to add lib %s linkmap\n", lib->name);
printf_dump(LOG_DEBUG, "Failure to add lib %s linkmap\n", lib->name);
break;
}
struct link_map real_lm;
#ifndef ANDROID
if(dlinfo(lib->w.lib, RTLD_DI_LINKMAP, &real_lm)) {
printf_log(LOG_DEBUG, "Failed to dlinfo lib %s\n", lib->name);
printf_dump(LOG_DEBUG, "Failed to dlinfo lib %s\n", lib->name);
}
#endif
lm->l_addr = real_lm.l_addr;
@ -253,7 +253,7 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box86context_t*
}
elfheader_t *elf_header = LoadAndCheckElfHeader(f, libname, 0);
if(!elf_header) {
printf_log(LOG_DEBUG, "Error: reading elf header of %s\n", libname); // this one can be too alarming...
printf_dump(LOG_DEBUG, "Error: reading elf header of %s\n", libname); // this one can be too alarming...
fclose(f);
return 0;
}
@ -304,21 +304,21 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box86context_t*
lib->path = box_strdup(libname);
}
printf_log(LOG_INFO, "Using emulated %s\n", libname);
printf_dump(LOG_INFO, "Using emulated %s\n", libname);
#ifdef DYNAREC
if(libname && box86_dynarec_bleeding_edge && strstr(libname, "libmonobdwgc-2.0.so")) {
printf_log(LOG_INFO, "MonoBleedingEdge detected, disable Dynarec BigBlock and enable Dynarec StrongMem\n");
printf_dump(LOG_INFO, "MonoBleedingEdge detected, disable Dynarec BigBlock and enable Dynarec StrongMem\n");
box86_dynarec_bigblock = 0;
box86_dynarec_strongmem = 1;
}
if(libname && box86_dynarec_jvm && strstr(libname, "libjvm.so")) {
printf_log(LOG_INFO, "libjvm detected, disable Dynarec BigBlock and enable Dynarec StrongMem\n");
printf_dump(LOG_INFO, "libjvm detected, disable Dynarec BigBlock and enable Dynarec StrongMem\n");
box86_dynarec_bigblock = 0;
box86_dynarec_strongmem = 1;
}
#endif
if(libname && box86_libcef && strstr(libname, "libcef.so")) {
printf_log(LOG_INFO, "libcef detected, using malloc_hack_2\n");
printf_dump(LOG_INFO, "libcef detected, using malloc_hack_2\n");
box86_malloc_hack = 2;
}
return 1;
@ -372,7 +372,7 @@ static int isEssentialLib(const char* name) {
library_t *NewLibrary(const char* path, box86context_t* context, elfheader_t* verneeded)
{
printf_log(LOG_DEBUG, "Trying to load \"%s\"\n", path);
printf_dump(LOG_DEBUG, "Trying to load \"%s\"\n", path);
library_t *lib = (library_t*)box_calloc(1, sizeof(library_t));
lib->path = box_realpath(path, NULL);
if(!lib->path)
@ -383,7 +383,7 @@ library_t *NewLibrary(const char* path, box86context_t* context, elfheader_t* ve
lib->name = Path2Name(path);
lib->nbdot = NbDot(lib->name);
lib->type = LIB_UNNKNOW;
printf_log(LOG_DEBUG, "Simplified name is \"%s\"\n", lib->name);
printf_dump(LOG_DEBUG, "Simplified name is \"%s\"\n", lib->name);
if(box86_nopulse) {
if(strstr(lib->name, "libpulse.so")==lib->name || strstr(lib->name, "libpulse-simple.so")==lib->name) {
box_free(lib->name);
@ -468,12 +468,12 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x86emu_t*
int weak;
if (GetGlobalSymbolStartEnd(local_maplib, trace_func, &trace_start, &trace_end, elf_header, -1, NULL, NULL, NULL)) {
SetTraceEmu(trace_start, trace_end);
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end);
printf_dump(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end);
box_free(trace_func);
trace_func = NULL;
} else if(GetLibLocalSymbolStartEnd(lib, trace_func, &trace_start, &trace_end, 0, &weak, -1, NULL, 0, NULL)) {
SetTraceEmu(trace_start, trace_end);
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end);
printf_dump(LOG_INFO, "TRACE on %s only (%p-%p)\n", trace_func, (void*)trace_start, (void*)trace_end);
box_free(trace_func);
trace_func = NULL;
}
@ -502,7 +502,7 @@ void Free1Library(library_t **the_lib, x86emu_t* emu)
library_t* lib = *the_lib;
printf_log(LOG_DEBUG, "Free1Library %s\n", lib->name);
printf_dump(LOG_DEBUG, "Free1Library %s\n", lib->name);
// remove lib from maplib/local_maplib...
if(my_context) {
MapLibRemoveLib(my_context->maplib, lib);
@ -611,7 +611,7 @@ int IsSameLib(library_t* lib, const char* path)
}
int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver)
{
if(!name[0])
if(!lib || !name[0])
return 0;
khint_t k;
// get a new symbol
@ -823,7 +823,7 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui
symbol = GetNativeSymbolUnversioned(lib->w.lib, newname);
}
if(!symbol) {
printf_log(LOG_INFO, "Warning, function %s not found in lib %s\n", name, lib->name);
printf_dump(LOG_INFO, "Warning, function %s not found in lib %s\n", name, lib->name);
return 0;
}
s->addr = AddBridge(lib->w.bridge, s->w, symbol, 0, name);
@ -879,7 +879,7 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui
symbol = GetNativeSymbolUnversioned(lib->w.lib, newname);
}
if(!symbol) {
printf_log(LOG_INFO, "Warning, function %s not found in lib %s\n", name, lib->name);
printf_dump(LOG_INFO, "Warning, function %s not found in lib %s\n", name, lib->name);
return 0;
}
s->addr = AddBridge(lib->w.bridge, s->w, symbol, 0, name);
@ -904,7 +904,7 @@ static int getSymbolInSymbolMaps(library_t*lib, const char* name, int noweak, ui
if(!symbol)
symbol = GetNativeSymbolUnversioned(lib->w.lib, kh_value(lib->w.symbol2map, k).name);
if(!symbol) {
printf_log(LOG_INFO, "Warning, function %s not found in lib %s\n", kh_value(lib->w.symbol2map, k).name, lib->name);
printf_dump(LOG_INFO, "Warning, function %s not found in lib %s\n", kh_value(lib->w.symbol2map, k).name, lib->name);
return 0;
}
s->addr = AddBridge(lib->w.bridge, s->w, symbol, 0, name);
@ -939,7 +939,7 @@ int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *add
int GetNeededLibsN(library_t* lib) {
switch (lib->type) {
case LIB_WRAPPED: return lib->w.needed?lib->w.needed->size:0;
case LIB_EMULATED: return lib->e.elf->needed->size;
case LIB_EMULATED: return lib->e.elf->needed?lib->e.elf->needed->size:0;
}
return 0;
}
@ -957,11 +957,11 @@ library_t* GetNeededLib(library_t* lib, int idx)
}
return NULL;
}
char** GetNeededLibs(library_t* lib)
char** GetNeededLibsNames(library_t* lib)
{
switch (lib->type) {
case LIB_WRAPPED: return lib->w.needed?lib->w.needed->names:NULL;
case LIB_EMULATED: return lib->e.elf->needed->names;
case LIB_EMULATED: return lib->e.elf->needed?lib->e.elf->needed->names:NULL;
}
return NULL;
}
@ -1078,7 +1078,7 @@ void add1lib_neededlib(needed_libs_t* needed, library_t* lib, const char* name)
// add it
if(needed->size+1<=needed->cap)
return;
needed->cap = needed->size+1;
needed->cap = needed->size+4;
needed->libs = (library_t**)realloc(needed->libs, needed->cap*sizeof(library_t*));
needed->names = (char**)realloc(needed->names, needed->cap*sizeof(char*));
needed->libs[needed->size] = lib;

1
tests/ref21.txt Normal file
View File

@ -0,0 +1 @@
2/1

BIN
tests/test21 Executable file

Binary file not shown.

41
tests/test21.c Normal file
View File

@ -0,0 +1,41 @@
/*
* Compile with (on x86_64 archs):
* gcc -m32 -DV1 -shared -o test21_v1.so test21.c
* gcc -m32 -DV2 -shared -o test21_v2.so test21.c
* gcc -m32 -o test21 test21.c -ldl -Wl,-z,origin,-rpath='$ORIGIN'
*/
#if defined(V1)
int __attribute__((noinline)) getVersion() { asm(""); return 1; }
int acquireVersion() { return getVersion(); }
#elif defined(V2)
int __attribute__((noinline)) getVersion() { asm(""); return 2; }
int returnVersion() { return getVersion(); }
#else
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
typedef int(*iFv_t)(void);
int main(int argc, char **argv) {
void* v1 = dlopen("test21_v1.so", RTLD_NOW);
void* v2 = dlopen("test21_v2.so", RTLD_NOW);
if(!v1 || !v2) {
printf("Error openning libs: v1=%p, v2=%p\n", v1, v2);
exit(-1);
}
iFv_t returnVersion = (iFv_t)dlsym(v2, "returnVersion");
iFv_t acquireVersion = (iFv_t)dlsym(v1, "acquireVersion");
if(!returnVersion || !acquireVersion) {
printf("Error getting symbol return=%p/acquire=%p\n", returnVersion, acquireVersion);
exit(-2);
}
printf("%d/%d\n", returnVersion(), acquireVersion()); return 0;
dlclose(v2);
dlclose(v1);
}
#endif

BIN
tests/test21_v1.so Executable file

Binary file not shown.

BIN
tests/test21_v2.so Executable file

Binary file not shown.