github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/cmd/6l/obj.c (about) 1 // Inferno utils/6l/obj.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/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/macho.h" 38 #include "../ld/dwarf.h" 39 #include "../ld/pe.h" 40 #include <ar.h> 41 42 char *noname = "<none>"; 43 char* thestring = "amd64"; 44 char* paramspace = "FP"; 45 46 Header headers[] = { 47 "plan9x32", Hplan9x32, 48 "plan9", Hplan9x64, 49 "elf", Helf, 50 "darwin", Hdarwin, 51 "dragonfly", Hdragonfly, 52 "linux", Hlinux, 53 "freebsd", Hfreebsd, 54 "netbsd", Hnetbsd, 55 "openbsd", Hopenbsd, 56 "windows", Hwindows, 57 "windowsgui", Hwindows, 58 0, 0 59 }; 60 61 /* 62 * -Hplan9x32 -T4128 -R4096 is plan9 32-bit format 63 * -Hplan9 -T0x200028 -R0x200000 is plan9 64-bit format 64 * -Helf -T0x80110000 -R4096 is ELF32 65 * -Hdarwin -Tx -Rx is apple MH-exec 66 * -Hdragonfly -Tx -Rx is DragonFly elf-exec 67 * -Hlinux -Tx -Rx is linux elf-exec 68 * -Hfreebsd -Tx -Rx is FreeBSD elf-exec 69 * -Hnetbsd -Tx -Rx is NetBSD elf-exec 70 * -Hopenbsd -Tx -Rx is OpenBSD elf-exec 71 * -Hwindows -Tx -Rx is MS Windows PE32+ 72 */ 73 74 void 75 main(int argc, char *argv[]) 76 { 77 Binit(&bso, 1, OWRITE); 78 listinit(); 79 memset(debug, 0, sizeof(debug)); 80 nerrors = 0; 81 outfile = nil; 82 HEADTYPE = -1; 83 INITTEXT = -1; 84 INITDAT = -1; 85 INITRND = -1; 86 INITENTRY = 0; 87 linkmode = LinkAuto; 88 nuxiinit(); 89 90 flagcount("1", "use alternate profiling code", &debug['1']); 91 flagcount("8", "assume 64-bit addresses", &debug['8']); 92 flagfn1("B", "info: define ELF NT_GNU_BUILD_ID note", addbuildinfo); 93 flagint64("D", "addr: data address", &INITDAT); 94 flagstr("E", "sym: entry symbol", &INITENTRY); 95 flagfn1("I", "interp: set ELF interp", setinterp); 96 flagfn1("L", "dir: add dir to library path", Lflag); 97 flagfn1("H", "head: header type", setheadtype); 98 flagcount("K", "add stack underflow checks", &debug['K']); 99 flagcount("O", "print pc-line tables", &debug['O']); 100 flagcount("Q", "debug byte-register code gen", &debug['Q']); 101 flagint32("R", "rnd: address rounding", &INITRND); 102 flagcount("S", "check type signatures", &debug['S']); 103 flagint64("T", "addr: text address", &INITTEXT); 104 flagfn0("V", "print version and exit", doversion); 105 flagcount("W", "disassemble input", &debug['W']); 106 flagfn2("X", "name value: define string data", addstrdata); 107 flagcount("Z", "clear stack frame on entry", &debug['Z']); 108 flagcount("a", "disassemble output", &debug['a']); 109 flagcount("c", "dump call graph", &debug['c']); 110 flagcount("d", "disable dynamic executable", &debug['d']); 111 flagstr("extld", "linker to run in external mode", &extld); 112 flagstr("extldflags", "flags for external linker", &extldflags); 113 flagcount("f", "ignore version mismatch", &debug['f']); 114 flagcount("g", "disable go package data checks", &debug['g']); 115 flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode); 116 flagstr("k", "sym: set field tracking symbol", &tracksym); 117 flagcount("n", "dump symbol table", &debug['n']); 118 flagstr("o", "outfile: set output file", &outfile); 119 flagcount("p", "insert profiling code", &debug['p']); 120 flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath); 121 flagcount("race", "enable race detector", &flag_race); 122 flagcount("s", "disable symbol table", &debug['s']); 123 flagcount("shared", "generate shared object (implies -linkmode external)", &flag_shared); 124 flagstr("tmpdir", "leave temporary files in this directory", &tmpdir); 125 flagcount("u", "reject unsafe packages", &debug['u']); 126 flagcount("v", "print link trace", &debug['v']); 127 flagcount("w", "disable DWARF generation", &debug['w']); 128 129 flagparse(&argc, &argv, usage); 130 131 if(argc != 1) 132 usage(); 133 134 mywhatsys(); // get goos 135 136 if(HEADTYPE == -1) 137 HEADTYPE = headtype(goos); 138 139 // getgoextlinkenabled is based on GO_EXTLINK_ENABLED when 140 // Go was built; see ../../make.bash. 141 if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0) 142 linkmode = LinkInternal; 143 144 if(flag_shared) 145 linkmode = LinkExternal; 146 147 switch(HEADTYPE) { 148 default: 149 if(linkmode == LinkAuto) 150 linkmode = LinkInternal; 151 if(linkmode == LinkExternal && strcmp(getgoextlinkenabled(), "1") != 0) 152 sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE)); 153 break; 154 case Hdarwin: 155 case Hfreebsd: 156 case Hlinux: 157 case Hnetbsd: 158 case Hopenbsd: 159 break; 160 } 161 162 if(outfile == nil) { 163 if(HEADTYPE == Hwindows) 164 outfile = "6.out.exe"; 165 else 166 outfile = "6.out"; 167 } 168 169 libinit(); 170 171 switch(HEADTYPE) { 172 default: 173 diag("unknown -H option"); 174 errorexit(); 175 case Hplan9x32: /* plan 9 */ 176 HEADR = 32L; 177 if(INITTEXT == -1) 178 INITTEXT = 4096+HEADR; 179 if(INITDAT == -1) 180 INITDAT = 0; 181 if(INITRND == -1) 182 INITRND = 4096; 183 break; 184 case Hplan9x64: /* plan 9 */ 185 HEADR = 32L + 8L; 186 if(INITTEXT == -1) 187 INITTEXT = 0x200000+HEADR; 188 if(INITDAT == -1) 189 INITDAT = 0; 190 if(INITRND == -1) 191 INITRND = 0x200000; 192 break; 193 case Helf: /* elf32 executable */ 194 HEADR = rnd(52L+3*32L, 16); 195 if(INITTEXT == -1) 196 INITTEXT = 0x80110000L; 197 if(INITDAT == -1) 198 INITDAT = 0; 199 if(INITRND == -1) 200 INITRND = 4096; 201 break; 202 case Hdarwin: /* apple MACH */ 203 /* 204 * OS X system constant - offset from 0(GS) to our TLS. 205 * Explained in ../../pkg/runtime/cgo/gcc_darwin_amd64.c. 206 */ 207 tlsoffset = 0x8a0; 208 machoinit(); 209 HEADR = INITIAL_MACHO_HEADR; 210 if(INITRND == -1) 211 INITRND = 4096; 212 if(INITTEXT == -1) 213 INITTEXT = 4096+HEADR; 214 if(INITDAT == -1) 215 INITDAT = 0; 216 break; 217 case Hlinux: /* elf64 executable */ 218 case Hfreebsd: /* freebsd */ 219 case Hnetbsd: /* netbsd */ 220 case Hopenbsd: /* openbsd */ 221 case Hdragonfly: /* dragonfly */ 222 /* 223 * ELF uses TLS offset negative from FS. 224 * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS). 225 * Also known to ../../pkg/runtime/sys_linux_amd64.s 226 * and ../../pkg/runtime/cgo/gcc_linux_amd64.c. 227 */ 228 tlsoffset = -16; 229 elfinit(); 230 HEADR = ELFRESERVE; 231 if(INITTEXT == -1) 232 INITTEXT = (1<<22)+HEADR; 233 if(INITDAT == -1) 234 INITDAT = 0; 235 if(INITRND == -1) 236 INITRND = 4096; 237 break; 238 case Hwindows: /* PE executable */ 239 peinit(); 240 HEADR = PEFILEHEADR; 241 if(INITTEXT == -1) 242 INITTEXT = PEBASE+PESECTHEADR; 243 if(INITDAT == -1) 244 INITDAT = 0; 245 if(INITRND == -1) 246 INITRND = PESECTALIGN; 247 break; 248 } 249 if(INITDAT != 0 && INITRND != 0) 250 print("warning: -D0x%llux is ignored because of -R0x%ux\n", 251 INITDAT, INITRND); 252 if(debug['v']) 253 Bprint(&bso, "HEADER = -H%d -T0x%llux -D0x%llux -R0x%ux\n", 254 HEADTYPE, INITTEXT, INITDAT, INITRND); 255 Bflush(&bso); 256 instinit(); 257 258 zprg.link = P; 259 zprg.pcond = P; 260 zprg.back = 2; 261 zprg.as = AGOK; 262 zprg.from.type = D_NONE; 263 zprg.from.index = D_NONE; 264 zprg.from.scale = 1; 265 zprg.to = zprg.from; 266 zprg.mode = 64; 267 268 pcstr = "%.6llux "; 269 histgen = 0; 270 pc = 0; 271 dtype = 4; 272 version = 0; 273 cbp = buf.cbuf; 274 cbc = sizeof(buf.cbuf); 275 276 addlibpath("command line", "command line", argv[0], "main"); 277 loadlib(); 278 deadcode(); 279 patch(); 280 follow(); 281 doelf(); 282 if(HEADTYPE == Hdarwin) 283 domacho(); 284 dostkoff(); 285 dostkcheck(); 286 paramspace = "SP"; /* (FP) now (SP) on output */ 287 if(debug['p']) 288 if(debug['1']) 289 doprof1(); 290 else 291 doprof2(); 292 span(); 293 if(HEADTYPE == Hwindows) 294 dope(); 295 addexport(); 296 textaddress(); 297 pclntab(); 298 symtab(); 299 dodata(); 300 address(); 301 doweak(); 302 reloc(); 303 asmb(); 304 undef(); 305 hostlink(); 306 if(debug['v']) { 307 Bprint(&bso, "%5.2f cpu time\n", cputime()); 308 Bprint(&bso, "%d symbols\n", nsymbol); 309 Bprint(&bso, "%d sizeof adr\n", sizeof(Adr)); 310 Bprint(&bso, "%d sizeof prog\n", sizeof(Prog)); 311 } 312 Bflush(&bso); 313 314 errorexit(); 315 } 316 317 static Sym* 318 zsym(char *pn, Biobuf *f, Sym *h[]) 319 { 320 int o; 321 322 o = BGETC(f); 323 if(o < 0 || o >= NSYM || h[o] == nil) 324 mangle(pn); 325 return h[o]; 326 } 327 328 static void 329 zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[]) 330 { 331 int t; 332 int32 l; 333 Sym *s; 334 Auto *u; 335 336 t = BGETC(f); 337 a->index = D_NONE; 338 a->scale = 0; 339 if(t & T_INDEX) { 340 a->index = BGETC(f); 341 a->scale = BGETC(f); 342 } 343 a->offset = 0; 344 if(t & T_OFFSET) { 345 a->offset = BGETLE4(f); 346 if(t & T_64) { 347 a->offset &= 0xFFFFFFFFULL; 348 a->offset |= (vlong)BGETLE4(f) << 32; 349 } 350 } 351 a->sym = S; 352 if(t & T_SYM) 353 a->sym = zsym(pn, f, h); 354 a->type = D_NONE; 355 if(t & T_FCONST) { 356 a->ieee.l = BGETLE4(f); 357 a->ieee.h = BGETLE4(f); 358 a->type = D_FCONST; 359 } else 360 if(t & T_SCONST) { 361 Bread(f, a->scon, NSNAME); 362 a->type = D_SCONST; 363 } 364 if(t & T_TYPE) 365 a->type = BGETC(f); 366 if(a->type < 0 || a->type >= D_SIZE) 367 mangle(pn); 368 adrgotype = S; 369 if(t & T_GOTYPE) 370 adrgotype = zsym(pn, f, h); 371 s = a->sym; 372 t = a->type; 373 if(t == D_INDIR+D_GS || a->index == D_GS) 374 a->offset += tlsoffset; 375 if(t != D_AUTO && t != D_PARAM) { 376 if(s && adrgotype) 377 s->gotype = adrgotype; 378 return; 379 } 380 l = a->offset; 381 for(u=curauto; u; u=u->link) { 382 if(u->asym == s) 383 if(u->type == t) { 384 if(u->aoffset > l) 385 u->aoffset = l; 386 if(adrgotype) 387 u->gotype = adrgotype; 388 return; 389 } 390 } 391 392 switch(t) { 393 case D_FILE: 394 case D_FILE1: 395 case D_AUTO: 396 case D_PARAM: 397 if(s == S) 398 mangle(pn); 399 } 400 401 u = mal(sizeof(*u)); 402 u->link = curauto; 403 curauto = u; 404 u->asym = s; 405 u->aoffset = l; 406 u->type = t; 407 u->gotype = adrgotype; 408 } 409 410 void 411 nopout(Prog *p) 412 { 413 p->as = ANOP; 414 p->from.type = D_NONE; 415 p->to.type = D_NONE; 416 } 417 418 void 419 ldobj1(Biobuf *f, char *pkg, int64 len, char *pn) 420 { 421 vlong ipc; 422 Prog *p; 423 int v, o, r, skip, mode; 424 Sym *h[NSYM], *s; 425 uint32 sig; 426 char *name, *x; 427 int ntext; 428 vlong eof; 429 char src[1024]; 430 Prog *lastp; 431 432 lastp = nil; 433 ntext = 0; 434 eof = Boffset(f) + len; 435 src[0] = 0; 436 pn = estrdup(pn); // we keep it in Sym* references 437 438 newloop: 439 memset(h, 0, sizeof(h)); 440 version++; 441 histfrogp = 0; 442 ipc = pc; 443 skip = 0; 444 mode = 64; 445 446 loop: 447 if(f->state == Bracteof || Boffset(f) >= eof) 448 goto eof; 449 o = BGETC(f); 450 if(o == Beof) 451 goto eof; 452 o |= BGETC(f) << 8; 453 if(o <= AXXX || o >= ALAST) { 454 if(o < 0) 455 goto eof; 456 diag("%s:#%lld: opcode out of range: %#ux", pn, Boffset(f), o); 457 print(" probably not a .6 file\n"); 458 errorexit(); 459 } 460 461 if(o == ANAME || o == ASIGNAME) { 462 sig = 0; 463 if(o == ASIGNAME) 464 sig = BGETLE4(f); 465 v = BGETC(f); /* type */ 466 o = BGETC(f); /* sym */ 467 r = 0; 468 if(v == D_STATIC) 469 r = version; 470 name = Brdline(f, '\0'); 471 if(name == nil) { 472 if(Blinelen(f) > 0) { 473 fprint(2, "%s: name too long\n", pn); 474 errorexit(); 475 } 476 goto eof; 477 } 478 x = expandpkg(name, pkg); 479 s = lookup(x, r); 480 if(x != name) 481 free(x); 482 483 if(debug['S'] && r == 0) 484 sig = 1729; 485 if(sig != 0){ 486 if(s->sig != 0 && s->sig != sig) 487 diag("incompatible type signatures " 488 "%ux(%s) and %ux(%s) for %s", 489 s->sig, s->file, sig, pn, s->name); 490 s->sig = sig; 491 s->file = pn; 492 } 493 494 if(debug['W']) 495 print(" ANAME %s\n", s->name); 496 if(o < 0 || o >= nelem(h)) 497 mangle(pn); 498 h[o] = s; 499 if((v == D_EXTERN || v == D_STATIC) && s->type == 0) 500 s->type = SXREF; 501 if(v == D_FILE) { 502 if(s->type != SFILE) { 503 histgen++; 504 s->type = SFILE; 505 s->value = histgen; 506 } 507 if(histfrogp < MAXHIST) { 508 histfrog[histfrogp] = s; 509 histfrogp++; 510 } else 511 collapsefrog(s); 512 dwarfaddfrag(s->value, s->name); 513 } 514 goto loop; 515 } 516 517 p = mal(sizeof(*p)); 518 p->as = o; 519 p->line = BGETLE4(f); 520 p->back = 2; 521 p->mode = mode; 522 zaddr(pn, f, &p->from, h); 523 fromgotype = adrgotype; 524 zaddr(pn, f, &p->to, h); 525 526 switch(p->as) { 527 case ATEXT: 528 case ADATA: 529 case AGLOBL: 530 if(p->from.sym == S) 531 mangle(pn); 532 break; 533 } 534 535 if(debug['W']) 536 print("%P\n", p); 537 538 switch(p->as) { 539 case AHISTORY: 540 if(p->to.offset == -1) { 541 addlib(src, pn); 542 histfrogp = 0; 543 goto loop; 544 } 545 if(src[0] == '\0') 546 copyhistfrog(src, sizeof src); 547 addhist(p->line, D_FILE); /* 'z' */ 548 if(p->to.offset) 549 addhist(p->to.offset, D_FILE1); /* 'Z' */ 550 savehist(p->line, p->to.offset); 551 histfrogp = 0; 552 goto loop; 553 554 case AEND: 555 histtoauto(); 556 if(cursym != nil && cursym->text) 557 cursym->autom = curauto; 558 curauto = 0; 559 cursym = nil; 560 if(Boffset(f) == eof) 561 return; 562 goto newloop; 563 564 case AGLOBL: 565 s = p->from.sym; 566 if(s->type == 0 || s->type == SXREF) { 567 s->type = SBSS; 568 s->size = 0; 569 } 570 if(s->type != SBSS && s->type != SNOPTRBSS && !s->dupok) { 571 diag("%s: redefinition: %s in %s", 572 pn, s->name, TNAME); 573 s->type = SBSS; 574 s->size = 0; 575 } 576 if(p->to.offset > s->size) 577 s->size = p->to.offset; 578 if(p->from.scale & DUPOK) 579 s->dupok = 1; 580 if(p->from.scale & RODATA) 581 s->type = SRODATA; 582 else if(p->from.scale & NOPTR) 583 s->type = SNOPTRBSS; 584 goto loop; 585 586 case ADATA: 587 // Assume that AGLOBL comes after ADATA. 588 // If we've seen an AGLOBL that said this sym was DUPOK, 589 // ignore any more ADATA we see, which must be 590 // redefinitions. 591 s = p->from.sym; 592 if(s->dupok) { 593 // if(debug['v']) 594 // Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn); 595 goto loop; 596 } 597 if(s->file == nil) 598 s->file = pn; 599 else if(s->file != pn) { 600 diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn); 601 errorexit(); 602 } 603 savedata(s, p, pn); 604 unmal(p, sizeof *p); 605 goto loop; 606 607 case AGOK: 608 diag("%s: GOK opcode in %s", pn, TNAME); 609 pc++; 610 goto loop; 611 612 case ATYPE: 613 if(skip) 614 goto casdef; 615 pc++; 616 goto loop; 617 618 case ATEXT: 619 s = p->from.sym; 620 if(s->text != nil) { 621 if(p->from.scale & DUPOK) { 622 skip = 1; 623 goto casdef; 624 } 625 diag("%s: %s: redefinition", pn, s->name); 626 return; 627 } 628 if(ntext++ == 0 && s->type != 0 && s->type != SXREF) { 629 /* redefinition, so file has probably been seen before */ 630 if(debug['v']) 631 Bprint(&bso, "skipping: %s: redefinition: %s", pn, s->name); 632 return; 633 } 634 if(cursym != nil && cursym->text) { 635 histtoauto(); 636 cursym->autom = curauto; 637 curauto = 0; 638 } 639 skip = 0; 640 if(etextp) 641 etextp->next = s; 642 else 643 textp = s; 644 etextp = s; 645 s->text = p; 646 cursym = s; 647 if(s->type != 0 && s->type != SXREF) { 648 if(p->from.scale & DUPOK) { 649 skip = 1; 650 goto casdef; 651 } 652 diag("%s: redefinition: %s\n%P", pn, s->name, p); 653 } 654 if(fromgotype) { 655 if(s->gotype && s->gotype != fromgotype) 656 diag("%s: type mismatch for %s", pn, s->name); 657 s->gotype = fromgotype; 658 } 659 s->type = STEXT; 660 s->hist = gethist(); 661 s->value = pc; 662 s->args = p->to.offset >> 32; 663 lastp = p; 664 p->pc = pc++; 665 goto loop; 666 667 case AMODE: 668 if(p->from.type == D_CONST || p->from.type == D_INDIR+D_NONE){ 669 switch((int)p->from.offset){ 670 case 16: case 32: case 64: 671 mode = p->from.offset; 672 break; 673 } 674 } 675 goto loop; 676 677 case AFMOVF: 678 case AFADDF: 679 case AFSUBF: 680 case AFSUBRF: 681 case AFMULF: 682 case AFDIVF: 683 case AFDIVRF: 684 case AFCOMF: 685 case AFCOMFP: 686 case AMOVSS: 687 case AADDSS: 688 case ASUBSS: 689 case AMULSS: 690 case ADIVSS: 691 case ACOMISS: 692 case AUCOMISS: 693 if(skip) 694 goto casdef; 695 if(p->from.type == D_FCONST) { 696 /* size sb 9 max */ 697 sprint(literal, "$%ux", ieeedtof(&p->from.ieee)); 698 s = lookup(literal, 0); 699 if(s->type == 0) { 700 s->type = SRODATA; 701 adduint32(s, ieeedtof(&p->from.ieee)); 702 s->reachable = 0; 703 } 704 p->from.type = D_EXTERN; 705 p->from.sym = s; 706 p->from.offset = 0; 707 } 708 goto casdef; 709 710 case AFMOVD: 711 case AFADDD: 712 case AFSUBD: 713 case AFSUBRD: 714 case AFMULD: 715 case AFDIVD: 716 case AFDIVRD: 717 case AFCOMD: 718 case AFCOMDP: 719 case AMOVSD: 720 case AADDSD: 721 case ASUBSD: 722 case AMULSD: 723 case ADIVSD: 724 case ACOMISD: 725 case AUCOMISD: 726 if(skip) 727 goto casdef; 728 if(p->from.type == D_FCONST) { 729 /* size sb 18 max */ 730 sprint(literal, "$%ux.%ux", 731 p->from.ieee.l, p->from.ieee.h); 732 s = lookup(literal, 0); 733 if(s->type == 0) { 734 s->type = SRODATA; 735 adduint32(s, p->from.ieee.l); 736 adduint32(s, p->from.ieee.h); 737 s->reachable = 0; 738 } 739 p->from.type = D_EXTERN; 740 p->from.sym = s; 741 p->from.offset = 0; 742 } 743 goto casdef; 744 745 casdef: 746 default: 747 if(skip) 748 nopout(p); 749 p->pc = pc; 750 pc++; 751 752 if(p->to.type == D_BRANCH) 753 p->to.offset += ipc; 754 if(lastp == nil) { 755 if(p->as != ANOP) 756 diag("unexpected instruction: %P", p); 757 goto loop; 758 } 759 lastp->link = p; 760 lastp = p; 761 goto loop; 762 } 763 764 eof: 765 diag("truncated object file: %s", pn); 766 } 767 768 Prog* 769 prg(void) 770 { 771 Prog *p; 772 773 p = mal(sizeof(*p)); 774 775 *p = zprg; 776 return p; 777 } 778 779 Prog* 780 copyp(Prog *q) 781 { 782 Prog *p; 783 784 p = prg(); 785 *p = *q; 786 return p; 787 } 788 789 Prog* 790 appendp(Prog *q) 791 { 792 Prog *p; 793 794 p = prg(); 795 p->link = q->link; 796 q->link = p; 797 p->line = q->line; 798 p->mode = q->mode; 799 return p; 800 }