Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * Pre-resolve references inside an object file.
3
 * Mark such functions static so that linking with
4
 * other object files can't get at them.
5
 * Also rename "main".
6
 */
7
#include <u.h>
8
#include <libc.h>
9
#include <bio.h>
10
#include "/sys/src/cmd/8c/8.out.h"
11
 
12
typedef struct Sym Sym;
13
struct Sym
14
{
15
	char *name;
16
	char *newname;
17
	short type;
18
	short version;
19
	Sym *link;
20
};
21
 
22
typedef struct Obj Obj;
23
struct Obj
24
{
25
	int fd;
26
	int version;
27
	uchar *bp;
28
	uchar *ep;
29
	char *name;
30
};
31
 
32
enum
33
{
34
	NHASH = 10007
35
};
36
 
37
Sym *hash[NHASH];
38
int nsymbol;
39
int renamemain = 1;
40
Sym *xsym[256];
41
int version = 1;
42
Obj **obj;
43
int nobj;
44
Biobuf bout;
45
char *prefix;
46
int verbose;
47
 
48
void *emalloc(ulong);
49
Sym *lookup(char*, int);
50
Obj *openobj(char*);
51
void walkobj(Obj*, void (*fn)(int, Sym*, uchar*, int));
52
void walkobjs(void (*fn)(int, Sym*, uchar*, int));
53
void dump(int, Sym*, uchar*, int);
54
void nop(int, Sym*, uchar*, int);
55
void owrite(int, Sym*, uchar*, int);
56
int zaddr(uchar*, Sym**);
57
void renamesyms(int, Sym*, uchar*, int);
58
 
59
void
60
usage(void)
61
{
62
	fprint(2, "usage: 8prelink [-mv] prefix file.8...\n");
63
	exits("usage");
64
}
65
 
66
void
67
main(int argc, char **argv)
68
{
69
	int i;
70
	Obj *o;
71
 
72
	ARGBEGIN{
73
	case 'm':
74
		renamemain = 0;
75
		break;
76
	case 'v':
77
		verbose = 1;
78
		break;
79
	default:
80
		usage();
81
	}ARGEND
82
 
83
	if(argc < 2)
84
		usage();
85
 
86
	prefix = argv[0];
87
	argv++;
88
	argc--;
89
 
90
	nobj = argc;
91
	obj = emalloc(nobj*sizeof obj[0]);
92
	for(i=0; i<argc; i++)
93
		obj[i] = openobj(argv[i]);
94
 
95
	walkobjs(nop);	/* initialize symbol table */
96
	if(verbose)
97
		walkobjs(dump);
98
	walkobjs(renamesyms);
99
 
100
	for(i=0; i<nobj; i++){
101
		o = obj[i];
102
		seek(o->fd, 0, 0);
103
		Binit(&bout, o->fd, OWRITE);
104
		walkobj(o, owrite);
105
		Bflush(&bout);
106
	}
107
	exits(0);
108
}
109
 
110
void
111
renamesyms(int op, Sym *sym, uchar*, int)
112
{
113
	if(sym && sym->version==0 && !sym->newname)
114
	switch(op){
115
	case AGLOBL:
116
	case AINIT:
117
	case ADATA:
118
	case ATEXT:
119
		if(!renamemain && strcmp(sym->name, "main") == 0)
120
			break;
121
		sym->newname = smprint("%s%s", prefix, sym->name);
122
		break;
123
	}	
124
}
125
 
126
void
127
dump(int op, Sym *sym, uchar*, int)
128
{
129
	if(sym && sym->version==0)
130
	switch(op){
131
	case AGLOBL:
132
	case AINIT:
133
	case ADATA:
134
	case ATEXT:
135
		print("%s\n", sym->name);
136
		break;
137
	}	
138
}
139
 
140
void
141
nop(int, Sym*, uchar*, int)
142
{
143
}
144
 
