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