blob: fbfe21a935274409fe3732777d311d4cd381d1b3 [file] [log] [blame]
Steve Reinhardt79767942003-12-01 19:34:38 -08001/*
Ali Saidiad9b28f2005-03-10 14:20:12 -05002 * Copyright (c) 2003-2005 The Regents of The University of Michigan
Steve Reinhardt79767942003-12-01 19:34:38 -08003 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Ali Saidicb0cf2d2006-05-31 19:26:56 -040027 *
28 * Authors: Steve Reinhardt
29 * Ali Saidi
Steve Reinhardt79767942003-12-01 19:34:38 -080030 */
31
Brandon Potter7a8dda42016-11-09 14:27:37 -060032#include "sim/syscall_emul.hh"
33
Ali Saidi53d2c932006-02-18 23:44:22 -050034#include <fcntl.h>
Tony Gutierrez3b7f8c22018-11-30 12:19:21 -050035#include <sys/syscall.h>
Steve Reinhardt79767942003-12-01 19:34:38 -080036#include <unistd.h>
37
Brandon Potter2c128682017-03-01 14:52:23 -060038#include <csignal>
Steve Reinhardt79767942003-12-01 19:34:38 -080039#include <iostream>
Brandon Potterf2abc6b2018-04-18 14:45:37 -040040#include <mutex>
Nathan Binkert2c5fe6f2009-11-04 16:57:01 -080041#include <string>
Steve Reinhardt79767942003-12-01 19:34:38 -080042
Gabe Black0dd1f7f2010-09-14 00:29:38 -070043#include "arch/utility.hh"
Ali Saidi97e42492006-03-15 17:04:50 -050044#include "base/chunk_generator.hh"
Steve Reinhardt79767942003-12-01 19:34:38 -080045#include "base/trace.hh"
Nathan Binkertd9f39c82009-09-23 08:34:21 -070046#include "config/the_isa.hh"
Nathan Binkert39a05562011-04-15 10:44:06 -070047#include "cpu/thread_context.hh"
Michael LeBeane51f43592018-04-27 19:49:26 -040048#include "dev/net/dist_iface.hh"
Ali Saidi97e42492006-03-15 17:04:50 -050049#include "mem/page_table.hh"
Brandon Potterf2abc6b2018-04-18 14:45:37 -040050#include "sim/byteswap.hh"
Steve Reinhardt79767942003-12-01 19:34:38 -080051#include "sim/process.hh"
Steve Reinhardt29e34a72006-06-09 23:01:31 -040052#include "sim/sim_exit.hh"
Brandon Potter1ced08c2016-11-09 14:27:40 -060053#include "sim/syscall_debug_macros.hh"
54#include "sim/syscall_desc.hh"
Nathan Binkert39a05562011-04-15 10:44:06 -070055#include "sim/system.hh"
Steve Reinhardt79767942003-12-01 19:34:38 -080056
57using namespace std;
Gabe Black463aa6d2006-02-19 02:34:37 -050058using namespace TheISA;
Steve Reinhardt79767942003-12-01 19:34:38 -080059
Ali Saidi232134a2005-03-09 15:52:10 -050060SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -060061unimplementedFunc(SyscallDesc *desc, int callnum, Process *process,
Kevin Limeb0e4162006-06-06 17:32:21 -040062 ThreadContext *tc)
Steve Reinhardt79767942003-12-01 19:34:38 -080063{
Brandon Potter1ced08c2016-11-09 14:27:40 -060064 fatal("syscall %s (#%d) unimplemented.", desc->name(), callnum);
Korey Sewell8ddd5092006-03-18 10:51:28 -050065
66 return 1;
Steve Reinhardt79767942003-12-01 19:34:38 -080067}
68
69
Ali Saidi232134a2005-03-09 15:52:10 -050070SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -060071ignoreFunc(SyscallDesc *desc, int callnum, Process *process,
Kevin Limeb0e4162006-06-06 17:32:21 -040072 ThreadContext *tc)
Steve Reinhardt79767942003-12-01 19:34:38 -080073{
Brandon Potter1ced08c2016-11-09 14:27:40 -060074 if (desc->needWarning()) {
75 warn("ignoring syscall %s(...)%s", desc->name(), desc->warnOnce() ?
76 "\n (further warnings will be suppressed)" : "");
Steve Reinhardtc65fa3d2015-05-05 09:25:59 -070077 }
Steve Reinhardt79767942003-12-01 19:34:38 -080078
Chris Emmonsccaaa982011-03-17 19:20:20 -050079 return 0;
80}
81
Brandon Potter23671982017-02-27 14:10:15 -050082static void
Brandon Potter2c128682017-03-01 14:52:23 -060083exitFutexWake(ThreadContext *tc, Addr addr, uint64_t tgid)
Brandon Potter23671982017-02-27 14:10:15 -050084{
Brandon Potter2c128682017-03-01 14:52:23 -060085 // Clear value at address pointed to by thread's childClearTID field.
86 BufferArg ctidBuf(addr, sizeof(long));
87 long *ctid = (long *)ctidBuf.bufferPtr();
88 *ctid = 0;
89 ctidBuf.copyOut(tc->getMemProxy());
Brandon Potter23671982017-02-27 14:10:15 -050090
Brandon Potter2c128682017-03-01 14:52:23 -060091 FutexMap &futex_map = tc->getSystemPtr()->futexMap;
92 // Wake one of the waiting threads.
93 futex_map.wakeup(addr, tgid, 1);
94}
95
96static SyscallReturn
97exitImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc,
98 bool group)
99{
100 int index = 0;
101 int status = p->getSyscallArg(tc, index);
102
103 System *sys = tc->getSystemPtr();
104
Brandon Potter2c128682017-03-01 14:52:23 -0600105 if (group)
106 *p->exitGroup = true;
107
108 if (p->childClearTID)
109 exitFutexWake(tc, p->childClearTID, p->tgid());
110
111 bool last_thread = true;
112 Process *parent = nullptr, *tg_lead = nullptr;
113 for (int i = 0; last_thread && i < sys->numContexts(); i++) {
114 Process *walk;
115 if (!(walk = sys->threadContexts[i]->getProcessPtr()))
116 continue;
117
118 /**
119 * Threads in a thread group require special handing. For instance,
120 * we send the SIGCHLD signal so that it appears that it came from
121 * the head of the group. We also only delete file descriptors if
122 * we are the last thread in the thread group.
123 */
124 if (walk->pid() == p->tgid())
125 tg_lead = walk;
126
Tuan Tabae0edb2018-04-02 16:21:37 -0400127 if ((sys->threadContexts[i]->status() != ThreadContext::Halted) &&
128 (sys->threadContexts[i]->status() != ThreadContext::Halting) &&
129 (walk != p)) {
Brandon Potter2c128682017-03-01 14:52:23 -0600130 /**
131 * Check if we share thread group with the pointer; this denotes
132 * that we are not the last thread active in the thread group.
133 * Note that setting this to false also prevents further
134 * iterations of the loop.
135 */
Tuan Tabae0edb2018-04-02 16:21:37 -0400136 if (walk->tgid() == p->tgid()) {
137 /**
138 * If p is trying to exit_group and both walk and p are in
139 * the same thread group (i.e., sharing the same tgid),
140 * we need to halt walk's thread context. After all threads
141 * except p are halted, p becomes the last thread in the
142 * group.
143 *
144 * If p is not doing exit_group and there exists another
145 * active thread context in the group, last_thread is
146 * set to false to prevent the parent thread from killing
147 * all threads in the group.
148 */
149 if (*(p->exitGroup)) {
150 sys->threadContexts[i]->halt();
151 } else {
152 last_thread = false;
153 }
154 }
Brandon Potter2c128682017-03-01 14:52:23 -0600155
156 /**
157 * A corner case exists which involves execve(). After execve(),
158 * the execve will enable SIGCHLD in the process. The problem
159 * occurs when the exiting process is the root process in the
160 * system; there is no parent to receive the signal. We obviate
161 * this problem by setting the root process' ppid to zero in the
162 * Python configuration files. We really should handle the
163 * root/execve specific case more gracefully.
164 */
165 if (*p->sigchld && (p->ppid() != 0) && (walk->pid() == p->ppid()))
166 parent = walk;
Brandon Potter23671982017-02-27 14:10:15 -0500167 }
168 }
Brandon Potter2c128682017-03-01 14:52:23 -0600169
170 if (last_thread) {
171 if (parent) {
172 assert(tg_lead);
173 sys->signalList.push_back(BasicSignal(tg_lead, parent, SIGCHLD));
174 }
175
176 /**
177 * Run though FD array of the exiting process and close all file
178 * descriptors except for the standard file descriptors.
179 * (The standard file descriptors are shared with gem5.)
180 */
181 for (int i = 0; i < p->fds->getSize(); i++) {
182 if ((*p->fds)[i])
183 p->fds->closeFDEntry(i);
184 }
185 }
186
187 tc->halt();
Tuan Tabae0edb2018-04-02 16:21:37 -0400188
189 /**
190 * check to see if there is no more active thread in the system. If so,
191 * exit the simulation loop
192 */
193 int activeContexts = 0;
194 for (auto &system: sys->systemList)
195 activeContexts += system->numRunningContexts();
196
197 if (activeContexts == 0) {
198 /**
199 * Even though we are terminating the final thread context, dist-gem5
200 * requires the simulation to remain active and provide
201 * synchronization messages to the switch process. So we just halt
202 * the last thread context and return. The simulation will be
203 * terminated by dist-gem5 in a coordinated manner once all nodes
204 * have signaled their readiness to exit. For non dist-gem5
205 * simulations, readyToExit() always returns true.
206 */
207 if (!DistIface::readyToExit(0)) {
208 return status;
209 }
210
211 exitSimLoop("exiting with last active thread context", status & 0xff);
212 return status;
213 }
214
Brandon Potter2c128682017-03-01 14:52:23 -0600215 return status;
Brandon Potter23671982017-02-27 14:10:15 -0500216}
Chris Emmonsccaaa982011-03-17 19:20:20 -0500217
218SyscallReturn
Brandon Potter23671982017-02-27 14:10:15 -0500219exitFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
Steve Reinhardt79767942003-12-01 19:34:38 -0800220{
Brandon Potter2c128682017-03-01 14:52:23 -0600221 return exitImpl(desc, callnum, p, tc, false);
Steve Reinhardt79767942003-12-01 19:34:38 -0800222}
223
Ali Saidi232134a2005-03-09 15:52:10 -0500224SyscallReturn
Brandon Potter2c128682017-03-01 14:52:23 -0600225exitGroupFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
Daniel Sanchezb0e96542009-04-21 08:17:36 -0700226{
Brandon Potter2c128682017-03-01 14:52:23 -0600227 return exitImpl(desc, callnum, p, tc, true);
Daniel Sanchezb0e96542009-04-21 08:17:36 -0700228}
229
Daniel Sanchezb0e96542009-04-21 08:17:36 -0700230SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600231getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Steve Reinhardt79767942003-12-01 19:34:38 -0800232{
Andreas Hanssone1ac9622014-09-03 07:42:21 -0400233 return (int)PageBytes;
Steve Reinhardt79767942003-12-01 19:34:38 -0800234}
235
236
Ali Saidi232134a2005-03-09 15:52:10 -0500237SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600238brkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Steve Reinhardt79767942003-12-01 19:34:38 -0800239{
240 // change brk addr to first arg
Gabe Black3f722b92009-10-30 00:44:55 -0700241 int index = 0;
242 Addr new_brk = p->getSyscallArg(tc, index);
Steve Reinhardt4514f562008-11-15 09:30:10 -0800243
Brandon Potter43418e72017-03-01 13:07:43 -0600244 std::shared_ptr<MemState> mem_state = p->memState;
245 Addr brk_point = mem_state->getBrkPoint();
246
Steve Reinhardt4514f562008-11-15 09:30:10 -0800247 // in Linux at least, brk(0) returns the current break value
248 // (note that the syscall and the glibc function have different behavior)
249 if (new_brk == 0)
Brandon Potter43418e72017-03-01 13:07:43 -0600250 return brk_point;
Steve Reinhardt4514f562008-11-15 09:30:10 -0800251
Brandon Potter43418e72017-03-01 13:07:43 -0600252 if (new_brk > brk_point) {
Steve Reinhardt4514f562008-11-15 09:30:10 -0800253 // might need to allocate some new pages
Brandon Potter43418e72017-03-01 13:07:43 -0600254 for (ChunkGenerator gen(brk_point,
255 new_brk - brk_point,
Andreas Hanssone1ac9622014-09-03 07:42:21 -0400256 PageBytes); !gen.done(); gen.next()) {
Steve Reinhardt4514f562008-11-15 09:30:10 -0800257 if (!p->pTable->translate(gen.addr()))
Andreas Hanssone1ac9622014-09-03 07:42:21 -0400258 p->allocateMem(roundDown(gen.addr(), PageBytes), PageBytes);
Timothy M. Jones03da1e52009-10-24 10:53:58 -0700259
260 // if the address is already there, zero it out
261 else {
Brandon Potter43418e72017-03-01 13:07:43 -0600262 uint8_t zero = 0;
Andreas Hansson9e3c8de2012-02-24 11:45:30 -0500263 SETranslatingPortProxy &tp = tc->getMemProxy();
Timothy M. Jones03da1e52009-10-24 10:53:58 -0700264
265 // split non-page aligned accesses
Andreas Hanssone1ac9622014-09-03 07:42:21 -0400266 Addr next_page = roundUp(gen.addr(), PageBytes);
Timothy M. Jones03da1e52009-10-24 10:53:58 -0700267 uint32_t size_needed = next_page - gen.addr();
Andreas Hansson9e3c8de2012-02-24 11:45:30 -0500268 tp.memsetBlob(gen.addr(), zero, size_needed);
Andreas Hanssone1ac9622014-09-03 07:42:21 -0400269 if (gen.addr() + PageBytes > next_page &&
Timothy M. Jones03da1e52009-10-24 10:53:58 -0700270 next_page < new_brk &&
Brandon Pottere5fe2b82017-03-01 13:18:49 -0600271 p->pTable->translate(next_page)) {
Andreas Hanssone1ac9622014-09-03 07:42:21 -0400272 size_needed = PageBytes - size_needed;
Andreas Hansson9e3c8de2012-02-24 11:45:30 -0500273 tp.memsetBlob(next_page, zero, size_needed);
Timothy M. Jones03da1e52009-10-24 10:53:58 -0700274 }
275 }
Ali Saidi97e42492006-03-15 17:04:50 -0500276 }
Ali Saidi232134a2005-03-09 15:52:10 -0500277 }
Steve Reinhardt4514f562008-11-15 09:30:10 -0800278
Brandon Potter43418e72017-03-01 13:07:43 -0600279 mem_state->setBrkPoint(new_brk);
Alexandru Dutu75d69102016-03-17 10:22:39 -0700280 DPRINTF_SYSCALL(Verbose, "brk: break point changed to: %#X\n",
Brandon Potter43418e72017-03-01 13:07:43 -0600281 mem_state->getBrkPoint());
282 return mem_state->getBrkPoint();
Steve Reinhardt79767942003-12-01 19:34:38 -0800283}
284
Brandon Potter23671982017-02-27 14:10:15 -0500285SyscallReturn
286setTidAddressFunc(SyscallDesc *desc, int callnum, Process *process,
287 ThreadContext *tc)
288{
289 int index = 0;
290 uint64_t tidPtr = process->getSyscallArg(tc, index);
291
292 process->childClearTID = tidPtr;
293 return process->pid();
294}
Steve Reinhardt79767942003-12-01 19:34:38 -0800295
Ali Saidi232134a2005-03-09 15:52:10 -0500296SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600297closeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Steve Reinhardt79767942003-12-01 19:34:38 -0800298{
Gabe Black3f722b92009-10-30 00:44:55 -0700299 int index = 0;
Brandon Potterd5a7f092015-07-24 12:25:23 -0700300 int tgt_fd = p->getSyscallArg(tc, index);
301
Brandon Potterd3d983c2016-11-09 14:27:42 -0600302 return p->fds->closeFDEntry(tgt_fd);
Steve Reinhardt79767942003-12-01 19:34:38 -0800303}
304
Ali Saidi232134a2005-03-09 15:52:10 -0500305SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600306lseekFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Steve Reinhardt79767942003-12-01 19:34:38 -0800307{
Gabe Black3f722b92009-10-30 00:44:55 -0700308 int index = 0;
Brandon Potterd5a7f092015-07-24 12:25:23 -0700309 int tgt_fd = p->getSyscallArg(tc, index);
Gabe Black3f722b92009-10-30 00:44:55 -0700310 uint64_t offs = p->getSyscallArg(tc, index);
311 int whence = p->getSyscallArg(tc, index);
Steve Reinhardt79767942003-12-01 19:34:38 -0800312
Brandon Potterd3d983c2016-11-09 14:27:42 -0600313 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
314 if (!ffdp)
Brandon Potterd5a7f092015-07-24 12:25:23 -0700315 return -EBADF;
Brandon Potterd3d983c2016-11-09 14:27:42 -0600316 int sim_fd = ffdp->getSimFD();
Brandon Potterd5a7f092015-07-24 12:25:23 -0700317
318 off_t result = lseek(sim_fd, offs, whence);
Steve Reinhardt79767942003-12-01 19:34:38 -0800319
Ali Saidiad9b28f2005-03-10 14:20:12 -0500320 return (result == (off_t)-1) ? -errno : result;
Steve Reinhardt79767942003-12-01 19:34:38 -0800321}
322
323
Ali Saidi232134a2005-03-09 15:52:10 -0500324SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600325_llseekFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Gabe Black23dc5092007-03-03 03:34:55 +0000326{
Gabe Black3f722b92009-10-30 00:44:55 -0700327 int index = 0;
Brandon Potterd5a7f092015-07-24 12:25:23 -0700328 int tgt_fd = p->getSyscallArg(tc, index);
Gabe Black3f722b92009-10-30 00:44:55 -0700329 uint64_t offset_high = p->getSyscallArg(tc, index);
330 uint32_t offset_low = p->getSyscallArg(tc, index);
331 Addr result_ptr = p->getSyscallArg(tc, index);
332 int whence = p->getSyscallArg(tc, index);
Gabe Black23dc5092007-03-03 03:34:55 +0000333
Brandon Potterd3d983c2016-11-09 14:27:42 -0600334 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
335 if (!ffdp)
Brandon Potterd5a7f092015-07-24 12:25:23 -0700336 return -EBADF;
Brandon Potterd3d983c2016-11-09 14:27:42 -0600337 int sim_fd = ffdp->getSimFD();
Brandon Potterd5a7f092015-07-24 12:25:23 -0700338
Gabe Black23dc5092007-03-03 03:34:55 +0000339 uint64_t offset = (offset_high << 32) | offset_low;
340
Brandon Potterd5a7f092015-07-24 12:25:23 -0700341 uint64_t result = lseek(sim_fd, offset, whence);
Gabe Black23dc5092007-03-03 03:34:55 +0000342 result = TheISA::htog(result);
343
Brandon Potterc05fa162016-03-17 10:22:39 -0700344 if (result == (off_t)-1)
Gabe Black23dc5092007-03-03 03:34:55 +0000345 return -errno;
Brandon Potterc05fa162016-03-17 10:22:39 -0700346 // Assuming that the size of loff_t is 64 bits on the target platform
347 BufferArg result_buf(result_ptr, sizeof(result));
348 memcpy(result_buf.bufferPtr(), &result, sizeof(result));
349 result_buf.copyOut(tc->getMemProxy());
350 return 0;
Gabe Black23dc5092007-03-03 03:34:55 +0000351}
352
353
354SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600355munmapFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Steve Reinhardt79767942003-12-01 19:34:38 -0800356{
Brandon Pottera04fac92016-03-17 10:24:17 -0700357 // With mmap more fully implemented, it might be worthwhile to bite
358 // the bullet and implement munmap. Should allow us to reuse simulated
359 // memory.
Ali Saidiad9b28f2005-03-10 14:20:12 -0500360 return 0;
Steve Reinhardt79767942003-12-01 19:34:38 -0800361}
362
363
364const char *hostname = "m5.eecs.umich.edu";
365
Ali Saidi232134a2005-03-09 15:52:10 -0500366SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600367gethostnameFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Steve Reinhardt79767942003-12-01 19:34:38 -0800368{
Gabe Black3f722b92009-10-30 00:44:55 -0700369 int index = 0;
Brandon Pottere5fe2b82017-03-01 13:18:49 -0600370 Addr buf_ptr = p->getSyscallArg(tc, index);
Gabe Black3f722b92009-10-30 00:44:55 -0700371 int name_len = p->getSyscallArg(tc, index);
Brandon Pottere5fe2b82017-03-01 13:18:49 -0600372 BufferArg name(buf_ptr, name_len);
Steve Reinhardt79767942003-12-01 19:34:38 -0800373
374 strncpy((char *)name.bufferPtr(), hostname, name_len);
375
Andreas Hanssonf85286b2012-01-17 12:55:08 -0600376 name.copyOut(tc->getMemProxy());
Steve Reinhardt79767942003-12-01 19:34:38 -0800377
Ali Saidiad9b28f2005-03-10 14:20:12 -0500378 return 0;
Steve Reinhardt79767942003-12-01 19:34:38 -0800379}
380
Ali Saidi232134a2005-03-09 15:52:10 -0500381SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600382getcwdFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Michael Adler2cd04fd2008-07-23 14:41:33 -0700383{
384 int result = 0;
Vince Weaver7da221c2009-11-09 10:02:55 -0500385 int index = 0;
Brandon Pottere5fe2b82017-03-01 13:18:49 -0600386 Addr buf_ptr = p->getSyscallArg(tc, index);
Gabe Black3f722b92009-10-30 00:44:55 -0700387 unsigned long size = p->getSyscallArg(tc, index);
Brandon Pottere5fe2b82017-03-01 13:18:49 -0600388 BufferArg buf(buf_ptr, size);
Michael Adler2cd04fd2008-07-23 14:41:33 -0700389
390 // Is current working directory defined?
391 string cwd = p->getcwd();
392 if (!cwd.empty()) {
393 if (cwd.length() >= size) {
394 // Buffer too small
395 return -ERANGE;
396 }
397 strncpy((char *)buf.bufferPtr(), cwd.c_str(), size);
398 result = cwd.length();
David Hashed0f6aad2015-07-20 09:15:18 -0500399 } else {
Brandon Potterd3d983c2016-11-09 14:27:42 -0600400 if (getcwd((char *)buf.bufferPtr(), size)) {
Michael Adler2cd04fd2008-07-23 14:41:33 -0700401 result = strlen((char *)buf.bufferPtr());
David Hashed0f6aad2015-07-20 09:15:18 -0500402 } else {
Michael Adler2cd04fd2008-07-23 14:41:33 -0700403 result = -1;
404 }
405 }
406
Andreas Hanssonf85286b2012-01-17 12:55:08 -0600407 buf.copyOut(tc->getMemProxy());
Michael Adler2cd04fd2008-07-23 14:41:33 -0700408
409 return (result == -1) ? -errno : result;
410}
411
Ali Saidic4a2f762014-04-17 16:55:05 -0500412SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600413readlinkFunc(SyscallDesc *desc, int callnum, Process *process,
414 ThreadContext *tc)
Ali Saidic4a2f762014-04-17 16:55:05 -0500415{
416 return readlinkFunc(desc, callnum, process, tc, 0);
417}
Michael Adler2cd04fd2008-07-23 14:41:33 -0700418
419SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600420readlinkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc,
421 int index)
Michael Adler2cd04fd2008-07-23 14:41:33 -0700422{
423 string path;
424
Andreas Hansson9e3c8de2012-02-24 11:45:30 -0500425 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
Steve Reinhardt109908c2014-05-12 14:23:31 -0700426 return -EFAULT;
Michael Adler2cd04fd2008-07-23 14:41:33 -0700427
428 // Adjust path for current working directory
429 path = p->fullPath(path);
430
Brandon Pottere5fe2b82017-03-01 13:18:49 -0600431 Addr buf_ptr = p->getSyscallArg(tc, index);
Gabe Black3f722b92009-10-30 00:44:55 -0700432 size_t bufsiz = p->getSyscallArg(tc, index);
433
Brandon Pottere5fe2b82017-03-01 13:18:49 -0600434 BufferArg buf(buf_ptr, bufsiz);
Michael Adler2cd04fd2008-07-23 14:41:33 -0700435
David Hashed0f6aad2015-07-20 09:15:18 -0500436 int result = -1;
437 if (path != "/proc/self/exe") {
438 result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz);
439 } else {
Joel Hestness395b31f2015-09-29 09:25:20 -0500440 // Emulate readlink() called on '/proc/self/exe' should return the
441 // absolute path of the binary running in the simulated system (the
Brandon Potter3886c4a2016-11-09 14:27:40 -0600442 // Process' executable). It is possible that using this path in
Joel Hestness395b31f2015-09-29 09:25:20 -0500443 // the simulated system will result in unexpected behavior if:
444 // 1) One binary runs another (e.g., -c time -o "my_binary"), and
445 // called binary calls readlink().
446 // 2) The host's full path to the running benchmark changes from one
447 // simulation to another. This can result in different simulated
448 // performance since the simulated system will process the binary
449 // path differently, even if the binary itself does not change.
450
451 // Get the absolute canonical path to the running application
452 char real_path[PATH_MAX];
453 char *check_real_path = realpath(p->progName(), real_path);
454 if (!check_real_path) {
455 fatal("readlink('/proc/self/exe') unable to resolve path to "
456 "executable: %s", p->progName());
457 }
458 strncpy((char*)buf.bufferPtr(), real_path, bufsiz);
459 size_t real_path_len = strlen(real_path);
460 if (real_path_len > bufsiz) {
David Hashed0f6aad2015-07-20 09:15:18 -0500461 // readlink will truncate the contents of the
462 // path to ensure it is no more than bufsiz
David Hashed0f6aad2015-07-20 09:15:18 -0500463 result = bufsiz;
464 } else {
Joel Hestness395b31f2015-09-29 09:25:20 -0500465 result = real_path_len;
David Hashed0f6aad2015-07-20 09:15:18 -0500466 }
Joel Hestness395b31f2015-09-29 09:25:20 -0500467
468 // Issue a warning about potential unexpected results
469 warn_once("readlink() called on '/proc/self/exe' may yield unexpected "
470 "results in various settings.\n Returning '%s'\n",
471 (char*)buf.bufferPtr());
David Hashed0f6aad2015-07-20 09:15:18 -0500472 }
Michael Adler2cd04fd2008-07-23 14:41:33 -0700473
Andreas Hanssonf85286b2012-01-17 12:55:08 -0600474 buf.copyOut(tc->getMemProxy());
Michael Adler2cd04fd2008-07-23 14:41:33 -0700475
476 return (result == -1) ? -errno : result;
477}
478
479SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600480unlinkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
David Oehmke95c248c2004-02-05 12:16:17 -0500481{
mike uptoncb911552015-01-03 17:51:48 -0600482 return unlinkHelper(desc, num, p, tc, 0);
483}
484
485SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600486unlinkHelper(SyscallDesc *desc, int num, Process *p, ThreadContext *tc,
487 int index)
mike uptoncb911552015-01-03 17:51:48 -0600488{
Steve Reinhardt22eccce2005-06-03 16:19:34 -0400489 string path;
David Oehmke95c248c2004-02-05 12:16:17 -0500490
Andreas Hansson9e3c8de2012-02-24 11:45:30 -0500491 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
Steve Reinhardt109908c2014-05-12 14:23:31 -0700492 return -EFAULT;
David Oehmke95c248c2004-02-05 12:16:17 -0500493
Nathan Binkert31d829d2006-11-16 12:43:11 -0800494 path = p->fullPath(path);
495
David Oehmke95c248c2004-02-05 12:16:17 -0500496 int result = unlink(path.c_str());
Ali Saidiad9b28f2005-03-10 14:20:12 -0500497 return (result == -1) ? -errno : result;
David Oehmke95c248c2004-02-05 12:16:17 -0500498}
499
Matt Sinclair3fb16fa2018-06-21 14:17:17 -0400500SyscallReturn
501linkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
502{
503 string path;
504 string new_path;
505
506 int index = 0;
507 auto &virt_mem = tc->getMemProxy();
508 if (!virt_mem.tryReadString(path, p->getSyscallArg(tc, index)))
509 return -EFAULT;
510 if (!virt_mem.tryReadString(new_path, p->getSyscallArg(tc, index)))
511 return -EFAULT;
512
513 path = p->fullPath(path);
514 new_path = p->fullPath(new_path);
515
516 int result = link(path.c_str(), new_path.c_str());
517 return (result == -1) ? -errno : result;
518}
Michael Adler2cd04fd2008-07-23 14:41:33 -0700519
520SyscallReturn
Matt Sinclair1678a082018-06-21 19:31:09 -0400521symlinkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
522{
523 string path;
524 string new_path;
525
526 int index = 0;
527 auto &virt_mem = tc->getMemProxy();
528 if (!virt_mem.tryReadString(path, p->getSyscallArg(tc, index)))
529 return -EFAULT;
530 if (!virt_mem.tryReadString(new_path, p->getSyscallArg(tc, index)))
531 return -EFAULT;
532
533 path = p->fullPath(path);
534 new_path = p->fullPath(new_path);
535
536 int result = symlink(path.c_str(), new_path.c_str());
537 return (result == -1) ? -errno : result;
538}
539
540SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600541mkdirFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Michael Adler2cd04fd2008-07-23 14:41:33 -0700542{
543 string path;
544
Gabe Black3f722b92009-10-30 00:44:55 -0700545 int index = 0;
Andreas Hansson9e3c8de2012-02-24 11:45:30 -0500546 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
Steve Reinhardt109908c2014-05-12 14:23:31 -0700547 return -EFAULT;
Michael Adler2cd04fd2008-07-23 14:41:33 -0700548
549 // Adjust path for current working directory
550 path = p->fullPath(path);
551
Gabe Black3f722b92009-10-30 00:44:55 -0700552 mode_t mode = p->getSyscallArg(tc, index);
Michael Adler2cd04fd2008-07-23 14:41:33 -0700553
554 int result = mkdir(path.c_str(), mode);
555 return (result == -1) ? -errno : result;
556}
557
Ali Saidi232134a2005-03-09 15:52:10 -0500558SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600559renameFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
David Oehmke95c248c2004-02-05 12:16:17 -0500560{
Steve Reinhardt22eccce2005-06-03 16:19:34 -0400561 string old_name;
David Oehmke95c248c2004-02-05 12:16:17 -0500562
Gabe Black3f722b92009-10-30 00:44:55 -0700563 int index = 0;
Andreas Hansson9e3c8de2012-02-24 11:45:30 -0500564 if (!tc->getMemProxy().tryReadString(old_name, p->getSyscallArg(tc, index)))
Ali Saidiad9b28f2005-03-10 14:20:12 -0500565 return -EFAULT;
David Oehmke95c248c2004-02-05 12:16:17 -0500566
Steve Reinhardt22eccce2005-06-03 16:19:34 -0400567 string new_name;
David Oehmke95c248c2004-02-05 12:16:17 -0500568
Andreas Hansson9e3c8de2012-02-24 11:45:30 -0500569 if (!tc->getMemProxy().tryReadString(new_name, p->getSyscallArg(tc, index)))
Ali Saidiad9b28f2005-03-10 14:20:12 -0500570 return -EFAULT;
David Oehmke95c248c2004-02-05 12:16:17 -0500571
Nathan Binkert31d829d2006-11-16 12:43:11 -0800572 // Adjust path for current working directory
573 old_name = p->fullPath(old_name);
574 new_name = p->fullPath(new_name);
575
Steve Reinhardt22eccce2005-06-03 16:19:34 -0400576 int64_t result = rename(old_name.c_str(), new_name.c_str());
Ali Saidiad9b28f2005-03-10 14:20:12 -0500577 return (result == -1) ? -errno : result;
David Oehmke95c248c2004-02-05 12:16:17 -0500578}
Steve Reinhardt79767942003-12-01 19:34:38 -0800579
Steve Reinhardt22eccce2005-06-03 16:19:34 -0400580SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600581truncateFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Steve Reinhardt22eccce2005-06-03 16:19:34 -0400582{
583 string path;
584
Gabe Black3f722b92009-10-30 00:44:55 -0700585 int index = 0;
Andreas Hansson9e3c8de2012-02-24 11:45:30 -0500586 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
Steve Reinhardt22eccce2005-06-03 16:19:34 -0400587 return -EFAULT;
588
Gabe Black3f722b92009-10-30 00:44:55 -0700589 off_t length = p->getSyscallArg(tc, index);
Steve Reinhardt22eccce2005-06-03 16:19:34 -0400590
Nathan Binkert31d829d2006-11-16 12:43:11 -0800591 // Adjust path for current working directory
592 path = p->fullPath(path);
593
Steve Reinhardt22eccce2005-06-03 16:19:34 -0400594 int result = truncate(path.c_str(), length);
595 return (result == -1) ? -errno : result;
596}
597
598SyscallReturn
Brandon Potterd3d983c2016-11-09 14:27:42 -0600599ftruncateFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Steve Reinhardt22eccce2005-06-03 16:19:34 -0400600{
Gabe Black3f722b92009-10-30 00:44:55 -0700601 int index = 0;
Brandon Potterd3d983c2016-11-09 14:27:42 -0600602 int tgt_fd = p->getSyscallArg(tc, index);
603 off_t length = p->getSyscallArg(tc, index);
Steve Reinhardt22eccce2005-06-03 16:19:34 -0400604
Brandon Potterd3d983c2016-11-09 14:27:42 -0600605 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
606 if (!ffdp)
Brandon Potterd5a7f092015-07-24 12:25:23 -0700607 return -EBADF;
Brandon Potterd3d983c2016-11-09 14:27:42 -0600608 int sim_fd = ffdp->getSimFD();
Brandon Potterd5a7f092015-07-24 12:25:23 -0700609
610 int result = ftruncate(sim_fd, length);
Steve Reinhardt22eccce2005-06-03 16:19:34 -0400611 return (result == -1) ? -errno : result;
612}
Kevin Lim6da93ea2005-11-22 12:08:08 -0500613
614SyscallReturn
Vince Weaver9ad3aca2009-10-30 12:31:55 -0400615truncate64Func(SyscallDesc *desc, int num,
Brandon Potter3886c4a2016-11-09 14:27:40 -0600616 Process *process, ThreadContext *tc)
Vince Weaver9ad3aca2009-10-30 12:31:55 -0400617{
618 int index = 0;
619 string path;
620
Andreas Hansson9e3c8de2012-02-24 11:45:30 -0500621 if (!tc->getMemProxy().tryReadString(path, process->getSyscallArg(tc, index)))
Brandon Pottere5fe2b82017-03-01 13:18:49 -0600622 return -EFAULT;
Vince Weaver9ad3aca2009-10-30 12:31:55 -0400623
Ali Saidi4e9ce182009-11-14 11:49:01 -0600624 int64_t length = process->getSyscallArg(tc, index, 64);
Vince Weaver9ad3aca2009-10-30 12:31:55 -0400625
626 // Adjust path for current working directory
627 path = process->fullPath(path);
628
Ali Saidi4e9ce182009-11-14 11:49:01 -0600629#if NO_STAT64
630 int result = truncate(path.c_str(), length);
631#else
Vince Weaver9ad3aca2009-10-30 12:31:55 -0400632 int result = truncate64(path.c_str(), length);
Ali Saidi4e9ce182009-11-14 11:49:01 -0600633#endif
Vince Weaver9ad3aca2009-10-30 12:31:55 -0400634 return (result == -1) ? -errno : result;
635}
636
637SyscallReturn
Brandon Potterd3d983c2016-11-09 14:27:42 -0600638ftruncate64Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Timothy M. Jonesc32d9192009-10-24 10:53:58 -0700639{
Gabe Black3f722b92009-10-30 00:44:55 -0700640 int index = 0;
Brandon Potterd3d983c2016-11-09 14:27:42 -0600641 int tgt_fd = p->getSyscallArg(tc, index);
642 int64_t length = p->getSyscallArg(tc, index, 64);
Timothy M. Jonesc32d9192009-10-24 10:53:58 -0700643
Brandon Potterd3d983c2016-11-09 14:27:42 -0600644 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
645 if (!ffdp)
Brandon Potterd5a7f092015-07-24 12:25:23 -0700646 return -EBADF;
Brandon Potterd3d983c2016-11-09 14:27:42 -0600647 int sim_fd = ffdp->getSimFD();
Brandon Potterd5a7f092015-07-24 12:25:23 -0700648
Ali Saidi4e9ce182009-11-14 11:49:01 -0600649#if NO_STAT64
Brandon Potterd5a7f092015-07-24 12:25:23 -0700650 int result = ftruncate(sim_fd, length);
Ali Saidi4e9ce182009-11-14 11:49:01 -0600651#else
Brandon Potterd5a7f092015-07-24 12:25:23 -0700652 int result = ftruncate64(sim_fd, length);
Ali Saidi4e9ce182009-11-14 11:49:01 -0600653#endif
Timothy M. Jonesc32d9192009-10-24 10:53:58 -0700654 return (result == -1) ? -errno : result;
655}
656
657SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600658umaskFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc)
Michael Adler2cd04fd2008-07-23 14:41:33 -0700659{
660 // Letting the simulated program change the simulator's umask seems like
661 // a bad idea. Compromise by just returning the current umask but not
662 // changing anything.
663 mode_t oldMask = umask(0);
664 umask(oldMask);
Nathan Binkert678abbc2008-08-03 18:19:53 -0700665 return (int)oldMask;
Michael Adler2cd04fd2008-07-23 14:41:33 -0700666}
667
668SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600669chownFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Kevin Lim6da93ea2005-11-22 12:08:08 -0500670{
671 string path;
672
Gabe Black3f722b92009-10-30 00:44:55 -0700673 int index = 0;
Andreas Hansson9e3c8de2012-02-24 11:45:30 -0500674 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
Kevin Lim6da93ea2005-11-22 12:08:08 -0500675 return -EFAULT;
676
677 /* XXX endianess */
Gabe Black3f722b92009-10-30 00:44:55 -0700678 uint32_t owner = p->getSyscallArg(tc, index);
Kevin Lim6da93ea2005-11-22 12:08:08 -0500679 uid_t hostOwner = owner;
Gabe Black3f722b92009-10-30 00:44:55 -0700680 uint32_t group = p->getSyscallArg(tc, index);
Kevin Lim6da93ea2005-11-22 12:08:08 -0500681 gid_t hostGroup = group;
682
Nathan Binkert31d829d2006-11-16 12:43:11 -0800683 // Adjust path for current working directory
684 path = p->fullPath(path);
685
Kevin Lim6da93ea2005-11-22 12:08:08 -0500686 int result = chown(path.c_str(), hostOwner, hostGroup);
687 return (result == -1) ? -errno : result;
688}
689
690SyscallReturn
Brandon Potterd3d983c2016-11-09 14:27:42 -0600691fchownFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Kevin Lim6da93ea2005-11-22 12:08:08 -0500692{
Gabe Black3f722b92009-10-30 00:44:55 -0700693 int index = 0;
Brandon Potterd3d983c2016-11-09 14:27:42 -0600694 int tgt_fd = p->getSyscallArg(tc, index);
Kevin Lim6da93ea2005-11-22 12:08:08 -0500695
Brandon Potterd3d983c2016-11-09 14:27:42 -0600696 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
697 if (!ffdp)
Kevin Lim6da93ea2005-11-22 12:08:08 -0500698 return -EBADF;
Brandon Potterd3d983c2016-11-09 14:27:42 -0600699 int sim_fd = ffdp->getSimFD();
Kevin Lim6da93ea2005-11-22 12:08:08 -0500700
701 /* XXX endianess */
Brandon Potterd3d983c2016-11-09 14:27:42 -0600702 uint32_t owner = p->getSyscallArg(tc, index);
Kevin Lim6da93ea2005-11-22 12:08:08 -0500703 uid_t hostOwner = owner;
Brandon Potterd3d983c2016-11-09 14:27:42 -0600704 uint32_t group = p->getSyscallArg(tc, index);
Kevin Lim6da93ea2005-11-22 12:08:08 -0500705 gid_t hostGroup = group;
706
Brandon Potterd5a7f092015-07-24 12:25:23 -0700707 int result = fchown(sim_fd, hostOwner, hostGroup);
Kevin Lim6da93ea2005-11-22 12:08:08 -0500708 return (result == -1) ? -errno : result;
709}
Ali Saidi53d2c932006-02-18 23:44:22 -0500710
Brandon Potterd3d983c2016-11-09 14:27:42 -0600711/**
Brandon Potter198c5152017-03-01 13:35:02 -0600712 * FIXME: The file description is not shared among file descriptors created
713 * with dup. Really, it's difficult to maintain fields like file offset or
714 * flags since an update to such a field won't be reflected in the metadata
715 * for the fd entries that we maintain for checkpoint restoration.
Brandon Potterd3d983c2016-11-09 14:27:42 -0600716 */
Ali Saidi53d2c932006-02-18 23:44:22 -0500717SyscallReturn
Brandon Potterd3d983c2016-11-09 14:27:42 -0600718dupFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Steve Reinhardtc5384362006-08-28 07:39:56 -0700719{
Gabe Black3f722b92009-10-30 00:44:55 -0700720 int index = 0;
Brandon Potterd3d983c2016-11-09 14:27:42 -0600721 int tgt_fd = p->getSyscallArg(tc, index);
Brandon Potterd5a7f092015-07-24 12:25:23 -0700722
Brandon Potterd3d983c2016-11-09 14:27:42 -0600723 auto old_hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
724 if (!old_hbfdp)
Steve Reinhardtc5384362006-08-28 07:39:56 -0700725 return -EBADF;
Brandon Potterd3d983c2016-11-09 14:27:42 -0600726 int sim_fd = old_hbfdp->getSimFD();
Rick Strong376c7282007-11-29 00:22:46 -0500727
Nilay Vaishb26fef82015-04-13 17:33:57 -0500728 int result = dup(sim_fd);
Brandon Potter198c5152017-03-01 13:35:02 -0600729 if (result == -1)
730 return -errno;
Brandon Potterd3d983c2016-11-09 14:27:42 -0600731
Brandon Potter198c5152017-03-01 13:35:02 -0600732 auto new_hbfdp = std::dynamic_pointer_cast<HBFDEntry>(old_hbfdp->clone());
Brandon Potterd3d983c2016-11-09 14:27:42 -0600733 new_hbfdp->setSimFD(result);
Brandon Potter198c5152017-03-01 13:35:02 -0600734 new_hbfdp->setCOE(false);
735 return p->fds->allocFD(new_hbfdp);
736}
Brandon Potterd3d983c2016-11-09 14:27:42 -0600737
Brandon Potter198c5152017-03-01 13:35:02 -0600738SyscallReturn
739dup2Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
740{
741 int index = 0;
742
743 int old_tgt_fd = p->getSyscallArg(tc, index);
744 auto old_hbp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[old_tgt_fd]);
745 if (!old_hbp)
746 return -EBADF;
747 int old_sim_fd = old_hbp->getSimFD();
748
749 /**
750 * We need a valid host file descriptor number to be able to pass into
751 * the second parameter for dup2 (newfd), but we don't know what the
752 * viable numbers are; we execute the open call to retrieve one.
753 */
754 int res_fd = dup2(old_sim_fd, open("/dev/null", O_RDONLY));
755 if (res_fd == -1)
756 return -errno;
757
758 int new_tgt_fd = p->getSyscallArg(tc, index);
759 auto new_hbp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[new_tgt_fd]);
760 if (new_hbp)
761 p->fds->closeFDEntry(new_tgt_fd);
762 new_hbp = std::dynamic_pointer_cast<HBFDEntry>(old_hbp->clone());
763 new_hbp->setSimFD(res_fd);
764 new_hbp->setCOE(false);
765
766 return p->fds->allocFD(new_hbp);
Steve Reinhardtc5384362006-08-28 07:39:56 -0700767}
768
Steve Reinhardtc5384362006-08-28 07:39:56 -0700769SyscallReturn
Brandon Potterd3d983c2016-11-09 14:27:42 -0600770fcntlFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Ali Saidi53d2c932006-02-18 23:44:22 -0500771{
Brandon Potter6f549412015-07-20 09:15:21 -0500772 int arg;
Gabe Black3f722b92009-10-30 00:44:55 -0700773 int index = 0;
Brandon Potterd3d983c2016-11-09 14:27:42 -0600774 int tgt_fd = p->getSyscallArg(tc, index);
Brandon Potter6f549412015-07-20 09:15:21 -0500775 int cmd = p->getSyscallArg(tc, index);
Ali Saidi53d2c932006-02-18 23:44:22 -0500776
Brandon Potterd3d983c2016-11-09 14:27:42 -0600777 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
778 if (!hbfdp)
Ali Saidi53d2c932006-02-18 23:44:22 -0500779 return -EBADF;
Brandon Potterd3d983c2016-11-09 14:27:42 -0600780 int sim_fd = hbfdp->getSimFD();
Ali Saidi53d2c932006-02-18 23:44:22 -0500781
Brandon Potter6f549412015-07-20 09:15:21 -0500782 int coe = hbfdp->getCOE();
783
Ali Saidi53d2c932006-02-18 23:44:22 -0500784 switch (cmd) {
Brandon Potter6f549412015-07-20 09:15:21 -0500785 case F_GETFD:
786 return coe & FD_CLOEXEC;
Ali Saidi53d2c932006-02-18 23:44:22 -0500787
Brandon Potter6f549412015-07-20 09:15:21 -0500788 case F_SETFD: {
789 arg = p->getSyscallArg(tc, index);
790 arg ? hbfdp->setCOE(true) : hbfdp->setCOE(false);
Ali Saidi53d2c932006-02-18 23:44:22 -0500791 return 0;
Brandon Potter6f549412015-07-20 09:15:21 -0500792 }
Ali Saidi53d2c932006-02-18 23:44:22 -0500793
Brandon Potter6f549412015-07-20 09:15:21 -0500794 // Rely on the host to maintain the file status flags for this file
795 // description rather than maintain it ourselves. Admittedly, this
796 // is suboptimal (and possibly error prone), but it is difficult to
797 // maintain the flags by tracking them across the different descriptors
798 // (that refer to this file description) caused by clone, dup, and
799 // subsequent fcntls.
800 case F_GETFL:
801 case F_SETFL: {
802 arg = p->getSyscallArg(tc, index);
803 int rv = fcntl(sim_fd, cmd, arg);
804 return (rv == -1) ? -errno : rv;
805 }
Ali Saidi53d2c932006-02-18 23:44:22 -0500806
807 default:
Brandon Potter6f549412015-07-20 09:15:21 -0500808 warn("fcntl: unsupported command %d\n", cmd);
Ali Saidi53d2c932006-02-18 23:44:22 -0500809 return 0;
810 }
811}
812
Ali Saidice3a6342006-03-09 15:42:09 -0500813SyscallReturn
Brandon Potterd3d983c2016-11-09 14:27:42 -0600814fcntl64Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Korey Sewell4cc31e12006-06-09 17:07:13 -0400815{
Gabe Black3f722b92009-10-30 00:44:55 -0700816 int index = 0;
Brandon Potterd3d983c2016-11-09 14:27:42 -0600817 int tgt_fd = p->getSyscallArg(tc, index);
Korey Sewell4cc31e12006-06-09 17:07:13 -0400818
Brandon Potterd3d983c2016-11-09 14:27:42 -0600819 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
820 if (!hbfdp)
Korey Sewell4cc31e12006-06-09 17:07:13 -0400821 return -EBADF;
Brandon Potterd3d983c2016-11-09 14:27:42 -0600822 int sim_fd = hbfdp->getSimFD();
Korey Sewell4cc31e12006-06-09 17:07:13 -0400823
Brandon Potterd3d983c2016-11-09 14:27:42 -0600824 int cmd = p->getSyscallArg(tc, index);
Korey Sewell4cc31e12006-06-09 17:07:13 -0400825 switch (cmd) {
826 case 33: //F_GETLK64
Brandon Potterd5a7f092015-07-24 12:25:23 -0700827 warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", tgt_fd);
Korey Sewell4cc31e12006-06-09 17:07:13 -0400828 return -EMFILE;
829
830 case 34: // F_SETLK64
831 case 35: // F_SETLKW64
Brandon Potterd5a7f092015-07-24 12:25:23 -0700832 warn("fcntl64(%d, F_SETLK(W)64) not supported, error returned\n",
833 tgt_fd);
Korey Sewell4cc31e12006-06-09 17:07:13 -0400834 return -EMFILE;
835
836 default:
837 // not sure if this is totally valid, but we'll pass it through
838 // to the underlying OS
Brandon Potterd5a7f092015-07-24 12:25:23 -0700839 warn("fcntl64(%d, %d) passed through to host\n", tgt_fd, cmd);
840 return fcntl(sim_fd, cmd);
Korey Sewell4cc31e12006-06-09 17:07:13 -0400841 }
842}
843
844SyscallReturn
Brandon Potter198c5152017-03-01 13:35:02 -0600845pipeImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc,
846 bool pseudoPipe)
Ali Saidice3a6342006-03-09 15:42:09 -0500847{
Brandon Potter198c5152017-03-01 13:35:02 -0600848 Addr tgt_addr = 0;
849 if (!pseudoPipe) {
850 int index = 0;
851 tgt_addr = p->getSyscallArg(tc, index);
852 }
853
Brandon Potterd3d983c2016-11-09 14:27:42 -0600854 int sim_fds[2], tgt_fds[2];
Ali Saidice3a6342006-03-09 15:42:09 -0500855
Brandon Potterd3d983c2016-11-09 14:27:42 -0600856 int pipe_retval = pipe(sim_fds);
Brandon Potter198c5152017-03-01 13:35:02 -0600857 if (pipe_retval == -1)
858 return -errno;
Ali Saidice3a6342006-03-09 15:42:09 -0500859
Brandon Potterd3d983c2016-11-09 14:27:42 -0600860 auto rend = PipeFDEntry::EndType::read;
861 auto rpfd = std::make_shared<PipeFDEntry>(sim_fds[0], O_WRONLY, rend);
Brandon Potter198c5152017-03-01 13:35:02 -0600862 tgt_fds[0] = p->fds->allocFD(rpfd);
Ali Saidice3a6342006-03-09 15:42:09 -0500863
Brandon Potterd3d983c2016-11-09 14:27:42 -0600864 auto wend = PipeFDEntry::EndType::write;
865 auto wpfd = std::make_shared<PipeFDEntry>(sim_fds[1], O_RDONLY, wend);
Brandon Potter198c5152017-03-01 13:35:02 -0600866 tgt_fds[1] = p->fds->allocFD(wpfd);
Brandon Potterd3d983c2016-11-09 14:27:42 -0600867
868 /**
869 * Now patch the read object to record the target file descriptor chosen
870 * as the write end of the pipe.
871 */
872 rpfd->setPipeReadSource(tgt_fds[1]);
873
874 /**
875 * Alpha Linux convention for pipe() is that fd[0] is returned as
876 * the return value of the function, and fd[1] is returned in r20.
877 */
Brandon Potter198c5152017-03-01 13:35:02 -0600878 if (pseudoPipe) {
879 tc->setIntReg(SyscallPseudoReturnReg, tgt_fds[1]);
880 return tgt_fds[0];
881 }
882
883 /**
884 * Copy the target file descriptors into buffer space and then copy
885 * the buffer space back into the target address space.
886 */
887 BufferArg tgt_handle(tgt_addr, sizeof(int[2]));
888 int *buf_ptr = (int*)tgt_handle.bufferPtr();
889 buf_ptr[0] = tgt_fds[0];
890 buf_ptr[1] = tgt_fds[1];
891 tgt_handle.copyOut(tc->getMemProxy());
892 return 0;
893}
894
895SyscallReturn
896pipePseudoFunc(SyscallDesc *desc, int callnum, Process *process,
897 ThreadContext *tc)
898{
899 return pipeImpl(desc, callnum, process, tc, true);
900}
901
902SyscallReturn
903pipeFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
904{
905 return pipeImpl(desc, callnum, process, tc, false);
Ali Saidice3a6342006-03-09 15:42:09 -0500906}
907
Brandon Potter073cb262017-02-27 14:10:02 -0500908SyscallReturn
909setpgidFunc(SyscallDesc *desc, int callnum, Process *process,
910 ThreadContext *tc)
911{
912 int index = 0;
913 int pid = process->getSyscallArg(tc, index);
914 int pgid = process->getSyscallArg(tc, index);
915
916 if (pgid < 0)
917 return -EINVAL;
918
919 if (pid == 0) {
920 process->setpgid(process->pid());
921 return 0;
922 }
923
Brandon Potter011ddf92017-03-01 15:15:51 -0600924 Process *matched_ph = nullptr;
Brandon Potter073cb262017-02-27 14:10:02 -0500925 System *sysh = tc->getSystemPtr();
926
927 // Retrieves process pointer from active/suspended thread contexts.
928 for (int i = 0; i < sysh->numContexts(); i++) {
929 if (sysh->threadContexts[i]->status() != ThreadContext::Halted) {
930 Process *temp_h = sysh->threadContexts[i]->getProcessPtr();
931 Process *walk_ph = (Process*)temp_h;
932
933 if (walk_ph && walk_ph->pid() == process->pid())
934 matched_ph = walk_ph;
935 }
936 }
937
Brandon Potter011ddf92017-03-01 15:15:51 -0600938 assert(matched_ph);
Brandon Potter073cb262017-02-27 14:10:02 -0500939 matched_ph->setpgid((pgid == 0) ? matched_ph->pid() : pgid);
940
941 return 0;
942}
Ali Saidice3a6342006-03-09 15:42:09 -0500943
944SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600945getpidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
946 ThreadContext *tc)
Ali Saidice3a6342006-03-09 15:42:09 -0500947{
948 // Make up a PID. There's no interprocess communication in
949 // fake_syscall mode, so there's no way for a process to know it's
950 // not getting a unique value.
951
Gabe Black30b87e92006-09-17 03:00:55 -0400952 tc->setIntReg(SyscallPseudoReturnReg, process->ppid());
953 return process->pid();
Ali Saidice3a6342006-03-09 15:42:09 -0500954}
955
956
957SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600958getuidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
959 ThreadContext *tc)
Ali Saidice3a6342006-03-09 15:42:09 -0500960{
961 // Make up a UID and EUID... it shouldn't matter, and we want the
962 // simulation to be deterministic.
963
964 // EUID goes in r20.
Brandon Pottere5fe2b82017-03-01 13:18:49 -0600965 tc->setIntReg(SyscallPseudoReturnReg, process->euid()); // EUID
966 return process->uid(); // UID
Ali Saidice3a6342006-03-09 15:42:09 -0500967}
968
969
970SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600971getgidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
972 ThreadContext *tc)
Ali Saidice3a6342006-03-09 15:42:09 -0500973{
974 // Get current group ID. EGID goes in r20.
Brandon Pottere5fe2b82017-03-01 13:18:49 -0600975 tc->setIntReg(SyscallPseudoReturnReg, process->egid()); // EGID
Gabe Black30b87e92006-09-17 03:00:55 -0400976 return process->gid();
Ali Saidice3a6342006-03-09 15:42:09 -0500977}
978
979
980SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600981setuidFunc(SyscallDesc *desc, int callnum, Process *process,
Kevin Limeb0e4162006-06-06 17:32:21 -0400982 ThreadContext *tc)
Ali Saidice3a6342006-03-09 15:42:09 -0500983{
984 // can't fathom why a benchmark would call this.
Gabe Black3f722b92009-10-30 00:44:55 -0700985 int index = 0;
986 warn("Ignoring call to setuid(%d)\n", process->getSyscallArg(tc, index));
Ali Saidice3a6342006-03-09 15:42:09 -0500987 return 0;
988}
989
990SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -0600991getpidFunc(SyscallDesc *desc, int callnum, Process *process,
Kevin Limeb0e4162006-06-06 17:32:21 -0400992 ThreadContext *tc)
Ali Saidice3a6342006-03-09 15:42:09 -0500993{
Brandon Potter073cb262017-02-27 14:10:02 -0500994 return process->tgid();
995}
Ali Saidice3a6342006-03-09 15:42:09 -0500996
Brandon Potter073cb262017-02-27 14:10:02 -0500997SyscallReturn
998gettidFunc(SyscallDesc *desc, int callnum, Process *process,
999 ThreadContext *tc)
1000{
Gabe Black30b87e92006-09-17 03:00:55 -04001001 return process->pid();
Ali Saidice3a6342006-03-09 15:42:09 -05001002}
1003
1004SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -06001005getppidFunc(SyscallDesc *desc, int callnum, Process *process,
1006 ThreadContext *tc)
Ali Saidice3a6342006-03-09 15:42:09 -05001007{
Gabe Black30b87e92006-09-17 03:00:55 -04001008 return process->ppid();
Ali Saidice3a6342006-03-09 15:42:09 -05001009}
1010
1011SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -06001012getuidFunc(SyscallDesc *desc, int callnum, Process *process,
Kevin Limeb0e4162006-06-06 17:32:21 -04001013 ThreadContext *tc)
Ali Saidice3a6342006-03-09 15:42:09 -05001014{
Ali Saidi3a3e3562008-09-10 14:26:15 -04001015 return process->uid(); // UID
Ali Saidice3a6342006-03-09 15:42:09 -05001016}
1017
1018SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -06001019geteuidFunc(SyscallDesc *desc, int callnum, Process *process,
1020 ThreadContext *tc)
Ali Saidice3a6342006-03-09 15:42:09 -05001021{
Ali Saidi3a3e3562008-09-10 14:26:15 -04001022 return process->euid(); // UID
Ali Saidice3a6342006-03-09 15:42:09 -05001023}
1024
1025SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -06001026getgidFunc(SyscallDesc *desc, int callnum, Process *process,
Kevin Limeb0e4162006-06-06 17:32:21 -04001027 ThreadContext *tc)
Ali Saidice3a6342006-03-09 15:42:09 -05001028{
Gabe Black30b87e92006-09-17 03:00:55 -04001029 return process->gid();
Ali Saidice3a6342006-03-09 15:42:09 -05001030}
1031
1032SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -06001033getegidFunc(SyscallDesc *desc, int callnum, Process *process,
1034 ThreadContext *tc)
Ali Saidice3a6342006-03-09 15:42:09 -05001035{
Gabe Black30b87e92006-09-17 03:00:55 -04001036 return process->egid();
Ali Saidice3a6342006-03-09 15:42:09 -05001037}
1038
Mitch Hayenga4a752b12013-01-08 08:54:07 -05001039SyscallReturn
Brandon Potterd3d983c2016-11-09 14:27:42 -06001040fallocateFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
Brandon Pottercc84eb82016-12-15 13:16:25 -05001041{
Brandon Potter93d8e6b2017-01-20 14:12:58 -05001042#if NO_FALLOCATE
1043 warn("Host OS cannot support calls to fallocate. Ignoring syscall");
1044#else
Brandon Pottercc84eb82016-12-15 13:16:25 -05001045 int index = 0;
Brandon Potterd3d983c2016-11-09 14:27:42 -06001046 int tgt_fd = p->getSyscallArg(tc, index);
1047 int mode = p->getSyscallArg(tc, index);
1048 off_t offset = p->getSyscallArg(tc, index);
1049 off_t len = p->getSyscallArg(tc, index);
Brandon Pottercc84eb82016-12-15 13:16:25 -05001050
Brandon Potterd3d983c2016-11-09 14:27:42 -06001051 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1052 if (!ffdp)
Brandon Pottercc84eb82016-12-15 13:16:25 -05001053 return -EBADF;
Brandon Potterd3d983c2016-11-09 14:27:42 -06001054 int sim_fd = ffdp->getSimFD();
Brandon Pottercc84eb82016-12-15 13:16:25 -05001055
1056 int result = fallocate(sim_fd, mode, offset, len);
1057 if (result < 0)
1058 return -errno;
Brandon Potter93d8e6b2017-01-20 14:12:58 -05001059#endif
Brandon Pottercc84eb82016-12-15 13:16:25 -05001060 return 0;
1061}
1062
1063SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -06001064accessFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc,
1065 int index)
Mitch Hayenga4a752b12013-01-08 08:54:07 -05001066{
Mitch Hayenga4a752b12013-01-08 08:54:07 -05001067 string path;
1068 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
Steve Reinhardt109908c2014-05-12 14:23:31 -07001069 return -EFAULT;
Mitch Hayenga4a752b12013-01-08 08:54:07 -05001070
1071 // Adjust path for current working directory
1072 path = p->fullPath(path);
1073
1074 mode_t mode = p->getSyscallArg(tc, index);
1075
1076 int result = access(path.c_str(), mode);
1077 return (result == -1) ? -errno : result;
1078}
Ali Saidic4a2f762014-04-17 16:55:05 -05001079
1080SyscallReturn
Brandon Potter3886c4a2016-11-09 14:27:40 -06001081accessFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
Ali Saidic4a2f762014-04-17 16:55:05 -05001082{
1083 return accessFunc(desc, callnum, p, tc, 0);
1084}
1085
Brandon Potterf2abc6b2018-04-18 14:45:37 -04001086SyscallReturn
1087mknodFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1088{
1089 int index = 0;
1090 std::string path;
1091 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
1092 return -EFAULT;
1093
1094 path = p->fullPath(path);
1095 mode_t mode = p->getSyscallArg(tc, index);
1096 dev_t dev = p->getSyscallArg(tc, index);
1097
1098 auto result = mknod(path.c_str(), mode, dev);
1099 return (result == -1) ? -errno : result;
1100}
1101
1102SyscallReturn
1103chdirFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1104{
1105 int index = 0;
1106 std::string path;
1107 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
1108 return -EFAULT;
1109
1110 path = p->fullPath(path);
1111
1112 auto result = chdir(path.c_str());
1113 return (result == -1) ? -errno : result;
1114}
1115
1116SyscallReturn
1117rmdirFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1118{
1119 int index = 0;
1120 std::string path;
1121 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
1122 return -EFAULT;
1123
1124 path = p->fullPath(path);
1125
1126 auto result = rmdir(path.c_str());
1127 return (result == -1) ? -errno : result;
1128}
1129
Javier Setoainf3a438e2019-01-09 14:24:31 +00001130#if defined(SYS_getdents) || defined(SYS_getdents64)
1131template<typename DE, int SYS_NUM>
1132static SyscallReturn
1133getdentsImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
Brandon Potterf2abc6b2018-04-18 14:45:37 -04001134{
1135 int index = 0;
1136 int tgt_fd = p->getSyscallArg(tc, index);
1137 Addr buf_ptr = p->getSyscallArg(tc, index);
1138 unsigned count = p->getSyscallArg(tc, index);
1139
1140 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1141 if (!hbfdp)
1142 return -EBADF;
1143 int sim_fd = hbfdp->getSimFD();
1144
1145 BufferArg buf_arg(buf_ptr, count);
Javier Setoainf3a438e2019-01-09 14:24:31 +00001146 auto status = syscall(SYS_NUM, sim_fd, buf_arg.bufferPtr(), count);
Brandon Potterf2abc6b2018-04-18 14:45:37 -04001147
1148 if (status == -1)
1149 return -errno;
1150
Brandon Potterf2abc6b2018-04-18 14:45:37 -04001151 unsigned traversed = 0;
1152 while (traversed < status) {
Javier Setoainf3a438e2019-01-09 14:24:31 +00001153 DE *buffer = (DE*)((Addr)buf_arg.bufferPtr() + traversed);
Brandon Potterf2abc6b2018-04-18 14:45:37 -04001154
1155 auto host_reclen = buffer->d_reclen;
1156
1157 /**
1158 * Convert the byte ordering from the host to the target before
1159 * passing the data back into the target's address space to preserve
1160 * endianness.
1161 */
1162 buffer->d_ino = htog(buffer->d_ino);
1163 buffer->d_off = htog(buffer->d_off);
1164 buffer->d_reclen = htog(buffer->d_reclen);
1165
1166 traversed += host_reclen;
1167 }
1168
1169 buf_arg.copyOut(tc->getMemProxy());
1170 return status;
1171}
Ciro Santillia66d12c2018-11-20 16:45:07 +00001172#endif
Javier Setoainf3a438e2019-01-09 14:24:31 +00001173
1174#if defined(SYS_getdents)
1175SyscallReturn
1176getdentsFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
1177{
1178 typedef struct linux_dirent {
1179 unsigned long d_ino;
1180 unsigned long d_off;
1181 unsigned short d_reclen;
1182 char dname[];
1183 } LinDent;
1184
1185 return getdentsImpl<LinDent, SYS_getdents>(desc, callnum, p, tc);
1186}
1187#endif
1188
1189#if defined(SYS_getdents64)
1190SyscallReturn
1191getdents64Func(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
1192{
1193 typedef struct linux_dirent64 {
1194 ino64_t d_ino;
1195 off64_t d_off;
1196 unsigned short d_reclen;
1197 char dname[];
1198 } LinDent64;
1199
1200 return getdentsImpl<LinDent64, SYS_getdents64>(desc, callnum, p, tc);
1201}
1202#endif
Brandon Pottera2ed7d52018-04-18 14:48:19 -04001203
1204SyscallReturn
1205shutdownFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1206{
1207 int index = 0;
1208 int tgt_fd = p->getSyscallArg(tc, index);
1209 int how = p->getSyscallArg(tc, index);
1210
1211 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1212 if (!sfdp)
1213 return -EBADF;
1214 int sim_fd = sfdp->getSimFD();
1215
1216 int retval = shutdown(sim_fd, how);
1217
1218 return (retval == -1) ? -errno : retval;
1219}
1220
1221SyscallReturn
1222bindFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1223{
1224 int index = 0;
1225 int tgt_fd = p->getSyscallArg(tc, index);
1226 Addr buf_ptr = p->getSyscallArg(tc, index);
1227 int addrlen = p->getSyscallArg(tc, index);
1228
1229 BufferArg bufSock(buf_ptr, addrlen);
1230 bufSock.copyIn(tc->getMemProxy());
1231
1232 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1233 if (!sfdp)
1234 return -EBADF;
1235 int sim_fd = sfdp->getSimFD();
1236
1237 int status = ::bind(sim_fd,
1238 (struct sockaddr *)bufSock.bufferPtr(),
1239 addrlen);
1240
1241 return (status == -1) ? -errno : status;
1242}
1243
1244SyscallReturn
1245listenFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1246{
1247 int index = 0;
1248 int tgt_fd = p->getSyscallArg(tc, index);
1249 int backlog = p->getSyscallArg(tc, index);
1250
1251 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1252 if (!sfdp)
1253 return -EBADF;
1254 int sim_fd = sfdp->getSimFD();
1255
1256 int status = listen(sim_fd, backlog);
1257
1258 return (status == -1) ? -errno : status;
1259}
1260
1261SyscallReturn
1262connectFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1263{
1264 int index = 0;
1265 int tgt_fd = p->getSyscallArg(tc, index);
1266 Addr buf_ptr = p->getSyscallArg(tc, index);
1267 int addrlen = p->getSyscallArg(tc, index);
1268
1269 BufferArg addr(buf_ptr, addrlen);
1270 addr.copyIn(tc->getMemProxy());
1271
1272 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1273 if (!sfdp)
1274 return -EBADF;
1275 int sim_fd = sfdp->getSimFD();
1276
1277 int status = connect(sim_fd,
1278 (struct sockaddr *)addr.bufferPtr(),
1279 (socklen_t)addrlen);
1280
1281 return (status == -1) ? -errno : status;
1282}
Brandon Potterc4e67f62018-04-18 14:55:30 -04001283
1284SyscallReturn
1285recvfromFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1286{
1287 int index = 0;
1288 int tgt_fd = p->getSyscallArg(tc, index);
1289 Addr bufrPtr = p->getSyscallArg(tc, index);
1290 size_t bufrLen = p->getSyscallArg(tc, index);
1291 int flags = p->getSyscallArg(tc, index);
1292 Addr addrPtr = p->getSyscallArg(tc, index);
1293 Addr addrlenPtr = p->getSyscallArg(tc, index);
1294
1295 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1296 if (!sfdp)
1297 return -EBADF;
1298 int sim_fd = sfdp->getSimFD();
1299
1300 // Reserve buffer space.
1301 BufferArg bufrBuf(bufrPtr, bufrLen);
1302
1303 // Get address length.
1304 socklen_t addrLen = 0;
1305 if (addrlenPtr != 0) {
1306 // Read address length parameter.
1307 BufferArg addrlenBuf(addrlenPtr, sizeof(socklen_t));
1308 addrlenBuf.copyIn(tc->getMemProxy());
1309 addrLen = *((socklen_t *)addrlenBuf.bufferPtr());
1310 }
1311
1312 struct sockaddr sa, *sap = NULL;
1313 if (addrLen != 0) {
1314 BufferArg addrBuf(addrPtr, addrLen);
1315 addrBuf.copyIn(tc->getMemProxy());
1316 memcpy(&sa, (struct sockaddr *)addrBuf.bufferPtr(),
1317 sizeof(struct sockaddr));
1318 sap = &sa;
1319 }
1320
1321 ssize_t recvd_size = recvfrom(sim_fd,
1322 (void *)bufrBuf.bufferPtr(),
1323 bufrLen, flags, sap, (socklen_t *)&addrLen);
1324
1325 if (recvd_size == -1)
1326 return -errno;
1327
1328 // Pass the received data out.
1329 bufrBuf.copyOut(tc->getMemProxy());
1330
1331 // Copy address to addrPtr and pass it on.
1332 if (sap != NULL) {
1333 BufferArg addrBuf(addrPtr, addrLen);
1334 memcpy(addrBuf.bufferPtr(), sap, sizeof(sa));
1335 addrBuf.copyOut(tc->getMemProxy());
1336 }
1337
1338 // Copy len to addrlenPtr and pass it on.
1339 if (addrLen != 0) {
1340 BufferArg addrlenBuf(addrlenPtr, sizeof(socklen_t));
1341 *(socklen_t *)addrlenBuf.bufferPtr() = addrLen;
1342 addrlenBuf.copyOut(tc->getMemProxy());
1343 }
1344
1345 return recvd_size;
1346}
1347
1348SyscallReturn
1349sendtoFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1350{
1351 int index = 0;
1352 int tgt_fd = p->getSyscallArg(tc, index);
1353 Addr bufrPtr = p->getSyscallArg(tc, index);
1354 size_t bufrLen = p->getSyscallArg(tc, index);
1355 int flags = p->getSyscallArg(tc, index);
1356 Addr addrPtr = p->getSyscallArg(tc, index);
1357 socklen_t addrLen = p->getSyscallArg(tc, index);
1358
1359 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1360 if (!sfdp)
1361 return -EBADF;
1362 int sim_fd = sfdp->getSimFD();
1363
1364 // Reserve buffer space.
1365 BufferArg bufrBuf(bufrPtr, bufrLen);
1366 bufrBuf.copyIn(tc->getMemProxy());
1367
1368 struct sockaddr sa, *sap = nullptr;
1369 memset(&sa, 0, sizeof(sockaddr));
1370 if (addrLen != 0) {
1371 BufferArg addrBuf(addrPtr, addrLen);
1372 addrBuf.copyIn(tc->getMemProxy());
1373 memcpy(&sa, (sockaddr*)addrBuf.bufferPtr(), addrLen);
1374 sap = &sa;
1375 }
1376
1377 ssize_t sent_size = sendto(sim_fd,
1378 (void *)bufrBuf.bufferPtr(),
1379 bufrLen, flags, sap, (socklen_t)addrLen);
1380
1381 return (sent_size == -1) ? -errno : sent_size;
1382}
1383
1384SyscallReturn
1385recvmsgFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1386{
1387 int index = 0;
1388 int tgt_fd = p->getSyscallArg(tc, index);
1389 Addr msgPtr = p->getSyscallArg(tc, index);
1390 int flags = p->getSyscallArg(tc, index);
1391
1392 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1393 if (!sfdp)
1394 return -EBADF;
1395 int sim_fd = sfdp->getSimFD();
1396
1397 /**
1398 * struct msghdr {
1399 * void *msg_name; // optional address
1400 * socklen_t msg_namelen; // size of address
1401 * struct iovec *msg_iov; // iovec array
1402 * size_t msg_iovlen; // number entries in msg_iov
1403 * i // entries correspond to buffer
1404 * void *msg_control; // ancillary data
1405 * size_t msg_controllen; // ancillary data buffer len
1406 * int msg_flags; // flags on received message
1407 * };
1408 *
1409 * struct iovec {
1410 * void *iov_base; // starting address
1411 * size_t iov_len; // number of bytes to transfer
1412 * };
1413 */
1414
1415 /**
1416 * The plan with this system call is to replace all of the pointers in the
1417 * structure and the substructure with BufferArg class pointers. We will
1418 * copy every field from the structures into our BufferArg classes.
1419 */
1420 BufferArg msgBuf(msgPtr, sizeof(struct msghdr));
1421 msgBuf.copyIn(tc->getMemProxy());
1422 struct msghdr *msgHdr = (struct msghdr *)msgBuf.bufferPtr();
1423
1424 /**
1425 * We will use these address place holders to retain the pointers which
1426 * we are going to replace with our own buffers in our simulator address
1427 * space.
1428 */
1429 Addr msg_name_phold = 0;
1430 Addr msg_iov_phold = 0;
1431 Addr iovec_base_phold[msgHdr->msg_iovlen];
1432 Addr msg_control_phold = 0;
1433
1434 /**
1435 * Record msg_name pointer then replace with buffer pointer.
1436 */
1437 BufferArg *nameBuf = NULL;
1438 if (msgHdr->msg_name) {
1439 /*1*/msg_name_phold = (Addr)msgHdr->msg_name;
1440 /*2*/nameBuf = new BufferArg(msg_name_phold, msgHdr->msg_namelen);
1441 /*3*/nameBuf->copyIn(tc->getMemProxy());
1442 /*4*/msgHdr->msg_name = nameBuf->bufferPtr();
1443 }
1444
1445 /**
1446 * Record msg_iov pointer then replace with buffer pointer. Also, setup
1447 * an array of buffer pointers for the iovec structs record and replace
1448 * their pointers with buffer pointers.
1449 */
1450 BufferArg *iovBuf = NULL;
1451 BufferArg *iovecBuf[msgHdr->msg_iovlen];
1452 for (int i = 0; i < msgHdr->msg_iovlen; i++) {
1453 iovec_base_phold[i] = 0;
1454 iovecBuf[i] = NULL;
1455 }
1456
1457 if (msgHdr->msg_iov) {
1458 /*1*/msg_iov_phold = (Addr)msgHdr->msg_iov;
1459 /*2*/iovBuf = new BufferArg(msg_iov_phold, msgHdr->msg_iovlen *
1460 sizeof(struct iovec));
1461 /*3*/iovBuf->copyIn(tc->getMemProxy());
1462 for (int i = 0; i < msgHdr->msg_iovlen; i++) {
1463 if (((struct iovec *)iovBuf->bufferPtr())[i].iov_base) {
1464 /*1*/iovec_base_phold[i] =
1465 (Addr)((struct iovec *)iovBuf->bufferPtr())[i].iov_base;
1466 /*2*/iovecBuf[i] = new BufferArg(iovec_base_phold[i],
1467 ((struct iovec *)iovBuf->bufferPtr())[i].iov_len);
1468 /*3*/iovecBuf[i]->copyIn(tc->getMemProxy());
1469 /*4*/((struct iovec *)iovBuf->bufferPtr())[i].iov_base =
1470 iovecBuf[i]->bufferPtr();
1471 }
1472 }
1473 /*4*/msgHdr->msg_iov = (struct iovec *)iovBuf->bufferPtr();
1474 }
1475
1476 /**
1477 * Record msg_control pointer then replace with buffer pointer.
1478 */
1479 BufferArg *controlBuf = NULL;
1480 if (msgHdr->msg_control) {
1481 /*1*/msg_control_phold = (Addr)msgHdr->msg_control;
1482 /*2*/controlBuf = new BufferArg(msg_control_phold,
1483 CMSG_ALIGN(msgHdr->msg_controllen));
1484 /*3*/controlBuf->copyIn(tc->getMemProxy());
1485 /*4*/msgHdr->msg_control = controlBuf->bufferPtr();
1486 }
1487
1488 ssize_t recvd_size = recvmsg(sim_fd, msgHdr, flags);
1489
1490 if (recvd_size < 0)
1491 return -errno;
1492
1493 if (msgHdr->msg_name) {
1494 nameBuf->copyOut(tc->getMemProxy());
1495 delete(nameBuf);
1496 msgHdr->msg_name = (void *)msg_name_phold;
1497 }
1498
1499 if (msgHdr->msg_iov) {
1500 for (int i = 0; i< msgHdr->msg_iovlen; i++) {
1501 if (((struct iovec *)iovBuf->bufferPtr())[i].iov_base) {
1502 iovecBuf[i]->copyOut(tc->getMemProxy());
1503 delete iovecBuf[i];
1504 ((struct iovec *)iovBuf->bufferPtr())[i].iov_base =
1505 (void *)iovec_base_phold[i];
1506 }
1507 }
1508 iovBuf->copyOut(tc->getMemProxy());
1509 delete iovBuf;
1510 msgHdr->msg_iov = (struct iovec *)msg_iov_phold;
1511 }
1512
1513 if (msgHdr->msg_control) {
1514 controlBuf->copyOut(tc->getMemProxy());
1515 delete(controlBuf);
1516 msgHdr->msg_control = (void *)msg_control_phold;
1517 }
1518
1519 msgBuf.copyOut(tc->getMemProxy());
1520
1521 return recvd_size;
1522}
1523
1524SyscallReturn
1525sendmsgFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1526{
1527 int index = 0;
1528 int tgt_fd = p->getSyscallArg(tc, index);
1529 Addr msgPtr = p->getSyscallArg(tc, index);
1530 int flags = p->getSyscallArg(tc, index);
1531
1532 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1533 if (!sfdp)
1534 return -EBADF;
1535 int sim_fd = sfdp->getSimFD();
1536
1537 /**
1538 * Reserve buffer space.
1539 */
1540 BufferArg msgBuf(msgPtr, sizeof(struct msghdr));
1541 msgBuf.copyIn(tc->getMemProxy());
1542 struct msghdr msgHdr = *((struct msghdr *)msgBuf.bufferPtr());
1543
1544 /**
1545 * Assuming msgHdr.msg_iovlen >= 1, then there is no point calling
1546 * recvmsg without a buffer.
1547 */
1548 struct iovec *iovPtr = msgHdr.msg_iov;
1549 BufferArg iovBuf((Addr)iovPtr, sizeof(struct iovec) * msgHdr.msg_iovlen);
1550 iovBuf.copyIn(tc->getMemProxy());
1551 struct iovec *iov = (struct iovec *)iovBuf.bufferPtr();
1552 msgHdr.msg_iov = iov;
1553
1554 /**
1555 * Cannot instantiate buffers till inside the loop.
1556 * Create array to hold buffer addresses, to be used during copyIn of
1557 * send data.
1558 */
1559 BufferArg **bufferArray = (BufferArg **)malloc(msgHdr.msg_iovlen
1560 * sizeof(BufferArg *));
1561
1562 /**
1563 * Iterate through the iovec structures:
1564 * Get the base buffer addreses, reserve iov_len amount of space for each.
1565 * Put the buf address into the bufferArray for later retrieval.
1566 */
1567 for (int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
1568 Addr basePtr = (Addr) iov[iovIndex].iov_base;
1569 bufferArray[iovIndex] = new BufferArg(basePtr, iov[iovIndex].iov_len);
1570 bufferArray[iovIndex]->copyIn(tc->getMemProxy());
1571 iov[iovIndex].iov_base = bufferArray[iovIndex]->bufferPtr();
1572 }
1573
1574 ssize_t sent_size = sendmsg(sim_fd, &msgHdr, flags);
1575 int local_errno = errno;
1576
1577 /**
1578 * Free dynamically allocated memory.
1579 */
1580 for (int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
1581 BufferArg *baseBuf = ( BufferArg *)bufferArray[iovIndex];
1582 delete(baseBuf);
1583 }
1584
1585 /**
1586 * Malloced above.
1587 */
1588 free(bufferArray);
1589
1590 return (sent_size < 0) ? -local_errno : sent_size;
1591}
1592
Brandon Potter7936e632018-04-18 15:00:14 -04001593SyscallReturn
1594getsockoptFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1595{
1596 // union of all possible return value types from getsockopt
1597 union val {
1598 int i_val;
1599 long l_val;
1600 struct linger linger_val;
1601 struct timeval timeval_val;
1602 } val;
1603
1604 int index = 0;
1605 int tgt_fd = p->getSyscallArg(tc, index);
1606 int level = p->getSyscallArg(tc, index);
1607 int optname = p->getSyscallArg(tc, index);
1608 Addr valPtr = p->getSyscallArg(tc, index);
1609 Addr lenPtr = p->getSyscallArg(tc, index);
1610
1611 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1612 if (!sfdp)
1613 return -EBADF;
1614 int sim_fd = sfdp->getSimFD();
1615
1616 socklen_t len = sizeof(val);
1617 int status = getsockopt(sim_fd, level, optname, &val, &len);
1618
1619 if (status == -1)
1620 return -errno;
1621
1622 // copy val to valPtr and pass it on
1623 BufferArg valBuf(valPtr, sizeof(val));
1624 memcpy(valBuf.bufferPtr(), &val, sizeof(val));
1625 valBuf.copyOut(tc->getMemProxy());
1626
1627 // copy len to lenPtr and pass it on
1628 BufferArg lenBuf(lenPtr, sizeof(len));
1629 memcpy(lenBuf.bufferPtr(), &len, sizeof(len));
1630 lenBuf.copyOut(tc->getMemProxy());
1631
1632 return status;
1633}
1634
1635SyscallReturn
1636getsocknameFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1637{
1638 int index = 0;
1639 int tgt_fd = p->getSyscallArg(tc, index);
1640 Addr addrPtr = p->getSyscallArg(tc, index);
1641 Addr lenPtr = p->getSyscallArg(tc, index);
1642
1643 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1644 if (!sfdp)
1645 return -EBADF;
1646 int sim_fd = sfdp->getSimFD();
1647
1648 // lenPtr is an in-out paramenter:
1649 // sending the address length in, conveying the final length out
1650
1651 // Read in the value of len from the passed pointer.
1652 BufferArg lenBuf(lenPtr, sizeof(socklen_t));
1653 lenBuf.copyIn(tc->getMemProxy());
1654 socklen_t len = *(socklen_t *)lenBuf.bufferPtr();
1655
1656 struct sockaddr sa;
1657 int status = getsockname(sim_fd, &sa, &len);
1658
1659 if (status == -1)
1660 return -errno;
1661
1662 // Copy address to addrPtr and pass it on.
1663 BufferArg addrBuf(addrPtr, sizeof(sa));
1664 memcpy(addrBuf.bufferPtr(), &sa, sizeof(sa));
1665 addrBuf.copyOut(tc->getMemProxy());
1666
1667 // Copy len to lenPtr and pass it on.
1668 *(socklen_t *)lenBuf.bufferPtr() = len;
1669 lenBuf.copyOut(tc->getMemProxy());
1670
1671 return status;
1672}
1673
1674SyscallReturn
1675getpeernameFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1676{
1677 int index = 0;
1678 int tgt_fd = p->getSyscallArg(tc, index);
1679 Addr sockAddrPtr = p->getSyscallArg(tc, index);
1680 Addr addrlenPtr = p->getSyscallArg(tc, index);
1681
1682 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1683 if (!sfdp)
1684 return -EBADF;
1685 int sim_fd = sfdp->getSimFD();
1686
1687 BufferArg bufAddrlen(addrlenPtr, sizeof(unsigned));
1688 bufAddrlen.copyIn(tc->getMemProxy());
1689 BufferArg bufSock(sockAddrPtr, *(unsigned *)bufAddrlen.bufferPtr());
1690
1691 int retval = getpeername(sim_fd,
1692 (struct sockaddr *)bufSock.bufferPtr(),
1693 (unsigned *)bufAddrlen.bufferPtr());
1694
1695 if (retval != -1) {
1696 bufSock.copyOut(tc->getMemProxy());
1697 bufAddrlen.copyOut(tc->getMemProxy());
1698 }
1699
1700 return (retval == -1) ? -errno : retval;
1701}
1702
1703SyscallReturn
1704setsockoptFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1705{
1706 int index = 0;
1707 int tgt_fd = p->getSyscallArg(tc, index);
1708 int level = p->getSyscallArg(tc, index);
1709 int optname = p->getSyscallArg(tc, index);
1710 Addr valPtr = p->getSyscallArg(tc, index);
1711 socklen_t len = p->getSyscallArg(tc, index);
1712
1713 BufferArg valBuf(valPtr, len);
1714 valBuf.copyIn(tc->getMemProxy());
1715
1716 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1717 if (!sfdp)
1718 return -EBADF;
1719 int sim_fd = sfdp->getSimFD();
1720
1721 int status = setsockopt(sim_fd, level, optname,
1722 (struct sockaddr *)valBuf.bufferPtr(), len);
1723
1724 return (status == -1) ? -errno : status;
1725}
1726