145
void
146
owrite(int op, Sym *sym, uchar *p, int l)
147
{
148
	switch(op){
149
	case ASIGNAME:
150
		Bwrite(&bout, p, 4);
151
		p += 4;
152
		l -= 4;
153
	case ANAME:
154
		if(sym->newname){
155
			Bwrite(&bout, p, 4);
156
			Bwrite(&bout, sym->newname, strlen(sym->newname)+1);
157
			break;
158
		}
159
	default:
160
		Bwrite(&bout, p, l);
161
		break;
162
	}
163
}
164
 
165
int
166
zaddr(uchar *p, Sym **symp)
167
{
168
	int c, t;
169
 
170
	t = p[0];
171
	c = 1;
172
	if(t & T_INDEX)
173
		c += 2;
174
	if(t & T_OFFSET)
175
		c += 4;
176
	if(t & T_SYM){
177
		if(symp)
178
			*symp = xsym[p[c]];
179
		c++;
180
	}
181
	if(t & T_FCONST)
182
		c += 8;
183
	else if(t & T_SCONST)
184
		c += NSNAME;
185
	if(t & T_TYPE)
186
		c++;
187
	return c;
188
}
189
 
190
void*
191
emalloc(ulong n)
192
{
193
	void *v;
194
 
195
	v = mallocz(n, 1);
196
	if(v == nil)
197
		sysfatal("out of memory");
198
	return v;
199
}
200
 
201
Sym*
202
lookup(char *symb, int v)
203
{
204
	Sym *s;
205
	char *p;
206
	long h;
207
	int l, c;
208
 
209
	h = v;
210
	for(p=symb; c = *p; p++)
211
		h = h+h+h + c;
212
	l = (p - symb) + 1;
213
	if(h < 0)
214
		h = ~h;
215
	h %= NHASH;
216
	for(s = hash[h]; s != nil; s = s->link)
217
		if(s->version == v)
218
		if(memcmp(s->name, symb, l) == 0)
219
			return s;
220
 
221
	s = emalloc(sizeof *s);
222
	s->name = emalloc(l + 1);
223
	memmove(s->name, symb, l);
224
 
225
	s->link = hash[h];
226
	s->type = 0;
227
	s->version = v;
228
	hash[h] = s;
229
	nsymbol++;
230
	return s;
231
}
232
 
233
Obj*
234
openobj(char *name)
235
{
236
	Dir *d;
237
	Obj *obj;
238
 
239
	obj = emalloc(sizeof *obj);
240
	obj->name = name;
241
	obj->version = version++;
242
	if((obj->fd = open(name, ORDWR)) < 0)
243
		sysfatal("open %s: %r", name);
244
	if((d = dirfstat(obj->fd)) == nil)
245
		sysfatal("dirfstat: %r");
246
	obj->bp = emalloc(d->length);
247
	if(readn(obj->fd, obj->bp, d->length) != d->length)
248
		sysfatal("read %s: %r", name);
249
	obj->ep = obj->bp+d->length;
250
	return obj;
251
}
252
 
253
void
254
walkobjs(void (*fn)(int, Sym*, uchar*, int))
255
{
256
	int i;
257
 
258
	for(i=0; i<nobj; i++)
259
		walkobj(obj[i], fn);
260
}
261
 
262
void
263
walkobj(Obj *obj, void (*fn)(int, Sym*, uchar*, int))
264
{
265
	int op, type;
266
	Sym *sym;
267
	uchar *p, *p0;
268
 
269
	for(p=obj->bp; p+4<=obj->ep; ){
270
		op = p[0] | (p[1]<<8);
271
		if(op <= AXXX || op >= ALAST)
272
			sysfatal("%s: opcode out of range - probably not a .8 file", obj->name);
273
		p0 = p;
274
		switch(op){
275
		case ASIGNAME:
276
			p += 4;	/* sign */
277
		case ANAME:
278
			type = p[2];
279
			sym = lookup((char*)p+4, type==D_STATIC ? obj->version : 0);
280
			xsym[p[3]] = sym;
281
			p += 4+strlen(sym->name)+1;
282
			fn(op, sym, p0, p-p0);
283
			break;
284
 
285
		default:
286
			p += 6;
287
			p += zaddr(p, &sym);
288
			p += zaddr(p, nil);
289
			fn(op, sym, p0, p-p0);
290
			break;
291
		}
292
	}
293
}
294