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