no more common syscall emulation, now common for everyone

check abi-tag note section of elf binary for OS
add pseudo functions (moved from alpha and made to be generic)
move setsyscallreturn into isa traits

arch/alpha/SConscript:
    no more common syscall emulation, now common for everyone
arch/alpha/isa_traits.hh:
    move setsyscallreturn into isa description
arch/alpha/linux/process.cc:
arch/alpha/tru64/process.cc:
    use generic functions rather than alpha specific ones
arch/sparc/isa_traits.hh:
    have consts for generic pseudo syscalls
arch/sparc/linux/process.cc:
    use generic functions
base/loader/elf_object.cc:
    check abi-tag note section of elf binary for OS
cpu/exec_context.hh:
    move syssyscallreturn into isa traits
sim/process.cc:
    find call num with a more generic
sim/syscall_emul.cc:
sim/syscall_emul.hh:
    add pseudo functions (moved from alpha and made to be generic)

--HG--
extra : convert_revision : 5a31024ecde7e39b830365ddd84593ea501a34d2
This commit is contained in:
Ali Saidi 2006-03-09 15:42:09 -05:00
parent ab67095b2a
commit ce3a6343b6
11 changed files with 328 additions and 193 deletions

View file

@ -65,7 +65,6 @@ full_system_sources = Split('''
# Syscall emulation (non-full-system) sources # Syscall emulation (non-full-system) sources
syscall_emulation_sources = Split(''' syscall_emulation_sources = Split('''
common_syscall_emul.cc
linux/process.cc linux/process.cc
tru64/process.cc tru64/process.cc
process.cc process.cc

View file

@ -53,6 +53,44 @@ int DTB_ASN_ASN(uint64_t reg);
int ITB_ASN_ASN(uint64_t reg); int ITB_ASN_ASN(uint64_t reg);
} }
#if !FULL_SYSTEM
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;
}
~SyscallReturn() {}
SyscallReturn& operator=(const SyscallReturn& s) {
retval = s.retval;
success = s.success;
return *this;
}
bool successful() { return success; }
uint64_t value() { return retval; }
private:
uint64_t retval;
bool success;
};
#endif
namespace AlphaISA namespace AlphaISA
{ {
@ -82,6 +120,7 @@ namespace AlphaISA
ProcedureValueReg = 27, ProcedureValueReg = 27,
ReturnAddressReg = 26, ReturnAddressReg = 26,
ReturnValueReg = 0, ReturnValueReg = 0,
SyscallNumReg = 0,
FramePointerReg = 15, FramePointerReg = 15,
ArgumentReg0 = 16, ArgumentReg0 = 16,
ArgumentReg1 = 17, ArgumentReg1 = 17,
@ -89,6 +128,10 @@ namespace AlphaISA
ArgumentReg3 = 19, ArgumentReg3 = 19,
ArgumentReg4 = 20, ArgumentReg4 = 20,
ArgumentReg5 = 21, ArgumentReg5 = 21,
SyscallSuccessReg = 19,
// Some OS use a second register (o1) to return a second value
// for some syscalls
SyscallPseudoReturnReg = ArgumentReg4,
LogVMPageSize = 13, // 8K bytes LogVMPageSize = 13, // 8K bytes
VMPageSize = (1 << LogVMPageSize), VMPageSize = (1 << LogVMPageSize),
@ -303,6 +346,21 @@ extern const int reg_redir[NumIntRegs];
template <class XC> template <class XC>
void zeroRegisters(XC *xc); void zeroRegisters(XC *xc);
static inline void setSyscallReturn(SyscallReturn return_value, RegFile *regs)
{
// 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()) {
// no error
regs->intRegFile[SyscallSuccessReg] = 0;
regs->intRegFile[ReturnValueReg] = return_value.value();
} else {
// got an error, return details
regs->intRegFile[SyscallSuccessReg] = (IntReg) -1;
regs->intRegFile[ReturnValueReg] = -return_value.value();
}
}
//typedef AlphaISA TheISA; //typedef AlphaISA TheISA;
@ -336,42 +394,6 @@ extern const int reg_redir[NumIntRegs];
const Addr MaxAddr = (Addr)-1; const Addr MaxAddr = (Addr)-1;
}; };
#if !FULL_SYSTEM
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;
}
~SyscallReturn() {}
SyscallReturn& operator=(const SyscallReturn& s) {
retval = s.retval;
success = s.success;
return *this;
}
bool successful() { return success; }
uint64_t value() { return retval; }
private:
uint64_t retval;
bool success;
};
#endif
static inline AlphaISA::ExtMachInst static inline AlphaISA::ExtMachInst
AlphaISA::makeExtMI(AlphaISA::MachInst inst, const uint64_t &pc) { AlphaISA::makeExtMI(AlphaISA::MachInst inst, const uint64_t &pc) {
#if FULL_SYSTEM #if FULL_SYSTEM

View file

@ -26,7 +26,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "arch/alpha/common_syscall_emul.hh"
#include "arch/alpha/linux/process.hh" #include "arch/alpha/linux/process.hh"
#include "arch/alpha/isa_traits.hh" #include "arch/alpha/isa_traits.hh"
@ -41,29 +40,7 @@
using namespace std; using namespace std;
using namespace AlphaISA; using namespace AlphaISA;
/// Target pipe() handler. Even though this is a generic Posix call,
/// the Alpha return convention is funky, so that makes it
/// Alpha-specific.
SyscallReturn
pipeFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
int fds[2], sim_fds[2];
int pipe_retval = pipe(fds);
if (pipe_retval < 0) {
// error
return pipe_retval;
}
sim_fds[0] = process->alloc_fd(fds[0]);
sim_fds[1] = process->alloc_fd(fds[1]);
// Alpha Linux convention for pipe() is that fd[0] is returned as
// the return value of the function, and fd[1] is returned in r20.
xc->regs.intRegFile[20] = sim_fds[1];
return sim_fds[0];
}
/// Target uname() handler. /// Target uname() handler.
@ -162,11 +139,11 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 17 */ SyscallDesc("brk", obreakFunc), /* 17 */ SyscallDesc("brk", obreakFunc),
/* 18 */ SyscallDesc("osf_getfsstat", unimplementedFunc), /* 18 */ SyscallDesc("osf_getfsstat", unimplementedFunc),
/* 19 */ SyscallDesc("lseek", lseekFunc), /* 19 */ SyscallDesc("lseek", lseekFunc),
/* 20 */ SyscallDesc("getxpid", getpidFunc), /* 20 */ SyscallDesc("getxpid", getpidPseudoFunc),
/* 21 */ SyscallDesc("osf_mount", unimplementedFunc), /* 21 */ SyscallDesc("osf_mount", unimplementedFunc),
/* 22 */ SyscallDesc("umount", unimplementedFunc), /* 22 */ SyscallDesc("umount", unimplementedFunc),
/* 23 */ SyscallDesc("setuid", setuidFunc), /* 23 */ SyscallDesc("setuid", setuidFunc),
/* 24 */ SyscallDesc("getxuid", getuidFunc), /* 24 */ SyscallDesc("getxuid", getuidPseudoFunc),
/* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc), /* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc),
/* 26 */ SyscallDesc("osf_ptrace", unimplementedFunc), /* 26 */ SyscallDesc("osf_ptrace", unimplementedFunc),
/* 27 */ SyscallDesc("osf_nrecvmsg", unimplementedFunc), /* 27 */ SyscallDesc("osf_nrecvmsg", unimplementedFunc),
@ -184,12 +161,12 @@ SyscallDesc AlphaLinuxProcess::syscallDescs[] = {
/* 39 */ SyscallDesc("setpgid", unimplementedFunc), /* 39 */ SyscallDesc("setpgid", unimplementedFunc),
/* 40 */ SyscallDesc("osf_old_lstat", unimplementedFunc), /* 40 */ SyscallDesc("osf_old_lstat", unimplementedFunc),
/* 41 */ SyscallDesc("dup", unimplementedFunc), /* 41 */ SyscallDesc("dup", unimplementedFunc),
/* 42 */ SyscallDesc("pipe", pipeFunc), /* 42 */ SyscallDesc("pipe", pipePseudoFunc),
/* 43 */ SyscallDesc("osf_set_program_attributes", unimplementedFunc), /* 43 */ SyscallDesc("osf_set_program_attributes", unimplementedFunc),
/* 44 */ SyscallDesc("osf_profil", unimplementedFunc), /* 44 */ SyscallDesc("osf_profil", unimplementedFunc),
/* 45 */ SyscallDesc("open", openFunc<Linux>), /* 45 */ SyscallDesc("open", openFunc<Linux>),
/* 46 */ SyscallDesc("osf_old_sigaction", unimplementedFunc), /* 46 */ SyscallDesc("osf_old_sigaction", unimplementedFunc),
/* 47 */ SyscallDesc("getxgid", getgidFunc), /* 47 */ SyscallDesc("getxgid", getgidPseudoFunc),
/* 48 */ SyscallDesc("osf_sigprocmask", ignoreFunc), /* 48 */ SyscallDesc("osf_sigprocmask", ignoreFunc),
/* 49 */ SyscallDesc("osf_getlogin", unimplementedFunc), /* 49 */ SyscallDesc("osf_getlogin", unimplementedFunc),
/* 50 */ SyscallDesc("osf_setlogin", unimplementedFunc), /* 50 */ SyscallDesc("osf_setlogin", unimplementedFunc),

View file

@ -27,7 +27,6 @@
*/ */
#include "arch/alpha/isa_traits.hh" #include "arch/alpha/isa_traits.hh"
#include "arch/alpha/common_syscall_emul.hh"
#include "arch/alpha/tru64/process.hh" #include "arch/alpha/tru64/process.hh"
#include "cpu/exec_context.hh" #include "cpu/exec_context.hh"
#include "kern/tru64/tru64.hh" #include "kern/tru64/tru64.hh"
@ -179,11 +178,11 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
/* 17 */ SyscallDesc("obreak", obreakFunc), /* 17 */ SyscallDesc("obreak", obreakFunc),
/* 18 */ SyscallDesc("pre_F64_getfsstat", unimplementedFunc), /* 18 */ SyscallDesc("pre_F64_getfsstat", unimplementedFunc),
/* 19 */ SyscallDesc("lseek", lseekFunc), /* 19 */ SyscallDesc("lseek", lseekFunc),
/* 20 */ SyscallDesc("getpid", getpidFunc), /* 20 */ SyscallDesc("getpid", getpidPseudoFunc),
/* 21 */ SyscallDesc("mount", unimplementedFunc), /* 21 */ SyscallDesc("mount", unimplementedFunc),
/* 22 */ SyscallDesc("unmount", unimplementedFunc), /* 22 */ SyscallDesc("unmount", unimplementedFunc),
/* 23 */ SyscallDesc("setuid", setuidFunc), /* 23 */ SyscallDesc("setuid", setuidFunc),
/* 24 */ SyscallDesc("getuid", getuidFunc), /* 24 */ SyscallDesc("getuid", getuidPseudoFunc),
/* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc), /* 25 */ SyscallDesc("exec_with_loader", unimplementedFunc),
/* 26 */ SyscallDesc("ptrace", unimplementedFunc), /* 26 */ SyscallDesc("ptrace", unimplementedFunc),
/* 27 */ SyscallDesc("recvmsg", unimplementedFunc), /* 27 */ SyscallDesc("recvmsg", unimplementedFunc),
@ -206,7 +205,7 @@ SyscallDesc AlphaTru64Process::syscallDescs[] = {
/* 44 */ SyscallDesc("profil", unimplementedFunc), /* 44 */ SyscallDesc("profil", unimplementedFunc),
/* 45 */ SyscallDesc("open", openFunc<Tru64>), /* 45 */ SyscallDesc("open", openFunc<Tru64>),
/* 46 */ SyscallDesc("obsolete osigaction", unimplementedFunc), /* 46 */ SyscallDesc("obsolete osigaction", unimplementedFunc),
/* 47 */ SyscallDesc("getgid", getgidFunc), /* 47 */ SyscallDesc("getgid", getgidPseudoFunc),
/* 48 */ SyscallDesc("sigprocmask", ignoreFunc), /* 48 */ SyscallDesc("sigprocmask", ignoreFunc),
/* 49 */ SyscallDesc("getlogin", unimplementedFunc), /* 49 */ SyscallDesc("getlogin", unimplementedFunc),
/* 50 */ SyscallDesc("setlogin", unimplementedFunc), /* 50 */ SyscallDesc("setlogin", unimplementedFunc),

View file

@ -78,6 +78,20 @@ namespace SparcISA
// semantically meaningful register indices // semantically meaningful register indices
ZeroReg = 0 // architecturally meaningful ZeroReg = 0 // architecturally meaningful
// the rest of these depend on the ABI // the rest of these depend on the ABI
SyscallNumReg = 1,
ArgumentReg0 = 8,
ArgumentReg1 = 9,
ArgumentReg2 = 10,
ArgumentReg3 = 11,
ArgumentReg4 = 12,
ArgumentReg5 = 13,
StackPoniterReg = 14,
ReturnAddressReg = 31, // Post Call, precall, 15
ReturnValueReg = 8, // Post return, 24 is pre-return.
// Some OS use a second register (o1) to return a second value
// for some syscalls
SyscallPseudoReturnReg = 9,
FramePointerReg = 30
}; };
typedef uint64_t IntReg; typedef uint64_t IntReg;
@ -455,6 +469,22 @@ namespace SparcISA
*/ */
template <class XC> template <class XC>
static void zeroRegisters(XC *xc); static void zeroRegisters(XC *xc);
static inline setSyscallReturn(SyscallReturn return_value, RegFile *regs)
{
// 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 ().
if (return_value.successful()) {
// no error
regs->miscRegFile.ccrFields.iccFields.c = 0;
regs->intRegFile[ReturnValueReg] = return_value.value();
} else {
// got an error, return details
regs->miscRegFile.ccrFields.iccFields.c = 1;
regs->intRegFile[ReturnValueReg] = -return_value.value();
}
}
}; };
const int VMPageSize = TheISA::VMPageSize; const int VMPageSize = TheISA::VMPageSize;

View file

@ -41,30 +41,6 @@
using namespace std; using namespace std;
using namespace SparcISA; using namespace SparcISA;
/// Target pipe() handler. Even though this is a generic Posix call,
/// the Alpha return convention is funky, so that makes it
/// Alpha-specific.
SyscallReturn
pipeFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
int fds[2], sim_fds[2];
int pipe_retval = pipe(fds);
if (pipe_retval < 0) {
// error
return pipe_retval;
}
sim_fds[0] = process->alloc_fd(fds[0]);
sim_fds[1] = process->alloc_fd(fds[1]);
// Alpha Linux convention for pipe() is that fd[0] is returned as
// the return value of the function, and fd[1] is returned in r20.
xc->regs.intRegFile[20] = sim_fds[1];
return sim_fds[0];
}
/// Target uname() handler. /// Target uname() handler.
static SyscallReturn static SyscallReturn
@ -77,95 +53,38 @@ unameFunc(SyscallDesc *desc, int callnum, Process *process,
strcpy(name->nodename, "m5.eecs.umich.edu"); strcpy(name->nodename, "m5.eecs.umich.edu");
strcpy(name->release, "2.4.20"); strcpy(name->release, "2.4.20");
strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003"); strcpy(name->version, "#1 Mon Aug 18 11:32:15 EDT 2003");
strcpy(name->machine, "alpha"); strcpy(name->machine, "sparc");
name.copyOut(xc->mem); name.copyOut(xc->mem);
return 0; return 0;
} }
/// Target osf_getsysyinfo() handler. Even though this call is
/// borrowed from Tru64, the subcases that get used appear to be
/// different in practice from those used by Tru64 processes.
static SyscallReturn
osf_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
unsigned op = xc->getSyscallArg(0);
// unsigned nbytes = xc->getSyscallArg(2);
switch (op) {
case 45: { // GSI_IEEE_FP_CONTROL
TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
// I don't think this exactly matches the HW FPCR
*fpcr = 0;
fpcr.copyOut(xc->mem);
return 0;
}
default:
cerr << "osf_getsysinfo: unknown op " << op << endl;
abort();
break;
}
return 1;
}
/// Target osf_setsysinfo() handler.
static SyscallReturn
osf_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
unsigned op = xc->getSyscallArg(0);
// unsigned nbytes = xc->getSyscallArg(2);
switch (op) {
case 14: { // SSI_IEEE_FP_CONTROL
TypedBufferArg<uint64_t> fpcr(xc->getSyscallArg(1));
// I don't think this exactly matches the HW FPCR
fpcr.copyIn(xc->mem);
DPRINTFR(SyscallVerbose, "osf_setsysinfo(SSI_IEEE_FP_CONTROL): "
" setting FPCR to 0x%x\n", gtoh(*(uint64_t*)fpcr));
return 0;
}
default:
cerr << "osf_setsysinfo: unknown op " << op << endl;
abort();
break;
}
return 1;
}
SyscallDesc SparcLinuxProcess::syscallDescs[] = { SyscallDesc SparcLinuxProcess::syscallDescs[] = {
/* 0 */ SyscallDesc("restart_syscall", unimplimentedFunc); /* 0 */ SyscallDesc("restart_syscall", unimplimentedFunc);
/* 1 */ SyscallDesc("exit", unimplimentedFunc); /* 1 */ SyscallDesc("exit", exitFunc);
/* 2 */ SyscallDesc("fork", unimplimentedFunc); /* 2 */ SyscallDesc("fork", unimplimentedFunc);
/* 3 */ SyscallDesc("read", unimplimentedFunc); /* 3 */ SyscallDesc("read", readFunc);
/* 4 */ SyscallDesc("write", unimplimentedFunc); /* 4 */ SyscallDesc("write", writeFunc);
/* 5 */ SyscallDesc("open", unimplimentedFunc); /* 5 */ SyscallDesc("open", openFunc<Linux>);
/* 6 */ SyscallDesc("close", unimplimentedFunc); /* 6 */ SyscallDesc("close", closeFinc);
/* 7 */ SyscallDesc("wait4", unimplimentedFunc); /* 7 */ SyscallDesc("wait4", unimplimentedFunc);
/* 8 */ SyscallDesc("creat", unimplimentedFunc); /* 8 */ SyscallDesc("creat", unimplimentedFunc);
/* 9 */ SyscallDesc("link", unimplimentedFunc); /* 9 */ SyscallDesc("link", unimplimentedFunc);
/* 10 */ SyscallDesc("unlink", unimplimentedFunc); /* 10 */ SyscallDesc("unlink", unlinkFunc);
/* 11 */ SyscallDesc("execv", unimplimentedFunc); /* 11 */ SyscallDesc("execv", unimplimentedFunc);
/* 12 */ SyscallDesc("chdir", unimplimentedFunc); /* 12 */ SyscallDesc("chdir", unimplimentedFunc);
/* 13 */ SyscallDesc("chown", unimplimentedFunc); /* 13 */ SyscallDesc("chown", chownFunc);
/* 14 */ SyscallDesc("mknod", unimplimentedFunc); /* 14 */ SyscallDesc("mknod", unimplimentedFunc);
/* 15 */ SyscallDesc("chmod", unimplimentedFunc); /* 15 */ SyscallDesc("chmod", chmodFunc<Linux>);
/* 16 */ SyscallDesc("lchown", unimplimentedFunc); /* 16 */ SyscallDesc("lchown", unimplimentedFunc);
/* 17 */ SyscallDesc("brk", unimplimentedFunc); /* 17 */ SyscallDesc("brk", obreakFunc);
/* 18 */ SyscallDesc("perfctr", unimplimentedFunc); /* 18 */ SyscallDesc("perfctr", unimplimentedFunc);
/* 19 */ SyscallDesc("lseek", unimplimentedFunc); /* 19 */ SyscallDesc("lseek", lseekFunc);
/* 20 */ SyscallDesc("getpid", unimplimentedFunc); /* 20 */ SyscallDesc("getpid", getpidFunc);
/* 21 */ SyscallDesc("capget", unimplimentedFunc); /* 21 */ SyscallDesc("capget", unimplimentedFunc);
/* 22 */ SyscallDesc("capset", unimplimentedFunc); /* 22 */ SyscallDesc("capset", unimplimentedFunc);
/* 23 */ SyscallDesc("setuid", unimplimentedFunc); /* 23 */ SyscallDesc("setuid", setuidFunc);
/* 24 */ SyscallDesc("getuid", unimplimentedFunc); /* 24 */ SyscallDesc("getuid", getuidFunc);
/* 25 */ SyscallDesc("time", unimplimentedFunc); /* 25 */ SyscallDesc("time", unimplimentedFunc);
/* 26 */ SyscallDesc("ptrace", unimplimentedFunc); /* 26 */ SyscallDesc("ptrace", unimplimentedFunc);
/* 27 */ SyscallDesc("alarm", unimplimentedFunc); /* 27 */ SyscallDesc("alarm", unimplimentedFunc);
@ -183,15 +102,15 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = {
/* 39 */ SyscallDesc("sendfile", unimplimentedFunc); /* 39 */ SyscallDesc("sendfile", unimplimentedFunc);
/* 40 */ SyscallDesc("lstat", unimplimentedFunc); /* 40 */ SyscallDesc("lstat", unimplimentedFunc);
/* 41 */ SyscallDesc("dup", unimplimentedFunc); /* 41 */ SyscallDesc("dup", unimplimentedFunc);
/* 42 */ SyscallDesc("pipe", unimplimentedFunc); /* 42 */ SyscallDesc("pipe", pipePseudoFunc);
/* 43 */ SyscallDesc("times", unimplimentedFunc); /* 43 */ SyscallDesc("times", unimplimentedFunc);
/* 44 */ SyscallDesc("getuid32", unimplimentedFunc); /* 44 */ SyscallDesc("getuid32", unimplimentedFunc);
/* 45 */ SyscallDesc("umount2", unimplimentedFunc); /* 45 */ SyscallDesc("umount2", unimplimentedFunc);
/* 46 */ SyscallDesc("setgid", unimplimentedFunc); /* 46 */ SyscallDesc("setgid", unimplimentedFunc);
/* 47 */ SyscallDesc("getgid", unimplimentedFunc); /* 47 */ SyscallDesc("getgid", getgidFunc);
/* 48 */ SyscallDesc("signal", unimplimentedFunc); /* 48 */ SyscallDesc("signal", unimplimentedFunc);
/* 49 */ SyscallDesc("geteuid", unimplimentedFunc); /* 49 */ SyscallDesc("geteuid", geteuidFunc);
/* 50 */ SyscallDesc("getegid", unimplimentedFunc); /* 50 */ SyscallDesc("getegid", getegidFunc);
/* 51 */ SyscallDesc("acct", unimplimentedFunc); /* 51 */ SyscallDesc("acct", unimplimentedFunc);
/* 52 */ SyscallDesc("memory_ordering", unimplimentedFunc); /* 52 */ SyscallDesc("memory_ordering", unimplimentedFunc);
/* 53 */ SyscallDesc("getgid32", unimplimentedFunc); /* 53 */ SyscallDesc("getgid32", unimplimentedFunc);
@ -330,7 +249,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = {
/* 186 */ SyscallDesc("fremovexattr", unimplimentedFunc); /* 186 */ SyscallDesc("fremovexattr", unimplimentedFunc);
/* 187 */ SyscallDesc("tkill", unimplimentedFunc); /* 187 */ SyscallDesc("tkill", unimplimentedFunc);
/* 188 */ SyscallDesc("exit_group", unimplimentedFunc); /* 188 */ SyscallDesc("exit_group", unimplimentedFunc);
/* 189 */ SyscallDesc("uname", unimplimentedFunc); /* 189 */ SyscallDesc("uname", unameFunc);
/* 190 */ SyscallDesc("init_module", unimplimentedFunc); /* 190 */ SyscallDesc("init_module", unimplimentedFunc);
/* 191 */ SyscallDesc("personality", unimplimentedFunc); /* 191 */ SyscallDesc("personality", unimplimentedFunc);
/* 192 */ SyscallDesc("remap_file_pages", unimplimentedFunc); /* 192 */ SyscallDesc("remap_file_pages", unimplimentedFunc);
@ -338,7 +257,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = {
/* 194 */ SyscallDesc("epoll_ctl", unimplimentedFunc); /* 194 */ SyscallDesc("epoll_ctl", unimplimentedFunc);
/* 195 */ SyscallDesc("epoll_wait", unimplimentedFunc); /* 195 */ SyscallDesc("epoll_wait", unimplimentedFunc);
/* 196 */ SyscallDesc("ioprio_set", unimplimentedFunc); /* 196 */ SyscallDesc("ioprio_set", unimplimentedFunc);
/* 197 */ SyscallDesc("getppid", unimplimentedFunc); /* 197 */ SyscallDesc("getppid", getppidFunc);
/* 198 */ SyscallDesc("sigaction", unimplimentedFunc); /* 198 */ SyscallDesc("sigaction", unimplimentedFunc);
/* 199 */ SyscallDesc("sgetmask", unimplimentedFunc); /* 199 */ SyscallDesc("sgetmask", unimplimentedFunc);
/* 200 */ SyscallDesc("ssetmask", unimplimentedFunc); /* 200 */ SyscallDesc("ssetmask", unimplimentedFunc);
@ -437,6 +356,10 @@ SparcLinuxProcess::SparcLinuxProcess(const std::string &name,
: LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp), : LiveProcess(name, objFile, stdin_fd, stdout_fd, stderr_fd, argv, envp),
Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc)) Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
{ {
// The sparc syscall table must be <= 283 entries because that is all there
// is space for.
assert(Num_Syscall_Descs <= 283);
init_regs->intRegFile[0] = 0; init_regs->intRegFile[0] = 0;
} }

View file

@ -75,15 +75,6 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
return NULL; return NULL;
} }
else { else {
// if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
// panic("32 bit ELF Binary, Not Supported");
/* @todo this emachine value isn't offical yet.
* so we probably shouldn't check it. */
// if (ehdr.e_machine != EM_ALPHA)
// panic("Non Alpha Binary, Not Supported");
elf_end(elf);
//Detect the architecture //Detect the architecture
//Versioning issues in libelf need to be resolved to get the correct //Versioning issues in libelf need to be resolved to get the correct
//SPARC constants. //SPARC constants.
@ -109,17 +100,61 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
//Detect the operating system //Detect the operating system
switch (ehdr.e_ident[EI_OSABI]) switch (ehdr.e_ident[EI_OSABI])
{ {
case ELFOSABI_LINUX: case ELFOSABI_LINUX:
opSys = ObjectFile::Linux; opSys = ObjectFile::Linux;
break; break;
case ELFOSABI_SOLARIS: case ELFOSABI_SOLARIS:
opSys = ObjectFile::Solaris; opSys = ObjectFile::Solaris;
break;
case ELFOSABI_TRU64: case ELFOSABI_TRU64:
opSys = ObjectFile::Tru64; opSys = ObjectFile::Tru64;
break;
default: default:
opSys = ObjectFile::UnknownOpSys; opSys = ObjectFile::UnknownOpSys;
} }
//take a look at the .note.ABI section
//It can let us know what's what.
if (opSys == ObjectFile::UnknownOpSys)
{
Elf_Scn *section;
GElf_Shdr shdr;
Elf_Data *data;
uint32_t osAbi;;
int secIdx = 1;
// Get the first section
section = elf_getscn(elf, secIdx);
// While there are no more sections
while (section != NULL) {
gelf_getshdr(section, &shdr);
if (shdr.sh_type == SHT_NOTE && !strcmp(".note.ABI-tag",
elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) {
// we have found a ABI note section
// Check the 5th 32bit word for OS 0 == linux, 1 == hurd,
// 2 == solaris, 3 == freebsd
data = elf_rawdata(section, NULL);
assert(data->d_buf);
if(ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
osAbi = htole(((uint32_t*)data->d_buf)[4]);
else
osAbi = htobe(((uint32_t*)data->d_buf)[4]);
switch(osAbi) {
case 0:
opSys = ObjectFile::Linux;
break;
case 2:
opSys = ObjectFile::Solaris;
break;
}
} // if section found
section = elf_getscn(elf, ++secIdx);
} // while sections
}
elf_end(elf);
return new ElfObject(fname, fd, len, data, arch, opSys); return new ElfObject(fname, fd, len, data, arch, opSys);
} }
} }

View file

@ -464,19 +464,7 @@ class ExecContext
void setSyscallReturn(SyscallReturn return_value) void setSyscallReturn(SyscallReturn return_value)
{ {
// check for error condition. Alpha syscall convention is to TheISA::setSyscallReturn(return_value, &regs);
// indicate success/failure in reg a3 (r19) and put the
// return value itself in the standard return value reg (v0).
const int RegA3 = 19; // only place this is used
if (return_value.successful()) {
// no error
regs.intRegFile[RegA3] = 0;
regs.intRegFile[TheISA::ReturnValueReg] = return_value.value();
} else {
// got an error, return details
regs.intRegFile[RegA3] = (TheISA::IntReg) -1;
regs.intRegFile[TheISA::ReturnValueReg] = -return_value.value();
}
} }
void syscall() void syscall()

View file

@ -354,7 +354,7 @@ LiveProcess::syscall(ExecContext *xc)
{ {
num_syscalls++; num_syscalls++;
int64_t callnum = xc->regs.intRegFile[ReturnValueReg]; int64_t callnum = xc->regs.intRegFile[SyscallNumReg];
SyscallDesc *desc = getDesc(callnum); SyscallDesc *desc = getDesc(callnum);
if (desc == NULL) if (desc == NULL)

View file

@ -324,4 +324,118 @@ fcntlFunc(SyscallDesc *desc, int num, Process *process,
} }
} }
SyscallReturn
pipePseudoFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
int fds[2], sim_fds[2];
int pipe_retval = pipe(fds);
if (pipe_retval < 0) {
// error
return pipe_retval;
}
sim_fds[0] = process->alloc_fd(fds[0]);
sim_fds[1] = process->alloc_fd(fds[1]);
// Alpha Linux convention for pipe() is that fd[0] is returned as
// the return value of the function, and fd[1] is returned in r20.
xc->regs.intRegFile[SyscallPseudoReturnReg] = sim_fds[1];
return sim_fds[0];
}
SyscallReturn
getpidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
// Make up a PID. There's no interprocess communication in
// fake_syscall mode, so there's no way for a process to know it's
// not getting a unique value.
xc->regs.intRegFile[SyscallPseudoReturnReg] = 99;
return 100;
}
SyscallReturn
getuidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
// Make up a UID and EUID... it shouldn't matter, and we want the
// simulation to be deterministic.
// EUID goes in r20.
xc->regs.intRegFile[SyscallPseudoReturnReg] = 100; // EUID
return 100; // UID
}
SyscallReturn
getgidPseudoFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
// Get current group ID. EGID goes in r20.
xc->regs.intRegFile[SyscallPseudoReturnReg] = 100;
return 100;
}
SyscallReturn
setuidFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
// can't fathom why a benchmark would call this.
warn("Ignoring call to setuid(%d)\n", xc->getSyscallArg(0));
return 0;
}
SyscallReturn
getpidFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
// Make up a PID. There's no interprocess communication in
// fake_syscall mode, so there's no way for a process to know it's
// not getting a unique value.
xc->regs.intRegFile[SyscallPseudoReturnReg] = 99;
return 100;
}
SyscallReturn
getppidFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
return 99;
}
SyscallReturn
getuidFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
return 100; // UID
}
SyscallReturn
geteuidFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
return 100; // UID
}
SyscallReturn
getgidFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
return 100;
}
SyscallReturn
getegidFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
return 100;
}

View file

@ -243,6 +243,54 @@ SyscallReturn fchownFunc(SyscallDesc *desc, int num,
SyscallReturn fcntlFunc(SyscallDesc *desc, int num, SyscallReturn fcntlFunc(SyscallDesc *desc, int num,
Process *process, ExecContext *xc); Process *process, ExecContext *xc);
/// Target setuid() handler.
SyscallReturn setuidFunc(SyscallDesc *desc, int num,
Process *p, ExecContext *xc);
/// Target getpid() handler.
SyscallReturn getpidFunc(SyscallDesc *desc, int num,
Process *p, ExecContext *xc);
/// Target getuid() handler.
SyscallReturn getuidFunc(SyscallDesc *desc, int num,
Process *p, ExecContext *xc);
/// Target getgid() handler.
SyscallReturn getgidFunc(SyscallDesc *desc, int num,
Process *p, ExecContext *xc);
/// Target getppid() handler.
SyscallReturn getppidFunc(SyscallDesc *desc, int num,
Process *p, ExecContext *xc);
/// Target geteuid() handler.
SyscallReturn geteuidFunc(SyscallDesc *desc, int num,
Process *p, ExecContext *xc);
/// Target getegid() handler.
SyscallReturn getegidFunc(SyscallDesc *desc, int num,
Process *p, ExecContext *xc);
/// Pseudo Funcs - These functions use a different return convension,
/// returning a second value in a register other than the normal return register
SyscallReturn pipePseudoFunc(SyscallDesc *desc, int num,
Process *process, ExecContext *xc);
/// Target getpidPseudo() handler.
SyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num,
Process *p, ExecContext *xc);
/// Target getuidPseudo() handler.
SyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num,
Process *p, ExecContext *xc);
/// Target getgidPseudo() handler.
SyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num,
Process *p, ExecContext *xc);
/// This struct is used to build an target-OS-dependent table that /// This struct is used to build an target-OS-dependent table that
/// maps the target's open() flags to the host open() flags. /// maps the target's open() flags to the host open() flags.
struct OpenFlagTransTable { struct OpenFlagTransTable {