+++ /dev/null
-/* $OpenBSD: prebind.c,v 1.34 2016/05/11 21:52:49 deraadt Exp $ */
-/*
- * Copyright (c) 2006 Dale Rahn <drahn@dalerahn.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <limits.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <nlist.h>
-#include <elf_abi.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <err.h>
-#include "resolve.h"
-#include "link.h"
-#include "path.h"
-#include "sod.h"
-#ifndef __mips64__
-#include "machine/reloc.h"
-#endif
-#include "prebind.h"
-#include "ld.h"
-
-/* seems to make sense to limit how big of file can be dealt with */
-#define MAX_FILE_SIZE (512 * 1024 * 1024)
-
-char *shstrtab;
-
-/* alpha uses RELOC_JMP_SLOT */
-#ifdef __amd64__
-#define RELOC_JMP_SLOT R_X86_64_JUMP_SLOT
-#endif
-#ifdef __arm__
-#define RELOC_JMP_SLOT R_ARM_JUMP_SLOT
-#endif
-#ifdef __hppa__
-#define RELOC_JMP_SLOT RELOC_IPLT
-#endif
-#ifdef __i386__
-#define RELOC_JMP_SLOT RELOC_JUMP_SLOT
-#endif
-#ifdef __sh__
-#define RELOC_JMP_SLOT R_SH_JMP_SLOT
-#endif
-#ifdef __mips64__
-#define RELOC_JMP_SLOT 0 /* XXX mips64 doesnt have PLT reloc */
-#endif
-#ifdef __m88k__
-#define RELOC_JMP_SLOT RELOC_GOTP_ENT
-#endif
-#ifdef __vax__
-#define RELOC_JMP_SLOT R_VAX_JMP_SLOT
-#endif
-/* powerpc uses RELOC_JMP_SLOT */
-/* sparc uses RELOC_JMP_SLOT */
-/* sparc64 uses RELOC_JMP_SLOT */
-
-#define BUFSZ (256 * 1024)
-
-#include "prebind_struct.h"
-struct proglist *curbin;
-
-obj_list_ty library_list =
- TAILQ_HEAD_INITIALIZER(library_list);
-
-prog_list_ty prog_list =
- TAILQ_HEAD_INITIALIZER(prog_list);
-
-struct objarray_list {
- struct elf_object *obj;
- struct symcache_noflag *symcache;
- struct symcache_noflag *pltsymcache;
- struct proglist *proglist;
- u_int32_t id0;
- u_int32_t id1;
- u_int32_t *idxtolib;
- void *oprebind_data;
- int numlibs;
-
- TAILQ_HEAD(, objlist) inst_list;
-} *objarray;
-
-
-struct prebind_info {
- struct elf_object *object;
- struct prebind_footer *footer;
- u_int32_t footer_offset;
- u_int32_t nfixup;
- struct nameidx *nameidx;
- struct symcachetab *symcache;
- struct symcachetab *pltsymcache;
- u_int32_t *fixuptab;
- u_int32_t *fixupcnt;
- struct fixup **fixup;
- u_int32_t *maptab;
- u_int32_t **libmap;
- u_int32_t *libmapcnt;
- char *nametab;
- u_int32_t nametablen;
-};
-
-int objarray_cnt;
-int objarray_sz;
-
-void copy_oldsymcache(int objidx, char *prebind_data);
-void elf_load_existing_prebind(struct elf_object *object, int fd);
-void insert_sym_objcache(struct elf_object *, int,
- const struct elf_object *, const Elf_Sym *, int);
-
-struct elf_object * elf_load_object(void *pexe, const char *name);
-void elf_free_object(struct elf_object *object);
-void map_to_virt(Elf_Phdr *, Elf_Ehdr *, Elf_Addr, u_long *);
-int load_obj_needed(struct elf_object *object);
-int load_lib(const char *name, struct elf_object *parent);
-elf_object_t * elf_load_shlib_hint(struct sod *sod, struct sod *req_sod,
- int use_hints, const char *libpath);
-char *elf_find_shlib(struct sod *sodp, const char *searchpath,
- int nohints);
-elf_object_t * elf_tryload_shlib(const char *libname);
-int elf_match_file(struct sod *sodp, char *name, int namelen);
-void elf_init_objarray(void);
-void elf_add_object(struct elf_object *object, int objtype);
-void elf_print_objarray(void);
-void elf_reloc(struct elf_object *object);
-
-struct elf_object * elf_lookup_object(const char *name);
-struct elf_object * elf_lookup_object_devino(dev_t dev, ino_t inode,
- int objtype);
-void elf_free_curbin_list(struct elf_object *obj);
-void elf_resolve_curbin(void);
-struct proglist *elf_newbin(void);
-void elf_sum_reloc(void);
-int elf_prep_lib_prebind(struct elf_object *object);
-int elf_prep_bin_prebind(struct proglist *pl);
-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);
-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);
-
-void elf_dump_footer(struct prebind_footer *footer);
-
-void elf_fixup_prog_load(int fd, struct prebind_footer *footer,
- struct elf_object *object);
-void elf_clear_prog_load(int fd, struct elf_object *object);
-
-void elf_find_symbol_rel(const char *s, struct elf_object *object,
- Elf_Rel *rel, struct symcache_noflag *symcache,
- struct symcache_noflag *pltsymcache);
-
-void elf_find_symbol_rela(const char *s, struct elf_object *object,
- Elf_RelA *rela, struct symcache_noflag *symcache,
- struct symcache_noflag *pltsymcache);
-
-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);
-
-int prebind_writefile(int fd, struct prebind_info *info);
-int prebind_writenewfile(int infd, char *name, struct stat *st, off_t orig_size,
- struct prebind_info *info);
-
-struct elf_object *load_object;
-
-struct elf_object *load_file(const char *filename, int lib);
-int elf_check_note(void *buf, Elf_Phdr *phdr);
-void load_file_or_dir(char *name);
-void load_dir(char *name);
-void load_exe(char *name);
-
-int
-prebind(char **argv)
-{
- int i;
-
- elf_init_objarray();
-
- for (i = 0; argv[i]; i++)
- load_file_or_dir(argv[i]);
-
- if (verbose > 4) {
- elf_print_objarray();
- elf_print_prog_list(&prog_list);
- }
- elf_sum_reloc();
-
- return (0);
-}
-
-/*
- * load ELF objects at the specified path it could be
- * either a either a directory or file, if the object is
- * a file, attempt to load it as an executable (will ignore shared objects
- * and any files that are not Elf execuables.
- * if the object is a directory pass it to a routine to deal with
- * directory parsing.
- */
-void
-load_file_or_dir(char *name)
-{
- struct stat sb;
- int ret;
-
- ret = lstat(name, &sb);
- if (ret != 0)
- return;
- switch (sb.st_mode & S_IFMT) {
- case S_IFREG:
- load_exe(name);
- break;
- case S_IFDIR:
- if (verbose > 0)
- printf("loading dir %s\n", name);
- load_dir(name);
- break;
- default:
- ; /* links and other files we skip */
- }
-
-}
-
-/*
- * for all of the objects in the directory, if it is a regular file
- * load it as a binary, if it is unknown (nfs mount) stat the file
- * and load the file for S_IFREG
- * any other type of directory object: symlink, directory, socket, ...
- * is ignored.
- */
-void
-load_dir(char *name)
-{
- struct dirent *dp;
- struct stat sb;
- DIR *dirp;
- char *buf;
-
- dirp = opendir(name);
-
- /* if dir failed to open, skip */
- if (dirp == NULL)
- return;
-
- while ((dp = readdir(dirp)) != NULL) {
- switch (dp->d_type) {
- case DT_UNKNOWN:
- /*
- * NFS will return unknown, since load_file
- * does stat the file, this just
- */
- if (asprintf(&buf, "%s/%s", name, dp->d_name) == -1) {
- warn("asprintf");
- goto done;
- }
- lstat(buf, &sb);
- if (sb.st_mode == S_IFREG)
- load_exe(buf);
- free(buf);
- break;
- case DT_REG:
- if (asprintf(&buf, "%s/%s", name, dp->d_name) == -1) {
- warn("asprintf");
- goto done;
- }
- load_exe(buf);
- free(buf);
- break;
- default:
- /* other files symlinks, dirs, ... we ignore */
- ;
- }
- }
-done:
- closedir(dirp);
-}
-
-/*
- * the given pathname is a regular file, however it may or may not
- * be an ELF file. Attempt to load the given path and calculate prebind
- * data for it.
- * if the given file is not a ELF binary this will 'fail' and
- * should not change any of the prebind state.
- */
-void
-load_exe(char *name)
-{
- struct elf_object *object;
- struct elf_object *interp;
- struct objlist *ol;
- int fail = 0;
-
- curbin = elf_newbin();
- if (verbose > 0)
- printf("processing %s\n", name);
- object = load_file(name, OBJTYPE_EXE);
- if (object != NULL && load_object != NULL &&
- object->load_object == NULL) {
- TAILQ_FOREACH(ol, &(curbin->curbin_list), list) {
- fail = load_obj_needed(ol->object);
- if (fail != 0)
- break; /* XXX */
-
- }
- if (fail == 0) {
- interp = load_file(curbin->interp, OBJTYPE_DLO);
- object->load_object = interp;
- if (interp == NULL)
- fail = 1;
- }
-
- /* slight abuse of this field */
-
- if (fail == 0) {
- objarray[object->dyn.null].proglist = curbin;
- elf_resolve_curbin();
- TAILQ_INSERT_TAIL(&prog_list, curbin, list);
- } else {
- printf("failed to load %s\n", name);
- elf_free_curbin_list(object);
- free(curbin);
- }
- if (load_object != NULL) {
- load_object = NULL;
- }
- } else {
- free(curbin);
- }
-}
-
-/*
- * given a path to a file, attempt to open it and load any data necessary
- * for prebind. this function is used for executables, libraries and ld.so
- * file, it will do a lookup on the dev/inode to use a cached version
- * of the file if it was already loaded, in case a library is referenced
- * by more than one program or there are hardlinks between executable names.
- * if the file is not an elf file of the appropriate type, it will return
- * failure.
- */
-struct elf_object *
-load_file(const char *filename, int objtype)
-{
- struct elf_object *obj = NULL;
- int fd = -1, i, note_found;
- struct stat ifstat;
- void *buf = NULL;
- Elf_Ehdr *ehdr;
- Elf_Shdr *shdr;
- Elf_Phdr *phdr;
- char *pexe;
-
- fd = open(filename, O_RDONLY);
- if (fd == -1) {
- perror(filename);
- goto done;
- }
-
- if (fstat(fd, &ifstat) == -1) {
- perror(filename);
- goto done;
- }
-
- if ((ifstat.st_mode & S_IFMT) != S_IFREG)
- goto done;
-
- if (ifstat.st_size < sizeof (Elf_Ehdr))
- goto done;
-
- obj = elf_lookup_object_devino(ifstat.st_dev, ifstat.st_ino, objtype);
- if (obj != NULL)
- goto done;
-
- buf = mmap(NULL, ifstat.st_size, PROT_READ, MAP_FILE | MAP_SHARED,
- fd, 0);
- if (buf == MAP_FAILED) {
- printf("%s: cannot mmap\n", filename);
- goto done;
- }
-
- ehdr = (Elf_Ehdr *)buf;
-
- if (IS_ELF(*ehdr) == 0)
- goto done;
-
- if (ehdr->e_machine != ELF_TARG_MACH) {
- if (verbose > 0)
- printf("%s: wrong arch\n", filename);
- goto done;
- }
-
- if (objtype == OBJTYPE_EXE) {
- if (ehdr->e_type != ET_EXEC)
- goto done;
-
- note_found = 0;
-
- phdr = (Elf_Phdr *)((char *)buf + ehdr->e_phoff);
- for (i = 0; i < ehdr->e_phnum; i++) {
- if (phdr[i].p_type == PT_NOTE) {
- note_found = elf_check_note(buf,&phdr[i]);
- break;
- }
- }
- if (note_found == 0)
- goto done; /* no OpenBSD note found */
- }
-
- if ((objtype == OBJTYPE_LIB || objtype == OBJTYPE_DLO) &&
- (ehdr->e_type != ET_DYN))
- goto done;
-
- pexe = buf;
- if (ehdr->e_shstrndx == 0)
- goto done;
-
- shdr = (Elf_Shdr *)(pexe + ehdr->e_shoff +
- (ehdr->e_shstrndx * ehdr->e_shentsize));
-
- shstrtab = (char *)(pexe + shdr->sh_offset);
-
- obj = elf_load_object(pexe, filename);
-
- munmap(buf, ifstat.st_size);
- buf = NULL;
-
- if (obj != NULL) {
- obj->obj_type = objtype;
-
- obj->dev = ifstat.st_dev;
- obj->inode = ifstat.st_ino;
- if (load_object == NULL)
- load_object = obj;
-
- elf_add_object(obj, objtype);
-
-#ifdef DEBUG1
- dump_info(obj);
-#endif
- }
- if ((objtype == OBJTYPE_LIB || objtype == OBJTYPE_DLO) &&
- merge == 1) {
- /*
- * for libraries and dynamic linker, check if old prebind
- * info exists and load it if we are in merge mode
- */
- elf_load_existing_prebind(obj, fd);
- }
-done:
- if (buf != NULL)
- munmap(buf, ifstat.st_size);
- if (fd != -1)
- close(fd);
- return obj;
-}
-
-/*
- * check if the given executable header on a ELF executable
- * has the proper OpenBSD note on the file if it is not present
- * binaries will be skipped.
- */
-int
-elf_check_note(void *buf, Elf_Phdr *phdr)
-{
- u_long address;
- u_int *pint;
- char *osname;
-
- address = phdr->p_offset;
- pint = (u_int *)((char *)buf + address);
- osname = (char *)buf + address + sizeof(*pint) * 3;
-
- if (pint[0] == 8 /* OpenBSD\0 */ &&
- pint[1] == 4 /* ??? */ &&
- pint[2] == 1 /* type_osversion */ &&
- strcmp("OpenBSD", osname) == 0)
- return 1;
-
- return 0;
-}
-
-struct elf_object *
-elf_load_object(void *pexe, const char *name)
-{
- struct elf_object *object;
- Elf_Dyn *dynp = NULL, *odynp;
- Elf_Ehdr *ehdr;
- Elf_Phdr *phdr;
- Elf_Addr lbase;
- Elf_Word *needed_list;
- int needed_cnt = 0, i;
-
- object = calloc(1, sizeof (struct elf_object));
- if (object == NULL) {
- printf("unable to allocate object for %s\n", name);
- exit(10);
- }
- ehdr = pexe;
- lbase = (Elf_Addr)pexe;
-
- object->load_base = lbase;
- object->load_name = strdup(name);
- if (object->load_name == NULL) {
- printf("unable to allocate object for %s\n", name);
- exit(10);
- }
-
- phdr = (Elf_Phdr *)((char *)pexe + ehdr->e_phoff);
- for (i = 0; i < ehdr->e_phnum; i++) {
- switch (phdr[i].p_type) {
- case PT_DYNAMIC:
- dynp = (Elf_Dyn *)(phdr[i].p_offset);
- break;
- case PT_INTERP:
- /* XXX can only occur in programs */
- curbin->interp = strdup((char *)((char *)pexe +
- phdr[i].p_offset));
- if (curbin->interp == NULL) {
- printf("unable to allocate object for %s\n",
- name);
- exit(10);
- }
- break;
- default:
- break;
- }
- }
-
- if (dynp == 0) {
- free(object);
- return NULL; /* not a dynamic binary */
- }
-
- dynp = (Elf_Dyn *)((unsigned long)dynp + lbase);
- odynp = dynp;
- while (dynp->d_tag != DT_NULL) {
- if (dynp->d_tag < DT_NUM)
- object->Dyn.info[dynp->d_tag] = dynp->d_un.d_val;
- else if (dynp->d_tag >= DT_LOPROC &&
- dynp->d_tag < DT_LOPROC + DT_PROCNUM)
- object->Dyn.info[dynp->d_tag + DT_NUM - DT_LOPROC] =
- dynp->d_un.d_val;
- if (dynp->d_tag == DT_TEXTREL)
- object->dyn.textrel = 1;
- if (dynp->d_tag == DT_SYMBOLIC)
- object->dyn.symbolic = 1;
- if (dynp->d_tag == DT_BIND_NOW)
- object->obj_flags |= DF_1_NOW;
- if (dynp->d_tag == DT_FLAGS_1)
- object->obj_flags |= dynp->d_un.d_val;
- if (dynp->d_tag == DT_NEEDED)
- needed_cnt++;
-
- dynp++;
- }
-
- needed_list = calloc((needed_cnt + 1), sizeof(Elf_Word));
- if (needed_list == NULL) {
- printf("unable to allocate needed_list for %s\n", name);
- exit(10);
- }
- needed_list[needed_cnt] = 0;
- for (dynp = odynp, i = 0; dynp->d_tag != DT_NULL; dynp++) {
- if (dynp->d_tag == DT_NEEDED) {
- needed_list[i] = dynp->d_un.d_val;
- i++;
- }
- }
-
- if (object->Dyn.info[DT_HASH])
- map_to_virt(phdr, ehdr, lbase, &object->Dyn.info[DT_HASH]);
- if (object->Dyn.info[DT_STRTAB])
- map_to_virt(phdr, ehdr, lbase, &object->Dyn.info[DT_STRTAB]);
- if (object->Dyn.info[DT_SYMTAB])
- map_to_virt(phdr, ehdr, lbase, &object->Dyn.info[DT_SYMTAB]);
-
- if (object->Dyn.info[DT_RELA])
- map_to_virt(phdr, ehdr, lbase, &object->Dyn.info[DT_RELA]);
- if (object->Dyn.info[DT_RPATH])
- object->Dyn.info[DT_RPATH] += object->Dyn.info[DT_STRTAB];
- if (object->Dyn.info[DT_REL])
- map_to_virt(phdr, ehdr, lbase, &object->Dyn.info[DT_REL]);
- if (object->Dyn.info[DT_JMPREL])
- map_to_virt(phdr, ehdr, lbase, &object->Dyn.info[DT_JMPREL]);
-
- {
- Elf_Sym *sym;
- char *str;
- Elf_Rel *rel;
- Elf_RelA *rela;
- Elf_Addr *hash;
- Elf_Word *hashtab;
- void *plt;
- size_t hashsz;
-
- if (object->Dyn.info[DT_HASH] != 0) {
- hash = object->dyn.hash;
- hashtab = (void *)hash;
- object->nbuckets = hashtab[0];
- object->nchains = hashtab[1];
- hash = reallocarray(NULL, 2 + object->nbuckets
- + object->nchains, sizeof(Elf_Word));
- if (hash == NULL) {
- printf("unable to allocate hash for %s\n",
- name);
- exit(10);
- }
- hashsz = (2 + object->nbuckets + object->nchains) *
- sizeof(Elf_Word);
-
- bcopy(object->dyn.hash, hash, hashsz);
- object->dyn.hash = hash;
- object->buckets = ((Elf_Word *)hash + 2);
- object->chains = object->buckets + object->nbuckets;
- }
-
- str = malloc(object->dyn.strsz);
- if (str == NULL) {
- printf("unable to allocate strtab for %s\n",
- name);
- exit(10);
- }
- bcopy(object->dyn.strtab, str, object->dyn.strsz);
- object->dyn.strtab = str;
-
- sym = calloc(object->nchains, sizeof(Elf_Sym));
- if (sym == NULL) {
- printf("unable to allocate symtab for %s\n",
- name);
- exit(10);
- }
- bcopy(object->dyn.symtab, sym,
- object->nchains * sizeof(Elf_Sym));
- object->dyn.symtab = sym;
-
- if (object->dyn.relsz != 0) {
- rel = malloc(object->dyn.relsz);
- if (rel == NULL) {
- printf("unable to allocate rel reloc for %s\n",
- name);
- exit(10);
- }
- bcopy(object->dyn.rel, rel, object->dyn.relsz);
- object->dyn.rel = rel;
- } else {
- object->dyn.rel = NULL;
- }
- if (object->dyn.relasz != 0) {
- rela = malloc(object->dyn.relasz);
- if (rela == NULL) {
- printf("unable to allocate rela reloc for %s\n",
- name);
- exit(10);
- }
- bcopy(object->dyn.rela, rela, object->dyn.relasz);
- object->dyn.rela = rela;
- } else {
- object->dyn.rela = NULL;
- }
- if (object->dyn.pltrelsz != 0) {
- plt = malloc(object->dyn.pltrelsz);
- if (plt == NULL) {
- printf("unable to allocate plt reloc for %s\n",
- name);
- exit(10);
- }
- bcopy((void*)object->dyn.jmprel, plt,
- object->dyn.pltrelsz);
- object->dyn.jmprel = (long)plt;
- } else {
- object->dyn.jmprel = 0;
- }
- if (object->dyn.rpath != NULL){
- object->rpath = _dl_split_path(object->dyn.rpath);
- if (object->rpath == NULL) {
- printf("unable to allocate rpath for %s\n",
- name);
- exit(10);
- }
- }
- object->dyn.needed = (Elf_Addr)needed_list;
- }
-
-#ifdef DEBUG1
- dump_info(object);
-#endif
- return object;
-}
-
-/*
- * Free any extra pieces associated with 'object'
- */
-void
-elf_free_object(struct elf_object *object)
-{
- free(object->load_name);
- free(object->dyn.hash);
- free((void *)object->dyn.strtab);
- free((void *)object->dyn.symtab);
- free(object->dyn.rel);
- free(object->dyn.rela);
- if (object->dyn.rpath != NULL)
- free((void *)object->dyn.rpath);
- free(object);
-}
-
-/*
- * translate an object address into a file offset for the
- * file assuming that the file is mapped at base.
- */
-void
-map_to_virt(Elf_Phdr *phdr, Elf_Ehdr *ehdr, Elf_Addr base, u_long *vaddr)
-{
- int i;
-
- for (i = 0; i < ehdr->e_phnum; i++) {
- switch (phdr[i].p_type) {
- case PT_LOAD:
- if (phdr[i].p_vaddr > *vaddr)
- continue;
- if (phdr[i].p_vaddr + phdr[i].p_memsz < *vaddr)
- continue;
-#ifdef DEBUG1
- printf("input address %lx translated to ", *vaddr);
-#endif
- *vaddr += phdr[i].p_offset - phdr[i].p_vaddr + base;
-#ifdef DEBUG1
- printf("%lx, base %lx %lx %llx\n", *vaddr, base,
- phdr[i].p_vaddr, phdr[i].p_offset );
-#endif
- break;
- default:
- break;
- }
- }
-}
-
-/*
- * given a dynamic elf object (executable or binary)
- * load any DT_NEEDED entries which were found when
- * the object was initially loaded.
- */
-int
-load_obj_needed(struct elf_object *object)
-{
- int i;
- Elf_Word *needed_list;
- int err;
-
- needed_list = (Elf_Word *)object->dyn.needed;
- for (i = 0; needed_list[i] != 0; i++) {
- if (verbose > 1)
- printf("lib: %s\n", needed_list[i] +
- object->dyn.strtab);
- err = load_lib(needed_list[i] + object->dyn.strtab, object);
- if (err) {
- printf("failed to load lib %s\n",
- needed_list[i] + object->dyn.strtab);
- return 1;
- }
- }
- return 0;
-}
-
-/*
- * allocate a proglist entry for a new binary
- * so that it is available for libraries to reference
- */
-struct proglist *
-elf_newbin(void)
-{
- struct proglist *proglist;
- proglist = malloc(sizeof (struct proglist));
- if (proglist == NULL) {
- printf("unable to allocate proglist\n");
- exit(10);
- }
- proglist->fixup = NULL;
- TAILQ_INIT(&(proglist->curbin_list));
- return proglist;
-}
-
-/*
- * Copy the contents of a libraries symbol cache instance into
- * the 'global' symbol cache for that library
- * this will currently resolve conflicts between mismatched
- * libraries by flagging any mismatches as invalid
- * which will cause all programs to generate a fixup
- * It probably would be interesting to modify this to keep the most
- * common entry as a library cache, and only have a fixup in programs
- * where the symbol is overridden.
- * This is run once each for the (got)symcache and pltsymcache
- */
-
-struct elf_object badobj_store;
-struct elf_object *badobj = &badobj_store;
-
-/*
- * copy the symbols found in a library symcache to the 'master/common'
- * symbol table note that this will skip copying the following references
- * 1. non-existing entries
- * 2. symobj == prog &&& obj != prog
- * 3. symobj == prog's interpter (references to dl_open)
- */
-void
-elf_copy_syms(struct symcache_noflag *tcache, struct symcache_noflag *scache,
- struct elf_object *obj, struct elf_object *prog, int nsyms)
-{
- int i;
- int lib_prog_ref;
- for (i = 0; i < nsyms; i++) {
- if (scache[i].obj == NULL)
- continue;
-
- if (tcache[i].obj != NULL) {
- lib_prog_ref = (obj != prog && scache[i].obj == prog);
- if (scache[i].obj != tcache[i].obj || lib_prog_ref) {
- if (verbose > 2) {
- printf("sym mismatch %d: "
- "obj %d: sym %ld %s "
- "nobj %s\n",
- i, (int)scache[i].obj->dyn.null,
- scache[i].sym -
- scache[i].obj->dyn.symtab,
- scache[i].sym->st_name +
- scache[i].obj->dyn.strtab,
- scache[i].obj->load_name);
- }
-
- /*
- * if one of the symbol entries
- * happens to be a self reference
- * go ahead and keep that reference
- * prevents some instances of fixups
- * for every binary, eg one program
- * overriding malloc() will not make
- * ever binary have a fixup for libc
- * references to malloc()
- */
- if (scache[i].obj == obj) {
- tcache[i].obj = scache[i].obj;
- tcache[i].sym = scache[i].sym;
- } else if (tcache[i].obj == obj) {
- /* no change necessary */
- } else {
- tcache[i].obj = badobj;
- tcache[i].sym = NULL;
- }
- }
- } else {
- if (scache[i].obj != prog) {
- tcache[i].obj = scache[i].obj;
- tcache[i].sym = scache[i].sym;
- }
- }
- }
-}
-
-void
-insert_sym_objcache(struct elf_object *obj, int idx,
- const struct elf_object *ref_obj, const Elf_Sym *ref_sym, int flags)
-{
- struct symcache_noflag *tcache;
- struct elf_object *prog;
-
- prog = TAILQ_FIRST(&(curbin->curbin_list))->object;
-
- if (flags)
- tcache = objarray[obj->dyn.null].pltsymcache;
- else
- tcache = objarray[obj->dyn.null].symcache;
-
- if (tcache[idx].obj != NULL) {
- if (ref_obj != tcache[idx].obj ||
- (obj != prog && ref_obj == prog)) {
- if (verbose > 2) {
- printf("sym mismatch %d: "
- "obj %d: sym %ld %s "
- "nobj %s\n",
- idx, (int)ref_obj->dyn.null,
- ref_sym -
- ref_obj->dyn.symtab,
- ref_sym->st_name +
- ref_obj->dyn.strtab,
- ref_obj->load_name);
- }
-
- /*
- * if one of the symbol entries
- * happens to be a self reference
- * go ahead and keep that reference
- * prevents some instances of fixups
- * for every binary, eg one program
- * overriding malloc() will not make
- * ever binary have a fixup for libc
- * references to malloc()
- */
- if (ref_obj == obj) {
- tcache[idx].obj = ref_obj;
- tcache[idx].sym = ref_sym;
- add_fixup_oldprog(prog, obj, idx, ref_obj,
- ref_sym, flags);
- } else if (tcache[idx].obj == obj) {
- /* no change necessary */
- add_fixup_prog(prog, obj, idx, ref_obj,
- ref_sym, flags);
- } else {
- add_fixup_oldprog(prog, obj, idx,
- tcache[idx].obj, tcache[idx].sym, flags);
- tcache[idx].obj = badobj;
- tcache[idx].sym = NULL;
- add_fixup_prog(prog, obj, idx, ref_obj,
- ref_sym, flags);
- }
- }
- } else {
- if (ref_obj != prog) {
- tcache[idx].obj = ref_obj;
- tcache[idx].sym = ref_sym;
- } else {
- add_fixup_prog(prog, obj, idx, ref_obj,
- ref_sym, flags);
- }
- }
-}
-
-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)
-{
- struct proglist *pl;
- int i, libidx, cnt;
-
- pl = objarray[prog->dyn.null].proglist;
-
- libidx = -1;
- for (i = 0; i < pl->nobj; i++) {
- if (pl->libmap[0][i] == obj->dyn.null) {
- libidx = (i * 2) + ((flag & SYM_PLT) ? 1 : 0);
- break;
- }
- }
- if (libidx == -1) {
- printf("unable to find object\n");
- return;
- }
-
- /* have to check for duplicate patches */
- for (i = 0; i < pl->fixupcnt[libidx]; i++) {
- if (pl->fixup[libidx][i].sym == idx)
- return;
- }
-
- if (verbose > 1)
- printf("fixup for obj %s on prog %s sym %s: %d\n",
- obj->load_name, prog->load_name,
- ref_obj->dyn.strtab + ref_sym->st_name,
- pl->fixupcnt[libidx]);
-
- if (pl->fixupcntalloc[libidx] < pl->fixupcnt[libidx] + 1) {
- pl->fixupcntalloc[libidx] += 16;
- pl->fixup[libidx] = reallocarray(pl->fixup[libidx],
- pl->fixupcntalloc[libidx], sizeof(struct fixup));
- if (pl->fixup[libidx] == NULL) {
- printf("realloc fixup, out of memory\n");
- exit(20);
- }
- }
- cnt = pl->fixupcnt[libidx];
- pl->fixup[libidx][cnt].sym = idx;
- pl->fixup[libidx][cnt].obj_idx = ref_obj->dyn.null;
- pl->fixup[libidx][cnt].sym_idx = ref_sym - ref_obj->dyn.symtab;
- pl->fixupcnt[libidx]++;
-}
-
-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)
-{
- struct objlist *ol;
-
- TAILQ_FOREACH(ol, &(objarray[obj->dyn.null].inst_list), inst_list) {
- if (ol->load_prog == prog) {
- continue;
- }
- /* process here */
-
- add_fixup_prog(ol->load_prog, obj, idx, ref_obj, ref_sym, flag);
- }
-
-}
-
-struct elf_object *
-elf_lookup_object(const char *name)
-{
- struct objlist *ol;
- TAILQ_FOREACH(ol, &(curbin->curbin_list), list) {
- if (strcmp (name, ol->object->load_name) == 0) {
- return ol->object;
- }
- }
- TAILQ_FOREACH(ol, &library_list, list) {
- if (strcmp (name, ol->object->load_name) == 0) {
- elf_add_object_curbin_list(ol->object);
- return ol->object;
- }
- }
- return NULL;
-}
-
-struct elf_object *
-elf_lookup_object_devino(dev_t dev, ino_t inode, int objtype)
-{
- struct objlist *ol;
- TAILQ_FOREACH(ol, &(curbin->curbin_list), list) {
- if (ol->object->dev == dev &&
- ol->object->inode == inode) {
- if (ol->object->obj_type != objtype)
- return NULL;
- return ol->object;
- }
- }
- TAILQ_FOREACH(ol, &library_list, list) {
- if (ol->object->dev == dev &&
- ol->object->inode == inode) {
- if (ol->object->obj_type != objtype)
- return NULL;
- if (objtype != OBJTYPE_EXE)
- elf_add_object_curbin_list(ol->object);
- return ol->object;
- }
- }
- return NULL;
-}
-
-void
-elf_find_symbol_rel(const char *name, struct elf_object *object,
- Elf_Rel *rel, struct symcache_noflag *symcache,
- struct symcache_noflag *pltsymcache)
-{
- struct objlist *ol;
- unsigned long h = 0;
- const char *p = name;
- const Elf_Sym *sym, *ref_sym = NULL;
- const Elf_Sym *weak_sym = NULL;
- struct elf_object *weak_obj = NULL;
- int flags = 0;
- int found = 0;
- int type, idx;
- struct elf_object *ref_object = NULL;
-
- sym = object->dyn.symtab + ELF_R_SYM(rel->r_info);
-
- while (*p) {
- unsigned long g;
- h = (h << 4) + *p++;
- if ((g = h & 0xf0000000))
- h ^= g >> 24;
- h &= ~g;
- }
-
- type = ELF_R_TYPE(rel->r_info);
- flags = SYM_SEARCH_ALL|SYM_WARNNOTFOUND;
- if (type == RELOC_JMP_SLOT)
- flags |= SYM_PLT;
-
- TAILQ_FOREACH(ol, &(curbin->curbin_list), list) {
- found = elf_find_symbol_obj(ol->object, name, h, flags, &sym,
- &weak_sym, &weak_obj);
- if (found) {
- ref_object = ol->object;
- break;
- }
-
- }
- if (found) {
- ref_object = ol->object;
- ref_sym = sym;
- } else if (weak_obj != NULL) {
- found = 1;
- ref_object = weak_obj;
- ref_sym = weak_sym;
- }
- if (found == 1) {
- idx = ELF_R_SYM(rel->r_info);
- if (flags & SYM_PLT) {
- pltsymcache[idx].obj = ref_object;
- pltsymcache[idx].sym = ref_sym;
- } else {
- symcache[idx].obj = ref_object;
- symcache[idx].sym = ref_sym;
- }
- } else {
- /* It is not an error to have an undefined weak symbol */
- const Elf_Sym *sym;
- sym = object->dyn.symtab + ELF_R_SYM(rel->r_info);
- if (ELF_ST_BIND(sym->st_info) != STB_WEAK) {
- printf("symbol not found %s\n", name);
- }
- }
-}
-
-void
-elf_find_symbol_rela(const char *name, struct elf_object *object,
- Elf_RelA *rela, struct symcache_noflag *symcache,
- struct symcache_noflag *pltsymcache)
-{
- struct objlist *ol;
- unsigned long h = 0;
- const char *p = name;
- const Elf_Sym *sym, *ref_sym = NULL;
- const Elf_Sym *weak_sym = NULL;
- struct elf_object *weak_obj = NULL;
- int flags = 0;
- int found = 0;
- int type, idx;
- struct elf_object *ref_object = NULL;
-
- sym = object->dyn.symtab + ELF_R_SYM(rela->r_info);
-
- while (*p) {
- unsigned long g;
- h = (h << 4) + *p++;
- if ((g = h & 0xf0000000))
- h ^= g >> 24;
- h &= ~g;
- }
-
- type = ELF_R_TYPE(rela->r_info);
- flags = SYM_SEARCH_ALL|SYM_WARNNOTFOUND;
- if (type == RELOC_JMP_SLOT)
- flags |= SYM_PLT;
-
- TAILQ_FOREACH(ol, &(curbin->curbin_list), list) {
-
-// printf("searching sym [%s] typ %d in obj %s\n", name, type, ol->object->load_name);
- found = elf_find_symbol_obj(ol->object, name, h, flags, &sym,
- &weak_sym, &weak_obj);
- if (found) {
- ref_object = ol->object;
- break;
- }
-
- }
- if (found) {
- ref_object = ol->object;
- ref_sym = sym;
- } else if (weak_obj != NULL) {
- found = 1;
- ref_object = weak_obj;
- ref_sym = weak_sym;
- }
- if (found == 1) {
- idx = ELF_R_SYM(rela->r_info);
- if (flags & SYM_PLT) {
- pltsymcache[idx].obj = ref_object;
- pltsymcache[idx].sym = ref_sym;
- } else {
- symcache[idx].obj = ref_object;
- symcache[idx].sym = ref_sym;
- }
- } else {
- /* It is not an error to have an undefined weak symbol */
- const Elf_Sym *sym;
- sym = object->dyn.symtab + ELF_R_SYM(rela->r_info);
- if (ELF_ST_BIND(sym->st_info) != STB_WEAK) {
- printf("symbol not found %s\n", name);
- }
- }
-}
-
-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)
-{
- const Elf_Sym *symt = object->dyn.symtab;
- const char *strt = object->dyn.strtab;
- long si;
- const char *symn;
-
- for (si = object->buckets[hash % object->nbuckets];
- si != STN_UNDEF; si = object->chains[si]) {
- const Elf_Sym *sym = symt + si;
-
- if (sym->st_value == 0)
- continue;
-
- if (ELF_ST_TYPE(sym->st_info) != STT_NOTYPE &&
- ELF_ST_TYPE(sym->st_info) != STT_OBJECT &&
- ELF_ST_TYPE(sym->st_info) != STT_FUNC)
- continue;
-
- symn = strt + sym->st_name;
- if (sym != *this && strcmp(symn, name))
- continue;
-
- /* allow this symbol if we are referring to a function
- * which has a value, even if section is UNDEF.
- * this allows &func to refer to PLT as per the
- * ELF spec. st_value is checked above.
- * if flags has SYM_PLT set, we must have actual
- * symbol, so this symbol is skipped.
- */
- if (sym->st_shndx == SHN_UNDEF) {
- if ((flags & SYM_PLT) || sym->st_value == 0 ||
- ELF_ST_TYPE(sym->st_info) != STT_FUNC)
- continue;
- }
-
- if (ELF_ST_BIND(sym->st_info) == STB_GLOBAL) {
- *this = sym;
- return 1;
- } else if (ELF_ST_BIND(sym->st_info) == STB_WEAK) {
- if (!*weak_sym) {
- *weak_sym = sym;
- *weak_object = object;
- }
- }
- }
- return 0;
-}
-
-void
-elf_reloc(struct elf_object *object)
-{
- const Elf_Sym *sym;
- Elf_Rel *rel;
- Elf_RelA *rela;
- int numrel;
- int numrela;
- int i;
- struct symcache_noflag *symcache;
- struct symcache_noflag *pltsymcache;
-
- numrel = object->dyn.relsz / sizeof(Elf_Rel);
-#ifdef DEBUG1
- printf("rel relocations: %d\n", numrel);
-#endif
-#if 1
- symcache = calloc(sizeof(struct symcache_noflag),
- object->nchains);
- pltsymcache = calloc(sizeof(struct symcache_noflag),
- object->nchains);
- if (symcache == NULL || pltsymcache == NULL) {
- printf("unable to allocate memory for cache %s\n",
- object->load_name);
- exit(20);
- }
-#endif
- rel = object->dyn.rel;
- for (i = 0; i < numrel; i++) {
- const char *s;
- sym = object->dyn.symtab + ELF_R_SYM(rel[i].r_info);
-
- /* hppa has entries without names, skip them */
- if (sym->st_name == 0)
- continue;
-
- s = (ELF_R_SYM(rel[i].r_info) == 0) ? "<rel>" :
- object->dyn.strtab + sym->st_name;
-#ifdef DEBUG1
- printf("%d: %x sym %x %s type %d\n", i, rel[i].r_offset,
- ELF_R_SYM(rel[i].r_info), s,
- ELF_R_TYPE(rel[i].r_info));
-#endif
- if (ELF_R_SYM(rel[i].r_info) != 0) {
- elf_find_symbol_rel(s, object, &rel[i],
- symcache, pltsymcache);
- }
- }
- if (numrel) {
- numrel = object->dyn.pltrelsz / sizeof(Elf_Rel);
- rel = (Elf_Rel *)(object->Dyn.info[DT_JMPREL]);
-#ifdef DEBUG1
- printf("rel plt relocations: %d\n", numrel);
-#endif
- for (i = 0; i < numrel; i++) {
- const char *s;
- sym = object->dyn.symtab + ELF_R_SYM(rel[i].r_info);
-
- /* hppa has entries without names, skip them */
- if (sym->st_name == 0)
- continue;
-
- s = (ELF_R_SYM(rel[i].r_info) == 0) ? "<rel>" :
- object->dyn.strtab + sym->st_name;
-#ifdef DEBUG1
- printf("%d: %x sym %d %s type %d\n", i, rel[i].r_offset,
- ELF_R_SYM(rel[i].r_info), s,
- ELF_R_TYPE(rel[i].r_info));
-#endif
- if (ELF_R_SYM(rel[i].r_info) != 0) {
- elf_find_symbol_rel(s, object, &rel[i],
- symcache, pltsymcache);
- }
- }
- }
-
- numrela = object->dyn.relasz / sizeof(Elf_RelA);
-#ifdef DEBUG1
- printf("rela relocations: %d\n", numrela);
-#endif
- rela = object->dyn.rela;
- for (i = 0; i < numrela; i++) {
- const char *s;
- sym = object->dyn.symtab + ELF_R_SYM(rela[i].r_info);
-
- /* hppa has entries without names, skip them */
- if (sym->st_name == 0)
- continue;
-
- s = (ELF_R_SYM(rela[i].r_info) == 0) ? "<rel>" :
- object->dyn.strtab + sym->st_name;
-#ifdef DEBUG1
- printf("%d: %x sym %x %s type %d\n", i, rela[i].r_offset,
- ELF_R_SYM(rela[i].r_info), s,
- ELF_R_TYPE(rela[i].r_info));
-#endif
- if (ELF_R_SYM(rela[i].r_info) != 0) {
- elf_find_symbol_rela(s, object, &rela[i],
- symcache, pltsymcache);
- }
- }
- if (numrela) {
- numrela = object->dyn.pltrelsz / sizeof(Elf_RelA);
-#ifdef DEBUG1
- printf("rela plt relocations: %d\n", numrela);
-#endif
- rela = (Elf_RelA *)(object->Dyn.info[DT_JMPREL]);
-
- for (i = 0; i < numrela; i++) {
- const char *s;
- sym = object->dyn.symtab + ELF_R_SYM(rela[i].r_info);
-
- /* hppa has entries without names, skip them */
- if (sym->st_name == 0)
- continue;
-
- s = (ELF_R_SYM(rela[i].r_info) == 0) ? "<rel>" :
- object->dyn.strtab + sym->st_name;
-#ifdef DEBUG1
- printf("%d: %x sym %x %s type %d\n", i,
- rela[i].r_offset,
- ELF_R_SYM(rela[i].r_info), s,
- ELF_R_TYPE(rela[i].r_info));
-#endif
- if (ELF_R_SYM(rela[i].r_info) != 0) {
- elf_find_symbol_rela(s, object, &rela[i],
- symcache, pltsymcache);
- }
- }
- }
-
- for (i = 0; i < object->nchains; i++)
- if (symcache[i].sym != NULL)
- insert_sym_objcache(object, i, symcache[i].obj,
- symcache[i].sym, 0);
-
- for (i = 0; i < object->nchains; i++)
- if (pltsymcache[i].sym != NULL)
- insert_sym_objcache(object, i, pltsymcache[i].obj,
- pltsymcache[i].sym, SYM_PLT);
-
- free(symcache);
- free(pltsymcache);
-}
-
-void
-elf_resolve_curbin(void)
-{
- struct objlist *ol;
- int numobj = 0;
-
-#ifdef DEBUG1
- elf_print_curbin_list(curbin);
-#endif
- TAILQ_FOREACH(ol, &(curbin->curbin_list), list) {
- numobj++;
- }
- curbin->nobj = numobj;
- curbin->libmap = xcalloc(numobj, sizeof (u_int32_t *));
- curbin->libmap[0] = xcalloc(numobj, sizeof (u_int32_t *));
- curbin->fixup = xcalloc(2 * numobj, sizeof (struct fixup *));
- curbin->fixupcnt = xcalloc(2 * numobj, sizeof (int));
- curbin->fixupcntalloc = xcalloc(2 * numobj, sizeof (int));
-
- numobj = 0;
- TAILQ_FOREACH(ol, &(curbin->curbin_list), list) {
- curbin->libmap[0][numobj] = ol->object->dyn.null;
- numobj++;
- }
- TAILQ_FOREACH(ol, &(curbin->curbin_list), list) {
- elf_reloc(ol->object);
- }
-}
-
-void
-elf_add_object_curbin_list(struct elf_object *object)
-{
- struct objlist *ol;
-
- ol = xmalloc(sizeof (struct objlist));
- ol->object = object;
- TAILQ_INSERT_TAIL(&(curbin->curbin_list), ol, list);
- if (load_object == NULL)
- load_object = object;
- ol->load_prog = load_object;
-
- TAILQ_INSERT_TAIL(&(objarray[object->dyn.null].inst_list), ol,
- inst_list);
-}
-void
-elf_init_objarray(void)
-{
- objarray_sz = 512;
- objarray = xcalloc(sizeof (objarray[0]), objarray_sz);
-}
-
-void
-elf_sum_reloc(void)
-{
- int numobjs;
- int err = 0;
- struct objlist *ol;
- struct proglist *pl;
-
- TAILQ_FOREACH(ol, &library_list, list) {
- err += elf_prep_lib_prebind(ol->object);
- }
- TAILQ_FOREACH(pl, &prog_list, list) {
- numobjs = 0;
- TAILQ_FOREACH(ol, &(pl->curbin_list), list) {
- numobjs++;
- }
- pl->nobj = numobjs;
- }
-
- TAILQ_FOREACH(pl, &prog_list, list)
- err += elf_prep_bin_prebind(pl);
-
- if (err != 0)
- printf("failures %d\n", err);
-}
-
-int
-elf_prep_lib_prebind(struct elf_object *object)
-{
- int numlibs = 0;
- int ret = 0;
- int i;
- int ref_obj;
- int *libmap;
- int *idxtolib;
- struct nameidx *nameidx;
- char *nametab;
- int nametablen;
- struct symcache_noflag *symcache;
- struct symcache_noflag *pltsymcache;
- struct symcachetab *symcachetab;
- int symcache_cnt = 0;
- struct symcachetab *pltsymcachetab;
- int pltsymcache_cnt = 0;
-
- symcache = objarray[object->dyn.null].symcache;
- pltsymcache = objarray[object->dyn.null].pltsymcache;
- libmap = xcalloc(objarray_cnt, sizeof (int));
- idxtolib = xcalloc(objarray_cnt, sizeof (int));
- objarray[object->dyn.null].idxtolib = idxtolib;
-
- for (i = 0; i < objarray_cnt; i++)
- libmap[i] = -1;
-
- nametablen = 0;
- for (i = 0; i < object->nchains; i++) {
- if (symcache[i].sym == NULL)
- continue;
- ref_obj = symcache[i].obj->dyn.null;
- symcache_cnt++;
- if (libmap[ref_obj] != -1)
- continue;
- libmap[ref_obj] = numlibs;
- idxtolib[numlibs] = ref_obj;
- nametablen += strlen(symcache[i].obj->load_name) + 1;
- numlibs++;
- }
- symcachetab = xcalloc(symcache_cnt , sizeof(struct symcachetab));
-
- symcache_cnt = 0;
- for (i = 0; i < object->nchains; i++) {
- if (symcache[i].sym == NULL)
- continue;
- symcachetab[symcache_cnt].idx = i;
- symcachetab[symcache_cnt].obj_idx =
- libmap[symcache[i].obj->dyn.null];
- symcachetab[symcache_cnt].sym_idx =
- symcache[i].sym - symcache[i].obj->dyn.symtab;
- symcache_cnt++;
- }
- for (i = 0; i < object->nchains; i++) {
- if (pltsymcache[i].sym == NULL)
- continue;
- ref_obj = pltsymcache[i].obj->dyn.null;
- pltsymcache_cnt++;
- if (libmap[ref_obj] != -1)
- continue;
- libmap[ref_obj] = numlibs;
- idxtolib[numlibs] = ref_obj;
- nametablen += strlen(pltsymcache[i].obj->load_name) + 1;
- numlibs++;
- }
- pltsymcachetab = xcalloc(pltsymcache_cnt , sizeof(struct symcachetab));
-
- pltsymcache_cnt = 0;
- for (i = 0; i < object->nchains; i++) {
- if (pltsymcache[i].sym == NULL)
- continue;
- pltsymcachetab[pltsymcache_cnt].idx = i;
- pltsymcachetab[pltsymcache_cnt].obj_idx =
- libmap[pltsymcache[i].obj->dyn.null];
- pltsymcachetab[pltsymcache_cnt].sym_idx =
- pltsymcache[i].sym - pltsymcache[i].obj->dyn.symtab;
- pltsymcache_cnt++;
- }
-
- objarray[object->dyn.null].numlibs = numlibs;
-
- nameidx = xcalloc(numlibs, sizeof (struct nameidx));
- nametab = xmalloc(nametablen);
-
- nametablen = 0;
- for (i = 0; i < numlibs; i++) {
- nameidx[i].name = nametablen;
- nameidx[i].id0 = objarray[idxtolib[i]].id0;
- nameidx[i].id1 = objarray[idxtolib[i]].id1;
- nametablen += strlen(objarray[idxtolib[i]].obj->load_name) + 1;
- strlcpy(&nametab[nameidx[i].name],
- objarray[idxtolib[i]].obj->load_name,
- nametablen - nameidx[i].name);
- }
-
- /* skip writing lib if using old prebind data */
- if (objarray[object->dyn.null].oprebind_data == NULL)
- ret = elf_write_lib(object, nameidx, nametab, nametablen,
- numlibs, 0, NULL, NULL, NULL, NULL, symcachetab,
- symcache_cnt, pltsymcachetab, pltsymcache_cnt);
-
- free(nameidx);
- free(nametab);
- free(libmap);
- free(pltsymcachetab);
- free(symcachetab);
-
- return ret;
-}
-
-int
-elf_prep_bin_prebind(struct proglist *pl)
-{
- int ret;
- int numlibs = 0;
- int i, j;
- int ref_obj;
- int *libmap;
- int *idxtolib;
- struct nameidx *nameidx;
- char *nametab;
- int nametablen;
- struct symcache_noflag *symcache;
- struct symcache_noflag *pltsymcache;
- struct symcachetab *symcachetab;
- int symcache_cnt;
- struct symcachetab *pltsymcachetab;
- int pltsymcache_cnt;
- struct elf_object *object;
- struct objlist *ol;
-
- object = TAILQ_FIRST(&(pl->curbin_list))->object;
- symcache = objarray[object->dyn.null].symcache;
- pltsymcache = objarray[object->dyn.null].pltsymcache;
- libmap = xcalloc(objarray_cnt, sizeof (int));
- idxtolib = xcalloc(pl->nobj, sizeof (int));
-
- for (i = 0; i < objarray_cnt; i++)
- libmap[i] = -1;
-
- for (i = 0; i < pl->nobj; i++)
- idxtolib[i] = -1;
-
- nametablen = 0;
- TAILQ_FOREACH(ol, &(pl->curbin_list), list) {
- ref_obj = ol->object->dyn.null;
- nametablen += strlen(ol->object->load_name) + 1;
- libmap[ref_obj] = numlibs;
- idxtolib[numlibs] = ref_obj;
- numlibs++;
- }
-
- /* do got */
- symcache_cnt = 0;
- for (i = 0; i < object->nchains; i++) {
- if (symcache[i].sym != NULL)
- symcache_cnt++;
- }
-
- symcachetab = xcalloc(symcache_cnt , sizeof(struct symcachetab));
-
- symcache_cnt = 0;
- for (i = 0; i < object->nchains; i++) {
- if (symcache[i].sym == NULL)
- continue;
- symcachetab[symcache_cnt].idx = i;
- symcachetab[symcache_cnt].obj_idx =
- libmap[symcache[i].obj->dyn.null];
- symcachetab[symcache_cnt].sym_idx =
- symcache[i].sym - symcache[i].obj->dyn.symtab;
- symcache_cnt++;
- }
-
- /* now do plt */
- pltsymcache_cnt = 0;
- for (i = 0; i < object->nchains; i++) {
- if (pltsymcache[i].sym != NULL)
- pltsymcache_cnt++;
- }
- pltsymcachetab = xcalloc(pltsymcache_cnt , sizeof(struct symcachetab));
-
- pltsymcache_cnt = 0;
- for (i = 0; i < object->nchains; i++) {
- if (pltsymcache[i].sym == NULL)
- continue;
- pltsymcachetab[pltsymcache_cnt].idx = i;
- pltsymcachetab[pltsymcache_cnt].obj_idx =
- libmap[pltsymcache[i].obj->dyn.null];
- pltsymcachetab[pltsymcache_cnt].sym_idx =
- pltsymcache[i].sym - pltsymcache[i].obj->dyn.symtab;
- pltsymcache_cnt++;
- }
-
- objarray[object->dyn.null].numlibs = numlibs;
-
- nameidx = xcalloc(numlibs, sizeof (struct nameidx));
- nametab = xmalloc(nametablen);
-
- nametablen = 0;
- for (i = 0; i < numlibs; i++) {
- nameidx[i].name = nametablen;
- nameidx[i].id0 = objarray[idxtolib[i]].id0;
- nameidx[i].id1 = objarray[idxtolib[i]].id1;
- nametablen += strlen(objarray[idxtolib[i]].obj->load_name) + 1;
-
- strlcpy(&nametab[nameidx[i].name],
- objarray[idxtolib[i]].obj->load_name,
- nametablen - nameidx[i].name);
- }
- pl->libmapcnt = xcalloc(numlibs, sizeof(u_int32_t));
-
- /* have to do both got and plt fixups */
- for (i = 0; i < numlibs; i++) {
- for (j = 0; j < pl->fixupcnt[2*i]; j++) {
- pl->fixup[2*i][j].obj_idx =
- libmap[pl->fixup[2*i][j].obj_idx];
- }
- for (j = 0; j < pl->fixupcnt[2*i+1]; j++) {
- pl->fixup[2*i+1][j].obj_idx =
- libmap[pl->fixup[2*i+1][j].obj_idx];
- }
-
- pl->libmapcnt[i] = objarray[idxtolib[i]].numlibs;
- pl->libmap[i] = xcalloc(objarray[idxtolib[i]].numlibs,
- sizeof(u_int32_t));
- if (i != 0) {
- for (j = 0; j < objarray[idxtolib[i]].numlibs; j++) {
- pl->libmap[i][j] =
- libmap[objarray[idxtolib[i]].idxtolib[j]];
- }
- }
- }
-
- ret = elf_write_lib(object, nameidx, nametab, nametablen, numlibs,
- numlibs, pl->fixup, pl->fixupcnt,
- pl->libmap, pl->libmapcnt,
- symcachetab, symcache_cnt,
- pltsymcachetab, pltsymcache_cnt);
-
- free(symcachetab);
- free(pltsymcachetab);
- free(idxtolib);
- free(nameidx);
- free(nametab);
- free(libmap);
-
- return ret;
-}
-
-
-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)
-{
- struct prebind_footer footer;
- struct prebind_info info;
- u_int32_t footer_offset, *maptab = NULL;
- u_int32_t next_start, *fixuptab = NULL;
- struct stat ifstat;
- off_t base_offset;
- ssize_t len;
- int fd = -1, i;
- int readonly = 0;
-
- /* open the file, if in safe mode, only open it readonly */
- if (safe == 0)
- fd = open(object->load_name, O_RDWR);
- if (fd == -1) {
- if (safe != 0 || errno == ETXTBSY)
- fd = open(object->load_name, O_RDONLY);
- if (fd == -1) {
- perror(object->load_name);
- return 1;
- }
- readonly = 1;
- }
- if (lseek(fd, -((off_t)sizeof(struct prebind_footer)), SEEK_END)
- == -1) {
- perror(object->load_name);
- close(fd);
- return 1;
- }
-
- len = read(fd, &footer, sizeof(struct prebind_footer));
- if (len != sizeof(struct prebind_footer)) {
- close(fd);
- if (len == -1)
- perror(object->load_name);
- else
- /* paranoia */
- warnx("%s on %s: short read (corrupted file?)",
- __func__, object->load_name);
- return 1;
- }
-
- if (fstat(fd, &ifstat) == -1) {
- perror(object->load_name);
- exit(10);
- }
-
- if (footer.bind_id[0] == BIND_ID0 &&
- footer.bind_id[1] == BIND_ID1 &&
- footer.bind_id[2] == BIND_ID2 &&
- footer.bind_id[3] == BIND_ID3 &&
- readonly == 0) {
-
- ftruncate(fd, footer.orig_size);
- elf_clear_prog_load(fd, object);
-
- base_offset = footer.orig_size;
- } else {
- base_offset = ifstat.st_size;
- }
-
- bzero(&footer, sizeof(struct prebind_footer));
-
-
- /* verify dev/inode - do we care about last modified? */
-
- /* pieces to store on lib
- *
- * offset to footer
- * nameidx - numlibs * sizeof nameidx
- * symcache - symcache_cnt * sizeof (symcache_idx)
- * pltsymcache - pltsymcache_cnt * sizeof (symcache_idx)
- * fixup(N/A for lib) - nfixup * sizeof (symcache_idx)
- * nametab - nametablen
- * footer (not aligned)
- */
-
- footer.orig_size = base_offset;
- base_offset = ELF_ROUND(base_offset, sizeof(u_int64_t));
- footer.prebind_base = base_offset;
- footer.nameidx_idx = sizeof(u_int32_t);
- footer.symcache_idx = footer.nameidx_idx +
- numlibs * sizeof (struct nameidx);
- footer.pltsymcache_idx = footer.symcache_idx +
- symcache_cnt * sizeof (struct nameidx);
- footer.symcache_cnt = symcache_cnt;
- footer.pltsymcache_cnt = pltsymcache_cnt;
- footer.fixup_cnt = 0;
- footer.numlibs = numlibs;
- next_start = footer.pltsymcache_idx +
- (pltsymcache_cnt * sizeof (struct symcachetab));
- if (nfixup != 0) {
- footer.fixup_cnt = nfixup;
- footer.fixup_idx = next_start;
- next_start += 2*nfixup * sizeof(u_int32_t);
- footer.fixupcnt_idx = next_start;
- next_start += 2*nfixup * sizeof(u_int32_t);
- fixuptab = xcalloc(2*nfixup, sizeof(u_int32_t));
- for (i = 0; i < 2*nfixup; i++) {
- fixuptab[i] = next_start;
- next_start += fixupcnt[i] * sizeof(struct fixup);
- }
- footer.libmap_idx = next_start;
- next_start += 2*nfixup * sizeof(u_int32_t);
- maptab = xcalloc(2*nfixup, sizeof(u_int32_t));
- maptab[0] = next_start;
- for (i = 1; i < nfixup; i++) {
- maptab[i] = next_start;
- next_start += libmapcnt[i] * sizeof(u_int32_t);
- }
- }
-
- footer.nametab_idx = next_start;
- next_start += nametablen;
- next_start = ELF_ROUND(next_start, sizeof(u_int64_t));
- footer_offset = next_start;
- if (verbose > 1) {
- printf("footer_offset %d\n", footer_offset);
- }
- footer.prebind_size = next_start + sizeof(struct prebind_footer);
-
- footer.prebind_version = PREBIND_VERSION;
- footer.id0 = objarray[object->dyn.null].id0;
- footer.id1 = objarray[object->dyn.null].id1;
- footer.bind_id[0] = BIND_ID0;
- footer.bind_id[1] = BIND_ID1;
- footer.bind_id[2] = BIND_ID2;
- footer.bind_id[3] = BIND_ID3;
-
-
- info.object = object;
- info.footer = &footer;
- info.footer_offset = footer_offset;
- info.nameidx = nameidx;
- info.symcache = symcachetab;
-
-
- info.pltsymcache = pltsymcachetab;
- info.nfixup = nfixup;
- if (nfixup != 0) {
- info.fixuptab = fixuptab;
- info.fixupcnt = fixupcnt;
- info.fixup = fixup;
- info.maptab = maptab;
- info.libmap = libmap;
- info.libmapcnt = libmapcnt;
- }
-
- info.nametab = nametab;
- info.nametablen = nametablen;
-
-
- if (readonly) {
- prebind_writenewfile(fd, object->load_name, &ifstat,
- (off_t)footer.orig_size, &info);
- } else {
- prebind_writefile(fd, &info);
- }
-
- if (fstat(fd, &ifstat) == -1) {
- perror(object->load_name);
- exit(10);
- }
- if (nfixup != 0) {
- free(fixuptab);
- free(maptab);
- }
-
- if (verbose > 0)
- printf("%s: prebind info %d bytes old size %lld, growth %f\n",
- object->load_name, footer.prebind_size, footer.orig_size,
- (double)(footer.prebind_size) / footer.orig_size);
-
- if (verbose > 1)
- elf_dump_footer(&footer);
-
- close(fd);
- return 0;
-}
-
-int
-prebind_writefile(int fd, struct prebind_info *info)
-{
- int i;
-
- struct prebind_footer *footer = info->footer;
-
- lseek(fd, footer->prebind_base, SEEK_SET);
- write(fd, &info->footer_offset, sizeof(u_int32_t));
-
- lseek(fd, footer->prebind_base+footer->nameidx_idx, SEEK_SET);
- write(fd, info->nameidx, footer->numlibs * sizeof (struct nameidx));
-
- lseek(fd, footer->prebind_base+footer->symcache_idx, SEEK_SET);
- write(fd, info->symcache, footer->symcache_cnt *
- sizeof (struct symcachetab));
-
- lseek(fd, footer->prebind_base+footer->pltsymcache_idx, SEEK_SET);
- write(fd, info->pltsymcache, footer->pltsymcache_cnt *
- sizeof (struct symcachetab));
-
- if (info->nfixup != 0) {
- lseek(fd, footer->prebind_base+footer->fixup_idx, SEEK_SET);
- write(fd, info->fixuptab, 2*info->nfixup * sizeof(u_int32_t));
- lseek(fd, footer->prebind_base+footer->fixupcnt_idx, SEEK_SET);
- write(fd, info->fixupcnt, 2*info->nfixup * sizeof(u_int32_t));
- for (i = 0; i < 2*info->nfixup; i++) {
- lseek(fd, footer->prebind_base+info->fixuptab[i],
- SEEK_SET);
- write(fd, info->fixup[i], info->fixupcnt[i] *
- sizeof(struct fixup));
- }
-
- lseek(fd, footer->prebind_base+footer->libmap_idx, SEEK_SET);
- write(fd, info->maptab, info->nfixup * sizeof(u_int32_t));
- for (i = 0; i < info->nfixup; i++) {
- lseek(fd, footer->prebind_base+info->maptab[i],
- SEEK_SET);
- write(fd, info->libmap[i], info->libmapcnt[i] *
- sizeof(u_int32_t));
- }
- }
- lseek(fd, footer->prebind_base+footer->nametab_idx, SEEK_SET);
- write(fd, info->nametab, info->nametablen);
-
- lseek(fd, footer->prebind_base+info->footer_offset, SEEK_SET);
- write(fd, footer, sizeof (struct prebind_footer));
-
- if (info->object->obj_type == OBJTYPE_EXE)
- elf_fixup_prog_load(fd, info->footer, info->object);
-
- return 0;
-}
-
-int
-prebind_writenewfile(int infd, char *name, struct stat *st, off_t orig_size,
- struct prebind_info *info)
-{
- struct timespec ts[2];
- char *newname, *buf;
- ssize_t len, wlen;
- int outfd;
-
- if (asprintf(&newname, "%s.XXXXXXXXXX", name) == -1) {
- if (verbose)
- warn("asprintf");
- return (-1);
- }
- outfd = open(newname, O_CREAT|O_RDWR|O_TRUNC, 0600);
- if (outfd == -1) {
- warn("%s", newname);
- free(newname);
- return (-1);
- }
-
- buf = malloc(BUFSZ);
- if (buf == NULL) {
- if (verbose)
- warn("malloc");
- goto fail;
- }
-
- /* copy old file to new file */
- lseek(infd, (off_t)0, SEEK_SET);
- while (1) {
- len = read(infd, buf, BUFSIZ);
- if (len == -1) {
- if (verbose)
- warn("read");
- free(buf);
- goto fail;
- }
- if (len == 0)
- break;
- wlen = write(outfd, buf, len);
- if (wlen != len) {
- free(buf);
- goto fail;
- }
- }
- free(buf);
-
- /* now back track, and delete the header */
- if (prebind_remove_load_section(outfd, newname) == -1)
- goto fail;
- if (orig_size != (off_t)-1 &&
- ftruncate(outfd, orig_size) == -1)
- goto fail;
-
- prebind_writefile(outfd, info);
-
- /* move new file into place */
- ts[0] = st->st_atimespec;
- ts[1] = st->st_mtimespec;
- if (futimens(outfd, ts) == -1)
- goto fail;
- if (fchown(outfd, st->st_uid, st->st_gid) == -1)
- goto fail;
- if (fchmod(outfd, st->st_mode) == -1)
- goto fail;
- if (fchflags(outfd, st->st_flags) == -1)
- goto fail;
- if (fstat(outfd, st) == -1) {
- /* XXX */
- goto fail;
- }
- if (rename(newname, name) == -1)
- goto fail;
-
- close (outfd);
- return (0);
-
-fail:
- unlink(newname);
- free(newname);
- close(outfd);
- return (-1);
-}
-
-void
-elf_fixup_prog_load(int fd, struct prebind_footer *footer,
- struct elf_object *object)
-{
- void *buf;
- Elf_Ehdr *ehdr;
- Elf_Phdr *phdr;
- Elf_Phdr phdr_empty;
- int loadsection;
-
- buf = mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_FILE | MAP_SHARED,
- fd, 0);
- if (buf == MAP_FAILED) {
- printf("%s: cannot mmap for write\n", object->load_name);
- return;
- }
-
- ehdr = (Elf_Ehdr *) buf;
- phdr = (Elf_Phdr *)((char *)buf + ehdr->e_phoff);
-
- for (loadsection = 0; loadsection < ehdr->e_phnum; loadsection++) {
- if (phdr[loadsection].p_type == PT_LOAD)
- break;
- }
-
- /* verify that extra slot is empty */
- bzero(&phdr_empty, sizeof(phdr_empty));
- if (bcmp(&phdr[ehdr->e_phnum], &phdr_empty, sizeof(phdr_empty)) != 0) {
- printf("extra slot not empty\n");
- goto done;
- }
- phdr[ehdr->e_phnum].p_type = PT_LOAD;
- phdr[ehdr->e_phnum].p_flags = PF_R | 0x08000000;
- phdr[ehdr->e_phnum].p_offset = footer->prebind_base;
- phdr[ehdr->e_phnum].p_vaddr = footer->prebind_base | 0x80000000;
- phdr[ehdr->e_phnum].p_paddr = footer->prebind_base | 0x40000000;
- phdr[ehdr->e_phnum].p_filesz = footer->prebind_size;
- phdr[ehdr->e_phnum].p_memsz = footer->prebind_size;
- phdr[ehdr->e_phnum].p_align = phdr[loadsection].p_align;
- ehdr->e_phnum++;
-
-done:
- msync(buf, 8192, MS_SYNC);
- munmap(buf, 8192);
-}
-
-void
-elf_clear_prog_load(int fd, struct elf_object *object)
-{
- void *buf;
- Elf_Ehdr *ehdr;
- Elf_Phdr *phdr;
- Elf_Phdr phdr_empty;
- int loadsection;
-
- buf = mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_FILE | MAP_SHARED,
- fd, 0);
- if (buf == MAP_FAILED) {
- printf("%s: cannot mmap for write\n", object->load_name);
- return;
- }
-
- ehdr = (Elf_Ehdr *) buf;
- phdr = (Elf_Phdr *)((char *)buf + ehdr->e_phoff);
-
- if (ehdr->e_type != ET_EXEC) {
- goto done;
- }
-
- loadsection = ehdr->e_phnum - 1;
- if ((phdr[loadsection].p_type != PT_LOAD) ||
- ((phdr[loadsection].p_flags & 0x08000000) == 0)) {
- /* doesn't look like ours */
- printf("mapped, %s id doesn't match %lx %d %d\n",
- object->load_name,
- (long)(phdr[loadsection].p_vaddr),
- phdr[loadsection].p_flags, loadsection);
- goto done;
- }
-
- /* verify that extra slot is empty */
- bzero(&phdr[loadsection], sizeof(phdr_empty));
-
- ehdr->e_phnum--;
-
-done:
- msync(buf, 8192, MS_SYNC);
- munmap(buf, 8192);
-}
-
-void
-elf_add_object(struct elf_object *object, int objtype)
-{
- struct objarray_list *newarray;
- struct objlist *ol;
- ol = xmalloc(sizeof (struct objlist));
- ol->object = object;
- if (objtype != OBJTYPE_EXE)
- TAILQ_INSERT_TAIL(&library_list, ol, list);
- if (objarray_cnt+1 >= objarray_sz) {
- objarray_sz += 512;
- newarray = reallocarray(objarray, objarray_sz,
- sizeof(objarray[0]));
- if (newarray != NULL)
- objarray = newarray;
- else {
- perror("objarray");
- exit(20);
- }
- }
- object->dyn.null = objarray_cnt; /* Major abuse, I know */
- TAILQ_INIT(&(objarray[objarray_cnt].inst_list));
- objarray[objarray_cnt].obj = object;
- objarray[objarray_cnt].id0 = arc4random();
- objarray[objarray_cnt].id1 = arc4random();
-
- objarray[objarray_cnt].symcache = xcalloc(
- sizeof(struct symcache_noflag), object->nchains);
- objarray[objarray_cnt].pltsymcache = xcalloc(
- sizeof(struct symcache_noflag), object->nchains);
-
- objarray[objarray_cnt].oprebind_data = NULL;
- objarray[objarray_cnt].proglist = NULL;
- objarray[objarray_cnt].numlibs = 0;
- objarray_cnt++;
-
- elf_add_object_curbin_list(object);
-}
-
-void
-elf_free_curbin_list(elf_object_t *object)
-{
- struct objlist *ol;
- int i;
-
- while (!TAILQ_EMPTY(&(curbin->curbin_list))) {
- ol = TAILQ_FIRST(&(curbin->curbin_list));
- TAILQ_REMOVE(&(objarray[ol->object->dyn.null].inst_list), ol, inst_list);
- TAILQ_REMOVE(&(curbin->curbin_list), ol, list);
- free(ol);
- }
-
- printf("trying to remove %s\n", object->load_name);
- for (i = objarray_cnt; i != 0;) {
- i--;
- printf("obj %s\n", objarray[i].obj->load_name);
- if (objarray[i].obj == object) {
- printf("found obj at %d max obj %d\n", i, objarray_cnt);
- TAILQ_FOREACH(ol, &(curbin->curbin_list), list) {
- }
- /* XXX - delete references */
- objarray_cnt = i;
- break;
- }
- }
-}
-
-void
-elf_print_objarray(void)
-{
- int i;
- struct objlist *ol;
-
- printf("loaded objs # %d\n", objarray_cnt);
- for (i = 0; i < objarray_cnt; i++) {
- printf("%3d: %d obj %s\n", i, (int)objarray[i].obj->dyn.null,
- objarray[i].obj->load_name);
- TAILQ_FOREACH(ol, &(objarray[i].inst_list),
- inst_list) {
- printf("\tprog %s\n", ol->load_prog->load_name);
- }
- }
-}
-
-void
-elf_load_existing_prebind(struct elf_object *object, int fd)
-{
- struct prebind_footer footer;
- void *prebind_data;
- ssize_t len;
-
- lseek(fd, -((off_t)sizeof(struct prebind_footer)), SEEK_END);
- len = read(fd, &footer, sizeof(struct prebind_footer));
- if (len != sizeof(struct prebind_footer))
- return;
-
- if (footer.bind_id[0] != BIND_ID0 ||
- footer.bind_id[1] != BIND_ID1 ||
- footer.bind_id[2] != BIND_ID2 ||
- footer.bind_id[3] != BIND_ID3)
- return;
-
- prebind_data = mmap(0, footer.prebind_size, PROT_READ,
- MAP_FILE, fd, footer.prebind_base);
- if (prebind_data == MAP_FAILED)
- return;
- objarray[object->dyn.null].oprebind_data = prebind_data;
- objarray[object->dyn.null].id0 = footer.id0;
- objarray[object->dyn.null].id1 = footer.id1;
-
- copy_oldsymcache(object->dyn.null, prebind_data);
-}
-
-void
-copy_oldsymcache(int objidx, char *prebind_map)
-{
- struct prebind_footer *footer;
- struct elf_object *tobj;
- struct symcache_noflag *tcache;
- struct symcachetab *symcache;
- int i, j, found, *idxtolib;
- char *c, *nametab;
- u_int32_t offset;
- u_int32_t *poffset;
- struct nameidx *nameidx;
-
- poffset = (u_int32_t *)prebind_map;
- c = prebind_map;
- offset = *poffset;
- c += offset;
- footer = (void *)c;
-
- nameidx = (void *)(prebind_map + footer->nameidx_idx);
- nametab = (void *)(prebind_map + footer->nametab_idx);
-
- idxtolib = xcalloc(footer->numlibs, sizeof(int));
- found = 0;
- for (i = 0; i < footer->numlibs; i++) {
- found = 0;
- for (j = 0; j < objarray_cnt; j++) {
- if (objarray[j].id0 == nameidx[i].id0 &&
- objarray[j].id1 == nameidx[i].id1) {
- found = 1;
- idxtolib[i] = j;
- if (strcmp(objarray[j].obj->load_name,
- &nametab[nameidx[i].name]) != 0) {
- printf("warning filename mismatch"
- " [%s] [%s]\n",
- objarray[j].obj->load_name,
- &nametab[nameidx[i].name]);
- }
- }
- }
- if (found == 0)
- break;
- }
- if (found == 0)
- goto done;
-
- /* build idxtolibs */
- tcache = objarray[objidx].symcache;
- symcache = (void *)(prebind_map + footer->symcache_idx);
-
- for (i = 0; i < footer->symcache_cnt; i++) {
- tobj = objarray[idxtolib[symcache[i].obj_idx]].obj;
-
- tcache[symcache[i].idx].obj = tobj;
- tcache[symcache[i].idx].sym = tobj->dyn.symtab +
- symcache[i].sym_idx;
- }
-
- tcache = objarray[objidx].pltsymcache;
- symcache = (void *)(prebind_map + footer->pltsymcache_idx);
- for (i = 0; i < footer->pltsymcache_cnt; i++) {
- tobj = objarray[idxtolib[symcache[i].obj_idx]].obj;
-
- tcache[symcache[i].idx].obj = tobj;
- tcache[symcache[i].idx].sym = tobj->dyn.symtab +
- symcache[i].sym_idx;
- }
-done:
- free(idxtolib);
- /* munmap(prebind_map, size);*/
-}