1 /* $OpenBSD: prebind.c,v 1.8 2006/11/13 13:13:14 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/param.h>
19 #include <sys/stat.h>
20 #include <sys/syslimits.h>
21 #include <sys/mman.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <nlist.h>
25 #include <elf_abi.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <dirent.h>
31 #include <err.h>
32 #include "resolve.h"
33 #include "link.h"
34 #include "sod.h"
35 #ifndef __mips64__
36 #include "machine/reloc.h"
37 #endif
38 #include "prebind.h"
39 #include "ld.h"
40
41 /* seems to make sense to limit how big of file can be dealt with */
42 #define MAX_FILE_SIZE (512 * 1024 * 1024)
43
44 char *shstrtab;
45
46 /* alpha uses RELOC_JMP_SLOT */
47 #ifdef __amd64__
48 #define RELOC_JMP_SLOT R_X86_64_JUMP_SLOT
49 #endif
50 #ifdef __arm__
51 #define RELOC_JMP_SLOT R_ARM_JUMP_SLOT
52 #endif
53 #ifdef __hppa__
54 #define RELOC_JMP_SLOT RELOC_IPLT
55 #endif
56 #ifdef __hppa64__
57 #define RELOC_JMP_SLOT RELOC_JMPSLOT
58 #endif
59 #ifdef __i386__
60 #define RELOC_JMP_SLOT RELOC_JUMP_SLOT
61 #endif
62 #ifdef __sh__
63 #define RELOC_JMP_SLOT R_SH_JMP_SLOT
64 #endif
65 #ifdef __mips64__
66 #define RELOC_JMP_SLOT 0 /* XXX mips64 doesnt have PLT reloc */
67 #endif
68 /* powerpc uses RELOC_JMP_SLOT */
69 /* sparc uses RELOC_JMP_SLOT */
70 /* sparc64 uses RELOC_JMP_SLOT */
71 #if defined(__sparc__) && !defined(__sparc64__)
72 /* ARGH, our sparc/include/reloc.h is wrong (for the moment) */
73 #undef RELOC_JMP_SLOT
74 #define RELOC_JMP_SLOT 21
75 #endif
76
77 #define BUFSZ (256 * 1024)
78
79 #include "prebind_struct.h"
80 struct proglist *curbin;
81
82 obj_list_ty library_list =
83 TAILQ_HEAD_INITIALIZER(library_list);
84
85 prog_list_ty prog_list =
86 TAILQ_HEAD_INITIALIZER(prog_list);
87
88 struct objarray_list {
89 struct elf_object *obj;
90 struct symcache_noflag *symcache;
91 struct symcache_noflag *pltsymcache;
92 struct proglist *proglist;
93 u_int32_t id0;
94 u_int32_t id1;
95 u_int32_t *idxtolib;
96 void *oprebind_data;
97 int numlibs;
98
99 TAILQ_HEAD(, objlist) inst_list;
100 } *objarray;
101
102
103 struct prebind_info {
104 struct elf_object *object;
105 struct prebind_footer *footer;
106 u_int32_t footer_offset;
107 u_int32_t nfixup;
108 struct nameidx *nameidx;
109 struct symcachetab *symcache;
110 struct symcachetab *pltsymcache;
111 u_int32_t *fixuptab;
112 u_int32_t *fixupcnt;
113 struct fixup **fixup;
114 u_int32_t *maptab;
115 u_int32_t **libmap;
116 u_int32_t *libmapcnt;
117 char *nametab;
118 u_int32_t nametablen;
119 };
120
121 int objarray_cnt;
122 int objarray_sz;
123
124 void copy_oldsymcache(int objidx, void *prebind_data);
125 void elf_load_existing_prebind(struct elf_object *object, int fd);
126
127 struct elf_object * elf_load_object(void *pexe, const char *name);
128 void elf_free_object(struct elf_object *object);
129 void map_to_virt(Elf_Phdr *, Elf_Ehdr *, Elf_Addr, u_long *);
130 int load_obj_needed(struct elf_object *object);
131 int load_lib(const char *name, struct elf_object *parent);
132 elf_object_t * elf_load_shlib_hint(struct sod *sod, struct sod *req_sod,
133 int use_hints, const char *libpath);
134 char * elf_find_shlib(struct sod *sodp, const char *searchpath,
135 int nohints);
136 elf_object_t * elf_tryload_shlib(const char *libname);
137 int elf_match_file(struct sod *sodp, char *name, int namelen);
138 void elf_init_objarray(void);
139 void elf_add_object(struct elf_object *object, int objtype);
140 void elf_print_objarray(void);
141 void elf_reloc(struct elf_object *object);
142
143 struct elf_object * elf_lookup_object(const char *name);
144 struct elf_object * elf_lookup_object_devino(dev_t dev, ino_t inode,
145 int objtype);
146 void elf_free_curbin_list(struct elf_object *obj);
147 void elf_resolve_curbin(void);
148 struct proglist *elf_newbin(void);
149 void elf_sum_reloc();
150 int elf_prep_lib_prebind(struct elf_object *object);
151 int elf_prep_bin_prebind(struct proglist *pl);
152 void add_fixup_prog(struct elf_object *prog, struct elf_object *obj, int idx,
153 const struct elf_object *ref_obj, const Elf_Sym *ref_sym, int flag);
154 void add_fixup_oldprog(struct elf_object *prog, struct elf_object *obj,
155 int idx, const struct elf_object *ref_obj, const Elf_Sym *ref_sym,
156 int flag);
157
158 void elf_dump_footer(struct prebind_footer *footer);
159
160 void elf_fixup_prog_load(int fd, struct prebind_footer *footer,
161 struct elf_object *object);
162 void elf_clear_prog_load(int fd, struct elf_object *object);
163
164 void elf_find_symbol_rel(const char *s, struct elf_object *object,
165 Elf_Rel *rel, struct symcache_noflag *symcache,
166 struct symcache_noflag *pltsymcache);
167
168 void elf_find_symbol_rela(const char *s, struct elf_object *object,
169 Elf_RelA *rela, struct symcache_noflag *symcache,
170 struct symcache_noflag *pltsymcache);
171
172 int elf_find_symbol_obj(elf_object_t *object, const char *name,
173 unsigned long hash, int flags, const Elf_Sym **this,
174 const Elf_Sym **weak_sym, elf_object_t **weak_object);
175
176 int prebind_writefile(int fd, struct prebind_info *info);
177 int prebind_writenewfile(int infd, char *name, struct stat *st, off_t orig_size,
178 struct prebind_info *info);
179
180 struct elf_object *load_object;
181
182 struct elf_object *load_file(const char *filename, int lib);
183 int elf_check_note(void *buf, Elf_Phdr *phdr);
184 void load_file_or_dir(char *name);
185 void load_dir(char *name);
186 void load_exe(char *name);
187
188 int
prebind(char ** argv)189 prebind(char **argv)
190 {
191 int i;
192
193 elf_init_objarray();
194
195 for (i = 0; argv[i]; i++)
196 load_file_or_dir(argv[i]);
197
198 if (verbose > 4) {
199 elf_print_objarray();
200 elf_print_prog_list(&prog_list);
201 }
202 elf_sum_reloc();
203
204 return (0);
205 }
206
207 /*
208 * load ELF objects at the specified path it could be
209 * either a either a directory or file, if the object is
210 * a file, attempt to load it as an executable (will ignore shared objects
211 * and any files that are not Elf execuables.
212 * if the object is a directory pass it to a routine to deal with
213 * directory parsing.
214 */
215 void
load_file_or_dir(char * name)216 load_file_or_dir(char *name)
217 {
218 struct stat sb;
219 int ret;
220
221 ret = lstat(name, &sb);
222 if (ret != 0)
223 return;
224 switch (sb.st_mode & S_IFMT) {
225 case S_IFREG:
226 load_exe(name);
227 break;
228 case S_IFDIR:
229 if (verbose > 0)
230 printf("loading dir %s\n", name);
231 load_dir(name);
232 break;
233 default:
234 ; /* links and other files we skip */
235 }
236
237 }
238
239 /*
240 * for all of the objects in the directory, if it is a regular file
241 * load it as a binary, if it is unknown (nfs mount) stat the file
242 * and load the file for S_IFREG
243 * any other type of directory object: symlink, directory, socket, ...
244 * is ignored.
245 */
246 void
load_dir(char * name)247 load_dir(char *name)
248 {
249 struct dirent *dp;
250 struct stat sb;
251 DIR *dirp;
252 char *buf;
253
254 dirp = opendir(name);
255
256 /* if dir failes to open, skip */
257 if (dirp == NULL)
258 return;
259
260 while ((dp = readdir(dirp)) != NULL) {
261 switch (dp->d_type) {
262 case DT_UNKNOWN:
263 /*
264 * NFS will return unknown, since load_file
265 * does stat the file, this just
266 */
267 asprintf(&buf, "%s/%s", name, dp->d_name);
268 lstat(buf, &sb);
269 if (sb.st_mode == S_IFREG)
270 load_exe(buf);
271 free(buf);
272 break;
273 case DT_REG:
274 asprintf(&buf, "%s/%s", name, dp->d_name);
275 load_exe(buf);
276 free(buf);
277 break;
278 default:
279 /* other files symlinks, dirs, ... we ignore */
280 ;
281 }
282 }
283 }
284
285 /*
286 * the given pathname is a regular file, however it may or may not
287 * be an ELF file. Attempt to load the given path and calculate prebind
288 * data for it.
289 * if the given file is not a ELF binary this will 'fail' and
290 * should not change any of the prebind state.
291 */
292 void
load_exe(char * name)293 load_exe(char *name)
294 {
295 struct elf_object *object;
296 struct elf_object *interp;
297 struct objlist *ol;
298 int fail = 0;
299
300 curbin = elf_newbin();
301 if (verbose > 0)
302 printf("processing %s\n", name);
303 object = load_file(name, OBJTYPE_EXE);
304 if (object != NULL && load_object != NULL &&
305 object->load_object == NULL) {
306 TAILQ_FOREACH(ol, &(curbin->curbin_list), list) {
307 fail = load_obj_needed(ol->object);
308 if (fail != 0)
309 break; /* XXX */
310
311 }
312 if (fail == 0) {
313 interp = load_file(curbin->interp, OBJTYPE_DLO);
314 object->load_object = interp;
315 if (interp == NULL)
316 fail = 1;
317 }
318
319 /* slight abuse of this field */
320
321 if (fail == 0) {
322 objarray[object->dyn.null].proglist = curbin;
323 elf_resolve_curbin();
324 TAILQ_INSERT_TAIL(&prog_list, curbin, list);
325 } else {
326 printf("failed to load %s\n", name);
327 elf_free_curbin_list(object);
328 free(curbin);
329 }
330 if (load_object != NULL) {
331 load_object = NULL;
332 }
333 } else {
334 free(curbin);
335 }
336 }
337
338 /*
339 * given a path to a file, attempt to open it and load any data necessary
340 * for prebind. this function is used for executables, libraries and ld.so
341 * file, it will do a lookup on the dev/inode to use a cached version
342 * of the file if it was already loaded, in case a library is referenced
343 * by more than one program or there are hardlinks between executable names.
344 * if the file is not an elf file of the appropriate type, it will return
345 * failure.
346 */
347 struct elf_object *
load_file(const char * filename,int objtype)348 load_file(const char *filename, int objtype)
349 {
350 struct elf_object *obj = NULL;
351 int fd = -1, i, note_found;
352 struct stat ifstat;
353 void *buf = NULL;
354 Elf_Ehdr *ehdr;
355 Elf_Shdr *shdr;
356 Elf_Phdr *phdr;
357 char *pexe;
358
359 fd = open(filename, O_RDONLY);
360 if (fd == -1) {
361 perror(filename);
362 goto done;
363 }
364
365 if (fstat(fd, &ifstat) == -1) {
366 perror(filename);
367 goto done;
368 }
369
370 if ((ifstat.st_mode & S_IFMT) != S_IFREG)
371 goto done;
372
373 if (ifstat.st_size < sizeof (Elf_Ehdr))
374 goto done;
375
376 obj = elf_lookup_object_devino(ifstat.st_dev, ifstat.st_ino, objtype);
377 if (obj != NULL)
378 goto done;
379
380 buf = mmap(NULL, ifstat.st_size, PROT_READ, MAP_FILE | MAP_SHARED,
381 fd, 0);
382 if (buf == MAP_FAILED) {
383 printf("%s: cannot mmap\n", filename);
384 goto done;
385 }
386
387 ehdr = (Elf_Ehdr *)buf;
388
389 if (IS_ELF(*ehdr) == 0)
390 goto done;
391
392 if (ehdr->e_machine != ELF_TARG_MACH) {
393 if (verbose > 0)
394 printf("%s: wrong arch\n", filename);
395 goto done;
396 }
397
398 if (objtype == OBJTYPE_EXE) {
399 if (ehdr->e_type != ET_EXEC)
400 goto done;
401
402 note_found = 0;
403
404 phdr = (Elf_Phdr *)((char *)buf + ehdr->e_phoff);
405 for (i = 0; i < ehdr->e_phnum; i++) {
406 if (phdr[i].p_type == PT_NOTE) {
407 note_found = elf_check_note(buf,&phdr[i]);
408 break;
409 }
410 }
411 if (note_found == 0)
412 goto done; /* no MirOS note found */
413 }
414
415 if ((objtype == OBJTYPE_LIB || objtype == OBJTYPE_DLO) &&
416 (ehdr->e_type != ET_DYN))
417 goto done;
418
419 pexe = buf;
420 if (ehdr->e_shstrndx == 0)
421 goto done;
422
423 shdr = (Elf_Shdr *)(pexe + ehdr->e_shoff +
424 (ehdr->e_shstrndx * ehdr->e_shentsize));
425
426 shstrtab = (char *)(pexe + shdr->sh_offset);
427
428 obj = elf_load_object(pexe, filename);
429
430 munmap(buf, ifstat.st_size);
431 buf = NULL;
432
433 if (obj != NULL) {
434 obj->obj_type = objtype;
435
436 obj->dev = ifstat.st_dev;
437 obj->inode = ifstat.st_ino;
438 if (load_object == NULL)
439 load_object = obj;
440
441 elf_add_object(obj, objtype);
442
443 #ifdef DEBUG1
444 dump_info(obj);
445 #endif
446 }
447 if ((objtype == OBJTYPE_LIB || objtype == OBJTYPE_DLO) &&
448 merge == 1) {
449 /*
450 * for libraries and dynamic linker, check if old prebind
451 * info exists and load it if we are in merge mode
452 */
453 elf_load_existing_prebind(obj, fd);
454 }
455 done:
456 if (buf != NULL)
457 munmap(buf, ifstat.st_size);
458 if (fd != -1)
459 close(fd);
460 return obj;
461 }
462
463 /*
464 * check if the given executable header on a ELF executable
465 * has the proper MirOS note on the file if it is not present
466 * binaries will be skipped.
467 */
468 int
elf_check_note(void * buf,Elf_Phdr * phdr)469 elf_check_note(void *buf, Elf_Phdr *phdr)
470 {
471 Elf_Ehdr *ehdr;
472 u_long address;
473 u_int *pint;
474 char *osname;
475
476 ehdr = (Elf_Ehdr *)buf;
477 address = phdr->p_offset;
478 pint = (u_int *)((char *)buf + address);
479 osname = (char *)buf + address + sizeof(*pint) * 3;
480
481 if (pint[0] == 0x0A /* MirOS·BSD\0 */ &&
482 pint[1] == 4 /* desc */ &&
483 pint[2] == 1 /* type_osversion */ &&
484 strcmp("MirOS BSD", osname) == 0)
485 return 1;
486
487 return 0;
488 }
489
490 struct elf_object *
elf_load_object(void * pexe,const char * name)491 elf_load_object(void *pexe, const char *name)
492 {
493 struct elf_object *object;
494 Elf_Dyn *dynp = NULL, *odynp;
495 Elf_Ehdr *ehdr;
496 Elf_Phdr *phdr;
497 const Elf_Sym *symt;
498 const char *strt;
499 Elf_Addr loff;
500 Elf_Word *needed_list;
501 int needed_cnt = 0, i;
502
503 object = calloc(1, sizeof (struct elf_object));
504 if (object == NULL) {
505 printf("unable to allocate object for %s\n", name);
506 exit(10);
507 }
508 ehdr = pexe;
509 loff = (Elf_Addr)pexe;
510
511 object->load_addr = 0;
512 object->load_name = strdup(name);
513
514 phdr = (Elf_Phdr *)((char *)pexe + ehdr->e_phoff);
515 for (i = 0; i < ehdr->e_phnum; i++) {
516 switch (phdr[i].p_type) {
517 case PT_DYNAMIC:
518 dynp = (Elf_Dyn *)(phdr[i].p_offset);
519 break;
520 case PT_INTERP:
521 /* XXX can only occur in programs */
522 curbin->interp = strdup((char *)((char *)pexe +
523 phdr[i].p_offset));
524 break;
525 default:
526 break;
527 }
528 }
529
530 if (dynp == 0) {
531 free(object);
532 return NULL; /* not a dynamic binary */
533 }
534
535 dynp = (Elf_Dyn *)((unsigned long)dynp + loff);
536 odynp = dynp;
537 while (dynp->d_tag != DT_NULL) {
538 if (dynp->d_tag < DT_NUM)
539 object->Dyn.info[dynp->d_tag] = dynp->d_un.d_val;
540 else if (dynp->d_tag >= DT_LOPROC &&
541 dynp->d_tag < DT_LOPROC + DT_PROCNUM)
542 object->Dyn.info[dynp->d_tag + DT_NUM - DT_LOPROC] =
543 dynp->d_un.d_val;
544 if (dynp->d_tag == DT_TEXTREL)
545 object->dyn.textrel = 1;
546 if (dynp->d_tag == DT_SYMBOLIC)
547 object->dyn.symbolic = 1;
548 if (dynp->d_tag == DT_BIND_NOW)
549 object->obj_flags = RTLD_NOW;
550 if (dynp->d_tag == DT_NEEDED)
551 needed_cnt++;
552
553 dynp++;
554 }
555
556 needed_list = calloc((needed_cnt + 1), sizeof(Elf_Word));
557 if (needed_list == NULL) {
558 printf("unable to allocate needed_list for %s\n", name);
559 exit(10);
560 }
561 needed_list[needed_cnt] = 0;
562 for (dynp = odynp, i = 0; dynp->d_tag != DT_NULL; dynp++) {
563 if (dynp->d_tag == DT_NEEDED) {
564 needed_list[i] = dynp->d_un.d_val;
565 i++;
566 }
567 }
568
569 if (object->Dyn.info[DT_HASH])
570 map_to_virt(phdr, ehdr, loff, &object->Dyn.info[DT_HASH]);
571 if (object->Dyn.info[DT_STRTAB])
572 map_to_virt(phdr, ehdr, loff, &object->Dyn.info[DT_STRTAB]);
573 if (object->Dyn.info[DT_SYMTAB])
574 map_to_virt(phdr, ehdr, loff, &object->Dyn.info[DT_SYMTAB]);
575
576 if (object->Dyn.info[DT_RELA])
577 map_to_virt(phdr, ehdr, loff, &object->Dyn.info[DT_RELA]);
578 if (object->Dyn.info[DT_RPATH])
579 object->Dyn.info[DT_RPATH] += object->Dyn.info[DT_STRTAB];
580 if (object->Dyn.info[DT_REL])
581 map_to_virt(phdr, ehdr, loff, &object->Dyn.info[DT_REL]);
582 if (object->Dyn.info[DT_JMPREL])
583 map_to_virt(phdr, ehdr, loff, &object->Dyn.info[DT_JMPREL]);
584
585 symt = object->dyn.symtab;
586 strt = object->dyn.strtab;
587
588 {
589 Elf_Sym *sym;
590 char *str;
591 Elf_Rel *rel;
592 Elf_RelA *rela;
593 Elf_Addr *hash;
594 Elf_Word *hashtab;
595 void *plt;
596 size_t hashsz;
597
598 if (object->Dyn.info[DT_HASH] != 0) {
599 hash = object->dyn.hash;
600 hashtab = (void *)hash;
601 object->nbuckets = hashtab[0];
602 object->nchains = hashtab[1];
603 hashsz = (2 + object->nbuckets + object->nchains) *
604 sizeof (Elf_Word);
605 hash = malloc(hashsz);
606 if (hash == NULL) {
607 printf("unable to allocate hash for %s\n",
608 name);
609 exit(10);
610 }
611 bcopy(object->dyn.hash, hash, hashsz);
612 object->dyn.hash = hash;
613 object->buckets = ((Elf_Word *)hash + 2);
614 object->chains = object->buckets + object->nbuckets;
615 }
616
617 str = malloc(object->dyn.strsz);
618 if (str == NULL) {
619 printf("unable to allocate strtab for %s\n",
620 name);
621 exit(10);
622 }
623 bcopy(object->dyn.strtab, str, object->dyn.strsz);
624 object->dyn.strtab = str;
625 strt = str;
626
627 sym = malloc(object->nchains * sizeof(Elf_Sym));
628 if (sym == NULL) {
629 printf("unable to allocate symtab for %s\n",
630 name);
631 exit(10);
632 }
633 bcopy(object->dyn.symtab, sym,
634 object->nchains * sizeof(Elf_Sym));
635 object->dyn.symtab = sym;
636 symt = sym;
637
638 if (object->dyn.relsz != 0) {
639 rel = malloc(object->dyn.relsz);
640 if (rel == NULL) {
641 printf("unable to allocate rel reloc for %s\n",
642 name);
643 exit(10);
644 }
645 bcopy(object->dyn.rel, rel, object->dyn.relsz);
646 object->dyn.rel = rel;
647 } else {
648 object->dyn.rel = NULL;
649 }
650 if (object->dyn.relasz != 0) {
651 rela = malloc(object->dyn.relasz);
652 if (rela == NULL) {
653 printf("unable to allocate rela reloc for %s\n",
654 name);
655 exit(10);
656 }
657 bcopy(object->dyn.rela, rela, object->dyn.relasz);
658 object->dyn.rela = rela;
659 } else {
660 object->dyn.rela = NULL;
661 }
662 if (object->dyn.pltrelsz != 0) {
663 plt = malloc(object->dyn.pltrelsz);
664 if (plt == NULL) {
665 printf("unable to allocate plt reloc for %s\n",
666 name);
667 exit(10);
668 }
669 bcopy((void*)object->dyn.jmprel, plt,
670 object->dyn.pltrelsz);
671 object->dyn.jmprel = (long)plt;
672 } else {
673 object->dyn.jmprel = 0;
674 }
675 if (object->dyn.rpath != NULL){
676 object->dyn.rpath = strdup(object->dyn.rpath);
677 if (object->dyn.rpath == NULL) {
678 printf("unable to allocate rpath for %s\n",
679 name);
680 exit(10);
681 }
682 }
683 object->dyn.needed = (Elf_Addr)needed_list;
684 }
685
686 #ifdef DEBUG1
687 dump_info(object);
688 #endif
689 return object;
690 }
691
692 /*
693 * Free any extra pieces associated with 'object'
694 */
695 void
elf_free_object(struct elf_object * object)696 elf_free_object(struct elf_object *object)
697 {
698 free(object->load_name);
699 if (object->dyn.hash != NULL)
700 free(object->dyn.hash);
701 free((void *)object->dyn.strtab);
702 free((void *)object->dyn.symtab);
703 if (object->dyn.rel != NULL)
704 free(object->dyn.rel);
705 if (object->dyn.rela != NULL)
706 free(object->dyn.rela);
707 if (object->dyn.rpath != NULL)
708 free((void *)object->dyn.rpath);
709 free(object);
710 }
711
712 /*
713 * translate an object address into a file offset for the
714 * file assuming that the file is mapped at base.
715 */
716 void
map_to_virt(Elf_Phdr * phdr,Elf_Ehdr * ehdr,Elf_Addr base,u_long * vaddr)717 map_to_virt(Elf_Phdr *phdr, Elf_Ehdr *ehdr, Elf_Addr base, u_long *vaddr)
718 {
719 int i;
720
721 for (i = 0; i < ehdr->e_phnum; i++) {
722 switch (phdr[i].p_type) {
723 case PT_LOAD:
724 if (phdr[i].p_vaddr > *vaddr)
725 continue;
726 if (phdr[i].p_vaddr + phdr[i].p_memsz < *vaddr)
727 continue;
728 #ifdef DEBUG1
729 printf("input address %lx translated to ", *vaddr);
730 #endif
731 *vaddr += phdr[i].p_offset - phdr[i].p_vaddr + base;
732 #ifdef DEBUG1
733 printf("%lx, base %lx %lx %llx\n", *vaddr, base,
734 phdr[i].p_vaddr, phdr[i].p_offset );
735 #endif
736 break;
737 default:
738 break;
739 }
740 }
741 }
742
743 /*
744 * given a dynamic elf object (executable or binary)
745 * load any DT_NEEDED entries which were found when
746 * the object was initially loaded.
747 */
748 int
load_obj_needed(struct elf_object * object)749 load_obj_needed(struct elf_object *object)
750 {
751 int i;
752 Elf_Word *needed_list;
753 int err;
754
755 needed_list = (Elf_Word *)object->dyn.needed;
756 for (i = 0; needed_list[i] != 0; i++) {
757 if (verbose > 1)
758 printf("lib: %s\n", needed_list[i] +
759 object->dyn.strtab);
760 err = load_lib(needed_list[i] + object->dyn.strtab, object);
761 if (err) {
762 printf("failed to load lib %s\n",
763 needed_list[i] + object->dyn.strtab);
764 return 1;
765 }
766 }
767 return 0;
768 }
769
770 /*
771 * allocate a proglist entry for a new binary
772 * so that it is available for libraries to reference
773 */
774 struct proglist *
elf_newbin(void)775 elf_newbin(void)
776 {
777 struct proglist *proglist;
778 proglist = malloc(sizeof (struct proglist));
779 if (proglist == NULL) {
780 printf("unable to allocate proglist\n");
781 exit(10);
782 }
783 proglist->fixup = NULL;
784 TAILQ_INIT(&(proglist->curbin_list));
785 return proglist;
786 }
787
788 /*
789 * Copy the contents of a libraries symbol cache instance into
790 * the 'global' symbol cache for that library
791 * this will currently resolve conflicts between mismatched
792 * libraries by flagging any mismatches as invalid
793 * which will cause all programs to generate a fixup
794 * It probably would be interesting to modify this to keep the most
795 * common entry as a library cache, and only have a fixup in programs
796 * where the symbol is overridden.
797 * This is run once each for the (got)symcache and pltsymcache
798 */
799
800 struct elf_object badobj_store;
801 struct elf_object *badobj = &badobj_store;
802
803 /*
804 * copy the symbols found in a library symcache to the 'master/common'
805 * symbol table note that this will skip copying the following references
806 * 1. non-existing entries
807 * 2. symobj == prog &&& obj != prog
808 * 3. symobj == prog's interpter (references to dl_open)
809 */
810 void
elf_copy_syms(struct symcache_noflag * tcache,struct symcache_noflag * scache,struct elf_object * obj,struct elf_object * prog,int nsyms)811 elf_copy_syms(struct symcache_noflag *tcache, struct symcache_noflag *scache,
812 struct elf_object *obj, struct elf_object *prog, int nsyms)
813 {
814 int i;
815 int lib_prog_ref;
816 for (i = 0; i < nsyms; i++) {
817 if (scache[i].obj == NULL)
818 continue;
819
820 if (tcache[i].obj != NULL) {
821 lib_prog_ref = (obj != prog && scache[i].obj == prog);
822 if (scache[i].obj != tcache[i].obj || lib_prog_ref) {
823 if (verbose > 2) {
824 printf("sym mismatch %d: "
825 "obj %d: sym %ld %s "
826 "nobj %s\n",
827 i, (int)scache[i].obj->dyn.null,
828 (long)(scache[i].sym -
829 scache[i].obj->dyn.symtab),
830 scache[i].sym->st_name +
831 scache[i].obj->dyn.strtab,
832 scache[i].obj->load_name);
833 }
834
835 /*
836 * if one of the symbol entries
837 * happens to be a self reference
838 * go ahead and keep that reference
839 * prevents some instances of fixups
840 * for every binary, eg one program
841 * overriding malloc() will not make
842 * ever binary have a fixup for libc
843 * references to malloc()
844 */
845 if (scache[i].obj == obj) {
846 tcache[i].obj = scache[i].obj;
847 tcache[i].sym = scache[i].sym;
848 } else if (tcache[i].obj == obj) {
849 /* no change necessary */
850 } else {
851 tcache[i].obj = badobj;
852 tcache[i].sym = NULL;
853 }
854 }
855 } else {
856 if (scache[i].obj != prog) {
857 tcache[i].obj = scache[i].obj;
858 tcache[i].sym = scache[i].sym;
859 }
860 }
861 }
862 }
863
864 void
insert_sym_objcache(struct elf_object * obj,int idx,const struct elf_object * ref_obj,const Elf_Sym * ref_sym,int flags)865 insert_sym_objcache(struct elf_object *obj, int idx,
866 const struct elf_object *ref_obj, const Elf_Sym *ref_sym, int flags)
867 {
868 struct symcache_noflag *tcache;
869 struct elf_object *prog;
870
871 prog = TAILQ_FIRST(&(curbin->curbin_list))->object;
872
873 if (flags)
874 tcache = objarray[obj->dyn.null].pltsymcache;
875 else
876 tcache = objarray[obj->dyn.null].symcache;
877
878 if (tcache[idx].obj != NULL) {
879 if (ref_obj != tcache[idx].obj ||
880 (obj != prog && ref_obj == prog)) {
881 if (verbose > 2) {
882 printf("sym mismatch %d: "
883 "obj %d: sym %ld %s "
884 "nobj %s\n",
885 idx, (int)ref_obj->dyn.null,
886 (long)(ref_sym -
887 ref_obj->dyn.symtab),
888 ref_sym->st_name +
889 ref_obj->dyn.strtab,
890 ref_obj->load_name);
891 }
892
893 /*
894 * if one of the symbol entries
895 * happens to be a self reference
896 * go ahead and keep that reference
897 * prevents some instances of fixups
898 * for every binary, eg one program
899 * overriding malloc() will not make
900 * ever binary have a fixup for libc
901 * references to malloc()
902 */
903 if (ref_obj == obj) {
904 tcache[idx].obj = ref_obj;
905 tcache[idx].sym = ref_sym;
906 add_fixup_oldprog(prog, obj, idx, ref_obj,
907 ref_sym, flags);
908 } else if (tcache[idx].obj == obj) {
909 /* no change necessary */
910 add_fixup_prog(prog, obj, idx, ref_obj,
911 ref_sym, flags);
912 } else {
913 add_fixup_oldprog(prog, obj, idx,
914 tcache[idx].obj, tcache[idx].sym, flags);
915 tcache[idx].obj = badobj;
916 tcache[idx].sym = NULL;
917 add_fixup_prog(prog, obj, idx, ref_obj,
918 ref_sym, flags);
919 }
920 }
921 } else {
922 if (ref_obj != prog) {
923 tcache[idx].obj = ref_obj;
924 tcache[idx].sym = ref_sym;
925 } else {
926 add_fixup_prog(prog, obj, idx, ref_obj,
927 ref_sym, flags);
928 }
929 }
930 }
931
932 void
add_fixup_prog(struct elf_object * prog,struct elf_object * obj,int idx,const struct elf_object * ref_obj,const Elf_Sym * ref_sym,int flag)933 add_fixup_prog(struct elf_object *prog, struct elf_object *obj, int idx,
934 const struct elf_object *ref_obj, const Elf_Sym *ref_sym, int flag)
935 {
936 struct proglist *pl;
937 int i, libidx, cnt;
938
939 pl = objarray[prog->dyn.null].proglist;
940
941 libidx = -1;
942 for (i = 0; i < pl->nobj; i++) {
943 if (pl->libmap[0][i] == obj->dyn.null) {
944 libidx = (i * 2) + ((flag & SYM_PLT) ? 1 : 0);
945 break;
946 }
947 }
948 if (libidx == -1) {
949 printf("unable to find object\n");
950 return;
951 }
952
953 /* have to check for duplicate patches */
954 for (i = 0; i < pl->fixupcnt[libidx]; i++) {
955 if (pl->fixup[libidx][i].sym == idx)
956 return;
957 }
958
959 if (verbose > 1)
960 printf("fixup for obj %s on prog %s sym %s: %d\n",
961 obj->load_name, prog->load_name,
962 ref_obj->dyn.strtab + ref_sym->st_name,
963 pl->fixupcnt[libidx]);
964
965 if (pl->fixupcntalloc[libidx] < pl->fixupcnt[libidx] + 1) {
966 pl->fixupcntalloc[libidx] += 16;
967 pl->fixup[libidx] = realloc(pl->fixup[libidx],
968 sizeof (struct fixup) * pl->fixupcntalloc[libidx]);
969 if (pl->fixup[libidx] == NULL) {
970 printf("realloc fixup, out of memory\n");
971 exit(20);
972 }
973 }
974 cnt = pl->fixupcnt[libidx];
975 pl->fixup[libidx][cnt].sym = idx;
976 pl->fixup[libidx][cnt].obj_idx = ref_obj->dyn.null;
977 pl->fixup[libidx][cnt].sym_idx = ref_sym - ref_obj->dyn.symtab;
978 pl->fixupcnt[libidx]++;
979 }
980
981 void
add_fixup_oldprog(struct elf_object * prog,struct elf_object * obj,int idx,const struct elf_object * ref_obj,const Elf_Sym * ref_sym,int flag)982 add_fixup_oldprog(struct elf_object *prog, struct elf_object *obj, int idx,
983 const struct elf_object *ref_obj, const Elf_Sym *ref_sym, int flag)
984 {
985 struct objlist *ol;
986
987 TAILQ_FOREACH(ol, &(objarray[obj->dyn.null].inst_list), inst_list) {
988 if (ol->load_prog == prog) {
989 continue;
990 }
991 /* process here */
992
993 add_fixup_prog(ol->load_prog, obj, idx, ref_obj, ref_sym, flag);
994 }
995
996 }
997
998 struct elf_object *
elf_lookup_object(const char * name)999 elf_lookup_object(const char *name)
1000 {
1001 struct objlist *ol;
1002 TAILQ_FOREACH(ol, &(curbin->curbin_list), list) {
1003 if (strcmp (name, ol->object->load_name) == 0) {
1004 return ol->object;
1005 }
1006 }
1007 TAILQ_FOREACH(ol, &library_list, list) {
1008 if (strcmp (name, ol->object->load_name) == 0) {
1009 elf_add_object_curbin_list(ol->object);
1010 return ol->object;
1011 }
1012 }
1013 return NULL;
1014 }
1015
1016 struct elf_object *
elf_lookup_object_devino(dev_t dev,ino_t inode,int objtype)1017 elf_lookup_object_devino(dev_t dev, ino_t inode, int objtype)
1018 {
1019 struct objlist *ol;
1020 TAILQ_FOREACH(ol, &(curbin->curbin_list), list) {
1021 if (ol->object->dev == dev &&
1022 ol->object->inode == inode) {
1023 if (ol->object->obj_type != objtype)
1024 return NULL;
1025 return ol->object;
1026 }
1027 }
1028 TAILQ_FOREACH(ol, &library_list, list) {
1029 if (ol->object->dev == dev &&
1030 ol->object->inode == inode) {
1031 if (ol->object->obj_type != objtype)
1032 return NULL;
1033 if (objtype != OBJTYPE_EXE)
1034 elf_add_object_curbin_list(ol->object);
1035 return ol->object;
1036 }
1037 }
1038 return NULL;
1039 }
1040
1041 void
elf_find_symbol_rel(const char * name,struct elf_object * object,Elf_Rel * rel,struct symcache_noflag * symcache,struct symcache_noflag * pltsymcache)1042 elf_find_symbol_rel(const char *name, struct elf_object *object,
1043 Elf_Rel *rel, struct symcache_noflag *symcache,
1044 struct symcache_noflag *pltsymcache)
1045 {
1046 struct objlist *ol;
1047 unsigned long h = 0;
1048 const char *p = name;
1049 const Elf_Sym *sym, *ref_sym = NULL;
1050 const Elf_Sym *weak_sym = NULL;
1051 struct elf_object *weak_obj = NULL;
1052 int flags = 0;
1053 int found = 0;
1054 int type, idx;
1055 struct elf_object *ref_object = NULL;
1056
1057 sym = object->dyn.symtab + ELF_R_SYM(rel->r_info);
1058
1059 while (*p) {
1060 unsigned long g;
1061 h = (h << 4) + *p++;
1062 if ((g = h & 0xf0000000))
1063 h ^= g >> 24;
1064 h &= ~g;
1065 }
1066
1067 type = ELF_R_TYPE(rel->r_info);
1068 flags = SYM_SEARCH_ALL|SYM_WARNNOTFOUND;
1069 if (type == RELOC_JMP_SLOT)
1070 flags |= SYM_PLT;
1071
1072 TAILQ_FOREACH(ol, &(curbin->curbin_list), list) {
1073 found = elf_find_symbol_obj(ol->object, name, h, flags, &sym,
1074 &weak_sym, &weak_obj);
1075 if (found) {
1076 ref_object = ol->object;
1077 break;
1078 }
1079
1080 }
1081 if (found) {
1082 ref_object = ol->object;
1083 ref_sym = sym;
1084 } else if (weak_obj != NULL) {
1085 found = 1;
1086 ref_object = weak_obj;
1087 ref_sym = weak_sym;
1088 }
1089 if (found == 1) {
1090 idx = ELF_R_SYM(rel->r_info);
1091 if (flags & SYM_PLT) {
1092 pltsymcache[idx].obj = ref_object;
1093 pltsymcache[idx].sym = ref_sym;
1094 } else {
1095 symcache[idx].obj = ref_object;
1096 symcache[idx].sym = ref_sym;
1097 }
1098 } else {
1099 printf("symbol not found %s\n", name);
1100 }
1101 }
1102
1103 void
elf_find_symbol_rela(const char * name,struct elf_object * object,Elf_RelA * rela,struct symcache_noflag * symcache,struct symcache_noflag * pltsymcache)1104 elf_find_symbol_rela(const char *name, struct elf_object *object,
1105 Elf_RelA *rela, struct symcache_noflag *symcache,
1106 struct symcache_noflag *pltsymcache)
1107 {
1108 struct objlist *ol;
1109 unsigned long h = 0;
1110 const char *p = name;
1111 const Elf_Sym *sym, *ref_sym = NULL;
1112 const Elf_Sym *weak_sym = NULL;
1113 struct elf_object *weak_obj = NULL;
1114 int flags = 0;
1115 int found = 0;
1116 int type, idx;
1117 struct elf_object *ref_object = NULL;
1118
1119 sym = object->dyn.symtab + ELF_R_SYM(rela->r_info);
1120
1121 while (*p) {
1122 unsigned long g;
1123 h = (h << 4) + *p++;
1124 if ((g = h & 0xf0000000))
1125 h ^= g >> 24;
1126 h &= ~g;
1127 }
1128
1129 type = ELF_R_TYPE(rela->r_info);
1130 flags = SYM_SEARCH_ALL|SYM_WARNNOTFOUND;
1131 if (type == RELOC_JMP_SLOT)
1132 flags |= SYM_PLT;
1133
1134 TAILQ_FOREACH(ol, &(curbin->curbin_list), list) {
1135
1136 // printf("searching sym [%s] typ %d in obj %s\n", name, type, ol->object->load_name);
1137 found = elf_find_symbol_obj(ol->object, name, h, flags, &sym,
1138 &weak_sym, &weak_obj);
1139 if (found) {
1140 ref_object = ol->object;
1141 break;
1142 }
1143
1144 }
1145 if (found) {
1146 ref_object = ol->object;
1147 ref_sym = sym;
1148 } else if (weak_obj != NULL) {
1149 found = 1;
1150 ref_object = weak_obj;
1151 ref_sym = weak_sym;
1152 }
1153 if (found == 1) {
1154 idx = ELF_R_SYM(rela->r_info);
1155 if (flags & SYM_PLT) {
1156 pltsymcache[idx].obj = ref_object;
1157 pltsymcache[idx].sym = ref_sym;
1158 } else {
1159 symcache[idx].obj = ref_object;
1160 symcache[idx].sym = ref_sym;
1161 }
1162 } else {
1163 printf("symbol not found %s\n", name);
1164 }
1165 }
1166
1167 int
elf_find_symbol_obj(elf_object_t * object,const char * name,unsigned long hash,int flags,const Elf_Sym ** this,const Elf_Sym ** weak_sym,elf_object_t ** weak_object)1168 elf_find_symbol_obj(elf_object_t *object, const char *name, unsigned long hash,
1169 int flags, const Elf_Sym **this, const Elf_Sym **weak_sym,
1170 elf_object_t **weak_object)
1171 {
1172 const Elf_Sym *symt = object->dyn.symtab;
1173 const char *strt = object->dyn.strtab;
1174 long si;
1175 const char *symn;
1176
1177 for (si = object->buckets[hash % object->nbuckets];
1178 si != STN_UNDEF; si = object->chains[si]) {
1179 const Elf_Sym *sym = symt + si;
1180
1181 if (sym->st_value == 0)
1182 continue;
1183
1184 if (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE &&
1185 ELF_ST_TYPE(sym->st_info) != STT_OBJECT &&
1186 ELF_ST_TYPE(sym->st_info) != STT_FUNC)
1187 continue;
1188
1189 symn = strt + sym->st_name;
1190 if (sym != *this && strcmp(symn, name))
1191 continue;
1192
1193 /* allow this symbol if we are referring to a function
1194 * which has a value, even if section is UNDEF.
1195 * this allows &func to refer to PLT as per the
1196 * ELF spec. st_value is checked above.
1197 * if flags has SYM_PLT set, we must have actual
1198 * symbol, so this symbol is skipped.
1199 */
1200 if (sym->st_shndx == SHN_UNDEF) {
1201 if ((flags & SYM_PLT) || sym->st_value == 0 ||
1202 ELF_ST_TYPE(sym->st_info) != STT_FUNC)
1203 continue;
1204 }
1205
1206 if (ELF_ST_BIND(sym->st_info) == STB_GLOBAL) {
1207 *this = sym;
1208 return 1;
1209 } else if (ELF_ST_BIND(sym->st_info) == STB_WEAK) {
1210 if (!*weak_sym) {
1211 *weak_sym = sym;
1212 *weak_object = object;
1213 }
1214 }
1215 }
1216 return 0;
1217 }
1218
1219 void
elf_reloc(struct elf_object * object)1220 elf_reloc(struct elf_object *object)
1221 {
1222 const Elf_Sym *sym;
1223 Elf_Rel *rel;
1224 Elf_RelA *rela;
1225 int numrel;
1226 int numrela;
1227 int i;
1228 struct symcache_noflag *symcache;
1229 struct symcache_noflag *pltsymcache;
1230
1231 numrel = object->dyn.relsz / sizeof(Elf_Rel);
1232 #ifdef DEBUG1
1233 printf("rel relocations: %d\n", numrel);
1234 #endif
1235 #if 1
1236 symcache = calloc(sizeof(struct symcache_noflag),
1237 object->nchains);
1238 pltsymcache = calloc(sizeof(struct symcache_noflag),
1239 object->nchains);
1240 if (symcache == NULL || pltsymcache == NULL) {
1241 printf("unable to allocate memory for cache %s\n",
1242 object->load_name);
1243 exit(20);
1244 }
1245 #endif
1246 rel = object->dyn.rel;
1247 for (i = 0; i < numrel; i++) {
1248 const char *s;
1249 sym = object->dyn.symtab + ELF_R_SYM(rel[i].r_info);
1250
1251 /* hppa has entries without names, skip them */
1252 if (sym->st_name == 0)
1253 continue;
1254
1255 s = (ELF_R_SYM(rel[i].r_info) == 0) ? "<rel>" :
1256 object->dyn.strtab + sym->st_name;
1257 #ifdef DEBUG1
1258 printf("%d: %x sym %x %s type %d\n", i, rel[i].r_offset,
1259 ELF_R_SYM(rel[i].r_info), s,
1260 ELF_R_TYPE(rel[i].r_info));
1261 #endif
1262 if (ELF_R_SYM(rel[i].r_info) != 0) {
1263 elf_find_symbol_rel(s, object, &rel[i],
1264 symcache, pltsymcache);
1265 }
1266 }
1267 if (numrel) {
1268 numrel = object->dyn.pltrelsz / sizeof(Elf_Rel);
1269 rel = (Elf_Rel *)(object->Dyn.info[DT_JMPREL]);
1270 #ifdef DEBUG1
1271 printf("rel plt relocations: %d\n", numrel);
1272 #endif
1273 for (i = 0; i < numrel; i++) {
1274 const char *s;
1275 sym = object->dyn.symtab + ELF_R_SYM(rel[i].r_info);
1276
1277 /* hppa has entries without names, skip them */
1278 if (sym->st_name == 0)
1279 continue;
1280
1281 s = (ELF_R_SYM(rel[i].r_info) == 0) ? "<rel>" :
1282 object->dyn.strtab + sym->st_name;
1283 #ifdef DEBUG1
1284 printf("%d: %x sym %d %s type %d\n", i, rel[i].r_offset,
1285 ELF_R_SYM(rel[i].r_info), s,
1286 ELF_R_TYPE(rel[i].r_info));
1287 #endif
1288 if (ELF_R_SYM(rel[i].r_info) != 0) {
1289 elf_find_symbol_rel(s, object, &rel[i],
1290 symcache, pltsymcache);
1291 }
1292 }
1293 }
1294
1295 numrela = object->dyn.relasz / sizeof(Elf_RelA);
1296 #ifdef DEBUG1
1297 printf("rela relocations: %d\n", numrela);
1298 #endif
1299 rela = object->dyn.rela;
1300 for (i = 0; i < numrela; i++) {
1301 const char *s;
1302 sym = object->dyn.symtab + ELF_R_SYM(rela[i].r_info);
1303
1304 /* hppa has entries without names, skip them */
1305 if (sym->st_name == 0)
1306 continue;
1307
1308 s = (ELF_R_SYM(rela[i].r_info) == 0) ? "<rel>" :
1309 object->dyn.strtab + sym->st_name;
1310 #ifdef DEBUG1
1311 printf("%d: %x sym %x %s type %d\n", i, rela[i].r_offset,
1312 ELF_R_SYM(rela[i].r_info), s,
1313 ELF_R_TYPE(rela[i].r_info));
1314 #endif
1315 if (ELF_R_SYM(rela[i].r_info) != 0) {
1316 elf_find_symbol_rela(s, object, &rela[i],
1317 symcache, pltsymcache);
1318 }
1319 }
1320 if (numrela) {
1321 numrela = object->dyn.pltrelsz / sizeof(Elf_RelA);
1322 #ifdef DEBUG1
1323 printf("rela plt relocations: %d\n", numrela);
1324 #endif
1325 rela = (Elf_RelA *)(object->Dyn.info[DT_JMPREL]);
1326
1327 for (i = 0; i < numrela; i++) {
1328 const char *s;
1329 sym = object->dyn.symtab + ELF_R_SYM(rela[i].r_info);
1330
1331 /* hppa has entries without names, skip them */
1332 if (sym->st_name == 0)
1333 continue;
1334
1335 s = (ELF_R_SYM(rela[i].r_info) == 0) ? "<rel>" :
1336 object->dyn.strtab + sym->st_name;
1337 #ifdef DEBUG1
1338 printf("%d: %x sym %x %s type %d\n", i,
1339 rela[i].r_offset,
1340 ELF_R_SYM(rela[i].r_info), s,
1341 ELF_R_TYPE(rela[i].r_info));
1342 #endif
1343 if (ELF_R_SYM(rela[i].r_info) != 0) {
1344 elf_find_symbol_rela(s, object, &rela[i],
1345 symcache, pltsymcache);
1346 }
1347 }
1348 }
1349
1350 for (i = 0; i < object->nchains; i++)
1351 if (symcache[i].sym != NULL)
1352 insert_sym_objcache(object, i, symcache[i].obj,
1353 symcache[i].sym, 0);
1354
1355 for (i = 0; i < object->nchains; i++)
1356 if (pltsymcache[i].sym != NULL)
1357 insert_sym_objcache(object, i, pltsymcache[i].obj,
1358 pltsymcache[i].sym, SYM_PLT);
1359
1360 free(symcache);
1361 free(pltsymcache);
1362 }
1363
1364 void
elf_resolve_curbin(void)1365 elf_resolve_curbin(void)
1366 {
1367 struct objlist *ol;
1368 int numobj = 0;
1369
1370 #ifdef DEBUG1
1371 elf_print_curbin_list(curbin);
1372 #endif
1373 TAILQ_FOREACH(ol, &(curbin->curbin_list), list) {
1374 numobj++;
1375 }
1376 curbin->nobj = numobj;
1377 curbin->libmap = xcalloc(numobj, sizeof (u_int32_t *));
1378 curbin->libmap[0] = xcalloc(numobj, sizeof (u_int32_t *));
1379 curbin->fixup = xcalloc(2 * numobj, sizeof (struct fixup *));
1380 curbin->fixupcnt = xcalloc(2 * numobj, sizeof (int));
1381 curbin->fixupcntalloc = xcalloc(2 * numobj, sizeof (int));
1382
1383 numobj = 0;
1384 TAILQ_FOREACH(ol, &(curbin->curbin_list), list) {
1385 curbin->libmap[0][numobj] = ol->object->dyn.null;
1386 numobj++;
1387 }
1388 TAILQ_FOREACH(ol, &(curbin->curbin_list), list) {
1389 elf_reloc(ol->object);
1390 }
1391 }
1392
1393 void
elf_add_object_curbin_list(struct elf_object * object)1394 elf_add_object_curbin_list(struct elf_object *object)
1395 {
1396 struct objlist *ol;
1397
1398 ol = xmalloc(sizeof (struct objlist));
1399 ol->object = object;
1400 TAILQ_INSERT_TAIL(&(curbin->curbin_list), ol, list);
1401 if (load_object == NULL)
1402 load_object = object;
1403 ol->load_prog = load_object;
1404
1405 TAILQ_INSERT_TAIL(&(objarray[object->dyn.null].inst_list), ol,
1406 inst_list);
1407 }
1408 void
elf_init_objarray(void)1409 elf_init_objarray(void)
1410 {
1411 objarray_sz = 512;
1412 objarray = xmalloc(sizeof (objarray[0]) * objarray_sz);
1413 }
1414
1415 void
elf_sum_reloc()1416 elf_sum_reloc()
1417 {
1418 int numobjs;
1419 int err = 0;
1420 struct objlist *ol;
1421 struct proglist *pl;
1422
1423 TAILQ_FOREACH(ol, &library_list, list) {
1424 err += elf_prep_lib_prebind(ol->object);
1425 }
1426 TAILQ_FOREACH(pl, &prog_list, list) {
1427 numobjs = 0;
1428 TAILQ_FOREACH(ol, &(pl->curbin_list), list) {
1429 numobjs++;
1430 }
1431 pl->nobj = numobjs;
1432 }
1433
1434 TAILQ_FOREACH(pl, &prog_list, list)
1435 err += elf_prep_bin_prebind(pl);
1436
1437 if (err != 0)
1438 printf("failures %d\n", err);
1439 }
1440
1441 int
elf_prep_lib_prebind(struct elf_object * object)1442 elf_prep_lib_prebind(struct elf_object *object)
1443 {
1444 int numlibs = 0;
1445 int ret = 0;
1446 int i;
1447 int ref_obj;
1448 int *libmap;
1449 int *idxtolib;
1450 struct nameidx *nameidx;
1451 char *nametab;
1452 int nametablen;
1453 struct symcache_noflag *symcache;
1454 struct symcache_noflag *pltsymcache;
1455 struct symcachetab *symcachetab;
1456 int symcache_cnt = 0;
1457 struct symcachetab *pltsymcachetab;
1458 int pltsymcache_cnt = 0;
1459
1460 symcache = objarray[object->dyn.null].symcache;
1461 pltsymcache = objarray[object->dyn.null].pltsymcache;
1462 libmap = xcalloc(objarray_cnt, sizeof (int));
1463 idxtolib = xcalloc(objarray_cnt, sizeof (int));
1464 objarray[object->dyn.null].idxtolib = idxtolib;
1465
1466 for (i = 0; i < objarray_cnt; i++)
1467 libmap[i] = -1;
1468
1469 nametablen = 0;
1470 for (i = 0; i < object->nchains; i++) {
1471 if (symcache[i].sym == NULL)
1472 continue;
1473 ref_obj = symcache[i].obj->dyn.null;
1474 symcache_cnt++;
1475 if (libmap[ref_obj] != -1)
1476 continue;
1477 libmap[ref_obj] = numlibs;
1478 idxtolib[numlibs] = ref_obj;
1479 nametablen += strlen(symcache[i].obj->load_name) + 1;
1480 numlibs++;
1481 }
1482 symcachetab = xcalloc(symcache_cnt , sizeof(struct symcachetab));
1483
1484 symcache_cnt = 0;
1485 for (i = 0; i < object->nchains; i++) {
1486 if (symcache[i].sym == NULL)
1487 continue;
1488 symcachetab[symcache_cnt].idx = i;
1489 symcachetab[symcache_cnt].obj_idx =
1490 libmap[symcache[i].obj->dyn.null];
1491 symcachetab[symcache_cnt].sym_idx =
1492 symcache[i].sym - symcache[i].obj->dyn.symtab;
1493 symcache_cnt++;
1494 }
1495 for (i = 0; i < object->nchains; i++) {
1496 if (pltsymcache[i].sym == NULL)
1497 continue;
1498 ref_obj = pltsymcache[i].obj->dyn.null;
1499 pltsymcache_cnt++;
1500 if (libmap[ref_obj] != -1)
1501 continue;
1502 libmap[ref_obj] = numlibs;
1503 idxtolib[numlibs] = ref_obj;
1504 nametablen += strlen(pltsymcache[i].obj->load_name) + 1;
1505 numlibs++;
1506 }
1507 pltsymcachetab = xcalloc(pltsymcache_cnt , sizeof(struct symcachetab));
1508
1509 pltsymcache_cnt = 0;
1510 for (i = 0; i < object->nchains; i++) {
1511 if (pltsymcache[i].sym == NULL)
1512 continue;
1513 pltsymcachetab[pltsymcache_cnt].idx = i;
1514 pltsymcachetab[pltsymcache_cnt].obj_idx =
1515 libmap[pltsymcache[i].obj->dyn.null];
1516 pltsymcachetab[pltsymcache_cnt].sym_idx =
1517 pltsymcache[i].sym - pltsymcache[i].obj->dyn.symtab;
1518 pltsymcache_cnt++;
1519 }
1520
1521 objarray[object->dyn.null].numlibs = numlibs;
1522
1523 nameidx = xcalloc(numlibs, sizeof (struct nameidx));
1524 nametab = xmalloc(nametablen);
1525
1526 nametablen = 0;
1527 for (i = 0; i < numlibs; i++) {
1528 nameidx[i].name = nametablen;
1529 nameidx[i].id0 = objarray[idxtolib[i]].id0;
1530 nameidx[i].id1 = objarray[idxtolib[i]].id1;
1531 nametablen += strlen(objarray[idxtolib[i]].obj->load_name) + 1;
1532 strlcpy(&nametab[nameidx[i].name],
1533 objarray[idxtolib[i]].obj->load_name,
1534 nametablen - nameidx[i].name);
1535 }
1536
1537 /* skip writing lib if using old prebind data */
1538 if (objarray[object->dyn.null].oprebind_data == NULL)
1539 ret = elf_write_lib(object, nameidx, nametab, nametablen,
1540 numlibs, 0, NULL, NULL, NULL, NULL, symcachetab,
1541 symcache_cnt, pltsymcachetab, pltsymcache_cnt);
1542
1543 free(nameidx);
1544 free(nametab);
1545 free(libmap);
1546 free(pltsymcachetab);
1547 free(symcachetab);
1548
1549 return ret;
1550 }
1551
1552 int
elf_prep_bin_prebind(struct proglist * pl)1553 elf_prep_bin_prebind(struct proglist *pl)
1554 {
1555 int ret;
1556 int numlibs = 0;
1557 int i, j;
1558 int ref_obj;
1559 int *libmap;
1560 int *idxtolib;
1561 struct nameidx *nameidx;
1562 char *nametab;
1563 int nametablen;
1564 struct symcache_noflag *symcache;
1565 struct symcache_noflag *pltsymcache;
1566 struct symcachetab *symcachetab;
1567 int symcache_cnt;
1568 struct symcachetab *pltsymcachetab;
1569 int pltsymcache_cnt;
1570 struct elf_object *object;
1571 struct objlist *ol;
1572
1573 object = TAILQ_FIRST(&(pl->curbin_list))->object;
1574 symcache = objarray[object->dyn.null].symcache;
1575 pltsymcache = objarray[object->dyn.null].pltsymcache;
1576 libmap = xcalloc(objarray_cnt, sizeof (int));
1577 idxtolib = xcalloc(pl->nobj, sizeof (int));
1578
1579 for (i = 0; i < objarray_cnt; i++)
1580 libmap[i] = -1;
1581
1582 for (i = 0; i < pl->nobj; i++)
1583 idxtolib[i] = -1;
1584
1585 nametablen = 0;
1586 TAILQ_FOREACH(ol, &(pl->curbin_list), list) {
1587 ref_obj = ol->object->dyn.null;
1588 nametablen += strlen(ol->object->load_name) + 1;
1589 libmap[ref_obj] = numlibs;
1590 idxtolib[numlibs] = ref_obj;
1591 numlibs++;
1592 }
1593
1594 /* do got */
1595 symcache_cnt = 0;
1596 for (i = 0; i < object->nchains; i++) {
1597 if (symcache[i].sym != NULL)
1598 symcache_cnt++;
1599 }
1600
1601 symcachetab = xcalloc(symcache_cnt , sizeof(struct symcachetab));
1602
1603 symcache_cnt = 0;
1604 for (i = 0; i < object->nchains; i++) {
1605 if (symcache[i].sym == NULL)
1606 continue;
1607 symcachetab[symcache_cnt].idx = i;
1608 symcachetab[symcache_cnt].obj_idx =
1609 libmap[symcache[i].obj->dyn.null];
1610 symcachetab[symcache_cnt].sym_idx =
1611 symcache[i].sym - symcache[i].obj->dyn.symtab;
1612 symcache_cnt++;
1613 }
1614
1615 /* now do plt */
1616 pltsymcache_cnt = 0;
1617 for (i = 0; i < object->nchains; i++) {
1618 if (pltsymcache[i].sym != NULL)
1619 pltsymcache_cnt++;
1620 }
1621 pltsymcachetab = xcalloc(pltsymcache_cnt , sizeof(struct symcachetab));
1622
1623 pltsymcache_cnt = 0;
1624 for (i = 0; i < object->nchains; i++) {
1625 if (pltsymcache[i].sym == NULL)
1626 continue;
1627 pltsymcachetab[pltsymcache_cnt].idx = i;
1628 pltsymcachetab[pltsymcache_cnt].obj_idx =
1629 libmap[pltsymcache[i].obj->dyn.null];
1630 pltsymcachetab[pltsymcache_cnt].sym_idx =
1631 pltsymcache[i].sym - pltsymcache[i].obj->dyn.symtab;
1632 pltsymcache_cnt++;
1633 }
1634
1635 objarray[object->dyn.null].numlibs = numlibs;
1636
1637 nameidx = xcalloc(numlibs, sizeof (struct nameidx));
1638 nametab = xmalloc(nametablen);
1639
1640 nametablen = 0;
1641 for (i = 0; i < numlibs; i++) {
1642 nameidx[i].name = nametablen;
1643 nameidx[i].id0 = objarray[idxtolib[i]].id0;
1644 nameidx[i].id1 = objarray[idxtolib[i]].id1;
1645 nametablen += strlen(objarray[idxtolib[i]].obj->load_name) + 1;
1646
1647 strlcpy(&nametab[nameidx[i].name],
1648 objarray[idxtolib[i]].obj->load_name,
1649 nametablen - nameidx[i].name);
1650 }
1651 pl->libmapcnt = xcalloc(numlibs, sizeof(u_int32_t));
1652
1653 /* have to do both got and plt fixups */
1654 for (i = 0; i < numlibs; i++) {
1655 for (j = 0; j < pl->fixupcnt[2*i]; j++) {
1656 pl->fixup[2*i][j].obj_idx =
1657 libmap[pl->fixup[2*i][j].obj_idx];
1658 }
1659 for (j = 0; j < pl->fixupcnt[2*i+1]; j++) {
1660 pl->fixup[2*i+1][j].obj_idx =
1661 libmap[pl->fixup[2*i+1][j].obj_idx];
1662 }
1663
1664 pl->libmapcnt[i] = objarray[idxtolib[i]].numlibs;
1665 pl->libmap[i] = xcalloc(objarray[idxtolib[i]].numlibs,
1666 sizeof(u_int32_t));
1667 if (i != 0) {
1668 for (j = 0; j < objarray[idxtolib[i]].numlibs; j++) {
1669 pl->libmap[i][j] =
1670 libmap[objarray[idxtolib[i]].idxtolib[j]];
1671 }
1672 }
1673 }
1674
1675 ret = elf_write_lib(object, nameidx, nametab, nametablen, numlibs,
1676 numlibs, pl->fixup, pl->fixupcnt,
1677 pl->libmap, pl->libmapcnt,
1678 symcachetab, symcache_cnt,
1679 pltsymcachetab, pltsymcache_cnt);
1680
1681 free(symcachetab);
1682 free(pltsymcachetab);
1683 free(idxtolib);
1684 free(nameidx);
1685 free(nametab);
1686 free(libmap);
1687
1688 return ret;
1689 }
1690
1691
1692 int
elf_write_lib(struct elf_object * object,struct nameidx * nameidx,char * nametab,int nametablen,int numlibs,int nfixup,struct fixup ** fixup,int * fixupcnt,u_int32_t ** libmap,int * libmapcnt,struct symcachetab * symcachetab,int symcache_cnt,struct symcachetab * pltsymcachetab,int pltsymcache_cnt)1693 elf_write_lib(struct elf_object *object, struct nameidx *nameidx,
1694 char *nametab, int nametablen, int numlibs,
1695 int nfixup, struct fixup **fixup, int *fixupcnt,
1696 u_int32_t **libmap, int *libmapcnt,
1697 struct symcachetab *symcachetab, int symcache_cnt,
1698 struct symcachetab *pltsymcachetab, int pltsymcache_cnt)
1699 {
1700 struct prebind_footer footer;
1701 struct prebind_info info;
1702 u_int32_t footer_offset, *maptab = NULL;
1703 u_int32_t next_start, *fixuptab = NULL;
1704 struct stat ifstat;
1705 off_t base_offset;
1706 size_t len;
1707 int fd = -1, i;
1708 int readonly = 0;
1709
1710 /* open the file, if in safe mode, only open it readonly */
1711 if (safe == 0)
1712 fd = open(object->load_name, O_RDWR);
1713 if (fd == -1) {
1714 if (safe != 0 || errno == ETXTBSY)
1715 fd = open(object->load_name, O_RDONLY);
1716 if (fd == -1) {
1717 perror(object->load_name);
1718 return 1;
1719 }
1720 readonly = 1;
1721 }
1722 lseek(fd, -((off_t)sizeof(struct prebind_footer)), SEEK_END);
1723 len = read(fd, &footer, sizeof(struct prebind_footer));
1724
1725 if (fstat(fd, &ifstat) == -1) {
1726 perror(object->load_name);
1727 exit(10);
1728 }
1729
1730 if (footer.bind_id[0] == BIND_ID0 &&
1731 footer.bind_id[1] == BIND_ID1 &&
1732 footer.bind_id[2] == BIND_ID2 &&
1733 footer.bind_id[3] == BIND_ID3 &&
1734 readonly == 0) {
1735
1736 ftruncate(fd, footer.orig_size);
1737 elf_clear_prog_load(fd, object);
1738
1739 base_offset = footer.orig_size;
1740 } else {
1741 base_offset = ifstat.st_size;
1742 }
1743
1744 bzero(&footer, sizeof(struct prebind_footer));
1745
1746
1747 /* verify dev/inode - do we care about last modified? */
1748
1749 /* pieces to store on lib
1750 *
1751 * offset to footer
1752 * nameidx - numlibs * sizeof nameidx
1753 * symcache - symcache_cnt * sizeof (symcache_idx)
1754 * pltsymcache - pltsymcache_cnt * sizeof (symcache_idx)
1755 * fixup(N/A for lib) - nfixup * sizeof (symcache_idx)
1756 * nametab - nametablen
1757 * footer (not aligned)
1758 */
1759
1760 footer.orig_size = base_offset;
1761 base_offset = ELF_ROUND(base_offset, sizeof(u_int64_t));
1762 footer.prebind_base = base_offset;
1763 footer.nameidx_idx = sizeof(u_int32_t);
1764 footer.symcache_idx = footer.nameidx_idx +
1765 numlibs * sizeof (struct nameidx);
1766 footer.pltsymcache_idx = footer.symcache_idx +
1767 symcache_cnt * sizeof (struct nameidx);
1768 footer.symcache_cnt = symcache_cnt;
1769 footer.pltsymcache_cnt = pltsymcache_cnt;
1770 footer.fixup_cnt = 0;
1771 footer.numlibs = numlibs;
1772 next_start = footer.pltsymcache_idx +
1773 (pltsymcache_cnt * sizeof (struct symcachetab));
1774 if (nfixup != 0) {
1775 footer.fixup_cnt = nfixup;
1776 footer.fixup_idx = next_start;
1777 next_start += 2*nfixup * sizeof(u_int32_t);
1778 footer.fixupcnt_idx = next_start;
1779 next_start += 2*nfixup * sizeof(u_int32_t);
1780 fixuptab = xcalloc(2*nfixup, sizeof(u_int32_t));
1781 for (i = 0; i < 2*nfixup; i++) {
1782 fixuptab[i] = next_start;
1783 next_start += fixupcnt[i] * sizeof(struct fixup);
1784 }
1785 footer.libmap_idx = next_start;
1786 next_start += 2*nfixup * sizeof(u_int32_t);
1787 maptab = xcalloc(2*nfixup, sizeof(u_int32_t));
1788 maptab[0] = next_start;
1789 for (i = 1; i < nfixup; i++) {
1790 maptab[i] = next_start;
1791 next_start += libmapcnt[i] * sizeof(u_int32_t);
1792 }
1793 }
1794
1795 footer.nametab_idx = next_start;
1796 next_start += nametablen;
1797 next_start = ELF_ROUND(next_start, sizeof(u_int64_t));
1798 footer_offset = next_start;
1799 if (verbose > 1) {
1800 printf("footer_offset %d\n", footer_offset);
1801 }
1802 footer.prebind_size = next_start + sizeof(struct prebind_footer);
1803
1804 footer.prebind_version = PREBIND_VERSION;
1805 footer.id0 = objarray[object->dyn.null].id0;
1806 footer.id1 = objarray[object->dyn.null].id1;
1807 footer.bind_id[0] = BIND_ID0;
1808 footer.bind_id[1] = BIND_ID1;
1809 footer.bind_id[2] = BIND_ID2;
1810 footer.bind_id[3] = BIND_ID3;
1811
1812
1813 info.object = object;
1814 info.footer = &footer;
1815 info.footer_offset = footer_offset;
1816 info.nameidx = nameidx;
1817 info.symcache = symcachetab;
1818
1819
1820 info.pltsymcache = pltsymcachetab;
1821 info.nfixup = nfixup;
1822 if (nfixup != 0) {
1823 info.fixuptab = fixuptab;
1824 info.fixupcnt = fixupcnt;
1825 info.fixup = fixup;
1826 info.maptab = maptab;
1827 info.libmap = libmap;
1828 info.libmapcnt = libmapcnt;
1829 }
1830
1831 info.nametab = nametab;
1832 info.nametablen = nametablen;
1833
1834
1835 if (readonly) {
1836 prebind_writenewfile(fd, object->load_name, &ifstat,
1837 (off_t)footer.orig_size, &info);
1838 } else {
1839 prebind_writefile(fd, &info);
1840 }
1841
1842 if (fstat(fd, &ifstat) == -1) {
1843 perror(object->load_name);
1844 exit(10);
1845 }
1846 if (nfixup != 0) {
1847 free(fixuptab);
1848 free(maptab);
1849 }
1850
1851 if (verbose > 0)
1852 printf("%s: prebind info %d bytes old size %lld, growth %f\n",
1853 object->load_name, footer.prebind_size, footer.orig_size,
1854 (double)(footer.prebind_size) / footer.orig_size);
1855
1856 if (verbose > 1)
1857 elf_dump_footer(&footer);
1858
1859 close(fd);
1860 return 0;
1861 }
1862
1863 int
prebind_writefile(int fd,struct prebind_info * info)1864 prebind_writefile(int fd, struct prebind_info *info)
1865 {
1866 int i;
1867
1868 struct prebind_footer *footer = info->footer;
1869
1870 lseek(fd, footer->prebind_base, SEEK_SET);
1871 write(fd, &info->footer_offset, sizeof(u_int32_t));
1872
1873 lseek(fd, footer->prebind_base+footer->nameidx_idx, SEEK_SET);
1874 write(fd, info->nameidx, footer->numlibs * sizeof (struct nameidx));
1875
1876 lseek(fd, footer->prebind_base+footer->symcache_idx, SEEK_SET);
1877 write(fd, info->symcache, footer->symcache_cnt *
1878 sizeof (struct symcachetab));
1879
1880 lseek(fd, footer->prebind_base+footer->pltsymcache_idx, SEEK_SET);
1881 write(fd, info->pltsymcache, footer->pltsymcache_cnt *
1882 sizeof (struct symcachetab));
1883
1884 if (info->nfixup != 0) {
1885 lseek(fd, footer->prebind_base+footer->fixup_idx, SEEK_SET);
1886 write(fd, info->fixuptab, 2*info->nfixup * sizeof(u_int32_t));
1887 lseek(fd, footer->prebind_base+footer->fixupcnt_idx, SEEK_SET);
1888 write(fd, info->fixupcnt, 2*info->nfixup * sizeof(u_int32_t));
1889 for (i = 0; i < 2*info->nfixup; i++) {
1890 lseek(fd, footer->prebind_base+info->fixuptab[i],
1891 SEEK_SET);
1892 write(fd, info->fixup[i], info->fixupcnt[i] *
1893 sizeof(struct fixup));
1894 }
1895
1896 lseek(fd, footer->prebind_base+footer->libmap_idx, SEEK_SET);
1897 write(fd, info->maptab, info->nfixup * sizeof(u_int32_t));
1898 for (i = 0; i < info->nfixup; i++) {
1899 lseek(fd, footer->prebind_base+info->maptab[i],
1900 SEEK_SET);
1901 write(fd, info->libmap[i], info->libmapcnt[i] *
1902 sizeof(u_int32_t));
1903 }
1904 }
1905 lseek(fd, footer->prebind_base+footer->nametab_idx, SEEK_SET);
1906 write(fd, info->nametab, info->nametablen);
1907
1908 lseek(fd, footer->prebind_base+info->footer_offset, SEEK_SET);
1909 write(fd, footer, sizeof (struct prebind_footer));
1910
1911 if (info->object->obj_type == OBJTYPE_EXE)
1912 elf_fixup_prog_load(fd, info->footer, info->object);
1913
1914 return 0;
1915 }
1916
1917 int
prebind_writenewfile(int infd,char * name,struct stat * st,off_t orig_size,struct prebind_info * info)1918 prebind_writenewfile(int infd, char *name, struct stat *st, off_t orig_size,
1919 struct prebind_info *info)
1920 {
1921 struct timeval tv[2];
1922 char *newname, *buf;
1923 ssize_t len, wlen;
1924 int outfd;
1925
1926 if (asprintf(&newname, "%s.XXXXXXXXXX", name) == -1) {
1927 if (verbose)
1928 warn("asprintf");
1929 return (-1);
1930 }
1931 outfd = open(newname, O_CREAT|O_RDWR|O_TRUNC, 0600);
1932 if (outfd == -1) {
1933 warn("%s", newname);
1934 free(newname);
1935 return (-1);
1936 }
1937
1938 buf = malloc(BUFSZ);
1939 if (buf == NULL) {
1940 if (verbose)
1941 warn("malloc");
1942 goto fail;
1943 }
1944
1945 /* copy old file to new file */
1946 lseek(infd, (off_t)0, SEEK_SET);
1947 while (1) {
1948 len = read(infd, buf, BUFSIZ);
1949 if (len == -1) {
1950 if (verbose)
1951 warn("read");
1952 free(buf);
1953 goto fail;
1954 }
1955 if (len == 0)
1956 break;
1957 wlen = write(outfd, buf, len);
1958 if (wlen != len) {
1959 free(buf);
1960 goto fail;
1961 }
1962 }
1963 free(buf);
1964
1965 /* now back track, and delete the header */
1966 if (prebind_remove_load_section(outfd, newname) == -1)
1967 goto fail;
1968 if (orig_size != (off_t)-1 &&
1969 ftruncate(outfd, orig_size) == -1)
1970 goto fail;
1971
1972 prebind_writefile(outfd, info);
1973
1974 /* move new file into place */
1975 TIMESPEC_TO_TIMEVAL(&tv[0], &st->st_atimespec);
1976 TIMESPEC_TO_TIMEVAL(&tv[1], &st->st_mtimespec);
1977 if (futimes(outfd, tv) == -1)
1978 goto fail;
1979 if (fchown(outfd, st->st_uid, st->st_gid) == -1)
1980 goto fail;
1981 if (fchmod(outfd, st->st_mode) == -1)
1982 goto fail;
1983 if (fchflags(outfd, st->st_flags) == -1)
1984 goto fail;
1985 if (fstat(outfd, st) == -1) {
1986 /* XXX */
1987 goto fail;
1988 }
1989 if (rename(newname, name) == -1)
1990 goto fail;
1991
1992 close (outfd);
1993 return (0);
1994
1995 fail:
1996 free(newname);
1997 unlink(newname);
1998 close(outfd);
1999 return (-1);
2000 }
2001
2002 void
elf_fixup_prog_load(int fd,struct prebind_footer * footer,struct elf_object * object)2003 elf_fixup_prog_load(int fd, struct prebind_footer *footer,
2004 struct elf_object *object)
2005 {
2006 void *buf;
2007 Elf_Ehdr *ehdr;
2008 Elf_Phdr *phdr;
2009 Elf_Phdr phdr_empty;
2010 int loadsection;
2011
2012 buf = mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_FILE | MAP_SHARED,
2013 fd, 0);
2014 if (buf == MAP_FAILED) {
2015 printf("%s: cannot mmap for write\n", object->load_name);
2016 return;
2017 }
2018
2019 ehdr = (Elf_Ehdr *) buf;
2020 phdr = (Elf_Phdr *)((char *)buf + ehdr->e_phoff);
2021
2022 for (loadsection = 0; loadsection < ehdr->e_phnum; loadsection++) {
2023 if (phdr[loadsection].p_type == PT_LOAD)
2024 break;
2025 }
2026
2027 /* verify that extra slot is empty */
2028 bzero(&phdr_empty, sizeof(phdr_empty));
2029 if (bcmp(&phdr[ehdr->e_phnum], &phdr_empty, sizeof(phdr_empty)) != 0) {
2030 printf("extra slot not empty\n");
2031 goto done;
2032 }
2033 phdr[ehdr->e_phnum].p_type = PT_LOAD;
2034 phdr[ehdr->e_phnum].p_flags = PF_R | 0x08000000;
2035 phdr[ehdr->e_phnum].p_offset = footer->prebind_base;
2036 phdr[ehdr->e_phnum].p_vaddr = footer->prebind_base | 0x80000000;
2037 phdr[ehdr->e_phnum].p_paddr = footer->prebind_base | 0x40000000;
2038 phdr[ehdr->e_phnum].p_filesz = footer->prebind_size;
2039 phdr[ehdr->e_phnum].p_memsz = footer->prebind_size;
2040 phdr[ehdr->e_phnum].p_align = phdr[loadsection].p_align;
2041 ehdr->e_phnum++;
2042
2043 done:
2044 msync(buf, 8192, MS_SYNC);
2045 munmap(buf, 8192);
2046 }
2047
2048 void
elf_clear_prog_load(int fd,struct elf_object * object)2049 elf_clear_prog_load(int fd, struct elf_object *object)
2050 {
2051 void *buf;
2052 Elf_Ehdr *ehdr;
2053 Elf_Phdr *phdr;
2054 Elf_Phdr phdr_empty;
2055 int loadsection;
2056
2057 buf = mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_FILE | MAP_SHARED,
2058 fd, 0);
2059 if (buf == MAP_FAILED) {
2060 printf("%s: cannot mmap for write\n", object->load_name);
2061 return;
2062 }
2063
2064 ehdr = (Elf_Ehdr *) buf;
2065 phdr = (Elf_Phdr *)((char *)buf + ehdr->e_phoff);
2066
2067 if (ehdr->e_type != ET_EXEC) {
2068 goto done;
2069 }
2070
2071 loadsection = ehdr->e_phnum - 1;
2072 if ((phdr[loadsection].p_type != PT_LOAD) ||
2073 ((phdr[loadsection].p_flags & 0x08000000) == 0)) {
2074 /* doesn't look like ours */
2075 printf("mapped, %s id doesn't match %lx %d %d\n",
2076 object->load_name,
2077 (long)(phdr[loadsection].p_vaddr),
2078 phdr[loadsection].p_flags, loadsection);
2079 goto done;
2080 }
2081
2082 /* verify that extra slot is empty */
2083 bzero(&phdr[loadsection], sizeof(phdr_empty));
2084
2085 ehdr->e_phnum--;
2086
2087 done:
2088 msync(buf, 8192, MS_SYNC);
2089 munmap(buf, 8192);
2090 }
2091
2092 void
elf_add_object(struct elf_object * object,int objtype)2093 elf_add_object(struct elf_object *object, int objtype)
2094 {
2095 struct objarray_list *newarray;
2096 struct objlist *ol;
2097 ol = xmalloc(sizeof (struct objlist));
2098 ol->object = object;
2099 if (objtype != OBJTYPE_EXE)
2100 TAILQ_INSERT_TAIL(&library_list, ol, list);
2101 if (objarray_cnt+1 >= objarray_sz) {
2102 objarray_sz += 512;
2103 newarray = realloc(objarray, sizeof (objarray[0]) *
2104 objarray_sz);
2105 if (newarray != NULL)
2106 objarray = newarray;
2107 else {
2108 perror("objarray");
2109 exit(20);
2110 }
2111 }
2112 object->dyn.null = objarray_cnt; /* Major abuse, I know */
2113 TAILQ_INIT(&(objarray[objarray_cnt].inst_list));
2114 objarray[objarray_cnt].obj = object;
2115 objarray[objarray_cnt].id0 = arc4random();
2116 objarray[objarray_cnt].id1 = arc4random();
2117
2118 objarray[objarray_cnt].symcache = xcalloc(
2119 sizeof(struct symcache_noflag), object->nchains);
2120 objarray[objarray_cnt].pltsymcache = xcalloc(
2121 sizeof(struct symcache_noflag), object->nchains);
2122
2123 objarray[objarray_cnt].oprebind_data = NULL;
2124 objarray[objarray_cnt].proglist = NULL;
2125 objarray[objarray_cnt].numlibs = 0;
2126 objarray_cnt++;
2127
2128 elf_add_object_curbin_list(object);
2129 }
2130
2131 void
elf_free_curbin_list(elf_object_t * object)2132 elf_free_curbin_list(elf_object_t *object)
2133 {
2134 struct objlist *ol;
2135 int i;
2136
2137 while (!TAILQ_EMPTY(&(curbin->curbin_list))) {
2138 ol = TAILQ_FIRST(&(curbin->curbin_list));
2139 TAILQ_REMOVE(&(objarray[ol->object->dyn.null].inst_list), ol, inst_list);
2140 TAILQ_REMOVE(&(curbin->curbin_list), ol, list);
2141 free(ol);
2142 }
2143
2144 printf("trying to remove %s\n", object->load_name);
2145 for (i = objarray_cnt; i != 0;) {
2146 i--;
2147 printf("obj %s\n", objarray[i].obj->load_name);
2148 if (objarray[i].obj == object) {
2149 printf("found obj at %d max obj %d\n", i, objarray_cnt);
2150 TAILQ_FOREACH(ol, &(curbin->curbin_list), list) {
2151 }
2152 /* XXX - delete references */
2153 objarray_cnt = i;
2154 break;
2155 }
2156 }
2157 }
2158
2159 void
elf_print_objarray(void)2160 elf_print_objarray(void)
2161 {
2162 int i;
2163 struct objlist *ol;
2164
2165 printf("loaded objs # %d\n", objarray_cnt);
2166 for (i = 0; i < objarray_cnt; i++) {
2167 printf("%3d: %d obj %s\n", i, (int)objarray[i].obj->dyn.null,
2168 objarray[i].obj->load_name);
2169 TAILQ_FOREACH(ol, &(objarray[i].inst_list),
2170 inst_list) {
2171 printf("\tprog %s\n", ol->load_prog->load_name);
2172 }
2173 }
2174 }
2175
2176 void
elf_load_existing_prebind(struct elf_object * object,int fd)2177 elf_load_existing_prebind(struct elf_object *object, int fd)
2178 {
2179 struct prebind_footer footer;
2180 void *prebind_data;
2181
2182 lseek(fd, -((off_t)sizeof(struct prebind_footer)), SEEK_END);
2183 read(fd, &footer, sizeof(struct prebind_footer));
2184
2185 if (footer.bind_id[0] != BIND_ID0 ||
2186 footer.bind_id[1] != BIND_ID1 ||
2187 footer.bind_id[2] != BIND_ID2 ||
2188 footer.bind_id[3] != BIND_ID3)
2189 return;
2190
2191 prebind_data = mmap(0, footer.prebind_size, PROT_READ,
2192 MAP_FILE, fd, footer.prebind_base);
2193 objarray[object->dyn.null].oprebind_data = prebind_data;
2194 objarray[object->dyn.null].id0 = footer.id0;
2195 objarray[object->dyn.null].id1 = footer.id1;
2196
2197 copy_oldsymcache(object->dyn.null, prebind_data);
2198 }
2199
2200 void
copy_oldsymcache(int objidx,void * prebind_map)2201 copy_oldsymcache(int objidx, void *prebind_map)
2202 {
2203 struct prebind_footer *footer;
2204 struct elf_object *object;
2205 struct elf_object *tobj;
2206 struct symcache_noflag *tcache;
2207 struct symcachetab *symcache;
2208 int i, j, found, *idxtolib;
2209 char *c, *nametab;
2210 u_int32_t offset;
2211 u_int32_t *poffset;
2212 struct nameidx *nameidx;
2213
2214 object = objarray[objidx].obj;
2215
2216 poffset = (u_int32_t *)prebind_map;
2217 c = prebind_map;
2218 offset = *poffset;
2219 c += offset;
2220 footer = (void *)c;
2221
2222 nameidx = prebind_map + footer->nameidx_idx;
2223 nametab = prebind_map + footer->nametab_idx;
2224
2225 idxtolib = xcalloc(footer->numlibs, sizeof(int));
2226 found = 0;
2227 for (i = 0; i < footer->numlibs; i++) {
2228 found = 0;
2229 for (j = 0; j < objarray_cnt; j++) {
2230 if (objarray[j].id0 == nameidx[i].id0 &&
2231 objarray[j].id1 == nameidx[i].id1) {
2232 found = 1;
2233 idxtolib[i] = j;
2234 if (strcmp(objarray[j].obj->load_name,
2235 &nametab[nameidx[i].name]) != 0) {
2236 printf("warning filename mismatch"
2237 " [%s] [%s]\n",
2238 objarray[j].obj->load_name,
2239 &nametab[nameidx[i].name]);
2240 }
2241 }
2242 }
2243 if (found == 0)
2244 break;
2245 }
2246 if (found == 0)
2247 goto done;
2248
2249 /* build idxtolibs */
2250 tcache = objarray[objidx].symcache;
2251 symcache = prebind_map + footer->symcache_idx;
2252
2253 for (i = 0; i < footer->symcache_cnt; i++) {
2254 tobj = objarray[idxtolib[symcache[i].obj_idx]].obj;
2255
2256 tcache[symcache[i].idx].obj = tobj;
2257 tcache[symcache[i].idx].sym = tobj->dyn.symtab +
2258 symcache[i].sym_idx;
2259 }
2260
2261 tcache = objarray[objidx].pltsymcache;
2262 symcache = prebind_map + footer->pltsymcache_idx;
2263 for (i = 0; i < footer->pltsymcache_cnt; i++) {
2264 tobj = objarray[idxtolib[symcache[i].obj_idx]].obj;
2265
2266 tcache[symcache[i].idx].obj = tobj;
2267 tcache[symcache[i].idx].sym = tobj->dyn.symtab +
2268 symcache[i].sym_idx;
2269 }
2270 done:
2271 free(idxtolib);
2272 /* munmap(prebind_map, size);*/
2273 }
2274