From fadb39dd81f0c4a1e9a8473bde6b54d6418eae1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Dom=C3=ADnguez?= Date: Fri, 6 Sep 2019 14:28:30 +0200 Subject: [PATCH] Support ARM64 architecture --- src/Makefile | 23 ++++++++++ src/arch/arm64/arch.c | 64 +++++++++++++++++++++++++++ src/arch/arm64/arch.h | 62 +++++++++++++++++++++++++++ src/tracy-event.c | 22 +++++++--- src/tracy-modification.c | 93 +++++++++++++++++++++++++++++++++++++++- src/tracy-safe-fork.c | 53 ++++++++++++++++++++--- src/tracy.c | 14 +++++- src/tracyarch.h | 8 ++++ src/trampy.c | 22 +++++++++- 9 files changed, 344 insertions(+), 17 deletions(-) create mode 100644 src/arch/arm64/arch.c create mode 100644 src/arch/arm64/arch.h diff --git a/src/Makefile b/src/Makefile index 0d5e251..08a2f23 100644 --- a/src/Makefile +++ b/src/Makefile @@ -29,7 +29,10 @@ ifeq ($(uname_M),armv5tel) arch="arm" else ifeq ($(uname_M),armv7l) arch="arm" +else ifeq ($(uname_M),aarch64) +arch="arm64" else ifeq ($(uname_M),x86_64) +CFLAGS+=-I/usr/include/x86_64-linux-gnu arch="x86_64" else ifeq ($(uname_M),i686) arch="i686" @@ -44,6 +47,9 @@ ARCH_OS=arch/amd64/arch.o else ifeq ($(arch), "arm") ARCH_HS=arch/arm/arch.h arch/arm/syscalls.h ARCH_OS=arch/arm/arch.o +else ifeq ($(arch), "arm64") +ARCH_HS=arch/arm64/arch.h arch/arm64/syscalls.h +ARCH_OS=arch/arm64/arch.o else ifeq ($(arch), "i686") ARCH_HS=arch/x86/arch.h arch/x86/syscalls.h ARCH_OS=arch/x86/arch.o @@ -187,6 +193,23 @@ arch/arm/syscall_eabi.h: | $(CC) $(CFLAGS) - -E -P | ( echo "#include " ; cat ) \ | grep -v '# '| $(CC) $(CFLAGS) -E -P - | grep '{.*' \ > arch/arm/syscall_eabi.h + +else ifeq ($(arch),"arm64") +# +# *** ARM64 *** +# +arch/arm64/arch.o: $(TRACY_HS) arch/arm64/syscalls.h +arch/arm64/syscalls.h: $(TRACY_HS) arch/arm64/syscall_eabi.h + +arch/arm64/syscall_eabi.h: + echo "#include " | $(CC) $(CFLAGS) - -E -P -dM | \ + grep "define SYS" | cut -f2 -d" " \ + | ( echo "#define DEF_SYSCALL(NAME) {#NAME, SYS_ ## NAME}," ; \ + sed 's/SYS_//;s/\(.*\)/DEF_SYSCALL(&)/' ; echo "{NULL, -1}") \ + | $(CC) $(CFLAGS) - -E -P | ( echo "#include " ; cat ) \ + | grep -v '# '| $(CC) $(CFLAGS) -E -P - | grep '{.*' \ + > arch/arm64/syscall_eabi.h + else ifeq ($(arch),"i686") # # *** x86 *** diff --git a/src/arch/arm64/arch.c b/src/arch/arm64/arch.c new file mode 100644 index 0000000..1749c1f --- /dev/null +++ b/src/arch/arm64/arch.c @@ -0,0 +1,64 @@ +#include + +#include "../../tracy.h" + +int get_abi(struct tracy_event *s) { + (void) s; + + return 0; +} + +long get_reg(struct TRACY_REGS_NAME *r, int reg, int abi) { + (void) abi; + + switch (reg) { + case 0: + return r->regs[0]; + break; + case 1: + return r->regs[1]; + break; + case 2: + return r->regs[2]; + break; + case 3: + return r->regs[3]; + break; + case 4: + return r->regs[4]; + break; + case 5: + return r->regs[5]; + break; + } + + /* We should never reach this */ + return -1; +} + +long set_reg(struct TRACY_REGS_NAME *r, int reg, int abi, long val) { + (void) abi; + + switch (reg) { + case 0: + r->regs[0] = val; + break; + case 1: + r->regs[1] = val; + break; + case 2: + r->regs[2] = val; + break; + case 3: + r->regs[3] = val; + break; + case 4: + r->regs[4] = val; + break; + case 5: + r->regs[5] = val; + break; + } + + return 0; +} diff --git a/src/arch/arm64/arch.h b/src/arch/arm64/arch.h new file mode 100644 index 0000000..36e4ea9 --- /dev/null +++ b/src/arch/arm64/arch.h @@ -0,0 +1,62 @@ +/* +pt_regs structure definition for reference: + +struct pt_regs { + union { + struct user_pt_regs user_regs; + struct { + u64 regs[31]; + u64 sp; + u64 pc; + u64 pstate; + }; + }; + u64 orig_x0; +#ifdef __AARCH64EB__ + u32 unused2; + s32 syscallno; +#else + s32 syscallno; + u32 unused2; +#endif + + u64 orig_addr_limit; + // Only valid when ARM64_HAS_IRQ_PRIO_MASKING is enabled. + u64 pmr_save; + u64 stackframe[2]; +}; +*/ + +#define TRACY_REGS_NAME user_pt_regs + +#define TRACY_SYSCALL_OPSIZE 8 + +/* ARM64 puts syscall number into X8 */ +#define TRACY_SYSCALL_REGISTER regs[8] +#define TRACY_SYSCALL_N regs[8] + +/* Return code is X0 */ +#define TRACY_RETURN_CODE regs[0] + +#define TRACY_IP_REG pc + +#define TRACY_STACK_POINTER sp + +#define TRACY_NR_MMAP __NR_mmap2 +#define __NR_vfork 1071 + +/* Register used to pass trampy code the tracer PID */ +#define TRAMPY_PID_REG regs[4] +#define TRAMPY_PID_ARG a4 + +#define TRACY_ABI_COUNT 1 + +#define TRACY_ABI_EABI 0 + +#define TRACY_ABI_NATIVE TRACY_ABI_EABI + +struct tracy_event; + +int get_abi(struct tracy_event *s); +long get_reg(struct TRACY_REGS_NAME *r, int reg, int abi); +long set_reg(struct TRACY_REGS_NAME *r, int reg, int abi, long val); diff --git a/src/tracy-event.c b/src/tracy-event.c index 166914d..7a971af 100644 --- a/src/tracy-event.c +++ b/src/tracy-event.c @@ -26,6 +26,8 @@ #include #include +#include +#include #include @@ -92,6 +94,8 @@ static int tracy_internal_syscall(struct tracy_event *s) { switch(s->syscall_num) { #pragma message "SYS_{fork,vfork,clone} cannot be used directly; not abi safe" /* TODO, FIXME XXX: SYS_fork is not always valid, depends on the ABI */ +#if !defined(__arm64__) && !defined(__aarch64__) + /* fork and vfork are not defined in ARM64, only clone is */ case SYS_fork: printf("Internal Syscall %s\n", get_syscall_name_abi(s->syscall_num, s->abi)); if (tracy_safe_fork(s->child, &child)) { @@ -107,14 +111,10 @@ static int tracy_internal_syscall(struct tracy_event *s) { printf("Added and resuming child\n"); tracy_continue(&new_child->event, 1); -#if 0 - printf("Continue parent\n"); - tracy_continue(s, 1); -#endif - printf("Done!\n"); return 0; break; +#endif case SYS_clone: printf("Internal Syscall %s\n", get_syscall_name_abi(s->syscall_num, s->abi)); @@ -150,6 +150,8 @@ static int tracy_internal_syscall(struct tracy_event *s) { return 0; break; +#if !defined(__arm64__) && !defined(__aarch64__) + /* fork and vfork are not defined in ARM64, only clone is */ case SYS_vfork: printf("Internal Syscall %s\n", get_syscall_name_abi(s->syscall_num, s->abi)); if (tracy_safe_fork(s->child, &child)) { @@ -173,6 +175,7 @@ static int tracy_internal_syscall(struct tracy_event *s) { printf("Done!\n"); return 0; break; +#endif default: break; @@ -386,7 +389,15 @@ struct tracy_event *tracy_wait_event(struct tracy *t, pid_t c_pid) { */ if (signal_id == (SIGTRAP | 0x80)) { /* Make functions to retrieve this */ +# if defined(__arm64__) || defined(__aarch64__) + struct iovec iov; + iov.iov_base = (void*) ®s; + iov.iov_len = sizeof(regs); + + ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov); +# else PTRACE_CHECK(PTRACE_GETREGS, pid, NULL, ®s, NULL); +# endif s->args.sp = regs.TRACY_STACK_POINTER; @@ -583,4 +594,3 @@ int tracy_continue(struct tracy_event *s, int sigoverride) { return 0; } - diff --git a/src/tracy-modification.c b/src/tracy-modification.c index 5d9feb4..992f1b3 100644 --- a/src/tracy-modification.c +++ b/src/tracy-modification.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include "tracy.h" @@ -109,7 +111,15 @@ int tracy_inject_syscall_pre_start(struct tracy_child *child, long syscall_numbe struct tracy_sc_args *a, tracy_hook_func callback) { /* TODO CHECK PRE_SYSCALL BIT */ +# if defined(__arm64__) || defined(__aarch64__) + struct iovec iov; + iov.iov_base = (void*) &child->inj.reg; + iov.iov_len = sizeof(child->inj.reg); + + ptrace(PTRACE_GETREGSET, child->pid, NT_PRSTATUS, &iov); +# else PTRACE_CHECK(PTRACE_GETREGS, child->pid, 0, &child->inj.reg, -1); +# endif child->inj.cb = callback; child->inj.injecting = 1; @@ -136,7 +146,15 @@ int tracy_inject_syscall_pre_start(struct tracy_child *child, long syscall_numbe int tracy_inject_syscall_pre_end(struct tracy_child *child, long *return_code) { struct TRACY_REGS_NAME newargs; +# if defined(__arm64__) || defined(__aarch64__) + struct iovec iov; + iov.iov_base = (void*) &newargs; + iov.iov_len = sizeof(newargs); + + ptrace(PTRACE_GETREGSET, child->pid, NT_PRSTATUS, &iov); +# else PTRACE_CHECK(PTRACE_GETREGS, child->pid, 0, &newargs, -1); +# endif *return_code = newargs.TRACY_RETURN_CODE; @@ -146,7 +164,14 @@ int tracy_inject_syscall_pre_end(struct tracy_child *child, long *return_code) { /* vvvv This is probably not required vvvv */ child->inj.reg.TRACY_SYSCALL_N = child->inj.reg.TRACY_SYSCALL_REGISTER; +# if defined(__arm64__) || defined(__aarch64__) + iov.iov_base = (void*) &child->inj.reg; + iov.iov_len = sizeof(child->inj.reg); + + ptrace(PTRACE_SETREGSET, child->pid, NT_PRSTATUS, &iov); +# else PTRACE_CHECK(PTRACE_SETREGS, child->pid, 0, &child->inj.reg, -1); +# endif PTRACE_CHECK(PTRACE_SYSCALL, child->pid, NULL, 0, -1); @@ -173,19 +198,41 @@ int tracy_inject_syscall_post_start(struct tracy_child *child, long syscall_numb struct TRACY_REGS_NAME newargs; /* TODO CHECK PRE_SYSCALL BIT */ +# if defined(__arm64__) || defined(__aarch64__) + struct iovec iov; + iov.iov_base = (void*) &child->inj.reg; + iov.iov_len = sizeof(child->inj.reg); + + ptrace(PTRACE_GETREGSET, child->pid, NT_PRSTATUS, &iov); +# else PTRACE_CHECK(PTRACE_GETREGS, child->pid, 0, &child->inj.reg, -1); +# endif child->inj.cb = callback; child->inj.injecting = 1; child->inj.pre = 0; child->inj.syscall_num = syscall_number; +# if defined(__arm64__) || defined(__aarch64__) + iov.iov_base = (void*) &newargs; + iov.iov_len = sizeof(newargs); + + ptrace(PTRACE_GETREGSET, child->pid, NT_PRSTATUS, &iov); +# else PTRACE_CHECK(PTRACE_GETREGS, child->pid, 0, &newargs, -1); +# endif /* POST, go back to PRE */ newargs.TRACY_IP_REG -= TRACY_SYSCALL_OPSIZE; +# if defined(__arm64__) || defined(__aarch64__) + iov.iov_base = (void*) &newargs; + iov.iov_len = sizeof(newargs); + + ptrace(PTRACE_SETREGSET, child->pid, NT_PRSTATUS, &iov); +# else PTRACE_CHECK(PTRACE_SETREGS, child->pid, 0, &newargs, -1); +# endif PTRACE_CHECK(PTRACE_SYSCALL, child->pid, NULL, 0, -1); @@ -213,11 +260,26 @@ int tracy_inject_syscall_post_start(struct tracy_child *child, long syscall_numb int tracy_inject_syscall_post_end(struct tracy_child *child, long *return_code) { struct TRACY_REGS_NAME newargs; +# if defined(__arm64__) || defined(__aarch64__) + struct iovec iov; + iov.iov_base = (void*) &newargs; + iov.iov_len = sizeof(newargs); + + ptrace(PTRACE_GETREGSET, child->pid, NT_PRSTATUS, &iov); +# else PTRACE_CHECK(PTRACE_GETREGS, child->pid, 0, &newargs, -1); +# endif *return_code = newargs.TRACY_RETURN_CODE; +# if defined(__arm64__) || defined(__aarch64__) + iov.iov_base = (void*) &child->inj.reg; + iov.iov_len = sizeof(child->inj.reg); + + ptrace(PTRACE_SETREGSET, child->pid, NT_PRSTATUS, &iov); +# else PTRACE_CHECK(PTRACE_SETREGS, child->pid, 0, &child->inj.reg, -1); +# endif return 0; } @@ -242,7 +304,15 @@ int tracy_modify_syscall_args(struct tracy_child *child, long syscall_number, struct tracy_sc_args *a) { struct TRACY_REGS_NAME newargs; +# if defined(__arm64__) || defined(__aarch64__) + struct iovec iov; + iov.iov_base = (void*) &newargs; + iov.iov_len = sizeof(newargs); + + ptrace(PTRACE_GETREGSET, child->pid, NT_PRSTATUS, &iov); +# else PTRACE_CHECK(PTRACE_GETREGS, child->pid, 0, &newargs, -1); +# endif newargs.TRACY_SYSCALL_REGISTER = syscall_number; newargs.TRACY_SYSCALL_N = syscall_number; /* TODO: REMOVE SYSCALL_N ???*/ @@ -262,7 +332,14 @@ int tracy_modify_syscall_args(struct tracy_child *child, long syscall_number, set_reg(&newargs, 5, child->event.abi, a->a5); } +# if defined(__arm64__) || defined(__aarch64__) + iov.iov_base = (void*) &newargs; + iov.iov_len = sizeof(newargs); + + ptrace(PTRACE_SETREGSET, child->pid, NT_PRSTATUS, &iov); +# else PTRACE_CHECK(PTRACE_SETREGS, child->pid, 0, &newargs, -1); +# endif return 0; } @@ -293,7 +370,15 @@ int tracy_modify_syscall_regs(struct tracy_child *child, long syscall_number, struct tracy_sc_args *a) { struct TRACY_REGS_NAME newargs; +# if defined(__arm64__) || defined(__aarch64__) + struct iovec iov; + iov.iov_base = (void*) &newargs; + iov.iov_len = sizeof(newargs); + + ptrace(PTRACE_GETREGSET, child->pid, NT_PRSTATUS, &iov); +# else PTRACE_CHECK(PTRACE_GETREGS, child->pid, 0, &newargs, -1); +# endif newargs.TRACY_SYSCALL_REGISTER = syscall_number; newargs.TRACY_SYSCALL_N = syscall_number; @@ -313,7 +398,14 @@ int tracy_modify_syscall_regs(struct tracy_child *child, long syscall_number, newargs.TRACY_STACK_POINTER = a->sp; } +# if defined(__arm64__) || defined(__aarch64__) + iov.iov_base = (void*) &newargs; + iov.iov_len = sizeof(newargs); + + ptrace(PTRACE_SETREGSET, child->pid, NT_PRSTATUS, &iov); +# else PTRACE_CHECK(PTRACE_SETREGS, child->pid, 0, &newargs, -1); +# endif return 0; } @@ -336,4 +428,3 @@ int tracy_deny_syscall(struct tracy_child *child) { child->denied_nr = nr; return r; } - diff --git a/src/tracy-safe-fork.c b/src/tracy-safe-fork.c index fbb93ef..86f9459 100644 --- a/src/tracy-safe-fork.c +++ b/src/tracy-safe-fork.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include "tracy.h" @@ -78,6 +80,16 @@ int tracy_safe_fork(struct tracy_child *c, pid_t *new_child) child_pid = -1; +# if defined(__arm64__) || defined(__aarch64__) + struct iovec iov_ret; + iov_ret.iov_base = (void*) &args_ret; + iov_ret.iov_len = sizeof(args_ret); + + struct iovec iov; + iov.iov_base = (void*) &args; + iov.iov_len = sizeof(args); +# endif + tracy_debug_current(c); /* @@ -122,20 +134,19 @@ int tracy_safe_fork(struct tracy_child *c, pid_t *new_child) /* Fetch the registers to store the original forking syscall and more importantly * the instruction pointer. */ + +# if defined(__arm64__) || defined(__aarch64__) + ptrace(PTRACE_GETREGSET, c->pid, NT_PRSTATUS, &iov); +# else PTRACE_CHECK(PTRACE_GETREGS, c->pid, 0, &args, -1); +# endif /* Deny so we can set the IP on the denied post and do our own fork in a * controlled environment */ tracy_deny_syscall(c); c->denied_nr = 0; PTRACE_CHECK(PTRACE_SYSCALL, c->pid, 0, 0, -1); -/* - puts("DENIED, in PRE"); -*/ waitpid(c->pid, &status, __WALL); -/* - puts("AFTER DENIED, entered POST"); -*/ /* Okay, the child is now in POST syscall mode, and it has * just executed a bogus syscall (getpid) inserted by deny syscall. @@ -182,7 +193,11 @@ int tracy_safe_fork(struct tracy_child *c, pid_t *new_child) printf(_b("Pointer data @ IP-4 0x%lx: 0x%lx")"\n", ip - 4, ptrace(PTRACE_PEEKDATA, c->pid, ip - 4, NULL)); */ +# if defined(__arm64__) || defined(__aarch64__) + ptrace(PTRACE_SETREGSET, c->pid, NT_PRSTATUS, &iov); +# else PTRACE_CHECK(PTRACE_SETREGS, c->pid, 0, &args, -1); +# endif /* printf("The IP was changed from %p to %p\n", (void*)ip, (void*)mmap_ret); @@ -197,7 +212,11 @@ int tracy_safe_fork(struct tracy_child *c, pid_t *new_child) * trying to execute a sched_yield, which we shall now make * into a fork syscall. */ +# if defined(__arm64__) || defined(__aarch64__) + ptrace(PTRACE_GETREGSET, c->pid, NT_PRSTATUS, &iov_ret); +# else PTRACE_CHECK(PTRACE_GETREGS, c->pid, 0, &args_ret, -1); +# endif /* printf("The IP is now %p\n", (void*)args_ret.TRACY_IP_REG); printf("Modifying syscall back to fork\n"); @@ -221,7 +240,11 @@ int tracy_safe_fork(struct tracy_child *c, pid_t *new_child) PTRACE_CHECK(PTRACE_SET_SYSCALL, c->pid, 0, (void*)orig_syscall, -1); #endif +# if defined(__arm64__) || defined(__aarch64__) + ptrace(PTRACE_SETREGSET, c->pid, NT_PRSTATUS, &iov_ret); +# else PTRACE_CHECK(PTRACE_SETREGS, c->pid, 0, &args_ret, -1); +# endif /* puts("PRE, Entering POST"); @@ -321,7 +344,11 @@ int tracy_safe_fork(struct tracy_child *c, pid_t *new_child) if (!is_vforking || child_pid == -1) { waitpid(c->pid, &status, __WALL); +# if defined(__arm64__) || defined(__aarch64__) + ptrace(PTRACE_GETREGSET, c->pid, NT_PRSTATUS, &iov_ret); +# else PTRACE_CHECK(PTRACE_GETREGS, c->pid, 0, &args_ret, -1); +# endif /* printf("The IP is now %p\n", (void*)args_ret.TRACY_IP_REG); @@ -346,7 +373,11 @@ int tracy_safe_fork(struct tracy_child *c, pid_t *new_child) args_ret.TRACY_IP_REG = ip; args_ret.TRACY_RETURN_CODE = child_pid; +# if defined(__arm64__) || defined(__aarch64__) + ptrace(PTRACE_SETREGSET, c->pid, NT_PRSTATUS, &iov_ret); +# else PTRACE_CHECK(PTRACE_SETREGS, c->pid, 0, &args_ret, -1); +# endif printf("Return code set to %d\n", child_pid); c->pre_syscall = 0; @@ -376,15 +407,23 @@ int tracy_safe_fork(struct tracy_child *c, pid_t *new_child) args.TRACY_RETURN_CODE = 0; /* Retrieve stack pointer first. - * + * * clone can modify the stack pointer, so the stack pointer * needs to be left untouched. */ +# if defined(__arm64__) || defined(__aarch64__) + ptrace(PTRACE_GETREGSET, child_pid, NT_PRSTATUS, &iov_ret); +# else PTRACE_CHECK(PTRACE_GETREGS, child_pid, 0, &args_ret, -1); +# endif args.TRACY_STACK_POINTER = args_ret.TRACY_STACK_POINTER; /* Now update child registers */ +# if defined(__arm64__) || defined(__aarch64__) + ptrace(PTRACE_SETREGSET, child_pid, NT_PRSTATUS, &iov); +# else PTRACE_CHECK(PTRACE_SETREGS, child_pid, 0, &args, -1); +# endif /* Set enhanced syscall tracing */ PTRACE_CHECK(PTRACE_SETOPTIONS, child_pid, 0, PTRACE_O_TRACESYSGOOD, -1); diff --git a/src/tracy.c b/src/tracy.c index 4bb9600..6005124 100644 --- a/src/tracy.c +++ b/src/tracy.c @@ -42,9 +42,11 @@ #include #include +#include #include #include +#include #include "ll.h" #include "tracy.h" @@ -62,6 +64,9 @@ #ifdef __arm__ #include "arch/arm/syscalls.h" #endif +#if defined(__arm64__) || defined(__aarch64__) +#include "arch/arm64/syscalls.h" +#endif #ifdef __powerpc__ #include "arch/ppc/syscalls.h" #endif @@ -693,7 +698,15 @@ int tracy_debug_current(struct tracy_child *child) { struct TRACY_REGS_NAME a; long abi; +# if defined(__arm64__) || defined(__aarch64__) + struct iovec iov; + iov.iov_base = (void*) &a; + iov.iov_len = sizeof(a); + ptrace(PTRACE_GETREGSET, child->pid, NT_PRSTATUS, &iov); + +# else PTRACE_CHECK(PTRACE_GETREGS, child->pid, 0, &a, -1); +# endif abi = child->event.abi; @@ -837,4 +850,3 @@ int tracy_main(struct tracy *tracy) { return 0; } - diff --git a/src/tracyarch.h b/src/tracyarch.h index e6ccad9..3e86a49 100644 --- a/src/tracyarch.h +++ b/src/tracyarch.h @@ -1,15 +1,23 @@ #ifdef __x86_64__ #include "arch/amd64/arch.h" #endif + #ifdef __arm__ #include "arch/arm/arch.h" #endif + +#if defined(__arm64__) || defined(__aarch64__) +#include "arch/arm64/arch.h" +#endif + #ifdef __ppc__ #include "arch/ppc/arch.h" #endif + #ifdef __i386__ #include "arch/x86/arch.h" #endif + #ifdef __powerpc__ #include "arch/ppc/arch.h" #endif diff --git a/src/trampy.c b/src/trampy.c index 2a4a26e..c391777 100644 --- a/src/trampy.c +++ b/src/trampy.c @@ -48,7 +48,7 @@ #define ENTER_KERNEL \ "mov %0, %%rax\n" \ "syscall\n" - + #elif defined(__i386__) /* x86 performs syscalls using the 0x80 interrupt, * the syscall number is stored within the EAX register @@ -94,7 +94,26 @@ "mov r7, %1\n" \ "swi %0\n" /* OABI SWI_BASE */ + #ifdef __ARM_EABI__ + #define TRACY_SWI_BASE (0x0) + #else #define TRACY_SWI_BASE (0x900000) + #endif + + #elif defined(__arm64__) || defined(__aarch64__) + /* + * ARM64 + */ + #define SET_SYSCALL "n" + #define INLINE_ARG0 "b" + #define INLINE_ARG1 "i" + #define LOAD_TRACER_PID \ + "mov x0, x4\n" \ + "mov x1, %1\n" + #define ENTER_KERNEL \ + "mov x8, %0\n" \ + "svc 0\n" + #elif defined(__powerpc__) /* On powerpc the syscall number is stored in r0, * the arguments in r3-r9 we use r30 for the storing of the pid @@ -227,4 +246,3 @@ void __trampy_container_func() { static int __trampy_size_sym() { return 42; } -