mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-24 23:56:06 +00:00

This commit adds support for AArch64 in instrumentation runtime library, including AArch64 system calls. Also this commit divides syscalls into target-specific files. Reviewed By: rafauler, yota9 Differential Revision: https://reviews.llvm.org/D151942
361 lines
12 KiB
C
361 lines
12 KiB
C
#ifndef LLVM_TOOLS_LLVM_BOLT_SYS_X86_64
|
|
#define LLVM_TOOLS_LLVM_BOLT_SYS_X86_64
|
|
|
|
// Save all registers while keeping 16B stack alignment
|
|
#define SAVE_ALL \
|
|
"push %%rax\n" \
|
|
"push %%rbx\n" \
|
|
"push %%rcx\n" \
|
|
"push %%rdx\n" \
|
|
"push %%rdi\n" \
|
|
"push %%rsi\n" \
|
|
"push %%rbp\n" \
|
|
"push %%r8\n" \
|
|
"push %%r9\n" \
|
|
"push %%r10\n" \
|
|
"push %%r11\n" \
|
|
"push %%r12\n" \
|
|
"push %%r13\n" \
|
|
"push %%r14\n" \
|
|
"push %%r15\n" \
|
|
"sub $8, %%rsp\n"
|
|
// Mirrors SAVE_ALL
|
|
#define RESTORE_ALL \
|
|
"add $8, %%rsp\n" \
|
|
"pop %%r15\n" \
|
|
"pop %%r14\n" \
|
|
"pop %%r13\n" \
|
|
"pop %%r12\n" \
|
|
"pop %%r11\n" \
|
|
"pop %%r10\n" \
|
|
"pop %%r9\n" \
|
|
"pop %%r8\n" \
|
|
"pop %%rbp\n" \
|
|
"pop %%rsi\n" \
|
|
"pop %%rdi\n" \
|
|
"pop %%rdx\n" \
|
|
"pop %%rcx\n" \
|
|
"pop %%rbx\n" \
|
|
"pop %%rax\n"
|
|
|
|
namespace {
|
|
|
|
// Get the difference between runtime addrress of .text section and
|
|
// static address in section header table. Can be extracted from arbitrary
|
|
// pc value recorded at runtime to get the corresponding static address, which
|
|
// in turn can be used to search for indirect call description. Needed because
|
|
// indirect call descriptions are read-only non-relocatable data.
|
|
uint64_t getTextBaseAddress() {
|
|
uint64_t DynAddr;
|
|
uint64_t StaticAddr;
|
|
__asm__ volatile("leaq __hot_end(%%rip), %0\n\t"
|
|
"movabsq $__hot_end, %1\n\t"
|
|
: "=r"(DynAddr), "=r"(StaticAddr));
|
|
return DynAddr - StaticAddr;
|
|
}
|
|
|
|
#define _STRINGIFY(x) #x
|
|
#define STRINGIFY(x) _STRINGIFY(x)
|
|
|
|
uint64_t __read(uint64_t fd, const void *buf, uint64_t count) {
|
|
uint64_t ret;
|
|
#if defined(__APPLE__)
|
|
#define READ_SYSCALL 0x2000003
|
|
#else
|
|
#define READ_SYSCALL 0
|
|
#endif
|
|
__asm__ __volatile__("movq $" STRINGIFY(READ_SYSCALL) ", %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(ret)
|
|
: "D"(fd), "S"(buf), "d"(count)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
uint64_t __write(uint64_t fd, const void *buf, uint64_t count) {
|
|
uint64_t ret;
|
|
#if defined(__APPLE__)
|
|
#define WRITE_SYSCALL 0x2000004
|
|
#else
|
|
#define WRITE_SYSCALL 1
|
|
#endif
|
|
__asm__ __volatile__("movq $" STRINGIFY(WRITE_SYSCALL) ", %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(ret)
|
|
: "D"(fd), "S"(buf), "d"(count)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
void *__mmap(uint64_t addr, uint64_t size, uint64_t prot, uint64_t flags,
|
|
uint64_t fd, uint64_t offset) {
|
|
#if defined(__APPLE__)
|
|
#define MMAP_SYSCALL 0x20000c5
|
|
#else
|
|
#define MMAP_SYSCALL 9
|
|
#endif
|
|
void *ret;
|
|
register uint64_t r8 asm("r8") = fd;
|
|
register uint64_t r9 asm("r9") = offset;
|
|
register uint64_t r10 asm("r10") = flags;
|
|
__asm__ __volatile__("movq $" STRINGIFY(MMAP_SYSCALL) ", %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(ret)
|
|
: "D"(addr), "S"(size), "d"(prot), "r"(r10), "r"(r8),
|
|
"r"(r9)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
uint64_t __munmap(void *addr, uint64_t size) {
|
|
#if defined(__APPLE__)
|
|
#define MUNMAP_SYSCALL 0x2000049
|
|
#else
|
|
#define MUNMAP_SYSCALL 11
|
|
#endif
|
|
uint64_t ret;
|
|
__asm__ __volatile__("movq $" STRINGIFY(MUNMAP_SYSCALL) ", %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(ret)
|
|
: "D"(addr), "S"(size)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
uint64_t __sigprocmask(int how, const void *set, void *oldset) {
|
|
#if defined(__APPLE__)
|
|
#define SIGPROCMASK_SYSCALL 0x2000030
|
|
#else
|
|
#define SIGPROCMASK_SYSCALL 14
|
|
#endif
|
|
uint64_t ret;
|
|
register long r10 asm("r10") = sizeof(uint64_t);
|
|
__asm__ __volatile__("movq $" STRINGIFY(SIGPROCMASK_SYSCALL) ", %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(ret)
|
|
: "D"(how), "S"(set), "d"(oldset), "r"(r10)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
uint64_t __getpid() {
|
|
uint64_t ret;
|
|
#if defined(__APPLE__)
|
|
#define GETPID_SYSCALL 20
|
|
#else
|
|
#define GETPID_SYSCALL 39
|
|
#endif
|
|
__asm__ __volatile__("movq $" STRINGIFY(GETPID_SYSCALL) ", %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(ret)
|
|
:
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
uint64_t __exit(uint64_t code) {
|
|
#if defined(__APPLE__)
|
|
#define EXIT_SYSCALL 0x2000001
|
|
#else
|
|
#define EXIT_SYSCALL 231
|
|
#endif
|
|
uint64_t ret;
|
|
__asm__ __volatile__("movq $" STRINGIFY(EXIT_SYSCALL) ", %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(ret)
|
|
: "D"(code)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
#if !defined(__APPLE__)
|
|
// We use a stack-allocated buffer for string manipulation in many pieces of
|
|
// this code, including the code that prints each line of the fdata file. This
|
|
// buffer needs to accomodate large function names, but shouldn't be arbitrarily
|
|
// large (dynamically allocated) for simplicity of our memory space usage.
|
|
|
|
// Declare some syscall wrappers we use throughout this code to avoid linking
|
|
// against system libc.
|
|
uint64_t __open(const char *pathname, uint64_t flags, uint64_t mode) {
|
|
uint64_t ret;
|
|
__asm__ __volatile__("movq $2, %%rax\n"
|
|
"syscall"
|
|
: "=a"(ret)
|
|
: "D"(pathname), "S"(flags), "d"(mode)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
long __getdents64(unsigned int fd, dirent64 *dirp, size_t count) {
|
|
long ret;
|
|
__asm__ __volatile__("movq $217, %%rax\n"
|
|
"syscall"
|
|
: "=a"(ret)
|
|
: "D"(fd), "S"(dirp), "d"(count)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
uint64_t __readlink(const char *pathname, char *buf, size_t bufsize) {
|
|
uint64_t ret;
|
|
__asm__ __volatile__("movq $89, %%rax\n"
|
|
"syscall"
|
|
: "=a"(ret)
|
|
: "D"(pathname), "S"(buf), "d"(bufsize)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
uint64_t __lseek(uint64_t fd, uint64_t pos, uint64_t whence) {
|
|
uint64_t ret;
|
|
__asm__ __volatile__("movq $8, %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(ret)
|
|
: "D"(fd), "S"(pos), "d"(whence)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
int __ftruncate(uint64_t fd, uint64_t length) {
|
|
int ret;
|
|
__asm__ __volatile__("movq $77, %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(ret)
|
|
: "D"(fd), "S"(length)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
int __close(uint64_t fd) {
|
|
uint64_t ret;
|
|
__asm__ __volatile__("movq $3, %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(ret)
|
|
: "D"(fd)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
int __madvise(void *addr, size_t length, int advice) {
|
|
int ret;
|
|
__asm__ __volatile__("movq $28, %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(ret)
|
|
: "D"(addr), "S"(length), "d"(advice)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
int __uname(struct UtsNameTy *Buf) {
|
|
int Ret;
|
|
__asm__ __volatile__("movq $63, %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(Ret)
|
|
: "D"(Buf)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return Ret;
|
|
}
|
|
|
|
uint64_t __nanosleep(const timespec *req, timespec *rem) {
|
|
uint64_t ret;
|
|
__asm__ __volatile__("movq $35, %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(ret)
|
|
: "D"(req), "S"(rem)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
int64_t __fork() {
|
|
uint64_t ret;
|
|
__asm__ __volatile__("movq $57, %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(ret)
|
|
:
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
int __mprotect(void *addr, size_t len, int prot) {
|
|
int ret;
|
|
__asm__ __volatile__("movq $10, %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(ret)
|
|
: "D"(addr), "S"(len), "d"(prot)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
uint64_t __getppid() {
|
|
uint64_t ret;
|
|
__asm__ __volatile__("movq $110, %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(ret)
|
|
:
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
int __setpgid(uint64_t pid, uint64_t pgid) {
|
|
int ret;
|
|
__asm__ __volatile__("movq $109, %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(ret)
|
|
: "D"(pid), "S"(pgid)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
uint64_t __getpgid(uint64_t pid) {
|
|
uint64_t ret;
|
|
__asm__ __volatile__("movq $121, %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(ret)
|
|
: "D"(pid)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
int __kill(uint64_t pid, int sig) {
|
|
int ret;
|
|
__asm__ __volatile__("movq $62, %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(ret)
|
|
: "D"(pid), "S"(sig)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
int __fsync(int fd) {
|
|
int ret;
|
|
__asm__ __volatile__("movq $74, %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(ret)
|
|
: "D"(fd)
|
|
: "cc", "rcx", "r11", "memory");
|
|
return ret;
|
|
}
|
|
|
|
// %rdi %rsi %rdx %r10 %r8
|
|
// sys_prctl int option unsigned unsigned unsigned unsigned
|
|
// long arg2 long arg3 long arg4 long arg5
|
|
int __prctl(int Option, unsigned long Arg2, unsigned long Arg3,
|
|
unsigned long Arg4, unsigned long Arg5) {
|
|
int Ret;
|
|
register long rdx asm("rdx") = Arg3;
|
|
register long r8 asm("r8") = Arg5;
|
|
register long r10 asm("r10") = Arg4;
|
|
__asm__ __volatile__("movq $157, %%rax\n"
|
|
"syscall\n"
|
|
: "=a"(Ret)
|
|
: "D"(Option), "S"(Arg2), "d"(rdx), "r"(r10), "r"(r8)
|
|
:);
|
|
return Ret;
|
|
}
|
|
|
|
#endif
|
|
|
|
} // anonymous namespace
|
|
|
|
#endif
|