summaryrefslogtreecommitdiff
path: root/src/sim
diff options
context:
space:
mode:
authorDavid Hashe <david.hashe@amd.com>2018-04-18 16:36:55 -0400
committerBrandon Potter <Brandon.Potter@amd.com>2019-04-25 18:11:34 +0000
commit54c77aa055ee41c8a4d2d500781752804cdfc339 (patch)
tree236e474ed1839963f1be6b542f131e509415bdb1 /src/sim
parente8d0b755eadffb0203b966479f55a75281522b18 (diff)
downloadgem5-54c77aa055ee41c8a4d2d500781752804cdfc339.tar.xz
sim-se: add a faux-filesystem
This change introduces the concept of a faux-filesystem. The faux-filesystem creates a directory structure in m5out (or whatever output dir the user specifies) where system calls may be redirected. This is useful to avoid non-determinism when reading files with varying path names (e.g., variations from run-to-run if the simulation is scheduled on a cluster where paths may change). Also, this changeset allows circumventing host pseudofiles which have information specific to the host processor (such as cache hierarchy or processor information). Bypassing host pseudofiles can be useful when executing runtimes in the absence of an operating system kernel since runtimes may try to query standard files (i.e. /proc or /sys) which are not relevant to an application executing in syscall emulation mode. Change-Id: I90821b3b403168b904a662fa98b85def1628621c Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/12119 Reviewed-by: Jason Lowe-Power <jason@lowepower.com> Maintainer: Jason Lowe-Power <jason@lowepower.com> Tested-by: kokoro <noreply+kokoro@google.com>
Diffstat (limited to 'src/sim')
-rw-r--r--src/sim/Process.py3
-rw-r--r--src/sim/RedirectPath.py43
-rw-r--r--src/sim/SConscript2
-rw-r--r--src/sim/System.py2
-rw-r--r--src/sim/process.cc91
-rw-r--r--src/sim/process.hh41
-rw-r--r--src/sim/redirect_path.cc63
-rw-r--r--src/sim/redirect_path.hh65
-rw-r--r--src/sim/syscall_emul.cc70
-rw-r--r--src/sim/syscall_emul.hh110
-rw-r--r--src/sim/system.cc5
-rw-r--r--src/sim/system.hh7
12 files changed, 409 insertions, 93 deletions
diff --git a/src/sim/Process.py b/src/sim/Process.py
index 2ffc51a33..73a0145fd 100644
--- a/src/sim/Process.py
+++ b/src/sim/Process.py
@@ -29,6 +29,7 @@
from m5.SimObject import *
from m5.params import *
from m5.proxy import *
+from os import getcwd
class Process(SimObject):
type = 'Process'
@@ -58,7 +59,7 @@ class Process(SimObject):
executable = Param.String('', "executable (overrides cmd[0] if set)")
cmd = VectorParam.String("command line (executable plus arguments)")
env = VectorParam.String([], "environment settings")
- cwd = Param.String('', "current working directory")
+ cwd = Param.String(getcwd(), "current working directory")
simpoint = Param.UInt64(0, 'simulation point at which to start simulation')
drivers = VectorParam.EmulatedDriver([], 'Available emulated drivers')
diff --git a/src/sim/RedirectPath.py b/src/sim/RedirectPath.py
new file mode 100644
index 000000000..08511b891
--- /dev/null
+++ b/src/sim/RedirectPath.py
@@ -0,0 +1,43 @@
+# Copyright (c) 2015 Advanced Micro Devices, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: David Hashe
+
+from m5.SimObject import SimObject
+from m5.params import *
+from m5.proxy import *
+
+class RedirectPath(SimObject):
+ """ Stores paths for filesystem redirection during syscalls. If a path
+ matches 'appPath', then the syscall is redirected to the first 'hostPath'
+ that contains the non-overlapping portion of the path as a valid file. If
+ there are no hits, then the syscall is redirected to the first value.
+ """
+ type = 'RedirectPath'
+ cxx_header = "sim/redirect_path.hh"
+
+ app_path = Param.String("/", "filesystem path from an app's perspective")
+ host_paths = VectorParam.String(["/"], "file path on host filesystem")
diff --git a/src/sim/SConscript b/src/sim/SConscript
index 54e251287..8ab2c72f9 100644
--- a/src/sim/SConscript
+++ b/src/sim/SConscript
@@ -38,6 +38,7 @@ SimObject('VoltageDomain.py')
SimObject('System.py')
SimObject('DVFSHandler.py')
SimObject('SubSystem.py')
+SimObject('RedirectPath.py')
Source('arguments.cc')
Source('async.cc')
@@ -56,6 +57,7 @@ Source('init_signals.cc')
Source('main.cc', tags='main')
Source('port.cc')
Source('python.cc', add_tags='python')
+Source('redirect_path.cc')
Source('root.cc')
Source('serialize.cc')
Source('drain.cc')
diff --git a/src/sim/System.py b/src/sim/System.py
index 51b1a743f..c012cb256 100644
--- a/src/sim/System.py
+++ b/src/sim/System.py
@@ -83,6 +83,8 @@ class System(MemObject):
cache_line_size = Param.Unsigned(64, "Cache line size in bytes")
+ redirect_paths = VectorParam.RedirectPath([], "Path redirections")
+
exit_on_work_items = Param.Bool(False, "Exit from the simulation loop when "
"encountering work item annotations.")
work_item_id = Param.Int(-1, "specific work item id")
diff --git a/src/sim/process.cc b/src/sim/process.cc
index 5cec2958e..10c68fe6c 100644
--- a/src/sim/process.cc
+++ b/src/sim/process.cc
@@ -50,6 +50,7 @@
#include <unistd.h>
#include <array>
+#include <climits>
#include <csignal>
#include <map>
#include <string>
@@ -67,6 +68,7 @@
#include "sim/emul_driver.hh"
#include "sim/fd_array.hh"
#include "sim/fd_entry.hh"
+#include "sim/redirect_path.hh"
#include "sim/syscall_desc.hh"
#include "sim/system.hh"
@@ -101,6 +103,14 @@
using namespace std;
using namespace TheISA;
+static std::string
+normalize(std::string& directory)
+{
+ if (directory.back() != '/')
+ directory += '/';
+ return directory;
+}
+
Process::Process(ProcessParams *params, EmulationPageTable *pTable,
ObjectFile *obj_file)
: SimObject(params), system(params->system),
@@ -111,8 +121,10 @@ Process::Process(ProcessParams *params, EmulationPageTable *pTable,
initVirtMem(system->getSystemPort(), this,
SETranslatingPortProxy::Always),
objFile(obj_file),
- argv(params->cmd), envp(params->env), cwd(params->cwd),
+ argv(params->cmd), envp(params->env),
executable(params->executable),
+ tgtCwd(normalize(params->cwd)),
+ hostCwd(checkPathRedirect(tgtCwd)),
_uid(params->uid), _euid(params->euid),
_gid(params->gid), _egid(params->egid),
_pid(params->pid), _ppid(params->ppid),
@@ -441,6 +453,42 @@ Process::findDriver(std::string filename)
return nullptr;
}
+std::string
+Process::checkPathRedirect(const std::string &filename)
+{
+ // If the input parameter contains a relative path, convert it. Note,
+ // the return value for this method should always return an absolute
+ // path on the host filesystem. The return value will be used to
+ // open and manipulate the path specified by the input parameter. Since
+ // all filesystem handling in syscall mode is passed through to the host,
+ // we deal only with host paths.
+ auto host_fs_abs_path = absolutePath(filename, true);
+
+ for (auto path : system->redirectPaths) {
+ // Search through the redirect paths to see if a starting substring of
+ // our path falls into any buckets which need to redirected.
+ if (startswith(host_fs_abs_path, path->appPath())) {
+ std::string tail = host_fs_abs_path.substr(path->appPath().size());
+
+ // If this path needs to be redirected, search through a list
+ // of targets to see if we can match a valid file (or directory).
+ for (auto host_path : path->hostPaths()) {
+ if (access((host_path + tail).c_str(), R_OK) == 0) {
+ // Return the valid match.
+ return host_path + tail;
+ }
+ }
+ // The path needs to be redirected, but the file or directory
+ // does not exist on the host filesystem. Return the first
+ // host path as a default.
+ return path->hostPaths()[0] + tail;
+ }
+ }
+
+ // The path does not need to be redirected.
+ return host_fs_abs_path;
+}
+
void
Process::updateBias()
{
@@ -489,6 +537,33 @@ Process::getStartPC()
return interp ? interp->entryPoint() : objFile->entryPoint();
}
+std::string
+Process::absolutePath(const std::string &filename, bool host_filesystem)
+{
+ if (filename.empty() || startswith(filename, "/"))
+ return filename;
+
+ // Verify that the current working directories are initialized properly.
+ // These members should be set initially via params from 'Process.py',
+ // although they may change over time depending on what the application
+ // does during simulation.
+ assert(!tgtCwd.empty());
+ assert(!hostCwd.empty());
+
+ // Construct the absolute path given the current working directory for
+ // either the host filesystem or target filesystem. The distinction only
+ // matters if filesystem redirection is utilized in the simulation.
+ auto path_base = host_filesystem ? hostCwd : tgtCwd;
+
+ // Add a trailing '/' if the current working directory did not have one.
+ normalize(path_base);
+
+ // Append the filename onto the current working path.
+ auto absolute_path = path_base + filename;
+
+ return absolute_path;
+}
+
Process *
ProcessParams::create()
{
@@ -649,17 +724,3 @@ ProcessParams::create()
fatal("Unknown error creating process object.");
return process;
}
-
-std::string
-Process::fullPath(const std::string &file_name)
-{
- if (file_name[0] == '/' || cwd.empty())
- return file_name;
-
- std::string full = cwd;
-
- if (cwd[cwd.size() - 1] != '/')
- full += '/';
-
- return full + file_name;
-}
diff --git a/src/sim/process.hh b/src/sim/process.hh
index a1ca84bf5..27c569602 100644
--- a/src/sim/process.hh
+++ b/src/sim/process.hh
@@ -91,8 +91,6 @@ class Process : public SimObject
inline void setpgid(uint64_t pgid) { _pgid = pgid; }
const char *progName() const { return executable.c_str(); }
- std::string fullPath(const std::string &filename);
- std::string getcwd() const { return cwd; }
/**
* Find an emulated device driver.
@@ -186,9 +184,46 @@ class Process : public SimObject
ObjectFile *objFile;
std::vector<std::string> argv;
std::vector<std::string> envp;
- std::string cwd;
std::string executable;
+ /**
+ * Return an absolute path given a relative path paired with the current
+ * working directory of the process running under simulation.
+ *
+ * @param path The relative path (generally a filename) that needs the
+ * current working directory prepended.
+ * @param host_fs A flag which determines whether to return a
+ * path for the host filesystem or the filesystem of the process running
+ * under simulation. Only matters if filesysem redirection is used to
+ * replace files (or directories) that would normally appear via the
+ * host filesystem.
+ * @return String containing an absolute path.
+ */
+ std::string absolutePath(const std::string &path, bool host_fs);
+
+ /**
+ * Redirect file path if it matches any keys initialized by system object.
+ * @param filename An input parameter containing either a relative path
+ * or an absolute path. If given a relative path, the path will be
+ * prepended to the current working directory of the simulation with
+ * respect to the host filesystem.
+ * @return String containing an absolute path.
+ */
+ std::string checkPathRedirect(const std::string &filename);
+
+ /**
+ * The cwd members are used to track changes to the current working
+ * directory for the purpose of executing system calls which depend on
+ * relative paths (i.e. open, chdir).
+ *
+ * The tgt member and host member may differ if the path for the current
+ * working directory is redirected to point to a different location
+ * (i.e. `cd /proc` should point to '$(gem5_repo)/m5out/fs/proc'
+ * instead of '/proc').
+ */
+ std::string tgtCwd;
+ std::string hostCwd;
+
// Id of the owner of the process
uint64_t _uid;
uint64_t _euid;
diff --git a/src/sim/redirect_path.cc b/src/sim/redirect_path.cc
new file mode 100644
index 000000000..8c41ffabd
--- /dev/null
+++ b/src/sim/redirect_path.cc
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: David Hashe
+ */
+
+#include "sim/redirect_path.hh"
+
+#include <unistd.h>
+
+static std::string
+normalizePath(std::string path)
+{
+ char buf[PATH_MAX];
+ std::string gem5_cwd = getcwd(buf, PATH_MAX);
+
+ if (!startswith(path, "/")) {
+ path = realpath((gem5_cwd + "/" + path).c_str(), buf);
+ }
+ if (path[path.length()-1] != '/') path.push_back('/');
+
+ return path;
+}
+
+RedirectPath::RedirectPath(const RedirectPathParams *p)
+ : SimObject(p)
+{
+ _appPath = normalizePath(p->app_path);
+
+ for (auto hp : p->host_paths) {
+ _hostPaths.push_back(normalizePath(hp));
+ }
+}
+
+RedirectPath*
+RedirectPathParams::create()
+{
+ return new RedirectPath(this);
+}
diff --git a/src/sim/redirect_path.hh b/src/sim/redirect_path.hh
new file mode 100644
index 000000000..7dbb4eaa7
--- /dev/null
+++ b/src/sim/redirect_path.hh
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: David Hashe
+ */
+
+#ifndef __SIM_REDIRECT_PATH_HH__
+#define __SIM_REDIRECT_PATH_HH__
+
+#include <string>
+#include <vector>
+
+#include "params/RedirectPath.hh"
+#include "sim/sim_object.hh"
+
+/**
+ * RedirectPath stores a mapping from one 'appPath' to a vector of
+ * 'hostPath'. Each 'appPath' and 'hostPath' is a filesystem path.
+ * Used by process.cc to redirect syscall accesses to different directories.
+ */
+class RedirectPath : public SimObject
+{
+ public:
+ RedirectPath(const RedirectPathParams *p);
+
+ const std::string& appPath() { return _appPath; };
+ const std::vector<std::string>& hostPaths() { return _hostPaths; };
+
+ protected:
+ /**
+ * An appPath is a path which needs to be redirected and replaced
+ * by one of the corresponding hostPath (when accessing files on the host
+ * filesystem.)
+ */
+ // _appPath holds the path as it would appear from an app's perspective.
+ std::string _appPath;
+ // _hostPaths holds a set of host filesystem paths
+ std::vector<std::string> _hostPaths;
+};
+
+#endif
diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc
index fbfe21a93..a9490fa57 100644
--- a/src/sim/syscall_emul.cc
+++ b/src/sim/syscall_emul.cc
@@ -388,7 +388,7 @@ getcwdFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
BufferArg buf(buf_ptr, size);
// Is current working directory defined?
- string cwd = p->getcwd();
+ string cwd = p->tgtCwd;
if (!cwd.empty()) {
if (cwd.length() >= size) {
// Buffer too small
@@ -425,8 +425,8 @@ readlinkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc,
if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
return -EFAULT;
- // Adjust path for current working directory
- path = p->fullPath(path);
+ // Adjust path for cwd and redirection
+ path = p->checkPathRedirect(path);
Addr buf_ptr = p->getSyscallArg(tc, index);
size_t bufsiz = p->getSyscallArg(tc, index);
@@ -491,7 +491,7 @@ unlinkHelper(SyscallDesc *desc, int num, Process *p, ThreadContext *tc,
if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
return -EFAULT;
- path = p->fullPath(path);
+ path = p->checkPathRedirect(path);
int result = unlink(path.c_str());
return (result == -1) ? -errno : result;
@@ -510,8 +510,8 @@ linkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
if (!virt_mem.tryReadString(new_path, p->getSyscallArg(tc, index)))
return -EFAULT;
- path = p->fullPath(path);
- new_path = p->fullPath(new_path);
+ path = p->absolutePath(path, true);
+ new_path = p->absolutePath(new_path, true);
int result = link(path.c_str(), new_path.c_str());
return (result == -1) ? -errno : result;
@@ -530,8 +530,8 @@ symlinkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
if (!virt_mem.tryReadString(new_path, p->getSyscallArg(tc, index)))
return -EFAULT;
- path = p->fullPath(path);
- new_path = p->fullPath(new_path);
+ path = p->absolutePath(path, true);
+ new_path = p->absolutePath(new_path, true);
int result = symlink(path.c_str(), new_path.c_str());
return (result == -1) ? -errno : result;
@@ -540,18 +540,15 @@ symlinkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
SyscallReturn
mkdirFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
{
- string path;
-
int index = 0;
+ std::string path;
if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
return -EFAULT;
- // Adjust path for current working directory
- path = p->fullPath(path);
-
+ path = p->checkPathRedirect(path);
mode_t mode = p->getSyscallArg(tc, index);
- int result = mkdir(path.c_str(), mode);
+ auto result = mkdir(path.c_str(), mode);
return (result == -1) ? -errno : result;
}
@@ -569,9 +566,9 @@ renameFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
if (!tc->getMemProxy().tryReadString(new_name, p->getSyscallArg(tc, index)))
return -EFAULT;
- // Adjust path for current working directory
- old_name = p->fullPath(old_name);
- new_name = p->fullPath(new_name);
+ // Adjust path for cwd and redirection
+ old_name = p->checkPathRedirect(old_name);
+ new_name = p->checkPathRedirect(new_name);
int64_t result = rename(old_name.c_str(), new_name.c_str());
return (result == -1) ? -errno : result;
@@ -588,8 +585,8 @@ truncateFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
off_t length = p->getSyscallArg(tc, index);
- // Adjust path for current working directory
- path = p->fullPath(path);
+ // Adjust path for cwd and redirection
+ path = p->checkPathRedirect(path);
int result = truncate(path.c_str(), length);
return (result == -1) ? -errno : result;
@@ -623,8 +620,8 @@ truncate64Func(SyscallDesc *desc, int num,
int64_t length = process->getSyscallArg(tc, index, 64);
- // Adjust path for current working directory
- path = process->fullPath(path);
+ // Adjust path for cwd and redirection
+ path = process->checkPathRedirect(path);
#if NO_STAT64
int result = truncate(path.c_str(), length);
@@ -680,8 +677,8 @@ chownFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
uint32_t group = p->getSyscallArg(tc, index);
gid_t hostGroup = group;
- // Adjust path for current working directory
- path = p->fullPath(path);
+ // Adjust path for cwd and redirection
+ path = p->checkPathRedirect(path);
int result = chown(path.c_str(), hostOwner, hostGroup);
return (result == -1) ? -errno : result;
@@ -1068,8 +1065,8 @@ accessFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc,
if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
return -EFAULT;
- // Adjust path for current working directory
- path = p->fullPath(path);
+ // Adjust path for cwd and redirection
+ path = p->checkPathRedirect(path);
mode_t mode = p->getSyscallArg(tc, index);
@@ -1091,7 +1088,7 @@ mknodFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
return -EFAULT;
- path = p->fullPath(path);
+ path = p->checkPathRedirect(path);
mode_t mode = p->getSyscallArg(tc, index);
dev_t dev = p->getSyscallArg(tc, index);
@@ -1107,10 +1104,23 @@ chdirFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
return -EFAULT;
- path = p->fullPath(path);
+ std::string tgt_cwd;
+ if (startswith(path, "/")) {
+ tgt_cwd = path;
+ } else {
+ char buf[PATH_MAX];
+ tgt_cwd = realpath((p->tgtCwd + "/" + path).c_str(), buf);
+ }
+ std::string host_cwd = p->checkPathRedirect(tgt_cwd);
- auto result = chdir(path.c_str());
- return (result == -1) ? -errno : result;
+ int result = chdir(host_cwd.c_str());
+
+ if (result == -1)
+ return -errno;
+
+ p->hostCwd = host_cwd;
+ p->tgtCwd = tgt_cwd;
+ return result;
}
SyscallReturn
@@ -1121,7 +1131,7 @@ rmdirFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
return -EFAULT;
- path = p->fullPath(path);
+ path = p->checkPathRedirect(path);
auto result = rmdir(path.c_str());
return (result == -1) ? -errno : result;
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index 87c16c489..1d14af921 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -837,14 +837,18 @@ openImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc,
* In every case, we should have a full path (which is relevant to the
* host) to work with after this block has been passed.
*/
- if (!isopenat || (isopenat && tgt_dirfd == OS::TGT_AT_FDCWD)) {
- path = p->fullPath(path);
+ std::string redir_path = path;
+ std::string abs_path = path;
+ if (!isopenat || tgt_dirfd == OS::TGT_AT_FDCWD) {
+ abs_path = p->absolutePath(path, true);
+ redir_path = p->checkPathRedirect(path);
} else if (!startswith(path, "/")) {
std::shared_ptr<FDEntry> fdep = ((*p->fds)[tgt_dirfd]);
auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(fdep);
if (!ffdp)
return -EBADF;
- path.insert(0, ffdp->getFileName() + "/");
+ abs_path = ffdp->getFileName() + path;
+ redir_path = p->checkPathRedirect(abs_path);
}
/**
@@ -853,13 +857,13 @@ openImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc,
* the process class through Python; this allows us to create a file
* descriptor for subsequent ioctl or mmap calls.
*/
- if (startswith(path, "/dev/")) {
- std::string filename = path.substr(strlen("/dev/"));
+ if (startswith(abs_path, "/dev/")) {
+ std::string filename = abs_path.substr(strlen("/dev/"));
EmulatedDriver *drv = p->findDriver(filename);
if (drv) {
DPRINTF_SYSCALL(Verbose, "open%s: passing call to "
"driver open with path[%s]\n",
- isopenat ? "at" : "", path.c_str());
+ isopenat ? "at" : "", abs_path.c_str());
return drv->open(p, tc, mode, host_flags);
}
/**
@@ -869,28 +873,49 @@ openImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc,
}
/**
- * Some special paths and files cannot be called on the host and need
- * to be handled as special cases inside the simulator.
- * If the full path that was created above does not match any of the
- * special cases, pass it through to the open call on the host to let
- * the host open the file on our behalf.
- * If the host cannot open the file, return the host's error code back
- * through the system call to the simulated process.
+ * We make several attempts resolve a call to open.
+ *
+ * 1) Resolve any path redirection before hand. This will set the path
+ * up with variable 'redir_path' which may contain a modified path or
+ * the original path value. This should already be done in prior code.
+ * 2) Try to handle the access using 'special_paths'. Some special_paths
+ * and files cannot be called on the host and need to be handled as
+ * special cases inside the simulator. These special_paths are handled by
+ * C++ routines to provide output back to userspace.
+ * 3) If the full path that was created above does not match any of the
+ * special cases, pass it through to the open call on the __HOST__ to let
+ * the host open the file on our behalf. Again, the openImpl tries to
+ * USE_THE_HOST_FILESYSTEM_OPEN (with a possible redirection to the
+ * faux-filesystem files). The faux-filesystem is dynamically created
+ * during simulator configuration using Python functions.
+ * 4) If the host cannot open the file, the open attempt failed in "3)".
+ * Return the host's error code back through the system call to the
+ * simulated process. If running a debug trace, also notify the user that
+ * the open call failed.
+ *
+ * Any success will set sim_fd to something other than -1 and skip the
+ * next conditions effectively bypassing them.
*/
int sim_fd = -1;
+ std::string used_path;
std::vector<std::string> special_paths =
- { "/proc/", "/system/", "/sys/", "/platform/", "/etc/passwd" };
+ { "/proc/meminfo/", "/system/", "/sys/", "/platform/",
+ "/etc/passwd" };
for (auto entry : special_paths) {
- if (startswith(path, entry))
- sim_fd = OS::openSpecialFile(path, p, tc);
+ if (startswith(path, entry)) {
+ sim_fd = OS::openSpecialFile(abs_path, p, tc);
+ used_path = abs_path;
+ }
}
if (sim_fd == -1) {
- sim_fd = open(path.c_str(), host_flags, mode);
+ sim_fd = open(redir_path.c_str(), host_flags, mode);
+ used_path = redir_path;
}
if (sim_fd == -1) {
int local = -errno;
- DPRINTF_SYSCALL(Verbose, "open%s: failed -> path:%s\n",
- isopenat ? "at" : "", path.c_str());
+ DPRINTF_SYSCALL(Verbose, "open%s: failed -> path:%s "
+ "(inferred from:%s)\n", isopenat ? "at" : "",
+ used_path.c_str(), path.c_str());
return local;
}
@@ -904,8 +929,9 @@ openImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc,
*/
auto ffdp = std::make_shared<FileFDEntry>(sim_fd, host_flags, path, 0);
int tgt_fd = p->fds->allocFD(ffdp);
- DPRINTF_SYSCALL(Verbose, "open%s: sim_fd[%d], target_fd[%d] -> path:%s\n",
- isopenat ? "at" : "", sim_fd, tgt_fd, path.c_str());
+ DPRINTF_SYSCALL(Verbose, "open%s: sim_fd[%d], target_fd[%d] -> path:%s\n"
+ "(inferred from:%s)\n", isopenat ? "at" : "",
+ sim_fd, tgt_fd, used_path.c_str(), path.c_str());
return tgt_fd;
}
@@ -995,9 +1021,9 @@ renameatFunc(SyscallDesc *desc, int callnum, Process *process,
process->getSyscallArg(tc, index)))
return -EFAULT;
- // Adjust path for current working directory
- old_name = process->fullPath(old_name);
- new_name = process->fullPath(new_name);
+ // Adjust path for cwd and redirection
+ old_name = process->checkPathRedirect(old_name);
+ new_name = process->checkPathRedirect(new_name);
int result = rename(old_name.c_str(), new_name.c_str());
return (result == -1) ? -errno : result;
@@ -1043,8 +1069,8 @@ chmodFunc(SyscallDesc *desc, int callnum, Process *process,
// XXX translate mode flags via OS::something???
hostMode = mode;
- // Adjust path for current working directory
- path = process->fullPath(path);
+ // Adjust path for cwd and redirection
+ path = process->checkPathRedirect(path);
// do the chmod
int result = chmod(path.c_str(), hostMode);
@@ -1244,8 +1270,8 @@ statFunc(SyscallDesc *desc, int callnum, Process *process,
}
Addr bufPtr = process->getSyscallArg(tc, index);
- // Adjust path for current working directory
- path = process->fullPath(path);
+ // Adjust path for cwd and redirection
+ path = process->checkPathRedirect(path);
struct stat hostBuf;
int result = stat(path.c_str(), &hostBuf);
@@ -1273,8 +1299,8 @@ stat64Func(SyscallDesc *desc, int callnum, Process *process,
return -EFAULT;
Addr bufPtr = process->getSyscallArg(tc, index);
- // Adjust path for current working directory
- path = process->fullPath(path);
+ // Adjust path for cwd and redirection
+ path = process->checkPathRedirect(path);
#if NO_STAT64
struct stat hostBuf;
@@ -1310,8 +1336,8 @@ fstatat64Func(SyscallDesc *desc, int callnum, Process *process,
return -EFAULT;
Addr bufPtr = process->getSyscallArg(tc, index);
- // Adjust path for current working directory
- path = process->fullPath(path);
+ // Adjust path for cwd and redirection
+ path = process->checkPathRedirect(path);
#if NO_STAT64
struct stat hostBuf;
@@ -1376,8 +1402,8 @@ lstatFunc(SyscallDesc *desc, int callnum, Process *process,
}
Addr bufPtr = process->getSyscallArg(tc, index);
- // Adjust path for current working directory
- path = process->fullPath(path);
+ // Adjust path for cwd and redirection
+ path = process->checkPathRedirect(path);
struct stat hostBuf;
int result = lstat(path.c_str(), &hostBuf);
@@ -1405,8 +1431,8 @@ lstat64Func(SyscallDesc *desc, int callnum, Process *process,
}
Addr bufPtr = process->getSyscallArg(tc, index);
- // Adjust path for current working directory
- path = process->fullPath(path);
+ // Adjust path for cwd and redirection
+ path = process->checkPathRedirect(path);
#if NO_STAT64
struct stat hostBuf;
@@ -1469,8 +1495,8 @@ statfsFunc(SyscallDesc *desc, int callnum, Process *process,
}
Addr bufPtr = process->getSyscallArg(tc, index);
- // Adjust path for current working directory
- path = process->fullPath(path);
+ // Adjust path for cwd and redirection
+ path = process->checkPathRedirect(path);
struct statfs hostBuf;
int result = statfs(path.c_str(), &hostBuf);
@@ -1531,7 +1557,7 @@ cloneFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
pp->executable.assign(*(new std::string(p->progName())));
pp->cmd.push_back(*(new std::string(p->progName())));
pp->system = p->system;
- pp->cwd.assign(p->getcwd());
+ pp->cwd.assign(p->tgtCwd);
pp->input.assign("stdin");
pp->output.assign("stdout");
pp->errout.assign("stderr");
@@ -2096,8 +2122,8 @@ utimesFunc(SyscallDesc *desc, int callnum, Process *process,
hostTimeval[i].tv_usec = TheISA::gtoh((*tp)[i].tv_usec);
}
- // Adjust path for current working directory
- path = process->fullPath(path);
+ // Adjust path for cwd and redirection
+ path = process->checkPathRedirect(path);
int result = utimes(path.c_str(), hostTimeval);
@@ -2159,7 +2185,7 @@ execveFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
pp->input.assign("cin");
pp->output.assign("cout");
pp->errout.assign("cerr");
- pp->cwd.assign(p->getcwd());
+ pp->cwd.assign(p->tgtCwd);
pp->system = p->system;
/**
* Prevent process object creation with identical PIDs (which will trip
diff --git a/src/sim/system.cc b/src/sim/system.cc
index 2113fc079..65ad6cdb0 100644
--- a/src/sim/system.cc
+++ b/src/sim/system.cc
@@ -70,6 +70,7 @@
#include "sim/byteswap.hh"
#include "sim/debug.hh"
#include "sim/full_system.hh"
+#include "sim/redirect_path.hh"
/**
* To avoid linking errors with LTO, only include the header if we
@@ -111,8 +112,10 @@ System::System(Params *p)
thermalModel(p->thermal_model),
_params(p),
totalNumInsts(0),
- instEventQueue("system instruction-based event queue")
+ instEventQueue("system instruction-based event queue"),
+ redirectPaths(p->redirect_paths)
{
+
// add self to global system list
systemList.push_back(this);
diff --git a/src/sim/system.hh b/src/sim/system.hh
index 69448d35f..6227ae660 100644
--- a/src/sim/system.hh
+++ b/src/sim/system.hh
@@ -64,6 +64,7 @@
#include "mem/port_proxy.hh"
#include "params/System.hh"
#include "sim/futex_map.hh"
+#include "sim/redirect_path.hh"
#include "sim/se_signal.hh"
/**
@@ -628,6 +629,11 @@ class System : public MemObject
// receiver will delete the signal upon reception.
std::list<BasicSignal> signalList;
+ // Used by syscall-emulation mode. This member contains paths which need
+ // to be redirected to the faux-filesystem (a duplicate filesystem
+ // intended to replace certain files on the host filesystem).
+ std::vector<RedirectPath*> redirectPaths;
+
protected:
/**
@@ -647,7 +653,6 @@ class System : public MemObject
* @param section relevant section in the checkpoint
*/
virtual void unserializeSymtab(CheckpointIn &cp) {}
-
};
void printSystems();