]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/8prefix.c
kbdfs: allow to escape ctlr-alt-del with shift for vmx and vnc.
[plan9front.git] / sys / src / cmd / aux / 8prefix.c
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: 8prefix [-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