Commit b99eae28 authored by Cyrill Gorcunov's avatar Cyrill Gorcunov

restore: Add some more structures for frame setup

Some of them are already in system header files
but until I debug all things I simply picked up
kernel's definitions just to be more-less safe.
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@gmail.com>
parent a74f379d
...@@ -3,8 +3,14 @@ ...@@ -3,8 +3,14 @@
#include <signal.h> #include <signal.h>
#include "compiler.h"
#include "types.h"
#include "image.h" #include "image.h"
#ifndef CONFIG_X86_64
# error Only x86-64 is supported
#endif
#define RESTORER_ARGS_SIZE 512 #define RESTORER_ARGS_SIZE 512
#define RESTORER_STACK_MIDDLE (16 << 10) #define RESTORER_STACK_MIDDLE (16 << 10)
#define RESTORER_STACK_SIZE (RESTORER_STACK_MIDDLE * 2) #define RESTORER_STACK_SIZE (RESTORER_STACK_MIDDLE * 2)
...@@ -19,6 +25,13 @@ typedef long (*restorer_fcall_t) (long cmd); ...@@ -19,6 +25,13 @@ typedef long (*restorer_fcall_t) (long cmd);
#define RESTORER_CMD__PR_ARG_STRING 3 #define RESTORER_CMD__PR_ARG_STRING 3
#define RESTORER_CMD__RESTORE_CORE 4 #define RESTORER_CMD__RESTORE_CORE 4
#define ABI_RED_ZONE 128
#define align_sigframe(sp) \
do { \
sp = round_down(sp, 16) - 8; \
} while (0)
struct restore_core_args { struct restore_core_args {
void *self_entry; /* restorer placed at */ void *self_entry; /* restorer placed at */
long self_size; /* size for restorer granted */ long self_size; /* size for restorer granted */
...@@ -26,10 +39,75 @@ struct restore_core_args { ...@@ -26,10 +39,75 @@ struct restore_core_args {
char self_vmas_path[64]; /* path to a self-vmas file */ char self_vmas_path[64]; /* path to a self-vmas file */
}; };
struct rt_sigcontext {
unsigned long r8;
unsigned long r9;
unsigned long r10;
unsigned long r11;
unsigned long r12;
unsigned long r13;
unsigned long r14;
unsigned long r15;
unsigned long rdi;
unsigned long rsi;
unsigned long rbp;
unsigned long rbx;
unsigned long rdx;
unsigned long rax;
unsigned long rcx;
unsigned long rsp;
unsigned long rip;
unsigned long eflags;
unsigned short cs;
unsigned short gs;
unsigned short fs;
unsigned short __pad0;
unsigned long err;
unsigned long trapno;
unsigned long oldmask;
unsigned long cr2;
struct user_fpregs_entry *fpstate;
unsigned long reserved1[8];
};
#ifndef __ARCH_SI_PREAMBLE_SIZE
#define __ARCH_SI_PREAMBLE_SIZE (3 * sizeof(int))
#endif
#define SI_MAX_SIZE 128
#ifndef SI_PAD_SIZE
#define SI_PAD_SIZE ((SI_MAX_SIZE - __ARCH_SI_PREAMBLE_SIZE) / sizeof(int))
#endif
typedef struct rt_siginfo {
int si_signo;
int si_errno;
int si_code;
int _pad[SI_PAD_SIZE];
} rt_siginfo_t;
typedef struct {
unsigned long sig[1];
} rt_sigset_t;
typedef struct rt_sigaltstack {
void *ss_sp;
int ss_flags;
size_t ss_size;
} rt_stack_t;
struct rt_ucontext {
unsigned long uc_flags;
struct rt_ucontext *uc_link;
rt_stack_t uc_stack;
struct rt_sigcontext uc_mcontext;
rt_sigset_t uc_sigmask; /* mask last for extensibility */
};
struct rt_sigframe { struct rt_sigframe {
char *pretcode; char *pretcode;
struct ucontext uc; struct rt_ucontext uc;
struct siginfo info; struct rt_siginfo info;
/* fp state follows here */ /* fp state follows here */
}; };
......
...@@ -37,6 +37,13 @@ ...@@ -37,6 +37,13 @@
c += 'a' - 10; \ c += 'a' - 10; \
} while (0) } while (0)
#define inline_memcpy(d,s,l) __builtin_memcpy(d,s,l)
#define inline_memset(d,c,l) __builtin_memset(d,c,l)
#define inline_memzero(d,l) __builtin_memset(d,0,l)
#define inline_memzero_p(d) __builtin_memset(d,0,sizeof(*(d)))
#define cp_reg(d,s,r) d->r = s->r
static void always_inline write_char(char c) static void always_inline write_char(char c)
{ {
sys_write(1, &c, 1); sys_write(1, &c, 1);
...@@ -143,7 +150,9 @@ self_len_end: ...@@ -143,7 +150,9 @@ self_len_end:
struct vma_entry vma_entry; struct vma_entry vma_entry;
u64 va; u64 va;
struct rt_sigframe *frame; struct user_fpregs_entry *fpregs;
struct user_regs_entry *gpregs;
struct rt_sigframe *rt_sigframe;
lea_args_off(args); lea_args_off(args);
...@@ -188,6 +197,7 @@ self_len_end: ...@@ -188,6 +197,7 @@ self_len_end:
} }
sys_close(fd_self_vmas); sys_close(fd_self_vmas);
sys_unlink(args->self_vmas_path);
/* /*
* OK, lets try to map new one. * OK, lets try to map new one.
...@@ -295,6 +305,33 @@ self_len_end: ...@@ -295,6 +305,33 @@ self_len_end:
goto core_restore_end; goto core_restore_end;
/*
* We need to prepare a valid sigframe here, so
* after sigreturn the kernel will pick up the
* registers from the frame, set them up and
* finally pass execution to the new IP.
*/
/*
* The sigframe should be on the stack, also
* note the kernel uses this stack not only
* for restoring registers and such but it
* save pt_regs there after sigframe, so make
* sure the stack is big enough to keep all
* this, otherwise the application get killed
* by the kernel with stack overflow error.
*/
/*
* Reuse arguments space for own needs,
* no more arguments needed so lets try
* to be thrifty with memory usage.
*/
lea_args_off(rt_sigframe);
inline_memzero_p(rt_sigframe);
/* Finally call for sigreturn */ /* Finally call for sigreturn */
sys_rt_sigreturn(); sys_rt_sigreturn();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment