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