sim-se: add ability to get/set sock metadata

Add getsockopt, getsockname, setsockname, and getpeername
system calls.

Change-Id: Ifa1d9a95f15b4fb12859dbfd3c4bd248de2e3d32
Reviewed-on: https://gem5-review.googlesource.com/c/12116
Reviewed-by: Anthony Gutierrez <anthony.gutierrez@amd.com>
Maintainer: Anthony Gutierrez <anthony.gutierrez@amd.com>
This commit is contained in:
Brandon Potter
2018-04-18 15:00:14 -04:00
committed by Anthony Gutierrez
parent bc74c58eaf
commit 7936e63336
3 changed files with 154 additions and 4 deletions

View File

@@ -273,11 +273,11 @@ static SyscallDesc syscallDescs64[] = {
/* 48 */ SyscallDesc("shutdown", shutdownFunc),
/* 49 */ SyscallDesc("bind", bindFunc),
/* 50 */ SyscallDesc("listen", listenFunc),
/* 51 */ SyscallDesc("getsockname", unimplementedFunc),
/* 52 */ SyscallDesc("getpeername", unimplementedFunc),
/* 51 */ SyscallDesc("getsockname", getsocknameFunc),
/* 52 */ SyscallDesc("getpeername", getpeernameFunc),
/* 53 */ SyscallDesc("socketpair", socketpairFunc<X86Linux64>),
/* 54 */ SyscallDesc("setsockopt", unimplementedFunc),
/* 55 */ SyscallDesc("getsockopt", unimplementedFunc),
/* 54 */ SyscallDesc("setsockopt", setsockoptFunc),
/* 55 */ SyscallDesc("getsockopt", getsockoptFunc),
/* 56 */ SyscallDesc("clone", cloneFunc<X86Linux64>),
/* 57 */ SyscallDesc("fork", unimplementedFunc),
/* 58 */ SyscallDesc("vfork", unimplementedFunc),

View File

@@ -1567,3 +1567,137 @@ sendmsgFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
return (sent_size < 0) ? -local_errno : sent_size;
}
SyscallReturn
getsockoptFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
{
// union of all possible return value types from getsockopt
union val {
int i_val;
long l_val;
struct linger linger_val;
struct timeval timeval_val;
} val;
int index = 0;
int tgt_fd = p->getSyscallArg(tc, index);
int level = p->getSyscallArg(tc, index);
int optname = p->getSyscallArg(tc, index);
Addr valPtr = p->getSyscallArg(tc, index);
Addr lenPtr = p->getSyscallArg(tc, index);
auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
if (!sfdp)
return -EBADF;
int sim_fd = sfdp->getSimFD();
socklen_t len = sizeof(val);
int status = getsockopt(sim_fd, level, optname, &val, &len);
if (status == -1)
return -errno;
// copy val to valPtr and pass it on
BufferArg valBuf(valPtr, sizeof(val));
memcpy(valBuf.bufferPtr(), &val, sizeof(val));
valBuf.copyOut(tc->getMemProxy());
// copy len to lenPtr and pass it on
BufferArg lenBuf(lenPtr, sizeof(len));
memcpy(lenBuf.bufferPtr(), &len, sizeof(len));
lenBuf.copyOut(tc->getMemProxy());
return status;
}
SyscallReturn
getsocknameFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
{
int index = 0;
int tgt_fd = p->getSyscallArg(tc, index);
Addr addrPtr = p->getSyscallArg(tc, index);
Addr lenPtr = p->getSyscallArg(tc, index);
auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
if (!sfdp)
return -EBADF;
int sim_fd = sfdp->getSimFD();
// lenPtr is an in-out paramenter:
// sending the address length in, conveying the final length out
// Read in the value of len from the passed pointer.
BufferArg lenBuf(lenPtr, sizeof(socklen_t));
lenBuf.copyIn(tc->getMemProxy());
socklen_t len = *(socklen_t *)lenBuf.bufferPtr();
struct sockaddr sa;
int status = getsockname(sim_fd, &sa, &len);
if (status == -1)
return -errno;
// Copy address to addrPtr and pass it on.
BufferArg addrBuf(addrPtr, sizeof(sa));
memcpy(addrBuf.bufferPtr(), &sa, sizeof(sa));
addrBuf.copyOut(tc->getMemProxy());
// Copy len to lenPtr and pass it on.
*(socklen_t *)lenBuf.bufferPtr() = len;
lenBuf.copyOut(tc->getMemProxy());
return status;
}
SyscallReturn
getpeernameFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
{
int index = 0;
int tgt_fd = p->getSyscallArg(tc, index);
Addr sockAddrPtr = p->getSyscallArg(tc, index);
Addr addrlenPtr = p->getSyscallArg(tc, index);
auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
if (!sfdp)
return -EBADF;
int sim_fd = sfdp->getSimFD();
BufferArg bufAddrlen(addrlenPtr, sizeof(unsigned));
bufAddrlen.copyIn(tc->getMemProxy());
BufferArg bufSock(sockAddrPtr, *(unsigned *)bufAddrlen.bufferPtr());
int retval = getpeername(sim_fd,
(struct sockaddr *)bufSock.bufferPtr(),
(unsigned *)bufAddrlen.bufferPtr());
if (retval != -1) {
bufSock.copyOut(tc->getMemProxy());
bufAddrlen.copyOut(tc->getMemProxy());
}
return (retval == -1) ? -errno : retval;
}
SyscallReturn
setsockoptFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc)
{
int index = 0;
int tgt_fd = p->getSyscallArg(tc, index);
int level = p->getSyscallArg(tc, index);
int optname = p->getSyscallArg(tc, index);
Addr valPtr = p->getSyscallArg(tc, index);
socklen_t len = p->getSyscallArg(tc, index);
BufferArg valBuf(valPtr, len);
valBuf.copyIn(tc->getMemProxy());
auto sfdp = std::dynamic_pointer_cast<SocketFDEntry>((*p->fds)[tgt_fd]);
if (!sfdp)
return -EBADF;
int sim_fd = sfdp->getSimFD();
int status = setsockopt(sim_fd, level, optname,
(struct sockaddr *)valBuf.bufferPtr(), len);
return (status == -1) ? -errno : status;
}

View File

@@ -302,6 +302,10 @@ SyscallReturn pipeImpl(SyscallDesc *desc, int num, Process *p,
SyscallReturn getpidFunc(SyscallDesc *desc, int num,
Process *p, ThreadContext *tc);
// Target getpeername() handler.
SyscallReturn getpeernameFunc(SyscallDesc *desc, int num,
Process *p, ThreadContext *tc);
// Target bind() handler.
SyscallReturn bindFunc(SyscallDesc *desc, int num,
Process *p, ThreadContext *tc);
@@ -369,6 +373,18 @@ SyscallReturn accessFunc(SyscallDesc *desc, int num,
Process *p, ThreadContext *tc,
int index);
// Target getsockopt() handler.
SyscallReturn getsockoptFunc(SyscallDesc *desc, int num,
Process *p, ThreadContext *tc);
// Target setsockopt() handler.
SyscallReturn setsockoptFunc(SyscallDesc *desc, int num,
Process *p, ThreadContext *tc);
// Target getsockname() handler.
SyscallReturn getsocknameFunc(SyscallDesc *desc, int num,
Process *p, ThreadContext *tc);
/// Futex system call
/// Implemented by Daniel Sanchez
/// Used by printf's in multi-threaded apps