gem5 [DEVELOP-FOR-25.1]
Loading...
Searching...
No Matches
syscall_emul.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024 Arm Limited
3 *
4 * The license below extends only to copyright in the software and
5 * shall not be construed as granting a license to any other
6 * intellectual property including but not limited to intellectual
7 * property relating to a hardware implementation of the
8 * functionality of the software licensed hereunder. You may use the
9 * software subject to the license terms below provided that you
10 * ensure that this notice is replicated unmodified and in its
11 * entirety in all distributions of the software, modified or
12 * unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2003-2005 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
41#include "sim/syscall_emul.hh"
42
43#include <fcntl.h>
44#include <sys/syscall.h>
45#include <unistd.h>
46
47#include <csignal>
48#include <iostream>
49#include <mutex>
50#include <string>
51#include <unordered_map>
52
54#include "base/trace.hh"
55#include "cpu/thread_context.hh"
56#include "dev/net/dist_iface.hh"
57#include "mem/page_table.hh"
59#include "sim/byteswap.hh"
60#include "sim/process.hh"
61#include "sim/proxy_ptr.hh"
62#include "sim/sim_exit.hh"
64#include "sim/syscall_desc.hh"
65#include "sim/system.hh"
66
67namespace gem5
68{
69
70void
71warnUnsupportedOS(std::string syscall_name)
72{
73 warn("Cannot invoke %s on host operating system.", syscall_name);
74}
75
76SyscallReturn
78{
79 fatal("syscall %s (#%d) unimplemented.", desc->name(), desc->num());
80}
81
82
83SyscallReturn
85{
86 warn("ignoring syscall %s(...)", desc->name());
87 return 0;
88}
89
90SyscallReturn
92{
93 static std::unordered_map<SyscallDesc *, bool> bool_map;
94
95 bool &warned = bool_map[desc];
96 if (!warned) {
97 warn("ignoring syscall %s(...)\n"
98 " (further warnings will be suppressed)", desc->name());
99 warned = true;
100 }
101
102 return 0;
103}
104
105SyscallReturn
107{
108 warn("ignoring syscall %s(...) returning -ENOSYS", desc->name());
109 return -ENOSYS;
110}
111
112static void
114{
115 // Clear value at address pointed to by thread's childClearTID field.
116 BufferArg ctidBuf(addr, sizeof(long));
117 long *ctid = (long *)ctidBuf.bufferPtr();
118 *ctid = 0;
119 ctidBuf.copyOut(SETranslatingPortProxy(tc));
120
121 FutexMap &futex_map = tc->getSystemPtr()->futexMap;
122 // Wake one of the waiting threads.
123 futex_map.wakeup(addr, tgid, 1);
124}
125
126static SyscallReturn
127exitImpl(SyscallDesc *desc, ThreadContext *tc, bool group, int status)
128{
129 auto p = tc->getProcessPtr();
130
131 System *sys = tc->getSystemPtr();
132
133 if (group)
134 *p->exitGroup = true;
135
136 if (p->childClearTID)
137 exitFutexWake(tc, p->childClearTID, p->tgid());
138
139 bool last_thread = true;
140 Process *parent = nullptr, *tg_lead = nullptr;
141 for (int i = 0; last_thread && i < sys->threads.size(); i++) {
142 Process *walk;
143 if (!(walk = sys->threads[i]->getProcessPtr()))
144 continue;
145
152 if (walk->pid() == p->tgid())
153 tg_lead = walk;
154
155 auto *tc = sys->threads[i];
156 if ((tc->status() != ThreadContext::Halted) &&
157 (tc->status() != ThreadContext::Halting) &&
158 (walk != p)) {
165 if (walk->tgid() == p->tgid()) {
178 if (*(p->exitGroup)) {
179 tc->halt();
180 } else {
181 last_thread = false;
182 }
183 }
184
194 if (*p->sigchld && (p->ppid() != 0) && (walk->pid() == p->ppid()))
195 parent = walk;
196 }
197 }
198
199 if (last_thread) {
200 if (parent) {
201 assert(tg_lead);
202 sys->signalList.push_back(BasicSignal(tg_lead, parent, SIGCHLD));
203 }
204
210 for (int i = 0; i < p->fds->getSize(); i++) {
211 if ((*p->fds)[i])
212 p->fds->closeFDEntry(i);
213 }
214 }
215
220 if (!p->vforkContexts.empty()) {
221 ThreadContext *vtc = sys->threads[p->vforkContexts.front()];
222 assert(vtc->status() == ThreadContext::Suspended);
223 vtc->activate();
224 }
225
226 tc->halt();
227
232 int activeContexts = 0;
233 for (auto &system: sys->systemList)
234 activeContexts += system->threads.numRunning();
235
236 if (activeContexts == 0) {
246 if (!DistIface::readyToExit(0)) {
247 return status;
248 }
249
250 exitSimLoop("exiting with last active thread context", status & 0xff);
251 return status;
252 }
253
254 return status;
255}
256
257SyscallReturn
259{
260 return exitImpl(desc, tc, false, status);
261}
262
263SyscallReturn
265{
266 return exitImpl(desc, tc, true, status);
267}
268
269SyscallReturn
271{
272 return (int)tc->getProcessPtr()->pTable->pageSize();
273}
274
275
276SyscallReturn
278{
279 // change brk addr to first arg
280 auto p = tc->getProcessPtr();
281
282 std::shared_ptr<MemState> mem_state = p->memState;
283 Addr brk_point = mem_state->getBrkPoint();
284
285 // in Linux at least, brk(0) returns the current break value
286 // (note that the syscall and the glibc function have different behavior)
287 if (new_brk == 0 || (new_brk == brk_point))
288 return brk_point;
289
290 mem_state->updateBrkRegion(brk_point, new_brk);
291
292 DPRINTF_SYSCALL(Verbose, "brk: break point changed to: %#X\n",
293 mem_state->getBrkPoint());
294
295 return mem_state->getBrkPoint();
296}
297
298SyscallReturn
300{
301 auto process = tc->getProcessPtr();
302
303 process->childClearTID = tidPtr;
304 return process->pid();
305}
306
307SyscallReturn
308closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
309{
310 auto p = tc->getProcessPtr();
311 return p->fds->closeFDEntry(tgt_fd);
312}
313
314
315SyscallReturn
317 int tgt_fd, uint32_t offset_high, uint32_t offset_low,
318 VPtr<> result_ptr, int whence)
319{
320 auto p = tc->getProcessPtr();
321
322 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
323 if (!ffdp)
324 return -EBADF;
325 int sim_fd = ffdp->getSimFD();
326
327 uint64_t offset = ((uint64_t) offset_high << 32) | offset_low;
328
329 uint64_t result = lseek(sim_fd, offset, whence);
330 result = htog(result, tc->getSystemPtr()->getGuestByteOrder());
331
332 if (result == (off_t)-1)
333 return -errno;
334 // Assuming that the size of loff_t is 64 bits on the target platform
335 BufferArg result_buf(result_ptr, sizeof(result));
336 std::memcpy(result_buf.bufferPtr(), &result, sizeof(result));
337 result_buf.copyOut(SETranslatingPortProxy(tc));
338 return 0;
339}
340
341
342const char *hostname = "m5.eecs.umich.edu";
343
346 VPtr<> buf_ptr, int name_len)
347{
348 BufferArg name(buf_ptr, name_len);
349 strncpy((char *)name.bufferPtr(), hostname, name_len);
350 name.copyOut(SETranslatingPortProxy(tc));
351 return 0;
352}
353
354SyscallReturn
356{
357 std::string path;
358 if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
359 return -EFAULT;
360
361 return unlinkImpl(desc, tc, path);
362}
363
364SyscallReturn
365unlinkImpl(SyscallDesc *desc, ThreadContext *tc, std::string path)
366{
367 auto p = tc->getProcessPtr();
368 path = p->checkPathRedirect(path);
369
370 int result = unlink(path.c_str());
371 return (result == -1) ? -errno : result;
372}
373
374SyscallReturn
376 VPtr<> pathname, VPtr<> new_pathname)
377{
378 std::string path;
379 std::string new_path;
380 auto p = tc->getProcessPtr();
381
382 SETranslatingPortProxy virt_mem(tc);
383 if (!virt_mem.tryReadString(path, pathname))
384 return -EFAULT;
385 if (!virt_mem.tryReadString(new_path, new_pathname))
386 return -EFAULT;
387
388 path = p->absolutePath(path, true);
389 new_path = p->absolutePath(new_path, true);
390
391 int result = link(path.c_str(), new_path.c_str());
392 return (result == -1) ? -errno : result;
393}
394
395SyscallReturn
397 VPtr<> pathname, VPtr<> new_pathname)
398{
399 std::string path;
400 std::string new_path;
401 auto p = tc->getProcessPtr();
402
403 SETranslatingPortProxy virt_mem(tc);
404 if (!virt_mem.tryReadString(path, pathname))
405 return -EFAULT;
406 if (!virt_mem.tryReadString(new_path, new_pathname))
407 return -EFAULT;
408
409 path = p->absolutePath(path, true);
410 new_path = p->absolutePath(new_path, true);
411
412 int result = symlink(path.c_str(), new_path.c_str());
413 return (result == -1) ? -errno : result;
414}
415
416SyscallReturn
417mkdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
418{
419 std::string path;
420 if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
421 return -EFAULT;
422
423 return mkdirImpl(desc, tc, path, mode);
424}
425
426SyscallReturn
427mkdirImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode)
428{
429 auto p = tc->getProcessPtr();
430 path = p->checkPathRedirect(path);
431
432 auto result = mkdir(path.c_str(), mode);
433 return (result == -1) ? -errno : result;
434}
435
436SyscallReturn
438 VPtr<> newpath)
439{
440 SETranslatingPortProxy proxy(tc);
441 std::string old_name;
442 if (!proxy.tryReadString(old_name, oldpath))
443 return -EFAULT;
444
445 std::string new_name;
446 if (!proxy.tryReadString(new_name, newpath))
447 return -EFAULT;
448
449 return renameImpl(desc, tc, old_name, new_name);
450}
451
452SyscallReturn
454 std::string old_name, std::string new_name)
455{
456 auto p = tc->getProcessPtr();
457
458 // Adjust path for cwd and redirection
459 old_name = p->checkPathRedirect(old_name);
460 new_name = p->checkPathRedirect(new_name);
461
462 int64_t result = rename(old_name.c_str(), new_name.c_str());
463 return (result == -1) ? -errno : result;
464}
465
466
467SyscallReturn
469 VPtr<> pathname, int64_t length)
470{
471 auto process = tc->getProcessPtr();
472 std::string path;
473
474 if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
475 return -EFAULT;
476
477 // Adjust path for cwd and redirection
478 path = process->checkPathRedirect(path);
479
480#if NO_STAT64
481 int result = truncate(path.c_str(), length);
482#else
483 int result = truncate64(path.c_str(), length);
484#endif
485 return (result == -1) ? -errno : result;
486}
487
488SyscallReturn
490 int tgt_fd, int64_t length)
491{
492 auto p = tc->getProcessPtr();
493
494 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
495 if (!ffdp)
496 return -EBADF;
497 int sim_fd = ffdp->getSimFD();
498
499#if NO_STAT64
500 int result = ftruncate(sim_fd, length);
501#else
502 int result = ftruncate64(sim_fd, length);
503#endif
504 return (result == -1) ? -errno : result;
505}
506
507SyscallReturn
509{
510 // Letting the simulated program change the simulator's umask seems like
511 // a bad idea. Compromise by just returning the current umask but not
512 // changing anything.
513 mode_t oldMask = umask(0);
514 umask(oldMask);
515 return (int)oldMask;
516}
517
518SyscallReturn
520 VPtr<> pathname, uint32_t owner, uint32_t group)
521{
522 std::string path;
523 if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
524 return -EFAULT;
525
526 return chownImpl(desc, tc, path, owner, group);
527}
528
529SyscallReturn
531 std::string path, uint32_t owner, uint32_t group)
532{
533 auto p = tc->getProcessPtr();
534
535 /* XXX endianess */
536 uid_t hostOwner = owner;
537 gid_t hostGroup = group;
538
539 // Adjust path for cwd and redirection
540 path = p->checkPathRedirect(path);
541
542 int result = chown(path.c_str(), hostOwner, hostGroup);
543 return (result == -1) ? -errno : result;
544}
545
546SyscallReturn
548 int tgt_fd, uint32_t owner, uint32_t group)
549{
550 auto p = tc->getProcessPtr();
551
552 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>((*p->fds)[tgt_fd]);
553 if (!ffdp)
554 return -EBADF;
555 int sim_fd = ffdp->getSimFD();
556
557 /* XXX endianess */
558 uid_t hostOwner = owner;
559 gid_t hostGroup = group;
560
561 int result = fchown(sim_fd, hostOwner, hostGroup);
562 return (result == -1) ? -errno : result;
563}
564
571SyscallReturn
572dupFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
573{
574 auto p = tc->getProcessPtr();
575
576 auto old_hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
577 if (!old_hbfdp)
578 return -EBADF;
579 int sim_fd = old_hbfdp->getSimFD();
580
581 int result = dup(sim_fd);
582 if (result == -1)
583 return -errno;
584
585 auto new_hbfdp = std::dynamic_pointer_cast<HBFDEntry>(old_hbfdp->clone());
586 new_hbfdp->setSimFD(result);
587 new_hbfdp->setCOE(false);
588 return p->fds->allocFD(new_hbfdp);
589}
590
591SyscallReturn
592dup2Func(SyscallDesc *desc, ThreadContext *tc, int old_tgt_fd, int new_tgt_fd)
593{
594 auto p = tc->getProcessPtr();
595 auto old_hbp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[old_tgt_fd]);
596 if (!old_hbp)
597 return -EBADF;
598 int old_sim_fd = old_hbp->getSimFD();
599
605 int res_fd = dup2(old_sim_fd, open("/dev/null", O_RDONLY));
606 if (res_fd == -1)
607 return -errno;
608
609 auto new_hbp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[new_tgt_fd]);
610 if (new_hbp)
611 p->fds->closeFDEntry(new_tgt_fd);
612 new_hbp = std::dynamic_pointer_cast<HBFDEntry>(old_hbp->clone());
613 new_hbp->setSimFD(res_fd);
614 new_hbp->setCOE(false);
615
616 return p->fds->allocFD(new_hbp);
617}
618
619SyscallReturn
621 int tgt_fd, int cmd, guest_abi::VarArgs<int> varargs)
622{
623 auto p = tc->getProcessPtr();
624
625 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
626 if (!hbfdp)
627 return -EBADF;
628 int sim_fd = hbfdp->getSimFD();
629
630 int coe = hbfdp->getCOE();
631
632 switch (cmd) {
633 case F_GETFD:
634 return coe & FD_CLOEXEC;
635
636 case F_SETFD: {
637 int arg = varargs.get<int>();
638 arg ? hbfdp->setCOE(true) : hbfdp->setCOE(false);
639 return 0;
640 }
641
642 // Rely on the host to maintain the file status flags for this file
643 // description rather than maintain it ourselves. Admittedly, this
644 // is suboptimal (and possibly error prone), but it is difficult to
645 // maintain the flags by tracking them across the different descriptors
646 // (that refer to this file description) caused by clone, dup, and
647 // subsequent fcntls.
648 case F_GETFL:
649 case F_SETFL: {
650 int arg = varargs.get<int>();
651 int rv = fcntl(sim_fd, cmd, arg);
652 return (rv == -1) ? -errno : rv;
653 }
654
655 default:
656 warn("fcntl: unsupported command %d\n", cmd);
657 return 0;
658 }
659}
660
661SyscallReturn
662fcntl64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd)
663{
664 auto p = tc->getProcessPtr();
665
666 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
667 if (!hbfdp)
668 return -EBADF;
669 int sim_fd = hbfdp->getSimFD();
670
671 switch (cmd) {
672 case 33: //F_GETLK64
673 warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", tgt_fd);
674 return -EMFILE;
675
676 case 34: // F_SETLK64
677 case 35: // F_SETLKW64
678 warn("fcntl64(%d, F_SETLK(W)64) not supported, error returned\n",
679 tgt_fd);
680 return -EMFILE;
681
682 default:
683 // not sure if this is totally valid, but we'll pass it through
684 // to the underlying OS
685 warn("fcntl64(%d, %d) passed through to host\n", tgt_fd, cmd);
686 return fcntl(sim_fd, cmd);
687 }
688}
689
690SyscallReturn
692{
693 return pipe2Func(desc, tc, 0, 0);
694}
695
696SyscallReturn
698{
699 return pipe2Func(desc, tc, tgt_addr, 0);
700}
701
702SyscallReturn
703pipe2Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr, int flags)
704{
705 auto p = tc->getProcessPtr();
706
707 int sim_fds[2], tgt_fds[2];
708
709 int pipe_retval = pipe(sim_fds);
710 if (pipe_retval == -1)
711 return -errno;
712
713 auto rend = PipeFDEntry::EndType::read;
714 auto rpfd = std::make_shared<PipeFDEntry>(sim_fds[0], O_WRONLY, rend);
715 tgt_fds[0] = p->fds->allocFD(rpfd);
716 int sim_fd_rpfd = rpfd->getSimFD();
717
718 auto wend = PipeFDEntry::EndType::write;
719 auto wpfd = std::make_shared<PipeFDEntry>(sim_fds[1], O_RDONLY, wend);
720 tgt_fds[1] = p->fds->allocFD(wpfd);
721 int sim_fd_wpfd = wpfd->getSimFD();
722
727 rpfd->setPipeReadSource(tgt_fds[1]);
728
734 if (tgt_addr == 0)
735 return SyscallReturn(tgt_fds[0], tgt_fds[1]);
736
741 BufferArg tgt_handle(tgt_addr, sizeof(int[2]));
742 int *buf_ptr = (int*)tgt_handle.bufferPtr();
743 buf_ptr[0] = tgt_fds[0];
744 buf_ptr[1] = tgt_fds[1];
745 tgt_handle.copyOut(SETranslatingPortProxy(tc));
746
747 if (flags) {
748 // pipe2 only uses O_NONBLOCK, O_CLOEXEC, and (O_NONBLOCK | O_CLOEXEC)
749 // if flags set to anything else, return EINVAL
750 if ((flags != O_CLOEXEC) && (flags != O_NONBLOCK) &&
751 (flags != (O_CLOEXEC | O_NONBLOCK))) {
752 return -EINVAL;
753 }
754
755 /*
756 If O_NONBLOCK is passed in as a flag to pipe2, set O_NONBLOCK file
757 status flag for two new open file descriptors.
758 */
759 if (flags & O_NONBLOCK) {
760 /*
761 O_NONBLOCK is set when the programmer wants to avoid a separate
762 call(s) to fcntl in their code, so mirror the fcntl
763 implementation for handling file descriptors -- rely on host to
764 maintain file status flags.
765 */
766 if (fcntl(sim_fd_rpfd, F_SETFL, O_NONBLOCK)) {
767 return -errno;
768 }
769 if (fcntl(sim_fd_wpfd, F_SETFL, O_NONBLOCK)) {
770 return -errno;
771 }
772 }
773
774 /*
775 If O_CLOEXEC is passed in as a flag to pipe2, set close-on-exec
776 (FD_CLOEXEC) file status flag for two new open file descriptors.
777 */
778 if (flags & O_CLOEXEC) {
779 rpfd->setCOE(true);
780 wpfd->setCOE(true);
781 }
782 }
783
784 return 0;
785}
786
787SyscallReturn
789{
790 auto process = tc->getProcessPtr();
791 return process->pgid();
792}
793
794SyscallReturn
795setpgidFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int pgid)
796{
797 auto process = tc->getProcessPtr();
798
799 if (pgid < 0)
800 return -EINVAL;
801
802 if (pid == 0) {
803 process->pgid(process->pid());
804 return 0;
805 }
806
807 Process *matched_ph = nullptr;
808 System *sysh = tc->getSystemPtr();
809
810 // Retrieves process pointer from active/suspended thread contexts.
811 for (auto *tc: sysh->threads) {
812 if (tc->status() != ThreadContext::Halted) {
813 Process *temp_h = tc->getProcessPtr();
814 Process *walk_ph = (Process*)temp_h;
815
816 if (walk_ph && walk_ph->pid() == process->pid())
817 matched_ph = walk_ph;
818 }
819 }
820
821 assert(matched_ph);
822 matched_ph->pgid((pgid == 0) ? matched_ph->pid() : pgid);
823
824 return 0;
825}
826
827
828SyscallReturn
830{
831 auto process = tc->getProcessPtr();
832 return process->tgid();
833}
834
835SyscallReturn
837{
838 auto process = tc->getProcessPtr();
839 return process->pid();
840}
841
842SyscallReturn
844{
845 auto process = tc->getProcessPtr();
846 return process->ppid();
847}
848
849SyscallReturn
851{
852 auto process = tc->getProcessPtr();
853 return process->uid(); // UID
854}
855
856SyscallReturn
858{
859 auto process = tc->getProcessPtr();
860 return process->euid(); // UID
861}
862
863SyscallReturn
865{
866 auto process = tc->getProcessPtr();
867 return process->gid();
868}
869
870SyscallReturn
872{
873 auto process = tc->getProcessPtr();
874 return process->egid();
875}
876
877SyscallReturn
879 VPtr<> pathname, mode_t mode)
880{
881 std::string path;
882 if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
883 return -EFAULT;
884
885 return accessImpl(desc, tc, path, mode);
886}
887
888SyscallReturn
890 std::string path, mode_t mode)
891{
892 auto p = tc->getProcessPtr();
893 // Adjust path for cwd and redirection
894 path = p->checkPathRedirect(path);
895
896 int result = access(path.c_str(), mode);
897 return (result == -1) ? -errno : result;
898}
899
900SyscallReturn
902 VPtr<> pathname, mode_t mode, dev_t dev)
903{
904 std::string path;
905 if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
906 return -EFAULT;
907
908 return mknodImpl(desc, tc, path, mode, dev);
909}
910
911SyscallReturn
913 std::string path, mode_t mode, dev_t dev)
914{
915 auto p = tc->getProcessPtr();
916 path = p->checkPathRedirect(path);
917
918 auto result = mknod(path.c_str(), mode, dev);
919 return (result == -1) ? -errno : result;
920}
921
922SyscallReturn
924{
925 auto p = tc->getProcessPtr();
926 std::string path;
927 if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
928 return -EFAULT;
929
930 std::string tgt_cwd;
931 if (startswith(path, "/")) {
932 tgt_cwd = path;
933 } else {
934 char buf[PATH_MAX];
935 if (!realpath((p->tgtCwd + "/" + path).c_str(), buf))
936 return -errno;
937 tgt_cwd = buf;
938 }
939 std::string host_cwd = p->checkPathRedirect(tgt_cwd);
940
941 int result = chdir(host_cwd.c_str());
942
943 if (result == -1)
944 return -errno;
945
946 p->hostCwd = host_cwd;
947 p->tgtCwd = tgt_cwd;
948 return result;
949}
950
951SyscallReturn
953{
954 std::string path;
955 if (!SETranslatingPortProxy(tc).tryReadString(path, pathname))
956 return -EFAULT;
957
958 return rmdirImpl(desc, tc, path);
959}
960
961SyscallReturn
962rmdirImpl(SyscallDesc *desc, ThreadContext *tc, std::string path)
963{
964 auto p = tc->getProcessPtr();
965 path = p->checkPathRedirect(path);
966
967 auto result = rmdir(path.c_str());
968 return (result == -1) ? -errno : result;
969}
970
971#if defined(SYS_getdents) || defined(SYS_getdents64)
972template<typename DE, int SYS_NUM>
973static SyscallReturn
974getdentsImpl(SyscallDesc *desc, ThreadContext *tc,
975 int tgt_fd, VPtr<> buf_ptr, unsigned count)
976{
977 auto p = tc->getProcessPtr();
978
979 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
980 if (!hbfdp)
981 return -EBADF;
982 int sim_fd = hbfdp->getSimFD();
983
984 BufferArg buf_arg(buf_ptr, count);
985 auto status = syscall(SYS_NUM, sim_fd, buf_arg.bufferPtr(), count);
986
987 if (status == -1)
988 return -errno;
989
990 unsigned traversed = 0;
991 while (traversed < status) {
992 DE *buffer = (DE*)((Addr)buf_arg.bufferPtr() + traversed);
993
994 auto host_reclen = buffer->d_reclen;
995
1001 const ByteOrder bo = tc->getSystemPtr()->getGuestByteOrder();
1002 buffer->d_ino = htog(buffer->d_ino, bo);
1003 buffer->d_off = htog(buffer->d_off, bo);
1004 buffer->d_reclen = htog(buffer->d_reclen, bo);
1005
1006 traversed += host_reclen;
1007 }
1008
1009 buf_arg.copyOut(SETranslatingPortProxy(tc));
1010 return status;
1011}
1012#endif
1013
1014#if defined(SYS_getdents)
1016getdentsFunc(SyscallDesc *desc, ThreadContext *tc,
1017 int tgt_fd, VPtr<> buf_ptr, unsigned count)
1018{
1019 typedef struct linux_dirent
1020 {
1021 unsigned long d_ino;
1022 unsigned long d_off;
1023 unsigned short d_reclen;
1024 char dname[];
1025 } LinDent;
1026
1027 return getdentsImpl<LinDent, SYS_getdents>(desc, tc,
1028 tgt_fd, buf_ptr, count);
1029}
1030#endif
1031
1032#if defined(SYS_getdents64)
1034getdents64Func(SyscallDesc *desc, ThreadContext *tc,
1035 int tgt_fd, VPtr<> buf_ptr, unsigned count)
1036{
1037 typedef struct linux_dirent64
1038 {
1039 ino64_t d_ino;
1040 off64_t d_off;
1041 unsigned short d_reclen;
1042 char dname[];
1043 } LinDent64;
1044
1045 return getdentsImpl<LinDent64, SYS_getdents64>(desc, tc,
1046 tgt_fd, buf_ptr, count);
1047}
1048#endif
1049
1051shutdownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int how)
1052{
1053 auto p = tc->getProcessPtr();
1054
1055 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1056 if (!sfdp)
1057 return -EBADF;
1058 int sim_fd = sfdp->getSimFD();
1059
1060 int retval = shutdown(sim_fd, how);
1061
1062 return (retval == -1) ? -errno : retval;
1063}
1064
1065SyscallReturn
1067 int tgt_fd, VPtr<> buf_ptr, int addrlen)
1068{
1069 auto p = tc->getProcessPtr();
1070
1071 BufferArg bufSock(buf_ptr, addrlen);
1072 bufSock.copyIn(SETranslatingPortProxy(tc));
1073
1074 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1075 if (!sfdp)
1076 return -EBADF;
1077 int sim_fd = sfdp->getSimFD();
1078
1079 int status = ::bind(sim_fd,
1080 (struct sockaddr *)bufSock.bufferPtr(),
1081 addrlen);
1082
1083 return (status == -1) ? -errno : status;
1084}
1085
1086SyscallReturn
1087listenFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int backlog)
1088{
1089 auto p = tc->getProcessPtr();
1090
1091 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1092 if (!sfdp)
1093 return -EBADF;
1094 int sim_fd = sfdp->getSimFD();
1095
1096 int status = listen(sim_fd, backlog);
1097
1098 return (status == -1) ? -errno : status;
1099}
1100
1101SyscallReturn
1103 int tgt_fd, VPtr<> buf_ptr, int addrlen)
1104{
1105 auto p = tc->getProcessPtr();
1106
1107 BufferArg addr(buf_ptr, addrlen);
1108 addr.copyIn(SETranslatingPortProxy(tc));
1109
1110 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1111 if (!sfdp)
1112 return -EBADF;
1113 int sim_fd = sfdp->getSimFD();
1114
1115 int status = connect(sim_fd,
1116 (struct sockaddr *)addr.bufferPtr(),
1117 (socklen_t)addrlen);
1118
1119 return (status == -1) ? -errno : status;
1120}
1121
1122
1123SyscallReturn
1125 int tgt_fd, VPtr<> msgPtr, int flags)
1126{
1127 auto p = tc->getProcessPtr();
1128
1129 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1130 if (!sfdp)
1131 return -EBADF;
1132 int sim_fd = sfdp->getSimFD();
1133
1151
1152 SETranslatingPortProxy proxy(tc);
1153
1159 BufferArg msgBuf(msgPtr, sizeof(struct msghdr));
1160 msgBuf.copyIn(proxy);
1161 struct msghdr *msgHdr = (struct msghdr *)msgBuf.bufferPtr();
1162
1168 Addr msg_name_phold = 0;
1169 Addr msg_iov_phold = 0;
1170 auto iovec_base_phold = std::make_unique<Addr[]>(msgHdr->msg_iovlen);
1171 Addr msg_control_phold = 0;
1172
1176 BufferArg *nameBuf = NULL;
1177 if (msgHdr->msg_name) {
1178 /*1*/msg_name_phold = (Addr)msgHdr->msg_name;
1179 /*2*/nameBuf = new BufferArg(msg_name_phold, msgHdr->msg_namelen);
1180 /*3*/nameBuf->copyIn(proxy);
1181 /*4*/msgHdr->msg_name = nameBuf->bufferPtr();
1182 }
1183
1189 BufferArg *iovBuf = NULL;
1190 auto iovecBuf = std::make_unique<BufferArg *[]>(msgHdr->msg_iovlen);
1191 for (int i = 0; i < msgHdr->msg_iovlen; i++) {
1192 iovec_base_phold[i] = 0;
1193 iovecBuf[i] = NULL;
1194 }
1195
1196 if (msgHdr->msg_iov) {
1197 /*1*/msg_iov_phold = (Addr)msgHdr->msg_iov;
1198 /*2*/iovBuf = new BufferArg(msg_iov_phold, msgHdr->msg_iovlen *
1199 sizeof(struct iovec));
1200 /*3*/iovBuf->copyIn(proxy);
1201 for (int i = 0; i < msgHdr->msg_iovlen; i++) {
1202 auto iov = ((struct iovec *)iovBuf->bufferPtr())[i];
1203 if (iov.iov_base) {
1204 /*1*/iovec_base_phold[i] = (Addr)iov.iov_base;
1205 /*2*/iovecBuf[i] = new BufferArg(
1206 iovec_base_phold[i], iov.iov_len);
1207 /*3*/iovecBuf[i]->copyIn(proxy);
1208 /*4*/iov.iov_base = iovecBuf[i]->bufferPtr();
1209 }
1210 }
1211 /*4*/msgHdr->msg_iov = (struct iovec *)iovBuf->bufferPtr();
1212 }
1213
1217 BufferArg *controlBuf = NULL;
1218 if (msgHdr->msg_control) {
1219 /*1*/msg_control_phold = (Addr)msgHdr->msg_control;
1220 /*2*/controlBuf = new BufferArg(msg_control_phold,
1221 CMSG_ALIGN(msgHdr->msg_controllen));
1222 /*3*/controlBuf->copyIn(proxy);
1223 /*4*/msgHdr->msg_control = controlBuf->bufferPtr();
1224 }
1225
1226 ssize_t recvd_size = recvmsg(sim_fd, msgHdr, flags);
1227
1228 if (recvd_size < 0)
1229 return -errno;
1230
1231 if (msgHdr->msg_name) {
1232 nameBuf->copyOut(proxy);
1233 delete(nameBuf);
1234 msgHdr->msg_name = (void *)msg_name_phold;
1235 }
1236
1237 if (msgHdr->msg_iov) {
1238 for (int i = 0; i< msgHdr->msg_iovlen; i++) {
1239 auto iov = ((struct iovec *)iovBuf->bufferPtr())[i];
1240 if (iov.iov_base) {
1241 iovecBuf[i]->copyOut(proxy);
1242 delete iovecBuf[i];
1243 iov.iov_base = (void *)iovec_base_phold[i];
1244 }
1245 }
1246 iovBuf->copyOut(proxy);
1247 delete iovBuf;
1248 msgHdr->msg_iov = (struct iovec *)msg_iov_phold;
1249 }
1250
1251 if (msgHdr->msg_control) {
1252 controlBuf->copyOut(proxy);
1253 delete(controlBuf);
1254 msgHdr->msg_control = (void *)msg_control_phold;
1255 }
1256
1257 msgBuf.copyOut(proxy);
1258
1259 return recvd_size;
1260}
1261
1262SyscallReturn
1264 int tgt_fd, VPtr<> msgPtr, int flags)
1265{
1266 auto p = tc->getProcessPtr();
1267
1268 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1269 if (!sfdp)
1270 return -EBADF;
1271 int sim_fd = sfdp->getSimFD();
1272
1273 SETranslatingPortProxy proxy(tc);
1274
1278 BufferArg msgBuf(msgPtr, sizeof(struct msghdr));
1279 msgBuf.copyIn(proxy);
1280 struct msghdr msgHdr = *((struct msghdr *)msgBuf.bufferPtr());
1281
1286 struct iovec *iovPtr = msgHdr.msg_iov;
1287 BufferArg iovBuf((Addr)iovPtr, sizeof(struct iovec) * msgHdr.msg_iovlen);
1288 iovBuf.copyIn(proxy);
1289 struct iovec *iov = (struct iovec *)iovBuf.bufferPtr();
1290 msgHdr.msg_iov = iov;
1291
1297 BufferArg **bufferArray = (BufferArg **)malloc(msgHdr.msg_iovlen
1298 * sizeof(BufferArg *));
1299
1305 for (int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
1306 Addr basePtr = (Addr) iov[iovIndex].iov_base;
1307 bufferArray[iovIndex] = new BufferArg(basePtr, iov[iovIndex].iov_len);
1308 bufferArray[iovIndex]->copyIn(proxy);
1309 iov[iovIndex].iov_base = bufferArray[iovIndex]->bufferPtr();
1310 }
1311
1312 ssize_t sent_size = sendmsg(sim_fd, &msgHdr, flags);
1313 int local_errno = errno;
1314
1318 for (int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
1319 BufferArg *baseBuf = ( BufferArg *)bufferArray[iovIndex];
1320 delete(baseBuf);
1321 }
1322
1326 free(bufferArray);
1327
1328 return (sent_size < 0) ? -local_errno : sent_size;
1329}
1330
1331SyscallReturn
1333 int tgt_fd, int level, int optname, VPtr<> valPtr,
1334 VPtr<> lenPtr)
1335{
1336 // union of all possible return value types from getsockopt
1337 union val
1338 {
1339 int i_val;
1340 long l_val;
1341 struct linger linger_val;
1342 struct timeval timeval_val;
1343 } val;
1344
1345 auto p = tc->getProcessPtr();
1346
1347 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1348 if (!sfdp)
1349 return -EBADF;
1350 int sim_fd = sfdp->getSimFD();
1351
1352 socklen_t len = sizeof(val);
1353 int status = getsockopt(sim_fd, level, optname, &val, &len);
1354
1355 if (status == -1)
1356 return -errno;
1357
1358 SETranslatingPortProxy proxy(tc);
1359
1360 // copy val to valPtr and pass it on
1361 BufferArg valBuf(valPtr, sizeof(val));
1362 memcpy(valBuf.bufferPtr(), &val, sizeof(val));
1363 valBuf.copyOut(proxy);
1364
1365 // copy len to lenPtr and pass it on
1366 BufferArg lenBuf(lenPtr, sizeof(len));
1367 memcpy(lenBuf.bufferPtr(), &len, sizeof(len));
1368 lenBuf.copyOut(proxy);
1369
1370 return status;
1371}
1372
1373SyscallReturn
1375 int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
1376{
1377 auto p = tc->getProcessPtr();
1378
1379 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1380 if (!sfdp)
1381 return -EBADF;
1382 int sim_fd = sfdp->getSimFD();
1383
1384 // lenPtr is an in-out paramenter:
1385 // sending the address length in, conveying the final length out
1386
1387 SETranslatingPortProxy proxy(tc);
1388
1389 // Read in the value of len from the passed pointer.
1390 BufferArg lenBuf(lenPtr, sizeof(socklen_t));
1391 lenBuf.copyIn(proxy);
1392 socklen_t len = *(socklen_t *)lenBuf.bufferPtr();
1393
1394 struct sockaddr sa;
1395 int status = getsockname(sim_fd, &sa, &len);
1396
1397 if (status == -1)
1398 return -errno;
1399
1400 // Copy address to addrPtr and pass it on.
1401 BufferArg addrBuf(addrPtr, sizeof(sa));
1402 memcpy(addrBuf.bufferPtr(), &sa, sizeof(sa));
1403 addrBuf.copyOut(proxy);
1404
1405 // Copy len to lenPtr and pass it on.
1406 *(socklen_t *)lenBuf.bufferPtr() = len;
1407 lenBuf.copyOut(proxy);
1408
1409 return status;
1410}
1411
1412SyscallReturn
1414 int tgt_fd, VPtr<> sockAddrPtr, VPtr<> addrlenPtr)
1415{
1416 auto p = tc->getProcessPtr();
1417
1418 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1419 if (!sfdp)
1420 return -EBADF;
1421 int sim_fd = sfdp->getSimFD();
1422
1423 SETranslatingPortProxy proxy(tc);
1424
1425 BufferArg bufAddrlen(addrlenPtr, sizeof(unsigned));
1426 bufAddrlen.copyIn(proxy);
1427 BufferArg bufSock(sockAddrPtr, *(unsigned *)bufAddrlen.bufferPtr());
1428
1429 int retval = getpeername(sim_fd,
1430 (struct sockaddr *)bufSock.bufferPtr(),
1431 (unsigned *)bufAddrlen.bufferPtr());
1432
1433 if (retval != -1) {
1434 bufSock.copyOut(proxy);
1435 bufAddrlen.copyOut(proxy);
1436 }
1437
1438 return (retval == -1) ? -errno : retval;
1439}
1440
1441SyscallReturn
1443 int tgt_fd, int level, int optname, VPtr<> valPtr,
1444 socklen_t len)
1445{
1446 auto p = tc->getProcessPtr();
1447
1448 BufferArg valBuf(valPtr, len);
1449 valBuf.copyIn(SETranslatingPortProxy(tc));
1450
1451 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1452 if (!sfdp)
1453 return -EBADF;
1454 int sim_fd = sfdp->getSimFD();
1455
1456 int status = setsockopt(sim_fd, level, optname,
1457 (struct sockaddr *)valBuf.bufferPtr(), len);
1458
1459 return (status == -1) ? -errno : status;
1460}
1461
1462SyscallReturn
1465{
1466 // unsigned is the same size (4) on all Linux supported ISAs.
1467 if (cpu)
1468 *cpu = htog(tc->contextId(), tc->getSystemPtr()->getGuestByteOrder());
1469
1470 // Set a fixed NUMA node 0.
1471 if (node)
1472 *node = 0;
1473
1474 return 0;
1475}
1476
1477SyscallReturn
1479 int pid, VPtr<int> paramPtr)
1480{
1481 if (!paramPtr || pid < 0)
1482 return -EINVAL;
1483
1484 warn_once("sched_getparam: pretending sched_priority is 0 for all PIDs\n");
1485 *paramPtr = 0;
1486 return 0;
1487}
1488
1489} // namespace gem5
Declaration and inline definition of ChunkGenerator object.
bool copyIn(const PortProxy &memproxy)
copy data into simulator space (read from target memory)
bool copyOut(const PortProxy &memproxy)
copy data out of simulator space (write to target memory)
BufferArg represents an untyped buffer in target user space that is passed by reference to an (emulat...
void * bufferPtr()
Return a pointer to the internal simulator-space buffer.
static bool readyToExit(Tick delay)
Initiate the exit from the simulation.
FutexMap class holds a map of all futexes used in the system.
Definition futex_map.hh:110
int wakeup(Addr addr, uint64_t tgid, int count)
Wakes up at most count waiting threads on a futex.
Definition futex_map.cc:59
bool tryReadString(std::string &str, Addr addr) const
Reads the string at guest address addr into the std::string str.
uint64_t egid()
Definition process.hh:84
uint64_t pid()
Definition process.hh:85
uint64_t uid()
Definition process.hh:81
uint64_t pgid()
Definition process.hh:87
uint64_t ppid()
Definition process.hh:86
std::string checkPathRedirect(const std::string &filename)
Redirect file path if it matches any keys initialized by system object.
Definition process.cc:464
uint64_t gid()
Definition process.hh:83
uint64_t tgid()
Definition process.hh:89
uint64_t euid()
Definition process.hh:82
EmulationPageTable * pTable
Definition process.hh:195
uint64_t childClearTID
Calls a futex wakeup at the address specified by this pointer when this process exits.
Definition process.hh:306
This class provides the wrapper interface for the system call implementations which are defined in th...
std::string name() const
This class represents the return value from an emulated system call, including any errno setting.
int size() const
Definition system.hh:215
std::list< BasicSignal > signalList
Definition system.hh:612
FutexMap futexMap
Definition system.hh:603
ByteOrder getGuestByteOrder() const
Get the guest byte order.
Definition system.hh:393
static std::vector< System * > systemList
Definition system.hh:598
Threads threads
Definition system.hh:315
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual void activate()=0
Set the status to Active.
virtual System * getSystemPtr()=0
virtual void halt()=0
Set the status to Halted.
@ Halted
Permanently shut down.
@ Halting
Trying to exit and waiting for an event to completely exit.
@ Suspended
Temporarily inactive.
virtual Status status() const =0
virtual Process * getProcessPtr()=0
virtual ContextID contextId() const =0
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:232
#define warn(...)
Definition logging.hh:288
#define warn_once(...)
Definition logging.hh:292
Bitfield< 3 > sa
Bitfield< 18, 16 > len
Bitfield< 4, 0 > mode
Definition misc_types.hh:74
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 23, 0 > offset
Definition types.hh:144
Bitfield< 5, 0 > status
Bitfield< 0 > p
Bitfield< 25, 21 > bo
Definition types.hh:82
Bitfield< 15 > system
Definition misc.hh:1032
Bitfield< 63 > val
Definition misc.hh:804
Bitfield< 20 > level
Definition intmessage.hh:51
Bitfield< 3 > addr
Definition types.hh:84
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
SyscallReturn linkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> new_pathname)
Target link() handler.
SyscallReturn getppidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getppid() handler.
SyscallReturn exitGroupFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit_group() handler: terminate simulation. (exit all threads)
SyscallReturn gettidFunc(SyscallDesc *desc, ThreadContext *tc)
Target gettid() handler.
SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
void warnUnsupportedOS(std::string syscall_name)
SyscallReturn brkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> new_brk)
Target brk() handler: set brk address.
SyscallReturn pipe2Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr, int flags)
Target pipe() handler.
SyscallReturn getpidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpid() handler.
bool startswith(const char *s, const char *prefix)
Return true if 's' starts with the prefix string 'prefix'.
Definition str.hh:230
SyscallReturn chdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Target chdir() handler.
SyscallReturn truncate64Func(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, int64_t length)
Target truncate64() handler.
SyscallReturn getuidFunc(SyscallDesc *desc, ThreadContext *tc)
SyscallReturn pipePseudoFunc(SyscallDesc *desc, ThreadContext *tc)
Pseudo Funcs - These functions use a different return convension, returning a second value in a regis...
static void exitFutexWake(ThreadContext *tc, VPtr<> addr, uint64_t tgid)
SyscallReturn chownFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, uint32_t owner, uint32_t group)
Target chown() handler.
const char * hostname
SyscallReturn renameImpl(SyscallDesc *desc, ThreadContext *tc, std::string old_name, std::string new_name)
SyscallReturn _llseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t offset_high, uint32_t offset_low, VPtr<> result_ptr, int whence)
Target _llseek() handler.
SyscallReturn mknodImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode, dev_t dev)
SyscallReturn renameFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> oldpath, VPtr<> newpath)
Target rename() handler.
SyscallReturn mknodFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode, dev_t dev)
Target mknod() handler.
SyscallReturn setpgidFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int pgid)
Target setpgid() handler.
SyscallReturn geteuidFunc(SyscallDesc *desc, ThreadContext *tc)
Target geteuid() handler.
SyscallReturn symlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, VPtr<> new_pathname)
Target symlink() handler.
ProxyPtr< T, SETranslatingPortProxy > VPtr
Definition proxy_ptr.hh:400
SyscallReturn unlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
Target unlink() handler.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
SyscallReturn accessImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode)
SyscallReturn chownImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, uint32_t owner, uint32_t group)
SyscallReturn pipeFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> tgt_addr)
Target pipe() handler.
SyscallReturn getsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, VPtr<> lenPtr)
void exitSimLoop(const std::string &message, int exit_code, Tick when, Tick repeat, bool serialize)
The "old style" exitSimLoop functions.
SyscallReturn fcntl64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd)
Target fcntl64() handler.
SyscallReturn ignoreWarnOnceFunc(SyscallDesc *desc, ThreadContext *tc)
Like above, but only prints a warning once per syscall desc it's used with.
SyscallReturn setsockoptFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int level, int optname, VPtr<> valPtr, socklen_t len)
SyscallReturn getpagesizeFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpagesize() handler.
SyscallReturn rmdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname)
SyscallReturn mkdirFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target mkdir() handler.
SyscallReturn getpgrpFunc(SyscallDesc *desc, ThreadContext *tc)
Target getpgrpFunc() handler.
SyscallReturn unlinkImpl(SyscallDesc *desc, ThreadContext *tc, std::string path)
SyscallReturn dupFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
FIXME: The file description is not shared among file descriptors created with dup.
SyscallReturn listenFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int backlog)
SyscallReturn ftruncate64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int64_t length)
Target ftruncate64() handler.
SyscallReturn fchownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint32_t owner, uint32_t group)
Target fchown() handler.
SyscallReturn setTidAddressFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> tidPtr)
Target set_tid_address() handler.
SyscallReturn fcntlFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int cmd, guest_abi::VarArgs< int > varargs)
Target fcntl() handler.
T htog(T value, ByteOrder guest_byte_order)
Definition byteswap.hh:187
SyscallReturn bindFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int addrlen)
SyscallReturn getegidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getegid() handler.
SyscallReturn shutdownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int how)
Target shutdown() handler.
SyscallReturn getcpuFunc(SyscallDesc *desc, ThreadContext *tc, VPtr< uint32_t > cpu, VPtr< uint32_t > node, VPtr< uint32_t > tcache)
SyscallReturn getsocknameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> addrPtr, VPtr<> lenPtr)
SyscallReturn mkdirImpl(SyscallDesc *desc, ThreadContext *tc, std::string path, mode_t mode)
SyscallReturn getpeernameFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> sockAddrPtr, VPtr<> addrlenPtr)
SyscallReturn unimplementedFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we haven't thought about.
SyscallReturn ignoreWithEnosysFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that return -ENOSYS to the target program.
SyscallReturn gethostnameFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, int name_len)
Target gethostname() handler.
SyscallReturn accessFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname, mode_t mode)
Target access() handler.
SyscallReturn sendmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags)
SyscallReturn ignoreFunc(SyscallDesc *desc, ThreadContext *tc)
Handler for unimplemented syscalls that we never intend to implement (signal handling,...
SyscallReturn rmdirImpl(SyscallDesc *desc, ThreadContext *tc, std::string path)
static SyscallReturn exitImpl(SyscallDesc *desc, ThreadContext *tc, bool group, int status)
SyscallReturn connectFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, int addrlen)
SyscallReturn sched_getparamFunc(SyscallDesc *desc, ThreadContext *tc, int pid, VPtr< int > paramPtr)
SyscallReturn exitFunc(SyscallDesc *desc, ThreadContext *tc, int status)
Target exit() handler: terminate current context.
SyscallReturn dup2Func(SyscallDesc *desc, ThreadContext *tc, int old_tgt_fd, int new_tgt_fd)
Target dup2() handler.
SyscallReturn getgidFunc(SyscallDesc *desc, ThreadContext *tc)
Target getgid() handler.
SyscallReturn closeFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd)
Target close() handler.
SyscallReturn umaskFunc(SyscallDesc *desc, ThreadContext *tc)
Target umask() handler.
Declarations of a non-full system Page Table.
#define DPRINTF_SYSCALL(FLAGEXT, FMT,...)
This macro is intended to help with readability.
This file defines objects used to emulate syscalls from the target application on the host machine.
const std::string & name()
Definition trace.cc:48

Generated on Mon Oct 27 2025 04:13:04 for gem5 by doxygen 1.14.0