syscall_emul.hh (13569:47a2291177a7) syscall_emul.hh (13570:b6484720c6a9)
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

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

73/// This file defines objects used to emulate syscalls from the target
74/// application on the host machine.
75
76#ifdef __CYGWIN32__
77#include <sys/fcntl.h>
78
79#endif
80#include <fcntl.h>
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

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

73/// This file defines objects used to emulate syscalls from the target
74/// application on the host machine.
75
76#ifdef __CYGWIN32__
77#include <sys/fcntl.h>
78
79#endif
80#include <fcntl.h>
81#include <poll.h>
81#include <sys/mman.h>
82#include <sys/socket.h>
83#include <sys/stat.h>
84#if (NO_STATFS == 0)
85#include <sys/statfs.h>
86#else
87#include <sys/mount.h>
88#endif
89#include <sys/time.h>
82#include <sys/mman.h>
83#include <sys/socket.h>
84#include <sys/stat.h>
85#if (NO_STATFS == 0)
86#include <sys/statfs.h>
87#else
88#include <sys/mount.h>
89#endif
90#include <sys/time.h>
91#include <sys/types.h>
90#include <sys/uio.h>
91#include <unistd.h>
92
93#include <cerrno>
94#include <memory>
95#include <string>
96
97#include "arch/generic/tlb.hh"

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

157/// Target brk() handler: set brk address.
158SyscallReturn brkFunc(SyscallDesc *desc, int num,
159 Process *p, ThreadContext *tc);
160
161/// Target close() handler.
162SyscallReturn closeFunc(SyscallDesc *desc, int num,
163 Process *p, ThreadContext *tc);
164
92#include <sys/uio.h>
93#include <unistd.h>
94
95#include <cerrno>
96#include <memory>
97#include <string>
98
99#include "arch/generic/tlb.hh"

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

159/// Target brk() handler: set brk address.
160SyscallReturn brkFunc(SyscallDesc *desc, int num,
161 Process *p, ThreadContext *tc);
162
163/// Target close() handler.
164SyscallReturn closeFunc(SyscallDesc *desc, int num,
165 Process *p, ThreadContext *tc);
166
165// Target read() handler.
166SyscallReturn readFunc(SyscallDesc *desc, int num,
167 Process *p, ThreadContext *tc);
168
169/// Target write() handler.
170SyscallReturn writeFunc(SyscallDesc *desc, int num,
171 Process *p, ThreadContext *tc);
172
173/// Target lseek() handler.
174SyscallReturn lseekFunc(SyscallDesc *desc, int num,
175 Process *p, ThreadContext *tc);
176
177/// Target _llseek() handler.
178SyscallReturn _llseekFunc(SyscallDesc *desc, int num,
179 Process *p, ThreadContext *tc);
180

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

941 // do the chmod
942 int result = chmod(path.c_str(), hostMode);
943 if (result < 0)
944 return -errno;
945
946 return 0;
947}
948
167/// Target lseek() handler.
168SyscallReturn lseekFunc(SyscallDesc *desc, int num,
169 Process *p, ThreadContext *tc);
170
171/// Target _llseek() handler.
172SyscallReturn _llseekFunc(SyscallDesc *desc, int num,
173 Process *p, ThreadContext *tc);
174

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

