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