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