gem5  v21.1.0.0
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 
196  tc->halt();
197 
202  int activeContexts = 0;
203  for (auto &system: sys->systemList)
204  activeContexts += system->threads.numRunning();
205 
206  if (activeContexts == 0) {
216  if (!DistIface::readyToExit(0)) {
217  return status;
218  }
219 
220  exitSimLoop("exiting with last active thread context", status & 0xff);
221  return status;
222  }
223 
224  return status;
225 }
226 
227 SyscallReturn
229 {
230  return exitImpl(desc, tc, false, status);
231 }
232 
233 SyscallReturn
235 {
236  return exitImpl(desc, tc, true, status);
237 }
238 
239 SyscallReturn
241 {
242  return (int)tc->getProcessPtr()->pTable->pageSize();
243 }
244 
245 
246 SyscallReturn
248 {
249  // change brk addr to first arg
250  auto p = tc->getProcessPtr();
251 
252  std::shared_ptr<MemState> mem_state = p->memState;
253  Addr brk_point = mem_state->getBrkPoint();
254 
255  // in Linux at least, brk(0) returns the current break value
256  // (note that the syscall and the glibc function have different behavior)
257  if (new_brk == 0 || (new_brk == brk_point))
258  return brk_point;
259 
260  mem_state->updateBrkRegion(brk_point, new_brk);
261 
262  DPRINTF_SYSCALL(Verbose, "brk: break point changed to: %#X\n",
263  mem_state->getBrkPoint());
264 
265  return mem_state->getBrkPoint();
266 }
267 
268 SyscallReturn
269 setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc, uint64_t tidPtr)
270 {
271  auto process = tc->getProcessPtr();
272 
273  process->childClearTID = tidPtr;
274  return process->pid();
275 }
276 
277 SyscallReturn
278 closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
279 {
280  auto p = tc->getProcessPtr();
281  return p->fds->closeFDEntry(tgt_fd);
282 }
283 
284 SyscallReturn
286  int tgt_fd, uint64_t offs, int whence)
287 {
288  auto p = tc->getProcessPtr();
289 
290  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
291  if (!ffdp)
292  return -EBADF;
293  int sim_fd = ffdp->getSimFD();
294 
295  off_t result = lseek(sim_fd, offs, whence);
296 
297  return (result == (off_t)-1) ? -errno : result;
298 }
299 
300 
301 SyscallReturn
303  int tgt_fd, uint64_t offset_high, uint32_t offset_low,
304  VPtr<> result_ptr, int whence)
305 {
306  auto p = tc->getProcessPtr();
307 
308  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
309  if (!ffdp)
310  return -EBADF;
311  int sim_fd = ffdp->getSimFD();
312 
313  uint64_t offset = (offset_high << 32) | offset_low;
314 
315  uint64_t result = lseek(sim_fd, offset, whence);
316  result = htog(result, tc->getSystemPtr()->getGuestByteOrder());
317 
318  if (result == (off_t)-1)
319  return -errno;
320  // Assuming that the size of loff_t is 64 bits on the target platform
321  BufferArg result_buf(result_ptr, sizeof(result));
322  std::memcpy(result_buf.bufferPtr(), &result, sizeof(result));
323  result_buf.copyOut(tc->getVirtProxy());
324  return 0;
325 }
326 
327 
328 SyscallReturn
329 munmapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, size_t length)
330 {
331  // Even if the system is currently not capable of recycling physical
332  // pages, there is no reason we can't unmap them so that we trigger
333  // appropriate seg faults when the application mistakenly tries to
334  // access them again.
335  auto p = tc->getProcessPtr();
336 
337  if (p->pTable->pageOffset(start))
338  return -EINVAL;
339 
340  length = roundUp(length, p->pTable->pageSize());
341 
342  p->memState->unmapRegion(start, length);
343 
344  return 0;
345 }
346 
347 
348 const char *hostname = "m5.eecs.umich.edu";
349 
352  VPtr<> buf_ptr, int name_len)
353 {
354  BufferArg name(buf_ptr, name_len);
355  strncpy((char *)name.bufferPtr(), hostname, name_len);
356  name.copyOut(tc->getVirtProxy());
357  return 0;
358 }
359 
360 SyscallReturn
362  VPtr<> buf_ptr, unsigned long size)
363 {
364  int result = 0;
365  auto p = tc->getProcessPtr();
366  BufferArg buf(buf_ptr, size);
367 
368  // Is current working directory defined?
369  std::string cwd = p->tgtCwd;
370  if (!cwd.empty()) {
371  if (cwd.length() >= size) {
372  // Buffer too small
373  return -ERANGE;
374  }
375  strncpy((char *)buf.bufferPtr(), cwd.c_str(), size);
376  result = cwd.length();
377  } else {
378  if (getcwd((char *)buf.bufferPtr(), size)) {
379  result = strlen((char *)buf.bufferPtr());
380  } else {
381  result = -1;
382  }
383  }
384 
385  buf.copyOut(tc->getVirtProxy());
386 
387  return (result == -1) ? -errno : result;
388 }
389 
390 SyscallReturn
392  VPtr<> pathname, VPtr<> buf_ptr, size_t bufsiz)
393 {
394  std::string path;
395  auto p = tc->getProcessPtr();
396 
397  if (!tc->getVirtProxy().tryReadString(path, pathname))
398  return -EFAULT;
399 
400  // Adjust path for cwd and redirection
401  path = p->checkPathRedirect(path);
402 
403  BufferArg buf(buf_ptr, bufsiz);
404 
405  int result = -1;
406  if (path != "/proc/self/exe") {
407  result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz);
408  } else {
409  // Emulate readlink() called on '/proc/self/exe' should return the
410  // absolute path of the binary running in the simulated system (the
411  // Process' executable). It is possible that using this path in
412  // the simulated system will result in unexpected behavior if:
413  // 1) One binary runs another (e.g., -c time -o "my_binary"), and
414  // called binary calls readlink().
415  // 2) The host's full path to the running benchmark changes from one
416  // simulation to another. This can result in different simulated
417  // performance since the simulated system will process the binary
418  // path differently, even if the binary itself does not change.
419 
420  // Get the absolute canonical path to the running application
421  char real_path[PATH_MAX];
422  char *check_real_path = realpath(p->progName(), real_path);
423  if (!check_real_path) {
424  fatal("readlink('/proc/self/exe') unable to resolve path to "
425  "executable: %s", p->progName());
426  }
427  strncpy((char*)buf.bufferPtr(), real_path, bufsiz);
428  size_t real_path_len = strlen(real_path);
429  if (real_path_len > bufsiz) {
430  // readlink will truncate the contents of the
431  // path to ensure it is no more than bufsiz
432  result = bufsiz;
433  } else {
434  result = real_path_len;
435  }
436 
437  // Issue a warning about potential unexpected results
438  warn_once("readlink() called on '/proc/self/exe' may yield unexpected "
439  "results in various settings.\n Returning '%s'\n",
440  (char*)buf.bufferPtr());
441  }
442 
443  buf.copyOut(tc->getVirtProxy());
444 
445  return (result == -1) ? -errno : result;
446 }
447 
448 SyscallReturn
450 {
451  std::string path;
452  auto p = tc->getProcessPtr();
453 
454  if (!tc->getVirtProxy().tryReadString(path, pathname))
455  return -EFAULT;
456 
457  path = p->checkPathRedirect(path);
458 
459  int result = unlink(path.c_str());
460  return (result == -1) ? -errno : result;
461 }
462 
463 SyscallReturn
465  VPtr<> pathname, VPtr<> new_pathname)
466 {
467  std::string path;
468  std::string new_path;
469  auto p = tc->getProcessPtr();
470 
471  auto &virt_mem = tc->getVirtProxy();
472  if (!virt_mem.tryReadString(path, pathname))
473  return -EFAULT;
474  if (!virt_mem.tryReadString(new_path, new_pathname))
475  return -EFAULT;
476 
477  path = p->absolutePath(path, true);
478  new_path = p->absolutePath(new_path, true);
479 
480  int result = link(path.c_str(), new_path.c_str());
481  return (result == -1) ? -errno : result;
482 }
483 
484 SyscallReturn
486  VPtr<> pathname, VPtr<> new_pathname)
487 {
488  std::string path;
489  std::string new_path;
490  auto p = tc->getProcessPtr();
491 
492  auto &virt_mem = tc->getVirtProxy();
493  if (!virt_mem.tryReadString(path, pathname))
494  return -EFAULT;
495  if (!virt_mem.tryReadString(new_path, new_pathname))
496  return -EFAULT;
497 
498  path = p->absolutePath(path, true);
499  new_path = p->absolutePath(new_path, true);
500 
501  int result = symlink(path.c_str(), new_path.c_str());
502  return (result == -1) ? -errno : result;
503 }
504 
505 SyscallReturn
506 mkdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
507 {
508  auto p = tc->getProcessPtr();
509  std::string path;
510  if (!tc->getVirtProxy().tryReadString(path, pathname))
511  return -EFAULT;
512 
513  path = p->checkPathRedirect(path);
514 
515  auto result = mkdir(path.c_str(), mode);
516  return (result == -1) ? -errno : result;
517 }
518 
519 SyscallReturn
521  VPtr<> newpath)
522 {
523  auto p = tc->getProcessPtr();
524 
525  std::string old_name;
526  if (!tc->getVirtProxy().tryReadString(old_name, oldpath))
527  return -EFAULT;
528 
529  std::string new_name;
530  if (!tc->getVirtProxy().tryReadString(new_name, newpath))
531  return -EFAULT;
532 
533  // Adjust path for cwd and redirection
534  old_name = p->checkPathRedirect(old_name);
535  new_name = p->checkPathRedirect(new_name);
536 
537  int64_t result = rename(old_name.c_str(), new_name.c_str());
538  return (result == -1) ? -errno : result;
539 }
540 
541 SyscallReturn
543  off_t length)
544 {
545  std::string path;
546  auto p = tc->getProcessPtr();
547 
548  if (!tc->getVirtProxy().tryReadString(path, pathname))
549  return -EFAULT;
550 
551  // Adjust path for cwd and redirection
552  path = p->checkPathRedirect(path);
553 
554  int result = truncate(path.c_str(), length);
555  return (result == -1) ? -errno : result;
556 }
557 
558 SyscallReturn
559 ftruncateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, off_t length)
560 {
561  auto p = tc->getProcessPtr();
562 
563  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
564  if (!ffdp)
565  return -EBADF;
566  int sim_fd = ffdp->getSimFD();
567 
568  int result = ftruncate(sim_fd, length);
569  return (result == -1) ? -errno : result;
570 }
571 
572 SyscallReturn
574  VPtr<> pathname, int64_t length)
575 {
576  auto process = tc->getProcessPtr();
577  std::string path;
578 
579  if (!tc->getVirtProxy().tryReadString(path, pathname))
580  return -EFAULT;
581 
582  // Adjust path for cwd and redirection
583  path = process->checkPathRedirect(path);
584 
585 #if NO_STAT64
586  int result = truncate(path.c_str(), length);
587 #else
588  int result = truncate64(path.c_str(), length);
589 #endif
590  return (result == -1) ? -errno : result;
591 }
592 
593 SyscallReturn
595  int tgt_fd, int64_t length)
596 {
597  auto p = tc->getProcessPtr();
598 
599  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
600  if (!ffdp)
601  return -EBADF;
602  int sim_fd = ffdp->getSimFD();
603 
604 #if NO_STAT64
605  int result = ftruncate(sim_fd, length);
606 #else
607  int result = ftruncate64(sim_fd, length);
608 #endif
609  return (result == -1) ? -errno : result;
610 }
611 
612 SyscallReturn
614 {
615  // Letting the simulated program change the simulator's umask seems like
616  // a bad idea. Compromise by just returning the current umask but not
617  // changing anything.
618  mode_t oldMask = umask(0);
619  umask(oldMask);
620  return (int)oldMask;
621 }
622 
623 SyscallReturn
625  VPtr<> pathname, uint32_t owner, uint32_t group)
626 {
627  std::string path;
628  auto p = tc->getProcessPtr();
629 
630  if (!tc->getVirtProxy().tryReadString(path, pathname))
631  return -EFAULT;
632 
633  /* XXX endianess */
634  uid_t hostOwner = owner;
635  gid_t hostGroup = group;
636 
637  // Adjust path for cwd and redirection
638  path = p->checkPathRedirect(path);
639 
640  int result = chown(path.c_str(), hostOwner, hostGroup);
641  return (result == -1) ? -errno : result;
642 }
643 
644 SyscallReturn
646  int tgt_fd, uint32_t owner, uint32_t group)
647 {
648  auto p = tc->getProcessPtr();
649 
650  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
651  if (!ffdp)
652  return -EBADF;
653  int sim_fd = ffdp->getSimFD();
654 
655  /* XXX endianess */
656  uid_t hostOwner = owner;
657  gid_t hostGroup = group;
658 
659  int result = fchown(sim_fd, hostOwner, hostGroup);
660  return (result == -1) ? -errno : result;
661 }
662 
669 SyscallReturn
670 dupFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
671 {
672  auto p = tc->getProcessPtr();
673 
674  auto old_hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
675  if (!old_hbfdp)
676  return -EBADF;
677  int sim_fd = old_hbfdp->getSimFD();
678 
679  int result = dup(sim_fd);
680  if (result == -1)
681  return -errno;
682 
683  auto new_hbfdp = std::dynamic_pointer_cast<HBFDEntry>(old_hbfdp->clone());
684  new_hbfdp->setSimFD(result);
685  new_hbfdp->setCOE(false);
686  return p->fds->allocFD(new_hbfdp);
687 }
688 
689 SyscallReturn
690 dup2Func(SyscallDesc *desc, ThreadContext *tc, int old_tgt_fd, int new_tgt_fd)
691 {
692  auto p = tc->getProcessPtr();
693  auto old_hbp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[old_tgt_fd]);
694  if (!old_hbp)
695  return -EBADF;
696  int old_sim_fd = old_hbp->getSimFD();
697 
703  int res_fd = dup2(old_sim_fd, open("/dev/null", O_RDONLY));
704  if (res_fd == -1)
705  return -errno;
706 
707  auto new_hbp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[new_tgt_fd]);
708  if (new_hbp)
709  p->fds->closeFDEntry(new_tgt_fd);
710  new_hbp = std::dynamic_pointer_cast<HBFDEntry>(old_hbp->clone());
711  new_hbp->setSimFD(res_fd);
712  new_hbp->setCOE(false);
713 
714  return p->fds->allocFD(new_hbp);
715 }
716 
717 SyscallReturn
719  int tgt_fd, int cmd, guest_abi::VarArgs<int> varargs)
720 {
721  auto p = tc->getProcessPtr();
722 
723  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
724  if (!hbfdp)
725  return -EBADF;
726  int sim_fd = hbfdp->getSimFD();
727 
728  int coe = hbfdp->getCOE();
729 
730  switch (cmd) {
731  case F_GETFD:
732  return coe & FD_CLOEXEC;
733 
734  case F_SETFD: {
735  int arg = varargs.get<int>();
736  arg ? hbfdp->setCOE(true) : hbfdp->setCOE(false);
737  return 0;
738  }
739 
740  // Rely on the host to maintain the file status flags for this file
741  // description rather than maintain it ourselves. Admittedly, this
742  // is suboptimal (and possibly error prone), but it is difficult to
743  // maintain the flags by tracking them across the different descriptors
744  // (that refer to this file description) caused by clone, dup, and
745  // subsequent fcntls.
746  case F_GETFL:
747  case F_SETFL: {
748  int arg = varargs.get<int>();
749  int rv = fcntl(sim_fd, cmd, arg);
750  return (rv == -1) ? -errno : rv;
751  }
752 
753  default:
754  warn("fcntl: unsupported command %d\n", cmd);
755  return 0;
756  }
757 }
758 
759 SyscallReturn
760 fcntl64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd)
761 {
762  auto p = tc->getProcessPtr();
763 
764  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
765  if (!hbfdp)
766  return -EBADF;
767  int sim_fd = hbfdp->getSimFD();
768 
769  switch (cmd) {
770  case 33: //F_GETLK64
771  warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", tgt_fd);
772  return -EMFILE;
773 
774  case 34: // F_SETLK64
775  case 35: // F_SETLKW64
776  warn("fcntl64(%d, F_SETLK(W)64) not supported, error returned\n",
777  tgt_fd);
778  return -EMFILE;
779 
780  default:
781  // not sure if this is totally valid, but we'll pass it through
782  // to the underlying OS
783  warn("fcntl64(%d, %d) passed through to host\n", tgt_fd, cmd);
784  return fcntl(sim_fd, cmd);
785  }
786 }
787 
788 SyscallReturn
790 {
791  return pipe2Func(desc, tc, 0, 0);
792 }
793 
794 SyscallReturn
796 {
797  return pipe2Func(desc, tc, tgt_addr, 0);
798 }
799 
800 SyscallReturn
801 pipe2Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr, int flags)
802 {
803  auto p = tc->getProcessPtr();
804 
805  int sim_fds[2], tgt_fds[2];
806 
807  int pipe_retval = pipe(sim_fds);
808  if (pipe_retval == -1)
809  return -errno;
810 
811  auto rend = PipeFDEntry::EndType::read;
812  auto rpfd = std::make_shared<PipeFDEntry>(sim_fds[0], O_WRONLY, rend);
813  tgt_fds[0] = p->fds->allocFD(rpfd);
814  int sim_fd_rpfd = rpfd->getSimFD();
815 
816  auto wend = PipeFDEntry::EndType::write;
817  auto wpfd = std::make_shared<PipeFDEntry>(sim_fds[1], O_RDONLY, wend);
818  tgt_fds[1] = p->fds->allocFD(wpfd);
819  int sim_fd_wpfd = wpfd->getSimFD();
820 
825  rpfd->setPipeReadSource(tgt_fds[1]);
826 
832  if (tgt_addr == 0)
833  return SyscallReturn(tgt_fds[0], tgt_fds[1]);
834 
839  BufferArg tgt_handle(tgt_addr, sizeof(int[2]));
840  int *buf_ptr = (int*)tgt_handle.bufferPtr();
841  buf_ptr[0] = tgt_fds[0];
842  buf_ptr[1] = tgt_fds[1];
843  tgt_handle.copyOut(tc->getVirtProxy());
844 
845  if (flags) {
846  // pipe2 only uses O_NONBLOCK, O_CLOEXEC, and (O_NONBLOCK | O_CLOEXEC)
847  // if flags set to anything else, return EINVAL
848  if ((flags != O_CLOEXEC) && (flags != O_NONBLOCK) &&
849  (flags != (O_CLOEXEC | O_NONBLOCK))) {
850  return -EINVAL;
851  }
852 
853  /*
854  If O_NONBLOCK is passed in as a flag to pipe2, set O_NONBLOCK file
855  status flag for two new open file descriptors.
856  */
857  if (flags & O_NONBLOCK) {
858  /*
859  O_NONBLOCK is set when the programmer wants to avoid a separate
860  call(s) to fcntl in their code, so mirror the fcntl
861  implementation for handling file descriptors -- rely on host to
862  maintain file status flags.
863  */
864  if (fcntl(sim_fd_rpfd, F_SETFL, O_NONBLOCK)) {
865  return -errno;
866  }
867  if (fcntl(sim_fd_wpfd, F_SETFL, O_NONBLOCK)) {
868  return -errno;
869  }
870  }
871 
872  /*
873  If O_CLOEXEC is passed in as a flag to pipe2, set close-on-exec
874  (FD_CLOEXEC) file status flag for two new open file descriptors.
875  */
876  if (flags & O_CLOEXEC) {
877  rpfd->setCOE(true);
878  wpfd->setCOE(true);
879  }
880  }
881 
882  return 0;
883 }
884 
885 SyscallReturn
887 {
888  auto process = tc->getProcessPtr();
889  return process->pgid();
890 }
891 
892 SyscallReturn
893 setpgidFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int pgid)
894 {
895  auto process = tc->getProcessPtr();
896 
897  if (pgid < 0)
898  return -EINVAL;
899 
900  if (pid == 0) {
901  process->pgid(process->pid());
902  return 0;
903  }
904 
905  Process *matched_ph = nullptr;
906  System *sysh = tc->getSystemPtr();
907 
908  // Retrieves process pointer from active/suspended thread contexts.
909  for (auto *tc: sysh->threads) {
910  if (tc->status() != ThreadContext::Halted) {
911  Process *temp_h = tc->getProcessPtr();
912  Process *walk_ph = (Process*)temp_h;
913 
914  if (walk_ph && walk_ph->pid() == process->pid())
915  matched_ph = walk_ph;
916  }
917  }
918 
919  assert(matched_ph);
920  matched_ph->pgid((pgid == 0) ? matched_ph->pid() : pgid);
921 
922  return 0;
923 }
924 
925 
926 SyscallReturn
928 {
929  auto process = tc->getProcessPtr();
930  return process->tgid();
931 }
932 
933 SyscallReturn
935 {
936  auto process = tc->getProcessPtr();
937  return process->pid();
938 }
939 
940 SyscallReturn
942 {
943  auto process = tc->getProcessPtr();
944  return process->ppid();
945 }
946 
947 SyscallReturn
949 {
950  auto process = tc->getProcessPtr();
951  return process->uid(); // UID
952 }
953 
954 SyscallReturn
956 {
957  auto process = tc->getProcessPtr();
958  return process->euid(); // UID
959 }
960 
961 SyscallReturn
963 {
964  auto process = tc->getProcessPtr();
965  return process->gid();
966 }
967 
968 SyscallReturn
970 {
971  auto process = tc->getProcessPtr();
972  return process->egid();
973 }
974 
975 SyscallReturn
977  int tgt_fd, int mode, off_t offset, off_t len)
978 {
979 #if defined(__linux__)
980  auto p = tc->getProcessPtr();
981 
982  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
983  if (!ffdp)
984  return -EBADF;
985  int sim_fd = ffdp->getSimFD();
986 
987  int result = fallocate(sim_fd, mode, offset, len);
988  if (result < 0)
989  return -errno;
990  return 0;
991 #else
992  warnUnsupportedOS("fallocate");
993  return -1;
994 #endif
995 }
996 
997 SyscallReturn
999  VPtr<> pathname, mode_t mode)
1000 {
1001  std::string path;
1002  auto p = tc->getProcessPtr();
1003  if (!tc->getVirtProxy().tryReadString(path, pathname))
1004  return -EFAULT;
1005 
1006  // Adjust path for cwd and redirection
1007  path = p->checkPathRedirect(path);
1008 
1009  int result = access(path.c_str(), mode);
1010  return (result == -1) ? -errno : result;
1011 }
1012 
1013 SyscallReturn
1015  VPtr<> pathname, mode_t mode, dev_t dev)
1016 {
1017  auto p = tc->getProcessPtr();
1018  std::string path;
1019  if (!tc->getVirtProxy().tryReadString(path, pathname))
1020  return -EFAULT;
1021 
1022  path = p->checkPathRedirect(path);
1023 
1024  auto result = mknod(path.c_str(), mode, dev);
1025  return (result == -1) ? -errno : result;
1026 }
1027 
1028 SyscallReturn
1030 {
1031  auto p = tc->getProcessPtr();
1032  std::string path;
1033  if (!tc->getVirtProxy().tryReadString(path, pathname))
1034  return -EFAULT;
1035 
1036  std::string tgt_cwd;
1037  if (startswith(path, "/")) {
1038  tgt_cwd = path;
1039  } else {
1040  char buf[PATH_MAX];
1041  tgt_cwd = realpath((p->tgtCwd + "/" + path).c_str(), buf);
1042  }
1043  std::string host_cwd = p->checkPathRedirect(tgt_cwd);
1044 
1045  int result = chdir(host_cwd.c_str());
1046 
1047  if (result == -1)
1048  return -errno;
1049 
1050  p->hostCwd = host_cwd;
1051  p->tgtCwd = tgt_cwd;
1052  return result;
1053 }
1054 
1055 SyscallReturn
1057 {
1058  auto p = tc->getProcessPtr();
1059  std::string path;
1060  if (!tc->getVirtProxy().tryReadString(path, pathname))
1061  return -EFAULT;
1062 
1063  path = p->checkPathRedirect(path);
1064 
1065  auto result = rmdir(path.c_str());
1066  return (result == -1) ? -errno : result;
1067 }
1068 
1069 #if defined(SYS_getdents) || defined(SYS_getdents64)
1070 template<typename DE, int SYS_NUM>
1071 static SyscallReturn
1072 getdentsImpl(SyscallDesc *desc, ThreadContext *tc,
1073  int tgt_fd, VPtr<> buf_ptr, unsigned count)
1074 {
1075  auto p = tc->getProcessPtr();
1076 
1077  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
1078  if (!hbfdp)
1079  return -EBADF;
1080  int sim_fd = hbfdp->getSimFD();
1081 
1082  BufferArg buf_arg(buf_ptr, count);
1083  auto status = syscall(SYS_NUM, sim_fd, buf_arg.bufferPtr(), count);
1084 
1085  if (status == -1)
1086  return -errno;
1087 
1088  unsigned traversed = 0;
1089  while (traversed < status) {
1090  DE *buffer = (DE*)((Addr)buf_arg.bufferPtr() + traversed);
1091 
1092  auto host_reclen = buffer->d_reclen;
1093 
1099  const ByteOrder bo = tc->getSystemPtr()->getGuestByteOrder();
1100  buffer->d_ino = htog(buffer->d_ino, bo);
1101  buffer->d_off = htog(buffer->d_off, bo);
1102  buffer->d_reclen = htog(buffer->d_reclen, bo);
1103 
1104  traversed += host_reclen;
1105  }
1106 
1107  buf_arg.copyOut(tc->getVirtProxy());
1108  return status;
1109 }
1110 #endif
1111 
1112 #if defined(SYS_getdents)
1113 SyscallReturn
1114 getdentsFunc(SyscallDesc *desc, ThreadContext *tc,
1115  int tgt_fd, VPtr<> buf_ptr, unsigned count)
1116 {
1117  typedef struct linux_dirent
1118  {
1119  unsigned long d_ino;
1120  unsigned long d_off;
1121  unsigned short d_reclen;
1122  char dname[];
1123  } LinDent;
1124 
1125  return getdentsImpl<LinDent, SYS_getdents>(desc, tc,
1126  tgt_fd, buf_ptr, count);
1127 }
1128 #endif
1129 
1130 #if defined(SYS_getdents64)
1131 SyscallReturn
1132 getdents64Func(SyscallDesc *desc, ThreadContext *tc,
1133  int tgt_fd, VPtr<> buf_ptr, unsigned count)
1134 {
1135  typedef struct linux_dirent64
1136  {
1137  ino64_t d_ino;
1138  off64_t d_off;
1139  unsigned short d_reclen;
1140  char dname[];
1141  } LinDent64;
1142 
1143  return getdentsImpl<LinDent64, SYS_getdents64>(desc, tc,
1144  tgt_fd, buf_ptr, count);
1145 }
1146 #endif
1147 
1148 SyscallReturn
1149 shutdownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int how)
1150 {
1151  auto p = tc->getProcessPtr();
1152 
1153  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1154  if (!sfdp)
1155  return -EBADF;
1156  int sim_fd = sfdp->getSimFD();
1157 
1158  int retval = shutdown(sim_fd, how);
1159 
1160  return (retval == -1) ? -errno : retval;
1161 }
1162 
1163 SyscallReturn
1165  int tgt_fd, VPtr<> buf_ptr, int addrlen)
1166 {
1167  auto p = tc->getProcessPtr();
1168 
1169  BufferArg bufSock(buf_ptr, addrlen);
1170  bufSock.copyIn(tc->getVirtProxy());
1171 
1172  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1173  if (!sfdp)
1174  return -EBADF;
1175  int sim_fd = sfdp->getSimFD();
1176 
1177  int status = ::bind(sim_fd,
1178  (struct sockaddr *)bufSock.bufferPtr(),
1179  addrlen);
1180 
1181  return (status == -1) ? -errno : status;
1182 }
1183 
1184 SyscallReturn
1185 listenFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int backlog)
1186 {
1187  auto p = tc->getProcessPtr();
1188 
1189  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1190  if (!sfdp)
1191  return -EBADF;
1192  int sim_fd = sfdp->getSimFD();
1193 
1194  int status = listen(sim_fd, backlog);
1195 
1196  return (status == -1) ? -errno : status;
1197 }
1198 
1199 SyscallReturn
1201  int tgt_fd, VPtr<> buf_ptr, int addrlen)
1202 {
1203  auto p = tc->getProcessPtr();
1204 
1205  BufferArg addr(buf_ptr, addrlen);
1206  addr.copyIn(tc->getVirtProxy());
1207 
1208  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1209  if (!sfdp)
1210  return -EBADF;
1211  int sim_fd = sfdp->getSimFD();
1212 
1213  int status = connect(sim_fd,
1214  (struct sockaddr *)addr.bufferPtr(),
1215  (socklen_t)addrlen);
1216 
1217  return (status == -1) ? -errno : status;
1218 }
1219 
1220 SyscallReturn
1222  int tgt_fd, VPtr<> bufrPtr, size_t bufrLen, int flags,
1223  VPtr<> addrPtr, VPtr<> addrlenPtr)
1224 {
1225  auto p = tc->getProcessPtr();
1226 
1227  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1228  if (!sfdp)
1229  return -EBADF;
1230  int sim_fd = sfdp->getSimFD();
1231 
1232  // Reserve buffer space.
1233  BufferArg bufrBuf(bufrPtr, bufrLen);
1234 
1235  // Get address length.
1236  socklen_t addrLen = 0;
1237  if (addrlenPtr != 0) {
1238  // Read address length parameter.
1239  BufferArg addrlenBuf(addrlenPtr, sizeof(socklen_t));
1240  addrlenBuf.copyIn(tc->getVirtProxy());
1241  addrLen = *((socklen_t *)addrlenBuf.bufferPtr());
1242  }
1243 
1244  struct sockaddr sa, *sap = NULL;
1245  if (addrLen != 0) {
1246  BufferArg addrBuf(addrPtr, addrLen);
1247  addrBuf.copyIn(tc->getVirtProxy());
1248  memcpy(&sa, (struct sockaddr *)addrBuf.bufferPtr(),
1249  sizeof(struct sockaddr));
1250  sap = &sa;
1251  }
1252 
1253  ssize_t recvd_size = recvfrom(sim_fd,
1254  (void *)bufrBuf.bufferPtr(),
1255  bufrLen, flags, sap, (socklen_t *)&addrLen);
1256 
1257  if (recvd_size == -1)
1258  return -errno;
1259 
1260  // Pass the received data out.
1261  bufrBuf.copyOut(tc->getVirtProxy());
1262 
1263  // Copy address to addrPtr and pass it on.
1264  if (sap != NULL) {
1265  BufferArg addrBuf(addrPtr, addrLen);
1266  memcpy(addrBuf.bufferPtr(), sap, sizeof(sa));
1267  addrBuf.copyOut(tc->getVirtProxy());
1268  }
1269 
1270  // Copy len to addrlenPtr and pass it on.
1271  if (addrLen != 0) {
1272  BufferArg addrlenBuf(addrlenPtr, sizeof(socklen_t));
1273  *(socklen_t *)addrlenBuf.bufferPtr() = addrLen;
1274  addrlenBuf.copyOut(tc->getVirtProxy());
1275  }
1276 
1277  return recvd_size;
1278 }
1279 
1280 SyscallReturn
1282  int tgt_fd, VPtr<> bufrPtr, size_t bufrLen, int flags,
1283  VPtr<> addrPtr, socklen_t addrLen)
1284 {
1285  auto p = tc->getProcessPtr();
1286 
1287  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1288  if (!sfdp)
1289  return -EBADF;
1290  int sim_fd = sfdp->getSimFD();
1291 
1292  // Reserve buffer space.
1293  BufferArg bufrBuf(bufrPtr, bufrLen);
1294  bufrBuf.copyIn(tc->getVirtProxy());
1295 
1296  struct sockaddr sa, *sap = nullptr;
1297  memset(&sa, 0, sizeof(sockaddr));
1298  if (addrLen != 0) {
1299  BufferArg addrBuf(addrPtr, addrLen);
1300  addrBuf.copyIn(tc->getVirtProxy());
1301  memcpy(&sa, (sockaddr*)addrBuf.bufferPtr(), addrLen);
1302  sap = &sa;
1303  }
1304 
1305  ssize_t sent_size = sendto(sim_fd,
1306  (void *)bufrBuf.bufferPtr(),
1307  bufrLen, flags, sap, (socklen_t)addrLen);
1308 
1309  return (sent_size == -1) ? -errno : sent_size;
1310 }
1311 
1312 SyscallReturn
1314  int tgt_fd, VPtr<> msgPtr, int flags)
1315 {
1316  auto p = tc->getProcessPtr();
1317 
1318  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1319  if (!sfdp)
1320  return -EBADF;
1321  int sim_fd = sfdp->getSimFD();
1322 
1346  BufferArg msgBuf(msgPtr, sizeof(struct msghdr));
1347  msgBuf.copyIn(tc->getVirtProxy());
1348  struct msghdr *msgHdr = (struct msghdr *)msgBuf.bufferPtr();
1349 
1355  Addr msg_name_phold = 0;
1356  Addr msg_iov_phold = 0;
1357  Addr iovec_base_phold[msgHdr->msg_iovlen];
1358  Addr msg_control_phold = 0;
1359 
1363  BufferArg *nameBuf = NULL;
1364  if (msgHdr->msg_name) {
1365  /*1*/msg_name_phold = (Addr)msgHdr->msg_name;
1366  /*2*/nameBuf = new BufferArg(msg_name_phold, msgHdr->msg_namelen);
1367  /*3*/nameBuf->copyIn(tc->getVirtProxy());
1368  /*4*/msgHdr->msg_name = nameBuf->bufferPtr();
1369  }
1370 
1376  BufferArg *iovBuf = NULL;
1377  BufferArg *iovecBuf[msgHdr->msg_iovlen];
1378  for (int i = 0; i < msgHdr->msg_iovlen; i++) {
1379  iovec_base_phold[i] = 0;
1380  iovecBuf[i] = NULL;
1381  }
1382 
1383  if (msgHdr->msg_iov) {
1384  /*1*/msg_iov_phold = (Addr)msgHdr->msg_iov;
1385  /*2*/iovBuf = new BufferArg(msg_iov_phold, msgHdr->msg_iovlen *
1386  sizeof(struct iovec));
1387  /*3*/iovBuf->copyIn(tc->getVirtProxy());
1388  for (int i = 0; i < msgHdr->msg_iovlen; i++) {
1389  if (((struct iovec *)iovBuf->bufferPtr())[i].iov_base) {
1390  /*1*/iovec_base_phold[i] =
1391  (Addr)((struct iovec *)iovBuf->bufferPtr())[i].iov_base;
1392  /*2*/iovecBuf[i] = new BufferArg(iovec_base_phold[i],
1393  ((struct iovec *)iovBuf->bufferPtr())[i].iov_len);
1394  /*3*/iovecBuf[i]->copyIn(tc->getVirtProxy());
1395  /*4*/((struct iovec *)iovBuf->bufferPtr())[i].iov_base =
1396  iovecBuf[i]->bufferPtr();
1397  }
1398  }
1399  /*4*/msgHdr->msg_iov = (struct iovec *)iovBuf->bufferPtr();
1400  }
1401 
1405  BufferArg *controlBuf = NULL;
1406  if (msgHdr->msg_control) {
1407  /*1*/msg_control_phold = (Addr)msgHdr->msg_control;
1408  /*2*/controlBuf = new BufferArg(msg_control_phold,
1409  CMSG_ALIGN(msgHdr->msg_controllen));
1410  /*3*/controlBuf->copyIn(tc->getVirtProxy());
1411  /*4*/msgHdr->msg_control = controlBuf->bufferPtr();
1412  }
1413 
1414  ssize_t recvd_size = recvmsg(sim_fd, msgHdr, flags);
1415 
1416  if (recvd_size < 0)
1417  return -errno;
1418 
1419  if (msgHdr->msg_name) {
1420  nameBuf->copyOut(tc->getVirtProxy());
1421  delete(nameBuf);
1422  msgHdr->msg_name = (void *)msg_name_phold;
1423  }
1424 
1425  if (msgHdr->msg_iov) {
1426  for (int i = 0; i< msgHdr->msg_iovlen; i++) {
1427  if (((struct iovec *)iovBuf->bufferPtr())[i].iov_base) {
1428  iovecBuf[i]->copyOut(tc->getVirtProxy());
1429  delete iovecBuf[i];
1430  ((struct iovec *)iovBuf->bufferPtr())[i].iov_base =
1431  (void *)iovec_base_phold[i];
1432  }
1433  }
1434  iovBuf->copyOut(tc->getVirtProxy());
1435  delete iovBuf;
1436  msgHdr->msg_iov = (struct iovec *)msg_iov_phold;
1437  }
1438 
1439  if (msgHdr->msg_control) {
1440  controlBuf->copyOut(tc->getVirtProxy());
1441  delete(controlBuf);
1442  msgHdr->msg_control = (void *)msg_control_phold;
1443  }
1444 
1445  msgBuf.copyOut(tc->getVirtProxy());
1446 
1447  return recvd_size;
1448 }
1449 
1450 SyscallReturn
1452  int tgt_fd, VPtr<> msgPtr, int flags)
1453 {
1454  auto p = tc->getProcessPtr();
1455 
1456  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1457  if (!sfdp)
1458  return -EBADF;
1459  int sim_fd = sfdp->getSimFD();
1460 
1464  BufferArg msgBuf(msgPtr, sizeof(struct msghdr));
1465  msgBuf.copyIn(tc->getVirtProxy());
1466  struct msghdr msgHdr = *((struct msghdr *)msgBuf.bufferPtr());
1467 
1472  struct iovec *iovPtr = msgHdr.msg_iov;
1473  BufferArg iovBuf((Addr)iovPtr, sizeof(struct iovec) * msgHdr.msg_iovlen);
1474  iovBuf.copyIn(tc->getVirtProxy());
1475  struct iovec *iov = (struct iovec *)iovBuf.bufferPtr();
1476  msgHdr.msg_iov = iov;
1477 
1483  BufferArg **bufferArray = (BufferArg **)malloc(msgHdr.msg_iovlen
1484  * sizeof(BufferArg *));
1485 
1491  for (int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
1492  Addr basePtr = (Addr) iov[iovIndex].iov_base;
1493  bufferArray[iovIndex] = new BufferArg(basePtr, iov[iovIndex].iov_len);
1494  bufferArray[iovIndex]->copyIn(tc->getVirtProxy());
1495  iov[iovIndex].iov_base = bufferArray[iovIndex]->bufferPtr();
1496  }
1497 
1498  ssize_t sent_size = sendmsg(sim_fd, &msgHdr, flags);
1499  int local_errno = errno;
1500 
1504  for (int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
1505  BufferArg *baseBuf = ( BufferArg *)bufferArray[iovIndex];
1506  delete(baseBuf);
1507  }
1508 
1512  free(bufferArray);
1513 
1514  return (sent_size < 0) ? -local_errno : sent_size;
1515 }
1516 
1517 SyscallReturn
1519  int tgt_fd, int level, int optname, VPtr<> valPtr,
1520  VPtr<> lenPtr)
1521 {
1522  // union of all possible return value types from getsockopt
1523  union val
1524  {
1525  int i_val;
1526  long l_val;
1527  struct linger linger_val;
1528  struct timeval timeval_val;
1529  } val;
1530 
1531  auto p = tc->getProcessPtr();
1532 
1533  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1534  if (!sfdp)
1535  return -EBADF;
1536  int sim_fd = sfdp->getSimFD();
1537 
1538  socklen_t len = sizeof(val);
1539  int status = getsockopt(sim_fd, level, optname, &val, &len);
1540 
1541  if (status == -1)
1542  return -errno;
1543 
1544  // copy val to valPtr and pass it on
1545  BufferArg valBuf(valPtr, sizeof(val));
1546  memcpy(valBuf.bufferPtr(), &val, sizeof(val));
1547  valBuf.copyOut(tc->getVirtProxy());
1548 
1549  // copy len to lenPtr and pass it on
1550  BufferArg lenBuf(lenPtr, sizeof(len));
1551  memcpy(lenBuf.bufferPtr(), &len, sizeof(len));
1552  lenBuf.copyOut(tc->getVirtProxy());
1553 
1554  return status;
1555 }
1556 
1557 SyscallReturn
1559  int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
1560 {
1561  auto p = tc->getProcessPtr();
1562 
1563  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1564  if (!sfdp)
1565  return -EBADF;
1566  int sim_fd = sfdp->getSimFD();
1567 
1568  // lenPtr is an in-out paramenter:
1569  // sending the address length in, conveying the final length out
1570 
1571  // Read in the value of len from the passed pointer.
1572  BufferArg lenBuf(lenPtr, sizeof(socklen_t));
1573  lenBuf.copyIn(tc->getVirtProxy());
1574  socklen_t len = *(socklen_t *)lenBuf.bufferPtr();
1575 
1576  struct sockaddr sa;
1577  int status = getsockname(sim_fd, &sa, &len);
1578 
1579  if (status == -1)
1580  return -errno;
1581 
1582  // Copy address to addrPtr and pass it on.
1583  BufferArg addrBuf(addrPtr, sizeof(sa));
1584  memcpy(addrBuf.bufferPtr(), &sa, sizeof(sa));
1585  addrBuf.copyOut(tc->getVirtProxy());
1586 
1587  // Copy len to lenPtr and pass it on.
1588  *(socklen_t *)lenBuf.bufferPtr() = len;
1589  lenBuf.copyOut(tc->getVirtProxy());
1590 
1591  return status;
1592 }
1593 
1594 SyscallReturn
1596  int tgt_fd, VPtr<> sockAddrPtr, VPtr<> addrlenPtr)
1597 {
1598  auto p = tc->getProcessPtr();
1599 
1600  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1601  if (!sfdp)
1602  return -EBADF;
1603  int sim_fd = sfdp->getSimFD();
1604 
1605  BufferArg bufAddrlen(addrlenPtr, sizeof(unsigned));
1606  bufAddrlen.copyIn(tc->getVirtProxy());
1607  BufferArg bufSock(sockAddrPtr, *(unsigned *)bufAddrlen.bufferPtr());
1608 
1609  int retval = getpeername(sim_fd,
1610  (struct sockaddr *)bufSock.bufferPtr(),
1611  (unsigned *)bufAddrlen.bufferPtr());
1612 
1613  if (retval != -1) {
1614  bufSock.copyOut(tc->getVirtProxy());
1615  bufAddrlen.copyOut(tc->getVirtProxy());
1616  }
1617 
1618  return (retval == -1) ? -errno : retval;
1619 }
1620 
1621 SyscallReturn
1623  int tgt_fd, int level, int optname, VPtr<> valPtr,
1624  socklen_t len)
1625 {
1626  auto p = tc->getProcessPtr();
1627 
1628  BufferArg valBuf(valPtr, len);
1629  valBuf.copyIn(tc->getVirtProxy());
1630 
1631  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1632  if (!sfdp)
1633  return -EBADF;
1634  int sim_fd = sfdp->getSimFD();
1635 
1636  int status = setsockopt(sim_fd, level, optname,
1637  (struct sockaddr *)valBuf.bufferPtr(), len);
1638 
1639  return (status == -1) ? -errno : status;
1640 }
1641 
1642 SyscallReturn
1644  VPtr<uint32_t> cpu, VPtr<uint32_t> node, VPtr<uint32_t> tcache)
1645 {
1646  // unsigned is the same size (4) on all Linux supported ISAs.
1647  if (cpu)
1648  *cpu = htog(tc->contextId(), tc->getSystemPtr()->getGuestByteOrder());
1649 
1650  // Set a fixed NUMA node 0.
1651  if (node)
1652  *node = 0;
1653 
1654  return 0;
1655 }
1656 
1657 } // 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:670
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:1029
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:1185
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:948
gem5::getsockoptFunc
SyscallReturn getsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, VPtr<> lenPtr)
Definition: syscall_emul.cc:1518
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:886
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:1164
gem5::fallocateFunc
SyscallReturn fallocateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int mode, off_t offset, off_t len)
Definition: syscall_emul.cc:976
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:348
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:506
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:361
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:247
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:278
gem5::getcpuFunc
SyscallReturn getcpuFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< uint32_t > cpu, VPtr< uint32_t > node, VPtr< uint32_t > tcache)
Definition: syscall_emul.cc:1643
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:613
gem5::setpgidFunc
SyscallReturn setpgidFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int pgid)
Target setpgid() handler.
Definition: syscall_emul.cc:893
gem5::getpagesizeFunc
SyscallReturn getpagesizeFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpagesize() handler.
Definition: syscall_emul.cc:240
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:234
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:1558
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:485
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:449
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:302
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:962
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:542
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:969
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:329
gem5::pipeFunc
SyscallReturn pipeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr)
Target pipe() handler.
Definition: syscall_emul.cc:795
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:573
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:934
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:410
gem5::setTidAddressFunc
SyscallReturn setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc, uint64_t tidPtr)
Target set_tid_address() handler.
Definition: syscall_emul.cc:269
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:718
gem5::readlinkFunc
SyscallReturn readlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> buf_ptr, size_t bufsiz)
Target readlink() handler.
Definition: syscall_emul.cc:391
gem5::connectFunc
SyscallReturn connectFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int addrlen)
Definition: syscall_emul.cc:1200
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:464
gem5::pipe2Func
SyscallReturn pipe2Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr, int flags)
Target pipe() handler.
Definition: syscall_emul.cc:801
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:998
gem5::sendmsgFunc
SyscallReturn sendmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
Definition: syscall_emul.cc:1451
gem5::gethostnameFunc
SyscallReturn gethostnameFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, int name_len)
Target gethostname() handler.
Definition: syscall_emul.cc:351
gem5::fcntl64Func
SyscallReturn fcntl64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd)
Target fcntl64() handler.
Definition: syscall_emul.cc:760
gem5::recvmsgFunc
SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
Definition: syscall_emul.cc:1313
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:559
gem5::exitFunc
SyscallReturn exitFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit() handler: terminate current context.
Definition: syscall_emul.cc:228
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:1149
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:789
gem5::rmdirFunc
SyscallReturn rmdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Definition: syscall_emul.cc:1056
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:1221
gem5::getppidFunc
SyscallReturn getppidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getppid() handler.
Definition: syscall_emul.cc:941
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:520
gem5::setsockoptFunc
SyscallReturn setsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, socklen_t len)
Definition: syscall_emul.cc:1622
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:645
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:927
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:690
gem5::mknodFunc
SyscallReturn mknodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode, dev_t dev)
Target mknod() handler.
Definition: syscall_emul.cc:1014
thread_context.hh
gem5::geteuidFunc
SyscallReturn geteuidFunc(SyscallDesc *desc, ThreadContext *tc)
Target geteuid() handler.
Definition: syscall_emul.cc:955
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:624
gem5::ftruncate64Func
SyscallReturn ftruncate64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int64_t length)
Target ftruncate64() handler.
Definition: syscall_emul.cc:594
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:285
gem5::getpeernameFunc
SyscallReturn getpeernameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> sockAddrPtr, VPtr<> addrlenPtr)
Definition: syscall_emul.cc:1595
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:1281
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 Wed Jul 28 2021 12:10:29 for gem5 by doxygen 1.8.17