about summary refs log tree commit diff stats
path: root/src/wrapped32/wrappedlibdl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/wrapped32/wrappedlibdl.c')
-rwxr-xr-xsrc/wrapped32/wrappedlibdl.c165
1 files changed, 165 insertions, 0 deletions
diff --git a/src/wrapped32/wrappedlibdl.c b/src/wrapped32/wrappedlibdl.c
new file mode 100755
index 00000000..c3a79feb
--- /dev/null
+++ b/src/wrapped32/wrappedlibdl.c
@@ -0,0 +1,165 @@
+#define _GNU_SOURCE         /* See feature_test_macros(7) */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <elf.h>
+#include <link.h>
+
+#include "wrappedlibs.h"
+
+#include "debug.h"
+#include "wrapper32.h"
+#include "bridge.h"
+#include "librarian/library_private.h"
+#include "emu/x64emu_private.h"
+#include "library.h"
+#include "librarian.h"
+#include "box32context.h"
+#include "elfloader.h"
+#include "elfs/elfloader_private.h"
+#include "x64emu.h"
+
+
+#define LIBNAME libdl
+#ifdef ANDROID
+    static const char* libdlName = "libdl.so";
+#else
+    static const char* libdlName = "libdl.so.2";
+#endif
+
+void* my_dlopen(x64emu_t* emu, void *filename, int flag) EXPORT;
+void* my_dlmopen(x64emu_t* emu, void* mlid, void *filename, int flag) EXPORT;
+char* my_dlerror(x64emu_t* emu) EXPORT;
+void* my_dlsym(x64emu_t* emu, void *handle, void *symbol) EXPORT;
+int my_dlclose(x64emu_t* emu, void *handle) EXPORT;
+int my32_dladdr(x64emu_t* emu, void *addr, void *info) EXPORT;
+int my32_dladdr1(x64emu_t* emu, void *addr, void *info, void** extra_info, int flags) EXPORT;
+void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, const char *vername) EXPORT;
+int my32_dlinfo(x64emu_t* emu, void* handle, int request, void* info) EXPORT;
+
+#ifndef RTLD_DL_SYMENT
+#define RTLD_DL_SYMENT 1
+#endif
+#ifndef RTLD_DL_LINKMAP
+#define RTLD_DL_LINKMAP 2
+#endif
+
+void dl_clear_error();
+#define CLEARERR    dl_clear_error()
+void dl_set_error(const char*);
+char* dl_last_error();
+library_t* dl_get_library(void* handle);
+
+typedef struct my_dl_info_32_s
+{
+  ptr_t dli_fname;	// const char*
+  ptr_t dli_fbase;	// void*
+  ptr_t dli_sname;	// const char*
+  ptr_t dli_saddr;	// void*
+} my_dl_info_32_t;
+
+int my32_dladdr1(x64emu_t* emu, void *addr, void *i, void** extra_info, int flags)
+{
+    //int dladdr(void *addr, my_dl_info_32_t *info);
+    CLEARERR;
+    my_dl_info_32_t *info = (my_dl_info_32_t*)i;
+    printf_log(LOG_DEBUG, "Warning: partially unimplement call to dladdr/dladdr1(%p, %p, %p, %d)\n", addr, info, extra_info, flags);
+    
+    //emu->quit = 1;
+    library_t* lib = NULL;
+    info->dli_saddr = 0;
+    info->dli_fname = 0;
+    void* start = NULL;
+    const char* fname = NULL;
+    void* base = NULL;
+    const char* sname = FindSymbolName(my_context->maplib, addr, &start, NULL, &fname, &base, &lib);
+    info->dli_saddr = to_ptrv(start);
+    info->dli_fname = to_ptrv((void*)fname);
+    info->dli_fbase = to_ptrv(base);
+    info->dli_sname = to_ptrv((void*)sname);
+    printf_log(LOG_DEBUG, "     dladdr return saddr=%p, fname=\"%s\", sname=\"%s\"\n", start, sname?sname:"", fname?fname:"");
+    if(flags==RTLD_DL_SYMENT) {
+        printf_log(LOG_INFO, "Warning, unimplement call to dladdr1 with RTLD_DL_SYMENT flags\n");
+    } else if (flags==RTLD_DL_LINKMAP) {
+        printf_log(LOG_INFO, "Warning, unimplemented call to dladdr1 with RTLD_DL_LINKMAP flags\n");
+        *(ptr_t*)extra_info = to_ptrv(getLinkMapLib32(lib));
+    }
+    return (info->dli_sname)?1:0;   // success is non-null here...
+}
+int my32_dladdr(x64emu_t* emu, void *addr, void *i)
+{
+    return my32_dladdr1(emu, addr, i, NULL, 0);
+}
+
+int my32_dlinfo(x64emu_t* emu, void* handle, int request, void* info)
+{
+    (void)emu;
+    printf_dlsym(LOG_DEBUG, "Call to dlinfo(%p, %d, %p)\n", handle, request, info);
+    CLEARERR;
+    library_t *lib = dl_get_library(handle);
+    if(lib==(library_t*)-1LL) {
+        printf_dlsym(LOG_DEBUG, "dlinfo: %s\n", dl_last_error());
+        return -1;
+    }
+    //elfheader_t *h = (GetElfIndex(lib)>-1)?my_context->elfs[GetElfIndex(lib)]:NULL;
+    switch(request) {
+        case 2: // RTLD_DI_LINKMAP
+            {
+                *(linkmap32_t**)info = getLinkMapLib32(lib);
+            }
+            return 0;
+        default:
+            printf_log(LOG_NONE, "Warning, unsupported call to dlinfo(%p, %d, %p)\n", handle, request, info);
+            {
+                char tmp[129] = {0};
+                snprintf(tmp, 129, "unsupported call to dlinfo request:%d\n", request);
+                dl_set_error(tmp);
+            }
+    }
+    return -1;
+}
+
+typedef struct my_dl_find_object_s {
+    uint64_t    dlfo_flags;
+    ptr_t       dlfo_map_start;
+    ptr_t       dlfo_map_end;
+    ptr_t       dlf_link_map;   //struct link_map *
+    ptr_t       dlfo_eh_frame;
+    // other stuff...
+} my_dl_find_object_t;
+
+EXPORT int my32__dl_find_object(x64emu_t* emu, void* addr, my_dl_find_object_t* result)
+{
+    //printf_log(LOG_INFO, "Unimplemented _dl_find_object called\n");
+    uintptr_t start=0, sz=0;
+    elfheader_t* h = FindElfAddress(my_context, (uintptr_t)addr);
+    if(h) {
+        // find an actual elf
+        const char* name = FindNearestSymbolName(h, addr, &start, &sz);
+        result->dlfo_map_start = start;
+        result->dlfo_map_end = start+sz-1;
+        result->dlfo_eh_frame = h->ehframehdr+h->delta;
+        result->dlfo_flags = 0;   // unused it seems
+        result->dlf_link_map = to_ptrv(getLinkMapElf32(h));
+        return 0;
+    }
+    return -1;
+}
+
+//#define CUSTOM_INIT\
+//        if(!box32_isglibc234) setNeededLibs(lib, 1, "libc.so.6");
+
+
+void closeAllDLOpenned();
+
+#define PRE_INIT\
+    if(1)                                                           \
+        lib->w.lib = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL);    \
+    else
+
+#define CUSTOM_FINI \
+    closeAllDLOpenned();
+
+// define all standard library functions
+#include "wrappedlib_init32.h"