gem5  v21.1.0.1
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
syscall_emul.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2003-2005 The Regents of The University of Michigan
3  * 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.
27  */
28 
29 #include "sim/syscall_emul.hh"
30 
31 #include <fcntl.h>
32 #include <sys/syscall.h>
33 #include <unistd.h>
34 
35 #include <csignal>
36 #include <iostream>
37 #include <mutex>
38 #include <string>
39 #include <unordered_map>
40 
41 #include "base/chunk_generator.hh"
42 #include "base/trace.hh"
43 #include "cpu/thread_context.hh"
44 #include "dev/net/dist_iface.hh"
45 #include "mem/page_table.hh"
46 #include "sim/byteswap.hh"
47 #include "sim/process.hh"
48 #include "sim/proxy_ptr.hh"
49 #include "sim/sim_exit.hh"
51 #include "sim/syscall_desc.hh"
52 #include "sim/system.hh"
53 
54 namespace gem5
55 {
56 
57 void
58 warnUnsupportedOS(std::string syscall_name)
59 {
60  warn("Cannot invoke %s on host operating system.", syscall_name);
61 }
62 
63 SyscallReturn
65 {
66  fatal("syscall %s (#%d) unimplemented.", desc->name(), desc->num());
67 }
68 
69 
70 SyscallReturn
72 {
73  warn("ignoring syscall %s(...)", desc->name());
74  return 0;
75 }
76 
77 SyscallReturn
79 {
80  static std::unordered_map<SyscallDesc *, bool> bool_map;
81 
82  bool &warned = bool_map[desc];
83  if (!warned) {
84  warn("ignoring syscall %s(...)\n"
85  " (further warnings will be suppressed)", desc->name());
86  warned = true;
87  }
88 
89  return 0;
90 }
91 
92 static void
93 exitFutexWake(ThreadContext *tc, VPtr<> addr, uint64_t tgid)
94 {
95  // Clear value at address pointed to by thread's childClearTID field.
96  BufferArg ctidBuf(addr, sizeof(long));
97  long *ctid = (long *)ctidBuf.bufferPtr();
98  *ctid = 0;
99  ctidBuf.copyOut(tc->getVirtProxy());
100 
101  FutexMap &futex_map = tc->getSystemPtr()->futexMap;
102  // Wake one of the waiting threads.
103  futex_map.wakeup(addr, tgid, 1);
104 }
105 
106 static SyscallReturn
107 exitImpl(SyscallDesc *desc, ThreadContext *tc, bool group, int status)
108 {
109  auto p = tc->getProcessPtr();
110 
111  System *sys = tc->getSystemPtr();
112 
113  if (group)
114  *p->exitGroup = true;
115 
116  if (p->childClearTID)
117  exitFutexWake(tc, p->childClearTID, p->tgid());
118 
119  bool last_thread = true;
120  Process *parent = nullptr, *tg_lead = nullptr;
121  for (int i = 0; last_thread && i < sys->threads.size(); i++) {
122  Process *walk;
123  if (!(walk = sys->threads[i]->getProcessPtr()))
124  continue;
125 
132  if (walk->pid() == p->tgid())
133  tg_lead = walk;
134 
135  auto *tc = sys->threads[i];
136  if ((tc->status() != ThreadContext::Halted) &&
137  (tc->status() != ThreadContext::Halting) &&
138  (walk != p)) {
145  if (walk->tgid() == p->tgid()) {
158  if (*(p->exitGroup)) {
159  tc->halt();
160  } else {
161  last_thread = false;
162  }
163  }
164 
174  if (*p->sigchld && (p->ppid() != 0) && (walk->pid() == p->ppid()))
175  parent = walk;
176  }
177  }
178 
179  if (last_thread) {
180  if (parent) {
181  assert(tg_lead);
182  sys->signalList.push_back(BasicSignal(tg_lead, parent, SIGCHLD));
183  }
184 
190  for (int i = 0; i < p->fds->getSize(); i++) {
191  if ((*p->fds)[i])
192  p->fds->closeFDEntry(i);
193  }
194  }
195 
200  if (!p->vforkContexts.empty()) {
201  ThreadContext *vtc = sys->threads[p->vforkContexts.front()];
202  assert(vtc->status() == ThreadContext::Suspended);
203  vtc->activate();
204  }
205 
206  tc->halt();
207 
212  int activeContexts = 0;
213  for (auto &system: sys->systemList)
214  activeContexts += system->threads.numRunning();
215 
216  if (activeContexts == 0) {
226  if (!DistIface::readyToExit(0)) {
227  return status;
228  }
229 
230  exitSimLoop("exiting with last active thread context", status & 0xff);
231  return status;
232  }
233 
234  return status;
235 }
236 
237 SyscallReturn
239 {
240  return exitImpl(desc, tc, false, status);
241 }
242 
243 SyscallReturn
245 {
246  return exitImpl(desc, tc, true, status);
247 }
248 
249 SyscallReturn
251 {
252  return (int)tc->getProcessPtr()->pTable->pageSize();
253 }
254 
255 
256 SyscallReturn
258 {
259  // change brk addr to first arg
260  auto p = tc->getProcessPtr();
261 
262  std::shared_ptr<MemState> mem_state = p->memState;
263  Addr brk_point = mem_state->getBrkPoint();
264 
265  // in Linux at least, brk(0) returns the current break value
266  // (note that the syscall and the glibc function have different behavior)
267  if (new_brk == 0 || (new_brk == brk_point))
268  return brk_point;
269 
270  mem_state->updateBrkRegion(brk_point, new_brk);
271 
272  DPRINTF_SYSCALL(Verbose, "brk: break point changed to: %#X\n",
273  mem_state->getBrkPoint());
274 
275  return mem_state->getBrkPoint();
276 }
277 
278 SyscallReturn
279 setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc, uint64_t tidPtr)
280 {
281  auto process = tc->getProcessPtr();
282 
283  process->childClearTID = tidPtr;
284  return process->pid();
285 }
286 
287 SyscallReturn
288 closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
289 {
290  auto p = tc->getProcessPtr();
291  return p->fds->closeFDEntry(tgt_fd);
292 }
293 
294 SyscallReturn
296  int tgt_fd, uint64_t offs, int whence)
297 {
298  auto p = tc->getProcessPtr();
299 
300  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
301  if (!ffdp)
302  return -EBADF;
303  int sim_fd = ffdp->getSimFD();
304 
305  off_t result = lseek(sim_fd, offs, whence);
306 
307  return (result == (off_t)-1) ? -errno : result;
308 }
309 
310 
311 SyscallReturn
313  int tgt_fd, uint64_t offset_high, uint32_t offset_low,
314  VPtr<> result_ptr, int whence)
315 {
316  auto p = tc->getProcessPtr();
317 
318  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
319  if (!ffdp)
320  return -EBADF;
321  int sim_fd = ffdp->getSimFD();
322 
323  uint64_t offset = (offset_high << 32) | offset_low;
324 
325  uint64_t result = lseek(sim_fd, offset, whence);
326  result = htog(result, tc->getSystemPtr()->getGuestByteOrder());
327 
328  if (result == (off_t)-1)
329  return -errno;
330  // Assuming that the size of loff_t is 64 bits on the target platform
331  BufferArg result_buf(result_ptr, sizeof(result));
332  std::memcpy(result_buf.bufferPtr(), &result, sizeof(result));
333  result_buf.copyOut(tc->getVirtProxy());
334  return 0;
335 }
336 
337 
338 SyscallReturn
339 munmapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, size_t length)
340 {
341  // Even if the system is currently not capable of recycling physical
342  // pages, there is no reason we can't unmap them so that we trigger
343  // appropriate seg faults when the application mistakenly tries to
344  // access them again.
345  auto p = tc->getProcessPtr();
346 
347  if (p->pTable->pageOffset(start))
348  return -EINVAL;
349 
350  length = roundUp(length, p->pTable->pageSize());
351 
352  p->memState->unmapRegion(start, length);
353 
354  return 0;
355 }
356 
357 
358 const char *hostname = "m5.eecs.umich.edu";
359 
362  VPtr<> buf_ptr, int name_len)
363 {
364  BufferArg name(buf_ptr, name_len);
365  strncpy((char *)name.bufferPtr(), hostname, name_len);
366  name.copyOut(tc->getVirtProxy());
367  return 0;
368 }
369 
370 SyscallReturn
372  VPtr<> buf_ptr, unsigned long size)
373 {
374  int result = 0;
375  auto p = tc->getProcessPtr();
376  BufferArg buf(buf_ptr, size);
377 
378  // Is current working directory defined?
379  std::string cwd = p->tgtCwd;
380  if (!cwd.empty()) {
381  if (cwd.length() >= size) {
382  // Buffer too small
383  return -ERANGE;
384  }
385  strncpy((char *)buf.bufferPtr(), cwd.c_str(), size);
386  result = cwd.length();
387  } else {
388  if (getcwd((char *)buf.bufferPtr(), size)) {
389  result = strlen((char *)buf.bufferPtr());
390  } else {
391  result = -1;
392  }
393  }
394 
395  buf.copyOut(tc->getVirtProxy());
396 
397  return (result == -1) ? -errno : result;
398 }
399 
400 SyscallReturn
402  VPtr<> pathname, VPtr<> buf_ptr, size_t bufsiz)
403 {
404  std::string path;
405  auto p = tc->getProcessPtr();
406 
407  if (!tc->getVirtProxy().tryReadString(path, pathname))
408  return -EFAULT;
409 
410  // Adjust path for cwd and redirection
411  path = p->checkPathRedirect(path);
412 
413  BufferArg buf(buf_ptr, bufsiz);
414 
415  int result = -1;
416  if (path != "/proc/self/exe") {
417  result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz);
418  } else {
419  // Emulate readlink() called on '/proc/self/exe' should return the
420  // absolute path of the binary running in the simulated system (the
421  // Process' executable). It is possible that using this path in
422  // the simulated system will result in unexpected behavior if:
423  // 1) One binary runs another (e.g., -c time -o "my_binary"), and
424  // called binary calls readlink().
425  // 2) The host's full path to the running benchmark changes from one
426  // simulation to another. This can result in different simulated
427  // performance since the simulated system will process the binary
428  // path differently, even if the binary itself does not change.
429 
430  // Get the absolute canonical path to the running application
431  char real_path[PATH_MAX];
432  char *check_real_path = realpath(p->progName(), real_path);
433  if (!check_real_path) {
434  fatal("readlink('/proc/self/exe') unable to resolve path to "
435  "executable: %s", p->progName());
436  }
437  strncpy((char*)buf.bufferPtr(), real_path, bufsiz);
438  size_t real_path_len = strlen(real_path);
439  if (real_path_len > bufsiz) {
440  // readlink will truncate the contents of the
441  // path to ensure it is no more than bufsiz
442  result = bufsiz;
443  } else {
444  result = real_path_len;
445  }
446 
447  // Issue a warning about potential unexpected results
448  warn_once("readlink() called on '/proc/self/exe' may yield unexpected "
449  "results in various settings.\n Returning '%s'\n",
450  (char*)buf.bufferPtr());
451  }
452 
453  buf.copyOut(tc->getVirtProxy());
454 
455  return (result == -1) ? -errno : result;
456 }
457 
458 SyscallReturn
460 {
461  std::string path;
462  auto p = tc->getProcessPtr();
463 
464  if (!tc->getVirtProxy().tryReadString(path, pathname))
465  return -EFAULT;
466 
467  path = p->checkPathRedirect(path);
468 
469  int result = unlink(path.c_str());
470  return (result == -1) ? -errno : result;
471 }
472 
473 SyscallReturn
475  VPtr<> pathname, VPtr<> new_pathname)
476 {
477  std::string path;
478  std::string new_path;
479  auto p = tc->getProcessPtr();
480 
481  auto &virt_mem = tc->getVirtProxy();
482  if (!virt_mem.tryReadString(path, pathname))
483  return -EFAULT;
484  if (!virt_mem.tryReadString(new_path, new_pathname))
485  return -EFAULT;
486 
487  path = p->absolutePath(path, true);
488  new_path = p->absolutePath(new_path, true);
489 
490  int result = link(path.c_str(), new_path.c_str());
491  return (result == -1) ? -errno : result;
492 }
493 
494 SyscallReturn
496  VPtr<> pathname, VPtr<> new_pathname)
497 {
498  std::string path;
499  std::string new_path;
500  auto p = tc->getProcessPtr();
501 
502  auto &virt_mem = tc->getVirtProxy();
503  if (!virt_mem.tryReadString(path, pathname))
504  return -EFAULT;
505  if (!virt_mem.tryReadString(new_path, new_pathname))
506  return -EFAULT;
507 
508  path = p->absolutePath(path, true);
509  new_path = p->absolutePath(new_path, true);
510 
511  int result = symlink(path.c_str(), new_path.c_str());
512  return (result == -1) ? -errno : result;
513 }
514 
515 SyscallReturn
516 mkdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
517 {
518  auto p = tc->getProcessPtr();
519  std::string path;
520  if (!tc->getVirtProxy().tryReadString(path, pathname))
521  return -EFAULT;
522 
523  path = p->checkPathRedirect(path);
524 
525  auto result = mkdir(path.c_str(), mode);
526  return (result == -1) ? -errno : result;
527 }
528 
529 SyscallReturn
531  VPtr<> newpath)
532 {
533  auto p = tc->getProcessPtr();
534 
535  std::string old_name;
536  if (!tc->getVirtProxy().tryReadString(old_name, oldpath))
537  return -EFAULT;
538 
539  std::string new_name;
540  if (!tc->getVirtProxy().tryReadString(new_name, newpath))
541  return -EFAULT;
542 
543  // Adjust path for cwd and redirection
544  old_name = p->checkPathRedirect(old_name);
545  new_name = p->checkPathRedirect(new_name);
546 
547  int64_t result = rename(old_name.c_str(), new_name.c_str());
548  return (result == -1) ? -errno : result;
549 }
550 
551 SyscallReturn
553  off_t length)
554 {
555  std::string path;
556  auto p = tc->getProcessPtr();
557 
558  if (!tc->getVirtProxy().tryReadString(path, pathname))
559  return -EFAULT;
560 
561  // Adjust path for cwd and redirection
562  path = p->checkPathRedirect(path);
563 
564  int result = truncate(path.c_str(), length);
565  return (result == -1) ? -errno : result;
566 }
567 
568 SyscallReturn
569 ftruncateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, off_t length)
570 {
571  auto p = tc->getProcessPtr();
572 
573  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
574  if (!ffdp)
575  return -EBADF;
576  int sim_fd = ffdp->getSimFD();
577 
578  int result = ftruncate(sim_fd, length);
579  return (result == -1) ? -errno : result;
580 }
581 
582 SyscallReturn
584  VPtr<> pathname, int64_t length)
585 {
586  auto process = tc->getProcessPtr();
587  std::string path;
588 
589  if (!tc->getVirtProxy().tryReadString(path, pathname))
590  return -EFAULT;
591 
592  // Adjust path for cwd and redirection
593  path = process->checkPathRedirect(path);
594 
595 #if NO_STAT64
596  int result = truncate(path.c_str(), length);
597 #else
598  int result = truncate64(path.c_str(), length);
599 #endif
600  return (result == -1) ? -errno : result;
601 }
602 
603 SyscallReturn
605  int tgt_fd, int64_t length)
606 {
607  auto p = tc->getProcessPtr();
608 
609  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
610  if (!ffdp)
611  return -EBADF;
612  int sim_fd = ffdp->getSimFD();
613 
614 #if NO_STAT64
615  int result = ftruncate(sim_fd, length);
616 #else
617  int result = ftruncate64(sim_fd, length);
618 #endif
619  return (result == -1) ? -errno : result;
620 }
621 
622 SyscallReturn
624 {
625  // Letting the simulated program change the simulator's umask seems like
626  // a bad idea. Compromise by just returning the current umask but not
627  // changing anything.
628  mode_t oldMask = umask(0);
629  umask(oldMask);
630  return (int)oldMask;
631 }
632 
633 SyscallReturn
635  VPtr<> pathname, uint32_t owner, uint32_t group)
636 {
637  std::string path;
638  auto p = tc->getProcessPtr();
639 
640  if (!tc->getVirtProxy().tryReadString(path, pathname))
641  return -EFAULT;
642 
643  /* XXX endianess */
644  uid_t hostOwner = owner;
645  gid_t hostGroup = group;
646 
647  // Adjust path for cwd and redirection
648  path = p->checkPathRedirect(path);
649 
650  int result = chown(path.c_str(), hostOwner, hostGroup);
651  return (result == -1) ? -errno : result;
652 }
653 
654 SyscallReturn
656  int tgt_fd, uint32_t owner, uint32_t group)
657 {
658  auto p = tc->getProcessPtr();
659 
660  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
661  if (!ffdp)
662  return -EBADF;
663  int sim_fd = ffdp->getSimFD();
664 
665  /* XXX endianess */
666  uid_t hostOwner = owner;
667  gid_t hostGroup = group;
668 
669  int result = fchown(sim_fd, hostOwner, hostGroup);
670  return (result == -1) ? -errno : result;
671 }
672 
679 SyscallReturn
680 dupFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
681 {
682  auto p = tc->getProcessPtr();
683 
684  auto old_hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
685  if (!old_hbfdp)
686  return -EBADF;
687  int sim_fd = old_hbfdp->getSimFD();
688 
689  int result = dup(sim_fd);
690  if (result == -1)
691  return -errno;
692 
693  auto new_hbfdp = std::dynamic_pointer_cast<HBFDEntry>(old_hbfdp->clone());
694  new_hbfdp->setSimFD(result);
695  new_hbfdp->setCOE(false);
696  return p->fds->allocFD(new_hbfdp);
697 }
698 
699 SyscallReturn
700 dup2Func(SyscallDesc *desc, ThreadContext *tc, int old_tgt_fd, int new_tgt_fd)
701 {
702  auto p = tc->getProcessPtr();
703  auto old_hbp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[old_tgt_fd]);
704  if (!old_hbp)
705  return -EBADF;
706  int old_sim_fd = old_hbp->getSimFD();
707 
713  int res_fd = dup2(old_sim_fd, open("/dev/null", O_RDONLY));
714  if (res_fd == -1)
715  return -errno;
716 
717  auto new_hbp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[new_tgt_fd]);
718  if (new_hbp)
719  p->fds->closeFDEntry(new_tgt_fd);
720  new_hbp = std::dynamic_pointer_cast<HBFDEntry>(old_hbp->clone());
721  new_hbp->setSimFD(res_fd);
722  new_hbp->setCOE(false);
723 
724  return p->fds->allocFD(new_hbp);
725 }
726 
727 SyscallReturn
729  int tgt_fd, int cmd, guest_abi::VarArgs<int> varargs)
730 {
731  auto p = tc->getProcessPtr();
732 
733  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
734  if (!hbfdp)
735  return -EBADF;
736  int sim_fd = hbfdp->getSimFD();
737 
738  int coe = hbfdp->getCOE();
739 
740  switch (cmd) {
741  case F_GETFD:
742  return coe & FD_CLOEXEC;
743 
744  case F_SETFD: {
745  int arg = varargs.get<int>();
746  arg ? hbfdp->setCOE(true) : hbfdp->setCOE(false);
747  return 0;
748  }
749 
750  // Rely on the host to maintain the file status flags for this file
751  // description rather than maintain it ourselves. Admittedly, this
752  // is suboptimal (and possibly error prone), but it is difficult to
753  // maintain the flags by tracking them across the different descriptors
754  // (that refer to this file description) caused by clone, dup, and
755  // subsequent fcntls.
756  case F_GETFL:
757  case F_SETFL: {
758  int arg = varargs.get<int>();
759  int rv = fcntl(sim_fd, cmd, arg);
760  return (rv == -1) ? -errno : rv;
761  }
762 
763  default:
764  warn("fcntl: unsupported command %d\n", cmd);
765  return 0;
766  }
767 }
768 
769 SyscallReturn
770 fcntl64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd)
771 {
772  auto p = tc->getProcessPtr();
773 
774  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
775  if (!hbfdp)
776  return -EBADF;
777  int sim_fd = hbfdp->getSimFD();
778 
779  switch (cmd) {
780  case 33: //F_GETLK64
781  warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", tgt_fd);
782  return -EMFILE;
783 
784  case 34: // F_SETLK64
785  case 35: // F_SETLKW64
786  warn("fcntl64(%d, F_SETLK(W)64) not supported, error returned\n",
787  tgt_fd);
788  return -EMFILE;
789 
790  default:
791  // not sure if this is totally valid, but we'll pass it through
792  // to the underlying OS
793  warn("fcntl64(%d, %d) passed through to host\n", tgt_fd, cmd);
794  return fcntl(sim_fd, cmd);
795  }
796 }
797 
798 SyscallReturn
800 {
801  return pipe2Func(desc, tc, 0, 0);
802 }
803 
804 SyscallReturn
806 {
807  return pipe2Func(desc, tc, tgt_addr, 0);
808 }
809 
810 SyscallReturn
811 pipe2Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr, int flags)
812 {
813  auto p = tc->getProcessPtr();
814 
815  int sim_fds[2], tgt_fds[2];
816 
817  int pipe_retval = pipe(sim_fds);
818  if (pipe_retval == -1)
819  return -errno;
820 
821  auto rend = PipeFDEntry::EndType::read;
822  auto rpfd = std::make_shared<PipeFDEntry>(sim_fds[0], O_WRONLY, rend);
823  tgt_fds[0] = p->fds->allocFD(rpfd);
824  int sim_fd_rpfd = rpfd->getSimFD();
825 
826  auto wend = PipeFDEntry::EndType::write;
827  auto wpfd = std::make_shared<PipeFDEntry>(sim_fds[1], O_RDONLY, wend);
828  tgt_fds[1] = p->fds->allocFD(wpfd);
829  int sim_fd_wpfd = wpfd->getSimFD();
830 
835  rpfd->setPipeReadSource(tgt_fds[1]);
836 
842  if (tgt_addr == 0)
843  return SyscallReturn(tgt_fds[0], tgt_fds[1]);
844 
849  BufferArg tgt_handle(tgt_addr, sizeof(int[2]));
850  int *buf_ptr = (int*)tgt_handle.bufferPtr();
851  buf_ptr[0] = tgt_fds[0];
852  buf_ptr[1] = tgt_fds[1];
853  tgt_handle.copyOut(tc->getVirtProxy());
854 
855  if (flags) {
856  // pipe2 only uses O_NONBLOCK, O_CLOEXEC, and (O_NONBLOCK | O_CLOEXEC)
857  // if flags set to anything else, return EINVAL
858  if ((flags != O_CLOEXEC) && (flags != O_NONBLOCK) &&
859  (flags != (O_CLOEXEC | O_NONBLOCK))) {
860  return -EINVAL;
861  }
862 
863  /*
864  If O_NONBLOCK is passed in as a flag to pipe2, set O_NONBLOCK file
865  status flag for two new open file descriptors.
866  */
867  if (flags & O_NONBLOCK) {
868  /*
869  O_NONBLOCK is set when the programmer wants to avoid a separate
870  call(s) to fcntl in their code, so mirror the fcntl
871  implementation for handling file descriptors -- rely on host to
872  maintain file status flags.
873  */
874  if (fcntl(sim_fd_rpfd, F_SETFL, O_NONBLOCK)) {
875  return -errno;
876  }
877  if (fcntl(sim_fd_wpfd, F_SETFL, O_NONBLOCK)) {
878  return -errno;
879  }
880  }
881 
882  /*
883  If O_CLOEXEC is passed in as a flag to pipe2, set close-on-exec
884  (FD_CLOEXEC) file status flag for two new open file descriptors.
885  */
886  if (flags & O_CLOEXEC) {
887  rpfd->setCOE(true);
888  wpfd->setCOE(true);
889  }
890  }
891 
892  return 0;
893 }
894 
895 SyscallReturn
897 {
898  auto process = tc->getProcessPtr();
899  return process->pgid();
900 }
901 
902 SyscallReturn
903 setpgidFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int pgid)
904 {
905  auto process = tc->getProcessPtr();
906 
907  if (pgid < 0)
908  return -EINVAL;
909 
910  if (pid == 0) {
911  process->pgid(process->pid());
912  return 0;
913  }
914 
915  Process *matched_ph = nullptr;
916  System *sysh = tc->getSystemPtr();
917 
918  // Retrieves process pointer from active/suspended thread contexts.
919  for (auto *tc: sysh->threads) {
920  if (tc->status() != ThreadContext::Halted) {
921  Process *temp_h = tc->getProcessPtr();
922  Process *walk_ph = (Process*)temp_h;
923 
924  if (walk_ph && walk_ph->pid() == process->pid())
925  matched_ph = walk_ph;
926  }
927  }
928 
929  assert(matched_ph);
930  matched_ph->pgid((pgid == 0) ? matched_ph->pid() : pgid);
931 
932  return 0;
933 }
934 
935 
936 SyscallReturn
938 {
939  auto process = tc->getProcessPtr();
940  return process->tgid();
941 }
942 
943 SyscallReturn
945 {
946  auto process = tc->getProcessPtr();
947  return process->pid();
948 }
949 
950 SyscallReturn
952 {
953  auto process = tc->getProcessPtr();
954  return process->ppid();
955 }
956 
957 SyscallReturn
959 {
960  auto process = tc->getProcessPtr();
961  return process->uid(); // UID
962 }
963 
964 SyscallReturn
966 {
967  auto process = tc->getProcessPtr();
968  return process->euid(); // UID
969 }
970 
971 SyscallReturn
973 {
974  auto process = tc->getProcessPtr();
975  return process->gid();
976 }
977 
978 SyscallReturn
980 {
981  auto process = tc->getProcessPtr();
982  return process->egid();
983 }
984 
985 SyscallReturn
987  int tgt_fd, int mode, off_t offset, off_t len)
988 {
989 #if defined(__linux__)
990  auto p = tc->getProcessPtr();
991 
992  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
993  if (!ffdp)
994  return -EBADF;
995  int sim_fd = ffdp->getSimFD();
996 
997  int result = fallocate(sim_fd, mode, offset, len);
998  if (result < 0)
999  return -errno;
1000  return 0;
1001 #else
1002  warnUnsupportedOS("fallocate");
1003  return -1;
1004 #endif
1005 }
1006 
1007 SyscallReturn
1009  VPtr<> pathname, mode_t mode)
1010 {
1011  std::string path;
1012  auto p = tc->getProcessPtr();
1013  if (!tc->getVirtProxy().tryReadString(path, pathname))
1014  return -EFAULT;
1015 
1016  // Adjust path for cwd and redirection
1017  path = p->checkPathRedirect(path);
1018 
1019  int result = access(path.c_str(), mode);
1020  return (result == -1) ? -errno : result;
1021 }
1022 
1023 SyscallReturn
1025  VPtr<> pathname, mode_t mode, dev_t dev)
1026 {
1027  auto p = tc->getProcessPtr();
1028  std::string path;
1029  if (!tc->getVirtProxy().tryReadString(path, pathname))
1030  return -EFAULT;
1031 
1032  path = p->checkPathRedirect(path);
1033 
1034  auto result = mknod(path.c_str(), mode, dev);
1035  return (result == -1) ? -errno : result;
1036 }
1037 
1038 SyscallReturn
1040 {
1041  auto p = tc->getProcessPtr();
1042  std::string path;
1043  if (!tc->getVirtProxy().tryReadString(path, pathname))
1044  return -EFAULT;
1045 
1046  std::string tgt_cwd;
1047  if (startswith(path, "/")) {
1048  tgt_cwd = path;
1049  } else {
1050  char buf[PATH_MAX];
1051  tgt_cwd = realpath((p->tgtCwd + "/" + path).c_str(), buf);
1052  }
1053  std::string host_cwd = p->checkPathRedirect(tgt_cwd);
1054 
1055  int result = chdir(host_cwd.c_str());
1056 
1057  if (result == -1)
1058  return -errno;
1059 
1060  p->hostCwd = host_cwd;
1061  p->tgtCwd = tgt_cwd;
1062  return result;
1063 }
1064 
1065 SyscallReturn
1067 {
1068  auto p = tc->getProcessPtr();
1069  std::string path;
1070  if (!tc->getVirtProxy().tryReadString(path, pathname))
1071  return -EFAULT;
1072 
1073  path = p->checkPathRedirect(path);
1074 
1075  auto result = rmdir(path.c_str());
1076  return (result == -1) ? -errno : result;
1077 }
1078 
1079 #if defined(SYS_getdents) || defined(SYS_getdents64)
1080 template<typename DE, int SYS_NUM>
1081 static SyscallReturn
1082 getdentsImpl(SyscallDesc *desc, ThreadContext *tc,
1083  int tgt_fd, VPtr<> buf_ptr, unsigned count)
1084 {
1085  auto p = tc->getProcessPtr();
1086 
1087  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1088  if (!hbfdp)
1089  return -EBADF;
1090  int sim_fd = hbfdp->getSimFD();
1091 
1092  BufferArg buf_arg(buf_ptr, count);
1093  auto status = syscall(SYS_NUM, sim_fd, buf_arg.bufferPtr(), count);
1094 
1095  if (status == -1)
1096  return -errno;
1097 
1098  unsigned traversed = 0;
1099  while (traversed < status) {
1100  DE *buffer = (DE*)((Addr)buf_arg.bufferPtr() + traversed);
1101 
1102  auto host_reclen = buffer->d_reclen;
1103 
1109  const ByteOrder bo = tc->getSystemPtr()->getGuestByteOrder();
1110  buffer->d_ino = htog(buffer->d_ino, bo);
1111  buffer->d_off = htog(buffer->d_off, bo);
1112  buffer->d_reclen = htog(buffer->d_reclen, bo);
1113 
1114  traversed += host_reclen;
1115  }
1116 
1117  buf_arg.copyOut(tc->getVirtProxy());
1118  return status;
1119 }
1120 #endif
1121 
1122 #if defined(SYS_getdents)
1123 SyscallReturn
1124 getdentsFunc(SyscallDesc *desc, ThreadContext *tc,
1125  int tgt_fd, VPtr<> buf_ptr, unsigned count)
1126 {
1127  typedef struct linux_dirent
1128  {
1129  unsigned long d_ino;
1130  unsigned long d_off;
1131  unsigned short d_reclen;
1132  char dname[];
1133  } LinDent;
1134 
1135  return getdentsImpl<LinDent, SYS_getdents>(desc, tc,
1136  tgt_fd, buf_ptr, count);
1137 }
1138 #endif
1139 
1140 #if defined(SYS_getdents64)
1141 SyscallReturn
1142 getdents64Func(SyscallDesc *desc, ThreadContext *tc,
1143  int tgt_fd, VPtr<> buf_ptr, unsigned count)
1144 {
1145  typedef struct linux_dirent64
1146  {
1147  ino64_t d_ino;
1148  off64_t d_off;
1149  unsigned short d_reclen;
1150  char dname[];
1151  } LinDent64;
1152 
1153  return getdentsImpl<LinDent64, SYS_getdents64>(desc, tc,
1154  tgt_fd, buf_ptr, count);
1155 }
1156 #endif
1157 
1158 SyscallReturn
1159 shutdownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int how)
1160 {
1161  auto p = tc->getProcessPtr();
1162 
1163  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1164  if (!sfdp)
1165  return -EBADF;
1166  int sim_fd = sfdp->getSimFD();
1167 
1168  int retval = shutdown(sim_fd, how);
1169 
1170  return (retval == -1) ? -errno : retval;
1171 }
1172 
1173 SyscallReturn
1175  int tgt_fd, VPtr<> buf_ptr, int addrlen)
1176 {
1177  auto p = tc->getProcessPtr();
1178 
1179  BufferArg bufSock(buf_ptr, addrlen);
1180  bufSock.copyIn(tc->getVirtProxy());
1181 
1182  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1183  if (!sfdp)
1184  return -EBADF;
1185  int sim_fd = sfdp->getSimFD();
1186 
1187  int status = ::bind(sim_fd,
1188  (struct sockaddr *)bufSock.bufferPtr(),
1189  addrlen);
1190 
1191  return (status == -1) ? -errno : status;
1192 }
1193 
1194 SyscallReturn
1195 listenFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int backlog)
1196 {
1197  auto p = tc->getProcessPtr();
1198 
1199  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1200  if (!sfdp)
1201  return -EBADF;
1202  int sim_fd = sfdp->getSimFD();
1203 
1204  int status = listen(sim_fd, backlog);
1205 
1206  return (status == -1) ? -errno : status;
1207 }
1208 
1209 SyscallReturn
1211  int tgt_fd, VPtr<> buf_ptr, int addrlen)
1212 {
1213  auto p = tc->getProcessPtr();
1214 
1215  BufferArg addr(buf_ptr, addrlen);
1216  addr.copyIn(tc->getVirtProxy());
1217 
1218  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1219  if (!sfdp)
1220  return -EBADF;
1221  int sim_fd = sfdp->getSimFD();
1222 
1223  int status = connect(sim_fd,
1224  (struct sockaddr *)addr.bufferPtr(),
1225  (socklen_t)addrlen);
1226 
1227  return (status == -1) ? -errno : status;
1228 }
1229 
1230 SyscallReturn
1232  int tgt_fd, VPtr<> bufrPtr, size_t bufrLen, int flags,
1233  VPtr<> addrPtr, VPtr<> addrlenPtr)
1234 {
1235  auto p = tc->getProcessPtr();
1236 
1237  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1238  if (!sfdp)
1239  return -EBADF;
1240  int sim_fd = sfdp->getSimFD();
1241 
1242  // Reserve buffer space.
1243  BufferArg bufrBuf(bufrPtr, bufrLen);
1244 
1245  // Get address length.
1246  socklen_t addrLen = 0;
1247  if (addrlenPtr != 0) {
1248  // Read address length parameter.
1249  BufferArg addrlenBuf(addrlenPtr, sizeof(socklen_t));
1250  addrlenBuf.copyIn(tc->getVirtProxy());
1251  addrLen = *((socklen_t *)addrlenBuf.bufferPtr());
1252  }
1253 
1254  struct sockaddr sa, *sap = NULL;
1255  if (addrLen != 0) {
1256  BufferArg addrBuf(addrPtr, addrLen);
1257  addrBuf.copyIn(tc->getVirtProxy());
1258  memcpy(&sa, (struct sockaddr *)addrBuf.bufferPtr(),
1259  sizeof(struct sockaddr));
1260  sap = &sa;
1261  }
1262 
1263  ssize_t recvd_size = recvfrom(sim_fd,
1264  (void *)bufrBuf.bufferPtr(),
1265  bufrLen, flags, sap, (socklen_t *)&addrLen);
1266 
1267  if (recvd_size == -1)
1268  return -errno;
1269 
1270  // Pass the received data out.
1271  bufrBuf.copyOut(tc->getVirtProxy());
1272 
1273  // Copy address to addrPtr and pass it on.
1274  if (sap != NULL) {
1275  BufferArg addrBuf(addrPtr, addrLen);
1276  memcpy(addrBuf.bufferPtr(), sap, sizeof(sa));
1277  addrBuf.copyOut(tc->getVirtProxy());
1278  }
1279 
1280  // Copy len to addrlenPtr and pass it on.
1281  if (addrLen != 0) {
1282  BufferArg addrlenBuf(addrlenPtr, sizeof(socklen_t));
1283  *(socklen_t *)addrlenBuf.bufferPtr() = addrLen;
1284  addrlenBuf.copyOut(tc->getVirtProxy());
1285  }
1286 
1287  return recvd_size;
1288 }
1289 
1290 SyscallReturn
1292  int tgt_fd, VPtr<> bufrPtr, size_t bufrLen, int flags,
1293  VPtr<> addrPtr, socklen_t addrLen)
1294 {
1295  auto p = tc->getProcessPtr();
1296 
1297  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1298  if (!sfdp)
1299  return -EBADF;
1300  int sim_fd = sfdp->getSimFD();
1301 
1302  // Reserve buffer space.
1303  BufferArg bufrBuf(bufrPtr, bufrLen);
1304  bufrBuf.copyIn(tc->getVirtProxy());
1305 
1306  struct sockaddr sa, *sap = nullptr;
1307  memset(&sa, 0, sizeof(sockaddr));
1308  if (addrLen != 0) {
1309  BufferArg addrBuf(addrPtr, addrLen);
1310  addrBuf.copyIn(tc->getVirtProxy());
1311  memcpy(&sa, (sockaddr*)addrBuf.bufferPtr(), addrLen);
1312  sap = &sa;
1313  }
1314 
1315  ssize_t sent_size = sendto(sim_fd,
1316  (void *)bufrBuf.bufferPtr(),
1317  bufrLen, flags, sap, (socklen_t)addrLen);
1318 
1319  return (sent_size == -1) ? -errno : sent_size;
1320 }
1321 
1322 SyscallReturn
1324  int tgt_fd, VPtr<> msgPtr, int flags)
1325 {
1326  auto p = tc->getProcessPtr();
1327 
1328  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1329  if (!sfdp)
1330  return -EBADF;
1331  int sim_fd = sfdp->getSimFD();
1332 
1356  BufferArg msgBuf(msgPtr, sizeof(struct msghdr));
1357  msgBuf.copyIn(tc->getVirtProxy());
1358  struct msghdr *msgHdr = (struct msghdr *)msgBuf.bufferPtr();
1359 
1365  Addr msg_name_phold = 0;
1366  Addr msg_iov_phold = 0;
1367  Addr iovec_base_phold[msgHdr->msg_iovlen];
1368  Addr msg_control_phold = 0;
1369 
1373  BufferArg *nameBuf = NULL;
1374  if (msgHdr->msg_name) {
1375  /*1*/msg_name_phold = (Addr)msgHdr->msg_name;
1376  /*2*/nameBuf = new BufferArg(msg_name_phold, msgHdr->msg_namelen);
1377  /*3*/nameBuf->copyIn(tc->getVirtProxy());
1378  /*4*/msgHdr->msg_name = nameBuf->bufferPtr();
1379  }
1380 
1386  BufferArg *iovBuf = NULL;
1387  BufferArg *iovecBuf[msgHdr->msg_iovlen];
1388  for (int i = 0; i < msgHdr->msg_iovlen; i++) {
1389  iovec_base_phold[i] = 0;
1390  iovecBuf[i] = NULL;
1391  }
1392 
1393  if (msgHdr->msg_iov) {
1394  /*1*/msg_iov_phold = (Addr)msgHdr->msg_iov;
1395  /*2*/iovBuf = new BufferArg(msg_iov_phold, msgHdr->msg_iovlen *
1396  sizeof(struct iovec));
1397  /*3*/iovBuf->copyIn(tc->getVirtProxy());
1398  for (int i = 0; i < msgHdr->msg_iovlen; i++) {
1399  if (((struct iovec *)iovBuf->bufferPtr())[i].iov_base) {
1400  /*1*/iovec_base_phold[i] =
1401  (Addr)((struct iovec *)iovBuf->bufferPtr())[i].iov_base;
1402  /*2*/iovecBuf[i] = new BufferArg(iovec_base_phold[i],
1403  ((struct iovec *)iovBuf->bufferPtr())[i].iov_len);
1404  /*3*/iovecBuf[i]->copyIn(tc->getVirtProxy());
1405  /*4*/((struct iovec *)iovBuf->bufferPtr())[i].iov_base =
1406  iovecBuf[i]->bufferPtr();
1407  }
1408  }
1409  /*4*/msgHdr->msg_iov = (struct iovec *)iovBuf->bufferPtr();
1410  }
1411 
1415  BufferArg *controlBuf = NULL;
1416  if (msgHdr->msg_control) {
1417  /*1*/msg_control_phold = (Addr)msgHdr->msg_control;
1418  /*2*/controlBuf = new BufferArg(msg_control_phold,
1419  CMSG_ALIGN(msgHdr->msg_controllen));
1420  /*3*/controlBuf->copyIn(tc->getVirtProxy());
1421  /*4*/msgHdr->msg_control = controlBuf->bufferPtr();
1422  }
1423 
1424  ssize_t recvd_size = recvmsg(sim_fd, msgHdr, flags);
1425 
1426  if (recvd_size < 0)
1427  return -errno;
1428 
1429  if (msgHdr->msg_name) {
1430  nameBuf->copyOut(tc->getVirtProxy());
1431  delete(nameBuf);
1432  msgHdr->msg_name = (void *)msg_name_phold;
1433  }
1434 
1435  if (msgHdr->msg_iov) {
1436  for (int i = 0; i< msgHdr->msg_iovlen; i++) {
1437  if (((struct iovec *)iovBuf->bufferPtr())[i].iov_base) {
1438  iovecBuf[i]->copyOut(tc->getVirtProxy());
1439  delete iovecBuf[i];
1440  ((struct iovec *)iovBuf->bufferPtr())[i].iov_base =
1441  (void *)iovec_base_phold[i];
1442  }
1443  }
1444  iovBuf->copyOut(tc->getVirtProxy());
1445  delete iovBuf;
1446  msgHdr->msg_iov = (struct iovec *)msg_iov_phold;
1447  }
1448 
1449  if (msgHdr->msg_control) {
1450  controlBuf->copyOut(tc->getVirtProxy());
1451  delete(controlBuf);
1452  msgHdr->msg_control = (void *)msg_control_phold;
1453  }
1454 
1455  msgBuf.copyOut(tc->getVirtProxy());
1456 
1457  return recvd_size;
1458 }
1459 
1460 SyscallReturn
1462  int tgt_fd, VPtr<> msgPtr, int flags)
1463 {
1464  auto p = tc->getProcessPtr();
1465 
1466  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1467  if (!sfdp)
1468  return -EBADF;
1469  int sim_fd = sfdp->getSimFD();
1470 
1474  BufferArg msgBuf(msgPtr, sizeof(struct msghdr));
1475  msgBuf.copyIn(tc->getVirtProxy());
1476  struct msghdr msgHdr = *((struct msghdr *)msgBuf.bufferPtr());
1477 
1482  struct iovec *iovPtr = msgHdr.msg_iov;
1483  BufferArg iovBuf((Addr)iovPtr, sizeof(struct iovec) * msgHdr.msg_iovlen);
1484  iovBuf.copyIn(tc->getVirtProxy());
1485  struct iovec *iov = (struct iovec *)iovBuf.bufferPtr();
1486  msgHdr.msg_iov = iov;
1487 
1493  BufferArg **bufferArray = (BufferArg **)malloc(msgHdr.msg_iovlen
1494  * sizeof(BufferArg *));
1495 
1501  for (int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
1502  Addr basePtr = (Addr) iov[iovIndex].iov_base;
1503  bufferArray[iovIndex] = new BufferArg(basePtr, iov[iovIndex].iov_len);
1504  bufferArray[iovIndex]->copyIn(tc->getVirtProxy());
1505  iov[iovIndex].iov_base = bufferArray[iovIndex]->bufferPtr();
1506  }
1507 
1508  ssize_t sent_size = sendmsg(sim_fd, &msgHdr, flags);
1509  int local_errno = errno;
1510 
1514  for (int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
1515  BufferArg *baseBuf = ( BufferArg *)bufferArray[iovIndex];
1516  delete(baseBuf);
1517  }
1518 
1522  free(bufferArray);
1523 
1524  return (sent_size < 0) ? -local_errno : sent_size;
1525 }
1526 
1527 SyscallReturn
1529  int tgt_fd, int level, int optname, VPtr<> valPtr,
1530  VPtr<> lenPtr)
1531 {
1532  // union of all possible return value types from getsockopt
1533  union val
1534  {
1535  int i_val;
1536  long l_val;
1537  struct linger linger_val;
1538  struct timeval timeval_val;
1539  } val;
1540 
1541  auto p = tc->getProcessPtr();
1542 
1543  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1544  if (!sfdp)
1545  return -EBADF;
1546  int sim_fd = sfdp->getSimFD();
1547 
1548  socklen_t len = sizeof(val);
1549  int status = getsockopt(sim_fd, level, optname, &val, &len);
1550 
1551  if (status == -1)
1552  return -errno;
1553 
1554  // copy val to valPtr and pass it on
1555  BufferArg valBuf(valPtr, sizeof(val));
1556  memcpy(valBuf.bufferPtr(), &val, sizeof(val));
1557  valBuf.copyOut(tc->getVirtProxy());
1558 
1559  // copy len to lenPtr and pass it on
1560  BufferArg lenBuf(lenPtr, sizeof(len));
1561  memcpy(lenBuf.bufferPtr(), &len, sizeof(len));
1562  lenBuf.copyOut(tc->getVirtProxy());
1563 
1564  return status;
1565 }
1566 
1567 SyscallReturn
1569  int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
1570 {
1571  auto p = tc->getProcessPtr();
1572 
1573  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1574  if (!sfdp)
1575  return -EBADF;
1576  int sim_fd = sfdp->getSimFD();
1577 
1578  // lenPtr is an in-out paramenter:
1579  // sending the address length in, conveying the final length out
1580 
1581  // Read in the value of len from the passed pointer.
1582  BufferArg lenBuf(lenPtr, sizeof(socklen_t));
1583  lenBuf.copyIn(tc->getVirtProxy());
1584  socklen_t len = *(socklen_t *)lenBuf.bufferPtr();
1585 
1586  struct sockaddr sa;
1587  int status = getsockname(sim_fd, &sa, &len);
1588 
1589  if (status == -1)
1590  return -errno;
1591 
1592  // Copy address to addrPtr and pass it on.
1593  BufferArg addrBuf(addrPtr, sizeof(sa));
1594  memcpy(addrBuf.bufferPtr(), &sa, sizeof(sa));
1595  addrBuf.copyOut(tc->getVirtProxy());
1596 
1597  // Copy len to lenPtr and pass it on.
1598  *(socklen_t *)lenBuf.bufferPtr() = len;
1599  lenBuf.copyOut(tc->getVirtProxy());
1600 
1601  return status;
1602 }
1603 
1604 SyscallReturn
1606  int tgt_fd, VPtr<> sockAddrPtr, VPtr<> addrlenPtr)
1607 {
1608  auto p = tc->getProcessPtr();
1609 
1610  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1611  if (!sfdp)
1612  return -EBADF;
1613  int sim_fd = sfdp->getSimFD();
1614 
1615  BufferArg bufAddrlen(addrlenPtr, sizeof(unsigned));
1616  bufAddrlen.copyIn(tc->getVirtProxy());
1617  BufferArg bufSock(sockAddrPtr, *(unsigned *)bufAddrlen.bufferPtr());
1618 
1619  int retval = getpeername(sim_fd,
1620  (struct sockaddr *)bufSock.bufferPtr(),
1621  (unsigned *)bufAddrlen.bufferPtr());
1622 
1623  if (retval != -1) {
1624  bufSock.copyOut(tc->getVirtProxy());
1625  bufAddrlen.copyOut(tc->getVirtProxy());
1626  }
1627 
1628  return (retval == -1) ? -errno : retval;
1629 }
1630 
1631 SyscallReturn
1633  int tgt_fd, int level, int optname, VPtr<> valPtr,
1634  socklen_t len)
1635 {
1636  auto p = tc->getProcessPtr();
1637 
1638  BufferArg valBuf(valPtr, len);
1639  valBuf.copyIn(tc->getVirtProxy());
1640 
1641  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1642  if (!sfdp)
1643  return -EBADF;
1644  int sim_fd = sfdp->getSimFD();
1645 
1646  int status = setsockopt(sim_fd, level, optname,
1647  (struct sockaddr *)valBuf.bufferPtr(), len);
1648 
1649  return (status == -1) ? -errno : status;
1650 }
1651 
1652 SyscallReturn
1654  VPtr<uint32_t> cpu, VPtr<uint32_t> node, VPtr<uint32_t> tcache)
1655 {
1656  // unsigned is the same size (4) on all Linux supported ISAs.
1657  if (cpu)
1658  *cpu = htog(tc->contextId(), tc->getSystemPtr()->getGuestByteOrder());
1659 
1660  // Set a fixed NUMA node 0.
1661  if (node)
1662  *node = 0;
1663 
1664  return 0;
1665 }
1666 
1667 } // namespace gem5
gem5::X86ISA::level
Bitfield< 20 > level
Definition: intmessage.hh:51
syscall_debug_macros.hh
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:189
gem5::DistIface::readyToExit
static bool readyToExit(Tick delay)
Initiate the exit from the simulation.
Definition: dist_iface.cc:895
gem5::dupFunc
SyscallReturn dupFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
FIXME: The file description is not shared among file descriptors created with dup.
Definition: syscall_emul.cc:680
gem5::Process::euid
uint64_t euid()
Definition: process.hh:83
gem5::chdirFunc
SyscallReturn chdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Target chdir() handler.
Definition: syscall_emul.cc:1039
gem5::exitFutexWake
static void exitFutexWake(ThreadContext *tc, VPtr<> addr, uint64_t tgid)
Definition: syscall_emul.cc:93
gem5::Process::tgid
uint64_t tgid()
Definition: process.hh:90
gem5::EmulationPageTable::pageSize
Addr pageSize()
Definition: page_table.hh:114
gem5::ThreadContext::getSystemPtr
virtual System * getSystemPtr()=0
gem5::ArmISA::len
Bitfield< 18, 16 > len
Definition: misc_types.hh:444
warn
#define warn(...)
Definition: logging.hh:245
gem5::System::Threads::size
int size() const
Definition: system.hh:216
gem5::listenFunc
SyscallReturn listenFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int backlog)
Definition: syscall_emul.cc:1195
system.hh
gem5::PortProxy::tryReadString
bool tryReadString(std::string &str, Addr addr) const
Reads the string at guest address addr into the std::string str.
Definition: port_proxy.cc:115
gem5::getuidFunc
SyscallReturn getuidFunc(SyscallDesc *desc, ThreadContext *tc)
Definition: syscall_emul.cc:958
gem5::getsockoptFunc
SyscallReturn getsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, VPtr<> lenPtr)
Definition: syscall_emul.cc:1528
gem5::ThreadContext::Halted
@ Halted
Permanently shut down.
Definition: thread_context.hh:121
gem5::SyscallReturn
This class represents the return value from an emulated system call, including any errno setting.
Definition: syscall_return.hh:55
gem5::getpgrpFunc
SyscallReturn getpgrpFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpgrpFunc() handler.
Definition: syscall_emul.cc:896
warn_once
#define warn_once(...)
Definition: logging.hh:249
gem5::bindFunc
SyscallReturn bindFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int addrlen)
Definition: syscall_emul.cc:1174
gem5::fallocateFunc
SyscallReturn fallocateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int mode, off_t offset, off_t len)
Definition: syscall_emul.cc:986
gem5::System::futexMap
FutexMap futexMap
Definition: system.hh:626
gem5::X86ISA::val
Bitfield< 63 > val
Definition: misc.hh:775
gem5::guest_abi::VarArgs::get
Arg get()
Definition: varargs.hh:165
gem5::hostname
const char * hostname
Definition: syscall_emul.cc:358
gem5::startswith
bool startswith(const char *s, const char *prefix)
Return true if 's' starts with the prefix string 'prefix'.
Definition: str.hh:242
gem5::mkdirFunc
SyscallReturn mkdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target mkdir() handler.
Definition: syscall_emul.cc:516
gem5::exitImpl
static SyscallReturn exitImpl(SyscallDesc *desc, ThreadContext *tc, bool group, int status)
Definition: syscall_emul.cc:107
gem5::ThreadContext::contextId
virtual ContextID contextId() const =0
gem5::X86ISA::system
Bitfield< 15 > system
Definition: misc.hh:1003
gem5::getcwdFunc
SyscallReturn getcwdFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, unsigned long size)
Target getcwd() handler.
Definition: syscall_emul.cc:371
gem5::ThreadContext::activate
virtual void activate()=0
Set the status to Active.
gem5::Process::egid
uint64_t egid()
Definition: process.hh:85
gem5::brkFunc
SyscallReturn brkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> new_brk)
Target brk() handler: set brk address.
Definition: syscall_emul.cc:257
gem5::Process::pid
uint64_t pid()
Definition: process.hh:86
proxy_ptr.hh
gem5::warnUnsupportedOS
void warnUnsupportedOS(std::string syscall_name)
Definition: syscall_emul.cc:58
gem5::ignoreWarnOnceFunc
SyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, ThreadContext *tc)
Like above, but only prints a warning once per syscall desc it's used with.
Definition: syscall_emul.cc:78
gem5::System::getGuestByteOrder
ByteOrder getGuestByteOrder() const
Get the guest byte order.
Definition: system.hh:401
gem5::ThreadContext::halt
virtual void halt()=0
Set the status to Halted.
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:66
sim_exit.hh
gem5::Process::gid
uint64_t gid()
Definition: process.hh:84
gem5::closeFunc
SyscallReturn closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
Target close() handler.
Definition: syscall_emul.cc:288
gem5::getcpuFunc
SyscallReturn getcpuFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< uint32_t > cpu, VPtr< uint32_t > node, VPtr< uint32_t > tcache)
Definition: syscall_emul.cc:1653
gem5::exitSimLoop
void exitSimLoop(const std::string &message, int exit_code, Tick when, Tick repeat, bool serialize)
Schedule an event to exit the simulation loop (returning to Python) at the end of the current cycle (...
Definition: sim_events.cc:88
gem5::ThreadContext::status
virtual Status status() const =0
gem5::umaskFunc
SyscallReturn umaskFunc(SyscallDesc *desc, ThreadContext *tc)
Target umask() handler.
Definition: syscall_emul.cc:623
gem5::setpgidFunc
SyscallReturn setpgidFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int pgid)
Target setpgid() handler.
Definition: syscall_emul.cc:903
gem5::getpagesizeFunc
SyscallReturn getpagesizeFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpagesize() handler.
Definition: syscall_emul.cc:250
gem5::Process::childClearTID
uint64_t childClearTID
Calls a futex wakeup at the address specified by this pointer when this process exits.
Definition: process.hh:282
gem5::exitGroupFunc
SyscallReturn exitGroupFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit_group() handler: terminate simulation. (exit all threads)
Definition: syscall_emul.cc:244
gem5::Process::uid
uint64_t uid()
Definition: process.hh:82
gem5::getsocknameFunc
SyscallReturn getsocknameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
Definition: syscall_emul.cc:1568
gem5::Process::ppid
uint64_t ppid()
Definition: process.hh:87
gem5::FutexMap
FutexMap class holds a map of all futexes used in the system.
Definition: futex_map.hh:109
gem5::symlinkFunc
SyscallReturn symlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> new_pathname)
Target symlink() handler.
Definition: syscall_emul.cc:495
gem5::System
Definition: system.hh:77
gem5::System::signalList
std::list< BasicSignal > signalList
Definition: system.hh:635
gem5::ThreadContext
ThreadContext is the external interface to all thread state for anything outside of the CPU.
Definition: thread_context.hh:93
gem5::unlinkFunc
SyscallReturn unlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Target unlink() handler.
Definition: syscall_emul.cc:459
gem5::ThreadContext::getVirtProxy
virtual PortProxy & getVirtProxy()=0
gem5::_llseekFunc
SyscallReturn _llseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t offset_high, uint32_t offset_low, VPtr<> result_ptr, int whence)
Target _llseek() handler.
Definition: syscall_emul.cc:312
gem5::ThreadContext::Suspended
@ Suspended
Temporarily inactive.
Definition: thread_context.hh:112
gem5::System::systemList
static std::vector< System * > systemList
Definition: system.hh:621
gem5::getgidFunc
SyscallReturn getgidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getgid() handler.
Definition: syscall_emul.cc:972
gem5::X86ISA::count
count
Definition: misc.hh:709
gem5::Process::pTable
EmulationPageTable * pTable
Definition: process.hh:171
gem5::PowerISA::bo
Bitfield< 25, 21 > bo
Definition: types.hh:82
gem5::truncateFunc
SyscallReturn truncateFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, off_t length)
Target truncate() handler.
Definition: syscall_emul.cc:552
DPRINTF_SYSCALL
#define DPRINTF_SYSCALL(FLAGEXT, FMT,...)
This macro is intended to help with readability.
Definition: syscall_debug_macros.hh:57
gem5::MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:326
process.hh
gem5::BufferArg
BufferArg represents an untyped buffer in target user space that is passed by reference to an (emulat...
Definition: syscall_emul_buf.hh:107
dist_iface.hh
gem5::getegidFunc
SyscallReturn getegidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getegid() handler.
Definition: syscall_emul.cc:979
gem5::FutexMap::wakeup
int wakeup(Addr addr, uint64_t tgid, int count)
Wakes up at most count waiting threads on a futex.
Definition: futex_map.cc:59
gem5::munmapFunc
SyscallReturn munmapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, size_t length)
Target munmap() handler.
Definition: syscall_emul.cc:339
gem5::pipeFunc
SyscallReturn pipeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr)
Target pipe() handler.
Definition: syscall_emul.cc:805
gem5::htog
T htog(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:187
gem5::ProxyPtr
Definition: proxy_ptr.hh:238
gem5::truncate64Func
SyscallReturn truncate64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, int64_t length)
Target truncate64() handler.
Definition: syscall_emul.cc:583
gem5::ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:144
gem5::gettidFunc
SyscallReturn gettidFunc(SyscallDesc *desc, ThreadContext *tc)
Target gettid() handler.
Definition: syscall_emul.cc:944
gem5::Process::checkPathRedirect
std::string checkPathRedirect(const std::string &filename)
Redirect file path if it matches any keys initialized by system object.
Definition: process.cc:417
gem5::setTidAddressFunc
SyscallReturn setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc, uint64_t tidPtr)
Target set_tid_address() handler.
Definition: syscall_emul.cc:279
gem5::fcntlFunc
SyscallReturn fcntlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd, guest_abi::VarArgs< int > varargs)
Target fcntl() handler.
Definition: syscall_emul.cc:728
gem5::readlinkFunc
SyscallReturn readlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> buf_ptr, size_t bufsiz)
Target readlink() handler.
Definition: syscall_emul.cc:401
gem5::connectFunc
SyscallReturn connectFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int addrlen)
Definition: syscall_emul.cc:1210
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::linkFunc
SyscallReturn linkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> new_pathname)
Target link() handler.
Definition: syscall_emul.cc:474
gem5::pipe2Func
SyscallReturn pipe2Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr, int flags)
Target pipe() handler.
Definition: syscall_emul.cc:811
name
const std::string & name()
Definition: trace.cc:49
gem5::accessFunc
SyscallReturn accessFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target access() handler.
Definition: syscall_emul.cc:1008
gem5::sendmsgFunc
SyscallReturn sendmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
Definition: syscall_emul.cc:1461
gem5::gethostnameFunc
SyscallReturn gethostnameFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, int name_len)
Target gethostname() handler.
Definition: syscall_emul.cc:361
gem5::fcntl64Func
SyscallReturn fcntl64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd)
Target fcntl64() handler.
Definition: syscall_emul.cc:770
gem5::recvmsgFunc
SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
Definition: syscall_emul.cc:1323
gem5::BaseBufferArg::copyIn
bool copyIn(const PortProxy &memproxy)
copy data into simulator space (read from target memory)
Definition: syscall_emul_buf.hh:81
gem5::Process
Definition: process.hh:67
gem5::ThreadContext::getProcessPtr
virtual Process * getProcessPtr()=0
gem5::ftruncateFunc
SyscallReturn ftruncateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, off_t length)
Target ftruncate() handler.
Definition: syscall_emul.cc:569
gem5::exitFunc
SyscallReturn exitFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit() handler: terminate current context.
Definition: syscall_emul.cc:238
gem5::BasicSignal
Definition: se_signal.hh:39
syscall_emul.hh
gem5::shutdownFunc
SyscallReturn shutdownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int how)
Target shutdown() handler.
Definition: syscall_emul.cc:1159
gem5::System::threads
Threads threads
Definition: system.hh:316
gem5::BaseBufferArg::copyOut
bool copyOut(const PortProxy &memproxy)
copy data out of simulator space (write to target memory)
Definition: syscall_emul_buf.hh:91
gem5::pipePseudoFunc
SyscallReturn pipePseudoFunc(SyscallDesc *desc, ThreadContext *tc)
Pseudo Funcs - These functions use a different return convension, returning a second value in a regis...
Definition: syscall_emul.cc:799
gem5::rmdirFunc
SyscallReturn rmdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Definition: syscall_emul.cc:1066
gem5::ThreadContext::Halting
@ Halting
Trying to exit and waiting for an event to completely exit.
Definition: thread_context.hh:116
gem5::recvfromFunc
SyscallReturn recvfromFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> bufrPtr, size_t bufrLen, int flags, VPtr<> addrPtr, VPtr<> addrlenPtr)
Definition: syscall_emul.cc:1231
gem5::getppidFunc
SyscallReturn getppidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getppid() handler.
Definition: syscall_emul.cc:951
gem5::roundUp
static constexpr T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:260
chunk_generator.hh
gem5::Process::pgid
uint64_t pgid()
Definition: process.hh:88
gem5::renameFunc
SyscallReturn renameFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> oldpath, VPtr<> newpath)
Target rename() handler.
Definition: syscall_emul.cc:530
gem5::setsockoptFunc
SyscallReturn setsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, socklen_t len)
Definition: syscall_emul.cc:1632
trace.hh
gem5::SyscallDesc
This class provides the wrapper interface for the system call implementations which are defined in th...
Definition: syscall_desc.hh:69
gem5::fchownFunc
SyscallReturn fchownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t owner, uint32_t group)
Target fchown() handler.
Definition: syscall_emul.cc:655
gem5::ignoreFunc
SyscallReturn ignoreFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we never intend to implement (signal handling,...
Definition: syscall_emul.cc:71
gem5::getpidFunc
SyscallReturn getpidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpid() handler.
Definition: syscall_emul.cc:937
gem5::guest_abi::VarArgs
Definition: varargs.hh:150
gem5::SyscallDesc::num
int num() const
Definition: syscall_desc.hh:81
gem5::BufferArg::bufferPtr
void * bufferPtr()
Return a pointer to the internal simulator-space buffer.
Definition: syscall_emul_buf.hh:119
page_table.hh
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: decoder.cc:40
gem5::SyscallDesc::name
std::string name() const
Definition: syscall_desc.hh:80
gem5::dup2Func
SyscallReturn dup2Func(SyscallDesc *desc, ThreadContext *tc, int old_tgt_fd, int new_tgt_fd)
Target dup2() handler.
Definition: syscall_emul.cc:700
gem5::mknodFunc
SyscallReturn mknodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode, dev_t dev)
Target mknod() handler.
Definition: syscall_emul.cc:1024
thread_context.hh
gem5::geteuidFunc
SyscallReturn geteuidFunc(SyscallDesc *desc, ThreadContext *tc)
Target geteuid() handler.
Definition: syscall_emul.cc:965
gem5::ArmISA::sa
Bitfield< 3 > sa
Definition: misc_types.hh:391
syscall_desc.hh
gem5::chownFunc
SyscallReturn chownFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, uint32_t owner, uint32_t group)
Target chown() handler.
Definition: syscall_emul.cc:634
gem5::ftruncate64Func
SyscallReturn ftruncate64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int64_t length)
Target ftruncate64() handler.
Definition: syscall_emul.cc:604
byteswap.hh
gem5::ArmISA::status
Bitfield< 5, 0 > status
Definition: misc_types.hh:422
gem5::ArmISA::mode
Bitfield< 4, 0 > mode
Definition: misc_types.hh:73
gem5::X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:84
gem5::lseekFunc
SyscallReturn lseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t offs, int whence)
Target lseek() handler.
Definition: syscall_emul.cc:295
gem5::getpeernameFunc
SyscallReturn getpeernameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> sockAddrPtr, VPtr<> addrlenPtr)
Definition: syscall_emul.cc:1605
gem5::sendtoFunc
SyscallReturn sendtoFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> bufrPtr, size_t bufrLen, int flags, VPtr<> addrPtr, socklen_t addrLen)
Definition: syscall_emul.cc:1291
gem5::unimplementedFunc
SyscallReturn unimplementedFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we haven't thought about.
Definition: syscall_emul.cc:64

Generated on Tue Sep 7 2021 14:53:49 for gem5 by doxygen 1.8.17