syscall_emul.hh (11906:4b99c1bb3b72) syscall_emul.hh (11907:48a3d32da9d8)
1/*
2 * Copyright (c) 2012-2013, 2015 ARM Limited
3 * Copyright (c) 2015 Advanced Micro Devices, Inc.
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating

--- 599 unchanged lines hidden (view full) ---

608 * return something better here, but at least we issue the warning.
609 */
610 warn("Unsupported ioctl call (return ENOTTY): ioctl(%d, 0x%x, ...) @ \n",
611 tgt_fd, req, tc->pcState());
612 return -ENOTTY;
613}
614
615template <class OS>
1/*
2 * Copyright (c) 2012-2013, 2015 ARM Limited
3 * Copyright (c) 2015 Advanced Micro Devices, Inc.
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating

--- 599 unchanged lines hidden (view full) ---

608 * return something better here, but at least we issue the warning.
609 */
610 warn("Unsupported ioctl call (return ENOTTY): ioctl(%d, 0x%x, ...) @ \n",
611 tgt_fd, req, tc->pcState());
612 return -ENOTTY;
613}
614
615template <class OS>
616static SyscallReturn
617openFunc(SyscallDesc *desc, int callnum, Process *process,
618 ThreadContext *tc, int index)
616SyscallReturn
617openImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc,
618 bool isopenat)
619{
619{
620 std::string path;
620 int index = 0;
621 int tgt_dirfd = -1;
621
622
622 if (!tc->getMemProxy().tryReadString(path,
623 process->getSyscallArg(tc, index)))
623 /**
624 * If using the openat variant, read in the target directory file
625 * descriptor from the simulated process.
626 */
627 if (isopenat)
628 tgt_dirfd = p->getSyscallArg(tc, index);
629
630 /**
631 * Retrieve the simulated process' memory proxy and then read in the path
632 * string from that memory space into the host's working memory space.
633 */
634 std::string path;
635 if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
624 return -EFAULT;
625
636 return -EFAULT;
637
626 int tgtFlags = process->getSyscallArg(tc, index);
627 int mode = process->getSyscallArg(tc, index);
628 int hostFlags = 0;
629
630 // translate open flags
638#ifdef __CYGWIN32__
639 int host_flags = O_BINARY;
640#else
641 int host_flags = 0;
642#endif
643 /**
644 * Translate target flags into host flags. Flags exist which are not
645 * ported between architectures which can cause check failures.
646 */
647 int tgt_flags = p->getSyscallArg(tc, index);
631 for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
648 for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) {
632 if (tgtFlags & OS::openFlagTable[i].tgtFlag) {
633 tgtFlags &= ~OS::openFlagTable[i].tgtFlag;
634 hostFlags |= OS::openFlagTable[i].hostFlag;
649 if (tgt_flags & OS::openFlagTable[i].tgtFlag) {
650 tgt_flags &= ~OS::openFlagTable[i].tgtFlag;
651 host_flags |= OS::openFlagTable[i].hostFlag;
635 }
636 }
652 }
653 }
637
638 // any target flags left?
639 if (tgtFlags != 0)
640 warn("Syscall: open: cannot decode flags 0x%x", tgtFlags);
641
654 if (tgt_flags) {
655 warn("open%s: cannot decode flags 0x%x",
656 isopenat ? "at" : "", tgt_flags);
657 }
642#ifdef __CYGWIN32__
658#ifdef __CYGWIN32__
643 hostFlags |= O_BINARY;
659 host_flags |= O_BINARY;
644#endif
645
660#endif
661
646 // Adjust path for current working directory
647 path = process->fullPath(path);
662 int mode = p->getSyscallArg(tc, index);
648
663
649 DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str());
664 /**
665 * If the simulated process called open or openat with AT_FDCWD specified,
666 * take the current working directory value which was passed into the
667 * process class as a Python parameter and append the current path to
668 * create a full path.
669 * Otherwise, openat with a valid target directory file descriptor has
670 * been called. If the path option, which was passed in as a parameter,
671 * is not absolute, retrieve the directory file descriptor's path and
672 * prepend it to the path passed in as a parameter.
673 * In every case, we should have a full path (which is relevant to the
674 * host) to work with after this block has been passed.
675 */
676 if (!isopenat || (isopenat && tgt_dirfd == OS::TGT_AT_FDCWD)) {
677 path = p->fullPath(path);
678 } else if (!startswith(path, "/")) {
679 std::shared_ptr<FDEntry> fdep = ((*p->fds)[tgt_dirfd]);
680 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
681 if (!ffdp)
682 return -EBADF;
683 path.insert(0, ffdp->getFileName());
684 }
650
685
686 /**
687 * Since this is an emulated environment, we create pseudo file
688 * descriptors for device requests that have been registered with
689 * the process class through Python; this allows us to create a file
690 * descriptor for subsequent ioctl or mmap calls.
691 */
651 if (startswith(path, "/dev/")) {
652 std::string filename = path.substr(strlen("/dev/"));
692 if (startswith(path, "/dev/")) {
693 std::string filename = path.substr(strlen("/dev/"));
653 if (filename == "sysdev0") {
654 // This is a memory-mapped high-resolution timer device on Alpha.
655 // We don't support it, so just punt.
656 warn("Ignoring open(%s, ...)\n", path);
657 return -ENOENT;
658 }
659
660 EmulatedDriver *drv = process->findDriver(filename);
694 EmulatedDriver *drv = p->findDriver(filename);
661 if (drv) {
695 if (drv) {
662 // the driver's open method will allocate a fd from the
663 // process if necessary.
664 return drv->open(process, tc, mode, hostFlags);
696 DPRINTF_SYSCALL(Verbose, "open%s: passing call to "
697 "driver open with path[%s]\n",
698 isopenat ? "at" : "", path.c_str());
699 return drv->open(p, tc, mode, host_flags);
665 }
700 }
701 /**
702 * Fall through here for pass through to host devices, such
703 * as /dev/zero
704 */
705 }
666
706
667 // fall through here for pass through to host devices, such as
668 // /dev/zero
707 /**
708 * Some special paths and files cannot be called on the host and need
709 * to be handled as special cases inside the simulator.
710 * If the full path that was created above does not match any of the
711 * special cases, pass it through to the open call on the host to let
712 * the host open the file on our behalf.
713 * If the host cannot open the file, return the host's error code back
714 * through the system call to the simulated process.
715 */
716 int sim_fd = -1;
717 std::vector<std::string> special_paths =
718 { "/proc/", "/system/", "/sys/", "/platform/", "/etc/passwd" };
719 for (auto entry : special_paths) {
720 if (startswith(path, entry))
721 sim_fd = OS::openSpecialFile(path, p, tc);
669 }
722 }
723 if (sim_fd == -1) {
724 sim_fd = open(path.c_str(), host_flags, mode);
725 }
726 if (sim_fd == -1) {
727 int local = -errno;
728 DPRINTF_SYSCALL(Verbose, "open%s: failed -> path:%s\n",
729 isopenat ? "at" : "", path.c_str());
730 return local;
731 }
670
732
671 int fd;
672 int local_errno;
673 if (startswith(path, "/proc/") || startswith(path, "/system/") ||
674 startswith(path, "/platform/") || startswith(path, "/sys/")) {
675 // It's a proc/sys entry and requires special handling
676 fd = OS::openSpecialFile(path, process, tc);
677 local_errno = ENOENT;
678 } else {
679 // open the file
680 fd = open(path.c_str(), hostFlags, mode);
681 local_errno = errno;
682 }
683
684 if (fd == -1)
685 return -local_errno;
686
687 std::shared_ptr<FileFDEntry> ffdp =
688 std::make_shared<FileFDEntry>(fd, hostFlags, path.c_str(), false);
689 return process->fds->allocFD(ffdp);
733 /**
734 * The file was opened successfully and needs to be recorded in the
735 * process' file descriptor array so that it can be retrieved later.
736 * The target file descriptor that is chosen will be the lowest unused
737 * file descriptor.
738 * Return the indirect target file descriptor back to the simulated
739 * process to act as a handle for the opened file.
740 */
741 auto ffdp = std::make_shared<FileFDEntry>(sim_fd, host_flags, path, 0);
742 int tgt_fd = p->fds->allocFD(ffdp);
743 DPRINTF_SYSCALL(Verbose, "open%s: sim_fd[%d], target_fd[%d] -> path:%s\n",
744 isopenat ? "at" : "", sim_fd, tgt_fd, path.c_str());
745 return tgt_fd;
690}
691
692/// Target open() handler.
693template <class OS>
694SyscallReturn
695openFunc(SyscallDesc *desc, int callnum, Process *process,
696 ThreadContext *tc)
697{
746}
747
748/// Target open() handler.
749template <class OS>
750SyscallReturn
751openFunc(SyscallDesc *desc, int callnum, Process *process,
752 ThreadContext *tc)
753{
698 return openFunc<OS>(desc, callnum, process, tc, 0);
754 return openImpl<OS>(desc, callnum, process, tc, false);
699}
700
701/// Target openat() handler.
702template <class OS>
703SyscallReturn
704openatFunc(SyscallDesc *desc, int callnum, Process *process,
705 ThreadContext *tc)
706{
755}
756
757/// Target openat() handler.
758template <class OS>
759SyscallReturn
760openatFunc(SyscallDesc *desc, int callnum, Process *process,
761 ThreadContext *tc)
762{
707 int index = 0;
708 int dirfd = process->getSyscallArg(tc, index);
709 if (dirfd != OS::TGT_AT_FDCWD)
710 warn("openat: first argument not AT_FDCWD; unlikely to work");
711 return openFunc<OS>(desc, callnum, process, tc, 1);
763 return openImpl<OS>(desc, callnum, process, tc, true);
712}
713
714/// Target unlinkat() handler.
715template <class OS>
716SyscallReturn
717unlinkatFunc(SyscallDesc *desc, int callnum, Process *process,
718 ThreadContext *tc)
719{

--- 1194 unchanged lines hidden ---
764}
765
766/// Target unlinkat() handler.
767template <class OS>
768SyscallReturn
769unlinkatFunc(SyscallDesc *desc, int callnum, Process *process,
770 ThreadContext *tc)
771{

--- 1194 unchanged lines hidden ---