1 /* $NetBSD: exec_aout.c,v 1.9 2000/06/14 06:49:20 cgd Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Christopher G. Demetriou. All rights reserved. 5 * Copyright (c) 1994 University of Maryland 6 * All Rights Reserved. 7 * 8 * Permission to use, copy, modify, distribute, and sell this software and its 9 * documentation for any purpose is hereby granted without fee, provided that 10 * the above copyright notice appear in all copies and that both that 11 * copyright notice and this permission notice appear in supporting 12 * documentation, and that the name of U.M. not be used in advertising or 13 * publicity pertaining to distribution of the software without specific, 14 * written prior permission. U.M. makes no representations about the 15 * suitability of this software for any purpose. It is provided "as is" 16 * without express or implied warranty. 17 * 18 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. 20 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 22 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 23 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 * 25 * Author: James da Silva, Systems Design and Analysis Group 26 * Computer Science Department 27 * University of Maryland at College Park 28 */ 29 30 #include <sys/cdefs.h> 31 #ifndef lint 32 __RCSID("$NetBSD: exec_aout.c,v 1.9 2000/06/14 06:49:20 cgd Exp $"); 33 #endif 34 35 #include <unistd.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <errno.h> 40 #include <a.out.h> 41 #include <sys/types.h> 42 #include <sys/stat.h> 43 44 #include "extern.h" 45 46 #if defined(NLIST_AOUT) 47 48 int nsyms, ntextrel, ndatarel; 49 struct exec *hdrp; 50 char *aoutdata, *strbase; 51 struct relocation_info *textrel, *datarel; 52 struct nlist *symbase; 53 54 55 #define SYMSTR(sp) (&strbase[(sp)->n_un.n_strx]) 56 57 /* is the symbol a global symbol defined in the current file? */ 58 #define IS_GLOBAL_DEFINED(sp) \ 59 (((sp)->n_type & N_EXT) && ((sp)->n_type & N_TYPE) != N_UNDF) 60 61 #ifdef __sparc__ 62 /* is the relocation entry dependent on a symbol? */ 63 #define IS_SYMBOL_RELOC(rp) \ 64 ((rp)->r_extern || \ 65 ((rp)->r_type >= RELOC_BASE10 && (rp)->r_type <= RELOC_BASE22) || \ 66 (rp)->r_type == RELOC_JMP_TBL) 67 #else 68 /* is the relocation entry dependent on a symbol? */ 69 #define IS_SYMBOL_RELOC(rp) \ 70 ((rp)->r_extern||(rp)->r_baserel||(rp)->r_jmptable) 71 #endif 72 73 static void check_reloc(const char *filename, struct relocation_info *relp); 74 75 int check_aout(int inf, const char *filename) 76 { 77 struct stat infstat; 78 struct exec eh; 79 80 /* 81 * check the header to make sure it's an a.out-format file. 82 */ 83 84 if(fstat(inf, &infstat) == -1) 85 return 0; 86 if(infstat.st_size < sizeof eh) 87 return 0; 88 if(read(inf, &eh, sizeof eh) != sizeof eh) 89 return 0; 90 91 if(N_BADMAG(eh)) 92 return 0; 93 94 return 1; 95 } 96 97 int hide_aout(int inf, const char *filename) 98 { 99 struct stat infstat; 100 struct relocation_info *relp; 101 struct nlist *symp; 102 int rc; 103 104 /* 105 * do some error checking. 106 */ 107 108 if(fstat(inf, &infstat) == -1) { 109 perror(filename); 110 return 1; 111 } 112 113 /* 114 * Read the entire file into memory. XXX - Really, we only need to 115 * read the header and from TRELOFF to the end of the file. 116 */ 117 118 if((aoutdata = (char *) malloc(infstat.st_size)) == NULL) { 119 fprintf(stderr, "%s: too big to read into memory\n", filename); 120 return 1; 121 } 122 123 if((rc = read(inf, aoutdata, infstat.st_size)) < infstat.st_size) { 124 fprintf(stderr, "%s: read error: %s\n", filename, 125 rc == -1? strerror(errno) : "short read"); 126 return 1; 127 } 128 129 /* 130 * Calculate offsets and sizes from the header. 131 */ 132 133 hdrp = (struct exec *) aoutdata; 134 135 #ifdef __FreeBSD__ 136 textrel = (struct relocation_info *) (aoutdata + N_RELOFF(*hdrp)); 137 datarel = (struct relocation_info *) (aoutdata + N_RELOFF(*hdrp) + 138 hdrp->a_trsize); 139 #else 140 textrel = (struct relocation_info *) (aoutdata + N_TRELOFF(*hdrp)); 141 datarel = (struct relocation_info *) (aoutdata + N_DRELOFF(*hdrp)); 142 #endif 143 symbase = (struct nlist *) (aoutdata + N_SYMOFF(*hdrp)); 144 strbase = (char *) (aoutdata + N_STROFF(*hdrp)); 145 146 ntextrel = hdrp->a_trsize / sizeof(struct relocation_info); 147 ndatarel = hdrp->a_drsize / sizeof(struct relocation_info); 148 nsyms = hdrp->a_syms / sizeof(struct nlist); 149 150 /* 151 * Zap the type field of all globally-defined symbols. The linker will 152 * subsequently ignore these entries. Don't zap any symbols in the 153 * keep list. 154 */ 155 156 for(symp = symbase; symp < symbase + nsyms; symp++) { 157 if(!IS_GLOBAL_DEFINED(symp)) /* keep undefined syms */ 158 continue; 159 160 /* keep (C) symbols which are on the keep list */ 161 if(SYMSTR(symp)[0] == '_' && in_keep_list(SYMSTR(symp) + 1)) 162 continue; 163 164 symp->n_type = 0; 165 } 166 167 /* 168 * Check whether the relocation entries reference any symbols that we 169 * just zapped. I don't know whether ld can handle this case, but I 170 * haven't encountered it yet. These checks are here so that the program 171 * doesn't fail silently should such symbols be encountered. 172 */ 173 174 for(relp = textrel; relp < textrel + ntextrel; relp++) 175 check_reloc(filename, relp); 176 for(relp = datarel; relp < datarel + ndatarel; relp++) 177 check_reloc(filename, relp); 178 179 /* 180 * Write the .o file back out to disk. XXX - Really, we only need to 181 * write the symbol table entries back out. 182 */ 183 lseek(inf, 0, SEEK_SET); 184 if((rc = write(inf, aoutdata, infstat.st_size)) < infstat.st_size) { 185 fprintf(stderr, "%s: write error: %s\n", filename, 186 rc == -1? strerror(errno) : "short write"); 187 return 1; 188 } 189 190 return 0; 191 } 192 193 194 static void check_reloc(const char *filename, struct relocation_info *relp) 195 { 196 /* bail out if we zapped a symbol that is needed */ 197 if(IS_SYMBOL_RELOC(relp) && symbase[relp->r_symbolnum].n_type == 0) { 198 fprintf(stderr, 199 "%s: oops, have hanging relocation for %s: bailing out!\n", 200 filename, SYMSTR(&symbase[relp->r_symbolnum])); 201 exit(1); 202 } 203 } 204 205 #endif /* defined(NLIST_AOUT) */ 206