1 /* $OpenBSD: boot.c,v 1.2 2014/07/06 17:33:10 otto Exp $ */ 2 3 /* 4 * Copyright (c) 1998 Per Fogelstrom, Opsycon AB 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28 29 /* 30 * IMPORTANT: any functions below are NOT protected by SSP. Please 31 * do not add anything except what is required to reach GOT with 32 * an adjustment. 33 */ 34 35 #define _DYN_LOADER 36 37 #include <sys/types.h> 38 #include <sys/mman.h> 39 #include <sys/exec.h> 40 #include <sys/param.h> 41 #include <sys/sysctl.h> 42 #include <nlist.h> 43 #include <link.h> 44 #include <dlfcn.h> 45 46 #include "syscall.h" 47 #include "archdep.h" 48 #include "path.h" 49 #include "resolve.h" 50 #include "sod.h" 51 #include "stdlib.h" 52 #include "dl_prebind.h" 53 54 #include "../../lib/csu/common_elf/os-note-elf.h" 55 56 /* 57 * Local decls. 58 */ 59 void _dl_boot_bind(const long, long *, Elf_Dyn *); 60 61 void 62 _dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynamicp) 63 { 64 struct elf_object dynld; /* Resolver data for the loader */ 65 AuxInfo *auxstack; 66 long *stack; 67 Elf_Dyn *dynp; 68 int n, argc; 69 char **argv, **envp; 70 long loff; 71 72 /* 73 * Scan argument and environment vectors. Find dynamic 74 * data vector put after them. 75 */ 76 stack = (long *)sp; 77 argc = *stack++; 78 argv = (char **)stack; 79 envp = &argv[argc + 1]; 80 stack = (long *)envp; 81 while (*stack++ != 0L) 82 ; 83 84 /* 85 * Zero out dl_data. 86 */ 87 for (n = 0; n <= AUX_entry; n++) 88 dl_data[n] = 0; 89 90 /* 91 * Dig out auxiliary data set up by exec call. Move all known 92 * tags to an indexed local table for easy access. 93 */ 94 for (auxstack = (AuxInfo *)stack; auxstack->au_id != AUX_null; 95 auxstack++) { 96 if (auxstack->au_id > AUX_entry) 97 continue; 98 dl_data[auxstack->au_id] = auxstack->au_v; 99 } 100 loff = dl_data[AUX_base]; /* XXX assumes ld.so is linked at 0x0 */ 101 102 /* 103 * We need to do 'selfreloc' in case the code weren't 104 * loaded at the address it was linked to. 105 * 106 * Scan the DYNAMIC section for the loader. 107 * Cache the data for easier access. 108 */ 109 110 #if defined(__alpha__) 111 dynp = (Elf_Dyn *)((long)_DYNAMIC); 112 #elif defined(__sparc__) || defined(__sparc64__) || defined(__powerpc__) || \ 113 defined(__hppa__) || defined(__sh__) 114 dynp = dynamicp; 115 #else 116 dynp = (Elf_Dyn *)((long)_DYNAMIC + loff); 117 #endif 118 while (dynp != NULL && dynp->d_tag != DT_NULL) { 119 if (dynp->d_tag < DT_NUM) 120 dynld.Dyn.info[dynp->d_tag] = dynp->d_un.d_val; 121 else if (dynp->d_tag >= DT_LOPROC && 122 dynp->d_tag < DT_LOPROC + DT_PROCNUM) 123 dynld.Dyn.info[dynp->d_tag - DT_LOPROC + DT_NUM] = 124 dynp->d_un.d_val; 125 if (dynp->d_tag == DT_TEXTREL) 126 dynld.dyn.textrel = 1; 127 dynp++; 128 } 129 130 /* 131 * Do the 'bootstrap relocation'. This is really only needed if 132 * the code was loaded at another location than it was linked to. 133 * We don't do undefined symbols resolving (to difficult..) 134 */ 135 136 /* "relocate" dyn.X values if they represent addresses */ 137 { 138 int i, val; 139 /* must be code, not pic data */ 140 int table[20]; 141 142 i = 0; 143 table[i++] = DT_PLTGOT; 144 table[i++] = DT_HASH; 145 table[i++] = DT_STRTAB; 146 table[i++] = DT_SYMTAB; 147 table[i++] = DT_RELA; 148 table[i++] = DT_INIT; 149 table[i++] = DT_FINI; 150 table[i++] = DT_REL; 151 table[i++] = DT_JMPREL; 152 /* other processors insert their extras here */ 153 table[i++] = DT_NULL; 154 for (i = 0; table[i] != DT_NULL; i++) { 155 val = table[i]; 156 if (val >= DT_LOPROC && val < DT_LOPROC + DT_PROCNUM) 157 val = val - DT_LOPROC + DT_NUM; 158 else if (val >= DT_NUM) 159 continue; 160 if (dynld.Dyn.info[val] != 0) 161 dynld.Dyn.info[val] += loff; 162 } 163 } 164 165 { 166 u_int32_t rs; 167 Elf_Rel *rp; 168 int i; 169 170 rp = (Elf_Rel *)(dynld.Dyn.info[DT_REL]); 171 rs = dynld.dyn.relsz; 172 173 for (i = 0; i < rs; i += sizeof (Elf_Rel)) { 174 Elf_Addr *ra; 175 const Elf_Sym *sp; 176 177 sp = dynld.dyn.symtab; 178 sp += ELF_R_SYM(rp->r_info); 179 180 if (ELF_R_SYM(rp->r_info) && sp->st_value == 0) { 181 #if 0 182 /* cannot printf in this function */ 183 _dl_wrstderr("Dynamic loader failure: self bootstrapping impossible.\n"); 184 _dl_wrstderr("Undefined symbol: "); 185 _dl_wrstderr((char *)dynld.dyn.strtab + 186 sp->st_name); 187 #endif 188 _dl_exit(5); 189 } 190 191 ra = (Elf_Addr *)(rp->r_offset + loff); 192 RELOC_REL(rp, sp, ra, loff); 193 rp++; 194 } 195 } 196 197 for (n = 0; n < 2; n++) { 198 unsigned long rs; 199 Elf_RelA *rp; 200 int i; 201 202 switch (n) { 203 case 0: 204 rp = (Elf_RelA *)(dynld.Dyn.info[DT_JMPREL]); 205 rs = dynld.dyn.pltrelsz; 206 break; 207 case 1: 208 rp = (Elf_RelA *)(dynld.Dyn.info[DT_RELA]); 209 rs = dynld.dyn.relasz; 210 break; 211 default: 212 rp = NULL; 213 rs = 0; 214 } 215 for (i = 0; i < rs; i += sizeof (Elf_RelA)) { 216 Elf_Addr *ra; 217 const Elf_Sym *sp; 218 219 sp = dynld.dyn.symtab; 220 sp += ELF_R_SYM(rp->r_info); 221 if (ELF_R_SYM(rp->r_info) && sp->st_value == 0) { 222 #if 0 223 _dl_wrstderr("Dynamic loader failure: self bootstrapping impossible.\n"); 224 _dl_wrstderr("Undefined symbol: "); 225 _dl_wrstderr((char *)dynld.dyn.strtab + 226 sp->st_name); 227 #endif 228 _dl_exit(6); 229 } 230 231 ra = (Elf_Addr *)(rp->r_offset + loff); 232 RELOC_RELA(rp, sp, ra, loff, dynld.dyn.pltgot); 233 rp++; 234 } 235 } 236 237 RELOC_GOT(&dynld, loff); 238 239 /* 240 * we have been fully relocated here, so most things no longer 241 * need the loff adjustment 242 */ 243 } 244