syscall_emul.cc (13568:9c11b79e3223) syscall_emul.cc (13569:47a2291177a7)
1/*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;

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

1299 int sim_fd = sfdp->getSimFD();
1300
1301 int status = connect(sim_fd,
1302 (struct sockaddr *)addr.bufferPtr(),
1303 (socklen_t)addrlen);
1304
1305 return (status == -1) ? -errno : status;
1306}
1/*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;

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

1299 int sim_fd = sfdp->getSimFD();
1300
1301 int status = connect(sim_fd,
1302 (struct sockaddr *)addr.bufferPtr(),
1303 (socklen_t)addrlen);
1304
1305 return (status == -1) ? -errno : status;
1306}
1307
1308SyscallReturn
1309recvfromFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1310{
1311 int index = 0;
1312 int tgt_fd = p->getSyscallArg(tc, index);
1313 Addr bufrPtr = p->getSyscallArg(tc, index);
1314 size_t bufrLen = p->getSyscallArg(tc, index);
1315 int flags = p->getSyscallArg(tc, index);
1316 Addr addrPtr = p->getSyscallArg(tc, index);
1317 Addr addrlenPtr = p->getSyscallArg(tc, index);
1318
1319 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1320 if (!sfdp)
1321 return -EBADF;
1322 int sim_fd = sfdp->getSimFD();
1323
1324 // Reserve buffer space.
1325 BufferArg bufrBuf(bufrPtr, bufrLen);
1326
1327 // Get address length.
1328 socklen_t addrLen = 0;
1329 if (addrlenPtr != 0) {
1330 // Read address length parameter.
1331 BufferArg addrlenBuf(addrlenPtr, sizeof(socklen_t));
1332 addrlenBuf.copyIn(tc->getMemProxy());
1333 addrLen = *((socklen_t *)addrlenBuf.bufferPtr());
1334 }
1335
1336 struct sockaddr sa, *sap = NULL;
1337 if (addrLen != 0) {
1338 BufferArg addrBuf(addrPtr, addrLen);
1339 addrBuf.copyIn(tc->getMemProxy());
1340 memcpy(&sa, (struct sockaddr *)addrBuf.bufferPtr(),
1341 sizeof(struct sockaddr));
1342 sap = &sa;
1343 }
1344
1345 ssize_t recvd_size = recvfrom(sim_fd,
1346 (void *)bufrBuf.bufferPtr(),
1347 bufrLen, flags, sap, (socklen_t *)&addrLen);
1348
1349 if (recvd_size == -1)
1350 return -errno;
1351
1352 // Pass the received data out.
1353 bufrBuf.copyOut(tc->getMemProxy());
1354
1355 // Copy address to addrPtr and pass it on.
1356 if (sap != NULL) {
1357 BufferArg addrBuf(addrPtr, addrLen);
1358 memcpy(addrBuf.bufferPtr(), sap, sizeof(sa));
1359 addrBuf.copyOut(tc->getMemProxy());
1360 }
1361
1362 // Copy len to addrlenPtr and pass it on.
1363 if (addrLen != 0) {
1364 BufferArg addrlenBuf(addrlenPtr, sizeof(socklen_t));
1365 *(socklen_t *)addrlenBuf.bufferPtr() = addrLen;
1366 addrlenBuf.copyOut(tc->getMemProxy());
1367 }
1368
1369 return recvd_size;
1370}
1371
1372SyscallReturn
1373sendtoFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1374{
1375 int index = 0;
1376 int tgt_fd = p->getSyscallArg(tc, index);
1377 Addr bufrPtr = p->getSyscallArg(tc, index);
1378 size_t bufrLen = p->getSyscallArg(tc, index);
1379 int flags = p->getSyscallArg(tc, index);
1380 Addr addrPtr = p->getSyscallArg(tc, index);
1381 socklen_t addrLen = p->getSyscallArg(tc, index);
1382
1383 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1384 if (!sfdp)
1385 return -EBADF;
1386 int sim_fd = sfdp->getSimFD();
1387
1388 // Reserve buffer space.
1389 BufferArg bufrBuf(bufrPtr, bufrLen);
1390 bufrBuf.copyIn(tc->getMemProxy());
1391
1392 struct sockaddr sa, *sap = nullptr;
1393 memset(&sa, 0, sizeof(sockaddr));
1394 if (addrLen != 0) {
1395 BufferArg addrBuf(addrPtr, addrLen);
1396 addrBuf.copyIn(tc->getMemProxy());
1397 memcpy(&sa, (sockaddr*)addrBuf.bufferPtr(), addrLen);
1398 sap = &sa;
1399 }
1400
1401 ssize_t sent_size = sendto(sim_fd,
1402 (void *)bufrBuf.bufferPtr(),
1403 bufrLen, flags, sap, (socklen_t)addrLen);
1404
1405 return (sent_size == -1) ? -errno : sent_size;
1406}
1407
1408SyscallReturn
1409recvmsgFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1410{
1411 int index = 0;
1412 int tgt_fd = p->getSyscallArg(tc, index);
1413 Addr msgPtr = p->getSyscallArg(tc, index);
1414 int flags = p->getSyscallArg(tc, index);
1415
1416 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1417 if (!sfdp)
1418 return -EBADF;
1419 int sim_fd = sfdp->getSimFD();
1420
1421 /**
1422 * struct msghdr {
1423 * void *msg_name; // optional address
1424 * socklen_t msg_namelen; // size of address
1425 * struct iovec *msg_iov; // iovec array
1426 * size_t msg_iovlen; // number entries in msg_iov
1427 * i // entries correspond to buffer
1428 * void *msg_control; // ancillary data
1429 * size_t msg_controllen; // ancillary data buffer len
1430 * int msg_flags; // flags on received message
1431 * };
1432 *
1433 * struct iovec {
1434 * void *iov_base; // starting address
1435 * size_t iov_len; // number of bytes to transfer
1436 * };
1437 */
1438
1439 /**
1440 * The plan with this system call is to replace all of the pointers in the
1441 * structure and the substructure with BufferArg class pointers. We will
1442 * copy every field from the structures into our BufferArg classes.
1443 */
1444 BufferArg msgBuf(msgPtr, sizeof(struct msghdr));
1445 msgBuf.copyIn(tc->getMemProxy());
1446 struct msghdr *msgHdr = (struct msghdr *)msgBuf.bufferPtr();
1447
1448 /**
1449 * We will use these address place holders to retain the pointers which
1450 * we are going to replace with our own buffers in our simulator address
1451 * space.
1452 */
1453 Addr msg_name_phold = 0;
1454 Addr msg_iov_phold = 0;
1455 Addr iovec_base_phold[msgHdr->msg_iovlen];
1456 Addr msg_control_phold = 0;
1457
1458 /**
1459 * Record msg_name pointer then replace with buffer pointer.
1460 */
1461 BufferArg *nameBuf = NULL;
1462 if (msgHdr->msg_name) {
1463 /*1*/msg_name_phold = (Addr)msgHdr->msg_name;
1464 /*2*/nameBuf = new BufferArg(msg_name_phold, msgHdr->msg_namelen);
1465 /*3*/nameBuf->copyIn(tc->getMemProxy());
1466 /*4*/msgHdr->msg_name = nameBuf->bufferPtr();
1467 }
1468
1469 /**
1470 * Record msg_iov pointer then replace with buffer pointer. Also, setup
1471 * an array of buffer pointers for the iovec structs record and replace
1472 * their pointers with buffer pointers.
1473 */
1474 BufferArg *iovBuf = NULL;
1475 BufferArg *iovecBuf[msgHdr->msg_iovlen];
1476 for (int i = 0; i < msgHdr->msg_iovlen; i++) {
1477 iovec_base_phold[i] = 0;
1478 iovecBuf[i] = NULL;
1479 }
1480
1481 if (msgHdr->msg_iov) {
1482 /*1*/msg_iov_phold = (Addr)msgHdr->msg_iov;
1483 /*2*/iovBuf = new BufferArg(msg_iov_phold, msgHdr->msg_iovlen *
1484 sizeof(struct iovec));
1485 /*3*/iovBuf->copyIn(tc->getMemProxy());
1486 for (int i = 0; i < msgHdr->msg_iovlen; i++) {
1487 if (((struct iovec *)iovBuf->bufferPtr())[i].iov_base) {
1488 /*1*/iovec_base_phold[i] =
1489 (Addr)((struct iovec *)iovBuf->bufferPtr())[i].iov_base;
1490 /*2*/iovecBuf[i] = new BufferArg(iovec_base_phold[i],
1491 ((struct iovec *)iovBuf->bufferPtr())[i].iov_len);
1492 /*3*/iovecBuf[i]->copyIn(tc->getMemProxy());
1493 /*4*/((struct iovec *)iovBuf->bufferPtr())[i].iov_base =
1494 iovecBuf[i]->bufferPtr();
1495 }
1496 }
1497 /*4*/msgHdr->msg_iov = (struct iovec *)iovBuf->bufferPtr();
1498 }
1499
1500 /**
1501 * Record msg_control pointer then replace with buffer pointer.
1502 */
1503 BufferArg *controlBuf = NULL;
1504 if (msgHdr->msg_control) {
1505 /*1*/msg_control_phold = (Addr)msgHdr->msg_control;
1506 /*2*/controlBuf = new BufferArg(msg_control_phold,
1507 CMSG_ALIGN(msgHdr->msg_controllen));
1508 /*3*/controlBuf->copyIn(tc->getMemProxy());
1509 /*4*/msgHdr->msg_control = controlBuf->bufferPtr();
1510 }
1511
1512 ssize_t recvd_size = recvmsg(sim_fd, msgHdr, flags);
1513
1514 if (recvd_size < 0)
1515 return -errno;
1516
1517 if (msgHdr->msg_name) {
1518 nameBuf->copyOut(tc->getMemProxy());
1519 delete(nameBuf);
1520 msgHdr->msg_name = (void *)msg_name_phold;
1521 }
1522
1523 if (msgHdr->msg_iov) {
1524 for (int i = 0; i< msgHdr->msg_iovlen; i++) {
1525 if (((struct iovec *)iovBuf->bufferPtr())[i].iov_base) {
1526 iovecBuf[i]->copyOut(tc->getMemProxy());
1527 delete iovecBuf[i];
1528 ((struct iovec *)iovBuf->bufferPtr())[i].iov_base =
1529 (void *)iovec_base_phold[i];
1530 }
1531 }
1532 iovBuf->copyOut(tc->getMemProxy());
1533 delete iovBuf;
1534 msgHdr->msg_iov = (struct iovec *)msg_iov_phold;
1535 }
1536
1537 if (msgHdr->msg_control) {
1538 controlBuf->copyOut(tc->getMemProxy());
1539 delete(controlBuf);
1540 msgHdr->msg_control = (void *)msg_control_phold;
1541 }
1542
1543 msgBuf.copyOut(tc->getMemProxy());
1544
1545 return recvd_size;
1546}
1547
1548SyscallReturn
1549sendmsgFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
1550{
1551 int index = 0;
1552 int tgt_fd = p->getSyscallArg(tc, index);
1553 Addr msgPtr = p->getSyscallArg(tc, index);
1554 int flags = p->getSyscallArg(tc, index);
1555
1556 auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
1557 if (!sfdp)
1558 return -EBADF;
1559 int sim_fd = sfdp->getSimFD();
1560
1561 /**
1562 * Reserve buffer space.
1563 */
1564 BufferArg msgBuf(msgPtr, sizeof(struct msghdr));
1565 msgBuf.copyIn(tc->getMemProxy());
1566 struct msghdr msgHdr = *((struct msghdr *)msgBuf.bufferPtr());
1567
1568 /**
1569 * Assuming msgHdr.msg_iovlen >= 1, then there is no point calling
1570 * recvmsg without a buffer.
1571 */
1572 struct iovec *iovPtr = msgHdr.msg_iov;
1573 BufferArg iovBuf((Addr)iovPtr, sizeof(struct iovec) * msgHdr.msg_iovlen);
1574 iovBuf.copyIn(tc->getMemProxy());
1575 struct iovec *iov = (struct iovec *)iovBuf.bufferPtr();
1576 msgHdr.msg_iov = iov;
1577
1578 /**
1579 * Cannot instantiate buffers till inside the loop.
1580 * Create array to hold buffer addresses, to be used during copyIn of
1581 * send data.
1582 */
1583 BufferArg **bufferArray = (BufferArg **)malloc(msgHdr.msg_iovlen
1584 * sizeof(BufferArg *));
1585
1586 /**
1587 * Iterate through the iovec structures:
1588 * Get the base buffer addreses, reserve iov_len amount of space for each.
1589 * Put the buf address into the bufferArray for later retrieval.
1590 */
1591 for (int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
1592 Addr basePtr = (Addr) iov[iovIndex].iov_base;
1593 bufferArray[iovIndex] = new BufferArg(basePtr, iov[iovIndex].iov_len);
1594 bufferArray[iovIndex]->copyIn(tc->getMemProxy());
1595 iov[iovIndex].iov_base = bufferArray[iovIndex]->bufferPtr();
1596 }
1597
1598 ssize_t sent_size = sendmsg(sim_fd, &msgHdr, flags);
1599 int local_errno = errno;
1600
1601 /**
1602 * Free dynamically allocated memory.
1603 */
1604 for (int iovIndex = 0 ; iovIndex < msgHdr.msg_iovlen; iovIndex++) {
1605 BufferArg *baseBuf = ( BufferArg *)bufferArray[iovIndex];
1606 delete(baseBuf);
1607 }
1608
1609 /**
1610 * Malloced above.
1611 */
1612 free(bufferArray);
1613
1614 return (sent_size < 0) ? -local_errno : sent_size;
1615}
1616