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