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

Generated on Tue Jun 22 2021 15:28:30 for gem5 by doxygen 1.8.17