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