1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-11-24 07:20:37 +00:00
emacs/exec/loader-x86_64.s
2024-01-02 10:30:05 +08:00

196 lines
4.9 KiB
ArmAsm

define(`CC', `
dnl')
CC Copyright (C) 2023-2024 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:
dnl movq $35, %rax CC SYS_nanosleep
dnl leaq timespec(%rip), %rdi
dnl xorq %rsi, %rsi
dnl 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
movq %rsp, %r14 CC r14 = start of string
.nextc:
addq $1, %rsp
movb (%rsp), %dil CC rdi = *rsp
cmpb $47, %dil CC *rsp == '/'?
jne .nextc1
movq %rsp, %r14 CC r14 = rsp
addq $1, %r14 CC r14 = char past separator
.nextc1:
cmpb $0, %dil 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
movq $157, %rax CC SYS_prctl
movq $15, %rdi CC PR_SET_NAME
movq %r14, %rsi CC arg1
xorq %rdx, %rdx CC arg2
xorq %r10, %r10 CC arg3
xorq %r8, %r8 CC arg4
xorq %r9, %r9 CC arg5
syscall
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
je .cleanup_1
movq %r12, %rdi
syscall
movq $3, %rax CC SYS_close
.cleanup_1:
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