diff options
author | jkh <jkh@FreeBSD.org> | 1998-09-14 11:35:32 +0000 |
---|---|---|
committer | jkh <jkh@FreeBSD.org> | 1998-09-14 11:35:32 +0000 |
commit | a4969a17ca93b529c57b07fb44668d7563024d3f (patch) | |
tree | 593ab577b803f64ca18aad0944f5c5ca1b308269 /usr.sbin | |
parent | e7f0dcd13762c2e1e086d5e60434578e55b0d1a6 (diff) | |
download | FreeBSD-src-a4969a17ca93b529c57b07fb44668d7563024d3f.zip FreeBSD-src-a4969a17ca93b529c57b07fb44668d7563024d3f.tar.gz |
Teach crunch about an elf/a.out world.
Submitted by: jhay
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/crunch/crunchide/Makefile | 2 | ||||
-rw-r--r-- | usr.sbin/crunch/crunchide/crunchide.c | 233 | ||||
-rw-r--r-- | usr.sbin/crunch/crunchide/exec_aout.c | 203 | ||||
-rw-r--r-- | usr.sbin/crunch/crunchide/exec_elf32.c | 389 | ||||
-rw-r--r-- | usr.sbin/crunch/crunchide/exec_elf64.c | 40 | ||||
-rw-r--r-- | usr.sbin/crunch/crunchide/extern.h | 68 |
6 files changed, 795 insertions, 140 deletions
diff --git a/usr.sbin/crunch/crunchide/Makefile b/usr.sbin/crunch/crunchide/Makefile index f6e1a8a..d7abd44 100644 --- a/usr.sbin/crunch/crunchide/Makefile +++ b/usr.sbin/crunch/crunchide/Makefile @@ -1,4 +1,6 @@ PROG= crunchide +SRCS= crunchide.c exec_aout.c exec_elf32.c exec_elf64.c + .include <bsd.prog.mk> diff --git a/usr.sbin/crunch/crunchide/crunchide.c b/usr.sbin/crunch/crunchide/crunchide.c index 2edc082..04bec03 100644 --- a/usr.sbin/crunch/crunchide/crunchide.c +++ b/usr.sbin/crunch/crunchide/crunchide.c @@ -1,4 +1,6 @@ +/* $NetBSD: crunchide.c,v 1.8 1997/11/01 06:51:45 lukem Exp $ */ /* + * Copyright (c) 1997 Christopher G. Demetriou. All rights reserved. * Copyright (c) 1994 University of Maryland * All Rights Reserved. * @@ -56,32 +58,45 @@ * that the final crunched binary BSS size is the max of all the * component programs' BSS sizes, rather than their sum. */ -#include <a.out.h> -#include <err.h> -#include <fcntl.h> +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: crunchide.c,v 1.8 1997/11/01 06:51:45 lukem Exp $"); +#endif + +#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <unistd.h> +#include <fcntl.h> +#include <a.out.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/errno.h> +#include "extern.h" + +char *pname = "crunchide"; + void usage(void); void add_to_keep_list(char *symbol); void add_file_to_keep_list(char *filename); -void hide_syms(char *filename); +int hide_syms(const char *filename); + +int verbose; +int main __P((int, char *[])); int main(argc, argv) int argc; char **argv; { - int ch; + int ch, errors; + + if(argc > 0) pname = argv[0]; - while ((ch = getopt(argc, argv, "k:f:")) != -1) + while ((ch = getopt(argc, argv, "k:f:v")) != -1) switch(ch) { case 'k': add_to_keep_list(optarg); @@ -89,6 +104,9 @@ char **argv; case 'f': add_file_to_keep_list(optarg); break; + case 'v': + verbose = 1; + break; default: usage(); } @@ -98,18 +116,21 @@ char **argv; if(argc == 0) usage(); + errors = 0; while(argc) { - hide_syms(*argv); + if (hide_syms(*argv)) + errors = 1; argc--, argv++; } - return 0; + return errors; } void usage(void) { fprintf(stderr, - "usage: crunchide [-k <symbol-name>] [-f <keep-list-file>] <files> ...\n"); + "Usage: %s [-k <symbol-name>] [-f <keep-list-file>] <files> ...\n", + pname); exit(1); } @@ -125,6 +146,8 @@ void add_to_keep_list(char *symbol) struct keep *newp, *prevp, *curp; int cmp; + cmp = 0; + for(curp = keep_list, prevp = NULL; curp; prevp = curp, curp = curp->next) if((cmp = strcmp(symbol, curp->sym)) <= 0) break; @@ -134,7 +157,8 @@ void add_to_keep_list(char *symbol) newp = (struct keep *) malloc(sizeof(struct keep)); if(newp) newp->sym = strdup(symbol); if(newp == NULL || newp->sym == NULL) { - errx(1, "out of memory for keep list"); + fprintf(stderr, "%s: out of memory for keep list\n", pname); + exit(1); } newp->next = curp; @@ -142,11 +166,13 @@ void add_to_keep_list(char *symbol) else keep_list = newp; } -int in_keep_list(char *symbol) +int in_keep_list(const char *symbol) { struct keep *curp; int cmp; + cmp = 0; + for(curp = keep_list; curp; curp = curp->next) if((cmp = strcmp(symbol, curp->sym)) <= 0) break; @@ -160,7 +186,7 @@ void add_file_to_keep_list(char *filename) int len; if((keepf = fopen(filename, "r")) == NULL) { - warn("%s", filename); + perror(filename); usage(); } @@ -174,141 +200,68 @@ void add_file_to_keep_list(char *filename) fclose(keepf); } -/* ---------------------- */ - -int nsyms, ntextrel, ndatarel; -struct exec *hdrp; -char *aoutdata, *strbase; -struct relocation_info *textrel, *datarel; -struct nlist *symbase; - - -#define SYMSTR(sp) &strbase[(sp)->n_un.n_strx] - -/* is the symbol a global symbol defined in the current file? */ -#define IS_GLOBAL_DEFINED(sp) \ - (((sp)->n_type & N_EXT) && ((sp)->n_type & N_TYPE) != N_UNDF) - -/* is the relocation entry dependent on a symbol? */ -#define IS_SYMBOL_RELOC(rp) \ - ((rp)->r_extern||(rp)->r_baserel||(rp)->r_jmptable) +/* ---------------------------- */ -void check_reloc(char *filename, struct relocation_info *relp); +struct { + const char *name; + int (*check)(int, const char *); /* 1 if match, zero if not */ + int (*hide)(int, const char *); /* non-zero if error */ +} exec_formats[] = { +#ifdef NLIST_AOUT + { "a.out", check_aout, hide_aout, }, +#endif +#ifdef NLIST_ECOFF + { "ECOFF", check_ecoff, hide_ecoff, }, +#endif +#ifdef NLIST_ELF32 + { "ELF32", check_elf32, hide_elf32, }, +#endif +#ifdef NLIST_ELF64 + { "ELF64", check_elf64, hide_elf64, }, +#endif +}; -void hide_syms(char *filename) +int hide_syms(const char *filename) { - int inf, rc; - struct stat infstat; - struct relocation_info *relp; - struct nlist *symp; - - /* - * Open the file and do some error checking. - */ - - if((inf = open(filename, O_RDWR)) == -1) { - warn("%s", filename); - return; - } - - if(fstat(inf, &infstat) == -1) { - warn("%s", filename); - close(inf); - return; - } - - if(infstat.st_size < sizeof(struct exec)) { - warnx("%s: short file", filename); - close(inf); - return; - } - - /* - * Read the entire file into memory. XXX - Really, we only need to - * read the header and from TRELOFF to the end of the file. - */ - - if((aoutdata = (char *) malloc(infstat.st_size)) == NULL) { - warnx("%s: too big to read into memory", filename); - close(inf); - return; - } - - if((rc = read(inf, aoutdata, infstat.st_size)) < infstat.st_size) { - warnx("%s: read error: %s", filename, - rc == -1? strerror(errno) : "short read"); - close(inf); - return; - } + int fd, i, n, rv; - /* - * Check the header and calculate offsets and sizes from it. - */ + fd = open(filename, O_RDWR, 0); + if (fd == -1) { + perror(filename); + return 1; + } - hdrp = (struct exec *) aoutdata; + rv = 0; - if(N_BADMAG(*hdrp)) { - warnx("%s: bad magic: not an a.out file", filename); - close(inf); - return; - } + n = sizeof exec_formats / sizeof exec_formats[0]; + for (i = 0; i < n; i++) { + if (lseek(fd, 0, SEEK_SET) != 0) { + perror(filename); + goto err; + } + if ((*exec_formats[i].check)(fd, filename) != 0) + break; + } + if (i == n) { + fprintf(stderr, "%s: unknown executable format\n", filename); + goto err; + } -#ifdef __FreeBSD__ - textrel = (struct relocation_info *) (aoutdata + N_RELOFF(*hdrp)); - datarel = (struct relocation_info *) (aoutdata + N_RELOFF(*hdrp) + - hdrp->a_trsize); -#else - textrel = (struct relocation_info *) (aoutdata + N_TRELOFF(*hdrp)); - datarel = (struct relocation_info *) (aoutdata + N_DRELOFF(*hdrp)); -#endif - symbase = (struct nlist *) (aoutdata + N_SYMOFF(*hdrp)); - strbase = (char *) (aoutdata + N_STROFF(*hdrp)); - - ntextrel = hdrp->a_trsize / sizeof(struct relocation_info); - ndatarel = hdrp->a_drsize / sizeof(struct relocation_info); - nsyms = hdrp->a_syms / sizeof(struct nlist); - - /* - * Zap the type field of all globally-defined symbols. The linker will - * subsequently ignore these entries. Don't zap any symbols in the - * keep list. - */ - - for(symp = symbase; symp < symbase + nsyms; symp++) - if(IS_GLOBAL_DEFINED(symp) && !in_keep_list(SYMSTR(symp))) - symp->n_type = 0; - - /* - * Check whether the relocation entries reference any symbols that we - * just zapped. I don't know whether ld can handle this case, but I - * haven't encountered it yet. These checks are here so that the program - * doesn't fail silently should such symbols be encountered. - */ - - for(relp = textrel; relp < textrel + ntextrel; relp++) - check_reloc(filename, relp); - for(relp = datarel; relp < datarel + ndatarel; relp++) - check_reloc(filename, relp); - - /* - * Write the .o file back out to disk. XXX - Really, we only need to - * write the symbol table entries back out. - */ - lseek(inf, 0, SEEK_SET); - if((rc = write(inf, aoutdata, infstat.st_size)) < infstat.st_size) { - warnx("%s: write error: %s", filename, - rc == -1? strerror(errno) : "short write"); - } + if (verbose) + fprintf(stderr, "%s is an %s binary\n", filename, + exec_formats[i].name); - close(inf); -} + if (lseek(fd, 0, SEEK_SET) != 0) { + perror(filename); + goto err; + } + rv = (*exec_formats[i].hide)(fd, filename); +out: + close (fd); + return (rv); -void check_reloc(char *filename, struct relocation_info *relp) -{ - /* bail out if we zapped a symbol that is needed */ - if(IS_SYMBOL_RELOC(relp) && symbase[relp->r_symbolnum].n_type == 0) { - errx(1, "%s: oops, have hanging relocation for %s: bailing out!", - filename, SYMSTR(&symbase[relp->r_symbolnum])); - } +err: + rv = 1; + goto out; } diff --git a/usr.sbin/crunch/crunchide/exec_aout.c b/usr.sbin/crunch/crunchide/exec_aout.c new file mode 100644 index 0000000..9f68115 --- /dev/null +++ b/usr.sbin/crunch/crunchide/exec_aout.c @@ -0,0 +1,203 @@ +/* $NetBSD: exec_aout.c,v 1.6 1997/08/02 21:30:17 perry Exp $ */ +/* + * Copyright (c) 1997 Christopher G. Demetriou. All rights reserved. + * Copyright (c) 1994 University of Maryland + * All Rights Reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of U.M. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. U.M. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. + * BE LIABLE FOR ANY SPECIAL, 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. + * + * Author: James da Silva, Systems Design and Analysis Group + * Computer Science Department + * University of Maryland at College Park + */ +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: exec_aout.c,v 1.6 1997/08/02 21:30:17 perry Exp $"); +#endif + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <a.out.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/errno.h> + +#include "extern.h" + +#if defined(NLIST_AOUT) + +int nsyms, ntextrel, ndatarel; +struct exec *hdrp; +char *aoutdata, *strbase; +struct relocation_info *textrel, *datarel; +struct nlist *symbase; + + +#define SYMSTR(sp) (&strbase[(sp)->n_un.n_strx]) + +/* is the symbol a global symbol defined in the current file? */ +#define IS_GLOBAL_DEFINED(sp) \ + (((sp)->n_type & N_EXT) && ((sp)->n_type & N_TYPE) != N_UNDF) + +#ifdef __sparc +/* is the relocation entry dependent on a symbol? */ +#define IS_SYMBOL_RELOC(rp) \ + ((rp)->r_extern || \ + ((rp)->r_type >= RELOC_BASE10 && (rp)->r_type <= RELOC_BASE22) || \ + (rp)->r_type == RELOC_JMP_TBL) +#else +/* is the relocation entry dependent on a symbol? */ +#define IS_SYMBOL_RELOC(rp) \ + ((rp)->r_extern||(rp)->r_baserel||(rp)->r_jmptable) +#endif + +static void check_reloc(const char *filename, struct relocation_info *relp); + +int check_aout(int inf, const char *filename) +{ + struct stat infstat; + struct exec eh; + + /* + * check the header to make sure it's an a.out-format file. + */ + + if(fstat(inf, &infstat) == -1) + return 0; + if(infstat.st_size < sizeof eh) + return 0; + if(read(inf, &eh, sizeof eh) != sizeof eh) + return 0; + + if(N_BADMAG(eh)) + return 0; + + return 1; +} + +int hide_aout(int inf, const char *filename) +{ + struct stat infstat; + struct relocation_info *relp; + struct nlist *symp; + int rc; + + /* + * do some error checking. + */ + + if(fstat(inf, &infstat) == -1) { + perror(filename); + return 1; + } + + /* + * Read the entire file into memory. XXX - Really, we only need to + * read the header and from TRELOFF to the end of the file. + */ + + if((aoutdata = (char *) malloc(infstat.st_size)) == NULL) { + fprintf(stderr, "%s: too big to read into memory\n", filename); + return 1; + } + + if((rc = read(inf, aoutdata, infstat.st_size)) < infstat.st_size) { + fprintf(stderr, "%s: read error: %s\n", filename, + rc == -1? strerror(errno) : "short read"); + return 1; + } + + /* + * Calculate offsets and sizes from the header. + */ + + hdrp = (struct exec *) aoutdata; + +#ifdef __FreeBSD__ + textrel = (struct relocation_info *) (aoutdata + N_RELOFF(*hdrp)); + datarel = (struct relocation_info *) (aoutdata + N_RELOFF(*hdrp) + + hdrp->a_trsize); +#else + textrel = (struct relocation_info *) (aoutdata + N_TRELOFF(*hdrp)); + datarel = (struct relocation_info *) (aoutdata + N_DRELOFF(*hdrp)); +#endif + symbase = (struct nlist *) (aoutdata + N_SYMOFF(*hdrp)); + strbase = (char *) (aoutdata + N_STROFF(*hdrp)); + + ntextrel = hdrp->a_trsize / sizeof(struct relocation_info); + ndatarel = hdrp->a_drsize / sizeof(struct relocation_info); + nsyms = hdrp->a_syms / sizeof(struct nlist); + + /* + * Zap the type field of all globally-defined symbols. The linker will + * subsequently ignore these entries. Don't zap any symbols in the + * keep list. + */ + + for(symp = symbase; symp < symbase + nsyms; symp++) { + if(!IS_GLOBAL_DEFINED(symp)) /* keep undefined syms */ + continue; + + /* keep (C) symbols which are on the keep list */ + if(SYMSTR(symp)[0] == '_' && in_keep_list(SYMSTR(symp) + 1)) + continue; + + symp->n_type = 0; + } + + /* + * Check whether the relocation entries reference any symbols that we + * just zapped. I don't know whether ld can handle this case, but I + * haven't encountered it yet. These checks are here so that the program + * doesn't fail silently should such symbols be encountered. + */ + + for(relp = textrel; relp < textrel + ntextrel; relp++) + check_reloc(filename, relp); + for(relp = datarel; relp < datarel + ndatarel; relp++) + check_reloc(filename, relp); + + /* + * Write the .o file back out to disk. XXX - Really, we only need to + * write the symbol table entries back out. + */ + lseek(inf, 0, SEEK_SET); + if((rc = write(inf, aoutdata, infstat.st_size)) < infstat.st_size) { + fprintf(stderr, "%s: write error: %s\n", filename, + rc == -1? strerror(errno) : "short write"); + return 1; + } + + return 0; +} + + +static void check_reloc(const char *filename, struct relocation_info *relp) +{ + /* bail out if we zapped a symbol that is needed */ + if(IS_SYMBOL_RELOC(relp) && symbase[relp->r_symbolnum].n_type == 0) { + fprintf(stderr, + "%s: oops, have hanging relocation for %s: bailing out!\n", + filename, SYMSTR(&symbase[relp->r_symbolnum])); + exit(1); + } +} + +#endif /* defined(NLIST_AOUT) */ 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 */ diff --git a/usr.sbin/crunch/crunchide/exec_elf64.c b/usr.sbin/crunch/crunchide/exec_elf64.c new file mode 100644 index 0000000..962cc07 --- /dev/null +++ b/usr.sbin/crunch/crunchide/exec_elf64.c @@ -0,0 +1,40 @@ +/* $NetBSD: exec_elf64.c,v 1.2 1997/08/02 21:30:19 perry 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 +__IDSTRING(elf64rcsid, "$NetBSD: exec_elf64.c,v 1.2 1997/08/02 21:30:19 perry Exp $"); +#endif + +#define ELFSIZE 64 + +#include "exec_elf32.c" diff --git a/usr.sbin/crunch/crunchide/extern.h b/usr.sbin/crunch/crunchide/extern.h new file mode 100644 index 0000000..a3d6586 --- /dev/null +++ b/usr.sbin/crunch/crunchide/extern.h @@ -0,0 +1,68 @@ +/* $NetBSD: extern.h,v 1.5 1998/05/06 13:16:57 mycroft 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. + */ + +#ifdef __alpha__ +#define NLIST_ECOFF +#define NLIST_ELF64 +#else +#ifdef __mips__ +#define NLIST_ELF32 +#else +#ifdef __powerpc__ +#define NLIST_ELF32 +#else +#define NLIST_AOUT +/* #define NLIST_ECOFF */ +#define NLIST_ELF32 +/* #define NLIST_ELF64 */ +#endif +#endif +#endif + +#ifdef NLIST_AOUT +int check_aout(int, const char *); +int hide_aout(int, const char *); +#endif +#ifdef NLIST_ECOFF +int check_ecoff(int, const char *); +int hide_ecoff(int, const char *); +#endif +#ifdef NLIST_ELF32 +int check_elf32(int, const char *); +int hide_elf32(int, const char *); +#endif +#ifdef NLIST_ELF64 +int check_elf64(int, const char *); +int hide_elf64(int, const char *); +#endif + +int in_keep_list(const char *symbol); |