github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/src/cmd/ld/data.c (about)

     1  // Inferno utils/8l/asm.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/8l/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  // Data layout and relocation.
    32  
    33  #include	"l.h"
    34  #include	"../ld/lib.h"
    35  #include	"../ld/elf.h"
    36  #include	"../ld/macho.h"
    37  #include	"../ld/pe.h"
    38  #include	"../../runtime/mgc0.h"
    39  
    40  void	dynreloc(void);
    41  
    42  /*
    43   * divide-and-conquer list-link
    44   * sort of LSym* structures.
    45   * Used for the data block.
    46   */
    47  int
    48  datcmp(LSym *s1, LSym *s2)
    49  {
    50  	if(s1->type != s2->type)
    51  		return (int)s1->type - (int)s2->type;
    52  	// For ppc64, we want to interleave the .got and .toc sections
    53  	// from input files.  Both are type SELFGOT, so in that case
    54  	// fall through to the name comparison (conveniently, .got
    55  	// sorts before .toc).
    56  	if(s1->type != SELFGOT && s1->size != s2->size) {
    57  		if(s1->size < s2->size)
    58  			return -1;
    59  		return +1;
    60  	}
    61  	return strcmp(s1->name, s2->name);
    62  }
    63  
    64  LSym*
    65  listsort(LSym *l, int (*cmp)(LSym*, LSym*), int off)
    66  {
    67  	LSym *l1, *l2, *le;
    68  	#define NEXT(l) (*(LSym**)((char*)(l)+off))
    69  
    70  	if(l == 0 || NEXT(l) == 0)
    71  		return l;
    72  
    73  	l1 = l;
    74  	l2 = l;
    75  	for(;;) {
    76  		l2 = NEXT(l2);
    77  		if(l2 == 0)
    78  			break;
    79  		l2 = NEXT(l2);
    80  		if(l2 == 0)
    81  			break;
    82  		l1 = NEXT(l1);
    83  	}
    84  
    85  	l2 = NEXT(l1);
    86  	NEXT(l1) = 0;
    87  	l1 = listsort(l, cmp, off);
    88  	l2 = listsort(l2, cmp, off);
    89  
    90  	/* set up lead element */
    91  	if(cmp(l1, l2) < 0) {
    92  		l = l1;
    93  		l1 = NEXT(l1);
    94  	} else {
    95  		l = l2;
    96  		l2 = NEXT(l2);
    97  	}
    98  	le = l;
    99  
   100  	for(;;) {
   101  		if(l1 == 0) {
   102  			while(l2) {
   103  				NEXT(le) = l2;
   104  				le = l2;
   105  				l2 = NEXT(l2);
   106  			}
   107  			NEXT(le) = 0;
   108  			break;
   109  		}
   110  		if(l2 == 0) {
   111  			while(l1) {
   112  				NEXT(le) = l1;
   113  				le = l1;
   114  				l1 = NEXT(l1);
   115  			}
   116  			break;
   117  		}
   118  		if(cmp(l1, l2) < 0) {
   119  			NEXT(le) = l1;
   120  			le = l1;
   121  			l1 = NEXT(l1);
   122  		} else {
   123  			NEXT(le) = l2;
   124  			le = l2;
   125  			l2 = NEXT(l2);
   126  		}
   127  	}
   128  	NEXT(le) = 0;
   129  	return l;
   130  	
   131  	#undef NEXT
   132  }
   133  
   134  void
   135  relocsym(LSym *s)
   136  {
   137  	Reloc *r;
   138  	LSym *rs;
   139  	int16 i16;
   140  	int32 i, off, siz, fl;
   141  	vlong o;
   142  	uchar *cast;
   143  
   144  	ctxt->cursym = s;
   145  	for(r=s->r; r<s->r+s->nr; r++) {
   146  		r->done = 1;
   147  		off = r->off;
   148  		siz = r->siz;
   149  		if(off < 0 || off+siz > s->np) {
   150  			diag("%s: invalid relocation %d+%d not in [%d,%d)", s->name, off, siz, 0, s->np);
   151  			continue;
   152  		}
   153  		if(r->sym != S && ((r->sym->type & (SMASK | SHIDDEN)) == 0 || (r->sym->type & SMASK) == SXREF)) {
   154  			diag("%s: not defined", r->sym->name);
   155  			continue;
   156  		}
   157  		if(r->type >= 256)
   158  			continue;
   159  		if(r->siz == 0) // informational relocation - no work to do
   160  			continue;
   161  
   162  		// Solaris needs the ability to reference dynimport symbols.
   163  		if(HEADTYPE != Hsolaris && r->sym != S && r->sym->type == SDYNIMPORT)
   164  			diag("unhandled relocation for %s (type %d rtype %d)", r->sym->name, r->sym->type, r->type);
   165  		if(r->sym != S && r->sym->type != STLSBSS && !r->sym->reachable)
   166  			diag("unreachable sym in relocation: %s %s", s->name, r->sym->name);
   167  
   168  		// Android emulates runtime.tlsg as a regular variable.
   169  		if (r->type == R_TLS && strcmp(goos, "android") == 0)
   170  			r->type = R_ADDR;
   171  
   172  		switch(r->type) {
   173  		default:
   174  			o = 0;
   175  			if(archreloc(r, s, &o) < 0)
   176  				diag("unknown reloc %d", r->type);
   177  			break;
   178  		case R_TLS:
   179  			if(linkmode == LinkInternal && iself && thechar == '5') {
   180  				// On ELF ARM, the thread pointer is 8 bytes before
   181  				// the start of the thread-local data block, so add 8
   182  				// to the actual TLS offset (r->sym->value).
   183  				// This 8 seems to be a fundamental constant of
   184  				// ELF on ARM (or maybe Glibc on ARM); it is not
   185  				// related to the fact that our own TLS storage happens
   186  				// to take up 8 bytes.
   187  				o = 8 + r->sym->value;
   188  				break;
   189  			}
   190  			r->done = 0;
   191  			o = 0;
   192  			if(thechar != '6')
   193  				o = r->add;
   194  			break;
   195  		case R_TLS_LE:
   196  			if(linkmode == LinkExternal && iself && HEADTYPE != Hopenbsd) {
   197  				r->done = 0;
   198  				r->sym = ctxt->tlsg;
   199  				r->xsym = ctxt->tlsg;
   200  				r->xadd = r->add;
   201  				o = 0;
   202  				if(thechar != '6')
   203  					o = r->add;
   204  				break;
   205  			}
   206  			o = ctxt->tlsoffset + r->add;
   207  			break;
   208  
   209  		case R_TLS_IE:
   210  			if(linkmode == LinkExternal && iself && HEADTYPE != Hopenbsd) {
   211  				r->done = 0;
   212  				r->sym = ctxt->tlsg;
   213  				r->xsym = ctxt->tlsg;
   214  				r->xadd = r->add;
   215  				o = 0;
   216  				if(thechar != '6')
   217  					o = r->add;
   218  				break;
   219  			}
   220  			if(iself || ctxt->headtype == Hplan9)
   221  				o = ctxt->tlsoffset + r->add;
   222  			else if(ctxt->headtype == Hwindows)
   223  				o = r->add;
   224  			else
   225  				sysfatal("unexpected R_TLS_IE relocation for %s", headstr(ctxt->headtype));
   226  			break;
   227  		case R_ADDR:
   228  			if(linkmode == LinkExternal && r->sym->type != SCONST) {
   229  				r->done = 0;
   230  
   231  				// set up addend for eventual relocation via outer symbol.
   232  				rs = r->sym;
   233  				r->xadd = r->add;
   234  				while(rs->outer != nil) {
   235  					r->xadd += symaddr(rs) - symaddr(rs->outer);
   236  					rs = rs->outer;
   237  				}
   238  				if(rs->type != SHOSTOBJ && rs->type != SDYNIMPORT && rs->sect == nil)
   239  					diag("missing section for %s", rs->name);
   240  				r->xsym = rs;
   241  
   242  				o = r->xadd;
   243  				if(iself) {
   244  					if(thechar == '6')
   245  						o = 0;
   246  				} else if(HEADTYPE == Hdarwin) {
   247  					if(rs->type != SHOSTOBJ)
   248  						o += symaddr(rs);
   249  				} else {
   250  					diag("unhandled pcrel relocation for %s", headstring);
   251  				}
   252  				break;
   253  			}
   254  			o = symaddr(r->sym) + r->add;
   255  
   256  			// On amd64, 4-byte offsets will be sign-extended, so it is impossible to
   257  			// access more than 2GB of static data; fail at link time is better than
   258  			// fail at runtime. See http://golang.org/issue/7980.
   259  			// Instead of special casing only amd64, we treat this as an error on all
   260  			// 64-bit architectures so as to be future-proof.
   261  			if((int32)o < 0 && PtrSize > 4 && siz == 4) {
   262  				diag("non-pc-relative relocation address is too big: %#llux", o);
   263  				errorexit();
   264  			}
   265  			break;
   266  		case R_CALL:
   267  		case R_PCREL:
   268  			// r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
   269  			if(linkmode == LinkExternal && r->sym && r->sym->type != SCONST && r->sym->sect != ctxt->cursym->sect) {
   270  				r->done = 0;
   271  
   272  				// set up addend for eventual relocation via outer symbol.
   273  				rs = r->sym;
   274  				r->xadd = r->add;
   275  				while(rs->outer != nil) {
   276  					r->xadd += symaddr(rs) - symaddr(rs->outer);
   277  					rs = rs->outer;
   278  				}
   279  				r->xadd -= r->siz; // relative to address after the relocated chunk
   280  				if(rs->type != SHOSTOBJ && rs->type != SDYNIMPORT && rs->sect == nil)
   281  					diag("missing section for %s", rs->name);
   282  				r->xsym = rs;
   283  
   284  				o = r->xadd;
   285  				if(iself) {
   286  					if(thechar == '6')
   287  						o = 0;
   288  				} else if(HEADTYPE == Hdarwin) {
   289  					if(r->type == R_CALL) {
   290  						if(rs->type != SHOSTOBJ)
   291  							o += symaddr(rs) - rs->sect->vaddr;
   292  						o -= r->off; // relative to section offset, not symbol
   293  					} else {
   294  						o += r->siz;
   295  					}
   296  				} else {
   297  					diag("unhandled pcrel relocation for %s", headstring);
   298  				}
   299  				break;
   300  			}
   301  			o = 0;
   302  			if(r->sym)
   303  				o += symaddr(r->sym);
   304  			// NOTE: The (int32) cast on the next line works around a bug in Plan 9's 8c
   305  			// compiler. The expression s->value + r->off + r->siz is int32 + int32 +
   306  			// uchar, and Plan 9 8c incorrectly treats the expression as type uint32
   307  			// instead of int32, causing incorrect values when sign extended for adding
   308  			// to o. The bug only occurs on Plan 9, because this C program is compiled by
   309  			// the standard host compiler (gcc on most other systems).
   310  			o += r->add - (s->value + r->off + (int32)r->siz);
   311  			break;
   312  		case R_SIZE:
   313  			o = r->sym->size + r->add;
   314  			break;
   315  		}
   316  		if(r->variant != RV_NONE)
   317  			o = archrelocvariant(r, s, o);
   318  //print("relocate %s %#llux (%#llux+%#llux, size %d) => %s %#llux +%#llx [%llx]\n", s->name, (uvlong)(s->value+off), (uvlong)s->value, (uvlong)r->off, r->siz, r->sym ? r->sym->name : "<nil>", (uvlong)symaddr(r->sym), (vlong)r->add, (vlong)o);
   319  		switch(siz) {
   320  		default:
   321  			ctxt->cursym = s;
   322  			diag("bad reloc size %#ux for %s", siz, r->sym->name);
   323  		case 1:
   324  			// TODO(rsc): Remove.
   325  			s->p[off] = (int8)o;
   326  			break;
   327  		case 2:
   328  			if(o != (int16)o)
   329  				diag("relocation address is too big: %#llx", o);
   330  			i16 = o;
   331  			cast = (uchar*)&i16;
   332  			for(i=0; i<2; i++)
   333  				s->p[off+i] = cast[inuxi2[i]];
   334  			break;
   335  		case 4:
   336  			if(r->type == R_PCREL || r->type == R_CALL) {
   337  				if(o != (int32)o)
   338  					diag("pc-relative relocation address is too big: %#llx", o);
   339  			} else {
   340  				if(o != (int32)o && o != (uint32)o)
   341  					diag("non-pc-relative relocation address is too big: %#llux", o);
   342  			}
   343  			fl = o;
   344  			cast = (uchar*)&fl;
   345  			for(i=0; i<4; i++)
   346  				s->p[off+i] = cast[inuxi4[i]];
   347  			break;
   348  		case 8:
   349  			cast = (uchar*)&o;
   350  			for(i=0; i<8; i++)
   351  				s->p[off+i] = cast[inuxi8[i]];
   352  			break;
   353  		}
   354  	}
   355  }
   356  
   357  void
   358  reloc(void)
   359  {
   360  	LSym *s;
   361  
   362  	if(debug['v'])
   363  		Bprint(&bso, "%5.2f reloc\n", cputime());
   364  	Bflush(&bso);
   365  
   366  	for(s=ctxt->textp; s!=S; s=s->next)
   367  		relocsym(s);
   368  	for(s=datap; s!=S; s=s->next)
   369  		relocsym(s);
   370  }
   371  
   372  void
   373  dynrelocsym(LSym *s)
   374  {
   375  	Reloc *r;
   376  
   377  	if(HEADTYPE == Hwindows) {
   378  		LSym *rel, *targ;
   379  
   380  		rel = linklookup(ctxt, ".rel", 0);
   381  		if(s == rel)
   382  			return;
   383  		for(r=s->r; r<s->r+s->nr; r++) {
   384  			targ = r->sym;
   385  			if(targ == nil)
   386  				continue;
   387  			if(!targ->reachable)
   388  				diag("internal inconsistency: dynamic symbol %s is not reachable.", targ->name);
   389  			if(r->sym->plt == -2 && r->sym->got != -2) { // make dynimport JMP table for PE object files.
   390  				targ->plt = rel->size;
   391  				r->sym = rel;
   392  				r->add = targ->plt;
   393  
   394  				// jmp *addr
   395  				if(thechar == '8') {
   396  					adduint8(ctxt, rel, 0xff);
   397  					adduint8(ctxt, rel, 0x25);
   398  					addaddr(ctxt, rel, targ);
   399  					adduint8(ctxt, rel, 0x90);
   400  					adduint8(ctxt, rel, 0x90);
   401  				} else {
   402  					adduint8(ctxt, rel, 0xff);
   403  					adduint8(ctxt, rel, 0x24);
   404  					adduint8(ctxt, rel, 0x25);
   405  					addaddrplus4(ctxt, rel, targ, 0);
   406  					adduint8(ctxt, rel, 0x90);
   407  				}
   408  			} else if(r->sym->plt >= 0) {
   409  				r->sym = rel;
   410  				r->add = targ->plt;
   411  			}
   412  		}
   413  		return;
   414  	}
   415  
   416  	for(r=s->r; r<s->r+s->nr; r++) {
   417  		if(r->sym != S && r->sym->type == SDYNIMPORT || r->type >= 256) {
   418  			if(r->sym != S && !r->sym->reachable)
   419  				diag("internal inconsistency: dynamic symbol %s is not reachable.", r->sym->name);
   420  			adddynrel(s, r);
   421  		}
   422  	}
   423  }
   424  
   425  void
   426  dynreloc(void)
   427  {
   428  	LSym *s;
   429  
   430  	// -d suppresses dynamic loader format, so we may as well not
   431  	// compute these sections or mark their symbols as reachable.
   432  	if(debug['d'] && HEADTYPE != Hwindows)
   433  		return;
   434  	if(debug['v'])
   435  		Bprint(&bso, "%5.2f reloc\n", cputime());
   436  	Bflush(&bso);
   437  
   438  	for(s=ctxt->textp; s!=S; s=s->next)
   439  		dynrelocsym(s);
   440  	for(s=datap; s!=S; s=s->next)
   441  		dynrelocsym(s);
   442  	if(iself)
   443  		elfdynhash();
   444  }
   445  
   446  static void
   447  blk(LSym *start, int64 addr, int64 size)
   448  {
   449  	LSym *sym;
   450  	int64 eaddr;
   451  	uchar *p, *ep;
   452  
   453  	for(sym = start; sym != nil; sym = sym->next)
   454  		if(!(sym->type&SSUB) && sym->value >= addr)
   455  			break;
   456  
   457  	eaddr = addr+size;
   458  	for(; sym != nil; sym = sym->next) {
   459  		if(sym->type&SSUB)
   460  			continue;
   461  		if(sym->value >= eaddr)
   462  			break;
   463  		ctxt->cursym = sym;
   464  		if(sym->value < addr) {
   465  			diag("phase error: addr=%#llx but sym=%#llx type=%d", (vlong)addr, (vlong)sym->value, sym->type);
   466  			errorexit();
   467  		}
   468  		for(; addr < sym->value; addr++)
   469  			cput(0);
   470  		p = sym->p;
   471  		ep = p + sym->np;
   472  		while(p < ep)
   473  			cput(*p++);
   474  		addr += sym->np;
   475  		for(; addr < sym->value+sym->size; addr++)
   476  			cput(0);
   477  		if(addr != sym->value+sym->size) {
   478  			diag("phase error: addr=%#llx value+size=%#llx", (vlong)addr, (vlong)sym->value+sym->size);
   479  			errorexit();
   480  		}
   481  		if(sym->value+sym->size >= eaddr)
   482  			break;
   483  	}
   484  
   485  	for(; addr < eaddr; addr++)
   486  		cput(0);
   487  	cflush();
   488  }
   489  
   490  void
   491  codeblk(int64 addr, int64 size)
   492  {
   493  	LSym *sym;
   494  	int64 eaddr, n;
   495  	uchar *q;
   496  
   497  	if(debug['a'])
   498  		Bprint(&bso, "codeblk [%#x,%#x) at offset %#llx\n", addr, addr+size, cpos());
   499  
   500  	blk(ctxt->textp, addr, size);
   501  
   502  	/* again for printing */
   503  	if(!debug['a'])
   504  		return;
   505  
   506  	for(sym = ctxt->textp; sym != nil; sym = sym->next) {
   507  		if(!sym->reachable)
   508  			continue;
   509  		if(sym->value >= addr)
   510  			break;
   511  	}
   512  
   513  	eaddr = addr + size;
   514  	for(; sym != nil; sym = sym->next) {
   515  		if(!sym->reachable)
   516  			continue;
   517  		if(sym->value >= eaddr)
   518  			break;
   519  
   520  		if(addr < sym->value) {
   521  			Bprint(&bso, "%-20s %.8llux|", "_", (vlong)addr);
   522  			for(; addr < sym->value; addr++)
   523  				Bprint(&bso, " %.2ux", 0);
   524  			Bprint(&bso, "\n");
   525  		}
   526  
   527  		Bprint(&bso, "%.6llux\t%-20s\n", (vlong)addr, sym->name);
   528  		n = sym->size;
   529  		q = sym->p;
   530  
   531  		while(n >= 16) {
   532  			Bprint(&bso, "%.6ux\t%-20.16I\n", addr, q);
   533  			addr += 16;
   534  			q += 16;
   535  			n -= 16;
   536  		}
   537  		if(n > 0)
   538  			Bprint(&bso, "%.6ux\t%-20.*I\n", addr, (int)n, q);
   539  		addr += n;
   540  	}
   541  
   542  	if(addr < eaddr) {
   543  		Bprint(&bso, "%-20s %.8llux|", "_", (vlong)addr);
   544  		for(; addr < eaddr; addr++)
   545  			Bprint(&bso, " %.2ux", 0);
   546  	}
   547  	Bflush(&bso);
   548  }
   549  
   550  void
   551  datblk(int64 addr, int64 size)
   552  {
   553  	LSym *sym;
   554  	int64 i, eaddr;
   555  	uchar *p, *ep;
   556  	char *typ, *rsname;
   557  	Reloc *r;
   558  
   559  	if(debug['a'])
   560  		Bprint(&bso, "datblk [%#x,%#x) at offset %#llx\n", addr, addr+size, cpos());
   561  
   562  	blk(datap, addr, size);
   563  
   564  	/* again for printing */
   565  	if(!debug['a'])
   566  		return;
   567  
   568  	for(sym = datap; sym != nil; sym = sym->next)
   569  		if(sym->value >= addr)
   570  			break;
   571  
   572  	eaddr = addr + size;
   573  	for(; sym != nil; sym = sym->next) {
   574  		if(sym->value >= eaddr)
   575  			break;
   576  		if(addr < sym->value) {
   577  			Bprint(&bso, "\t%.8ux| 00 ...\n", addr);
   578  			addr = sym->value;
   579  		}
   580  		Bprint(&bso, "%s\n\t%.8ux|", sym->name, (uint)addr);
   581  		p = sym->p;
   582  		ep = p + sym->np;
   583  		while(p < ep) {
   584  			if(p > sym->p && (int)(p-sym->p)%16 == 0)
   585  				Bprint(&bso, "\n\t%.8ux|", (uint)(addr+(p-sym->p)));
   586  			Bprint(&bso, " %.2ux", *p++);
   587  		}
   588  		addr += sym->np;
   589  		for(; addr < sym->value+sym->size; addr++)
   590  			Bprint(&bso, " %.2ux", 0);
   591  		Bprint(&bso, "\n");
   592  		
   593  		if(linkmode == LinkExternal) {
   594  			for(i=0; i<sym->nr; i++) {
   595  				r = &sym->r[i];
   596  				rsname = "";
   597  				if(r->sym)
   598  					rsname = r->sym->name;
   599  				typ = "?";
   600  				switch(r->type) {
   601  				case R_ADDR:
   602  					typ = "addr";
   603  					break;
   604  				case R_PCREL:
   605  					typ = "pcrel";
   606  					break;
   607  				case R_CALL:
   608  					typ = "call";
   609  					break;
   610  				}
   611  				Bprint(&bso, "\treloc %.8ux/%d %s %s+%#llx [%#llx]\n",
   612  					(uint)(sym->value+r->off), r->siz, typ, rsname, (vlong)r->add, (vlong)(r->sym->value+r->add));
   613  			}
   614  		}				
   615  	}
   616  
   617  	if(addr < eaddr)
   618  		Bprint(&bso, "\t%.8ux| 00 ...\n", (uint)addr);
   619  	Bprint(&bso, "\t%.8ux|\n", (uint)eaddr);
   620  }
   621  
   622  void
   623  strnput(char *s, int n)
   624  {
   625  	for(; n > 0 && *s; s++) {
   626  		cput(*s);
   627  		n--;
   628  	}
   629  	while(n > 0) {
   630  		cput(0);
   631  		n--;
   632  	}
   633  }
   634  
   635  void
   636  addstrdata(char *name, char *value)
   637  {
   638  	LSym *s, *sp;
   639  	char *p;
   640  	uchar reachable;
   641  
   642  	p = smprint("%s.str", name);
   643  	sp = linklookup(ctxt, p, 0);
   644  	free(p);
   645  	addstring(sp, value);
   646  	sp->type = SRODATA;
   647  
   648  	s = linklookup(ctxt, name, 0);
   649  	s->size = 0;
   650  	s->dupok = 1;
   651  	reachable = s->reachable;
   652  	addaddr(ctxt, s, sp);
   653  	adduintxx(ctxt, s, strlen(value), PtrSize);
   654  
   655  	// addstring, addaddr, etc., mark the symbols as reachable.
   656  	// In this case that is not necessarily true, so stick to what
   657  	// we know before entering this function.
   658  	s->reachable = reachable;
   659  	sp->reachable = reachable;
   660  }
   661  
   662  vlong
   663  addstring(LSym *s, char *str)
   664  {
   665  	int n;
   666  	int32 r;
   667  
   668  	if(s->type == 0)
   669  		s->type = SNOPTRDATA;
   670  	s->reachable = 1;
   671  	r = s->size;
   672  	n = strlen(str)+1;
   673  	if(strcmp(s->name, ".shstrtab") == 0)
   674  		elfsetstring(str, r);
   675  	symgrow(ctxt, s, r+n);
   676  	memmove(s->p+r, str, n);
   677  	s->size += n;
   678  	return r;
   679  }
   680  
   681  void
   682  dosymtype(void)
   683  {
   684  	LSym *s;
   685  
   686  	for(s = ctxt->allsym; s != nil; s = s->allsym) {
   687  		if(s->np > 0) {
   688  			if(s->type == SBSS)
   689  				s->type = SDATA;
   690  			if(s->type == SNOPTRBSS)
   691  				s->type = SNOPTRDATA;
   692  		}
   693  	}
   694  }
   695  
   696  static int32
   697  symalign(LSym *s)
   698  {
   699  	int32 align;
   700  
   701  	if(s->align != 0)
   702  		return s->align;
   703  
   704  	align = MaxAlign;
   705  	while(align > s->size && align > 1)
   706  		align >>= 1;
   707  	if(align < s->align)
   708  		align = s->align;
   709  	return align;
   710  }
   711  	
   712  static vlong
   713  aligndatsize(vlong datsize, LSym *s)
   714  {
   715  	return rnd(datsize, symalign(s));
   716  }
   717  
   718  // maxalign returns the maximum required alignment for
   719  // the list of symbols s; the list stops when s->type exceeds type.
   720  static int32
   721  maxalign(LSym *s, int type)
   722  {
   723  	int32 align, max;
   724  	
   725  	max = 0;
   726  	for(; s != S && s->type <= type; s = s->next) {
   727  		align = symalign(s);
   728  		if(max < align)
   729  			max = align;
   730  	}
   731  	return max;
   732  }
   733  
   734  // Helper object for building GC type programs.
   735  typedef struct ProgGen ProgGen;
   736  struct ProgGen
   737  {
   738  	LSym*	s;
   739  	int32	datasize;
   740  	uint8	data[256/PointersPerByte];
   741  	vlong	pos;
   742  };
   743  
   744  static void
   745  proggeninit(ProgGen *g, LSym *s)
   746  {
   747  	g->s = s;
   748  	g->datasize = 0;
   749  	g->pos = 0;
   750  	memset(g->data, 0, sizeof(g->data));
   751  }
   752  
   753  static void
   754  proggenemit(ProgGen *g, uint8 v)
   755  {
   756  	adduint8(ctxt, g->s, v);
   757  }
   758  
   759  // Writes insData block from g->data.
   760  static void
   761  proggendataflush(ProgGen *g)
   762  {
   763  	int32 i, s;
   764  
   765  	if(g->datasize == 0)
   766  		return;
   767  	proggenemit(g, insData);
   768  	proggenemit(g, g->datasize);
   769  	s = (g->datasize + PointersPerByte - 1)/PointersPerByte;
   770  	for(i = 0; i < s; i++)
   771  		proggenemit(g, g->data[i]);
   772  	g->datasize = 0;
   773  	memset(g->data, 0, sizeof(g->data));
   774  }
   775  
   776  static void
   777  proggendata(ProgGen *g, uint8 d)
   778  {
   779  	g->data[g->datasize/PointersPerByte] |= d << ((g->datasize%PointersPerByte)*BitsPerPointer);
   780  	g->datasize++;
   781  	if(g->datasize == 255)
   782  		proggendataflush(g);
   783  }
   784  
   785  // Skip v bytes due to alignment, etc.
   786  static void
   787  proggenskip(ProgGen *g, vlong off, vlong v)
   788  {
   789  	vlong i;
   790  
   791  	for(i = off; i < off+v; i++) {
   792  		if((i%PtrSize) == 0)
   793  			proggendata(g, BitsScalar);
   794  	}
   795  }
   796  
   797  // Emit insArray instruction.
   798  static void
   799  proggenarray(ProgGen *g, vlong len)
   800  {
   801  	int32 i;
   802  
   803  	proggendataflush(g);
   804  	proggenemit(g, insArray);
   805  	for(i = 0; i < PtrSize; i++, len >>= 8)
   806  		proggenemit(g, len);
   807  }
   808  
   809  static void
   810  proggenarrayend(ProgGen *g)
   811  {
   812  	proggendataflush(g);
   813  	proggenemit(g, insArrayEnd);
   814  }
   815  
   816  static void
   817  proggenfini(ProgGen *g, vlong size)
   818  {
   819  	proggenskip(g, g->pos, size - g->pos);
   820  	proggendataflush(g);
   821  	proggenemit(g, insEnd);
   822  }
   823  
   824  
   825  // This function generates GC pointer info for global variables.
   826  static void
   827  proggenaddsym(ProgGen *g, LSym *s)
   828  {
   829  	LSym *gcprog;
   830  	uint8 *mask;
   831  	vlong i, size;
   832  
   833  	if(s->size == 0)
   834  		return;
   835  
   836  	// Skip alignment hole from the previous symbol.
   837  	proggenskip(g, g->pos, s->value - g->pos);
   838  	g->pos += s->value - g->pos;
   839  
   840  	// The test for names beginning with . here is meant
   841  	// to keep .dynamic and .dynsym from turning up as
   842  	// conservative symbols. They should be marked SELFSECT
   843  	// and not SDATA, but sometimes that doesn't happen.
   844  	// Leave debugging the SDATA issue for the Go rewrite.
   845  
   846  	if(s->gotype == nil && s->size >= PtrSize && s->name[0] != '.') {
   847  		// conservative scan
   848  		diag("missing Go type information for global symbol: %s size %d", s->name, (int)s->size);
   849  		if((s->size%PtrSize) || (g->pos%PtrSize))
   850  			diag("proggenaddsym: unaligned conservative symbol %s: size=%lld pos=%lld",
   851  				s->name, s->size, g->pos);
   852  		size = (s->size+PtrSize-1)/PtrSize*PtrSize;
   853  		if(size < 32*PtrSize) {
   854  			// Emit small symbols as data.
   855  			for(i = 0; i < size/PtrSize; i++)
   856  				proggendata(g, BitsPointer);
   857  		} else {
   858  			// Emit large symbols as array.
   859  			proggenarray(g, size/PtrSize);
   860  			proggendata(g, BitsPointer);
   861  			proggenarrayend(g);
   862  		}
   863  		g->pos = s->value + size;
   864  	} else if(s->gotype == nil || decodetype_noptr(s->gotype) || s->size < PtrSize || s->name[0] == '.') {
   865  		// no scan
   866  		if(s->size < 32*PtrSize) {
   867  			// Emit small symbols as data.
   868  			// This case also handles unaligned and tiny symbols, so tread carefully.
   869  			for(i = s->value; i < s->value+s->size; i++) {
   870  				if((i%PtrSize) == 0)
   871  					proggendata(g, BitsScalar);
   872  			}
   873  		} else {
   874  			// Emit large symbols as array.
   875  			if((s->size%PtrSize) || (g->pos%PtrSize))
   876  				diag("proggenaddsym: unaligned noscan symbol %s: size=%lld pos=%lld",
   877  					s->name, s->size, g->pos);
   878  			proggenarray(g, s->size/PtrSize);
   879  			proggendata(g, BitsScalar);
   880  			proggenarrayend(g);
   881  		}
   882  		g->pos = s->value + s->size;
   883  	} else if(decodetype_usegcprog(s->gotype)) {
   884  		// gc program, copy directly
   885  		proggendataflush(g);
   886  		gcprog = decodetype_gcprog(s->gotype);
   887  		size = decodetype_size(s->gotype);
   888  		if((size%PtrSize) || (g->pos%PtrSize))
   889  			diag("proggenaddsym: unaligned gcprog symbol %s: size=%lld pos=%lld",
   890  				s->name, s->size, g->pos);
   891  		for(i = 0; i < gcprog->np-1; i++)
   892  			proggenemit(g, gcprog->p[i]);
   893  		g->pos = s->value + size;
   894  	} else {
   895  		// gc mask, it's small so emit as data
   896  		mask = decodetype_gcmask(s->gotype);
   897  		size = decodetype_size(s->gotype);
   898  		if((size%PtrSize) || (g->pos%PtrSize))
   899  			diag("proggenaddsym: unaligned gcmask symbol %s: size=%lld pos=%lld",
   900  				s->name, s->size, g->pos);
   901  		for(i = 0; i < size; i += PtrSize)
   902  			proggendata(g, (mask[i/PtrSize/2]>>((i/PtrSize%2)*4+2))&BitsMask);
   903  		g->pos = s->value + size;
   904  	}
   905  }
   906  
   907  void
   908  growdatsize(vlong *datsizep, LSym *s)
   909  {
   910  	vlong datsize;
   911  	
   912  	datsize = *datsizep;
   913  	if(s->size < 0)
   914  		diag("negative size (datsize = %lld, s->size = %lld)", datsize, s->size);
   915  	if(datsize + s->size < datsize)
   916  		diag("symbol too large (datsize = %lld, s->size = %lld)", datsize, s->size);
   917  	*datsizep = datsize + s->size;
   918  }
   919  
   920  void
   921  dodata(void)
   922  {
   923  	int32 n;
   924  	vlong datsize;
   925  	Section *sect;
   926  	Segment *segro;
   927  	LSym *s, *last, **l, *toc;
   928  	LSym *gcdata, *gcbss;
   929  	ProgGen gen;
   930  
   931  	if(debug['v'])
   932  		Bprint(&bso, "%5.2f dodata\n", cputime());
   933  	Bflush(&bso);
   934  
   935  	last = nil;
   936  	datap = nil;
   937  
   938  	for(s=ctxt->allsym; s!=S; s=s->allsym) {
   939  		if(!s->reachable || s->special)
   940  			continue;
   941  		if(STEXT < s->type && s->type < SXREF) {
   942  			if(s->onlist)
   943  				sysfatal("symbol %s listed multiple times", s->name);
   944  			s->onlist = 1;
   945  			if(last == nil)
   946  				datap = s;
   947  			else
   948  				last->next = s;
   949  			s->next = nil;
   950  			last = s;
   951  		}
   952  	}
   953  
   954  	for(s = datap; s != nil; s = s->next) {
   955  		if(s->np > s->size)
   956  			diag("%s: initialize bounds (%lld < %d)",
   957  				s->name, (vlong)s->size, s->np);
   958  	}
   959  
   960  
   961  	/*
   962  	 * now that we have the datap list, but before we start
   963  	 * to assign addresses, record all the necessary
   964  	 * dynamic relocations.  these will grow the relocation
   965  	 * symbol, which is itself data.
   966  	 *
   967  	 * on darwin, we need the symbol table numbers for dynreloc.
   968  	 */
   969  	if(HEADTYPE == Hdarwin)
   970  		machosymorder();
   971  	dynreloc();
   972  
   973  	/* some symbols may no longer belong in datap (Mach-O) */
   974  	for(l=&datap; (s=*l) != nil; ) {
   975  		if(s->type <= STEXT || SXREF <= s->type)
   976  			*l = s->next;
   977  		else
   978  			l = &s->next;
   979  	}
   980  	*l = nil;
   981  
   982  	datap = listsort(datap, datcmp, offsetof(LSym, next));
   983  
   984  	/*
   985  	 * allocate sections.  list is sorted by type,
   986  	 * so we can just walk it for each piece we want to emit.
   987  	 * segdata is processed before segtext, because we need
   988  	 * to see all symbols in the .data and .bss sections in order
   989  	 * to generate garbage collection information.
   990  	 */
   991  
   992  	/* begin segdata */
   993  
   994  	/* skip symbols belonging to segtext */
   995  	s = datap;
   996  	for(; s != nil && s->type < SELFSECT; s = s->next)
   997  		;
   998  
   999  	/* writable ELF sections */
  1000  	datsize = 0;
  1001  	for(; s != nil && s->type < SELFGOT; s = s->next) {
  1002  		sect = addsection(&segdata, s->name, 06);
  1003  		sect->align = symalign(s);
  1004  		datsize = rnd(datsize, sect->align);
  1005  		sect->vaddr = datsize;
  1006  		s->sect = sect;
  1007  		s->type = SDATA;
  1008  		s->value = datsize - sect->vaddr;
  1009  		growdatsize(&datsize, s);
  1010  		sect->len = datsize - sect->vaddr;
  1011  	}
  1012  
  1013  	/* .got (and .toc on ppc64) */
  1014  	if(s->type == SELFGOT) {
  1015  		sect = addsection(&segdata, ".got", 06);
  1016  		sect->align = maxalign(s, SELFGOT);
  1017  		datsize = rnd(datsize, sect->align);
  1018  		sect->vaddr = datsize;
  1019  		for(; s != nil && s->type == SELFGOT; s = s->next) {
  1020  			datsize = aligndatsize(datsize, s);
  1021  			s->sect = sect;
  1022  			s->type = SDATA;
  1023  			s->value = datsize - sect->vaddr;
  1024  
  1025  			// Resolve .TOC. symbol for this object file (ppc64)
  1026  			toc = linkrlookup(ctxt, ".TOC.", s->version);
  1027  			if(toc != nil) {
  1028  				toc->sect = sect;
  1029  				toc->outer = s;
  1030  				toc->sub = s->sub;
  1031  				s->sub = toc;
  1032  
  1033  				toc->value = 0x8000;
  1034  			}
  1035  			growdatsize(&datsize, s);
  1036  		}
  1037  		sect->len = datsize - sect->vaddr;
  1038  	}
  1039  
  1040  	/* pointer-free data */
  1041  	sect = addsection(&segdata, ".noptrdata", 06);
  1042  	sect->align = maxalign(s, SINITARR-1);
  1043  	datsize = rnd(datsize, sect->align);
  1044  	sect->vaddr = datsize;
  1045  	linklookup(ctxt, "runtime.noptrdata", 0)->sect = sect;
  1046  	linklookup(ctxt, "runtime.enoptrdata", 0)->sect = sect;
  1047  	for(; s != nil && s->type < SINITARR; s = s->next) {
  1048  		datsize = aligndatsize(datsize, s);
  1049  		s->sect = sect;
  1050  		s->type = SDATA;
  1051  		s->value = datsize - sect->vaddr;
  1052  		growdatsize(&datsize, s);
  1053  	}
  1054  	sect->len = datsize - sect->vaddr;
  1055  
  1056  	/* shared library initializer */
  1057  	if(flag_shared) {
  1058  		sect = addsection(&segdata, ".init_array", 06);
  1059  		sect->align = maxalign(s, SINITARR);
  1060  		datsize = rnd(datsize, sect->align);
  1061  		sect->vaddr = datsize;
  1062  		for(; s != nil && s->type == SINITARR; s = s->next) {
  1063  			datsize = aligndatsize(datsize, s);
  1064  			s->sect = sect;
  1065  			s->value = datsize - sect->vaddr;
  1066  			growdatsize(&datsize, s);
  1067  		}
  1068  		sect->len = datsize - sect->vaddr;
  1069  	}
  1070  
  1071  	/* data */
  1072  	sect = addsection(&segdata, ".data", 06);
  1073  	sect->align = maxalign(s, SBSS-1);
  1074  	datsize = rnd(datsize, sect->align);
  1075  	sect->vaddr = datsize;
  1076  	linklookup(ctxt, "runtime.data", 0)->sect = sect;
  1077  	linklookup(ctxt, "runtime.edata", 0)->sect = sect;
  1078  	gcdata = linklookup(ctxt, "runtime.gcdata", 0);
  1079  	proggeninit(&gen, gcdata);
  1080  	for(; s != nil && s->type < SBSS; s = s->next) {
  1081  		if(s->type == SINITARR) {
  1082  			ctxt->cursym = s;
  1083  			diag("unexpected symbol type %d", s->type);
  1084  		}
  1085  		s->sect = sect;
  1086  		s->type = SDATA;
  1087  		datsize = aligndatsize(datsize, s);
  1088  		s->value = datsize - sect->vaddr;
  1089  		proggenaddsym(&gen, s);  // gc
  1090  		growdatsize(&datsize, s);
  1091  	}
  1092  	sect->len = datsize - sect->vaddr;
  1093  	proggenfini(&gen, sect->len);  // gc
  1094  
  1095  	/* bss */
  1096  	sect = addsection(&segdata, ".bss", 06);
  1097  	sect->align = maxalign(s, SNOPTRBSS-1);
  1098  	datsize = rnd(datsize, sect->align);
  1099  	sect->vaddr = datsize;
  1100  	linklookup(ctxt, "runtime.bss", 0)->sect = sect;
  1101  	linklookup(ctxt, "runtime.ebss", 0)->sect = sect;
  1102  	gcbss = linklookup(ctxt, "runtime.gcbss", 0);
  1103  	proggeninit(&gen, gcbss);
  1104  	for(; s != nil && s->type < SNOPTRBSS; s = s->next) {
  1105  		s->sect = sect;
  1106  		datsize = aligndatsize(datsize, s);
  1107  		s->value = datsize - sect->vaddr;
  1108  		proggenaddsym(&gen, s);  // gc
  1109  		growdatsize(&datsize, s);
  1110  	}
  1111  	sect->len = datsize - sect->vaddr;
  1112  	proggenfini(&gen, sect->len);  // gc
  1113  
  1114  	/* pointer-free bss */
  1115  	sect = addsection(&segdata, ".noptrbss", 06);
  1116  	sect->align = maxalign(s, SNOPTRBSS);
  1117  	datsize = rnd(datsize, sect->align);
  1118  	sect->vaddr = datsize;
  1119  	linklookup(ctxt, "runtime.noptrbss", 0)->sect = sect;
  1120  	linklookup(ctxt, "runtime.enoptrbss", 0)->sect = sect;
  1121  	for(; s != nil && s->type == SNOPTRBSS; s = s->next) {
  1122  		datsize = aligndatsize(datsize, s);
  1123  		s->sect = sect;
  1124  		s->value = datsize - sect->vaddr;
  1125  		growdatsize(&datsize, s);
  1126  	}
  1127  	sect->len = datsize - sect->vaddr;
  1128  	linklookup(ctxt, "runtime.end", 0)->sect = sect;
  1129  
  1130  	// 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
  1131  	if(datsize != (uint32)datsize) {
  1132  		diag("data or bss segment too large");
  1133  	}
  1134  	
  1135  	if(iself && linkmode == LinkExternal && s != nil && s->type == STLSBSS && HEADTYPE != Hopenbsd) {
  1136  		sect = addsection(&segdata, ".tbss", 06);
  1137  		sect->align = PtrSize;
  1138  		sect->vaddr = 0;
  1139  		datsize = 0;
  1140  		for(; s != nil && s->type == STLSBSS; s = s->next) {
  1141  			datsize = aligndatsize(datsize, s);
  1142  			s->sect = sect;
  1143  			s->value = datsize - sect->vaddr;
  1144  			growdatsize(&datsize, s);
  1145  		}
  1146  		sect->len = datsize;
  1147  	} else {
  1148  		// Might be internal linking but still using cgo.
  1149  		// In that case, the only possible STLSBSS symbol is runtime.tlsg.
  1150  		// Give it offset 0, because it's the only thing here.
  1151  		if(s != nil && s->type == STLSBSS && strcmp(s->name, "runtime.tlsg") == 0) {
  1152  			s->value = 0;
  1153  			s = s->next;
  1154  		}
  1155  	}
  1156  	
  1157  	if(s != nil) {
  1158  		ctxt->cursym = nil;
  1159  		diag("unexpected symbol type %d for %s", s->type, s->name);
  1160  	}
  1161  
  1162  	/*
  1163  	 * We finished data, begin read-only data.
  1164  	 * Not all systems support a separate read-only non-executable data section.
  1165  	 * ELF systems do.
  1166  	 * OS X and Plan 9 do not.
  1167  	 * Windows PE may, but if so we have not implemented it.
  1168  	 * And if we're using external linking mode, the point is moot,
  1169  	 * since it's not our decision; that code expects the sections in
  1170  	 * segtext.
  1171  	 */
  1172  	if(iself && linkmode == LinkInternal)
  1173  		segro = &segrodata;
  1174  	else
  1175  		segro = &segtext;
  1176  
  1177  	s = datap;
  1178  	
  1179  	datsize = 0;
  1180  	
  1181  	/* read-only executable ELF, Mach-O sections */
  1182  	for(; s != nil && s->type < STYPE; s = s->next) {
  1183  		sect = addsection(&segtext, s->name, 04);
  1184  		sect->align = symalign(s);
  1185  		datsize = rnd(datsize, sect->align);
  1186  		sect->vaddr = datsize;
  1187  		s->sect = sect;
  1188  		s->type = SRODATA;
  1189  		s->value = datsize - sect->vaddr;
  1190  		growdatsize(&datsize, s);
  1191  		sect->len = datsize - sect->vaddr;
  1192  	}
  1193  
  1194  	/* read-only data */
  1195  	sect = addsection(segro, ".rodata", 04);
  1196  	sect->align = maxalign(s, STYPELINK-1);
  1197  	datsize = rnd(datsize, sect->align);
  1198  	sect->vaddr = 0;
  1199  	linklookup(ctxt, "runtime.rodata", 0)->sect = sect;
  1200  	linklookup(ctxt, "runtime.erodata", 0)->sect = sect;
  1201  	for(; s != nil && s->type < STYPELINK; s = s->next) {
  1202  		datsize = aligndatsize(datsize, s);
  1203  		s->sect = sect;
  1204  		s->type = SRODATA;
  1205  		s->value = datsize - sect->vaddr;
  1206  		growdatsize(&datsize, s);
  1207  	}
  1208  	sect->len = datsize - sect->vaddr;
  1209  
  1210  	/* typelink */
  1211  	sect = addsection(segro, ".typelink", 04);
  1212  	sect->align = maxalign(s, STYPELINK);
  1213  	datsize = rnd(datsize, sect->align);
  1214  	sect->vaddr = datsize;
  1215  	linklookup(ctxt, "runtime.typelink", 0)->sect = sect;
  1216  	linklookup(ctxt, "runtime.etypelink", 0)->sect = sect;
  1217  	for(; s != nil && s->type == STYPELINK; s = s->next) {
  1218  		datsize = aligndatsize(datsize, s);
  1219  		s->sect = sect;
  1220  		s->type = SRODATA;
  1221  		s->value = datsize - sect->vaddr;
  1222  		growdatsize(&datsize, s);
  1223  	}
  1224  	sect->len = datsize - sect->vaddr;
  1225  
  1226  	/* gosymtab */
  1227  	sect = addsection(segro, ".gosymtab", 04);
  1228  	sect->align = maxalign(s, SPCLNTAB-1);
  1229  	datsize = rnd(datsize, sect->align);
  1230  	sect->vaddr = datsize;
  1231  	linklookup(ctxt, "runtime.symtab", 0)->sect = sect;
  1232  	linklookup(ctxt, "runtime.esymtab", 0)->sect = sect;
  1233  	for(; s != nil && s->type < SPCLNTAB; s = s->next) {
  1234  		datsize = aligndatsize(datsize, s);
  1235  		s->sect = sect;
  1236  		s->type = SRODATA;
  1237  		s->value = datsize - sect->vaddr;
  1238  		growdatsize(&datsize, s);
  1239  	}
  1240  	sect->len = datsize - sect->vaddr;
  1241  
  1242  	/* gopclntab */
  1243  	sect = addsection(segro, ".gopclntab", 04);
  1244  	sect->align = maxalign(s, SELFROSECT-1);
  1245  	datsize = rnd(datsize, sect->align);
  1246  	sect->vaddr = datsize;
  1247  	linklookup(ctxt, "runtime.pclntab", 0)->sect = sect;
  1248  	linklookup(ctxt, "runtime.epclntab", 0)->sect = sect;
  1249  	for(; s != nil && s->type < SELFROSECT; s = s->next) {
  1250  		datsize = aligndatsize(datsize, s);
  1251  		s->sect = sect;
  1252  		s->type = SRODATA;
  1253  		s->value = datsize - sect->vaddr;
  1254  		growdatsize(&datsize, s);
  1255  	}
  1256  	sect->len = datsize - sect->vaddr;
  1257  
  1258  	/* read-only ELF, Mach-O sections */
  1259  	for(; s != nil && s->type < SELFSECT; s = s->next) {
  1260  		sect = addsection(segro, s->name, 04);
  1261  		sect->align = symalign(s);
  1262  		datsize = rnd(datsize, sect->align);
  1263  		sect->vaddr = datsize;
  1264  		s->sect = sect;
  1265  		s->type = SRODATA;
  1266  		s->value = datsize - sect->vaddr;
  1267  		growdatsize(&datsize, s);
  1268  		sect->len = datsize - sect->vaddr;
  1269  	}
  1270  
  1271  	// 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
  1272  	if(datsize != (uint32)datsize) {
  1273  		diag("read-only data segment too large");
  1274  	}
  1275  	
  1276  	/* number the sections */
  1277  	n = 1;
  1278  	for(sect = segtext.sect; sect != nil; sect = sect->next)
  1279  		sect->extnum = n++;
  1280  	for(sect = segrodata.sect; sect != nil; sect = sect->next)
  1281  		sect->extnum = n++;
  1282  	for(sect = segdata.sect; sect != nil; sect = sect->next)
  1283  		sect->extnum = n++;
  1284  }
  1285  
  1286  // assign addresses to text
  1287  void
  1288  textaddress(void)
  1289  {
  1290  	uvlong va;
  1291  	Section *sect;
  1292  	LSym *sym, *sub;
  1293  
  1294  	addsection(&segtext, ".text", 05);
  1295  
  1296  	// Assign PCs in text segment.
  1297  	// Could parallelize, by assigning to text
  1298  	// and then letting threads copy down, but probably not worth it.
  1299  	sect = segtext.sect;
  1300  	sect->align = funcalign;
  1301  	linklookup(ctxt, "runtime.text", 0)->sect = sect;
  1302  	linklookup(ctxt, "runtime.etext", 0)->sect = sect;
  1303  	va = INITTEXT;
  1304  	sect->vaddr = va;
  1305  	for(sym = ctxt->textp; sym != nil; sym = sym->next) {
  1306  		sym->sect = sect;
  1307  		if(sym->type & SSUB)
  1308  			continue;
  1309  		if(sym->align != 0)
  1310  			va = rnd(va, sym->align);
  1311  		else
  1312  			va = rnd(va, funcalign);
  1313  		sym->value = 0;
  1314  		for(sub = sym; sub != S; sub = sub->sub)
  1315  			sub->value += va;
  1316  		if(sym->size == 0 && sym->sub != S)
  1317  			ctxt->cursym = sym;
  1318  		if(sym->size < MINFUNC)
  1319  			va += MINFUNC; // spacing required for findfunctab
  1320  		else
  1321  			va += sym->size;
  1322  	}
  1323  	sect->len = va - sect->vaddr;
  1324  }
  1325  
  1326  // assign addresses
  1327  void
  1328  address(void)
  1329  {
  1330  	Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss;
  1331  	Section *typelink;
  1332  	LSym *sym, *sub;
  1333  	uvlong va;
  1334  	vlong vlen;
  1335  
  1336  	va = INITTEXT;
  1337  	segtext.rwx = 05;
  1338  	segtext.vaddr = va;
  1339  	segtext.fileoff = HEADR;
  1340  	for(s=segtext.sect; s != nil; s=s->next) {
  1341  		va = rnd(va, s->align);
  1342  		s->vaddr = va;
  1343  		va += s->len;
  1344  	}
  1345  	segtext.len = va - INITTEXT;
  1346  	segtext.filelen = segtext.len;
  1347  	if(HEADTYPE == Hnacl)
  1348  		va += 32; // room for the "halt sled"
  1349  
  1350  	if(segrodata.sect != nil) {
  1351  		// align to page boundary so as not to mix
  1352  		// rodata and executable text.
  1353  		va = rnd(va, INITRND);
  1354  
  1355  		segrodata.rwx = 04;
  1356  		segrodata.vaddr = va;
  1357  		segrodata.fileoff = va - segtext.vaddr + segtext.fileoff;
  1358  		segrodata.filelen = 0;
  1359  		for(s=segrodata.sect; s != nil; s=s->next) {
  1360  			va = rnd(va, s->align);
  1361  			s->vaddr = va;
  1362  			va += s->len;
  1363  		}
  1364  		segrodata.len = va - segrodata.vaddr;
  1365  		segrodata.filelen = segrodata.len;
  1366  	}
  1367  
  1368  	va = rnd(va, INITRND);
  1369  	segdata.rwx = 06;
  1370  	segdata.vaddr = va;
  1371  	segdata.fileoff = va - segtext.vaddr + segtext.fileoff;
  1372  	segdata.filelen = 0;
  1373  	if(HEADTYPE == Hwindows)
  1374  		segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN);
  1375  	if(HEADTYPE == Hplan9)
  1376  		segdata.fileoff = segtext.fileoff + segtext.filelen;
  1377  	data = nil;
  1378  	noptr = nil;
  1379  	bss = nil;
  1380  	noptrbss = nil;
  1381  	for(s=segdata.sect; s != nil; s=s->next) {
  1382  		vlen = s->len;
  1383  		if(s->next)
  1384  			vlen = s->next->vaddr - s->vaddr;
  1385  		s->vaddr = va;
  1386  		va += vlen;
  1387  		segdata.len = va - segdata.vaddr;
  1388  		if(strcmp(s->name, ".data") == 0)
  1389  			data = s;
  1390  		if(strcmp(s->name, ".noptrdata") == 0)
  1391  			noptr = s;
  1392  		if(strcmp(s->name, ".bss") == 0)
  1393  			bss = s;
  1394  		if(strcmp(s->name, ".noptrbss") == 0)
  1395  			noptrbss = s;
  1396  	}
  1397  	segdata.filelen = bss->vaddr - segdata.vaddr;
  1398  
  1399  	text = segtext.sect;
  1400  	if(segrodata.sect)
  1401  		rodata = segrodata.sect;
  1402  	else
  1403  		rodata = text->next;
  1404  	typelink = rodata->next;
  1405  	symtab = typelink->next;
  1406  	pclntab = symtab->next;
  1407  
  1408  	for(sym = datap; sym != nil; sym = sym->next) {
  1409  		ctxt->cursym = sym;
  1410  		if(sym->sect != nil)
  1411  			sym->value += sym->sect->vaddr;
  1412  		for(sub = sym->sub; sub != nil; sub = sub->sub)
  1413  			sub->value += sym->value;
  1414  	}
  1415  
  1416  	xdefine("runtime.text", STEXT, text->vaddr);
  1417  	xdefine("runtime.etext", STEXT, text->vaddr + text->len);
  1418  	xdefine("runtime.rodata", SRODATA, rodata->vaddr);
  1419  	xdefine("runtime.erodata", SRODATA, rodata->vaddr + rodata->len);
  1420  	xdefine("runtime.typelink", SRODATA, typelink->vaddr);
  1421  	xdefine("runtime.etypelink", SRODATA, typelink->vaddr + typelink->len);
  1422  
  1423  	sym = linklookup(ctxt, "runtime.gcdata", 0);
  1424  	xdefine("runtime.egcdata", SRODATA, symaddr(sym) + sym->size);
  1425  	linklookup(ctxt, "runtime.egcdata", 0)->sect = sym->sect;
  1426  
  1427  	sym = linklookup(ctxt, "runtime.gcbss", 0);
  1428  	xdefine("runtime.egcbss", SRODATA, symaddr(sym) + sym->size);
  1429  	linklookup(ctxt, "runtime.egcbss", 0)->sect = sym->sect;
  1430  
  1431  	xdefine("runtime.symtab", SRODATA, symtab->vaddr);
  1432  	xdefine("runtime.esymtab", SRODATA, symtab->vaddr + symtab->len);
  1433  	xdefine("runtime.pclntab", SRODATA, pclntab->vaddr);
  1434  	xdefine("runtime.epclntab", SRODATA, pclntab->vaddr + pclntab->len);
  1435  	xdefine("runtime.noptrdata", SNOPTRDATA, noptr->vaddr);
  1436  	xdefine("runtime.enoptrdata", SNOPTRDATA, noptr->vaddr + noptr->len);
  1437  	xdefine("runtime.bss", SBSS, bss->vaddr);
  1438  	xdefine("runtime.ebss", SBSS, bss->vaddr + bss->len);
  1439  	xdefine("runtime.data", SDATA, data->vaddr);
  1440  	xdefine("runtime.edata", SDATA, data->vaddr + data->len);
  1441  	xdefine("runtime.noptrbss", SNOPTRBSS, noptrbss->vaddr);
  1442  	xdefine("runtime.enoptrbss", SNOPTRBSS, noptrbss->vaddr + noptrbss->len);
  1443  	xdefine("runtime.end", SBSS, segdata.vaddr + segdata.len);
  1444  }