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