#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <sys/mman.h>
#include "box64stack.h"
#include "box64context.h"
#include "elfloader.h"
#include "debug.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "auxval.h"
#include "custommem.h"
EXPORTDYN
int CalcStackSize(box64context_t *context)
{
printf_log(LOG_DEBUG, "Calc stack size, based on %d elf(s)\n", context->elfsize);
context->stacksz = 8*1024*1024; context->stackalign=16;
for (int i=0; i<context->elfsize; ++i)
CalcStack(context->elfs[i], &context->stacksz, &context->stackalign);
context->stack = internal_mmap(NULL, context->stacksz, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
if (context->stack==(void*)-1) {
printf_log(LOG_NONE, "Cannot allocate aligned memory (0x%lx/0x%zx) for stack\n", context->stacksz, context->stackalign);
return 1;
} else
setProtection((uintptr_t)context->stack, context->stacksz, PROT_READ|PROT_WRITE);
printf_log(LOG_DEBUG, "Stack is @%p size=0x%lx align=0x%zx\n", context->stack, context->stacksz, context->stackalign);
return 0;
}
void PushString(x64emu_t *emu, const char* s)
{
int sz = strlen(s) + 1;
R_RSP -= sz;
memcpy((void*)R_RSP, s, sz);
}
EXPORTDYN
void SetupInitialStack(x64emu_t *emu)
{
Push64(emu, 0);
PushString(emu, emu->context->argv[0]);
uintptr_t p_arg0 = R_RSP;
uintptr_t p_envv[emu->context->envc];
for (int i=emu->context->envc-1; i>=0; --i) {
PushString(emu, emu->context->envv[i]);
box_free(emu->context->envv[i]);
p_envv[i] = R_RSP;
}
uintptr_t p_argv[emu->context->argc];
for (int i=emu->context->argc-1; i>=0; --i) {
PushString(emu, emu->context->argv[i]);
p_argv[i] = R_RSP;
box_free(emu->context->argv[i]);
emu->context->argv[i] = (char*)p_argv[i];
}
uintptr_t tmp = (R_RSP)&~(emu->context->stackalign-1);
memset((void*)tmp, 0, R_RSP-tmp);
R_RSP=tmp;
PushString(emu, "x86_64");
uintptr_t p_x86_64 = R_RSP;
uintptr_t p_random = real_getauxval(25);
if(!p_random) {
for (int i=0; i<4; ++i)
Push32(emu, random());
p_random = R_RSP;
}
tmp = (R_RSP)&~(emu->context->stackalign-1);
memset((void*)tmp, 0, R_RSP-tmp);
R_RSP=tmp;
3 0x400040
4 0x38
5 0xb
6 0x1000
7 0x7f7addca6000
8 (nil)
9 0x401040
11 0x3e8
12 0x3e8
13 0x3e8
14 0x3e8
16 0xbfebfbff
15 0x7ffd5074c4c9
17 0x64
23 (nil)
25 0x7ffd5074c4b9
26 (nil)
31 0x7ffd5074efea
33 0x7ffd507e6000
*/
Push64(emu, 0); Push64(emu, 0);
Push64(emu, box64_pagesize); Push64(emu, 6);
Push64(emu, 0); Push64(emu, 8);
Push64(emu, R_RIP); Push64(emu, 9);
Push64(emu, real_getauxval(11)); Push64(emu, 11);
Push64(emu, real_getauxval(12)); Push64(emu, 12);
Push64(emu, real_getauxval(13)); Push64(emu, 13);
Push64(emu, real_getauxval(14)); Push64(emu, 14);
Push64(emu, p_x86_64); Push64(emu, 15);
Push64(emu, 1<<0
| 1<<4
| 1<<8
| 1<<11
| 1<<15
| 1<<19
| 1<<23
| 1<<24
| 1<<25
| 1<<26
| 1<<28
| 1<<30
);
Push64(emu, 16);
Push64(emu, real_getauxval(23)); Push64(emu, 23);
Push64(emu, p_random); Push64(emu, 25);
Push64(emu, 0); Push64(emu, 26);
Push64(emu, p_arg0); Push64(emu, 31);
Push64(emu, emu->context->vsyscall); Push64(emu, 32);
if(!emu->context->auxval_start)
emu->context->auxval_start = (uintptr_t*)R_RSP;
Push64(emu, 0);
for (int i=emu->context->envc-1; i>=0; --i)
Push64(emu, p_envv[i]);
box_free(emu->context->envv);
emu->context->envv = (char**)R_RSP;
Push64(emu, 0);
for (int i=emu->context->argc-1; i>=0; --i)
Push64(emu, p_argv[i]);
box_free(emu->context->argv);
emu->context->argv = (char**)R_RSP;
Push64(emu, emu->context->argc);
}