github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/cmd/internal/ld/lib.go (about) 1 // Inferno utils/8l/asm.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/8l/asm.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 package ld 32 33 import ( 34 "bytes" 35 "cmd/internal/obj" 36 "debug/elf" 37 "fmt" 38 "io" 39 "io/ioutil" 40 "log" 41 "os" 42 "os/exec" 43 "path/filepath" 44 "strings" 45 ) 46 47 // Data layout and relocation. 48 49 // Derived from Inferno utils/6l/l.h 50 // http://code.google.com/p/inferno-os/source/browse/utils/6l/l.h 51 // 52 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 53 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 54 // Portions Copyright © 1997-1999 Vita Nuova Limited 55 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 56 // Portions Copyright © 2004,2006 Bruce Ellis 57 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 58 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 59 // Portions Copyright © 2009 The Go Authors. All rights reserved. 60 // 61 // Permission is hereby granted, free of charge, to any person obtaining a copy 62 // of this software and associated documentation files (the "Software"), to deal 63 // in the Software without restriction, including without limitation the rights 64 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 65 // copies of the Software, and to permit persons to whom the Software is 66 // furnished to do so, subject to the following conditions: 67 // 68 // The above copyright notice and this permission notice shall be included in 69 // all copies or substantial portions of the Software. 70 // 71 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 72 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 73 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 74 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 75 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 76 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 77 // THE SOFTWARE. 78 79 type Arch struct { 80 Thechar int 81 Ptrsize int 82 Intsize int 83 Regsize int 84 Funcalign int 85 Maxalign int 86 Minlc int 87 Dwarfregsp int 88 Linuxdynld string 89 Freebsddynld string 90 Netbsddynld string 91 Openbsddynld string 92 Dragonflydynld string 93 Solarisdynld string 94 Adddynlib func(string) 95 Adddynrel func(*LSym, *Reloc) 96 Adddynsym func(*Link, *LSym) 97 Archinit func() 98 Archreloc func(*Reloc, *LSym, *int64) int 99 Archrelocvariant func(*Reloc, *LSym, int64) int64 100 Asmb func() 101 Elfreloc1 func(*Reloc, int64) int 102 Elfsetupplt func() 103 Gentext func() 104 Machoreloc1 func(*Reloc, int64) int 105 PEreloc1 func(*Reloc, int64) bool 106 Lput func(uint32) 107 Wput func(uint16) 108 Vput func(uint64) 109 } 110 111 type Rpath struct { 112 set bool 113 val string 114 } 115 116 func (r *Rpath) Set(val string) error { 117 r.set = true 118 r.val = val 119 return nil 120 } 121 122 func (r *Rpath) String() string { 123 return r.val 124 } 125 126 var ( 127 Thearch Arch 128 datap *LSym 129 Debug [128]int 130 Lcsize int32 131 rpath Rpath 132 Spsize int32 133 Symsize int32 134 ) 135 136 // Terrible but standard terminology. 137 // A segment describes a block of file to load into memory. 138 // A section further describes the pieces of that block for 139 // use in debuggers and such. 140 141 const ( 142 MAXIO = 8192 143 MINFUNC = 16 // minimum size for a function 144 ) 145 146 type Segment struct { 147 Rwx uint8 // permission as usual unix bits (5 = r-x etc) 148 Vaddr uint64 // virtual address 149 Length uint64 // length in memory 150 Fileoff uint64 // file offset 151 Filelen uint64 // length on disk 152 Sect *Section 153 } 154 155 type Section struct { 156 Rwx uint8 157 Extnum int16 158 Align int32 159 Name string 160 Vaddr uint64 161 Length uint64 162 Next *Section 163 Seg *Segment 164 Elfsect interface{} 165 Reloff uint64 166 Rellen uint64 167 } 168 169 // DynlinkingGo returns whether we are producing Go code that can live 170 // in separate shared libraries linked together at runtime. 171 func DynlinkingGo() bool { 172 return Buildmode == BuildmodeShared || Linkshared 173 } 174 175 var ( 176 Thestring string 177 Thelinkarch *LinkArch 178 outfile string 179 dynexp []*LSym 180 ldflag []string 181 havedynamic int 182 Funcalign int 183 iscgo bool 184 elfglobalsymndx int 185 flag_installsuffix string 186 flag_race int 187 Buildmode BuildMode 188 Linkshared bool 189 tracksym string 190 interpreter string 191 tmpdir string 192 extld string 193 extldflags string 194 debug_s int // backup old value of debug['s'] 195 Ctxt *Link 196 HEADR int32 197 HEADTYPE int32 198 INITRND int32 199 INITTEXT int64 200 INITDAT int64 201 INITENTRY string /* entry point */ 202 nerrors int 203 Linkmode int 204 liveness int64 205 ) 206 207 // for dynexport field of LSym 208 const ( 209 CgoExportDynamic = 1 << 0 210 CgoExportStatic = 1 << 1 211 ) 212 213 var ( 214 Segtext Segment 215 Segrodata Segment 216 Segdata Segment 217 Segdwarf Segment 218 ) 219 220 /* set by call to mywhatsys() */ 221 222 /* whence for ldpkg */ 223 const ( 224 FileObj = 0 + iota 225 ArchiveObj 226 Pkgdef 227 ) 228 229 var ( 230 headstring string 231 // buffered output 232 Bso Biobuf 233 coutbuf Biobuf 234 ) 235 236 const ( 237 // Whether to assume that the external linker is "gold" 238 // (http://sourceware.org/ml/binutils/2008-03/msg00162.html). 239 AssumeGoldLinker = 0 240 ) 241 242 const ( 243 symname = "__.GOSYMDEF" 244 pkgname = "__.PKGDEF" 245 ) 246 247 var ( 248 cout *os.File 249 // Set if we see an object compiled by the host compiler that is not 250 // from a package that is known to support internal linking mode. 251 externalobj = false 252 goroot string 253 goarch string 254 goos string 255 theline string 256 ) 257 258 func Lflag(arg string) { 259 Ctxt.Libdir = append(Ctxt.Libdir, arg) 260 } 261 262 // A BuildMode indicates the sort of object we are building: 263 // "exe": build a main package and everything it imports into an executable. 264 // "c-shared": build a main package, plus all packages that it imports, into a 265 // single C shared library. The only callable symbols will be those functions 266 // marked as exported. 267 // "shared": combine all packages passed on the command line, and their 268 // dependencies, into a single shared library that will be used when 269 // building with the -linkshared option. 270 type BuildMode uint8 271 272 const ( 273 BuildmodeExe BuildMode = iota 274 BuildmodeCArchive 275 BuildmodeCShared 276 BuildmodeShared 277 ) 278 279 func (mode *BuildMode) Set(s string) error { 280 goos := obj.Getgoos() 281 goarch := obj.Getgoarch() 282 badmode := func() error { 283 return fmt.Errorf("buildmode %s not supported on %s/%s", s, goos, goarch) 284 } 285 switch s { 286 default: 287 return fmt.Errorf("invalid buildmode: %q", s) 288 case "exe": 289 *mode = BuildmodeExe 290 case "c-archive": 291 if goos != "darwin" { 292 return badmode() 293 } 294 *mode = BuildmodeCArchive 295 case "c-shared": 296 if goarch != "amd64" && goarch != "arm" { 297 return badmode() 298 } 299 *mode = BuildmodeCShared 300 case "shared": 301 if goos != "linux" || goarch != "amd64" { 302 return badmode() 303 } 304 *mode = BuildmodeShared 305 } 306 return nil 307 } 308 309 func (mode *BuildMode) String() string { 310 switch *mode { 311 case BuildmodeExe: 312 return "exe" 313 case BuildmodeCArchive: 314 return "c-archive" 315 case BuildmodeCShared: 316 return "c-shared" 317 case BuildmodeShared: 318 return "shared" 319 } 320 return fmt.Sprintf("BuildMode(%d)", uint8(*mode)) 321 } 322 323 /* 324 * Unix doesn't like it when we write to a running (or, sometimes, 325 * recently run) binary, so remove the output file before writing it. 326 * On Windows 7, remove() can force a subsequent create() to fail. 327 * S_ISREG() does not exist on Plan 9. 328 */ 329 func mayberemoveoutfile() { 330 if fi, err := os.Lstat(outfile); err == nil && !fi.Mode().IsRegular() { 331 return 332 } 333 os.Remove(outfile) 334 } 335 336 func libinit() { 337 Funcalign = Thearch.Funcalign 338 mywhatsys() // get goroot, goarch, goos 339 340 // add goroot to the end of the libdir list. 341 suffix := "" 342 343 suffixsep := "" 344 if flag_installsuffix != "" { 345 suffixsep = "_" 346 suffix = flag_installsuffix 347 } else if flag_race != 0 { 348 suffixsep = "_" 349 suffix = "race" 350 } 351 352 Lflag(fmt.Sprintf("%s/pkg/%s_%s%s%s", goroot, goos, goarch, suffixsep, suffix)) 353 354 mayberemoveoutfile() 355 f, err := os.OpenFile(outfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0775) 356 if err != nil { 357 Diag("cannot create %s: %v", outfile, err) 358 Errorexit() 359 } 360 361 cout = f 362 coutbuf = *Binitw(f) 363 364 if INITENTRY == "" { 365 switch Buildmode { 366 case BuildmodeCShared, BuildmodeCArchive: 367 INITENTRY = fmt.Sprintf("_rt0_%s_%s_lib", goarch, goos) 368 case BuildmodeExe: 369 INITENTRY = fmt.Sprintf("_rt0_%s_%s", goarch, goos) 370 case BuildmodeShared: 371 // No INITENTRY for -buildmode=shared 372 default: 373 Diag("unknown INITENTRY for buildmode %v", Buildmode) 374 } 375 } 376 377 if !DynlinkingGo() { 378 Linklookup(Ctxt, INITENTRY, 0).Type = SXREF 379 } 380 } 381 382 func Errorexit() { 383 if cout != nil { 384 // For rmtemp run at atexit time on Windows. 385 cout.Close() 386 } 387 388 if nerrors != 0 { 389 if cout != nil { 390 mayberemoveoutfile() 391 } 392 Exit(2) 393 } 394 395 Exit(0) 396 } 397 398 func loadinternal(name string) { 399 found := 0 400 for i := 0; i < len(Ctxt.Libdir); i++ { 401 if Linkshared { 402 shlibname := fmt.Sprintf("%s/%s.shlibname", Ctxt.Libdir[i], name) 403 if Debug['v'] != 0 { 404 fmt.Fprintf(&Bso, "searching for %s.a in %s\n", name, shlibname) 405 } 406 if obj.Access(shlibname, obj.AEXIST) >= 0 { 407 addlibpath(Ctxt, "internal", "internal", "", name, shlibname) 408 found = 1 409 break 410 } 411 } 412 pname := fmt.Sprintf("%s/%s.a", Ctxt.Libdir[i], name) 413 if Debug['v'] != 0 { 414 fmt.Fprintf(&Bso, "searching for %s.a in %s\n", name, pname) 415 } 416 if obj.Access(pname, obj.AEXIST) >= 0 { 417 addlibpath(Ctxt, "internal", "internal", pname, name, "") 418 found = 1 419 break 420 } 421 } 422 423 if found == 0 { 424 fmt.Fprintf(&Bso, "warning: unable to find %s.a\n", name) 425 } 426 } 427 428 func loadlib() { 429 switch Buildmode { 430 case BuildmodeCShared: 431 s := Linklookup(Ctxt, "runtime.islibrary", 0) 432 s.Dupok = 1 433 Adduint8(Ctxt, s, 1) 434 case BuildmodeCArchive: 435 s := Linklookup(Ctxt, "runtime.isarchive", 0) 436 s.Dupok = 1 437 Adduint8(Ctxt, s, 1) 438 } 439 440 loadinternal("runtime") 441 if Thearch.Thechar == '5' { 442 loadinternal("math") 443 } 444 if flag_race != 0 { 445 loadinternal("runtime/race") 446 } 447 448 var i int 449 for i = 0; i < len(Ctxt.Library); i++ { 450 if Debug['v'] > 1 { 451 fmt.Fprintf(&Bso, "%5.2f autolib: %s (from %s)\n", obj.Cputime(), Ctxt.Library[i].File, Ctxt.Library[i].Objref) 452 } 453 iscgo = iscgo || Ctxt.Library[i].Pkg == "runtime/cgo" 454 if Ctxt.Library[i].Shlib != "" { 455 ldshlibsyms(Ctxt.Library[i].Shlib) 456 } else { 457 objfile(Ctxt.Library[i].File, Ctxt.Library[i].Pkg) 458 } 459 } 460 461 if Linkmode == LinkAuto { 462 if iscgo && externalobj { 463 Linkmode = LinkExternal 464 } else { 465 Linkmode = LinkInternal 466 } 467 468 // Force external linking for android. 469 if goos == "android" { 470 Linkmode = LinkExternal 471 } 472 473 // cgo on Darwin must use external linking 474 // we can always use external linking, but then there will be circular 475 // dependency problems when compiling natively (external linking requires 476 // runtime/cgo, runtime/cgo requires cmd/cgo, but cmd/cgo needs to be 477 // compiled using external linking.) 478 if (Thearch.Thechar == '5' || Thearch.Thechar == '7') && HEADTYPE == Hdarwin && iscgo { 479 Linkmode = LinkExternal 480 } 481 } 482 483 // cmd/7l doesn't support cgo internal linking 484 // This is https://golang.org/issue/10373. 485 if iscgo && goarch == "arm64" { 486 Linkmode = LinkExternal 487 } 488 489 if Linkmode == LinkExternal && !iscgo { 490 // This indicates a user requested -linkmode=external. 491 // The startup code uses an import of runtime/cgo to decide 492 // whether to initialize the TLS. So give it one. This could 493 // be handled differently but it's an unusual case. 494 loadinternal("runtime/cgo") 495 496 if i < len(Ctxt.Library) { 497 if Ctxt.Library[i].Shlib != "" { 498 ldshlibsyms(Ctxt.Library[i].Shlib) 499 } else { 500 objfile(Ctxt.Library[i].File, Ctxt.Library[i].Pkg) 501 } 502 } 503 } 504 505 if Linkmode == LinkInternal { 506 // Drop all the cgo_import_static declarations. 507 // Turns out we won't be needing them. 508 for s := Ctxt.Allsym; s != nil; s = s.Allsym { 509 if s.Type == SHOSTOBJ { 510 // If a symbol was marked both 511 // cgo_import_static and cgo_import_dynamic, 512 // then we want to make it cgo_import_dynamic 513 // now. 514 if s.Extname != "" && s.Dynimplib != "" && s.Cgoexport == 0 { 515 s.Type = SDYNIMPORT 516 } else { 517 s.Type = 0 518 } 519 } 520 } 521 } 522 523 tlsg := Linklookup(Ctxt, "runtime.tlsg", 0) 524 525 // For most ports, runtime.tlsg is a placeholder symbol for TLS 526 // relocation. However, the Android and Darwin arm ports need it 527 // to be a real variable. 528 // 529 // TODO(crawshaw): android should require leaving the tlsg->type 530 // alone (as the runtime-provided SNOPTRBSS) just like darwin/arm. 531 // But some other part of the linker is expecting STLSBSS. 532 if tlsg.Type != SDYNIMPORT && (goos != "darwin" || Thearch.Thechar != '5') { 533 tlsg.Type = STLSBSS 534 } 535 tlsg.Size = int64(Thearch.Ptrsize) 536 tlsg.Reachable = true 537 Ctxt.Tlsg = tlsg 538 539 // Now that we know the link mode, trim the dynexp list. 540 x := CgoExportDynamic 541 542 if Linkmode == LinkExternal { 543 x = CgoExportStatic 544 } 545 w := 0 546 for i := 0; i < len(dynexp); i++ { 547 if int(dynexp[i].Cgoexport)&x != 0 { 548 dynexp[w] = dynexp[i] 549 w++ 550 } 551 } 552 dynexp = dynexp[:w] 553 554 // In internal link mode, read the host object files. 555 if Linkmode == LinkInternal { 556 hostobjs() 557 } else { 558 hostlinksetup() 559 } 560 561 // We've loaded all the code now. 562 // If there are no dynamic libraries needed, gcc disables dynamic linking. 563 // Because of this, glibc's dynamic ELF loader occasionally (like in version 2.13) 564 // assumes that a dynamic binary always refers to at least one dynamic library. 565 // Rather than be a source of test cases for glibc, disable dynamic linking 566 // the same way that gcc would. 567 // 568 // Exception: on OS X, programs such as Shark only work with dynamic 569 // binaries, so leave it enabled on OS X (Mach-O) binaries. 570 // Also leave it enabled on Solaris which doesn't support 571 // statically linked binaries. 572 if Buildmode == BuildmodeExe && havedynamic == 0 && HEADTYPE != Hdarwin && HEADTYPE != Hsolaris { 573 Debug['d'] = 1 574 } 575 576 importcycles() 577 } 578 579 /* 580 * look for the next file in an archive. 581 * adapted from libmach. 582 */ 583 func nextar(bp *Biobuf, off int64, a *ArHdr) int64 { 584 if off&1 != 0 { 585 off++ 586 } 587 Bseek(bp, off, 0) 588 buf := make([]byte, SAR_HDR) 589 if n := Bread(bp, buf); n < len(buf) { 590 if n >= 0 { 591 return 0 592 } 593 return -1 594 } 595 596 a.name = artrim(buf[0:16]) 597 a.date = artrim(buf[16:28]) 598 a.uid = artrim(buf[28:34]) 599 a.gid = artrim(buf[34:40]) 600 a.mode = artrim(buf[40:48]) 601 a.size = artrim(buf[48:58]) 602 a.fmag = artrim(buf[58:60]) 603 604 arsize := atolwhex(a.size) 605 if arsize&1 != 0 { 606 arsize++ 607 } 608 return int64(arsize) + SAR_HDR 609 } 610 611 func objfile(file string, pkg string) { 612 pkg = pathtoprefix(pkg) 613 614 if Debug['v'] > 1 { 615 fmt.Fprintf(&Bso, "%5.2f ldobj: %s (%s)\n", obj.Cputime(), file, pkg) 616 } 617 Bflush(&Bso) 618 var err error 619 var f *Biobuf 620 f, err = Bopenr(file) 621 if err != nil { 622 Diag("cannot open file %s: %v", file, err) 623 Errorexit() 624 } 625 626 magbuf := make([]byte, len(ARMAG)) 627 if Bread(f, magbuf) != len(magbuf) || !strings.HasPrefix(string(magbuf), ARMAG) { 628 /* load it as a regular file */ 629 l := Bseek(f, 0, 2) 630 631 Bseek(f, 0, 0) 632 ldobj(f, pkg, l, file, file, FileObj) 633 Bterm(f) 634 635 return 636 } 637 638 /* skip over optional __.GOSYMDEF and process __.PKGDEF */ 639 off := Boffset(f) 640 641 var arhdr ArHdr 642 l := nextar(f, off, &arhdr) 643 var pname string 644 if l <= 0 { 645 Diag("%s: short read on archive file symbol header", file) 646 goto out 647 } 648 649 if strings.HasPrefix(arhdr.name, symname) { 650 off += l 651 l = nextar(f, off, &arhdr) 652 if l <= 0 { 653 Diag("%s: short read on archive file symbol header", file) 654 goto out 655 } 656 } 657 658 if !strings.HasPrefix(arhdr.name, pkgname) { 659 Diag("%s: cannot find package header", file) 660 goto out 661 } 662 663 off += l 664 665 if Debug['u'] != 0 { 666 ldpkg(f, pkg, atolwhex(arhdr.size), file, Pkgdef) 667 } 668 669 /* 670 * load all the object files from the archive now. 671 * this gives us sequential file access and keeps us 672 * from needing to come back later to pick up more 673 * objects. it breaks the usual C archive model, but 674 * this is Go, not C. the common case in Go is that 675 * we need to load all the objects, and then we throw away 676 * the individual symbols that are unused. 677 * 678 * loading every object will also make it possible to 679 * load foreign objects not referenced by __.GOSYMDEF. 680 */ 681 for { 682 l = nextar(f, off, &arhdr) 683 if l == 0 { 684 break 685 } 686 if l < 0 { 687 Diag("%s: malformed archive", file) 688 Errorexit() 689 goto out 690 } 691 692 off += l 693 694 pname = fmt.Sprintf("%s(%s)", file, arhdr.name) 695 l = atolwhex(arhdr.size) 696 ldobj(f, pkg, l, pname, file, ArchiveObj) 697 } 698 699 out: 700 Bterm(f) 701 } 702 703 type Hostobj struct { 704 ld func(*Biobuf, string, int64, string) 705 pkg string 706 pn string 707 file string 708 off int64 709 length int64 710 } 711 712 var hostobj []Hostobj 713 714 // These packages can use internal linking mode. 715 // Others trigger external mode. 716 var internalpkg = []string{ 717 "crypto/x509", 718 "net", 719 "os/user", 720 "runtime/cgo", 721 "runtime/race", 722 } 723 724 func ldhostobj(ld func(*Biobuf, string, int64, string), f *Biobuf, pkg string, length int64, pn string, file string) { 725 isinternal := false 726 for i := 0; i < len(internalpkg); i++ { 727 if pkg == internalpkg[i] { 728 isinternal = true 729 break 730 } 731 } 732 733 // DragonFly declares errno with __thread, which results in a symbol 734 // type of R_386_TLS_GD or R_X86_64_TLSGD. The Go linker does not 735 // currently know how to handle TLS relocations, hence we have to 736 // force external linking for any libraries that link in code that 737 // uses errno. This can be removed if the Go linker ever supports 738 // these relocation types. 739 if HEADTYPE == Hdragonfly { 740 if pkg == "net" || pkg == "os/user" { 741 isinternal = false 742 } 743 } 744 745 if !isinternal { 746 externalobj = true 747 } 748 749 hostobj = append(hostobj, Hostobj{}) 750 h := &hostobj[len(hostobj)-1] 751 h.ld = ld 752 h.pkg = pkg 753 h.pn = pn 754 h.file = file 755 h.off = Boffset(f) 756 h.length = length 757 } 758 759 func hostobjs() { 760 var f *Biobuf 761 var h *Hostobj 762 763 for i := 0; i < len(hostobj); i++ { 764 h = &hostobj[i] 765 var err error 766 f, err = Bopenr(h.file) 767 if f == nil { 768 Ctxt.Cursym = nil 769 Diag("cannot reopen %s: %v", h.pn, err) 770 Errorexit() 771 } 772 773 Bseek(f, h.off, 0) 774 h.ld(f, h.pkg, h.length, h.pn) 775 Bterm(f) 776 } 777 } 778 779 // provided by lib9 780 781 func rmtemp() { 782 os.RemoveAll(tmpdir) 783 } 784 785 func hostlinksetup() { 786 if Linkmode != LinkExternal { 787 return 788 } 789 790 // create temporary directory and arrange cleanup 791 if tmpdir == "" { 792 dir, err := ioutil.TempDir("", "go-link-") 793 if err != nil { 794 log.Fatal(err) 795 } 796 tmpdir = dir 797 AtExit(rmtemp) 798 } 799 800 // change our output to temporary object file 801 cout.Close() 802 803 p := fmt.Sprintf("%s/go.o", tmpdir) 804 var err error 805 cout, err = os.OpenFile(p, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0775) 806 if err != nil { 807 Diag("cannot create %s: %v", p, err) 808 Errorexit() 809 } 810 811 coutbuf = *Binitw(cout) 812 } 813 814 // hostobjCopy creates a copy of the object files in hostobj in a 815 // temporary directory. 816 func hostobjCopy() (paths []string) { 817 for i, h := range hostobj { 818 f, err := os.Open(h.file) 819 if err != nil { 820 Ctxt.Cursym = nil 821 Diag("cannot reopen %s: %v", h.pn, err) 822 Errorexit() 823 } 824 if _, err := f.Seek(h.off, 0); err != nil { 825 Ctxt.Cursym = nil 826 Diag("cannot seek %s: %v", h.pn, err) 827 Errorexit() 828 } 829 830 p := fmt.Sprintf("%s/%06d.o", tmpdir, i) 831 paths = append(paths, p) 832 w, err := os.Create(p) 833 if err != nil { 834 Ctxt.Cursym = nil 835 Diag("cannot create %s: %v", p, err) 836 Errorexit() 837 } 838 if _, err := io.CopyN(w, f, h.length); err != nil { 839 Ctxt.Cursym = nil 840 Diag("cannot write %s: %v", p, err) 841 Errorexit() 842 } 843 if err := w.Close(); err != nil { 844 Ctxt.Cursym = nil 845 Diag("cannot close %s: %v", p, err) 846 Errorexit() 847 } 848 } 849 return paths 850 } 851 852 // archive builds a .a archive from the hostobj object files. 853 func archive() { 854 if Buildmode != BuildmodeCArchive { 855 return 856 } 857 858 os.Remove(outfile) 859 argv := []string{"ar", "-q", "-c", outfile} 860 argv = append(argv, hostobjCopy()...) 861 argv = append(argv, fmt.Sprintf("%s/go.o", tmpdir)) 862 863 if Debug['v'] != 0 { 864 fmt.Fprintf(&Bso, "archive: %s\n", strings.Join(argv, " ")) 865 Bflush(&Bso) 866 } 867 868 if out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput(); err != nil { 869 Ctxt.Cursym = nil 870 Diag("%s: running %s failed: %v\n%s", os.Args[0], argv[0], err, out) 871 Errorexit() 872 } 873 } 874 875 func hostlink() { 876 if Linkmode != LinkExternal || nerrors > 0 { 877 return 878 } 879 if Buildmode == BuildmodeCArchive { 880 return 881 } 882 883 if extld == "" { 884 extld = "gcc" 885 } 886 887 var argv []string 888 argv = append(argv, extld) 889 switch Thearch.Thechar { 890 case '8': 891 argv = append(argv, "-m32") 892 893 case '6', '9': 894 argv = append(argv, "-m64") 895 896 case '5': 897 argv = append(argv, "-marm") 898 899 case '7': 900 // nothing needed 901 } 902 903 if Debug['s'] == 0 && debug_s == 0 { 904 argv = append(argv, "-gdwarf-2") 905 } else { 906 argv = append(argv, "-s") 907 } 908 909 if HEADTYPE == Hdarwin { 910 argv = append(argv, "-Wl,-no_pie,-pagezero_size,4000000") 911 } 912 if HEADTYPE == Hopenbsd { 913 argv = append(argv, "-Wl,-nopie") 914 } 915 if HEADTYPE == Hwindows { 916 if headstring == "windowsgui" { 917 argv = append(argv, "-mwindows") 918 } else { 919 argv = append(argv, "-mconsole") 920 } 921 } 922 923 if Iself && AssumeGoldLinker != 0 /*TypeKind(100016)*/ { 924 argv = append(argv, "-Wl,--rosegment") 925 } 926 927 switch Buildmode { 928 case BuildmodeCShared: 929 argv = append(argv, "-Wl,-Bsymbolic") 930 argv = append(argv, "-shared") 931 case BuildmodeShared: 932 // TODO(mwhudson): unless you do this, dynamic relocations fill 933 // out the findfunctab table and for some reason shared libraries 934 // and the executable both define a main function and putting the 935 // address of executable's main into the shared libraries 936 // findfunctab violates the assumptions of the runtime. TBH, I 937 // think we may well end up wanting to use -Bsymbolic here 938 // anyway. 939 argv = append(argv, "-Wl,-Bsymbolic-functions") 940 argv = append(argv, "-shared") 941 } 942 943 if Linkshared && Iself { 944 // We force all symbol resolution to be done at program startup 945 // because lazy PLT resolution can use large amounts of stack at 946 // times we cannot allow it to do so. 947 argv = append(argv, "-znow") 948 } 949 950 argv = append(argv, "-o") 951 argv = append(argv, outfile) 952 953 if rpath.val != "" { 954 argv = append(argv, fmt.Sprintf("-Wl,-rpath,%s", rpath.val)) 955 } 956 957 // Force global symbols to be exported for dlopen, etc. 958 if Iself { 959 argv = append(argv, "-rdynamic") 960 } 961 962 if strings.Contains(argv[0], "clang") { 963 argv = append(argv, "-Qunused-arguments") 964 } 965 966 argv = append(argv, hostobjCopy()...) 967 argv = append(argv, fmt.Sprintf("%s/go.o", tmpdir)) 968 969 if Linkshared { 970 for _, shlib := range Ctxt.Shlibs { 971 dir, base := filepath.Split(shlib) 972 argv = append(argv, "-L"+dir) 973 if !rpath.set { 974 argv = append(argv, "-Wl,-rpath="+dir) 975 } 976 base = strings.TrimSuffix(base, ".so") 977 base = strings.TrimPrefix(base, "lib") 978 argv = append(argv, "-l"+base) 979 } 980 } 981 982 argv = append(argv, ldflag...) 983 984 for _, p := range strings.Fields(extldflags) { 985 argv = append(argv, p) 986 987 // clang, unlike GCC, passes -rdynamic to the linker 988 // even when linking with -static, causing a linker 989 // error when using GNU ld. So take out -rdynamic if 990 // we added it. We do it in this order, rather than 991 // only adding -rdynamic later, so that -extldflags 992 // can override -rdynamic without using -static. 993 if Iself && p == "-static" { 994 for i := range argv { 995 if argv[i] == "-rdynamic" { 996 argv[i] = "-static" 997 } 998 } 999 } 1000 } 1001 if HEADTYPE == Hwindows { 1002 argv = append(argv, peimporteddlls()...) 1003 } 1004 1005 if Debug['v'] != 0 { 1006 fmt.Fprintf(&Bso, "host link:") 1007 for _, v := range argv { 1008 fmt.Fprintf(&Bso, " %q", v) 1009 } 1010 fmt.Fprintf(&Bso, "\n") 1011 Bflush(&Bso) 1012 } 1013 1014 if out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput(); err != nil { 1015 Ctxt.Cursym = nil 1016 Diag("%s: running %s failed: %v\n%s", os.Args[0], argv[0], err, out) 1017 Errorexit() 1018 } 1019 } 1020 1021 func ldobj(f *Biobuf, pkg string, length int64, pn string, file string, whence int) { 1022 eof := Boffset(f) + length 1023 1024 pn = pn 1025 1026 start := Boffset(f) 1027 c1 := Bgetc(f) 1028 c2 := Bgetc(f) 1029 c3 := Bgetc(f) 1030 c4 := Bgetc(f) 1031 Bseek(f, start, 0) 1032 1033 magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4) 1034 if magic == 0x7f454c46 { // \x7F E L F 1035 ldhostobj(ldelf, f, pkg, length, pn, file) 1036 return 1037 } 1038 1039 if magic&^1 == 0xfeedface || magic&^0x01000000 == 0xcefaedfe { 1040 ldhostobj(ldmacho, f, pkg, length, pn, file) 1041 return 1042 } 1043 1044 if c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86 { 1045 ldhostobj(ldpe, f, pkg, length, pn, file) 1046 return 1047 } 1048 1049 /* check the header */ 1050 line := Brdline(f, '\n') 1051 1052 var import0 int64 1053 var import1 int64 1054 var t string 1055 if line == "" { 1056 if Blinelen(f) > 0 { 1057 Diag("%s: not an object file", pn) 1058 return 1059 } 1060 1061 goto eof 1062 } 1063 1064 if !strings.HasPrefix(line, "go object ") { 1065 if strings.HasSuffix(pn, ".go") { 1066 fmt.Printf("%cl: input %s is not .%c file (use %cg to compile .go files)\n", Thearch.Thechar, pn, Thearch.Thechar, Thearch.Thechar) 1067 Errorexit() 1068 } 1069 1070 if line == Thestring { 1071 // old header format: just $GOOS 1072 Diag("%s: stale object file", pn) 1073 1074 return 1075 } 1076 1077 Diag("%s: not an object file", pn) 1078 1079 return 1080 } 1081 1082 // First, check that the basic goos, goarch, and version match. 1083 t = fmt.Sprintf("%s %s %s ", goos, obj.Getgoarch(), obj.Getgoversion()) 1084 1085 line = strings.TrimRight(line, "\n") 1086 if !strings.HasPrefix(line[10:]+" ", t) && Debug['f'] == 0 { 1087 Diag("%s: object is [%s] expected [%s]", pn, line[10:], t) 1088 return 1089 } 1090 1091 // Second, check that longer lines match each other exactly, 1092 // so that the Go compiler and write additional information 1093 // that must be the same from run to run. 1094 if len(line) >= len(t)+10 { 1095 if theline == "" { 1096 theline = line[10:] 1097 } else if theline != line[10:] { 1098 Diag("%s: object is [%s] expected [%s]", pn, line[10:], theline) 1099 return 1100 } 1101 } 1102 1103 /* skip over exports and other info -- ends with \n!\n */ 1104 import0 = Boffset(f) 1105 1106 c1 = '\n' // the last line ended in \n 1107 c2 = Bgetc(f) 1108 c3 = Bgetc(f) 1109 for c1 != '\n' || c2 != '!' || c3 != '\n' { 1110 c1 = c2 1111 c2 = c3 1112 c3 = Bgetc(f) 1113 if c3 == Beof { 1114 goto eof 1115 } 1116 } 1117 1118 import1 = Boffset(f) 1119 1120 Bseek(f, import0, 0) 1121 ldpkg(f, pkg, import1-import0-2, pn, whence) // -2 for !\n 1122 Bseek(f, import1, 0) 1123 1124 ldobjfile(Ctxt, f, pkg, eof-Boffset(f), pn) 1125 1126 return 1127 1128 eof: 1129 Diag("truncated object file: %s", pn) 1130 } 1131 1132 func ldshlibsyms(shlib string) { 1133 found := false 1134 libpath := "" 1135 for _, libdir := range Ctxt.Libdir { 1136 libpath = filepath.Join(libdir, shlib) 1137 if _, err := os.Stat(libpath); err == nil { 1138 found = true 1139 break 1140 } 1141 } 1142 if !found { 1143 Diag("cannot find shared library: %s", shlib) 1144 return 1145 } 1146 for _, processedname := range Ctxt.Shlibs { 1147 if processedname == libpath { 1148 return 1149 } 1150 } 1151 if Ctxt.Debugvlog > 1 && Ctxt.Bso != nil { 1152 fmt.Fprintf(Ctxt.Bso, "%5.2f ldshlibsyms: found library with name %s at %s\n", obj.Cputime(), shlib, libpath) 1153 Bflush(Ctxt.Bso) 1154 } 1155 1156 f, err := elf.Open(libpath) 1157 if err != nil { 1158 Diag("cannot open shared library: %s", libpath) 1159 return 1160 } 1161 defer f.Close() 1162 syms, err := f.DynamicSymbols() 1163 if err != nil { 1164 Diag("cannot read symbols from shared library: %s", libpath) 1165 return 1166 } 1167 for _, s := range syms { 1168 if elf.ST_TYPE(s.Info) == elf.STT_NOTYPE || elf.ST_TYPE(s.Info) == elf.STT_SECTION { 1169 continue 1170 } 1171 if s.Section == elf.SHN_UNDEF { 1172 continue 1173 } 1174 if strings.HasPrefix(s.Name, "_") { 1175 continue 1176 } 1177 lsym := Linklookup(Ctxt, s.Name, 0) 1178 if lsym.Type != 0 && lsym.Dupok == 0 { 1179 Diag( 1180 "Found duplicate symbol %s reading from %s, first found in %s", 1181 s.Name, shlib, lsym.File) 1182 } 1183 lsym.Type = SDYNIMPORT 1184 lsym.File = libpath 1185 } 1186 1187 // We might have overwritten some functions above (this tends to happen for the 1188 // autogenerated type equality/hashing functions) and we don't want to generated 1189 // pcln table entries for these any more so unstitch them from the Textp linked 1190 // list. 1191 var last *LSym 1192 1193 for s := Ctxt.Textp; s != nil; s = s.Next { 1194 if s.Type == SDYNIMPORT { 1195 continue 1196 } 1197 1198 if last == nil { 1199 Ctxt.Textp = s 1200 } else { 1201 last.Next = s 1202 } 1203 last = s 1204 } 1205 1206 if last == nil { 1207 Ctxt.Textp = nil 1208 Ctxt.Etextp = nil 1209 } else { 1210 last.Next = nil 1211 Ctxt.Etextp = last 1212 } 1213 1214 Ctxt.Shlibs = append(Ctxt.Shlibs, libpath) 1215 } 1216 1217 func mywhatsys() { 1218 goroot = obj.Getgoroot() 1219 goos = obj.Getgoos() 1220 goarch = obj.Getgoarch() 1221 1222 if !strings.HasPrefix(goarch, Thestring) { 1223 log.Fatalf("cannot use %cc with GOARCH=%s", Thearch.Thechar, goarch) 1224 } 1225 } 1226 1227 // Copied from ../gc/subr.c:/^pathtoprefix; must stay in sync. 1228 /* 1229 * Convert raw string to the prefix that will be used in the symbol table. 1230 * Invalid bytes turn into %xx. Right now the only bytes that need 1231 * escaping are %, ., and ", but we escape all control characters too. 1232 * 1233 * If you edit this, edit ../gc/subr.c:/^pathtoprefix too. 1234 * If you edit this, edit ../../debug/goobj/read.go:/importPathToPrefix too. 1235 */ 1236 func pathtoprefix(s string) string { 1237 slash := strings.LastIndex(s, "/") 1238 for i := 0; i < len(s); i++ { 1239 c := s[i] 1240 if c <= ' ' || i >= slash && c == '.' || c == '%' || c == '"' || c >= 0x7F { 1241 var buf bytes.Buffer 1242 for i := 0; i < len(s); i++ { 1243 c := s[i] 1244 if c <= ' ' || i >= slash && c == '.' || c == '%' || c == '"' || c >= 0x7F { 1245 fmt.Fprintf(&buf, "%%%02x", c) 1246 continue 1247 } 1248 buf.WriteByte(c) 1249 } 1250 return buf.String() 1251 } 1252 } 1253 return s 1254 } 1255 1256 func addsection(seg *Segment, name string, rwx int) *Section { 1257 var l **Section 1258 1259 for l = &seg.Sect; *l != nil; l = &(*l).Next { 1260 } 1261 sect := new(Section) 1262 sect.Rwx = uint8(rwx) 1263 sect.Name = name 1264 sect.Seg = seg 1265 sect.Align = int32(Thearch.Ptrsize) // everything is at least pointer-aligned 1266 *l = sect 1267 return sect 1268 } 1269 1270 func Le16(b []byte) uint16 { 1271 return uint16(b[0]) | uint16(b[1])<<8 1272 } 1273 1274 func Le32(b []byte) uint32 { 1275 return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 1276 } 1277 1278 func Le64(b []byte) uint64 { 1279 return uint64(Le32(b)) | uint64(Le32(b[4:]))<<32 1280 } 1281 1282 func Be16(b []byte) uint16 { 1283 return uint16(b[0])<<8 | uint16(b[1]) 1284 } 1285 1286 func Be32(b []byte) uint32 { 1287 return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3]) 1288 } 1289 1290 func Be64(b []byte) uint64 { 1291 return uint64(Be32(b))<<32 | uint64(Be32(b[4:])) 1292 } 1293 1294 type Chain struct { 1295 sym *LSym 1296 up *Chain 1297 limit int // limit on entry to sym 1298 } 1299 1300 var ( 1301 morestack *LSym 1302 newstack *LSym 1303 ) 1304 1305 // TODO: Record enough information in new object files to 1306 // allow stack checks here. 1307 1308 func haslinkregister() bool { 1309 return Thearch.Thechar == '5' || Thearch.Thechar == '9' || Thearch.Thechar == '7' 1310 } 1311 1312 func callsize() int { 1313 if haslinkregister() { 1314 return 0 1315 } 1316 return Thearch.Regsize 1317 } 1318 1319 func dostkcheck() { 1320 var ch Chain 1321 1322 morestack = Linklookup(Ctxt, "runtime.morestack", 0) 1323 newstack = Linklookup(Ctxt, "runtime.newstack", 0) 1324 1325 // Every splitting function ensures that there are at least StackLimit 1326 // bytes available below SP when the splitting prologue finishes. 1327 // If the splitting function calls F, then F begins execution with 1328 // at least StackLimit - callsize() bytes available. 1329 // Check that every function behaves correctly with this amount 1330 // of stack, following direct calls in order to piece together chains 1331 // of non-splitting functions. 1332 ch.up = nil 1333 1334 ch.limit = obj.StackLimit - callsize() 1335 1336 // Check every function, but do the nosplit functions in a first pass, 1337 // to make the printed failure chains as short as possible. 1338 for s := Ctxt.Textp; s != nil; s = s.Next { 1339 // runtime.racesymbolizethunk is called from gcc-compiled C 1340 // code running on the operating system thread stack. 1341 // It uses more than the usual amount of stack but that's okay. 1342 if s.Name == "runtime.racesymbolizethunk" { 1343 continue 1344 } 1345 1346 if s.Nosplit != 0 { 1347 Ctxt.Cursym = s 1348 ch.sym = s 1349 stkcheck(&ch, 0) 1350 } 1351 } 1352 1353 for s := Ctxt.Textp; s != nil; s = s.Next { 1354 if s.Nosplit == 0 { 1355 Ctxt.Cursym = s 1356 ch.sym = s 1357 stkcheck(&ch, 0) 1358 } 1359 } 1360 } 1361 1362 func stkcheck(up *Chain, depth int) int { 1363 limit := up.limit 1364 s := up.sym 1365 1366 // Don't duplicate work: only need to consider each 1367 // function at top of safe zone once. 1368 if limit == obj.StackLimit-callsize() { 1369 if s.Stkcheck != 0 { 1370 return 0 1371 } 1372 s.Stkcheck = 1 1373 } 1374 1375 if depth > 100 { 1376 Diag("nosplit stack check too deep") 1377 stkbroke(up, 0) 1378 return -1 1379 } 1380 1381 if s.External != 0 || s.Pcln == nil { 1382 // external function. 1383 // should never be called directly. 1384 // only diagnose the direct caller. 1385 // TODO(mwhudson): actually think about this. 1386 if depth == 1 && s.Type != SXREF && !DynlinkingGo() { 1387 Diag("call to external function %s", s.Name) 1388 } 1389 return -1 1390 } 1391 1392 if limit < 0 { 1393 stkbroke(up, limit) 1394 return -1 1395 } 1396 1397 // morestack looks like it calls functions, 1398 // but it switches the stack pointer first. 1399 if s == morestack { 1400 return 0 1401 } 1402 1403 var ch Chain 1404 ch.up = up 1405 1406 // Walk through sp adjustments in function, consuming relocs. 1407 ri := 0 1408 1409 endr := len(s.R) 1410 var ch1 Chain 1411 var pcsp Pciter 1412 var r *Reloc 1413 for pciterinit(Ctxt, &pcsp, &s.Pcln.Pcsp); pcsp.done == 0; pciternext(&pcsp) { 1414 // pcsp.value is in effect for [pcsp.pc, pcsp.nextpc). 1415 1416 // Check stack size in effect for this span. 1417 if int32(limit)-pcsp.value < 0 { 1418 stkbroke(up, int(int32(limit)-pcsp.value)) 1419 return -1 1420 } 1421 1422 // Process calls in this span. 1423 for ; ri < endr && uint32(s.R[ri].Off) < pcsp.nextpc; ri++ { 1424 r = &s.R[ri] 1425 switch r.Type { 1426 // Direct call. 1427 case R_CALL, R_CALLARM, R_CALLARM64, R_CALLPOWER: 1428 ch.limit = int(int32(limit) - pcsp.value - int32(callsize())) 1429 1430 ch.sym = r.Sym 1431 if stkcheck(&ch, depth+1) < 0 { 1432 return -1 1433 } 1434 1435 // If this is a call to morestack, we've just raised our limit back 1436 // to StackLimit beyond the frame size. 1437 if strings.HasPrefix(r.Sym.Name, "runtime.morestack") { 1438 limit = int(obj.StackLimit + s.Locals) 1439 if haslinkregister() { 1440 limit += Thearch.Regsize 1441 } 1442 } 1443 1444 // Indirect call. Assume it is a call to a splitting function, 1445 // so we have to make sure it can call morestack. 1446 // Arrange the data structures to report both calls, so that 1447 // if there is an error, stkprint shows all the steps involved. 1448 case R_CALLIND: 1449 ch.limit = int(int32(limit) - pcsp.value - int32(callsize())) 1450 1451 ch.sym = nil 1452 ch1.limit = ch.limit - callsize() // for morestack in called prologue 1453 ch1.up = &ch 1454 ch1.sym = morestack 1455 if stkcheck(&ch1, depth+2) < 0 { 1456 return -1 1457 } 1458 } 1459 } 1460 } 1461 1462 return 0 1463 } 1464 1465 func stkbroke(ch *Chain, limit int) { 1466 Diag("nosplit stack overflow") 1467 stkprint(ch, limit) 1468 } 1469 1470 func stkprint(ch *Chain, limit int) { 1471 var name string 1472 1473 if ch.sym != nil { 1474 name = ch.sym.Name 1475 } else { 1476 name = "function pointer" 1477 } 1478 1479 if ch.up == nil { 1480 // top of chain. ch->sym != nil. 1481 if ch.sym.Nosplit != 0 { 1482 fmt.Printf("\t%d\tassumed on entry to %s\n", ch.limit, name) 1483 } else { 1484 fmt.Printf("\t%d\tguaranteed after split check in %s\n", ch.limit, name) 1485 } 1486 } else { 1487 stkprint(ch.up, ch.limit+callsize()) 1488 if !haslinkregister() { 1489 fmt.Printf("\t%d\ton entry to %s\n", ch.limit, name) 1490 } 1491 } 1492 1493 if ch.limit != limit { 1494 fmt.Printf("\t%d\tafter %s uses %d\n", limit, name, ch.limit-limit) 1495 } 1496 } 1497 1498 func Yconv(s *LSym) string { 1499 var fp string 1500 1501 if s == nil { 1502 fp += fmt.Sprintf("<nil>") 1503 } else { 1504 fmt_ := "" 1505 fmt_ += fmt.Sprintf("%s @0x%08x [%d]", s.Name, int64(s.Value), int64(s.Size)) 1506 for i := 0; int64(i) < s.Size; i++ { 1507 if i%8 == 0 { 1508 fmt_ += fmt.Sprintf("\n\t0x%04x ", i) 1509 } 1510 fmt_ += fmt.Sprintf("%02x ", s.P[i]) 1511 } 1512 1513 fmt_ += fmt.Sprintf("\n") 1514 for i := 0; i < len(s.R); i++ { 1515 fmt_ += fmt.Sprintf("\t0x%04x[%x] %d %s[%x]\n", s.R[i].Off, s.R[i].Siz, s.R[i].Type, s.R[i].Sym.Name, int64(s.R[i].Add)) 1516 } 1517 1518 str := fmt_ 1519 fp += str 1520 } 1521 1522 return fp 1523 } 1524 1525 func Cflush() { 1526 Bflush(&coutbuf) 1527 } 1528 1529 func Cpos() int64 { 1530 return Boffset(&coutbuf) 1531 } 1532 1533 func Cseek(p int64) { 1534 Bseek(&coutbuf, p, 0) 1535 } 1536 1537 func Cwrite(p []byte) { 1538 Bwrite(&coutbuf, p) 1539 } 1540 1541 func Cput(c uint8) { 1542 Bputc(&coutbuf, c) 1543 } 1544 1545 func usage() { 1546 fmt.Fprintf(os.Stderr, "usage: %cl [options] obj.%c\n", Thearch.Thechar, Thearch.Thechar) 1547 obj.Flagprint(2) 1548 Exit(2) 1549 } 1550 1551 func setheadtype(s string) { 1552 h := headtype(s) 1553 if h < 0 { 1554 fmt.Fprintf(os.Stderr, "unknown header type -H %s\n", s) 1555 Errorexit() 1556 } 1557 1558 headstring = s 1559 HEADTYPE = int32(headtype(s)) 1560 } 1561 1562 func setinterp(s string) { 1563 Debug['I'] = 1 // denote cmdline interpreter override 1564 interpreter = s 1565 } 1566 1567 func doversion() { 1568 fmt.Printf("%cl version %s\n", Thearch.Thechar, obj.Getgoversion()) 1569 Errorexit() 1570 } 1571 1572 func genasmsym(put func(*LSym, string, int, int64, int64, int, *LSym)) { 1573 // These symbols won't show up in the first loop below because we 1574 // skip STEXT symbols. Normal STEXT symbols are emitted by walking textp. 1575 s := Linklookup(Ctxt, "runtime.text", 0) 1576 1577 if s.Type == STEXT { 1578 put(s, s.Name, 'T', s.Value, s.Size, int(s.Version), nil) 1579 } 1580 s = Linklookup(Ctxt, "runtime.etext", 0) 1581 if s.Type == STEXT { 1582 put(s, s.Name, 'T', s.Value, s.Size, int(s.Version), nil) 1583 } 1584 1585 for s := Ctxt.Allsym; s != nil; s = s.Allsym { 1586 if s.Hide != 0 || (s.Name[0] == '.' && s.Version == 0 && s.Name != ".rathole") { 1587 continue 1588 } 1589 switch s.Type & SMASK { 1590 case SCONST, 1591 SRODATA, 1592 SSYMTAB, 1593 SPCLNTAB, 1594 SINITARR, 1595 SDATA, 1596 SNOPTRDATA, 1597 SELFROSECT, 1598 SMACHOGOT, 1599 STYPE, 1600 SSTRING, 1601 SGOSTRING, 1602 SGOFUNC, 1603 SWINDOWS: 1604 if !s.Reachable { 1605 continue 1606 } 1607 put(s, s.Name, 'D', Symaddr(s), s.Size, int(s.Version), s.Gotype) 1608 1609 case SBSS, SNOPTRBSS: 1610 if !s.Reachable { 1611 continue 1612 } 1613 if len(s.P) > 0 { 1614 Diag("%s should not be bss (size=%d type=%d special=%d)", s.Name, int(len(s.P)), s.Type, s.Special) 1615 } 1616 put(s, s.Name, 'B', Symaddr(s), s.Size, int(s.Version), s.Gotype) 1617 1618 case SFILE: 1619 put(nil, s.Name, 'f', s.Value, 0, int(s.Version), nil) 1620 1621 case SHOSTOBJ: 1622 if HEADTYPE == Hwindows || Iself { 1623 put(s, s.Name, 'U', s.Value, 0, int(s.Version), nil) 1624 } 1625 1626 case SDYNIMPORT: 1627 if !s.Reachable { 1628 continue 1629 } 1630 put(s, s.Extname, 'U', 0, 0, int(s.Version), nil) 1631 1632 case STLSBSS: 1633 if Linkmode == LinkExternal && HEADTYPE != Hopenbsd { 1634 var type_ int 1635 if goos == "android" { 1636 type_ = 'B' 1637 } else { 1638 type_ = 't' 1639 } 1640 put(s, s.Name, type_, Symaddr(s), s.Size, int(s.Version), s.Gotype) 1641 } 1642 } 1643 } 1644 1645 var a *Auto 1646 var off int32 1647 for s := Ctxt.Textp; s != nil; s = s.Next { 1648 put(s, s.Name, 'T', s.Value, s.Size, int(s.Version), s.Gotype) 1649 1650 // NOTE(ality): acid can't produce a stack trace without .frame symbols 1651 put(nil, ".frame", 'm', int64(s.Locals)+int64(Thearch.Ptrsize), 0, 0, nil) 1652 1653 for a = s.Autom; a != nil; a = a.Link { 1654 // Emit a or p according to actual offset, even if label is wrong. 1655 // This avoids negative offsets, which cannot be encoded. 1656 if a.Name != A_AUTO && a.Name != A_PARAM { 1657 continue 1658 } 1659 1660 // compute offset relative to FP 1661 if a.Name == A_PARAM { 1662 off = a.Aoffset 1663 } else { 1664 off = a.Aoffset - int32(Thearch.Ptrsize) 1665 } 1666 1667 // FP 1668 if off >= 0 { 1669 put(nil, a.Asym.Name, 'p', int64(off), 0, 0, a.Gotype) 1670 continue 1671 } 1672 1673 // SP 1674 if off <= int32(-Thearch.Ptrsize) { 1675 put(nil, a.Asym.Name, 'a', -(int64(off) + int64(Thearch.Ptrsize)), 0, 0, a.Gotype) 1676 continue 1677 } 1678 } 1679 } 1680 1681 // Otherwise, off is addressing the saved program counter. 1682 // Something underhanded is going on. Say nothing. 1683 if Debug['v'] != 0 || Debug['n'] != 0 { 1684 fmt.Fprintf(&Bso, "%5.2f symsize = %d\n", obj.Cputime(), uint32(Symsize)) 1685 } 1686 Bflush(&Bso) 1687 } 1688 1689 func Symaddr(s *LSym) int64 { 1690 if !s.Reachable { 1691 Diag("unreachable symbol in symaddr - %s", s.Name) 1692 } 1693 return s.Value 1694 } 1695 1696 func xdefine(p string, t int, v int64) { 1697 s := Linklookup(Ctxt, p, 0) 1698 s.Type = int16(t) 1699 s.Value = v 1700 s.Reachable = true 1701 s.Special = 1 1702 s.Local = true 1703 } 1704 1705 func datoff(addr int64) int64 { 1706 if uint64(addr) >= Segdata.Vaddr { 1707 return int64(uint64(addr) - Segdata.Vaddr + Segdata.Fileoff) 1708 } 1709 if uint64(addr) >= Segtext.Vaddr { 1710 return int64(uint64(addr) - Segtext.Vaddr + Segtext.Fileoff) 1711 } 1712 Diag("datoff %#x", addr) 1713 return 0 1714 } 1715 1716 func Entryvalue() int64 { 1717 a := INITENTRY 1718 if a[0] >= '0' && a[0] <= '9' { 1719 return atolwhex(a) 1720 } 1721 s := Linklookup(Ctxt, a, 0) 1722 if s.Type == 0 { 1723 return INITTEXT 1724 } 1725 if s.Type != STEXT { 1726 Diag("entry not text: %s", s.Name) 1727 } 1728 return s.Value 1729 } 1730 1731 func undefsym(s *LSym) { 1732 var r *Reloc 1733 1734 Ctxt.Cursym = s 1735 for i := 0; i < len(s.R); i++ { 1736 r = &s.R[i] 1737 if r.Sym == nil { // happens for some external ARM relocs 1738 continue 1739 } 1740 if r.Sym.Type == Sxxx || r.Sym.Type == SXREF { 1741 Diag("undefined: %s", r.Sym.Name) 1742 } 1743 if !r.Sym.Reachable { 1744 Diag("use of unreachable symbol: %s", r.Sym.Name) 1745 } 1746 } 1747 } 1748 1749 func undef() { 1750 for s := Ctxt.Textp; s != nil; s = s.Next { 1751 undefsym(s) 1752 } 1753 for s := datap; s != nil; s = s.Next { 1754 undefsym(s) 1755 } 1756 if nerrors > 0 { 1757 Errorexit() 1758 } 1759 } 1760 1761 func callgraph() { 1762 if Debug['c'] == 0 { 1763 return 1764 } 1765 1766 var i int 1767 var r *Reloc 1768 for s := Ctxt.Textp; s != nil; s = s.Next { 1769 for i = 0; i < len(s.R); i++ { 1770 r = &s.R[i] 1771 if r.Sym == nil { 1772 continue 1773 } 1774 if (r.Type == R_CALL || r.Type == R_CALLARM || r.Type == R_CALLPOWER) && r.Sym.Type == STEXT { 1775 fmt.Fprintf(&Bso, "%s calls %s\n", s.Name, r.Sym.Name) 1776 } 1777 } 1778 } 1779 } 1780 1781 func Diag(format string, args ...interface{}) { 1782 tn := "" 1783 sep := "" 1784 if Ctxt.Cursym != nil { 1785 tn = Ctxt.Cursym.Name 1786 sep = ": " 1787 } 1788 fmt.Printf("%s%s%s\n", tn, sep, fmt.Sprintf(format, args...)) 1789 1790 nerrors++ 1791 if nerrors > 20 { 1792 fmt.Printf("too many errors\n") 1793 Errorexit() 1794 } 1795 } 1796 1797 func checkgo() { 1798 if Debug['C'] == 0 { 1799 return 1800 } 1801 1802 // TODO(rsc,khr): Eventually we want to get to no Go-called C functions at all, 1803 // which would simplify this logic quite a bit. 1804 1805 // Mark every Go-called C function with cfunc=2, recursively. 1806 var changed int 1807 var i int 1808 var r *Reloc 1809 var s *LSym 1810 for { 1811 changed = 0 1812 for s = Ctxt.Textp; s != nil; s = s.Next { 1813 if s.Cfunc == 0 || (s.Cfunc == 2 && s.Nosplit != 0) { 1814 for i = 0; i < len(s.R); i++ { 1815 r = &s.R[i] 1816 if r.Sym == nil { 1817 continue 1818 } 1819 if (r.Type == R_CALL || r.Type == R_CALLARM) && r.Sym.Type == STEXT { 1820 if r.Sym.Cfunc == 1 { 1821 changed = 1 1822 r.Sym.Cfunc = 2 1823 } 1824 } 1825 } 1826 } 1827 } 1828 if changed == 0 { 1829 break 1830 } 1831 } 1832 1833 // Complain about Go-called C functions that can split the stack 1834 // (that can be preempted for garbage collection or trigger a stack copy). 1835 for s := Ctxt.Textp; s != nil; s = s.Next { 1836 if s.Cfunc == 0 || (s.Cfunc == 2 && s.Nosplit != 0) { 1837 for i = 0; i < len(s.R); i++ { 1838 r = &s.R[i] 1839 if r.Sym == nil { 1840 continue 1841 } 1842 if (r.Type == R_CALL || r.Type == R_CALLARM) && r.Sym.Type == STEXT { 1843 if s.Cfunc == 0 && r.Sym.Cfunc == 2 && r.Sym.Nosplit == 0 { 1844 fmt.Printf("Go %s calls C %s\n", s.Name, r.Sym.Name) 1845 } else if s.Cfunc == 2 && s.Nosplit != 0 && r.Sym.Nosplit == 0 { 1846 fmt.Printf("Go calls C %s calls %s\n", s.Name, r.Sym.Name) 1847 } 1848 } 1849 } 1850 } 1851 } 1852 } 1853 1854 func Rnd(v int64, r int64) int64 { 1855 if r <= 0 { 1856 return v 1857 } 1858 v += r - 1 1859 c := v % r 1860 if c < 0 { 1861 c += r 1862 } 1863 v -= c 1864 return v 1865 }