diff options
Diffstat (limited to 'exec/loader-x86.s')
-rw-r--r-- | exec/loader-x86.s | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/exec/loader-x86.s b/exec/loader-x86.s new file mode 100644 index 00000000000..216bc88f976 --- /dev/null +++ b/exec/loader-x86.s @@ -0,0 +1,203 @@ +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 movl $162, %eax CC SYS_nanosleep +dnl leal timespec, %ebx +dnl xorl %ecx, %ecx +dnl int $0x80 + leal 8(%esp), %ebp CC ebp = start of load area + subl $8, %esp CC (%esp) = primary fd, 4(%esp) = secondary fd + movl $-1, 4(%esp) +.next_action: + movl (%ebp), %edx CC edx = action number + andl $-17, %edx + cmpl $0, %edx CC open file? + je .open_file + cmpl $3, %edx CC jump? + je .rest_of_exec + cmpl $4, %edx CC anonymous mmap? + je .do_mmap_anon +.do_mmap: + subl $24, %esp + movl $90, %eax CC SYS_old_mmap + movl %esp, %ebx + movl 4(%ebp), %ecx CC address + movl %ecx, (%esp) + movl 16(%ebp), %ecx CC length + movl %ecx, 4(%esp) + movl 12(%ebp), %ecx CC protection + movl %ecx, 8(%esp) + movl 20(%ebp), %ecx CC flags + movl %ecx, 12(%esp) + testl $16, (%ebp) CC primary? + movl 28(%esp), %ecx + cmovzl 24(%esp), %ecx + movl %ecx, 16(%esp) CC fd + movl 8(%ebp), %ecx CC offset + movl %ecx, 20(%esp) +.do_mmap_1: + int $0x80 + addl $24, %esp CC restore esp + cmpl $-1, %eax CC mmap failed? + je .perror + movl 24(%ebp), %ecx CC clear + testl %ecx, %ecx + jz .continue + movl 4(%ebp), %esi CC start of mapping + addl 16(%ebp), %esi CC end of mapping + subl %ecx, %esi CC start of clear area +.again: + testl %ecx, %ecx + jz .continue + subl $1, %ecx + movb $0, (%esi, %ecx, 1) + jmp .again +.continue: + leal 28(%ebp), %ebp + jmp .next_action +.do_mmap_anon: + subl $24, %esp + movl $90, %eax CC SYS_old_mmap + movl %esp, %ebx + movl 4(%ebp), %ecx CC address + movl %ecx, (%esp) + movl 16(%ebp), %ecx CC length + movl %ecx, 4(%esp) + movl 12(%ebp), %ecx CC protection + movl %ecx, 8(%esp) + movl 20(%ebp), %ecx CC flags + movl %ecx, 12(%esp) + movl $-1, 16(%esp) CC fd + movl 8(%ebp), %ecx CC offset + movl %ecx, 20(%esp) + jmp .do_mmap_1 +.open_file: + movl $5, %eax CC SYS_open + leal 4(%ebp), %ebx CC ebx = %esp + 8 + pushl %ebx + xorl %ecx, %ecx CC flags = O_RDONLY + xorl %edx, %edx CC mode = 0 + int $0x80 + cmpl $-1, %eax CC open failed? + jle .perror + movl %ebp, %esi CC (esi) = original action number + popl %ebp CC ebp = start of string + movl %ebp, %ecx CC char past separator + decl %ebp +.nextc: + incl %ebp + movb (%ebp), %dl CC dl = *ebp + cmpb $47, %dl CC dl == '\?'? + jne .nextc1 + leal 1(%ebp), %ecx CC ecx = char past separator +.nextc1: + cmpb $0, %dl CC dl == 0? + jne .nextc + addl $4, %ebp CC adjust past ebp prior to rounding + andl $-4, %ebp CC round ebp up to the next long + testl $16, (%esi) CC original action number & 16? + jz .primary + movl %eax, 4(%esp) CC secondary fd = eax + jmp .next_action +.primary: + pushl %ebp + xorl %esi, %esi CC arg3 + movl %eax, 4(%esp) CC primary fd = eax + xorl %edx, %edx CC arg2 + movl $15, %ebx CC PR_SET_NAME, arg1 = ecx + xorl %edi, %edi CC arg4 + movl $172, %eax CC SYS_prctl + xorl %ebp, %ebp CC arg5 + int $0x80 CC syscall + popl %ebp + jmp .next_action +.perror: + movl %eax, %ebx + negl %ebx + movl $1, %eax + int $0x80 +.rest_of_exec: + movl 8(%esp), %ecx CC ecx = original stack pointer + movl (%ecx), %esi CC esi = argc + leal 8(%ecx, %esi, 4), %ecx CC ecx = start of environ +.skip_environ: + movl (%ecx), %esi CC envp[N] + addl $4, %ecx + testl %esi, %esi CC envp[n] ? + jnz .skip_environ CC otherwise, esi is now at the start of auxv +.one_auxv: + movl (%ecx), %esi CC auxv type + leal 8(%ecx), %ecx CC skip to next auxv + testl %esi, %esi CC is 0? + jz .cleanup + cmpl $3, %esi CC is AT_PHDR + je .replace_phdr + cmpl $4, %esi CC is AT_PHENT? + je .replace_phent + cmpl $5, %esi CC is AT_PHNUM? + je .replace_phnum + cmpl $9, %esi CC is AT_ENTRY? + je .replace_entry + cmpl $7, %esi CC is AT_BASE + je .replace_base + jmp .one_auxv +.replace_phdr: + movl 20(%ebp), %esi + movl %esi, -4(%ecx) + jmp .one_auxv +.replace_phent: + movl 12(%ebp), %esi + movl %esi, -4(%ecx) + jmp .one_auxv +.replace_phnum: + movl 16(%ebp), %esi + movl %esi, -4(%ecx) + jmp .one_auxv +.replace_entry: + movl 8(%ebp), %esi + movl %esi, -4(%ecx) + jmp .one_auxv +.replace_base: + movl 24(%ebp), %esi + movl %esi, -4(%ecx) + jmp .one_auxv +.cleanup: + movl $6, %eax CC SYS_close + cmpl $-1, 4(%esp) CC see if interpreter fd is set + je .cleanup_1 + movl 4(%esp), %ebx + int $0x80 + movl $6, %eax CC SYS_close +.cleanup_1: + movl (%esp), %ebx + int $0x80 +.enter: + pushl $0 + popfl CC restore floating point state + movl 8(%esp), %esp CC restore initial stack pointer + xorl %edx, %edx CC clear rtld_fini + jmpl *4(%ebp) CC entry + +timespec: + .long 10 + .long 10 |