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
199
200
201
|
#include <a.out.h>
#include "gprof.h"
static void getstrtab(FILE *, const char *);
static void getsymtab(FILE *, const char *);
static void gettextspace(FILE *);
static bool funcsymbol(struct nlist *);
static char *strtab; /* string table in core */
static long ssiz; /* size of the string table */
static struct exec xbuf; /* exec header of a.out */
/* Things which get -E excluded by default. */
static char *excludes[] = { "mcount", "__mcleanup", NULL };
/*
* Set up string and symbol tables from a.out.
* and optionally the text space.
* On return symbol table is sorted by value.
*
* Returns 0 on success, -1 on failure.
*/
int
aout_getnfile(const char *filename, char ***defaultEs)
{
FILE *nfile;
int valcmp();
nfile = fopen( filename ,"r");
if (nfile == NULL) {
perror( filename );
done();
}
fread(&xbuf, 1, sizeof(xbuf), nfile);
if (N_BADMAG(xbuf)) {
fclose(nfile);
return -1;
}
getstrtab(nfile, filename);
getsymtab(nfile, filename);
gettextspace( nfile );
fclose(nfile);
# ifdef DEBUG
if ( debug & AOUTDEBUG ) {
register int j;
for (j = 0; j < nname; j++){
printf("[getnfile] 0X%08x\t%s\n", nl[j].value, nl[j].name);
}
}
# endif DEBUG
*defaultEs = excludes;
return 0;
}
static void
getstrtab(FILE *nfile, const char *filename)
{
fseek(nfile, (long)(N_SYMOFF(xbuf) + xbuf.a_syms), 0);
if (fread(&ssiz, sizeof (ssiz), 1, nfile) == 0) {
warnx("%s: no string table (old format?)" , filename );
done();
}
strtab = calloc(ssiz, 1);
if (strtab == NULL) {
warnx("%s: no room for %d bytes of string table", filename , ssiz);
done();
}
if (fread(strtab+sizeof(ssiz), ssiz-sizeof(ssiz), 1, nfile) != 1) {
warnx("%s: error reading string table", filename );
done();
}
}
/*
* Read in symbol table
*/
static void
getsymtab(FILE *nfile, const char *filename)
{
register long i;
int askfor;
struct nlist nbuf;
/* pass1 - count symbols */
fseek(nfile, (long)N_SYMOFF(xbuf), 0);
nname = 0;
for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) {
fread(&nbuf, sizeof(nbuf), 1, nfile);
if ( ! funcsymbol( &nbuf ) ) {
continue;
}
nname++;
}
if (nname == 0) {
warnx("%s: no symbols", filename );
done();
}
askfor = nname + 1;
nl = (nltype *) calloc( askfor , sizeof(nltype) );
if (nl == 0) {
warnx("no room for %d bytes of symbol table", askfor * sizeof(nltype) );
done();
}
/* pass2 - read symbols */
fseek(nfile, (long)N_SYMOFF(xbuf), 0);
npe = nl;
nname = 0;
for (i = xbuf.a_syms; i > 0; i -= sizeof(struct nlist)) {
fread(&nbuf, sizeof(nbuf), 1, nfile);
if ( ! funcsymbol( &nbuf ) ) {
# ifdef DEBUG
if ( debug & AOUTDEBUG ) {
printf( "[getsymtab] rejecting: 0x%x %s\n" ,
nbuf.n_type , strtab + nbuf.n_un.n_strx );
}
# endif DEBUG
continue;
}
npe->value = nbuf.n_value;
npe->name = strtab+nbuf.n_un.n_strx;
# ifdef DEBUG
if ( debug & AOUTDEBUG ) {
printf( "[getsymtab] %d %s 0x%08x\n" ,
nname , npe -> name , npe -> value );
}
# endif DEBUG
npe++;
nname++;
}
npe->value = -1;
}
/*
* read in the text space of an a.out file
*/
static void
gettextspace(FILE *nfile)
{
if ( cflag == 0 ) {
return;
}
textspace = (u_char *) malloc( xbuf.a_text );
if ( textspace == 0 ) {
warnx("ran out room for %d bytes of text space: can't do -c" ,
xbuf.a_text );
return;
}
(void) fseek( nfile , N_TXTOFF( xbuf ) , 0 );
if ( fread( textspace , 1 , xbuf.a_text , nfile ) != xbuf.a_text ) {
warnx("couldn't read text space: can't do -c");
free( textspace );
textspace = 0;
return;
}
}
static bool
funcsymbol(struct nlist *nlistp)
{
char *name, c;
/*
* must be a text symbol,
* and static text symbols don't qualify if aflag set.
*/
if ( ! ( ( nlistp -> n_type == ( N_TEXT | N_EXT ) )
|| ( ( nlistp -> n_type == N_TEXT ) && ( aflag == 0 ) ) ) ) {
return FALSE;
}
/*
* name must start with an underscore if uflag is set.
* can't have any `funny' characters in name,
* where `funny' means `.' (.o file names)
* need to make an exception for sparc .mul & co.
* perhaps we should just drop this code entirely...
*/
name = strtab + nlistp -> n_un.n_strx;
if ( uflag && *name != '_' )
return FALSE;
#ifdef sparc
if ( *name == '.' ) {
char *p = name + 1;
if ( *p == 'u' )
p++;
if ( strcmp ( p, "mul" ) == 0 || strcmp ( p, "div" ) == 0 ||
strcmp ( p, "rem" ) == 0 )
return TRUE;
}
#endif
while ( c = *name++ ) {
if ( c == '.' ) {
return FALSE;
}
}
return TRUE;
}
|