1 #include "l.h"
2
3 #define Dbufslop 100
4
5 long
entryvalue(void)6 entryvalue(void)
7 {
8 char *a;
9 Sym *s;
10
11 a = INITENTRY;
12 if(*a >= '0' && *a <= '9')
13 return atolwhex(a);
14 s = lookup(a, 0);
15 if(s->type == 0)
16 return INITTEXT;
17 switch(s->type) {
18 case STEXT:
19 break;
20 case SDATA:
21 if(dlm)
22 return s->value+INITDAT;
23 default:
24 diag("entry not text: %s", s->name);
25 }
26 return s->value;
27 }
28
29 /* these need to take long arguments to be compatible with elf.c */
30 void
wputl(long w)31 wputl(long w)
32 {
33 cput(w);
34 cput(w>>8);
35 }
36
37 void
wput(long w)38 wput(long w)
39 {
40 cput(w>>8);
41 cput(w);
42 }
43
44 void
lput(long l)45 lput(long l)
46 {
47 cput(l>>24);
48 cput(l>>16);
49 cput(l>>8);
50 cput(l);
51 }
52
53 void
lputl(long l)54 lputl(long l)
55 {
56 cput(l);
57 cput(l>>8);
58 cput(l>>16);
59 cput(l>>24);
60 }
61
62 void
llput(vlong v)63 llput(vlong v)
64 {
65 lput(v>>32);
66 lput(v);
67 }
68
69 void
llputl(vlong v)70 llputl(vlong v)
71 {
72 lputl(v);
73 lputl(v>>32);
74 }
75
76 void
strnput(char * s,int n)77 strnput(char *s, int n)
78 {
79 for(; *s && n > 0; s++){
80 cput(*s);
81 n--;
82 }
83 while(n > 0){
84 cput(0);
85 n--;
86 }
87 }
88
89 void
asmb(void)90 asmb(void)
91 {
92 Prog *p;
93 long v, magic;
94 int a;
95 uchar *op1;
96
97 if(debug['v'])
98 Bprint(&bso, "%5.2f asmb\n", cputime());
99 Bflush(&bso);
100
101 seek(cout, HEADR, 0);
102 pc = INITTEXT;
103 curp = firstp;
104 for(p = firstp; p != P; p = p->link) {
105 if(p->as == ATEXT)
106 curtext = p;
107 if(p->pc != pc) {
108 if(!debug['a'])
109 print("%P\n", curp);
110 diag("phase error %lux sb %lux in %s", p->pc, pc, TNAME);
111 pc = p->pc;
112 }
113 curp = p;
114 asmins(p);
115 if(cbc < sizeof(and))
116 cflush();
117 a = (andptr - and);
118 if(debug['a']) {
119 Bprint(&bso, pcstr, pc);
120 for(op1 = and; op1 < andptr; op1++)
121 Bprint(&bso, "%.2ux", *op1 & 0xff);
122 Bprint(&bso, "\t%P\n", curp);
123 }
124 if(dlm) {
125 if(p->as == ATEXT)
126 reloca = nil;
127 else if(reloca != nil)
128 diag("reloc failure: %P", curp);
129 }
130 memmove(cbp, and, a);
131 cbp += a;
132 pc += a;
133 cbc -= a;
134 }
135 cflush();
136 switch(HEADTYPE) {
137 default:
138 diag("unknown header type %ld", HEADTYPE);
139 case 0:
140 seek(cout, rnd(HEADR+textsize, 8192), 0);
141 break;
142 case 1:
143 textsize = rnd(HEADR+textsize, 4096)-HEADR;
144 seek(cout, textsize+HEADR, 0);
145 break;
146 case 2:
147 case 5:
148 seek(cout, HEADR+textsize, 0);
149 break;
150 case 3:
151 case 4:
152 seek(cout, HEADR+rnd(textsize, INITRND), 0);
153 break;
154 }
155
156 if(debug['v'])
157 Bprint(&bso, "%5.2f datblk\n", cputime());
158 Bflush(&bso);
159
160 if(dlm){
161 char buf[8];
162
163 write(cout, buf, INITDAT-textsize);
164 textsize = INITDAT;
165 }
166
167 for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
168 if(datsize-v > sizeof(buf)-Dbufslop)
169 datblk(v, sizeof(buf)-Dbufslop);
170 else
171 datblk(v, datsize-v);
172 }
173
174 symsize = 0;
175 spsize = 0;
176 lcsize = 0;
177 if(!debug['s']) {
178 if(debug['v'])
179 Bprint(&bso, "%5.2f sym\n", cputime());
180 Bflush(&bso);
181 switch(HEADTYPE) {
182 default:
183 case 0:
184 seek(cout, rnd(HEADR+textsize, 8192)+datsize, 0);
185 break;
186 case 1:
187 seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
188 break;
189 case 2:
190 case 5:
191 seek(cout, HEADR+textsize+datsize, 0);
192 break;
193 case 3:
194 case 4:
195 debug['s'] = 1;
196 break;
197 }
198 if(!debug['s'])
199 asmsym();
200 if(debug['v'])
201 Bprint(&bso, "%5.2f sp\n", cputime());
202 Bflush(&bso);
203 if(debug['v'])
204 Bprint(&bso, "%5.2f pc\n", cputime());
205 Bflush(&bso);
206 if(!debug['s'])
207 asmlc();
208 if(dlm)
209 asmdyn();
210 cflush();
211 }
212 else if(dlm){
213 seek(cout, HEADR+textsize+datsize, 0);
214 asmdyn();
215 cflush();
216 }
217 if(debug['v'])
218 Bprint(&bso, "%5.2f headr\n", cputime());
219 Bflush(&bso);
220 seek(cout, 0L, 0);
221 switch(HEADTYPE) {
222 default:
223 case 0: /* garbage */
224 lput(0x160L<<16); /* magic and sections */
225 lput(0L); /* time and date */
226 lput(rnd(HEADR+textsize, 4096)+datsize);
227 lput(symsize); /* nsyms */
228 lput((0x38L<<16)|7L); /* size of optional hdr and flags */
229 lput((0413<<16)|0437L); /* magic and version */
230 lput(rnd(HEADR+textsize, 4096));/* sizes */
231 lput(datsize);
232 lput(bsssize);
233 lput(entryvalue()); /* va of entry */
234 lput(INITTEXT-HEADR); /* va of base of text */
235 lput(INITDAT); /* va of base of data */
236 lput(INITDAT+datsize); /* va of base of bss */
237 lput(~0L); /* gp reg mask */
238 lput(0L);
239 lput(0L);
240 lput(0L);
241 lput(0L);
242 lput(~0L); /* gp value ?? */
243 break;
244 case 1: /* unix coff */
245 /*
246 * file header
247 */
248 lputl(0x0004014c); /* 4 sections, magic */
249 lputl(0); /* unix time stamp */
250 lputl(0); /* symbol table */
251 lputl(0); /* nsyms */
252 lputl(0x0003001c); /* flags, sizeof a.out header */
253 /*
254 * a.out header
255 */
256 lputl(0x10b); /* magic, version stamp */
257 lputl(rnd(textsize, INITRND)); /* text sizes */
258 lputl(datsize); /* data sizes */
259 lputl(bsssize); /* bss sizes */
260 lput(entryvalue()); /* va of entry */
261 lputl(INITTEXT); /* text start */
262 lputl(INITDAT); /* data start */
263 /*
264 * text section header
265 */
266 strnput(".text", 8);
267 lputl(HEADR); /* pa */
268 lputl(HEADR); /* va */
269 lputl(textsize); /* text size */
270 lputl(HEADR); /* file offset */
271 lputl(0); /* relocation */
272 lputl(0); /* line numbers */
273 lputl(0); /* relocation, line numbers */
274 lputl(0x20); /* flags text only */
275 /*
276 * data section header
277 */
278 strnput(".data", 8);
279 lputl(INITDAT); /* pa */
280 lputl(INITDAT); /* va */
281 lputl(datsize); /* data size */
282 lputl(HEADR+textsize); /* file offset */
283 lputl(0); /* relocation */
284 lputl(0); /* line numbers */
285 lputl(0); /* relocation, line numbers */
286 lputl(0x40); /* flags data only */
287 /*
288 * bss section header
289 */
290 strnput(".bss", 8);
291 lputl(INITDAT+datsize); /* pa */
292 lputl(INITDAT+datsize); /* va */
293 lputl(bsssize); /* bss size */
294 lputl(0); /* file offset */
295 lputl(0); /* relocation */
296 lputl(0); /* line numbers */
297 lputl(0); /* relocation, line numbers */
298 lputl(0x80); /* flags bss only */
299 /*
300 * comment section header
301 */
302 strnput(".comment", 8);
303 lputl(0); /* pa */
304 lputl(0); /* va */
305 lputl(symsize+lcsize); /* comment size */
306 lputl(HEADR+textsize+datsize); /* file offset */
307 lputl(HEADR+textsize+datsize); /* offset of syms */
308 lputl(HEADR+textsize+datsize+symsize);/* offset of line numbers */
309 lputl(0); /* relocation, line numbers */
310 lputl(0x200); /* flags comment only */
311 break;
312 case 2: /* plan9 */
313 magic = 4*11*11+7;
314 if(dlm)
315 magic |= 0x80000000;
316 lput(magic); /* magic */
317 lput(textsize); /* sizes */
318 lput(datsize);
319 lput(bsssize);
320 lput(symsize); /* nsyms */
321 lput(entryvalue()); /* va of entry */
322 lput(spsize); /* sp offsets */
323 lput(lcsize); /* line offsets */
324 break;
325 case 3:
326 /* MS-DOS .COM */
327 break;
328 case 4:
329 /* fake MS-DOS .EXE */
330 v = rnd(HEADR+textsize, INITRND)+datsize;
331 wputl(0x5A4D); /* 'MZ' */
332 wputl(v % 512); /* bytes in last page */
333 wputl(rnd(v, 512)/512); /* total number of pages */
334 wputl(0x0000); /* number of reloc items */
335 v = rnd(HEADR-(INITTEXT & 0xFFFF), 16);
336 wputl(v/16); /* size of header */
337 wputl(0x0000); /* minimum allocation */
338 wputl(0xFFFF); /* maximum allocation */
339 wputl(0x0000); /* initial ss value */
340 wputl(0x0100); /* initial sp value */
341 wputl(0x0000); /* complemented checksum */
342 v = entryvalue();
343 wputl(v); /* initial ip value (!) */
344 wputl(0x0000); /* initial cs value */
345 wputl(0x0000);
346 wputl(0x0000);
347 wputl(0x003E); /* reloc table offset */
348 wputl(0x0000); /* overlay number */
349 break;
350 case 5:
351 elf32(I386, ELFDATA2LSB, 0, nil);
352 break;
353 }
354 cflush();
355 }
356
357 void
cflush(void)358 cflush(void)
359 {
360 int n;
361
362 n = sizeof(buf.cbuf) - cbc;
363 if(n)
364 write(cout, buf.cbuf, n);
365 cbp = buf.cbuf;
366 cbc = sizeof(buf.cbuf);
367 }
368
369 void
datblk(long s,long n)370 datblk(long s, long n)
371 {
372 Prog *p;
373 char *cast;
374 long l, fl, j;
375 int i, c;
376
377 memset(buf.dbuf, 0, n+Dbufslop);
378 for(p = datap; p != P; p = p->link) {
379 curp = p;
380 l = p->from.sym->value + p->from.offset - s;
381 c = p->from.scale;
382 i = 0;
383 if(l < 0) {
384 if(l+c <= 0)
385 continue;
386 while(l < 0) {
387 l++;
388 i++;
389 }
390 }
391 if(l >= n)
392 continue;
393 if(p->as != AINIT && p->as != ADYNT) {
394 for(j=l+(c-i)-1; j>=l; j--)
395 if(buf.dbuf[j]) {
396 print("%P\n", p);
397 diag("multiple initialization");
398 break;
399 }
400 }
401 switch(p->to.type) {
402 case D_FCONST:
403 switch(c) {
404 default:
405 case 4:
406 fl = ieeedtof(&p->to.ieee);
407 cast = (char*)&fl;
408 if(debug['a'] && i == 0) {
409 Bprint(&bso, pcstr, l+s+INITDAT);
410 for(j=0; j<c; j++)
411 Bprint(&bso, "%.2ux", cast[fnuxi4[j]] & 0xff);
412 Bprint(&bso, "\t%P\n", curp);
413 }
414 for(; i<c; i++) {
415 buf.dbuf[l] = cast[fnuxi4[i]];
416 l++;
417 }
418 break;
419 case 8:
420 cast = (char*)&p->to.ieee;
421 if(debug['a'] && i == 0) {
422 Bprint(&bso, pcstr, l+s+INITDAT);
423 for(j=0; j<c; j++)
424 Bprint(&bso, "%.2ux", cast[fnuxi8[j]] & 0xff);
425 Bprint(&bso, "\t%P\n", curp);
426 }
427 for(; i<c; i++) {
428 buf.dbuf[l] = cast[fnuxi8[i]];
429 l++;
430 }
431 break;
432 }
433 break;
434
435 case D_SCONST:
436 if(debug['a'] && i == 0) {
437 Bprint(&bso, pcstr, l+s+INITDAT);
438 for(j=0; j<c; j++)
439 Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);
440 Bprint(&bso, "\t%P\n", curp);
441 }
442 for(; i<c; i++) {
443 buf.dbuf[l] = p->to.scon[i];
444 l++;
445 }
446 break;
447 default:
448 fl = p->to.offset;
449 if(p->to.type == D_ADDR) {
450 if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
451 diag("DADDR type%P", p);
452 if(p->to.sym) {
453 if(p->to.sym->type == SUNDEF)
454 ckoff(p->to.sym, fl);
455 fl += p->to.sym->value;
456 if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF)
457 fl += INITDAT;
458 if(dlm)
459 dynreloc(p->to.sym, l+s+INITDAT, 1);
460 }
461 }
462 cast = (char*)&fl;
463 switch(c) {
464 default:
465 diag("bad nuxi %d %d\n%P", c, i, curp);
466 break;
467 case 1:
468 if(debug['a'] && i == 0) {
469 Bprint(&bso, pcstr, l+s+INITDAT);
470 for(j=0; j<c; j++)
471 Bprint(&bso, "%.2ux", cast[inuxi1[j]] & 0xff);
472 Bprint(&bso, "\t%P\n", curp);
473 }
474 for(; i<c; i++) {
475 buf.dbuf[l] = cast[inuxi1[i]];
476 l++;
477 }
478 break;
479 case 2:
480 if(debug['a'] && i == 0) {
481 Bprint(&bso, pcstr, l+s+INITDAT);
482 for(j=0; j<c; j++)
483 Bprint(&bso, "%.2ux", cast[inuxi2[j]] & 0xff);
484 Bprint(&bso, "\t%P\n", curp);
485 }
486 for(; i<c; i++) {
487 buf.dbuf[l] = cast[inuxi2[i]];
488 l++;
489 }
490 break;
491 case 4:
492 if(debug['a'] && i == 0) {
493 Bprint(&bso, pcstr, l+s+INITDAT);
494 for(j=0; j<c; j++)
495 Bprint(&bso, "%.2ux", cast[inuxi4[j]] & 0xff);
496 Bprint(&bso, "\t%P\n", curp);
497 }
498 for(; i<c; i++) {
499 buf.dbuf[l] = cast[inuxi4[i]];
500 l++;
501 }
502 break;
503 }
504 break;
505 }
506 }
507 write(cout, buf.dbuf, n);
508 }
509
510 long
rnd(long v,long r)511 rnd(long v, long r)
512 {
513 long c;
514
515 if(r <= 0)
516 return v;
517 v += r - 1;
518 c = v % r;
519 if(c < 0)
520 c += r;
521 v -= c;
522 return v;
523 }
524