github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/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 if Debug['u'] != 0 { 813 ldpkg(f, pkg, atolwhex(arhdr.size), lib.File, Pkgdef) 814 } 815 816 /* 817 * load all the object files from the archive now. 818 * this gives us sequential file access and keeps us 819 * from needing to come back later to pick up more 820 * objects. it breaks the usual C archive model, but 821 * this is Go, not C. the common case in Go is that 822 * we need to load all the objects, and then we throw away 823 * the individual symbols that are unused. 824 * 825 * loading every object will also make it possible to 826 * load foreign objects not referenced by __.GOSYMDEF. 827 */ 828 for { 829 l = nextar(f, off, &arhdr) 830 if l == 0 { 831 break 832 } 833 if l < 0 { 834 Exitf("%s: malformed archive", lib.File) 835 } 836 837 off += l 838 839 pname = fmt.Sprintf("%s(%s)", lib.File, arhdr.name) 840 l = atolwhex(arhdr.size) 841 ldobj(f, pkg, l, pname, lib.File, ArchiveObj) 842 } 843 844 out: 845 obj.Bterm(f) 846 } 847 848 type Hostobj struct { 849 ld func(*obj.Biobuf, string, int64, string) 850 pkg string 851 pn string 852 file string 853 off int64 854 length int64 855 } 856 857 var hostobj []Hostobj 858 859 // These packages can use internal linking mode. 860 // Others trigger external mode. 861 var internalpkg = []string{ 862 "crypto/x509", 863 "net", 864 "os/user", 865 "runtime/cgo", 866 "runtime/race", 867 "runtime/msan", 868 } 869 870 func ldhostobj(ld func(*obj.Biobuf, string, int64, string), f *obj.Biobuf, pkg string, length int64, pn string, file string) *Hostobj { 871 isinternal := false 872 for i := 0; i < len(internalpkg); i++ { 873 if pkg == internalpkg[i] { 874 isinternal = true 875 break 876 } 877 } 878 879 // DragonFly declares errno with __thread, which results in a symbol 880 // type of R_386_TLS_GD or R_X86_64_TLSGD. The Go linker does not 881 // currently know how to handle TLS relocations, hence we have to 882 // force external linking for any libraries that link in code that 883 // uses errno. This can be removed if the Go linker ever supports 884 // these relocation types. 885 if HEADTYPE == obj.Hdragonfly { 886 if pkg == "net" || pkg == "os/user" { 887 isinternal = false 888 } 889 } 890 891 if !isinternal { 892 externalobj = true 893 } 894 895 hostobj = append(hostobj, Hostobj{}) 896 h := &hostobj[len(hostobj)-1] 897 h.ld = ld 898 h.pkg = pkg 899 h.pn = pn 900 h.file = file 901 h.off = obj.Boffset(f) 902 h.length = length 903 return h 904 } 905 906 func hostobjs() { 907 var f *obj.Biobuf 908 var h *Hostobj 909 910 for i := 0; i < len(hostobj); i++ { 911 h = &hostobj[i] 912 var err error 913 f, err = obj.Bopenr(h.file) 914 if f == nil { 915 Exitf("cannot reopen %s: %v", h.pn, err) 916 } 917 918 obj.Bseek(f, h.off, 0) 919 h.ld(f, h.pkg, h.length, h.pn) 920 obj.Bterm(f) 921 } 922 } 923 924 // provided by lib9 925 926 func rmtemp() { 927 os.RemoveAll(tmpdir) 928 } 929 930 func hostlinksetup() { 931 if Linkmode != LinkExternal { 932 return 933 } 934 935 // For external link, record that we need to tell the external linker -s, 936 // and turn off -s internally: the external linker needs the symbol 937 // information for its final link. 938 debug_s = Debug['s'] 939 Debug['s'] = 0 940 941 // create temporary directory and arrange cleanup 942 if tmpdir == "" { 943 dir, err := ioutil.TempDir("", "go-link-") 944 if err != nil { 945 log.Fatal(err) 946 } 947 tmpdir = dir 948 AtExit(rmtemp) 949 } 950 951 // change our output to temporary object file 952 coutbuf.f.Close() 953 mayberemoveoutfile() 954 955 p := fmt.Sprintf("%s/go.o", tmpdir) 956 var err error 957 f, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0775) 958 if err != nil { 959 Exitf("cannot create %s: %v", p, err) 960 } 961 962 coutbuf.Writer = bufio.NewWriter(f) 963 coutbuf.f = f 964 } 965 966 // hostobjCopy creates a copy of the object files in hostobj in a 967 // temporary directory. 968 func hostobjCopy() (paths []string) { 969 var wg sync.WaitGroup 970 sema := make(chan struct{}, runtime.NumCPU()) // limit open file descriptors 971 for i, h := range hostobj { 972 h := h 973 dst := fmt.Sprintf("%s/%06d.o", tmpdir, i) 974 paths = append(paths, dst) 975 976 wg.Add(1) 977 go func() { 978 sema <- struct{}{} 979 defer func() { 980 <-sema 981 wg.Done() 982 }() 983 f, err := os.Open(h.file) 984 if err != nil { 985 Exitf("cannot reopen %s: %v", h.pn, err) 986 } 987 if _, err := f.Seek(h.off, 0); err != nil { 988 Exitf("cannot seek %s: %v", h.pn, err) 989 } 990 991 w, err := os.Create(dst) 992 if err != nil { 993 Exitf("cannot create %s: %v", dst, err) 994 } 995 if _, err := io.CopyN(w, f, h.length); err != nil { 996 Exitf("cannot write %s: %v", dst, err) 997 } 998 if err := w.Close(); err != nil { 999 Exitf("cannot close %s: %v", dst, err) 1000 } 1001 }() 1002 } 1003 wg.Wait() 1004 return paths 1005 } 1006 1007 // archive builds a .a archive from the hostobj object files. 1008 func archive() { 1009 if Buildmode != BuildmodeCArchive { 1010 return 1011 } 1012 1013 mayberemoveoutfile() 1014 argv := []string{"ar", "-q", "-c", "-s", outfile} 1015 argv = append(argv, fmt.Sprintf("%s/go.o", tmpdir)) 1016 argv = append(argv, hostobjCopy()...) 1017 1018 if Debug['v'] != 0 { 1019 fmt.Fprintf(&Bso, "archive: %s\n", strings.Join(argv, " ")) 1020 Bso.Flush() 1021 } 1022 1023 if out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput(); err != nil { 1024 Exitf("running %s failed: %v\n%s", argv[0], err, out) 1025 } 1026 } 1027 1028 func hostlink() { 1029 if Linkmode != LinkExternal || nerrors > 0 { 1030 return 1031 } 1032 if Buildmode == BuildmodeCArchive { 1033 return 1034 } 1035 1036 if extld == "" { 1037 extld = "gcc" 1038 } 1039 1040 var argv []string 1041 argv = append(argv, extld) 1042 argv = append(argv, hostlinkArchArgs()...) 1043 1044 if Debug['s'] == 0 && debug_s == 0 { 1045 argv = append(argv, "-gdwarf-2") 1046 } else { 1047 argv = append(argv, "-s") 1048 } 1049 1050 if HEADTYPE == obj.Hdarwin { 1051 argv = append(argv, "-Wl,-no_pie,-headerpad,1144") 1052 } 1053 if HEADTYPE == obj.Hopenbsd { 1054 argv = append(argv, "-Wl,-nopie") 1055 } 1056 if HEADTYPE == obj.Hwindows { 1057 if headstring == "windowsgui" { 1058 argv = append(argv, "-mwindows") 1059 } else { 1060 argv = append(argv, "-mconsole") 1061 } 1062 } 1063 1064 switch Buildmode { 1065 case BuildmodeExe: 1066 if HEADTYPE == obj.Hdarwin { 1067 argv = append(argv, "-Wl,-pagezero_size,4000000") 1068 } 1069 case BuildmodePIE: 1070 argv = append(argv, "-pie") 1071 case BuildmodeCShared: 1072 if HEADTYPE == obj.Hdarwin { 1073 argv = append(argv, "-dynamiclib") 1074 } else { 1075 // ELF. 1076 argv = append(argv, "-Wl,-Bsymbolic") 1077 if UseRelro() { 1078 argv = append(argv, "-Wl,-z,relro") 1079 } 1080 // Pass -z nodelete to mark the shared library as 1081 // non-closeable: a dlclose will do nothing. 1082 argv = append(argv, "-shared", "-Wl,-z,nodelete") 1083 } 1084 case BuildmodeShared: 1085 if UseRelro() { 1086 argv = append(argv, "-Wl,-z,relro") 1087 } 1088 argv = append(argv, "-shared") 1089 } 1090 1091 if Iself && DynlinkingGo() { 1092 // We force all symbol resolution to be done at program startup 1093 // because lazy PLT resolution can use large amounts of stack at 1094 // times we cannot allow it to do so. 1095 argv = append(argv, "-Wl,-znow") 1096 } 1097 1098 if Iself && len(buildinfo) > 0 { 1099 argv = append(argv, fmt.Sprintf("-Wl,--build-id=0x%x", buildinfo)) 1100 } 1101 1102 // On Windows, given -o foo, GCC will append ".exe" to produce 1103 // "foo.exe". We have decided that we want to honor the -o 1104 // option. To make this work, we append a '.' so that GCC 1105 // will decide that the file already has an extension. We 1106 // only want to do this when producing a Windows output file 1107 // on a Windows host. 1108 outopt := outfile 1109 if goos == "windows" && runtime.GOOS == "windows" && filepath.Ext(outopt) == "" { 1110 outopt += "." 1111 } 1112 argv = append(argv, "-o") 1113 argv = append(argv, outopt) 1114 1115 if rpath.val != "" { 1116 argv = append(argv, fmt.Sprintf("-Wl,-rpath,%s", rpath.val)) 1117 } 1118 1119 // Force global symbols to be exported for dlopen, etc. 1120 if Iself { 1121 argv = append(argv, "-rdynamic") 1122 } 1123 1124 if strings.Contains(argv[0], "clang") { 1125 argv = append(argv, "-Qunused-arguments") 1126 } 1127 1128 argv = append(argv, fmt.Sprintf("%s/go.o", tmpdir)) 1129 argv = append(argv, hostobjCopy()...) 1130 1131 if Linkshared { 1132 seenDirs := make(map[string]bool) 1133 seenLibs := make(map[string]bool) 1134 addshlib := func(path string) { 1135 dir, base := filepath.Split(path) 1136 if !seenDirs[dir] { 1137 argv = append(argv, "-L"+dir) 1138 if !rpath.set { 1139 argv = append(argv, "-Wl,-rpath="+dir) 1140 } 1141 seenDirs[dir] = true 1142 } 1143 base = strings.TrimSuffix(base, ".so") 1144 base = strings.TrimPrefix(base, "lib") 1145 if !seenLibs[base] { 1146 argv = append(argv, "-l"+base) 1147 seenLibs[base] = true 1148 } 1149 } 1150 for _, shlib := range Ctxt.Shlibs { 1151 addshlib(shlib.Path) 1152 for _, dep := range shlib.Deps { 1153 if dep == "" { 1154 continue 1155 } 1156 libpath := findshlib(dep) 1157 if libpath != "" { 1158 addshlib(libpath) 1159 } 1160 } 1161 } 1162 } 1163 1164 argv = append(argv, ldflag...) 1165 1166 for _, p := range strings.Fields(extldflags) { 1167 argv = append(argv, p) 1168 1169 // clang, unlike GCC, passes -rdynamic to the linker 1170 // even when linking with -static, causing a linker 1171 // error when using GNU ld. So take out -rdynamic if 1172 // we added it. We do it in this order, rather than 1173 // only adding -rdynamic later, so that -extldflags 1174 // can override -rdynamic without using -static. 1175 if Iself && p == "-static" { 1176 for i := range argv { 1177 if argv[i] == "-rdynamic" { 1178 argv[i] = "-static" 1179 } 1180 } 1181 } 1182 } 1183 if HEADTYPE == obj.Hwindows { 1184 argv = append(argv, peimporteddlls()...) 1185 } 1186 1187 if Debug['v'] != 0 { 1188 fmt.Fprintf(&Bso, "host link:") 1189 for _, v := range argv { 1190 fmt.Fprintf(&Bso, " %q", v) 1191 } 1192 fmt.Fprintf(&Bso, "\n") 1193 Bso.Flush() 1194 } 1195 1196 if out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput(); err != nil { 1197 Exitf("running %s failed: %v\n%s", argv[0], err, out) 1198 } else if Debug['v'] != 0 && len(out) > 0 { 1199 fmt.Fprintf(&Bso, "%s", out) 1200 Bso.Flush() 1201 } 1202 1203 if Debug['s'] == 0 && debug_s == 0 && HEADTYPE == obj.Hdarwin { 1204 // Skip combining dwarf on arm. 1205 if Thearch.Thechar != '5' && Thearch.Thechar != '7' { 1206 dsym := fmt.Sprintf("%s/go.dwarf", tmpdir) 1207 if out, err := exec.Command("dsymutil", "-f", outfile, "-o", dsym).CombinedOutput(); err != nil { 1208 Ctxt.Cursym = nil 1209 Exitf("%s: running dsymutil failed: %v\n%s", os.Args[0], err, out) 1210 } 1211 // Skip combining if `dsymutil` didn't generate a file. See #11994. 1212 if _, err := os.Stat(dsym); os.IsNotExist(err) { 1213 return 1214 } 1215 // For os.Rename to work reliably, must be in same directory as outfile. 1216 combinedOutput := outfile + "~" 1217 if err := machoCombineDwarf(outfile, dsym, combinedOutput); err != nil { 1218 Ctxt.Cursym = nil 1219 Exitf("%s: combining dwarf failed: %v", os.Args[0], err) 1220 } 1221 os.Remove(outfile) 1222 if err := os.Rename(combinedOutput, outfile); err != nil { 1223 Ctxt.Cursym = nil 1224 Exitf("%s: %v", os.Args[0], err) 1225 } 1226 } 1227 } 1228 } 1229 1230 // hostlinkArchArgs returns arguments to pass to the external linker 1231 // based on the architecture. 1232 func hostlinkArchArgs() []string { 1233 switch Thearch.Thechar { 1234 case '8': 1235 return []string{"-m32"} 1236 case '6', '9': 1237 return []string{"-m64"} 1238 case '5': 1239 return []string{"-marm"} 1240 case '7': 1241 // nothing needed 1242 } 1243 return nil 1244 } 1245 1246 // ldobj loads an input object. If it is a host object (an object 1247 // compiled by a non-Go compiler) it returns the Hostobj pointer. If 1248 // it is a Go object, it returns nil. 1249 func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, whence int) *Hostobj { 1250 eof := obj.Boffset(f) + length 1251 1252 start := obj.Boffset(f) 1253 c1 := obj.Bgetc(f) 1254 c2 := obj.Bgetc(f) 1255 c3 := obj.Bgetc(f) 1256 c4 := obj.Bgetc(f) 1257 obj.Bseek(f, start, 0) 1258 1259 magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4) 1260 if magic == 0x7f454c46 { // \x7F E L F 1261 return ldhostobj(ldelf, f, pkg, length, pn, file) 1262 } 1263 1264 if magic&^1 == 0xfeedface || magic&^0x01000000 == 0xcefaedfe { 1265 return ldhostobj(ldmacho, f, pkg, length, pn, file) 1266 } 1267 1268 if c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86 { 1269 return ldhostobj(ldpe, f, pkg, length, pn, file) 1270 } 1271 1272 /* check the header */ 1273 line := obj.Brdline(f, '\n') 1274 if line == "" { 1275 if obj.Blinelen(f) > 0 { 1276 Diag("%s: not an object file", pn) 1277 return nil 1278 } 1279 Diag("truncated object file: %s", pn) 1280 return nil 1281 } 1282 1283 if !strings.HasPrefix(line, "go object ") { 1284 if strings.HasSuffix(pn, ".go") { 1285 Exitf("%cl: input %s is not .%c file (use %cg to compile .go files)", Thearch.Thechar, pn, Thearch.Thechar, Thearch.Thechar) 1286 } 1287 1288 if line == Thestring { 1289 // old header format: just $GOOS 1290 Diag("%s: stale object file", pn) 1291 return nil 1292 } 1293 1294 Diag("%s: not an object file", pn) 1295 return nil 1296 } 1297 1298 // First, check that the basic goos, goarch, and version match. 1299 t := fmt.Sprintf("%s %s %s ", goos, obj.Getgoarch(), obj.Getgoversion()) 1300 1301 line = strings.TrimRight(line, "\n") 1302 if !strings.HasPrefix(line[10:]+" ", t) && Debug['f'] == 0 { 1303 Diag("%s: object is [%s] expected [%s]", pn, line[10:], t) 1304 return nil 1305 } 1306 1307 // Second, check that longer lines match each other exactly, 1308 // so that the Go compiler and write additional information 1309 // that must be the same from run to run. 1310 if len(line) >= len(t)+10 { 1311 if theline == "" { 1312 theline = line[10:] 1313 } else if theline != line[10:] { 1314 Diag("%s: object is [%s] expected [%s]", pn, line[10:], theline) 1315 return nil 1316 } 1317 } 1318 1319 /* skip over exports and other info -- ends with \n!\n */ 1320 import0 := obj.Boffset(f) 1321 1322 c1 = '\n' // the last line ended in \n 1323 c2 = obj.Bgetc(f) 1324 c3 = obj.Bgetc(f) 1325 for c1 != '\n' || c2 != '!' || c3 != '\n' { 1326 c1 = c2 1327 c2 = c3 1328 c3 = obj.Bgetc(f) 1329 if c3 == obj.Beof { 1330 Diag("truncated object file: %s", pn) 1331 return nil 1332 } 1333 } 1334 1335 import1 := obj.Boffset(f) 1336 1337 obj.Bseek(f, import0, 0) 1338 ldpkg(f, pkg, import1-import0-2, pn, whence) // -2 for !\n 1339 obj.Bseek(f, import1, 0) 1340 1341 ldobjfile(Ctxt, f, pkg, eof-obj.Boffset(f), pn) 1342 return nil 1343 } 1344 1345 func readelfsymboldata(f *elf.File, sym *elf.Symbol) []byte { 1346 data := make([]byte, sym.Size) 1347 sect := f.Sections[sym.Section] 1348 if sect.Type != elf.SHT_PROGBITS && sect.Type != elf.SHT_NOTE { 1349 Diag("reading %s from non-data section", sym.Name) 1350 } 1351 n, err := sect.ReadAt(data, int64(sym.Value-sect.Addr)) 1352 if uint64(n) != sym.Size { 1353 Diag("reading contents of %s: %v", sym.Name, err) 1354 } 1355 return data 1356 } 1357 1358 func readwithpad(r io.Reader, sz int32) ([]byte, error) { 1359 data := make([]byte, Rnd(int64(sz), 4)) 1360 _, err := io.ReadFull(r, data) 1361 if err != nil { 1362 return nil, err 1363 } 1364 data = data[:sz] 1365 return data, nil 1366 } 1367 1368 func readnote(f *elf.File, name []byte, typ int32) ([]byte, error) { 1369 for _, sect := range f.Sections { 1370 if sect.Type != elf.SHT_NOTE { 1371 continue 1372 } 1373 r := sect.Open() 1374 for { 1375 var namesize, descsize, noteType int32 1376 err := binary.Read(r, f.ByteOrder, &namesize) 1377 if err != nil { 1378 if err == io.EOF { 1379 break 1380 } 1381 return nil, fmt.Errorf("read namesize failed: %v", err) 1382 } 1383 err = binary.Read(r, f.ByteOrder, &descsize) 1384 if err != nil { 1385 return nil, fmt.Errorf("read descsize failed: %v", err) 1386 } 1387 err = binary.Read(r, f.ByteOrder, ¬eType) 1388 if err != nil { 1389 return nil, fmt.Errorf("read type failed: %v", err) 1390 } 1391 noteName, err := readwithpad(r, namesize) 1392 if err != nil { 1393 return nil, fmt.Errorf("read name failed: %v", err) 1394 } 1395 desc, err := readwithpad(r, descsize) 1396 if err != nil { 1397 return nil, fmt.Errorf("read desc failed: %v", err) 1398 } 1399 if string(name) == string(noteName) && typ == noteType { 1400 return desc, nil 1401 } 1402 } 1403 } 1404 return nil, nil 1405 } 1406 1407 func findshlib(shlib string) string { 1408 for _, libdir := range Ctxt.Libdir { 1409 libpath := filepath.Join(libdir, shlib) 1410 if _, err := os.Stat(libpath); err == nil { 1411 return libpath 1412 } 1413 } 1414 Diag("cannot find shared library: %s", shlib) 1415 return "" 1416 } 1417 1418 func ldshlibsyms(shlib string) { 1419 libpath := findshlib(shlib) 1420 if libpath == "" { 1421 return 1422 } 1423 for _, processedlib := range Ctxt.Shlibs { 1424 if processedlib.Path == libpath { 1425 return 1426 } 1427 } 1428 if Ctxt.Debugvlog > 1 && Ctxt.Bso != nil { 1429 fmt.Fprintf(Ctxt.Bso, "%5.2f ldshlibsyms: found library with name %s at %s\n", obj.Cputime(), shlib, libpath) 1430 Ctxt.Bso.Flush() 1431 } 1432 1433 f, err := elf.Open(libpath) 1434 if err != nil { 1435 Diag("cannot open shared library: %s", libpath) 1436 return 1437 } 1438 1439 hash, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GOABIHASH_TAG) 1440 if err != nil { 1441 Diag("cannot read ABI hash from shared library %s: %v", libpath, err) 1442 return 1443 } 1444 1445 depsbytes, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GODEPS_TAG) 1446 if err != nil { 1447 Diag("cannot read dep list from shared library %s: %v", libpath, err) 1448 return 1449 } 1450 deps := strings.Split(string(depsbytes), "\n") 1451 1452 syms, err := f.DynamicSymbols() 1453 if err != nil { 1454 Diag("cannot read symbols from shared library: %s", libpath) 1455 return 1456 } 1457 gcdata_locations := make(map[uint64]*LSym) 1458 for _, elfsym := range syms { 1459 if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION { 1460 continue 1461 } 1462 lsym := Linklookup(Ctxt, elfsym.Name, 0) 1463 if lsym.Type != 0 && lsym.Type != obj.SDYNIMPORT && lsym.Dupok == 0 { 1464 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 { 1465 Diag("Found duplicate symbol %s reading from %s, first found in %s", elfsym.Name, shlib, lsym.File) 1466 } 1467 if lsym.Size > int64(elfsym.Size) { 1468 // If the existing symbol is a BSS value that is 1469 // larger than the one read from the shared library, 1470 // keep references to that. Conversely, if the 1471 // version from the shared libray is larger, we want 1472 // to make all references be to that. 1473 continue 1474 } 1475 } 1476 lsym.Type = obj.SDYNIMPORT 1477 lsym.ElfType = elf.ST_TYPE(elfsym.Info) 1478 lsym.Size = int64(elfsym.Size) 1479 if elfsym.Section != elf.SHN_UNDEF { 1480 // Set .File for the library that actually defines the symbol. 1481 lsym.File = libpath 1482 // The decodetype_* functions in decodetype.go need access to 1483 // the type data. 1484 if strings.HasPrefix(lsym.Name, "type.") && !strings.HasPrefix(lsym.Name, "type..") { 1485 lsym.P = readelfsymboldata(f, &elfsym) 1486 gcdata_locations[elfsym.Value+2*uint64(Thearch.Ptrsize)+8+1*uint64(Thearch.Ptrsize)] = lsym 1487 } 1488 } 1489 } 1490 gcdata_addresses := make(map[*LSym]uint64) 1491 if Thearch.Thechar == '7' { 1492 for _, sect := range f.Sections { 1493 if sect.Type == elf.SHT_RELA { 1494 var rela elf.Rela64 1495 rdr := sect.Open() 1496 for { 1497 err := binary.Read(rdr, f.ByteOrder, &rela) 1498 if err == io.EOF { 1499 break 1500 } else if err != nil { 1501 Diag("reading relocation failed %v", err) 1502 return 1503 } 1504 t := elf.R_AARCH64(rela.Info & 0xffff) 1505 if t != elf.R_AARCH64_RELATIVE { 1506 continue 1507 } 1508 if lsym, ok := gcdata_locations[rela.Off]; ok { 1509 gcdata_addresses[lsym] = uint64(rela.Addend) 1510 } 1511 } 1512 } 1513 } 1514 } 1515 1516 // We might have overwritten some functions above (this tends to happen for the 1517 // autogenerated type equality/hashing functions) and we don't want to generated 1518 // pcln table entries for these any more so unstitch them from the Textp linked 1519 // list. 1520 var last *LSym 1521 1522 for s := Ctxt.Textp; s != nil; s = s.Next { 1523 if s.Type == obj.SDYNIMPORT { 1524 continue 1525 } 1526 1527 if last == nil { 1528 Ctxt.Textp = s 1529 } else { 1530 last.Next = s 1531 } 1532 last = s 1533 } 1534 1535 if last == nil { 1536 Ctxt.Textp = nil 1537 Ctxt.Etextp = nil 1538 } else { 1539 last.Next = nil 1540 Ctxt.Etextp = last 1541 } 1542 1543 Ctxt.Shlibs = append(Ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f, gcdata_addresses: gcdata_addresses}) 1544 } 1545 1546 func mywhatsys() { 1547 goroot = obj.Getgoroot() 1548 goos = obj.Getgoos() 1549 goarch = obj.Getgoarch() 1550 1551 if !strings.HasPrefix(goarch, Thestring) { 1552 log.Fatalf("cannot use %cc with GOARCH=%s", Thearch.Thechar, goarch) 1553 } 1554 } 1555 1556 // Copied from ../gc/subr.c:/^pathtoprefix; must stay in sync. 1557 /* 1558 * Convert raw string to the prefix that will be used in the symbol table. 1559 * Invalid bytes turn into %xx. Right now the only bytes that need 1560 * escaping are %, ., and ", but we escape all control characters too. 1561 * 1562 * If you edit this, edit ../gc/subr.c:/^pathtoprefix too. 1563 * If you edit this, edit ../../debug/goobj/read.go:/importPathToPrefix too. 1564 */ 1565 func pathtoprefix(s string) string { 1566 slash := strings.LastIndex(s, "/") 1567 for i := 0; i < len(s); i++ { 1568 c := s[i] 1569 if c <= ' ' || i >= slash && c == '.' || c == '%' || c == '"' || c >= 0x7F { 1570 var buf bytes.Buffer 1571 for i := 0; i < len(s); i++ { 1572 c := s[i] 1573 if c <= ' ' || i >= slash && c == '.' || c == '%' || c == '"' || c >= 0x7F { 1574 fmt.Fprintf(&buf, "%%%02x", c) 1575 continue 1576 } 1577 buf.WriteByte(c) 1578 } 1579 return buf.String() 1580 } 1581 } 1582 return s 1583 } 1584 1585 func addsection(seg *Segment, name string, rwx int) *Section { 1586 var l **Section 1587 1588 for l = &seg.Sect; *l != nil; l = &(*l).Next { 1589 } 1590 sect := new(Section) 1591 sect.Rwx = uint8(rwx) 1592 sect.Name = name 1593 sect.Seg = seg 1594 sect.Align = int32(Thearch.Ptrsize) // everything is at least pointer-aligned 1595 *l = sect 1596 return sect 1597 } 1598 1599 func Le16(b []byte) uint16 { 1600 return uint16(b[0]) | uint16(b[1])<<8 1601 } 1602 1603 func Le32(b []byte) uint32 { 1604 return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 1605 } 1606 1607 func Le64(b []byte) uint64 { 1608 return uint64(Le32(b)) | uint64(Le32(b[4:]))<<32 1609 } 1610 1611 func Be16(b []byte) uint16 { 1612 return uint16(b[0])<<8 | uint16(b[1]) 1613 } 1614 1615 func Be32(b []byte) uint32 { 1616 return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3]) 1617 } 1618 1619 type Chain struct { 1620 sym *LSym 1621 up *Chain 1622 limit int // limit on entry to sym 1623 } 1624 1625 var morestack *LSym 1626 1627 // TODO: Record enough information in new object files to 1628 // allow stack checks here. 1629 1630 func haslinkregister() bool { 1631 return Ctxt.FixedFrameSize() != 0 1632 } 1633 1634 func callsize() int { 1635 if haslinkregister() { 1636 return 0 1637 } 1638 return Thearch.Regsize 1639 } 1640 1641 func dostkcheck() { 1642 var ch Chain 1643 1644 morestack = Linklookup(Ctxt, "runtime.morestack", 0) 1645 1646 // Every splitting function ensures that there are at least StackLimit 1647 // bytes available below SP when the splitting prologue finishes. 1648 // If the splitting function calls F, then F begins execution with 1649 // at least StackLimit - callsize() bytes available. 1650 // Check that every function behaves correctly with this amount 1651 // of stack, following direct calls in order to piece together chains 1652 // of non-splitting functions. 1653 ch.up = nil 1654 1655 ch.limit = obj.StackLimit - callsize() 1656 1657 // Check every function, but do the nosplit functions in a first pass, 1658 // to make the printed failure chains as short as possible. 1659 for s := Ctxt.Textp; s != nil; s = s.Next { 1660 // runtime.racesymbolizethunk is called from gcc-compiled C 1661 // code running on the operating system thread stack. 1662 // It uses more than the usual amount of stack but that's okay. 1663 if s.Name == "runtime.racesymbolizethunk" { 1664 continue 1665 } 1666 1667 if s.Nosplit != 0 { 1668 Ctxt.Cursym = s 1669 ch.sym = s 1670 stkcheck(&ch, 0) 1671 } 1672 } 1673 1674 for s := Ctxt.Textp; s != nil; s = s.Next { 1675 if s.Nosplit == 0 { 1676 Ctxt.Cursym = s 1677 ch.sym = s 1678 stkcheck(&ch, 0) 1679 } 1680 } 1681 } 1682 1683 func stkcheck(up *Chain, depth int) int { 1684 limit := up.limit 1685 s := up.sym 1686 1687 // Don't duplicate work: only need to consider each 1688 // function at top of safe zone once. 1689 top := limit == obj.StackLimit-callsize() 1690 if top { 1691 if s.Stkcheck != 0 { 1692 return 0 1693 } 1694 s.Stkcheck = 1 1695 } 1696 1697 if depth > 100 { 1698 Diag("nosplit stack check too deep") 1699 stkbroke(up, 0) 1700 return -1 1701 } 1702 1703 if s.External != 0 || s.Pcln == nil { 1704 // external function. 1705 // should never be called directly. 1706 // only diagnose the direct caller. 1707 // TODO(mwhudson): actually think about this. 1708 if depth == 1 && s.Type != obj.SXREF && !DynlinkingGo() && 1709 Buildmode != BuildmodePIE && Buildmode != BuildmodeCShared { 1710 Diag("call to external function %s", s.Name) 1711 } 1712 return -1 1713 } 1714 1715 if limit < 0 { 1716 stkbroke(up, limit) 1717 return -1 1718 } 1719 1720 // morestack looks like it calls functions, 1721 // but it switches the stack pointer first. 1722 if s == morestack { 1723 return 0 1724 } 1725 1726 var ch Chain 1727 ch.up = up 1728 1729 if s.Nosplit == 0 { 1730 // Ensure we have enough stack to call morestack. 1731 ch.limit = limit - callsize() 1732 ch.sym = morestack 1733 if stkcheck(&ch, depth+1) < 0 { 1734 return -1 1735 } 1736 if !top { 1737 return 0 1738 } 1739 // Raise limit to allow frame. 1740 limit = int(obj.StackLimit+s.Locals) + int(Ctxt.FixedFrameSize()) 1741 } 1742 1743 // Walk through sp adjustments in function, consuming relocs. 1744 ri := 0 1745 1746 endr := len(s.R) 1747 var ch1 Chain 1748 var pcsp Pciter 1749 var r *Reloc 1750 for pciterinit(Ctxt, &pcsp, &s.Pcln.Pcsp); pcsp.done == 0; pciternext(&pcsp) { 1751 // pcsp.value is in effect for [pcsp.pc, pcsp.nextpc). 1752 1753 // Check stack size in effect for this span. 1754 if int32(limit)-pcsp.value < 0 { 1755 stkbroke(up, int(int32(limit)-pcsp.value)) 1756 return -1 1757 } 1758 1759 // Process calls in this span. 1760 for ; ri < endr && uint32(s.R[ri].Off) < pcsp.nextpc; ri++ { 1761 r = &s.R[ri] 1762 switch r.Type { 1763 // Direct call. 1764 case obj.R_CALL, obj.R_CALLARM, obj.R_CALLARM64, obj.R_CALLPOWER, obj.R_CALLMIPS: 1765 ch.limit = int(int32(limit) - pcsp.value - int32(callsize())) 1766 ch.sym = r.Sym 1767 if stkcheck(&ch, depth+1) < 0 { 1768 return -1 1769 } 1770 1771 // Indirect call. Assume it is a call to a splitting function, 1772 // so we have to make sure it can call morestack. 1773 // Arrange the data structures to report both calls, so that 1774 // if there is an error, stkprint shows all the steps involved. 1775 case obj.R_CALLIND: 1776 ch.limit = int(int32(limit) - pcsp.value - int32(callsize())) 1777 1778 ch.sym = nil 1779 ch1.limit = ch.limit - callsize() // for morestack in called prologue 1780 ch1.up = &ch 1781 ch1.sym = morestack 1782 if stkcheck(&ch1, depth+2) < 0 { 1783 return -1 1784 } 1785 } 1786 } 1787 } 1788 1789 return 0 1790 } 1791 1792 func stkbroke(ch *Chain, limit int) { 1793 Diag("nosplit stack overflow") 1794 stkprint(ch, limit) 1795 } 1796 1797 func stkprint(ch *Chain, limit int) { 1798 var name string 1799 1800 if ch.sym != nil { 1801 name = ch.sym.Name 1802 if ch.sym.Nosplit != 0 { 1803 name += " (nosplit)" 1804 } 1805 } else { 1806 name = "function pointer" 1807 } 1808 1809 if ch.up == nil { 1810 // top of chain. ch->sym != nil. 1811 if ch.sym.Nosplit != 0 { 1812 fmt.Printf("\t%d\tassumed on entry to %s\n", ch.limit, name) 1813 } else { 1814 fmt.Printf("\t%d\tguaranteed after split check in %s\n", ch.limit, name) 1815 } 1816 } else { 1817 stkprint(ch.up, ch.limit+callsize()) 1818 if !haslinkregister() { 1819 fmt.Printf("\t%d\ton entry to %s\n", ch.limit, name) 1820 } 1821 } 1822 1823 if ch.limit != limit { 1824 fmt.Printf("\t%d\tafter %s uses %d\n", limit, name, ch.limit-limit) 1825 } 1826 } 1827 1828 func Cflush() { 1829 if err := coutbuf.Writer.Flush(); err != nil { 1830 Exitf("flushing %s: %v", coutbuf.f.Name(), err) 1831 } 1832 } 1833 1834 func Cpos() int64 { 1835 off, err := coutbuf.f.Seek(0, 1) 1836 if err != nil { 1837 Exitf("seeking in output [0, 1]: %v", err) 1838 } 1839 return off + int64(coutbuf.Buffered()) 1840 } 1841 1842 func Cseek(p int64) { 1843 Cflush() 1844 if _, err := coutbuf.f.Seek(p, 0); err != nil { 1845 Exitf("seeking in output [0, 1]: %v", err) 1846 } 1847 } 1848 1849 func Cwrite(p []byte) { 1850 coutbuf.Write(p) 1851 } 1852 1853 func Cput(c uint8) { 1854 coutbuf.WriteByte(c) 1855 } 1856 1857 func usage() { 1858 fmt.Fprintf(os.Stderr, "usage: link [options] main.o\n") 1859 obj.Flagprint(2) 1860 Exit(2) 1861 } 1862 1863 func setheadtype(s string) { 1864 h := headtype(s) 1865 if h < 0 { 1866 Exitf("unknown header type -H %s", s) 1867 } 1868 1869 headstring = s 1870 HEADTYPE = int32(headtype(s)) 1871 } 1872 1873 func setinterp(s string) { 1874 Debug['I'] = 1 // denote cmdline interpreter override 1875 interpreter = s 1876 } 1877 1878 func doversion() { 1879 Exitf("version %s", obj.Getgoversion()) 1880 } 1881 1882 func genasmsym(put func(*LSym, string, int, int64, int64, int, *LSym)) { 1883 // These symbols won't show up in the first loop below because we 1884 // skip STEXT symbols. Normal STEXT symbols are emitted by walking textp. 1885 s := Linklookup(Ctxt, "runtime.text", 0) 1886 1887 if s.Type == obj.STEXT { 1888 put(s, s.Name, 'T', s.Value, s.Size, int(s.Version), nil) 1889 } 1890 s = Linklookup(Ctxt, "runtime.etext", 0) 1891 if s.Type == obj.STEXT { 1892 put(s, s.Name, 'T', s.Value, s.Size, int(s.Version), nil) 1893 } 1894 1895 for s := Ctxt.Allsym; s != nil; s = s.Allsym { 1896 if s.Hide != 0 || ((s.Name == "" || s.Name[0] == '.') && s.Version == 0 && s.Name != ".rathole" && s.Name != ".TOC.") { 1897 continue 1898 } 1899 switch s.Type & obj.SMASK { 1900 case obj.SCONST, 1901 obj.SRODATA, 1902 obj.SSYMTAB, 1903 obj.SPCLNTAB, 1904 obj.SINITARR, 1905 obj.SDATA, 1906 obj.SNOPTRDATA, 1907 obj.SELFROSECT, 1908 obj.SMACHOGOT, 1909 obj.STYPE, 1910 obj.SSTRING, 1911 obj.SGOSTRING, 1912 obj.SGOFUNC, 1913 obj.SGCBITS, 1914 obj.STYPERELRO, 1915 obj.SSTRINGRELRO, 1916 obj.SGOSTRINGRELRO, 1917 obj.SGOFUNCRELRO, 1918 obj.SGCBITSRELRO, 1919 obj.SRODATARELRO, 1920 obj.STYPELINK, 1921 obj.SWINDOWS: 1922 if !s.Reachable { 1923 continue 1924 } 1925 put(s, s.Name, 'D', Symaddr(s), s.Size, int(s.Version), s.Gotype) 1926 1927 case obj.SBSS, obj.SNOPTRBSS: 1928 if !s.Reachable { 1929 continue 1930 } 1931 if len(s.P) > 0 { 1932 Diag("%s should not be bss (size=%d type=%d special=%d)", s.Name, int(len(s.P)), s.Type, s.Special) 1933 } 1934 put(s, s.Name, 'B', Symaddr(s), s.Size, int(s.Version), s.Gotype) 1935 1936 case obj.SFILE: 1937 put(nil, s.Name, 'f', s.Value, 0, int(s.Version), nil) 1938 1939 case obj.SHOSTOBJ: 1940 if HEADTYPE == obj.Hwindows || Iself { 1941 put(s, s.Name, 'U', s.Value, 0, int(s.Version), nil) 1942 } 1943 1944 case obj.SDYNIMPORT: 1945 if !s.Reachable { 1946 continue 1947 } 1948 put(s, s.Extname, 'U', 0, 0, int(s.Version), nil) 1949 1950 case obj.STLSBSS: 1951 if Linkmode == LinkExternal && HEADTYPE != obj.Hopenbsd { 1952 put(s, s.Name, 't', Symaddr(s), s.Size, int(s.Version), s.Gotype) 1953 } 1954 } 1955 } 1956 1957 var a *Auto 1958 var off int32 1959 for s := Ctxt.Textp; s != nil; s = s.Next { 1960 put(s, s.Name, 'T', s.Value, s.Size, int(s.Version), s.Gotype) 1961 1962 // NOTE(ality): acid can't produce a stack trace without .frame symbols 1963 put(nil, ".frame", 'm', int64(s.Locals)+int64(Thearch.Ptrsize), 0, 0, nil) 1964 1965 for a = s.Autom; a != nil; a = a.Link { 1966 // Emit a or p according to actual offset, even if label is wrong. 1967 // This avoids negative offsets, which cannot be encoded. 1968 if a.Name != obj.A_AUTO && a.Name != obj.A_PARAM { 1969 continue 1970 } 1971 1972 // compute offset relative to FP 1973 if a.Name == obj.A_PARAM { 1974 off = a.Aoffset 1975 } else { 1976 off = a.Aoffset - int32(Thearch.Ptrsize) 1977 } 1978 1979 // FP 1980 if off >= 0 { 1981 put(nil, a.Asym.Name, 'p', int64(off), 0, 0, a.Gotype) 1982 continue 1983 } 1984 1985 // SP 1986 if off <= int32(-Thearch.Ptrsize) { 1987 put(nil, a.Asym.Name, 'a', -(int64(off) + int64(Thearch.Ptrsize)), 0, 0, a.Gotype) 1988 continue 1989 } 1990 } 1991 } 1992 1993 // Otherwise, off is addressing the saved program counter. 1994 // Something underhanded is going on. Say nothing. 1995 if Debug['v'] != 0 || Debug['n'] != 0 { 1996 fmt.Fprintf(&Bso, "%5.2f symsize = %d\n", obj.Cputime(), uint32(Symsize)) 1997 } 1998 Bso.Flush() 1999 } 2000 2001 func Symaddr(s *LSym) int64 { 2002 if !s.Reachable { 2003 Diag("unreachable symbol in symaddr - %s", s.Name) 2004 } 2005 return s.Value 2006 } 2007 2008 func xdefine(p string, t int, v int64) { 2009 s := Linklookup(Ctxt, p, 0) 2010 s.Type = int16(t) 2011 s.Value = v 2012 s.Reachable = true 2013 s.Special = 1 2014 s.Local = true 2015 } 2016 2017 func datoff(addr int64) int64 { 2018 if uint64(addr) >= Segdata.Vaddr { 2019 return int64(uint64(addr) - Segdata.Vaddr + Segdata.Fileoff) 2020 } 2021 if uint64(addr) >= Segtext.Vaddr { 2022 return int64(uint64(addr) - Segtext.Vaddr + Segtext.Fileoff) 2023 } 2024 Diag("datoff %#x", addr) 2025 return 0 2026 } 2027 2028 func Entryvalue() int64 { 2029 a := INITENTRY 2030 if a[0] >= '0' && a[0] <= '9' { 2031 return atolwhex(a) 2032 } 2033 s := Linklookup(Ctxt, a, 0) 2034 if s.Type == 0 { 2035 return INITTEXT 2036 } 2037 if s.Type != obj.STEXT { 2038 Diag("entry not text: %s", s.Name) 2039 } 2040 return s.Value 2041 } 2042 2043 func undefsym(s *LSym) { 2044 var r *Reloc 2045 2046 Ctxt.Cursym = s 2047 for i := 0; i < len(s.R); i++ { 2048 r = &s.R[i] 2049 if r.Sym == nil { // happens for some external ARM relocs 2050 continue 2051 } 2052 if r.Sym.Type == obj.Sxxx || r.Sym.Type == obj.SXREF { 2053 Diag("undefined: %s", r.Sym.Name) 2054 } 2055 if !r.Sym.Reachable { 2056 Diag("use of unreachable symbol: %s", r.Sym.Name) 2057 } 2058 } 2059 } 2060 2061 func undef() { 2062 for s := Ctxt.Textp; s != nil; s = s.Next { 2063 undefsym(s) 2064 } 2065 for s := datap; s != nil; s = s.Next { 2066 undefsym(s) 2067 } 2068 if nerrors > 0 { 2069 errorexit() 2070 } 2071 } 2072 2073 func callgraph() { 2074 if Debug['c'] == 0 { 2075 return 2076 } 2077 2078 var i int 2079 var r *Reloc 2080 for s := Ctxt.Textp; s != nil; s = s.Next { 2081 for i = 0; i < len(s.R); i++ { 2082 r = &s.R[i] 2083 if r.Sym == nil { 2084 continue 2085 } 2086 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 { 2087 fmt.Fprintf(&Bso, "%s calls %s\n", s.Name, r.Sym.Name) 2088 } 2089 } 2090 } 2091 } 2092 2093 func Diag(format string, args ...interface{}) { 2094 tn := "" 2095 sep := "" 2096 if Ctxt.Cursym != nil { 2097 tn = Ctxt.Cursym.Name 2098 sep = ": " 2099 } 2100 fmt.Printf("%s%s%s\n", tn, sep, fmt.Sprintf(format, args...)) 2101 nerrors++ 2102 if Debug['h'] != 0 { 2103 panic("error") 2104 } 2105 if nerrors > 20 { 2106 Exitf("too many errors") 2107 } 2108 } 2109 2110 func checkgo() { 2111 if Debug['C'] == 0 { 2112 return 2113 } 2114 2115 // TODO(rsc,khr): Eventually we want to get to no Go-called C functions at all, 2116 // which would simplify this logic quite a bit. 2117 2118 // Mark every Go-called C function with cfunc=2, recursively. 2119 var changed int 2120 var i int 2121 var r *Reloc 2122 var s *LSym 2123 for { 2124 changed = 0 2125 for s = Ctxt.Textp; s != nil; s = s.Next { 2126 if s.Cfunc == 0 || (s.Cfunc == 2 && s.Nosplit != 0) { 2127 for i = 0; i < len(s.R); i++ { 2128 r = &s.R[i] 2129 if r.Sym == nil { 2130 continue 2131 } 2132 if (r.Type == obj.R_CALL || r.Type == obj.R_CALLARM) && r.Sym.Type == obj.STEXT { 2133 if r.Sym.Cfunc == 1 { 2134 changed = 1 2135 r.Sym.Cfunc = 2 2136 } 2137 } 2138 } 2139 } 2140 } 2141 if changed == 0 { 2142 break 2143 } 2144 } 2145 2146 // Complain about Go-called C functions that can split the stack 2147 // (that can be preempted for garbage collection or trigger a stack copy). 2148 for s := Ctxt.Textp; s != nil; s = s.Next { 2149 if s.Cfunc == 0 || (s.Cfunc == 2 && s.Nosplit != 0) { 2150 for i = 0; i < len(s.R); i++ { 2151 r = &s.R[i] 2152 if r.Sym == nil { 2153 continue 2154 } 2155 if (r.Type == obj.R_CALL || r.Type == obj.R_CALLARM) && r.Sym.Type == obj.STEXT { 2156 if s.Cfunc == 0 && r.Sym.Cfunc == 2 && r.Sym.Nosplit == 0 { 2157 fmt.Printf("Go %s calls C %s\n", s.Name, r.Sym.Name) 2158 } else if s.Cfunc == 2 && s.Nosplit != 0 && r.Sym.Nosplit == 0 { 2159 fmt.Printf("Go calls C %s calls %s\n", s.Name, r.Sym.Name) 2160 } 2161 } 2162 } 2163 } 2164 } 2165 } 2166 2167 func Rnd(v int64, r int64) int64 { 2168 if r <= 0 { 2169 return v 2170 } 2171 v += r - 1 2172 c := v % r 2173 if c < 0 { 2174 c += r 2175 } 2176 v -= c 2177 return v 2178 }