1 #include "l.h" 2 3 #define Dbufslop 100 4 5 long 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 31 wputl(long w) 32 { 33 cput(w); 34 cput(w>>8); 35 } 36 37 void 38 wput(long w) 39 { 40 cput(w>>8); 41 cput(w); 42 } 43 44 void 45 lput(long l) 46 { 47 cput(l>>24); 48 cput(l>>16); 49 cput(l>>8); 50 cput(l); 51 } 52 53 void 54 lputl(long l) 55 { 56 cput(l); 57 cput(l>>8); 58 cput(l>>16); 59 cput(l>>24); 60 } 61 62 void 63 llput(vlong v) 64 { 65 lput(v>>32); 66 lput(v); 67 } 68 69 void 70 llputl(vlong v) 71 { 72 lputl(v); 73 lputl(v>>32); 74 } 75 76 void 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 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 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 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[(int)fnuxi4[j]] & 0xff); 412 Bprint(&bso, "\t%P\n", curp); 413 } 414 for(; i<c; i++) { 415 buf.dbuf[l] = cast[(int)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[(int)fnuxi8[j]] & 0xff); 425 Bprint(&bso, "\t%P\n", curp); 426 } 427 for(; i<c; i++) { 428 buf.dbuf[l] = cast[(int)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[(int)inuxi1[j]] & 0xff); 472 Bprint(&bso, "\t%P\n", curp); 473 } 474 for(; i<c; i++) { 475 buf.dbuf[l] = cast[(int)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[(int)inuxi2[j]] & 0xff); 484 Bprint(&bso, "\t%P\n", curp); 485 } 486 for(; i<c; i++) { 487 buf.dbuf[l] = cast[(int)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[(int)inuxi4[j]] & 0xff); 496 Bprint(&bso, "\t%P\n", curp); 497 } 498 for(; i<c; i++) { 499 buf.dbuf[l] = cast[(int)inuxi4[i]]; 500 l++; 501 } 502 break; 503 } 504 break; 505 } 506 } 507 write(cout, buf.dbuf, n); 508 } 509 510 long 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