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