935 // do the chmod
936 int result = chmod(path.c_str(), hostMode);
937 if (result < 0)
938 return -errno;
939
940 return 0;
941}
942
943template <class OS>
944SyscallReturn
945pollFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
946{
947 int index = 0;
948 Addr fdsPtr = p->getSyscallArg(tc, index);
949 int nfds = p->getSyscallArg(tc, index);
950 int tmout = p->getSyscallArg(tc, index);
949
951
952 BufferArg fdsBuf(fdsPtr, sizeof(struct pollfd) * nfds);
953 fdsBuf.copyIn(tc->getMemProxy());
954
955 /**
956 * Record the target file descriptors in a local variable. We need to
957 * replace them with host file descriptors but we need a temporary copy
958 * for later. Afterwards, replace each target file descriptor in the
959 * poll_fd array with its host_fd.
960 */
961 int temp_tgt_fds[nfds];
962 for (index = 0; index < nfds; index++) {
963 temp_tgt_fds[index] = ((struct pollfd *)fdsBuf.bufferPtr())[index].fd;
964 auto tgt_fd = temp_tgt_fds[index];
965 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
966 if (!hbfdp)
967 return -EBADF;
968 auto host_fd = hbfdp->getSimFD();
969 ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = host_fd;
970 }
971
972 /**
973 * We cannot allow an infinite poll to occur or it will inevitably cause
974 * a deadlock in the gem5 simulator with clone. We must pass in tmout with
975 * a non-negative value, however it also makes no sense to poll on the
976 * underlying host for any other time than tmout a zero timeout.
977 */
978 int status;
979 if (tmout < 0) {
980 status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0);
981 if (status == 0) {
982 /**
983 * If blocking indefinitely, check the signal list to see if a
984 * signal would break the poll out of the retry cycle and try
985 * to return the signal interrupt instead.
986 */
987 System *sysh = tc->getSystemPtr();
988 std::list<BasicSignal>::iterator it;
989 for (it=sysh->signalList.begin(); it!=sysh->signalList.end(); it++)
990 if (it->receiver == p)
991 return -EINTR;
992 return SyscallReturn::retry();
993 }
994 } else
995 status = poll((struct pollfd *)fdsBuf.bufferPtr(), nfds, 0);
996
997 if (status == -1)
998 return -errno;
999
1000 /**
1001 * Replace each host_fd in the returned poll_fd array with its original
1002 * target file descriptor.
1003 */
1004 for (index = 0; index < nfds; index++) {
1005 auto tgt_fd = temp_tgt_fds[index];
1006 ((struct pollfd *)fdsBuf.bufferPtr())[index].fd = tgt_fd;
1007 }
1008
1009 /**
1010 * Copy out the pollfd struct because the host may have updated fields
1011 * in the structure.
1012 */
1013 fdsBuf.copyOut(tc->getMemProxy());
1014
1015 return status;
1016}
1017
950/// Target fchmod() handler.
951template <class OS>
952SyscallReturn
953fchmodFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
954{
955 int index = 0;
956 int tgt_fd = p->getSyscallArg(tc, index);
957 uint32_t mode = p->getSyscallArg(tc, index);

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

1264 if (result < 0)
1265 return -errno;
1266
1267 copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (sim_fd == 1));
1268
1269 return 0;
1270}
1271
1018/// Target fchmod() handler.
1019template <class OS>
1020SyscallReturn
1021fchmodFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
1022{
1023 int index = 0;
1024 int tgt_fd = p->getSyscallArg(tc, index);
1025 uint32_t mode = p->getSyscallArg(tc, index);

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

1332 if (result < 0)
1333 return -errno;
1334
1335 copyOutStatBuf<OS>(tc->getMemProxy(), bufPtr, &hostBuf, (sim_fd == 1));
1336
1337 return 0;
1338}
1339
1272
1273/// Target statfs() handler.
1274template <class OS>
1275SyscallReturn
1276statfsFunc(SyscallDesc *desc, int callnum, Process *process,
1277 ThreadContext *tc)
1278{
1279#if NO_STATFS
1280 warn("Host OS cannot support calls to statfs. Ignoring syscall");

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

2153 fds[0] = p->fds->allocFD(sfdp1);
2154 auto sfdp2 = std::make_shared<SocketFDEntry>(fds[1], domain, type, prot);
2155 fds[1] = p->fds->allocFD(sfdp2);
2156 svBuf.copyOut(tc->getMemProxy());
2157
2158 return status;
2159}
2160
1340/// Target statfs() handler.
1341template <class OS>
1342SyscallReturn
1343statfsFunc(SyscallDesc *desc, int callnum, Process *process,
1344 ThreadContext *tc)
1345{
1346#if NO_STATFS
1347 warn("Host OS cannot support calls to statfs. Ignoring syscall");

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

2220 fds[0] = p->fds->allocFD(sfdp1);
2221 auto sfdp2 = std::make_shared<SocketFDEntry>(fds[1], domain, type, prot);
2222 fds[1] = p->fds->allocFD(sfdp2);
2223 svBuf.copyOut(tc->getMemProxy());
2224
2225 return status;
2226}
2227
2228template <class OS>
2229SyscallReturn
2230selectFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc)
2231{
2232 int retval;
2233
2234 int index = 0;
2235 int nfds_t = p->getSyscallArg(tc, index);
2236 Addr fds_read_ptr = p->getSyscallArg(tc, index);
2237 Addr fds_writ_ptr = p->getSyscallArg(tc, index);
2238 Addr fds_excp_ptr = p->getSyscallArg(tc, index);
2239 Addr time_val_ptr = p->getSyscallArg(tc, index);
2240
2241 TypedBufferArg<typename OS::fd_set> rd_t(fds_read_ptr);
2242 TypedBufferArg<typename OS::fd_set> wr_t(fds_writ_ptr);
2243 TypedBufferArg<typename OS::fd_set> ex_t(fds_excp_ptr);
2244 TypedBufferArg<typename OS::timeval> tp(time_val_ptr);
2245
2246 /**
2247 * Host fields. Notice that these use the definitions from the system
2248 * headers instead of the gem5 headers and libraries. If the host and
2249 * target have different header file definitions, this will not work.
2250 */
2251 fd_set rd_h;
2252 FD_ZERO(&rd_h);
2253 fd_set wr_h;
2254 FD_ZERO(&wr_h);
2255 fd_set ex_h;
2256 FD_ZERO(&ex_h);
2257
2258 /**
2259 * Copy in the fd_set from the target.
2260 */
2261 if (fds_read_ptr)
2262 rd_t.copyIn(tc->getMemProxy());
2263 if (fds_writ_ptr)
2264 wr_t.copyIn(tc->getMemProxy());
2265 if (fds_excp_ptr)
2266 ex_t.copyIn(tc->getMemProxy());
2267
2268 /**
2269 * We need to translate the target file descriptor set into a host file
2270 * descriptor set. This involves both our internal process fd array
2271 * and the fd_set defined in Linux header files. The nfds field also
2272 * needs to be updated as it will be only target specific after
2273 * retrieving it from the target; the nfds value is expected to be the
2274 * highest file descriptor that needs to be checked, so we need to extend
2275 * it out for nfds_h when we do the update.
2276 */
2277 int nfds_h = 0;
2278 std::map<int, int> trans_map;
2279 auto try_add_host_set = [&](fd_set *tgt_set_entry,
2280 fd_set *hst_set_entry,
2281 int iter) -> bool
2282 {
2283 /**
2284 * By this point, we know that we are looking at a valid file
2285 * descriptor set on the target. We need to check if the target file
2286 * descriptor value passed in as iter is part of the set.
2287 */
2288 if (FD_ISSET(iter, tgt_set_entry)) {
2289 /**
2290 * We know that the target file descriptor belongs to the set,
2291 * but we do not yet know if the file descriptor is valid or
2292 * that we have a host mapping. Check that now.
2293 */
2294 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[iter]);
2295 if (!hbfdp)
2296 return true;
2297 auto sim_fd = hbfdp->getSimFD();
2298
2299 /**
2300 * Add the sim_fd to tgt_fd translation into trans_map for use
2301 * later when we need to zero the target fd_set structures and
2302 * then update them with hits returned from the host select call.
2303 */
2304 trans_map[sim_fd] = iter;
2305
2306 /**
2307 * We know that the host file descriptor exists so now we check
2308 * if we need to update the max count for nfds_h before passing
2309 * the duplicated structure into the host.
2310 */
2311 nfds_h = std::max(nfds_h - 1, sim_fd + 1);
2312
2313 /**
2314 * Add the host file descriptor to the set that we are going to
2315 * pass into the host.
2316 */
2317 FD_SET(sim_fd, hst_set_entry);
2318 }
2319 return false;
2320 };
2321
2322 for (int i = 0; i < nfds_t; i++) {
2323 if (fds_read_ptr) {
2324 bool ebadf = try_add_host_set((fd_set*)&*rd_t, &rd_h, i);
2325 if (ebadf) return -EBADF;
2326 }
2327 if (fds_writ_ptr) {
2328 bool ebadf = try_add_host_set((fd_set*)&*wr_t, &wr_h, i);
2329 if (ebadf) return -EBADF;
2330 }
2331 if (fds_excp_ptr) {
2332 bool ebadf = try_add_host_set((fd_set*)&*ex_t, &ex_h, i);
2333 if (ebadf) return -EBADF;
2334 }
2335 }
2336
2337 if (time_val_ptr) {
2338 /**
2339 * It might be possible to decrement the timeval based on some
2340 * derivation of wall clock determined from elapsed simulator ticks
2341 * but that seems like overkill. Rather, we just set the timeval with
2342 * zero timeout. (There is no reason to block during the simulation
2343 * as it only decreases simulator performance.)
2344 */
2345 tp->tv_sec = 0;
2346 tp->tv_usec = 0;
2347
2348 retval = select(nfds_h,
2349 fds_read_ptr ? &rd_h : nullptr,
2350 fds_writ_ptr ? &wr_h : nullptr,
2351 fds_excp_ptr ? &ex_h : nullptr,
2352 (timeval*)&*tp);
2353 } else {
2354 /**
2355 * If the timeval pointer is null, setup a new timeval structure to
2356 * pass into the host select call. Unfortunately, we will need to
2357 * manually check the return value and throw a retry fault if the
2358 * return value is zero. Allowing the system call to block will
2359 * likely deadlock the event queue.
2360 */
2361 struct timeval tv = { 0, 0 };
2362
2363 retval = select(nfds_h,
2364 fds_read_ptr ? &rd_h : nullptr,
2365 fds_writ_ptr ? &wr_h : nullptr,
2366 fds_excp_ptr ? &ex_h : nullptr,
2367 &tv);
2368
2369 if (retval == 0) {
2370 /**
2371 * If blocking indefinitely, check the signal list to see if a
2372 * signal would break the poll out of the retry cycle and try to
2373 * return the signal interrupt instead.
2374 */
2375 for (auto sig : tc->getSystemPtr()->signalList)
2376 if (sig.receiver == p)
2377 return -EINTR;
2378 return SyscallReturn::retry();
2379 }
2380 }
2381
2382 if (retval == -1)
2383 return -errno;
2384
2385 FD_ZERO((fd_set*)&*rd_t);
2386 FD_ZERO((fd_set*)&*wr_t);
2387 FD_ZERO((fd_set*)&*ex_t);
2388
2389 /**
2390 * We need to translate the host file descriptor set into a target file
2391 * descriptor set. This involves both our internal process fd array
2392 * and the fd_set defined in header files.
2393 */
2394 for (int i = 0; i < nfds_h; i++) {
2395 if (fds_read_ptr) {
2396 if (FD_ISSET(i, &rd_h))
2397 FD_SET(trans_map[i], (fd_set*)&*rd_t);
2398 }
2399
2400 if (fds_writ_ptr) {
2401 if (FD_ISSET(i, &wr_h))
2402 FD_SET(trans_map[i], (fd_set*)&*wr_t);
2403 }
2404
2405 if (fds_excp_ptr) {
2406 if (FD_ISSET(i, &ex_h))
2407 FD_SET(trans_map[i], (fd_set*)&*ex_t);
2408 }
2409 }
2410
2411 if (fds_read_ptr)
2412 rd_t.copyOut(tc->getMemProxy());
2413 if (fds_writ_ptr)
2414 wr_t.copyOut(tc->getMemProxy());
2415 if (fds_excp_ptr)
2416 ex_t.copyOut(tc->getMemProxy());
2417 if (time_val_ptr)
2418 tp.copyOut(tc->getMemProxy());
2419
2420 return retval;
2421}
2422
2423template <class OS>
2424SyscallReturn
2425readFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
2426{
2427 int index = 0;
2428 int tgt_fd = p->getSyscallArg(tc, index);
2429 Addr buf_ptr = p->getSyscallArg(tc, index);
2430 int nbytes = p->getSyscallArg(tc, index);
2431
2432 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
2433 if (!hbfdp)
2434 return -EBADF;
2435 int sim_fd = hbfdp->getSimFD();
2436
2437 struct pollfd pfd;
2438 pfd.fd = sim_fd;
2439 pfd.events = POLLIN | POLLPRI;
2440 if ((poll(&pfd, 1, 0) == 0)
2441 && !(hbfdp->getFlags() & OS::TGT_O_NONBLOCK))
2442 return SyscallReturn::retry();
2443
2444 BufferArg buf_arg(buf_ptr, nbytes);
2445 int bytes_read = read(sim_fd, buf_arg.bufferPtr(), nbytes);
2446
2447 if (bytes_read > 0)
2448 buf_arg.copyOut(tc->getMemProxy());
2449
2450 return (bytes_read == -1) ? -errno : bytes_read;
2451}
2452
2453template <class OS>
2454SyscallReturn
2455writeFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
2456{
2457 int index = 0;
2458 int tgt_fd = p->getSyscallArg(tc, index);
2459 Addr buf_ptr = p->getSyscallArg(tc, index);
2460 int nbytes = p->getSyscallArg(tc, index);
2461
2462 auto hbfdp = std::dynamic_pointer_cast<HBFDEntry>((*p->fds)[tgt_fd]);
2463 if (!hbfdp)
2464 return -EBADF;
2465 int sim_fd = hbfdp->getSimFD();
2466
2467 BufferArg buf_arg(buf_ptr, nbytes);
2468 buf_arg.copyIn(tc->getMemProxy());
2469
2470 struct pollfd pfd;
2471 pfd.fd = sim_fd;
2472 pfd.events = POLLOUT;
2473
2474 /**
2475 * We don't want to poll on /dev/random. The kernel will not enable the
2476 * file descriptor for writing unless the entropy in the system falls
2477 * below write_wakeup_threshold. This is not guaranteed to happen
2478 * depending on host settings.
2479 */
2480 auto ffdp = std::dynamic_pointer_cast<FileFDEntry>(hbfdp);
2481 if (ffdp && (ffdp->getFileName() != "/dev/random")) {
2482 if (!poll(&pfd, 1, 0) && !(ffdp->getFlags() & OS::TGT_O_NONBLOCK))
2483 return SyscallReturn::retry();
2484 }
2485
2486 int bytes_written = write(sim_fd, buf_arg.bufferPtr(), nbytes);
2487
2488 if (bytes_written != -1)
2489 fsync(sim_fd);
2490
2491 return (bytes_written == -1) ? -errno : bytes_written;
2492}
2493
2494template <class OS>
2495SyscallReturn
2496wait4Func(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
2497{
2498 int index = 0;
2499 pid_t pid = p->getSyscallArg(tc, index);
2500 Addr statPtr = p->getSyscallArg(tc, index);
2501 int options = p->getSyscallArg(tc, index);
2502 Addr rusagePtr = p->getSyscallArg(tc, index);
2503
2504 if (rusagePtr)
2505 DPRINTFR(SyscallVerbose,
2506 "%d: %s: syscall wait4: rusage pointer provided however "
2507 "functionality not supported. Ignoring rusage pointer.\n",
2508 curTick(), tc->getCpuPtr()->name());
2509
2510 /**
2511 * Currently, wait4 is only implemented so that it will wait for children
2512 * exit conditions which are denoted by a SIGCHLD signals posted into the
2513 * system signal list. We return no additional information via any of the
2514 * parameters supplied to wait4. If nothing is found in the system signal
2515 * list, we will wait indefinitely for SIGCHLD to post by retrying the
2516 * call.
2517 */
2518 System *sysh = tc->getSystemPtr();
2519 std::list<BasicSignal>::iterator iter;
2520 for (iter=sysh->signalList.begin(); iter!=sysh->signalList.end(); iter++) {
2521 if (iter->receiver == p) {
2522 if (pid < -1) {
2523 if ((iter->sender->pgid() == -pid)
2524 && (iter->signalValue == OS::TGT_SIGCHLD))
2525 goto success;
2526 } else if (pid == -1) {
2527 if (iter->signalValue == OS::TGT_SIGCHLD)
2528 goto success;
2529 } else if (pid == 0) {
2530 if ((iter->sender->pgid() == p->pgid())
2531 && (iter->signalValue == OS::TGT_SIGCHLD))
2532 goto success;
2533 } else {
2534 if ((iter->sender->pid() == pid)
2535 && (iter->signalValue == OS::TGT_SIGCHLD))
2536 goto success;
2537 }
2538 }
2539 }
2540
2541 return (options & OS::TGT_WNOHANG) ? 0 : SyscallReturn::retry();
2542
2543success:
2544 // Set status to EXITED for WIFEXITED evaluations.
2545 const int EXITED = 0;
2546 BufferArg statusBuf(statPtr, sizeof(int));
2547 *(int *)statusBuf.bufferPtr() = EXITED;
2548 statusBuf.copyOut(tc->getMemProxy());
2549
2550 // Return the child PID.
2551 pid_t retval = iter->sender->pid();
2552 sysh->signalList.erase(iter);
2553 return retval;
2554}
2555
2556template <class OS>
2557SyscallReturn
2558acceptFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
2559{
2560 struct sockaddr sa;
2561 socklen_t addrLen;
2562 int host_fd;
2563 int index = 0;
2564 int tgt_fd = p->getSyscallArg(tc, index);
2565 Addr addrPtr = p->getSyscallArg(tc, index);
2566 Addr lenPtr = p->getSyscallArg(tc, index);
2567
2568 BufferArg *lenBufPtr = nullptr;
2569 BufferArg *addrBufPtr = nullptr;
2570
2571 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
2572 if (!sfdp)
2573 return -EBADF;
2574 int sim_fd = sfdp->getSimFD();
2575
2576 /**
2577 * We poll the socket file descriptor first to guarantee that we do not
2578 * block on our accept call. The socket can be opened without the
2579 * non-blocking flag (it blocks). This will cause deadlocks between
2580 * communicating processes.
2581 */
2582 struct pollfd pfd;
2583 pfd.fd = sim_fd;
2584 pfd.events = POLLIN | POLLPRI;
2585 if ((poll(&pfd, 1, 0) == 0)
2586 && !(sfdp->getFlags() & OS::TGT_O_NONBLOCK))
2587 return SyscallReturn::retry();
2588
2589 if (lenPtr) {
2590 lenBufPtr = new BufferArg(lenPtr, sizeof(socklen_t));
2591 lenBufPtr->copyIn(tc->getMemProxy());
2592 memcpy(&addrLen, (socklen_t *)lenBufPtr->bufferPtr(),
2593 sizeof(socklen_t));
2594 }
2595
2596 if (addrPtr) {
2597 addrBufPtr = new BufferArg(addrPtr, sizeof(struct sockaddr));
2598 addrBufPtr->copyIn(tc->getMemProxy());
2599 memcpy(&sa, (struct sockaddr *)addrBufPtr->bufferPtr(),
2600 sizeof(struct sockaddr));
2601 }
2602
2603 host_fd = accept(sim_fd, &sa, &addrLen);
2604
2605 if (host_fd == -1)
2606 return -errno;
2607
2608 if (addrPtr) {
2609 memcpy(addrBufPtr->bufferPtr(), &sa, sizeof(sa));
2610 addrBufPtr->copyOut(tc->getMemProxy());
2611 delete(addrBufPtr);
2612 }
2613
2614 if (lenPtr) {
2615 *(socklen_t *)lenBufPtr->bufferPtr() = addrLen;
2616 lenBufPtr->copyOut(tc->getMemProxy());
2617 delete(lenBufPtr);
2618 }
2619
2620 auto afdp = std::make_shared<SocketFDEntry>(host_fd, sfdp->_domain,
2621 sfdp->_type, sfdp->_protocol);
2622 return p->fds->allocFD(afdp);
2623}
2624
2161#endif // __SIM_SYSCALL_EMUL_HH__
2625#endif // __SIM_SYSCALL_EMUL_HH__