syscall: Add readlink to x86 with special case /proc/self/exe
authorDavid Hashe <david.hashe@amd.com>
Mon, 20 Jul 2015 14:15:18 +0000 (09:15 -0500)
committerDavid Hashe <david.hashe@amd.com>
Mon, 20 Jul 2015 14:15:18 +0000 (09:15 -0500)
This patch implements the correct behavior.

src/arch/x86/linux/process.cc
src/sim/syscall_emul.cc

index ed17d73889665ca0539c51dd78fb0bde93b81c07..5bb237c107fff34b6f8b2b05c0b432d366d1e8fb 100644 (file)
@@ -485,7 +485,7 @@ static SyscallDesc syscallDescs64[] = {
     /* 264 */ SyscallDesc("renameat", unimplementedFunc),
     /* 265 */ SyscallDesc("linkat", unimplementedFunc),
     /* 266 */ SyscallDesc("symlinkat", unimplementedFunc),
-    /* 267 */ SyscallDesc("readlinkat", unimplementedFunc),
+    /* 267 */ SyscallDesc("readlinkat", readlinkFunc),
     /* 268 */ SyscallDesc("fchmodat", unimplementedFunc),
     /* 269 */ SyscallDesc("faccessat", unimplementedFunc),
     /* 270 */ SyscallDesc("pselect6", unimplementedFunc),
@@ -626,7 +626,7 @@ static SyscallDesc syscallDescs32[] = {
     /*  82 */ SyscallDesc("select", unimplementedFunc),
     /*  83 */ SyscallDesc("symlink", unimplementedFunc),
     /*  84 */ SyscallDesc("oldlstat", unimplementedFunc),
-    /*  85 */ SyscallDesc("readlink", unimplementedFunc),
+    /*  85 */ SyscallDesc("readlink", readlinkFunc),
     /*  86 */ SyscallDesc("uselib", unimplementedFunc),
     /*  87 */ SyscallDesc("swapon", unimplementedFunc),
     /*  88 */ SyscallDesc("reboot", unimplementedFunc),
@@ -846,7 +846,7 @@ static SyscallDesc syscallDescs32[] = {
     /* 302 */ SyscallDesc("renameat", unimplementedFunc),
     /* 303 */ SyscallDesc("linkat", unimplementedFunc),
     /* 304 */ SyscallDesc("symlinkat", unimplementedFunc),
-    /* 305 */ SyscallDesc("readlinkat", unimplementedFunc),
+    /* 305 */ SyscallDesc("readlinkat", readlinkFunc),
     /* 306 */ SyscallDesc("fchmodat", unimplementedFunc),
     /* 307 */ SyscallDesc("faccessat", unimplementedFunc),
     /* 308 */ SyscallDesc("pselect6", unimplementedFunc),
index d628365328e88d57baf4373cbc6b0044519dcd67..f5b273202b34e04000b2a51bfb435cb364211a70 100644 (file)
@@ -365,12 +365,10 @@ getcwdFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
         }
         strncpy((char *)buf.bufferPtr(), cwd.c_str(), size);
         result = cwd.length();
-    }
-    else {
+    } else {
         if (getcwd((char *)buf.bufferPtr(), size) != NULL) {
             result = strlen((char *)buf.bufferPtr());
-        }
-        else {
+        } else {
             result = -1;
         }
     }
@@ -405,7 +403,30 @@ readlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc,
 
     BufferArg buf(bufPtr, bufsiz);
 
-    int result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz);
+    int result = -1;
+    if (path != "/proc/self/exe") {
+        result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz);
+    } else {
+        // readlink() will return the path of the binary given
+        // with the -c option, however it is possible that this
+        // will still result in incorrect behavior if one binary
+        // runs another, e.g., -c time -o "my_binary" where
+        // my_binary calls readlink(). this is a very unlikely case,
+        // so we issue a warning.
+        warn_once("readlink may yield unexpected results if multiple "
+                  "binaries are used\n");
+        if (strlen(p->progName()) > bufsiz) {
+            // readlink will truncate the contents of the
+            // path to ensure it is no more than bufsiz
+            strncpy((char*)buf.bufferPtr(), p->progName(), bufsiz);
+            result = bufsiz;
+        } else {
+            // return the program's working path rather
+            // than the one for the gem5 binary itself.
+            strcpy((char*)buf.bufferPtr(), p->progName());
+            result = strlen((char*)buf.bufferPtr());
+        }
+    }
 
     buf.copyOut(tc->getMemProxy());