github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/cmd/5l/obj.c (about) 1 // Inferno utils/5l/obj.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/5l/obj.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 // Reading object files. 32 33 #define EXTERN 34 #include "l.h" 35 #include "../ld/lib.h" 36 #include "../ld/elf.h" 37 #include "../ld/dwarf.h" 38 #include <ar.h> 39 40 #ifndef DEFAULT 41 #define DEFAULT '9' 42 #endif 43 44 char *noname = "<none>"; 45 char *thestring = "arm"; 46 47 Header headers[] = { 48 "noheader", Hnoheader, 49 "risc", Hrisc, 50 "plan9", Hplan9x32, 51 "ixp1200", Hixp1200, 52 "ipaq", Hipaq, 53 "linux", Hlinux, 54 "freebsd", Hfreebsd, 55 "netbsd", Hnetbsd, 56 0, 0 57 }; 58 59 /* 60 * -Hrisc -T0x10005000 -R4 is aif for risc os 61 * -Hplan9 -T4128 -R4096 is plan9 format 62 * -Hixp1200 is IXP1200 (raw) 63 * -Hipaq -T0xC0008010 -R1024 is ipaq 64 * -Hlinux -Tx -Rx is linux elf 65 * -Hfreebsd is freebsd elf 66 * -Hnetbsd is netbsd elf 67 */ 68 69 void 70 main(int argc, char *argv[]) 71 { 72 char *p; 73 Sym *s; 74 75 Binit(&bso, 1, OWRITE); 76 listinit(); 77 nerrors = 0; 78 outfile = "5.out"; 79 HEADTYPE = -1; 80 INITTEXT = -1; 81 INITDAT = -1; 82 INITRND = -1; 83 INITENTRY = 0; 84 linkmode = LinkAuto; 85 nuxiinit(); 86 87 p = getgoarm(); 88 if(p != nil) 89 goarm = atoi(p); 90 else 91 goarm = 6; 92 if(goarm == 5) 93 debug['F'] = 1; 94 95 flagcount("1", "use alternate profiling code", &debug['1']); 96 flagfn1("B", "info: define ELF NT_GNU_BUILD_ID note", addbuildinfo); 97 flagstr("E", "sym: entry symbol", &INITENTRY); 98 flagint32("D", "addr: data address", &INITDAT); 99 flagcount("G", "debug pseudo-ops", &debug['G']); 100 flagfn1("I", "interp: set ELF interp", setinterp); 101 flagfn1("L", "dir: add dir to library path", Lflag); 102 flagfn1("H", "head: header type", setheadtype); 103 flagcount("K", "add stack underflow checks", &debug['K']); 104 flagcount("M", "disable software div/mod", &debug['M']); 105 flagcount("O", "print pc-line tables", &debug['O']); 106 flagcount("P", "debug code generation", &debug['P']); 107 flagint32("R", "rnd: address rounding", &INITRND); 108 flagint32("T", "addr: text address", &INITTEXT); 109 flagfn0("V", "print version and exit", doversion); 110 flagcount("W", "disassemble input", &debug['W']); 111 flagfn2("X", "name value: define string data", addstrdata); 112 flagcount("Z", "clear stack frame on entry", &debug['Z']); 113 flagcount("a", "disassemble output", &debug['a']); 114 flagcount("c", "dump call graph", &debug['c']); 115 flagcount("d", "disable dynamic executable", &debug['d']); 116 flagstr("extld", "linker to run in external mode", &extld); 117 flagstr("extldflags", "flags for external linker", &extldflags); 118 flagcount("f", "ignore version mismatch", &debug['f']); 119 flagcount("g", "disable go package data checks", &debug['g']); 120 flagstr("installsuffix", "pkg directory suffix", &flag_installsuffix); 121 flagstr("k", "sym: set field tracking symbol", &tracksym); 122 flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode); 123 flagcount("n", "dump symbol table", &debug['n']); 124 flagstr("o", "outfile: set output file", &outfile); 125 flagcount("p", "insert profiling code", &debug['p']); 126 flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath); 127 flagcount("race", "enable race detector", &flag_race); 128 flagcount("s", "disable symbol table", &debug['s']); 129 flagcount("shared", "generate shared object (implies -linkmode external)", &flag_shared); 130 flagstr("tmpdir", "leave temporary files in this directory", &tmpdir); 131 flagcount("u", "reject unsafe packages", &debug['u']); 132 flagcount("v", "print link trace", &debug['v']); 133 flagcount("w", "disable DWARF generation", &debug['w']); 134 135 flagparse(&argc, &argv, usage); 136 137 if(argc != 1) 138 usage(); 139 140 if(flag_shared) 141 linkmode = LinkExternal; 142 143 mywhatsys(); 144 145 if(HEADTYPE == -1) 146 HEADTYPE = headtype(goos); 147 148 // getgoextlinkenabled is based on GO_EXTLINK_ENABLED when 149 // Go was built; see ../../make.bash. 150 if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0) 151 linkmode = LinkInternal; 152 153 switch(HEADTYPE) { 154 default: 155 if(linkmode == LinkAuto) 156 linkmode = LinkInternal; 157 if(linkmode == LinkExternal && strcmp(getgoextlinkenabled(), "1") != 0) 158 sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE)); 159 break; 160 case Hlinux: 161 break; 162 } 163 164 libinit(); 165 166 switch(HEADTYPE) { 167 default: 168 diag("unknown -H option"); 169 errorexit(); 170 case Hnoheader: /* no header */ 171 HEADR = 0L; 172 if(INITTEXT == -1) 173 INITTEXT = 0; 174 if(INITDAT == -1) 175 INITDAT = 0; 176 if(INITRND == -1) 177 INITRND = 4; 178 break; 179 case Hrisc: /* aif for risc os */ 180 HEADR = 128L; 181 if(INITTEXT == -1) 182 INITTEXT = 0x10005000 + HEADR; 183 if(INITDAT == -1) 184 INITDAT = 0; 185 if(INITRND == -1) 186 INITRND = 4; 187 break; 188 case Hplan9x32: /* plan 9 */ 189 HEADR = 32L; 190 if(INITTEXT == -1) 191 INITTEXT = 4128; 192 if(INITDAT == -1) 193 INITDAT = 0; 194 if(INITRND == -1) 195 INITRND = 4096; 196 break; 197 case Hixp1200: /* boot for IXP1200 */ 198 HEADR = 0L; 199 if(INITTEXT == -1) 200 INITTEXT = 0x0; 201 if(INITDAT == -1) 202 INITDAT = 0; 203 if(INITRND == -1) 204 INITRND = 4; 205 break; 206 case Hipaq: /* boot for ipaq */ 207 HEADR = 16L; 208 if(INITTEXT == -1) 209 INITTEXT = 0xC0008010; 210 if(INITDAT == -1) 211 INITDAT = 0; 212 if(INITRND == -1) 213 INITRND = 1024; 214 break; 215 case Hlinux: /* arm elf */ 216 case Hfreebsd: 217 case Hnetbsd: 218 debug['d'] = 0; // with dynamic linking 219 tlsoffset = -8; // hardcoded number, first 4-byte word for g, and then 4-byte word for m 220 // this number is known to ../../pkg/runtime/rt0_*_arm.s 221 elfinit(); 222 HEADR = ELFRESERVE; 223 if(INITTEXT == -1) 224 INITTEXT = 0x10000 + HEADR; 225 if(INITDAT == -1) 226 INITDAT = 0; 227 if(INITRND == -1) 228 INITRND = 4096; 229 break; 230 } 231 if(INITDAT != 0 && INITRND != 0) 232 print("warning: -D0x%ux is ignored because of -R0x%ux\n", 233 INITDAT, INITRND); 234 if(debug['v']) 235 Bprint(&bso, "HEADER = -H0x%d -T0x%ux -D0x%ux -R0x%ux\n", 236 HEADTYPE, INITTEXT, INITDAT, INITRND); 237 Bflush(&bso); 238 zprg.as = AGOK; 239 zprg.scond = 14; 240 zprg.reg = NREG; 241 zprg.from.name = D_NONE; 242 zprg.from.type = D_NONE; 243 zprg.from.reg = NREG; 244 zprg.to = zprg.from; 245 buildop(); 246 histgen = 0; 247 pc = 0; 248 dtype = 4; 249 250 version = 0; 251 cbp = buf.cbuf; 252 cbc = sizeof(buf.cbuf); 253 254 // embed goarm to runtime.goarm 255 s = lookup("runtime.goarm", 0); 256 s->dupok = 1; 257 adduint8(s, goarm); 258 259 addlibpath("command line", "command line", argv[0], "main"); 260 loadlib(); 261 262 // mark some functions that are only referenced after linker code editing 263 if(debug['F']) 264 mark(rlookup("_sfloat", 0)); 265 mark(lookup("runtime.read_tls_fallback", 0)); 266 deadcode(); 267 if(textp == nil) { 268 diag("no code"); 269 errorexit(); 270 } 271 272 patch(); 273 if(debug['p']) 274 if(debug['1']) 275 doprof1(); 276 else 277 doprof2(); 278 doelf(); 279 follow(); 280 softfloat(); 281 // 5l -Z means zero the stack frame on entry. 282 // This slows down function calls but can help avoid 283 // false positives in garbage collection. 284 if(debug['Z']) 285 dozerostk(); 286 noops(); // generate stack split prolog, handle div/mod, etc. 287 dostkcheck(); 288 span(); 289 addexport(); 290 // textaddress() functionality is handled in span() 291 pclntab(); 292 symtab(); 293 dodata(); 294 address(); 295 doweak(); 296 reloc(); 297 asmb(); 298 undef(); 299 hostlink(); 300 301 if(debug['c']) 302 print("ARM size = %d\n", armsize); 303 if(debug['v']) { 304 Bprint(&bso, "%5.2f cpu time\n", cputime()); 305 Bprint(&bso, "%d sizeof adr\n", sizeof(Adr)); 306 Bprint(&bso, "%d sizeof prog\n", sizeof(Prog)); 307 } 308 Bflush(&bso); 309 errorexit(); 310 } 311 312 static Sym* 313 zsym(char *pn, Biobuf *f, Sym *h[]) 314 { 315 int o; 316 317 o = BGETC(f); 318 if(o == 0) 319 return S; 320 if(o < 0 || o >= NSYM || h[o] == nil) 321 mangle(pn); 322 return h[o]; 323 } 324 325 static void 326 zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[]) 327 { 328 int i, c; 329 int32 l; 330 Sym *s; 331 Auto *u; 332 333 a->type = BGETC(f); 334 a->reg = BGETC(f); 335 c = BGETC(f); 336 if(c < 0 || c > NSYM){ 337 print("sym out of range: %d\n", c); 338 BPUTC(f, ALAST+1); 339 return; 340 } 341 a->sym = h[c]; 342 a->name = BGETC(f); 343 adrgotype = zsym(pn, f, h); 344 345 if((schar)a->reg < 0 || a->reg > NREG) { 346 print("register out of range %d\n", a->reg); 347 BPUTC(f, ALAST+1); 348 return; /* force real diagnostic */ 349 } 350 351 if(a->type == D_CONST || a->type == D_OCONST) { 352 if(a->name == D_EXTERN || a->name == D_STATIC) { 353 s = a->sym; 354 if(s != S && (s->type == STEXT || s->type == SCONST || s->type == SXREF)) { 355 if(0 && !s->fnptr && s->name[0] != '.') 356 print("%s used as function pointer\n", s->name); 357 s->fnptr = 1; // over the top cos of SXREF 358 } 359 } 360 } 361 362 switch(a->type) { 363 default: 364 print("unknown type %d\n", a->type); 365 BPUTC(f, ALAST+1); 366 return; /* force real diagnostic */ 367 368 case D_NONE: 369 case D_REG: 370 case D_FREG: 371 case D_PSR: 372 case D_FPCR: 373 break; 374 375 case D_REGREG: 376 case D_REGREG2: 377 a->offset = BGETC(f); 378 break; 379 380 case D_CONST2: 381 a->offset2 = BGETLE4(f); // fall through 382 case D_BRANCH: 383 case D_OREG: 384 case D_CONST: 385 case D_OCONST: 386 case D_SHIFT: 387 a->offset = BGETLE4(f); 388 break; 389 390 case D_SCONST: 391 a->sval = mal(NSNAME); 392 Bread(f, a->sval, NSNAME); 393 break; 394 395 case D_FCONST: 396 a->ieee.l = BGETLE4(f); 397 a->ieee.h = BGETLE4(f); 398 break; 399 } 400 s = a->sym; 401 if(s == S) 402 return; 403 i = a->name; 404 if(i != D_AUTO && i != D_PARAM) { 405 if(s && adrgotype) 406 s->gotype = adrgotype; 407 return; 408 } 409 410 l = a->offset; 411 for(u=curauto; u; u=u->link) 412 if(u->asym == s) 413 if(u->type == i) { 414 if(u->aoffset > l) 415 u->aoffset = l; 416 if(adrgotype) 417 u->gotype = adrgotype; 418 return; 419 } 420 421 u = mal(sizeof(Auto)); 422 u->link = curauto; 423 curauto = u; 424 u->asym = s; 425 u->aoffset = l; 426 u->type = i; 427 u->gotype = adrgotype; 428 } 429 430 void 431 nopout(Prog *p) 432 { 433 p->as = ANOP; 434 p->from.type = D_NONE; 435 p->to.type = D_NONE; 436 } 437 438 void 439 ldobj1(Biobuf *f, char *pkg, int64 len, char *pn) 440 { 441 int32 ipc; 442 Prog *p; 443 Sym *h[NSYM], *s; 444 int v, o, r, skip; 445 uint32 sig; 446 char *name; 447 int ntext; 448 int32 eof; 449 char src[1024], *x; 450 Prog *lastp; 451 452 lastp = nil; 453 ntext = 0; 454 eof = Boffset(f) + len; 455 src[0] = 0; 456 pn = estrdup(pn); // we keep it in Sym* references 457 458 newloop: 459 memset(h, 0, sizeof(h)); 460 version++; 461 histfrogp = 0; 462 ipc = pc; 463 skip = 0; 464 465 loop: 466 if(f->state == Bracteof || Boffset(f) >= eof) 467 goto eof; 468 o = BGETC(f); 469 if(o == Beof) 470 goto eof; 471 472 if(o <= AXXX || o >= ALAST) { 473 diag("%s:#%lld: opcode out of range: %#ux", pn, Boffset(f), o); 474 print(" probably not a .5 file\n"); 475 errorexit(); 476 } 477 if(o == ANAME || o == ASIGNAME) { 478 sig = 0; 479 if(o == ASIGNAME) 480 sig = BGETLE4(f); 481 v = BGETC(f); /* type */ 482 o = BGETC(f); /* sym */ 483 r = 0; 484 if(v == D_STATIC) 485 r = version; 486 name = Brdline(f, '\0'); 487 if(name == nil) { 488 if(Blinelen(f) > 0) { 489 fprint(2, "%s: name too long\n", pn); 490 errorexit(); 491 } 492 goto eof; 493 } 494 x = expandpkg(name, pkg); 495 s = lookup(x, r); 496 if(x != name) 497 free(x); 498 499 if(sig != 0){ 500 if(s->sig != 0 && s->sig != sig) 501 diag("incompatible type signatures %ux(%s) and %ux(%s) for %s", s->sig, s->file, sig, pn, s->name); 502 s->sig = sig; 503 s->file = pn; 504 } 505 506 if(debug['W']) 507 print(" ANAME %s\n", s->name); 508 if(o < 0 || o >= nelem(h)) { 509 fprint(2, "%s: mangled input file\n", pn); 510 errorexit(); 511 } 512 h[o] = s; 513 if((v == D_EXTERN || v == D_STATIC) && s->type == 0) 514 s->type = SXREF; 515 if(v == D_FILE) { 516 if(s->type != SFILE) { 517 histgen++; 518 s->type = SFILE; 519 s->value = histgen; 520 } 521 if(histfrogp < MAXHIST) { 522 histfrog[histfrogp] = s; 523 histfrogp++; 524 } else 525 collapsefrog(s); 526 dwarfaddfrag(s->value, s->name); 527 } 528 goto loop; 529 } 530 531 p = mal(sizeof(Prog)); 532 p->as = o; 533 p->scond = BGETC(f); 534 p->reg = BGETC(f); 535 p->line = BGETLE4(f); 536 537 zaddr(pn, f, &p->from, h); 538 fromgotype = adrgotype; 539 zaddr(pn, f, &p->to, h); 540 541 if(p->as != ATEXT && p->as != AGLOBL && p->reg > NREG) 542 diag("register out of range %A %d", p->as, p->reg); 543 544 p->link = P; 545 p->cond = P; 546 547 if(debug['W']) 548 print("%P\n", p); 549 550 switch(o) { 551 case AHISTORY: 552 if(p->to.offset == -1) { 553 addlib(src, pn); 554 histfrogp = 0; 555 goto loop; 556 } 557 if(src[0] == '\0') 558 copyhistfrog(src, sizeof src); 559 addhist(p->line, D_FILE); /* 'z' */ 560 if(p->to.offset) 561 addhist(p->to.offset, D_FILE1); /* 'Z' */ 562 savehist(p->line, p->to.offset); 563 histfrogp = 0; 564 goto loop; 565 566 case AEND: 567 histtoauto(); 568 if(cursym != nil && cursym->text) 569 cursym->autom = curauto; 570 curauto = 0; 571 cursym = nil; 572 if(Boffset(f) == eof) 573 return; 574 goto newloop; 575 576 case AGLOBL: 577 s = p->from.sym; 578 if(s == S) { 579 diag("GLOBL must have a name\n%P", p); 580 errorexit(); 581 } 582 if(s->type == 0 || s->type == SXREF) { 583 s->type = SBSS; 584 s->value = 0; 585 } 586 if(s->type != SBSS && s->type != SNOPTRBSS && !s->dupok) { 587 diag("redefinition: %s\n%P", s->name, p); 588 s->type = SBSS; 589 s->value = 0; 590 } 591 if(p->to.offset > s->size) 592 s->size = p->to.offset; 593 if(p->reg & DUPOK) 594 s->dupok = 1; 595 if(p->reg & RODATA) 596 s->type = SRODATA; 597 else if(p->reg & NOPTR) 598 s->type = SNOPTRBSS; 599 break; 600 601 case ADATA: 602 // Assume that AGLOBL comes after ADATA. 603 // If we've seen an AGLOBL that said this sym was DUPOK, 604 // ignore any more ADATA we see, which must be 605 // redefinitions. 606 s = p->from.sym; 607 if(s->dupok) { 608 // if(debug['v']) 609 // Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn); 610 goto loop; 611 } 612 if(s->file == nil) 613 s->file = pn; 614 else if(s->file != pn) { 615 diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn); 616 errorexit(); 617 } 618 savedata(s, p, pn); 619 unmal(p, sizeof *p); 620 break; 621 622 case AGOK: 623 diag("unknown opcode\n%P", p); 624 p->pc = pc; 625 pc++; 626 break; 627 628 case ATYPE: 629 if(skip) 630 goto casedef; 631 pc++; 632 goto loop; 633 634 case ATEXT: 635 if(cursym != nil && cursym->text) { 636 histtoauto(); 637 cursym->autom = curauto; 638 curauto = 0; 639 } 640 s = p->from.sym; 641 if(s == S) { 642 diag("TEXT must have a name\n%P", p); 643 errorexit(); 644 } 645 cursym = s; 646 if(s->type != 0 && s->type != SXREF && (p->reg & DUPOK)) { 647 skip = 1; 648 goto casedef; 649 } 650 if(ntext++ == 0 && s->type != 0 && s->type != SXREF) { 651 /* redefinition, so file has probably been seen before */ 652 if(debug['v']) 653 Bprint(&bso, "skipping: %s: redefinition: %s", pn, s->name); 654 return; 655 } 656 skip = 0; 657 if(s->type != 0 && s->type != SXREF) 658 diag("redefinition: %s\n%P", s->name, p); 659 if(etextp) 660 etextp->next = s; 661 else 662 textp = s; 663 if(fromgotype) { 664 if(s->gotype && s->gotype != fromgotype) 665 diag("%s: type mismatch for %s", pn, s->name); 666 s->gotype = fromgotype; 667 } 668 etextp = s; 669 p->align = 4; 670 autosize = (p->to.offset+3L) & ~3L; 671 p->to.offset = autosize; 672 autosize += 4; 673 s->type = STEXT; 674 s->hist = gethist(); 675 s->text = p; 676 s->value = pc; 677 s->args = p->to.offset2; 678 lastp = p; 679 p->pc = pc; 680 pc++; 681 break; 682 683 case ASUB: 684 if(p->from.type == D_CONST) 685 if(p->from.name == D_NONE) 686 if(p->from.offset < 0) { 687 p->from.offset = -p->from.offset; 688 p->as = AADD; 689 } 690 goto casedef; 691 692 case AADD: 693 if(p->from.type == D_CONST) 694 if(p->from.name == D_NONE) 695 if(p->from.offset < 0) { 696 p->from.offset = -p->from.offset; 697 p->as = ASUB; 698 } 699 goto casedef; 700 701 case AMOVWD: 702 case AMOVWF: 703 case AMOVDW: 704 case AMOVFW: 705 case AMOVFD: 706 case AMOVDF: 707 // case AMOVF: 708 // case AMOVD: 709 case ACMPF: 710 case ACMPD: 711 case AADDF: 712 case AADDD: 713 case ASUBF: 714 case ASUBD: 715 case AMULF: 716 case AMULD: 717 case ADIVF: 718 case ADIVD: 719 goto casedef; 720 721 case AMOVF: 722 if(skip) 723 goto casedef; 724 725 if(p->from.type == D_FCONST && chipfloat(&p->from.ieee) < 0 && 726 (chipzero(&p->from.ieee) < 0 || (p->scond & C_SCOND) != C_SCOND_NONE)) { 727 /* size sb 9 max */ 728 sprint(literal, "$%ux", ieeedtof(&p->from.ieee)); 729 s = lookup(literal, 0); 730 if(s->type == 0) { 731 s->type = SRODATA; 732 adduint32(s, ieeedtof(&p->from.ieee)); 733 s->reachable = 0; 734 } 735 p->from.type = D_OREG; 736 p->from.sym = s; 737 p->from.name = D_EXTERN; 738 p->from.offset = 0; 739 } 740 goto casedef; 741 742 case AMOVD: 743 if(skip) 744 goto casedef; 745 746 if(p->from.type == D_FCONST && chipfloat(&p->from.ieee) < 0 && 747 (chipzero(&p->from.ieee) < 0 || (p->scond & C_SCOND) != C_SCOND_NONE)) { 748 /* size sb 18 max */ 749 sprint(literal, "$%ux.%ux", 750 p->from.ieee.l, p->from.ieee.h); 751 s = lookup(literal, 0); 752 if(s->type == 0) { 753 s->type = SRODATA; 754 adduint32(s, p->from.ieee.l); 755 adduint32(s, p->from.ieee.h); 756 s->reachable = 0; 757 } 758 p->from.type = D_OREG; 759 p->from.sym = s; 760 p->from.name = D_EXTERN; 761 p->from.offset = 0; 762 } 763 goto casedef; 764 765 default: 766 casedef: 767 if(skip) 768 nopout(p); 769 p->pc = pc; 770 pc++; 771 if(p->to.type == D_BRANCH) 772 p->to.offset += ipc; 773 if(lastp == nil) { 774 if(p->as != ANOP) 775 diag("unexpected instruction: %P", p); 776 break; 777 } 778 lastp->link = p; 779 lastp = p; 780 break; 781 } 782 goto loop; 783 784 eof: 785 diag("truncated object file: %s", pn); 786 } 787 788 Prog* 789 prg(void) 790 { 791 Prog *p; 792 793 p = mal(sizeof(Prog)); 794 *p = zprg; 795 return p; 796 } 797 798 Prog* 799 appendp(Prog *q) 800 { 801 Prog *p; 802 803 p = prg(); 804 p->link = q->link; 805 q->link = p; 806 p->line = q->line; 807 return p; 808 }