syscall emulation: clean up & comment SyscallReturn
This commit is contained in:
@@ -220,19 +220,18 @@ AlphaLiveProcess::setSyscallArg(ThreadContext *tc,
|
||||
}
|
||||
|
||||
void
|
||||
AlphaLiveProcess::setSyscallReturn(ThreadContext *tc,
|
||||
SyscallReturn return_value)
|
||||
AlphaLiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
|
||||
{
|
||||
// check for error condition. Alpha syscall convention is to
|
||||
// indicate success/failure in reg a3 (r19) and put the
|
||||
// return value itself in the standard return value reg (v0).
|
||||
if (return_value.successful()) {
|
||||
if (sysret.successful()) {
|
||||
// no error
|
||||
tc->setIntReg(SyscallSuccessReg, 0);
|
||||
tc->setIntReg(ReturnValueReg, return_value.value());
|
||||
tc->setIntReg(ReturnValueReg, sysret.returnValue());
|
||||
} else {
|
||||
// got an error, return details
|
||||
tc->setIntReg(SyscallSuccessReg, (IntReg)-1);
|
||||
tc->setIntReg(ReturnValueReg, -return_value.value());
|
||||
tc->setIntReg(ReturnValueReg, sysret.errnoValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,15 +454,13 @@ ArmLiveProcess64::setSyscallArg(ThreadContext *tc,
|
||||
}
|
||||
|
||||
void
|
||||
ArmLiveProcess32::setSyscallReturn(ThreadContext *tc,
|
||||
SyscallReturn return_value)
|
||||
ArmLiveProcess32::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
|
||||
{
|
||||
tc->setIntReg(ReturnValueReg, return_value.value());
|
||||
tc->setIntReg(ReturnValueReg, sysret.encodedValue());
|
||||
}
|
||||
|
||||
void
|
||||
ArmLiveProcess64::setSyscallReturn(ThreadContext *tc,
|
||||
SyscallReturn return_value)
|
||||
ArmLiveProcess64::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
|
||||
{
|
||||
tc->setIntReg(ReturnValueReg, return_value.value());
|
||||
tc->setIntReg(ReturnValueReg, sysret.encodedValue());
|
||||
}
|
||||
|
||||
@@ -197,16 +197,15 @@ MipsLiveProcess::setSyscallArg(ThreadContext *tc,
|
||||
}
|
||||
|
||||
void
|
||||
MipsLiveProcess::setSyscallReturn(ThreadContext *tc,
|
||||
SyscallReturn return_value)
|
||||
MipsLiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
|
||||
{
|
||||
if (return_value.successful()) {
|
||||
if (sysret.successful()) {
|
||||
// no error
|
||||
tc->setIntReg(SyscallSuccessReg, 0);
|
||||
tc->setIntReg(ReturnValueReg, return_value.value());
|
||||
tc->setIntReg(ReturnValueReg, sysret.returnValue());
|
||||
} else {
|
||||
// got an error, return details
|
||||
tc->setIntReg(SyscallSuccessReg, (IntReg) -1);
|
||||
tc->setIntReg(ReturnValueReg, -return_value.value());
|
||||
tc->setIntReg(ReturnValueReg, sysret.errnoValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,15 +277,14 @@ PowerLiveProcess::setSyscallArg(ThreadContext *tc,
|
||||
}
|
||||
|
||||
void
|
||||
PowerLiveProcess::setSyscallReturn(ThreadContext *tc,
|
||||
SyscallReturn return_value)
|
||||
PowerLiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
|
||||
{
|
||||
Cr cr = tc->readIntReg(INTREG_CR);
|
||||
if (return_value.successful()) {
|
||||
if (sysret.successful()) {
|
||||
cr.cr0.so = 0;
|
||||
} else {
|
||||
cr.cr0.so = 1;
|
||||
}
|
||||
tc->setIntReg(INTREG_CR, cr);
|
||||
tc->setIntReg(ReturnValueReg, return_value.value());
|
||||
tc->setIntReg(ReturnValueReg, sysret.encodedValue());
|
||||
}
|
||||
|
||||
@@ -532,26 +532,25 @@ Sparc64LiveProcess::setSyscallArg(ThreadContext *tc, int i, IntReg val)
|
||||
}
|
||||
|
||||
void
|
||||
SparcLiveProcess::setSyscallReturn(ThreadContext *tc,
|
||||
SyscallReturn return_value)
|
||||
SparcLiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
|
||||
{
|
||||
// check for error condition. SPARC syscall convention is to
|
||||
// indicate success/failure in reg the carry bit of the ccr
|
||||
// and put the return value itself in the standard return value reg ().
|
||||
PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE);
|
||||
if (return_value.successful()) {
|
||||
if (sysret.successful()) {
|
||||
// no error, clear XCC.C
|
||||
tc->setIntReg(NumIntArchRegs + 2,
|
||||
tc->readIntReg(NumIntArchRegs + 2) & 0xEE);
|
||||
IntReg val = return_value.value();
|
||||
tc->readIntReg(NumIntArchRegs + 2) & 0xEE);
|
||||
IntReg val = sysret.returnValue();
|
||||
if (pstate.am)
|
||||
val = bits(val, 31, 0);
|
||||
tc->setIntReg(ReturnValueReg, val);
|
||||
} else {
|
||||
// got an error, set XCC.C
|
||||
tc->setIntReg(NumIntArchRegs + 2,
|
||||
tc->readIntReg(NumIntArchRegs + 2) | 0x11);
|
||||
IntReg val = -return_value.value();
|
||||
tc->readIntReg(NumIntArchRegs + 2) | 0x11);
|
||||
IntReg val = sysret.errnoValue();
|
||||
if (pstate.am)
|
||||
val = bits(val, 31, 0);
|
||||
tc->setIntReg(ReturnValueReg, val);
|
||||
|
||||
@@ -678,9 +678,9 @@ I386LiveProcess::argsInit(int intSize, int pageSize)
|
||||
}
|
||||
|
||||
void
|
||||
X86LiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn return_value)
|
||||
X86LiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn retval)
|
||||
{
|
||||
tc->setIntReg(INTREG_RAX, return_value.value());
|
||||
tc->setIntReg(INTREG_RAX, retval.encodedValue());
|
||||
}
|
||||
|
||||
X86ISA::IntReg
|
||||
|
||||
@@ -69,7 +69,7 @@ SyscallDesc::doSyscall(int callnum, LiveProcess *process, ThreadContext *tc)
|
||||
SyscallReturn retval = (*funcPtr)(this, callnum, process, tc);
|
||||
|
||||
DPRINTFR(SyscallVerbose, "%d: %s: syscall %s returns %d\n",
|
||||
curTick(),tc->getCpuPtr()->name(), name, retval.value());
|
||||
curTick(), tc->getCpuPtr()->name(), name, retval.encodedValue());
|
||||
|
||||
if (!(flags & SyscallDesc::SuppressReturnValue))
|
||||
process->setSyscallReturn(tc, retval);
|
||||
@@ -366,7 +366,7 @@ readlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc,
|
||||
string path;
|
||||
|
||||
if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
|
||||
return (TheISA::IntReg)-EFAULT;
|
||||
return -EFAULT;
|
||||
|
||||
// Adjust path for current working directory
|
||||
path = p->fullPath(path);
|
||||
@@ -390,7 +390,7 @@ unlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
|
||||
|
||||
int index = 0;
|
||||
if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
|
||||
return (TheISA::IntReg)-EFAULT;
|
||||
return -EFAULT;
|
||||
|
||||
// Adjust path for current working directory
|
||||
path = p->fullPath(path);
|
||||
@@ -407,7 +407,7 @@ mkdirFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
|
||||
|
||||
int index = 0;
|
||||
if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
|
||||
return (TheISA::IntReg)-EFAULT;
|
||||
return -EFAULT;
|
||||
|
||||
// Adjust path for current working directory
|
||||
path = p->fullPath(path);
|
||||
@@ -864,7 +864,7 @@ accessFunc(SyscallDesc *desc, int callnum, LiveProcess *p, ThreadContext *tc,
|
||||
{
|
||||
string path;
|
||||
if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
|
||||
return (TheISA::IntReg)-EFAULT;
|
||||
return -EFAULT;
|
||||
|
||||
// Adjust path for current working directory
|
||||
path = p->fullPath(path);
|
||||
|
||||
@@ -33,38 +33,71 @@
|
||||
|
||||
#include "base/types.hh"
|
||||
|
||||
/**
|
||||
* This class represents the return value from an emulated system call,
|
||||
* including any errno setting.
|
||||
*
|
||||
* On some platforms, the return value and errno are encoded in a
|
||||
* single signed integer. A value less than zero but greater than
|
||||
* -4096 indicates an error, and the value is the negation of the
|
||||
* errno value. Otherwise, the call was successful and the integer is
|
||||
* the return value. (Large negative numbers are considered
|
||||
* successful to allow syscalls to return pointers to high memory,
|
||||
* e.g., stack addresses.) See, for example, Appendix A of the AMD64
|
||||
* ABI spec at http://www.x86-64.org/documentation/abi.pdf.
|
||||
*
|
||||
* Other platforms use a more complex interface, returning a value and
|
||||
* an error code in separate registers.
|
||||
*
|
||||
* This class is designed to support both types of interfaces.
|
||||
*/
|
||||
class SyscallReturn
|
||||
{
|
||||
public:
|
||||
template <class T>
|
||||
SyscallReturn(T v, bool s)
|
||||
{
|
||||
retval = (uint64_t)v;
|
||||
success = s;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SyscallReturn(T v)
|
||||
{
|
||||
success = (v >= 0);
|
||||
retval = (uint64_t)v;
|
||||
}
|
||||
/// For simplicity, allow the object to be initialized with a
|
||||
/// single signed integer using the same positive=success,
|
||||
/// negative=-errno convention described above.
|
||||
///
|
||||
/// Typically this constructor is used as a default type
|
||||
/// conversion, so a bare integer is used where a SyscallReturn
|
||||
/// value is expected, e.g., as the return value from a system
|
||||
/// call emulation function ('return 0;' or 'return -EFAULT;').
|
||||
SyscallReturn(int64_t v)
|
||||
: value(v)
|
||||
{}
|
||||
|
||||
~SyscallReturn() {}
|
||||
|
||||
SyscallReturn& operator=(const SyscallReturn& s)
|
||||
/// Was the system call successful?
|
||||
bool successful() const
|
||||
{
|
||||
retval = s.retval;
|
||||
success = s.success;
|
||||
return *this;
|
||||
return (value >= 0 || value <= -4096);
|
||||
}
|
||||
|
||||
bool successful() { return success; }
|
||||
uint64_t value() { return retval; }
|
||||
/// The return value
|
||||
int64_t returnValue() const
|
||||
{
|
||||
assert(successful());
|
||||
return value;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t retval;
|
||||
bool success;
|
||||
/// The errno value
|
||||
int errnoValue() const
|
||||
{
|
||||
assert(!successful());
|
||||
return -value;
|
||||
}
|
||||
|
||||
/// The encoded value (as described above)
|
||||
int64_t encodedValue() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int64_t value;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user