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 . .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