| xf.li | bdd93d5 | 2023-05-12 07:10:14 -0700 | [diff] [blame] | 1 | /* Copyright (C) 2011-2016 Free Software Foundation, Inc. | 
|  | 2 | This file is part of the GNU C Library. | 
|  | 3 | Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011. | 
|  | 4 |  | 
|  | 5 | The GNU C Library is free software; you can redistribute it and/or | 
|  | 6 | modify it under the terms of the GNU Lesser General Public | 
|  | 7 | License as published by the Free Software Foundation; either | 
|  | 8 | version 2.1 of the License, or (at your option) any later version. | 
|  | 9 |  | 
|  | 10 | In addition to the permissions in the GNU Lesser General Public | 
|  | 11 | License, the Free Software Foundation gives you unlimited | 
|  | 12 | permission to link the compiled version of this file with other | 
|  | 13 | programs, and to distribute those programs without any restriction | 
|  | 14 | coming from the use of this file. (The GNU Lesser General Public | 
|  | 15 | License restrictions do apply in other respects; for example, they | 
|  | 16 | cover modification of the file, and distribution when not linked | 
|  | 17 | into another program.) | 
|  | 18 |  | 
|  | 19 | Note that people who make modified versions of this file are not | 
|  | 20 | obligated to grant this special exception for their modified | 
|  | 21 | versions; it is their choice whether to do so. The GNU Lesser | 
|  | 22 | General Public License gives permission to release a modified | 
|  | 23 | version without this exception; this exception also makes it | 
|  | 24 | possible to release a modified version which carries forward this | 
|  | 25 | exception. | 
|  | 26 |  | 
|  | 27 | The GNU C Library is distributed in the hope that it will be useful, | 
|  | 28 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 29 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | 30 | Lesser General Public License for more details. | 
|  | 31 |  | 
|  | 32 | You should have received a copy of the GNU Lesser General Public | 
|  | 33 | License along with the GNU C Library.  If not, see | 
|  | 34 | <http://www.gnu.org/licenses/>.  */ | 
|  | 35 |  | 
|  | 36 | /* This is the canonical entry point, usually the first thing in the text | 
|  | 37 | segment.  The ELF standard tells us that the stack is set up like this on | 
|  | 38 | entry (the left side is the offset from "sp"), in units of | 
|  | 39 | __SIZEOF_POINTER__ entries: | 
|  | 40 |  | 
|  | 41 | +0		argc | 
|  | 42 | +1		argv[0] | 
|  | 43 | ... | 
|  | 44 | +(argc+1)	NULL | 
|  | 45 | +(argc+2)	envp[0] | 
|  | 46 | ... | 
|  | 47 | NULL | 
|  | 48 | ...		ElfInfo | 
|  | 49 |  | 
|  | 50 | The ElfInfo is pairs of key/value long words following the envp | 
|  | 51 | pointers and terminated by a zero-valued key. | 
|  | 52 |  | 
|  | 53 | Although not mandated by the standard, it happens to be the case | 
|  | 54 | that we store the actual argv and envp strings immediately after | 
|  | 55 | the ElfInfo data on the stack. | 
|  | 56 |  | 
|  | 57 | On entry r0 points to the shared library termination function, or 0 | 
|  | 58 | if there isn't one. | 
|  | 59 | */ | 
|  | 60 |  | 
|  | 61 | #include <features.h> | 
|  | 62 | #include <sysdep.h> | 
|  | 63 | #include <arch/abi.h> | 
|  | 64 |  | 
|  | 65 | /* Just create no-ops if we don't support PC-relative PLT relocations. */ | 
|  | 66 | #ifdef NO_PLT_PCREL | 
|  | 67 | # define hw2_last_plt(x)	0 | 
|  | 68 | # define hw1_plt(x)		0 | 
|  | 69 | # define hw0_plt(x)		0 | 
|  | 70 | #endif | 
|  | 71 |  | 
|  | 72 | .text | 
|  | 73 | .global _start | 
|  | 74 | .type   _start,@function | 
|  | 75 | .align 8 | 
|  | 76 | _start: | 
|  | 77 | /* Linux starts us with sp pointing at the conventional Elf layout, | 
|  | 78 | but we need to allow two "caller" words for our ABI convention.  */ | 
|  | 79 | { | 
|  | 80 | /* Load argc (stored as a "long", equivalent to a pointer type). */ | 
|  | 81 | LD_PTR r1, sp | 
|  | 82 |  | 
|  | 83 | /* Save incoming 'sp', which points to the Elf argument block. */ | 
|  | 84 | move r52, sp | 
|  | 85 | } | 
|  | 86 |  | 
|  | 87 | { | 
|  | 88 | /* Allocate stack frame callee space for __libc_start_main. */ | 
|  | 89 | ADDI_PTR r12, sp, -(2 * REGSIZE) | 
|  | 90 | } | 
|  | 91 |  | 
|  | 92 | { | 
|  | 93 | /* Get our PC. */ | 
|  | 94 | lnk r13 | 
|  | 95 |  | 
|  | 96 | /* sp is not necessarily properly aligned on startup because | 
|  | 97 | of the way ld.so pops off leading argv elements. So align it. */ | 
|  | 98 | andi sp, r12, -8 | 
|  | 99 | } | 
|  | 100 | .Lmy_pc: | 
|  | 101 |  | 
|  | 102 | { | 
|  | 103 | /* Pass the address of the shared library termination function. */ | 
|  | 104 | move r5, r0 | 
|  | 105 |  | 
|  | 106 | /* Compute location where __libc_start_main's caller is supposed to | 
|  | 107 | store its frame pointer. */ | 
|  | 108 | ADDI_PTR r12, sp, REGSIZE | 
|  | 109 |  | 
|  | 110 | /* Zero out callee space for return address. Unnecessary but free. | 
|  | 111 | This is just paranoia to help backtracing not go awry. */ | 
|  | 112 | ST sp, zero | 
|  | 113 | } | 
|  | 114 | { | 
|  | 115 | /* Zero out our frame pointer for __libc_start_main. */ | 
|  | 116 | ST r12, zero | 
|  | 117 |  | 
|  | 118 | /* Zero out lr to make __libc_start_main the end of backtrace.  */ | 
|  | 119 | move lr, zero | 
|  | 120 |  | 
|  | 121 | /* Compute a pointer to argv. envp will be determined | 
|  | 122 | later in __libc_start_main.  We set up the first argument | 
|  | 123 | (the address of main) below. */ | 
|  | 124 | ADDI_PTR r2, r52, __SIZEOF_POINTER__ | 
|  | 125 | } | 
|  | 126 | { | 
|  | 127 | /* Pass the highest stack address to user code. */ | 
|  | 128 | ADDI_PTR r6, sp, (2 * REGSIZE) | 
|  | 129 |  | 
|  | 130 | /* Pass address of main() in r0, and of our own entry | 
|  | 131 | points to .fini and .init in r3 and r4.  */ | 
|  | 132 | #ifdef __tilegx__ | 
|  | 133 | moveli r0, hw2_last(main - .Lmy_pc) | 
|  | 134 | } | 
|  | 135 | { | 
|  | 136 | shl16insli r0, r0, hw1(main - .Lmy_pc) | 
|  | 137 | moveli r3, hw2_last(__libc_csu_init - .Lmy_pc) | 
|  | 138 | } | 
|  | 139 | { | 
|  | 140 | shl16insli r0, r0, hw0(main - .Lmy_pc) | 
|  | 141 | shl16insli r3, r3, hw1(__libc_csu_init - .Lmy_pc) | 
|  | 142 | } | 
|  | 143 | { | 
|  | 144 | ADD_PTR r0, r0, r13 | 
|  | 145 | shl16insli r3, r3, hw0(__libc_csu_init - .Lmy_pc) | 
|  | 146 | } | 
|  | 147 | { | 
|  | 148 | moveli r12, hw2_last_plt(__libc_start_main - .Lmy_pc) | 
|  | 149 | ADD_PTR r3, r3, r13 | 
|  | 150 | } | 
|  | 151 | { | 
|  | 152 | shl16insli r12, r12, hw1_plt(__libc_start_main - .Lmy_pc) | 
|  | 153 | moveli r4, hw2_last(__libc_csu_fini - .Lmy_pc) | 
|  | 154 | } | 
|  | 155 | { | 
|  | 156 | shl16insli r12, r12, hw0_plt(__libc_start_main - .Lmy_pc) | 
|  | 157 | shl16insli r4, r4, hw1(__libc_csu_fini - .Lmy_pc) | 
|  | 158 | } | 
|  | 159 | { | 
|  | 160 | ADD_PTR r12, r12, r13 | 
|  | 161 | shl16insli r4, r4, hw0(__libc_csu_fini - .Lmy_pc) | 
|  | 162 | } | 
|  | 163 | { | 
|  | 164 | ADD_PTR r4, r4, r13 | 
|  | 165 | # ifdef NO_PLT_PCREL | 
|  | 166 | j plt(__libc_start_main) | 
|  | 167 | # else | 
|  | 168 | jr r12 | 
|  | 169 | # endif | 
|  | 170 | } | 
|  | 171 | #else | 
|  | 172 | addli r0, r13, lo16(main - .Lmy_pc) | 
|  | 173 | } | 
|  | 174 | { | 
|  | 175 | auli r0, r0, ha16(main - .Lmy_pc) | 
|  | 176 | addli r3, r13, lo16(__libc_csu_init - .Lmy_pc) | 
|  | 177 | } | 
|  | 178 | { | 
|  | 179 | auli r3, r3, ha16(__libc_csu_init - .Lmy_pc) | 
|  | 180 | addli r4, r13, lo16(__libc_csu_fini - .Lmy_pc) | 
|  | 181 | } | 
|  | 182 | { | 
|  | 183 | auli r4, r4, ha16(__libc_csu_fini - .Lmy_pc) | 
|  | 184 | /* Call the user's main function, and exit with its value. | 
|  | 185 | But let the libc call main. */ | 
|  | 186 | j plt(__libc_start_main) | 
|  | 187 | } | 
|  | 188 | #endif | 
|  | 189 |  | 
|  | 190 | { | 
|  | 191 | /* Tell backtracer to give up (_start has no caller). */ | 
|  | 192 | info INFO_OP_CANNOT_BACKTRACE | 
|  | 193 | } | 
|  | 194 | .size _start, .-_start | 
|  | 195 |  | 
|  | 196 | /* Define a symbol for the first piece of initialized data.  */ | 
|  | 197 | .data | 
|  | 198 | .global __data_start | 
|  | 199 | .align 8 | 
|  | 200 | __data_start: | 
|  | 201 | .long 0 | 
|  | 202 | .weak data_start | 
|  | 203 | data_start = __data_start |