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