# Node ID 76fcde446236449d99df66851ceab503c991a5e0 # Parent ecbab252275728bc4dfd93631e0edaecf39b8d95 diff --git a/src/arch/x86/linux/process.cc b/src/arch/x86/linux/process.cc --- a/src/arch/x86/linux/process.cc +++ b/src/arch/x86/linux/process.cc @@ -485,7 +485,7 @@ /* 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 @@ /* 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 @@ /* 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), diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -348,12 +348,10 @@ } 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; } } @@ -372,23 +370,48 @@ } SyscallReturn -readlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc, - int index) +readlinkFunc(SyscallDesc *desc, int num, LiveProcess *process, + ThreadContext *tc, int index) { string path; - if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) + if (!tc->getMemProxy().tryReadString(path, + process->getSyscallArg(tc, index))) { return -EFAULT; + } // Adjust path for current working directory - path = p->fullPath(path); + path = process->fullPath(path); - Addr bufPtr = p->getSyscallArg(tc, index); - size_t bufsiz = p->getSyscallArg(tc, index); + Addr bufPtr = process->getSyscallArg(tc, index); + size_t bufsiz = process->getSyscallArg(tc, index); 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(process->progName()) > bufsiz) { + // readlink will truncate the contents of the + // path to ensure it is no more than bufsiz + strncpy((char*)buf.bufferPtr(), process->progName(), bufsiz); + result = bufsiz; + } else { + // return the program's working path rather + // than the one for the gem5 binary itself. + strcpy((char*)buf.bufferPtr(), process->progName()); + result = strlen((char*)buf.bufferPtr()); + } + } buf.copyOut(tc->getMemProxy());