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