github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/5l/obj.c (about) 1 // Inferno utils/5l/obj.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/5l/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/dwarf.h" 38 #include <ar.h> 39 40 #ifndef DEFAULT 41 #define DEFAULT '9' 42 #endif 43 44 char *noname = "<none>"; 45 char *thestring = "arm"; 46 47 Header headers[] = { 48 "noheader", Hnoheader, 49 "risc", Hrisc, 50 "plan9", Hplan9x32, 51 "ixp1200", Hixp1200, 52 "ipaq", Hipaq, 53 "linux", Hlinux, 54 "freebsd", Hfreebsd, 55 "netbsd", Hnetbsd, 56 0, 0 57 }; 58 59 /* 60 * -Hrisc -T0x10005000 -R4 is aif for risc os 61 * -Hplan9 -T4128 -R4096 is plan9 format 62 * -Hixp1200 is IXP1200 (raw) 63 * -Hipaq -T0xC0008010 -R1024 is ipaq 64 * -Hlinux -Tx -Rx is linux elf 65 * -Hfreebsd is freebsd elf 66 * -Hnetbsd is netbsd elf 67 */ 68 69 void 70 main(int argc, char *argv[]) 71 { 72 char *p; 73 Sym *s; 74 75 Binit(&bso, 1, OWRITE); 76 listinit(); 77 nerrors = 0; 78 outfile = "5.out"; 79 HEADTYPE = -1; 80 INITTEXT = -1; 81 INITDAT = -1; 82 INITRND = -1; 83 INITENTRY = 0; 84 LIBINITENTRY = 0; 85 linkmode = LinkInternal; // TODO: LinkAuto once everything works. 86 nuxiinit(); 87 88 p = getgoarm(); 89 if(p != nil) 90 goarm = atoi(p); 91 else 92 goarm = 6; 93 if(goarm == 5) 94 debug['F'] = 1; 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 flagcount("G", "debug pseudo-ops", &debug['G']); 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("M", "disable software div/mod", &debug['M']); 106 flagcount("O", "print pc-line tables", &debug['O']); 107 flagcount("P", "debug code generation", &debug['P']); 108 flagint32("R", "rnd: address rounding", &INITRND); 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("k", "sym: set field tracking symbol", &tracksym); 122 flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode); 123 flagcount("n", "dump symbol table", &debug['n']); 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 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 flagcount("shared", "generate shared object", &flag_shared); 134 // TODO: link mode flag 135 136 flagparse(&argc, &argv, usage); 137 138 if(argc != 1) 139 usage(); 140 141 // getgoextlinkenabled is based on GO_EXTLINK_ENABLED when 142 // Go was built; see ../../make.bash. 143 if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0) 144 linkmode = LinkInternal; 145 146 if(linkmode == LinkExternal) { 147 diag("only -linkmode=internal is supported"); 148 errorexit(); 149 } else if(linkmode == LinkAuto) { 150 linkmode = LinkInternal; 151 } 152 153 libinit(); 154 155 if(HEADTYPE == -1) 156 HEADTYPE = headtype(goos); 157 switch(HEADTYPE) { 158 default: 159 diag("unknown -H option"); 160 errorexit(); 161 case Hnoheader: /* no header */ 162 HEADR = 0L; 163 if(INITTEXT == -1) 164 INITTEXT = 0; 165 if(INITDAT == -1) 166 INITDAT = 0; 167 if(INITRND == -1) 168 INITRND = 4; 169 break; 170 case Hrisc: /* aif for risc os */ 171 HEADR = 128L; 172 if(INITTEXT == -1) 173 INITTEXT = 0x10005000 + HEADR; 174 if(INITDAT == -1) 175 INITDAT = 0; 176 if(INITRND == -1) 177 INITRND = 4; 178 break; 179 case Hplan9x32: /* plan 9 */ 180 HEADR = 32L; 181 if(INITTEXT == -1) 182 INITTEXT = 4128; 183 if(INITDAT == -1) 184 INITDAT = 0; 185 if(INITRND == -1) 186 INITRND = 4096; 187 break; 188 case Hixp1200: /* boot for IXP1200 */ 189 HEADR = 0L; 190 if(INITTEXT == -1) 191 INITTEXT = 0x0; 192 if(INITDAT == -1) 193 INITDAT = 0; 194 if(INITRND == -1) 195 INITRND = 4; 196 break; 197 case Hipaq: /* boot for ipaq */ 198 HEADR = 16L; 199 if(INITTEXT == -1) 200 INITTEXT = 0xC0008010; 201 if(INITDAT == -1) 202 INITDAT = 0; 203 if(INITRND == -1) 204 INITRND = 1024; 205 break; 206 case Hlinux: /* arm elf */ 207 case Hfreebsd: 208 case Hnetbsd: 209 debug['d'] = 0; // with dynamic linking 210 tlsoffset = -8; // hardcoded number, first 4-byte word for g, and then 4-byte word for m 211 // this number is known to ../../pkg/runtime/cgo/gcc_linux_arm.c 212 elfinit(); 213 HEADR = ELFRESERVE; 214 if(INITTEXT == -1) 215 INITTEXT = 0x10000 + HEADR; 216 if(INITDAT == -1) 217 INITDAT = 0; 218 if(INITRND == -1) 219 INITRND = 4096; 220 break; 221 } 222 if(INITDAT != 0 && INITRND != 0) 223 print("warning: -D0x%ux is ignored because of -R0x%ux\n", 224 INITDAT, INITRND); 225 if(debug['v']) 226 Bprint(&bso, "HEADER = -H0x%d -T0x%ux -D0x%ux -R0x%ux\n", 227 HEADTYPE, INITTEXT, INITDAT, INITRND); 228 Bflush(&bso); 229 zprg.as = AGOK; 230 zprg.scond = 14; 231 zprg.reg = NREG; 232 zprg.from.name = D_NONE; 233 zprg.from.type = D_NONE; 234 zprg.from.reg = NREG; 235 zprg.to = zprg.from; 236 buildop(); 237 histgen = 0; 238 pc = 0; 239 dtype = 4; 240 241 version = 0; 242 cbp = buf.cbuf; 243 cbc = sizeof(buf.cbuf); 244 245 // embed goarm to runtime.goarm 246 s = lookup("runtime.goarm", 0); 247 s->dupok = 1; 248 adduint8(s, goarm); 249 250 addlibpath("command line", "command line", argv[0], "main"); 251 loadlib(); 252 253 // mark some functions that are only referenced after linker code editing 254 if(debug['F']) 255 mark(rlookup("_sfloat", 0)); 256 deadcode(); 257 if(textp == nil) { 258 diag("no code"); 259 errorexit(); 260 } 261 262 patch(); 263 if(debug['p']) 264 if(debug['1']) 265 doprof1(); 266 else 267 doprof2(); 268 doelf(); 269 follow(); 270 softfloat(); 271 // 5l -Z means zero the stack frame on entry. 272 // This slows down function calls but can help avoid 273 // false positives in garbage collection. 274 if(debug['Z']) 275 dozerostk(); 276 noops(); // generate stack split prolog, handle div/mod, etc. 277 dostkcheck(); 278 span(); 279 addexport(); 280 // textaddress() functionality is handled in span() 281 pclntab(); 282 symtab(); 283 dodata(); 284 address(); 285 doweak(); 286 reloc(); 287 asmb(); 288 undef(); 289 hostlink(); 290 291 if(debug['c']) 292 print("ARM size = %d\n", armsize); 293 if(debug['v']) { 294 Bprint(&bso, "%5.2f cpu time\n", cputime()); 295 Bprint(&bso, "%d sizeof adr\n", sizeof(Adr)); 296 Bprint(&bso, "%d sizeof prog\n", sizeof(Prog)); 297 } 298 Bflush(&bso); 299 errorexit(); 300 } 301 302 static Sym* 303 zsym(char *pn, Biobuf *f, Sym *h[]) 304 { 305 int o; 306 307 o = BGETC(f); 308 if(o == 0) 309 return S; 310 if(o < 0 || o >= NSYM || h[o] == nil) 311 mangle(pn); 312 return h[o]; 313 } 314 315 static void 316 zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[]) 317 { 318 int i, c; 319 int32 l; 320 Sym *s; 321 Auto *u; 322 323 a->type = BGETC(f); 324 a->reg = BGETC(f); 325 c = BGETC(f); 326 if(c < 0 || c > NSYM){ 327 print("sym out of range: %d\n", c); 328 Bputc(f, ALAST+1); 329 return; 330 } 331 a->sym = h[c]; 332 a->name = BGETC(f); 333 adrgotype = zsym(pn, f, h); 334 335 if((schar)a->reg < 0 || a->reg > NREG) { 336 print("register out of range %d\n", a->reg); 337 Bputc(f, ALAST+1); 338 return; /* force real diagnostic */ 339 } 340 341 if(a->type == D_CONST || a->type == D_OCONST) { 342 if(a->name == D_EXTERN || a->name == D_STATIC) { 343 s = a->sym; 344 if(s != S && (s->type == STEXT || s->type == SCONST || s->type == SXREF)) { 345 if(0 && !s->fnptr && s->name[0] != '.') 346 print("%s used as function pointer\n", s->name); 347 s->fnptr = 1; // over the top cos of SXREF 348 } 349 } 350 } 351 352 switch(a->type) { 353 default: 354 print("unknown type %d\n", a->type); 355 Bputc(f, ALAST+1); 356 return; /* force real diagnostic */ 357 358 case D_NONE: 359 case D_REG: 360 case D_FREG: 361 case D_PSR: 362 case D_FPCR: 363 break; 364 365 case D_REGREG: 366 case D_REGREG2: 367 a->offset = BGETC(f); 368 break; 369 370 case D_CONST2: 371 a->offset2 = Bget4(f); // fall through 372 case D_BRANCH: 373 case D_OREG: 374 case D_CONST: 375 case D_OCONST: 376 case D_SHIFT: 377 a->offset = Bget4(f); 378 break; 379 380 case D_SCONST: 381 a->sval = mal(NSNAME); 382 Bread(f, a->sval, NSNAME); 383 break; 384 385 case D_FCONST: 386 a->ieee.l = Bget4(f); 387 a->ieee.h = Bget4(f); 388 break; 389 } 390 s = a->sym; 391 if(s == S) 392 return; 393 i = a->name; 394 if(i != D_AUTO && i != D_PARAM) { 395 if(s && adrgotype) 396 s->gotype = adrgotype; 397 return; 398 } 399 400 l = a->offset; 401 for(u=curauto; u; u=u->link) 402 if(u->asym == s) 403 if(u->type == i) { 404 if(u->aoffset > l) 405 u->aoffset = l; 406 if(adrgotype) 407 u->gotype = adrgotype; 408 return; 409 } 410 411 u = mal(sizeof(Auto)); 412 u->link = curauto; 413 curauto = u; 414 u->asym = s; 415 u->aoffset = l; 416 u->type = i; 417 u->gotype = adrgotype; 418 } 419 420 void 421 nopout(Prog *p) 422 { 423 p->as = ANOP; 424 p->from.type = D_NONE; 425 p->to.type = D_NONE; 426 } 427 428 void 429 ldobj1(Biobuf *f, char *pkg, int64 len, char *pn) 430 { 431 int32 ipc; 432 Prog *p; 433 Sym *h[NSYM], *s; 434 int v, o, r, skip; 435 uint32 sig; 436 char *name; 437 int ntext; 438 int32 eof; 439 char src[1024], *x; 440 Prog *lastp; 441 442 lastp = nil; 443 ntext = 0; 444 eof = Boffset(f) + len; 445 src[0] = 0; 446 pn = estrdup(pn); // we keep it in Sym* references 447 448 newloop: 449 memset(h, 0, sizeof(h)); 450 version++; 451 histfrogp = 0; 452 ipc = pc; 453 skip = 0; 454 455 loop: 456 if(f->state == Bracteof || Boffset(f) >= eof) 457 goto eof; 458 o = BGETC(f); 459 if(o == Beof) 460 goto eof; 461 462 if(o <= AXXX || o >= ALAST) { 463 diag("%s:#%lld: opcode out of range: %#ux", pn, Boffset(f), o); 464 print(" probably not a .5 file\n"); 465 errorexit(); 466 } 467 if(o == ANAME || o == ASIGNAME) { 468 sig = 0; 469 if(o == ASIGNAME) 470 sig = Bget4(f); 471 v = BGETC(f); /* type */ 472 o = BGETC(f); /* sym */ 473 r = 0; 474 if(v == D_STATIC) 475 r = version; 476 name = Brdline(f, '\0'); 477 if(name == nil) { 478 if(Blinelen(f) > 0) { 479 fprint(2, "%s: name too long\n", pn); 480 errorexit(); 481 } 482 goto eof; 483 } 484 x = expandpkg(name, pkg); 485 s = lookup(x, r); 486 if(x != name) 487 free(x); 488 489 if(sig != 0){ 490 if(s->sig != 0 && s->sig != sig) 491 diag("incompatible type signatures %ux(%s) and %ux(%s) for %s", s->sig, s->file, sig, pn, s->name); 492 s->sig = sig; 493 s->file = pn; 494 } 495 496 if(debug['W']) 497 print(" ANAME %s\n", s->name); 498 if(o < 0 || o >= nelem(h)) { 499 fprint(2, "%s: mangled input file\n", pn); 500 errorexit(); 501 } 502 h[o] = s; 503 if((v == D_EXTERN || v == D_STATIC) && s->type == 0) 504 s->type = SXREF; 505 if(v == D_FILE) { 506 if(s->type != SFILE) { 507 histgen++; 508 s->type = SFILE; 509 s->value = histgen; 510 } 511 if(histfrogp < MAXHIST) { 512 histfrog[histfrogp] = s; 513 histfrogp++; 514 } else 515 collapsefrog(s); 516 dwarfaddfrag(s->value, s->name); 517 } 518 goto loop; 519 } 520 521 p = mal(sizeof(Prog)); 522 p->as = o; 523 p->scond = BGETC(f); 524 p->reg = BGETC(f); 525 p->line = Bget4(f); 526 527 zaddr(pn, f, &p->from, h); 528 fromgotype = adrgotype; 529 zaddr(pn, f, &p->to, h); 530 531 if(p->as != ATEXT && p->as != AGLOBL && p->reg > NREG) 532 diag("register out of range %A %d", p->as, p->reg); 533 534 p->link = P; 535 p->cond = P; 536 537 if(debug['W']) 538 print("%P\n", p); 539 540 switch(o) { 541 case AHISTORY: 542 if(p->to.offset == -1) { 543 addlib(src, pn); 544 histfrogp = 0; 545 goto loop; 546 } 547 if(src[0] == '\0') 548 copyhistfrog(src, sizeof src); 549 addhist(p->line, D_FILE); /* 'z' */ 550 if(p->to.offset) 551 addhist(p->to.offset, D_FILE1); /* 'Z' */ 552 histfrogp = 0; 553 goto loop; 554 555 case AEND: 556 histtoauto(); 557 if(cursym != nil && cursym->text) 558 cursym->autom = curauto; 559 curauto = 0; 560 cursym = nil; 561 if(Boffset(f) == eof) 562 return; 563 goto newloop; 564 565 case AGLOBL: 566 s = p->from.sym; 567 if(s == S) { 568 diag("GLOBL must have a name\n%P", p); 569 errorexit(); 570 } 571 if(s->type == 0 || s->type == SXREF) { 572 s->type = SBSS; 573 s->value = 0; 574 } 575 if(s->type != SBSS && s->type != SNOPTRBSS && !s->dupok) { 576 diag("redefinition: %s\n%P", s->name, p); 577 s->type = SBSS; 578 s->value = 0; 579 } 580 if(p->to.offset > s->size) 581 s->size = p->to.offset; 582 if(p->reg & DUPOK) 583 s->dupok = 1; 584 if(p->reg & RODATA) 585 s->type = SRODATA; 586 else if(p->reg & NOPTR) 587 s->type = SNOPTRBSS; 588 break; 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 break; 610 611 case AGOK: 612 diag("unknown opcode\n%P", p); 613 p->pc = pc; 614 pc++; 615 break; 616 617 case ALOCALS: 618 if(skip) 619 goto casedef; 620 cursym->locals = p->to.offset; 621 pc++; 622 break; 623 624 case ATYPE: 625 if(skip) 626 goto casedef; 627 pc++; 628 goto loop; 629 630 case ATEXT: 631 if(cursym != nil && cursym->text) { 632 histtoauto(); 633 cursym->autom = curauto; 634 curauto = 0; 635 } 636 s = p->from.sym; 637 if(s == S) { 638 diag("TEXT must have a name\n%P", p); 639 errorexit(); 640 } 641 cursym = s; 642 if(s->type != 0 && s->type != SXREF && (p->reg & DUPOK)) { 643 skip = 1; 644 goto casedef; 645 } 646 if(ntext++ == 0 && s->type != 0 && s->type != SXREF) { 647 /* redefinition, so file has probably been seen before */ 648 if(debug['v']) 649 Bprint(&bso, "skipping: %s: redefinition: %s", pn, s->name); 650 return; 651 } 652 skip = 0; 653 if(s->type != 0 && s->type != SXREF) 654 diag("redefinition: %s\n%P", s->name, p); 655 if(etextp) 656 etextp->next = s; 657 else 658 textp = s; 659 if(fromgotype) { 660 if(s->gotype && s->gotype != fromgotype) 661 diag("%s: type mismatch for %s", pn, s->name); 662 s->gotype = fromgotype; 663 } 664 etextp = s; 665 p->align = 4; 666 autosize = (p->to.offset+3L) & ~3L; 667 p->to.offset = autosize; 668 autosize += 4; 669 s->type = STEXT; 670 s->text = p; 671 s->value = pc; 672 s->args = p->to.offset2; 673 lastp = p; 674 p->pc = pc; 675 pc++; 676 break; 677 678 case ASUB: 679 if(p->from.type == D_CONST) 680 if(p->from.name == D_NONE) 681 if(p->from.offset < 0) { 682 p->from.offset = -p->from.offset; 683 p->as = AADD; 684 } 685 goto casedef; 686 687 case AADD: 688 if(p->from.type == D_CONST) 689 if(p->from.name == D_NONE) 690 if(p->from.offset < 0) { 691 p->from.offset = -p->from.offset; 692 p->as = ASUB; 693 } 694 goto casedef; 695 696 case AMOVWD: 697 case AMOVWF: 698 case AMOVDW: 699 case AMOVFW: 700 case AMOVFD: 701 case AMOVDF: 702 // case AMOVF: 703 // case AMOVD: 704 case ACMPF: 705 case ACMPD: 706 case AADDF: 707 case AADDD: 708 case ASUBF: 709 case ASUBD: 710 case AMULF: 711 case AMULD: 712 case ADIVF: 713 case ADIVD: 714 goto casedef; 715 716 case AMOVF: 717 if(skip) 718 goto casedef; 719 720 if(p->from.type == D_FCONST && chipfloat(&p->from.ieee) < 0 && 721 (chipzero(&p->from.ieee) < 0 || (p->scond & C_SCOND) != C_SCOND_NONE)) { 722 /* size sb 9 max */ 723 sprint(literal, "$%ux", ieeedtof(&p->from.ieee)); 724 s = lookup(literal, 0); 725 if(s->type == 0) { 726 s->type = SRODATA; 727 adduint32(s, ieeedtof(&p->from.ieee)); 728 s->reachable = 0; 729 } 730 p->from.type = D_OREG; 731 p->from.sym = s; 732 p->from.name = D_EXTERN; 733 p->from.offset = 0; 734 } 735 goto casedef; 736 737 case AMOVD: 738 if(skip) 739 goto casedef; 740 741 if(p->from.type == D_FCONST && chipfloat(&p->from.ieee) < 0 && 742 (chipzero(&p->from.ieee) < 0 || (p->scond & C_SCOND) != C_SCOND_NONE)) { 743 /* size sb 18 max */ 744 sprint(literal, "$%ux.%ux", 745 p->from.ieee.l, p->from.ieee.h); 746 s = lookup(literal, 0); 747 if(s->type == 0) { 748 s->type = SRODATA; 749 adduint32(s, p->from.ieee.l); 750 adduint32(s, p->from.ieee.h); 751 s->reachable = 0; 752 } 753 p->from.type = D_OREG; 754 p->from.sym = s; 755 p->from.name = D_EXTERN; 756 p->from.offset = 0; 757 } 758 goto casedef; 759 760 default: 761 casedef: 762 if(skip) 763 nopout(p); 764 p->pc = pc; 765 pc++; 766 if(p->to.type == D_BRANCH) 767 p->to.offset += ipc; 768 if(lastp == nil) { 769 if(p->as != ANOP) 770 diag("unexpected instruction: %P", p); 771 break; 772 } 773 lastp->link = p; 774 lastp = p; 775 break; 776 } 777 goto loop; 778 779 eof: 780 diag("truncated object file: %s", pn); 781 } 782 783 Prog* 784 prg(void) 785 { 786 Prog *p; 787 788 p = mal(sizeof(Prog)); 789 *p = zprg; 790 return p; 791 } 792 793 Prog* 794 appendp(Prog *q) 795 { 796 Prog *p; 797 798 p = prg(); 799 p->link = q->link; 800 q->link = p; 801 p->line = q->line; 802 return p; 803 }