| 1 | /* Startup code compliant to the ELF x86-64 ABI. | 
|---|
| 2 | Copyright (C) 2001-2020 Free Software Foundation, Inc. | 
|---|
| 3 | This file is part of the GNU C Library. | 
|---|
| 4 | Contributed by Andreas Jaeger <aj@suse.de>, 2001. | 
|---|
| 5 |  | 
|---|
| 6 | The GNU C Library is free software; you can redistribute it and/or | 
|---|
| 7 | modify it under the terms of the GNU Lesser General Public | 
|---|
| 8 | License as published by the Free Software Foundation; either | 
|---|
| 9 | version 2.1 of the License, or (at your option) any later version. | 
|---|
| 10 |  | 
|---|
| 11 | In addition to the permissions in the GNU Lesser General Public | 
|---|
| 12 | License, the Free Software Foundation gives you unlimited | 
|---|
| 13 | permission to link the compiled version of this file with other | 
|---|
| 14 | programs, and to distribute those programs without any restriction | 
|---|
| 15 | coming from the use of this file. (The GNU Lesser General Public | 
|---|
| 16 | License restrictions do apply in other respects; for example, they | 
|---|
| 17 | cover modification of the file, and distribution when not linked | 
|---|
| 18 | into another program.) | 
|---|
| 19 |  | 
|---|
| 20 | Note that people who make modified versions of this file are not | 
|---|
| 21 | obligated to grant this special exception for their modified | 
|---|
| 22 | versions; it is their choice whether to do so. The GNU Lesser | 
|---|
| 23 | General Public License gives permission to release a modified | 
|---|
| 24 | version without this exception; this exception also makes it | 
|---|
| 25 | possible to release a modified version which carries forward this | 
|---|
| 26 | exception. | 
|---|
| 27 |  | 
|---|
| 28 | The GNU C Library is distributed in the hope that it will be useful, | 
|---|
| 29 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 30 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|---|
| 31 | Lesser General Public License for more details. | 
|---|
| 32 |  | 
|---|
| 33 | You should have received a copy of the GNU Lesser General Public | 
|---|
| 34 | License along with the GNU C Library; if not, see | 
|---|
| 35 | <https://www.gnu.org/licenses/>.  */ | 
|---|
| 36 |  | 
|---|
| 37 | /* This is the canonical entry point, usually the first thing in the text | 
|---|
| 38 | segment.  The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry | 
|---|
| 39 | point runs, most registers' values are unspecified, except for: | 
|---|
| 40 |  | 
|---|
| 41 | %rdx		Contains a function pointer to be registered with `atexit'. | 
|---|
| 42 | This is how the dynamic linker arranges to have DT_FINI | 
|---|
| 43 | functions called for shared libraries that have been loaded | 
|---|
| 44 | before this code runs. | 
|---|
| 45 |  | 
|---|
| 46 | %rsp		The stack contains the arguments and environment: | 
|---|
| 47 | 0(%rsp)				argc | 
|---|
| 48 | LP_SIZE(%rsp)			argv[0] | 
|---|
| 49 | ... | 
|---|
| 50 | (LP_SIZE*argc)(%rsp)		NULL | 
|---|
| 51 | (LP_SIZE*(argc+1))(%rsp)	envp[0] | 
|---|
| 52 | ... | 
|---|
| 53 | NULL | 
|---|
| 54 | */ | 
|---|
| 55 |  | 
|---|
| 56 | #include <sysdep.h> | 
|---|
| 57 |  | 
|---|
| 58 | ENTRY (_start) | 
|---|
| 59 | /* Clearing frame pointer is insufficient, use CFI.  */ | 
|---|
| 60 | cfi_undefined (rip) | 
|---|
| 61 | /* Clear the frame pointer.  The ABI suggests this be done, to mark | 
|---|
| 62 | the outermost frame obviously.  */ | 
|---|
| 63 | xorl %ebp, %ebp | 
|---|
| 64 |  | 
|---|
| 65 | /* Extract the arguments as encoded on the stack and set up | 
|---|
| 66 | the arguments for __libc_start_main (int (*main) (int, char **, char **), | 
|---|
| 67 | int argc, char *argv, | 
|---|
| 68 | void (*init) (void), void (*fini) (void), | 
|---|
| 69 | void (*rtld_fini) (void), void *stack_end). | 
|---|
| 70 | The arguments are passed via registers and on the stack: | 
|---|
| 71 | main:		%rdi | 
|---|
| 72 | argc:		%rsi | 
|---|
| 73 | argv:		%rdx | 
|---|
| 74 | init:		%rcx | 
|---|
| 75 | fini:		%r8 | 
|---|
| 76 | rtld_fini:	%r9 | 
|---|
| 77 | stack_end:	stack.	*/ | 
|---|
| 78 |  | 
|---|
| 79 | mov %RDX_LP, %R9_LP	/* Address of the shared library termination | 
|---|
| 80 | function.  */ | 
|---|
| 81 | #ifdef __ILP32__ | 
|---|
| 82 | mov (%rsp), %esi	/* Simulate popping 4-byte argument count.  */ | 
|---|
| 83 | add $4, %esp | 
|---|
| 84 | #else | 
|---|
| 85 | popq %rsi		/* Pop the argument count.  */ | 
|---|
| 86 | #endif | 
|---|
| 87 | /* argv starts just at the current stack top.  */ | 
|---|
| 88 | mov %RSP_LP, %RDX_LP | 
|---|
| 89 | /* Align the stack to a 16 byte boundary to follow the ABI.  */ | 
|---|
| 90 | and  $~15, %RSP_LP | 
|---|
| 91 |  | 
|---|
| 92 | /* Push garbage because we push 8 more bytes.  */ | 
|---|
| 93 | pushq %rax | 
|---|
| 94 |  | 
|---|
| 95 | /* Provide the highest stack address to the user code (for stacks | 
|---|
| 96 | which grow downwards).  */ | 
|---|
| 97 | pushq %rsp | 
|---|
| 98 |  | 
|---|
| 99 | #ifdef PIC | 
|---|
| 100 | /* Pass address of our own entry points to .fini and .init.  */ | 
|---|
| 101 | mov __libc_csu_fini@GOTPCREL(%rip), %R8_LP | 
|---|
| 102 | mov __libc_csu_init@GOTPCREL(%rip), %RCX_LP | 
|---|
| 103 |  | 
|---|
| 104 | mov main@GOTPCREL(%rip), %RDI_LP | 
|---|
| 105 | #else | 
|---|
| 106 | /* Pass address of our own entry points to .fini and .init.  */ | 
|---|
| 107 | mov $__libc_csu_fini, %R8_LP | 
|---|
| 108 | mov $__libc_csu_init, %RCX_LP | 
|---|
| 109 |  | 
|---|
| 110 | mov $main, %RDI_LP | 
|---|
| 111 | #endif | 
|---|
| 112 |  | 
|---|
| 113 | /* Call the user's main function, and exit with its value. | 
|---|
| 114 | But let the libc call main.  Since __libc_start_main in | 
|---|
| 115 | libc.so is called very early, lazy binding isn't relevant | 
|---|
| 116 | here.  Use indirect branch via GOT to avoid extra branch | 
|---|
| 117 | to PLT slot.  In case of static executable, ld in binutils | 
|---|
| 118 | 2.26 or above can convert indirect branch into direct | 
|---|
| 119 | branch.  */ | 
|---|
| 120 | call *__libc_start_main@GOTPCREL(%rip) | 
|---|
| 121 |  | 
|---|
| 122 | hlt			/* Crash if somehow `exit' does return.	 */ | 
|---|
| 123 | END (_start) | 
|---|
| 124 |  | 
|---|
| 125 | /* Define a symbol for the first piece of initialized data.  */ | 
|---|
| 126 | .data | 
|---|
| 127 | .globl __data_start | 
|---|
| 128 | __data_start: | 
|---|
| 129 | .long 0 | 
|---|
| 130 | .weak data_start | 
|---|
| 131 | data_start = __data_start | 
|---|
| 132 |  | 
|---|