github.com/bir3/gocompiler@v0.9.2202/src/cmd/link/internal/ld/lib.go (about) 1 // Inferno utils/8l/asm.c 2 // https://bitbucket.org/inferno-os/inferno-os/src/master/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 "bytes" 35 "debug/elf" 36 "debug/macho" 37 "encoding/base64" 38 "encoding/binary" 39 "fmt" 40 "github.com/bir3/gocompiler/src/internal/buildcfg" 41 "io" 42 "log" 43 "os" 44 "github.com/bir3/gocompiler/exec" 45 "path/filepath" 46 "runtime" 47 "sort" 48 "strings" 49 "sync" 50 51 "github.com/bir3/gocompiler/src/cmd/internal/bio" 52 "github.com/bir3/gocompiler/src/cmd/internal/goobj" 53 "github.com/bir3/gocompiler/src/cmd/internal/notsha256" 54 "github.com/bir3/gocompiler/src/cmd/internal/objabi" 55 "github.com/bir3/gocompiler/src/cmd/internal/sys" 56 "github.com/bir3/gocompiler/src/cmd/link/internal/loadelf" 57 "github.com/bir3/gocompiler/src/cmd/link/flag_objabi" 58 "github.com/bir3/gocompiler/src/cmd/link/internal/loader" 59 "github.com/bir3/gocompiler/src/cmd/link/internal/loadmacho" 60 "github.com/bir3/gocompiler/src/cmd/link/internal/loadpe" 61 "github.com/bir3/gocompiler/src/cmd/link/internal/loadxcoff" 62 "github.com/bir3/gocompiler/src/cmd/link/internal/sym" 63 ) 64 65 // Data layout and relocation. 66 67 // Derived from Inferno utils/6l/l.h 68 // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/l.h 69 // 70 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 71 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 72 // Portions Copyright © 1997-1999 Vita Nuova Limited 73 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 74 // Portions Copyright © 2004,2006 Bruce Ellis 75 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 76 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 77 // Portions Copyright © 2009 The Go Authors. All rights reserved. 78 // 79 // Permission is hereby granted, free of charge, to any person obtaining a copy 80 // of this software and associated documentation files (the "Software"), to deal 81 // in the Software without restriction, including without limitation the rights 82 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 83 // copies of the Software, and to permit persons to whom the Software is 84 // furnished to do so, subject to the following conditions: 85 // 86 // The above copyright notice and this permission notice shall be included in 87 // all copies or substantial portions of the Software. 88 // 89 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 90 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 91 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 92 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 93 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 94 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 95 // THE SOFTWARE. 96 97 // ArchSyms holds a number of architecture specific symbols used during 98 // relocation. Rather than allowing them universal access to all symbols, 99 // we keep a subset for relocation application. 100 type ArchSyms struct { 101 Rel loader.Sym 102 Rela loader.Sym 103 RelPLT loader.Sym 104 RelaPLT loader.Sym 105 106 LinkEditGOT loader.Sym 107 LinkEditPLT loader.Sym 108 109 TOC loader.Sym 110 DotTOC []loader.Sym // for each version 111 112 GOT loader.Sym 113 PLT loader.Sym 114 GOTPLT loader.Sym 115 116 Tlsg loader.Sym 117 Tlsoffset int 118 119 Dynamic loader.Sym 120 DynSym loader.Sym 121 DynStr loader.Sym 122 123 unreachableMethod loader.Sym 124 125 // Symbol containing a list of all the inittasks that need 126 // to be run at startup. 127 mainInittasks loader.Sym 128 } 129 130 // mkArchSym is a helper for setArchSyms, to set up a special symbol. 131 func (ctxt *Link) mkArchSym(name string, ver int, ls *loader.Sym) { 132 *ls = ctxt.loader.LookupOrCreateSym(name, ver) 133 ctxt.loader.SetAttrReachable(*ls, true) 134 } 135 136 // mkArchSymVec is similar to setArchSyms, but operates on elements within 137 // a slice, where each element corresponds to some symbol version. 138 func (ctxt *Link) mkArchSymVec(name string, ver int, ls []loader.Sym) { 139 ls[ver] = ctxt.loader.LookupOrCreateSym(name, ver) 140 ctxt.loader.SetAttrReachable(ls[ver], true) 141 } 142 143 // setArchSyms sets up the ArchSyms structure, and must be called before 144 // relocations are applied. 145 func (ctxt *Link) setArchSyms() { 146 ctxt.mkArchSym(".got", 0, &ctxt.GOT) 147 ctxt.mkArchSym(".plt", 0, &ctxt.PLT) 148 ctxt.mkArchSym(".got.plt", 0, &ctxt.GOTPLT) 149 ctxt.mkArchSym(".dynamic", 0, &ctxt.Dynamic) 150 ctxt.mkArchSym(".dynsym", 0, &ctxt.DynSym) 151 ctxt.mkArchSym(".dynstr", 0, &ctxt.DynStr) 152 ctxt.mkArchSym("runtime.unreachableMethod", abiInternalVer, &ctxt.unreachableMethod) 153 154 if ctxt.IsPPC64() { 155 ctxt.mkArchSym("TOC", 0, &ctxt.TOC) 156 157 ctxt.DotTOC = make([]loader.Sym, ctxt.MaxVersion()+1) 158 for i := 0; i <= ctxt.MaxVersion(); i++ { 159 if i >= sym.SymVerABICount && i < sym.SymVerStatic { // these versions are not used currently 160 continue 161 } 162 ctxt.mkArchSymVec(".TOC.", i, ctxt.DotTOC) 163 } 164 } 165 if ctxt.IsElf() { 166 ctxt.mkArchSym(".rel", 0, &ctxt.Rel) 167 ctxt.mkArchSym(".rela", 0, &ctxt.Rela) 168 ctxt.mkArchSym(".rel.plt", 0, &ctxt.RelPLT) 169 ctxt.mkArchSym(".rela.plt", 0, &ctxt.RelaPLT) 170 } 171 if ctxt.IsDarwin() { 172 ctxt.mkArchSym(".linkedit.got", 0, &ctxt.LinkEditGOT) 173 ctxt.mkArchSym(".linkedit.plt", 0, &ctxt.LinkEditPLT) 174 } 175 } 176 177 type Arch struct { 178 Funcalign int 179 Maxalign int 180 Minalign int 181 Dwarfregsp int 182 Dwarfreglr int 183 184 // Threshold of total text size, used for trampoline insertion. If the total 185 // text size is smaller than TrampLimit, we won't need to insert trampolines. 186 // It is pretty close to the offset range of a direct CALL machine instruction. 187 // We leave some room for extra stuff like PLT stubs. 188 TrampLimit uint64 189 190 // Empty spaces between codeblocks will be padded with this value. 191 // For example an architecture might want to pad with a trap instruction to 192 // catch wayward programs. Architectures that do not define a padding value 193 // are padded with zeros. 194 CodePad []byte 195 196 // Plan 9 variables. 197 Plan9Magic uint32 198 Plan9_64Bit bool 199 200 Adddynrel func(*Target, *loader.Loader, *ArchSyms, loader.Sym, loader.Reloc, int) bool 201 Archinit func(*Link) 202 // Archreloc is an arch-specific hook that assists in relocation processing 203 // (invoked by 'relocsym'); it handles target-specific relocation tasks. 204 // Here "rel" is the current relocation being examined, "sym" is the symbol 205 // containing the chunk of data to which the relocation applies, and "off" 206 // is the contents of the to-be-relocated data item (from sym.P). Return 207 // value is the appropriately relocated value (to be written back to the 208 // same spot in sym.P), number of external _host_ relocations needed (i.e. 209 // ELF/Mach-O/etc. relocations, not Go relocations, this must match ELF.Reloc1, 210 // etc.), and a boolean indicating success/failure (a failing value indicates 211 // a fatal error). 212 Archreloc func(*Target, *loader.Loader, *ArchSyms, loader.Reloc, loader.Sym, 213 int64) (relocatedOffset int64, nExtReloc int, ok bool) 214 // Archrelocvariant is a second arch-specific hook used for 215 // relocation processing; it handles relocations where r.Type is 216 // insufficient to describe the relocation (r.Variant != 217 // sym.RV_NONE). Here "rel" is the relocation being applied, "sym" 218 // is the symbol containing the chunk of data to which the 219 // relocation applies, and "off" is the contents of the 220 // to-be-relocated data item (from sym.P). Return is an updated 221 // offset value. 222 Archrelocvariant func(target *Target, ldr *loader.Loader, rel loader.Reloc, 223 rv sym.RelocVariant, sym loader.Sym, offset int64, data []byte) (relocatedOffset int64) 224 225 // Generate a trampoline for a call from s to rs if necessary. ri is 226 // index of the relocation. 227 Trampoline func(ctxt *Link, ldr *loader.Loader, ri int, rs, s loader.Sym) 228 229 // Assembling the binary breaks into two phases, writing the code/data/ 230 // dwarf information (which is rather generic), and some more architecture 231 // specific work like setting up the elf headers/dynamic relocations, etc. 232 // The phases are called "Asmb" and "Asmb2". Asmb2 needs to be defined for 233 // every architecture, but only if architecture has an Asmb function will 234 // it be used for assembly. Otherwise a generic assembly Asmb function is 235 // used. 236 Asmb func(*Link, *loader.Loader) 237 Asmb2 func(*Link, *loader.Loader) 238 239 // Extreloc is an arch-specific hook that converts a Go relocation to an 240 // external relocation. Return the external relocation and whether it is 241 // needed. 242 Extreloc func(*Target, *loader.Loader, loader.Reloc, loader.Sym) (loader.ExtReloc, bool) 243 244 Gentext func(*Link, *loader.Loader) // Generate text before addressing has been performed. 245 Machoreloc1 func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool 246 MachorelocSize uint32 // size of an Mach-O relocation record, must match Machoreloc1. 247 PEreloc1 func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool 248 Xcoffreloc1 func(*sys.Arch, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool 249 250 // Generate additional symbols for the native symbol table just prior to 251 // code generation. 252 GenSymsLate func(*Link, *loader.Loader) 253 254 // TLSIEtoLE converts a TLS Initial Executable relocation to 255 // a TLS Local Executable relocation. 256 // 257 // This is possible when a TLS IE relocation refers to a local 258 // symbol in an executable, which is typical when internally 259 // linking PIE binaries. 260 TLSIEtoLE func(P []byte, off, size int) 261 262 // optional override for assignAddress 263 AssignAddress func(ldr *loader.Loader, sect *sym.Section, n int, s loader.Sym, va uint64, isTramp bool) (*sym.Section, int, uint64) 264 265 // ELF specific information. 266 ELF ELFArch 267 } 268 269 var ( 270 thearch Arch 271 lcSize int32 272 rpath Rpath 273 spSize int32 274 symSize int32 275 ) 276 277 const ( 278 MINFUNC = 16 // minimum size for a function 279 ) 280 281 // Symbol version of ABIInternal symbols. It is sym.SymVerABIInternal if ABI wrappers 282 // are used, 0 otherwise. 283 var abiInternalVer = sym.SymVerABIInternal 284 285 // DynlinkingGo reports whether we are producing Go code that can live 286 // in separate shared libraries linked together at runtime. 287 func (ctxt *Link) DynlinkingGo() bool { 288 if !ctxt.Loaded { 289 panic("DynlinkingGo called before all symbols loaded") 290 } 291 return ctxt.BuildMode == BuildModeShared || ctxt.linkShared || ctxt.BuildMode == BuildModePlugin || ctxt.canUsePlugins 292 } 293 294 // CanUsePlugins reports whether a plugins can be used 295 func (ctxt *Link) CanUsePlugins() bool { 296 if !ctxt.Loaded { 297 panic("CanUsePlugins called before all symbols loaded") 298 } 299 return ctxt.canUsePlugins 300 } 301 302 // NeedCodeSign reports whether we need to code-sign the output binary. 303 func (ctxt *Link) NeedCodeSign() bool { 304 return ctxt.IsDarwin() && ctxt.IsARM64() 305 } 306 307 var ( 308 dynlib []string 309 ldflag []string 310 havedynamic int 311 Funcalign int 312 iscgo bool 313 elfglobalsymndx int 314 interpreter string 315 316 debug_s bool // backup old value of debug['s'] 317 HEADR int32 318 319 nerrors int 320 liveness int64 // size of liveness data (funcdata), printed if -v 321 322 // See -strictdups command line flag. 323 checkStrictDups int // 0=off 1=warning 2=error 324 strictDupMsgCount int 325 ) 326 327 var ( 328 Segtext sym.Segment 329 Segrodata sym.Segment 330 Segrelrodata sym.Segment 331 Segdata sym.Segment 332 Segdwarf sym.Segment 333 Segpdata sym.Segment // windows-only 334 Segxdata sym.Segment // windows-only 335 336 Segments = []*sym.Segment{&Segtext, &Segrodata, &Segrelrodata, &Segdata, &Segdwarf, &Segpdata, &Segxdata} 337 ) 338 339 const pkgdef = "__.PKGDEF" 340 341 var ( 342 // externalobj is set to true if we see an object compiled by 343 // the host compiler that is not from a package that is known 344 // to support internal linking mode. 345 externalobj = false 346 347 // dynimportfail is a list of packages for which generating 348 // the dynimport file, _cgo_import.go, failed. If there are 349 // any of these objects, we must link externally. Issue 52863. 350 dynimportfail []string 351 352 // preferlinkext is a list of packages for which the Go command 353 // noticed use of peculiar C flags. If we see any of these, 354 // default to linking externally unless overridden by the 355 // user. See issues #58619, #58620, and #58848. 356 preferlinkext []string 357 358 // unknownObjFormat is set to true if we see an object whose 359 // format we don't recognize. 360 unknownObjFormat = false 361 362 theline string 363 ) 364 365 func Lflag(ctxt *Link, arg string) { 366 ctxt.Libdir = append(ctxt.Libdir, arg) 367 } 368 369 /* 370 * Unix doesn't like it when we write to a running (or, sometimes, 371 * recently run) binary, so remove the output file before writing it. 372 * On Windows 7, remove() can force a subsequent create() to fail. 373 * S_ISREG() does not exist on Plan 9. 374 */ 375 func mayberemoveoutfile() { 376 if fi, err := os.Lstat(*flagOutfile); err == nil && !fi.Mode().IsRegular() { 377 return 378 } 379 os.Remove(*flagOutfile) 380 } 381 382 func libinit(ctxt *Link) { 383 Funcalign = thearch.Funcalign 384 385 // add goroot to the end of the libdir list. 386 suffix := "" 387 388 suffixsep := "" 389 if *flagInstallSuffix != "" { 390 suffixsep = "_" 391 suffix = *flagInstallSuffix 392 } else if *flagRace { 393 suffixsep = "_" 394 suffix = "race" 395 } else if *flagMsan { 396 suffixsep = "_" 397 suffix = "msan" 398 } else if *flagAsan { 399 suffixsep = "_" 400 suffix = "asan" 401 } 402 403 if buildcfg.GOROOT != "" { 404 Lflag(ctxt, filepath.Join(buildcfg.GOROOT, "pkg", fmt.Sprintf("%s_%s%s%s", buildcfg.GOOS, buildcfg.GOARCH, suffixsep, suffix))) 405 } 406 407 mayberemoveoutfile() 408 409 if err := ctxt.Out.Open(*flagOutfile); err != nil { 410 Exitf("cannot create %s: %v", *flagOutfile, err) 411 } 412 413 if *flagEntrySymbol == "" { 414 switch ctxt.BuildMode { 415 case BuildModeCShared, BuildModeCArchive: 416 *flagEntrySymbol = fmt.Sprintf("_rt0_%s_%s_lib", buildcfg.GOARCH, buildcfg.GOOS) 417 case BuildModeExe, BuildModePIE: 418 *flagEntrySymbol = fmt.Sprintf("_rt0_%s_%s", buildcfg.GOARCH, buildcfg.GOOS) 419 case BuildModeShared, BuildModePlugin: 420 // No *flagEntrySymbol for -buildmode=shared and plugin 421 default: 422 Errorf(nil, "unknown *flagEntrySymbol for buildmode %v", ctxt.BuildMode) 423 } 424 } 425 } 426 427 func exitIfErrors() { 428 if nerrors != 0 || checkStrictDups > 1 && strictDupMsgCount > 0 { 429 mayberemoveoutfile() 430 Exit(2) 431 } 432 433 } 434 435 func errorexit() { 436 exitIfErrors() 437 Exit(0) 438 } 439 440 func loadinternal(ctxt *Link, name string) *sym.Library { 441 zerofp := goobj.FingerprintType{} 442 if ctxt.linkShared && ctxt.PackageShlib != nil { 443 if shlib := ctxt.PackageShlib[name]; shlib != "" { 444 return addlibpath(ctxt, "internal", "internal", "", name, shlib, zerofp) 445 } 446 } 447 if ctxt.PackageFile != nil { 448 if pname := ctxt.PackageFile[name]; pname != "" { 449 return addlibpath(ctxt, "internal", "internal", pname, name, "", zerofp) 450 } 451 ctxt.Logf("loadinternal: cannot find %s\n", name) 452 return nil 453 } 454 455 for _, libdir := range ctxt.Libdir { 456 if ctxt.linkShared { 457 shlibname := filepath.Join(libdir, name+".shlibname") 458 if ctxt.Debugvlog != 0 { 459 ctxt.Logf("searching for %s.a in %s\n", name, shlibname) 460 } 461 if _, err := os.Stat(shlibname); err == nil { 462 return addlibpath(ctxt, "internal", "internal", "", name, shlibname, zerofp) 463 } 464 } 465 pname := filepath.Join(libdir, name+".a") 466 if ctxt.Debugvlog != 0 { 467 ctxt.Logf("searching for %s.a in %s\n", name, pname) 468 } 469 if _, err := os.Stat(pname); err == nil { 470 return addlibpath(ctxt, "internal", "internal", pname, name, "", zerofp) 471 } 472 } 473 474 if name == "runtime" { 475 Exitf("error: unable to find runtime.a") 476 } 477 ctxt.Logf("warning: unable to find %s.a\n", name) 478 return nil 479 } 480 481 // extld returns the current external linker. 482 func (ctxt *Link) extld() []string { 483 if len(flagExtld) == 0 { 484 // Return the default external linker for the platform. 485 // This only matters when link tool is called directly without explicit -extld, 486 // go tool already passes the correct linker in other cases. 487 switch buildcfg.GOOS { 488 case "darwin", "freebsd", "openbsd": 489 flagExtld = []string{"clang"} 490 default: 491 flagExtld = []string{"gcc"} 492 } 493 } 494 return flagExtld 495 } 496 497 // findLibPathCmd uses cmd command to find gcc library libname. 498 // It returns library full path if found, or "none" if not found. 499 func (ctxt *Link) findLibPathCmd(cmd, libname string) string { 500 extld := ctxt.extld() 501 name, args := extld[0], extld[1:] 502 args = append(args, hostlinkArchArgs(ctxt.Arch)...) 503 args = append(args, cmd) 504 if ctxt.Debugvlog != 0 { 505 ctxt.Logf("%s %v\n", extld, args) 506 } 507 out, err := exec.Command(name, args...).Output() 508 if err != nil { 509 if ctxt.Debugvlog != 0 { 510 ctxt.Logf("not using a %s file because compiler failed\n%v\n%s\n", libname, err, out) 511 } 512 return "none" 513 } 514 return strings.TrimSpace(string(out)) 515 } 516 517 // findLibPath searches for library libname. 518 // It returns library full path if found, or "none" if not found. 519 func (ctxt *Link) findLibPath(libname string) string { 520 return ctxt.findLibPathCmd("--print-file-name="+libname, libname) 521 } 522 523 func (ctxt *Link) loadlib() { 524 var flags uint32 525 switch *FlagStrictDups { 526 case 0: 527 // nothing to do 528 case 1, 2: 529 flags |= loader.FlagStrictDups 530 default: 531 log.Fatalf("invalid -strictdups flag value %d", *FlagStrictDups) 532 } 533 ctxt.loader = loader.NewLoader(flags, &ctxt.ErrorReporter.ErrorReporter) 534 ctxt.ErrorReporter.SymName = func(s loader.Sym) string { 535 return ctxt.loader.SymName(s) 536 } 537 538 // ctxt.Library grows during the loop, so not a range loop. 539 i := 0 540 for ; i < len(ctxt.Library); i++ { 541 lib := ctxt.Library[i] 542 if lib.Shlib == "" { 543 if ctxt.Debugvlog > 1 { 544 ctxt.Logf("autolib: %s (from %s)\n", lib.File, lib.Objref) 545 } 546 loadobjfile(ctxt, lib) 547 } 548 } 549 550 // load internal packages, if not already 551 if *flagRace { 552 loadinternal(ctxt, "runtime/race") 553 } 554 if *flagMsan { 555 loadinternal(ctxt, "runtime/msan") 556 } 557 if *flagAsan { 558 loadinternal(ctxt, "runtime/asan") 559 } 560 loadinternal(ctxt, "runtime") 561 for ; i < len(ctxt.Library); i++ { 562 lib := ctxt.Library[i] 563 if lib.Shlib == "" { 564 loadobjfile(ctxt, lib) 565 } 566 } 567 // At this point, the Go objects are "preloaded". Not all the symbols are 568 // added to the symbol table (only defined package symbols are). Looking 569 // up symbol by name may not get expected result. 570 571 iscgo = ctxt.LibraryByPkg["runtime/cgo"] != nil 572 573 // Plugins a require cgo support to function. Similarly, plugins may require additional 574 // internal linker support on some platforms which may not be implemented. 575 ctxt.canUsePlugins = ctxt.LibraryByPkg["plugin"] != nil && iscgo 576 577 // We now have enough information to determine the link mode. 578 determineLinkMode(ctxt) 579 580 if ctxt.LinkMode == LinkExternal && !iscgo && !(buildcfg.GOOS == "darwin" && ctxt.BuildMode != BuildModePlugin && ctxt.Arch.Family == sys.AMD64) { 581 // This indicates a user requested -linkmode=external. 582 // The startup code uses an import of runtime/cgo to decide 583 // whether to initialize the TLS. So give it one. This could 584 // be handled differently but it's an unusual case. 585 if lib := loadinternal(ctxt, "runtime/cgo"); lib != nil && lib.Shlib == "" { 586 if ctxt.BuildMode == BuildModeShared || ctxt.linkShared { 587 Exitf("cannot implicitly include runtime/cgo in a shared library") 588 } 589 for ; i < len(ctxt.Library); i++ { 590 lib := ctxt.Library[i] 591 if lib.Shlib == "" { 592 loadobjfile(ctxt, lib) 593 } 594 } 595 } 596 } 597 598 // Add non-package symbols and references of externally defined symbols. 599 ctxt.loader.LoadSyms(ctxt.Arch) 600 601 // Load symbols from shared libraries, after all Go object symbols are loaded. 602 for _, lib := range ctxt.Library { 603 if lib.Shlib != "" { 604 if ctxt.Debugvlog > 1 { 605 ctxt.Logf("autolib: %s (from %s)\n", lib.Shlib, lib.Objref) 606 } 607 ldshlibsyms(ctxt, lib.Shlib) 608 } 609 } 610 611 // Process cgo directives (has to be done before host object loading). 612 ctxt.loadcgodirectives() 613 614 // Conditionally load host objects, or setup for external linking. 615 hostobjs(ctxt) 616 hostlinksetup(ctxt) 617 618 if ctxt.LinkMode == LinkInternal && len(hostobj) != 0 { 619 // If we have any undefined symbols in external 620 // objects, try to read them from the libgcc file. 621 any := false 622 undefs, froms := ctxt.loader.UndefinedRelocTargets(1) 623 if len(undefs) > 0 { 624 any = true 625 if ctxt.Debugvlog > 1 { 626 ctxt.Logf("loadlib: first unresolved is %s [%d] from %s [%d]\n", 627 ctxt.loader.SymName(undefs[0]), undefs[0], 628 ctxt.loader.SymName(froms[0]), froms[0]) 629 } 630 } 631 if any { 632 if *flagLibGCC == "" { 633 *flagLibGCC = ctxt.findLibPathCmd("--print-libgcc-file-name", "libgcc") 634 } 635 if runtime.GOOS == "openbsd" && *flagLibGCC == "libgcc.a" { 636 // On OpenBSD `clang --print-libgcc-file-name` returns "libgcc.a". 637 // In this case we fail to load libgcc.a and can encounter link 638 // errors - see if we can find libcompiler_rt.a instead. 639 *flagLibGCC = ctxt.findLibPathCmd("--print-file-name=libcompiler_rt.a", "libcompiler_rt") 640 } 641 if ctxt.HeadType == objabi.Hwindows { 642 loadWindowsHostArchives(ctxt) 643 } 644 if *flagLibGCC != "none" { 645 hostArchive(ctxt, *flagLibGCC) 646 } 647 // For glibc systems, the linker setup used by GCC 648 // looks like 649 // 650 // GROUP ( /lib/x86_64-linux-gnu/libc.so.6 651 // /usr/lib/x86_64-linux-gnu/libc_nonshared.a 652 // AS_NEEDED ( /lib64/ld-linux-x86-64.so.2 ) ) 653 // 654 // where libc_nonshared.a contains a small set of 655 // symbols including "__stack_chk_fail_local" and a 656 // few others. Thus if we are doing internal linking 657 // and "__stack_chk_fail_local" is unresolved (most 658 // likely due to the use of -fstack-protector), try 659 // loading libc_nonshared.a to resolve it. 660 // 661 // On Alpine Linux (musl-based), the library providing 662 // this symbol is called libssp_nonshared.a. 663 isunresolved := symbolsAreUnresolved(ctxt, []string{"__stack_chk_fail_local"}) 664 if isunresolved[0] { 665 if p := ctxt.findLibPath("libc_nonshared.a"); p != "none" { 666 hostArchive(ctxt, p) 667 } 668 if p := ctxt.findLibPath("libssp_nonshared.a"); p != "none" { 669 hostArchive(ctxt, p) 670 } 671 } 672 } 673 } 674 675 // We've loaded all the code now. 676 ctxt.Loaded = true 677 678 strictDupMsgCount = ctxt.loader.NStrictDupMsgs() 679 } 680 681 // loadWindowsHostArchives loads in host archives and objects when 682 // doing internal linking on windows. Older toolchains seem to require 683 // just a single pass through the various archives, but some modern 684 // toolchains when linking a C program with mingw pass library paths 685 // multiple times to the linker, e.g. "... -lmingwex -lmingw32 ... 686 // -lmingwex -lmingw32 ...". To accommodate this behavior, we make two 687 // passes over the host archives below. 688 func loadWindowsHostArchives(ctxt *Link) { 689 any := true 690 for i := 0; any && i < 2; i++ { 691 // Link crt2.o (if present) to resolve "atexit" when 692 // using LLVM-based compilers. 693 isunresolved := symbolsAreUnresolved(ctxt, []string{"atexit"}) 694 if isunresolved[0] { 695 if p := ctxt.findLibPath("crt2.o"); p != "none" { 696 hostObject(ctxt, "crt2", p) 697 } 698 } 699 if *flagRace { 700 if p := ctxt.findLibPath("libsynchronization.a"); p != "none" { 701 hostArchive(ctxt, p) 702 } 703 } 704 if p := ctxt.findLibPath("libmingwex.a"); p != "none" { 705 hostArchive(ctxt, p) 706 } 707 if p := ctxt.findLibPath("libmingw32.a"); p != "none" { 708 hostArchive(ctxt, p) 709 } 710 // Link libmsvcrt.a to resolve '__acrt_iob_func' symbol 711 // (see https://golang.org/issue/23649 for details). 712 if p := ctxt.findLibPath("libmsvcrt.a"); p != "none" { 713 hostArchive(ctxt, p) 714 } 715 any = false 716 undefs, froms := ctxt.loader.UndefinedRelocTargets(1) 717 if len(undefs) > 0 { 718 any = true 719 if ctxt.Debugvlog > 1 { 720 ctxt.Logf("loadWindowsHostArchives: remaining unresolved is %s [%d] from %s [%d]\n", 721 ctxt.loader.SymName(undefs[0]), undefs[0], 722 ctxt.loader.SymName(froms[0]), froms[0]) 723 } 724 } 725 } 726 // If needed, create the __CTOR_LIST__ and __DTOR_LIST__ 727 // symbols (referenced by some of the mingw support library 728 // routines). Creation of these symbols is normally done by the 729 // linker if not already present. 730 want := []string{"__CTOR_LIST__", "__DTOR_LIST__"} 731 isunresolved := symbolsAreUnresolved(ctxt, want) 732 for k, w := range want { 733 if isunresolved[k] { 734 sb := ctxt.loader.CreateSymForUpdate(w, 0) 735 sb.SetType(sym.SDATA) 736 sb.AddUint64(ctxt.Arch, 0) 737 sb.SetReachable(true) 738 ctxt.loader.SetAttrSpecial(sb.Sym(), true) 739 } 740 } 741 742 // Fix up references to DLL import symbols now that we're done 743 // pulling in new objects. 744 if err := loadpe.PostProcessImports(); err != nil { 745 Errorf(nil, "%v", err) 746 } 747 748 // TODO: maybe do something similar to peimporteddlls to collect 749 // all lib names and try link them all to final exe just like 750 // libmingwex.a and libmingw32.a: 751 /* 752 for: 753 #cgo windows LDFLAGS: -lmsvcrt -lm 754 import: 755 libmsvcrt.a libm.a 756 */ 757 } 758 759 // loadcgodirectives reads the previously discovered cgo directives, creating 760 // symbols in preparation for host object loading or use later in the link. 761 func (ctxt *Link) loadcgodirectives() { 762 l := ctxt.loader 763 hostObjSyms := make(map[loader.Sym]struct{}) 764 for _, d := range ctxt.cgodata { 765 setCgoAttr(ctxt, d.file, d.pkg, d.directives, hostObjSyms) 766 } 767 ctxt.cgodata = nil 768 769 if ctxt.LinkMode == LinkInternal { 770 // Drop all the cgo_import_static declarations. 771 // Turns out we won't be needing them. 772 for symIdx := range hostObjSyms { 773 if l.SymType(symIdx) == sym.SHOSTOBJ { 774 // If a symbol was marked both 775 // cgo_import_static and cgo_import_dynamic, 776 // then we want to make it cgo_import_dynamic 777 // now. 778 su := l.MakeSymbolUpdater(symIdx) 779 if l.SymExtname(symIdx) != "" && l.SymDynimplib(symIdx) != "" && !(l.AttrCgoExportStatic(symIdx) || l.AttrCgoExportDynamic(symIdx)) { 780 su.SetType(sym.SDYNIMPORT) 781 } else { 782 su.SetType(0) 783 } 784 } 785 } 786 } 787 } 788 789 // Set up flags and special symbols depending on the platform build mode. 790 // This version works with loader.Loader. 791 func (ctxt *Link) linksetup() { 792 switch ctxt.BuildMode { 793 case BuildModeCShared, BuildModePlugin: 794 symIdx := ctxt.loader.LookupOrCreateSym("runtime.islibrary", 0) 795 sb := ctxt.loader.MakeSymbolUpdater(symIdx) 796 sb.SetType(sym.SNOPTRDATA) 797 sb.AddUint8(1) 798 case BuildModeCArchive: 799 symIdx := ctxt.loader.LookupOrCreateSym("runtime.isarchive", 0) 800 sb := ctxt.loader.MakeSymbolUpdater(symIdx) 801 sb.SetType(sym.SNOPTRDATA) 802 sb.AddUint8(1) 803 } 804 805 // Recalculate pe parameters now that we have ctxt.LinkMode set. 806 if ctxt.HeadType == objabi.Hwindows { 807 Peinit(ctxt) 808 } 809 810 if ctxt.LinkMode == LinkExternal { 811 // When external linking, we are creating an object file. The 812 // absolute address is irrelevant. 813 *FlagTextAddr = 0 814 } 815 816 // If there are no dynamic libraries needed, gcc disables dynamic linking. 817 // Because of this, glibc's dynamic ELF loader occasionally (like in version 2.13) 818 // assumes that a dynamic binary always refers to at least one dynamic library. 819 // Rather than be a source of test cases for glibc, disable dynamic linking 820 // the same way that gcc would. 821 // 822 // Exception: on OS X, programs such as Shark only work with dynamic 823 // binaries, so leave it enabled on OS X (Mach-O) binaries. 824 // Also leave it enabled on Solaris which doesn't support 825 // statically linked binaries. 826 if ctxt.BuildMode == BuildModeExe { 827 if havedynamic == 0 && ctxt.HeadType != objabi.Hdarwin && ctxt.HeadType != objabi.Hsolaris { 828 *FlagD = true 829 } 830 } 831 832 if ctxt.LinkMode == LinkExternal && ctxt.Arch.Family == sys.PPC64 && buildcfg.GOOS != "aix" { 833 toc := ctxt.loader.LookupOrCreateSym(".TOC.", 0) 834 sb := ctxt.loader.MakeSymbolUpdater(toc) 835 sb.SetType(sym.SDYNIMPORT) 836 } 837 838 // The Android Q linker started to complain about underalignment of the our TLS 839 // section. We don't actually use the section on android, so don't 840 // generate it. 841 if buildcfg.GOOS != "android" { 842 tlsg := ctxt.loader.LookupOrCreateSym("runtime.tlsg", 0) 843 sb := ctxt.loader.MakeSymbolUpdater(tlsg) 844 845 // runtime.tlsg is used for external linking on platforms that do not define 846 // a variable to hold g in assembly (currently only intel). 847 if sb.Type() == 0 { 848 sb.SetType(sym.STLSBSS) 849 sb.SetSize(int64(ctxt.Arch.PtrSize)) 850 } else if sb.Type() != sym.SDYNIMPORT { 851 Errorf(nil, "runtime declared tlsg variable %v", sb.Type()) 852 } 853 ctxt.loader.SetAttrReachable(tlsg, true) 854 ctxt.Tlsg = tlsg 855 } 856 857 var moduledata loader.Sym 858 var mdsb *loader.SymbolBuilder 859 if ctxt.BuildMode == BuildModePlugin { 860 moduledata = ctxt.loader.LookupOrCreateSym("local.pluginmoduledata", 0) 861 mdsb = ctxt.loader.MakeSymbolUpdater(moduledata) 862 ctxt.loader.SetAttrLocal(moduledata, true) 863 } else { 864 moduledata = ctxt.loader.LookupOrCreateSym("runtime.firstmoduledata", 0) 865 mdsb = ctxt.loader.MakeSymbolUpdater(moduledata) 866 } 867 if mdsb.Type() != 0 && mdsb.Type() != sym.SDYNIMPORT { 868 // If the module (toolchain-speak for "executable or shared 869 // library") we are linking contains the runtime package, it 870 // will define the runtime.firstmoduledata symbol and we 871 // truncate it back to 0 bytes so we can define its entire 872 // contents in symtab.go:symtab(). 873 mdsb.SetSize(0) 874 875 // In addition, on ARM, the runtime depends on the linker 876 // recording the value of GOARM. 877 if ctxt.Arch.Family == sys.ARM { 878 goarm := ctxt.loader.LookupOrCreateSym("runtime.goarm", 0) 879 sb := ctxt.loader.MakeSymbolUpdater(goarm) 880 sb.SetType(sym.SDATA) 881 sb.SetSize(0) 882 sb.AddUint8(uint8(buildcfg.GOARM.Version)) 883 884 goarmsoftfp := ctxt.loader.LookupOrCreateSym("runtime.goarmsoftfp", 0) 885 sb2 := ctxt.loader.MakeSymbolUpdater(goarmsoftfp) 886 sb2.SetType(sym.SDATA) 887 sb2.SetSize(0) 888 if buildcfg.GOARM.SoftFloat { 889 sb2.AddUint8(1) 890 } else { 891 sb2.AddUint8(0) 892 } 893 } 894 895 // Set runtime.disableMemoryProfiling bool if 896 // runtime.MemProfile is not retained in the binary after 897 // deadcode (and we're not dynamically linking). 898 memProfile := ctxt.loader.Lookup("runtime.MemProfile", abiInternalVer) 899 if memProfile != 0 && !ctxt.loader.AttrReachable(memProfile) && !ctxt.DynlinkingGo() { 900 memProfSym := ctxt.loader.LookupOrCreateSym("runtime.disableMemoryProfiling", 0) 901 sb := ctxt.loader.MakeSymbolUpdater(memProfSym) 902 sb.SetType(sym.SDATA) 903 sb.SetSize(0) 904 sb.AddUint8(1) // true bool 905 } 906 } else { 907 // If OTOH the module does not contain the runtime package, 908 // create a local symbol for the moduledata. 909 moduledata = ctxt.loader.LookupOrCreateSym("local.moduledata", 0) 910 mdsb = ctxt.loader.MakeSymbolUpdater(moduledata) 911 ctxt.loader.SetAttrLocal(moduledata, true) 912 } 913 // In all cases way we mark the moduledata as noptrdata to hide it from 914 // the GC. 915 mdsb.SetType(sym.SNOPTRDATA) 916 ctxt.loader.SetAttrReachable(moduledata, true) 917 ctxt.Moduledata = moduledata 918 919 if ctxt.Arch == sys.Arch386 && ctxt.HeadType != objabi.Hwindows { 920 if (ctxt.BuildMode == BuildModeCArchive && ctxt.IsELF) || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE || ctxt.DynlinkingGo() { 921 got := ctxt.loader.LookupOrCreateSym("_GLOBAL_OFFSET_TABLE_", 0) 922 sb := ctxt.loader.MakeSymbolUpdater(got) 923 sb.SetType(sym.SDYNIMPORT) 924 ctxt.loader.SetAttrReachable(got, true) 925 } 926 } 927 928 // DWARF-gen and other phases require that the unit Textp slices 929 // be populated, so that it can walk the functions in each unit. 930 // Call into the loader to do this (requires that we collect the 931 // set of internal libraries first). NB: might be simpler if we 932 // moved isRuntimeDepPkg to cmd/internal and then did the test in 933 // loader.AssignTextSymbolOrder. 934 ctxt.Library = postorder(ctxt.Library) 935 intlibs := []bool{} 936 for _, lib := range ctxt.Library { 937 intlibs = append(intlibs, isRuntimeDepPkg(lib.Pkg)) 938 } 939 ctxt.Textp = ctxt.loader.AssignTextSymbolOrder(ctxt.Library, intlibs, ctxt.Textp) 940 } 941 942 // mangleTypeSym shortens the names of symbols that represent Go types 943 // if they are visible in the symbol table. 944 // 945 // As the names of these symbols are derived from the string of 946 // the type, they can run to many kilobytes long. So we shorten 947 // them using a SHA-1 when the name appears in the final binary. 948 // This also removes characters that upset external linkers. 949 // 950 // These are the symbols that begin with the prefix 'type.' and 951 // contain run-time type information used by the runtime and reflect 952 // packages. All Go binaries contain these symbols, but only 953 // those programs loaded dynamically in multiple parts need these 954 // symbols to have entries in the symbol table. 955 func (ctxt *Link) mangleTypeSym() { 956 if ctxt.BuildMode != BuildModeShared && !ctxt.linkShared && ctxt.BuildMode != BuildModePlugin && !ctxt.CanUsePlugins() { 957 return 958 } 959 960 ldr := ctxt.loader 961 for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ { 962 if !ldr.AttrReachable(s) && !ctxt.linkShared { 963 // If -linkshared, the GCProg generation code may need to reach 964 // out to the shared library for the type descriptor's data, even 965 // the type descriptor itself is not actually needed at run time 966 // (therefore not reachable). We still need to mangle its name, 967 // so it is consistent with the one stored in the shared library. 968 continue 969 } 970 name := ldr.SymName(s) 971 newName := typeSymbolMangle(name) 972 if newName != name { 973 ldr.SetSymExtname(s, newName) 974 975 // When linking against a shared library, the Go object file may 976 // have reference to the original symbol name whereas the shared 977 // library provides a symbol with the mangled name. We need to 978 // copy the payload of mangled to original. 979 // XXX maybe there is a better way to do this. 980 dup := ldr.Lookup(newName, ldr.SymVersion(s)) 981 if dup != 0 { 982 st := ldr.SymType(s) 983 dt := ldr.SymType(dup) 984 if st == sym.Sxxx && dt != sym.Sxxx { 985 ldr.CopySym(dup, s) 986 } 987 } 988 } 989 } 990 } 991 992 // typeSymbolMangle mangles the given symbol name into something shorter. 993 // 994 // Keep the type:. prefix, which parts of the linker (like the 995 // DWARF generator) know means the symbol is not decodable. 996 // Leave type:runtime. symbols alone, because other parts of 997 // the linker manipulates them. 998 func typeSymbolMangle(name string) string { 999 isType := strings.HasPrefix(name, "type:") 1000 if !isType && !strings.Contains(name, "@") { 1001 // Issue 58800: instantiated symbols may include a type name, which may contain "@" 1002 return name 1003 } 1004 if strings.HasPrefix(name, "type:runtime.") { 1005 return name 1006 } 1007 if strings.HasPrefix(name, "go:string.") { 1008 // String symbols will be grouped to a single go:string.* symbol. 1009 // No need to mangle individual symbol names. 1010 return name 1011 } 1012 if len(name) <= 14 && !strings.Contains(name, "@") { // Issue 19529 1013 return name 1014 } 1015 if isType { 1016 hash := notsha256.Sum256([]byte(name[5:])) 1017 prefix := "type:" 1018 if name[5] == '.' { 1019 prefix = "type:." 1020 } 1021 return prefix + base64.StdEncoding.EncodeToString(hash[:6]) 1022 } 1023 // instantiated symbol, replace type name in [] 1024 i := strings.IndexByte(name, '[') 1025 j := strings.LastIndexByte(name, ']') 1026 if j == -1 || j <= i { 1027 j = len(name) 1028 } 1029 hash := notsha256.Sum256([]byte(name[i+1 : j])) 1030 return name[:i+1] + base64.StdEncoding.EncodeToString(hash[:6]) + name[j:] 1031 } 1032 1033 /* 1034 * look for the next file in an archive. 1035 * adapted from libmach. 1036 */ 1037 func nextar(bp *bio.Reader, off int64, a *ArHdr) int64 { 1038 if off&1 != 0 { 1039 off++ 1040 } 1041 bp.MustSeek(off, 0) 1042 var buf [SAR_HDR]byte 1043 if n, err := io.ReadFull(bp, buf[:]); err != nil { 1044 if n == 0 && err != io.EOF { 1045 return -1 1046 } 1047 return 0 1048 } 1049 1050 a.name = artrim(buf[0:16]) 1051 a.date = artrim(buf[16:28]) 1052 a.uid = artrim(buf[28:34]) 1053 a.gid = artrim(buf[34:40]) 1054 a.mode = artrim(buf[40:48]) 1055 a.size = artrim(buf[48:58]) 1056 a.fmag = artrim(buf[58:60]) 1057 1058 arsize := atolwhex(a.size) 1059 if arsize&1 != 0 { 1060 arsize++ 1061 } 1062 return arsize + SAR_HDR 1063 } 1064 1065 func loadobjfile(ctxt *Link, lib *sym.Library) { 1066 pkg := objabi.PathToPrefix(lib.Pkg) 1067 1068 if ctxt.Debugvlog > 1 { 1069 ctxt.Logf("ldobj: %s (%s)\n", lib.File, pkg) 1070 } 1071 f, err := bio.Open(lib.File) 1072 if err != nil { 1073 Exitf("cannot open file %s: %v", lib.File, err) 1074 } 1075 defer f.Close() 1076 defer func() { 1077 if pkg == "main" && !lib.Main { 1078 Exitf("%s: not package main", lib.File) 1079 } 1080 }() 1081 1082 for i := 0; i < len(ARMAG); i++ { 1083 if c, err := f.ReadByte(); err == nil && c == ARMAG[i] { 1084 continue 1085 } 1086 1087 /* load it as a regular file */ 1088 l := f.MustSeek(0, 2) 1089 f.MustSeek(0, 0) 1090 ldobj(ctxt, f, lib, l, lib.File, lib.File) 1091 return 1092 } 1093 1094 /* 1095 * load all the object files from the archive now. 1096 * this gives us sequential file access and keeps us 1097 * from needing to come back later to pick up more 1098 * objects. it breaks the usual C archive model, but 1099 * this is Go, not C. the common case in Go is that 1100 * we need to load all the objects, and then we throw away 1101 * the individual symbols that are unused. 1102 * 1103 * loading every object will also make it possible to 1104 * load foreign objects not referenced by __.PKGDEF. 1105 */ 1106 var arhdr ArHdr 1107 off := f.Offset() 1108 for { 1109 l := nextar(f, off, &arhdr) 1110 if l == 0 { 1111 break 1112 } 1113 if l < 0 { 1114 Exitf("%s: malformed archive", lib.File) 1115 } 1116 off += l 1117 1118 // __.PKGDEF isn't a real Go object file, and it's 1119 // absent in -linkobj builds anyway. Skipping it 1120 // ensures consistency between -linkobj and normal 1121 // build modes. 1122 if arhdr.name == pkgdef { 1123 continue 1124 } 1125 1126 if arhdr.name == "dynimportfail" { 1127 dynimportfail = append(dynimportfail, lib.Pkg) 1128 } 1129 if arhdr.name == "preferlinkext" { 1130 // Ignore this directive if -linkmode has been 1131 // set explicitly. 1132 if ctxt.LinkMode == LinkAuto { 1133 preferlinkext = append(preferlinkext, lib.Pkg) 1134 } 1135 } 1136 1137 // Skip other special (non-object-file) sections that 1138 // build tools may have added. Such sections must have 1139 // short names so that the suffix is not truncated. 1140 if len(arhdr.name) < 16 { 1141 if ext := filepath.Ext(arhdr.name); ext != ".o" && ext != ".syso" { 1142 continue 1143 } 1144 } 1145 1146 pname := fmt.Sprintf("%s(%s)", lib.File, arhdr.name) 1147 l = atolwhex(arhdr.size) 1148 ldobj(ctxt, f, lib, l, pname, lib.File) 1149 } 1150 } 1151 1152 type Hostobj struct { 1153 ld func(*Link, *bio.Reader, string, int64, string) 1154 pkg string 1155 pn string 1156 file string 1157 off int64 1158 length int64 1159 } 1160 1161 var hostobj []Hostobj 1162 1163 // These packages can use internal linking mode. 1164 // Others trigger external mode. 1165 var internalpkg = []string{ 1166 "crypto/internal/boring", 1167 "crypto/internal/boring/syso", 1168 "crypto/x509", 1169 "net", 1170 "os/user", 1171 "runtime/cgo", 1172 "runtime/race", 1173 "runtime/race/internal/amd64v1", 1174 "runtime/race/internal/amd64v3", 1175 "runtime/msan", 1176 "runtime/asan", 1177 } 1178 1179 func ldhostobj(ld func(*Link, *bio.Reader, string, int64, string), headType objabi.HeadType, f *bio.Reader, pkg string, length int64, pn string, file string) *Hostobj { 1180 isinternal := false 1181 for _, intpkg := range internalpkg { 1182 if pkg == intpkg { 1183 isinternal = true 1184 break 1185 } 1186 } 1187 1188 // DragonFly declares errno with __thread, which results in a symbol 1189 // type of R_386_TLS_GD or R_X86_64_TLSGD. The Go linker does not 1190 // currently know how to handle TLS relocations, hence we have to 1191 // force external linking for any libraries that link in code that 1192 // uses errno. This can be removed if the Go linker ever supports 1193 // these relocation types. 1194 if headType == objabi.Hdragonfly { 1195 if pkg == "net" || pkg == "os/user" { 1196 isinternal = false 1197 } 1198 } 1199 1200 if !isinternal { 1201 externalobj = true 1202 } 1203 1204 hostobj = append(hostobj, Hostobj{}) 1205 h := &hostobj[len(hostobj)-1] 1206 h.ld = ld 1207 h.pkg = pkg 1208 h.pn = pn 1209 h.file = file 1210 h.off = f.Offset() 1211 h.length = length 1212 return h 1213 } 1214 1215 func hostobjs(ctxt *Link) { 1216 if ctxt.LinkMode != LinkInternal { 1217 return 1218 } 1219 var h *Hostobj 1220 1221 for i := 0; i < len(hostobj); i++ { 1222 h = &hostobj[i] 1223 f, err := bio.Open(h.file) 1224 if err != nil { 1225 Exitf("cannot reopen %s: %v", h.pn, err) 1226 } 1227 f.MustSeek(h.off, 0) 1228 if h.ld == nil { 1229 Errorf(nil, "%s: unrecognized object file format", h.pn) 1230 continue 1231 } 1232 h.ld(ctxt, f, h.pkg, h.length, h.pn) 1233 if *flagCaptureHostObjs != "" { 1234 captureHostObj(h) 1235 } 1236 f.Close() 1237 } 1238 } 1239 1240 func hostlinksetup(ctxt *Link) { 1241 if ctxt.LinkMode != LinkExternal { 1242 return 1243 } 1244 1245 // For external link, record that we need to tell the external linker -s, 1246 // and turn off -s internally: the external linker needs the symbol 1247 // information for its final link. 1248 debug_s = *FlagS 1249 *FlagS = false 1250 1251 // create temporary directory and arrange cleanup 1252 if *flagTmpdir == "" { 1253 dir, err := os.MkdirTemp("", "go-link-") 1254 if err != nil { 1255 log.Fatal(err) 1256 } 1257 *flagTmpdir = dir 1258 ownTmpDir = true 1259 AtExit(func() { 1260 os.RemoveAll(*flagTmpdir) 1261 }) 1262 } 1263 1264 // change our output to temporary object file 1265 if err := ctxt.Out.Close(); err != nil { 1266 Exitf("error closing output file") 1267 } 1268 mayberemoveoutfile() 1269 1270 p := filepath.Join(*flagTmpdir, "go.o") 1271 if err := ctxt.Out.Open(p); err != nil { 1272 Exitf("cannot create %s: %v", p, err) 1273 } 1274 } 1275 1276 // hostobjCopy creates a copy of the object files in hostobj in a 1277 // temporary directory. 1278 func (ctxt *Link) hostobjCopy() (paths []string) { 1279 var wg sync.WaitGroup 1280 sema := make(chan struct{}, runtime.NumCPU()) // limit open file descriptors 1281 for i, h := range hostobj { 1282 h := h 1283 dst := filepath.Join(*flagTmpdir, fmt.Sprintf("%06d.o", i)) 1284 paths = append(paths, dst) 1285 if ctxt.Debugvlog != 0 { 1286 ctxt.Logf("host obj copy: %s from pkg %s -> %s\n", h.pn, h.pkg, dst) 1287 } 1288 1289 wg.Add(1) 1290 go func() { 1291 sema <- struct{}{} 1292 defer func() { 1293 <-sema 1294 wg.Done() 1295 }() 1296 f, err := os.Open(h.file) 1297 if err != nil { 1298 Exitf("cannot reopen %s: %v", h.pn, err) 1299 } 1300 defer f.Close() 1301 if _, err := f.Seek(h.off, 0); err != nil { 1302 Exitf("cannot seek %s: %v", h.pn, err) 1303 } 1304 1305 w, err := os.Create(dst) 1306 if err != nil { 1307 Exitf("cannot create %s: %v", dst, err) 1308 } 1309 if _, err := io.CopyN(w, f, h.length); err != nil { 1310 Exitf("cannot write %s: %v", dst, err) 1311 } 1312 if err := w.Close(); err != nil { 1313 Exitf("cannot close %s: %v", dst, err) 1314 } 1315 }() 1316 } 1317 wg.Wait() 1318 return paths 1319 } 1320 1321 // writeGDBLinkerScript creates gcc linker script file in temp 1322 // directory. writeGDBLinkerScript returns created file path. 1323 // The script is used to work around gcc bug 1324 // (see https://golang.org/issue/20183 for details). 1325 func writeGDBLinkerScript() string { 1326 name := "fix_debug_gdb_scripts.ld" 1327 path := filepath.Join(*flagTmpdir, name) 1328 src := `SECTIONS 1329 { 1330 .debug_gdb_scripts BLOCK(__section_alignment__) (NOLOAD) : 1331 { 1332 *(.debug_gdb_scripts) 1333 } 1334 } 1335 INSERT AFTER .debug_types; 1336 ` 1337 err := os.WriteFile(path, []byte(src), 0666) 1338 if err != nil { 1339 Errorf(nil, "WriteFile %s failed: %v", name, err) 1340 } 1341 return path 1342 } 1343 1344 // archive builds a .a archive from the hostobj object files. 1345 func (ctxt *Link) archive() { 1346 if ctxt.BuildMode != BuildModeCArchive { 1347 return 1348 } 1349 1350 exitIfErrors() 1351 1352 if *flagExtar == "" { 1353 *flagExtar = "ar" 1354 } 1355 1356 mayberemoveoutfile() 1357 1358 // Force the buffer to flush here so that external 1359 // tools will see a complete file. 1360 if err := ctxt.Out.Close(); err != nil { 1361 Exitf("error closing %v", *flagOutfile) 1362 } 1363 1364 argv := []string{*flagExtar, "-q", "-c", "-s"} 1365 if ctxt.HeadType == objabi.Haix { 1366 argv = append(argv, "-X64") 1367 } 1368 argv = append(argv, *flagOutfile) 1369 argv = append(argv, filepath.Join(*flagTmpdir, "go.o")) 1370 argv = append(argv, ctxt.hostobjCopy()...) 1371 1372 if ctxt.Debugvlog != 0 { 1373 ctxt.Logf("archive: %s\n", strings.Join(argv, " ")) 1374 } 1375 1376 // If supported, use syscall.Exec() to invoke the archive command, 1377 // which should be the final remaining step needed for the link. 1378 // This will reduce peak RSS for the link (and speed up linking of 1379 // large applications), since when the archive command runs we 1380 // won't be holding onto all of the linker's live memory. 1381 if syscallExecSupported && !ownTmpDir { 1382 runAtExitFuncs() 1383 ctxt.execArchive(argv) 1384 panic("should not get here") 1385 } 1386 1387 // Otherwise invoke 'ar' in the usual way (fork + exec). 1388 if out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput(); err != nil { 1389 Exitf("running %s failed: %v\n%s", argv[0], err, out) 1390 } 1391 } 1392 1393 func (ctxt *Link) hostlink() { 1394 if ctxt.LinkMode != LinkExternal || nerrors > 0 { 1395 return 1396 } 1397 if ctxt.BuildMode == BuildModeCArchive { 1398 return 1399 } 1400 1401 var argv []string 1402 argv = append(argv, ctxt.extld()...) 1403 argv = append(argv, hostlinkArchArgs(ctxt.Arch)...) 1404 1405 if *FlagS || debug_s { 1406 if ctxt.HeadType == objabi.Hdarwin { 1407 // Recent versions of macOS print 1408 // ld: warning: option -s is obsolete and being ignored 1409 // so do not pass any arguments (but we strip symbols below). 1410 } else { 1411 argv = append(argv, "-s") 1412 } 1413 } 1414 1415 // On darwin, whether to combine DWARF into executable. 1416 // Only macOS supports unmapped segments such as our __DWARF segment. 1417 combineDwarf := ctxt.IsDarwin() && !*FlagW && machoPlatform == PLATFORM_MACOS 1418 1419 switch ctxt.HeadType { 1420 case objabi.Hdarwin: 1421 if combineDwarf { 1422 // Leave room for DWARF combining. 1423 // -headerpad is incompatible with -fembed-bitcode. 1424 argv = append(argv, "-Wl,-headerpad,1144") 1425 } 1426 if ctxt.DynlinkingGo() && buildcfg.GOOS != "ios" { 1427 // -flat_namespace is deprecated on iOS. 1428 // It is useful for supporting plugins. We don't support plugins on iOS. 1429 // -flat_namespace may cause the dynamic linker to hang at forkExec when 1430 // resolving a lazy binding. See issue 38824. 1431 // Force eager resolution to work around. 1432 argv = append(argv, "-Wl,-flat_namespace", "-Wl,-bind_at_load") 1433 } 1434 if !combineDwarf { 1435 argv = append(argv, "-Wl,-S") // suppress STAB (symbolic debugging) symbols 1436 if debug_s { 1437 // We are generating a binary with symbol table suppressed. 1438 // Suppress local symbols. We need to keep dynamically exported 1439 // and referenced symbols so the dynamic linker can resolve them. 1440 argv = append(argv, "-Wl,-x") 1441 } 1442 } 1443 case objabi.Hopenbsd: 1444 argv = append(argv, "-Wl,-nopie") 1445 argv = append(argv, "-pthread") 1446 if ctxt.Arch.InFamily(sys.ARM64) { 1447 // Disable execute-only on openbsd/arm64 - the Go arm64 assembler 1448 // currently stores constants in the text section rather than in rodata. 1449 // See issue #59615. 1450 argv = append(argv, "-Wl,--no-execute-only") 1451 } 1452 case objabi.Hwindows: 1453 if windowsgui { 1454 argv = append(argv, "-mwindows") 1455 } else { 1456 argv = append(argv, "-mconsole") 1457 } 1458 // Mark as having awareness of terminal services, to avoid 1459 // ancient compatibility hacks. 1460 argv = append(argv, "-Wl,--tsaware") 1461 1462 // Enable DEP 1463 argv = append(argv, "-Wl,--nxcompat") 1464 1465 argv = append(argv, fmt.Sprintf("-Wl,--major-os-version=%d", PeMinimumTargetMajorVersion)) 1466 argv = append(argv, fmt.Sprintf("-Wl,--minor-os-version=%d", PeMinimumTargetMinorVersion)) 1467 argv = append(argv, fmt.Sprintf("-Wl,--major-subsystem-version=%d", PeMinimumTargetMajorVersion)) 1468 argv = append(argv, fmt.Sprintf("-Wl,--minor-subsystem-version=%d", PeMinimumTargetMinorVersion)) 1469 case objabi.Haix: 1470 argv = append(argv, "-pthread") 1471 // prevent ld to reorder .text functions to keep the same 1472 // first/last functions for moduledata. 1473 argv = append(argv, "-Wl,-bnoobjreorder") 1474 // mcmodel=large is needed for every gcc generated files, but 1475 // ld still need -bbigtoc in order to allow larger TOC. 1476 argv = append(argv, "-mcmodel=large") 1477 argv = append(argv, "-Wl,-bbigtoc") 1478 } 1479 1480 // On PPC64, verify the external toolchain supports Power10. This is needed when 1481 // PC relative relocations might be generated by Go. Only targets compiling ELF 1482 // binaries might generate these relocations. 1483 if ctxt.IsPPC64() && ctxt.IsElf() && buildcfg.GOPPC64 >= 10 { 1484 if !linkerFlagSupported(ctxt.Arch, argv[0], "", "-mcpu=power10") { 1485 Exitf("The external toolchain does not support -mcpu=power10. " + 1486 " This is required to externally link GOPPC64 >= power10") 1487 } 1488 } 1489 1490 // Enable/disable ASLR on Windows. 1491 addASLRargs := func(argv []string, val bool) []string { 1492 // Old/ancient versions of GCC support "--dynamicbase" and 1493 // "--high-entropy-va" but don't enable it by default. In 1494 // addition, they don't accept "--disable-dynamicbase" or 1495 // "--no-dynamicbase", so the only way to disable ASLR is to 1496 // not pass any flags at all. 1497 // 1498 // More modern versions of GCC (and also clang) enable ASLR 1499 // by default. With these compilers, however you can turn it 1500 // off if you want using "--disable-dynamicbase" or 1501 // "--no-dynamicbase". 1502 // 1503 // The strategy below is to try using "--disable-dynamicbase"; 1504 // if this succeeds, then assume we're working with more 1505 // modern compilers and act accordingly. If it fails, assume 1506 // an ancient compiler with ancient defaults. 1507 var dbopt string 1508 var heopt string 1509 dbon := "--dynamicbase" 1510 heon := "--high-entropy-va" 1511 dboff := "--disable-dynamicbase" 1512 heoff := "--disable-high-entropy-va" 1513 if val { 1514 dbopt = dbon 1515 heopt = heon 1516 } else { 1517 // Test to see whether "--disable-dynamicbase" works. 1518 newer := linkerFlagSupported(ctxt.Arch, argv[0], "", "-Wl,"+dboff) 1519 if newer { 1520 // Newer compiler, which supports both on/off options. 1521 dbopt = dboff 1522 heopt = heoff 1523 } else { 1524 // older toolchain: we have to say nothing in order to 1525 // get a no-ASLR binary. 1526 dbopt = "" 1527 heopt = "" 1528 } 1529 } 1530 if dbopt != "" { 1531 argv = append(argv, "-Wl,"+dbopt) 1532 } 1533 // enable high-entropy ASLR on 64-bit. 1534 if ctxt.Arch.PtrSize >= 8 && heopt != "" { 1535 argv = append(argv, "-Wl,"+heopt) 1536 } 1537 return argv 1538 } 1539 1540 switch ctxt.BuildMode { 1541 case BuildModeExe: 1542 if ctxt.HeadType == objabi.Hdarwin { 1543 if machoPlatform == PLATFORM_MACOS && ctxt.IsAMD64() { 1544 argv = append(argv, "-Wl,-no_pie") 1545 } 1546 } 1547 if *flagRace && ctxt.HeadType == objabi.Hwindows { 1548 // Current windows/amd64 race detector tsan support 1549 // library can't handle PIE mode (see #53539 for more details). 1550 // For now, explicitly disable PIE (since some compilers 1551 // default to it) if -race is in effect. 1552 argv = addASLRargs(argv, false) 1553 } 1554 case BuildModePIE: 1555 switch ctxt.HeadType { 1556 case objabi.Hdarwin, objabi.Haix: 1557 case objabi.Hwindows: 1558 if *flagAslr && *flagRace { 1559 // Current windows/amd64 race detector tsan support 1560 // library can't handle PIE mode (see #53539 for more details). 1561 // Disable alsr if -race in effect. 1562 *flagAslr = false 1563 } 1564 argv = addASLRargs(argv, *flagAslr) 1565 default: 1566 // ELF. 1567 if ctxt.UseRelro() { 1568 argv = append(argv, "-Wl,-z,relro") 1569 } 1570 argv = append(argv, "-pie") 1571 } 1572 case BuildModeCShared: 1573 if ctxt.HeadType == objabi.Hdarwin { 1574 argv = append(argv, "-dynamiclib") 1575 } else { 1576 if ctxt.UseRelro() { 1577 argv = append(argv, "-Wl,-z,relro") 1578 } 1579 argv = append(argv, "-shared") 1580 if ctxt.HeadType == objabi.Hwindows { 1581 argv = addASLRargs(argv, *flagAslr) 1582 } else { 1583 // Pass -z nodelete to mark the shared library as 1584 // non-closeable: a dlclose will do nothing. 1585 argv = append(argv, "-Wl,-z,nodelete") 1586 // Only pass Bsymbolic on non-Windows. 1587 argv = append(argv, "-Wl,-Bsymbolic") 1588 } 1589 } 1590 case BuildModeShared: 1591 if ctxt.UseRelro() { 1592 argv = append(argv, "-Wl,-z,relro") 1593 } 1594 argv = append(argv, "-shared") 1595 case BuildModePlugin: 1596 if ctxt.HeadType == objabi.Hdarwin { 1597 argv = append(argv, "-dynamiclib") 1598 } else { 1599 if ctxt.UseRelro() { 1600 argv = append(argv, "-Wl,-z,relro") 1601 } 1602 argv = append(argv, "-shared") 1603 } 1604 } 1605 1606 var altLinker string 1607 if ctxt.IsELF && ctxt.DynlinkingGo() { 1608 // We force all symbol resolution to be done at program startup 1609 // because lazy PLT resolution can use large amounts of stack at 1610 // times we cannot allow it to do so. 1611 argv = append(argv, "-Wl,-z,now") 1612 1613 // Do not let the host linker generate COPY relocations. These 1614 // can move symbols out of sections that rely on stable offsets 1615 // from the beginning of the section (like sym.STYPE). 1616 argv = append(argv, "-Wl,-z,nocopyreloc") 1617 1618 if buildcfg.GOOS == "android" { 1619 // Use lld to avoid errors from default linker (issue #38838) 1620 altLinker = "lld" 1621 } 1622 1623 if ctxt.Arch.InFamily(sys.ARM64) && buildcfg.GOOS == "linux" { 1624 // On ARM64, the GNU linker will fail with 1625 // -znocopyreloc if it thinks a COPY relocation is 1626 // required. Switch to gold. 1627 // https://sourceware.org/bugzilla/show_bug.cgi?id=19962 1628 // https://go.dev/issue/22040 1629 altLinker = "gold" 1630 1631 // If gold is not installed, gcc will silently switch 1632 // back to ld.bfd. So we parse the version information 1633 // and provide a useful error if gold is missing. 1634 name, args := flagExtld[0], flagExtld[1:] 1635 args = append(args, "-fuse-ld=gold", "-Wl,--version") 1636 cmd := exec.Command(name, args...) 1637 if out, err := cmd.CombinedOutput(); err == nil { 1638 if !bytes.Contains(out, []byte("GNU gold")) { 1639 log.Fatalf("ARM64 external linker must be gold (issue #15696, 22040), but is not: %s", out) 1640 } 1641 } 1642 } 1643 } 1644 if ctxt.Arch.Family == sys.ARM64 && buildcfg.GOOS == "freebsd" { 1645 // Switch to ld.bfd on freebsd/arm64. 1646 altLinker = "bfd" 1647 1648 // Provide a useful error if ld.bfd is missing. 1649 name, args := flagExtld[0], flagExtld[1:] 1650 args = append(args, "-fuse-ld=bfd", "-Wl,--version") 1651 cmd := exec.Command(name, args...) 1652 if out, err := cmd.CombinedOutput(); err == nil { 1653 if !bytes.Contains(out, []byte("GNU ld")) { 1654 log.Fatalf("ARM64 external linker must be ld.bfd (issue #35197), please install devel/binutils") 1655 } 1656 } 1657 } 1658 if altLinker != "" { 1659 argv = append(argv, "-fuse-ld="+altLinker) 1660 } 1661 1662 if ctxt.IsELF && len(buildinfo) > 0 { 1663 argv = append(argv, fmt.Sprintf("-Wl,--build-id=0x%x", buildinfo)) 1664 } 1665 1666 // On Windows, given -o foo, GCC will append ".exe" to produce 1667 // "foo.exe". We have decided that we want to honor the -o 1668 // option. To make this work, we append a '.' so that GCC 1669 // will decide that the file already has an extension. We 1670 // only want to do this when producing a Windows output file 1671 // on a Windows host. 1672 outopt := *flagOutfile 1673 if buildcfg.GOOS == "windows" && runtime.GOOS == "windows" && filepath.Ext(outopt) == "" { 1674 outopt += "." 1675 } 1676 argv = append(argv, "-o") 1677 argv = append(argv, outopt) 1678 1679 if rpath.val != "" { 1680 argv = append(argv, fmt.Sprintf("-Wl,-rpath,%s", rpath.val)) 1681 } 1682 1683 if *flagInterpreter != "" { 1684 // Many linkers support both -I and the --dynamic-linker flags 1685 // to set the ELF interpreter, but lld only supports 1686 // --dynamic-linker so prefer that (ld on very old Solaris only 1687 // supports -I but that seems less important). 1688 argv = append(argv, fmt.Sprintf("-Wl,--dynamic-linker,%s", *flagInterpreter)) 1689 } 1690 1691 // Force global symbols to be exported for dlopen, etc. 1692 if ctxt.IsELF { 1693 if ctxt.DynlinkingGo() || ctxt.BuildMode == BuildModeCShared || !linkerFlagSupported(ctxt.Arch, argv[0], altLinker, "-Wl,--export-dynamic-symbol=main") { 1694 argv = append(argv, "-rdynamic") 1695 } else { 1696 var exports []string 1697 ctxt.loader.ForAllCgoExportDynamic(func(s loader.Sym) { 1698 exports = append(exports, "-Wl,--export-dynamic-symbol="+ctxt.loader.SymExtname(s)) 1699 }) 1700 sort.Strings(exports) 1701 argv = append(argv, exports...) 1702 } 1703 } 1704 if ctxt.HeadType == objabi.Haix { 1705 fileName := xcoffCreateExportFile(ctxt) 1706 argv = append(argv, "-Wl,-bE:"+fileName) 1707 } 1708 1709 const unusedArguments = "-Qunused-arguments" 1710 if linkerFlagSupported(ctxt.Arch, argv[0], altLinker, unusedArguments) { 1711 argv = append(argv, unusedArguments) 1712 } 1713 1714 if ctxt.IsWindows() { 1715 // Suppress generation of the PE file header timestamp, 1716 // so as to avoid spurious build ID differences between 1717 // linked binaries that are otherwise identical other than 1718 // the date/time they were linked. 1719 const noTimeStamp = "-Wl,--no-insert-timestamp" 1720 if linkerFlagSupported(ctxt.Arch, argv[0], altLinker, noTimeStamp) { 1721 argv = append(argv, noTimeStamp) 1722 } 1723 } 1724 1725 const compressDWARF = "-Wl,--compress-debug-sections=zlib" 1726 if ctxt.compressDWARF && linkerFlagSupported(ctxt.Arch, argv[0], altLinker, compressDWARF) { 1727 argv = append(argv, compressDWARF) 1728 } 1729 1730 argv = append(argv, filepath.Join(*flagTmpdir, "go.o")) 1731 argv = append(argv, ctxt.hostobjCopy()...) 1732 if ctxt.HeadType == objabi.Haix { 1733 // We want to have C files after Go files to remove 1734 // trampolines csects made by ld. 1735 argv = append(argv, "-nostartfiles") 1736 argv = append(argv, "/lib/crt0_64.o") 1737 1738 extld := ctxt.extld() 1739 name, args := extld[0], extld[1:] 1740 // Get starting files. 1741 getPathFile := func(file string) string { 1742 args := append(args, "-maix64", "--print-file-name="+file) 1743 out, err := exec.Command(name, args...).CombinedOutput() 1744 if err != nil { 1745 log.Fatalf("running %s failed: %v\n%s", extld, err, out) 1746 } 1747 return strings.Trim(string(out), "\n") 1748 } 1749 // Since GCC version 11, the 64-bit version of GCC starting files 1750 // are now suffixed by "_64". Even under "-maix64" multilib directory 1751 // "crtcxa.o" is 32-bit. 1752 crtcxa := getPathFile("crtcxa_64.o") 1753 if !filepath.IsAbs(crtcxa) { 1754 crtcxa = getPathFile("crtcxa.o") 1755 } 1756 crtdbase := getPathFile("crtdbase_64.o") 1757 if !filepath.IsAbs(crtdbase) { 1758 crtdbase = getPathFile("crtdbase.o") 1759 } 1760 argv = append(argv, crtcxa) 1761 argv = append(argv, crtdbase) 1762 } 1763 1764 if ctxt.linkShared { 1765 seenDirs := make(map[string]bool) 1766 seenLibs := make(map[string]bool) 1767 addshlib := func(path string) { 1768 dir, base := filepath.Split(path) 1769 if !seenDirs[dir] { 1770 argv = append(argv, "-L"+dir) 1771 if !rpath.set { 1772 argv = append(argv, "-Wl,-rpath="+dir) 1773 } 1774 seenDirs[dir] = true 1775 } 1776 base = strings.TrimSuffix(base, ".so") 1777 base = strings.TrimPrefix(base, "lib") 1778 if !seenLibs[base] { 1779 argv = append(argv, "-l"+base) 1780 seenLibs[base] = true 1781 } 1782 } 1783 for _, shlib := range ctxt.Shlibs { 1784 addshlib(shlib.Path) 1785 for _, dep := range shlib.Deps { 1786 if dep == "" { 1787 continue 1788 } 1789 libpath := findshlib(ctxt, dep) 1790 if libpath != "" { 1791 addshlib(libpath) 1792 } 1793 } 1794 } 1795 } 1796 1797 // clang, unlike GCC, passes -rdynamic to the linker 1798 // even when linking with -static, causing a linker 1799 // error when using GNU ld. So take out -rdynamic if 1800 // we added it. We do it in this order, rather than 1801 // only adding -rdynamic later, so that -extldflags 1802 // can override -rdynamic without using -static. 1803 // Similarly for -Wl,--dynamic-linker. 1804 checkStatic := func(arg string) { 1805 if ctxt.IsELF && arg == "-static" { 1806 for i := range argv { 1807 if argv[i] == "-rdynamic" || strings.HasPrefix(argv[i], "-Wl,--dynamic-linker,") { 1808 argv[i] = "-static" 1809 } 1810 } 1811 } 1812 } 1813 1814 for _, p := range ldflag { 1815 argv = append(argv, p) 1816 checkStatic(p) 1817 } 1818 1819 // When building a program with the default -buildmode=exe the 1820 // gc compiler generates code requires DT_TEXTREL in a 1821 // position independent executable (PIE). On systems where the 1822 // toolchain creates PIEs by default, and where DT_TEXTREL 1823 // does not work, the resulting programs will not run. See 1824 // issue #17847. To avoid this problem pass -no-pie to the 1825 // toolchain if it is supported. 1826 if ctxt.BuildMode == BuildModeExe && !ctxt.linkShared && !(ctxt.IsDarwin() && ctxt.IsARM64()) { 1827 // GCC uses -no-pie, clang uses -nopie. 1828 for _, nopie := range []string{"-no-pie", "-nopie"} { 1829 if linkerFlagSupported(ctxt.Arch, argv[0], altLinker, nopie) { 1830 argv = append(argv, nopie) 1831 break 1832 } 1833 } 1834 } 1835 1836 for _, p := range flagExtldflags { 1837 argv = append(argv, p) 1838 checkStatic(p) 1839 } 1840 if ctxt.HeadType == objabi.Hwindows { 1841 // Determine which linker we're using. Add in the extldflags in 1842 // case used has specified "-fuse-ld=...". 1843 extld := ctxt.extld() 1844 name, args := extld[0], extld[1:] 1845 args = append(args, trimLinkerArgv(flagExtldflags)...) 1846 args = append(args, "-Wl,--version") 1847 cmd := exec.Command(name, args...) 1848 usingLLD := false 1849 if out, err := cmd.CombinedOutput(); err == nil { 1850 if bytes.Contains(out, []byte("LLD ")) { 1851 usingLLD = true 1852 } 1853 } 1854 1855 // use gcc linker script to work around gcc bug 1856 // (see https://golang.org/issue/20183 for details). 1857 if !usingLLD { 1858 p := writeGDBLinkerScript() 1859 argv = append(argv, "-Wl,-T,"+p) 1860 } 1861 if *flagRace { 1862 if p := ctxt.findLibPath("libsynchronization.a"); p != "libsynchronization.a" { 1863 argv = append(argv, "-lsynchronization") 1864 } 1865 } 1866 // libmingw32 and libmingwex have some inter-dependencies, 1867 // so must use linker groups. 1868 argv = append(argv, "-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group") 1869 argv = append(argv, peimporteddlls()...) 1870 } 1871 1872 argv = ctxt.passLongArgsInResponseFile(argv, altLinker) 1873 1874 if ctxt.Debugvlog != 0 { 1875 ctxt.Logf("host link:") 1876 for _, v := range argv { 1877 ctxt.Logf(" %q", v) 1878 } 1879 ctxt.Logf("\n") 1880 } 1881 1882 out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput() 1883 if err != nil { 1884 Exitf("running %s failed: %v\n%s", argv[0], err, out) 1885 } 1886 1887 // Filter out useless linker warnings caused by bugs outside Go. 1888 // See also cmd/go/internal/work/exec.go's gccld method. 1889 var save [][]byte 1890 var skipLines int 1891 for _, line := range bytes.SplitAfter(out, []byte("\n")) { 1892 // golang.org/issue/26073 - Apple Xcode bug 1893 if bytes.Contains(line, []byte("ld: warning: text-based stub file")) { 1894 continue 1895 } 1896 1897 if skipLines > 0 { 1898 skipLines-- 1899 continue 1900 } 1901 1902 // Remove TOC overflow warning on AIX. 1903 if bytes.Contains(line, []byte("ld: 0711-783")) { 1904 skipLines = 2 1905 continue 1906 } 1907 1908 save = append(save, line) 1909 } 1910 out = bytes.Join(save, nil) 1911 1912 if len(out) > 0 { 1913 // always print external output even if the command is successful, so that we don't 1914 // swallow linker warnings (see https://golang.org/issue/17935). 1915 if ctxt.IsDarwin() && ctxt.IsAMD64() { 1916 const noPieWarning = "ld: warning: -no_pie is deprecated when targeting new OS versions\n" 1917 if i := bytes.Index(out, []byte(noPieWarning)); i >= 0 { 1918 // swallow -no_pie deprecation warning, issue 54482 1919 out = append(out[:i], out[i+len(noPieWarning):]...) 1920 } 1921 } 1922 if ctxt.IsDarwin() { 1923 const bindAtLoadWarning = "ld: warning: -bind_at_load is deprecated on macOS\n" 1924 if i := bytes.Index(out, []byte(bindAtLoadWarning)); i >= 0 { 1925 // -bind_at_load is deprecated with ld-prime, but needed for 1926 // correctness with older versions of ld64. Swallow the warning. 1927 // TODO: maybe pass -bind_at_load conditionally based on C 1928 // linker version. 1929 out = append(out[:i], out[i+len(bindAtLoadWarning):]...) 1930 } 1931 } 1932 ctxt.Logf("%s", out) 1933 } 1934 1935 if combineDwarf { 1936 // Find "dsymutils" and "strip" tools using CC --print-prog-name. 1937 var cc []string 1938 cc = append(cc, ctxt.extld()...) 1939 cc = append(cc, hostlinkArchArgs(ctxt.Arch)...) 1940 cc = append(cc, "--print-prog-name", "dsymutil") 1941 out, err := exec.Command(cc[0], cc[1:]...).CombinedOutput() 1942 if err != nil { 1943 Exitf("%s: finding dsymutil failed: %v\n%s", os.Args[0], err, out) 1944 } 1945 dsymutilCmd := strings.TrimSuffix(string(out), "\n") 1946 1947 cc[len(cc)-1] = "strip" 1948 out, err = exec.Command(cc[0], cc[1:]...).CombinedOutput() 1949 if err != nil { 1950 Exitf("%s: finding strip failed: %v\n%s", os.Args[0], err, out) 1951 } 1952 stripCmd := strings.TrimSuffix(string(out), "\n") 1953 1954 dsym := filepath.Join(*flagTmpdir, "go.dwarf") 1955 cmd := exec.Command(dsymutilCmd, "-f", *flagOutfile, "-o", dsym) 1956 // dsymutil may not clean up its temp directory at exit. 1957 // Set DSYMUTIL_REPRODUCER_PATH to work around. see issue 59026. 1958 cmd.Env = append(os.Environ(), "DSYMUTIL_REPRODUCER_PATH="+*flagTmpdir) 1959 if ctxt.Debugvlog != 0 { 1960 ctxt.Logf("host link dsymutil:") 1961 for _, v := range cmd.Args { 1962 ctxt.Logf(" %q", v) 1963 } 1964 ctxt.Logf("\n") 1965 } 1966 if out, err := cmd.CombinedOutput(); err != nil { 1967 Exitf("%s: running dsymutil failed: %v\n%s", os.Args[0], err, out) 1968 } 1969 // Remove STAB (symbolic debugging) symbols after we are done with them (by dsymutil). 1970 // They contain temporary file paths and make the build not reproducible. 1971 var stripArgs = []string{"-S"} 1972 if debug_s { 1973 // We are generating a binary with symbol table suppressed. 1974 // Suppress local symbols. We need to keep dynamically exported 1975 // and referenced symbols so the dynamic linker can resolve them. 1976 stripArgs = append(stripArgs, "-x") 1977 } 1978 stripArgs = append(stripArgs, *flagOutfile) 1979 if ctxt.Debugvlog != 0 { 1980 ctxt.Logf("host link strip: %q", stripCmd) 1981 for _, v := range stripArgs { 1982 ctxt.Logf(" %q", v) 1983 } 1984 ctxt.Logf("\n") 1985 } 1986 if out, err := exec.Command(stripCmd, stripArgs...).CombinedOutput(); err != nil { 1987 Exitf("%s: running strip failed: %v\n%s", os.Args[0], err, out) 1988 } 1989 // Skip combining if `dsymutil` didn't generate a file. See #11994. 1990 if _, err := os.Stat(dsym); os.IsNotExist(err) { 1991 return 1992 } 1993 // For os.Rename to work reliably, must be in same directory as outfile. 1994 combinedOutput := *flagOutfile + "~" 1995 exef, err := os.Open(*flagOutfile) 1996 if err != nil { 1997 Exitf("%s: combining dwarf failed: %v", os.Args[0], err) 1998 } 1999 defer exef.Close() 2000 exem, err := macho.NewFile(exef) 2001 if err != nil { 2002 Exitf("%s: parsing Mach-O header failed: %v", os.Args[0], err) 2003 } 2004 if err := machoCombineDwarf(ctxt, exef, exem, dsym, combinedOutput); err != nil { 2005 Exitf("%s: combining dwarf failed: %v", os.Args[0], err) 2006 } 2007 os.Remove(*flagOutfile) 2008 if err := os.Rename(combinedOutput, *flagOutfile); err != nil { 2009 Exitf("%s: %v", os.Args[0], err) 2010 } 2011 } 2012 if ctxt.NeedCodeSign() { 2013 err := machoCodeSign(ctxt, *flagOutfile) 2014 if err != nil { 2015 Exitf("%s: code signing failed: %v", os.Args[0], err) 2016 } 2017 } 2018 } 2019 2020 // passLongArgsInResponseFile writes the arguments into a file if they 2021 // are very long. 2022 func (ctxt *Link) passLongArgsInResponseFile(argv []string, altLinker string) []string { 2023 c := 0 2024 for _, arg := range argv { 2025 c += len(arg) 2026 } 2027 2028 if c < sys.ExecArgLengthLimit { 2029 return argv 2030 } 2031 2032 // Only use response files if they are supported. 2033 response := filepath.Join(*flagTmpdir, "response") 2034 if err := os.WriteFile(response, nil, 0644); err != nil { 2035 log.Fatalf("failed while testing response file: %v", err) 2036 } 2037 if !linkerFlagSupported(ctxt.Arch, argv[0], altLinker, "@"+response) { 2038 if ctxt.Debugvlog != 0 { 2039 ctxt.Logf("not using response file because linker does not support one") 2040 } 2041 return argv 2042 } 2043 2044 var buf bytes.Buffer 2045 for _, arg := range argv[1:] { 2046 // The external linker response file supports quoted strings. 2047 fmt.Fprintf(&buf, "%q\n", arg) 2048 } 2049 if err := os.WriteFile(response, buf.Bytes(), 0644); err != nil { 2050 log.Fatalf("failed while writing response file: %v", err) 2051 } 2052 if ctxt.Debugvlog != 0 { 2053 ctxt.Logf("response file %s contents:\n%s", response, buf.Bytes()) 2054 } 2055 return []string{ 2056 argv[0], 2057 "@" + response, 2058 } 2059 } 2060 2061 var createTrivialCOnce sync.Once 2062 2063 func linkerFlagSupported(arch *sys.Arch, linker, altLinker, flag string) bool { 2064 createTrivialCOnce.Do(func() { 2065 src := filepath.Join(*flagTmpdir, "trivial.c") 2066 if err := os.WriteFile(src, []byte("int main() { return 0; }"), 0666); err != nil { 2067 Errorf(nil, "WriteFile trivial.c failed: %v", err) 2068 } 2069 }) 2070 2071 flags := hostlinkArchArgs(arch) 2072 2073 moreFlags := trimLinkerArgv(append(flagExtldflags, ldflag...)) 2074 flags = append(flags, moreFlags...) 2075 2076 if altLinker != "" { 2077 flags = append(flags, "-fuse-ld="+altLinker) 2078 } 2079 trivialPath := filepath.Join(*flagTmpdir, "trivial.c") 2080 outPath := filepath.Join(*flagTmpdir, "a.out") 2081 flags = append(flags, "-o", outPath, flag, trivialPath) 2082 2083 cmd := exec.Command(linker, flags...) 2084 cmd.Env = append([]string{"LC_ALL=C"}, os.Environ()...) 2085 out, err := cmd.CombinedOutput() 2086 // GCC says "unrecognized command line option ‘-no-pie’" 2087 // clang says "unknown argument: '-no-pie'" 2088 return err == nil && !bytes.Contains(out, []byte("unrecognized")) && !bytes.Contains(out, []byte("unknown")) 2089 } 2090 2091 // trimLinkerArgv returns a new copy of argv that does not include flags 2092 // that are not relevant for testing whether some linker option works. 2093 func trimLinkerArgv(argv []string) []string { 2094 flagsWithNextArgSkip := []string{ 2095 "-F", 2096 "-l", 2097 "-L", 2098 "-framework", 2099 "-Wl,-framework", 2100 "-Wl,-rpath", 2101 "-Wl,-undefined", 2102 } 2103 flagsWithNextArgKeep := []string{ 2104 "-arch", 2105 "-isysroot", 2106 "--sysroot", 2107 "-target", 2108 } 2109 prefixesToKeep := []string{ 2110 "-f", 2111 "-m", 2112 "-p", 2113 "-Wl,", 2114 "-arch", 2115 "-isysroot", 2116 "--sysroot", 2117 "-target", 2118 } 2119 2120 var flags []string 2121 keep := false 2122 skip := false 2123 for _, f := range argv { 2124 if keep { 2125 flags = append(flags, f) 2126 keep = false 2127 } else if skip { 2128 skip = false 2129 } else if f == "" || f[0] != '-' { 2130 } else if contains(flagsWithNextArgSkip, f) { 2131 skip = true 2132 } else if contains(flagsWithNextArgKeep, f) { 2133 flags = append(flags, f) 2134 keep = true 2135 } else { 2136 for _, p := range prefixesToKeep { 2137 if strings.HasPrefix(f, p) { 2138 flags = append(flags, f) 2139 break 2140 } 2141 } 2142 } 2143 } 2144 return flags 2145 } 2146 2147 // hostlinkArchArgs returns arguments to pass to the external linker 2148 // based on the architecture. 2149 func hostlinkArchArgs(arch *sys.Arch) []string { 2150 switch arch.Family { 2151 case sys.I386: 2152 return []string{"-m32"} 2153 case sys.AMD64: 2154 if buildcfg.GOOS == "darwin" { 2155 return []string{"-arch", "x86_64", "-m64"} 2156 } 2157 return []string{"-m64"} 2158 case sys.S390X: 2159 return []string{"-m64"} 2160 case sys.ARM: 2161 return []string{"-marm"} 2162 case sys.ARM64: 2163 if buildcfg.GOOS == "darwin" { 2164 return []string{"-arch", "arm64"} 2165 } 2166 case sys.Loong64: 2167 return []string{"-mabi=lp64d"} 2168 case sys.MIPS64: 2169 return []string{"-mabi=64"} 2170 case sys.MIPS: 2171 return []string{"-mabi=32"} 2172 case sys.PPC64: 2173 if buildcfg.GOOS == "aix" { 2174 return []string{"-maix64"} 2175 } else { 2176 return []string{"-m64"} 2177 } 2178 2179 } 2180 return nil 2181 } 2182 2183 var wantHdr = objabi.HeaderString() 2184 2185 // ldobj loads an input object. If it is a host object (an object 2186 // compiled by a non-Go compiler) it returns the Hostobj pointer. If 2187 // it is a Go object, it returns nil. 2188 func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, file string) *Hostobj { 2189 pkg := objabi.PathToPrefix(lib.Pkg) 2190 2191 eof := f.Offset() + length 2192 start := f.Offset() 2193 c1 := bgetc(f) 2194 c2 := bgetc(f) 2195 c3 := bgetc(f) 2196 c4 := bgetc(f) 2197 f.MustSeek(start, 0) 2198 2199 unit := &sym.CompilationUnit{Lib: lib} 2200 lib.Units = append(lib.Units, unit) 2201 2202 magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4) 2203 if magic == 0x7f454c46 { // \x7F E L F 2204 ldelf := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) { 2205 textp, flags, err := loadelf.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn, ehdr.Flags) 2206 if err != nil { 2207 Errorf(nil, "%v", err) 2208 return 2209 } 2210 ehdr.Flags = flags 2211 ctxt.Textp = append(ctxt.Textp, textp...) 2212 } 2213 return ldhostobj(ldelf, ctxt.HeadType, f, pkg, length, pn, file) 2214 } 2215 2216 if magic&^1 == 0xfeedface || magic&^0x01000000 == 0xcefaedfe { 2217 ldmacho := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) { 2218 textp, err := loadmacho.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn) 2219 if err != nil { 2220 Errorf(nil, "%v", err) 2221 return 2222 } 2223 ctxt.Textp = append(ctxt.Textp, textp...) 2224 } 2225 return ldhostobj(ldmacho, ctxt.HeadType, f, pkg, length, pn, file) 2226 } 2227 2228 switch c1<<8 | c2 { 2229 case 0x4c01, // 386 2230 0x6486, // amd64 2231 0xc401, // arm 2232 0x64aa: // arm64 2233 ldpe := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) { 2234 ls, err := loadpe.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn) 2235 if err != nil { 2236 Errorf(nil, "%v", err) 2237 return 2238 } 2239 if len(ls.Resources) != 0 { 2240 setpersrc(ctxt, ls.Resources) 2241 } 2242 if ls.PData != 0 { 2243 sehp.pdata = append(sehp.pdata, ls.PData) 2244 } 2245 if ls.XData != 0 { 2246 sehp.xdata = append(sehp.xdata, ls.XData) 2247 } 2248 ctxt.Textp = append(ctxt.Textp, ls.Textp...) 2249 } 2250 return ldhostobj(ldpe, ctxt.HeadType, f, pkg, length, pn, file) 2251 } 2252 2253 if c1 == 0x01 && (c2 == 0xD7 || c2 == 0xF7) { 2254 ldxcoff := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) { 2255 textp, err := loadxcoff.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn) 2256 if err != nil { 2257 Errorf(nil, "%v", err) 2258 return 2259 } 2260 ctxt.Textp = append(ctxt.Textp, textp...) 2261 } 2262 return ldhostobj(ldxcoff, ctxt.HeadType, f, pkg, length, pn, file) 2263 } 2264 2265 if c1 != 'g' || c2 != 'o' || c3 != ' ' || c4 != 'o' { 2266 // An unrecognized object is just passed to the external linker. 2267 // If we try to read symbols from this object, we will 2268 // report an error at that time. 2269 unknownObjFormat = true 2270 return ldhostobj(nil, ctxt.HeadType, f, pkg, length, pn, file) 2271 } 2272 2273 /* check the header */ 2274 line, err := f.ReadString('\n') 2275 if err != nil { 2276 Errorf(nil, "truncated object file: %s: %v", pn, err) 2277 return nil 2278 } 2279 2280 if !strings.HasPrefix(line, "go object ") { 2281 if strings.HasSuffix(pn, ".go") { 2282 Exitf("%s: uncompiled .go source file", pn) 2283 return nil 2284 } 2285 2286 if line == ctxt.Arch.Name { 2287 // old header format: just $GOOS 2288 Errorf(nil, "%s: stale object file", pn) 2289 return nil 2290 } 2291 2292 Errorf(nil, "%s: not an object file: @%d %q", pn, start, line) 2293 return nil 2294 } 2295 2296 // First, check that the basic GOOS, GOARCH, and Version match. 2297 if line != wantHdr { 2298 Errorf(nil, "%s: linked object header mismatch:\nhave %q\nwant %q\n", pn, line, wantHdr) 2299 } 2300 2301 // Skip over exports and other info -- ends with \n!\n. 2302 // 2303 // Note: It's possible for "\n!\n" to appear within the binary 2304 // package export data format. To avoid truncating the package 2305 // definition prematurely (issue 21703), we keep track of 2306 // how many "$$" delimiters we've seen. 2307 2308 import0 := f.Offset() 2309 2310 c1 = '\n' // the last line ended in \n 2311 c2 = bgetc(f) 2312 c3 = bgetc(f) 2313 markers := 0 2314 for { 2315 if c1 == '\n' { 2316 if markers%2 == 0 && c2 == '!' && c3 == '\n' { 2317 break 2318 } 2319 if c2 == '$' && c3 == '$' { 2320 markers++ 2321 } 2322 } 2323 2324 c1 = c2 2325 c2 = c3 2326 c3 = bgetc(f) 2327 if c3 == -1 { 2328 Errorf(nil, "truncated object file: %s", pn) 2329 return nil 2330 } 2331 } 2332 2333 import1 := f.Offset() 2334 2335 f.MustSeek(import0, 0) 2336 ldpkg(ctxt, f, lib, import1-import0-2, pn) // -2 for !\n 2337 f.MustSeek(import1, 0) 2338 2339 fingerprint := ctxt.loader.Preload(ctxt.IncVersion(), f, lib, unit, eof-f.Offset()) 2340 if !fingerprint.IsZero() { // Assembly objects don't have fingerprints. Ignore them. 2341 // Check fingerprint, to ensure the importing and imported packages 2342 // have consistent view of symbol indices. 2343 // Normally the go command should ensure this. But in case something 2344 // goes wrong, it could lead to obscure bugs like run-time crash. 2345 // Check it here to be sure. 2346 if lib.Fingerprint.IsZero() { // Not yet imported. Update its fingerprint. 2347 lib.Fingerprint = fingerprint 2348 } 2349 checkFingerprint(lib, fingerprint, lib.Srcref, lib.Fingerprint) 2350 } 2351 2352 addImports(ctxt, lib, pn) 2353 return nil 2354 } 2355 2356 // symbolsAreUnresolved scans through the loader's list of unresolved 2357 // symbols and checks to see whether any of them match the names of the 2358 // symbols in 'want'. Return value is a list of bools, with list[K] set 2359 // to true if there is an unresolved reference to the symbol in want[K]. 2360 func symbolsAreUnresolved(ctxt *Link, want []string) []bool { 2361 returnAllUndefs := -1 2362 undefs, _ := ctxt.loader.UndefinedRelocTargets(returnAllUndefs) 2363 seen := make(map[loader.Sym]struct{}) 2364 rval := make([]bool, len(want)) 2365 wantm := make(map[string]int) 2366 for k, w := range want { 2367 wantm[w] = k 2368 } 2369 count := 0 2370 for _, s := range undefs { 2371 if _, ok := seen[s]; ok { 2372 continue 2373 } 2374 seen[s] = struct{}{} 2375 if k, ok := wantm[ctxt.loader.SymName(s)]; ok { 2376 rval[k] = true 2377 count++ 2378 if count == len(want) { 2379 return rval 2380 } 2381 } 2382 } 2383 return rval 2384 } 2385 2386 // hostObject reads a single host object file (compare to "hostArchive"). 2387 // This is used as part of internal linking when we need to pull in 2388 // files such as "crt?.o". 2389 func hostObject(ctxt *Link, objname string, path string) { 2390 if ctxt.Debugvlog > 1 { 2391 ctxt.Logf("hostObject(%s)\n", path) 2392 } 2393 objlib := sym.Library{ 2394 Pkg: objname, 2395 } 2396 f, err := bio.Open(path) 2397 if err != nil { 2398 Exitf("cannot open host object %q file %s: %v", objname, path, err) 2399 } 2400 defer f.Close() 2401 h := ldobj(ctxt, f, &objlib, 0, path, path) 2402 if h.ld == nil { 2403 Exitf("unrecognized object file format in %s", path) 2404 } 2405 h.file = path 2406 h.length = f.MustSeek(0, 2) 2407 f.MustSeek(h.off, 0) 2408 h.ld(ctxt, f, h.pkg, h.length, h.pn) 2409 if *flagCaptureHostObjs != "" { 2410 captureHostObj(h) 2411 } 2412 } 2413 2414 func checkFingerprint(lib *sym.Library, libfp goobj.FingerprintType, src string, srcfp goobj.FingerprintType) { 2415 if libfp != srcfp { 2416 Exitf("fingerprint mismatch: %s has %x, import from %s expecting %x", lib, libfp, src, srcfp) 2417 } 2418 } 2419 2420 func readelfsymboldata(ctxt *Link, f *elf.File, sym *elf.Symbol) []byte { 2421 data := make([]byte, sym.Size) 2422 sect := f.Sections[sym.Section] 2423 if sect.Type != elf.SHT_PROGBITS && sect.Type != elf.SHT_NOTE { 2424 Errorf(nil, "reading %s from non-data section", sym.Name) 2425 } 2426 n, err := sect.ReadAt(data, int64(sym.Value-sect.Addr)) 2427 if uint64(n) != sym.Size { 2428 Errorf(nil, "reading contents of %s: %v", sym.Name, err) 2429 } 2430 return data 2431 } 2432 2433 func readwithpad(r io.Reader, sz int32) ([]byte, error) { 2434 data := make([]byte, Rnd(int64(sz), 4)) 2435 _, err := io.ReadFull(r, data) 2436 if err != nil { 2437 return nil, err 2438 } 2439 data = data[:sz] 2440 return data, nil 2441 } 2442 2443 func readnote(f *elf.File, name []byte, typ int32) ([]byte, error) { 2444 for _, sect := range f.Sections { 2445 if sect.Type != elf.SHT_NOTE { 2446 continue 2447 } 2448 r := sect.Open() 2449 for { 2450 var namesize, descsize, noteType int32 2451 err := binary.Read(r, f.ByteOrder, &namesize) 2452 if err != nil { 2453 if err == io.EOF { 2454 break 2455 } 2456 return nil, fmt.Errorf("read namesize failed: %v", err) 2457 } 2458 err = binary.Read(r, f.ByteOrder, &descsize) 2459 if err != nil { 2460 return nil, fmt.Errorf("read descsize failed: %v", err) 2461 } 2462 err = binary.Read(r, f.ByteOrder, ¬eType) 2463 if err != nil { 2464 return nil, fmt.Errorf("read type failed: %v", err) 2465 } 2466 noteName, err := readwithpad(r, namesize) 2467 if err != nil { 2468 return nil, fmt.Errorf("read name failed: %v", err) 2469 } 2470 desc, err := readwithpad(r, descsize) 2471 if err != nil { 2472 return nil, fmt.Errorf("read desc failed: %v", err) 2473 } 2474 if string(name) == string(noteName) && typ == noteType { 2475 return desc, nil 2476 } 2477 } 2478 } 2479 return nil, nil 2480 } 2481 2482 func findshlib(ctxt *Link, shlib string) string { 2483 if filepath.IsAbs(shlib) { 2484 return shlib 2485 } 2486 for _, libdir := range ctxt.Libdir { 2487 libpath := filepath.Join(libdir, shlib) 2488 if _, err := os.Stat(libpath); err == nil { 2489 return libpath 2490 } 2491 } 2492 Errorf(nil, "cannot find shared library: %s", shlib) 2493 return "" 2494 } 2495 2496 func ldshlibsyms(ctxt *Link, shlib string) { 2497 var libpath string 2498 if filepath.IsAbs(shlib) { 2499 libpath = shlib 2500 shlib = filepath.Base(shlib) 2501 } else { 2502 libpath = findshlib(ctxt, shlib) 2503 if libpath == "" { 2504 return 2505 } 2506 } 2507 for _, processedlib := range ctxt.Shlibs { 2508 if processedlib.Path == libpath { 2509 return 2510 } 2511 } 2512 if ctxt.Debugvlog > 1 { 2513 ctxt.Logf("ldshlibsyms: found library with name %s at %s\n", shlib, libpath) 2514 } 2515 2516 f, err := elf.Open(libpath) 2517 if err != nil { 2518 Errorf(nil, "cannot open shared library: %s", libpath) 2519 return 2520 } 2521 // Keep the file open as decodetypeGcprog needs to read from it. 2522 // TODO: fix. Maybe mmap the file. 2523 //defer f.Close() 2524 2525 hash, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GOABIHASH_TAG) 2526 if err != nil { 2527 Errorf(nil, "cannot read ABI hash from shared library %s: %v", libpath, err) 2528 return 2529 } 2530 2531 depsbytes, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GODEPS_TAG) 2532 if err != nil { 2533 Errorf(nil, "cannot read dep list from shared library %s: %v", libpath, err) 2534 return 2535 } 2536 var deps []string 2537 for _, dep := range strings.Split(string(depsbytes), "\n") { 2538 if dep == "" { 2539 continue 2540 } 2541 if !filepath.IsAbs(dep) { 2542 // If the dep can be interpreted as a path relative to the shlib 2543 // in which it was found, do that. Otherwise, we will leave it 2544 // to be resolved by libdir lookup. 2545 abs := filepath.Join(filepath.Dir(libpath), dep) 2546 if _, err := os.Stat(abs); err == nil { 2547 dep = abs 2548 } 2549 } 2550 deps = append(deps, dep) 2551 } 2552 2553 syms, err := f.DynamicSymbols() 2554 if err != nil { 2555 Errorf(nil, "cannot read symbols from shared library: %s", libpath) 2556 return 2557 } 2558 2559 for _, elfsym := range syms { 2560 if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION { 2561 continue 2562 } 2563 2564 // Symbols whose names start with "type:" are compiler generated, 2565 // so make functions with that prefix internal. 2566 ver := 0 2567 symname := elfsym.Name // (unmangled) symbol name 2568 if elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC && strings.HasPrefix(elfsym.Name, "type:") { 2569 ver = abiInternalVer 2570 } else if buildcfg.Experiment.RegabiWrappers && elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC { 2571 // Demangle the ABI name. Keep in sync with symtab.go:mangleABIName. 2572 if strings.HasSuffix(elfsym.Name, ".abiinternal") { 2573 ver = sym.SymVerABIInternal 2574 symname = strings.TrimSuffix(elfsym.Name, ".abiinternal") 2575 } else if strings.HasSuffix(elfsym.Name, ".abi0") { 2576 ver = 0 2577 symname = strings.TrimSuffix(elfsym.Name, ".abi0") 2578 } 2579 } 2580 2581 l := ctxt.loader 2582 s := l.LookupOrCreateSym(symname, ver) 2583 2584 // Because loadlib above loads all .a files before loading 2585 // any shared libraries, any non-dynimport symbols we find 2586 // that duplicate symbols already loaded should be ignored 2587 // (the symbols from the .a files "win"). 2588 if l.SymType(s) != 0 && l.SymType(s) != sym.SDYNIMPORT { 2589 continue 2590 } 2591 su := l.MakeSymbolUpdater(s) 2592 su.SetType(sym.SDYNIMPORT) 2593 l.SetSymElfType(s, elf.ST_TYPE(elfsym.Info)) 2594 su.SetSize(int64(elfsym.Size)) 2595 if elfsym.Section != elf.SHN_UNDEF { 2596 // Set .File for the library that actually defines the symbol. 2597 l.SetSymPkg(s, libpath) 2598 2599 // The decodetype_* functions in decodetype.go need access to 2600 // the type data. 2601 sname := l.SymName(s) 2602 if strings.HasPrefix(sname, "type:") && !strings.HasPrefix(sname, "type:.") { 2603 su.SetData(readelfsymboldata(ctxt, f, &elfsym)) 2604 } 2605 } 2606 2607 if symname != elfsym.Name { 2608 l.SetSymExtname(s, elfsym.Name) 2609 } 2610 } 2611 ctxt.Shlibs = append(ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f}) 2612 } 2613 2614 func addsection(ldr *loader.Loader, arch *sys.Arch, seg *sym.Segment, name string, rwx int) *sym.Section { 2615 sect := ldr.NewSection() 2616 sect.Rwx = uint8(rwx) 2617 sect.Name = name 2618 sect.Seg = seg 2619 sect.Align = int32(arch.PtrSize) // everything is at least pointer-aligned 2620 seg.Sections = append(seg.Sections, sect) 2621 return sect 2622 } 2623 2624 func usage() { 2625 fmt.Fprintf(os.Stderr, "usage: link [options] main.o\n") 2626 flag_objabi.Flagprint(os.Stderr) 2627 Exit(2) 2628 } 2629 2630 type SymbolType int8 // TODO: after genasmsym is gone, maybe rename to plan9typeChar or something 2631 2632 const ( 2633 // see also https://9p.io/magic/man2html/1/nm 2634 TextSym SymbolType = 'T' 2635 DataSym SymbolType = 'D' 2636 BSSSym SymbolType = 'B' 2637 UndefinedSym SymbolType = 'U' 2638 TLSSym SymbolType = 't' 2639 FrameSym SymbolType = 'm' 2640 ParamSym SymbolType = 'p' 2641 AutoSym SymbolType = 'a' 2642 2643 // Deleted auto (not a real sym, just placeholder for type) 2644 DeletedAutoSym = 'x' 2645 ) 2646 2647 // defineInternal defines a symbol used internally by the go runtime. 2648 func (ctxt *Link) defineInternal(p string, t sym.SymKind) loader.Sym { 2649 s := ctxt.loader.CreateSymForUpdate(p, 0) 2650 s.SetType(t) 2651 s.SetSpecial(true) 2652 s.SetLocal(true) 2653 return s.Sym() 2654 } 2655 2656 func (ctxt *Link) xdefine(p string, t sym.SymKind, v int64) loader.Sym { 2657 s := ctxt.defineInternal(p, t) 2658 ctxt.loader.SetSymValue(s, v) 2659 return s 2660 } 2661 2662 func datoff(ldr *loader.Loader, s loader.Sym, addr int64) int64 { 2663 if uint64(addr) >= Segdata.Vaddr { 2664 return int64(uint64(addr) - Segdata.Vaddr + Segdata.Fileoff) 2665 } 2666 if uint64(addr) >= Segtext.Vaddr { 2667 return int64(uint64(addr) - Segtext.Vaddr + Segtext.Fileoff) 2668 } 2669 ldr.Errorf(s, "invalid datoff %#x", addr) 2670 return 0 2671 } 2672 2673 func Entryvalue(ctxt *Link) int64 { 2674 a := *flagEntrySymbol 2675 if a[0] >= '0' && a[0] <= '9' { 2676 return atolwhex(a) 2677 } 2678 ldr := ctxt.loader 2679 s := ldr.Lookup(a, 0) 2680 if s == 0 { 2681 Errorf(nil, "missing entry symbol %q", a) 2682 return 0 2683 } 2684 st := ldr.SymType(s) 2685 if st == 0 { 2686 return *FlagTextAddr 2687 } 2688 if !ctxt.IsAIX() && st != sym.STEXT { 2689 ldr.Errorf(s, "entry not text") 2690 } 2691 return ldr.SymValue(s) 2692 } 2693 2694 func (ctxt *Link) callgraph() { 2695 if !*FlagC { 2696 return 2697 } 2698 2699 ldr := ctxt.loader 2700 for _, s := range ctxt.Textp { 2701 relocs := ldr.Relocs(s) 2702 for i := 0; i < relocs.Count(); i++ { 2703 r := relocs.At(i) 2704 rs := r.Sym() 2705 if rs == 0 { 2706 continue 2707 } 2708 if r.Type().IsDirectCall() && ldr.SymType(rs) == sym.STEXT { 2709 ctxt.Logf("%s calls %s\n", ldr.SymName(s), ldr.SymName(rs)) 2710 } 2711 } 2712 } 2713 } 2714 2715 func Rnd(v int64, r int64) int64 { 2716 if r <= 0 { 2717 return v 2718 } 2719 v += r - 1 2720 c := v % r 2721 if c < 0 { 2722 c += r 2723 } 2724 v -= c 2725 return v 2726 } 2727 2728 func bgetc(r *bio.Reader) int { 2729 c, err := r.ReadByte() 2730 if err != nil { 2731 if err != io.EOF { 2732 log.Fatalf("reading input: %v", err) 2733 } 2734 return -1 2735 } 2736 return int(c) 2737 } 2738 2739 type markKind uint8 // for postorder traversal 2740 const ( 2741 _ markKind = iota 2742 visiting 2743 visited 2744 ) 2745 2746 func postorder(libs []*sym.Library) []*sym.Library { 2747 order := make([]*sym.Library, 0, len(libs)) // hold the result 2748 mark := make(map[*sym.Library]markKind, len(libs)) 2749 for _, lib := range libs { 2750 dfs(lib, mark, &order) 2751 } 2752 return order 2753 } 2754 2755 func dfs(lib *sym.Library, mark map[*sym.Library]markKind, order *[]*sym.Library) { 2756 if mark[lib] == visited { 2757 return 2758 } 2759 if mark[lib] == visiting { 2760 panic("found import cycle while visiting " + lib.Pkg) 2761 } 2762 mark[lib] = visiting 2763 for _, i := range lib.Imports { 2764 dfs(i, mark, order) 2765 } 2766 mark[lib] = visited 2767 *order = append(*order, lib) 2768 } 2769 2770 func ElfSymForReloc(ctxt *Link, s loader.Sym) int32 { 2771 // If putelfsym created a local version of this symbol, use that in all 2772 // relocations. 2773 les := ctxt.loader.SymLocalElfSym(s) 2774 if les != 0 { 2775 return les 2776 } else { 2777 return ctxt.loader.SymElfSym(s) 2778 } 2779 } 2780 2781 func AddGotSym(target *Target, ldr *loader.Loader, syms *ArchSyms, s loader.Sym, elfRelocTyp uint32) { 2782 if ldr.SymGot(s) >= 0 { 2783 return 2784 } 2785 2786 Adddynsym(ldr, target, syms, s) 2787 got := ldr.MakeSymbolUpdater(syms.GOT) 2788 ldr.SetGot(s, int32(got.Size())) 2789 got.AddUint(target.Arch, 0) 2790 2791 if target.IsElf() { 2792 if target.Arch.PtrSize == 8 { 2793 rela := ldr.MakeSymbolUpdater(syms.Rela) 2794 rela.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s))) 2795 rela.AddUint64(target.Arch, elf.R_INFO(uint32(ldr.SymDynid(s)), elfRelocTyp)) 2796 rela.AddUint64(target.Arch, 0) 2797 } else { 2798 rel := ldr.MakeSymbolUpdater(syms.Rel) 2799 rel.AddAddrPlus(target.Arch, got.Sym(), int64(ldr.SymGot(s))) 2800 rel.AddUint32(target.Arch, elf.R_INFO32(uint32(ldr.SymDynid(s)), elfRelocTyp)) 2801 } 2802 } else if target.IsDarwin() { 2803 leg := ldr.MakeSymbolUpdater(syms.LinkEditGOT) 2804 leg.AddUint32(target.Arch, uint32(ldr.SymDynid(s))) 2805 if target.IsPIE() && target.IsInternal() { 2806 // Mach-O relocations are a royal pain to lay out. 2807 // They use a compact stateful bytecode representation. 2808 // Here we record what are needed and encode them later. 2809 MachoAddBind(int64(ldr.SymGot(s)), s) 2810 } 2811 } else { 2812 ldr.Errorf(s, "addgotsym: unsupported binary format") 2813 } 2814 } 2815 2816 var hostobjcounter int 2817 2818 // captureHostObj writes out the content of a host object (pulled from 2819 // an archive or loaded from a *.o file directly) to a directory 2820 // specified via the linker's "-capturehostobjs" debugging flag. This 2821 // is intended to make it easier for a developer to inspect the actual 2822 // object feeding into "CGO internal" link step. 2823 func captureHostObj(h *Hostobj) { 2824 // Form paths for info file and obj file. 2825 ofile := fmt.Sprintf("captured-obj-%d.o", hostobjcounter) 2826 ifile := fmt.Sprintf("captured-obj-%d.txt", hostobjcounter) 2827 hostobjcounter++ 2828 opath := filepath.Join(*flagCaptureHostObjs, ofile) 2829 ipath := filepath.Join(*flagCaptureHostObjs, ifile) 2830 2831 // Write the info file. 2832 info := fmt.Sprintf("pkg: %s\npn: %s\nfile: %s\noff: %d\nlen: %d\n", 2833 h.pkg, h.pn, h.file, h.off, h.length) 2834 if err := os.WriteFile(ipath, []byte(info), 0666); err != nil { 2835 log.Fatalf("error writing captured host obj info %s: %v", ipath, err) 2836 } 2837 2838 readObjData := func() []byte { 2839 inf, err := os.Open(h.file) 2840 if err != nil { 2841 log.Fatalf("capturing host obj: open failed on %s: %v", h.pn, err) 2842 } 2843 res := make([]byte, h.length) 2844 if n, err := inf.ReadAt(res, h.off); err != nil || n != int(h.length) { 2845 log.Fatalf("capturing host obj: readat failed on %s: %v", h.pn, err) 2846 } 2847 return res 2848 } 2849 2850 // Write the object file. 2851 if err := os.WriteFile(opath, readObjData(), 0666); err != nil { 2852 log.Fatalf("error writing captured host object %s: %v", opath, err) 2853 } 2854 2855 fmt.Fprintf(os.Stderr, "link: info: captured host object %s to %s\n", 2856 h.file, opath) 2857 }