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