Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support ARM64 architecture #1

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
Expand Down Expand Up @@ -187,6 +193,23 @@ arch/arm/syscall_eabi.h:
| $(CC) $(CFLAGS) - -E -P | ( echo "#include <sys/syscall.h>" ; 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 <sys/syscall.h>" | $(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 <sys/syscall.h>" ; cat ) \
| grep -v '# '| $(CC) $(CFLAGS) -E -P - | grep '{.*' \
> arch/arm64/syscall_eabi.h

else ifeq ($(arch),"i686")
#
# *** x86 ***
Expand Down
64 changes: 64 additions & 0 deletions src/arch/arm64/arch.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <stdlib.h>

#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;
}
62 changes: 62 additions & 0 deletions src/arch/arm64/arch.h
Original file line number Diff line number Diff line change
@@ -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);
22 changes: 16 additions & 6 deletions src/tracy-event.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

#include <sys/syscall.h>
#include <sys/ptrace.h>
#include <sys/uio.h>
#include <linux/elf.h>

#include <string.h>

Expand Down Expand Up @@ -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)) {
Expand All @@ -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));
Expand Down Expand Up @@ -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)) {
Expand All @@ -173,6 +175,7 @@ static int tracy_internal_syscall(struct tracy_event *s) {
printf("Done!\n");
return 0;
break;
#endif

default:
break;
Expand Down Expand Up @@ -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*) &regs;
iov.iov_len = sizeof(regs);

ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov);
# else
PTRACE_CHECK(PTRACE_GETREGS, pid, NULL, &regs, NULL);
# endif

s->args.sp = regs.TRACY_STACK_POINTER;

Expand Down Expand Up @@ -583,4 +594,3 @@ int tracy_continue(struct tracy_event *s, int sigoverride) {

return 0;
}

Loading