gem5  v20.0.0.2
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/sim_exit.hh"
52 #include "sim/syscall_desc.hh"
53 #include "sim/system.hh"
54 
55 using namespace std;
56 using namespace TheISA;
57 
58 void
59 warnUnsupportedOS(std::string syscall_name)
60 {
61  warn("Cannot invoke %s on host operating system.", syscall_name);
62 }
63 
66 {
67  fatal("syscall %s (#%d) unimplemented.", desc->name(), desc->num());
68 }
69 
70 
73 {
74  warn("ignoring syscall %s(...)", desc->name());
75  return 0;
76 }
77 
80 {
81  static std::unordered_map<SyscallDesc *, bool> bool_map;
82 
83  bool &warned = bool_map[desc];
84  if (!warned) {
85  warn("ignoring syscall %s(...)\n"
86  " (further warnings will be suppressed)", desc->name());
87  warned = true;
88  }
89 
90  return 0;
91 }
92 
93 static void
94 exitFutexWake(ThreadContext *tc, Addr addr, uint64_t tgid)
95 {
96  // Clear value at address pointed to by thread's childClearTID field.
97  BufferArg ctidBuf(addr, sizeof(long));
98  long *ctid = (long *)ctidBuf.bufferPtr();
99  *ctid = 0;
100  ctidBuf.copyOut(tc->getVirtProxy());
101 
102  FutexMap &futex_map = tc->getSystemPtr()->futexMap;
103  // Wake one of the waiting threads.
104  futex_map.wakeup(addr, tgid, 1);
105 }
106 
107 static SyscallReturn
108 exitImpl(SyscallDesc *desc, ThreadContext *tc, bool group, int status)
109 {
110  auto p = tc->getProcessPtr();
111 
112  System *sys = tc->getSystemPtr();
113 
114  if (group)
115  *p->exitGroup = true;
116 
117  if (p->childClearTID)
118  exitFutexWake(tc, p->childClearTID, p->tgid());
119 
120  bool last_thread = true;
121  Process *parent = nullptr, *tg_lead = nullptr;
122  for (int i = 0; last_thread && i < sys->numContexts(); i++) {
123  Process *walk;
124  if (!(walk = sys->threadContexts[i]->getProcessPtr()))
125  continue;
126 
133  if (walk->pid() == p->tgid())
134  tg_lead = walk;
135 
136  if ((sys->threadContexts[i]->status() != ThreadContext::Halted) &&
137  (sys->threadContexts[i]->status() != ThreadContext::Halting) &&
138  (walk != p)) {
145  if (walk->tgid() == p->tgid()) {
158  if (*(p->exitGroup)) {
159  sys->threadContexts[i]->halt();
160  } else {
161  last_thread = false;
162  }
163  }
164 
174  if (*p->sigchld && (p->ppid() != 0) && (walk->pid() == p->ppid()))
175  parent = walk;
176  }
177  }
178 
179  if (last_thread) {
180  if (parent) {
181  assert(tg_lead);
182  sys->signalList.push_back(BasicSignal(tg_lead, parent, SIGCHLD));
183  }
184 
190  for (int i = 0; i < p->fds->getSize(); i++) {
191  if ((*p->fds)[i])
192  p->fds->closeFDEntry(i);
193  }
194  }
195 
196  tc->halt();
197 
202  int activeContexts = 0;
203  for (auto &system: sys->systemList)
204  activeContexts += system->numRunningContexts();
205 
206  if (activeContexts == 0) {
216  if (!DistIface::readyToExit(0)) {
217  return status;
218  }
219 
220  exitSimLoop("exiting with last active thread context", status & 0xff);
221  return status;
222  }
223 
224  return status;
225 }
226 
229 {
230  return exitImpl(desc, tc, false, status);
231 }
232 
235 {
236  return exitImpl(desc, tc, true, status);
237 }
238 
241 {
242  return (int)PageBytes;
243 }
244 
245 
247 brkFunc(SyscallDesc *desc, ThreadContext *tc, Addr new_brk)
248 {
249  // change brk addr to first arg
250  auto p = tc->getProcessPtr();
251 
252  std::shared_ptr<MemState> mem_state = p->memState;
253  Addr brk_point = mem_state->getBrkPoint();
254 
255  // in Linux at least, brk(0) returns the current break value
256  // (note that the syscall and the glibc function have different behavior)
257  if (new_brk == 0 || (new_brk == brk_point))
258  return brk_point;
259 
260  mem_state->updateBrkRegion(brk_point, new_brk);
261 
262  DPRINTF_SYSCALL(Verbose, "brk: break point changed to: %#X\n",
263  mem_state->getBrkPoint());
264 
265  return mem_state->getBrkPoint();
266 }
267 
269 setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc, uint64_t tidPtr)
270 {
271  auto process = tc->getProcessPtr();
272 
273  process->childClearTID = tidPtr;
274  return process->pid();
275 }
276 
278 closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
279 {
280  auto p = tc->getProcessPtr();
281  return p->fds->closeFDEntry(tgt_fd);
282 }
283 
286  int tgt_fd, uint64_t offs, int whence)
287 {
288  auto p = tc->getProcessPtr();
289 
290  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
291  if (!ffdp)
292  return -EBADF;
293  int sim_fd = ffdp->getSimFD();
294 
295  off_t result = lseek(sim_fd, offs, whence);
296 
297  return (result == (off_t)-1) ? -errno : result;
298 }
299 
300 
303  int tgt_fd, uint64_t offset_high, uint32_t offset_low,
304  Addr result_ptr, int whence)
305 {
306  auto p = tc->getProcessPtr();
307 
308  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
309  if (!ffdp)
310  return -EBADF;
311  int sim_fd = ffdp->getSimFD();
312 
313  uint64_t offset = (offset_high << 32) | offset_low;
314 
315  uint64_t result = lseek(sim_fd, offset, whence);
316  result = htog(result, tc->getSystemPtr()->getGuestByteOrder());
317 
318  if (result == (off_t)-1)
319  return -errno;
320  // Assuming that the size of loff_t is 64 bits on the target platform
321  BufferArg result_buf(result_ptr, sizeof(result));
322  memcpy(result_buf.bufferPtr(), &result, sizeof(result));
323  result_buf.copyOut(tc->getVirtProxy());
324  return 0;
325 }
326 
327 
329 munmapFunc(SyscallDesc *desc, ThreadContext *tc, Addr start, size_t length)
330 {
331  // Even if the system is currently not capable of recycling physical
332  // pages, there is no reason we can't unmap them so that we trigger
333  // appropriate seg faults when the application mistakenly tries to
334  // access them again.
335  auto p = tc->getProcessPtr();
336 
337  if (start & (tc->getSystemPtr()->getPageBytes() - 1) || !length) {
338  return -EINVAL;
339  }
340 
341  length = roundUp(length, tc->getSystemPtr()->getPageBytes());
342 
343  p->memState->unmapRegion(start, length);
344 
345  return 0;
346 }
347 
348 
349 const char *hostname = "m5.eecs.umich.edu";
350 
353  Addr buf_ptr, int name_len)
354 {
355  BufferArg name(buf_ptr, name_len);
356  strncpy((char *)name.bufferPtr(), hostname, name_len);
357  name.copyOut(tc->getVirtProxy());
358  return 0;
359 }
360 
363  Addr buf_ptr, unsigned long size)
364 {
365  int result = 0;
366  auto p = tc->getProcessPtr();
367  BufferArg buf(buf_ptr, size);
368 
369  // Is current working directory defined?
370  string cwd = p->tgtCwd;
371  if (!cwd.empty()) {
372  if (cwd.length() >= size) {
373  // Buffer too small
374  return -ERANGE;
375  }
376  strncpy((char *)buf.bufferPtr(), cwd.c_str(), size);
377  result = cwd.length();
378  } else {
379  if (getcwd((char *)buf.bufferPtr(), size)) {
380  result = strlen((char *)buf.bufferPtr());
381  } else {
382  result = -1;
383  }
384  }
385 
386  buf.copyOut(tc->getVirtProxy());
387 
388  return (result == -1) ? -errno : result;
389 }
390 
393  Addr pathname, Addr buf_ptr, size_t bufsiz)
394 {
395  string path;
396  auto p = tc->getProcessPtr();
397 
398  if (!tc->getVirtProxy().tryReadString(path, pathname))
399  return -EFAULT;
400 
401  // Adjust path for cwd and redirection
402  path = p->checkPathRedirect(path);
403 
404  BufferArg buf(buf_ptr, bufsiz);
405 
406  int result = -1;
407  if (path != "/proc/self/exe") {
408  result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz);
409  } else {
410  // Emulate readlink() called on '/proc/self/exe' should return the
411  // absolute path of the binary running in the simulated system (the
412  // Process' executable). It is possible that using this path in
413  // the simulated system will result in unexpected behavior if:
414  // 1) One binary runs another (e.g., -c time -o "my_binary"), and
415  // called binary calls readlink().
416  // 2) The host's full path to the running benchmark changes from one
417  // simulation to another. This can result in different simulated
418  // performance since the simulated system will process the binary
419  // path differently, even if the binary itself does not change.
420 
421  // Get the absolute canonical path to the running application
422  char real_path[PATH_MAX];
423  char *check_real_path = realpath(p->progName(), real_path);
424  if (!check_real_path) {
425  fatal("readlink('/proc/self/exe') unable to resolve path to "
426  "executable: %s", p->progName());
427  }
428  strncpy((char*)buf.bufferPtr(), real_path, bufsiz);
429  size_t real_path_len = strlen(real_path);
430  if (real_path_len > bufsiz) {
431  // readlink will truncate the contents of the
432  // path to ensure it is no more than bufsiz
433  result = bufsiz;
434  } else {
435  result = real_path_len;
436  }
437 
438  // Issue a warning about potential unexpected results
439  warn_once("readlink() called on '/proc/self/exe' may yield unexpected "
440  "results in various settings.\n Returning '%s'\n",
441  (char*)buf.bufferPtr());
442  }
443 
444  buf.copyOut(tc->getVirtProxy());
445 
446  return (result == -1) ? -errno : result;
447 }
448 
451 {
452  string path;
453  auto p = tc->getProcessPtr();
454 
455  if (!tc->getVirtProxy().tryReadString(path, pathname))
456  return -EFAULT;
457 
458  path = p->checkPathRedirect(path);
459 
460  int result = unlink(path.c_str());
461  return (result == -1) ? -errno : result;
462 }
463 
466  Addr pathname, Addr new_pathname)
467 {
468  string path;
469  string new_path;
470  auto p = tc->getProcessPtr();
471 
472  auto &virt_mem = tc->getVirtProxy();
473  if (!virt_mem.tryReadString(path, pathname))
474  return -EFAULT;
475  if (!virt_mem.tryReadString(new_path, new_pathname))
476  return -EFAULT;
477 
478  path = p->absolutePath(path, true);
479  new_path = p->absolutePath(new_path, true);
480 
481  int result = link(path.c_str(), new_path.c_str());
482  return (result == -1) ? -errno : result;
483 }
484 
487  Addr pathname, Addr new_pathname)
488 {
489  string path;
490  string new_path;
491  auto p = tc->getProcessPtr();
492 
493  auto &virt_mem = tc->getVirtProxy();
494  if (!virt_mem.tryReadString(path, pathname))
495  return -EFAULT;
496  if (!virt_mem.tryReadString(new_path, new_pathname))
497  return -EFAULT;
498 
499  path = p->absolutePath(path, true);
500  new_path = p->absolutePath(new_path, true);
501 
502  int result = symlink(path.c_str(), new_path.c_str());
503  return (result == -1) ? -errno : result;
504 }
505 
507 mkdirFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, mode_t mode)
508 {
509  auto p = tc->getProcessPtr();
510  std::string path;
511  if (!tc->getVirtProxy().tryReadString(path, pathname))
512  return -EFAULT;
513 
514  path = p->checkPathRedirect(path);
515 
516  auto result = mkdir(path.c_str(), mode);
517  return (result == -1) ? -errno : result;
518 }
519 
521 renameFunc(SyscallDesc *desc, ThreadContext *tc, Addr oldpath, Addr newpath)
522 {
523  auto p = tc->getProcessPtr();
524 
525  string old_name;
526  if (!tc->getVirtProxy().tryReadString(old_name, oldpath))
527  return -EFAULT;
528 
529  string new_name;
530  if (!tc->getVirtProxy().tryReadString(new_name, newpath))
531  return -EFAULT;
532 
533  // Adjust path for cwd and redirection
534  old_name = p->checkPathRedirect(old_name);
535  new_name = p->checkPathRedirect(new_name);
536 
537  int64_t result = rename(old_name.c_str(), new_name.c_str());
538  return (result == -1) ? -errno : result;
539 }
540 
542 truncateFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, off_t length)
543 {
544  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  Addr pathname, int64_t length)
574 {
575  auto process = tc->getProcessPtr();
576  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  Addr pathname, uint32_t owner, uint32_t group)
625 {
626  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 
794 pipeFunc(SyscallDesc *desc, ThreadContext *tc, Addr tgt_addr)
795 {
796  return pipe2Func(desc, tc, tgt_addr, 0);
797 }
798 
800 pipe2Func(SyscallDesc *desc, ThreadContext *tc, Addr 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 (int i = 0; i < sysh->numContexts(); i++) {
909  if (sysh->threadContexts[i]->status() != ThreadContext::Halted) {
910  Process *temp_h = sysh->threadContexts[i]->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  Addr pathname, mode_t mode)
999 {
1000  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  Addr 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, Addr 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, Addr 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, Addr 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, Addr 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, Addr 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, Addr bufrPtr, size_t bufrLen, int flags,
1220  Addr addrPtr, Addr 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, Addr bufrPtr, size_t bufrLen, int flags,
1280  Addr 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, Addr 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, Addr 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, Addr valPtr, Addr lenPtr)
1517 {
1518  // union of all possible return value types from getsockopt
1519  union val {
1520  int i_val;
1521  long l_val;
1522  struct linger linger_val;
1523  struct timeval timeval_val;
1524  } val;
1525 
1526  auto p = tc->getProcessPtr();
1527 
1528  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1529  if (!sfdp)
1530  return -EBADF;
1531  int sim_fd = sfdp->getSimFD();
1532 
1533  socklen_t len = sizeof(val);
1534  int status = getsockopt(sim_fd, level, optname, &val, &len);
1535 
1536  if (status == -1)
1537  return -errno;
1538 
1539  // copy val to valPtr and pass it on
1540  BufferArg valBuf(valPtr, sizeof(val));
1541  memcpy(valBuf.bufferPtr(), &val, sizeof(val));
1542  valBuf.copyOut(tc->getVirtProxy());
1543 
1544  // copy len to lenPtr and pass it on
1545  BufferArg lenBuf(lenPtr, sizeof(len));
1546  memcpy(lenBuf.bufferPtr(), &len, sizeof(len));
1547  lenBuf.copyOut(tc->getVirtProxy());
1548 
1549  return status;
1550 }
1551 
1554  int tgt_fd, Addr addrPtr, Addr lenPtr)
1555 {
1556  auto p = tc->getProcessPtr();
1557 
1558  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1559  if (!sfdp)
1560  return -EBADF;
1561  int sim_fd = sfdp->getSimFD();
1562 
1563  // lenPtr is an in-out paramenter:
1564  // sending the address length in, conveying the final length out
1565 
1566  // Read in the value of len from the passed pointer.
1567  BufferArg lenBuf(lenPtr, sizeof(socklen_t));
1568  lenBuf.copyIn(tc->getVirtProxy());
1569  socklen_t len = *(socklen_t *)lenBuf.bufferPtr();
1570 
1571  struct sockaddr sa;
1572  int status = getsockname(sim_fd, &sa, &len);
1573 
1574  if (status == -1)
1575  return -errno;
1576 
1577  // Copy address to addrPtr and pass it on.
1578  BufferArg addrBuf(addrPtr, sizeof(sa));
1579  memcpy(addrBuf.bufferPtr(), &sa, sizeof(sa));
1580  addrBuf.copyOut(tc->getVirtProxy());
1581 
1582  // Copy len to lenPtr and pass it on.
1583  *(socklen_t *)lenBuf.bufferPtr() = len;
1584  lenBuf.copyOut(tc->getVirtProxy());
1585 
1586  return status;
1587 }
1588 
1591  int tgt_fd, Addr sockAddrPtr, Addr addrlenPtr)
1592 {
1593  auto p = tc->getProcessPtr();
1594 
1595  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1596  if (!sfdp)
1597  return -EBADF;
1598  int sim_fd = sfdp->getSimFD();
1599 
1600  BufferArg bufAddrlen(addrlenPtr, sizeof(unsigned));
1601  bufAddrlen.copyIn(tc->getVirtProxy());
1602  BufferArg bufSock(sockAddrPtr, *(unsigned *)bufAddrlen.bufferPtr());
1603 
1604  int retval = getpeername(sim_fd,
1605  (struct sockaddr *)bufSock.bufferPtr(),
1606  (unsigned *)bufAddrlen.bufferPtr());
1607 
1608  if (retval != -1) {
1609  bufSock.copyOut(tc->getVirtProxy());
1610  bufAddrlen.copyOut(tc->getVirtProxy());
1611  }
1612 
1613  return (retval == -1) ? -errno : retval;
1614 }
1615 
1618  int tgt_fd, int level, int optname, Addr valPtr, socklen_t len)
1619 {
1620  auto p = tc->getProcessPtr();
1621 
1622  BufferArg valBuf(valPtr, len);
1623  valBuf.copyIn(tc->getVirtProxy());
1624 
1625  auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1626  if (!sfdp)
1627  return -EBADF;
1628  int sim_fd = sfdp->getSimFD();
1629 
1630  int status = setsockopt(sim_fd, level, optname,
1631  (struct sockaddr *)valBuf.bufferPtr(), len);
1632 
1633  return (status == -1) ? -errno : status;
1634 }
1635 
1638  Addr cpu_ptr, Addr node_ptr, Addr tcache_ptr)
1639 {
1640  bool error = false;
1641 
1642  // unsigned is the same size (4) on all Linux supported ISAs.
1643  if (cpu_ptr != 0) {
1644  TypedBufferArg<uint32_t> result(cpu_ptr);
1645  *result = htog(tc->contextId(),
1646  tc->getSystemPtr()->getGuestByteOrder());
1647  error |= !result.copyOut(tc->getVirtProxy());
1648  }
1649 
1650  // Set a fixed NUMA node 0.
1651  if (node_ptr != 0) {
1652  TypedBufferArg<uint32_t> result(node_ptr);
1653  *result = 0;
1654  error |= !result.copyOut(tc->getVirtProxy());
1655  }
1656 
1657  return error ? -EFAULT : 0;
1658 }
count
Definition: misc.hh:703
SyscallReturn getpidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpid() handler.
FutexMap futexMap
Definition: system.hh:495
virtual void halt()=0
Set the status to Halted.
virtual System * getSystemPtr()=0
SyscallReturn closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
Target close() handler.
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:171
SyscallReturn ignoreFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we never intend to implement (signal handling, etc.) and should not affect the correct behavior of the program.
Definition: syscall_emul.cc:72
const std::string & name()
Definition: trace.cc:50
SyscallReturn readlinkFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr buf_ptr, size_t bufsiz)
Target readlink() handler.
uint64_t childClearTID
Calls a futex wakeup at the address specified by this pointer when this process exits.
Definition: process.hh:285
Bitfield< 7 > i
Trying to exit and waiting for an event to completely exit.
SyscallReturn linkFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr new_pathname)
Target link() handler.
bool copyIn(PortProxy &memproxy)
copy data into simulator space (read from target memory)
ip6_addr_t addr
Definition: inet.hh:330
uint64_t uid()
Definition: process.hh:80
virtual PortProxy & getVirtProxy()=0
SyscallReturn setsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, Addr valPtr, socklen_t len)
SyscallReturn recvfromFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr bufrPtr, size_t bufrLen, int flags, Addr addrPtr, Addr addrlenPtr)
virtual Process * getProcessPtr()=0
SyscallReturn sendmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr msgPtr, int flags)
Holds file descriptors for host-backed files; host-backed files are files which were opened on the ph...
Definition: fd_entry.hh:110
SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr msgPtr, int flags)
SyscallReturn pipe2Func(SyscallDesc *desc, ThreadContext *tc, Addr tgt_addr, int flags)
Target pipe() handler.
Definition: system.hh:72
Bitfield< 23, 0 > offset
Definition: types.hh:152
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:587
ByteOrder getGuestByteOrder() const
Get the guest byte order.
Definition: system.hh:254
Bitfield< 4, 0 > mode
const char * hostname
T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
Definition: intmath.hh:114
SyscallReturn fcntlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd, GuestABI::VarArgs< int > varargs)
Target fcntl() handler.
SyscallReturn getpeernameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr sockAddrPtr, Addr addrlenPtr)
TypedBufferArg is a class template; instances of this template represent typed buffers in target user...
ThreadContext is the external interface to all thread state for anything outside of the CPU...
SyscallReturn ftruncateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, off_t length)
Target ftruncate() handler.
SyscallReturn sendtoFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr bufrPtr, size_t bufrLen, int flags, Addr addrPtr, socklen_t addrLen)
#define DPRINTF_SYSCALL(FLAGEXT, FMT,...)
This macro is intended to help with readability.
SyscallReturn fallocateFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int mode, off_t offset, off_t len)
Bitfield< 63 > val
Definition: misc.hh:769
Bitfield< 5, 0 > status
SyscallReturn pipeFunc(SyscallDesc *desc, ThreadContext *tc, Addr tgt_addr)
Target pipe() handler.
SyscallReturn getgidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getgid() handler.
SyscallReturn getcwdFunc(SyscallDesc *desc, ThreadContext *tc, Addr buf_ptr, unsigned long size)
Target getcwd() handler.
SyscallReturn fcntl64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd)
Target fcntl64() handler.
SyscallReturn unimplementedFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we haven&#39;t thought about.
Definition: syscall_emul.cc:65
SyscallReturn munmapFunc(SyscallDesc *desc, ThreadContext *tc, Addr start, size_t length)
Target munmap() handler.
SyscallReturn getuidFunc(SyscallDesc *desc, ThreadContext *tc)
SyscallReturn getppidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getppid() handler.
SyscallReturn listenFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int backlog)
T htog(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:155
SyscallReturn lseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t offs, int whence)
Target lseek() handler.
SyscallReturn getsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, Addr valPtr, Addr lenPtr)
uint64_t ppid()
Definition: process.hh:85
SyscallReturn truncateFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, off_t length)
Target truncate() handler.
SyscallReturn accessFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, mode_t mode)
Target access() handler.
int wakeup(Addr addr, uint64_t tgid, int count)
Wakes up at most count waiting threads on a futex.
Definition: futex_map.hh:140
uint64_t pid()
Definition: process.hh:84
SyscallReturn symlinkFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, Addr new_pathname)
Target symlink() handler.
SyscallReturn rmdirFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname)
ByteOrder
Definition: types.hh:245
uint64_t euid()
Definition: process.hh:81
SyscallReturn getsocknameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr addrPtr, Addr lenPtr)
SyscallReturn brkFunc(SyscallDesc *desc, ThreadContext *tc, Addr new_brk)
Target brk() handler: set brk address.
Bitfield< 3 > sa
std::vector< ThreadContext * > threadContexts
Definition: system.hh:182
Bitfield< 18, 16 > len
int num() const
Definition: syscall_desc.hh:77
Extends the base class to include a host-backed file descriptor field that records the integer used t...
Definition: fd_entry.hh:74
unsigned numContexts() const
Definition: system.hh:198
void * bufferPtr()
Return a pointer to the internal simulator-space buffer.
SyscallReturn fchownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t owner, uint32_t group)
Target fchown() handler.
SyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, ThreadContext *tc)
Like above, but only prints a warning once per syscall desc it&#39;s used with.
Definition: syscall_emul.cc:79
static bool readyToExit(Tick delay)
Initiate the exit from the simulation.
Definition: dist_iface.cc:896
SyscallReturn pipePseudoFunc(SyscallDesc *desc, ThreadContext *tc)
Pseudo Funcs - These functions use a different return convension, returning a second value in a regis...
uint64_t pgid()
Definition: process.hh:86
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:140
std::string name() const
Definition: syscall_desc.hh:76
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.
SyscallReturn bindFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr buf_ptr, int addrlen)
#define warn_once(...)
Definition: logging.hh:212
std::list< BasicSignal > signalList
Definition: system.hh:504
bool startswith(const char *s, const char *prefix)
Return true if &#39;s&#39; starts with the prefix string &#39;prefix&#39;.
Definition: str.hh:224
Bitfield< 15 > system
Definition: misc.hh:997
Bitfield< 20 > level
Definition: intmessage.hh:47
This class provides the wrapper interface for the system call implementations which are defined in th...
Definition: syscall_desc.hh:66
SyscallReturn mkdirFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, mode_t mode)
Target mkdir() handler.
SyscallReturn gethostnameFunc(SyscallDesc *desc, ThreadContext *tc, Addr buf_ptr, int name_len)
Target gethostname() handler.
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
Bitfield< 25, 21 > bo
Definition: types.hh:62
Declarations of a non-full system Page Table.
SyscallReturn truncate64Func(SyscallDesc *desc, ThreadContext *tc, Addr pathname, int64_t length)
Target truncate64() handler.
This file defines objects used to emulate syscalls from the target application on the host machine...
Permanently shut down.
SyscallReturn getpgrpFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpgrpFunc() handler.
SyscallReturn connectFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, Addr buf_ptr, int addrlen)
std::string checkPathRedirect(const std::string &filename)
Redirect file path if it matches any keys initialized by system object.
Definition: process.cc:408
bool copyOut(PortProxy &memproxy)
copy data out of simulator space (write to target memory)
SyscallReturn getpagesizeFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpagesize() handler.
SyscallReturn unlinkFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname)
Target unlink() handler.
FutexMap class holds a map of all futexes used in the system.
Definition: futex_map.hh:117
virtual ContextID contextId() const =0
SyscallReturn exitGroupFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit_group() handler: terminate simulation. (exit all threads)
uint64_t gid()
Definition: process.hh:82
SyscallReturn chdirFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname)
Target chdir() handler.
const Addr PageBytes
Definition: isa_traits.hh:56
BufferArg represents an untyped buffer in target user space that is passed by reference to an (emulat...
SyscallReturn mknodFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, mode_t mode, dev_t dev)
Target mknod() handler.
SyscallReturn geteuidFunc(SyscallDesc *desc, ThreadContext *tc)
Target geteuid() handler.
SyscallReturn setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc, uint64_t tidPtr)
Target set_tid_address() handler.
uint8_t length
Definition: inet.hh:329
SyscallReturn umaskFunc(SyscallDesc *desc, ThreadContext *tc)
Target umask() handler.
static SyscallReturn exitImpl(SyscallDesc *desc, ThreadContext *tc, bool group, int status)
#define warn(...)
Definition: logging.hh:208
SyscallReturn renameFunc(SyscallDesc *desc, ThreadContext *tc, Addr oldpath, Addr newpath)
Target rename() handler.
Declaration and inline definition of ChunkGenerator object.
This class represents the return value from an emulated system call, including any errno setting...
SyscallReturn getegidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getegid() handler.
void warnUnsupportedOS(std::string syscall_name)
Definition: syscall_emul.cc:59
uint64_t tgid()
Definition: process.hh:88
SyscallReturn setpgidFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int pgid)
Target setpgid() handler.
SyscallReturn shutdownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int how)
Target shutdown() handler.
SyscallReturn dupFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
FIXME: The file description is not shared among file descriptors created with dup.
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
Bitfield< 0 > p
SyscallReturn getcpuFunc(SyscallDesc *desc, ThreadContext *tc, Addr cpu_ptr, Addr node_ptr, Addr tcache_ptr)
SyscallReturn dup2Func(SyscallDesc *desc, ThreadContext *tc, int old_tgt_fd, int new_tgt_fd)
Target dup2() handler.
static void exitFutexWake(ThreadContext *tc, Addr addr, uint64_t tgid)
Definition: syscall_emul.cc:94
SyscallReturn ftruncate64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int64_t length)
Target ftruncate64() handler.
Addr getPageBytes() const
Get the page bytes for the ISA.
Definition: system.hh:266
uint64_t egid()
Definition: process.hh:83
SyscallReturn exitFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit() handler: terminate current context.
SyscallReturn chownFunc(SyscallDesc *desc, ThreadContext *tc, Addr pathname, uint32_t owner, uint32_t group)
Target chown() handler.
SyscallReturn gettidFunc(SyscallDesc *desc, ThreadContext *tc)
Target gettid() handler.
static std::vector< System * > systemList
Definition: system.hh:490

Generated on Mon Jun 8 2020 15:45:13 for gem5 by doxygen 1.8.13