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