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

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

53/// @file syscall_emul.hh
54///
55/// This file defines objects used to emulate syscalls from the target
56/// application on the host machine.
57
58#ifdef __CYGWIN32__
59#include <sys/fcntl.h> // for O_BINARY
60#endif
1/*
2 * Copyright (c) 2012-2013, 2015 ARM Limited
3 * Copyright (c) 2015 Advanced Micro Devices, Inc.
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating

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

53/// @file syscall_emul.hh
54///
55/// This file defines objects used to emulate syscalls from the target
56/// application on the host machine.
57
58#ifdef __CYGWIN32__
59#include <sys/fcntl.h> // for O_BINARY
60#endif
61#include <sys/mman.h>
61#include <sys/stat.h>
62#include <sys/time.h>
63#include <sys/uio.h>
64#include <fcntl.h>
65
66#include <cerrno>
67#include <string>
68

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

1219 if (result < 0)
1220 return -errno;
1221
1222 return result;
1223}
1224
1225
1226/// Target mmap() handler.
62#include <sys/stat.h>
63#include <sys/time.h>
64#include <sys/uio.h>
65#include <fcntl.h>
66
67#include <cerrno>
68#include <string>
69

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

1220 if (result < 0)
1221 return -errno;
1222
1223 return result;
1224}
1225
1226
1227/// Target mmap() handler.
1227///
1228/// We don't really handle mmap(). If the target is mmaping an
1229/// anonymous region or /dev/zero, we can get away with doing basically
1230/// nothing (since memory is initialized to zero and the simulator
1231/// doesn't really check addresses anyway).
1232///
1233template <class OS>
1234SyscallReturn
1235mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
1236{
1237 int index = 0;
1238 Addr start = p->getSyscallArg(tc, index);
1239 uint64_t length = p->getSyscallArg(tc, index);
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);
1240 index++; // int prot = p->getSyscallArg(tc, index);
1241 int flags = p->getSyscallArg(tc, index);
1235 int prot = p->getSyscallArg(tc, index);
1236 int tgt_flags = p->getSyscallArg(tc, index);
1242 int tgt_fd = p->getSyscallArg(tc, index);
1243 int offset = p->getSyscallArg(tc, index);
1244
1237 int tgt_fd = p->getSyscallArg(tc, index);
1238 int offset = p->getSyscallArg(tc, index);
1239
1245 if (length > 0x100000000ULL)
1246 warn("mmap length argument %#x is unreasonably large.\n", length);
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);
1247
1243
1248 if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
1249 FDEntry *fde = p->getFDEntry(tgt_fd);
1250 if (!fde || fde->fd < 0) {
1251 warn("mmap failing: target fd %d is not valid\n", tgt_fd);
1252 return -EBADF;
1253 }
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 }
1254
1253
1255 if (fde->filename != "/dev/zero") {
1256 // This is very likely broken, but leave a warning here
1257 // (rather than panic) in case /dev/zero is known by
1258 // another name on some platform
1259 warn("allowing mmap of file %s; mmap not supported on files"
1260 " other than /dev/zero\n", fde->filename);
1261 }
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");
1262 }
1263
1264 length = roundUp(length, TheISA::PageBytes);
1265
1278 }
1279
1280 length = roundUp(length, TheISA::PageBytes);
1281
1266 if ((start % TheISA::PageBytes) != 0 ||
1267 (offset % TheISA::PageBytes) != 0) {
1268 warn("mmap failing: arguments not page-aligned: "
1269 "start 0x%x offset 0x%x",
1270 start, offset);
1271 return -EINVAL;
1272 }
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;
1273
1288
1274 // are we ok with clobbering existing mappings? only set this to
1275 // true if the user has been warned.
1276 bool clobber = false;
1289 pmap = (decltype(pmap))mmap(NULL, length, PROT_READ, MAP_PRIVATE,
1290 sim_fd, offset);
1277
1291
1278 // try to use the caller-provided address if there is one
1279 bool use_provided_address = (start != 0);
1280
1281 if (use_provided_address) {
1282 // check to see if the desired address is already in use
1283 if (!p->pTable->isUnmapped(start, length)) {
1284 // there are existing mappings in the desired range
1285 // whether we clobber them or not depends on whether the caller
1286 // specified MAP_FIXED
1287 if (flags & OS::TGT_MAP_FIXED) {
1288 // MAP_FIXED specified: map attempt fails
1289 return -EINVAL;
1290 } else {
1291 // MAP_FIXED not specified: ignore suggested start address
1292 warn("mmap: ignoring suggested map address 0x%x\n", start);
1293 use_provided_address = false;
1294 }
1292 if (pmap == (decltype(pmap))-1) {
1293 warn("mmap: failed to map file into host address space");
1294 return -errno;
1295 }
1296 }
1297
1295 }
1296 }
1297
1298 if (!use_provided_address) {
1299 // no address provided, or provided address unusable:
1300 // pick next address from our "mmap region"
1301 if (OS::mmapGrowsDown()) {
1302 start = p->mmap_end - length;
1303 p->mmap_end = start;
1304 } else {
1305 start = p->mmap_end;
1306 p->mmap_end += length;
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();
1307 }
1308 }
1309
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.
1310 p->allocateMem(start, length, clobber);
1311
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
1312 return start;
1313}
1314
1315/// Target getrlimit() handler.
1316template <class OS>
1317SyscallReturn
1318getrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
1319 ThreadContext *tc)

--- 222 unchanged lines hidden ---
1363 return start;
1364}
1365
1366/// Target getrlimit() handler.
1367template <class OS>
1368SyscallReturn
1369getrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
1370 ThreadContext *tc)

--- 222 unchanged lines hidden ---