1 #include "l.h" 2 3 #define Dbufslop 100 4 5 #define PADDR(a) ((ulong)(a) & ~0xF0000000) 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 %lux sb %lux in %s", p->pc, pc, TNAME); 98 pc = p->pc; 99 } 100 curp = p; 101 asmins(p); 102 if(cbc < sizeof(and)) 103 cflush(); 104 a = (andptr - and); 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 case 1: /* unix coff */ 232 /* 233 * file header 234 */ 235 lputl(0x0004014c); /* 4 sections, magic */ 236 lputl(0); /* unix time stamp */ 237 lputl(0); /* symbol table */ 238 lputl(0); /* nsyms */ 239 lputl(0x0003001c); /* flags, sizeof a.out header */ 240 /* 241 * a.out header 242 */ 243 lputl(0x10b); /* magic, version stamp */ 244 lputl(rnd(textsize, INITRND)); /* text sizes */ 245 lputl(datsize); /* data sizes */ 246 lputl(bsssize); /* bss sizes */ 247 lput(entryvalue()); /* va of entry */ 248 lputl(INITTEXT); /* text start */ 249 lputl(INITDAT); /* data start */ 250 /* 251 * text section header 252 */ 253 strnput(".text", 8); 254 lputl(HEADR); /* pa */ 255 lputl(HEADR); /* va */ 256 lputl(textsize); /* text size */ 257 lputl(HEADR); /* file offset */ 258 lputl(0); /* relocation */ 259 lputl(0); /* line numbers */ 260 lputl(0); /* relocation, line numbers */ 261 lputl(0x20); /* flags text only */ 262 /* 263 * data section header 264 */ 265 strnput(".data", 8); 266 lputl(INITDAT); /* pa */ 267 lputl(INITDAT); /* va */ 268 lputl(datsize); /* data size */ 269 lputl(HEADR+textsize); /* file offset */ 270 lputl(0); /* relocation */ 271 lputl(0); /* line numbers */ 272 lputl(0); /* relocation, line numbers */ 273 lputl(0x40); /* flags data only */ 274 /* 275 * bss section header 276 */ 277 strnput(".bss", 8); 278 lputl(INITDAT+datsize); /* pa */ 279 lputl(INITDAT+datsize); /* va */ 280 lputl(bsssize); /* bss size */ 281 lputl(0); /* file offset */ 282 lputl(0); /* relocation */ 283 lputl(0); /* line numbers */ 284 lputl(0); /* relocation, line numbers */ 285 lputl(0x80); /* flags bss only */ 286 /* 287 * comment section header 288 */ 289 strnput(".comment", 8); 290 lputl(0); /* pa */ 291 lputl(0); /* va */ 292 lputl(symsize+lcsize); /* comment size */ 293 lputl(HEADR+textsize+datsize); /* file offset */ 294 lputl(HEADR+textsize+datsize); /* offset of syms */ 295 lputl(HEADR+textsize+datsize+symsize);/* offset of line numbers */ 296 lputl(0); /* relocation, line numbers */ 297 lputl(0x200); /* flags comment only */ 298 break; 299 case 2: /* plan9 */ 300 magic = 4*11*11+7; 301 if(dlm) 302 magic |= 0x80000000; 303 lput(magic); /* magic */ 304 lput(textsize); /* sizes */ 305 lput(datsize); 306 lput(bsssize); 307 lput(symsize); /* nsyms */ 308 lput(entryvalue()); /* va of entry */ 309 lput(spsize); /* sp offsets */ 310 lput(lcsize); /* line offsets */ 311 break; 312 case 3: 313 /* MS-DOS .COM */ 314 break; 315 case 4: 316 /* fake MS-DOS .EXE */ 317 v = rnd(HEADR+textsize, INITRND)+datsize; 318 wputl(0x5A4D); /* 'MZ' */ 319 wputl(v % 512); /* bytes in last page */ 320 wputl(rnd(v, 512)/512); /* total number of pages */ 321 wputl(0x0000); /* number of reloc items */ 322 v = rnd(HEADR-(INITTEXT & 0xFFFF), 16); 323 wputl(v/16); /* size of header */ 324 wputl(0x0000); /* minimum allocation */ 325 wputl(0xFFFF); /* maximum allocation */ 326 wputl(0x0000); /* initial ss value */ 327 wputl(0x0100); /* initial sp value */ 328 wputl(0x0000); /* complemented checksum */ 329 v = entryvalue(); 330 wputl(v); /* initial ip value (!) */ 331 wputl(0x0000); /* initial cs value */ 332 wputl(0x0000); 333 wputl(0x0000); 334 wputl(0x003E); /* reloc table offset */ 335 wputl(0x0000); /* overlay number */ 336 break; 337 case 5: 338 strnput("\177ELF", 4); /* e_ident */ 339 cput(1); /* class = 32 bit */ 340 cput(1); /* data = LSB */ 341 cput(1); /* version = CURRENT */ 342 strnput("", 9); 343 wputl(2); /* type = EXEC */ 344 wputl(3); /* machine = 386 */ 345 lputl(1L); /* version = CURRENT */ 346 lputl(PADDR(entryvalue())); /* entry vaddr */ 347 lputl(52L); /* offset to first phdr */ 348 lputl(0L); /* offset to first shdr */ 349 lputl(0L); /* flags = 386 */ 350 wputl(52); /* Ehdr size */ 351 wputl(32); /* Phdr size */ 352 wputl(3); /* # of Phdrs */ 353 wputl(0); /* Shdr size */ 354 wputl(0); /* # of Shdrs */ 355 wputl(0); /* Shdr string size */ 356 357 lputl(1L); /* text - type = PT_LOAD */ 358 lputl(HEADR); /* file offset */ 359 lputl(INITTEXT); /* vaddr */ 360 lputl(PADDR(INITTEXT)); /* paddr */ 361 lputl(textsize); /* file size */ 362 lputl(textsize); /* memory size */ 363 lputl(0x05L); /* protections = RX */ 364 lputl(INITRND); /* alignment */ 365 366 lputl(1L); /* data - type = PT_LOAD */ 367 lputl(HEADR+textsize); /* file offset */ 368 lputl(INITDAT); /* vaddr */ 369 lputl(PADDR(INITDAT)); /* paddr */ 370 lputl(datsize); /* file size */ 371 lputl(datsize+bsssize); /* memory size */ 372 lputl(0x06L); /* protections = RW */ 373 lputl(INITRND); /* alignment */ 374 375 lputl(0L); /* data - type = PT_NULL */ 376 lputl(HEADR+textsize+datsize); /* file offset */ 377 lputl(0L); 378 lputl(0L); 379 lputl(symsize); /* symbol table size */ 380 lputl(lcsize); /* line number size */ 381 lputl(0x04L); /* protections = R */ 382 lputl(0x04L); /* alignment */ 383 break; 384 } 385 cflush(); 386 } 387 388 void 389 cflush(void) 390 { 391 int n; 392 393 n = sizeof(buf.cbuf) - cbc; 394 if(n) 395 write(cout, buf.cbuf, n); 396 cbp = buf.cbuf; 397 cbc = sizeof(buf.cbuf); 398 } 399 400 void 401 datblk(long s, long n) 402 { 403 Prog *p; 404 char *cast; 405 long l, fl, j; 406 int i, c; 407 408 memset(buf.dbuf, 0, n+Dbufslop); 409 for(p = datap; p != P; p = p->link) { 410 curp = p; 411 l = p->from.sym->value + p->from.offset - s; 412 c = p->from.scale; 413 i = 0; 414 if(l < 0) { 415 if(l+c <= 0) 416 continue; 417 while(l < 0) { 418 l++; 419 i++; 420 } 421 } 422 if(l >= n) 423 continue; 424 if(p->as != AINIT && p->as != ADYNT) { 425 for(j=l+(c-i)-1; j>=l; j--) 426 if(buf.dbuf[j]) { 427 print("%P\n", p); 428 diag("multiple initialization"); 429 break; 430 } 431 } 432 switch(p->to.type) { 433 case D_FCONST: 434 switch(c) { 435 default: 436 case 4: 437 fl = ieeedtof(&p->to.ieee); 438 cast = (char*)&fl; 439 if(debug['a'] && i == 0) { 440 Bprint(&bso, pcstr, l+s+INITDAT); 441 for(j=0; j<c; j++) 442 Bprint(&bso, "%.2ux", cast[fnuxi4[j]] & 0xff); 443 Bprint(&bso, "\t%P\n", curp); 444 } 445 for(; i<c; i++) { 446 buf.dbuf[l] = cast[fnuxi4[i]]; 447 l++; 448 } 449 break; 450 case 8: 451 cast = (char*)&p->to.ieee; 452 if(debug['a'] && i == 0) { 453 Bprint(&bso, pcstr, l+s+INITDAT); 454 for(j=0; j<c; j++) 455 Bprint(&bso, "%.2ux", cast[fnuxi8[j]] & 0xff); 456 Bprint(&bso, "\t%P\n", curp); 457 } 458 for(; i<c; i++) { 459 buf.dbuf[l] = cast[fnuxi8[i]]; 460 l++; 461 } 462 break; 463 } 464 break; 465 466 case D_SCONST: 467 if(debug['a'] && i == 0) { 468 Bprint(&bso, pcstr, l+s+INITDAT); 469 for(j=0; j<c; j++) 470 Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff); 471 Bprint(&bso, "\t%P\n", curp); 472 } 473 for(; i<c; i++) { 474 buf.dbuf[l] = p->to.scon[i]; 475 l++; 476 } 477 break; 478 default: 479 fl = p->to.offset; 480 if(p->to.type == D_ADDR) { 481 if(p->to.index != D_STATIC && p->to.index != D_EXTERN) 482 diag("DADDR type%P", p); 483 if(p->to.sym) { 484 if(p->to.sym->type == SUNDEF) 485 ckoff(p->to.sym, fl); 486 fl += p->to.sym->value; 487 if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF) 488 fl += INITDAT; 489 if(dlm) 490 dynreloc(p->to.sym, l+s+INITDAT, 1); 491 } 492 } 493 cast = (char*)&fl; 494 switch(c) { 495 default: 496 diag("bad nuxi %d %d\n%P", c, i, curp); 497 break; 498 case 1: 499 if(debug['a'] && i == 0) { 500 Bprint(&bso, pcstr, l+s+INITDAT); 501 for(j=0; j<c; j++) 502 Bprint(&bso, "%.2ux", cast[inuxi1[j]] & 0xff); 503 Bprint(&bso, "\t%P\n", curp); 504 } 505 for(; i<c; i++) { 506 buf.dbuf[l] = cast[inuxi1[i]]; 507 l++; 508 } 509 break; 510 case 2: 511 if(debug['a'] && i == 0) { 512 Bprint(&bso, pcstr, l+s+INITDAT); 513 for(j=0; j<c; j++) 514 Bprint(&bso, "%.2ux", cast[inuxi2[j]] & 0xff); 515 Bprint(&bso, "\t%P\n", curp); 516 } 517 for(; i<c; i++) { 518 buf.dbuf[l] = cast[inuxi2[i]]; 519 l++; 520 } 521 break; 522 case 4: 523 if(debug['a'] && i == 0) { 524 Bprint(&bso, pcstr, l+s+INITDAT); 525 for(j=0; j<c; j++) 526 Bprint(&bso, "%.2ux", cast[inuxi4[j]] & 0xff); 527 Bprint(&bso, "\t%P\n", curp); 528 } 529 for(; i<c; i++) { 530 buf.dbuf[l] = cast[inuxi4[i]]; 531 l++; 532 } 533 break; 534 } 535 break; 536 } 537 } 538 write(cout, buf.dbuf, n); 539 } 540 541 long 542 rnd(long v, long r) 543 { 544 long c; 545 546 if(r <= 0) 547 return v; 548 v += r - 1; 549 c = v % r; 550 if(c < 0) 551 c += r; 552 v -= c; 553 return v; 554 } 555