blob: 10ee11291e38d3fa6a927ab72e59c1ccdcf06907 [file] [log] [blame]
/*
* Copyright (c) 2007 The Hewlett-Packard Development Company
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Gabe Black
*/
#include "arch/x86/linux/process.hh"
#include <sys/syscall.h>
#include "arch/x86/isa_traits.hh"
#include "arch/x86/linux/linux.hh"
#include "arch/x86/registers.hh"
#include "base/loader/object_file.hh"
#include "base/trace.hh"
#include "cpu/thread_context.hh"
#include "kern/linux/linux.hh"
#include "sim/process.hh"
#include "sim/syscall_desc.hh"
#include "sim/syscall_emul.hh"
using namespace std;
using namespace X86ISA;
namespace
{
class X86LinuxObjectFileLoader : public Process::Loader
{
public:
Process *
load(ProcessParams *params, ObjectFile *obj_file) override
{
auto arch = obj_file->getArch();
auto opsys = obj_file->getOpSys();
if (arch != ObjectFile::X86_64 && arch != ObjectFile::I386)
return nullptr;
if (opsys == ObjectFile::UnknownOpSys) {
warn("Unknown operating system; assuming Linux.");
opsys = ObjectFile::Linux;
}
if (opsys != ObjectFile::Linux)
return nullptr;
if (arch == ObjectFile::X86_64)
return new X86_64LinuxProcess(params, obj_file);
else
return new I386LinuxProcess(params, obj_file);
}
};
X86LinuxObjectFileLoader loader;
} // anonymous namespace
/// Target uname() handler.
static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
{
int index = 0;
auto process = tc->getProcessPtr();
TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, index));
strcpy(name->sysname, "Linux");
strcpy(name->nodename, "sim.gem5.org");
strcpy(name->release, process->release.c_str());
strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
strcpy(name->machine, "x86_64");
name.copyOut(tc->getVirtProxy());
return 0;
}
static SyscallReturn
archPrctlFunc(SyscallDesc *desc, int callnum, ThreadContext *tc)
{
enum ArchPrctlCodes
{
SetFS = 0x1002,
GetFS = 0x1003,
SetGS = 0x1001,
GetGS = 0x1004
};
// First argument is the code, second is the address
int index = 0;
auto process = tc->getProcessPtr();
int code = process->getSyscallArg(tc, index);
uint64_t addr = process->getSyscallArg(tc, index);
uint64_t fsBase, gsBase;
PortProxy &p = tc->getVirtProxy();
switch(code)
{
// Each of these valid options should actually check addr.
case SetFS:
tc->setMiscRegNoEffect(MISCREG_FS_BASE, addr);
tc->setMiscRegNoEffect(MISCREG_FS_EFF_BASE, addr);
return 0;
case GetFS:
fsBase = tc->readMiscRegNoEffect(MISCREG_FS_BASE);
p.write(addr, fsBase);
return 0;
case SetGS:
tc->setMiscRegNoEffect(MISCREG_GS_BASE, addr);
tc->setMiscRegNoEffect(MISCREG_GS_EFF_BASE, addr);
return 0;
case GetGS:
gsBase = tc->readMiscRegNoEffect(MISCREG_GS_BASE);
p.write(addr, gsBase);
return 0;
default:
return -EINVAL;
}
}
BitUnion32(UserDescFlags)
Bitfield<0> seg_32bit;
Bitfield<2, 1> contents;
Bitfield<3> read_exec_only;
Bitfield<4> limit_in_pages;
Bitfield<5> seg_not_present;
Bitfield<6> useable;
EndBitUnion(UserDescFlags)
struct UserDesc32 {
uint32_t entry_number;
uint32_t base_addr;
uint32_t limit;
uint32_t flags;
};
struct UserDesc64 {
uint32_t entry_number;
uint32_t __padding1;
uint64_t base_addr;
uint32_t limit;
uint32_t flags;
};
static SyscallReturn
setThreadArea32Func(SyscallDesc *desc, int callnum, ThreadContext *tc)
{
const int minTLSEntry = 6;
const int numTLSEntries = 3;
const int maxTLSEntry = minTLSEntry + numTLSEntries - 1;
auto process = tc->getProcessPtr();
X86Process *x86p = dynamic_cast<X86Process *>(process);
assert(x86p);
assert((maxTLSEntry + 1) * sizeof(uint64_t) <= x86p->gdtSize());
int argIndex = 0;
TypedBufferArg<UserDesc32> userDesc(process->getSyscallArg(tc, argIndex));
TypedBufferArg<uint64_t>
gdt(x86p->gdtStart() + minTLSEntry * sizeof(uint64_t),
numTLSEntries * sizeof(uint64_t));
if (!userDesc.copyIn(tc->getVirtProxy()))
return -EFAULT;
if (!gdt.copyIn(tc->getVirtProxy()))
panic("Failed to copy in GDT for %s.\n", desc->name());
if (userDesc->entry_number == (uint32_t)(-1)) {
// Find a free TLS entry.
for (int i = 0; i < numTLSEntries; i++) {
if (gdt[i] == 0) {
userDesc->entry_number = i + minTLSEntry;
break;
}
}
// We failed to find one.
if (userDesc->entry_number == (uint32_t)(-1))
return -ESRCH;
}
int index = userDesc->entry_number;
if (index < minTLSEntry || index > maxTLSEntry)
return -EINVAL;
index -= minTLSEntry;
// Build the entry we're going to add.
SegDescriptor segDesc = 0;
UserDescFlags flags = userDesc->flags;
segDesc.limitLow = bits(userDesc->limit, 15, 0);
segDesc.baseLow = bits(userDesc->base_addr, 23, 0);
segDesc.type.a = 1;
if (!flags.read_exec_only)
segDesc.type.w = 1;
if (bits((uint8_t)flags.contents, 0))
segDesc.type.e = 1;
if (bits((uint8_t)flags.contents, 1))
segDesc.type.codeOrData = 1;
segDesc.s = 1;
segDesc.dpl = 3;
if (!flags.seg_not_present)
segDesc.p = 1;
segDesc.limitHigh = bits(userDesc->limit, 19, 16);
if (flags.useable)
segDesc.avl = 1;
segDesc.l = 0;
if (flags.seg_32bit)
segDesc.d = 1;
if (flags.limit_in_pages)
segDesc.g = 1;
segDesc.baseHigh = bits(userDesc->base_addr, 31, 24);
gdt[index] = (uint64_t)segDesc;
if (!userDesc.copyOut(tc->getVirtProxy()))
return -EFAULT;
if (!gdt.copyOut(tc->getVirtProxy()))
panic("Failed to copy out GDT for %s.\n", desc->name());
return 0;
}
static SyscallDescABI<DefaultSyscallABI> syscallDescs64[] = {
/* 0 */ { "read", readFunc<X86Linux64> },
/* 1 */ { "write", writeFunc<X86Linux64> },
/* 2 */ { "open", openFunc<X86Linux64> },
/* 3 */ { "close", closeFunc },
/* 4 */ { "stat", stat64Func<X86Linux64> },
/* 5 */ { "fstat", fstat64Func<X86Linux64> },
/* 6 */ { "lstat", lstat64Func<X86Linux64> },
/* 7 */ { "poll", pollFunc<X86Linux64> },
/* 8 */ { "lseek", lseekFunc },
/* 9 */ { "mmap", mmapFunc<X86Linux64> },
/* 10 */ { "mprotect", ignoreFunc },
/* 11 */ { "munmap", munmapFunc },
/* 12 */ { "brk", brkFunc },
/* 13 */ { "rt_sigaction", ignoreWarnOnceFunc },
/* 14 */ { "rt_sigprocmask", ignoreWarnOnceFunc },
/* 15 */ { "rt_sigreturn" },
/* 16 */ { "ioctl", ioctlFunc<X86Linux64> },
/* 17 */ { "pread64" },
/* 18 */ { "pwrite64", pwrite64Func<X86Linux64> },
/* 19 */ { "readv", readvFunc<X86Linux64> },
/* 20 */ { "writev", writevFunc<X86Linux64> },
/* 21 */ { "access", ignoreFunc },
/* 22 */ { "pipe", pipeFunc },
/* 23 */ { "select", selectFunc<X86Linux64> },
/* 24 */ { "sched_yield", ignoreFunc },
/* 25 */ { "mremap", mremapFunc<X86Linux64> },
/* 26 */ { "msync" },
/* 27 */ { "mincore" },
/* 28 */ { "madvise", ignoreFunc },
/* 29 */ { "shmget" },
/* 30 */ { "shmat" },
/* 31 */ { "shmctl" },
/* 32 */ { "dup", dupFunc },
/* 33 */ { "dup2", dup2Func },
/* 34 */ { "pause" },
/* 35 */ { "nanosleep", ignoreWarnOnceFunc },
/* 36 */ { "getitimer" },
/* 37 */ { "alarm" },
/* 38 */ { "setitimer" },
/* 39 */ { "getpid", getpidFunc },
/* 40 */ { "sendfile" },
/* 41 */ { "socket", socketFunc<X86Linux64> },
/* 42 */ { "connect", connectFunc },
/* 43 */ { "accept", acceptFunc<X86Linux64> },
/* 44 */ { "sendto", sendtoFunc },
/* 45 */ { "recvfrom", recvfromFunc },
/* 46 */ { "sendmsg", sendmsgFunc },
/* 47 */ { "recvmsg", recvmsgFunc },
/* 48 */ { "shutdown", shutdownFunc },
/* 49 */ { "bind", bindFunc },
/* 50 */ { "listen", listenFunc },
/* 51 */ { "getsockname", getsocknameFunc },
/* 52 */ { "getpeername", getpeernameFunc },
/* 53 */ { "socketpair", socketpairFunc<X86Linux64> },
/* 54 */ { "setsockopt", setsockoptFunc },
/* 55 */ { "getsockopt", getsockoptFunc },
/* 56 */ { "clone", cloneFunc<X86Linux64> },
/* 57 */ { "fork" },
/* 58 */ { "vfork" },
/* 59 */ { "execve", execveFunc<X86Linux64> },
/* 60 */ { "exit", exitFunc },
/* 61 */ { "wait4", wait4Func<X86Linux64> },
/* 62 */ { "kill" },
/* 63 */ { "uname", unameFunc },
/* 64 */ { "semget" },
/* 65 */ { "semop" },
/* 66 */ { "semctl" },
/* 67 */ { "shmdt" },
/* 68 */ { "msgget" },
/* 69 */ { "msgsnd" },
/* 70 */ { "msgrcv" },
/* 71 */ { "msgctl" },
/* 72 */ { "fcntl", fcntlFunc },
/* 73 */ { "flock" },
/* 74 */ { "fsync" },
/* 75 */ { "fdatasync" },
/* 76 */ { "truncate", truncateFunc },
/* 77 */ { "ftruncate", ftruncateFunc },
#if defined(SYS_getdents)
/* 78 */ { "getdents", getdentsFunc },
#else
/* 78 */ { "getdents" },
#endif
/* 79 */ { "getcwd", getcwdFunc },
/* 80 */ { "chdir", chdirFunc },
/* 81 */ { "fchdir" },
/* 82 */ { "rename", renameFunc },
/* 83 */ { "mkdir", mkdirFunc },
/* 84 */ { "rmdir", rmdirFunc },
/* 85 */ { "creat" },
/* 86 */ { "link", linkFunc },
/* 87 */ { "unlink", unlinkFunc },
/* 88 */ { "symlink", symlinkFunc },
/* 89 */ { "readlink", readlinkFunc },
/* 90 */ { "chmod" },
/* 91 */ { "fchmod" },
/* 92 */ { "chown" },
/* 93 */ { "fchown" },
/* 94 */ { "lchown" },
/* 95 */ { "umask", umaskFunc },
/* 96 */ { "gettimeofday", gettimeofdayFunc<X86Linux64> },
/* 97 */ { "getrlimit", getrlimitFunc<X86Linux64> },
/* 98 */ { "getrusage", getrusageFunc<X86Linux64> },
/* 99 */ { "sysinfo", sysinfoFunc<X86Linux64> },
/* 100 */ { "times", timesFunc<X86Linux64> },
/* 101 */ { "ptrace" },
/* 102 */ { "getuid", getuidFunc },
/* 103 */ { "syslog" },
/* 104 */ { "getgid", getgidFunc },
/* 105 */ { "setuid" },
/* 106 */ { "setgid" },
/* 107 */ { "geteuid", geteuidFunc },
/* 108 */ { "getegid", getegidFunc },
/* 109 */ { "setpgid", setpgidFunc },
/* 110 */ { "getppid", getppidFunc },
/* 111 */ { "getpgrp", getpgrpFunc },
/* 112 */ { "setsid" },
/* 113 */ { "setreuid" },
/* 114 */ { "setregid" },
/* 115 */ { "getgroups" },
/* 116 */ { "setgroups" },
/* 117 */ { "setresuid", ignoreFunc },
/* 118 */ { "getresuid" },
/* 119 */ { "setresgid" },
/* 120 */ { "getresgid" },
/* 121 */ { "getpgid" },
/* 122 */ { "setfsuid" },
/* 123 */ { "setfsgid" },
/* 124 */ { "getsid" },
/* 125 */ { "capget" },
/* 126 */ { "capset" },
/* 127 */ { "rt_sigpending" },
/* 128 */ { "rt_sigtimedwait" },
/* 129 */ { "rt_sigqueueinfo" },
/* 130 */ { "rt_sigsuspend" },
/* 131 */ { "sigaltstack" },
/* 132 */ { "utime" },
/* 133 */ { "mknod", mknodFunc },
/* 134 */ { "uselib" },
/* 135 */ { "personality" },
/* 136 */ { "ustat" },
/* 137 */ { "statfs", statfsFunc<X86Linux64> },
/* 138 */ { "fstatfs", fstatfsFunc<X86Linux64> },
/* 139 */ { "sysfs" },
/* 140 */ { "getpriority" },
/* 141 */ { "setpriority", ignoreFunc },
/* 142 */ { "sched_setparam" },
/* 143 */ { "sched_getparam" },
/* 144 */ { "sched_setscheduler" },
/* 145 */ { "sched_getscheduler" },
/* 146 */ { "sched_get_priority_max" },
/* 147 */ { "sched_get_priority_min" },
/* 148 */ { "sched_rr_get_interval" },
/* 149 */ { "mlock" },
/* 150 */ { "munlock" },
/* 151 */ { "mlockall" },
/* 152 */ { "munlockall" },
/* 153 */ { "vhangup" },
/* 154 */ { "modify_ldt" },
/* 155 */ { "pivot_root" },
/* 156 */ { "_sysctl" },
/* 157 */ { "prctl" },
/* 158 */ { "arch_prctl", archPrctlFunc },
/* 159 */ { "adjtimex" },
/* 160 */ { "setrlimit", ignoreFunc },
/* 161 */ { "chroot" },
/* 162 */ { "sync" },
/* 163 */ { "acct" },
/* 164 */ { "settimeofday" },
/* 165 */ { "mount" },
/* 166 */ { "umount2" },
/* 167 */ { "swapon" },
/* 168 */ { "swapoff" },
/* 169 */ { "reboot" },
/* 170 */ { "sethostname" },
/* 171 */ { "setdomainname" },
/* 172 */ { "iopl" },
/* 173 */ { "ioperm" },
/* 174 */ { "create_module" },
/* 175 */ { "init_module" },
/* 176 */ { "delete_module" },
/* 177 */ { "get_kernel_syms" },
/* 178 */ { "query_module" },
/* 179 */ { "quotactl" },
/* 180 */ { "nfsservctl" },
/* 181 */ { "getpmsg" },
/* 182 */ { "putpmsg" },
/* 183 */ { "afs_syscall" },
/* 184 */ { "tuxcall" },
/* 185 */ { "security" },
/* 186 */ { "gettid", gettidFunc },
/* 187 */ { "readahead" },
/* 188 */ { "setxattr" },
/* 189 */ { "lsetxattr" },
/* 190 */ { "fsetxattr" },
/* 191 */ { "getxattr" },
/* 192 */ { "lgetxattr" },
/* 193 */ { "fgetxattr" },
/* 194 */ { "listxattr" },
/* 195 */ { "llistxattr" },
/* 196 */ { "flistxattr" },
/* 197 */ { "removexattr" },
/* 198 */ { "lremovexattr" },
/* 199 */ { "fremovexattr" },
/* 200 */ { "tkill" },
/* 201 */ { "time", timeFunc<X86Linux64> },
/* 202 */ { "futex", futexFunc<X86Linux64> },
/* 203 */ { "sched_setaffinity" },
/* 204 */ { "sched_getaffinity", ignoreFunc },
/* 205 */ { "set_thread_area" },
/* 206 */ { "io_setup" },
/* 207 */ { "io_destroy" },
/* 208 */ { "io_getevents" },
/* 209 */ { "io_submit" },
/* 210 */ { "io_cancel" },
/* 211 */ { "get_thread_area" },
/* 212 */ { "lookup_dcookie" },
/* 213 */ { "epoll_create" },
/* 214 */ { "epoll_ctl_old" },
/* 215 */ { "epoll_wait_old" },
/* 216 */ { "remap_file_pages" },
/* 217 */ { "getdents64" },
/* 218 */ { "set_tid_address", setTidAddressFunc },
/* 219 */ { "restart_syscall" },
/* 220 */ { "semtimedop" },
/* 221 */ { "fadvise64", ignoreFunc },
/* 222 */ { "timer_create" },
/* 223 */ { "timer_settime" },
/* 224 */ { "timer_gettime" },
/* 225 */ { "timer_getoverrun" },
/* 226 */ { "timer_delete" },
/* 227 */ { "clock_settime" },
/* 228 */ { "clock_gettime", clock_gettimeFunc<X86Linux64> },
/* 229 */ { "clock_getres", clock_getresFunc<X86Linux64> },
/* 230 */ { "clock_nanosleep" },
/* 231 */ { "exit_group", exitGroupFunc },
/* 232 */ { "epoll_wait" },
/* 233 */ { "epoll_ctl" },
/* 234 */ { "tgkill", tgkillFunc<X86Linux64> },
/* 235 */ { "utimes" },
/* 236 */ { "vserver" },
/* 237 */ { "mbind" },
/* 238 */ { "set_mempolicy" },
/* 239 */ { "get_mempolicy", ignoreFunc },
/* 240 */ { "mq_open" },
/* 241 */ { "mq_unlink" },
/* 242 */ { "mq_timedsend" },
/* 243 */ { "mq_timedreceive" },
/* 244 */ { "mq_notify" },
/* 245 */ { "mq_getsetattr" },
/* 246 */ { "kexec_load" },
/* 247 */ { "waitid" },
/* 248 */ { "add_key" },
/* 249 */ { "request_key" },
/* 250 */ { "keyctl" },
/* 251 */ { "ioprio_set" },
/* 252 */ { "ioprio_get" },
/* 253 */ { "inotify_init" },
/* 254 */ { "inotify_add_watch" },
/* 255 */ { "inotify_rm_watch" },
/* 256 */ { "migrate_pages" },
/* 257 */ { "openat", openatFunc<X86Linux64> },
/* 258 */ { "mkdirat" },
/* 259 */ { "mknodat" },
/* 260 */ { "fchownat" },
/* 261 */ { "futimesat" },
/* 262 */ { "newfstatat" },
/* 263 */ { "unlinkat" },
/* 264 */ { "renameat" },
/* 265 */ { "linkat" },
/* 266 */ { "symlinkat" },
/* 267 */ { "readlinkat", readlinkFunc },
/* 268 */ { "fchmodat" },
/* 269 */ { "faccessat" },
/* 270 */ { "pselect6" },
/* 271 */ { "ppoll" },
/* 272 */ { "unshare" },
/* 273 */ { "set_robust_list", ignoreFunc },
/* 274 */ { "get_robust_list" },
/* 275 */ { "splice" },
/* 276 */ { "tee" },
/* 277 */ { "sync_file_range" },
/* 278 */ { "vmsplice" },
/* 279 */ { "move_pages" },
/* 280 */ { "utimensat" },
/* 281 */ { "epoll_pwait" },
/* 282 */ { "signalfd" },
/* 283 */ { "timerfd_create" },
/* 284 */ { "eventfd", eventfdFunc<X86Linux64> },
/* 285 */ { "fallocate", fallocateFunc },
/* 286 */ { "timerfd_settime" },
/* 287 */ { "timerfd_gettime" },
/* 288 */ { "accept4" },
/* 289 */ { "signalfd4" },
/* 290 */ { "eventfd2", eventfdFunc<X86Linux64> },
/* 291 */ { "epoll_create1" },
/* 292 */ { "dup3" },
/* 293 */ { "pipe2", pipe2Func },
/* 294 */ { "inotify_init1" },
/* 295 */ { "preadv" },
/* 296 */ { "pwritev" },
/* 297 */ { "rt_tgsigqueueinfo" },
/* 298 */ { "perf_event_open" },
/* 299 */ { "recvmmsg" },
/* 300 */ { "fanotify_init" },
/* 301 */ { "fanotify_mark" },
/* 302 */ { "prlimit64", prlimitFunc<X86Linux64> },
/* 303 */ { "name_to_handle_at" },
/* 304 */ { "open_by_handle_at" },
/* 305 */ { "clock_adjtime" },
/* 306 */ { "syncfs" },
/* 307 */ { "sendmmsg" },
/* 308 */ { "setns" },
/* 309 */ { "getcpu" },
/* 310 */ { "proess_vm_readv" },
/* 311 */ { "proess_vm_writev" },
/* 312 */ { "kcmp" },
/* 313 */ { "finit_module" },
};
X86_64LinuxProcess::X86_64LinuxProcess(ProcessParams * params,
ObjectFile *objFile)
: X86_64Process(params, objFile, syscallDescs64,
sizeof(syscallDescs64) / sizeof(SyscallDesc))
{}
void
X86_64LinuxProcess::syscall(ThreadContext *tc, Fault *fault)
{
doSyscall(tc->readIntReg(INTREG_RAX), tc, fault);
}
void
X86_64LinuxProcess::clone(ThreadContext *old_tc, ThreadContext *new_tc,
Process *process, RegVal flags)
{
X86_64Process::clone(old_tc, new_tc, (X86_64Process*)process, flags);
}
static SyscallDescABI<DefaultSyscallABI> syscallDescs32[] = {
/* 0 */ { "restart_syscall" },
/* 1 */ { "exit", exitFunc },
/* 2 */ { "fork" },
/* 3 */ { "read", readFunc<X86Linux32> },
/* 4 */ { "write", writeFunc<X86Linux32> },
/* 5 */ { "open", openFunc<X86Linux32> },
/* 6 */ { "close", closeFunc },
/* 7 */ { "waitpid" },
/* 8 */ { "creat" },
/* 9 */ { "link" },
/* 10 */ { "unlink" },
/* 11 */ { "execve", execveFunc<X86Linux32> },
/* 12 */ { "chdir", chdirFunc },
/* 13 */ { "time", timeFunc<X86Linux32> },
/* 14 */ { "mknod", mknodFunc },
/* 15 */ { "chmod" },
/* 16 */ { "lchown" },
/* 17 */ { "break" },
/* 18 */ { "oldstat" },
/* 19 */ { "lseek" },
/* 20 */ { "getpid", getpidFunc },
/* 21 */ { "mount" },
/* 22 */ { "umount" },
/* 23 */ { "setuid" },
/* 24 */ { "getuid", getuidFunc },
/* 25 */ { "stime" },
/* 26 */ { "ptrace" },
/* 27 */ { "alarm" },
/* 28 */ { "oldfstat" },
/* 29 */ { "pause" },
/* 30 */ { "utime" },
/* 31 */ { "stty" },
/* 32 */ { "gtty" },
/* 33 */ { "access", ignoreFunc },
/* 34 */ { "nice" },
/* 35 */ { "ftime" },
/* 36 */ { "sync" },
/* 37 */ { "kill" },
/* 38 */ { "rename" },
/* 39 */ { "mkdir", mkdirFunc },
/* 40 */ { "rmdir", mkdirFunc },
/* 41 */ { "dup", dupFunc },
/* 42 */ { "pipe", pipeFunc },
/* 43 */ { "times", timesFunc<X86Linux32> },
/* 44 */ { "prof" },
/* 45 */ { "brk", brkFunc },
/* 46 */ { "setgid" },
/* 47 */ { "getgid", getgidFunc },
/* 48 */ { "signal" },
/* 49 */ { "geteuid", geteuidFunc },
/* 50 */ { "getegid", getegidFunc },
/* 51 */ { "acct" },
/* 52 */ { "umount2" },
/* 53 */ { "lock" },
/* 54 */ { "ioctl", ioctlFunc<X86Linux32> },
/* 55 */ { "fcntl", fcntlFunc },
/* 56 */ { "mpx" },
/* 57 */ { "setpgid", setpgidFunc },
/* 58 */ { "ulimit" },
/* 59 */ { "oldolduname" },
/* 60 */ { "umask", umaskFunc },
/* 61 */ { "chroot" },
/* 62 */ { "ustat" },
/* 63 */ { "dup2", dup2Func },
/* 64 */ { "getppid" },
/* 65 */ { "getpgrp" },
/* 66 */ { "setsid" },
/* 67 */ { "sigaction" },
/* 68 */ { "sgetmask" },
/* 69 */ { "ssetmask" },
/* 70 */ { "setreuid" },
/* 71 */ { "setregid" },
/* 72 */ { "sigsuspend" },
/* 73 */ { "sigpending" },
/* 74 */ { "sethostname" },
/* 75 */ { "setrlimit", ignoreFunc },
/* 76 */ { "getrlimit", getrlimitFunc<X86Linux32> },
/* 77 */ { "getrusage", getrusageFunc<X86Linux32> },
/* 78 */ { "gettimeofday" },
/* 79 */ { "settimeofday" },
/* 80 */ { "getgroups" },
/* 81 */ { "setgroups" },
/* 82 */ { "select", selectFunc<X86Linux32> },
/* 83 */ { "symlink" },
/* 84 */ { "oldlstat" },
/* 85 */ { "readlink", readlinkFunc },
/* 86 */ { "uselib" },
/* 87 */ { "swapon" },
/* 88 */ { "reboot" },
/* 89 */ { "readdir" },
/* 90 */ { "mmap" },
/* 91 */ { "munmap", munmapFunc },
/* 92 */ { "truncate", truncateFunc },
/* 93 */ { "ftruncate", ftruncateFunc },
/* 94 */ { "fchmod" },
/* 95 */ { "fchown" },
/* 96 */ { "getpriority" },
/* 97 */ { "setpriority", ignoreFunc },
/* 98 */ { "profil" },
/* 99 */ { "statfs", ignoreFunc },
/* 100 */ { "fstatfs" },
/* 101 */ { "ioperm" },
/* 102 */ { "socketcall" },
/* 103 */ { "syslog" },
/* 104 */ { "setitimer" },
/* 105 */ { "getitimer" },
/* 106 */ { "stat" },
/* 107 */ { "lstat" },
/* 108 */ { "fstat" },
/* 109 */ { "olduname" },
/* 110 */ { "iopl" },
/* 111 */ { "vhangup" },
/* 112 */ { "idle" },
/* 113 */ { "vm86old" },
/* 114 */ { "wait4", wait4Func<X86Linux32> },
/* 115 */ { "swapoff" },
/* 116 */ { "sysinfo", sysinfoFunc<X86Linux32> },
/* 117 */ { "ipc" },
/* 118 */ { "fsync" },
/* 119 */ { "sigreturn" },
/* 120 */ { "clone", cloneFunc<X86Linux32> },
/* 121 */ { "setdomainname" },
/* 122 */ { "uname", unameFunc },
/* 123 */ { "modify_ldt" },
/* 124 */ { "adjtimex" },
/* 125 */ { "mprotect", ignoreFunc },
/* 126 */ { "sigprocmask" },
/* 127 */ { "create_module" },
/* 128 */ { "init_module" },
/* 129 */ { "delete_module" },
/* 130 */ { "get_kernel_syms" },
/* 131 */ { "quotactl" },
/* 132 */ { "getpgid" },
/* 133 */ { "fchdir" },
/* 134 */ { "bdflush" },
/* 135 */ { "sysfs" },
/* 136 */ { "personality" },
/* 137 */ { "afs_syscall" },
/* 138 */ { "setfsuid" },
/* 139 */ { "setfsgid" },
/* 140 */ { "_llseek", _llseekFunc },
#if defined(SYS_getdents)
/* 141 */ { "getdents", getdentsFunc },
#else
/* 141 */ { "getdents" },
#endif
/* 142 */ { "_newselect" },
/* 143 */ { "flock" },
/* 144 */ { "msync" },
/* 145 */ { "readv", readvFunc<X86Linux32> },
/* 146 */ { "writev", writevFunc<X86Linux32> },
/* 147 */ { "getsid" },
/* 148 */ { "fdatasync" },
/* 149 */ { "_sysctl" },
/* 150 */ { "mlock" },
/* 151 */ { "munlock" },
/* 152 */ { "mlockall" },
/* 153 */ { "munlockall" },
/* 154 */ { "sched_setparam" },
/* 155 */ { "sched_getparam" },
/* 156 */ { "sched_setscheduler" },
/* 157 */ { "sched_getscheduler" },
/* 158 */ { "sched_yield", ignoreFunc },
/* 159 */ { "sched_get_priority_max" },
/* 160 */ { "sched_get_priority_min" },
/* 161 */ { "sched_rr_get_interval" },
/* 162 */ { "nanosleep", ignoreFunc },
/* 163 */ { "mremap" },
/* 164 */ { "setresuid", ignoreFunc },
/* 165 */ { "getresuid" },
/* 166 */ { "vm86" },
/* 167 */ { "query_module" },
/* 168 */ { "poll", pollFunc<X86Linux32> },
/* 169 */ { "nfsservctl" },
/* 170 */ { "setresgid" },
/* 171 */ { "getresgid" },
/* 172 */ { "prctl" },
/* 173 */ { "rt_sigreturn" },
/* 174 */ { "rt_sigaction", ignoreFunc },
/* 175 */ { "rt_sigprocmask", ignoreFunc },
/* 176 */ { "rt_sigpending" },
/* 177 */ { "rt_sigtimedwait" },
/* 178 */ { "rt_sigqueueinfo" },
/* 179 */ { "rt_sigsuspend" },
/* 180 */ { "pread64" },
/* 181 */ { "pwrite64" },
/* 182 */ { "chown" },
/* 183 */ { "getcwd", getcwdFunc },
/* 184 */ { "capget" },
/* 185 */ { "capset" },
/* 186 */ { "sigaltstack" },
/* 187 */ { "sendfile" },
/* 188 */ { "getpmsg" },
/* 189 */ { "putpmsg" },
/* 190 */ { "vfork" },
/* 191 */ { "ugetrlimit", ignoreFunc },
/* 192 */ { "mmap2", mmap2Func<X86Linux32> },
/* 193 */ { "truncate64", truncate64Func },
/* 194 */ { "ftruncate64", ftruncate64Func },
/* 195 */ { "stat64", stat64Func<X86Linux32> },
/* 196 */ { "lstat64" },
/* 197 */ { "fstat64", fstat64Func<X86Linux32> },
/* 198 */ { "lchown32" },
/* 199 */ { "getuid32", getuidFunc },
/* 200 */ { "getgid32", getgidFunc },
/* 201 */ { "geteuid32", geteuidFunc },
/* 202 */ { "getegid32", getegidFunc },
/* 203 */ { "setreuid32" },
/* 204 */ { "setregid32" },
/* 205 */ { "getgroups32" },
/* 206 */ { "setgroups32" },
/* 207 */ { "fchown32" },
/* 208 */ { "setresuid32" },
/* 209 */ { "getresuid32" },
/* 210 */ { "setresgid32" },
/* 211 */ { "getresgid32" },
/* 212 */ { "chown32" },
/* 213 */ { "setuid32" },
/* 214 */ { "setgid32" },
/* 215 */ { "setfsuid32" },
/* 216 */ { "setfsgid32" },
/* 217 */ { "pivot_root" },
/* 218 */ { "mincore" },
/* 219 */ { "madvise", ignoreFunc },
/* 220 */ { "madvise1" },
/* 221 */ { "getdents64" },
/* 222 */ { "fcntl64" },
/* 223 */ { "unused" },
/* 224 */ { "gettid", gettidFunc },
/* 225 */ { "readahead" },
/* 226 */ { "setxattr" },
/* 227 */ { "lsetxattr" },
/* 228 */ { "fsetxattr" },
/* 229 */ { "getxattr" },
/* 230 */ { "lgetxattr" },
/* 231 */ { "fgetxattr" },
/* 232 */ { "listxattr" },
/* 233 */ { "llistxattr" },
/* 234 */ { "flistxattr" },
/* 235 */ { "removexattr" },
/* 236 */ { "lremovexattr" },
/* 237 */ { "fremovexattr" },
/* 238 */ { "tkill" },
/* 239 */ { "sendfile64" },
/* 240 */ { "futex" },
/* 241 */ { "sched_setaffinity" },
/* 242 */ { "sched_getaffinity", ignoreFunc },
/* 243 */ { "set_thread_area", setThreadArea32Func },
/* 244 */ { "get_thread_area" },
/* 245 */ { "io_setup" },
/* 246 */ { "io_destroy" },
/* 247 */ { "io_getevents" },
/* 248 */ { "io_submit" },
/* 249 */ { "io_cancel" },
/* 250 */ { "fadvise64" },
/* 251 */ { "unused" },
/* 252 */ { "exit_group", exitFunc },
/* 253 */ { "lookup_dcookie" },
/* 254 */ { "epoll_create" },
/* 255 */ { "epoll_ctl" },
/* 256 */ { "epoll_wait" },
/* 257 */ { "remap_file_pages" },
/* 258 */ { "set_tid_address", setTidAddressFunc },
/* 259 */ { "timer_create" },
/* 260 */ { "timer_settime" },
/* 261 */ { "timer_gettime" },
/* 262 */ { "timer_getoverrun" },
/* 263 */ { "timer_delete" },
/* 264 */ { "clock_settime" },
/* 265 */ { "clock_gettime", clock_gettimeFunc<X86Linux32> },
/* 266 */ { "clock_getres" },
/* 267 */ { "clock_nanosleep" },
/* 268 */ { "statfs64" },
/* 269 */ { "fstatfs64" },
/* 270 */ { "tgkill", tgkillFunc<X86Linux32> },
/* 271 */ { "utimes" },
/* 272 */ { "fadvise64_64" },
/* 273 */ { "vserver" },
/* 274 */ { "mbind" },
/* 275 */ { "get_mempolicy", ignoreFunc },
/* 276 */ { "set_mempolicy" },
/* 277 */ { "mq_open" },
/* 278 */ { "mq_unlink" },
/* 279 */ { "mq_timedsend" },
/* 280 */ { "mq_timedreceive" },
/* 281 */ { "mq_notify" },
/* 282 */ { "mq_getsetattr" },
/* 283 */ { "kexec_load" },
/* 284 */ { "waitid" },
/* 285 */ { "sys_setaltroot" },
/* 286 */ { "add_key" },
/* 287 */ { "request_key" },
/* 288 */ { "keyctl" },
/* 289 */ { "ioprio_set" },
/* 290 */ { "ioprio_get" },
/* 291 */ { "inotify_init" },
/* 292 */ { "inotify_add_watch" },
/* 293 */ { "inotify_rm_watch" },
/* 294 */ { "migrate_pages" },
/* 295 */ { "openat", openatFunc<X86Linux32> },
/* 296 */ { "mkdirat" },
/* 297 */ { "mknodat" },
/* 298 */ { "fchownat" },
/* 299 */ { "futimesat" },
/* 300 */ { "fstatat64" },
/* 301 */ { "unlinkat" },
/* 302 */ { "renameat" },
/* 303 */ { "linkat" },
/* 304 */ { "symlinkat" },
/* 305 */ { "readlinkat", readlinkFunc },
/* 306 */ { "fchmodat" },
/* 307 */ { "faccessat" },
/* 308 */ { "pselect6" },
/* 309 */ { "ppoll" },
/* 310 */ { "unshare" },
/* 311 */ { "set_robust_list", ignoreFunc },
/* 312 */ { "get_robust_list", ignoreFunc },
/* 313 */ { "splice" },
/* 314 */ { "sync_file_range" },
/* 315 */ { "tee" },
/* 316 */ { "vmsplice" },
/* 317 */ { "move_pages" },
/* 318 */ { "getcpu" },
/* 319 */ { "epoll_pwait" },
/* 320 */ { "utimensat" },
/* 321 */ { "signalfd" },
/* 322 */ { "timerfd" },
/* 323 */ { "eventfd", eventfdFunc<X86Linux32> }
};
I386LinuxProcess::I386LinuxProcess(ProcessParams * params, ObjectFile *objFile)
: I386Process(params, objFile, syscallDescs32,
sizeof(syscallDescs32) / sizeof(SyscallDesc))
{}
void
I386LinuxProcess::syscall(ThreadContext *tc, Fault *fault)
{
PCState pc = tc->pcState();
Addr eip = pc.pc();
if (eip >= vsyscallPage.base &&
eip < vsyscallPage.base + vsyscallPage.size) {
pc.npc(vsyscallPage.base + vsyscallPage.vsysexitOffset);
tc->pcState(pc);
}
doSyscall(tc->readIntReg(INTREG_RAX), tc, fault);
}
void
I386LinuxProcess::clone(ThreadContext *old_tc, ThreadContext *new_tc,
Process *process, RegVal flags)
{
I386Process::clone(old_tc, new_tc, (I386Process*)process, flags);
}