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