mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-10-04 05:31:02 +00:00
Mint APE Loader v1.5
This change ports APE Loader to Linux AARCH64, so that Raspberry Pi users can run programs like redbean, without the executable needing to modify itself. Progress has also slipped into this change on the issue of making progress better conforming to user expectations and industry standards regarding which symbols we're allowed to declare
This commit is contained in:
parent
6843150e0c
commit
7e0a09feec
510 changed files with 1783 additions and 1483 deletions
|
@ -72,7 +72,9 @@ SECTIONS {
|
|||
KEEP(*(SORT_NONE(.fini)))
|
||||
} =0x1f2003d5
|
||||
|
||||
.privileged ALIGN(CONSTANT(COMMONPAGESIZE)) : {
|
||||
. += CONSTANT(COMMONPAGESIZE);
|
||||
|
||||
.privileged : {
|
||||
__privileged_start = .;
|
||||
*(.privileged*)
|
||||
} =0x1f2003d6
|
||||
|
@ -119,7 +121,7 @@ SECTIONS {
|
|||
_etext = .;
|
||||
PROVIDE(etext = .);
|
||||
|
||||
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
||||
. += CONSTANT(COMMONPAGESIZE);
|
||||
. = DATA_SEGMENT_ALIGN(CONSTANT(COMMONPAGESIZE), CONSTANT(COMMONPAGESIZE));
|
||||
|
||||
.eh_frame : ONLY_IF_RW {
|
||||
|
|
18
ape/ape-m1.c
18
ape/ape-m1.c
|
@ -190,6 +190,19 @@ static int StrCmp(const char *l, const char *r) {
|
|||
return (l[i] & 255) - (r[i] & 255);
|
||||
}
|
||||
|
||||
static const char *BaseName(const char *s) {
|
||||
int c;
|
||||
const char *b = "";
|
||||
if (s) {
|
||||
while ((c = *s++)) {
|
||||
if (c == '/') {
|
||||
b = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
static void Bzero(void *a, unsigned long n) {
|
||||
long z;
|
||||
char *p, *e;
|
||||
|
@ -848,7 +861,7 @@ int main(int argc, char **argv, char **envp) {
|
|||
} else if (argc < 2) {
|
||||
Emit("usage: ape PROG [ARGV1,ARGV2,...]\n"
|
||||
" ape - PROG [ARGV0,ARGV1,...]\n"
|
||||
"actually portable executable loader silicon 1.4\n"
|
||||
"actually portable executable loader silicon 1.5\n"
|
||||
"copyright 2023 justine alexandra roberts tunney\n"
|
||||
"https://justine.lol/ape.html\n");
|
||||
_exit(1);
|
||||
|
@ -871,7 +884,8 @@ int main(int argc, char **argv, char **envp) {
|
|||
pe = M->ehdr.buf + rc;
|
||||
|
||||
// resolve argv[0] to reflect path search
|
||||
if (argc > 0 && *prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) {
|
||||
if ((argc > 0 && *prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) ||
|
||||
!StrCmp(BaseName(prog), argv[0])) {
|
||||
tp -= (n = StrLen(exe) + 1);
|
||||
MemMove(tp, exe, n);
|
||||
argv[0] = tp;
|
||||
|
|
|
@ -610,7 +610,7 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
|
|||
// extract the loader into a temp folder, and use it to
|
||||
// load the APE without modifying it.
|
||||
.ascii "[ x\"$1\" != x--assimilate ] && {\n"
|
||||
.ascii "t=\"${TMPDIR:-${HOME:-.}}/.ape-1.4\"\n"
|
||||
.ascii "t=\"${TMPDIR:-${HOME:-.}}/.ape-1.5\"\n"
|
||||
.ascii "[ -x \"$t\" ] || {\n"
|
||||
.ascii "mkdir -p \"${t%/*}\" &&\n"
|
||||
.ascii "dd if=\"$o\" of=\"$t.$$\" skip="
|
||||
|
@ -717,8 +717,8 @@ emush: .ascii "\n@\n#'\"\n"
|
|||
.previous
|
||||
// ...
|
||||
// decentralized section (.emush)
|
||||
// - STATIC_YOINK("blink_linux_aarch64"); // for raspberry pi
|
||||
// - STATIC_YOINK("blink_xnu_aarch64"); // is apple silicon
|
||||
// - __static_yoink("blink_linux_aarch64"); // for raspberry pi
|
||||
// - __static_yoink("blink_xnu_aarch64"); // is apple silicon
|
||||
// ...
|
||||
.section .emushepilogue,"a",@progbits
|
||||
.ascii "echo \"$0: this ape binary lacks $m support\" >&2\n"
|
||||
|
@ -818,7 +818,7 @@ ape.ident:
|
|||
.long 1
|
||||
1: .asciz "APE"
|
||||
2: .balign 4
|
||||
3: .long 104000000
|
||||
3: .long 105000000
|
||||
4: .size ape.ident,.-ape.ident
|
||||
.type ape.ident,@object
|
||||
.previous
|
||||
|
|
|
@ -432,6 +432,7 @@ SECTIONS {
|
|||
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
|
||||
KEEP(*(.piro.pad.data))
|
||||
KEEP(*(.dataepilogue))
|
||||
. = ALIGN(512);
|
||||
/*END: NT FORK COPYING */
|
||||
_edata = .;
|
||||
PROVIDE(edata = .);
|
||||
|
|
50
ape/ape.mk
50
ape/ape.mk
|
@ -35,7 +35,7 @@ APELINK = \
|
|||
$(FIXUPOBJ) \
|
||||
$@
|
||||
|
||||
APE_SRCS = ape/ape.S
|
||||
APE_SRCS = ape/ape.S ape/start.S ape/launch.S ape/systemcall.S
|
||||
APE_OBJS = o/$(MODE)/ape/ape.o
|
||||
APE_NO_MODIFY_SELF = $(APE)
|
||||
APE_COPY_SELF = $(APE)
|
||||
|
@ -52,6 +52,54 @@ o/$(MODE)/ape/aarch64.lds: \
|
|||
libc/macros.internal.h \
|
||||
libc/str/str.h
|
||||
|
||||
APE_LOADER_LDFLAGS = \
|
||||
-pie \
|
||||
-static \
|
||||
-nostdlib \
|
||||
--no-dynamic-linker \
|
||||
-z norelro \
|
||||
-z common-page-size=0x4000 \
|
||||
-z max-page-size=0x4000
|
||||
|
||||
APE_LOADER_FLAGS = \
|
||||
-DNDEBUG \
|
||||
-iquote. \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-fpie \
|
||||
-Os \
|
||||
-ffreestanding \
|
||||
-mgeneral-regs-only \
|
||||
-fno-asynchronous-unwind-tables \
|
||||
-fno-stack-protector \
|
||||
-fno-ident \
|
||||
-fno-gnu-unique \
|
||||
-c \
|
||||
$(OUTPUT_OPTION) \
|
||||
$<
|
||||
|
||||
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
|
||||
$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -g $< $@
|
||||
|
||||
o/$(MODE)/ape/ape.elf.dbg: \
|
||||
o/$(MODE)/ape/start.o \
|
||||
o/$(MODE)/ape/loader.o \
|
||||
o/$(MODE)/ape/launch.o \
|
||||
o/$(MODE)/ape/systemcall.o
|
||||
@$(COMPILE) -ALINK.elf $(LD) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^)
|
||||
|
||||
o/$(MODE)/ape/loader.o: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=1 -g $(APE_LOADER_FLAGS)
|
||||
o/$(MODE)/ape/start.o: ape/start.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
o/$(MODE)/ape/launch.o: ape/launch.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
o/$(MODE)/ape/systemcall.o: ape/systemcall.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
|
||||
.PHONY: o/$(MODE)/ape
|
||||
o/$(MODE)/ape: o/$(MODE)/ape/ape.elf
|
||||
|
||||
else
|
||||
|
||||
APE = o/$(MODE)/ape/ape.o \
|
||||
|
|
|
@ -37,6 +37,7 @@ for x in .ape \
|
|||
.ape-1.1 \
|
||||
.ape-1.3 \
|
||||
.ape-1.4 \
|
||||
.ape-1.5 \
|
||||
.ape-blink-0.9.2 \
|
||||
.ape-blink-1.0.0; do
|
||||
rm -f \
|
||||
|
|
41
ape/launch.S
41
ape/launch.S
|
@ -34,7 +34,44 @@
|
|||
// @param rdx is stack pointer (becomes zero)
|
||||
// @param rcx is passed through as-is
|
||||
// @noreturn
|
||||
Launch: xor %r8d,%r8d
|
||||
Launch:
|
||||
#ifdef __aarch64__
|
||||
|
||||
mov x16,x1
|
||||
mov sp,x2
|
||||
mov x1,0
|
||||
mov x2,0
|
||||
mov x3,0
|
||||
mov x4,0
|
||||
mov x5,0
|
||||
mov x6,0
|
||||
mov x7,0
|
||||
mov x8,0
|
||||
mov x9,0
|
||||
mov x10,0
|
||||
mov x11,0
|
||||
mov x12,0
|
||||
mov x13,0
|
||||
mov x14,0
|
||||
mov x15,0
|
||||
mov x17,0
|
||||
mov x19,0
|
||||
mov x20,0
|
||||
mov x21,0
|
||||
mov x22,0
|
||||
mov x23,0
|
||||
mov x24,0
|
||||
mov x25,0
|
||||
mov x26,0
|
||||
mov x27,0
|
||||
mov x28,0
|
||||
mov x29,0
|
||||
mov x30,0
|
||||
br x16
|
||||
|
||||
#else
|
||||
|
||||
xor %r8d,%r8d
|
||||
xor %r9d,%r9d
|
||||
xor %r10d,%r10d
|
||||
xor %r11d,%r11d
|
||||
|
@ -50,4 +87,6 @@ Launch: xor %r8d,%r8d
|
|||
xor %ebx,%ebx
|
||||
xor %eax,%eax
|
||||
ret
|
||||
|
||||
#endif
|
||||
.endfn Launch,globl
|
||||
|
|
162
ape/loader.c
162
ape/loader.c
|
@ -98,6 +98,12 @@
|
|||
#define IsOpenbsd() (SupportsOpenbsd() && os == OPENBSD)
|
||||
#define IsNetbsd() (SupportsNetbsd() && os == NETBSD)
|
||||
|
||||
#ifdef __aarch64__
|
||||
#define IsAarch64() 1
|
||||
#else
|
||||
#define IsAarch64() 0
|
||||
#endif
|
||||
|
||||
#define O_RDONLY 0
|
||||
#define PROT_NONE 0
|
||||
#define PROT_READ 1
|
||||
|
@ -111,6 +117,7 @@
|
|||
#define ELFCLASS32 1
|
||||
#define ELFDATA2LSB 1
|
||||
#define EM_NEXGEN32E 62
|
||||
#define EM_AARCH64 183
|
||||
#define ET_EXEC 2
|
||||
#define ET_DYN 3
|
||||
#define PT_LOAD 1
|
||||
|
@ -229,6 +236,19 @@ static int StrCmp(const char *l, const char *r) {
|
|||
return (l[i] & 255) - (r[i] & 255);
|
||||
}
|
||||
|
||||
static const char *BaseName(const char *s) {
|
||||
int c;
|
||||
const char *b = "";
|
||||
if (s) {
|
||||
while ((c = *s++)) {
|
||||
if (c == '/') {
|
||||
b = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
static void Bzero(void *a, unsigned long n) {
|
||||
long z;
|
||||
char *p, *e;
|
||||
|
@ -354,42 +374,86 @@ __attribute__((__noinline__)) static long CallSystem(long arg1, long arg2,
|
|||
}
|
||||
|
||||
__attribute__((__noreturn__)) static void Exit(long rc, int os) {
|
||||
CallSystem(rc, 0, 0, 0, 0, 0, 0, IsLinux() ? 60 : 1, os);
|
||||
int numba;
|
||||
if (IsLinux()) {
|
||||
if (IsAarch64()) {
|
||||
numba = 94;
|
||||
} else {
|
||||
numba = 60;
|
||||
}
|
||||
} else {
|
||||
numba = 1;
|
||||
}
|
||||
CallSystem(rc, 0, 0, 0, 0, 0, 0, numba, os);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
static int Close(int fd, int os) {
|
||||
return CallSystem(fd, 0, 0, 0, 0, 0, 0, IsLinux() ? 3 : 6, os);
|
||||
int numba;
|
||||
if (IsLinux()) {
|
||||
if (IsAarch64()) {
|
||||
numba = 57;
|
||||
} else {
|
||||
numba = 3;
|
||||
}
|
||||
} else {
|
||||
numba = 6;
|
||||
}
|
||||
return CallSystem(fd, 0, 0, 0, 0, 0, 0, numba, os);
|
||||
}
|
||||
|
||||
static long Pread(int fd, void *data, unsigned long size, long off, int os) {
|
||||
long magi;
|
||||
long numba;
|
||||
if (IsLinux()) {
|
||||
magi = 0x011;
|
||||
if (IsAarch64()) {
|
||||
numba = 0x043;
|
||||
} else {
|
||||
numba = 0x011;
|
||||
}
|
||||
} else if (IsXnu()) {
|
||||
magi = 0x2000099;
|
||||
numba = 0x2000099;
|
||||
} else if (IsFreebsd()) {
|
||||
magi = 0x1db;
|
||||
numba = 0x1db;
|
||||
} else if (IsOpenbsd()) {
|
||||
magi = 0x0a9; /* OpenBSD v7.3+ */
|
||||
numba = 0x0a9; /* OpenBSD v7.3+ */
|
||||
} else if (IsNetbsd()) {
|
||||
magi = 0x0ad;
|
||||
numba = 0x0ad;
|
||||
} else {
|
||||
__builtin_unreachable();
|
||||
}
|
||||
return SystemCall(fd, (long)data, size, off, off, 0, 0, magi);
|
||||
return SystemCall(fd, (long)data, size, off, off, 0, 0, numba);
|
||||
}
|
||||
|
||||
static long Write(int fd, const void *data, unsigned long size, int os) {
|
||||
return CallSystem(fd, (long)data, size, 0, 0, 0, 0, IsLinux() ? 1 : 4, os);
|
||||
int numba;
|
||||
if (IsLinux()) {
|
||||
if (IsAarch64()) {
|
||||
numba = 64;
|
||||
} else {
|
||||
numba = 1;
|
||||
}
|
||||
} else {
|
||||
numba = 4;
|
||||
}
|
||||
return CallSystem(fd, (long)data, size, 0, 0, 0, 0, numba, os);
|
||||
}
|
||||
|
||||
static int Execve(const char *prog, char **argv, char **envp, int os) {
|
||||
return CallSystem((long)prog, (long)argv, (long)envp, 0, 0, 0, 0, 59, os);
|
||||
int numba;
|
||||
if (IsLinux() && IsAarch64()) {
|
||||
numba = 221;
|
||||
} else {
|
||||
numba = 59;
|
||||
}
|
||||
return CallSystem((long)prog, (long)argv, (long)envp, 0, 0, 0, 0, numba, os);
|
||||
}
|
||||
|
||||
static int Access(const char *path, int mode, int os) {
|
||||
return CallSystem((long)path, mode, 0, 0, 0, 0, 0, IsLinux() ? 21 : 33, os);
|
||||
if (IsLinux() && IsAarch64()) {
|
||||
return SystemCall(-100, (long)path, mode, 0, 0, 0, 0, 48);
|
||||
} else {
|
||||
return CallSystem((long)path, mode, 0, 0, 0, 0, 0, IsLinux() ? 21 : 33, os);
|
||||
}
|
||||
}
|
||||
|
||||
static int Msyscall(long p, unsigned long n, int os) {
|
||||
|
@ -401,31 +465,49 @@ static int Msyscall(long p, unsigned long n, int os) {
|
|||
}
|
||||
|
||||
static int Open(const char *path, int flags, int mode, int os) {
|
||||
return CallSystem((long)path, flags, mode, 0, 0, 0, 0, IsLinux() ? 2 : 5, os);
|
||||
if (IsLinux() && IsAarch64()) {
|
||||
return SystemCall(-100, (long)path, flags, mode, 0, 0, 0, 56);
|
||||
} else {
|
||||
return CallSystem((long)path, flags, mode, 0, 0, 0, 0, IsLinux() ? 2 : 5,
|
||||
os);
|
||||
}
|
||||
}
|
||||
|
||||
static int Mprotect(void *addr, unsigned long size, int prot, int os) {
|
||||
return CallSystem((long)addr, size, prot, 0, 0, 0, 0, IsLinux() ? 10 : 74,
|
||||
os);
|
||||
int numba;
|
||||
if (IsLinux()) {
|
||||
if (IsAarch64()) {
|
||||
numba = 226;
|
||||
} else {
|
||||
numba = 10;
|
||||
}
|
||||
} else {
|
||||
numba = 74;
|
||||
}
|
||||
return CallSystem((long)addr, size, prot, 0, 0, 0, 0, numba, os);
|
||||
}
|
||||
|
||||
static long Mmap(void *addr, unsigned long size, int prot, int flags, int fd,
|
||||
long off, int os) {
|
||||
long magi;
|
||||
long numba;
|
||||
if (IsLinux()) {
|
||||
magi = 9;
|
||||
if (IsAarch64()) {
|
||||
numba = 222;
|
||||
} else {
|
||||
numba = 9;
|
||||
}
|
||||
} else if (IsXnu()) {
|
||||
magi = 0x2000000 | 197;
|
||||
numba = 0x2000000 | 197;
|
||||
} else if (IsFreebsd()) {
|
||||
magi = 477;
|
||||
numba = 477;
|
||||
} else if (IsOpenbsd()) {
|
||||
magi = 49; /* OpenBSD v7.3+ */
|
||||
numba = 49; /* OpenBSD v7.3+ */
|
||||
} else if (IsNetbsd()) {
|
||||
magi = 197;
|
||||
numba = 197;
|
||||
} else {
|
||||
__builtin_unreachable();
|
||||
}
|
||||
return SystemCall((long)addr, size, prot, flags, fd, off, off, magi);
|
||||
return SystemCall((long)addr, size, prot, flags, fd, off, off, numba);
|
||||
}
|
||||
|
||||
static long Print(int os, int fd, const char *s, ...) {
|
||||
|
@ -703,9 +785,15 @@ static const char *TryElf(struct ApeLoader *M, const char *exe, int fd,
|
|||
if (e->e_type != ET_EXEC && e->e_type != ET_DYN) {
|
||||
return "ELF not ET_EXEC or ET_DYN";
|
||||
}
|
||||
#ifdef __aarch64__
|
||||
if (e->e_machine != EM_AARCH64) {
|
||||
return "couldn't find ELF header with AARCH64 machine type";
|
||||
}
|
||||
#else
|
||||
if (e->e_machine != EM_NEXGEN32E) {
|
||||
return "couldn't find ELF header with x86-64 machine type";
|
||||
}
|
||||
#endif
|
||||
if (e->e_phentsize != sizeof(struct ElfPhdr)) {
|
||||
Pexit(os, exe, 0, "e_phentsize is wrong");
|
||||
}
|
||||
|
@ -796,7 +884,7 @@ static __attribute__((__noreturn__)) void ShowUsage(int os, int fd, int rc) {
|
|||
Print(os, fd,
|
||||
"NAME\n"
|
||||
"\n"
|
||||
" actually portable executable loader version 1.4\n"
|
||||
" actually portable executable loader version 1.5\n"
|
||||
" copyright 2023 justine alexandra roberts tunney\n"
|
||||
" https://justine.lol/ape.html\n"
|
||||
"\n"
|
||||
|
@ -814,10 +902,10 @@ static __attribute__((__noreturn__)) void ShowUsage(int os, int fd, int rc) {
|
|||
Exit(rc, os);
|
||||
}
|
||||
|
||||
__attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
|
||||
__attribute__((__noreturn__)) //
|
||||
void ApeLoader(long di, long *sp, char dl) {
|
||||
int rc;
|
||||
unsigned i, n;
|
||||
int usetheforce;
|
||||
int c, fd, os, argc;
|
||||
struct ApeLoader *M;
|
||||
unsigned long pagesz;
|
||||
|
@ -879,14 +967,11 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
|
|||
}
|
||||
|
||||
/* parse flags */
|
||||
usetheforce = 0;
|
||||
while (argc > 1) {
|
||||
if (argv[1][0] != '-') break; /* normal argument */
|
||||
if (!argv[1][1]) break; /* hyphen argument */
|
||||
if (!StrCmp(argv[1], "-h") || !StrCmp(argv[1], "--help")) {
|
||||
ShowUsage(os, 1, 0);
|
||||
} else if (!StrCmp(argv[1], "-f")) {
|
||||
usetheforce = 1;
|
||||
} else {
|
||||
Print(os, 2, ape, ": invalid flag (pass -h for help)\n", 0l);
|
||||
Exit(1, os);
|
||||
|
@ -926,25 +1011,16 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
|
|||
pe = M->ehdr.buf + rc;
|
||||
|
||||
/* change argv[0] to resolved path if it's ambiguous */
|
||||
if (argc > 0 && *prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) {
|
||||
if ((argc > 0 && *prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) ||
|
||||
!StrCmp(BaseName(prog), argv[0])) {
|
||||
argv[0] = exe;
|
||||
}
|
||||
|
||||
/* ape intended behavior
|
||||
1. if file is a native executable, try to run it natively
|
||||
2. if ape, will scan shell script for elf printf statements
|
||||
3. shell script may have multiple lines producing elf headers
|
||||
4. all elf printf lines must exist in the first 8192 bytes of file
|
||||
5. elf program headers may appear anywhere in the binary */
|
||||
if (!usetheforce &&
|
||||
((IsXnu() && READ32(M->ehdr.buf) == 0xFEEDFACE + 1) ||
|
||||
(!IsXnu() && READ32(M->ehdr.buf) == READ32("\177ELF")))) {
|
||||
Close(fd, os);
|
||||
Execve(exe, argv, envp, os);
|
||||
if ((fd = Open(exe, O_RDONLY, 0, os)) < 0) {
|
||||
Pexit(os, exe, rc, "execve and open failed");
|
||||
}
|
||||
}
|
||||
1. if ape, will scan shell script for elf printf statements
|
||||
2. shell script may have multiple lines producing elf headers
|
||||
3. all elf printf lines must exist in the first 8192 bytes of file
|
||||
4. elf program headers may appear anywhere in the binary */
|
||||
if (READ64(M->ehdr.buf) == READ64("MZqFpD='") ||
|
||||
READ64(M->ehdr.buf) == READ64("jartsr='") ||
|
||||
READ64(M->ehdr.buf) == READ64("APEDBG='")) {
|
||||
|
|
13
ape/start.S
13
ape/start.S
|
@ -19,6 +19,15 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
#ifdef __aarch64__
|
||||
|
||||
_start: mov x1,sp
|
||||
mov x29,0
|
||||
bl ApeLoader
|
||||
.endfn _start,globl
|
||||
|
||||
#else
|
||||
|
||||
XnuEntrypoint:
|
||||
mov $_HOSTXNU,%dl // xnu's not unix!
|
||||
ElfEntrypoint:
|
||||
|
@ -56,6 +65,8 @@ ape.ident:
|
|||
.long 1
|
||||
1: .asciz "APE"
|
||||
2: .balign 4
|
||||
3: .long 104000000
|
||||
3: .long 105000000
|
||||
4: .size ape.ident,.-ape.ident
|
||||
.type ape.ident,@object
|
||||
|
||||
#endif
|
||||
|
|
|
@ -28,6 +28,16 @@
|
|||
// errors are returned as `-errno`. BSD systems are normalized
|
||||
// to follow this convention automatically.
|
||||
SystemCall:
|
||||
#ifdef __aarch64__
|
||||
mov x8,x7
|
||||
mov x9,0
|
||||
adds x9,x9,0
|
||||
svc 0
|
||||
bcs 1f
|
||||
ret
|
||||
1: neg x0,x0
|
||||
ret
|
||||
#else
|
||||
mov %rcx,%r10
|
||||
mov 16(%rsp),%eax
|
||||
clc
|
||||
|
@ -35,4 +45,5 @@ SystemCall:
|
|||
jnc 1f
|
||||
neg %rax
|
||||
1: ret
|
||||
#endif
|
||||
.endfn SystemCall,globl
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue