1/* Startup code compliant to the ELF s390 ABI. 2 Copyright (C) 2000-2022 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 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 <https://www.gnu.org/licenses/>. */ 35 36#include <sysdep.h> 37 38/* 39 This is the canonical entry point, usually the first thing in the text 40 segment. Most registers' values are unspecified, except for: 41 42 %r14 Contains a function pointer to be registered with `atexit'. 43 This is how the dynamic linker arranges to have DT_FINI 44 functions called for shared libraries that have been loaded 45 before this code runs. 46 47 %r15 The stack contains the arguments and environment: 48 0(%r15) argc 49 4(%r15) argv[0] 50 ... 51 (4*argc)(%r15) NULL 52 (4*(argc+1))(%r15) envp[0] 53 ... 54 NULL 55*/ 56 57 .text 58 .globl _start 59 .type _start,@function 60_start: 61 cfi_startproc 62 /* Mark r14 as undefined in order to stop unwinding here! */ 63 cfi_undefined (r14) 64 65 /* Check if the kernel provides highgprs facility if needed by 66 the binary. */ 67 68 lr %r6,%r15 69 la %r6,4(%r6) /* Skip the argument counter. */ 70 71.L11: l %r5,0(%r6) /* Skip the argument vector. */ 72 la %r6,4(%r6) 73 ltr %r5,%r5 74 jne .L11 75 76.L12: l %r5,0(%r6) /* Skip the environment vector. */ 77 la %r6,4(%r6) 78 ltr %r5,%r5 79 jne .L12 80 81 /* Usually the auxiliary vector can be expected directly after 82 the environment variables. But we have to skip extra zeros 83 because the loader might have removed unsecure variables for 84 setuid programs. */ 85 86.L26: l %r5,0(%r6) 87 la %r6,4(%r6) 88 ltr %r5,%r5 89 jz .L26 90 91 ahi %r6,-4 92 93 /* Obtain the needed values from the auxiliary vector. */ 94 95 lhi %r7,16 /* AT_HWCAP */ 96 lhi %r8,3 /* AT_PHDR */ 97 lhi %r9,5 /* AT_PHNUM */ 98 lhi %r2,4 /* AT_PHENT */ 99.L13: l %r5,0(%r6) 100 clr %r5,%r7 101 jne .L15 102 l %r10,4(%r6) /* r10 = AT_HWCAP value. */ 103.L15: clr %r5,%r8 104 jne .L16 105 l %r11,4(%r6) /* r11 = AT_PHDR value. */ 106.L16: clr %r5,%r9 107 jne .L17 108 l %r12,4(%r6) /* r12 = AT_PHNUM value. */ 109.L17: clr %r5,%r2 110 jne .L18 111 l %r0,4(%r6) /* r0 = AT_PHENT value. */ 112.L18: ltr %r5,%r5 113 la %r6,8(%r6) 114 jnz .L13 115 116 /* Locate the ELF header by looking for the first PT_LOAD 117 segment with a p_offset of zero. */ 118 119 lr %r4,%r11 /* Backup AT_PHDR. */ 120 lhi %r7,1 /* PT_LOAD id */ 121 lhi %r8,0 122.L19: cl %r7,0(%r4) /* p_type == PT_LOAD? */ 123 jne .L20 124 cl %r8,4(%r4) /* p_offset == 0? */ 125 jne .L20 126 l %r9,8(%r4) /* r9 = PT_LOAD.p_vaddr <- ELF header address */ 127 j .L24 128.L20: alr %r4,%r0 /* r4 += AT_PHENT value */ 129 brct %r12,.L19 130 131 j .+2 /* Trap, there must be such a phdr. */ 132 133.L24: lr %r4,%r11 /* Backup AT_PHDR. */ 134 lhi %r2,6 /* PT_PHDR id */ 135.L23: cl %r2,0(%r4) 136 jne .L22 137 l %r3,8(%r4) /* r3 = PT_PHDR p_vaddr */ 138 j .L25 139.L22: alr %r4,%r0 /* r4 += AT_PHENT value */ 140 brct %r12,.L23 141 142 j .L14 /* No PT_PHDR found - skip checking. */ 143 144.L25: slr %r11,%r3 /* AT_PHDR - PT_PHDR.p_vaddr (relocation offset)*/ 145 alr %r9,%r11 /* PT_LOAD.p_vaddr += relocation offset */ 146 147 l %r5,36(%r9) /* Load the e_flags field. */ 148 tml %r5,1 149 jz .L14 /* Binary does not require highgprs facility. */ 150 151 tml %r10,512 /* Check the AT_HWCAP value. */ 152 jz 2 /* Trap if no highgprs facility available. */ 153.L14: 154 155 /* Setup pointer to literal pool of _start */ 156 basr %r13,0 157.L0: ahi %r13,.Llit-.L0 158 159 /* load argc and argv from stack */ 160 la %r4,4(%r15) # get argv 161 l %r3,0(%r15) # get argc 162 163 /* align the stack to a double word boundary */ 164 lhi %r0,-8 165 nr %r15,%r0 166 167 /* Setup a stack frame and a parameter area */ 168 ahi %r15,-104 # make room on stack 169 xc 0(4,%r15),0(%r15) # clear back-chain 170 171 /* set up arguments for __libc_start_main: 172 main, argc, argv, envp, _init, _fini, rtld_fini, stack_end 173 Note that envp will be determined later in __libc_start_main 174 */ 175 stm %r14,%r15,96(%r15) # store rtld_fini/stack_end to parameter area 176 la %r7,96(%r15) 177 l %r2,.L3-.Llit(%r13) # load pointer to main 178 l %r1,.L4-.Llit(%r13) # load pointer to __libc_start_main 179#ifdef PIC 180 l %r12,.L5-.Llit(%r13) # load .got pointer 181 la %r12,0(%r13,%r12) 182 l %r2,0(%r12,%r2) 183 la %r1,0(%r13,%r1) 184#endif 185 lhi %r6, 0 # Used to fini. 186 lhi %r5, 0 # Used to init. 187 188 /* ok, now branch to the libc main routine */ 189 basr %r14,%r1 190 191 /* crash if __libc_start_main returns */ 192 .word 0 193 194 cfi_endproc 195.Llit: 196#ifndef PIC 197.L3: .long main 198.L4: .long __libc_start_main 199#else 200.L3: .long main@GOT 201.L4: .long __libc_start_main@plt-.Llit 202.L5: .long _GLOBAL_OFFSET_TABLE_-.Llit 203#endif 204 205/* Define a symbol for the first piece of initialized data. */ 206 .data 207 .globl __data_start 208__data_start: 209 .long 0 210 .weak data_start 211 data_start = __data_start 212