139172Sjkh/* $NetBSD: exec_aout.c,v 1.6 1997/08/02 21:30:17 perry Exp $ */ 239172Sjkh/* 339172Sjkh * Copyright (c) 1997 Christopher G. Demetriou. All rights reserved. 439172Sjkh * Copyright (c) 1994 University of Maryland 539172Sjkh * All Rights Reserved. 639172Sjkh * 739172Sjkh * Permission to use, copy, modify, distribute, and sell this software and its 839172Sjkh * documentation for any purpose is hereby granted without fee, provided that 939172Sjkh * the above copyright notice appear in all copies and that both that 1039172Sjkh * copyright notice and this permission notice appear in supporting 1139172Sjkh * documentation, and that the name of U.M. not be used in advertising or 1239172Sjkh * publicity pertaining to distribution of the software without specific, 1339172Sjkh * written prior permission. U.M. makes no representations about the 1439172Sjkh * suitability of this software for any purpose. It is provided "as is" 1539172Sjkh * without express or implied warranty. 1639172Sjkh * 1739172Sjkh * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 1839172Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. 1939172Sjkh * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 2039172Sjkh * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 2139172Sjkh * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 2239172Sjkh * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 2339172Sjkh * 2439172Sjkh * Author: James da Silva, Systems Design and Analysis Group 2539172Sjkh * Computer Science Department 2639172Sjkh * University of Maryland at College Park 2739172Sjkh */ 2839172Sjkh#include <sys/cdefs.h> 2939172Sjkh#ifndef lint 3039172Sjkh__RCSID("$NetBSD: exec_aout.c,v 1.6 1997/08/02 21:30:17 perry Exp $"); 3195781Sru__FBSDID("$FreeBSD$"); 3239172Sjkh#endif 3339172Sjkh 3439172Sjkh#include <unistd.h> 3539172Sjkh#include <stdio.h> 3639172Sjkh#include <stdlib.h> 3739172Sjkh#include <string.h> 3839172Sjkh#include <a.out.h> 3939172Sjkh#include <sys/types.h> 40130927Sobrien#include <sys/endian.h> 4139172Sjkh#include <sys/stat.h> 4239172Sjkh#include <sys/errno.h> 43129652Sstefanf#include <netinet/in.h> 4439172Sjkh 4539172Sjkh#include "extern.h" 4639172Sjkh 4739172Sjkh#if defined(NLIST_AOUT) 4839172Sjkh 4939172Sjkhint nsyms, ntextrel, ndatarel; 5039172Sjkhstruct exec *hdrp; 5139172Sjkhchar *aoutdata, *strbase; 5239172Sjkhstruct relocation_info *textrel, *datarel; 5339172Sjkhstruct nlist *symbase; 5439172Sjkh 5539172Sjkh 5639172Sjkh#define SYMSTR(sp) (&strbase[(sp)->n_un.n_strx]) 5739172Sjkh 5839172Sjkh/* is the symbol a global symbol defined in the current file? */ 5939172Sjkh#define IS_GLOBAL_DEFINED(sp) \ 6039172Sjkh (((sp)->n_type & N_EXT) && ((sp)->n_type & N_TYPE) != N_UNDF) 6139172Sjkh 6239172Sjkh/* is the relocation entry dependent on a symbol? */ 6339172Sjkh#define IS_SYMBOL_RELOC(rp) \ 6439172Sjkh ((rp)->r_extern||(rp)->r_baserel||(rp)->r_jmptable) 6539172Sjkh 6639172Sjkhstatic void check_reloc(const char *filename, struct relocation_info *relp); 6739172Sjkh 6839172Sjkhint check_aout(int inf, const char *filename) 6939172Sjkh{ 7039172Sjkh struct stat infstat; 7139172Sjkh struct exec eh; 7239172Sjkh 7339172Sjkh /* 7439172Sjkh * check the header to make sure it's an a.out-format file. 7539172Sjkh */ 7639172Sjkh 7739172Sjkh if(fstat(inf, &infstat) == -1) 7839172Sjkh return 0; 7939172Sjkh if(infstat.st_size < sizeof eh) 8039172Sjkh return 0; 8139172Sjkh if(read(inf, &eh, sizeof eh) != sizeof eh) 8239172Sjkh return 0; 8339172Sjkh 8439172Sjkh if(N_BADMAG(eh)) 8539172Sjkh return 0; 8639172Sjkh 8739172Sjkh return 1; 8839172Sjkh} 8939172Sjkh 9039172Sjkhint hide_aout(int inf, const char *filename) 9139172Sjkh{ 9239172Sjkh struct stat infstat; 9339172Sjkh struct relocation_info *relp; 9439172Sjkh struct nlist *symp; 9539172Sjkh int rc; 9639172Sjkh 9739172Sjkh /* 9839172Sjkh * do some error checking. 9939172Sjkh */ 10039172Sjkh 10139172Sjkh if(fstat(inf, &infstat) == -1) { 10239172Sjkh perror(filename); 10339172Sjkh return 1; 10439172Sjkh } 10539172Sjkh 10639172Sjkh /* 10739172Sjkh * Read the entire file into memory. XXX - Really, we only need to 10839172Sjkh * read the header and from TRELOFF to the end of the file. 10939172Sjkh */ 11039172Sjkh 11139172Sjkh if((aoutdata = (char *) malloc(infstat.st_size)) == NULL) { 11239172Sjkh fprintf(stderr, "%s: too big to read into memory\n", filename); 11339172Sjkh return 1; 11439172Sjkh } 11539172Sjkh 11639172Sjkh if((rc = read(inf, aoutdata, infstat.st_size)) < infstat.st_size) { 11739172Sjkh fprintf(stderr, "%s: read error: %s\n", filename, 11839172Sjkh rc == -1? strerror(errno) : "short read"); 11939172Sjkh return 1; 12039172Sjkh } 12139172Sjkh 12239172Sjkh /* 12339172Sjkh * Calculate offsets and sizes from the header. 12439172Sjkh */ 12539172Sjkh 12639172Sjkh hdrp = (struct exec *) aoutdata; 12739172Sjkh 12839172Sjkh#ifdef __FreeBSD__ 12939172Sjkh textrel = (struct relocation_info *) (aoutdata + N_RELOFF(*hdrp)); 13039172Sjkh datarel = (struct relocation_info *) (aoutdata + N_RELOFF(*hdrp) + 13139172Sjkh hdrp->a_trsize); 13239172Sjkh#else 13339172Sjkh textrel = (struct relocation_info *) (aoutdata + N_TRELOFF(*hdrp)); 13439172Sjkh datarel = (struct relocation_info *) (aoutdata + N_DRELOFF(*hdrp)); 13539172Sjkh#endif 13639172Sjkh symbase = (struct nlist *) (aoutdata + N_SYMOFF(*hdrp)); 13739172Sjkh strbase = (char *) (aoutdata + N_STROFF(*hdrp)); 13839172Sjkh 13939172Sjkh ntextrel = hdrp->a_trsize / sizeof(struct relocation_info); 14039172Sjkh ndatarel = hdrp->a_drsize / sizeof(struct relocation_info); 14139172Sjkh nsyms = hdrp->a_syms / sizeof(struct nlist); 14239172Sjkh 14339172Sjkh /* 14439172Sjkh * Zap the type field of all globally-defined symbols. The linker will 14539172Sjkh * subsequently ignore these entries. Don't zap any symbols in the 14639172Sjkh * keep list. 14739172Sjkh */ 14839172Sjkh 14939172Sjkh for(symp = symbase; symp < symbase + nsyms; symp++) { 15039172Sjkh if(!IS_GLOBAL_DEFINED(symp)) /* keep undefined syms */ 15139172Sjkh continue; 15239172Sjkh 15339172Sjkh /* keep (C) symbols which are on the keep list */ 15439172Sjkh if(SYMSTR(symp)[0] == '_' && in_keep_list(SYMSTR(symp) + 1)) 15539172Sjkh continue; 15639172Sjkh 15739172Sjkh symp->n_type = 0; 15839172Sjkh } 15939172Sjkh 16039172Sjkh /* 16139172Sjkh * Check whether the relocation entries reference any symbols that we 16239172Sjkh * just zapped. I don't know whether ld can handle this case, but I 16339172Sjkh * haven't encountered it yet. These checks are here so that the program 16439172Sjkh * doesn't fail silently should such symbols be encountered. 16539172Sjkh */ 16639172Sjkh 16739172Sjkh for(relp = textrel; relp < textrel + ntextrel; relp++) 16839172Sjkh check_reloc(filename, relp); 16939172Sjkh for(relp = datarel; relp < datarel + ndatarel; relp++) 17039172Sjkh check_reloc(filename, relp); 17139172Sjkh 17239172Sjkh /* 17339172Sjkh * Write the .o file back out to disk. XXX - Really, we only need to 17439172Sjkh * write the symbol table entries back out. 17539172Sjkh */ 17639172Sjkh lseek(inf, 0, SEEK_SET); 17739172Sjkh if((rc = write(inf, aoutdata, infstat.st_size)) < infstat.st_size) { 17839172Sjkh fprintf(stderr, "%s: write error: %s\n", filename, 17939172Sjkh rc == -1? strerror(errno) : "short write"); 18039172Sjkh return 1; 18139172Sjkh } 18239172Sjkh 18339172Sjkh return 0; 18439172Sjkh} 18539172Sjkh 18639172Sjkh 18739172Sjkhstatic void check_reloc(const char *filename, struct relocation_info *relp) 18839172Sjkh{ 18939172Sjkh /* bail out if we zapped a symbol that is needed */ 19039172Sjkh if(IS_SYMBOL_RELOC(relp) && symbase[relp->r_symbolnum].n_type == 0) { 19139172Sjkh fprintf(stderr, 19239172Sjkh "%s: oops, have hanging relocation for %s: bailing out!\n", 19339172Sjkh filename, SYMSTR(&symbase[relp->r_symbolnum])); 19439172Sjkh exit(1); 19539172Sjkh } 19639172Sjkh} 19739172Sjkh 19839172Sjkh#endif /* defined(NLIST_AOUT) */ 199