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