github.com/robhaswell/grandperspective-scan@v0.1.0/test/go-go1.7.1/src/cmd/link/internal/ppc64/asm.go (about)

     1  // Inferno utils/5l/asm.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/5l/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 ppc64
    32  
    33  import (
    34  	"cmd/internal/obj"
    35  	"cmd/link/internal/ld"
    36  	"encoding/binary"
    37  	"fmt"
    38  	"log"
    39  )
    40  
    41  func genplt() {
    42  	// The ppc64 ABI PLT has similar concepts to other
    43  	// architectures, but is laid out quite differently. When we
    44  	// see an R_PPC64_REL24 relocation to a dynamic symbol
    45  	// (indicating that the call needs to go through the PLT), we
    46  	// generate up to three stubs and reserve a PLT slot.
    47  	//
    48  	// 1) The call site will be bl x; nop (where the relocation
    49  	//    applies to the bl).  We rewrite this to bl x_stub; ld
    50  	//    r2,24(r1).  The ld is necessary because x_stub will save
    51  	//    r2 (the TOC pointer) at 24(r1) (the "TOC save slot").
    52  	//
    53  	// 2) We reserve space for a pointer in the .plt section (once
    54  	//    per referenced dynamic function).  .plt is a data
    55  	//    section filled solely by the dynamic linker (more like
    56  	//    .plt.got on other architectures).  Initially, the
    57  	//    dynamic linker will fill each slot with a pointer to the
    58  	//    corresponding x@plt entry point.
    59  	//
    60  	// 3) We generate the "call stub" x_stub (once per dynamic
    61  	//    function/object file pair).  This saves the TOC in the
    62  	//    TOC save slot, reads the function pointer from x's .plt
    63  	//    slot and calls it like any other global entry point
    64  	//    (including setting r12 to the function address).
    65  	//
    66  	// 4) We generate the "symbol resolver stub" x@plt (once per
    67  	//    dynamic function).  This is solely a branch to the glink
    68  	//    resolver stub.
    69  	//
    70  	// 5) We generate the glink resolver stub (only once).  This
    71  	//    computes which symbol resolver stub we came through and
    72  	//    invokes the dynamic resolver via a pointer provided by
    73  	//    the dynamic linker. This will patch up the .plt slot to
    74  	//    point directly at the function so future calls go
    75  	//    straight from the call stub to the real function, and
    76  	//    then call the function.
    77  
    78  	// NOTE: It's possible we could make ppc64 closer to other
    79  	// architectures: ppc64's .plt is like .plt.got on other
    80  	// platforms and ppc64's .glink is like .plt on other
    81  	// platforms.
    82  
    83  	// Find all R_PPC64_REL24 relocations that reference dynamic
    84  	// imports. Reserve PLT entries for these symbols and
    85  	// generate call stubs. The call stubs need to live in .text,
    86  	// which is why we need to do this pass this early.
    87  	//
    88  	// This assumes "case 1" from the ABI, where the caller needs
    89  	// us to save and restore the TOC pointer.
    90  	for _, s := range ld.Ctxt.Textp {
    91  		for i := range s.R {
    92  			r := &s.R[i]
    93  			if r.Type != 256+ld.R_PPC64_REL24 || r.Sym.Type != obj.SDYNIMPORT {
    94  				continue
    95  			}
    96  
    97  			// Reserve PLT entry and generate symbol
    98  			// resolver
    99  			addpltsym(ld.Ctxt, r.Sym)
   100  
   101  			// Generate call stub
   102  			n := fmt.Sprintf("%s.%s", s.Name, r.Sym.Name)
   103  
   104  			stub := ld.Linklookup(ld.Ctxt, n, 0)
   105  			if s.Attr.Reachable() {
   106  				stub.Attr |= ld.AttrReachable
   107  			}
   108  			if stub.Size == 0 {
   109  				// Need outer to resolve .TOC.
   110  				stub.Outer = s
   111  				ld.Ctxt.Textp = append(ld.Ctxt.Textp, stub)
   112  				gencallstub(1, stub, r.Sym)
   113  			}
   114  
   115  			// Update the relocation to use the call stub
   116  			r.Sym = stub
   117  
   118  			// Restore TOC after bl. The compiler put a
   119  			// nop here for us to overwrite.
   120  			const o1 = 0xe8410018 // ld r2,24(r1)
   121  			ld.Ctxt.Arch.ByteOrder.PutUint32(s.P[r.Off+4:], o1)
   122  		}
   123  	}
   124  }
   125  
   126  func genaddmoduledata() {
   127  	addmoduledata := ld.Linkrlookup(ld.Ctxt, "runtime.addmoduledata", 0)
   128  	if addmoduledata.Type == obj.STEXT {
   129  		return
   130  	}
   131  	addmoduledata.Attr |= ld.AttrReachable
   132  	initfunc := ld.Linklookup(ld.Ctxt, "go.link.addmoduledata", 0)
   133  	initfunc.Type = obj.STEXT
   134  	initfunc.Attr |= ld.AttrLocal
   135  	initfunc.Attr |= ld.AttrReachable
   136  	o := func(op uint32) {
   137  		ld.Adduint32(ld.Ctxt, initfunc, op)
   138  	}
   139  	// addis r2, r12, .TOC.-func@ha
   140  	rel := ld.Addrel(initfunc)
   141  	rel.Off = int32(initfunc.Size)
   142  	rel.Siz = 8
   143  	rel.Sym = ld.Linklookup(ld.Ctxt, ".TOC.", 0)
   144  	rel.Type = obj.R_ADDRPOWER_PCREL
   145  	o(0x3c4c0000)
   146  	// addi r2, r2, .TOC.-func@l
   147  	o(0x38420000)
   148  	// mflr r31
   149  	o(0x7c0802a6)
   150  	// stdu r31, -32(r1)
   151  	o(0xf801ffe1)
   152  	// addis r3, r2, local.moduledata@got@ha
   153  	rel = ld.Addrel(initfunc)
   154  	rel.Off = int32(initfunc.Size)
   155  	rel.Siz = 8
   156  	rel.Sym = ld.Linklookup(ld.Ctxt, "local.moduledata", 0)
   157  	rel.Type = obj.R_ADDRPOWER_GOT
   158  	o(0x3c620000)
   159  	// ld r3, local.moduledata@got@l(r3)
   160  	o(0xe8630000)
   161  	// bl runtime.addmoduledata
   162  	rel = ld.Addrel(initfunc)
   163  	rel.Off = int32(initfunc.Size)
   164  	rel.Siz = 4
   165  	rel.Sym = addmoduledata
   166  	rel.Type = obj.R_CALLPOWER
   167  	o(0x48000001)
   168  	// nop
   169  	o(0x60000000)
   170  	// ld r31, 0(r1)
   171  	o(0xe8010000)
   172  	// mtlr r31
   173  	o(0x7c0803a6)
   174  	// addi r1,r1,32
   175  	o(0x38210020)
   176  	// blr
   177  	o(0x4e800020)
   178  
   179  	ld.Ctxt.Textp = append(ld.Ctxt.Textp, initfunc)
   180  	initarray_entry := ld.Linklookup(ld.Ctxt, "go.link.addmoduledatainit", 0)
   181  	initarray_entry.Attr |= ld.AttrReachable
   182  	initarray_entry.Attr |= ld.AttrLocal
   183  	initarray_entry.Type = obj.SINITARR
   184  	ld.Addaddr(ld.Ctxt, initarray_entry, initfunc)
   185  }
   186  
   187  func gentext() {
   188  	if ld.DynlinkingGo() {
   189  		genaddmoduledata()
   190  	}
   191  
   192  	if ld.Linkmode == ld.LinkInternal {
   193  		genplt()
   194  	}
   195  }
   196  
   197  // Construct a call stub in stub that calls symbol targ via its PLT
   198  // entry.
   199  func gencallstub(abicase int, stub *ld.LSym, targ *ld.LSym) {
   200  	if abicase != 1 {
   201  		// If we see R_PPC64_TOCSAVE or R_PPC64_REL24_NOTOC
   202  		// relocations, we'll need to implement cases 2 and 3.
   203  		log.Fatalf("gencallstub only implements case 1 calls")
   204  	}
   205  
   206  	plt := ld.Linklookup(ld.Ctxt, ".plt", 0)
   207  
   208  	stub.Type = obj.STEXT
   209  
   210  	// Save TOC pointer in TOC save slot
   211  	ld.Adduint32(ld.Ctxt, stub, 0xf8410018) // std r2,24(r1)
   212  
   213  	// Load the function pointer from the PLT.
   214  	r := ld.Addrel(stub)
   215  
   216  	r.Off = int32(stub.Size)
   217  	r.Sym = plt
   218  	r.Add = int64(targ.Plt)
   219  	r.Siz = 2
   220  	if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
   221  		r.Off += int32(r.Siz)
   222  	}
   223  	r.Type = obj.R_POWER_TOC
   224  	r.Variant = ld.RV_POWER_HA
   225  	ld.Adduint32(ld.Ctxt, stub, 0x3d820000) // addis r12,r2,targ@plt@toc@ha
   226  	r = ld.Addrel(stub)
   227  	r.Off = int32(stub.Size)
   228  	r.Sym = plt
   229  	r.Add = int64(targ.Plt)
   230  	r.Siz = 2
   231  	if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
   232  		r.Off += int32(r.Siz)
   233  	}
   234  	r.Type = obj.R_POWER_TOC
   235  	r.Variant = ld.RV_POWER_LO
   236  	ld.Adduint32(ld.Ctxt, stub, 0xe98c0000) // ld r12,targ@plt@toc@l(r12)
   237  
   238  	// Jump to the loaded pointer
   239  	ld.Adduint32(ld.Ctxt, stub, 0x7d8903a6) // mtctr r12
   240  	ld.Adduint32(ld.Ctxt, stub, 0x4e800420) // bctr
   241  }
   242  
   243  func adddynrel(s *ld.LSym, r *ld.Reloc) {
   244  	targ := r.Sym
   245  	ld.Ctxt.Cursym = s
   246  
   247  	switch r.Type {
   248  	default:
   249  		if r.Type >= 256 {
   250  			ld.Diag("unexpected relocation type %d", r.Type)
   251  			return
   252  		}
   253  
   254  		// Handle relocations found in ELF object files.
   255  	case 256 + ld.R_PPC64_REL24:
   256  		r.Type = obj.R_CALLPOWER
   257  
   258  		// This is a local call, so the caller isn't setting
   259  		// up r12 and r2 is the same for the caller and
   260  		// callee. Hence, we need to go to the local entry
   261  		// point.  (If we don't do this, the callee will try
   262  		// to use r12 to compute r2.)
   263  		r.Add += int64(r.Sym.Localentry) * 4
   264  
   265  		if targ.Type == obj.SDYNIMPORT {
   266  			// Should have been handled in elfsetupplt
   267  			ld.Diag("unexpected R_PPC64_REL24 for dyn import")
   268  		}
   269  
   270  		return
   271  
   272  	case 256 + ld.R_PPC_REL32:
   273  		r.Type = obj.R_PCREL
   274  		r.Add += 4
   275  
   276  		if targ.Type == obj.SDYNIMPORT {
   277  			ld.Diag("unexpected R_PPC_REL32 for dyn import")
   278  		}
   279  
   280  		return
   281  
   282  	case 256 + ld.R_PPC64_ADDR64:
   283  		r.Type = obj.R_ADDR
   284  		if targ.Type == obj.SDYNIMPORT {
   285  			// These happen in .toc sections
   286  			ld.Adddynsym(ld.Ctxt, targ)
   287  
   288  			rela := ld.Linklookup(ld.Ctxt, ".rela", 0)
   289  			ld.Addaddrplus(ld.Ctxt, rela, s, int64(r.Off))
   290  			ld.Adduint64(ld.Ctxt, rela, ld.ELF64_R_INFO(uint32(targ.Dynid), ld.R_PPC64_ADDR64))
   291  			ld.Adduint64(ld.Ctxt, rela, uint64(r.Add))
   292  			r.Type = 256 // ignore during relocsym
   293  		}
   294  
   295  		return
   296  
   297  	case 256 + ld.R_PPC64_TOC16:
   298  		r.Type = obj.R_POWER_TOC
   299  		r.Variant = ld.RV_POWER_LO | ld.RV_CHECK_OVERFLOW
   300  		return
   301  
   302  	case 256 + ld.R_PPC64_TOC16_LO:
   303  		r.Type = obj.R_POWER_TOC
   304  		r.Variant = ld.RV_POWER_LO
   305  		return
   306  
   307  	case 256 + ld.R_PPC64_TOC16_HA:
   308  		r.Type = obj.R_POWER_TOC
   309  		r.Variant = ld.RV_POWER_HA | ld.RV_CHECK_OVERFLOW
   310  		return
   311  
   312  	case 256 + ld.R_PPC64_TOC16_HI:
   313  		r.Type = obj.R_POWER_TOC
   314  		r.Variant = ld.RV_POWER_HI | ld.RV_CHECK_OVERFLOW
   315  		return
   316  
   317  	case 256 + ld.R_PPC64_TOC16_DS:
   318  		r.Type = obj.R_POWER_TOC
   319  		r.Variant = ld.RV_POWER_DS | ld.RV_CHECK_OVERFLOW
   320  		return
   321  
   322  	case 256 + ld.R_PPC64_TOC16_LO_DS:
   323  		r.Type = obj.R_POWER_TOC
   324  		r.Variant = ld.RV_POWER_DS
   325  		return
   326  
   327  	case 256 + ld.R_PPC64_REL16_LO:
   328  		r.Type = obj.R_PCREL
   329  		r.Variant = ld.RV_POWER_LO
   330  		r.Add += 2 // Compensate for relocation size of 2
   331  		return
   332  
   333  	case 256 + ld.R_PPC64_REL16_HI:
   334  		r.Type = obj.R_PCREL
   335  		r.Variant = ld.RV_POWER_HI | ld.RV_CHECK_OVERFLOW
   336  		r.Add += 2
   337  		return
   338  
   339  	case 256 + ld.R_PPC64_REL16_HA:
   340  		r.Type = obj.R_PCREL
   341  		r.Variant = ld.RV_POWER_HA | ld.RV_CHECK_OVERFLOW
   342  		r.Add += 2
   343  		return
   344  	}
   345  
   346  	// Handle references to ELF symbols from our own object files.
   347  	if targ.Type != obj.SDYNIMPORT {
   348  		return
   349  	}
   350  
   351  	// TODO(austin): Translate our relocations to ELF
   352  
   353  	ld.Diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ.Name, r.Type, targ.Type)
   354  }
   355  
   356  func elfreloc1(r *ld.Reloc, sectoff int64) int {
   357  	ld.Thearch.Vput(uint64(sectoff))
   358  
   359  	elfsym := r.Xsym.ElfsymForReloc()
   360  	switch r.Type {
   361  	default:
   362  		return -1
   363  
   364  	case obj.R_ADDR:
   365  		switch r.Siz {
   366  		case 4:
   367  			ld.Thearch.Vput(ld.R_PPC64_ADDR32 | uint64(elfsym)<<32)
   368  		case 8:
   369  			ld.Thearch.Vput(ld.R_PPC64_ADDR64 | uint64(elfsym)<<32)
   370  		default:
   371  			return -1
   372  		}
   373  
   374  	case obj.R_POWER_TLS:
   375  		ld.Thearch.Vput(ld.R_PPC64_TLS | uint64(elfsym)<<32)
   376  
   377  	case obj.R_POWER_TLS_LE:
   378  		ld.Thearch.Vput(ld.R_PPC64_TPREL16 | uint64(elfsym)<<32)
   379  
   380  	case obj.R_POWER_TLS_IE:
   381  		ld.Thearch.Vput(ld.R_PPC64_GOT_TPREL16_HA | uint64(elfsym)<<32)
   382  		ld.Thearch.Vput(uint64(r.Xadd))
   383  		ld.Thearch.Vput(uint64(sectoff + 4))
   384  		ld.Thearch.Vput(ld.R_PPC64_GOT_TPREL16_LO_DS | uint64(elfsym)<<32)
   385  
   386  	case obj.R_ADDRPOWER:
   387  		ld.Thearch.Vput(ld.R_PPC64_ADDR16_HA | uint64(elfsym)<<32)
   388  		ld.Thearch.Vput(uint64(r.Xadd))
   389  		ld.Thearch.Vput(uint64(sectoff + 4))
   390  		ld.Thearch.Vput(ld.R_PPC64_ADDR16_LO | uint64(elfsym)<<32)
   391  
   392  	case obj.R_ADDRPOWER_DS:
   393  		ld.Thearch.Vput(ld.R_PPC64_ADDR16_HA | uint64(elfsym)<<32)
   394  		ld.Thearch.Vput(uint64(r.Xadd))
   395  		ld.Thearch.Vput(uint64(sectoff + 4))
   396  		ld.Thearch.Vput(ld.R_PPC64_ADDR16_LO_DS | uint64(elfsym)<<32)
   397  
   398  	case obj.R_ADDRPOWER_GOT:
   399  		ld.Thearch.Vput(ld.R_PPC64_GOT16_HA | uint64(elfsym)<<32)
   400  		ld.Thearch.Vput(uint64(r.Xadd))
   401  		ld.Thearch.Vput(uint64(sectoff + 4))
   402  		ld.Thearch.Vput(ld.R_PPC64_GOT16_LO_DS | uint64(elfsym)<<32)
   403  
   404  	case obj.R_ADDRPOWER_PCREL:
   405  		ld.Thearch.Vput(ld.R_PPC64_REL16_HA | uint64(elfsym)<<32)
   406  		ld.Thearch.Vput(uint64(r.Xadd))
   407  		ld.Thearch.Vput(uint64(sectoff + 4))
   408  		ld.Thearch.Vput(ld.R_PPC64_REL16_LO | uint64(elfsym)<<32)
   409  		r.Xadd += 4
   410  
   411  	case obj.R_ADDRPOWER_TOCREL:
   412  		ld.Thearch.Vput(ld.R_PPC64_TOC16_HA | uint64(elfsym)<<32)
   413  		ld.Thearch.Vput(uint64(r.Xadd))
   414  		ld.Thearch.Vput(uint64(sectoff + 4))
   415  		ld.Thearch.Vput(ld.R_PPC64_TOC16_LO | uint64(elfsym)<<32)
   416  
   417  	case obj.R_ADDRPOWER_TOCREL_DS:
   418  		ld.Thearch.Vput(ld.R_PPC64_TOC16_HA | uint64(elfsym)<<32)
   419  		ld.Thearch.Vput(uint64(r.Xadd))
   420  		ld.Thearch.Vput(uint64(sectoff + 4))
   421  		ld.Thearch.Vput(ld.R_PPC64_TOC16_LO_DS | uint64(elfsym)<<32)
   422  
   423  	case obj.R_CALLPOWER:
   424  		if r.Siz != 4 {
   425  			return -1
   426  		}
   427  		ld.Thearch.Vput(ld.R_PPC64_REL24 | uint64(elfsym)<<32)
   428  
   429  	}
   430  	ld.Thearch.Vput(uint64(r.Xadd))
   431  
   432  	return 0
   433  }
   434  
   435  func elfsetupplt() {
   436  	plt := ld.Linklookup(ld.Ctxt, ".plt", 0)
   437  	if plt.Size == 0 {
   438  		// The dynamic linker stores the address of the
   439  		// dynamic resolver and the DSO identifier in the two
   440  		// doublewords at the beginning of the .plt section
   441  		// before the PLT array. Reserve space for these.
   442  		plt.Size = 16
   443  	}
   444  }
   445  
   446  func machoreloc1(r *ld.Reloc, sectoff int64) int {
   447  	return -1
   448  }
   449  
   450  // Return the value of .TOC. for symbol s
   451  func symtoc(s *ld.LSym) int64 {
   452  	var toc *ld.LSym
   453  
   454  	if s.Outer != nil {
   455  		toc = ld.Linkrlookup(ld.Ctxt, ".TOC.", int(s.Outer.Version))
   456  	} else {
   457  		toc = ld.Linkrlookup(ld.Ctxt, ".TOC.", int(s.Version))
   458  	}
   459  
   460  	if toc == nil {
   461  		ld.Diag("TOC-relative relocation in object without .TOC.")
   462  		return 0
   463  	}
   464  
   465  	return toc.Value
   466  }
   467  
   468  func archrelocaddr(r *ld.Reloc, s *ld.LSym, val *int64) int {
   469  	var o1, o2 uint32
   470  	if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
   471  		o1 = uint32(*val >> 32)
   472  		o2 = uint32(*val)
   473  	} else {
   474  		o1 = uint32(*val)
   475  		o2 = uint32(*val >> 32)
   476  	}
   477  
   478  	// We are spreading a 31-bit address across two instructions, putting the
   479  	// high (adjusted) part in the low 16 bits of the first instruction and the
   480  	// low part in the low 16 bits of the second instruction, or, in the DS case,
   481  	// bits 15-2 (inclusive) of the address into bits 15-2 of the second
   482  	// instruction (it is an error in this case if the low 2 bits of the address
   483  	// are non-zero).
   484  
   485  	t := ld.Symaddr(r.Sym) + r.Add
   486  	if t < 0 || t >= 1<<31 {
   487  		ld.Ctxt.Diag("relocation for %s is too big (>=2G): %d", s.Name, ld.Symaddr(r.Sym))
   488  	}
   489  	if t&0x8000 != 0 {
   490  		t += 0x10000
   491  	}
   492  
   493  	switch r.Type {
   494  	case obj.R_ADDRPOWER:
   495  		o1 |= (uint32(t) >> 16) & 0xffff
   496  		o2 |= uint32(t) & 0xffff
   497  
   498  	case obj.R_ADDRPOWER_DS:
   499  		o1 |= (uint32(t) >> 16) & 0xffff
   500  		if t&3 != 0 {
   501  			ld.Ctxt.Diag("bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym))
   502  		}
   503  		o2 |= uint32(t) & 0xfffc
   504  
   505  	default:
   506  		return -1
   507  	}
   508  
   509  	if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
   510  		*val = int64(o1)<<32 | int64(o2)
   511  	} else {
   512  		*val = int64(o2)<<32 | int64(o1)
   513  	}
   514  	return 0
   515  }
   516  
   517  func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
   518  	if ld.Linkmode == ld.LinkExternal {
   519  		switch r.Type {
   520  		default:
   521  			return -1
   522  
   523  		case obj.R_POWER_TLS, obj.R_POWER_TLS_LE, obj.R_POWER_TLS_IE:
   524  			r.Done = 0
   525  			// check Outer is nil, Type is TLSBSS?
   526  			r.Xadd = r.Add
   527  			r.Xsym = r.Sym
   528  			return 0
   529  
   530  		case obj.R_ADDRPOWER,
   531  			obj.R_ADDRPOWER_DS,
   532  			obj.R_ADDRPOWER_TOCREL,
   533  			obj.R_ADDRPOWER_TOCREL_DS,
   534  			obj.R_ADDRPOWER_GOT,
   535  			obj.R_ADDRPOWER_PCREL:
   536  			r.Done = 0
   537  
   538  			// set up addend for eventual relocation via outer symbol.
   539  			rs := r.Sym
   540  			r.Xadd = r.Add
   541  			for rs.Outer != nil {
   542  				r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
   543  				rs = rs.Outer
   544  			}
   545  
   546  			if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil {
   547  				ld.Diag("missing section for %s", rs.Name)
   548  			}
   549  			r.Xsym = rs
   550  
   551  			return 0
   552  
   553  		case obj.R_CALLPOWER:
   554  			r.Done = 0
   555  			r.Xsym = r.Sym
   556  			r.Xadd = r.Add
   557  			return 0
   558  		}
   559  	}
   560  
   561  	switch r.Type {
   562  	case obj.R_CONST:
   563  		*val = r.Add
   564  		return 0
   565  
   566  	case obj.R_GOTOFF:
   567  		*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ld.Linklookup(ld.Ctxt, ".got", 0))
   568  		return 0
   569  
   570  	case obj.R_ADDRPOWER, obj.R_ADDRPOWER_DS:
   571  		return archrelocaddr(r, s, val)
   572  
   573  	case obj.R_CALLPOWER:
   574  		// Bits 6 through 29 = (S + A - P) >> 2
   575  
   576  		t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off))
   577  		if t&3 != 0 {
   578  			ld.Ctxt.Diag("relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t)
   579  		}
   580  		if int64(int32(t<<6)>>6) != t {
   581  			// TODO(austin) This can happen if text > 32M.
   582  			// Add a call trampoline to .text in that case.
   583  			ld.Ctxt.Diag("relocation for %s+%d is too big: %d", r.Sym.Name, r.Off, t)
   584  		}
   585  
   586  		*val |= int64(uint32(t) &^ 0xfc000003)
   587  		return 0
   588  
   589  	case obj.R_POWER_TOC: // S + A - .TOC.
   590  		*val = ld.Symaddr(r.Sym) + r.Add - symtoc(s)
   591  
   592  		return 0
   593  
   594  	case obj.R_POWER_TLS_LE:
   595  		// The thread pointer points 0x7000 bytes after the start of the the
   596  		// thread local storage area as documented in section "3.7.2 TLS
   597  		// Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI
   598  		// Specification".
   599  		v := r.Sym.Value - 0x7000
   600  		if int64(int16(v)) != v {
   601  			ld.Diag("TLS offset out of range %d", v)
   602  		}
   603  		*val = (*val &^ 0xffff) | (v & 0xffff)
   604  		return 0
   605  	}
   606  
   607  	return -1
   608  }
   609  
   610  func archrelocvariant(r *ld.Reloc, s *ld.LSym, t int64) int64 {
   611  	switch r.Variant & ld.RV_TYPE_MASK {
   612  	default:
   613  		ld.Diag("unexpected relocation variant %d", r.Variant)
   614  		fallthrough
   615  
   616  	case ld.RV_NONE:
   617  		return t
   618  
   619  	case ld.RV_POWER_LO:
   620  		if r.Variant&ld.RV_CHECK_OVERFLOW != 0 {
   621  			// Whether to check for signed or unsigned
   622  			// overflow depends on the instruction
   623  			var o1 uint32
   624  			if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
   625  				o1 = ld.Be32(s.P[r.Off-2:])
   626  			} else {
   627  				o1 = ld.Le32(s.P[r.Off:])
   628  			}
   629  			switch o1 >> 26 {
   630  			case 24, // ori
   631  				26, // xori
   632  				28: // andi
   633  				if t>>16 != 0 {
   634  					goto overflow
   635  				}
   636  
   637  			default:
   638  				if int64(int16(t)) != t {
   639  					goto overflow
   640  				}
   641  			}
   642  		}
   643  
   644  		return int64(int16(t))
   645  
   646  	case ld.RV_POWER_HA:
   647  		t += 0x8000
   648  		fallthrough
   649  
   650  		// Fallthrough
   651  	case ld.RV_POWER_HI:
   652  		t >>= 16
   653  
   654  		if r.Variant&ld.RV_CHECK_OVERFLOW != 0 {
   655  			// Whether to check for signed or unsigned
   656  			// overflow depends on the instruction
   657  			var o1 uint32
   658  			if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
   659  				o1 = ld.Be32(s.P[r.Off-2:])
   660  			} else {
   661  				o1 = ld.Le32(s.P[r.Off:])
   662  			}
   663  			switch o1 >> 26 {
   664  			case 25, // oris
   665  				27, // xoris
   666  				29: // andis
   667  				if t>>16 != 0 {
   668  					goto overflow
   669  				}
   670  
   671  			default:
   672  				if int64(int16(t)) != t {
   673  					goto overflow
   674  				}
   675  			}
   676  		}
   677  
   678  		return int64(int16(t))
   679  
   680  	case ld.RV_POWER_DS:
   681  		var o1 uint32
   682  		if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
   683  			o1 = uint32(ld.Be16(s.P[r.Off:]))
   684  		} else {
   685  			o1 = uint32(ld.Le16(s.P[r.Off:]))
   686  		}
   687  		if t&3 != 0 {
   688  			ld.Diag("relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t)
   689  		}
   690  		if (r.Variant&ld.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t {
   691  			goto overflow
   692  		}
   693  		return int64(o1)&0x3 | int64(int16(t))
   694  	}
   695  
   696  overflow:
   697  	ld.Diag("relocation for %s+%d is too big: %d", r.Sym.Name, r.Off, t)
   698  	return t
   699  }
   700  
   701  func addpltsym(ctxt *ld.Link, s *ld.LSym) {
   702  	if s.Plt >= 0 {
   703  		return
   704  	}
   705  
   706  	ld.Adddynsym(ctxt, s)
   707  
   708  	if ld.Iself {
   709  		plt := ld.Linklookup(ctxt, ".plt", 0)
   710  		rela := ld.Linklookup(ctxt, ".rela.plt", 0)
   711  		if plt.Size == 0 {
   712  			elfsetupplt()
   713  		}
   714  
   715  		// Create the glink resolver if necessary
   716  		glink := ensureglinkresolver()
   717  
   718  		// Write symbol resolver stub (just a branch to the
   719  		// glink resolver stub)
   720  		r := ld.Addrel(glink)
   721  
   722  		r.Sym = glink
   723  		r.Off = int32(glink.Size)
   724  		r.Siz = 4
   725  		r.Type = obj.R_CALLPOWER
   726  		ld.Adduint32(ctxt, glink, 0x48000000) // b .glink
   727  
   728  		// In the ppc64 ABI, the dynamic linker is responsible
   729  		// for writing the entire PLT.  We just need to
   730  		// reserve 8 bytes for each PLT entry and generate a
   731  		// JMP_SLOT dynamic relocation for it.
   732  		//
   733  		// TODO(austin): ABI v1 is different
   734  		s.Plt = int32(plt.Size)
   735  
   736  		plt.Size += 8
   737  
   738  		ld.Addaddrplus(ctxt, rela, plt, int64(s.Plt))
   739  		ld.Adduint64(ctxt, rela, ld.ELF64_R_INFO(uint32(s.Dynid), ld.R_PPC64_JMP_SLOT))
   740  		ld.Adduint64(ctxt, rela, 0)
   741  	} else {
   742  		ld.Diag("addpltsym: unsupported binary format")
   743  	}
   744  }
   745  
   746  // Generate the glink resolver stub if necessary and return the .glink section
   747  func ensureglinkresolver() *ld.LSym {
   748  	glink := ld.Linklookup(ld.Ctxt, ".glink", 0)
   749  	if glink.Size != 0 {
   750  		return glink
   751  	}
   752  
   753  	// This is essentially the resolver from the ppc64 ELF ABI.
   754  	// At entry, r12 holds the address of the symbol resolver stub
   755  	// for the target routine and the argument registers hold the
   756  	// arguments for the target routine.
   757  	//
   758  	// This stub is PIC, so first get the PC of label 1 into r11.
   759  	// Other things will be relative to this.
   760  	ld.Adduint32(ld.Ctxt, glink, 0x7c0802a6) // mflr r0
   761  	ld.Adduint32(ld.Ctxt, glink, 0x429f0005) // bcl 20,31,1f
   762  	ld.Adduint32(ld.Ctxt, glink, 0x7d6802a6) // 1: mflr r11
   763  	ld.Adduint32(ld.Ctxt, glink, 0x7c0803a6) // mtlf r0
   764  
   765  	// Compute the .plt array index from the entry point address.
   766  	// Because this is PIC, everything is relative to label 1b (in
   767  	// r11):
   768  	//   r0 = ((r12 - r11) - (res_0 - r11)) / 4 = (r12 - res_0) / 4
   769  	ld.Adduint32(ld.Ctxt, glink, 0x3800ffd0) // li r0,-(res_0-1b)=-48
   770  	ld.Adduint32(ld.Ctxt, glink, 0x7c006214) // add r0,r0,r12
   771  	ld.Adduint32(ld.Ctxt, glink, 0x7c0b0050) // sub r0,r0,r11
   772  	ld.Adduint32(ld.Ctxt, glink, 0x7800f082) // srdi r0,r0,2
   773  
   774  	// r11 = address of the first byte of the PLT
   775  	r := ld.Addrel(glink)
   776  
   777  	r.Off = int32(glink.Size)
   778  	r.Sym = ld.Linklookup(ld.Ctxt, ".plt", 0)
   779  	r.Siz = 8
   780  	r.Type = obj.R_ADDRPOWER
   781  
   782  	ld.Adduint32(ld.Ctxt, glink, 0x3d600000) // addis r11,0,.plt@ha
   783  	ld.Adduint32(ld.Ctxt, glink, 0x396b0000) // addi r11,r11,.plt@l
   784  
   785  	// Load r12 = dynamic resolver address and r11 = DSO
   786  	// identifier from the first two doublewords of the PLT.
   787  	ld.Adduint32(ld.Ctxt, glink, 0xe98b0000) // ld r12,0(r11)
   788  	ld.Adduint32(ld.Ctxt, glink, 0xe96b0008) // ld r11,8(r11)
   789  
   790  	// Jump to the dynamic resolver
   791  	ld.Adduint32(ld.Ctxt, glink, 0x7d8903a6) // mtctr r12
   792  	ld.Adduint32(ld.Ctxt, glink, 0x4e800420) // bctr
   793  
   794  	// The symbol resolvers must immediately follow.
   795  	//   res_0:
   796  
   797  	// Add DT_PPC64_GLINK .dynamic entry, which points to 32 bytes
   798  	// before the first symbol resolver stub.
   799  	s := ld.Linklookup(ld.Ctxt, ".dynamic", 0)
   800  
   801  	ld.Elfwritedynentsymplus(s, ld.DT_PPC64_GLINK, glink, glink.Size-32)
   802  
   803  	return glink
   804  }
   805  
   806  func asmb() {
   807  	if ld.Debug['v'] != 0 {
   808  		fmt.Fprintf(ld.Bso, "%5.2f asmb\n", obj.Cputime())
   809  	}
   810  	ld.Bso.Flush()
   811  
   812  	if ld.Iself {
   813  		ld.Asmbelfsetup()
   814  	}
   815  
   816  	sect := ld.Segtext.Sect
   817  	ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
   818  	ld.Codeblk(int64(sect.Vaddr), int64(sect.Length))
   819  	for sect = sect.Next; sect != nil; sect = sect.Next {
   820  		ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
   821  		ld.Datblk(int64(sect.Vaddr), int64(sect.Length))
   822  	}
   823  
   824  	if ld.Segrodata.Filelen > 0 {
   825  		if ld.Debug['v'] != 0 {
   826  			fmt.Fprintf(ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
   827  		}
   828  		ld.Bso.Flush()
   829  
   830  		ld.Cseek(int64(ld.Segrodata.Fileoff))
   831  		ld.Datblk(int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
   832  	}
   833  
   834  	if ld.Debug['v'] != 0 {
   835  		fmt.Fprintf(ld.Bso, "%5.2f datblk\n", obj.Cputime())
   836  	}
   837  	ld.Bso.Flush()
   838  
   839  	ld.Cseek(int64(ld.Segdata.Fileoff))
   840  	ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
   841  
   842  	ld.Cseek(int64(ld.Segdwarf.Fileoff))
   843  	ld.Dwarfblk(int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
   844  
   845  	/* output symbol table */
   846  	ld.Symsize = 0
   847  
   848  	ld.Lcsize = 0
   849  	symo := uint32(0)
   850  	if ld.Debug['s'] == 0 {
   851  		// TODO: rationalize
   852  		if ld.Debug['v'] != 0 {
   853  			fmt.Fprintf(ld.Bso, "%5.2f sym\n", obj.Cputime())
   854  		}
   855  		ld.Bso.Flush()
   856  		switch ld.HEADTYPE {
   857  		default:
   858  			if ld.Iself {
   859  				symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
   860  				symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND)))
   861  			}
   862  
   863  		case obj.Hplan9:
   864  			symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
   865  		}
   866  
   867  		ld.Cseek(int64(symo))
   868  		switch ld.HEADTYPE {
   869  		default:
   870  			if ld.Iself {
   871  				if ld.Debug['v'] != 0 {
   872  					fmt.Fprintf(ld.Bso, "%5.2f elfsym\n", obj.Cputime())
   873  				}
   874  				ld.Asmelfsym()
   875  				ld.Cflush()
   876  				ld.Cwrite(ld.Elfstrdat)
   877  
   878  				if ld.Linkmode == ld.LinkExternal {
   879  					ld.Elfemitreloc()
   880  				}
   881  			}
   882  
   883  		case obj.Hplan9:
   884  			ld.Asmplan9sym()
   885  			ld.Cflush()
   886  
   887  			sym := ld.Linklookup(ld.Ctxt, "pclntab", 0)
   888  			if sym != nil {
   889  				ld.Lcsize = int32(len(sym.P))
   890  				for i := 0; int32(i) < ld.Lcsize; i++ {
   891  					ld.Cput(sym.P[i])
   892  				}
   893  
   894  				ld.Cflush()
   895  			}
   896  		}
   897  	}
   898  
   899  	ld.Ctxt.Cursym = nil
   900  	if ld.Debug['v'] != 0 {
   901  		fmt.Fprintf(ld.Bso, "%5.2f header\n", obj.Cputime())
   902  	}
   903  	ld.Bso.Flush()
   904  	ld.Cseek(0)
   905  	switch ld.HEADTYPE {
   906  	default:
   907  	case obj.Hplan9: /* plan 9 */
   908  		ld.Thearch.Lput(0x647)                      /* magic */
   909  		ld.Thearch.Lput(uint32(ld.Segtext.Filelen)) /* sizes */
   910  		ld.Thearch.Lput(uint32(ld.Segdata.Filelen))
   911  		ld.Thearch.Lput(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
   912  		ld.Thearch.Lput(uint32(ld.Symsize))      /* nsyms */
   913  		ld.Thearch.Lput(uint32(ld.Entryvalue())) /* va of entry */
   914  		ld.Thearch.Lput(0)
   915  		ld.Thearch.Lput(uint32(ld.Lcsize))
   916  
   917  	case obj.Hlinux,
   918  		obj.Hfreebsd,
   919  		obj.Hnetbsd,
   920  		obj.Hopenbsd,
   921  		obj.Hnacl:
   922  		ld.Asmbelf(int64(symo))
   923  	}
   924  
   925  	ld.Cflush()
   926  	if ld.Debug['c'] != 0 {
   927  		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
   928  		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
   929  		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
   930  		fmt.Printf("symsize=%d\n", ld.Symsize)
   931  		fmt.Printf("lcsize=%d\n", ld.Lcsize)
   932  		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
   933  	}
   934  }