1 /* $OpenBSD: dl_prebind.c,v 1.8 2006/05/12 22:14:04 drahn Exp $ */
2 /*
3 * Copyright (c) 2006 Dale Rahn <drahn@dalerahn.com>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <sys/types.h>
19 #include <sys/mman.h>
20 #include <sys/exec.h>
21 #include <sys/param.h>
22 #include <sys/sysctl.h>
23 #include <nlist.h>
24 #include <string.h>
25 #include <link.h>
26 #include <dlfcn.h>
27 #include <unistd.h>
28
29 #include "syscall.h"
30 #include "archdep.h"
31 #include "resolve.h"
32 #include "sod.h"
33 #include "stdlib.h"
34 #include "dl_prebind.h"
35
36 void elf_dump_footer(struct prebind_footer *footer);
37 void dump_prelink(Elf_Addr base, u_long size);
38 void prebind_dump_footer(struct prebind_footer *footer, char *file);
39 void prebind_dump_symcache(struct symcachetab *symcachetab, u_int32_t cnt);
40 void prebind_dump_nameidx(struct nameidx *nameidx, u_int32_t numblibs,
41 char *nametab);
42 void prebind_dump_fixup(struct fixup *fixup, u_int32_t numfixups);
43 void prebind_dump_libmap(u_int32_t *libmap, u_int32_t numlibs);
44 struct prebind_footer *_dl_prebind_data_to_footer(void *data);
45
46 void *_dl_prog_prebind_map;
47 struct prebind_footer *prog_footer;
48 extern char *_dl_noprebind;
49 extern char *_dl_prebind_validate;
50
51 int _dl_prebind_match_failed; /* = 0 */
52
53 char *prebind_bind_now = "prebind";
54
55 struct prebind_footer *
_dl_prebind_data_to_footer(void * prebind_data)56 _dl_prebind_data_to_footer(void *prebind_data)
57 {
58 u_int32_t *poffset, offset;
59 struct prebind_footer *footer;
60 char *c;
61
62 poffset = prebind_data;
63 c = prebind_data;
64 offset = *poffset;
65 c += offset;
66 footer = (void *)c;
67 return footer;
68 }
69
70 void
prebind_load_exe(Elf_Phdr * phdp,elf_object_t * exe_obj)71 prebind_load_exe(Elf_Phdr *phdp, elf_object_t *exe_obj)
72 {
73 struct prebind_footer *footer;
74
75 exe_obj->prebind_data = (void *)phdp->p_vaddr;
76 _dl_prog_prebind_map = exe_obj->prebind_data;
77
78 footer = _dl_prebind_data_to_footer(_dl_objects->prebind_data);
79
80 if (footer->bind_id[0] == BIND_ID0 &&
81 footer->bind_id[1] == BIND_ID1 &&
82 footer->bind_id[2] == BIND_ID2 &&
83 footer->bind_id[3] == BIND_ID3 &&
84 footer->prebind_version == PREBIND_VERSION) {
85 prog_footer = footer;
86 if (_dl_bindnow == NULL)
87 _dl_bindnow = prebind_bind_now;
88 } else {
89 DL_DEB(("prebind data missing\n"));
90 _dl_prog_prebind_map = NULL;
91 }
92 if (_dl_noprebind != NULL) {
93 /*prog_footer is valid, we should free it */
94 _dl_prog_prebind_map = NULL;
95 prog_footer = NULL;
96 exe_obj->prebind_data = NULL;
97 if (_dl_bindnow == prebind_bind_now)
98 _dl_bindnow = NULL;
99 }
100 #if 0
101 else if (_dl_debug)
102 dump_prelink((long)_dl_prog_prebind_map,
103 prog_footer->prebind_size);
104 #endif
105 }
106
107 void *
prebind_load_fd(int fd,const char * name)108 prebind_load_fd(int fd, const char *name)
109 {
110 struct prebind_footer footer;
111 struct nameidx *nameidx;
112 void *prebind_data;
113 char *nametab;
114 ssize_t len;
115 int idx;
116
117 if (_dl_prog_prebind_map == NULL || _dl_prebind_match_failed)
118 return 0;
119
120 _dl_lseek(fd, -(off_t)sizeof(struct prebind_footer), SEEK_END);
121 len = _dl_read(fd, (void *)&footer, sizeof(struct prebind_footer));
122
123 if (len != sizeof(struct prebind_footer) ||
124 footer.bind_id[0] != BIND_ID0 ||
125 footer.bind_id[1] != BIND_ID1 ||
126 footer.bind_id[2] != BIND_ID2 ||
127 footer.bind_id[3] != BIND_ID3 ||
128 footer.prebind_version != PREBIND_VERSION) {
129 _dl_prebind_match_failed = 1;
130 DL_DEB(("prebind match failed %s\n", name));
131 return (NULL);
132 }
133
134 prebind_data = _dl_mmap(0, footer.prebind_size, PROT_READ,
135 MAP_FILE, fd, footer.prebind_base);
136 DL_DEB(("prebind_load_fd for lib %s\n", name));
137
138 nameidx = _dl_prog_prebind_map + prog_footer->nameidx_idx;
139 nametab = _dl_prog_prebind_map + prog_footer->nametab_idx;
140
141 /* libraries are loaded in random order, so we just have
142 * to look thru the list to find ourselves
143 */
144 for (idx = 0; idx < prog_footer->numlibs; idx++) {
145 if (_dl_strcmp(nametab + nameidx[idx].name, name) == 0)
146 break;
147 }
148
149 if (idx == prog_footer->numlibs) {
150 _dl_prebind_match_failed = 1; /* not found */
151 } else if (footer.id0 != nameidx[idx].id0 ||
152 footer.id1 != nameidx[idx].id1) {
153 _dl_prebind_match_failed = 1;
154 DL_DEB(("prebind match id0 %d pid0 %d id1 %d pid1 %d\n",
155 footer.id0, nameidx[idx].id0,
156 footer.id1, nameidx[idx].id1));
157 }
158
159 if (_dl_prebind_match_failed == 1) {
160 DL_DEB(("prebind match failed for %s\n", name));
161 }
162
163 return prebind_data;
164 }
165 #define NUM_STATIC_OBJS 10
166 elf_object_t *objarray_static[NUM_STATIC_OBJS];
167 elf_object_t **objarray;
168
169 void
prebind_symcache(elf_object_t * object,int plt)170 prebind_symcache(elf_object_t *object, int plt)
171 {
172 u_int32_t *fixupidx, *fixupcnt, *libmap, *idxtolib;
173 u_int32_t *poffset, offset, symcache_cnt;
174 struct symcachetab *symcachetab;
175 struct prebind_footer *footer;
176 int i = 0, cur_obj = -1, idx;
177 void *prebind_map;
178 struct nameidx *nameidx;
179 char *nametab, *c;
180 struct fixup *fixup;
181 elf_object_t *obj;
182
183 struct symcachetab *s;
184
185 if (object->prebind_data == NULL)
186 return;
187 // DL_DEB(("prebind symcache %s\n", object->load_name));
188
189 obj = _dl_objects;
190 while (obj != NULL) {
191 if (obj == object)
192 cur_obj = i;
193 i++;
194 obj = obj->next;
195 }
196
197 if (cur_obj == -1)
198 return; /* unable to find object ? */
199
200 if (objarray == NULL) {
201 if (i <= NUM_STATIC_OBJS) {
202 objarray = &objarray_static[0];
203 } else {
204 objarray = _dl_malloc(sizeof(elf_object_t *) * i);
205 }
206
207 obj = _dl_objects;
208 i = 0;
209 while (obj != NULL) {
210 objarray[i] = obj;
211 i++;
212 obj = obj->next;
213 }
214 }
215
216 poffset = (u_int32_t *)object->prebind_data;
217 c = object->prebind_data;
218 offset = *poffset;
219 c += offset;
220
221 footer = (void *)c;
222 prebind_map = (void *)object->prebind_data;
223 nameidx = prebind_map + footer->nameidx_idx;;
224 if (plt) {
225 symcachetab = prebind_map + footer->pltsymcache_idx;
226 symcache_cnt = footer->pltsymcache_cnt;
227 // DL_DEB(("loading plt %d\n", symcache_cnt));
228 } else {
229 symcachetab = prebind_map + footer->symcache_idx;
230 symcache_cnt = footer->symcache_cnt;
231 // DL_DEB(("loading got %d\n", symcache_cnt));
232 }
233 nametab = prebind_map + footer->nametab_idx;
234
235 libmap = _dl_prog_prebind_map + prog_footer->libmap_idx;
236 idxtolib = _dl_prog_prebind_map + libmap[cur_obj];
237
238 for (i = 0; i < symcache_cnt; i++) {
239 struct elf_object *tobj;
240 const Elf_Sym *sym;
241 const char *str;
242
243 s = &(symcachetab[i]);
244 if (cur_obj == 0)
245 idx = s->obj_idx;
246 else
247 idx = idxtolib[s->obj_idx];
248
249 if (idx == -1) /* somehow an invalid object ref happend */
250 continue;
251 #if 0
252 DL_DEB(("%s:", object->load_name));
253 DL_DEB(("symidx %d: obj %d %d sym %d flags %x\n",
254 s->idx, s->obj_idx, idx, s->sym_idx,
255 SYM_SEARCH_ALL|SYM_WARNNOTFOUND|plt));
256 #endif
257 tobj = objarray[idx];
258 sym = tobj->dyn.symtab + s->sym_idx;
259 str = tobj->dyn.strtab + sym->st_name;
260 #ifdef DEBUG2
261 DL_DEB(("symidx %d: obj %d %s sym %d %s flags %d %x\n",
262 s->idx, s->obj_idx, tobj->load_name,
263 s->sym_idx, str, SYM_SEARCH_ALL|SYM_WARNNOTFOUND|plt,
264 object->load_addr + sym->st_value));
265 #endif
266 _dl_symcache[s->idx].obj = tobj;
267 _dl_symcache[s->idx].sym = sym;
268 _dl_symcache[s->idx].flags =
269 SYM_SEARCH_ALL|SYM_WARNNOTFOUND|plt;
270 }
271
272 if (!plt) {
273 fixupidx = _dl_prog_prebind_map + prog_footer->fixup_idx;
274 fixup = _dl_prog_prebind_map + fixupidx[2*cur_obj];
275 fixupcnt = _dl_prog_prebind_map + prog_footer->fixupcnt_idx;
276
277 for (i = 0; i < fixupcnt[2*cur_obj]; i++) {
278 struct fixup *f;
279 struct elf_object *tobj;
280 const Elf_Sym *sym;
281 const char *str;
282
283 f = &(fixup[i]);
284 #if 0
285 DL_DEB(("symidx %d: obj %d sym %d flags %x\n",
286 f->sym, f->obj_idx, f->sym_idx, f->flags));
287 #endif
288 tobj = objarray[f->obj_idx];
289 sym = tobj->dyn.symtab + f->sym_idx;
290 str = tobj->dyn.strtab + sym->st_name;
291 #ifdef DEBUG2
292 DL_DEB(("symidx %d: obj %d %s sym %d %s flags %d %x\n",
293 f->sym, f->obj_idx, tobj->load_name,
294 f->sym_idx, str, SYM_SEARCH_ALL|SYM_WARNNOTFOUND|plt,
295 object->load_addr + sym->st_value));
296 #endif
297 _dl_symcache[f->sym].obj = tobj;
298 _dl_symcache[f->sym].sym = sym;
299 _dl_symcache[f->sym].flags =
300 SYM_SEARCH_ALL|SYM_WARNNOTFOUND|plt;
301 }
302 } else {
303
304 fixupidx = _dl_prog_prebind_map + prog_footer->fixup_idx;
305 fixup = _dl_prog_prebind_map + fixupidx[2*cur_obj+1];
306 fixupcnt = _dl_prog_prebind_map + prog_footer->fixupcnt_idx;
307
308 #if 0
309 DL_DEB(("prebind loading symbols fixup plt %s\n",
310 object->load_name));
311 #endif
312 for (i = 0; i < fixupcnt[2*cur_obj+1]; i++) {
313 struct fixup *f;
314 struct elf_object *tobj;
315 const Elf_Sym *sym;
316 const char *str;
317
318 f = &(fixup[i]);
319 #if 0
320 DL_DEB(("symidx %d: obj %d sym %d flags %x\n",
321 f->sym, f->obj_idx, f->sym_idx,
322 SYM_SEARCH_ALL|SYM_WARNNOTFOUND|plt));
323 #endif
324 tobj = objarray[f->obj_idx];
325 sym = tobj->dyn.symtab + f->sym_idx;
326 str = tobj->dyn.strtab + sym->st_name;
327 #ifdef DEBUG2
328 DL_DEB(("symidx %d: obj %d %s sym %d %s flags %d %x\n",
329 f->sym, f->obj_idx, tobj->load_name,
330 f->sym_idx, str, SYM_SEARCH_ALL|SYM_WARNNOTFOUND|plt,
331 object->load_addr + sym->st_value));
332 #endif
333 _dl_symcache[f->sym].obj = tobj;
334 _dl_symcache[f->sym].sym = sym;
335 _dl_symcache[f->sym].flags =
336 SYM_SEARCH_ALL|SYM_WARNNOTFOUND|plt;
337 }
338 }
339 // DL_DEB(("prebind_data loaded\n"));
340 }
341
342 void
prebind_free(elf_object_t * object)343 prebind_free(elf_object_t *object)
344 {
345 struct prebind_footer *footer;
346
347 if (object->prebind_data == NULL)
348 return;
349 #ifdef DEBUG1
350 DL_DEB(("prebind_free for %s %p\n", object->load_name,
351 object->prebind_data));
352 #endif
353 if (object->prebind_data != 0) {
354 footer = _dl_prebind_data_to_footer(object->prebind_data);
355
356 #ifdef DEBUG1
357 DL_DEB(("freeing prebind data sz %x\n", footer->prebind_size));
358 #endif
359
360 _dl_munmap((void *)ELF_TRUNC((long)object->prebind_data, _dl_pagesz),
361 ELF_ROUND((long)object->prebind_data+footer->prebind_size,
362 _dl_pagesz) - ELF_TRUNC((long)object->prebind_data, _dl_pagesz));
363
364 object->prebind_data = NULL;
365 _dl_prog_prebind_map = NULL;
366
367 if (_dl_bindnow == prebind_bind_now)
368 _dl_bindnow = NULL;
369 }
370 }
371
372 int validate_errs;
373
374 struct timeval beforetp;
375
376 void
_dl_prebind_pre_resolve()377 _dl_prebind_pre_resolve()
378 {
379 struct prebind_footer *footer;
380 elf_object_t *object;
381 struct nameidx *nameidx;
382 char *nametab, *name;
383 int idx;
384
385 if (_dl_prog_prebind_map != NULL) {
386 nameidx = _dl_prog_prebind_map + prog_footer->nameidx_idx;
387 nametab = _dl_prog_prebind_map + prog_footer->nametab_idx;
388 for (idx = 1, object = _dl_objects->next; object != NULL;
389 object = object->next, idx++) {
390 if (object->prebind_data == NULL) {
391 /* ld.so doesn't have prebind data */
392 if (object->next == NULL)
393 continue;
394 DL_DEB(("missing prebind data %s\n",
395 object->load_name));
396 _dl_prebind_match_failed = 1;
397 break;
398 }
399 footer = _dl_prebind_data_to_footer(
400 object->prebind_data);
401 if (footer == NULL ||
402 nameidx[idx].id0 != footer->id0 ||
403 nameidx[idx].id1 != footer->id1) {
404 DL_DEB(("invalid prebind data %s\n",
405 object->load_name));
406 _dl_prebind_match_failed = 1;
407 break;
408 }
409 name = object->load_name;
410 if (_dl_strcmp(nametab + nameidx[idx].name, name)
411 != 0) {
412 DL_DEB(("invalid prebind name %s\n",
413 object->load_name));
414 _dl_prebind_match_failed = 1;
415 break;
416 }
417 }
418 }
419
420 if (_dl_prebind_match_failed) {
421 for (object = _dl_objects; object != NULL;
422 object = object->next)
423 prebind_free(object);
424 if (_dl_bindnow == prebind_bind_now)
425 _dl_bindnow = NULL;
426 }
427
428 if (_dl_debug)
429 _dl_gettimeofday(&beforetp, NULL);
430 }
431
432 void
_dl_prebind_post_resolve()433 _dl_prebind_post_resolve()
434 {
435 char buf[7];
436 int i;
437 struct timeval after_tp;
438 struct timeval diff_tp;
439 elf_object_t *object;
440
441 if (_dl_debug) {
442 _dl_gettimeofday(&after_tp, NULL);
443
444 timersub(&after_tp, &beforetp, &diff_tp);
445
446 for (i = 0; i < 6; i++) {
447 buf[5-i] = (diff_tp.tv_usec % 10) + '0';
448 diff_tp.tv_usec /= 10;
449 }
450 buf[6] = '\0';
451
452 _dl_printf("relocation took %d.%s\n", diff_tp.tv_sec, buf);
453 }
454
455 for (object = _dl_objects; object != NULL; object = object->next)
456 prebind_free(object);
457
458 if (_dl_prebind_validate) {
459 if (validate_errs) {
460 _dl_printf("validate_errs %d\n", validate_errs);
461 _dl_exit(20);
462 } else {
463 _dl_exit(0);
464 }
465 }
466 }
467
468 void
prebind_validate(elf_object_t * req_obj,unsigned int symidx,int flags,const Elf_Sym * ref_sym)469 prebind_validate(elf_object_t *req_obj, unsigned int symidx, int flags,
470 const Elf_Sym *ref_sym)
471 {
472 const Elf_Sym *sym, **this;
473 const elf_object_t *sobj;
474 const char *symn;
475 Elf_Addr ret;
476
477 /* Don't verify non-matching flags*/
478
479 sym = req_obj->dyn.symtab;
480 sym += symidx;
481 symn = req_obj->dyn.strtab + sym->st_name;
482 this = &sym;
483
484 //_dl_printf("checking %s\n", symn);
485 ret = _dl_find_symbol(symn, this, flags, ref_sym, req_obj, &sobj);
486
487 if (_dl_symcache[symidx].sym != *this ||
488 _dl_symcache[symidx].obj != sobj) {
489 _dl_printf("symbol %d mismatch on sym %s req_obj %s,\n"
490 "should be obj %s is obj %s\n",
491 symidx, symn, req_obj->load_name, sobj->load_name,
492 _dl_symcache[symidx].obj->load_name);
493 if (req_obj == sobj)
494 _dl_printf("obj %p %p\n", _dl_symcache[symidx].obj, sobj);
495 sym = _dl_symcache[symidx].obj->dyn.symtab;
496 sym += symidx;
497 symn = _dl_symcache[symidx].obj->dyn.strtab + sym->st_name;
498 _dl_printf("obj %s name %s\n",
499 _dl_symcache[symidx].obj->load_name,
500 symn);
501 }
502 }
503
504 #ifdef DEBUG1
505 void
prebind_dump_symcache(struct symcachetab * symcachetab,u_int32_t cnt)506 prebind_dump_symcache(struct symcachetab *symcachetab, u_int32_t cnt)
507 {
508 struct symcachetab *s;
509 int i;
510
511 _dl_printf("cache: cnt %d\n", cnt);
512 for (i = 0; i < cnt; i++) {
513 s = &(symcachetab[i]);
514 _dl_printf("symidx %d: obj %d sym %d\n",
515 s->idx, s->obj_idx, s->sym_idx);
516 }
517 }
518
519 void
prebind_dump_nameidx(struct nameidx * nameidx,u_int32_t numlibs,char * nametab)520 prebind_dump_nameidx(struct nameidx *nameidx, u_int32_t numlibs, char *nametab)
521 {
522 struct nameidx *n;
523 int i;
524
525 _dl_printf("libs:\n");
526 for (i = 0; i < numlibs; i++) {
527 _dl_printf("lib %d offset %d id0 %d, id1 %d\n", i,
528 nameidx[i].name, nameidx[i].id0, nameidx[i].id1);
529 }
530 for (i = 0; i < numlibs; i++) {
531 n = &(nameidx[i]);
532 _dl_printf("nametab %p n %d\n", nametab, n->name);
533 _dl_printf("lib %s %x %x\n", nametab + n->name, n->id0, n->id1);
534 }
535 }
536
537 void
prebind_dump_fixup(struct fixup * fixup,u_int32_t numfixups)538 prebind_dump_fixup(struct fixup *fixup, u_int32_t numfixups)
539 {
540 struct fixup *f;
541 int i;
542
543 _dl_printf("fixup: %d\n", numfixups);
544 for (i = 0; i < numfixups; i++) {
545 f = &(fixup[i]);
546
547 _dl_printf("idx %d obj %d sym idx %d\n",
548 f->sym, f->obj_idx, f->sym_idx);
549
550 }
551 }
552
553 void
prebind_dump_libmap(u_int32_t * libmap,u_int32_t numlibs)554 prebind_dump_libmap(u_int32_t *libmap, u_int32_t numlibs)
555 {
556 int i;
557
558 for (i = 0; i < numlibs; i++) {
559 //_dl_printf("lib%d off %d %s\n", i, libmap[i], strtab+libmap[i]);
560 _dl_printf("lib%d off %d\n", i, libmap[i]);
561 }
562 }
563
564 void
dl_dump_footer(struct prebind_footer * footer)565 dl_dump_footer(struct prebind_footer *footer)
566 {
567 // _dl_printf("base %qd\n", (long long)footer->prebind_base);
568 _dl_printf("nameidx_idx %d\n", footer->nameidx_idx);
569 _dl_printf("symcache_idx %d\n", footer->symcache_idx);
570 _dl_printf("fixupcnt_idx %d\n", footer->fixupcnt_idx);
571 _dl_printf("fixup_cnt %d\n", footer->fixup_cnt);
572 _dl_printf("nametab_idx %d\n", footer->nametab_idx);
573 _dl_printf("symcache_cnt %d\n", footer->symcache_cnt);
574 _dl_printf("fixup_cnt %d\n", footer->fixup_cnt);
575 _dl_printf("numlibs %d\n", footer->numlibs);
576 _dl_printf("id0 %d\n", footer->id0);
577 _dl_printf("id1 %d\n", footer->id1);
578 // _dl_printf("orig_size %lld\n", (long long)footer->orig_size);
579 _dl_printf("version %d\n", footer->prebind_version);
580 _dl_printf("bind_id %c%c%c%c\n", footer->bind_id[0],
581 footer->bind_id[1], footer->bind_id[2], footer->bind_id[3]);
582 }
583 void
dump_prelink(Elf_Addr base,u_long size)584 dump_prelink(Elf_Addr base, u_long size)
585 {
586 u_int32_t *fixupidx, *fixupcnt, *libmap;
587 struct symcachetab *symcachetab;
588 struct prebind_footer *footer;
589 struct nameidx *nameidx;
590 struct fixup *fixup;
591 char *nametab, *id;
592 void *prebind_map;
593 int i;
594
595 id = (char *) (base+size);
596 id -= 4;
597 DL_DEB(("id %c %c %c %c\n", id[0], id[1], id[2], id[3]));
598 footer = (void *) (base+size - sizeof (struct prebind_footer));
599 dl_dump_footer(footer);
600
601 prebind_map = (void *)base;
602 nameidx = prebind_map + footer->nameidx_idx;;
603 symcachetab = prebind_map + footer->symcache_idx;
604 fixupidx = prebind_map + footer->fixup_idx;
605 nametab = prebind_map + footer->nametab_idx;
606 fixupcnt = prebind_map + footer->fixupcnt_idx;
607 libmap = prebind_map + footer->libmap_idx;
608
609 prebind_dump_symcache(symcachetab, footer->symcache_cnt);
610 prebind_dump_nameidx(nameidx, footer->numlibs, nametab);
611 for (i = 0; i < footer->fixup_cnt; i++) {
612 _dl_printf("fixup %d cnt %d idx %d\n", i, fixupcnt[i], fixupidx[i]);
613 fixup = prebind_map + fixupidx[i];
614 prebind_dump_fixup(fixup, fixupcnt[i]);
615 }
616 prebind_dump_libmap(libmap, footer->numlibs);
617 }
618 #endif /* DEBUG1 */
619