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