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