1 /*-
2 * Copyright (c) 1998 Michael Smith
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD: releng/10.0/sys/kern/subr_module.c 218494 2011-02-09 19:08:21Z marcel $");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/linker.h>
33
34 /*
35 * Preloaded module support
36 */
37
38 vm_offset_t preload_addr_relocate = 0;
39 caddr_t preload_metadata;
40
41 /*
42 * Search for the preloaded module (name)
43 */
44 caddr_t
45 preload_search_by_name(const char *name)
46 {
47 caddr_t curp;
48 uint32_t *hdr;
49 int next;
50
51 if (preload_metadata != NULL) {
52
53 curp = preload_metadata;
54 for (;;) {
55 hdr = (uint32_t *)curp;
56 if (hdr[0] == 0 && hdr[1] == 0)
57 break;
58
59 /* Search for a MODINFO_NAME field */
60 if ((hdr[0] == MODINFO_NAME) &&
61 !strcmp(name, curp + sizeof(uint32_t) * 2))
62 return(curp);
63
64 /* skip to next field */
65 next = sizeof(uint32_t) * 2 + hdr[1];
66 next = roundup(next, sizeof(u_long));
67 curp += next;
68 }
69 }
70 return(NULL);
71 }
72
73 /*
74 * Search for the first preloaded module of (type)
75 */
76 caddr_t
77 preload_search_by_type(const char *type)
78 {
79 caddr_t curp, lname;
80 uint32_t *hdr;
81 int next;
82
83 if (preload_metadata != NULL) {
84
85 curp = preload_metadata;
86 lname = NULL;
87 for (;;) {
88 hdr = (uint32_t *)curp;
89 if (hdr[0] == 0 && hdr[1] == 0)
90 break;
91
92 /* remember the start of each record */
93 if (hdr[0] == MODINFO_NAME)
94 lname = curp;
95
96 /* Search for a MODINFO_TYPE field */
97 if ((hdr[0] == MODINFO_TYPE) &&
98 !strcmp(type, curp + sizeof(uint32_t) * 2))
99 return(lname);
100
101 /* skip to next field */
102 next = sizeof(uint32_t) * 2 + hdr[1];
103 next = roundup(next, sizeof(u_long));
104 curp += next;
105 }
106 }
107 return(NULL);
108 }
109
110 /*
111 * Walk through the preloaded module list
112 */
113 caddr_t
114 preload_search_next_name(caddr_t base)
115 {
116 caddr_t curp;
117 uint32_t *hdr;
118 int next;
119
120 if (preload_metadata != NULL) {
121
122 /* Pick up where we left off last time */
123 if (base) {
124 /* skip to next field */
125 curp = base;
126 hdr = (uint32_t *)curp;
127 next = sizeof(uint32_t) * 2 + hdr[1];
128 next = roundup(next, sizeof(u_long));
129 curp += next;
130 } else
131 curp = preload_metadata;
132
133 for (;;) {
134 hdr = (uint32_t *)curp;
135 if (hdr[0] == 0 && hdr[1] == 0)
136 break;
137
138 /* Found a new record? */
139 if (hdr[0] == MODINFO_NAME)
140 return curp;
141
142 /* skip to next field */
143 next = sizeof(uint32_t) * 2 + hdr[1];
144 next = roundup(next, sizeof(u_long));
145 curp += next;
146 }
147 }
148 return(NULL);
149 }
150
151 /*
152 * Given a preloaded module handle (mod), return a pointer
153 * to the data for the attribute (inf).
154 */
155 caddr_t
156 preload_search_info(caddr_t mod, int inf)
157 {
158 caddr_t curp;
159 uint32_t *hdr;
160 uint32_t type = 0;
161 int next;
162
163 curp = mod;
164 for (;;) {
165 hdr = (uint32_t *)curp;
166 /* end of module data? */
167 if (hdr[0] == 0 && hdr[1] == 0)
168 break;
169 /*
170 * We give up once we've looped back to what we were looking at
171 * first - this should normally be a MODINFO_NAME field.
172 */
173 if (type == 0) {
174 type = hdr[0];
175 } else {
176 if (hdr[0] == type)
177 break;
178 }
179
180 /*
181 * Attribute match? Return pointer to data.
182 * Consumer may safely assume that size value precedes
183 * data.
184 */
185 if (hdr[0] == inf)
186 return(curp + (sizeof(uint32_t) * 2));
187
188 /* skip to next field */
189 next = sizeof(uint32_t) * 2 + hdr[1];
190 next = roundup(next, sizeof(u_long));
191 curp += next;
192 }
193 return(NULL);
194 }
195
196 /*
197 * Delete a preload record by name.
198 */
199 void
200 preload_delete_name(const char *name)
201 {
202 caddr_t curp;
203 uint32_t *hdr;
204 int next;
205 int clearing;
206
207 if (preload_metadata != NULL) {
208
209 clearing = 0;
210 curp = preload_metadata;
211 for (;;) {
212 hdr = (uint32_t *)curp;
213 if (hdr[0] == 0 && hdr[1] == 0)
214 break;
215
216 /* Search for a MODINFO_NAME field */
217 if (hdr[0] == MODINFO_NAME) {
218 if (!strcmp(name, curp + sizeof(uint32_t) * 2))
219 clearing = 1; /* got it, start clearing */
220 else if (clearing)
221 clearing = 0; /* at next one now.. better stop */
222 }
223 if (clearing)
224 hdr[0] = MODINFO_EMPTY;
225
226 /* skip to next field */
227 next = sizeof(uint32_t) * 2 + hdr[1];
228 next = roundup(next, sizeof(u_long));
229 curp += next;
230 }
231 }
232 }
233
234 void *
235 preload_fetch_addr(caddr_t mod)
236 {
237 caddr_t *mdp;
238
239 mdp = (caddr_t *)preload_search_info(mod, MODINFO_ADDR);
240 if (mdp == NULL)
241 return (NULL);
242 return (*mdp + preload_addr_relocate);
243 }
244
245 size_t
246 preload_fetch_size(caddr_t mod)
247 {
248 size_t *mdp;
249
250 mdp = (size_t *)preload_search_info(mod, MODINFO_SIZE);
251 if (mdp == NULL)
252 return (0);
253 return (*mdp);
254 }
255
256 /* Called from locore on i386. Convert physical pointers to kvm. Sigh. */
257 void
258 preload_bootstrap_relocate(vm_offset_t offset)
259 {
260 caddr_t curp;
261 uint32_t *hdr;
262 vm_offset_t *ptr;
263 int next;
264
265 if (preload_metadata != NULL) {
266
267 curp = preload_metadata;
268 for (;;) {
269 hdr = (uint32_t *)curp;
270 if (hdr[0] == 0 && hdr[1] == 0)
271 break;
272
273 /* Deal with the ones that we know we have to fix */
274 switch (hdr[0]) {
275 case MODINFO_ADDR:
276 case MODINFO_METADATA|MODINFOMD_SSYM:
277 case MODINFO_METADATA|MODINFOMD_ESYM:
278 ptr = (vm_offset_t *)(curp + (sizeof(uint32_t) * 2));
279 *ptr += offset;
280 break;
281 }
282 /* The rest is beyond us for now */
283
284 /* skip to next field */
285 next = sizeof(uint32_t) * 2 + hdr[1];
286 next = roundup(next, sizeof(u_long));
287 curp += next;
288 }
289 }
290 }
Cache object: 625648251bc87f9c91e9569c9326244d
|