...

Source file src/pkg/cmd/link/internal/ppc64/asm.go

     1	// Inferno utils/5l/asm.c
     2	// https://bitbucket.org/inferno-os/inferno-os/src/default/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/objabi"
    35		"cmd/internal/sys"
    36		"cmd/link/internal/ld"
    37		"cmd/link/internal/sym"
    38		"debug/elf"
    39		"encoding/binary"
    40		"fmt"
    41		"log"
    42		"strings"
    43	)
    44	
    45	func genplt(ctxt *ld.Link) {
    46		// The ppc64 ABI PLT has similar concepts to other
    47		// architectures, but is laid out quite differently. When we
    48		// see an R_PPC64_REL24 relocation to a dynamic symbol
    49		// (indicating that the call needs to go through the PLT), we
    50		// generate up to three stubs and reserve a PLT slot.
    51		//
    52		// 1) The call site will be bl x; nop (where the relocation
    53		//    applies to the bl).  We rewrite this to bl x_stub; ld
    54		//    r2,24(r1).  The ld is necessary because x_stub will save
    55		//    r2 (the TOC pointer) at 24(r1) (the "TOC save slot").
    56		//
    57		// 2) We reserve space for a pointer in the .plt section (once
    58		//    per referenced dynamic function).  .plt is a data
    59		//    section filled solely by the dynamic linker (more like
    60		//    .plt.got on other architectures).  Initially, the
    61		//    dynamic linker will fill each slot with a pointer to the
    62		//    corresponding x@plt entry point.
    63		//
    64		// 3) We generate the "call stub" x_stub (once per dynamic
    65		//    function/object file pair).  This saves the TOC in the
    66		//    TOC save slot, reads the function pointer from x's .plt
    67		//    slot and calls it like any other global entry point
    68		//    (including setting r12 to the function address).
    69		//
    70		// 4) We generate the "symbol resolver stub" x@plt (once per
    71		//    dynamic function).  This is solely a branch to the glink
    72		//    resolver stub.
    73		//
    74		// 5) We generate the glink resolver stub (only once).  This
    75		//    computes which symbol resolver stub we came through and
    76		//    invokes the dynamic resolver via a pointer provided by
    77		//    the dynamic linker. This will patch up the .plt slot to
    78		//    point directly at the function so future calls go
    79		//    straight from the call stub to the real function, and
    80		//    then call the function.
    81	
    82		// NOTE: It's possible we could make ppc64 closer to other
    83		// architectures: ppc64's .plt is like .plt.got on other
    84		// platforms and ppc64's .glink is like .plt on other
    85		// platforms.
    86	
    87		// Find all R_PPC64_REL24 relocations that reference dynamic
    88		// imports. Reserve PLT entries for these symbols and
    89		// generate call stubs. The call stubs need to live in .text,
    90		// which is why we need to do this pass this early.
    91		//
    92		// This assumes "case 1" from the ABI, where the caller needs
    93		// us to save and restore the TOC pointer.
    94		var stubs []*sym.Symbol
    95		for _, s := range ctxt.Textp {
    96			for i := range s.R {
    97				r := &s.R[i]
    98				if r.Type != objabi.ElfRelocOffset+objabi.RelocType(elf.R_PPC64_REL24) || r.Sym.Type != sym.SDYNIMPORT {
    99					continue
   100				}
   101	
   102				// Reserve PLT entry and generate symbol
   103				// resolver
   104				addpltsym(ctxt, r.Sym)
   105	
   106				// Generate call stub
   107				n := fmt.Sprintf("%s.%s", s.Name, r.Sym.Name)
   108	
   109				stub := ctxt.Syms.Lookup(n, 0)
   110				if s.Attr.Reachable() {
   111					stub.Attr |= sym.AttrReachable
   112				}
   113				if stub.Size == 0 {
   114					// Need outer to resolve .TOC.
   115					stub.Outer = s
   116					stubs = append(stubs, stub)
   117					gencallstub(ctxt, 1, stub, r.Sym)
   118				}
   119	
   120				// Update the relocation to use the call stub
   121				r.Sym = stub
   122	
   123				// Restore TOC after bl. The compiler put a
   124				// nop here for us to overwrite.
   125				const o1 = 0xe8410018 // ld r2,24(r1)
   126				ctxt.Arch.ByteOrder.PutUint32(s.P[r.Off+4:], o1)
   127			}
   128		}
   129		// Put call stubs at the beginning (instead of the end).
   130		// So when resolving the relocations to calls to the stubs,
   131		// the addresses are known and trampolines can be inserted
   132		// when necessary.
   133		ctxt.Textp = append(stubs, ctxt.Textp...)
   134	}
   135	
   136	func genaddmoduledata(ctxt *ld.Link) {
   137		addmoduledata := ctxt.Syms.ROLookup("runtime.addmoduledata", sym.SymVerABI0)
   138		if addmoduledata.Type == sym.STEXT && ctxt.BuildMode != ld.BuildModePlugin {
   139			return
   140		}
   141		addmoduledata.Attr |= sym.AttrReachable
   142		initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
   143		initfunc.Type = sym.STEXT
   144		initfunc.Attr |= sym.AttrLocal
   145		initfunc.Attr |= sym.AttrReachable
   146		o := func(op uint32) {
   147			initfunc.AddUint32(ctxt.Arch, op)
   148		}
   149		// addis r2, r12, .TOC.-func@ha
   150		rel := initfunc.AddRel()
   151		rel.Off = int32(initfunc.Size)
   152		rel.Siz = 8
   153		rel.Sym = ctxt.Syms.Lookup(".TOC.", 0)
   154		rel.Sym.Attr |= sym.AttrReachable
   155		rel.Type = objabi.R_ADDRPOWER_PCREL
   156		o(0x3c4c0000)
   157		// addi r2, r2, .TOC.-func@l
   158		o(0x38420000)
   159		// mflr r31
   160		o(0x7c0802a6)
   161		// stdu r31, -32(r1)
   162		o(0xf801ffe1)
   163		// addis r3, r2, local.moduledata@got@ha
   164		rel = initfunc.AddRel()
   165		rel.Off = int32(initfunc.Size)
   166		rel.Siz = 8
   167		if s := ctxt.Syms.ROLookup("local.moduledata", 0); s != nil {
   168			rel.Sym = s
   169		} else if s := ctxt.Syms.ROLookup("local.pluginmoduledata", 0); s != nil {
   170			rel.Sym = s
   171		} else {
   172			rel.Sym = ctxt.Syms.Lookup("runtime.firstmoduledata", 0)
   173		}
   174		rel.Sym.Attr |= sym.AttrReachable
   175		rel.Sym.Attr |= sym.AttrLocal
   176		rel.Type = objabi.R_ADDRPOWER_GOT
   177		o(0x3c620000)
   178		// ld r3, local.moduledata@got@l(r3)
   179		o(0xe8630000)
   180		// bl runtime.addmoduledata
   181		rel = initfunc.AddRel()
   182		rel.Off = int32(initfunc.Size)
   183		rel.Siz = 4
   184		rel.Sym = addmoduledata
   185		rel.Type = objabi.R_CALLPOWER
   186		o(0x48000001)
   187		// nop
   188		o(0x60000000)
   189		// ld r31, 0(r1)
   190		o(0xe8010000)
   191		// mtlr r31
   192		o(0x7c0803a6)
   193		// addi r1,r1,32
   194		o(0x38210020)
   195		// blr
   196		o(0x4e800020)
   197	
   198		if ctxt.BuildMode == ld.BuildModePlugin {
   199			ctxt.Textp = append(ctxt.Textp, addmoduledata)
   200		}
   201		initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
   202		ctxt.Textp = append(ctxt.Textp, initfunc)
   203		initarray_entry.Attr |= sym.AttrReachable
   204		initarray_entry.Attr |= sym.AttrLocal
   205		initarray_entry.Type = sym.SINITARR
   206		initarray_entry.AddAddr(ctxt.Arch, initfunc)
   207	}
   208	
   209	func gentext(ctxt *ld.Link) {
   210		if ctxt.DynlinkingGo() {
   211			genaddmoduledata(ctxt)
   212		}
   213	
   214		if ctxt.LinkMode == ld.LinkInternal {
   215			genplt(ctxt)
   216		}
   217	}
   218	
   219	// Construct a call stub in stub that calls symbol targ via its PLT
   220	// entry.
   221	func gencallstub(ctxt *ld.Link, abicase int, stub *sym.Symbol, targ *sym.Symbol) {
   222		if abicase != 1 {
   223			// If we see R_PPC64_TOCSAVE or R_PPC64_REL24_NOTOC
   224			// relocations, we'll need to implement cases 2 and 3.
   225			log.Fatalf("gencallstub only implements case 1 calls")
   226		}
   227	
   228		plt := ctxt.Syms.Lookup(".plt", 0)
   229	
   230		stub.Type = sym.STEXT
   231	
   232		// Save TOC pointer in TOC save slot
   233		stub.AddUint32(ctxt.Arch, 0xf8410018) // std r2,24(r1)
   234	
   235		// Load the function pointer from the PLT.
   236		r := stub.AddRel()
   237	
   238		r.Off = int32(stub.Size)
   239		r.Sym = plt
   240		r.Add = int64(targ.Plt())
   241		r.Siz = 2
   242		if ctxt.Arch.ByteOrder == binary.BigEndian {
   243			r.Off += int32(r.Siz)
   244		}
   245		r.Type = objabi.R_POWER_TOC
   246		r.Variant = sym.RV_POWER_HA
   247		stub.AddUint32(ctxt.Arch, 0x3d820000) // addis r12,r2,targ@plt@toc@ha
   248		r = stub.AddRel()
   249		r.Off = int32(stub.Size)
   250		r.Sym = plt
   251		r.Add = int64(targ.Plt())
   252		r.Siz = 2
   253		if ctxt.Arch.ByteOrder == binary.BigEndian {
   254			r.Off += int32(r.Siz)
   255		}
   256		r.Type = objabi.R_POWER_TOC
   257		r.Variant = sym.RV_POWER_LO
   258		stub.AddUint32(ctxt.Arch, 0xe98c0000) // ld r12,targ@plt@toc@l(r12)
   259	
   260		// Jump to the loaded pointer
   261		stub.AddUint32(ctxt.Arch, 0x7d8903a6) // mtctr r12
   262		stub.AddUint32(ctxt.Arch, 0x4e800420) // bctr
   263	}
   264	
   265	func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
   266		if ctxt.IsELF {
   267			return addelfdynrel(ctxt, s, r)
   268		} else if ctxt.HeadType == objabi.Haix {
   269			return ld.Xcoffadddynrel(ctxt, s, r)
   270		}
   271		return false
   272	}
   273	func addelfdynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
   274		targ := r.Sym
   275		r.InitExt()
   276	
   277		switch r.Type {
   278		default:
   279			if r.Type >= objabi.ElfRelocOffset {
   280				ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
   281				return false
   282			}
   283	
   284			// Handle relocations found in ELF object files.
   285		case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24):
   286			r.Type = objabi.R_CALLPOWER
   287	
   288			// This is a local call, so the caller isn't setting
   289			// up r12 and r2 is the same for the caller and
   290			// callee. Hence, we need to go to the local entry
   291			// point.  (If we don't do this, the callee will try
   292			// to use r12 to compute r2.)
   293			r.Add += int64(r.Sym.Localentry()) * 4
   294	
   295			if targ.Type == sym.SDYNIMPORT {
   296				// Should have been handled in elfsetupplt
   297				ld.Errorf(s, "unexpected R_PPC64_REL24 for dyn import")
   298			}
   299	
   300			return true
   301	
   302		case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC_REL32):
   303			r.Type = objabi.R_PCREL
   304			r.Add += 4
   305	
   306			if targ.Type == sym.SDYNIMPORT {
   307				ld.Errorf(s, "unexpected R_PPC_REL32 for dyn import")
   308			}
   309	
   310			return true
   311	
   312		case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_ADDR64):
   313			r.Type = objabi.R_ADDR
   314			if targ.Type == sym.SDYNIMPORT {
   315				// These happen in .toc sections
   316				ld.Adddynsym(ctxt, targ)
   317	
   318				rela := ctxt.Syms.Lookup(".rela", 0)
   319				rela.AddAddrPlus(ctxt.Arch, s, int64(r.Off))
   320				rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(targ.Dynid), uint32(elf.R_PPC64_ADDR64)))
   321				rela.AddUint64(ctxt.Arch, uint64(r.Add))
   322				r.Type = objabi.ElfRelocOffset // ignore during relocsym
   323			}
   324	
   325			return true
   326	
   327		case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16):
   328			r.Type = objabi.R_POWER_TOC
   329			r.Variant = sym.RV_POWER_LO | sym.RV_CHECK_OVERFLOW
   330			return true
   331	
   332		case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO):
   333			r.Type = objabi.R_POWER_TOC
   334			r.Variant = sym.RV_POWER_LO
   335			return true
   336	
   337		case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HA):
   338			r.Type = objabi.R_POWER_TOC
   339			r.Variant = sym.RV_POWER_HA | sym.RV_CHECK_OVERFLOW
   340			return true
   341	
   342		case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HI):
   343			r.Type = objabi.R_POWER_TOC
   344			r.Variant = sym.RV_POWER_HI | sym.RV_CHECK_OVERFLOW
   345			return true
   346	
   347		case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_DS):
   348			r.Type = objabi.R_POWER_TOC
   349			r.Variant = sym.RV_POWER_DS | sym.RV_CHECK_OVERFLOW
   350			return true
   351	
   352		case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO_DS):
   353			r.Type = objabi.R_POWER_TOC
   354			r.Variant = sym.RV_POWER_DS
   355			return true
   356	
   357		case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_LO):
   358			r.Type = objabi.R_PCREL
   359			r.Variant = sym.RV_POWER_LO
   360			r.Add += 2 // Compensate for relocation size of 2
   361			return true
   362	
   363		case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HI):
   364			r.Type = objabi.R_PCREL
   365			r.Variant = sym.RV_POWER_HI | sym.RV_CHECK_OVERFLOW
   366			r.Add += 2
   367			return true
   368	
   369		case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HA):
   370			r.Type = objabi.R_PCREL
   371			r.Variant = sym.RV_POWER_HA | sym.RV_CHECK_OVERFLOW
   372			r.Add += 2
   373			return true
   374		}
   375	
   376		// Handle references to ELF symbols from our own object files.
   377		if targ.Type != sym.SDYNIMPORT {
   378			return true
   379		}
   380	
   381		// TODO(austin): Translate our relocations to ELF
   382	
   383		return false
   384	}
   385	
   386	func xcoffreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
   387		rs := r.Xsym
   388	
   389		emitReloc := func(v uint16, off uint64) {
   390			out.Write64(uint64(sectoff) + off)
   391			out.Write32(uint32(rs.Dynid))
   392			out.Write16(v)
   393		}
   394	
   395		var v uint16
   396		switch r.Type {
   397		default:
   398			return false
   399		case objabi.R_ADDR:
   400			v = ld.XCOFF_R_POS
   401			if r.Siz == 4 {
   402				v |= 0x1F << 8
   403			} else {
   404				v |= 0x3F << 8
   405			}
   406			emitReloc(v, 0)
   407		case objabi.R_ADDRPOWER_TOCREL:
   408		case objabi.R_ADDRPOWER_TOCREL_DS:
   409			emitReloc(ld.XCOFF_R_TOCU|(0x0F<<8), 2)
   410			emitReloc(ld.XCOFF_R_TOCL|(0x0F<<8), 6)
   411		case objabi.R_POWER_TLS_LE:
   412			emitReloc(ld.XCOFF_R_TLS_LE|0x0F<<8, 2)
   413		case objabi.R_CALLPOWER:
   414			if r.Siz != 4 {
   415				return false
   416			}
   417			emitReloc(ld.XCOFF_R_RBR|0x19<<8, 0)
   418		case objabi.R_XCOFFREF:
   419			emitReloc(ld.XCOFF_R_REF|0x3F<<8, 0)
   420	
   421		}
   422		return true
   423	
   424	}
   425	
   426	func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
   427		// Beware that bit0~bit15 start from the third byte of a instruction in Big-Endian machines.
   428		if r.Type == objabi.R_ADDR || r.Type == objabi.R_POWER_TLS || r.Type == objabi.R_CALLPOWER {
   429		} else {
   430			if ctxt.Arch.ByteOrder == binary.BigEndian {
   431				sectoff += 2
   432			}
   433		}
   434		ctxt.Out.Write64(uint64(sectoff))
   435	
   436		elfsym := r.Xsym.ElfsymForReloc()
   437		switch r.Type {
   438		default:
   439			return false
   440		case objabi.R_ADDR:
   441			switch r.Siz {
   442			case 4:
   443				ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR32) | uint64(elfsym)<<32)
   444			case 8:
   445				ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR64) | uint64(elfsym)<<32)
   446			default:
   447				return false
   448			}
   449		case objabi.R_POWER_TLS:
   450			ctxt.Out.Write64(uint64(elf.R_PPC64_TLS) | uint64(elfsym)<<32)
   451		case objabi.R_POWER_TLS_LE:
   452			ctxt.Out.Write64(uint64(elf.R_PPC64_TPREL16) | uint64(elfsym)<<32)
   453		case objabi.R_POWER_TLS_IE:
   454			ctxt.Out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_HA) | uint64(elfsym)<<32)
   455			ctxt.Out.Write64(uint64(r.Xadd))
   456			ctxt.Out.Write64(uint64(sectoff + 4))
   457			ctxt.Out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_LO_DS) | uint64(elfsym)<<32)
   458		case objabi.R_ADDRPOWER:
   459			ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32)
   460			ctxt.Out.Write64(uint64(r.Xadd))
   461			ctxt.Out.Write64(uint64(sectoff + 4))
   462			ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_LO) | uint64(elfsym)<<32)
   463		case objabi.R_ADDRPOWER_DS:
   464			ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32)
   465			ctxt.Out.Write64(uint64(r.Xadd))
   466			ctxt.Out.Write64(uint64(sectoff + 4))
   467			ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_LO_DS) | uint64(elfsym)<<32)
   468		case objabi.R_ADDRPOWER_GOT:
   469			ctxt.Out.Write64(uint64(elf.R_PPC64_GOT16_HA) | uint64(elfsym)<<32)
   470			ctxt.Out.Write64(uint64(r.Xadd))
   471			ctxt.Out.Write64(uint64(sectoff + 4))
   472			ctxt.Out.Write64(uint64(elf.R_PPC64_GOT16_LO_DS) | uint64(elfsym)<<32)
   473		case objabi.R_ADDRPOWER_PCREL:
   474			ctxt.Out.Write64(uint64(elf.R_PPC64_REL16_HA) | uint64(elfsym)<<32)
   475			ctxt.Out.Write64(uint64(r.Xadd))
   476			ctxt.Out.Write64(uint64(sectoff + 4))
   477			ctxt.Out.Write64(uint64(elf.R_PPC64_REL16_LO) | uint64(elfsym)<<32)
   478			r.Xadd += 4
   479		case objabi.R_ADDRPOWER_TOCREL:
   480			ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32)
   481			ctxt.Out.Write64(uint64(r.Xadd))
   482			ctxt.Out.Write64(uint64(sectoff + 4))
   483			ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_LO) | uint64(elfsym)<<32)
   484		case objabi.R_ADDRPOWER_TOCREL_DS:
   485			ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32)
   486			ctxt.Out.Write64(uint64(r.Xadd))
   487			ctxt.Out.Write64(uint64(sectoff + 4))
   488			ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_LO_DS) | uint64(elfsym)<<32)
   489		case objabi.R_CALLPOWER:
   490			if r.Siz != 4 {
   491				return false
   492			}
   493			ctxt.Out.Write64(uint64(elf.R_PPC64_REL24) | uint64(elfsym)<<32)
   494	
   495		}
   496		ctxt.Out.Write64(uint64(r.Xadd))
   497	
   498		return true
   499	}
   500	
   501	func elfsetupplt(ctxt *ld.Link) {
   502		plt := ctxt.Syms.Lookup(".plt", 0)
   503		if plt.Size == 0 {
   504			// The dynamic linker stores the address of the
   505			// dynamic resolver and the DSO identifier in the two
   506			// doublewords at the beginning of the .plt section
   507			// before the PLT array. Reserve space for these.
   508			plt.Size = 16
   509		}
   510	}
   511	
   512	func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
   513		return false
   514	}
   515	
   516	// Return the value of .TOC. for symbol s
   517	func symtoc(ctxt *ld.Link, s *sym.Symbol) int64 {
   518		var toc *sym.Symbol
   519	
   520		if s.Outer != nil {
   521			toc = ctxt.Syms.ROLookup(".TOC.", int(s.Outer.Version))
   522		} else {
   523			toc = ctxt.Syms.ROLookup(".TOC.", int(s.Version))
   524		}
   525	
   526		if toc == nil {
   527			ld.Errorf(s, "TOC-relative relocation in object without .TOC.")
   528			return 0
   529		}
   530	
   531		return toc.Value
   532	}
   533	
   534	// archreloctoc relocates a TOC relative symbol.
   535	// If the symbol pointed by this TOC relative symbol is in .data or .bss, the
   536	// default load instruction can be changed to an addi instruction and the
   537	// symbol address can be used directly.
   538	// This code is for AIX only.
   539	func archreloctoc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
   540		if ctxt.HeadType == objabi.Hlinux {
   541			ld.Errorf(s, "archrelocaddr called for %s relocation\n", r.Sym.Name)
   542		}
   543		var o1, o2 uint32
   544	
   545		o1 = uint32(val >> 32)
   546		o2 = uint32(val)
   547	
   548		var t int64
   549		useAddi := false
   550		const prefix = "TOC."
   551		var tarSym *sym.Symbol
   552		if strings.HasPrefix(r.Sym.Name, prefix) {
   553			tarSym = ctxt.Syms.ROLookup(strings.TrimPrefix(r.Sym.Name, prefix), 0)
   554		} else {
   555			ld.Errorf(s, "archreloctoc called for a symbol without TOC anchor")
   556		}
   557	
   558		if ctxt.LinkMode == ld.LinkInternal && tarSym != nil && tarSym.Attr.Reachable() && (tarSym.Sect.Seg == &ld.Segdata) {
   559			t = ld.Symaddr(tarSym) + r.Add - ctxt.Syms.ROLookup("TOC", 0).Value
   560			// change ld to addi in the second instruction
   561			o2 = (o2 & 0x03FF0000) | 0xE<<26
   562			useAddi = true
   563		} else {
   564			t = ld.Symaddr(r.Sym) + r.Add - ctxt.Syms.ROLookup("TOC", 0).Value
   565		}
   566	
   567		if t != int64(int32(t)) {
   568			ld.Errorf(s, "TOC relocation for %s is too big to relocate %s: 0x%x", s.Name, r.Sym, t)
   569		}
   570	
   571		if t&0x8000 != 0 {
   572			t += 0x10000
   573		}
   574	
   575		o1 |= uint32((t >> 16) & 0xFFFF)
   576	
   577		switch r.Type {
   578		case objabi.R_ADDRPOWER_TOCREL_DS:
   579			if useAddi {
   580				o2 |= uint32(t) & 0xFFFF
   581			} else {
   582				if t&3 != 0 {
   583					ld.Errorf(s, "bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym))
   584				}
   585				o2 |= uint32(t) & 0xFFFC
   586			}
   587		default:
   588			return -1
   589		}
   590	
   591		return int64(o1)<<32 | int64(o2)
   592	}
   593	
   594	// archrelocaddr relocates a symbol address.
   595	// This code is for AIX only.
   596	func archrelocaddr(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
   597		if ctxt.HeadType == objabi.Haix {
   598			ld.Errorf(s, "archrelocaddr called for %s relocation\n", r.Sym.Name)
   599		}
   600		var o1, o2 uint32
   601		if ctxt.Arch.ByteOrder == binary.BigEndian {
   602			o1 = uint32(val >> 32)
   603			o2 = uint32(val)
   604		} else {
   605			o1 = uint32(val)
   606			o2 = uint32(val >> 32)
   607		}
   608	
   609		// We are spreading a 31-bit address across two instructions, putting the
   610		// high (adjusted) part in the low 16 bits of the first instruction and the
   611		// low part in the low 16 bits of the second instruction, or, in the DS case,
   612		// bits 15-2 (inclusive) of the address into bits 15-2 of the second
   613		// instruction (it is an error in this case if the low 2 bits of the address
   614		// are non-zero).
   615	
   616		t := ld.Symaddr(r.Sym) + r.Add
   617		if t < 0 || t >= 1<<31 {
   618			ld.Errorf(s, "relocation for %s is too big (>=2G): 0x%x", s.Name, ld.Symaddr(r.Sym))
   619		}
   620		if t&0x8000 != 0 {
   621			t += 0x10000
   622		}
   623	
   624		switch r.Type {
   625		case objabi.R_ADDRPOWER:
   626			o1 |= (uint32(t) >> 16) & 0xffff
   627			o2 |= uint32(t) & 0xffff
   628		case objabi.R_ADDRPOWER_DS:
   629			o1 |= (uint32(t) >> 16) & 0xffff
   630			if t&3 != 0 {
   631				ld.Errorf(s, "bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym))
   632			}
   633			o2 |= uint32(t) & 0xfffc
   634		default:
   635			return -1
   636		}
   637	
   638		if ctxt.Arch.ByteOrder == binary.BigEndian {
   639			return int64(o1)<<32 | int64(o2)
   640		}
   641		return int64(o2)<<32 | int64(o1)
   642	}
   643	
   644	// resolve direct jump relocation r in s, and add trampoline if necessary
   645	func trampoline(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol) {
   646	
   647		// Trampolines are created if the branch offset is too large and the linker cannot insert a call stub to handle it.
   648		// For internal linking, trampolines are always created for long calls.
   649		// For external linking, the linker can insert a call stub to handle a long call, but depends on having the TOC address in
   650		// r2.  For those build modes with external linking where the TOC address is not maintained in r2, trampolines must be created.
   651		if ctxt.LinkMode == ld.LinkExternal && (ctxt.DynlinkingGo() || ctxt.BuildMode == ld.BuildModeCArchive || ctxt.BuildMode == ld.BuildModeCShared || ctxt.BuildMode == ld.BuildModePIE) {
   652			// No trampolines needed since r2 contains the TOC
   653			return
   654		}
   655	
   656		t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off))
   657		switch r.Type {
   658		case objabi.R_CALLPOWER:
   659	
   660			// If branch offset is too far then create a trampoline.
   661	
   662			if (ctxt.LinkMode == ld.LinkExternal && s.Sect != r.Sym.Sect) || (ctxt.LinkMode == ld.LinkInternal && int64(int32(t<<6)>>6) != t) || (*ld.FlagDebugTramp > 1 && s.File != r.Sym.File) {
   663				var tramp *sym.Symbol
   664				for i := 0; ; i++ {
   665	
   666					// Using r.Add as part of the name is significant in functions like duffzero where the call
   667					// target is at some offset within the function.  Calls to duff+8 and duff+256 must appear as
   668					// distinct trampolines.
   669	
   670					name := r.Sym.Name
   671					if r.Add == 0 {
   672						name = name + fmt.Sprintf("-tramp%d", i)
   673					} else {
   674						name = name + fmt.Sprintf("%+x-tramp%d", r.Add, i)
   675					}
   676	
   677					// Look up the trampoline in case it already exists
   678	
   679					tramp = ctxt.Syms.Lookup(name, int(r.Sym.Version))
   680					if tramp.Value == 0 {
   681						break
   682					}
   683	
   684					t = ld.Symaddr(tramp) + r.Add - (s.Value + int64(r.Off))
   685	
   686					// With internal linking, the trampoline can be used if it is not too far.
   687					// With external linking, the trampoline must be in this section for it to be reused.
   688					if (ctxt.LinkMode == ld.LinkInternal && int64(int32(t<<6)>>6) == t) || (ctxt.LinkMode == ld.LinkExternal && s.Sect == tramp.Sect) {
   689						break
   690					}
   691				}
   692				if tramp.Type == 0 {
   693					if ctxt.DynlinkingGo() || ctxt.BuildMode == ld.BuildModeCArchive || ctxt.BuildMode == ld.BuildModeCShared || ctxt.BuildMode == ld.BuildModePIE {
   694						// Should have returned for above cases
   695						ld.Errorf(s, "unexpected trampoline for shared or dynamic linking\n")
   696					} else {
   697						ctxt.AddTramp(tramp)
   698						gentramp(ctxt, tramp, r.Sym, r.Add)
   699					}
   700				}
   701				r.Sym = tramp
   702				r.Add = 0 // This was folded into the trampoline target address
   703				r.Done = false
   704			}
   705		default:
   706			ld.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
   707		}
   708	}
   709	
   710	func gentramp(ctxt *ld.Link, tramp, target *sym.Symbol, offset int64) {
   711		tramp.Size = 16 // 4 instructions
   712		tramp.P = make([]byte, tramp.Size)
   713		t := ld.Symaddr(target) + offset
   714		var o1, o2 uint32
   715	
   716		if ctxt.HeadType == objabi.Haix {
   717			// On AIX, the address is retrieved with a TOC symbol.
   718			// For internal linking, the "Linux" way might still be used.
   719			// However, all text symbols are accessed with a TOC symbol as
   720			// text relocations aren't supposed to be possible.
   721			// So, keep using the external linking way to be more AIX friendly.
   722			o1 = uint32(0x3fe20000) // lis r2, toctargetaddr hi
   723			o2 = uint32(0xebff0000) // ld r31, toctargetaddr lo
   724	
   725			toctramp := ctxt.Syms.Lookup("TOC."+tramp.Name, 0)
   726			toctramp.Type = sym.SXCOFFTOC
   727			toctramp.Attr |= sym.AttrReachable
   728			toctramp.AddAddr(ctxt.Arch, target)
   729	
   730			tr := tramp.AddRel()
   731			tr.Off = 0
   732			tr.Type = objabi.R_ADDRPOWER_TOCREL_DS
   733			tr.Siz = 8 // generates 2 relocations:  HA + LO
   734			tr.Sym = toctramp
   735			tr.Add = offset
   736		} else {
   737			// Used for default build mode for an executable
   738			// Address of the call target is generated using
   739			// relocation and doesn't depend on r2 (TOC).
   740			o1 = uint32(0x3fe00000) // lis r31,targetaddr hi
   741			o2 = uint32(0x3bff0000) // addi r31,targetaddr lo
   742	
   743			// With external linking, the target address must be
   744			// relocated using LO and HA
   745			if ctxt.LinkMode == ld.LinkExternal {
   746				tr := tramp.AddRel()
   747				tr.Off = 0
   748				tr.Type = objabi.R_ADDRPOWER
   749				tr.Siz = 8 // generates 2 relocations:  HA + LO
   750				tr.Sym = target
   751				tr.Add = offset
   752	
   753			} else {
   754				// adjustment needed if lo has sign bit set
   755				// when using addi to compute address
   756				val := uint32((t & 0xffff0000) >> 16)
   757				if t&0x8000 != 0 {
   758					val += 1
   759				}
   760				o1 |= val                // hi part of addr
   761				o2 |= uint32(t & 0xffff) // lo part of addr
   762			}
   763		}
   764	
   765		o3 := uint32(0x7fe903a6) // mtctr r31
   766		o4 := uint32(0x4e800420) // bctr
   767		ctxt.Arch.ByteOrder.PutUint32(tramp.P, o1)
   768		ctxt.Arch.ByteOrder.PutUint32(tramp.P[4:], o2)
   769		ctxt.Arch.ByteOrder.PutUint32(tramp.P[8:], o3)
   770		ctxt.Arch.ByteOrder.PutUint32(tramp.P[12:], o4)
   771	}
   772	
   773	func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
   774		if ctxt.LinkMode == ld.LinkExternal {
   775			// On AIX, relocations (except TLS ones) must be also done to the
   776			// value with the current addresses.
   777			switch r.Type {
   778			default:
   779				if ctxt.HeadType != objabi.Haix {
   780					return val, false
   781				}
   782			case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
   783				r.Done = false
   784				// check Outer is nil, Type is TLSBSS?
   785				r.Xadd = r.Add
   786				r.Xsym = r.Sym
   787				return val, true
   788			case objabi.R_ADDRPOWER,
   789				objabi.R_ADDRPOWER_DS,
   790				objabi.R_ADDRPOWER_TOCREL,
   791				objabi.R_ADDRPOWER_TOCREL_DS,
   792				objabi.R_ADDRPOWER_GOT,
   793				objabi.R_ADDRPOWER_PCREL:
   794				r.Done = false
   795	
   796				// set up addend for eventual relocation via outer symbol.
   797				rs := r.Sym
   798				r.Xadd = r.Add
   799				for rs.Outer != nil {
   800					r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
   801					rs = rs.Outer
   802				}
   803	
   804				if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
   805					ld.Errorf(s, "missing section for %s", rs.Name)
   806				}
   807				r.Xsym = rs
   808	
   809				if ctxt.HeadType != objabi.Haix {
   810					return val, true
   811				}
   812			case objabi.R_CALLPOWER:
   813				r.Done = false
   814				r.Xsym = r.Sym
   815				r.Xadd = r.Add
   816				if ctxt.HeadType != objabi.Haix {
   817					return val, true
   818				}
   819			}
   820		}
   821	
   822		switch r.Type {
   823		case objabi.R_CONST:
   824			return r.Add, true
   825		case objabi.R_GOTOFF:
   826			return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
   827		case objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS:
   828			return archreloctoc(ctxt, r, s, val), true
   829		case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS:
   830			return archrelocaddr(ctxt, r, s, val), true
   831		case objabi.R_CALLPOWER:
   832			// Bits 6 through 29 = (S + A - P) >> 2
   833	
   834			t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off))
   835	
   836			if t&3 != 0 {
   837				ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t)
   838			}
   839			// If branch offset is too far then create a trampoline.
   840	
   841			if int64(int32(t<<6)>>6) != t {
   842				ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t)
   843			}
   844			return val | int64(uint32(t)&^0xfc000003), true
   845		case objabi.R_POWER_TOC: // S + A - .TOC.
   846			return ld.Symaddr(r.Sym) + r.Add - symtoc(ctxt, s), true
   847	
   848		case objabi.R_POWER_TLS_LE:
   849			// The thread pointer points 0x7000 bytes after the start of the
   850			// thread local storage area as documented in section "3.7.2 TLS
   851			// Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI
   852			// Specification".
   853			v := r.Sym.Value - 0x7000
   854			if ctxt.HeadType == objabi.Haix {
   855				// On AIX, the thread pointer points 0x7800 bytes after
   856				// the TLS.
   857				v -= 0x800
   858			}
   859			if int64(int16(v)) != v {
   860				ld.Errorf(s, "TLS offset out of range %d", v)
   861			}
   862			return (val &^ 0xffff) | (v & 0xffff), true
   863		}
   864	
   865		return val, false
   866	}
   867	
   868	func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
   869		switch r.Variant & sym.RV_TYPE_MASK {
   870		default:
   871			ld.Errorf(s, "unexpected relocation variant %d", r.Variant)
   872			fallthrough
   873	
   874		case sym.RV_NONE:
   875			return t
   876	
   877		case sym.RV_POWER_LO:
   878			if r.Variant&sym.RV_CHECK_OVERFLOW != 0 {
   879				// Whether to check for signed or unsigned
   880				// overflow depends on the instruction
   881				var o1 uint32
   882				if ctxt.Arch.ByteOrder == binary.BigEndian {
   883					o1 = binary.BigEndian.Uint32(s.P[r.Off-2:])
   884				} else {
   885					o1 = binary.LittleEndian.Uint32(s.P[r.Off:])
   886				}
   887				switch o1 >> 26 {
   888				case 24, // ori
   889					26, // xori
   890					28: // andi
   891					if t>>16 != 0 {
   892						goto overflow
   893					}
   894	
   895				default:
   896					if int64(int16(t)) != t {
   897						goto overflow
   898					}
   899				}
   900			}
   901	
   902			return int64(int16(t))
   903	
   904		case sym.RV_POWER_HA:
   905			t += 0x8000
   906			fallthrough
   907	
   908			// Fallthrough
   909		case sym.RV_POWER_HI:
   910			t >>= 16
   911	
   912			if r.Variant&sym.RV_CHECK_OVERFLOW != 0 {
   913				// Whether to check for signed or unsigned
   914				// overflow depends on the instruction
   915				var o1 uint32
   916				if ctxt.Arch.ByteOrder == binary.BigEndian {
   917					o1 = binary.BigEndian.Uint32(s.P[r.Off-2:])
   918				} else {
   919					o1 = binary.LittleEndian.Uint32(s.P[r.Off:])
   920				}
   921				switch o1 >> 26 {
   922				case 25, // oris
   923					27, // xoris
   924					29: // andis
   925					if t>>16 != 0 {
   926						goto overflow
   927					}
   928	
   929				default:
   930					if int64(int16(t)) != t {
   931						goto overflow
   932					}
   933				}
   934			}
   935	
   936			return int64(int16(t))
   937	
   938		case sym.RV_POWER_DS:
   939			var o1 uint32
   940			if ctxt.Arch.ByteOrder == binary.BigEndian {
   941				o1 = uint32(binary.BigEndian.Uint16(s.P[r.Off:]))
   942			} else {
   943				o1 = uint32(binary.LittleEndian.Uint16(s.P[r.Off:]))
   944			}
   945			if t&3 != 0 {
   946				ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t)
   947			}
   948			if (r.Variant&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t {
   949				goto overflow
   950			}
   951			return int64(o1)&0x3 | int64(int16(t))
   952		}
   953	
   954	overflow:
   955		ld.Errorf(s, "relocation for %s+%d is too big: %d", r.Sym.Name, r.Off, t)
   956		return t
   957	}
   958	
   959	func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
   960		if s.Plt() >= 0 {
   961			return
   962		}
   963	
   964		ld.Adddynsym(ctxt, s)
   965	
   966		if ctxt.IsELF {
   967			plt := ctxt.Syms.Lookup(".plt", 0)
   968			rela := ctxt.Syms.Lookup(".rela.plt", 0)
   969			if plt.Size == 0 {
   970				elfsetupplt(ctxt)
   971			}
   972	
   973			// Create the glink resolver if necessary
   974			glink := ensureglinkresolver(ctxt)
   975	
   976			// Write symbol resolver stub (just a branch to the
   977			// glink resolver stub)
   978			r := glink.AddRel()
   979	
   980			r.Sym = glink
   981			r.Off = int32(glink.Size)
   982			r.Siz = 4
   983			r.Type = objabi.R_CALLPOWER
   984			glink.AddUint32(ctxt.Arch, 0x48000000) // b .glink
   985	
   986			// In the ppc64 ABI, the dynamic linker is responsible
   987			// for writing the entire PLT.  We just need to
   988			// reserve 8 bytes for each PLT entry and generate a
   989			// JMP_SLOT dynamic relocation for it.
   990			//
   991			// TODO(austin): ABI v1 is different
   992			s.SetPlt(int32(plt.Size))
   993	
   994			plt.Size += 8
   995	
   996			rela.AddAddrPlus(ctxt.Arch, plt, int64(s.Plt()))
   997			rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_PPC64_JMP_SLOT)))
   998			rela.AddUint64(ctxt.Arch, 0)
   999		} else {
  1000			ld.Errorf(s, "addpltsym: unsupported binary format")
  1001		}
  1002	}
  1003	
  1004	// Generate the glink resolver stub if necessary and return the .glink section
  1005	func ensureglinkresolver(ctxt *ld.Link) *sym.Symbol {
  1006		glink := ctxt.Syms.Lookup(".glink", 0)
  1007		if glink.Size != 0 {
  1008			return glink
  1009		}
  1010	
  1011		// This is essentially the resolver from the ppc64 ELF ABI.
  1012		// At entry, r12 holds the address of the symbol resolver stub
  1013		// for the target routine and the argument registers hold the
  1014		// arguments for the target routine.
  1015		//
  1016		// This stub is PIC, so first get the PC of label 1 into r11.
  1017		// Other things will be relative to this.
  1018		glink.AddUint32(ctxt.Arch, 0x7c0802a6) // mflr r0
  1019		glink.AddUint32(ctxt.Arch, 0x429f0005) // bcl 20,31,1f
  1020		glink.AddUint32(ctxt.Arch, 0x7d6802a6) // 1: mflr r11
  1021		glink.AddUint32(ctxt.Arch, 0x7c0803a6) // mtlf r0
  1022	
  1023		// Compute the .plt array index from the entry point address.
  1024		// Because this is PIC, everything is relative to label 1b (in
  1025		// r11):
  1026		//   r0 = ((r12 - r11) - (res_0 - r11)) / 4 = (r12 - res_0) / 4
  1027		glink.AddUint32(ctxt.Arch, 0x3800ffd0) // li r0,-(res_0-1b)=-48
  1028		glink.AddUint32(ctxt.Arch, 0x7c006214) // add r0,r0,r12
  1029		glink.AddUint32(ctxt.Arch, 0x7c0b0050) // sub r0,r0,r11
  1030		glink.AddUint32(ctxt.Arch, 0x7800f082) // srdi r0,r0,2
  1031	
  1032		// r11 = address of the first byte of the PLT
  1033		r := glink.AddRel()
  1034	
  1035		r.Off = int32(glink.Size)
  1036		r.Sym = ctxt.Syms.Lookup(".plt", 0)
  1037		r.Siz = 8
  1038		r.Type = objabi.R_ADDRPOWER
  1039	
  1040		glink.AddUint32(ctxt.Arch, 0x3d600000) // addis r11,0,.plt@ha
  1041		glink.AddUint32(ctxt.Arch, 0x396b0000) // addi r11,r11,.plt@l
  1042	
  1043		// Load r12 = dynamic resolver address and r11 = DSO
  1044		// identifier from the first two doublewords of the PLT.
  1045		glink.AddUint32(ctxt.Arch, 0xe98b0000) // ld r12,0(r11)
  1046		glink.AddUint32(ctxt.Arch, 0xe96b0008) // ld r11,8(r11)
  1047	
  1048		// Jump to the dynamic resolver
  1049		glink.AddUint32(ctxt.Arch, 0x7d8903a6) // mtctr r12
  1050		glink.AddUint32(ctxt.Arch, 0x4e800420) // bctr
  1051	
  1052		// The symbol resolvers must immediately follow.
  1053		//   res_0:
  1054	
  1055		// Add DT_PPC64_GLINK .dynamic entry, which points to 32 bytes
  1056		// before the first symbol resolver stub.
  1057		s := ctxt.Syms.Lookup(".dynamic", 0)
  1058	
  1059		ld.Elfwritedynentsymplus(ctxt, s, ld.DT_PPC64_GLINK, glink, glink.Size-32)
  1060	
  1061		return glink
  1062	}
  1063	
  1064	func asmb(ctxt *ld.Link) {
  1065		if ctxt.Debugvlog != 0 {
  1066			ctxt.Logf("%5.2f asmb\n", ld.Cputime())
  1067		}
  1068	
  1069		if ctxt.IsELF {
  1070			ld.Asmbelfsetup()
  1071		}
  1072	
  1073		for _, sect := range ld.Segtext.Sections {
  1074			ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
  1075			// Handle additional text sections with Codeblk
  1076			if sect.Name == ".text" {
  1077				ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
  1078			} else {
  1079				ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
  1080			}
  1081		}
  1082	
  1083		if ld.Segrodata.Filelen > 0 {
  1084			if ctxt.Debugvlog != 0 {
  1085				ctxt.Logf("%5.2f rodatblk\n", ld.Cputime())
  1086			}
  1087			ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff))
  1088			ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
  1089		}
  1090		if ld.Segrelrodata.Filelen > 0 {
  1091			if ctxt.Debugvlog != 0 {
  1092				ctxt.Logf("%5.2f relrodatblk\n", ld.Cputime())
  1093			}
  1094			ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff))
  1095			ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
  1096		}
  1097	
  1098		if ctxt.Debugvlog != 0 {
  1099			ctxt.Logf("%5.2f datblk\n", ld.Cputime())
  1100		}
  1101	
  1102		ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff))
  1103		ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
  1104	
  1105		ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
  1106		ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
  1107	}
  1108	
  1109	func asmb2(ctxt *ld.Link) {
  1110		/* output symbol table */
  1111		ld.Symsize = 0
  1112	
  1113		ld.Lcsize = 0
  1114		symo := uint32(0)
  1115		if !*ld.FlagS {
  1116			// TODO: rationalize
  1117			if ctxt.Debugvlog != 0 {
  1118				ctxt.Logf("%5.2f sym\n", ld.Cputime())
  1119			}
  1120			switch ctxt.HeadType {
  1121			default:
  1122				if ctxt.IsELF {
  1123					symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
  1124					symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
  1125				}
  1126	
  1127			case objabi.Hplan9:
  1128				symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
  1129	
  1130			case objabi.Haix:
  1131				// Nothing to do
  1132			}
  1133	
  1134			ctxt.Out.SeekSet(int64(symo))
  1135			switch ctxt.HeadType {
  1136			default:
  1137				if ctxt.IsELF {
  1138					if ctxt.Debugvlog != 0 {
  1139						ctxt.Logf("%5.2f elfsym\n", ld.Cputime())
  1140					}
  1141					ld.Asmelfsym(ctxt)
  1142					ctxt.Out.Flush()
  1143					ctxt.Out.Write(ld.Elfstrdat)
  1144	
  1145					if ctxt.LinkMode == ld.LinkExternal {
  1146						ld.Elfemitreloc(ctxt)
  1147					}
  1148				}
  1149	
  1150			case objabi.Hplan9:
  1151				ld.Asmplan9sym(ctxt)
  1152				ctxt.Out.Flush()
  1153	
  1154				sym := ctxt.Syms.Lookup("pclntab", 0)
  1155				if sym != nil {
  1156					ld.Lcsize = int32(len(sym.P))
  1157					ctxt.Out.Write(sym.P)
  1158					ctxt.Out.Flush()
  1159				}
  1160	
  1161			case objabi.Haix:
  1162				// symtab must be added once sections have been created in ld.Asmbxcoff
  1163				ctxt.Out.Flush()
  1164			}
  1165		}
  1166	
  1167		if ctxt.Debugvlog != 0 {
  1168			ctxt.Logf("%5.2f header\n", ld.Cputime())
  1169		}
  1170		ctxt.Out.SeekSet(0)
  1171		switch ctxt.HeadType {
  1172		default:
  1173		case objabi.Hplan9: /* plan 9 */
  1174			ctxt.Out.Write32(0x647)                      /* magic */
  1175			ctxt.Out.Write32(uint32(ld.Segtext.Filelen)) /* sizes */
  1176			ctxt.Out.Write32(uint32(ld.Segdata.Filelen))
  1177			ctxt.Out.Write32(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
  1178			ctxt.Out.Write32(uint32(ld.Symsize))          /* nsyms */
  1179			ctxt.Out.Write32(uint32(ld.Entryvalue(ctxt))) /* va of entry */
  1180			ctxt.Out.Write32(0)
  1181			ctxt.Out.Write32(uint32(ld.Lcsize))
  1182	
  1183		case objabi.Hlinux,
  1184			objabi.Hfreebsd,
  1185			objabi.Hnetbsd,
  1186			objabi.Hopenbsd,
  1187			objabi.Hnacl:
  1188			ld.Asmbelf(ctxt, int64(symo))
  1189	
  1190		case objabi.Haix:
  1191			fileoff := uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
  1192			fileoff = uint32(ld.Rnd(int64(fileoff), int64(*ld.FlagRound)))
  1193			ld.Asmbxcoff(ctxt, int64(fileoff))
  1194		}
  1195	
  1196		ctxt.Out.Flush()
  1197		if *ld.FlagC {
  1198			fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
  1199			fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
  1200			fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
  1201			fmt.Printf("symsize=%d\n", ld.Symsize)
  1202			fmt.Printf("lcsize=%d\n", ld.Lcsize)
  1203			fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
  1204		}
  1205	}
  1206	

View as plain text