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