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