summaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/x86/process.cc60
-rw-r--r--src/arch/x86/process.hh14
2 files changed, 66 insertions, 8 deletions
diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc
index 54d5d07ab..4a61ed168 100644
--- a/src/arch/x86/process.cc
+++ b/src/arch/x86/process.cc
@@ -152,12 +152,32 @@ X86_64LiveProcess::X86_64LiveProcess(LiveProcessParams *params,
mmap_start = mmap_end = (Addr)0x2aaaaaaab000ULL;
}
+void
+I386LiveProcess::syscall(int64_t callnum, ThreadContext *tc)
+{
+ Addr eip = tc->readPC();
+ if (eip >= vsyscallPage.base &&
+ eip < vsyscallPage.base + vsyscallPage.size) {
+ tc->setNextPC(vsyscallPage.base + vsyscallPage.vsysexitOffset);
+ }
+ X86LiveProcess::syscall(callnum, tc);
+}
+
+
I386LiveProcess::I386LiveProcess(LiveProcessParams *params,
ObjectFile *objFile, SyscallDesc *_syscallDescs,
int _numSyscallDescs) :
X86LiveProcess(params, objFile, _syscallDescs, _numSyscallDescs)
{
- stack_base = (Addr)0xffffe000ULL;
+ _gdtStart = 0x100000000;
+ _gdtSize = VMPageSize;
+
+ vsyscallPage.base = 0xffffe000ULL;
+ vsyscallPage.size = VMPageSize;
+ vsyscallPage.vsyscallOffset = 0x400;
+ vsyscallPage.vsysexitOffset = 0x410;
+
+ stack_base = vsyscallPage.base;
// Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
@@ -255,8 +275,6 @@ I386LiveProcess::startup()
* Set up a GDT for this process. The whole GDT wouldn't really be for
* this process, but the only parts we care about are.
*/
- _gdtStart = stack_base;
- _gdtSize = VMPageSize;
pTable->allocate(_gdtStart, _gdtSize);
uint64_t zero = 0;
assert(_gdtSize % sizeof(zero) == 0);
@@ -265,6 +283,27 @@ I386LiveProcess::startup()
initVirtMem->write(gdtCurrent, zero);
}
+ // Set up the vsyscall page for this process.
+ pTable->allocate(vsyscallPage.base, vsyscallPage.size);
+ uint8_t vsyscallBlob[] = {
+ 0x51, // push %ecx
+ 0x52, // push %edp
+ 0x55, // push %ebp
+ 0x89, 0xe5, // mov %esp, %ebp
+ 0x0f, 0x34 // sysenter
+ };
+ initVirtMem->writeBlob(vsyscallPage.base + vsyscallPage.vsyscallOffset,
+ vsyscallBlob, sizeof(vsyscallBlob));
+
+ uint8_t vsysexitBlob[] = {
+ 0x5d, // pop %ebp
+ 0x5a, // pop %edx
+ 0x59, // pop %ecx
+ 0xc3 // ret
+ };
+ initVirtMem->writeBlob(vsyscallPage.base + vsyscallPage.vsysexitOffset,
+ vsysexitBlob, sizeof(vsysexitBlob));
+
for (int i = 0; i < contextIds.size(); i++) {
ThreadContext * tc = system->getThreadContext(contextIds[i]);
@@ -332,12 +371,13 @@ I386LiveProcess::startup()
template<class IntType>
void
-X86LiveProcess::argsInit(int pageSize)
+X86LiveProcess::argsInit(int pageSize,
+ std::vector<AuxVector<IntType> > extraAuxvs)
{
int intSize = sizeof(IntType);
typedef AuxVector<IntType> auxv_t;
- std::vector<auxv_t> auxv;
+ std::vector<auxv_t> auxv = extraAuxvs;
string filename;
if(argv.size() < 1)
@@ -608,13 +648,19 @@ X86LiveProcess::argsInit(int pageSize)
void
X86_64LiveProcess::argsInit(int intSize, int pageSize)
{
- X86LiveProcess::argsInit<uint64_t>(pageSize);
+ std::vector<AuxVector<uint64_t> > extraAuxvs;
+ X86LiveProcess::argsInit<uint64_t>(pageSize, extraAuxvs);
}
void
I386LiveProcess::argsInit(int intSize, int pageSize)
{
- X86LiveProcess::argsInit<uint32_t>(pageSize);
+ std::vector<AuxVector<uint32_t> > extraAuxvs;
+ //Tell the binary where the vsyscall part of the vsyscall page is.
+ extraAuxvs.push_back(AuxVector<uint32_t>(0x20,
+ vsyscallPage.base + vsyscallPage.vsyscallOffset));
+ extraAuxvs.push_back(AuxVector<uint32_t>(0x21, vsyscallPage.base));
+ X86LiveProcess::argsInit<uint32_t>(pageSize, extraAuxvs);
}
void
diff --git a/src/arch/x86/process.hh b/src/arch/x86/process.hh
index 2d72d3fd0..cd6d99e66 100644
--- a/src/arch/x86/process.hh
+++ b/src/arch/x86/process.hh
@@ -80,7 +80,8 @@ namespace X86ISA
SyscallDesc *_syscallDescs, int _numSyscallDescs);
template<class IntType>
- void argsInit(int pageSize);
+ void argsInit(int pageSize,
+ std::vector<AuxVector<IntType> > extraAuxvs);
public:
Addr gdtStart()
@@ -114,10 +115,21 @@ namespace X86ISA
I386LiveProcess(LiveProcessParams *params, ObjectFile *objFile,
SyscallDesc *_syscallDescs, int _numSyscallDescs);
+ class VSyscallPage
+ {
+ public:
+ Addr base;
+ Addr size;
+ Addr vsyscallOffset;
+ Addr vsysexitOffset;
+ };
+ VSyscallPage vsyscallPage;
+
public:
void argsInit(int intSize, int pageSize);
void startup();
+ void syscall(int64_t callnum, ThreadContext *tc);
X86ISA::IntReg getSyscallArg(ThreadContext *tc, int i);
void setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val);
};