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