#include "cpu/thread_context.hh"
#include "debug/SyscallVerbose.hh"
#include "mem/page_table.hh"
-#include "mem/se_translating_port_proxy.hh"
#include "sim/byteswap.hh"
+#include "sim/emul_driver.hh"
#include "sim/process.hh"
+#include "sim/syscall_emul_buf.hh"
#include "sim/syscallreturn.hh"
#include "sim/system.hh"
};
-class BaseBufferArg {
-
- public:
-
- BaseBufferArg(Addr _addr, int _size) : addr(_addr), size(_size)
- {
- bufPtr = new uint8_t[size];
- // clear out buffer: in case we only partially populate this,
- // and then do a copyOut(), we want to make sure we don't
- // introduce any random junk into the simulated address space
- memset(bufPtr, 0, size);
- }
-
- virtual ~BaseBufferArg() { delete [] bufPtr; }
-
- //
- // copy data into simulator space (read from target memory)
- //
- virtual bool copyIn(SETranslatingPortProxy &memproxy)
- {
- memproxy.readBlob(addr, bufPtr, size);
- return true; // no EFAULT detection for now
- }
-
- //
- // copy data out of simulator space (write to target memory)
- //
- virtual bool copyOut(SETranslatingPortProxy &memproxy)
- {
- memproxy.writeBlob(addr, bufPtr, size);
- return true; // no EFAULT detection for now
- }
-
- protected:
- Addr addr;
- int size;
- uint8_t *bufPtr;
-};
-
-
-class BufferArg : public BaseBufferArg
-{
- public:
- BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { }
- void *bufferPtr() { return bufPtr; }
-};
-
-template <class T>
-class TypedBufferArg : public BaseBufferArg
-{
- public:
- // user can optionally specify a specific number of bytes to
- // allocate to deal with those structs that have variable-size
- // arrays at the end
- TypedBufferArg(Addr _addr, int _size = sizeof(T))
- : BaseBufferArg(_addr, _size)
- { }
-
- // type case
- operator T*() { return (T *)bufPtr; }
-
- // dereference operators
- T &operator*() { return *((T *)bufPtr); }
- T* operator->() { return (T *)bufPtr; }
- T &operator[](int i) { return ((T *)bufPtr)[i]; }
-};
-
//////////////////////////////////////////////////////////////////////
//
// The following emulation functions are generic enough that they
LiveProcess *p, ThreadContext *tc);
/// Target unlink() handler.
+SyscallReturn unlinkHelper(SyscallDesc *desc, int num,
+ LiveProcess *p, ThreadContext *tc,
+ int index);
SyscallReturn unlinkFunc(SyscallDesc *desc, int num,
LiveProcess *p, ThreadContext *tc);
DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
- if (fd < 0 || process->sim_fd(fd) < 0) {
+ Process::FdMap *fdObj = process->sim_fd_obj(fd);
+
+ if (fdObj == NULL) {
// doesn't map to any simulator fd: not a valid target fd
return -EBADF;
}
+ if (fdObj->driver != NULL) {
+ return fdObj->driver->ioctl(process, tc, req);
+ }
+
if (OS::isTtyReq(req)) {
return -ENOTTY;
}
process->getSyscallArg(tc, index)))
return -EFAULT;
- if (path == "/dev/sysdev0") {
- // This is a memory-mapped high-resolution timer device on Alpha.
- // We don't support it, so just punt.
- warn("Ignoring open(%s, ...)\n", path);
- return -ENOENT;
- }
-
int tgtFlags = process->getSyscallArg(tc, index);
int mode = process->getSyscallArg(tc, index);
int hostFlags = 0;
DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str());
+ if (startswith(path, "/dev/")) {
+ std::string filename = path.substr(strlen("/dev/"));
+ if (filename == "sysdev0") {
+ // This is a memory-mapped high-resolution timer device on Alpha.
+ // We don't support it, so just punt.
+ warn("Ignoring open(%s, ...)\n", path);
+ return -ENOENT;
+ }
+
+ EmulatedDriver *drv = process->findDriver(filename);
+ if (drv != NULL) {
+ // the driver's open method will allocate a fd from the
+ // process if necessary.
+ return drv->open(process, tc, mode, hostFlags);
+ }
+
+ // fall through here for pass through to host devices, such as
+ // /dev/zero
+ }
+
int fd;
int local_errno;
if (startswith(path, "/proc/") || startswith(path, "/system/") ||
return openFunc<OS>(desc, callnum, process, tc, 1);
}
+/// Target unlinkat() handler.
+template <class OS>
+SyscallReturn
+unlinkatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+ ThreadContext *tc)
+{
+ int index = 0;
+ int dirfd = process->getSyscallArg(tc, index);
+ if (dirfd != OS::TGT_AT_FDCWD)
+ warn("unlinkat: first argument not AT_FDCWD; unlikely to work");
+
+ return unlinkHelper(desc, callnum, process, tc, 1);
+}
+
/// Target facessat() handler
template <class OS>
SyscallReturn
if (result < 0)
return -errno;
- return 0;
+ return result;
}