Commit ff0a7c11 authored by Alexander Kartashov's avatar Alexander Kartashov Committed by Pavel Emelyanov

cr: implemented the support for the AArch64 architecture

aarch64: TLS register checkpoint/restore implementation by Christopher Covington.
Signed-off-by: 's avatarAlexander Kartashov <alekskartashov@parallels.com>
Signed-off-by: 's avatarChristopher Covington <cov@codeaurora.org>
Reviewed-by: 's avatarChristopher Covington <cov@codeaurora.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent c524562c
targets += syscalls
targets += crtools
SYS-ASM := syscalls.S
syscalls-asm-y += $(SYS-ASM:.S=).o
crtools-obj-y += crtools.o
crtools-obj-y += cpu.o
SYS-DEF := ../arm/syscall.def
SYS-ASM-COMMON := syscall-common.S
SYS-TYPES := include/syscall-types.h
SYS-CODES := include/syscall-codes.h
SYS-PROTO := include/syscall.h
SYS-GEN := ../scripts/arm/gen-syscalls.pl
SYS-GEN-TBL := ../scripts/arm/gen-sys-exec-tbl.pl
SYS-EXEC-TBL := sys-exec-tbl.c
syscalls-asm-y-asmflags += -fpie -Wstrict-prototypes -Wa,--noexecstack
syscalls-asm-y-asmflags += -nostdlib -fomit-frame-pointer -I$(obj)
ASMFLAGS += -D__ASSEMBLY__
ARCH_BITS := 64
$(obj)/$(SYS-ASM): $(obj)/$(SYS-GEN) $(obj)/$(SYS-DEF) $(obj)/$(SYS-ASM-COMMON) $(SYS-TYPES)
$(E) " GEN " $@
$(Q) perl \
$(obj)/$(SYS-GEN) \
$(obj)/$(SYS-DEF) \
$(SYS-CODES) \
$(SYS-PROTO) \
$(obj)/$(SYS-ASM) \
$(SYS-ASM-COMMON) \
$(SYS-TYPES) \
$(ARCH_BITS)
$(obj)/syscalls.o: $(obj)/$(SYS-ASM)
$(obj)/$(SYS-EXEC-TBL): $(obj)/$(SYS-GEN-TBL) $(obj)/$(SYS-DEF)
$(E) " GEN " $@
$(Q) perl \
$(obj)/$(SYS-GEN-TBL) \
$(obj)/$(SYS-DEF) \
$(obj)/$(SYS-EXEC-TBL) \
$(ARCH_BITS)
_all += $(obj)/$(SYS-EXEC-TBL)
cleanup-y += $(obj)/$(SYS-EXEC-TBL) $(obj)/$(SYS-ASM)
cleanup-y += $(SYS-CODES)
cleanup-y += $(SYS-PROTO)
ifneq ($(MAKECMDGOALS),clean)
deps-after := $(obj)/$(SYS-ASM)
incdeps := y
endif
#undef LOG_PREFIX
#define LOG_PREFIX "cpu: "
#include "cpu.h"
void cpu_set_feature(unsigned int feature)
{
}
bool cpu_has_feature(unsigned int feature)
{
return false;
}
int cpu_init(void)
{
return 0;
}
#include <string.h>
#include <unistd.h>
#include <linux/elf.h>
#include "asm/types.h"
#include "asm/restorer.h"
#include "compiler.h"
#include "ptrace.h"
#include "asm/processor-flags.h"
#include "protobuf.h"
#include "protobuf/core.pb-c.h"
#include "protobuf/creds.pb-c.h"
#include "parasite-syscall.h"
#include "syscall.h"
#include "log.h"
#include "util.h"
#include "cpu.h"
#include "parasite-syscall.h"
#include "restorer.h"
/*
* Injected syscall instruction
*/
const char code_syscall[] = {
0x01, 0x00, 0x00, 0xd4, /* SVC #0 */
0x00, 0x00, 0x20, 0xd4 /* BRK #0 */
};
const int code_syscall_size = round_up(sizeof(code_syscall), sizeof(long));
static inline void __check_code_syscall(void)
{
BUILD_BUG_ON(sizeof(code_syscall) != BUILTIN_SYSCALL_SIZE);
BUILD_BUG_ON(!is_log2(sizeof(code_syscall)));
}
void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs)
{
regs->pc = new_ip;
if (stack)
regs->sp = (unsigned long)stack;
}
bool arch_can_dump_task(pid_t pid)
{
/*
* TODO: Add proper check here
*/
return true;
}
int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
unsigned long arg1,
unsigned long arg2,
unsigned long arg3,
unsigned long arg4,
unsigned long arg5,
unsigned long arg6)
{
user_regs_struct_t regs = ctl->orig.regs;
int err;
regs.regs[8] = (unsigned long)nr;
regs.regs[0] = arg1;
regs.regs[1] = arg2;
regs.regs[2] = arg3;
regs.regs[3] = arg4;
regs.regs[4] = arg5;
regs.regs[5] = arg6;
regs.regs[6] = 0;
regs.regs[7] = 0;
err = __parasite_execute_syscall(ctl, &regs);
*ret = regs.regs[0];
return err;
}
#define assign_reg(dst, src, e) dst->e = (__typeof__(dst->e))(src).e
int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
{
struct iovec iov;
struct user_fpsimd_state fpsimd;
int i, ret;
pr_info("Dumping GP/FPU registers for %d\n", pid);
iov.iov_base = &regs;
iov.iov_len = sizeof(user_regs_struct_t);
if ((ret = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov))) {
pr_err("Failed to obtain CPU registers for %d!", pid);
goto err;
}
iov.iov_base = &fpsimd;
iov.iov_len = sizeof(fpsimd);
if ((ret = ptrace(PTRACE_GETREGSET, pid, NT_PRFPREG, &iov))) {
pr_err("Failed to obtain FPU registers for %d!", pid);
goto err;
}
// Save the Aarch64 CPU state
for (i = 0; i < 31; ++i)
assign_reg(core->ti_aarch64->gpregs, regs, regs[i]);
assign_reg(core->ti_aarch64->gpregs, regs, sp);
assign_reg(core->ti_aarch64->gpregs, regs, pc);
assign_reg(core->ti_aarch64->gpregs, regs, pstate);
// Save the FP/SIMD state
for (i = 0; i < 32; ++i)
{
core->ti_aarch64->fpsimd->vregs[2*i] = fpsimd.vregs[i];
core->ti_aarch64->fpsimd->vregs[2*i + 1] = fpsimd.vregs[i] >> 64;
}
assign_reg(core->ti_aarch64->fpsimd, fpsimd, fpsr);
assign_reg(core->ti_aarch64->fpsimd, fpsimd, fpcr);
ret = 0;
err:
return ret;
}
int arch_alloc_thread_info(CoreEntry *core)
{
ThreadInfoAarch64 *ti_aarch64;
UserAarch64RegsEntry *gpregs;
UserAarch64FpsimdContextEntry *fpsimd;
ti_aarch64 = xmalloc(sizeof(*ti_aarch64));
if (!ti_aarch64)
goto err;
thread_info_aarch64__init(ti_aarch64);
core->ti_aarch64 = ti_aarch64;
gpregs = xmalloc(sizeof(*gpregs));
if (!gpregs)
goto err;
user_aarch64_regs_entry__init(gpregs);
gpregs->regs = xmalloc(31*sizeof(uint64_t));
if (!gpregs->regs)
goto err;
gpregs->n_regs = 31;
ti_aarch64->gpregs = gpregs;
fpsimd = xmalloc(sizeof(*fpsimd));
if (!fpsimd)
goto err;
user_aarch64_fpsimd_context_entry__init(fpsimd);
ti_aarch64->fpsimd = fpsimd;
fpsimd->vregs = xmalloc(64*sizeof(fpsimd->vregs[0]));
fpsimd->n_vregs = 64;
if (!fpsimd->vregs)
goto err;
return 0;
err:
return -1;
}
void arch_free_thread_info(CoreEntry *core)
{
if (CORE_THREAD_ARCH_INFO(core)) {
if (CORE_THREAD_ARCH_INFO(core)->fpsimd) {
xfree(CORE_THREAD_ARCH_INFO(core)->fpsimd->vregs);
xfree(CORE_THREAD_ARCH_INFO(core)->fpsimd);
}
xfree(CORE_THREAD_ARCH_INFO(core)->gpregs->regs);
xfree(CORE_THREAD_ARCH_INFO(core)->gpregs);
xfree(CORE_THREAD_ARCH_INFO(core));
CORE_THREAD_ARCH_INFO(core) = NULL;
}
}
int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core)
{
int i;
struct fpsimd_context *fpsimd = &RT_SIGFRAME_FPU(sigframe);
if (core->ti_aarch64->fpsimd->n_vregs != 64)
return 1;
for (i = 0; i < 32; ++i)
fpsimd->vregs[i] = (__uint128_t)core->ti_aarch64->fpsimd->vregs[2*i] |
((__uint128_t)core->ti_aarch64->fpsimd->vregs[2*i + 1] << 64);
assign_reg(fpsimd, *core->ti_aarch64->fpsimd, fpsr);
assign_reg(fpsimd, *core->ti_aarch64->fpsimd, fpcr);
fpsimd->head.magic = FPSIMD_MAGIC;
fpsimd->head.size = sizeof(*fpsimd);
return 0;
}
void *mmap_seized(
struct parasite_ctl *ctl,
void *addr, size_t length, int prot,
int flags, int fd, off_t offset)
{
unsigned long map;
int err;
err = syscall_seized(ctl, __NR_mmap, &map,
(unsigned long)addr, length, prot, flags, fd, offset);
if (err < 0 || map > TASK_SIZE)
map = 0;
return (void *)map;
}
int restore_gpregs(struct rt_sigframe *f, UserRegsEntry *r)
{
#define CPREG1(d) f->uc.uc_mcontext.d = r->d
int i;
for (i = 0; i < 31; ++i)
CPREG1(regs[i]);
CPREG1(sp);
CPREG1(pc);
CPREG1(pstate);
#undef CPREG1
return 0;
}
#ifndef __CR_ATOMIC_H__
#define __CR_ATOMIC_H__
typedef struct {
int counter;
} atomic_t;
/* Copied from the Linux header arch/arm/include/asm/barrier.h */
#define smp_mb() asm volatile("dmb ish" : : : "memory")
/* Copied from the Linux kernel header arch/arm64/include/asm/atomic.h */
static inline int atomic_read(const atomic_t *v)
{
return (*(volatile int *)&(v)->counter);
}
static inline void atomic_set(atomic_t *v, int i)
{
v->counter = i;
}
#define atomic_get atomic_read
static inline int atomic_add_return(int i, atomic_t *v)
{
unsigned long tmp;
int result;
asm volatile(
"1: ldxr %w0, %2\n"
" add %w0, %w0, %w3\n"
" stlxr %w1, %w0, %2\n"
" cbnz %w1, 1b"
: "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
: "Ir" (i)
: "cc", "memory");
smp_mb();
return result;
}
static inline int atomic_sub_return(int i, atomic_t *v)
{
unsigned long tmp;
int result;
asm volatile(
"1: ldxr %w0, %2\n"
" sub %w0, %w0, %w3\n"
" stlxr %w1, %w0, %2\n"
" cbnz %w1, 1b"
: "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
: "Ir" (i)
: "cc", "memory");
smp_mb();
return result;
}
static inline int atomic_inc(atomic_t *v) { return atomic_add_return(1, v) - 1; }
static inline int atomic_add(int val, atomic_t *v) { return atomic_add_return(val, v) - val; }
static inline int atomic_dec(atomic_t *v) { return atomic_sub_return(1, v) + 1; }
/* true if the result is 0, or false for all other cases. */
#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0)
#define atomic_inc_return(v) (atomic_add_return(1, v))
#endif /* __CR_ATOMIC_H__ */
#ifndef __CR_ASM_BITOPS_H__
#define __CR_ASM_BITOPS_H__
#include "compiler.h"
#include "asm-generic/bitops.h"
#endif /* __CR_ASM_BITOPS_H__ */
#ifndef __CR_BITSPERLONG_H__
#define __CR_BITSPERLONG_H__
#define BITS_PER_LONG 64
#endif /* __CR_BITSPERLONG_H__ */
#ifndef __CR_ASM_DUMP_H__
#define __CR_ASM_DUMP_H__
extern int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core);
extern int arch_alloc_thread_info(CoreEntry *core);
extern void arch_free_thread_info(CoreEntry *core);
static inline void core_put_tls(CoreEntry *core, tls_t tls)
{
core->ti_aarch64->tls = tls;
}
#endif
#ifndef __CR_ASM_FPU_H__
#define __CR_ASM_FPU_H__
#endif /* __CR_ASM_FPU_H__ */
#ifndef __CR_ASM_INT_H__
#define __CR_ASM_INT_H__
#include "asm-generic/int.h"
#endif /* __CR_ASM_INT_H__ */
#ifndef __CR_LINKAGE_H__
#define __CR_LINKAGE_H__
#ifdef __ASSEMBLY__
#define __ALIGN .align 4, 0x00
#define __ALIGN_STR ".align 4, 0x00"
#define GLOBAL(name) \
.globl name; \
name:
#define ENTRY(name) \
.globl name; \
.type name, #function; \
__ALIGN; \
name:
#define END(sym) \
.size sym, . - sym
#endif /* __ASSEMBLY__ */
#endif /* __CR_LINKAGE_H__ */
#ifndef __CR_ASM_PARASITE_SYSCALL_H__
#define __CR_ASM_PARASITE_SYSCALL_H__
#define ARCH_SI_TRAP TRAP_BRKPT
extern const char code_syscall[];
extern const int code_syscall_size;
void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs);
void *mmap_seized(struct parasite_ctl *ctl,
void *addr, size_t length, int prot,
int flags, int fd, off_t offset);
#endif
#ifndef __ASM_PARASITE_H__
#define __ASM_PARASITE_H__
static inline void arch_get_tls(tls_t *ptls)
{
tls_t tls;
asm("mrs %0, tpidr_el0" : "=r" (tls));
*ptls = tls;
}
#endif
#ifndef __CR_PROCESSOR_FLAGS_H__
#define __CR_PROCESSOR_FLAGS_H__
#endif
#ifndef __CR_ASM_RESTORE_H__
#define __CR_ASM_RESTORE_H__
#include "asm/restorer.h"
#include "protobuf/core.pb-c.h"
#define JUMP_TO_RESTORER_BLOB(new_sp, restore_task_exec_start, \
task_args) \
asm volatile( \
"and sp, %0, #~15 \n" \
"mov x0, %2 \n" \
"br %1 \n" \
: \
: "r"(new_sp), \
"r"(restore_task_exec_start), \
"r"(task_args) \
: "sp", "x0", "memory")
static inline void core_get_tls(CoreEntry *pcore, tls_t *ptls)
{
*ptls = pcore->ti_aarch64->tls;
}
int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core);
#endif
#ifndef __CR_ASM_RESTORER_H__
#define __CR_ASM_RESTORER_H__
#include <asm/sigcontext.h>
#include <sys/ucontext.h>
#include "asm/types.h"
#include "protobuf/core.pb-c.h"
/* Copied from the kernel header arch/arm64/include/uapi/asm/sigcontext.h */
#define FPSIMD_MAGIC 0x46508001
typedef struct fpsimd_context fpu_state_t;
struct aux_context {
struct fpsimd_context fpsimd;
/* additional context to be added before "end" */
struct _aarch64_ctx end;
};
// XXX: the idetifier rt_sigcontext is expected to be struct by the CRIU code
#define rt_sigcontext sigcontext
#include "sigframe.h"
/* Copied from the kernel source arch/arm64/kernel/signal.c */
struct rt_sigframe {
siginfo_t info;
struct ucontext uc;
u64 fp;
u64 lr;
};
#define ARCH_RT_SIGRETURN(new_sp) \
asm volatile( \
"mov sp, %0 \n" \
"mov x8, #"__stringify(__NR_rt_sigreturn)" \n" \
"svc #0 \n" \
: \
: "r"(new_sp) \
: "sp", "x8", "memory")
#define RUN_CLONE_RESTORE_FN(ret, clone_flags, new_sp, parent_tid, \
thread_args, clone_restore_fn) \
asm volatile( \
"clone_emul: \n" \
"and x1, %2, #~15 \n" \
"sub x1, x2, #16 \n" \
"stp %5, %6, [x1] \n" \
"mov x0, %1 \n" \
"mov x2, %3 \n" \
"mov x3, %4 \n" \
"mov x8, #"__stringify(__NR_clone)" \n" \
"svc #0 \n" \
\
"cbz x0, thread_run \n" \
\
"mov %0, x0 \n" \
"b clone_end \n" \
\
"thread_run: \n" \
"ldp x1, x0, [sp] \n" \
"br x1 \n" \
\
"clone_end: \n" \
: "=r"(ret) \
: "r"(clone_flags), \
"r"(new_sp), \
"r"(&parent_tid), \
"r"(&thread_args[i].pid), \
"r"(clone_restore_fn), \
"r"(&thread_args[i]) \
: "x0", "x1", "x2", "x3", "x8", "memory")
#define ARCH_FAIL_CORE_RESTORE \
asm volatile( \
"mov sp, %0 \n" \
"mov x0, #0 \n" \
"b x0 \n" \
: \
: "r"(ret) \
: "sp", "x0", "memory")
#define RT_SIGFRAME_UC(rt_sigframe) rt_sigframe->uc
#define RT_SIGFRAME_REGIP(rt_sigframe) ((long unsigned int)(rt_sigframe)->uc.uc_mcontext.pc)
#define RT_SIGFRAME_HAS_FPU(rt_sigframe) (1)
#define RT_SIGFRAME_FPU(rt_sigframe) ((struct aux_context*)&(rt_sigframe)->uc.uc_mcontext.__reserved)->fpsimd
#define SIGFRAME_OFFSET 0
int restore_gpregs(struct rt_sigframe *f, UserAarch64RegsEntry *r);
int restore_nonsigframe_gpregs(UserAarch64RegsEntry *r);
static inline int sigreturn_prep_fpu_frame(struct rt_sigframe *sigframe, fpu_state_t *fpu_state) { return 0; }
static inline void restore_tls(tls_t *ptls)
{
asm("msr tpidr_el0, %0" : : "r" (*ptls));
}
#endif
#ifndef __CR_ASM_STRING_H__
#define __CR_ASM_STRING_H__
#include "compiler.h"
#include "asm-generic/string.h"
#endif /* __CR_ASM_STRING_H__ */
/**
* This source contains emulation of syscalls
* that are not implemented in the AArch64 Linux kernel
*/
ENTRY(sys_open)
mov x3, x2
mov x2, x1
mov x1, x0
mov x0, #-100
b sys_openat
END(sys_open)
ENTRY(sys_mkdir)
mov x3, x2
mov x2, x1
mov x1, x0
mov x0, #-100
b sys_mkdirat
END(sys_mkdir)
ENTRY(sys_rmdir)
mov x2, #0x200 // flags = AT_REMOVEDIR
mov x1, x0
mov x0, #-100
b sys_unlinkat
END(sys_rmdir)
ENTRY(sys_unlink)
mov x2, #0 // flags = 0
mov x1, x0
mov x0, #-100
b sys_unlinkat
END(sys_unlink)
#ifndef __CR_ASM_TYPES_H__
#define __CR_ASM_TYPES_H__
#include <stdbool.h>
#include <signal.h>
#include "protobuf/core.pb-c.h"
#include "asm-generic/page.h"
#include "asm/bitops.h"
#include "asm/int.h"
#define SIGMAX 64
#define SIGMAX_OLD 31
#define MAJOR(dev) ((dev)>>8)
#define MINOR(dev) ((dev) & 0xff)
typedef void rt_signalfn_t(int, siginfo_t *, void *);
typedef rt_signalfn_t *rt_sighandler_t;
typedef void rt_restorefn_t(void);
typedef rt_restorefn_t *rt_sigrestore_t;
#define _KNSIG 64
#define _NSIG_BPW 64
#define _KNSIG_WORDS (_KNSIG / _NSIG_BPW)
typedef struct {
unsigned long sig[_KNSIG_WORDS];
} k_rtsigset_t;
static inline void ksigfillset(k_rtsigset_t *set)
{
int i;
for (i = 0; i < _KNSIG_WORDS; i++)
set->sig[i] = (unsigned long)-1;
}
#define SA_RESTORER 0x00000000
typedef struct {
rt_sighandler_t rt_sa_handler;
unsigned long rt_sa_flags;
rt_sigrestore_t rt_sa_restorer;
k_rtsigset_t rt_sa_mask;
} rt_sigaction_t;
/*
* Copied from the Linux kernel header arch/arm64/include/uapi/asm/ptrace.h
*
* A thread ARM CPU context
*/
typedef struct user_pt_regs user_regs_struct_t;
#define ASSIGN_TYPED(a, b) do { a = (typeof(a))b; } while (0)
#define ASSIGN_MEMBER(a,b,m) do { ASSIGN_TYPED((a)->m, (b)->m); } while (0)
#define REG_RES(regs) ((u64)(regs).regs[0])
#define REG_IP(regs) ((u64)(regs).pc)
#define REG_SYSCALL_NR(regs) ((u64)(regs).regs[8])
// Copied from the Linux kernel arch/arm64/include/asm/memory.h
// FIXME: what about a 32bit task?
#define TASK_SIZE (1ULL << 39)
#define AT_VECTOR_SIZE 40
typedef UserAarch64RegsEntry UserRegsEntry;
#define CORE_ENTRY__MARCH CORE_ENTRY__MARCH__AARCH64
#define CORE_THREAD_ARCH_INFO(core) core->ti_aarch64
#define TI_SP(core) ((core)->ti_aarch64->gpregs->sp)
typedef uint64_t auxv_t;
typedef uint64_t tls_t;
static inline void *decode_pointer(uint64_t v) { return (void*)v; }
static inline uint64_t encode_pointer(void *p) { return (uint64_t)p; }
#endif /* __CR_ASM_TYPES_H__ */
#ifndef __CR_ASM_VDSO_H__
#define __CR_ASM_VDSO_H__
#include <sys/types.h>
#include "protobuf/vma.pb-c.h"
struct vdso_symtable;
struct parasite_ctl;
struct vm_area_list;
enum {
VDSO_SYMBOL_CLOCK_GETRES,
VDSO_SYMBOL_CLOCK_GETTIME,
VDSO_SYMBOL_GETTIMEOFDAY,
VDSO_SYMBOL_RT_SIGRETURN,
VDSO_SYMBOL_MAX
};
#define VDSO_SYMBOL_CLOCK_GETRES_NAME "__kernel_clock_getres"
#define VDSO_SYMBOL_CLOCK_GETTIME_NAME "__kernel_clock_gettime"
#define VDSO_SYMBOL_GETTIMEOFDAY_NAME "__kernel_gettimeofday"
#define VDSO_SYMBOL_RT_SIGRETURN_NAME "__kernel_rt_sigreturn"
#define DECLARE_VDSO(ident_name, symtab_name) \
\
char ident_name[] = { \
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
}; \
\
char *symtab_name[VDSO_SYMBOL_MAX] = { \
[VDSO_SYMBOL_CLOCK_GETRES] = VDSO_SYMBOL_CLOCK_GETRES_NAME, \
[VDSO_SYMBOL_RT_SIGRETURN] = VDSO_SYMBOL_RT_SIGRETURN_NAME, \
[VDSO_SYMBOL_GETTIMEOFDAY] = VDSO_SYMBOL_GETTIMEOFDAY_NAME, \
[VDSO_SYMBOL_CLOCK_GETTIME] = VDSO_SYMBOL_CLOCK_GETTIME_NAME \
};
extern int vdso_redirect_calls(void *base_to, void *base_from, struct vdso_symtable *to, struct vdso_symtable *from);
extern int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
struct vm_area_list *vma_area_list);
#endif /* __CR_ASM_VDSO_H__ */
#include "asm/linkage.h"
#include "parasite.h"
.section .head.text, "ax"
ENTRY(__export_parasite_head_start)
adr x2, __export_parasite_head_start // get the address of this instruction
ldr x0, __export_parasite_cmd
ldr x1, parasite_args_ptr
add x1, x1, x2 // fixup __export_parasite_args
bl parasite_service
brk #0 // the instruction BRK #0 generates the signal SIGTRAP in Linux
parasite_args_ptr:
.quad __export_parasite_args
__export_parasite_cmd:
.quad 0
END(__export_parasite_head_start)
#include <unistd.h>
#include "restorer.h"
#include "asm/restorer.h"
#include "asm/string.h"
#include "syscall.h"
#include "log.h"
#include "asm/fpu.h"
#include "cpu.h"
int restore_nonsigframe_gpregs(UserRegsEntry *r)
{
return 0;
}
#include "asm/linkage.h"
syscall_common:
svc #0
ret
.macro syscall name, nr
ENTRY(\name)
mov x8, \nr
b syscall_common
END(\name)
.endm
ENTRY(__cr_restore_rt)
mov x8, __NR_rt_sigreturn
svc #0
END(__cr_restore_rt)
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <elf.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include "asm/string.h"
#include "asm/types.h"
#include "compiler.h"
#include "syscall.h"
#include "crtools.h"
#include "vdso.h"
#include "vma.h"
#include "log.h"
#ifdef LOG_PREFIX
# undef LOG_PREFIX
#endif
#define LOG_PREFIX "vdso: "
int vdso_redirect_calls(void *base_to, void *base_from,
struct vdso_symtable *to,
struct vdso_symtable *from)
{
pr_err("vDSO proxy isn't implemented yet");
return -1;
}
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <elf.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include "parasite-syscall.h"
#include "parasite.h"
#include "compiler.h"
#include "kerndat.h"
#include "vdso.h"
#include "util.h"
#include "log.h"
#include "mem.h"
#include "vma.h"
#include "asm/types.h"
#include "asm/parasite-syscall.h"
#ifdef LOG_PREFIX
# undef LOG_PREFIX
#endif
#define LOG_PREFIX "vdso: "
int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
struct vm_area_list *vma_area_list)
{
return 0;
}
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