about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2022-03-01 23:39:01 +0100
committerptitSeb <sebastien.chev@gmail.com>2022-03-01 23:39:01 +0100
commit8b1f55aff0201549279684dc3f1d59f42a8fb0d4 (patch)
tree2c4480443e86913bd870fff033865dc2e8e38a49 /src
parentb00764d658fbf3a9068a57cfe1fe41e2283ad5cb (diff)
downloadbox64-8b1f55aff0201549279684dc3f1d59f42a8fb0d4.tar.gz
box64-8b1f55aff0201549279684dc3f1d59f42a8fb0d4.zip
More work on readlinkat and clone syscall
Diffstat (limited to 'src')
-rwxr-xr-xsrc/box64context.c3
-rwxr-xr-xsrc/elfs/elfloader.c13
-rwxr-xr-xsrc/emu/x64int3.c2
-rwxr-xr-xsrc/emu/x64syscall.c134
-rwxr-xr-xsrc/include/box64context.h2
-rwxr-xr-xsrc/include/elfloader.h2
-rwxr-xr-xsrc/main.c29
-rw-r--r--src/wrapped/generated/functions_list.txt6
-rw-r--r--src/wrapped/generated/wrappedlibctypes.h2
-rw-r--r--src/wrapped/generated/wrappedlibdltypes.h4
-rw-r--r--src/wrapped/generated/wrapper.c4
-rw-r--r--src/wrapped/generated/wrapper.h2
-rwxr-xr-xsrc/wrapped/wrappedlibc.c14
-rwxr-xr-xsrc/wrapped/wrappedlibc_private.h7
-rwxr-xr-xsrc/wrapped/wrappedlibdl.c23
-rwxr-xr-xsrc/wrapped/wrappedlibdl_private.h2
16 files changed, 211 insertions, 38 deletions
diff --git a/src/box64context.c b/src/box64context.c
index ee56ce5a..9d8e5d5d 100755
--- a/src/box64context.c
+++ b/src/box64context.c
@@ -259,6 +259,9 @@ void FreeBox64Context(box64context_t** context)
     freeGLProcWrapper(ctx);
     freeALProcWrapper(ctx);
 
+    if(ctx->stack_clone)
+        free(ctx->stack_clone);
+
 
     void* ptr;
     if ((ptr = pthread_getspecific(ctx->tlskey)) != NULL) {
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c
index 761d2ee4..afd9002d 100755
--- a/src/elfs/elfloader.c
+++ b/src/elfs/elfloader.c
@@ -147,6 +147,12 @@ const char* ElfName(elfheader_t* head)
         return "(noelf)";
     return head->name;
 }
+const char* ElfPath(elfheader_t* head)
+{
+    if(!head)
+        return NULL;
+    return head->path;
+}
 int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
 {
     uintptr_t offs = 0;
@@ -1368,6 +1374,13 @@ void* GetTLSPointer(box64context_t* context, elfheader_t* h)
     return ptr->tlsdata+(ptr->tlssize+h->tlsbase);
 }
 
+void* GetDynamicSection(elfheader_t* h)
+{
+    if(!h)
+        return NULL;
+    return h->Dynamic;
+}
+
 #ifdef DYNAREC
 dynablocklist_t* GetDynablocksFromAddress(box64context_t *context, uintptr_t addr)
 {
diff --git a/src/emu/x64int3.c b/src/emu/x64int3.c
index 86f1f0af..f7bb6291 100755
--- a/src/emu/x64int3.c
+++ b/src/emu/x64int3.c
@@ -97,7 +97,7 @@ void x64Int3(x64emu_t* emu)
                 s = GetNativeName((void*)addr);
                 if(addr==(uintptr_t)PltResolver) {
                     snprintf(buff, 256, "%s", " ... ");
-                } else if (!strcmp(s, "__open") || !strcmp(s, "open") || !strcmp(s, "open ")) {
+                } else if (!strcmp(s, "__open") || !strcmp(s, "open") || !strcmp(s, "open ") || !strcmp(s, "open64")) {
                     tmp = (char*)(R_RDI);
                     snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d (,%d))", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (int)(R_ESI), (int)(R_EDX));
                     perr = 1;
diff --git a/src/emu/x64syscall.c b/src/emu/x64syscall.c
index 2a4e65d6..edcbfff4 100755
--- a/src/emu/x64syscall.c
+++ b/src/emu/x64syscall.c
@@ -106,12 +106,13 @@ scwrap_t syscallwrap[] = {
     { 46, __NR_sendmsg, 3},
     { 47, __NR_recvmsg, 3},
     { 53, __NR_socketpair, 4},
-    #ifdef __NR_vfork
-    {56, __NR_vfork, 0},
-    #endif
+    //{56, __NR_clone, 5},
     #ifdef __NR_fork
     { 57, __NR_fork, 0 },    // should wrap this one, because of the struct pt_regs (the only arg)?
     #endif
+    #ifdef __NR_vfork
+    {58, __NR_vfork, 0},
+    #endif
     { 61, __NR_wait4, 4},
     //{ 63, __NR_uname, 1}, // Needs wrapping, use old_utsname
     { 66, __NR_semctl, 4},
@@ -253,15 +254,16 @@ typedef struct old_utsname_s {
 //	int  xss;
 //};
 
-//int clone_fn(void* arg)
-//{
-//    x64emu_t *emu = (x64emu_t*)arg;
-//    R_RAX = 0;
-//    DynaRun(emu);
-//    int ret = R_EAX;
-//    FreeX64Emu(&emu);
-//    return ret;
-//}
+int clone_fn(void* arg)
+{
+    x64emu_t *emu = (x64emu_t*)arg;
+    R_RAX = 0;
+    DynaRun(emu);
+    int ret = R_EAX;
+    FreeX64Emu(&emu);
+    my_context->stack_clone_used = 0;
+    return ret;
+}
 
 void EXPORT x64Syscall(x64emu_t *emu)
 {
@@ -344,19 +346,63 @@ void EXPORT x64Syscall(x64emu_t *emu)
         case 25: // sys_mremap
             R_RAX = (uintptr_t)my_mremap(emu, (void*)R_RDI, R_RSI, R_RDX, R_R10d, (void*)R_R8);
             break;
-        #ifndef __NR_vfork
-        case 56:   // vfork
+        case 56: // sys_clone
+            if(R_RSI)
             {
-                int64_t r = vfork();
-                R_RAX = r;
+                void* stack_base = (void*)R_RSI;
+                int stack_size = 0;
+                if(!R_RSI) {
+                    // allocate a new stack...
+                    int currstack = 0;
+                    if((R_RSP>=(uintptr_t)emu->init_stack) && (R_RSP<=((uintptr_t)emu->init_stack+emu->size_stack)))
+                        currstack = 1;
+                    stack_size = (currstack)?emu->size_stack:(1024*1024);
+                    stack_base = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
+                    // copy value from old stack to new stack
+                    if(currstack)
+                        memcpy(stack_base, emu->init_stack, stack_size);
+                    else {
+                        int size_to_copy = (uintptr_t)emu->init_stack + emu->size_stack - (R_RSP);
+                        memcpy(stack_base+stack_size-size_to_copy, (void*)R_RSP, size_to_copy);
+                    }
+                }
+                x64emu_t * newemu = NewX64Emu(emu->context, R_RIP, (uintptr_t)stack_base, stack_size, (R_RSI)?0:1);
+                SetupX64Emu(newemu);
+                CloneEmu(newemu, emu);
+                SetRSP(newemu, (uintptr_t)stack_base);
+                void* mystack = NULL;
+                if(my_context->stack_clone_used) {
+                    mystack = malloc(1024*1024);  // stack for own process... memory leak, but no practical way to remove it
+                } else {
+                    if(!my_context->stack_clone)
+                        my_context->stack_clone = malloc(1024*1024);
+                    mystack = my_context->stack_clone;
+                    my_context->stack_clone_used = 1;
+                }
+                // x86_64 raw clone is long clone(unsigned long flags, void *stack, int *parent_tid, int *child_tid, unsigned long tls);
+                int64_t ret = clone(clone_fn, (void*)((uintptr_t)mystack+1024*1024), R_RDI, newemu, R_R10, R_R9, R_R8);
+                R_RAX = ret;
             }
+            else
+                #ifdef NOALIGN
+                return syscall(__NR_clone, R_RSI, R_RDX, R_R10, R_R8, R_R9);
+                #else
+                return syscall(__NR_clone, R_RSI, R_RDX, R_R10, R_R9, R_R8);    // invert R_R8/R_R9 on Aarch64 and most other
+                #endif
             break;
-        #endif
         #ifndef __NR_fork
         case 57: 
             R_RAX = fork();
             break;
         #endif
+        #ifndef __NR_vfork
+        case 58:   // vfork
+            {
+                int64_t r = vfork();
+                R_RAX = r;
+            }
+            break;
+        #endif
         case 63:    //uname
             {
                 old_utsname_t *old = (old_utsname_t*)R_RDI;
@@ -493,14 +539,60 @@ uintptr_t EXPORT my_syscall(x64emu_t *emu)
         #endif
         case 25: // sys_mremap
             return (uintptr_t)my_mremap(emu, (void*)R_RSI, R_RDX, R_RCX, R_R8d, (void*)R_R9);
-        #ifndef __NR_vfork
-        case 56:   // vfork
-            return vfork();
-        #endif
+        case 56: // sys_clone
+            if(R_RDX)
+            {
+                void* stack_base = (void*)R_RDX;
+                int stack_size = 0;
+                if(!stack_base) {
+                    // allocate a new stack...
+                    int currstack = 0;
+                    if((R_RSP>=(uintptr_t)emu->init_stack) && (R_RSP<=((uintptr_t)emu->init_stack+emu->size_stack)))
+                        currstack = 1;
+                    stack_size = (currstack)?emu->size_stack:(1024*1024);
+                    stack_base = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
+                    // copy value from old stack to new stack
+                    if(currstack)
+                        memcpy(stack_base, emu->init_stack, stack_size);
+                    else {
+                        int size_to_copy = (uintptr_t)emu->init_stack + emu->size_stack - (R_RSP);
+                        memcpy(stack_base+stack_size-size_to_copy, (void*)R_RSP, size_to_copy);
+                    }
+                }
+                x64emu_t * newemu = NewX64Emu(emu->context, R_RIP, (uintptr_t)stack_base, stack_size, (R_RDX)?0:1);
+                SetupX64Emu(newemu);
+                CloneEmu(newemu, emu);
+                Push64(newemu, 0);
+                PushExit(newemu);
+                SetRSP(newemu, (uintptr_t)stack_base);
+                void* mystack = NULL;
+                if(my_context->stack_clone_used) {
+                    mystack = malloc(1024*1024);  // stack for own process... memory leak, but no practical way to remove it
+                } else {
+                    if(!my_context->stack_clone)
+                        my_context->stack_clone = malloc(1024*1024);
+                    mystack = my_context->stack_clone;
+                    my_context->stack_clone_used = 1;
+                }
+                // x86_64 raw clone is long clone(unsigned long flags, void *stack, int *parent_tid, int *child_tid, unsigned long tls);
+                int64_t ret = clone(clone_fn, (void*)((uintptr_t)mystack+1024*1024), R_ESI, newemu, R_RCX, R_R9, R_R8);
+                return ret;
+            }
+            else
+                #ifdef NOALIGN
+                return syscall(__NR_clone, R_RSI, R_RDX, R_RCX, R_R8, R_R9);
+                #else
+                return syscall(__NR_clone, R_RSI, R_RDX, R_RCX, R_R9, R_R8);    // invert R_R8/R_R9 on Aarch64 and most other
+                #endif
+            break;
         #ifndef __NR_fork
         case 57: 
             return fork();
         #endif
+        #ifndef __NR_vfork
+        case 58:   // vfork
+            return vfork();
+        #endif
         case 63:    //uname
             {
                 old_utsname_t *old = (old_utsname_t*)R_RSI;
diff --git a/src/include/box64context.h b/src/include/box64context.h
index ecb00c3e..9d660664 100755
--- a/src/include/box64context.h
+++ b/src/include/box64context.h
@@ -188,6 +188,8 @@ typedef struct box64context_s {
     x64emu_t            *emu_sig;       // the emu with stack used for signal handling (must be separated from main ones)
     int                 no_sigsegv;
     int                 no_sigill;
+    void*               stack_clone;
+    int                 stack_clone_used;
 
 } box64context_t;
 
diff --git a/src/include/elfloader.h b/src/include/elfloader.h
index c1b4ce89..4e06546b 100755
--- a/src/include/elfloader.h
+++ b/src/include/elfloader.h
@@ -16,6 +16,7 @@ typedef struct dynablocklist_s dynablocklist_t;
 elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec); // exec : 0 = lib, 1 = exec
 void FreeElfHeader(elfheader_t** head);
 const char* ElfName(elfheader_t* head);
+const char* ElfPath(elfheader_t* head);
 void ElfAttachLib(elfheader_t* head, library_t* lib);
 
 // return 0 if OK
@@ -52,6 +53,7 @@ dynablocklist_t* GetDynablocksFromElf(elfheader_t* h);
 #endif
 void ResetSpecialCaseMainElf(elfheader_t* h);
 void CreateMemorymapFile(box64context_t* context, int fd);
+void* GetDynamicSection(elfheader_t* h);
 
 int ElfCheckIfUseTCMallocMinimal(elfheader_t* h);   // return 1 if tcmalloc is used
 
diff --git a/src/main.c b/src/main.c
index 48c8f99e..388fea7d 100755
--- a/src/main.c
+++ b/src/main.c
@@ -956,6 +956,18 @@ int main(int argc, const char **argv, const char **env) {
             //wine_preloaded = 1;
         }
     }
+    #if 0
+    // pre-check for pressure-vessel-wrap
+    if(strstr(prog, "pressure-vessel-wrap")==(prog+strlen(prog)-strlen("pressure-vessel-wrap"))) {
+        // pressure-vessel-wrap detecter, skipping it and all -- args until "--" if needed
+        ++nextarg;
+        if(argv[nextarg][0]=='-' && argv[nextarg][1]=='-')
+            while(argv[nextarg][0]=='-' && argv[nextarg][1]=='-')
+                ++nextarg;
+        prog = argv[nextarg];
+        printf_log(LOG_INFO, "BOX64: pressure-vessel-wrap detected, loading \"%s\" directly\n", prog);
+    }
+    #endif
     // check if this is wine
     if(!strcmp(prog, "wine64")
      || !strcmp(prog, "wine64-development") 
@@ -990,9 +1002,9 @@ int main(int argc, const char **argv, const char **env) {
     // allocate extra space for new environment variables such as BOX64_PATH
     my_context->envv = (char**)calloc(my_context->envc+4, sizeof(char*));
     GatherEnv(&my_context->envv, environ?environ:env, my_context->box64path);
-    if(box64_dump) {
+    if(box64_dump || 1) {
         for (int i=0; i<my_context->envc; ++i)
-            printf_dump(LOG_NEVER, " Env[%02d]: %s\n", i, my_context->envv[i]);
+            printf_dump(/*LOG_NEVER*/LOG_INFO, " Env[%02d]: %s\n", i, my_context->envv[i]);
     }
 
     path_collection_t ld_preload = {0};
@@ -1117,16 +1129,19 @@ int main(int argc, const char **argv, const char **env) {
         free_contextargv();
         FreeCollection(&ld_preload);
         if(x86) {
-            // duplicate the array to change 1st arg as box86
-            const char** newargv = (const char**)calloc(argc+1, sizeof(char*));
+            // duplicate the array and insert 1st arg as box86
+            const char** newargv = (const char**)calloc(my_context->argc+2, sizeof(char*));
             newargv[0] = my_context->box86path;
+            for(int i=0; i<my_context->argc; ++i)
+                newargv[i+1] = my_context->argv[i];
             FreeBox64Context(&my_context);
-            for(int i=1; i<argc; ++i)
-                newargv[i] = argv[i];
             return execvp(newargv[0], (char * const*)newargv);
         } else {
+            const char** newargv = (const char**)calloc(my_context->argc+1, sizeof(char*));
+            for(int i=0; i<my_context->argc; ++i)
+                newargv[i] = my_context->argv[i];
             FreeBox64Context(&my_context);
-            return execvp(argv[1], (char * const*)(argv+1));
+            return execvp(newargv[0], (char * const*)newargv);
         }
         printf_log(LOG_NONE, "Failed to execvp: error is %s\n", strerror(errno));
     }
diff --git a/src/wrapped/generated/functions_list.txt b/src/wrapped/generated/functions_list.txt
index 8550ed82..25f672bb 100644
--- a/src/wrapped/generated/functions_list.txt
+++ b/src/wrapped/generated/functions_list.txt
@@ -1046,6 +1046,7 @@
 #() vFppppp
 #() iFEiipp
 #() iFEiipV
+#() iFEippL
 #() iFEippp
 #() iFEpiii
 #() iFEpipi
@@ -1060,6 +1061,7 @@
 #() iFEppiV
 #() iFEppiA
 #() iFEpplp
+#() iFEpppi
 #() iFEpppp
 #() iFEpppV
 #() iFiiipu
@@ -2757,6 +2759,8 @@ wrappedlibc:
   - semctl
 - iFipii:
   - epoll_wait
+- iFippL:
+  - readlinkat
 - iFpipp:
   - __vasprintf_chk
   - glob
@@ -2832,6 +2836,8 @@ wrappedlibdl:
   - dlmopen
 - pFppp:
   - dlvsym
+- iFpppi:
+  - dladdr1
 wrappedlibdrm:
 wrappedlibform:
 wrappedlibformw:
diff --git a/src/wrapped/generated/wrappedlibctypes.h b/src/wrapped/generated/wrappedlibctypes.h
index 2e0d5a12..688beb6c 100644
--- a/src/wrapped/generated/wrappedlibctypes.h
+++ b/src/wrapped/generated/wrappedlibctypes.h
@@ -55,6 +55,7 @@ typedef void (*vFpLLp_t)(void*, uintptr_t, uintptr_t, void*);
 typedef int64_t (*iFiiip_t)(int64_t, int64_t, int64_t, void*);
 typedef int64_t (*iFiiiN_t)(int64_t, int64_t, int64_t, ...);
 typedef int64_t (*iFipii_t)(int64_t, void*, int64_t, int64_t);
+typedef int64_t (*iFippL_t)(int64_t, void*, void*, uintptr_t);
 typedef int64_t (*iFpipp_t)(void*, int64_t, void*, void*);
 typedef int64_t (*iFpipV_t)(void*, int64_t, void*, ...);
 typedef int64_t (*iFpLpp_t)(void*, uintptr_t, void*, void*);
@@ -183,6 +184,7 @@ typedef int64_t (*iFpippppp_t)(void*, int64_t, void*, void*, void*, void*, void*
 	GO(epoll_ctl, iFiiip_t) \
 	GO(semctl, iFiiiN_t) \
 	GO(epoll_wait, iFipii_t) \
+	GO(readlinkat, iFippL_t) \
 	GO(__vasprintf_chk, iFpipp_t) \
 	GO(glob, iFpipp_t) \
 	GO(glob64, iFpipp_t) \
diff --git a/src/wrapped/generated/wrappedlibdltypes.h b/src/wrapped/generated/wrappedlibdltypes.h
index 4f3e67b2..0c448396 100644
--- a/src/wrapped/generated/wrappedlibdltypes.h
+++ b/src/wrapped/generated/wrappedlibdltypes.h
@@ -19,6 +19,7 @@ typedef void* (*pFpp_t)(void*, void*);
 typedef int64_t (*iFpip_t)(void*, int64_t, void*);
 typedef void* (*pFppi_t)(void*, void*, int64_t);
 typedef void* (*pFppp_t)(void*, void*, void*);
+typedef int64_t (*iFpppi_t)(void*, void*, void*, int64_t);
 
 #define SUPER() ADDED_FUNCTIONS() \
 	GO(dlclose, iFp_t) \
@@ -28,6 +29,7 @@ typedef void* (*pFppp_t)(void*, void*, void*);
 	GO(dlsym, pFpp_t) \
 	GO(dlinfo, iFpip_t) \
 	GO(dlmopen, pFppi_t) \
-	GO(dlvsym, pFppp_t)
+	GO(dlvsym, pFppp_t) \
+	GO(dladdr1, iFpppi_t)
 
 #endif // __wrappedlibdlTYPES_H_
diff --git a/src/wrapped/generated/wrapper.c b/src/wrapped/generated/wrapper.c
index 693f0388..0afca20a 100644
--- a/src/wrapped/generated/wrapper.c
+++ b/src/wrapped/generated/wrapper.c
@@ -1080,6 +1080,7 @@ typedef void (*vFppppL_t)(void*, void*, void*, void*, uintptr_t);
 typedef void (*vFppppp_t)(void*, void*, void*, void*, void*);
 typedef int64_t (*iFEiipp_t)(x64emu_t*, int64_t, int64_t, void*, void*);
 typedef int64_t (*iFEiipV_t)(x64emu_t*, int64_t, int64_t, void*, void*);
+typedef int64_t (*iFEippL_t)(x64emu_t*, int64_t, void*, void*, uintptr_t);
 typedef int64_t (*iFEippp_t)(x64emu_t*, int64_t, void*, void*, void*);
 typedef int64_t (*iFEpiii_t)(x64emu_t*, void*, int64_t, int64_t, int64_t);
 typedef int64_t (*iFEpipi_t)(x64emu_t*, void*, int64_t, void*, int64_t);
@@ -1094,6 +1095,7 @@ typedef int64_t (*iFEppip_t)(x64emu_t*, void*, void*, int64_t, void*);
 typedef int64_t (*iFEppiV_t)(x64emu_t*, void*, void*, int64_t, void*);
 typedef int64_t (*iFEppiA_t)(x64emu_t*, void*, void*, int64_t, void*);
 typedef int64_t (*iFEpplp_t)(x64emu_t*, void*, void*, intptr_t, void*);
+typedef int64_t (*iFEpppi_t)(x64emu_t*, void*, void*, void*, int64_t);
 typedef int64_t (*iFEpppp_t)(x64emu_t*, void*, void*, void*, void*);
 typedef int64_t (*iFEpppV_t)(x64emu_t*, void*, void*, void*, void*);
 typedef int64_t (*iFiiipu_t)(int64_t, int64_t, int64_t, void*, uint64_t);
@@ -3124,6 +3126,7 @@ void vFppppL(x64emu_t *emu, uintptr_t fcn) { vFppppL_t fn = (vFppppL_t)fcn; fn((
 void vFppppp(x64emu_t *emu, uintptr_t fcn) { vFppppp_t fn = (vFppppp_t)fcn; fn((void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8); }
 void iFEiipp(x64emu_t *emu, uintptr_t fcn) { iFEiipp_t fn = (iFEiipp_t)fcn; R_RAX=(int64_t)fn(emu, (int64_t)R_RDI, (int64_t)R_RSI, (void*)R_RDX, (void*)R_RCX); }
 void iFEiipV(x64emu_t *emu, uintptr_t fcn) { iFEiipV_t fn = (iFEiipV_t)fcn; R_RAX=(int64_t)fn(emu, (int64_t)R_RDI, (int64_t)R_RSI, (void*)R_RDX, (void*)(R_RSP + 8)); }
+void iFEippL(x64emu_t *emu, uintptr_t fcn) { iFEippL_t fn = (iFEippL_t)fcn; R_RAX=(int64_t)fn(emu, (int64_t)R_RDI, (void*)R_RSI, (void*)R_RDX, (uintptr_t)R_RCX); }
 void iFEippp(x64emu_t *emu, uintptr_t fcn) { iFEippp_t fn = (iFEippp_t)fcn; R_RAX=(int64_t)fn(emu, (int64_t)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX); }
 void iFEpiii(x64emu_t *emu, uintptr_t fcn) { iFEpiii_t fn = (iFEpiii_t)fcn; R_RAX=(int64_t)fn(emu, (void*)R_RDI, (int64_t)R_RSI, (int64_t)R_RDX, (int64_t)R_RCX); }
 void iFEpipi(x64emu_t *emu, uintptr_t fcn) { iFEpipi_t fn = (iFEpipi_t)fcn; R_RAX=(int64_t)fn(emu, (void*)R_RDI, (int64_t)R_RSI, (void*)R_RDX, (int64_t)R_RCX); }
@@ -3138,6 +3141,7 @@ void iFEppip(x64emu_t *emu, uintptr_t fcn) { iFEppip_t fn = (iFEppip_t)fcn; R_RA
 void iFEppiV(x64emu_t *emu, uintptr_t fcn) { iFEppiV_t fn = (iFEppiV_t)fcn; R_RAX=(int64_t)fn(emu, (void*)R_RDI, (void*)R_RSI, (int64_t)R_RDX, (void*)(R_RSP + 8)); }
 void iFEppiA(x64emu_t *emu, uintptr_t fcn) { iFEppiA_t fn = (iFEppiA_t)fcn; R_RAX=(int64_t)fn(emu, (void*)R_RDI, (void*)R_RSI, (int64_t)R_RDX, (void*)R_RCX); }
 void iFEpplp(x64emu_t *emu, uintptr_t fcn) { iFEpplp_t fn = (iFEpplp_t)fcn; R_RAX=(int64_t)fn(emu, (void*)R_RDI, (void*)R_RSI, (intptr_t)R_RDX, (void*)R_RCX); }
+void iFEpppi(x64emu_t *emu, uintptr_t fcn) { iFEpppi_t fn = (iFEpppi_t)fcn; R_RAX=(int64_t)fn(emu, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int64_t)R_RCX); }
 void iFEpppp(x64emu_t *emu, uintptr_t fcn) { iFEpppp_t fn = (iFEpppp_t)fcn; R_RAX=(int64_t)fn(emu, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX); }
 void iFEpppV(x64emu_t *emu, uintptr_t fcn) { iFEpppV_t fn = (iFEpppV_t)fcn; R_RAX=(int64_t)fn(emu, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)(R_RSP + 8)); }
 void iFiiipu(x64emu_t *emu, uintptr_t fcn) { iFiiipu_t fn = (iFiiipu_t)fcn; R_RAX=(int64_t)fn((int64_t)R_RDI, (int64_t)R_RSI, (int64_t)R_RDX, (void*)R_RCX, (uint64_t)R_R8); }
diff --git a/src/wrapped/generated/wrapper.h b/src/wrapped/generated/wrapper.h
index 8ac3a7de..360bc132 100644
--- a/src/wrapped/generated/wrapper.h
+++ b/src/wrapped/generated/wrapper.h
@@ -1079,6 +1079,7 @@ void vFppppL(x64emu_t *emu, uintptr_t fnc);
 void vFppppp(x64emu_t *emu, uintptr_t fnc);
 void iFEiipp(x64emu_t *emu, uintptr_t fnc);
 void iFEiipV(x64emu_t *emu, uintptr_t fnc);
+void iFEippL(x64emu_t *emu, uintptr_t fnc);
 void iFEippp(x64emu_t *emu, uintptr_t fnc);
 void iFEpiii(x64emu_t *emu, uintptr_t fnc);
 void iFEpipi(x64emu_t *emu, uintptr_t fnc);
@@ -1093,6 +1094,7 @@ void iFEppip(x64emu_t *emu, uintptr_t fnc);
 void iFEppiV(x64emu_t *emu, uintptr_t fnc);
 void iFEppiA(x64emu_t *emu, uintptr_t fnc);
 void iFEpplp(x64emu_t *emu, uintptr_t fnc);
+void iFEpppi(x64emu_t *emu, uintptr_t fnc);
 void iFEpppp(x64emu_t *emu, uintptr_t fnc);
 void iFEpppV(x64emu_t *emu, uintptr_t fnc);
 void iFiiipu(x64emu_t *emu, uintptr_t fnc);
diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c
index f0b7933e..e2ae9c76 100755
--- a/src/wrapped/wrappedlibc.c
+++ b/src/wrapped/wrappedlibc.c
@@ -2101,13 +2101,23 @@ EXPORT void my___explicit_bzero_chk(x64emu_t* emu, void* dst, uint32_t len, uint
 
 EXPORT void* my_realpath(x64emu_t* emu, void* path, void* resolved_path)
 {
-
     if(isProcSelf(path, "exe")) {
         return realpath(emu->context->fullpath, resolved_path);
     }
-        return realpath(path, resolved_path);
+    return realpath(path, resolved_path);
 }
 
+EXPORT int my_readlinkat(x64emu_t* emu, int fd, void* path, void* buf, size_t bufsize)
+{
+    if(isProcSelf(path, "exe")) {
+        strncpy(buf, emu->context->fullpath, bufsize);
+        size_t l = strlen(emu->context->fullpath);
+        return (l>bufsize)?bufsize:(l+1);
+    }
+    return readlinkat(fd, path, buf, bufsize);
+}
+
+
 EXPORT void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int64_t offset)
 {
     (void)emu;
diff --git a/src/wrapped/wrappedlibc_private.h b/src/wrapped/wrappedlibc_private.h
index 2dae6e29..36ef89b4 100755
--- a/src/wrapped/wrappedlibc_private.h
+++ b/src/wrapped/wrappedlibc_private.h
@@ -4,6 +4,7 @@
 
 //socklen_t is u32
 // typedef unsigned long int nfds_t;
+// pid_t is S32
 // key_t is S32
 // uid_t is u32
 // gid_t is u32
@@ -99,8 +100,8 @@ GOW(calloc, pFLL)
 //GO(callrpc, iFpLLL@p@p)
 //GO(__call_tls_dtors, vFv)
 GOW(canonicalize_file_name, pFp)
-//GO(capget, 
-//GO(capset, 
+GO(capget, iFpp)
+GO(capset, iFpp)
 GO(catclose, iFp)
 GO(catgets, pFpiip)
 GO(catopen, pFpi)
@@ -1466,7 +1467,7 @@ GOW(readdir64, pFp)
 GOW(readdir64_r, iFppp)
 GOW(readdir_r, iFppp)
 GOWM(readlink, lFEppL)
-GO(readlinkat, lFippL)
+GOM(readlinkat, iFEippL)
 //GO(__readlinkat_chk, 
 //GO(__readlink_chk, 
 //GO(__read_nocancel, 
diff --git a/src/wrapped/wrappedlibdl.c b/src/wrapped/wrappedlibdl.c
index 53566797..dffc9fa9 100755
--- a/src/wrapped/wrappedlibdl.c
+++ b/src/wrapped/wrappedlibdl.c
@@ -4,6 +4,7 @@
 #include <string.h>
 #include <dlfcn.h>
 #include <elf.h>
+#include <link.h>
 
 #include "wrappedlibs.h"
 
@@ -42,6 +43,7 @@ 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 my_dladdr(x64emu_t* emu, void *addr, void *info) EXPORT;
+int my_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 my_dlinfo(x64emu_t* emu, void* handle, int request, void* info) EXPORT;
 
@@ -338,21 +340,38 @@ int my_dlclose(x64emu_t* emu, void *handle)
     }
     return 0;
 }
-int my_dladdr(x64emu_t* emu, void *addr, void *i)
+int my_dladdr1(x64emu_t* emu, void *addr, void *i, void** extra_info, int flags)
 {
     //int dladdr(void *addr, Dl_info *info);
     dlprivate_t *dl = emu->context->dlprivate;
     CLEARERR
     Dl_info *info = (Dl_info*)i;
-    printf_log(LOG_DEBUG, "Warning: partially unimplement call to dladdr(%p, %p)\n", addr, info);
+    printf_log(LOG_DEBUG, "Warning: partially unimplement call to dladdr/dladdr1(%p, %p, %p, %d)\n", addr, info, extra_info, flags);
     
     //emu->quit = 1;
     info->dli_saddr = NULL;
     info->dli_fname = NULL;
     info->dli_sname = FindSymbolName(emu->context->maplib, addr, &info->dli_saddr, NULL, &info->dli_fname, &info->dli_fbase);
     printf_log(LOG_DEBUG, "     dladdr return saddr=%p, fname=\"%s\", sname=\"%s\"\n", info->dli_saddr, info->dli_sname?info->dli_sname:"", info->dli_fname?info->dli_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, partially unimplement call to dladdr1 with RTLD_DL_LINKMAP flags\n");
+        static struct link_map my_map = {0};
+        elfheader_t* elf = FindElfAddress(my_context, (uintptr_t)addr);
+        if(elf) {
+            my_map.l_addr = (uintptr_t)GetElfDelta(elf);
+            my_map.l_name = (char*)ElfPath(elf);
+            my_map.l_ld = GetDynamicSection(elf);
+        }
+        *extra_info = &my_map;
+    }
     return (info->dli_sname)?1:0;   // success is non-null here...
 }
+int my_dladdr(x64emu_t* emu, void *addr, void *i)
+{
+    return my_dladdr1(emu, addr, i, NULL, 0);
+}
 void* my_dlvsym(x64emu_t* emu, void *handle, void *symbol, const char *vername)
 {
     dlprivate_t *dl = emu->context->dlprivate;
diff --git a/src/wrapped/wrappedlibdl_private.h b/src/wrapped/wrappedlibdl_private.h
index 58064bca..4753af0b 100755
--- a/src/wrapped/wrappedlibdl_private.h
+++ b/src/wrapped/wrappedlibdl_private.h
@@ -1,7 +1,7 @@
 #if defined(GO) && defined(GOM) && defined(GO2) && defined(DATA)
 
 GOM(dladdr, iFEpp)
-// dladdr1
+GOM(dladdr1, iFEpppi)
 GOM(dlclose, iFEp)
 GOM(dlerror, pFEv)
 DATAB(_dlfcn_hook, 8)