github.com/reiver/go@v0.0.0-20150109200633-1d0c7792f172/src/cmd/9l/asm.c (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  // Writing object files.
    32  
    33  #include	"l.h"
    34  #include	"../ld/lib.h"
    35  #include	"../ld/elf.h"
    36  #include	"../ld/dwarf.h"
    37  
    38  
    39  // TODO(austin): ABI v1 uses /usr/lib/ld.so.1
    40  char linuxdynld[] = "/lib64/ld64.so.1";
    41  char freebsddynld[] = "XXX";
    42  char openbsddynld[] = "XXX";
    43  char netbsddynld[] = "XXX";
    44  char dragonflydynld[] = "XXX";
    45  char solarisdynld[] = "XXX";
    46  
    47  static int
    48  needlib(char *name)
    49  {
    50  	char *p;
    51  	LSym *s;
    52  
    53  	if(*name == '\0')
    54  		return 0;
    55  
    56  	/* reuse hash code in symbol table */
    57  	p = smprint(".dynlib.%s", name);
    58  	s = linklookup(ctxt, p, 0);
    59  	free(p);
    60  	if(s->type == 0) {
    61  		s->type = 100;	// avoid SDATA, etc.
    62  		return 1;
    63  	}
    64  	return 0;
    65  }
    66  
    67  int	nelfsym = 1;
    68  
    69  static void	gencallstub(int abicase, LSym *stub, LSym *targ);
    70  static void	addpltsym(Link*, LSym*);
    71  static LSym*	ensureglinkresolver(void);
    72  
    73  void
    74  gentext(void)
    75  {
    76  	LSym *s, *stub, **pprevtextp;
    77  	Reloc *r;
    78  	char *n;
    79  	uint32 o1;
    80  	uchar *cast;
    81  	int i;
    82  
    83  	// The ppc64 ABI PLT has similar concepts to other
    84  	// architectures, but is laid out quite differently.  When we
    85  	// see an R_PPC64_REL24 relocation to a dynamic symbol
    86  	// (indicating that the call needs to go through the PLT), we
    87  	// generate up to three stubs and reserve a PLT slot.
    88  	//
    89  	// 1) The call site will be bl x; nop (where the relocation
    90  	//    applies to the bl).  We rewrite this to bl x_stub; ld
    91  	//    r2,24(r1).  The ld is necessary because x_stub will save
    92  	//    r2 (the TOC pointer) at 24(r1) (the "TOC save slot").
    93  	//
    94  	// 2) We reserve space for a pointer in the .plt section (once
    95  	//    per referenced dynamic function).  .plt is a data
    96  	//    section filled solely by the dynamic linker (more like
    97  	//    .plt.got on other architectures).  Initially, the
    98  	//    dynamic linker will fill each slot with a pointer to the
    99  	//    corresponding x@plt entry point.
   100  	//
   101  	// 3) We generate the "call stub" x_stub (once per dynamic
   102  	//    function/object file pair).  This saves the TOC in the
   103  	//    TOC save slot, reads the function pointer from x's .plt
   104  	//    slot and calls it like any other global entry point
   105  	//    (including setting r12 to the function address).
   106  	//
   107  	// 4) We generate the "symbol resolver stub" x@plt (once per
   108  	//    dynamic function).  This is solely a branch to the glink
   109  	//    resolver stub.
   110  	//
   111  	// 5) We generate the glink resolver stub (only once).  This
   112  	//    computes which symbol resolver stub we came through and
   113  	//    invokes the dynamic resolver via a pointer provided by
   114  	//    the dynamic linker.  This will patch up the .plt slot to
   115  	//    point directly at the function so future calls go
   116  	//    straight from the call stub to the real function, and
   117  	//    then call the function.
   118  
   119  	// NOTE: It's possible we could make ppc64 closer to other
   120  	// architectures: ppc64's .plt is like .plt.got on other
   121  	// platforms and ppc64's .glink is like .plt on other
   122  	// platforms.
   123  
   124  	// Find all R_PPC64_REL24 relocations that reference dynamic
   125  	// imports.  Reserve PLT entries for these symbols and
   126  	// generate call stubs.  The call stubs need to live in .text,
   127  	// which is why we need to do this pass this early.
   128  	//
   129  	// This assumes "case 1" from the ABI, where the caller needs
   130  	// us to save and restore the TOC pointer.
   131  	pprevtextp = &ctxt->textp;
   132  	for(s=*pprevtextp; s!=S; pprevtextp=&s->next, s=*pprevtextp) {
   133  		for(r=s->r; r<s->r+s->nr; r++) {
   134  			if(!(r->type == 256 + R_PPC64_REL24 &&
   135  			     r->sym->type == SDYNIMPORT))
   136  				continue;
   137  
   138  			// Reserve PLT entry and generate symbol
   139  			// resolver
   140  			addpltsym(ctxt, r->sym);
   141  
   142  			// Generate call stub
   143  			n = smprint("%s.%s", s->name, r->sym->name);
   144  			stub = linklookup(ctxt, n, 0);
   145  			free(n);
   146  			stub->reachable |= s->reachable;
   147  			if(stub->size == 0) {
   148  				// Need outer to resolve .TOC.
   149  				stub->outer = s;
   150  
   151  				// Link in to textp before s (we could
   152  				// do it after, but would have to skip
   153  				// the subsymbols)
   154  				*pprevtextp = stub;
   155  				stub->next = s;
   156  				pprevtextp = &stub->next;
   157  
   158  				gencallstub(1, stub, r->sym);
   159  			}
   160  
   161  			// Update the relocation to use the call stub
   162  			r->sym = stub;
   163  
   164  			// Restore TOC after bl.  The compiler put a
   165  			// nop here for us to overwrite.
   166  			o1 = 0xe8410018; // ld r2,24(r1)
   167  			cast = (uchar*)&o1;
   168  			for(i=0; i<4; i++)
   169  				s->p[r->off+4+i] = cast[inuxi4[i]];
   170  		}
   171  	}
   172  }
   173  
   174  // Construct a call stub in stub that calls symbol targ via its PLT
   175  // entry.
   176  static void
   177  gencallstub(int abicase, LSym *stub, LSym *targ)
   178  {
   179  	LSym *plt;
   180  	Reloc *r;
   181  
   182  	if(abicase != 1)
   183  		// If we see R_PPC64_TOCSAVE or R_PPC64_REL24_NOTOC
   184  		// relocations, we'll need to implement cases 2 and 3.
   185  		sysfatal("gencallstub only implements case 1 calls");
   186  
   187  	plt = linklookup(ctxt, ".plt", 0);
   188  
   189  	stub->type = STEXT;
   190  
   191  	// Save TOC pointer in TOC save slot
   192  	adduint32(ctxt, stub, 0xf8410018); // std r2,24(r1)
   193  
   194  	// Load the function pointer from the PLT.
   195  	r = addrel(stub);
   196  	r->off = stub->size;
   197  	r->sym = plt;
   198  	r->add = targ->plt;
   199  	r->siz = 2;
   200  	if(ctxt->arch->endian == BigEndian)
   201  		r->off += r->siz;
   202  	r->type = R_POWER_TOC;
   203  	r->variant = RV_POWER_HA;
   204  	adduint32(ctxt, stub, 0x3d820000); // addis r12,r2,targ@plt@toc@ha
   205  	r = addrel(stub);
   206  	r->off = stub->size;
   207  	r->sym = plt;
   208  	r->add = targ->plt;
   209  	r->siz = 2;
   210  	if(ctxt->arch->endian == BigEndian)
   211  		r->off += r->siz;
   212  	r->type = R_POWER_TOC;
   213  	r->variant = RV_POWER_LO;
   214  	adduint32(ctxt, stub, 0xe98c0000); // ld r12,targ@plt@toc@l(r12)
   215  
   216  	// Jump to the loaded pointer
   217  	adduint32(ctxt, stub, 0x7d8903a6); // mtctr r12
   218  	adduint32(ctxt, stub, 0x4e800420); // bctr
   219  }
   220  
   221  void
   222  adddynrela(LSym *rel, LSym *s, Reloc *r)
   223  {
   224  	USED(rel); USED(s); USED(r);
   225  	sysfatal("adddynrela not implemented");
   226  }
   227  
   228  void
   229  adddynrel(LSym *s, Reloc *r)
   230  {
   231  	LSym *targ, *rela;
   232  
   233  	targ = r->sym;
   234  	ctxt->cursym = s;
   235  
   236  	switch(r->type) {
   237  	default:
   238  		if(r->type >= 256) {
   239  			diag("unexpected relocation type %d", r->type);
   240  			return;
   241  		}
   242  		break;
   243  
   244  	// Handle relocations found in ELF object files.
   245  	case 256 + R_PPC64_REL24:
   246  		r->type = R_CALLPOWER;
   247  		// This is a local call, so the caller isn't setting
   248  		// up r12 and r2 is the same for the caller and
   249  		// callee.  Hence, we need to go to the local entry
   250  		// point.  (If we don't do this, the callee will try
   251  		// to use r12 to compute r2.)
   252  		r->add += r->sym->localentry * 4;
   253  		if(targ->type == SDYNIMPORT)
   254  			// Should have been handled in elfsetupplt
   255  			diag("unexpected R_PPC64_REL24 for dyn import");
   256  		return;
   257  
   258  	case 256 + R_PPC64_ADDR64:
   259  		r->type = R_ADDR;
   260  		if(targ->type == SDYNIMPORT) {
   261  			// These happen in .toc sections
   262  			adddynsym(ctxt, targ);
   263  
   264  			rela = linklookup(ctxt, ".rela", 0);
   265  			addaddrplus(ctxt, rela, s, r->off);
   266  			adduint64(ctxt, rela, ELF64_R_INFO(targ->dynid, R_PPC64_ADDR64));
   267  			adduint64(ctxt, rela, r->add);
   268  			r->type = 256;	// ignore during relocsym
   269  		}
   270  		return;
   271  
   272  	case 256 + R_PPC64_TOC16:
   273  		r->type = R_POWER_TOC;
   274  		r->variant = RV_POWER_LO | RV_CHECK_OVERFLOW;
   275  		return;
   276  
   277  	case 256 + R_PPC64_TOC16_LO:
   278  		r->type = R_POWER_TOC;
   279  		r->variant = RV_POWER_LO;
   280  		return;
   281  
   282  	case 256 + R_PPC64_TOC16_HA:
   283  		r->type = R_POWER_TOC;
   284  		r->variant = RV_POWER_HA | RV_CHECK_OVERFLOW;
   285  		return;
   286  
   287  	case 256 + R_PPC64_TOC16_HI:
   288  		r->type = R_POWER_TOC;
   289  		r->variant = RV_POWER_HI | RV_CHECK_OVERFLOW;
   290  		return;
   291  
   292  	case 256 + R_PPC64_TOC16_DS:
   293  		r->type = R_POWER_TOC;
   294  		r->variant = RV_POWER_DS | RV_CHECK_OVERFLOW;
   295  		return;
   296  
   297  	case 256 + R_PPC64_TOC16_LO_DS:
   298  		r->type = R_POWER_TOC;
   299  		r->variant = RV_POWER_DS;
   300  		return;
   301  
   302  	case 256 + R_PPC64_REL16_LO:
   303  		r->type = R_PCREL;
   304  		r->variant = RV_POWER_LO;
   305  		r->add += 2;	// Compensate for relocation size of 2
   306  		return;
   307  
   308  	case 256 + R_PPC64_REL16_HI:
   309  		r->type = R_PCREL;
   310  		r->variant = RV_POWER_HI | RV_CHECK_OVERFLOW;
   311  		r->add += 2;
   312  		return;
   313  
   314  	case 256 + R_PPC64_REL16_HA:
   315  		r->type = R_PCREL;
   316  		r->variant = RV_POWER_HA | RV_CHECK_OVERFLOW;
   317  		r->add += 2;
   318  		return;
   319  	}
   320  
   321  	// Handle references to ELF symbols from our own object files.
   322  	if(targ->type != SDYNIMPORT)
   323  		return;
   324  
   325  	// TODO(austin): Translate our relocations to ELF
   326  
   327  	diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ->name, r->type, targ->type);
   328  }
   329  
   330  int
   331  elfreloc1(Reloc *r, vlong sectoff)
   332  {
   333  	USED(r); USED(sectoff);
   334  	// TODO(minux)
   335  	return -1;
   336  }
   337  
   338  void
   339  elfsetupplt(void)
   340  {
   341  	LSym *plt;
   342  
   343  	plt = linklookup(ctxt, ".plt", 0);
   344  	if(plt->size == 0) {
   345  		// The dynamic linker stores the address of the
   346  		// dynamic resolver and the DSO identifier in the two
   347  		// doublewords at the beginning of the .plt section
   348  		// before the PLT array.  Reserve space for these.
   349  		plt->size = 16;
   350  	}
   351  }
   352  
   353  int
   354  machoreloc1(Reloc *r, vlong sectoff)
   355  {
   356  	USED(r);
   357  	USED(sectoff);
   358  
   359  	return -1;
   360  }
   361  
   362  // Return the value of .TOC. for symbol s
   363  static vlong
   364  symtoc(LSym *s)
   365  {
   366  	LSym *toc;
   367  
   368  	if(s->outer != nil)
   369  		toc = linkrlookup(ctxt, ".TOC.", s->outer->version);
   370  	else
   371  		toc = linkrlookup(ctxt, ".TOC.", s->version);
   372  
   373  	if(toc == nil) {
   374  		diag("TOC-relative relocation in object without .TOC.");
   375  		return 0;
   376  	}
   377  	return toc->value;
   378  }
   379  
   380  int
   381  archreloc(Reloc *r, LSym *s, vlong *val)
   382  {
   383  	uint32 o1, o2;
   384  	vlong t;
   385  
   386  	if(linkmode == LinkExternal) {
   387  		// TODO(minux): translate R_ADDRPOWER and R_CALLPOWER into standard ELF relocations.
   388  		// R_ADDRPOWER corresponds to R_PPC_ADDR16_HA and R_PPC_ADDR16_LO.
   389  		// R_CALLPOWER corresponds to R_PPC_REL24.
   390  		return -1;
   391  	}
   392  	switch(r->type) {
   393  	case R_CONST:
   394  		*val = r->add;
   395  		return 0;
   396  	case R_GOTOFF:
   397  		*val = symaddr(r->sym) + r->add - symaddr(linklookup(ctxt, ".got", 0));
   398  		return 0;
   399  	case R_ADDRPOWER:
   400  		// r->add is two ppc64 instructions holding an immediate 32-bit constant.
   401  		// We want to add r->sym's address to that constant.
   402  		// The encoding of the immediate x<<16 + y,
   403  		// where x is the low 16 bits of the first instruction and y is the low 16
   404  		// bits of the second. Both x and y are signed (int16, not uint16).
   405  		o1 = r->add >> 32;
   406  		o2 = r->add;
   407  		t = symaddr(r->sym);
   408  		if(t < 0) {
   409  			ctxt->diag("relocation for %s is too big (>=2G): %lld", s->name, symaddr(r->sym));
   410  		}
   411  		t += ((o1 & 0xffff) << 16) + ((int32)o2 << 16 >> 16);
   412  		if(t & 0x8000)
   413  			t += 0x10000;
   414  		o1 = (o1 & 0xffff0000) | ((t >> 16) & 0xffff);
   415  		o2 = (o2 & 0xffff0000) | (t & 0xffff);
   416  		// when laid out, the instruction order must always be o1, o2.
   417  		if(ctxt->arch->endian == BigEndian)
   418  			*val = ((vlong)o1 << 32) | o2;
   419  		else
   420  			*val = ((vlong)o2 << 32) | o1;
   421  		return 0;
   422  	case R_CALLPOWER:
   423  		// Bits 6 through 29 = (S + A - P) >> 2
   424  		if(ctxt->arch->endian == BigEndian)
   425  			o1 = be32(s->p + r->off);
   426  		else
   427  			o1 = le32(s->p + r->off);
   428  
   429  		t = symaddr(r->sym) + r->add - (s->value + r->off);
   430  		if(t & 3)
   431  			ctxt->diag("relocation for %s+%d is not aligned: %lld", r->sym->name, r->off, t);
   432  		if((int32)(t << 6) >> 6 != t)
   433  			// TODO(austin) This can happen if text > 32M.
   434  			// Add a call trampoline to .text in that case.
   435  			ctxt->diag("relocation for %s+%d is too big: %lld", r->sym->name, r->off, t);
   436  
   437  		*val = (o1 & 0xfc000003U) | (t & ~0xfc000003U);
   438  		return 0;
   439  	case R_POWER_TOC:	// S + A - .TOC.
   440  		*val = symaddr(r->sym) + r->add - symtoc(s);
   441  		return 0;
   442  	}
   443  	return -1;
   444  }
   445  
   446  vlong
   447  archrelocvariant(Reloc *r, LSym *s, vlong t)
   448  {
   449  	uint32 o1;
   450  	switch(r->variant & RV_TYPE_MASK) {
   451  	default:
   452  		diag("unexpected relocation variant %d", r->variant);
   453  
   454  	case RV_NONE:
   455  		return t;
   456  
   457  	case RV_POWER_LO:
   458  		if(r->variant & RV_CHECK_OVERFLOW) {
   459  			// Whether to check for signed or unsigned
   460  			// overflow depends on the instruction
   461  			if(ctxt->arch->endian == BigEndian)
   462  				o1 = be32(s->p + r->off - 2);
   463  			else
   464  				o1 = le32(s->p + r->off);
   465  			switch(o1 >> 26) {
   466  			case 24:	// ori
   467  			case 26:	// xori
   468  			case 28:	// andi
   469  				if((t >> 16) != 0)
   470  					goto overflow;
   471  				break;
   472  			default:
   473  				if((int16)t != t)
   474  					goto overflow;
   475  				break;
   476  			}
   477  		}
   478  		return (int16)t;
   479  
   480  	case RV_POWER_HA:
   481  		t += 0x8000;
   482  		// Fallthrough
   483  	case RV_POWER_HI:
   484  		t >>= 16;
   485  		if(r->variant & RV_CHECK_OVERFLOW) {
   486  			// Whether to check for signed or unsigned
   487  			// overflow depends on the instruction
   488  			if(ctxt->arch->endian == BigEndian)
   489  				o1 = be32(s->p + r->off - 2);
   490  			else
   491  				o1 = le32(s->p + r->off);
   492  			switch(o1 >> 26) {
   493  			case 25:	// oris
   494  			case 27:	// xoris
   495  			case 29:	// andis
   496  				if((t >> 16) != 0)
   497  					goto overflow;
   498  				break;
   499  			default:
   500  				if((int16)t != t)
   501  					goto overflow;
   502  				break;
   503  			}
   504  		}
   505  		return (int16)t;
   506  
   507  	case RV_POWER_DS:
   508  		if(ctxt->arch->endian == BigEndian)
   509  			o1 = be16(s->p + r->off);
   510  		else
   511  			o1 = le16(s->p + r->off);
   512  		if(t & 3)
   513  			diag("relocation for %s+%d is not aligned: %lld", r->sym->name, r->off, t);
   514  		if((r->variant & RV_CHECK_OVERFLOW) && (int16)t != t)
   515  			goto overflow;
   516  		return (o1 & 0x3) | (vlong)(int16)t;
   517  	}
   518  
   519  overflow:
   520  	diag("relocation for %s+%d is too big: %lld", r->sym->name, r->off, t);
   521  	return t;
   522  }
   523  
   524  static void
   525  addpltsym(Link *ctxt, LSym *s)
   526  {
   527  	if(s->plt >= 0)
   528  		return;
   529  
   530  	adddynsym(ctxt, s);
   531  
   532  	if(iself) {
   533  		LSym *plt, *rela, *glink;
   534  		Reloc *r;
   535  
   536  		plt = linklookup(ctxt, ".plt", 0);
   537  		rela = linklookup(ctxt, ".rela.plt", 0);
   538  		if(plt->size == 0)
   539  			elfsetupplt();
   540  
   541  		// Create the glink resolver if necessary
   542  		glink = ensureglinkresolver();
   543  
   544  		// Write symbol resolver stub (just a branch to the
   545  		// glink resolver stub)
   546  		r = addrel(glink);
   547  		r->sym = glink;
   548  		r->off = glink->size;
   549  		r->siz = 4;
   550  		r->type = R_CALLPOWER;
   551  		adduint32(ctxt, glink, 0x48000000); // b .glink
   552  
   553  		// In the ppc64 ABI, the dynamic linker is responsible
   554  		// for writing the entire PLT.  We just need to
   555  		// reserve 8 bytes for each PLT entry and generate a
   556  		// JMP_SLOT dynamic relocation for it.
   557  		//
   558  		// TODO(austin): ABI v1 is different
   559  		s->plt = plt->size;
   560  		plt->size += 8;
   561  
   562  		addaddrplus(ctxt, rela, plt, s->plt);
   563  		adduint64(ctxt, rela, ELF64_R_INFO(s->dynid, R_PPC64_JMP_SLOT));
   564  		adduint64(ctxt, rela, 0);
   565  	} else {
   566  		diag("addpltsym: unsupported binary format");
   567  	}
   568  }
   569  
   570  // Generate the glink resolver stub if necessary and return the .glink section
   571  static LSym*
   572  ensureglinkresolver(void)
   573  {
   574  	LSym *glink, *s;
   575  	Reloc *r;
   576  
   577  	glink = linklookup(ctxt, ".glink", 0);
   578  	if(glink->size != 0)
   579  		return glink;
   580  
   581  	// This is essentially the resolver from the ppc64 ELF ABI.
   582  	// At entry, r12 holds the address of the symbol resolver stub
   583  	// for the target routine and the argument registers hold the
   584  	// arguments for the target routine.
   585  	//
   586  	// This stub is PIC, so first get the PC of label 1 into r11.
   587  	// Other things will be relative to this.
   588  	adduint32(ctxt, glink, 0x7c0802a6); // mflr r0
   589  	adduint32(ctxt, glink, 0x429f0005); // bcl 20,31,1f
   590  	adduint32(ctxt, glink, 0x7d6802a6); // 1: mflr r11
   591  	adduint32(ctxt, glink, 0x7c0803a6); // mtlf r0
   592  
   593  	// Compute the .plt array index from the entry point address.
   594  	// Because this is PIC, everything is relative to label 1b (in
   595  	// r11):
   596  	//   r0 = ((r12 - r11) - (res_0 - r11)) / 4 = (r12 - res_0) / 4
   597  	adduint32(ctxt, glink, 0x3800ffd0); // li r0,-(res_0-1b)=-48
   598  	adduint32(ctxt, glink, 0x7c006214); // add r0,r0,r12
   599  	adduint32(ctxt, glink, 0x7c0b0050); // sub r0,r0,r11
   600  	adduint32(ctxt, glink, 0x7800f082); // srdi r0,r0,2
   601  
   602  	// r11 = address of the first byte of the PLT
   603  	r = addrel(glink);
   604  	r->off = glink->size;
   605  	r->sym = linklookup(ctxt, ".plt", 0);
   606  	r->siz = 8;
   607  	r->type = R_ADDRPOWER;
   608  	// addis r11,0,.plt@ha; addi r11,r11,.plt@l
   609  	r->add = (0x3d600000ull << 32) | 0x396b0000;
   610  	glink->size += 8;
   611  
   612  	// Load r12 = dynamic resolver address and r11 = DSO
   613  	// identifier from the first two doublewords of the PLT.
   614  	adduint32(ctxt, glink, 0xe98b0000); // ld r12,0(r11)
   615  	adduint32(ctxt, glink, 0xe96b0008); // ld r11,8(r11)
   616  
   617  	// Jump to the dynamic resolver
   618  	adduint32(ctxt, glink, 0x7d8903a6); // mtctr r12
   619  	adduint32(ctxt, glink, 0x4e800420); // bctr
   620  
   621  	// The symbol resolvers must immediately follow.
   622  	//   res_0:
   623  
   624  	// Add DT_PPC64_GLINK .dynamic entry, which points to 32 bytes
   625  	// before the first symbol resolver stub.
   626  	s = linklookup(ctxt, ".dynamic", 0);
   627  	elfwritedynentsymplus(s, DT_PPC64_GLINK, glink, glink->size - 32);
   628  
   629  	return glink;
   630  }
   631  
   632  void
   633  adddynsym(Link *ctxt, LSym *s)
   634  {
   635  	LSym *d;
   636  	int t;
   637  	char *name;
   638  
   639  	if(s->dynid >= 0)
   640  		return;
   641  
   642  	if(iself) {
   643  		s->dynid = nelfsym++;
   644  
   645  		d = linklookup(ctxt, ".dynsym", 0);
   646  
   647  		name = s->extname;
   648  		adduint32(ctxt, d, addstring(linklookup(ctxt, ".dynstr", 0), name));
   649  
   650  		/* type */
   651  		t = STB_GLOBAL << 4;
   652  		if(s->cgoexport && (s->type&SMASK) == STEXT)
   653  			t |= STT_FUNC;
   654  		else
   655  			t |= STT_OBJECT;
   656  		adduint8(ctxt, d, t);
   657  
   658  		/* reserved */
   659  		adduint8(ctxt, d, 0);
   660  
   661  		/* section where symbol is defined */
   662  		if(s->type == SDYNIMPORT)
   663  			adduint16(ctxt, d, SHN_UNDEF);
   664  		else
   665  			adduint16(ctxt, d, 1);
   666  
   667  		/* value */
   668  		if(s->type == SDYNIMPORT)
   669  			adduint64(ctxt, d, 0);
   670  		else
   671  			addaddr(ctxt, d, s);
   672  
   673  		/* size of object */
   674  		adduint64(ctxt, d, s->size);
   675  	} else {
   676  		diag("adddynsym: unsupported binary format");
   677  	}
   678  }
   679  
   680  void
   681  adddynlib(char *lib)
   682  {
   683  	LSym *s;
   684  	
   685  	if(!needlib(lib))
   686  		return;
   687  	
   688  	if(iself) {
   689  		s = linklookup(ctxt, ".dynstr", 0);
   690  		if(s->size == 0)
   691  			addstring(s, "");
   692  		elfwritedynent(linklookup(ctxt, ".dynamic", 0), DT_NEEDED, addstring(s, lib));
   693  	} else {
   694  		diag("adddynlib: unsupported binary format");
   695  	}
   696  }
   697  
   698  void
   699  asmb(void)
   700  {
   701  	uint32 symo;
   702  	Section *sect;
   703  	LSym *sym;
   704  	int i;
   705  
   706  	if(debug['v'])
   707  		Bprint(&bso, "%5.2f asmb\n", cputime());
   708  	Bflush(&bso);
   709  
   710  	if(iself)
   711  		asmbelfsetup();
   712  
   713  	sect = segtext.sect;
   714  	cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
   715  	codeblk(sect->vaddr, sect->len);
   716  	for(sect = sect->next; sect != nil; sect = sect->next) {
   717  		cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
   718  		datblk(sect->vaddr, sect->len);
   719  	}
   720  
   721  	if(segrodata.filelen > 0) {
   722  		if(debug['v'])
   723  			Bprint(&bso, "%5.2f rodatblk\n", cputime());
   724  		Bflush(&bso);
   725  
   726  		cseek(segrodata.fileoff);
   727  		datblk(segrodata.vaddr, segrodata.filelen);
   728  	}
   729  
   730  	if(debug['v'])
   731  		Bprint(&bso, "%5.2f datblk\n", cputime());
   732  	Bflush(&bso);
   733  
   734  	cseek(segdata.fileoff);
   735  	datblk(segdata.vaddr, segdata.filelen);
   736  
   737  	/* output symbol table */
   738  	symsize = 0;
   739  	lcsize = 0;
   740  	symo = 0;
   741  	if(!debug['s']) {
   742  		// TODO: rationalize
   743  		if(debug['v'])
   744  			Bprint(&bso, "%5.2f sym\n", cputime());
   745  		Bflush(&bso);
   746  		switch(HEADTYPE) {
   747  		default:
   748  			if(iself)
   749  				goto ElfSym;
   750  		case Hplan9:
   751  			symo = segdata.fileoff+segdata.filelen;
   752  			break;
   753  		ElfSym:
   754  			symo = segdata.fileoff+segdata.filelen;
   755  			symo = rnd(symo, INITRND);
   756  			break;
   757  		}
   758  		cseek(symo);
   759  		switch(HEADTYPE) {
   760  		default:
   761  			if(iself) {
   762  				if(debug['v'])
   763  					Bprint(&bso, "%5.2f elfsym\n", cputime());
   764  				asmelfsym();
   765  				cflush();
   766  				cwrite(elfstrdat, elfstrsize);
   767  	
   768  				if(debug['v'])
   769  					Bprint(&bso, "%5.2f dwarf\n", cputime());
   770  				dwarfemitdebugsections();
   771  				
   772  				if(linkmode == LinkExternal)
   773  					elfemitreloc();
   774  			}
   775  			break;
   776  		case Hplan9:
   777  			asmplan9sym();
   778  			cflush();
   779  
   780  			sym = linklookup(ctxt, "pclntab", 0);
   781  			if(sym != nil) {
   782  				lcsize = sym->np;
   783  				for(i=0; i < lcsize; i++)
   784  					cput(sym->p[i]);
   785  
   786  				cflush();
   787  			}
   788  			break;
   789  		}
   790  	}
   791  
   792  	ctxt->cursym = nil;
   793  	if(debug['v'])
   794  		Bprint(&bso, "%5.2f header\n", cputime());
   795  	Bflush(&bso);
   796  	cseek(0L);
   797  	switch(HEADTYPE) {
   798  	default:
   799  	case Hplan9:	/* plan 9 */
   800  		LPUT(0x647);			/* magic */
   801  		LPUT(segtext.filelen);			/* sizes */
   802  		LPUT(segdata.filelen);
   803  		LPUT(segdata.len - segdata.filelen);
   804  		LPUT(symsize);			/* nsyms */
   805  		LPUT(entryvalue());		/* va of entry */
   806  		LPUT(0L);
   807  		LPUT(lcsize);
   808  		break;
   809  	case Hlinux:
   810  	case Hfreebsd:
   811  	case Hnetbsd:
   812  	case Hopenbsd:
   813  	case Hnacl:
   814  		asmbelf(symo);
   815  		break;
   816  	}
   817  	cflush();
   818  	if(debug['c']){
   819  		print("textsize=%ulld\n", segtext.filelen);
   820  		print("datsize=%ulld\n", segdata.filelen);
   821  		print("bsssize=%ulld\n", segdata.len - segdata.filelen);
   822  		print("symsize=%d\n", symsize);
   823  		print("lcsize=%d\n", lcsize);
   824  		print("total=%lld\n", segtext.filelen+segdata.len+symsize+lcsize);
   825  	}
   826  }
   827  
   828  vlong
   829  rnd(vlong v, int32 r)
   830  {
   831  	vlong c;
   832  
   833  	if(r <= 0)
   834  		return v;
   835  	v += r - 1;
   836  	c = v % r;
   837  	if(c < 0)
   838  		c += r;
   839  	v -= c;
   840  	return v;
   841  }