summaryrefslogtreecommitdiffstats
path: root/usr.sbin/crunch/crunchide/exec_aout.c
blob: a608c233166648fb983768808fb62ce6796d119e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/*	$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 $");
__FBSDID("$FreeBSD$");
#endif
 
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <a.out.h>
#include <sys/types.h>
#include <sys/endian.h>
#include <sys/stat.h> 
#include <sys/errno.h>
#include <netinet/in.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)

/* is the relocation entry dependent on a symbol? */
#define IS_SYMBOL_RELOC(rp)   \
                  ((rp)->r_extern||(rp)->r_baserel||(rp)->r_jmptable)

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) */
OpenPOWER on IntegriCloud