summaryrefslogtreecommitdiff
path: root/exec/loader-x86_64.s
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2023-04-30 21:37:19 +0800
committerPo Lu <luangruo@yahoo.com>2023-04-30 21:37:19 +0800
commit368f6f3942a1f8b9483763a6ac24b3b3021e92bf (patch)
tree284ff92e18076ed7a8be3d2775ee450922b3166d /exec/loader-x86_64.s
parent4289ed6cffdb5ea758a78037fe385fd7c4e23677 (diff)
downloademacs-368f6f3942a1f8b9483763a6ac24b3b3021e92bf.tar.gz
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.
Diffstat (limited to 'exec/loader-x86_64.s')
-rw-r--r--exec/loader-x86_64.s180
1 files changed, 180 insertions, 0 deletions
diff --git a/exec/loader-x86_64.s b/exec/loader-x86_64.s
new file mode 100644
index 00000000000..07227d38396
--- /dev/null
+++ b/exec/loader-x86_64.s
@@ -0,0 +1,180 @@
+define(`CC', `
+dnl')
+
+CC Copyright (C) 2023 Free Software Foundation, Inc.
+CC
+CC This file is part of GNU Emacs.
+CC
+CC GNU Emacs is free software: you can redistribute it and/or modify
+CC it under the terms of the GNU General Public License as published
+CC by the Free Software Foundation, either version 3 of the License,
+CC or (at your option) any later version.
+CC
+CC GNU Emacs is distributed in the hope that it will be useful, but
+CC WITHOUT ANY WARRANTY; without even the implied warranty of
+CC MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+CC General Public License for more details.
+CC
+CC You should have received a copy of the GNU General Public License
+CC along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+ .section .text
+ .global _start
+_start:
+ #movq $35, %rax CC SYS_nanosleep
+ #leaq timespec(%rip), %rdi
+ #xorq %rsi, %rsi
+ #syscall
+ popq %r13 CC original SP
+ popq %r15 CC size of load area.
+ movq $-1, %r12 CC r12 is the interpreter fd
+.next_action:
+ movq (%rsp), %r14 CC action number
+ movq %r14, %r15 CC original action number
+ andq $-17, %r14
+ cmpq $0, %r14 CC open file?
+ je .open_file
+ cmpq $3, %r14 CC jump?
+ je .rest_of_exec
+ cmpq $4, %r14 CC anonymous mmap?
+ je .do_mmap_anon
+.do_mmap:
+ movq $9, %rax CC SYS_mmap
+ movq 8(%rsp), %rdi CC address
+ movq 16(%rsp), %r9 CC offset
+ movq 24(%rsp), %rdx CC protection
+ movq 32(%rsp), %rsi CC length
+ movq 40(%rsp), %r10 CC flags
+ CC set r8 to the primary fd unless r15 & 16
+ testq $16, %r15
+ movq %r12, %r8
+ cmovzq %rbx, %r8
+.do_mmap_1:
+ syscall
+ cmpq $-1, %rax CC mmap failed
+ je .perror
+ movq 48(%rsp), %r9 CC clear
+ testq %r9, %r9
+ jz .continue
+ movq 8(%rsp), %r10 CC start of mapping
+ addq 32(%rsp), %r10 CC end of mapping
+ subq %r9, %r10 CC start of clear area
+.again:
+ testq %r9, %r9
+ jz .continue
+ subq $1, %r9
+ movb $0, (%r10, %r9, 1)
+ jmp .again
+.continue:
+ leaq 56(%rsp), %rsp
+ jmp .next_action
+.do_mmap_anon:
+ movq $9, %rax CC SYS_mmap
+ movq 8(%rsp), %rdi CC address
+ movq 16(%rsp), %r9 CC offset
+ movq 24(%rsp), %rdx CC protection
+ movq 32(%rsp), %rsi CC length
+ movq 40(%rsp), %r10 CC flags
+ movq $-1, %r8 CC -1
+ jmp .do_mmap_1
+.open_file:
+ movq $2, %rax CC SYS_open
+ leaq 8(%rsp), %rdi CC rdi = %rsp + 8
+ xorq %rsi, %rsi CC flags = O_RDONLY
+ xorq %rdx, %rdx CC mode = 0
+ syscall
+ cmpq $-1, %rax CC open failed
+ jle .perror
+ movq %rdi, %rsp CC rsp = start of string
+ subq $1, %rsp
+.nextc:
+ addq $1, %rsp
+ cmpb $0, (%rsp) CC *rsp == 0?
+ jne .nextc
+ addq $8, %rsp CC adjust past rsp prior to rounding
+ andq $-8, %rsp CC round rsp up to the next quad
+ testq $16, %r15 CC r15 & 16?
+ jz .primary
+ movq %rax, %r12 CC otherwise, move fd to r12
+ jmp .next_action
+.primary:
+ movq %rax, %rbx CC if not, move fd to rbx
+ jmp .next_action
+.perror:
+ movq %rax, %r12 CC error code
+ negq %r12
+ movq $1, %rax CC SYS_write
+ movq $1, %rdi CC stdout
+ leaq error(%rip), %rsi CC buffer
+ movq $23, %rdx CC count
+ syscall
+ movq $60, %rax CC SYS_exit
+ movq %r12, %rdi CC code
+ syscall
+.rest_of_exec: CC rsp now points to six quads:
+ movq %rsp, %r8 CC now, they are r8
+ movq %r13, %rsp CC restore SP
+ popq %r10 CC argc
+ leaq 8(%rsp,%r10,8), %rsp CC now at start of environ
+.skip_environ:
+ popq %r10 CC envp[N]
+ testq %r10, %r10 CC envp[n]?
+ jnz .skip_environ CC otherwise, rsp is now at the start of auxv
+.one_auxv:
+ popq %rcx CC auxv type
+ addq $8, %rsp CC skip value
+ testq %rcx, %rcx CC is 0?
+ jz .cleanup
+ cmpq $3, %rcx CC is AT_PHDR?
+ je .replace_phdr
+ cmpq $4, %rcx CC is AT_PHENT?
+ je .replace_phent
+ cmpq $5, %rcx CC is AT_PHNUM?
+ je .replace_phnum
+ cmpq $9, %rcx CC is AT_ENTRY?
+ je .replace_entry
+ cmpq $7, %rcx CC is AT_BASE?
+ je .replace_base
+ jmp .one_auxv
+.replace_phdr:
+ movq 40(%r8), %r9
+ movq %r9, -8(%rsp) CC set at_phdr
+ jmp .one_auxv
+.replace_phent:
+ movq 24(%r8), %r9
+ movq %r9, -8(%rsp) CC set at_phent
+ jmp .one_auxv
+.replace_phnum:
+ movq 32(%r8), %r9
+ movq %r9, -8(%rsp) CC set at_phnum
+ jmp .one_auxv
+.replace_entry:
+ movq 16(%r8), %r9
+ movq %r9, -8(%rsp) CC set at_entry
+ jmp .one_auxv
+.replace_base:
+ movq 48(%r8), %r9
+ movq %r9, -8(%rsp) CC set at_base
+ jmp .one_auxv
+.cleanup:
+ movq $3, %rax CC SYS_close
+ cmpq $-1, %r12 CC see if interpreter fd is set
+ jne .cleanup_1
+ movq %r12, %rdi
+ syscall
+.cleanup_1:
+ movq $3, %rax CC SYS_close
+ movq %rbx, %rdi
+ syscall
+.enter:
+ pushq $0
+ popfq CC clear FP state
+ movq %r13, %rsp CC restore SP
+ xorq %rdx, %rdx CC clear rtld_fini
+ jmpq *8(%r8) CC entry
+
+error:
+ .ascii "_start: internal error."
+timespec:
+ .quad 10
+ .quad 10