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