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

Generated on Wed Sep 30 2020 14:02:14 for gem5 by doxygen 1.8.17