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