1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-30 12:21:25 -08:00
emacs/exec/loader-aarch64.s
Po Lu 368f6f3942 Add helper binary `exec1'
* .gitignore: New files.
* Makefile.in (mostlyclean_dirs): Add libexec, if its Makefile
exists.
* autogen.sh (do_git): Autoreconf in exec as well.
* configure.ac: Configure libexec on Android.
* exec/Makefile.in:
* exec/README:
* exec/config-mips.m4.in:
* exec/config.guess:
* exec/config.h.in:
* exec/config.sub:
* exec/configure:
* exec/configure.ac:
* exec/deps.mk:
* exec/exec.c (MIN, struct exec_open_command)
(struct exec_map_command, struct exec_jump_command)
(write_open_command, write_load_command, process_interpreter_1)
(process_interpreter, process_program_header, insert_args)
(exec_0):
* exec/exec.h (_EXEC_H_, struct elf_header_32)
(struct program_header_32, struct dt_entry_32)
(struct elf_header_64, struct program_header_64)
(struct dt_entry_64, struct exec_tracee):
* exec/exec1.c (main):
* exec/install-sh (scriptversion):
* exec/loader-aarch64.s (_start):
* exec/loader-armeabi.s (_start):
* exec/loader-mips64el.s (__start):
* exec/loader-mipsel.s (__start):
* exec/loader-x86.s (_start):
* exec/loader-x86_64.s (_start):
* exec/mipsel-user.h (_MIPSEL_USER_H_):
* exec/mipsfpu.c (MIPS_ABI_FP_ANY, fpu_reqs, valid_abi_p)
(fp_mode_for_abi, cpu_supports_fr0_p, determine_fpu_mode):
* exec/mipsfpu.h (_MIPSFPU_H_, FP_FR0):
* exec/test.c (print_usage, main):
* exec/trace.c (MAX_TRACEES, aarch64_set_regs, read_memory)
(user_alloca, user_copy, remove_tracee, handle_clone)
(syscall_trap_p, handle_exec, process_system_call, tracing_execve)
(after_fork, find_tracee, exec_waitpid, exec_init): New files.
* java/Makefile.in (CROSS_EXEC_BINS): Add exec1 and
loader.
($(CROSS_EXEC_BINS) &): New target.
2023-04-30 21:37:19 +08:00

174 lines
4.7 KiB
ArmAsm

// Copyright (C) 2023 Free Software Foundation, Inc.
//
// This file is part of GNU Emacs.
//
// GNU Emacs is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// GNU Emacs is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
// Notice that aarch64 requires that sp be aligned to 16 bytes while
// accessing memory from sp, so x20 is used to chase down the load
// area.
.section .text
.global _start
_start:
//mov x8, 101 // SYS_nanosleep
//adr x0, timespec // req
//mov x1, #0 // rem
//svc #0 // syscall
mov x20, sp // x20 = sp
ldr x10, [x20] // x10 = original SP
add x20, x20, #16 // x20 = start of load area
mov x28, #-1 // x28 = secondary fd
.next_action:
ldr x11, [x20] // action number
and x12, x11, #-17 // actual action number
cbz x12, .open_file // open file?
cmp x12, #3 // jump?
beq .rest_of_exec
cmp x12, #4 // anonymous mmap?
beq .do_mmap_anon
.do_mmap:
ldr x0, [x20, 8] // vm_address
ldr x1, [x20, 32] // length
ldr x2, [x20, 24] // protection
ldr x3, [x20, 40] // flags
tst x11, #16 // primary fd?
mov x4, x29 // primary fd
beq .do_mmap_1
mov x4, x28 // secondary fd
.do_mmap_1:
mov x8, #222 // SYS_mmap
ldr x5, [x20, 16] // file_offset
svc #0 // syscall
ldr x9, [x20, 8] // length
cmp x0, x9 // mmap result
bne .perror // print error
ldr x3, [x20, 48] // clear
add x1, x1, x0 // x1 = vm_address + end
sub x3, x1, x3 // x3 = x1 - clear
mov x0, #0 // x0 = 0
.fill64:
sub x2, x1, x3 // x2 = x1 - x3
cmp x2, #63 // x2 >= 64?
ble .fillb // start filling bytes
stp x0, x0, [x3] // x3[0] = 0, x3[1] = 0
stp x0, x0, [x3, 16] // x3[2] = 0, x3[3] = 0
stp x0, x0, [x3, 32] // x3[4] = 0, x3[5] = 0
stp x0, x0, [x3, 48] // x3[6] = 0, x3[7] = 0
add x3, x3, #64 // x3 += 8
b .fill64
.fillb:
cmp x1, x3 // x1 == x3?
beq .continue // done
strb w0, [x3], #1 // ((char *) x3)++ = 0
b .fillb
.continue:
add x20, x20, #56 // next action
b .next_action
.do_mmap_anon:
ldr x0, [x20, 8] // vm_address
ldr x1, [x20, 32] // length
ldr x2, [x20, 24] // protection
ldr x3, [x20, 40] // flags
mov x4, #-1 // fd
b .do_mmap_1
.open_file:
mov x8, #56 // SYS_openat
mov x0, #-100 // AT_FDCWD
add x1, x20, #8 // file name
mov x2, #0 // O_RDONLY
mov x3, #0 // mode
svc #0 // syscall
cmp x0, #-1 // rc < 0?
ble .perror
.nextc:
ldrb w2, [x1], #1 // b = *x1++
cbnz w2, .nextc // b?
add x1, x1, #7 // round up x1
and x20, x1, #-8 // mask for round, set x20
tst x11, #16 // primary fd?
bne .secondary // secondary fd
mov x29, x0 // primary fd
b .next_action // next action
.secondary:
mov x28, x0 // secondary fd
b .next_action // next action.
.perror:
mov x8, #93 // SYS_exit
mvn x0, x0 // x1 = ~x0
add x0, x0, 1 // x1 += 1
svc #0 // exit
.rest_of_exec:
mov x7, x20 // x7 = x20
mov x20, x10 // x20 = x10
ldr x9, [x20] // argc
add x9, x9, #2 // x9 += 2
lsl x9, x9, #3 // argc * 8
add x20, x20, x9 // now past argv
.skipenv:
ldr x9, [x20], #8 // x9 = *envp++
cbnz x9, .skipenv // x9?
.one_auxv:
ldr x9, [x20], #16 // x9 = *sp, sp += 2
cbz x9, .cleanup // !x9?
cmp x9, #3 // is AT_PHDR?
beq .replace_phdr // replace
cmp x9, #4 // is AT_PHENT?
beq .replace_phent // replace
cmp x9, #5 // is AT_PHNUM?
beq .replace_phnum // replace
cmp x9, #9 // is AT_ENTRY?
beq .replace_entry // replace
cmp x9, #7 // is AT_BASE?
beq .replace_base // replace
b .one_auxv // next auxv
.replace_phdr:
ldr x9, [x7, 40] // at_phdr
str x9, [x20, -8] // store value
b .one_auxv
.replace_phent:
ldr x9, [x7, 24] // at_phent
str x9, [x20, -8] // store value
b .one_auxv
.replace_phnum:
ldr x9, [x7, 32] // at_phnum
str x9, [x20, -8] // store value
b .one_auxv
.replace_entry:
ldr x9, [x7, 16] // at_entry
str x9, [x20, -8] // store value
b .one_auxv
.replace_base:
ldr x9, [x7, 48] // at_base
str x9, [x20, -8] // store value
b .one_auxv
.cleanup:
cmp x28, #-1 // is secondary fd set?
bne .cleanup1 // not set
mov x8, #57 // SYS_close
mov x0, x28 // secondary fd
svc #0 // syscall
.cleanup1:
mov x8, #57 // SYS_close
mov x0, x29 // primary fd
svc #0 // syscall
.enter:
mov sp, x10 // restore original SP
mov x0, #0 // clear rtld_fini
ldr x1, [x7, 8] // branch to code
br x1
timespec:
.quad 10
.quad 10