1 /* $OpenBSD: boot.c,v 1.1 2014/02/16 01:16:38 martynas 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 <string.h> 44 #include <link.h> 45 #include <dlfcn.h> 46 47 #include "syscall.h" 48 #include "archdep.h" 49 #include "path.h" 50 #include "resolve.h" 51 #include "sod.h" 52 #include "stdlib.h" 53 #include "dl_prebind.h" 54 55 #include "../../lib/csu/common_elf/os-note-elf.h" 56 57 /* 58 * Local decls. 59 */ 60 void _dl_boot_bind(const long, long *, Elf_Dyn *); 61 62 void 63 _dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynamicp) 64 { 65 struct elf_object dynld; /* Resolver data for the loader */ 66 AuxInfo *auxstack; 67 long *stack; 68 Elf_Dyn *dynp; 69 int n, argc; 70 char **argv, **envp; 71 long loff; 72 73 /* 74 * Scan argument and environment vectors. Find dynamic 75 * data vector put after them. 76 */ 77 stack = (long *)sp; 78 argc = *stack++; 79 argv = (char **)stack; 80 envp = &argv[argc + 1]; 81 stack = (long *)envp; 82 while (*stack++ != 0L) 83 ; 84 85 /* 86 * Zero out dl_data. 87 */ 88 for (n = 0; n <= AUX_entry; n++) 89 dl_data[n] = 0; 90 91 /* 92 * Dig out auxiliary data set up by exec call. Move all known 93 * tags to an indexed local table for easy access. 94 */ 95 for (auxstack = (AuxInfo *)stack; auxstack->au_id != AUX_null; 96 auxstack++) { 97 if (auxstack->au_id > AUX_entry) 98 continue; 99 dl_data[auxstack->au_id] = auxstack->au_v; 100 } 101 loff = dl_data[AUX_base]; /* XXX assumes ld.so is linked at 0x0 */ 102 103 /* 104 * We need to do 'selfreloc' in case the code weren't 105 * loaded at the address it was linked to. 106 * 107 * Scan the DYNAMIC section for the loader. 108 * Cache the data for easier access. 109 */ 110 111 #if defined(__alpha__) 112 dynp = (Elf_Dyn *)((long)_DYNAMIC); 113 #elif defined(__sparc__) || defined(__sparc64__) || defined(__powerpc__) || \ 114 defined(__hppa__) || defined(__sh__) 115 dynp = dynamicp; 116 #else 117 dynp = (Elf_Dyn *)((long)_DYNAMIC + loff); 118 #endif 119 while (dynp != NULL && dynp->d_tag != DT_NULL) { 120 if (dynp->d_tag < DT_NUM) 121 dynld.Dyn.info[dynp->d_tag] = dynp->d_un.d_val; 122 else if (dynp->d_tag >= DT_LOPROC && 123 dynp->d_tag < DT_LOPROC + DT_PROCNUM) 124 dynld.Dyn.info[dynp->d_tag - DT_LOPROC + DT_NUM] = 125 dynp->d_un.d_val; 126 if (dynp->d_tag == DT_TEXTREL) 127 dynld.dyn.textrel = 1; 128 dynp++; 129 } 130 131 /* 132 * Do the 'bootstrap relocation'. This is really only needed if 133 * the code was loaded at another location than it was linked to. 134 * We don't do undefined symbols resolving (to difficult..) 135 */ 136 137 /* "relocate" dyn.X values if they represent addresses */ 138 { 139 int i, val; 140 /* must be code, not pic data */ 141 int table[20]; 142 143 i = 0; 144 table[i++] = DT_PLTGOT; 145 table[i++] = DT_HASH; 146 table[i++] = DT_STRTAB; 147 table[i++] = DT_SYMTAB; 148 table[i++] = DT_RELA; 149 table[i++] = DT_INIT; 150 table[i++] = DT_FINI; 151 table[i++] = DT_REL; 152 table[i++] = DT_JMPREL; 153 /* other processors insert their extras here */ 154 table[i++] = DT_NULL; 155 for (i = 0; table[i] != DT_NULL; i++) { 156 val = table[i]; 157 if (val >= DT_LOPROC && val < DT_LOPROC + DT_PROCNUM) 158 val = val - DT_LOPROC + DT_NUM; 159 else if (val >= DT_NUM) 160 continue; 161 if (dynld.Dyn.info[val] != 0) 162 dynld.Dyn.info[val] += loff; 163 } 164 } 165 166 { 167 u_int32_t rs; 168 Elf_Rel *rp; 169 int i; 170 171 rp = (Elf_Rel *)(dynld.Dyn.info[DT_REL]); 172 rs = dynld.dyn.relsz; 173 174 for (i = 0; i < rs; i += sizeof (Elf_Rel)) { 175 Elf_Addr *ra; 176 const Elf_Sym *sp; 177 178 sp = dynld.dyn.symtab; 179 sp += ELF_R_SYM(rp->r_info); 180 181 if (ELF_R_SYM(rp->r_info) && sp->st_value == 0) { 182 #if 0 183 /* cannot printf in this function */ 184 _dl_wrstderr("Dynamic loader failure: self bootstrapping impossible.\n"); 185 _dl_wrstderr("Undefined symbol: "); 186 _dl_wrstderr((char *)dynld.dyn.strtab + 187 sp->st_name); 188 #endif 189 _dl_exit(5); 190 } 191 192 ra = (Elf_Addr *)(rp->r_offset + loff); 193 RELOC_REL(rp, sp, ra, loff); 194 rp++; 195 } 196 } 197 198 for (n = 0; n < 2; n++) { 199 unsigned long rs; 200 Elf_RelA *rp; 201 int i; 202 203 switch (n) { 204 case 0: 205 rp = (Elf_RelA *)(dynld.Dyn.info[DT_JMPREL]); 206 rs = dynld.dyn.pltrelsz; 207 break; 208 case 1: 209 rp = (Elf_RelA *)(dynld.Dyn.info[DT_RELA]); 210 rs = dynld.dyn.relasz; 211 break; 212 default: 213 rp = NULL; 214 rs = 0; 215 } 216 for (i = 0; i < rs; i += sizeof (Elf_RelA)) { 217 Elf_Addr *ra; 218 const Elf_Sym *sp; 219 220 sp = dynld.dyn.symtab; 221 sp += ELF_R_SYM(rp->r_info); 222 if (ELF_R_SYM(rp->r_info) && sp->st_value == 0) { 223 #if 0 224 _dl_wrstderr("Dynamic loader failure: self bootstrapping impossible.\n"); 225 _dl_wrstderr("Undefined symbol: "); 226 _dl_wrstderr((char *)dynld.dyn.strtab + 227 sp->st_name); 228 #endif 229 _dl_exit(6); 230 } 231 232 ra = (Elf_Addr *)(rp->r_offset + loff); 233 RELOC_RELA(rp, sp, ra, loff, dynld.dyn.pltgot); 234 rp++; 235 } 236 } 237 238 RELOC_GOT(&dynld, loff); 239 240 /* 241 * we have been fully relocated here, so most things no longer 242 * need the loff adjustment 243 */ 244 } 245