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