2011-10-24 22:23:06 +04:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "compiler.h"
|
|
|
|
#include "types.h"
|
|
|
|
#include "syscall.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "image.h"
|
|
|
|
|
2011-10-25 21:25:42 +04:00
|
|
|
#include "crtools.h"
|
2011-10-24 22:23:06 +04:00
|
|
|
#include "restorer.h"
|
|
|
|
|
2011-10-25 21:25:42 +04:00
|
|
|
#define get_rt_sigframe_addr(stack) \
|
|
|
|
(struct rt_sigframe *)(stack - sizeof(long))
|
|
|
|
|
2011-10-25 00:01:27 +04:00
|
|
|
#define lea_args_off(p) \
|
|
|
|
do { \
|
|
|
|
asm volatile( \
|
|
|
|
"leaq restore_args__(%%rip), %%rax \n\t" \
|
|
|
|
"movq %%rax, %0 \n\t" \
|
|
|
|
: "=m"(p) \
|
|
|
|
: \
|
|
|
|
: "memory"); \
|
|
|
|
} while (0)
|
|
|
|
|
2011-10-25 21:25:42 +04:00
|
|
|
static void always_inline write_string(char *str)
|
|
|
|
{
|
|
|
|
int len = 0;
|
|
|
|
|
|
|
|
while (str[len])
|
|
|
|
len++;
|
|
|
|
|
|
|
|
sys_write(1, str, len);
|
|
|
|
}
|
|
|
|
|
2011-10-24 22:23:06 +04:00
|
|
|
long restorer(long cmd)
|
|
|
|
{
|
|
|
|
long ret;
|
|
|
|
|
|
|
|
asm volatile(
|
|
|
|
"jmp 1f \n\t"
|
|
|
|
"restore_args__: \n\t"
|
|
|
|
".skip "__stringify(RESTORER_ARGS_SIZE)",0 \n\t"
|
|
|
|
"1: \n\t"
|
|
|
|
:
|
|
|
|
:
|
|
|
|
: "memory");
|
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case RESTORER_CMD__PR_ARG_STRING:
|
|
|
|
{
|
|
|
|
char *str = NULL;
|
|
|
|
int size = 0;
|
|
|
|
|
2011-10-25 00:01:27 +04:00
|
|
|
lea_args_off(str);
|
2011-10-24 22:23:06 +04:00
|
|
|
while (str[size])
|
|
|
|
size++;
|
2011-10-25 00:01:27 +04:00
|
|
|
|
2011-10-24 22:23:06 +04:00
|
|
|
sys_write(1, str, size);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RESTORER_CMD__GET_ARG_OFFSET:
|
2011-10-25 00:01:27 +04:00
|
|
|
lea_args_off(ret);
|
2011-10-24 22:23:06 +04:00
|
|
|
break;
|
|
|
|
|
2011-10-24 23:56:36 +04:00
|
|
|
/*
|
|
|
|
* This one is very special, we never return there
|
|
|
|
* but use sigreturn facility to restore core registers
|
|
|
|
* and jump execution to some predefined ip read from
|
|
|
|
* core file.
|
|
|
|
*/
|
|
|
|
case RESTORER_CMD__RESTORE_CORE:
|
|
|
|
{
|
2011-10-25 21:25:42 +04:00
|
|
|
char *core_path;
|
|
|
|
int fd_core;
|
|
|
|
|
|
|
|
struct core_entry core_entry;
|
|
|
|
struct rt_sigframe *frame;
|
|
|
|
|
|
|
|
lea_args_off(core_path);
|
|
|
|
|
|
|
|
write_string(core_path);
|
|
|
|
write_string("\n");
|
|
|
|
|
|
|
|
fd_core = sys_open(core_path, O_RDONLY, CR_FD_PERM);
|
|
|
|
return fd_core;
|
|
|
|
|
2011-10-24 23:56:36 +04:00
|
|
|
/*
|
|
|
|
* Unmap all but self, note that we reply on
|
|
|
|
* caller that it has placed this execution
|
|
|
|
* code at the VMA which we can keep mapped.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Map VMAs we will need.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Threads here with registers and pids
|
|
|
|
* we need.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Setup a sigreturn frame.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Finally call for sigreturn */
|
|
|
|
sys_rt_sigreturn();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ret = -1;
|
|
|
|
break;
|
2011-10-24 22:23:06 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
asm volatile(".align "__stringify(RESTORER_SIZE));
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|