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