summaryrefslogtreecommitdiffstats
path: root/usr.sbin/crunch/crunchide/exec_elf32.c
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1998-09-14 11:35:32 +0000
committerjkh <jkh@FreeBSD.org>1998-09-14 11:35:32 +0000
commita4969a17ca93b529c57b07fb44668d7563024d3f (patch)
tree593ab577b803f64ca18aad0944f5c5ca1b308269 /usr.sbin/crunch/crunchide/exec_elf32.c
parente7f0dcd13762c2e1e086d5e60434578e55b0d1a6 (diff)
downloadFreeBSD-src-a4969a17ca93b529c57b07fb44668d7563024d3f.zip
FreeBSD-src-a4969a17ca93b529c57b07fb44668d7563024d3f.tar.gz
Teach crunch about an elf/a.out world.
Submitted by: jhay
Diffstat (limited to 'usr.sbin/crunch/crunchide/exec_elf32.c')
-rw-r--r--usr.sbin/crunch/crunchide/exec_elf32.c389
1 files changed, 389 insertions, 0 deletions
diff --git a/usr.sbin/crunch/crunchide/exec_elf32.c b/usr.sbin/crunch/crunchide/exec_elf32.c
new file mode 100644
index 0000000..45883f4
--- /dev/null
+++ b/usr.sbin/crunch/crunchide/exec_elf32.c
@@ -0,0 +1,389 @@
+/* $NetBSD: exec_elf32.c,v 1.4 1997/08/12 06:07:24 mikel Exp $ */
+
+/*
+ * Copyright (c) 1997 Christopher G. Demetriou. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: exec_elf32.c,v 1.4 1997/08/12 06:07:24 mikel Exp $");
+#endif
+
+#ifndef ELFSIZE
+#define ELFSIZE 32
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+#if (defined(NLIST_ELF32) && (ELFSIZE == 32)) || \
+ (defined(NLIST_ELF64) && (ELFSIZE == 64))
+
+#include <elf.h>
+
+#define CONCAT(x,y) __CONCAT(x,y)
+#define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x)))
+#define ELFNAME2(x,y) CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y))))
+#define ELFNAMEEND(x) CONCAT(x,CONCAT(_elf,ELFSIZE))
+#define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x)))
+
+struct listelem {
+ struct listelem *next;
+ void *mem;
+ off_t file;
+ size_t size;
+};
+
+static ssize_t
+xreadatoff(int fd, void *buf, off_t off, size_t size, const char *fn)
+{
+ ssize_t rv;
+
+ if (lseek(fd, off, SEEK_SET) != off) {
+ perror(fn);
+ return -1;
+ }
+ if ((rv = read(fd, buf, size)) != size) {
+ fprintf(stderr, "%s: read error: %s\n", fn,
+ rv == -1 ? strerror(errno) : "short read");
+ return -1;
+ }
+ return size;
+}
+
+static ssize_t
+xwriteatoff(int fd, void *buf, off_t off, size_t size, const char *fn)
+{
+ ssize_t rv;
+
+ if (lseek(fd, off, SEEK_SET) != off) {
+ perror(fn);
+ return -1;
+ }
+ if ((rv = write(fd, buf, size)) != size) {
+ fprintf(stderr, "%s: write error: %s\n", fn,
+ rv == -1 ? strerror(errno) : "short write");
+ return -1;
+ }
+ return size;
+}
+
+static void *
+xmalloc(size_t size, const char *fn, const char *use)
+{
+ void *rv;
+
+ rv = malloc(size);
+ if (rv == NULL)
+ fprintf(stderr, "%s: out of memory (allocating for %s)\n",
+ fn, use);
+ return (rv);
+}
+
+int
+ELFNAMEEND(check)(int fd, const char *fn)
+{
+ Elf_Ehdr eh;
+ struct stat sb;
+
+ /*
+ * Check the header to maek sure it's an ELF file (of the
+ * appropriate size).
+ */
+ if (fstat(fd, &sb) == -1)
+ return 0;
+ if (sb.st_size < sizeof eh)
+ return 0;
+ if (read(fd, &eh, sizeof eh) != sizeof eh)
+ return 0;
+
+ if (IS_ELF(eh) == 0)
+ return 0;
+
+ switch (eh.e_machine) {
+ case EM_386: break;
+ case EM_ALPHA: break;
+/* ELFDEFNNAME(MACHDEP_ID_CASES) */
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+int
+ELFNAMEEND(hide)(int fd, const char *fn)
+{
+ Elf_Ehdr ehdr;
+ Elf_Shdr *shdrp = NULL, *symtabshdr, *strtabshdr;
+ Elf_Sym *symtabp = NULL;
+ char *strtabp = NULL;
+ Elf_Word *symfwmap = NULL, *symrvmap = NULL, nsyms, nlocalsyms, ewi;
+ struct listelem *relalist = NULL, *rellist = NULL, *tmpl;
+ ssize_t shdrsize;
+ int rv, i, weird;
+
+ rv = 0;
+ if (xreadatoff(fd, &ehdr, 0, sizeof ehdr, fn) != sizeof ehdr)
+ goto bad;
+
+ shdrsize = ehdr.e_shnum * ehdr.e_shentsize;
+ if ((shdrp = xmalloc(shdrsize, fn, "section header table")) == NULL)
+ goto bad;
+ if (xreadatoff(fd, shdrp, ehdr.e_shoff, shdrsize, fn) != shdrsize)
+ goto bad;
+
+ symtabshdr = strtabshdr = NULL;
+ weird = 0;
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ switch (shdrp[i].sh_type) {
+ case SHT_SYMTAB:
+ if (symtabshdr != NULL)
+ weird = 1;
+ symtabshdr = &shdrp[i];
+ strtabshdr = &shdrp[shdrp[i].sh_link];
+ break;
+ case SHT_RELA:
+ tmpl = xmalloc(sizeof *tmpl, fn, "rela list element");
+ if (tmpl == NULL)
+ goto bad;
+ tmpl->mem = NULL;
+ tmpl->file = shdrp[i].sh_offset;
+ tmpl->size = shdrp[i].sh_size;
+ tmpl->next = relalist;
+ relalist = tmpl;
+ break;
+ case SHT_REL:
+ tmpl = xmalloc(sizeof *tmpl, fn, "rel list element");
+ if (tmpl == NULL)
+ goto bad;
+ tmpl->mem = NULL;
+ tmpl->file = shdrp[i].sh_offset;
+ tmpl->size = shdrp[i].sh_size;
+ tmpl->next = rellist;
+ rellist = tmpl;
+ break;
+ }
+ }
+ if (symtabshdr == NULL)
+ goto out;
+ if (strtabshdr == NULL)
+ weird = 1;
+ if (weird) {
+ fprintf(stderr, "%s: weird executable (unsupported)\n", fn);
+ goto bad;
+ }
+
+ /*
+ * load up everything we need
+ */
+
+ /* symbol table */
+ if ((symtabp = xmalloc(symtabshdr->sh_size, fn, "symbol table"))
+ == NULL)
+ goto bad;
+ if (xreadatoff(fd, symtabp, symtabshdr->sh_offset, symtabshdr->sh_size,
+ fn) != symtabshdr->sh_size)
+ goto bad;
+
+ /* string table */
+ if ((strtabp = xmalloc(strtabshdr->sh_size, fn, "string table"))
+ == NULL)
+ goto bad;
+ if (xreadatoff(fd, strtabp, strtabshdr->sh_offset, strtabshdr->sh_size,
+ fn) != strtabshdr->sh_size)
+ goto bad;
+
+ /* any rela tables */
+ for (tmpl = relalist; tmpl != NULL; tmpl = tmpl->next) {
+ if ((tmpl->mem = xmalloc(tmpl->size, fn, "rela table"))
+ == NULL)
+ goto bad;
+ if (xreadatoff(fd, tmpl->mem, tmpl->file, tmpl->size, fn) !=
+ tmpl->size)
+ goto bad;
+ }
+
+ /* any rel tables */
+ for (tmpl = rellist; tmpl != NULL; tmpl = tmpl->next) {
+ if ((tmpl->mem = xmalloc(tmpl->size, fn, "rel table"))
+ == NULL)
+ goto bad;
+ if (xreadatoff(fd, tmpl->mem, tmpl->file, tmpl->size, fn) !=
+ tmpl->size)
+ goto bad;
+ }
+
+ /* Prepare data structures for symbol movement. */
+ nsyms = symtabshdr->sh_size / symtabshdr->sh_entsize;
+ nlocalsyms = symtabshdr->sh_info;
+ if ((symfwmap = xmalloc(nsyms * sizeof (Elf_Word), fn,
+ "symbol forward mapping table")) == NULL)
+ goto bad;
+ if ((symrvmap = xmalloc(nsyms * sizeof (Elf_Word), fn,
+ "symbol reverse mapping table")) == NULL)
+ goto bad;
+
+ /* init location -> symbol # table */
+ for (ewi = 0; ewi < nsyms; ewi++)
+ symrvmap[ewi] = ewi;
+
+ /* move symbols, making them local */
+ for (ewi = nlocalsyms; ewi < nsyms; ewi++) {
+ Elf_Sym *sp, symswap;
+ Elf_Word mapswap;
+
+ sp = &symtabp[ewi];
+
+ /* if it's on our keep list, don't move it */
+ if (in_keep_list(strtabp + sp->st_name))
+ continue;
+
+ /* if it's an undefined symbol, keep it */
+ if (sp->st_shndx == SHN_UNDEF)
+ continue;
+
+ /* adjust the symbol so that it's local */
+ sp->st_info =
+ ELF_ST_INFO(STB_LOCAL, sp->st_info);
+/* (STB_LOCAL << 4) | ELF_SYM_TYPE(sp->st_info); *//* XXX */
+
+ /*
+ * move the symbol to its new location
+ */
+
+ /* note that symbols in those locations have been swapped */
+ mapswap = symrvmap[ewi];
+ symrvmap[ewi] = symrvmap[nlocalsyms];
+ symrvmap[nlocalsyms] = mapswap;
+
+ /* and swap the symbols */
+ symswap = *sp;
+ *sp = symtabp[nlocalsyms];
+ symtabp[nlocalsyms] = symswap;
+
+ nlocalsyms++; /* note new local sym */
+ }
+ symtabshdr->sh_info = nlocalsyms;
+
+ /* set up symbol # -> location mapping table */
+ for (ewi = 0; ewi < nsyms; ewi++)
+ symfwmap[symrvmap[ewi]] = ewi;
+
+ /* any rela tables */
+ for (tmpl = relalist; tmpl != NULL; tmpl = tmpl->next) {
+ Elf_Rela *relap = tmpl->mem;
+
+ for (ewi = 0; ewi < tmpl->size / sizeof(*relap); ewi++) {
+ relap[ewi].r_info =
+#if (ELFSIZE == 32) /* XXX */
+ symfwmap[ELF_R_SYM(relap[ewi].r_info)] << 8 |
+ ELF_R_TYPE(relap[ewi].r_info);
+#elif (ELFSIZE == 64) /* XXX */
+ symfwmap[ELF_R_SYM(relap[ewi].r_info)] << 32 |
+ ELF_R_TYPE(relap[ewi].r_info);
+#endif /* XXX */
+ }
+ }
+
+ /* any rel tables */
+ for (tmpl = rellist; tmpl != NULL; tmpl = tmpl->next) {
+ Elf_Rel *relp = tmpl->mem;
+
+ for (ewi = 0; ewi < tmpl->size / sizeof *relp; ewi++) {
+ relp[ewi].r_info =
+#if (ELFSIZE == 32) /* XXX */
+ symfwmap[ELF_R_SYM(relp[ewi].r_info)] << 8 |
+ ELF_R_TYPE(relp[ewi].r_info);
+#elif (ELFSIZE == 64) /* XXX */
+ symfwmap[ELF_R_SYM(relp[ewi].r_info)] << 32 |
+ ELF_R_TYPE(relp[ewi].r_info);
+#endif /* XXX */
+ }
+ }
+
+ /*
+ * write new tables to the file
+ */
+ if (xwriteatoff(fd, shdrp, ehdr.e_shoff, shdrsize, fn) != shdrsize)
+ goto bad;
+ if (xwriteatoff(fd, symtabp, symtabshdr->sh_offset,
+ symtabshdr->sh_size, fn) != symtabshdr->sh_size)
+ goto bad;
+ for (tmpl = relalist; tmpl != NULL; tmpl = tmpl->next) {
+ if (xwriteatoff(fd, tmpl->mem, tmpl->file, tmpl->size, fn) !=
+ tmpl->size)
+ goto bad;
+ }
+ for (tmpl = rellist; tmpl != NULL; tmpl = tmpl->next) {
+ if (xwriteatoff(fd, tmpl->mem, tmpl->file, tmpl->size, fn) !=
+ tmpl->size)
+ goto bad;
+ }
+
+out:
+ if (shdrp != NULL)
+ free(shdrp);
+ if (symtabp != NULL)
+ free(symtabp);
+ if (strtabp != NULL)
+ free(strtabp);
+ if (symfwmap != NULL)
+ free(symfwmap);
+ if (symrvmap != NULL)
+ free(symrvmap);
+ while ((tmpl = relalist) != NULL) {
+ relalist = tmpl->next;
+ if (tmpl->mem != NULL)
+ free(tmpl->mem);
+ free(tmpl);
+ }
+ while ((tmpl = rellist) != NULL) {
+ rellist = tmpl->next;
+ if (tmpl->mem != NULL)
+ free(tmpl->mem);
+ free(tmpl);
+ }
+ return (rv);
+
+bad:
+ rv = 1;
+ goto out;
+}
+
+#endif /* include this size of ELF */
OpenPOWER on IntegriCloud