xref: /openbsd-src/libexec/ld.so/boot.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
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