about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <seebastien.chev@gmail.com>2023-08-27 11:38:00 +0200
committerptitSeb <seebastien.chev@gmail.com>2023-08-27 11:38:00 +0200
commitc7db4470e4ea0bab6fb05f29b1f4cfb69d7b7afe (patch)
treea43df95f8a831ec2d6ee30041311b31d4b0dc38b /src
parent2e55fc8c3207df407f775a0d531519ad561b8817 (diff)
downloadbox64-c7db4470e4ea0bab6fb05f29b1f4cfb69d7b7afe.tar.gz
box64-c7db4470e4ea0bab6fb05f29b1f4cfb69d7b7afe.zip
[ELFLOADER] Better handling of dlopen library without RTLD_GLOBAL flags
Diffstat (limited to 'src')
-rw-r--r--src/include/box64context.h1
-rw-r--r--src/include/librarian.h1
-rw-r--r--src/librarian/librarian.c106
-rw-r--r--src/librarian/library.c40
4 files changed, 100 insertions, 48 deletions
diff --git a/src/include/box64context.h b/src/include/box64context.h
index aa8c95b6..0a8f6532 100644
--- a/src/include/box64context.h
+++ b/src/include/box64context.h
@@ -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);
diff --git a/src/include/librarian.h b/src/include/librarian.h
index 6fc89320..13cb3890 100644
--- a/src/include/librarian.h
+++ b/src/include/librarian.h
@@ -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);
 
diff --git a/src/librarian/librarian.c b/src/librarian/librarian.c
index 072ef811..fad45e4f 100644
--- a/src/librarian/librarian.c
+++ b/src/librarian/librarian.c
@@ -41,7 +41,7 @@ void FreeLibrarian(lib_t **maplib, x64emu_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, box64context_t* box64, x64emu_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, box64, 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(box64, 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 = (Elf64_Addr)GetElfDelta(lib->e.elf);
@@ -272,7 +289,7 @@ int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, elf
         // it's an emulated lib, 
         // load dependancies and launch init sequence
         if(LoadNeededLibs(mainelf, maplib, 0, bindnow, box64, emu)) {
-            printf_log(LOG_DEBUG, "Failure to Add dependant lib => fail\n");
+            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, box64conte
         return;
     for(int i=0; i<needed->size; ++i) {
         if(box64_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], box64, 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
@@ -449,29 +480,36 @@ 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)
             if(GetLibGlobalSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i]), globdefver))
-                if(*start)
+                if(*start) {
                     return 1;
+                }
     // search in global symbols
     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)
+                if(*start) {
                     return 1;
+                }
         }
     }
 
@@ -479,14 +517,24 @@ 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;
+                }
 
     if(maplib)
     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))
-            if(*start)
+            if(*start) {
                 ok = 1;
+            }
     }
     // nope, not found
     return (ok && *start)?1:0;
@@ -540,7 +588,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)
diff --git a/src/librarian/library.c b/src/librarian/library.c
index 86eb507f..a6c355d1 100644
--- a/src/librarian/library.c
+++ b/src/librarian/library.c
@@ -209,7 +209,7 @@ static void initWrappedLib(library_t *lib, box64context_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,12 +225,12 @@ static void initWrappedLib(library_t *lib, box64context_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;
             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);
             }
             lm->l_addr = real_lm.l_addr;
             lm->l_name = real_lm.l_name;
@@ -251,7 +251,7 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box64context_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;
         }
@@ -302,21 +302,21 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box64context_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 && box64_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");
             box64_dynarec_bigblock = 0;
             box64_dynarec_strongmem = 1;
         }
         if(libname && box64_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");
             box64_dynarec_bigblock = 0;
             box64_dynarec_strongmem = 1;
         }
         #endif
         if(libname && box64_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");
             box64_malloc_hack = 2;
         }
         return 1;
@@ -370,7 +370,7 @@ static int isEssentialLib(const char* name) {
 
 library_t *NewLibrary(const char* path, box64context_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)
@@ -381,7 +381,7 @@ library_t *NewLibrary(const char* path, box64context_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(box64_nopulse) {
         if(strstr(lib->name, "libpulse.so")==lib->name || strstr(lib->name, "libpulse-simple.so")==lib->name) {
             box_free(lib->name);
@@ -466,12 +466,12 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x64emu_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;
             }
@@ -544,7 +544,7 @@ void Free1Library(library_t **the_lib, x64emu_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);
@@ -653,7 +653,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;
     kh_bridgemap_t *map = local?lib->lbridgemap:((*weak)?lib->wbridgemap:lib->gbridgemap);
@@ -865,7 +865,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);
@@ -921,7 +921,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);
@@ -946,7 +946,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);
@@ -981,7 +981,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;
 }
@@ -999,11 +999,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;
 }