gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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  * Authors: Steve Reinhardt
29  * Ali Saidi
30  */
31 
32 #include "sim/syscall_emul.hh"
33 
34 #include <fcntl.h>
35 #include <unistd.h>
36 
37 #include <csignal>
38 #include <iostream>
39 #include <string>
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 "mem/page_table.hh"
47 #include "sim/process.hh"
48 #include "sim/sim_exit.hh"
50 #include "sim/syscall_desc.hh"
51 #include "sim/system.hh"
52 
53 using namespace std;
54 using namespace TheISA;
55 
57 unimplementedFunc(SyscallDesc *desc, int callnum, Process *process,
58  ThreadContext *tc)
59 {
60  fatal("syscall %s (#%d) unimplemented.", desc->name(), callnum);
61 
62  return 1;
63 }
64 
65 
67 ignoreFunc(SyscallDesc *desc, int callnum, Process *process,
68  ThreadContext *tc)
69 {
70  if (desc->needWarning()) {
71  warn("ignoring syscall %s(...)%s", desc->name(), desc->warnOnce() ?
72  "\n (further warnings will be suppressed)" : "");
73  }
74 
75  return 0;
76 }
77 
78 static void
79 exitFutexWake(ThreadContext *tc, Addr addr, uint64_t tgid)
80 {
81  // Clear value at address pointed to by thread's childClearTID field.
82  BufferArg ctidBuf(addr, sizeof(long));
83  long *ctid = (long *)ctidBuf.bufferPtr();
84  *ctid = 0;
85  ctidBuf.copyOut(tc->getMemProxy());
86 
87  FutexMap &futex_map = tc->getSystemPtr()->futexMap;
88  // Wake one of the waiting threads.
89  futex_map.wakeup(addr, tgid, 1);
90 }
91 
92 static SyscallReturn
93 exitImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc,
94  bool group)
95 {
96  int index = 0;
97  int status = p->getSyscallArg(tc, index);
98 
99  System *sys = tc->getSystemPtr();
100 
101  int activeContexts = 0;
102  for (auto &system: sys->systemList)
103  activeContexts += system->numRunningContexts();
104  if (activeContexts == 1) {
105  exitSimLoop("exiting with last active thread context", status & 0xff);
106  return status;
107  }
108 
109  if (group)
110  *p->exitGroup = true;
111 
112  if (p->childClearTID)
113  exitFutexWake(tc, p->childClearTID, p->tgid());
114 
115  bool last_thread = true;
116  Process *parent = nullptr, *tg_lead = nullptr;
117  for (int i = 0; last_thread && i < sys->numContexts(); i++) {
118  Process *walk;
119  if (!(walk = sys->threadContexts[i]->getProcessPtr()))
120  continue;
121 
128  if (walk->pid() == p->tgid())
129  tg_lead = walk;
130 
131  if ((sys->threadContexts[i]->status() != ThreadContext::Halted)
132  && (walk != p)) {
139  if (walk->tgid() == p->tgid())
140  last_thread = false;
141 
151  if (*p->sigchld && (p->ppid() != 0) && (walk->pid() == p->ppid()))
152  parent = walk;
153  }
154  }
155 
156  if (last_thread) {
157  if (parent) {
158  assert(tg_lead);
159  sys->signalList.push_back(BasicSignal(tg_lead, parent, SIGCHLD));
160  }
161 
167  for (int i = 0; i < p->fds->getSize(); i++) {
168  if ((*p->fds)[i])
169  p->fds->closeFDEntry(i);
170  }
171  }
172 
173  tc->halt();
174  return status;
175 }
176 
178 exitFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
179 {
180  return exitImpl(desc, callnum, p, tc, false);
181 }
182 
184 exitGroupFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
185 {
186  return exitImpl(desc, callnum, p, tc, true);
187 }
188 
191 {
192  return (int)PageBytes;
193 }
194 
195 
197 brkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
198 {
199  // change brk addr to first arg
200  int index = 0;
201  Addr new_brk = p->getSyscallArg(tc, index);
202 
203  std::shared_ptr<MemState> mem_state = p->memState;
204  Addr brk_point = mem_state->getBrkPoint();
205 
206  // in Linux at least, brk(0) returns the current break value
207  // (note that the syscall and the glibc function have different behavior)
208  if (new_brk == 0)
209  return brk_point;
210 
211  if (new_brk > brk_point) {
212  // might need to allocate some new pages
213  for (ChunkGenerator gen(brk_point,
214  new_brk - brk_point,
215  PageBytes); !gen.done(); gen.next()) {
216  if (!p->pTable->translate(gen.addr()))
217  p->allocateMem(roundDown(gen.addr(), PageBytes), PageBytes);
218 
219  // if the address is already there, zero it out
220  else {
221  uint8_t zero = 0;
223 
224  // split non-page aligned accesses
225  Addr next_page = roundUp(gen.addr(), PageBytes);
226  uint32_t size_needed = next_page - gen.addr();
227  tp.memsetBlob(gen.addr(), zero, size_needed);
228  if (gen.addr() + PageBytes > next_page &&
229  next_page < new_brk &&
230  p->pTable->translate(next_page)) {
231  size_needed = PageBytes - size_needed;
232  tp.memsetBlob(next_page, zero, size_needed);
233  }
234  }
235  }
236  }
237 
238  mem_state->setBrkPoint(new_brk);
239  DPRINTF_SYSCALL(Verbose, "brk: break point changed to: %#X\n",
240  mem_state->getBrkPoint());
241  return mem_state->getBrkPoint();
242 }
243 
245 setTidAddressFunc(SyscallDesc *desc, int callnum, Process *process,
246  ThreadContext *tc)
247 {
248  int index = 0;
249  uint64_t tidPtr = process->getSyscallArg(tc, index);
250 
251  process->childClearTID = tidPtr;
252  return process->pid();
253 }
254 
257 {
258  int index = 0;
259  int tgt_fd = p->getSyscallArg(tc, index);
260 
261  return p->fds->closeFDEntry(tgt_fd);
262 }
263 
264 
267 {
268  int index = 0;
269  int tgt_fd = p->getSyscallArg(tc, index);
270  Addr buf_ptr = p->getSyscallArg(tc, index);
271  int nbytes = p->getSyscallArg(tc, index);
272 
273  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
274  if (!hbfdp)
275  return -EBADF;
276  int sim_fd = hbfdp->getSimFD();
277 
278  BufferArg bufArg(buf_ptr, nbytes);
279  int bytes_read = read(sim_fd, bufArg.bufferPtr(), nbytes);
280 
281  if (bytes_read > 0)
282  bufArg.copyOut(tc->getMemProxy());
283 
284  return bytes_read;
285 }
286 
289 {
290  int index = 0;
291  int tgt_fd = p->getSyscallArg(tc, index);
292  Addr buf_ptr = p->getSyscallArg(tc, index);
293  int nbytes = p->getSyscallArg(tc, index);
294 
295  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
296  if (!hbfdp)
297  return -EBADF;
298  int sim_fd = hbfdp->getSimFD();
299 
300  BufferArg bufArg(buf_ptr, nbytes);
301  bufArg.copyIn(tc->getMemProxy());
302 
303  int bytes_written = write(sim_fd, bufArg.bufferPtr(), nbytes);
304 
305  fsync(sim_fd);
306 
307  return bytes_written;
308 }
309 
310 
313 {
314  int index = 0;
315  int tgt_fd = p->getSyscallArg(tc, index);
316  uint64_t offs = p->getSyscallArg(tc, index);
317  int whence = p->getSyscallArg(tc, index);
318 
319  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
320  if (!ffdp)
321  return -EBADF;
322  int sim_fd = ffdp->getSimFD();
323 
324  off_t result = lseek(sim_fd, offs, whence);
325 
326  return (result == (off_t)-1) ? -errno : result;
327 }
328 
329 
332 {
333  int index = 0;
334  int tgt_fd = p->getSyscallArg(tc, index);
335  uint64_t offset_high = p->getSyscallArg(tc, index);
336  uint32_t offset_low = p->getSyscallArg(tc, index);
337  Addr result_ptr = p->getSyscallArg(tc, index);
338  int whence = p->getSyscallArg(tc, index);
339 
340  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
341  if (!ffdp)
342  return -EBADF;
343  int sim_fd = ffdp->getSimFD();
344 
345  uint64_t offset = (offset_high << 32) | offset_low;
346 
347  uint64_t result = lseek(sim_fd, offset, whence);
348  result = TheISA::htog(result);
349 
350  if (result == (off_t)-1)
351  return -errno;
352  // Assuming that the size of loff_t is 64 bits on the target platform
353  BufferArg result_buf(result_ptr, sizeof(result));
354  memcpy(result_buf.bufferPtr(), &result, sizeof(result));
355  result_buf.copyOut(tc->getMemProxy());
356  return 0;
357 }
358 
359 
362 {
363  // With mmap more fully implemented, it might be worthwhile to bite
364  // the bullet and implement munmap. Should allow us to reuse simulated
365  // memory.
366  return 0;
367 }
368 
369 
370 const char *hostname = "m5.eecs.umich.edu";
371 
374 {
375  int index = 0;
376  Addr buf_ptr = p->getSyscallArg(tc, index);
377  int name_len = p->getSyscallArg(tc, index);
378  BufferArg name(buf_ptr, name_len);
379 
380  strncpy((char *)name.bufferPtr(), hostname, name_len);
381 
382  name.copyOut(tc->getMemProxy());
383 
384  return 0;
385 }
386 
389 {
390  int result = 0;
391  int index = 0;
392  Addr buf_ptr = p->getSyscallArg(tc, index);
393  unsigned long size = p->getSyscallArg(tc, index);
394  BufferArg buf(buf_ptr, size);
395 
396  // Is current working directory defined?
397  string cwd = p->getcwd();
398  if (!cwd.empty()) {
399  if (cwd.length() >= size) {
400  // Buffer too small
401  return -ERANGE;
402  }
403  strncpy((char *)buf.bufferPtr(), cwd.c_str(), size);
404  result = cwd.length();
405  } else {
406  if (getcwd((char *)buf.bufferPtr(), size)) {
407  result = strlen((char *)buf.bufferPtr());
408  } else {
409  result = -1;
410  }
411  }
412 
413  buf.copyOut(tc->getMemProxy());
414 
415  return (result == -1) ? -errno : result;
416 }
417 
419 readlinkFunc(SyscallDesc *desc, int callnum, Process *process,
420  ThreadContext *tc)
421 {
422  return readlinkFunc(desc, callnum, process, tc, 0);
423 }
424 
427  int index)
428 {
429  string path;
430 
431  if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
432  return -EFAULT;
433 
434  // Adjust path for current working directory
435  path = p->fullPath(path);
436 
437  Addr buf_ptr = p->getSyscallArg(tc, index);
438  size_t bufsiz = p->getSyscallArg(tc, index);
439 
440  BufferArg buf(buf_ptr, bufsiz);
441 
442  int result = -1;
443  if (path != "/proc/self/exe") {
444  result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz);
445  } else {
446  // Emulate readlink() called on '/proc/self/exe' should return the
447  // absolute path of the binary running in the simulated system (the
448  // Process' executable). It is possible that using this path in
449  // the simulated system will result in unexpected behavior if:
450  // 1) One binary runs another (e.g., -c time -o "my_binary"), and
451  // called binary calls readlink().
452  // 2) The host's full path to the running benchmark changes from one
453  // simulation to another. This can result in different simulated
454  // performance since the simulated system will process the binary
455  // path differently, even if the binary itself does not change.
456 
457  // Get the absolute canonical path to the running application
458  char real_path[PATH_MAX];
459  char *check_real_path = realpath(p->progName(), real_path);
460  if (!check_real_path) {
461  fatal("readlink('/proc/self/exe') unable to resolve path to "
462  "executable: %s", p->progName());
463  }
464  strncpy((char*)buf.bufferPtr(), real_path, bufsiz);
465  size_t real_path_len = strlen(real_path);
466  if (real_path_len > bufsiz) {
467  // readlink will truncate the contents of the
468  // path to ensure it is no more than bufsiz
469  result = bufsiz;
470  } else {
471  result = real_path_len;
472  }
473 
474  // Issue a warning about potential unexpected results
475  warn_once("readlink() called on '/proc/self/exe' may yield unexpected "
476  "results in various settings.\n Returning '%s'\n",
477  (char*)buf.bufferPtr());
478  }
479 
480  buf.copyOut(tc->getMemProxy());
481 
482  return (result == -1) ? -errno : result;
483 }
484 
487 {
488  return unlinkHelper(desc, num, p, tc, 0);
489 }
490 
493  int index)
494 {
495  string path;
496 
497  if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
498  return -EFAULT;
499 
500  // Adjust path for current working directory
501  path = p->fullPath(path);
502 
503  int result = unlink(path.c_str());
504  return (result == -1) ? -errno : result;
505 }
506 
507 
510 {
511  string path;
512 
513  int index = 0;
514  if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
515  return -EFAULT;
516 
517  // Adjust path for current working directory
518  path = p->fullPath(path);
519 
520  mode_t mode = p->getSyscallArg(tc, index);
521 
522  int result = mkdir(path.c_str(), mode);
523  return (result == -1) ? -errno : result;
524 }
525 
528 {
529  string old_name;
530 
531  int index = 0;
532  if (!tc->getMemProxy().tryReadString(old_name, p->getSyscallArg(tc, index)))
533  return -EFAULT;
534 
535  string new_name;
536 
537  if (!tc->getMemProxy().tryReadString(new_name, p->getSyscallArg(tc, index)))
538  return -EFAULT;
539 
540  // Adjust path for current working directory
541  old_name = p->fullPath(old_name);
542  new_name = p->fullPath(new_name);
543 
544  int64_t result = rename(old_name.c_str(), new_name.c_str());
545  return (result == -1) ? -errno : result;
546 }
547 
550 {
551  string path;
552 
553  int index = 0;
554  if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
555  return -EFAULT;
556 
557  off_t length = p->getSyscallArg(tc, index);
558 
559  // Adjust path for current working directory
560  path = p->fullPath(path);
561 
562  int result = truncate(path.c_str(), length);
563  return (result == -1) ? -errno : result;
564 }
565 
568 {
569  int index = 0;
570  int tgt_fd = p->getSyscallArg(tc, index);
571  off_t length = p->getSyscallArg(tc, index);
572 
573  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
574  if (!ffdp)
575  return -EBADF;
576  int sim_fd = ffdp->getSimFD();
577 
578  int result = ftruncate(sim_fd, length);
579  return (result == -1) ? -errno : result;
580 }
581 
584  Process *process, ThreadContext *tc)
585 {
586  int index = 0;
587  string path;
588 
589  if (!tc->getMemProxy().tryReadString(path, process->getSyscallArg(tc, index)))
590  return -EFAULT;
591 
592  int64_t length = process->getSyscallArg(tc, index, 64);
593 
594  // Adjust path for current working directory
595  path = process->fullPath(path);
596 
597 #if NO_STAT64
598  int result = truncate(path.c_str(), length);
599 #else
600  int result = truncate64(path.c_str(), length);
601 #endif
602  return (result == -1) ? -errno : result;
603 }
604 
607 {
608  int index = 0;
609  int tgt_fd = p->getSyscallArg(tc, index);
610  int64_t length = p->getSyscallArg(tc, index, 64);
611 
612  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
613  if (!ffdp)
614  return -EBADF;
615  int sim_fd = ffdp->getSimFD();
616 
617 #if NO_STAT64
618  int result = ftruncate(sim_fd, length);
619 #else
620  int result = ftruncate64(sim_fd, length);
621 #endif
622  return (result == -1) ? -errno : result;
623 }
624 
626 umaskFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc)
627 {
628  // Letting the simulated program change the simulator's umask seems like
629  // a bad idea. Compromise by just returning the current umask but not
630  // changing anything.
631  mode_t oldMask = umask(0);
632  umask(oldMask);
633  return (int)oldMask;
634 }
635 
638 {
639  string path;
640 
641  int index = 0;
642  if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
643  return -EFAULT;
644 
645  /* XXX endianess */
646  uint32_t owner = p->getSyscallArg(tc, index);
647  uid_t hostOwner = owner;
648  uint32_t group = p->getSyscallArg(tc, index);
649  gid_t hostGroup = group;
650 
651  // Adjust path for current working directory
652  path = p->fullPath(path);
653 
654  int result = chown(path.c_str(), hostOwner, hostGroup);
655  return (result == -1) ? -errno : result;
656 }
657 
660 {
661  int index = 0;
662  int tgt_fd = p->getSyscallArg(tc, index);
663 
664  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
665  if (!ffdp)
666  return -EBADF;
667  int sim_fd = ffdp->getSimFD();
668 
669  /* XXX endianess */
670  uint32_t owner = p->getSyscallArg(tc, index);
671  uid_t hostOwner = owner;
672  uint32_t group = p->getSyscallArg(tc, index);
673  gid_t hostGroup = group;
674 
675  int result = fchown(sim_fd, hostOwner, hostGroup);
676  return (result == -1) ? -errno : result;
677 }
678 
686 dupFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
687 {
688  int index = 0;
689  int tgt_fd = p->getSyscallArg(tc, index);
690 
691  auto old_hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
692  if (!old_hbfdp)
693  return -EBADF;
694  int sim_fd = old_hbfdp->getSimFD();
695 
696  int result = dup(sim_fd);
697  if (result == -1)
698  return -errno;
699 
700  auto new_hbfdp = std::dynamic_pointer_cast<HBFDEntry>(old_hbfdp->clone());
701  new_hbfdp->setSimFD(result);
702  new_hbfdp->setCOE(false);
703  return p->fds->allocFD(new_hbfdp);
704 }
705 
708 {
709  int index = 0;
710 
711  int old_tgt_fd = p->getSyscallArg(tc, index);
712  auto old_hbp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[old_tgt_fd]);
713  if (!old_hbp)
714  return -EBADF;
715  int old_sim_fd = old_hbp->getSimFD();
716 
722  int res_fd = dup2(old_sim_fd, open("/dev/null", O_RDONLY));
723  if (res_fd == -1)
724  return -errno;
725 
726  int new_tgt_fd = p->getSyscallArg(tc, index);
727  auto new_hbp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[new_tgt_fd]);
728  if (new_hbp)
729  p->fds->closeFDEntry(new_tgt_fd);
730  new_hbp = std::dynamic_pointer_cast<HBFDEntry>(old_hbp->clone());
731  new_hbp->setSimFD(res_fd);
732  new_hbp->setCOE(false);
733 
734  return p->fds->allocFD(new_hbp);
735 }
736 
739 {
740  int arg;
741  int index = 0;
742  int tgt_fd = p->getSyscallArg(tc, index);
743  int cmd = p->getSyscallArg(tc, index);
744 
745  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
746  if (!hbfdp)
747  return -EBADF;
748  int sim_fd = hbfdp->getSimFD();
749 
750  int coe = hbfdp->getCOE();
751 
752  switch (cmd) {
753  case F_GETFD:
754  return coe & FD_CLOEXEC;
755 
756  case F_SETFD: {
757  arg = p->getSyscallArg(tc, index);
758  arg ? hbfdp->setCOE(true) : hbfdp->setCOE(false);
759  return 0;
760  }
761 
762  // Rely on the host to maintain the file status flags for this file
763  // description rather than maintain it ourselves. Admittedly, this
764  // is suboptimal (and possibly error prone), but it is difficult to
765  // maintain the flags by tracking them across the different descriptors
766  // (that refer to this file description) caused by clone, dup, and
767  // subsequent fcntls.
768  case F_GETFL:
769  case F_SETFL: {
770  arg = p->getSyscallArg(tc, index);
771  int rv = fcntl(sim_fd, cmd, arg);
772  return (rv == -1) ? -errno : rv;
773  }
774 
775  default:
776  warn("fcntl: unsupported command %d\n", cmd);
777  return 0;
778  }
779 }
780 
783 {
784  int index = 0;
785  int tgt_fd = p->getSyscallArg(tc, index);
786 
787  auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
788  if (!hbfdp)
789  return -EBADF;
790  int sim_fd = hbfdp->getSimFD();
791 
792  int cmd = p->getSyscallArg(tc, index);
793  switch (cmd) {
794  case 33: //F_GETLK64
795  warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", tgt_fd);
796  return -EMFILE;
797 
798  case 34: // F_SETLK64
799  case 35: // F_SETLKW64
800  warn("fcntl64(%d, F_SETLK(W)64) not supported, error returned\n",
801  tgt_fd);
802  return -EMFILE;
803 
804  default:
805  // not sure if this is totally valid, but we'll pass it through
806  // to the underlying OS
807  warn("fcntl64(%d, %d) passed through to host\n", tgt_fd, cmd);
808  return fcntl(sim_fd, cmd);
809  }
810 }
811 
813 pipeImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc,
814  bool pseudoPipe)
815 {
816  Addr tgt_addr = 0;
817  if (!pseudoPipe) {
818  int index = 0;
819  tgt_addr = p->getSyscallArg(tc, index);
820  }
821 
822  int sim_fds[2], tgt_fds[2];
823 
824  int pipe_retval = pipe(sim_fds);
825  if (pipe_retval == -1)
826  return -errno;
827 
828  auto rend = PipeFDEntry::EndType::read;
829  auto rpfd = std::make_shared<PipeFDEntry>(sim_fds[0], O_WRONLY, rend);
830  tgt_fds[0] = p->fds->allocFD(rpfd);
831 
832  auto wend = PipeFDEntry::EndType::write;
833  auto wpfd = std::make_shared<PipeFDEntry>(sim_fds[1], O_RDONLY, wend);
834  tgt_fds[1] = p->fds->allocFD(wpfd);
835 
840  rpfd->setPipeReadSource(tgt_fds[1]);
841 
846  if (pseudoPipe) {
847  tc->setIntReg(SyscallPseudoReturnReg, tgt_fds[1]);
848  return tgt_fds[0];
849  }
850 
855  BufferArg tgt_handle(tgt_addr, sizeof(int[2]));
856  int *buf_ptr = (int*)tgt_handle.bufferPtr();
857  buf_ptr[0] = tgt_fds[0];
858  buf_ptr[1] = tgt_fds[1];
859  tgt_handle.copyOut(tc->getMemProxy());
860  return 0;
861 }
862 
864 pipePseudoFunc(SyscallDesc *desc, int callnum, Process *process,
865  ThreadContext *tc)
866 {
867  return pipeImpl(desc, callnum, process, tc, true);
868 }
869 
871 pipeFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
872 {
873  return pipeImpl(desc, callnum, process, tc, false);
874 }
875 
877 setpgidFunc(SyscallDesc *desc, int callnum, Process *process,
878  ThreadContext *tc)
879 {
880  int index = 0;
881  int pid = process->getSyscallArg(tc, index);
882  int pgid = process->getSyscallArg(tc, index);
883 
884  if (pgid < 0)
885  return -EINVAL;
886 
887  if (pid == 0) {
888  process->setpgid(process->pid());
889  return 0;
890  }
891 
892  Process *matched_ph = nullptr;
893  System *sysh = tc->getSystemPtr();
894 
895  // Retrieves process pointer from active/suspended thread contexts.
896  for (int i = 0; i < sysh->numContexts(); i++) {
897  if (sysh->threadContexts[i]->status() != ThreadContext::Halted) {
898  Process *temp_h = sysh->threadContexts[i]->getProcessPtr();
899  Process *walk_ph = (Process*)temp_h;
900 
901  if (walk_ph && walk_ph->pid() == process->pid())
902  matched_ph = walk_ph;
903  }
904  }
905 
906  assert(matched_ph);
907  matched_ph->setpgid((pgid == 0) ? matched_ph->pid() : pgid);
908 
909  return 0;
910 }
911 
913 getpidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
914  ThreadContext *tc)
915 {
916  // Make up a PID. There's no interprocess communication in
917  // fake_syscall mode, so there's no way for a process to know it's
918  // not getting a unique value.
919 
920  tc->setIntReg(SyscallPseudoReturnReg, process->ppid());
921  return process->pid();
922 }
923 
924 
926 getuidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
927  ThreadContext *tc)
928 {
929  // Make up a UID and EUID... it shouldn't matter, and we want the
930  // simulation to be deterministic.
931 
932  // EUID goes in r20.
933  tc->setIntReg(SyscallPseudoReturnReg, process->euid()); // EUID
934  return process->uid(); // UID
935 }
936 
937 
939 getgidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
940  ThreadContext *tc)
941 {
942  // Get current group ID. EGID goes in r20.
943  tc->setIntReg(SyscallPseudoReturnReg, process->egid()); // EGID
944  return process->gid();
945 }
946 
947 
949 setuidFunc(SyscallDesc *desc, int callnum, Process *process,
950  ThreadContext *tc)
951 {
952  // can't fathom why a benchmark would call this.
953  int index = 0;
954  warn("Ignoring call to setuid(%d)\n", process->getSyscallArg(tc, index));
955  return 0;
956 }
957 
959 getpidFunc(SyscallDesc *desc, int callnum, Process *process,
960  ThreadContext *tc)
961 {
962  return process->tgid();
963 }
964 
966 gettidFunc(SyscallDesc *desc, int callnum, Process *process,
967  ThreadContext *tc)
968 {
969  return process->pid();
970 }
971 
973 getppidFunc(SyscallDesc *desc, int callnum, Process *process,
974  ThreadContext *tc)
975 {
976  return process->ppid();
977 }
978 
980 getuidFunc(SyscallDesc *desc, int callnum, Process *process,
981  ThreadContext *tc)
982 {
983  return process->uid(); // UID
984 }
985 
987 geteuidFunc(SyscallDesc *desc, int callnum, Process *process,
988  ThreadContext *tc)
989 {
990  return process->euid(); // UID
991 }
992 
994 getgidFunc(SyscallDesc *desc, int callnum, Process *process,
995  ThreadContext *tc)
996 {
997  return process->gid();
998 }
999 
1001 getegidFunc(SyscallDesc *desc, int callnum, Process *process,
1002  ThreadContext *tc)
1003 {
1004  return process->egid();
1005 }
1006 
1009 {
1010 #if NO_FALLOCATE
1011  warn("Host OS cannot support calls to fallocate. Ignoring syscall");
1012 #else
1013  int index = 0;
1014  int tgt_fd = p->getSyscallArg(tc, index);
1015  int mode = p->getSyscallArg(tc, index);
1016  off_t offset = p->getSyscallArg(tc, index);
1017  off_t len = p->getSyscallArg(tc, index);
1018 
1019  auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
1020  if (!ffdp)
1021  return -EBADF;
1022  int sim_fd = ffdp->getSimFD();
1023 
1024  int result = fallocate(sim_fd, mode, offset, len);
1025  if (result < 0)
1026  return -errno;
1027 #endif
1028  return 0;
1029 }
1030 
1032 accessFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc,
1033  int index)
1034 {
1035  string path;
1036  if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
1037  return -EFAULT;
1038 
1039  // Adjust path for current working directory
1040  path = p->fullPath(path);
1041 
1042  mode_t mode = p->getSyscallArg(tc, index);
1043 
1044  int result = access(path.c_str(), mode);
1045  return (result == -1) ? -errno : result;
1046 }
1047 
1049 accessFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
1050 {
1051  return accessFunc(desc, callnum, p, tc, 0);
1052 }
1053 
SyscallReturn ftruncateFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target ftruncate() handler.
FutexMap futexMap
Definition: system.hh:555
virtual void halt()=0
Set the status to Halted.
virtual System * getSystemPtr()=0
Bitfield< 30, 0 > index
SyscallReturn brkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target brk() handler: set brk address.
T htog(T value)
Definition: byteswap.hh:177
const std::string & name()
Definition: trace.cc:49
uint64_t childClearTID
Calls a futex wakeup at the address specified by this pointer when this process exits.
Definition: process.hh:212
Bitfield< 7 > i
Definition: miscregs.hh:1378
SyscallReturn fallocateFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
SyscallReturn dupFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
FIXME: The file description is not shared among file descriptors created with dup.
SyscallReturn getcwdFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target getcwd() handler.
void allocateMem(Addr vaddr, int64_t size, bool clobber=false)
Definition: process.cc:310
bool * sigchld
Definition: process.hh:215
bool copyIn(SETranslatingPortProxy &memproxy)
copy data into simulator space (read from target memory)
ip6_addr_t addr
Definition: inet.hh:335
SyscallReturn pipeImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc, bool pseudoPipe)
Internal pipe() handler.
SyscallReturn ignoreFunc(SyscallDesc *desc, int callnum, Process *process, 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:67
uint64_t uid()
Definition: process.hh:83
SyscallReturn setTidAddressFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target set_tid_address() handler.
bool warnOnce() const
SyscallReturn getppidFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target getppid() handler.
SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target getpagesize() handler.
std::string name()
SyscallReturn readlinkFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
virtual TheISA::IntReg getSyscallArg(ThreadContext *tc, int &i)=0
#define warn_once(...)
Definition: misc.hh:226
Holds file descriptors for host-backed files; host-backed files are files which were opened on the ph...
Definition: fd_entry.hh:102
Definition: system.hh:83
SyscallReturn getgidPseudoFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target getgidPseudo() handler.
virtual void setIntReg(int reg_idx, uint64_t val)=0
Bitfield< 23, 0 > offset
Definition: types.hh:149
Bitfield< 4, 0 > mode
Definition: miscregs.hh:1385
const char * hostname
T roundUp(const T &val, const U &align)
Definition: intmath.hh:205
SyscallReturn getpidFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target getpid() handler.
std::shared_ptr< MemState > memState
Definition: process.hh:206
ThreadContext is the external interface to all thread state for anything outside of the CPU...
#define DPRINTF_SYSCALL(FLAGEXT, FMT,...)
This macro is intended to help with readability.
SyscallReturn truncate64Func(SyscallDesc *desc, int num, Process *process, ThreadContext *tc)
Target truncate64() handler.
SyscallReturn getegidFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target getegid() handler.
SyscallReturn _llseekFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target _llseek() handler.
SyscallReturn fcntlFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target fcntl() handler.
#define warn(...)
Definition: misc.hh:219
Bitfield< 5, 0 > status
Definition: miscregs.hh:1604
bool copyOut(SETranslatingPortProxy &memproxy)
copy data out of simulator space (write to target memory)
SyscallReturn munmapFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target munmap() handler.
system
Definition: isa.cc:226
SyscallReturn writeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target write() handler.
SyscallReturn unimplementedFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Handler for unimplemented syscalls that we haven't thought about.
Definition: syscall_emul.cc:57
SyscallReturn exitGroupFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
Target exit_group() handler: terminate simulation. (exit all threads)
SyscallReturn lseekFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target lseek() handler.
bool tryReadString(std::string &str, Addr addr) const
static SyscallReturn exitImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc, bool group)
Definition: syscall_emul.cc:93
uint64_t ppid()
Definition: process.hh:88
SyscallReturn fchownFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target fchown() handler.
bool translate(Addr vaddr, Addr &paddr)
Translate function.
Definition: page_table.cc:173
int wakeup(Addr addr, uint64_t tgid, int count)
Wakes up at most count waiting threads on a futex.
Definition: futex_map.hh:110
uint64_t pid()
Definition: process.hh:87
This class takes an arbitrary memory region (address/length pair) and generates a series of appropria...
SyscallReturn unlinkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
uint64_t euid()
Definition: process.hh:84
const char * progName() const
Definition: process.hh:93
std::vector< ThreadContext * > threadContexts
Definition: system.hh:199
#define fatal(...)
Definition: misc.hh:163
SyscallReturn gettidFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target gettid() handler.
Extends the base class to include a host-backed file descriptor field that records the integer used t...
Definition: fd_entry.hh:76
void * bufferPtr()
Return a pointer to the internal simulator-space buffer.
SyscallReturn geteuidFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target geteuid() handler.
T roundDown(const T &val, const U &align)
Definition: intmath.hh:213
const RegIndex SyscallPseudoReturnReg
Definition: registers.hh:88
virtual SETranslatingPortProxy & getMemProxy()=0
SyscallReturn getuidPseudoFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target getuidPseudo() handler.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
std::string getcwd() const
Definition: process.hh:95
virtual void memsetBlob(Addr addr, uint8_t val, int size) const
Fill size bytes starting at addr with byte value val.
int numContexts()
Definition: system.hh:208
std::list< BasicSignal > signalList
Definition: system.hh:564
SyscallReturn mkdirFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target mkdir() handler.
const Addr PageBytes
Definition: isa_traits.hh:52
PageTableBase * pTable
Definition: process.hh:178
SyscallReturn setuidFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target setuid() handler.
std::string fullPath(const std::string &filename)
Definition: process.cc:646
This class provides the wrapper interface for the system call implementations which are defined in th...
Definition: syscall_desc.hh:63
SyscallReturn truncateFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target truncate() handler.
SyscallReturn getgidFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target getgid() handler.
SyscallReturn pipePseudoFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Pseudo Funcs - These functions use a different return convension, returning a second value in a regis...
SyscallReturn renameFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target rename() 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:83
SyscallReturn setpgidFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target setpgid() handler.
int size()
Definition: pagetable.hh:146
SyscallReturn fcntl64Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target fcntl64() handler.
Declarations of a non-full system Page Table.
This file defines objects used to emulate syscalls from the target application on the host machine...
Permanently shut down.
SyscallReturn getuidFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target getuid() handler.
bool done() const
Are we done? That is, did the last call to next() advance past the end of the region?
void setpgid(uint64_t pgid)
Definition: process.hh:91
SyscallReturn umaskFunc(SyscallDesc *desc, int num, Process *process, ThreadContext *tc)
Target umask() handler.
SyscallReturn accessFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc, int index)
SyscallReturn dup2Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target dup2() handler.
SyscallReturn chownFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target chown() handler.
FutexMap class holds a map of all futexes used in the system.
Definition: futex_map.hh:87
SyscallReturn unlinkHelper(SyscallDesc *desc, int num, Process *p, ThreadContext *tc, int index)
Target unlink() handler.
Bitfield< 18, 16 > len
Definition: miscregs.hh:1626
SyscallReturn gethostnameFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target gethostname() handler.
SyscallReturn getpidPseudoFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target getpidPseudo() handler.
uint64_t gid()
Definition: process.hh:85
BufferArg represents an untyped buffer in target user space that is passed by reference to an (emulat...
SyscallReturn exitFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
Target exit() handler: terminate current context.
uint8_t length
Definition: inet.hh:334
SyscallReturn ftruncate64Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target ftruncate64() handler.
SyscallReturn closeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
Target close() handler.
Declaration and inline definition of ChunkGenerator object.
This class represents the return value from an emulated system call, including any errno setting...
uint64_t tgid()
Definition: process.hh:90
bool needWarning()
Return false if WarnOnce is set and a warning has already been issued.
Definition: syscall_desc.cc:90
Bitfield< 0 > p
SyscallReturn pipeFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
Target pipe() handler.
static void exitFutexWake(ThreadContext *tc, Addr addr, uint64_t tgid)
Definition: syscall_emul.cc:79
SyscallReturn readFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
bool * exitGroup
Definition: process.hh:205
uint64_t egid()
Definition: process.hh:86
std::shared_ptr< FDArray > fds
Definition: process.hh:203
static std::vector< System * > systemList
Definition: system.hh:550

Generated on Fri Jun 9 2017 13:03:51 for gem5 by doxygen 1.8.6