syscall_emul.hh revision 11383
19651SAndreas.Sandberg@ARM.com/* 29651SAndreas.Sandberg@ARM.com * Copyright (c) 2012-2013, 2015 ARM Limited 39651SAndreas.Sandberg@ARM.com * Copyright (c) 2015 Advanced Micro Devices, Inc. 49651SAndreas.Sandberg@ARM.com * All rights reserved 59651SAndreas.Sandberg@ARM.com * 69651SAndreas.Sandberg@ARM.com * The license below extends only to copyright in the software and shall 79651SAndreas.Sandberg@ARM.com * not be construed as granting a license to any other intellectual 89651SAndreas.Sandberg@ARM.com * property including but not limited to intellectual property relating 99651SAndreas.Sandberg@ARM.com * to a hardware implementation of the functionality of the software 109651SAndreas.Sandberg@ARM.com * licensed hereunder. You may use the software subject to the license 119651SAndreas.Sandberg@ARM.com * terms below provided that you ensure that this notice is replicated 129651SAndreas.Sandberg@ARM.com * unmodified and in its entirety in all distributions of the software, 139651SAndreas.Sandberg@ARM.com * modified or unmodified, in source code or in binary form. 149651SAndreas.Sandberg@ARM.com * 159651SAndreas.Sandberg@ARM.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 169651SAndreas.Sandberg@ARM.com * All rights reserved. 179651SAndreas.Sandberg@ARM.com * 189651SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without 199651SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are 209651SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright 219651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer; 229651SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright 239651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the 249651SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution; 259651SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its 269651SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from 279651SAndreas.Sandberg@ARM.com * this software without specific prior written permission. 289651SAndreas.Sandberg@ARM.com * 299651SAndreas.Sandberg@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 309651SAndreas.Sandberg@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 319651SAndreas.Sandberg@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 329651SAndreas.Sandberg@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 339651SAndreas.Sandberg@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 349651SAndreas.Sandberg@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 359651SAndreas.Sandberg@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 369651SAndreas.Sandberg@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 379651SAndreas.Sandberg@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 389651SAndreas.Sandberg@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 399651SAndreas.Sandberg@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 409651SAndreas.Sandberg@ARM.com * 419651SAndreas.Sandberg@ARM.com * Authors: Steve Reinhardt 429651SAndreas.Sandberg@ARM.com * Kevin Lim 439651SAndreas.Sandberg@ARM.com */ 449651SAndreas.Sandberg@ARM.com 459651SAndreas.Sandberg@ARM.com#ifndef __SIM_SYSCALL_EMUL_HH__ 469651SAndreas.Sandberg@ARM.com#define __SIM_SYSCALL_EMUL_HH__ 479651SAndreas.Sandberg@ARM.com 489651SAndreas.Sandberg@ARM.com#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \ 499760Sandreas@sandberg.pp.se defined(__FreeBSD__) || defined(__CYGWIN__) || \ 509651SAndreas.Sandberg@ARM.com defined(__NetBSD__)) 519651SAndreas.Sandberg@ARM.com 529683Sandreas@sandberg.pp.se/// 539753Sandreas@sandberg.pp.se/// @file syscall_emul.hh 549651SAndreas.Sandberg@ARM.com/// 559651SAndreas.Sandberg@ARM.com/// This file defines objects used to emulate syscalls from the target 569651SAndreas.Sandberg@ARM.com/// application on the host machine. 579651SAndreas.Sandberg@ARM.com 589651SAndreas.Sandberg@ARM.com#ifdef __CYGWIN32__ 599651SAndreas.Sandberg@ARM.com#include <sys/fcntl.h> // for O_BINARY 609651SAndreas.Sandberg@ARM.com#endif 619753Sandreas@sandberg.pp.se#include <sys/mman.h> 629753Sandreas@sandberg.pp.se#include <sys/stat.h> 639651SAndreas.Sandberg@ARM.com#include <sys/time.h> 649651SAndreas.Sandberg@ARM.com#include <sys/uio.h> 659651SAndreas.Sandberg@ARM.com#include <fcntl.h> 669651SAndreas.Sandberg@ARM.com 679651SAndreas.Sandberg@ARM.com#include <cerrno> 689651SAndreas.Sandberg@ARM.com#include <string> 699651SAndreas.Sandberg@ARM.com 709651SAndreas.Sandberg@ARM.com#include "base/chunk_generator.hh" 719651SAndreas.Sandberg@ARM.com#include "base/intmath.hh" // for RoundUp 729651SAndreas.Sandberg@ARM.com#include "base/misc.hh" 739651SAndreas.Sandberg@ARM.com#include "base/trace.hh" 749651SAndreas.Sandberg@ARM.com#include "base/types.hh" 759651SAndreas.Sandberg@ARM.com#include "config/the_isa.hh" 769651SAndreas.Sandberg@ARM.com#include "cpu/base.hh" 779651SAndreas.Sandberg@ARM.com#include "cpu/thread_context.hh" 789651SAndreas.Sandberg@ARM.com#include "debug/SyscallBase.hh" 799651SAndreas.Sandberg@ARM.com#include "debug/SyscallVerbose.hh" 809652SAndreas.Sandberg@ARM.com#include "mem/page_table.hh" 819652SAndreas.Sandberg@ARM.com#include "sim/byteswap.hh" 829651SAndreas.Sandberg@ARM.com#include "sim/emul_driver.hh" 839651SAndreas.Sandberg@ARM.com#include "sim/process.hh" 849651SAndreas.Sandberg@ARM.com#include "sim/syscall_emul_buf.hh" 859651SAndreas.Sandberg@ARM.com#include "sim/syscallreturn.hh" 869655SAndreas.Sandberg@ARM.com#include "sim/system.hh" 879754Sandreas@sandberg.pp.se 889752Sandreas@sandberg.pp.se// This wrapper macro helps out with readability a bit. FLAGEXT specifies 899753Sandreas@sandberg.pp.se// the verbosity and FMT is the message to be appended to the syscall 909752Sandreas@sandberg.pp.se// header information. The syscall header information contains the cpuid 919651SAndreas.Sandberg@ARM.com// and thread id. 929651SAndreas.Sandberg@ARM.com#define DPRINTF_SYSCALL(FLAGEXT, FMT, ...) \ 939651SAndreas.Sandberg@ARM.com DPRINTFS(Syscall##FLAGEXT, tc->getCpuPtr(), "T%d : syscall " FMT, \ 949651SAndreas.Sandberg@ARM.com tc->threadId(), __VA_ARGS__) 959651SAndreas.Sandberg@ARM.com 969651SAndreas.Sandberg@ARM.com/// 979651SAndreas.Sandberg@ARM.com/// System call descriptor. 989651SAndreas.Sandberg@ARM.com/// 999651SAndreas.Sandberg@ARM.comclass SyscallDesc { 1009651SAndreas.Sandberg@ARM.com 1019651SAndreas.Sandberg@ARM.com public: 1029651SAndreas.Sandberg@ARM.com 1039651SAndreas.Sandberg@ARM.com /// Typedef for target syscall handler functions. 1049655SAndreas.Sandberg@ARM.com typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num, 1059655SAndreas.Sandberg@ARM.com LiveProcess *, ThreadContext *); 1069655SAndreas.Sandberg@ARM.com 1079655SAndreas.Sandberg@ARM.com const char *name; //!< Syscall name (e.g., "open"). 1089754Sandreas@sandberg.pp.se FuncPtr funcPtr; //!< Pointer to emulation function. 1099655SAndreas.Sandberg@ARM.com int flags; //!< Flags (see Flags enum). 1109655SAndreas.Sandberg@ARM.com bool warned; //!< Have we warned about unimplemented syscall? 1119655SAndreas.Sandberg@ARM.com 1129754Sandreas@sandberg.pp.se /// Flag values for controlling syscall behavior. 1139651SAndreas.Sandberg@ARM.com enum Flags { 1149651SAndreas.Sandberg@ARM.com /// Don't set return regs according to funcPtr return value. 1159651SAndreas.Sandberg@ARM.com /// Used for syscalls with non-standard return conventions 1169651SAndreas.Sandberg@ARM.com /// that explicitly set the ThreadContext regs (e.g., 1179651SAndreas.Sandberg@ARM.com /// sigreturn). 1189651SAndreas.Sandberg@ARM.com SuppressReturnValue = 1, 1199651SAndreas.Sandberg@ARM.com WarnOnce = 2 1209651SAndreas.Sandberg@ARM.com }; 1219651SAndreas.Sandberg@ARM.com 1229651SAndreas.Sandberg@ARM.com /// Constructor. 1239651SAndreas.Sandberg@ARM.com SyscallDesc(const char *_name, FuncPtr _funcPtr, int _flags = 0) 1249651SAndreas.Sandberg@ARM.com : name(_name), funcPtr(_funcPtr), flags(_flags), warned(false) 1259651SAndreas.Sandberg@ARM.com { 1269651SAndreas.Sandberg@ARM.com } 1279651SAndreas.Sandberg@ARM.com 1289651SAndreas.Sandberg@ARM.com /// Emulate the syscall. Public interface for calling through funcPtr. 1299651SAndreas.Sandberg@ARM.com void doSyscall(int callnum, LiveProcess *proc, ThreadContext *tc); 1309651SAndreas.Sandberg@ARM.com 1319651SAndreas.Sandberg@ARM.com /// Is the WarnOnce flag set? 1329651SAndreas.Sandberg@ARM.com bool warnOnce() const { return (flags & WarnOnce); } 1339651SAndreas.Sandberg@ARM.com}; 1349651SAndreas.Sandberg@ARM.com 1359651SAndreas.Sandberg@ARM.com 1369651SAndreas.Sandberg@ARM.com////////////////////////////////////////////////////////////////////// 1379651SAndreas.Sandberg@ARM.com// 1389651SAndreas.Sandberg@ARM.com// The following emulation functions are generic enough that they 1399651SAndreas.Sandberg@ARM.com// don't need to be recompiled for different emulated OS's. They are 1409651SAndreas.Sandberg@ARM.com// defined in sim/syscall_emul.cc. 1419651SAndreas.Sandberg@ARM.com// 1429690Sandreas@sandberg.pp.se////////////////////////////////////////////////////////////////////// 1439690Sandreas@sandberg.pp.se 1449690Sandreas@sandberg.pp.se 1459651SAndreas.Sandberg@ARM.com/// Handler for unimplemented syscalls that we haven't thought about. 1469651SAndreas.Sandberg@ARM.comSyscallReturn unimplementedFunc(SyscallDesc *desc, int num, 1479651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 1489651SAndreas.Sandberg@ARM.com 1499651SAndreas.Sandberg@ARM.com/// Handler for unimplemented syscalls that we never intend to 1509651SAndreas.Sandberg@ARM.com/// implement (signal handling, etc.) and should not affect the correct 1519651SAndreas.Sandberg@ARM.com/// behavior of the program. Print a warning only if the appropriate 1529651SAndreas.Sandberg@ARM.com/// trace flag is enabled. Return success to the target program. 1539651SAndreas.Sandberg@ARM.comSyscallReturn ignoreFunc(SyscallDesc *desc, int num, 1549651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 1559651SAndreas.Sandberg@ARM.com 1569651SAndreas.Sandberg@ARM.com/// Target exit() handler: terminate current context. 1579651SAndreas.Sandberg@ARM.comSyscallReturn exitFunc(SyscallDesc *desc, int num, 1589651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 1599753Sandreas@sandberg.pp.se 1609753Sandreas@sandberg.pp.se/// Target exit_group() handler: terminate simulation. (exit all threads) 1619753Sandreas@sandberg.pp.seSyscallReturn exitGroupFunc(SyscallDesc *desc, int num, 1629753Sandreas@sandberg.pp.se LiveProcess *p, ThreadContext *tc); 1639651SAndreas.Sandberg@ARM.com 1649651SAndreas.Sandberg@ARM.com/// Target getpagesize() handler. 1659651SAndreas.Sandberg@ARM.comSyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, 1669651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 1679651SAndreas.Sandberg@ARM.com 1689651SAndreas.Sandberg@ARM.com/// Target brk() handler: set brk address. 1699651SAndreas.Sandberg@ARM.comSyscallReturn brkFunc(SyscallDesc *desc, int num, 1709651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 1719651SAndreas.Sandberg@ARM.com 1729651SAndreas.Sandberg@ARM.com/// Target close() handler. 1739651SAndreas.Sandberg@ARM.comSyscallReturn closeFunc(SyscallDesc *desc, int num, 1749651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 1759690Sandreas@sandberg.pp.se 1769690Sandreas@sandberg.pp.se/// Target read() handler. 1779690Sandreas@sandberg.pp.seSyscallReturn readFunc(SyscallDesc *desc, int num, 1789651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 1799651SAndreas.Sandberg@ARM.com 1809651SAndreas.Sandberg@ARM.com/// Target write() handler. 1819651SAndreas.Sandberg@ARM.comSyscallReturn writeFunc(SyscallDesc *desc, int num, 1829651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 1839651SAndreas.Sandberg@ARM.com 1849732Sandreas@sandberg.pp.se/// Target lseek() handler. 1859732Sandreas@sandberg.pp.seSyscallReturn lseekFunc(SyscallDesc *desc, int num, 1869651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 1879651SAndreas.Sandberg@ARM.com 1889651SAndreas.Sandberg@ARM.com/// Target _llseek() handler. 1899651SAndreas.Sandberg@ARM.comSyscallReturn _llseekFunc(SyscallDesc *desc, int num, 1909651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 1919651SAndreas.Sandberg@ARM.com 1929651SAndreas.Sandberg@ARM.com/// Target munmap() handler. 1939651SAndreas.Sandberg@ARM.comSyscallReturn munmapFunc(SyscallDesc *desc, int num, 1949651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 1959684Sandreas@sandberg.pp.se 1969684Sandreas@sandberg.pp.se/// Target gethostname() handler. 1979684Sandreas@sandberg.pp.seSyscallReturn gethostnameFunc(SyscallDesc *desc, int num, 1989684Sandreas@sandberg.pp.se LiveProcess *p, ThreadContext *tc); 1999684Sandreas@sandberg.pp.se 2009651SAndreas.Sandberg@ARM.com/// Target getcwd() handler. 2019651SAndreas.Sandberg@ARM.comSyscallReturn getcwdFunc(SyscallDesc *desc, int num, 2029651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 2039651SAndreas.Sandberg@ARM.com 2049651SAndreas.Sandberg@ARM.com/// Target readlink() handler. 2059755Sandreas@sandberg.pp.seSyscallReturn readlinkFunc(SyscallDesc *desc, int num, 2069755Sandreas@sandberg.pp.se LiveProcess *p, ThreadContext *tc, 2079755Sandreas@sandberg.pp.se int index = 0); 2089755Sandreas@sandberg.pp.seSyscallReturn readlinkFunc(SyscallDesc *desc, int num, 2099755Sandreas@sandberg.pp.se LiveProcess *p, ThreadContext *tc); 2109755Sandreas@sandberg.pp.se 2119755Sandreas@sandberg.pp.se/// Target unlink() handler. 2129755Sandreas@sandberg.pp.seSyscallReturn unlinkHelper(SyscallDesc *desc, int num, 2139755Sandreas@sandberg.pp.se LiveProcess *p, ThreadContext *tc, 2149755Sandreas@sandberg.pp.se int index); 2159651SAndreas.Sandberg@ARM.comSyscallReturn unlinkFunc(SyscallDesc *desc, int num, 2169651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 2179651SAndreas.Sandberg@ARM.com 2189651SAndreas.Sandberg@ARM.com/// Target mkdir() handler. 2199651SAndreas.Sandberg@ARM.comSyscallReturn mkdirFunc(SyscallDesc *desc, int num, 2209651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 2219651SAndreas.Sandberg@ARM.com 2229651SAndreas.Sandberg@ARM.com/// Target rename() handler. 2239651SAndreas.Sandberg@ARM.comSyscallReturn renameFunc(SyscallDesc *desc, int num, 2249651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 2259651SAndreas.Sandberg@ARM.com 2269651SAndreas.Sandberg@ARM.com 2279651SAndreas.Sandberg@ARM.com/// Target truncate() handler. 2289651SAndreas.Sandberg@ARM.comSyscallReturn truncateFunc(SyscallDesc *desc, int num, 2299651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 2309651SAndreas.Sandberg@ARM.com 2319651SAndreas.Sandberg@ARM.com 2329651SAndreas.Sandberg@ARM.com/// Target ftruncate() handler. 2339651SAndreas.Sandberg@ARM.comSyscallReturn ftruncateFunc(SyscallDesc *desc, int num, 2349651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 2359651SAndreas.Sandberg@ARM.com 2369651SAndreas.Sandberg@ARM.com 2379651SAndreas.Sandberg@ARM.com/// Target truncate64() handler. 2389651SAndreas.Sandberg@ARM.comSyscallReturn truncate64Func(SyscallDesc *desc, int num, 2399651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 2409651SAndreas.Sandberg@ARM.com 2419651SAndreas.Sandberg@ARM.com/// Target ftruncate64() handler. 2429651SAndreas.Sandberg@ARM.comSyscallReturn ftruncate64Func(SyscallDesc *desc, int num, 2439651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 2449651SAndreas.Sandberg@ARM.com 2459651SAndreas.Sandberg@ARM.com 2469651SAndreas.Sandberg@ARM.com/// Target umask() handler. 2479651SAndreas.Sandberg@ARM.comSyscallReturn umaskFunc(SyscallDesc *desc, int num, 2489651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 2499683Sandreas@sandberg.pp.se 2509683Sandreas@sandberg.pp.se 2519683Sandreas@sandberg.pp.se/// Target chown() handler. 2529683Sandreas@sandberg.pp.seSyscallReturn chownFunc(SyscallDesc *desc, int num, 2539683Sandreas@sandberg.pp.se LiveProcess *p, ThreadContext *tc); 2549651SAndreas.Sandberg@ARM.com 2559651SAndreas.Sandberg@ARM.com 2569651SAndreas.Sandberg@ARM.com/// Target fchown() handler. 2579651SAndreas.Sandberg@ARM.comSyscallReturn fchownFunc(SyscallDesc *desc, int num, 2589651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 2599651SAndreas.Sandberg@ARM.com 2609651SAndreas.Sandberg@ARM.com/// Target dup() handler. 2619651SAndreas.Sandberg@ARM.comSyscallReturn dupFunc(SyscallDesc *desc, int num, 2629651SAndreas.Sandberg@ARM.com LiveProcess *process, ThreadContext *tc); 2639683Sandreas@sandberg.pp.se 2649683Sandreas@sandberg.pp.se/// Target fnctl() handler. 2659651SAndreas.Sandberg@ARM.comSyscallReturn fcntlFunc(SyscallDesc *desc, int num, 2669651SAndreas.Sandberg@ARM.com LiveProcess *process, ThreadContext *tc); 2679651SAndreas.Sandberg@ARM.com 2689652SAndreas.Sandberg@ARM.com/// Target fcntl64() handler. 2699651SAndreas.Sandberg@ARM.comSyscallReturn fcntl64Func(SyscallDesc *desc, int num, 2709651SAndreas.Sandberg@ARM.com LiveProcess *process, ThreadContext *tc); 2719651SAndreas.Sandberg@ARM.com 2729651SAndreas.Sandberg@ARM.com/// Target setuid() handler. 2739651SAndreas.Sandberg@ARM.comSyscallReturn setuidFunc(SyscallDesc *desc, int num, 2749651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 2759651SAndreas.Sandberg@ARM.com 2769651SAndreas.Sandberg@ARM.com/// Target getpid() handler. 2779753Sandreas@sandberg.pp.seSyscallReturn getpidFunc(SyscallDesc *desc, int num, 2789753Sandreas@sandberg.pp.se LiveProcess *p, ThreadContext *tc); 2799753Sandreas@sandberg.pp.se 2809753Sandreas@sandberg.pp.se/// Target getuid() handler. 2819753Sandreas@sandberg.pp.seSyscallReturn getuidFunc(SyscallDesc *desc, int num, 2829753Sandreas@sandberg.pp.se LiveProcess *p, ThreadContext *tc); 2839753Sandreas@sandberg.pp.se 2849753Sandreas@sandberg.pp.se/// Target getgid() handler. 2859753Sandreas@sandberg.pp.seSyscallReturn getgidFunc(SyscallDesc *desc, int num, 2869753Sandreas@sandberg.pp.se LiveProcess *p, ThreadContext *tc); 2879753Sandreas@sandberg.pp.se 2889753Sandreas@sandberg.pp.se/// Target getppid() handler. 2899651SAndreas.Sandberg@ARM.comSyscallReturn getppidFunc(SyscallDesc *desc, int num, 2909753Sandreas@sandberg.pp.se LiveProcess *p, ThreadContext *tc); 2919753Sandreas@sandberg.pp.se 2929753Sandreas@sandberg.pp.se/// Target geteuid() handler. 2939753Sandreas@sandberg.pp.seSyscallReturn geteuidFunc(SyscallDesc *desc, int num, 2949753Sandreas@sandberg.pp.se LiveProcess *p, ThreadContext *tc); 2959753Sandreas@sandberg.pp.se 2969753Sandreas@sandberg.pp.se/// Target getegid() handler. 2979651SAndreas.Sandberg@ARM.comSyscallReturn getegidFunc(SyscallDesc *desc, int num, 2989753Sandreas@sandberg.pp.se LiveProcess *p, ThreadContext *tc); 2999753Sandreas@sandberg.pp.se 3009753Sandreas@sandberg.pp.se/// Target clone() handler. 3019753Sandreas@sandberg.pp.seSyscallReturn cloneFunc(SyscallDesc *desc, int num, 3029753Sandreas@sandberg.pp.se LiveProcess *p, ThreadContext *tc); 3039753Sandreas@sandberg.pp.se 3049753Sandreas@sandberg.pp.se/// Target access() handler 3059753Sandreas@sandberg.pp.seSyscallReturn accessFunc(SyscallDesc *desc, int num, 3069753Sandreas@sandberg.pp.se LiveProcess *p, ThreadContext *tc); 3079753Sandreas@sandberg.pp.seSyscallReturn accessFunc(SyscallDesc *desc, int num, 3089753Sandreas@sandberg.pp.se LiveProcess *p, ThreadContext *tc, 3099753Sandreas@sandberg.pp.se int index); 3109753Sandreas@sandberg.pp.se 3119753Sandreas@sandberg.pp.se/// Futex system call 3129753Sandreas@sandberg.pp.se/// Implemented by Daniel Sanchez 3139753Sandreas@sandberg.pp.se/// Used by printf's in multi-threaded apps 3149753Sandreas@sandberg.pp.setemplate <class OS> 3159753Sandreas@sandberg.pp.seSyscallReturn 3169753Sandreas@sandberg.pp.sefutexFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 3179753Sandreas@sandberg.pp.se ThreadContext *tc) 3189753Sandreas@sandberg.pp.se{ 3199753Sandreas@sandberg.pp.se int index_uaddr = 0; 3209753Sandreas@sandberg.pp.se int index_op = 1; 3219753Sandreas@sandberg.pp.se int index_val = 2; 3229753Sandreas@sandberg.pp.se int index_timeout = 3; 3239753Sandreas@sandberg.pp.se 3249753Sandreas@sandberg.pp.se uint64_t uaddr = process->getSyscallArg(tc, index_uaddr); 3259753Sandreas@sandberg.pp.se int op = process->getSyscallArg(tc, index_op); 3269753Sandreas@sandberg.pp.se int val = process->getSyscallArg(tc, index_val); 3279753Sandreas@sandberg.pp.se uint64_t timeout = process->getSyscallArg(tc, index_timeout); 3289753Sandreas@sandberg.pp.se 3299753Sandreas@sandberg.pp.se std::map<uint64_t, std::list<ThreadContext *> * > 3309753Sandreas@sandberg.pp.se &futex_map = tc->getSystemPtr()->futexMap; 3319753Sandreas@sandberg.pp.se 3329753Sandreas@sandberg.pp.se DPRINTF(SyscallVerbose, "In sys_futex: Address=%llx, op=%d, val=%d\n", 3339651SAndreas.Sandberg@ARM.com uaddr, op, val); 3349651SAndreas.Sandberg@ARM.com 3359651SAndreas.Sandberg@ARM.com op &= ~OS::TGT_FUTEX_PRIVATE_FLAG; 3369651SAndreas.Sandberg@ARM.com 3379651SAndreas.Sandberg@ARM.com if (op == OS::TGT_FUTEX_WAIT) { 3389651SAndreas.Sandberg@ARM.com if (timeout != 0) { 3399651SAndreas.Sandberg@ARM.com warn("sys_futex: FUTEX_WAIT with non-null timeout unimplemented;" 3409651SAndreas.Sandberg@ARM.com "we'll wait indefinitely"); 3419651SAndreas.Sandberg@ARM.com } 3429651SAndreas.Sandberg@ARM.com 3439651SAndreas.Sandberg@ARM.com uint8_t *buf = new uint8_t[sizeof(int)]; 3449651SAndreas.Sandberg@ARM.com tc->getMemProxy().readBlob((Addr)uaddr, buf, (int)sizeof(int)); 3459651SAndreas.Sandberg@ARM.com int mem_val = *((int *)buf); 3469651SAndreas.Sandberg@ARM.com delete[] buf; 3479651SAndreas.Sandberg@ARM.com 3489651SAndreas.Sandberg@ARM.com if (val != mem_val) { 3499651SAndreas.Sandberg@ARM.com DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, read: %d, " 3509651SAndreas.Sandberg@ARM.com "expected: %d\n", mem_val, val); 3519651SAndreas.Sandberg@ARM.com return -OS::TGT_EWOULDBLOCK; 3529651SAndreas.Sandberg@ARM.com } 3539651SAndreas.Sandberg@ARM.com 3549651SAndreas.Sandberg@ARM.com // Queue the thread context 3559651SAndreas.Sandberg@ARM.com std::list<ThreadContext *> * tcWaitList; 3569651SAndreas.Sandberg@ARM.com if (futex_map.count(uaddr)) { 3579651SAndreas.Sandberg@ARM.com tcWaitList = futex_map.find(uaddr)->second; 3589651SAndreas.Sandberg@ARM.com } else { 3599651SAndreas.Sandberg@ARM.com tcWaitList = new std::list<ThreadContext *>(); 3609651SAndreas.Sandberg@ARM.com futex_map.insert(std::pair< uint64_t, 3619652SAndreas.Sandberg@ARM.com std::list<ThreadContext *> * >(uaddr, tcWaitList)); 3629652SAndreas.Sandberg@ARM.com } 3639651SAndreas.Sandberg@ARM.com tcWaitList->push_back(tc); 3649651SAndreas.Sandberg@ARM.com DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAIT, suspending calling " 3659651SAndreas.Sandberg@ARM.com "thread context\n"); 3669651SAndreas.Sandberg@ARM.com tc->suspend(); 3679651SAndreas.Sandberg@ARM.com return 0; 3689651SAndreas.Sandberg@ARM.com } else if (op == OS::TGT_FUTEX_WAKE){ 3699651SAndreas.Sandberg@ARM.com int wokenUp = 0; 3709651SAndreas.Sandberg@ARM.com std::list<ThreadContext *> * tcWaitList; 3719651SAndreas.Sandberg@ARM.com if (futex_map.count(uaddr)) { 3729651SAndreas.Sandberg@ARM.com tcWaitList = futex_map.find(uaddr)->second; 3739651SAndreas.Sandberg@ARM.com while (tcWaitList->size() > 0 && wokenUp < val) { 3749651SAndreas.Sandberg@ARM.com tcWaitList->front()->activate(); 3759651SAndreas.Sandberg@ARM.com tcWaitList->pop_front(); 3769651SAndreas.Sandberg@ARM.com wokenUp++; 3779651SAndreas.Sandberg@ARM.com } 3789651SAndreas.Sandberg@ARM.com if (tcWaitList->empty()) { 3799651SAndreas.Sandberg@ARM.com futex_map.erase(uaddr); 3809651SAndreas.Sandberg@ARM.com delete tcWaitList; 3819651SAndreas.Sandberg@ARM.com } 3829651SAndreas.Sandberg@ARM.com } 3839651SAndreas.Sandberg@ARM.com DPRINTF(SyscallVerbose, "sys_futex: FUTEX_WAKE, activated %d waiting " 3849651SAndreas.Sandberg@ARM.com "thread contexts\n", wokenUp); 3859651SAndreas.Sandberg@ARM.com return wokenUp; 3869753Sandreas@sandberg.pp.se } else { 3879753Sandreas@sandberg.pp.se warn("sys_futex: op %d is not implemented, just returning...", op); 3889753Sandreas@sandberg.pp.se return 0; 3899753Sandreas@sandberg.pp.se } 3909753Sandreas@sandberg.pp.se 3919753Sandreas@sandberg.pp.se} 3929651SAndreas.Sandberg@ARM.com 3939651SAndreas.Sandberg@ARM.com 3949651SAndreas.Sandberg@ARM.com/// Pseudo Funcs - These functions use a different return convension, 3959651SAndreas.Sandberg@ARM.com/// returning a second value in a register other than the normal return register 3969651SAndreas.Sandberg@ARM.comSyscallReturn pipePseudoFunc(SyscallDesc *desc, int num, 3979651SAndreas.Sandberg@ARM.com LiveProcess *process, ThreadContext *tc); 3989651SAndreas.Sandberg@ARM.com 3999651SAndreas.Sandberg@ARM.com/// Target getpidPseudo() handler. 4009651SAndreas.Sandberg@ARM.comSyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num, 4019651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 4029651SAndreas.Sandberg@ARM.com 4039651SAndreas.Sandberg@ARM.com/// Target getuidPseudo() handler. 4049651SAndreas.Sandberg@ARM.comSyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num, 4059651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 4069651SAndreas.Sandberg@ARM.com 4079651SAndreas.Sandberg@ARM.com/// Target getgidPseudo() handler. 4089651SAndreas.Sandberg@ARM.comSyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num, 4099651SAndreas.Sandberg@ARM.com LiveProcess *p, ThreadContext *tc); 4109651SAndreas.Sandberg@ARM.com 4119651SAndreas.Sandberg@ARM.com 4129651SAndreas.Sandberg@ARM.com/// A readable name for 1,000,000, for converting microseconds to seconds. 4139651SAndreas.Sandberg@ARM.comconst int one_million = 1000000; 4149651SAndreas.Sandberg@ARM.com/// A readable name for 1,000,000,000, for converting nanoseconds to seconds. 4159651SAndreas.Sandberg@ARM.comconst int one_billion = 1000000000; 4169651SAndreas.Sandberg@ARM.com 4179651SAndreas.Sandberg@ARM.com/// Approximate seconds since the epoch (1/1/1970). About a billion, 4189651SAndreas.Sandberg@ARM.com/// by my reckoning. We want to keep this a constant (not use the 4199651SAndreas.Sandberg@ARM.com/// real-world time) to keep simulations repeatable. 4209651SAndreas.Sandberg@ARM.comconst unsigned seconds_since_epoch = 1000000000; 4219651SAndreas.Sandberg@ARM.com 4229651SAndreas.Sandberg@ARM.com/// Helper function to convert current elapsed time to seconds and 4239651SAndreas.Sandberg@ARM.com/// microseconds. 4249651SAndreas.Sandberg@ARM.comtemplate <class T1, class T2> 4259754Sandreas@sandberg.pp.sevoid 4269651SAndreas.Sandberg@ARM.comgetElapsedTimeMicro(T1 &sec, T2 &usec) 4279651SAndreas.Sandberg@ARM.com{ 4289651SAndreas.Sandberg@ARM.com uint64_t elapsed_usecs = curTick() / SimClock::Int::us; 4299651SAndreas.Sandberg@ARM.com sec = elapsed_usecs / one_million; 4309651SAndreas.Sandberg@ARM.com usec = elapsed_usecs % one_million; 4319651SAndreas.Sandberg@ARM.com} 4329651SAndreas.Sandberg@ARM.com 4339651SAndreas.Sandberg@ARM.com/// Helper function to convert current elapsed time to seconds and 4349651SAndreas.Sandberg@ARM.com/// nanoseconds. 4359651SAndreas.Sandberg@ARM.comtemplate <class T1, class T2> 4369651SAndreas.Sandberg@ARM.comvoid 4379651SAndreas.Sandberg@ARM.comgetElapsedTimeNano(T1 &sec, T2 &nsec) 4389651SAndreas.Sandberg@ARM.com{ 4399651SAndreas.Sandberg@ARM.com uint64_t elapsed_nsecs = curTick() / SimClock::Int::ns; 4409651SAndreas.Sandberg@ARM.com sec = elapsed_nsecs / one_billion; 4419651SAndreas.Sandberg@ARM.com nsec = elapsed_nsecs % one_billion; 4429651SAndreas.Sandberg@ARM.com} 4439651SAndreas.Sandberg@ARM.com 4449651SAndreas.Sandberg@ARM.com////////////////////////////////////////////////////////////////////// 4459651SAndreas.Sandberg@ARM.com// 4469651SAndreas.Sandberg@ARM.com// The following emulation functions are generic, but need to be 4479651SAndreas.Sandberg@ARM.com// templated to account for differences in types, constants, etc. 4489651SAndreas.Sandberg@ARM.com// 4499651SAndreas.Sandberg@ARM.com////////////////////////////////////////////////////////////////////// 4509651SAndreas.Sandberg@ARM.com 4519651SAndreas.Sandberg@ARM.com#if NO_STAT64 4529651SAndreas.Sandberg@ARM.com typedef struct stat hst_stat; 4539651SAndreas.Sandberg@ARM.com typedef struct stat hst_stat64; 4549651SAndreas.Sandberg@ARM.com#else 4559651SAndreas.Sandberg@ARM.com typedef struct stat hst_stat; 4569651SAndreas.Sandberg@ARM.com typedef struct stat64 hst_stat64; 4579651SAndreas.Sandberg@ARM.com#endif 4589651SAndreas.Sandberg@ARM.com 4599651SAndreas.Sandberg@ARM.com//// Helper function to convert a host stat buffer to a target stat 4609651SAndreas.Sandberg@ARM.com//// buffer. Also copies the target buffer out to the simulated 4619651SAndreas.Sandberg@ARM.com//// memory space. Used by stat(), fstat(), and lstat(). 4629651SAndreas.Sandberg@ARM.com 4639651SAndreas.Sandberg@ARM.comtemplate <typename target_stat, typename host_stat> 4649651SAndreas.Sandberg@ARM.comstatic void 4659651SAndreas.Sandberg@ARM.comconvertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) 4669651SAndreas.Sandberg@ARM.com{ 4679651SAndreas.Sandberg@ARM.com using namespace TheISA; 4689651SAndreas.Sandberg@ARM.com 4699652SAndreas.Sandberg@ARM.com if (fakeTTY) 4709652SAndreas.Sandberg@ARM.com tgt->st_dev = 0xA; 4719652SAndreas.Sandberg@ARM.com else 4729652SAndreas.Sandberg@ARM.com tgt->st_dev = host->st_dev; 4739652SAndreas.Sandberg@ARM.com tgt->st_dev = TheISA::htog(tgt->st_dev); 4749652SAndreas.Sandberg@ARM.com tgt->st_ino = host->st_ino; 4759652SAndreas.Sandberg@ARM.com tgt->st_ino = TheISA::htog(tgt->st_ino); 4769652SAndreas.Sandberg@ARM.com tgt->st_mode = host->st_mode; 4779652SAndreas.Sandberg@ARM.com if (fakeTTY) { 4789651SAndreas.Sandberg@ARM.com // Claim to be a character device 4799651SAndreas.Sandberg@ARM.com tgt->st_mode &= ~S_IFMT; // Clear S_IFMT 4809651SAndreas.Sandberg@ARM.com tgt->st_mode |= S_IFCHR; // Set S_IFCHR 4819752Sandreas@sandberg.pp.se } 4829651SAndreas.Sandberg@ARM.com tgt->st_mode = TheISA::htog(tgt->st_mode); 4839651SAndreas.Sandberg@ARM.com tgt->st_nlink = host->st_nlink; 4849651SAndreas.Sandberg@ARM.com tgt->st_nlink = TheISA::htog(tgt->st_nlink); 4859651SAndreas.Sandberg@ARM.com tgt->st_uid = host->st_uid; 4869651SAndreas.Sandberg@ARM.com tgt->st_uid = TheISA::htog(tgt->st_uid); 4879651SAndreas.Sandberg@ARM.com tgt->st_gid = host->st_gid; 4889752Sandreas@sandberg.pp.se tgt->st_gid = TheISA::htog(tgt->st_gid); 4899651SAndreas.Sandberg@ARM.com if (fakeTTY) 4909651SAndreas.Sandberg@ARM.com tgt->st_rdev = 0x880d; 4919651SAndreas.Sandberg@ARM.com else 4929651SAndreas.Sandberg@ARM.com tgt->st_rdev = host->st_rdev; 4939651SAndreas.Sandberg@ARM.com tgt->st_rdev = TheISA::htog(tgt->st_rdev); 4949651SAndreas.Sandberg@ARM.com tgt->st_size = host->st_size; 4959651SAndreas.Sandberg@ARM.com tgt->st_size = TheISA::htog(tgt->st_size); 4969651SAndreas.Sandberg@ARM.com tgt->st_atimeX = host->st_atime; 4979651SAndreas.Sandberg@ARM.com tgt->st_atimeX = TheISA::htog(tgt->st_atimeX); 4989651SAndreas.Sandberg@ARM.com tgt->st_mtimeX = host->st_mtime; 4999651SAndreas.Sandberg@ARM.com tgt->st_mtimeX = TheISA::htog(tgt->st_mtimeX); 5009753Sandreas@sandberg.pp.se tgt->st_ctimeX = host->st_ctime; 5019753Sandreas@sandberg.pp.se tgt->st_ctimeX = TheISA::htog(tgt->st_ctimeX); 5029651SAndreas.Sandberg@ARM.com // Force the block size to be 8k. This helps to ensure buffered io works 5039651SAndreas.Sandberg@ARM.com // consistently across different hosts. 5049753Sandreas@sandberg.pp.se tgt->st_blksize = 0x2000; 5059753Sandreas@sandberg.pp.se tgt->st_blksize = TheISA::htog(tgt->st_blksize); 5069753Sandreas@sandberg.pp.se tgt->st_blocks = host->st_blocks; 5079753Sandreas@sandberg.pp.se tgt->st_blocks = TheISA::htog(tgt->st_blocks); 5089753Sandreas@sandberg.pp.se} 5099753Sandreas@sandberg.pp.se 5109651SAndreas.Sandberg@ARM.com// Same for stat64 5119651SAndreas.Sandberg@ARM.com 5129753Sandreas@sandberg.pp.setemplate <typename target_stat, typename host_stat64> 5139753Sandreas@sandberg.pp.sestatic void 5149753Sandreas@sandberg.pp.seconvertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false) 5159753Sandreas@sandberg.pp.se{ 5169753Sandreas@sandberg.pp.se using namespace TheISA; 5179753Sandreas@sandberg.pp.se 5189753Sandreas@sandberg.pp.se convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY); 5199753Sandreas@sandberg.pp.se#if defined(STAT_HAVE_NSEC) 5209753Sandreas@sandberg.pp.se tgt->st_atime_nsec = host->st_atime_nsec; 5219753Sandreas@sandberg.pp.se tgt->st_atime_nsec = TheISA::htog(tgt->st_atime_nsec); 5229753Sandreas@sandberg.pp.se tgt->st_mtime_nsec = host->st_mtime_nsec; 5239753Sandreas@sandberg.pp.se tgt->st_mtime_nsec = TheISA::htog(tgt->st_mtime_nsec); 5249753Sandreas@sandberg.pp.se tgt->st_ctime_nsec = host->st_ctime_nsec; 5259753Sandreas@sandberg.pp.se tgt->st_ctime_nsec = TheISA::htog(tgt->st_ctime_nsec); 5269753Sandreas@sandberg.pp.se#else 5279753Sandreas@sandberg.pp.se tgt->st_atime_nsec = 0; 5289753Sandreas@sandberg.pp.se tgt->st_mtime_nsec = 0; 5299753Sandreas@sandberg.pp.se tgt->st_ctime_nsec = 0; 5309753Sandreas@sandberg.pp.se#endif 5319753Sandreas@sandberg.pp.se} 5329753Sandreas@sandberg.pp.se 5339753Sandreas@sandberg.pp.se//Here are a couple convenience functions 5349753Sandreas@sandberg.pp.setemplate<class OS> 5359753Sandreas@sandberg.pp.sestatic void 5369753Sandreas@sandberg.pp.secopyOutStatBuf(SETranslatingPortProxy &mem, Addr addr, 5379755Sandreas@sandberg.pp.se hst_stat *host, bool fakeTTY = false) 5389753Sandreas@sandberg.pp.se{ 5399755Sandreas@sandberg.pp.se typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf; 5409755Sandreas@sandberg.pp.se tgt_stat_buf tgt(addr); 5419753Sandreas@sandberg.pp.se convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY); 5429755Sandreas@sandberg.pp.se tgt.copyOut(mem); 5439753Sandreas@sandberg.pp.se} 5449753Sandreas@sandberg.pp.se 5459753Sandreas@sandberg.pp.setemplate<class OS> 5469753Sandreas@sandberg.pp.sestatic void 5479753Sandreas@sandberg.pp.secopyOutStat64Buf(SETranslatingPortProxy &mem, Addr addr, 5489651SAndreas.Sandberg@ARM.com hst_stat64 *host, bool fakeTTY = false) 5499753Sandreas@sandberg.pp.se{ 5509753Sandreas@sandberg.pp.se typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf; 5519651SAndreas.Sandberg@ARM.com tgt_stat_buf tgt(addr); 5529753Sandreas@sandberg.pp.se convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY); 5539753Sandreas@sandberg.pp.se tgt.copyOut(mem); 5549753Sandreas@sandberg.pp.se} 5559753Sandreas@sandberg.pp.se 5569753Sandreas@sandberg.pp.se/// Target ioctl() handler. For the most part, programs call ioctl() 5579753Sandreas@sandberg.pp.se/// only to find out if their stdout is a tty, to determine whether to 5589753Sandreas@sandberg.pp.se/// do line or block buffering. We always claim that output fds are 5599753Sandreas@sandberg.pp.se/// not TTYs to provide repeatable results. 5609753Sandreas@sandberg.pp.setemplate <class OS> 5619753Sandreas@sandberg.pp.seSyscallReturn 5629753Sandreas@sandberg.pp.seioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 5639753Sandreas@sandberg.pp.se ThreadContext *tc) 5649753Sandreas@sandberg.pp.se{ 5659753Sandreas@sandberg.pp.se int index = 0; 5669753Sandreas@sandberg.pp.se int tgt_fd = process->getSyscallArg(tc, index); 5679753Sandreas@sandberg.pp.se unsigned req = process->getSyscallArg(tc, index); 5689753Sandreas@sandberg.pp.se 5699651SAndreas.Sandberg@ARM.com DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", tgt_fd, req); 5709651SAndreas.Sandberg@ARM.com 5719735Sandreas@sandberg.pp.se FDEntry *fde = process->getFDEntry(tgt_fd); 5729735Sandreas@sandberg.pp.se 5739735Sandreas@sandberg.pp.se if (fde == NULL) { 5749735Sandreas@sandberg.pp.se // doesn't map to any simulator fd: not a valid target fd 5759735Sandreas@sandberg.pp.se return -EBADF; 5769735Sandreas@sandberg.pp.se } 5779651SAndreas.Sandberg@ARM.com 5789651SAndreas.Sandberg@ARM.com if (fde->driver != NULL) { 5799651SAndreas.Sandberg@ARM.com return fde->driver->ioctl(process, tc, req); 5809753Sandreas@sandberg.pp.se } 5819651SAndreas.Sandberg@ARM.com 5829651SAndreas.Sandberg@ARM.com if (OS::isTtyReq(req)) { 5839655SAndreas.Sandberg@ARM.com return -ENOTTY; 5849753Sandreas@sandberg.pp.se } 5859753Sandreas@sandberg.pp.se 5869753Sandreas@sandberg.pp.se warn("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ \n", 5879753Sandreas@sandberg.pp.se tgt_fd, req, tc->pcState()); 5889753Sandreas@sandberg.pp.se return -ENOTTY; 5899735Sandreas@sandberg.pp.se} 5909755Sandreas@sandberg.pp.se 5919755Sandreas@sandberg.pp.setemplate <class OS> 5929753Sandreas@sandberg.pp.sestatic SyscallReturn 5939753Sandreas@sandberg.pp.seopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 5949753Sandreas@sandberg.pp.se ThreadContext *tc, int index) 5959753Sandreas@sandberg.pp.se{ 5969655SAndreas.Sandberg@ARM.com std::string path; 5979753Sandreas@sandberg.pp.se 5989753Sandreas@sandberg.pp.se if (!tc->getMemProxy().tryReadString(path, 5999753Sandreas@sandberg.pp.se process->getSyscallArg(tc, index))) 6009753Sandreas@sandberg.pp.se return -EFAULT; 6019753Sandreas@sandberg.pp.se 6029753Sandreas@sandberg.pp.se int tgtFlags = process->getSyscallArg(tc, index); 6039753Sandreas@sandberg.pp.se int mode = process->getSyscallArg(tc, index); 6049753Sandreas@sandberg.pp.se int hostFlags = 0; 6059753Sandreas@sandberg.pp.se 6069753Sandreas@sandberg.pp.se // translate open flags 6079753Sandreas@sandberg.pp.se for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { 6089753Sandreas@sandberg.pp.se if (tgtFlags & OS::openFlagTable[i].tgtFlag) { 6099753Sandreas@sandberg.pp.se tgtFlags &= ~OS::openFlagTable[i].tgtFlag; 6109753Sandreas@sandberg.pp.se hostFlags |= OS::openFlagTable[i].hostFlag; 6119753Sandreas@sandberg.pp.se } 6129753Sandreas@sandberg.pp.se } 6139753Sandreas@sandberg.pp.se 6149753Sandreas@sandberg.pp.se // any target flags left? 6159753Sandreas@sandberg.pp.se if (tgtFlags != 0) 6169753Sandreas@sandberg.pp.se warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); 6179753Sandreas@sandberg.pp.se 6189753Sandreas@sandberg.pp.se#ifdef __CYGWIN32__ 6199753Sandreas@sandberg.pp.se hostFlags |= O_BINARY; 6209753Sandreas@sandberg.pp.se#endif 6219753Sandreas@sandberg.pp.se 6229753Sandreas@sandberg.pp.se // Adjust path for current working directory 6239753Sandreas@sandberg.pp.se path = process->fullPath(path); 6249753Sandreas@sandberg.pp.se 6259753Sandreas@sandberg.pp.se DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); 6269753Sandreas@sandberg.pp.se 6279753Sandreas@sandberg.pp.se if (startswith(path, "/dev/")) { 6289753Sandreas@sandberg.pp.se std::string filename = path.substr(strlen("/dev/")); 6299753Sandreas@sandberg.pp.se if (filename == "sysdev0") { 6309753Sandreas@sandberg.pp.se // This is a memory-mapped high-resolution timer device on Alpha. 6319753Sandreas@sandberg.pp.se // We don't support it, so just punt. 6329753Sandreas@sandberg.pp.se warn("Ignoring open(%s, ...)\n", path); 6339753Sandreas@sandberg.pp.se return -ENOENT; 6349753Sandreas@sandberg.pp.se } 6359753Sandreas@sandberg.pp.se 6369753Sandreas@sandberg.pp.se EmulatedDriver *drv = process->findDriver(filename); 6379753Sandreas@sandberg.pp.se if (drv != NULL) { 6389753Sandreas@sandberg.pp.se // the driver's open method will allocate a fd from the 6399753Sandreas@sandberg.pp.se // process if necessary. 6409753Sandreas@sandberg.pp.se return drv->open(process, tc, mode, hostFlags); 6419753Sandreas@sandberg.pp.se } 6429753Sandreas@sandberg.pp.se 6439753Sandreas@sandberg.pp.se // fall through here for pass through to host devices, such as 6449753Sandreas@sandberg.pp.se // /dev/zero 6459753Sandreas@sandberg.pp.se } 6469753Sandreas@sandberg.pp.se 6479753Sandreas@sandberg.pp.se int fd; 6489753Sandreas@sandberg.pp.se int local_errno; 6499753Sandreas@sandberg.pp.se if (startswith(path, "/proc/") || startswith(path, "/system/") || 6509753Sandreas@sandberg.pp.se startswith(path, "/platform/") || startswith(path, "/sys/")) { 6519753Sandreas@sandberg.pp.se // It's a proc/sys entry and requires special handling 6529753Sandreas@sandberg.pp.se fd = OS::openSpecialFile(path, process, tc); 6539753Sandreas@sandberg.pp.se local_errno = ENOENT; 6549753Sandreas@sandberg.pp.se } else { 6559753Sandreas@sandberg.pp.se // open the file 6569753Sandreas@sandberg.pp.se fd = open(path.c_str(), hostFlags, mode); 6579753Sandreas@sandberg.pp.se local_errno = errno; 6589753Sandreas@sandberg.pp.se } 6599753Sandreas@sandberg.pp.se 6609753Sandreas@sandberg.pp.se if (fd == -1) 6619753Sandreas@sandberg.pp.se return -local_errno; 6629753Sandreas@sandberg.pp.se 6639753Sandreas@sandberg.pp.se return process->allocFD(fd, path.c_str(), hostFlags, mode, false); 6649651SAndreas.Sandberg@ARM.com} 6659655SAndreas.Sandberg@ARM.com 6669651SAndreas.Sandberg@ARM.com/// Target open() handler. 6679651SAndreas.Sandberg@ARM.comtemplate <class OS> 6689651SAndreas.Sandberg@ARM.comSyscallReturn 6699651SAndreas.Sandberg@ARM.comopenFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6709651SAndreas.Sandberg@ARM.com ThreadContext *tc) 6719651SAndreas.Sandberg@ARM.com{ 6729651SAndreas.Sandberg@ARM.com return openFunc<OS>(desc, callnum, process, tc, 0); 6739651SAndreas.Sandberg@ARM.com} 6749651SAndreas.Sandberg@ARM.com 6759651SAndreas.Sandberg@ARM.com/// Target openat() handler. 6769651SAndreas.Sandberg@ARM.comtemplate <class OS> 6779651SAndreas.Sandberg@ARM.comSyscallReturn 6789651SAndreas.Sandberg@ARM.comopenatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6799651SAndreas.Sandberg@ARM.com ThreadContext *tc) 6809651SAndreas.Sandberg@ARM.com{ 6819651SAndreas.Sandberg@ARM.com int index = 0; 6829651SAndreas.Sandberg@ARM.com int dirfd = process->getSyscallArg(tc, index); 6839651SAndreas.Sandberg@ARM.com if (dirfd != OS::TGT_AT_FDCWD) 6849651SAndreas.Sandberg@ARM.com warn("openat: first argument not AT_FDCWD; unlikely to work"); 6859651SAndreas.Sandberg@ARM.com return openFunc<OS>(desc, callnum, process, tc, 1); 6869651SAndreas.Sandberg@ARM.com} 6879651SAndreas.Sandberg@ARM.com 6889651SAndreas.Sandberg@ARM.com/// Target unlinkat() handler. 6899651SAndreas.Sandberg@ARM.comtemplate <class OS> 6909651SAndreas.Sandberg@ARM.comSyscallReturn 6919651SAndreas.Sandberg@ARM.comunlinkatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 6929651SAndreas.Sandberg@ARM.com ThreadContext *tc) 6939651SAndreas.Sandberg@ARM.com{ 6949651SAndreas.Sandberg@ARM.com int index = 0; 6959651SAndreas.Sandberg@ARM.com int dirfd = process->getSyscallArg(tc, index); 6969651SAndreas.Sandberg@ARM.com if (dirfd != OS::TGT_AT_FDCWD) 6979651SAndreas.Sandberg@ARM.com warn("unlinkat: first argument not AT_FDCWD; unlikely to work"); 6989651SAndreas.Sandberg@ARM.com 6999651SAndreas.Sandberg@ARM.com return unlinkHelper(desc, callnum, process, tc, 1); 7009651SAndreas.Sandberg@ARM.com} 7019651SAndreas.Sandberg@ARM.com 7029651SAndreas.Sandberg@ARM.com/// Target facessat() handler 7039651SAndreas.Sandberg@ARM.comtemplate <class OS> 7049651SAndreas.Sandberg@ARM.comSyscallReturn 7059651SAndreas.Sandberg@ARM.comfaccessatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7069651SAndreas.Sandberg@ARM.com ThreadContext *tc) 7079651SAndreas.Sandberg@ARM.com{ 7089651SAndreas.Sandberg@ARM.com int index = 0; 7099651SAndreas.Sandberg@ARM.com int dirfd = process->getSyscallArg(tc, index); 7109651SAndreas.Sandberg@ARM.com if (dirfd != OS::TGT_AT_FDCWD) 7119651SAndreas.Sandberg@ARM.com warn("faccessat: first argument not AT_FDCWD; unlikely to work"); 7129651SAndreas.Sandberg@ARM.com return accessFunc(desc, callnum, process, tc, 1); 7139651SAndreas.Sandberg@ARM.com} 7149651SAndreas.Sandberg@ARM.com 7159651SAndreas.Sandberg@ARM.com/// Target readlinkat() handler 7169651SAndreas.Sandberg@ARM.comtemplate <class OS> 7179651SAndreas.Sandberg@ARM.comSyscallReturn 7189651SAndreas.Sandberg@ARM.comreadlinkatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7199651SAndreas.Sandberg@ARM.com ThreadContext *tc) 7209651SAndreas.Sandberg@ARM.com{ 7219651SAndreas.Sandberg@ARM.com int index = 0; 7229651SAndreas.Sandberg@ARM.com int dirfd = process->getSyscallArg(tc, index); 7239651SAndreas.Sandberg@ARM.com if (dirfd != OS::TGT_AT_FDCWD) 7249651SAndreas.Sandberg@ARM.com warn("openat: first argument not AT_FDCWD; unlikely to work"); 7259651SAndreas.Sandberg@ARM.com return readlinkFunc(desc, callnum, process, tc, 1); 7269651SAndreas.Sandberg@ARM.com} 7279651SAndreas.Sandberg@ARM.com 7289651SAndreas.Sandberg@ARM.com/// Target renameat() handler. 7299651SAndreas.Sandberg@ARM.comtemplate <class OS> 7309651SAndreas.Sandberg@ARM.comSyscallReturn 7319651SAndreas.Sandberg@ARM.comrenameatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7329651SAndreas.Sandberg@ARM.com ThreadContext *tc) 7339651SAndreas.Sandberg@ARM.com{ 7349651SAndreas.Sandberg@ARM.com int index = 0; 7359651SAndreas.Sandberg@ARM.com 7369651SAndreas.Sandberg@ARM.com int olddirfd = process->getSyscallArg(tc, index); 7379651SAndreas.Sandberg@ARM.com if (olddirfd != OS::TGT_AT_FDCWD) 7389651SAndreas.Sandberg@ARM.com warn("renameat: first argument not AT_FDCWD; unlikely to work"); 7399651SAndreas.Sandberg@ARM.com 7409651SAndreas.Sandberg@ARM.com std::string old_name; 7419651SAndreas.Sandberg@ARM.com 7429651SAndreas.Sandberg@ARM.com if (!tc->getMemProxy().tryReadString(old_name, 7439651SAndreas.Sandberg@ARM.com process->getSyscallArg(tc, index))) 7449651SAndreas.Sandberg@ARM.com return -EFAULT; 7459651SAndreas.Sandberg@ARM.com 7469651SAndreas.Sandberg@ARM.com int newdirfd = process->getSyscallArg(tc, index); 7479651SAndreas.Sandberg@ARM.com if (newdirfd != OS::TGT_AT_FDCWD) 7489651SAndreas.Sandberg@ARM.com warn("renameat: third argument not AT_FDCWD; unlikely to work"); 7499651SAndreas.Sandberg@ARM.com 7509651SAndreas.Sandberg@ARM.com std::string new_name; 7519651SAndreas.Sandberg@ARM.com 7529651SAndreas.Sandberg@ARM.com if (!tc->getMemProxy().tryReadString(new_name, 7539651SAndreas.Sandberg@ARM.com process->getSyscallArg(tc, index))) 7549651SAndreas.Sandberg@ARM.com return -EFAULT; 7559651SAndreas.Sandberg@ARM.com 7569651SAndreas.Sandberg@ARM.com // Adjust path for current working directory 7579651SAndreas.Sandberg@ARM.com old_name = process->fullPath(old_name); 7589651SAndreas.Sandberg@ARM.com new_name = process->fullPath(new_name); 7599651SAndreas.Sandberg@ARM.com 7609651SAndreas.Sandberg@ARM.com int result = rename(old_name.c_str(), new_name.c_str()); 7619651SAndreas.Sandberg@ARM.com return (result == -1) ? -errno : result; 7629651SAndreas.Sandberg@ARM.com} 7639651SAndreas.Sandberg@ARM.com 7649651SAndreas.Sandberg@ARM.com/// Target sysinfo() handler. 7659651SAndreas.Sandberg@ARM.comtemplate <class OS> 7669651SAndreas.Sandberg@ARM.comSyscallReturn 7679651SAndreas.Sandberg@ARM.comsysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7689651SAndreas.Sandberg@ARM.com ThreadContext *tc) 7699651SAndreas.Sandberg@ARM.com{ 7709651SAndreas.Sandberg@ARM.com 7719651SAndreas.Sandberg@ARM.com int index = 0; 7729651SAndreas.Sandberg@ARM.com TypedBufferArg<typename OS::tgt_sysinfo> 7739651SAndreas.Sandberg@ARM.com sysinfo(process->getSyscallArg(tc, index)); 7749651SAndreas.Sandberg@ARM.com 7759651SAndreas.Sandberg@ARM.com sysinfo->uptime=seconds_since_epoch; 7769651SAndreas.Sandberg@ARM.com sysinfo->totalram=process->system->memSize(); 7779651SAndreas.Sandberg@ARM.com 7789651SAndreas.Sandberg@ARM.com sysinfo.copyOut(tc->getMemProxy()); 7799651SAndreas.Sandberg@ARM.com 7809651SAndreas.Sandberg@ARM.com return 0; 7819651SAndreas.Sandberg@ARM.com} 7829651SAndreas.Sandberg@ARM.com 7839651SAndreas.Sandberg@ARM.com/// Target chmod() handler. 7849651SAndreas.Sandberg@ARM.comtemplate <class OS> 7859651SAndreas.Sandberg@ARM.comSyscallReturn 7869651SAndreas.Sandberg@ARM.comchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 7879651SAndreas.Sandberg@ARM.com ThreadContext *tc) 7889651SAndreas.Sandberg@ARM.com{ 7899651SAndreas.Sandberg@ARM.com std::string path; 7909651SAndreas.Sandberg@ARM.com 7919651SAndreas.Sandberg@ARM.com int index = 0; 7929651SAndreas.Sandberg@ARM.com if (!tc->getMemProxy().tryReadString(path, 7939651SAndreas.Sandberg@ARM.com process->getSyscallArg(tc, index))) { 7949651SAndreas.Sandberg@ARM.com return -EFAULT; 7959651SAndreas.Sandberg@ARM.com } 7969651SAndreas.Sandberg@ARM.com 7979651SAndreas.Sandberg@ARM.com uint32_t mode = process->getSyscallArg(tc, index); 7989651SAndreas.Sandberg@ARM.com mode_t hostMode = 0; 7999651SAndreas.Sandberg@ARM.com 8009651SAndreas.Sandberg@ARM.com // XXX translate mode flags via OS::something??? 8019651SAndreas.Sandberg@ARM.com hostMode = mode; 8029651SAndreas.Sandberg@ARM.com 8039651SAndreas.Sandberg@ARM.com // Adjust path for current working directory 8049651SAndreas.Sandberg@ARM.com path = process->fullPath(path); 8059651SAndreas.Sandberg@ARM.com 8069651SAndreas.Sandberg@ARM.com // do the chmod 8079651SAndreas.Sandberg@ARM.com int result = chmod(path.c_str(), hostMode); 8089651SAndreas.Sandberg@ARM.com if (result < 0) 8099651SAndreas.Sandberg@ARM.com return -errno; 8109651SAndreas.Sandberg@ARM.com 8119652SAndreas.Sandberg@ARM.com return 0; 8129652SAndreas.Sandberg@ARM.com} 8139652SAndreas.Sandberg@ARM.com 8149652SAndreas.Sandberg@ARM.com 8159652SAndreas.Sandberg@ARM.com/// Target fchmod() handler. 8169652SAndreas.Sandberg@ARM.comtemplate <class OS> 8179652SAndreas.Sandberg@ARM.comSyscallReturn 8189652SAndreas.Sandberg@ARM.comfchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 8199652SAndreas.Sandberg@ARM.com ThreadContext *tc) 8209652SAndreas.Sandberg@ARM.com{ 8219652SAndreas.Sandberg@ARM.com int index = 0; 8229652SAndreas.Sandberg@ARM.com int tgt_fd = process->getSyscallArg(tc, index); 8239652SAndreas.Sandberg@ARM.com uint32_t mode = process->getSyscallArg(tc, index); 8249652SAndreas.Sandberg@ARM.com 8259652SAndreas.Sandberg@ARM.com int sim_fd = process->getSimFD(tgt_fd); 8269652SAndreas.Sandberg@ARM.com if (sim_fd < 0) 8279652SAndreas.Sandberg@ARM.com return -EBADF; 8289652SAndreas.Sandberg@ARM.com 8299652SAndreas.Sandberg@ARM.com mode_t hostMode = 0; 8309652SAndreas.Sandberg@ARM.com 8319652SAndreas.Sandberg@ARM.com // XXX translate mode flags via OS::someting??? 8329652SAndreas.Sandberg@ARM.com hostMode = mode; 8339652SAndreas.Sandberg@ARM.com 8349652SAndreas.Sandberg@ARM.com // do the fchmod 8359651SAndreas.Sandberg@ARM.com int result = fchmod(sim_fd, hostMode); 8369651SAndreas.Sandberg@ARM.com if (result < 0) 8379651SAndreas.Sandberg@ARM.com return -errno; 8389651SAndreas.Sandberg@ARM.com 8399753Sandreas@sandberg.pp.se return 0; 8409651SAndreas.Sandberg@ARM.com} 8419753Sandreas@sandberg.pp.se 8429753Sandreas@sandberg.pp.se/// Target mremap() handler. 8439753Sandreas@sandberg.pp.setemplate <class OS> 8449651SAndreas.Sandberg@ARM.comSyscallReturn 8459651SAndreas.Sandberg@ARM.commremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc) 8469651SAndreas.Sandberg@ARM.com{ 8479651SAndreas.Sandberg@ARM.com int index = 0; 8489651SAndreas.Sandberg@ARM.com Addr start = process->getSyscallArg(tc, index); 8499651SAndreas.Sandberg@ARM.com uint64_t old_length = process->getSyscallArg(tc, index); 8509651SAndreas.Sandberg@ARM.com uint64_t new_length = process->getSyscallArg(tc, index); 8519651SAndreas.Sandberg@ARM.com uint64_t flags = process->getSyscallArg(tc, index); 8529753Sandreas@sandberg.pp.se uint64_t provided_address = 0; 8539651SAndreas.Sandberg@ARM.com bool use_provided_address = flags & OS::TGT_MREMAP_FIXED; 8549651SAndreas.Sandberg@ARM.com 8559651SAndreas.Sandberg@ARM.com if (use_provided_address) 8569651SAndreas.Sandberg@ARM.com provided_address = process->getSyscallArg(tc, index); 8579651SAndreas.Sandberg@ARM.com 8589651SAndreas.Sandberg@ARM.com if ((start % TheISA::PageBytes != 0) || 8599651SAndreas.Sandberg@ARM.com (provided_address % TheISA::PageBytes != 0)) { 8609651SAndreas.Sandberg@ARM.com warn("mremap failing: arguments not page aligned"); 8619651SAndreas.Sandberg@ARM.com return -EINVAL; 8629651SAndreas.Sandberg@ARM.com } 8639651SAndreas.Sandberg@ARM.com 8649651SAndreas.Sandberg@ARM.com new_length = roundUp(new_length, TheISA::PageBytes); 8659651SAndreas.Sandberg@ARM.com 8669651SAndreas.Sandberg@ARM.com if (new_length > old_length) { 8679651SAndreas.Sandberg@ARM.com if ((start + old_length) == process->mmap_end && 8689651SAndreas.Sandberg@ARM.com (!use_provided_address || provided_address == start)) { 8699651SAndreas.Sandberg@ARM.com uint64_t diff = new_length - old_length; 8709651SAndreas.Sandberg@ARM.com process->allocateMem(process->mmap_end, diff); 8719651SAndreas.Sandberg@ARM.com process->mmap_end += diff; 8729753Sandreas@sandberg.pp.se return start; 8739651SAndreas.Sandberg@ARM.com } else { 8749651SAndreas.Sandberg@ARM.com if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) { 8759651SAndreas.Sandberg@ARM.com warn("can't remap here and MREMAP_MAYMOVE flag not set\n"); 8769651SAndreas.Sandberg@ARM.com return -ENOMEM; 8779651SAndreas.Sandberg@ARM.com } else { 8789651SAndreas.Sandberg@ARM.com uint64_t new_start = use_provided_address ? 8799651SAndreas.Sandberg@ARM.com provided_address : process->mmap_end; 8809651SAndreas.Sandberg@ARM.com process->pTable->remap(start, old_length, new_start); 8819651SAndreas.Sandberg@ARM.com warn("mremapping to new vaddr %08p-%08p, adding %d\n", 8829651SAndreas.Sandberg@ARM.com new_start, new_start + new_length, 8839651SAndreas.Sandberg@ARM.com new_length - old_length); 8849651SAndreas.Sandberg@ARM.com // add on the remaining unallocated pages 8859651SAndreas.Sandberg@ARM.com process->allocateMem(new_start + old_length, 8869651SAndreas.Sandberg@ARM.com new_length - old_length, 8879651SAndreas.Sandberg@ARM.com use_provided_address /* clobber */); 8889651SAndreas.Sandberg@ARM.com if (!use_provided_address) 8899651SAndreas.Sandberg@ARM.com process->mmap_end += new_length; 8909651SAndreas.Sandberg@ARM.com if (use_provided_address && 8919651SAndreas.Sandberg@ARM.com new_start + new_length > process->mmap_end) { 8929651SAndreas.Sandberg@ARM.com // something fishy going on here, at least notify the user 8939651SAndreas.Sandberg@ARM.com // @todo: increase mmap_end? 8949651SAndreas.Sandberg@ARM.com warn("mmap region limit exceeded with MREMAP_FIXED\n"); 8959651SAndreas.Sandberg@ARM.com } 8969651SAndreas.Sandberg@ARM.com warn("returning %08p as start\n", new_start); 8979651SAndreas.Sandberg@ARM.com return new_start; 8989689Sandreas@sandberg.pp.se } 8999651SAndreas.Sandberg@ARM.com } 9009651SAndreas.Sandberg@ARM.com } else { 9019651SAndreas.Sandberg@ARM.com if (use_provided_address && provided_address != start) 9029651SAndreas.Sandberg@ARM.com process->pTable->remap(start, new_length, provided_address); 9039651SAndreas.Sandberg@ARM.com process->pTable->unmap(start + new_length, old_length - new_length); 9049651SAndreas.Sandberg@ARM.com return use_provided_address ? provided_address : start; 9059651SAndreas.Sandberg@ARM.com } 9069651SAndreas.Sandberg@ARM.com} 9079651SAndreas.Sandberg@ARM.com 9089651SAndreas.Sandberg@ARM.com/// Target stat() handler. 9099651SAndreas.Sandberg@ARM.comtemplate <class OS> 9109651SAndreas.Sandberg@ARM.comSyscallReturn 9119651SAndreas.Sandberg@ARM.comstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 9129651SAndreas.Sandberg@ARM.com ThreadContext *tc) 9139651SAndreas.Sandberg@ARM.com{ 9149651SAndreas.Sandberg@ARM.com std::string path; 9159651SAndreas.Sandberg@ARM.com 9169651SAndreas.Sandberg@ARM.com int index = 0; 9179651SAndreas.Sandberg@ARM.com if (!tc->getMemProxy().tryReadString(path, 9189651SAndreas.Sandberg@ARM.com process->getSyscallArg(tc, index))) { 9199651SAndreas.Sandberg@ARM.com return -EFAULT; 9209651SAndreas.Sandberg@ARM.com } 9219651SAndreas.Sandberg@ARM.com Addr bufPtr = process->getSyscallArg(tc, index); 9229651SAndreas.Sandberg@ARM.com 9239651SAndreas.Sandberg@ARM.com // Adjust path for current working directory 9249651SAndreas.Sandberg@ARM.com path = process->fullPath(path); 9259651SAndreas.Sandberg@ARM.com 9269651SAndreas.Sandberg@ARM.com struct stat hostBuf; 9279651SAndreas.Sandberg@ARM.com int result = stat(path.c_str(), &hostBuf); 9289689Sandreas@sandberg.pp.se 9299651SAndreas.Sandberg@ARM.com if (result < 0) 9309651SAndreas.Sandberg@ARM.com return -errno; 9319651SAndreas.Sandberg@ARM.com 9329651SAndreas.Sandberg@ARM.com copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 9339651SAndreas.Sandberg@ARM.com 9349651SAndreas.Sandberg@ARM.com return 0; 9359651SAndreas.Sandberg@ARM.com} 9369689Sandreas@sandberg.pp.se 9379651SAndreas.Sandberg@ARM.com 9389651SAndreas.Sandberg@ARM.com/// Target stat64() handler. 9399651SAndreas.Sandberg@ARM.comtemplate <class OS> 9409651SAndreas.Sandberg@ARM.comSyscallReturn 9419651SAndreas.Sandberg@ARM.comstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 9429651SAndreas.Sandberg@ARM.com ThreadContext *tc) 9439651SAndreas.Sandberg@ARM.com{ 9449651SAndreas.Sandberg@ARM.com std::string path; 9459689Sandreas@sandberg.pp.se 9469651SAndreas.Sandberg@ARM.com int index = 0; 9479651SAndreas.Sandberg@ARM.com if (!tc->getMemProxy().tryReadString(path, 9489651SAndreas.Sandberg@ARM.com process->getSyscallArg(tc, index))) 9499651SAndreas.Sandberg@ARM.com return -EFAULT; 9509651SAndreas.Sandberg@ARM.com Addr bufPtr = process->getSyscallArg(tc, index); 9519651SAndreas.Sandberg@ARM.com 9529651SAndreas.Sandberg@ARM.com // Adjust path for current working directory 9539760Sandreas@sandberg.pp.se path = process->fullPath(path); 9549760Sandreas@sandberg.pp.se 9559760Sandreas@sandberg.pp.se#if NO_STAT64 9569682Sandreas@sandberg.pp.se struct stat hostBuf; 9579760Sandreas@sandberg.pp.se int result = stat(path.c_str(), &hostBuf); 9589760Sandreas@sandberg.pp.se#else 9599760Sandreas@sandberg.pp.se struct stat64 hostBuf; 9609760Sandreas@sandberg.pp.se int result = stat64(path.c_str(), &hostBuf); 9619760Sandreas@sandberg.pp.se#endif 9629760Sandreas@sandberg.pp.se 9639760Sandreas@sandberg.pp.se if (result < 0) 9649760Sandreas@sandberg.pp.se return -errno; 9659760Sandreas@sandberg.pp.se 9669651SAndreas.Sandberg@ARM.com copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 9679651SAndreas.Sandberg@ARM.com 9689651SAndreas.Sandberg@ARM.com return 0; 9699651SAndreas.Sandberg@ARM.com} 9709760Sandreas@sandberg.pp.se 9719760Sandreas@sandberg.pp.se 9729882Sandreas@sandberg.pp.se/// Target fstatat64() handler. 9739882Sandreas@sandberg.pp.setemplate <class OS> 9749882Sandreas@sandberg.pp.seSyscallReturn 9759882Sandreas@sandberg.pp.sefstatat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 9769760Sandreas@sandberg.pp.se ThreadContext *tc) 9779760Sandreas@sandberg.pp.se{ 9789760Sandreas@sandberg.pp.se int index = 0; 9799651SAndreas.Sandberg@ARM.com int dirfd = process->getSyscallArg(tc, index); 9809651SAndreas.Sandberg@ARM.com if (dirfd != OS::TGT_AT_FDCWD) 9819753Sandreas@sandberg.pp.se warn("fstatat64: first argument not AT_FDCWD; unlikely to work"); 9829753Sandreas@sandberg.pp.se 9839753Sandreas@sandberg.pp.se std::string path; 9849753Sandreas@sandberg.pp.se if (!tc->getMemProxy().tryReadString(path, 9859753Sandreas@sandberg.pp.se process->getSyscallArg(tc, index))) 9869753Sandreas@sandberg.pp.se return -EFAULT; 9879753Sandreas@sandberg.pp.se Addr bufPtr = process->getSyscallArg(tc, index); 9889753Sandreas@sandberg.pp.se 9899753Sandreas@sandberg.pp.se // Adjust path for current working directory 9909753Sandreas@sandberg.pp.se path = process->fullPath(path); 9919753Sandreas@sandberg.pp.se 9929753Sandreas@sandberg.pp.se#if NO_STAT64 9939753Sandreas@sandberg.pp.se struct stat hostBuf; 9949753Sandreas@sandberg.pp.se int result = stat(path.c_str(), &hostBuf); 9959753Sandreas@sandberg.pp.se#else 9969753Sandreas@sandberg.pp.se struct stat64 hostBuf; 9979753Sandreas@sandberg.pp.se int result = stat64(path.c_str(), &hostBuf); 9989753Sandreas@sandberg.pp.se#endif 9999753Sandreas@sandberg.pp.se 10009753Sandreas@sandberg.pp.se if (result < 0) 10019753Sandreas@sandberg.pp.se return -errno; 10029651SAndreas.Sandberg@ARM.com 10039651SAndreas.Sandberg@ARM.com copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 10049651SAndreas.Sandberg@ARM.com 10059651SAndreas.Sandberg@ARM.com return 0; 10069651SAndreas.Sandberg@ARM.com} 10079651SAndreas.Sandberg@ARM.com 10089651SAndreas.Sandberg@ARM.com 10099651SAndreas.Sandberg@ARM.com/// Target fstat64() handler. 10109651SAndreas.Sandberg@ARM.comtemplate <class OS> 10119651SAndreas.Sandberg@ARM.comSyscallReturn 10129651SAndreas.Sandberg@ARM.comfstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 10139651SAndreas.Sandberg@ARM.com ThreadContext *tc) 10149651SAndreas.Sandberg@ARM.com{ 10159651SAndreas.Sandberg@ARM.com int index = 0; 10169651SAndreas.Sandberg@ARM.com int tgt_fd = process->getSyscallArg(tc, index); 10179651SAndreas.Sandberg@ARM.com Addr bufPtr = process->getSyscallArg(tc, index); 10189651SAndreas.Sandberg@ARM.com 10199651SAndreas.Sandberg@ARM.com int sim_fd = process->getSimFD(tgt_fd); 10209651SAndreas.Sandberg@ARM.com if (sim_fd < 0) 10219651SAndreas.Sandberg@ARM.com return -EBADF; 10229651SAndreas.Sandberg@ARM.com 10239651SAndreas.Sandberg@ARM.com#if NO_STAT64 10249651SAndreas.Sandberg@ARM.com struct stat hostBuf; 10259651SAndreas.Sandberg@ARM.com int result = fstat(sim_fd, &hostBuf); 10269651SAndreas.Sandberg@ARM.com#else 10279651SAndreas.Sandberg@ARM.com struct stat64 hostBuf; 10289651SAndreas.Sandberg@ARM.com int result = fstat64(sim_fd, &hostBuf); 10299651SAndreas.Sandberg@ARM.com#endif 10309651SAndreas.Sandberg@ARM.com 10319651SAndreas.Sandberg@ARM.com if (result < 0) 10329651SAndreas.Sandberg@ARM.com return -errno; 10339651SAndreas.Sandberg@ARM.com 10349651SAndreas.Sandberg@ARM.com copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (sim_fd == 1)); 10359651SAndreas.Sandberg@ARM.com 10369651SAndreas.Sandberg@ARM.com return 0; 10379651SAndreas.Sandberg@ARM.com} 10389651SAndreas.Sandberg@ARM.com 10399651SAndreas.Sandberg@ARM.com 10409651SAndreas.Sandberg@ARM.com/// Target lstat() handler. 10419651SAndreas.Sandberg@ARM.comtemplate <class OS> 10429651SAndreas.Sandberg@ARM.comSyscallReturn 10439651SAndreas.Sandberg@ARM.comlstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 10449651SAndreas.Sandberg@ARM.com ThreadContext *tc) 10459651SAndreas.Sandberg@ARM.com{ 10469651SAndreas.Sandberg@ARM.com std::string path; 10479651SAndreas.Sandberg@ARM.com 10489753Sandreas@sandberg.pp.se int index = 0; 10499753Sandreas@sandberg.pp.se if (!tc->getMemProxy().tryReadString(path, 10509753Sandreas@sandberg.pp.se process->getSyscallArg(tc, index))) { 10519753Sandreas@sandberg.pp.se return -EFAULT; 10529753Sandreas@sandberg.pp.se } 10539753Sandreas@sandberg.pp.se Addr bufPtr = process->getSyscallArg(tc, index); 10549753Sandreas@sandberg.pp.se 10559753Sandreas@sandberg.pp.se // Adjust path for current working directory 10569753Sandreas@sandberg.pp.se path = process->fullPath(path); 10579753Sandreas@sandberg.pp.se 10589753Sandreas@sandberg.pp.se struct stat hostBuf; 10599753Sandreas@sandberg.pp.se int result = lstat(path.c_str(), &hostBuf); 10609753Sandreas@sandberg.pp.se 10619753Sandreas@sandberg.pp.se if (result < 0) 10629753Sandreas@sandberg.pp.se return -errno; 10639753Sandreas@sandberg.pp.se 10649753Sandreas@sandberg.pp.se copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 10659753Sandreas@sandberg.pp.se 10669753Sandreas@sandberg.pp.se return 0; 10679753Sandreas@sandberg.pp.se} 10689753Sandreas@sandberg.pp.se 10699753Sandreas@sandberg.pp.se/// Target lstat64() handler. 10709753Sandreas@sandberg.pp.setemplate <class OS> 10719753Sandreas@sandberg.pp.seSyscallReturn 10729753Sandreas@sandberg.pp.selstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process, 10739753Sandreas@sandberg.pp.se ThreadContext *tc) 10749753Sandreas@sandberg.pp.se{ 10759753Sandreas@sandberg.pp.se std::string path; 10769753Sandreas@sandberg.pp.se 10779753Sandreas@sandberg.pp.se int index = 0; 10789753Sandreas@sandberg.pp.se if (!tc->getMemProxy().tryReadString(path, 10799753Sandreas@sandberg.pp.se process->getSyscallArg(tc, index))) { 10809753Sandreas@sandberg.pp.se return -EFAULT; 10819753Sandreas@sandberg.pp.se } 10829753Sandreas@sandberg.pp.se Addr bufPtr = process->getSyscallArg(tc, index); 10839753Sandreas@sandberg.pp.se 10849753Sandreas@sandberg.pp.se // Adjust path for current working directory 10859753Sandreas@sandberg.pp.se path = process->fullPath(path); 10869753Sandreas@sandberg.pp.se 10879753Sandreas@sandberg.pp.se#if NO_STAT64 10889753Sandreas@sandberg.pp.se struct stat hostBuf; 10899753Sandreas@sandberg.pp.se int result = lstat(path.c_str(), &hostBuf); 10909753Sandreas@sandberg.pp.se#else 10919753Sandreas@sandberg.pp.se struct stat64 hostBuf; 10929651SAndreas.Sandberg@ARM.com int result = lstat64(path.c_str(), &hostBuf); 10939651SAndreas.Sandberg@ARM.com#endif 10949651SAndreas.Sandberg@ARM.com 10959651SAndreas.Sandberg@ARM.com if (result < 0) 10969651SAndreas.Sandberg@ARM.com return -errno; 10979651SAndreas.Sandberg@ARM.com 10989651SAndreas.Sandberg@ARM.com copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf); 10999651SAndreas.Sandberg@ARM.com 11009651SAndreas.Sandberg@ARM.com return 0; 11019651SAndreas.Sandberg@ARM.com} 11029655SAndreas.Sandberg@ARM.com 11039655SAndreas.Sandberg@ARM.com/// Target fstat() handler. 11049655SAndreas.Sandberg@ARM.comtemplate <class OS> 11059655SAndreas.Sandberg@ARM.comSyscallReturn 11069655SAndreas.Sandberg@ARM.comfstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 11079655SAndreas.Sandberg@ARM.com ThreadContext *tc) 11089655SAndreas.Sandberg@ARM.com{ 11099655SAndreas.Sandberg@ARM.com int index = 0; 11109655SAndreas.Sandberg@ARM.com int tgt_fd = process->getSyscallArg(tc, index); 11119655SAndreas.Sandberg@ARM.com Addr bufPtr = process->getSyscallArg(tc, index); 11129655SAndreas.Sandberg@ARM.com 11139651SAndreas.Sandberg@ARM.com DPRINTF_SYSCALL(Verbose, "fstat(%d, ...)\n", tgt_fd); 11149651SAndreas.Sandberg@ARM.com 11159651SAndreas.Sandberg@ARM.com int sim_fd = process->getSimFD(tgt_fd); 11169651SAndreas.Sandberg@ARM.com if (sim_fd < 0) 11179651SAndreas.Sandberg@ARM.com return -EBADF; 11189651SAndreas.Sandberg@ARM.com 11199651SAndreas.Sandberg@ARM.com struct stat hostBuf; 11209651SAndreas.Sandberg@ARM.com int result = fstat(sim_fd, &hostBuf); 11219651SAndreas.Sandberg@ARM.com 11229651SAndreas.Sandberg@ARM.com if (result < 0) 11239753Sandreas@sandberg.pp.se return -errno; 11249753Sandreas@sandberg.pp.se 11259753Sandreas@sandberg.pp.se copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (sim_fd == 1)); 11269753Sandreas@sandberg.pp.se 11279753Sandreas@sandberg.pp.se return 0; 11289753Sandreas@sandberg.pp.se} 11299753Sandreas@sandberg.pp.se 11309753Sandreas@sandberg.pp.se 11319753Sandreas@sandberg.pp.se/// Target statfs() handler. 11329753Sandreas@sandberg.pp.setemplate <class OS> 11339753Sandreas@sandberg.pp.seSyscallReturn 11349753Sandreas@sandberg.pp.sestatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 11359753Sandreas@sandberg.pp.se ThreadContext *tc) 11369753Sandreas@sandberg.pp.se{ 11379753Sandreas@sandberg.pp.se std::string path; 11389753Sandreas@sandberg.pp.se 11399753Sandreas@sandberg.pp.se int index = 0; 11409753Sandreas@sandberg.pp.se if (!tc->getMemProxy().tryReadString(path, 11419753Sandreas@sandberg.pp.se process->getSyscallArg(tc, index))) { 11429753Sandreas@sandberg.pp.se return -EFAULT; 11439753Sandreas@sandberg.pp.se } 11449753Sandreas@sandberg.pp.se Addr bufPtr = process->getSyscallArg(tc, index); 11459753Sandreas@sandberg.pp.se 11469753Sandreas@sandberg.pp.se // Adjust path for current working directory 11479753Sandreas@sandberg.pp.se path = process->fullPath(path); 11489753Sandreas@sandberg.pp.se 11499753Sandreas@sandberg.pp.se struct statfs hostBuf; 11509753Sandreas@sandberg.pp.se int result = statfs(path.c_str(), &hostBuf); 11519753Sandreas@sandberg.pp.se 11529753Sandreas@sandberg.pp.se if (result < 0) 11539753Sandreas@sandberg.pp.se return -errno; 11549753Sandreas@sandberg.pp.se 11559753Sandreas@sandberg.pp.se OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf); 1156 1157 return 0; 1158} 1159 1160 1161/// Target fstatfs() handler. 1162template <class OS> 1163SyscallReturn 1164fstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1165 ThreadContext *tc) 1166{ 1167 int index = 0; 1168 int tgt_fd = process->getSyscallArg(tc, index); 1169 Addr bufPtr = process->getSyscallArg(tc, index); 1170 1171 int sim_fd = process->getSimFD(tgt_fd); 1172 if (sim_fd < 0) 1173 return -EBADF; 1174 1175 struct statfs hostBuf; 1176 int result = fstatfs(sim_fd, &hostBuf); 1177 1178 if (result < 0) 1179 return -errno; 1180 1181 OS::copyOutStatfsBuf(tc->getMemProxy(), bufPtr, &hostBuf); 1182 1183 return 0; 1184} 1185 1186 1187/// Target writev() handler. 1188template <class OS> 1189SyscallReturn 1190writevFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1191 ThreadContext *tc) 1192{ 1193 int index = 0; 1194 int tgt_fd = process->getSyscallArg(tc, index); 1195 1196 int sim_fd = process->getSimFD(tgt_fd); 1197 if (sim_fd < 0) 1198 return -EBADF; 1199 1200 SETranslatingPortProxy &p = tc->getMemProxy(); 1201 uint64_t tiov_base = process->getSyscallArg(tc, index); 1202 size_t count = process->getSyscallArg(tc, index); 1203 struct iovec hiov[count]; 1204 for (size_t i = 0; i < count; ++i) { 1205 typename OS::tgt_iovec tiov; 1206 1207 p.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), 1208 (uint8_t*)&tiov, sizeof(typename OS::tgt_iovec)); 1209 hiov[i].iov_len = TheISA::gtoh(tiov.iov_len); 1210 hiov[i].iov_base = new char [hiov[i].iov_len]; 1211 p.readBlob(TheISA::gtoh(tiov.iov_base), (uint8_t *)hiov[i].iov_base, 1212 hiov[i].iov_len); 1213 } 1214 1215 int result = writev(sim_fd, hiov, count); 1216 1217 for (size_t i = 0; i < count; ++i) 1218 delete [] (char *)hiov[i].iov_base; 1219 1220 if (result < 0) 1221 return -errno; 1222 1223 return result; 1224} 1225 1226 1227/// Target mmap() handler. 1228template <class OS> 1229SyscallReturn 1230mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 1231{ 1232 int index = 0; 1233 Addr start = p->getSyscallArg(tc, index); 1234 uint64_t length = p->getSyscallArg(tc, index); 1235 int prot = p->getSyscallArg(tc, index); 1236 int tgt_flags = p->getSyscallArg(tc, index); 1237 int tgt_fd = p->getSyscallArg(tc, index); 1238 int offset = p->getSyscallArg(tc, index); 1239 1240 DPRINTF_SYSCALL(Verbose, "mmap(0x%x, len %d, prot %d, flags %d, fd %d, " 1241 "offs %d)\n", start, length, prot, tgt_flags, tgt_fd, 1242 offset); 1243 1244 if (start & (TheISA::PageBytes - 1) || 1245 offset & (TheISA::PageBytes - 1) || 1246 (tgt_flags & OS::TGT_MAP_PRIVATE && 1247 tgt_flags & OS::TGT_MAP_SHARED) || 1248 (!(tgt_flags & OS::TGT_MAP_PRIVATE) && 1249 !(tgt_flags & OS::TGT_MAP_SHARED)) || 1250 !length) { 1251 return -EINVAL; 1252 } 1253 1254 if ((prot & PROT_WRITE) && (tgt_flags & OS::TGT_MAP_SHARED)) { 1255 // With shared mmaps, there are two cases to consider: 1256 // 1) anonymous: writes should modify the mapping and this should be 1257 // visible to observers who share the mapping. Currently, it's 1258 // difficult to update the shared mapping because there's no 1259 // structure which maintains information about the which virtual 1260 // memory areas are shared. If that structure existed, it would be 1261 // possible to make the translations point to the same frames. 1262 // 2) file-backed: writes should modify the mapping and the file 1263 // which is backed by the mapping. The shared mapping problem is the 1264 // same as what was mentioned about the anonymous mappings. For 1265 // file-backed mappings, the writes to the file are difficult 1266 // because it requires syncing what the mapping holds with the file 1267 // that resides on the host system. So, any write on a real system 1268 // would cause the change to be propagated to the file mapping at 1269 // some point in the future (the inode is tracked along with the 1270 // mapping). This isn't guaranteed to always happen, but it usually 1271 // works well enough. The guarantee is provided by the msync system 1272 // call. We could force the change through with shared mappings with 1273 // a call to msync, but that again would require more information 1274 // than we currently maintain. 1275 warn("mmap: writing to shared mmap region is currently " 1276 "unsupported. The write succeeds on the target, but it " 1277 "will not be propagated to the host or shared mappings"); 1278 } 1279 1280 length = roundUp(length, TheISA::PageBytes); 1281 1282 int sim_fd = -1; 1283 uint8_t *pmap = nullptr; 1284 if (!(tgt_flags & OS::TGT_MAP_ANONYMOUS)) { 1285 sim_fd = p->getSimFD(tgt_fd); 1286 if (sim_fd < 0) 1287 return -EBADF; 1288 1289 pmap = (decltype(pmap))mmap(NULL, length, PROT_READ, MAP_PRIVATE, 1290 sim_fd, offset); 1291 1292 if (pmap == (decltype(pmap))-1) { 1293 warn("mmap: failed to map file into host address space"); 1294 return -errno; 1295 } 1296 } 1297 1298 // Extend global mmap region if necessary. Note that we ignore the 1299 // start address unless MAP_FIXED is specified. 1300 if (!(tgt_flags & OS::TGT_MAP_FIXED)) { 1301 start = (OS::mmapGrowsDown()) ? p->mmap_end - length : p->mmap_end; 1302 p->mmap_end = (OS::mmapGrowsDown()) ? start : p->mmap_end + length; 1303 } 1304 1305 DPRINTF_SYSCALL(Verbose, " mmap range is 0x%x - 0x%x\n", 1306 start, start + length - 1); 1307 1308 // We only allow mappings to overwrite existing mappings if 1309 // TGT_MAP_FIXED is set. Otherwise it shouldn't be a problem 1310 // because we ignore the start hint if TGT_MAP_FIXED is not set. 1311 int clobber = tgt_flags & OS::TGT_MAP_FIXED; 1312 if (clobber) { 1313 for (auto tc : p->system->threadContexts) { 1314 // If we might be overwriting old mappings, we need to 1315 // invalidate potentially stale mappings out of the TLBs. 1316 tc->getDTBPtr()->flushAll(); 1317 tc->getITBPtr()->flushAll(); 1318 } 1319 } 1320 1321 // Allocate physical memory and map it in. If the page table is already 1322 // mapped and clobber is not set, the simulator will issue throw a 1323 // fatal and bail out of the simulation. 1324 p->allocateMem(start, length, clobber); 1325 1326 // Transfer content into target address space. 1327 SETranslatingPortProxy &tp = tc->getMemProxy(); 1328 if (tgt_flags & OS::TGT_MAP_ANONYMOUS) { 1329 // In general, we should zero the mapped area for anonymous mappings, 1330 // with something like: 1331 // tp.memsetBlob(start, 0, length); 1332 // However, given that we don't support sparse mappings, and 1333 // some applications can map a couple of gigabytes of space 1334 // (intending sparse usage), that can get painfully expensive. 1335 // Fortunately, since we don't properly implement munmap either, 1336 // there's no danger of remapping used memory, so for now all 1337 // newly mapped memory should already be zeroed so we can skip it. 1338 } else { 1339 // It is possible to mmap an area larger than a file, however 1340 // accessing unmapped portions the system triggers a "Bus error" 1341 // on the host. We must know when to stop copying the file from 1342 // the host into the target address space. 1343 struct stat file_stat; 1344 if (fstat(sim_fd, &file_stat) > 0) 1345 fatal("mmap: cannot stat file"); 1346 1347 // Copy the portion of the file that is resident. This requires 1348 // checking both the mmap size and the filesize that we are 1349 // trying to mmap into this space; the mmap size also depends 1350 // on the specified offset into the file. 1351 uint64_t size = std::min((uint64_t)file_stat.st_size - offset, 1352 length); 1353 tp.writeBlob(start, pmap, size); 1354 1355 // Cleanup the mmap region before exiting this function. 1356 munmap(pmap, length); 1357 1358 // Note that we do not zero out the remainder of the mapping. This 1359 // is done by a real system, but it probably will not affect 1360 // execution (hopefully). 1361 } 1362 1363 return start; 1364} 1365 1366/// Target getrlimit() handler. 1367template <class OS> 1368SyscallReturn 1369getrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1370 ThreadContext *tc) 1371{ 1372 int index = 0; 1373 unsigned resource = process->getSyscallArg(tc, index); 1374 TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index)); 1375 1376 switch (resource) { 1377 case OS::TGT_RLIMIT_STACK: 1378 // max stack size in bytes: make up a number (8MB for now) 1379 rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024; 1380 rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 1381 rlp->rlim_max = TheISA::htog(rlp->rlim_max); 1382 break; 1383 1384 case OS::TGT_RLIMIT_DATA: 1385 // max data segment size in bytes: make up a number 1386 rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024; 1387 rlp->rlim_cur = TheISA::htog(rlp->rlim_cur); 1388 rlp->rlim_max = TheISA::htog(rlp->rlim_max); 1389 break; 1390 1391 default: 1392 warn("getrlimit: unimplemented resource %d", resource); 1393 return -EINVAL; 1394 break; 1395 } 1396 1397 rlp.copyOut(tc->getMemProxy()); 1398 return 0; 1399} 1400 1401/// Target clock_gettime() function. 1402template <class OS> 1403SyscallReturn 1404clock_gettimeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 1405{ 1406 int index = 1; 1407 //int clk_id = p->getSyscallArg(tc, index); 1408 TypedBufferArg<typename OS::timespec> tp(p->getSyscallArg(tc, index)); 1409 1410 getElapsedTimeNano(tp->tv_sec, tp->tv_nsec); 1411 tp->tv_sec += seconds_since_epoch; 1412 tp->tv_sec = TheISA::htog(tp->tv_sec); 1413 tp->tv_nsec = TheISA::htog(tp->tv_nsec); 1414 1415 tp.copyOut(tc->getMemProxy()); 1416 1417 return 0; 1418} 1419 1420/// Target clock_getres() function. 1421template <class OS> 1422SyscallReturn 1423clock_getresFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) 1424{ 1425 int index = 1; 1426 TypedBufferArg<typename OS::timespec> tp(p->getSyscallArg(tc, index)); 1427 1428 // Set resolution at ns, which is what clock_gettime() returns 1429 tp->tv_sec = 0; 1430 tp->tv_nsec = 1; 1431 1432 tp.copyOut(tc->getMemProxy()); 1433 1434 return 0; 1435} 1436 1437/// Target gettimeofday() handler. 1438template <class OS> 1439SyscallReturn 1440gettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1441 ThreadContext *tc) 1442{ 1443 int index = 0; 1444 TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index)); 1445 1446 getElapsedTimeMicro(tp->tv_sec, tp->tv_usec); 1447 tp->tv_sec += seconds_since_epoch; 1448 tp->tv_sec = TheISA::htog(tp->tv_sec); 1449 tp->tv_usec = TheISA::htog(tp->tv_usec); 1450 1451 tp.copyOut(tc->getMemProxy()); 1452 1453 return 0; 1454} 1455 1456 1457/// Target utimes() handler. 1458template <class OS> 1459SyscallReturn 1460utimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1461 ThreadContext *tc) 1462{ 1463 std::string path; 1464 1465 int index = 0; 1466 if (!tc->getMemProxy().tryReadString(path, 1467 process->getSyscallArg(tc, index))) { 1468 return -EFAULT; 1469 } 1470 1471 TypedBufferArg<typename OS::timeval [2]> 1472 tp(process->getSyscallArg(tc, index)); 1473 tp.copyIn(tc->getMemProxy()); 1474 1475 struct timeval hostTimeval[2]; 1476 for (int i = 0; i < 2; ++i) 1477 { 1478 hostTimeval[i].tv_sec = TheISA::gtoh((*tp)[i].tv_sec); 1479 hostTimeval[i].tv_usec = TheISA::gtoh((*tp)[i].tv_usec); 1480 } 1481 1482 // Adjust path for current working directory 1483 path = process->fullPath(path); 1484 1485 int result = utimes(path.c_str(), hostTimeval); 1486 1487 if (result < 0) 1488 return -errno; 1489 1490 return 0; 1491} 1492/// Target getrusage() function. 1493template <class OS> 1494SyscallReturn 1495getrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1496 ThreadContext *tc) 1497{ 1498 int index = 0; 1499 int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN 1500 TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index)); 1501 1502 rup->ru_utime.tv_sec = 0; 1503 rup->ru_utime.tv_usec = 0; 1504 rup->ru_stime.tv_sec = 0; 1505 rup->ru_stime.tv_usec = 0; 1506 rup->ru_maxrss = 0; 1507 rup->ru_ixrss = 0; 1508 rup->ru_idrss = 0; 1509 rup->ru_isrss = 0; 1510 rup->ru_minflt = 0; 1511 rup->ru_majflt = 0; 1512 rup->ru_nswap = 0; 1513 rup->ru_inblock = 0; 1514 rup->ru_oublock = 0; 1515 rup->ru_msgsnd = 0; 1516 rup->ru_msgrcv = 0; 1517 rup->ru_nsignals = 0; 1518 rup->ru_nvcsw = 0; 1519 rup->ru_nivcsw = 0; 1520 1521 switch (who) { 1522 case OS::TGT_RUSAGE_SELF: 1523 getElapsedTimeMicro(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec); 1524 rup->ru_utime.tv_sec = TheISA::htog(rup->ru_utime.tv_sec); 1525 rup->ru_utime.tv_usec = TheISA::htog(rup->ru_utime.tv_usec); 1526 break; 1527 1528 case OS::TGT_RUSAGE_CHILDREN: 1529 // do nothing. We have no child processes, so they take no time. 1530 break; 1531 1532 default: 1533 // don't really handle THREAD or CHILDREN, but just warn and 1534 // plow ahead 1535 warn("getrusage() only supports RUSAGE_SELF. Parameter %d ignored.", 1536 who); 1537 } 1538 1539 rup.copyOut(tc->getMemProxy()); 1540 1541 return 0; 1542} 1543 1544/// Target times() function. 1545template <class OS> 1546SyscallReturn 1547timesFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1548 ThreadContext *tc) 1549{ 1550 int index = 0; 1551 TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index)); 1552 1553 // Fill in the time structure (in clocks) 1554 int64_t clocks = curTick() * OS::M5_SC_CLK_TCK / SimClock::Int::s; 1555 bufp->tms_utime = clocks; 1556 bufp->tms_stime = 0; 1557 bufp->tms_cutime = 0; 1558 bufp->tms_cstime = 0; 1559 1560 // Convert to host endianness 1561 bufp->tms_utime = TheISA::htog(bufp->tms_utime); 1562 1563 // Write back 1564 bufp.copyOut(tc->getMemProxy()); 1565 1566 // Return clock ticks since system boot 1567 return clocks; 1568} 1569 1570/// Target time() function. 1571template <class OS> 1572SyscallReturn 1573timeFunc(SyscallDesc *desc, int callnum, LiveProcess *process, 1574 ThreadContext *tc) 1575{ 1576 typename OS::time_t sec, usec; 1577 getElapsedTimeMicro(sec, usec); 1578 sec += seconds_since_epoch; 1579 1580 int index = 0; 1581 Addr taddr = (Addr)process->getSyscallArg(tc, index); 1582 if (taddr != 0) { 1583 typename OS::time_t t = sec; 1584 t = TheISA::htog(t); 1585 SETranslatingPortProxy &p = tc->getMemProxy(); 1586 p.writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t)); 1587 } 1588 return sec; 1589} 1590 1591 1592#endif // __SIM_SYSCALL_EMUL_HH__ 1593