github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/cmd/ld/elf.c (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  #include	"l.h"
     6  #include	"lib.h"
     7  #include	"../ld/elf.h"
     8  
     9  /*
    10   * We use the 64-bit data structures on both 32- and 64-bit machines
    11   * in order to write the code just once.  The 64-bit data structure is
    12   * written in the 32-bit format on the 32-bit machines.
    13   */
    14  #define	NSECT	48
    15  
    16  int	iself;
    17  
    18  static	int	elf64;
    19  static	ElfEhdr	hdr;
    20  static	ElfPhdr	*phdr[NSECT];
    21  static	ElfShdr	*shdr[NSECT];
    22  static	char	*interp;
    23  
    24  typedef struct Elfstring Elfstring;
    25  struct Elfstring
    26  {
    27  	char *s;
    28  	int off;
    29  };
    30  
    31  static Elfstring elfstr[100];
    32  static int nelfstr;
    33  
    34  static char buildinfo[32];
    35  
    36  /*
    37   Initialize the global variable that describes the ELF header. It will be updated as
    38   we write section and prog headers.
    39   */
    40  void
    41  elfinit(void)
    42  {
    43  	iself = 1;
    44  
    45  	switch(thechar) {
    46  	// 64-bit architectures
    47  	case '6':
    48  		elf64 = 1;
    49  		hdr.phoff = ELF64HDRSIZE;	/* Must be be ELF64HDRSIZE: first PHdr must follow ELF header */
    50  		hdr.shoff = ELF64HDRSIZE;	/* Will move as we add PHeaders */
    51  		hdr.ehsize = ELF64HDRSIZE;	/* Must be ELF64HDRSIZE */
    52  		hdr.phentsize = ELF64PHDRSIZE;	/* Must be ELF64PHDRSIZE */
    53  		hdr.shentsize = ELF64SHDRSIZE;	/* Must be ELF64SHDRSIZE */
    54  		break;
    55  
    56  	// 32-bit architectures
    57  	case '5':
    58  		// we use EABI on both linux/arm and freebsd/arm.
    59  		if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd)
    60  			hdr.flags = 0x5000002; // has entry point, Version5 EABI
    61  		// fallthrough
    62  	default:
    63  		hdr.phoff = ELF32HDRSIZE;	/* Must be be ELF32HDRSIZE: first PHdr must follow ELF header */
    64  		hdr.shoff = ELF32HDRSIZE;	/* Will move as we add PHeaders */
    65  		hdr.ehsize = ELF32HDRSIZE;	/* Must be ELF32HDRSIZE */
    66  		hdr.phentsize = ELF32PHDRSIZE;	/* Must be ELF32PHDRSIZE */
    67  		hdr.shentsize = ELF32SHDRSIZE;	/* Must be ELF32SHDRSIZE */
    68  	}
    69  }
    70  
    71  void
    72  elf64phdr(ElfPhdr *e)
    73  {
    74  	LPUT(e->type);
    75  	LPUT(e->flags);
    76  	VPUT(e->off);
    77  	VPUT(e->vaddr);
    78  	VPUT(e->paddr);
    79  	VPUT(e->filesz);
    80  	VPUT(e->memsz);
    81  	VPUT(e->align);
    82  }
    83  
    84  void
    85  elf32phdr(ElfPhdr *e)
    86  {
    87  	int frag;
    88  	
    89  	if(e->type == PT_LOAD) {
    90  		// Correct ELF loaders will do this implicitly,
    91  		// but buggy ELF loaders like the one in some
    92  		// versions of QEMU won't.
    93  		frag = e->vaddr&(e->align-1);
    94  		e->off -= frag;
    95  		e->vaddr -= frag;
    96  		e->paddr -= frag;
    97  		e->filesz += frag;
    98  		e->memsz += frag;
    99  	}
   100  	LPUT(e->type);
   101  	LPUT(e->off);
   102  	LPUT(e->vaddr);
   103  	LPUT(e->paddr);
   104  	LPUT(e->filesz);
   105  	LPUT(e->memsz);
   106  	LPUT(e->flags);
   107  	LPUT(e->align);
   108  }
   109  
   110  void
   111  elf64shdr(ElfShdr *e)
   112  {
   113  	LPUT(e->name);
   114  	LPUT(e->type);
   115  	VPUT(e->flags);
   116  	VPUT(e->addr);
   117  	VPUT(e->off);
   118  	VPUT(e->size);
   119  	LPUT(e->link);
   120  	LPUT(e->info);
   121  	VPUT(e->addralign);
   122  	VPUT(e->entsize);
   123  }
   124  
   125  void
   126  elf32shdr(ElfShdr *e)
   127  {
   128  	LPUT(e->name);
   129  	LPUT(e->type);
   130  	LPUT(e->flags);
   131  	LPUT(e->addr);
   132  	LPUT(e->off);
   133  	LPUT(e->size);
   134  	LPUT(e->link);
   135  	LPUT(e->info);
   136  	LPUT(e->addralign);
   137  	LPUT(e->entsize);
   138  }
   139  
   140  uint32
   141  elfwriteshdrs(void)
   142  {
   143  	int i;
   144  
   145  	if (elf64) {
   146  		for (i = 0; i < hdr.shnum; i++)
   147  			elf64shdr(shdr[i]);
   148  		return hdr.shnum * ELF64SHDRSIZE;
   149  	}
   150  	for (i = 0; i < hdr.shnum; i++)
   151  		elf32shdr(shdr[i]);
   152  	return hdr.shnum * ELF32SHDRSIZE;
   153  }
   154  
   155  void
   156  elfsetstring(char *s, int off)
   157  {
   158  	if(nelfstr >= nelem(elfstr)) {
   159  		diag("too many elf strings");
   160  		errorexit();
   161  	}
   162  	elfstr[nelfstr].s = s;
   163  	elfstr[nelfstr].off = off;
   164  	nelfstr++;
   165  }
   166  
   167  uint32
   168  elfwritephdrs(void)
   169  {
   170  	int i;
   171  
   172  	if (elf64) {
   173  		for (i = 0; i < hdr.phnum; i++)
   174  			elf64phdr(phdr[i]);
   175  		return hdr.phnum * ELF64PHDRSIZE;
   176  	}
   177  	for (i = 0; i < hdr.phnum; i++)
   178  		elf32phdr(phdr[i]);
   179  	return hdr.phnum * ELF32PHDRSIZE;
   180  }
   181  
   182  ElfPhdr*
   183  newElfPhdr(void)
   184  {
   185  	ElfPhdr *e;
   186  
   187  	e = mal(sizeof *e);
   188  	if (hdr.phnum >= NSECT)
   189  		diag("too many phdrs");
   190  	else
   191  		phdr[hdr.phnum++] = e;
   192  	if (elf64)
   193  		hdr.shoff += ELF64PHDRSIZE;
   194  	else
   195  		hdr.shoff += ELF32PHDRSIZE;
   196  	return e;
   197  }
   198  
   199  ElfShdr*
   200  newElfShdr(vlong name)
   201  {
   202  	ElfShdr *e;
   203  
   204  	e = mal(sizeof *e);
   205  	e->name = name;
   206  	e->shnum = hdr.shnum;
   207  	if (hdr.shnum >= NSECT) {
   208  		diag("too many shdrs");
   209  	} else {
   210  		shdr[hdr.shnum++] = e;
   211  	}
   212  	return e;
   213  }
   214  
   215  ElfEhdr*
   216  getElfEhdr(void)
   217  {
   218  	return &hdr;
   219  }
   220  
   221  uint32
   222  elf64writehdr(void)
   223  {
   224  	int i;
   225  
   226  	for (i = 0; i < EI_NIDENT; i++)
   227  		cput(hdr.ident[i]);
   228  	WPUT(hdr.type);
   229  	WPUT(hdr.machine);
   230  	LPUT(hdr.version);
   231  	VPUT(hdr.entry);
   232  	VPUT(hdr.phoff);
   233  	VPUT(hdr.shoff);
   234  	LPUT(hdr.flags);
   235  	WPUT(hdr.ehsize);
   236  	WPUT(hdr.phentsize);
   237  	WPUT(hdr.phnum);
   238  	WPUT(hdr.shentsize);
   239  	WPUT(hdr.shnum);
   240  	WPUT(hdr.shstrndx);
   241  	return ELF64HDRSIZE;
   242  }
   243  
   244  uint32
   245  elf32writehdr(void)
   246  {
   247  	int i;
   248  
   249  	for (i = 0; i < EI_NIDENT; i++)
   250  		cput(hdr.ident[i]);
   251  	WPUT(hdr.type);
   252  	WPUT(hdr.machine);
   253  	LPUT(hdr.version);
   254  	LPUT(hdr.entry);
   255  	LPUT(hdr.phoff);
   256  	LPUT(hdr.shoff);
   257  	LPUT(hdr.flags);
   258  	WPUT(hdr.ehsize);
   259  	WPUT(hdr.phentsize);
   260  	WPUT(hdr.phnum);
   261  	WPUT(hdr.shentsize);
   262  	WPUT(hdr.shnum);
   263  	WPUT(hdr.shstrndx);
   264  	return ELF32HDRSIZE;
   265  }
   266  
   267  uint32
   268  elfwritehdr(void)
   269  {
   270  	if(elf64)
   271  		return elf64writehdr();
   272  	return elf32writehdr();
   273  }
   274  
   275  /* Taken directly from the definition document for ELF64 */
   276  uint32
   277  elfhash(uchar *name)
   278  {
   279  	uint32 h = 0, g;
   280  	while (*name) {
   281  		h = (h << 4) + *name++;
   282  		if (g = h & 0xf0000000)
   283  			h ^= g >> 24;
   284  		h &= 0x0fffffff;
   285  	}
   286  	return h;
   287  }
   288  
   289  void
   290  elfwritedynent(LSym *s, int tag, uint64 val)
   291  {
   292  	if(elf64) {
   293  		adduint64(ctxt, s, tag);
   294  		adduint64(ctxt, s, val);
   295  	} else {
   296  		adduint32(ctxt, s, tag);
   297  		adduint32(ctxt, s, val);
   298  	}
   299  }
   300  
   301  void
   302  elfwritedynentsym(LSym *s, int tag, LSym *t)
   303  {
   304  	if(elf64)
   305  		adduint64(ctxt, s, tag);
   306  	else
   307  		adduint32(ctxt, s, tag);
   308  	addaddr(ctxt, s, t);
   309  }
   310  
   311  void
   312  elfwritedynentsymsize(LSym *s, int tag, LSym *t)
   313  {
   314  	if(elf64)
   315  		adduint64(ctxt, s, tag);
   316  	else
   317  		adduint32(ctxt, s, tag);
   318  	addsize(ctxt, s, t);
   319  }
   320  
   321  int
   322  elfinterp(ElfShdr *sh, uint64 startva, uint64 resoff, char *p)
   323  {
   324  	int n;
   325  
   326  	interp = p;
   327  	n = strlen(interp)+1;
   328  	sh->addr = startva + resoff - n;
   329  	sh->off = resoff - n;
   330  	sh->size = n;
   331  
   332  	return n;
   333  }
   334  
   335  int
   336  elfwriteinterp(void)
   337  {
   338  	ElfShdr *sh;
   339  	
   340  	sh = elfshname(".interp");
   341  	cseek(sh->off);
   342  	cwrite(interp, sh->size);
   343  	return sh->size;
   344  }
   345  
   346  int
   347  elfnote(ElfShdr *sh, uint64 startva, uint64 resoff, int sz)
   348  {
   349  	uint64 n;
   350  
   351  	n = sizeof(Elf_Note) + sz + resoff % 4;
   352  
   353  	sh->type = SHT_NOTE;
   354  	sh->flags = SHF_ALLOC;
   355  	sh->addralign = 4;
   356  	sh->addr = startva + resoff - n;
   357  	sh->off = resoff - n;
   358  	sh->size = n - resoff % 4;
   359  
   360  	return n;
   361  }
   362  
   363  ElfShdr *
   364  elfwritenotehdr(char *str, uint32 namesz, uint32 descsz, uint32 tag)
   365  {
   366  	ElfShdr *sh;
   367  	
   368  	sh = elfshname(str);
   369  
   370  	// Write Elf_Note header.
   371  	cseek(sh->off);
   372  	LPUT(namesz);
   373  	LPUT(descsz);
   374  	LPUT(tag);
   375  
   376  	return sh;
   377  }
   378  
   379  // NetBSD Signature (as per sys/exec_elf.h)
   380  #define ELF_NOTE_NETBSD_NAMESZ		7
   381  #define ELF_NOTE_NETBSD_DESCSZ		4
   382  #define ELF_NOTE_NETBSD_TAG		1
   383  #define ELF_NOTE_NETBSD_NAME		"NetBSD\0\0"
   384  #define ELF_NOTE_NETBSD_VERSION		599000000	/* NetBSD 5.99 */
   385  
   386  int
   387  elfnetbsdsig(ElfShdr *sh, uint64 startva, uint64 resoff)
   388  {
   389  	int n;
   390  
   391  	n = rnd(ELF_NOTE_NETBSD_NAMESZ, 4) + rnd(ELF_NOTE_NETBSD_DESCSZ, 4);
   392  	return elfnote(sh, startva, resoff, n);
   393  }
   394  
   395  int
   396  elfwritenetbsdsig(void)
   397  {
   398  	ElfShdr *sh;
   399  
   400  	// Write Elf_Note header.
   401  	sh = elfwritenotehdr(".note.netbsd.ident", ELF_NOTE_NETBSD_NAMESZ, ELF_NOTE_NETBSD_DESCSZ, ELF_NOTE_NETBSD_TAG);
   402  	if(sh == nil)
   403  		return 0;
   404  
   405  	// Followed by NetBSD string and version.
   406  	cwrite(ELF_NOTE_NETBSD_NAME, ELF_NOTE_NETBSD_NAMESZ + 1);
   407  	LPUT(ELF_NOTE_NETBSD_VERSION);
   408  
   409  	return sh->size;
   410  }
   411  
   412  // OpenBSD Signature
   413  #define ELF_NOTE_OPENBSD_NAMESZ		8
   414  #define ELF_NOTE_OPENBSD_DESCSZ		4
   415  #define ELF_NOTE_OPENBSD_TAG		1
   416  #define ELF_NOTE_OPENBSD_NAME		"OpenBSD\0"
   417  #define ELF_NOTE_OPENBSD_VERSION	0
   418  
   419  int
   420  elfopenbsdsig(ElfShdr *sh, uint64 startva, uint64 resoff)
   421  {
   422  	int n;
   423  
   424  	n = ELF_NOTE_OPENBSD_NAMESZ + ELF_NOTE_OPENBSD_DESCSZ;
   425  	return elfnote(sh, startva, resoff, n);
   426  }
   427  
   428  int
   429  elfwriteopenbsdsig(void)
   430  {
   431  	ElfShdr *sh;
   432  
   433  	// Write Elf_Note header.
   434  	sh = elfwritenotehdr(".note.openbsd.ident", ELF_NOTE_OPENBSD_NAMESZ, ELF_NOTE_OPENBSD_DESCSZ, ELF_NOTE_OPENBSD_TAG);
   435  	if(sh == nil)
   436  		return 0;
   437  
   438  	// Followed by OpenBSD string and version.
   439  	cwrite(ELF_NOTE_OPENBSD_NAME, ELF_NOTE_OPENBSD_NAMESZ);
   440  	LPUT(ELF_NOTE_OPENBSD_VERSION);
   441  
   442  	return sh->size;
   443  }
   444  
   445  void
   446  addbuildinfo(char *val)
   447  {
   448  	char *ov;
   449  	int i, b, j;
   450  
   451  	if(val[0] != '0' || val[1] != 'x') {
   452  		fprint(2, "%s: -B argument must start with 0x: %s\n", argv0, val);
   453  		exits("usage");
   454  	}
   455  	ov = val;
   456  	val += 2;
   457  	i = 0;
   458  	while(*val != '\0') {
   459  		if(val[1] == '\0') {
   460  			fprint(2, "%s: -B argument must have even number of digits: %s\n", argv0, ov);
   461  			exits("usage");
   462  		}
   463  		b = 0;
   464  		for(j = 0; j < 2; j++, val++) {
   465  			b *= 16;
   466  		  	if(*val >= '0' && *val <= '9')
   467  				b += *val - '0';
   468  			else if(*val >= 'a' && *val <= 'f')
   469  				b += *val - 'a' + 10;
   470  			else if(*val >= 'A' && *val <= 'F')
   471  				b += *val - 'A' + 10;
   472  			else {
   473  				fprint(2, "%s: -B argument contains invalid hex digit %c: %s\n", argv0, *val, ov);
   474  				exits("usage");
   475  			}
   476  		}
   477  		if(i >= nelem(buildinfo)) {
   478  			fprint(2, "%s: -B option too long (max %d digits): %s\n", argv0, (int)nelem(buildinfo), ov);
   479  			exits("usage");
   480  		}
   481  		buildinfo[i++] = b;
   482  	}
   483  	buildinfolen = i;
   484  }
   485  
   486  // Build info note
   487  #define ELF_NOTE_BUILDINFO_NAMESZ	4
   488  #define ELF_NOTE_BUILDINFO_TAG		3
   489  #define ELF_NOTE_BUILDINFO_NAME		"GNU\0"
   490  
   491  int
   492  elfbuildinfo(ElfShdr *sh, uint64 startva, uint64 resoff)
   493  {
   494  	int n;
   495  
   496  	n = ELF_NOTE_BUILDINFO_NAMESZ + rnd(buildinfolen, 4);
   497  	return elfnote(sh, startva, resoff, n);
   498  }
   499  
   500  int
   501  elfwritebuildinfo(void)
   502  {
   503  	ElfShdr *sh;
   504  
   505  	sh = elfwritenotehdr(".note.gnu.build-id", ELF_NOTE_BUILDINFO_NAMESZ, buildinfolen, ELF_NOTE_BUILDINFO_TAG);
   506  	if(sh == nil)
   507  		return 0;
   508  
   509  	cwrite(ELF_NOTE_BUILDINFO_NAME, ELF_NOTE_BUILDINFO_NAMESZ);
   510  	cwrite(buildinfo, buildinfolen);
   511  	cwrite("\0\0\0", rnd(buildinfolen, 4) - buildinfolen);
   512  
   513  	return sh->size;
   514  }
   515  
   516  extern int nelfsym;
   517  int elfverneed;
   518  
   519  typedef struct Elfaux Elfaux;
   520  typedef struct Elflib Elflib;
   521  
   522  struct Elflib
   523  {
   524  	Elflib *next;
   525  	Elfaux *aux;
   526  	char *file;
   527  };
   528  
   529  struct Elfaux
   530  {
   531  	Elfaux *next;
   532  	int num;
   533  	char *vers;
   534  };
   535  
   536  Elfaux*
   537  addelflib(Elflib **list, char *file, char *vers)
   538  {
   539  	Elflib *lib;
   540  	Elfaux *aux;
   541  	
   542  	for(lib=*list; lib; lib=lib->next)
   543  		if(strcmp(lib->file, file) == 0)
   544  			goto havelib;
   545  	lib = mal(sizeof *lib);
   546  	lib->next = *list;
   547  	lib->file = file;
   548  	*list = lib;
   549  havelib:
   550  	for(aux=lib->aux; aux; aux=aux->next)
   551  		if(strcmp(aux->vers, vers) == 0)
   552  			goto haveaux;
   553  	aux = mal(sizeof *aux);
   554  	aux->next = lib->aux;
   555  	aux->vers = vers;
   556  	lib->aux = aux;
   557  haveaux:
   558  	return aux;
   559  }
   560  
   561  void
   562  elfdynhash(void)
   563  {
   564  	LSym *s, *sy, *dynstr;
   565  	int i, j, nbucket, b, nfile;
   566  	uint32 hc, *chain, *buckets;
   567  	int nsym;
   568  	char *name;
   569  	Elfaux **need;
   570  	Elflib *needlib;
   571  	Elflib *l;
   572  	Elfaux *x;
   573  	
   574  	if(!iself)
   575  		return;
   576  
   577  	nsym = nelfsym;
   578  	s = linklookup(ctxt, ".hash", 0);
   579  	s->type = SELFROSECT;
   580  	s->reachable = 1;
   581  
   582  	i = nsym;
   583  	nbucket = 1;
   584  	while(i > 0) {
   585  		++nbucket;
   586  		i >>= 1;
   587  	}
   588  
   589  	needlib = nil;
   590  	need = malloc(nsym * sizeof need[0]);
   591  	chain = malloc(nsym * sizeof chain[0]);
   592  	buckets = malloc(nbucket * sizeof buckets[0]);
   593  	if(need == nil || chain == nil || buckets == nil) {
   594  		ctxt->cursym = nil;
   595  		diag("out of memory");
   596  		errorexit();
   597  	}
   598  	memset(need, 0, nsym * sizeof need[0]);
   599  	memset(chain, 0, nsym * sizeof chain[0]);
   600  	memset(buckets, 0, nbucket * sizeof buckets[0]);
   601  	for(sy=ctxt->allsym; sy!=S; sy=sy->allsym) {
   602  		if (sy->dynid <= 0)
   603  			continue;
   604  
   605  		if(sy->dynimpvers)
   606  			need[sy->dynid] = addelflib(&needlib, sy->dynimplib, sy->dynimpvers);
   607  
   608  		name = sy->extname;
   609  		hc = elfhash((uchar*)name);
   610  
   611  		b = hc % nbucket;
   612  		chain[sy->dynid] = buckets[b];
   613  		buckets[b] = sy->dynid;
   614  	}
   615  
   616  	adduint32(ctxt, s, nbucket);
   617  	adduint32(ctxt, s, nsym);
   618  	for(i = 0; i<nbucket; i++)
   619  		adduint32(ctxt, s, buckets[i]);
   620  	for(i = 0; i<nsym; i++)
   621  		adduint32(ctxt, s, chain[i]);
   622  
   623  	free(chain);
   624  	free(buckets);
   625  	
   626  	// version symbols
   627  	dynstr = linklookup(ctxt, ".dynstr", 0);
   628  	s = linklookup(ctxt, ".gnu.version_r", 0);
   629  	i = 2;
   630  	nfile = 0;
   631  	for(l=needlib; l; l=l->next) {
   632  		nfile++;
   633  		// header
   634  		adduint16(ctxt, s, 1);  // table version
   635  		j = 0;
   636  		for(x=l->aux; x; x=x->next)
   637  			j++;
   638  		adduint16(ctxt, s, j);	// aux count
   639  		adduint32(ctxt, s, addstring(dynstr, l->file));  // file string offset
   640  		adduint32(ctxt, s, 16);  // offset from header to first aux
   641  		if(l->next)
   642  			adduint32(ctxt, s, 16+j*16);  // offset from this header to next
   643  		else
   644  			adduint32(ctxt, s, 0);
   645  		
   646  		for(x=l->aux; x; x=x->next) {
   647  			x->num = i++;
   648  			// aux struct
   649  			adduint32(ctxt, s, elfhash((uchar*)x->vers));  // hash
   650  			adduint16(ctxt, s, 0);  // flags
   651  			adduint16(ctxt, s, x->num);  // other - index we refer to this by
   652  			adduint32(ctxt, s, addstring(dynstr, x->vers));  // version string offset
   653  			if(x->next)
   654  				adduint32(ctxt, s, 16);  // offset from this aux to next
   655  			else
   656  				adduint32(ctxt, s, 0);
   657  		}
   658  	}
   659  
   660  	// version references
   661  	s = linklookup(ctxt, ".gnu.version", 0);
   662  	for(i=0; i<nsym; i++) {
   663  		if(i == 0)
   664  			adduint16(ctxt, s, 0); // first entry - no symbol
   665  		else if(need[i] == nil)
   666  			adduint16(ctxt, s, 1); // global
   667  		else
   668  			adduint16(ctxt, s, need[i]->num);
   669  	}
   670  
   671  	free(need);
   672  
   673  	s = linklookup(ctxt, ".dynamic", 0);
   674  	elfverneed = nfile;
   675  	if(elfverneed) {
   676  		elfwritedynentsym(s, DT_VERNEED, linklookup(ctxt, ".gnu.version_r", 0));
   677  		elfwritedynent(s, DT_VERNEEDNUM, nfile);
   678  		elfwritedynentsym(s, DT_VERSYM, linklookup(ctxt, ".gnu.version", 0));
   679  	}
   680  
   681  	if(thechar == '6') {
   682  		sy = linklookup(ctxt, ".rela.plt", 0);
   683  		if(sy->size > 0) {
   684  			elfwritedynent(s, DT_PLTREL, DT_RELA);
   685  			elfwritedynentsymsize(s, DT_PLTRELSZ, sy);
   686  			elfwritedynentsym(s, DT_JMPREL, sy);
   687  		}
   688  	} else {
   689  		sy = linklookup(ctxt, ".rel.plt", 0);
   690  		if(sy->size > 0) {
   691  			elfwritedynent(s, DT_PLTREL, DT_REL);
   692  			elfwritedynentsymsize(s, DT_PLTRELSZ, sy);
   693  			elfwritedynentsym(s, DT_JMPREL, sy);
   694  		}
   695  	}
   696  
   697  	elfwritedynent(s, DT_NULL, 0);
   698  }
   699  
   700  ElfPhdr*
   701  elfphload(Segment *seg)
   702  {
   703  	ElfPhdr *ph;
   704  	
   705  	ph = newElfPhdr();
   706  	ph->type = PT_LOAD;
   707  	if(seg->rwx & 4)
   708  		ph->flags |= PF_R;
   709  	if(seg->rwx & 2)
   710  		ph->flags |= PF_W;
   711  	if(seg->rwx & 1)
   712  		ph->flags |= PF_X;
   713  	ph->vaddr = seg->vaddr;
   714  	ph->paddr = seg->vaddr;
   715  	ph->memsz = seg->len;
   716  	ph->off = seg->fileoff;
   717  	ph->filesz = seg->filelen;
   718  	ph->align = INITRND;
   719  	
   720  	return ph;
   721  }
   722  
   723  ElfShdr*
   724  elfshname(char *name)
   725  {
   726  	int i, off;
   727  	ElfShdr *sh;
   728  	
   729  	for(i=0; i<nelfstr; i++) {
   730  		if(strcmp(name, elfstr[i].s) == 0) {
   731  			off = elfstr[i].off;
   732  			goto found;
   733  		}
   734  	}
   735  	diag("cannot find elf name %s", name);
   736  	errorexit();
   737  	return nil;
   738  
   739  found:
   740  	for(i=0; i<hdr.shnum; i++) {
   741  		sh = shdr[i];
   742  		if(sh->name == off)
   743  			return sh;
   744  	}
   745  	
   746  	sh = newElfShdr(off);
   747  	return sh;
   748  }
   749  
   750  ElfShdr*
   751  elfshalloc(Section *sect)
   752  {
   753  	ElfShdr *sh;
   754  	
   755  	sh = elfshname(sect->name);
   756  	sect->elfsect = sh;
   757  	return sh;
   758  }
   759  
   760  ElfShdr*
   761  elfshbits(Section *sect)
   762  {
   763  	ElfShdr *sh;
   764  	
   765  	sh = elfshalloc(sect);
   766  	if(sh->type > 0)
   767  		return sh;
   768  
   769  	if(sect->vaddr < sect->seg->vaddr + sect->seg->filelen)
   770  		sh->type = SHT_PROGBITS;
   771  	else
   772  		sh->type = SHT_NOBITS;
   773  	sh->flags = SHF_ALLOC;
   774  	if(sect->rwx & 1)
   775  		sh->flags |= SHF_EXECINSTR;
   776  	if(sect->rwx & 2)
   777  		sh->flags |= SHF_WRITE;
   778  	if(strcmp(sect->name, ".tbss") == 0) {
   779  		if(strcmp(goos, "android") != 0)
   780  			sh->flags |= SHF_TLS; // no TLS on android
   781  		sh->type = SHT_NOBITS;
   782  	}
   783  	if(linkmode != LinkExternal)
   784  		sh->addr = sect->vaddr;
   785  	sh->addralign = sect->align;
   786  	sh->size = sect->len;
   787  	sh->off = sect->seg->fileoff + sect->vaddr - sect->seg->vaddr;
   788  
   789  	return sh;
   790  }
   791  
   792  ElfShdr*
   793  elfshreloc(Section *sect)
   794  {
   795  	int typ;
   796  	ElfShdr *sh;
   797  	char *prefix;
   798  	char buf[100];
   799  	
   800  	// If main section is SHT_NOBITS, nothing to relocate.
   801  	// Also nothing to relocate in .shstrtab.
   802  	if(sect->vaddr >= sect->seg->vaddr + sect->seg->filelen)
   803  		return nil;
   804  	if(strcmp(sect->name, ".shstrtab") == 0 || strcmp(sect->name, ".tbss") == 0)
   805  		return nil;
   806  
   807  	if(thechar == '6') {
   808  		prefix = ".rela";
   809  		typ = SHT_RELA;
   810  	} else {
   811  		prefix = ".rel";
   812  		typ = SHT_REL;
   813  	}
   814  
   815  	snprint(buf, sizeof buf, "%s%s", prefix, sect->name);
   816  	sh = elfshname(buf);
   817  	sh->type = typ;
   818  	sh->entsize = RegSize*(2+(typ==SHT_RELA));
   819  	sh->link = elfshname(".symtab")->shnum;
   820  	sh->info = sect->elfsect->shnum;
   821  	sh->off = sect->reloff;
   822  	sh->size = sect->rellen;
   823  	sh->addralign = RegSize;
   824  	return sh;
   825  }
   826  
   827  void
   828  elfrelocsect(Section *sect, LSym *first)
   829  {
   830  	LSym *sym;
   831  	int32 eaddr;
   832  	Reloc *r;
   833  
   834  	// If main section is SHT_NOBITS, nothing to relocate.
   835  	// Also nothing to relocate in .shstrtab.
   836  	if(sect->vaddr >= sect->seg->vaddr + sect->seg->filelen)
   837  		return;
   838  	if(strcmp(sect->name, ".shstrtab") == 0)
   839  		return;
   840  
   841  	sect->reloff = cpos();
   842  	for(sym = first; sym != nil; sym = sym->next) {
   843  		if(!sym->reachable)
   844  			continue;
   845  		if(sym->value >= sect->vaddr)
   846  			break;
   847  	}
   848  	
   849  	eaddr = sect->vaddr + sect->len;
   850  	for(; sym != nil; sym = sym->next) {
   851  		if(!sym->reachable)
   852  			continue;
   853  		if(sym->value >= eaddr)
   854  			break;
   855  		ctxt->cursym = sym;
   856  		
   857  		for(r = sym->r; r < sym->r+sym->nr; r++) {
   858  			if(r->done)
   859  				continue;
   860  			if(r->xsym == nil) {
   861  				diag("missing xsym in relocation");
   862  				continue;
   863  			}
   864  			if(r->xsym->elfsym == 0)
   865  				diag("reloc %d to non-elf symbol %s (outer=%s) %d", r->type, r->sym->name, r->xsym->name, r->sym->type);
   866  			if(elfreloc1(r, sym->value+r->off - sect->vaddr) < 0)
   867  				diag("unsupported obj reloc %d/%d to %s", r->type, r->siz, r->sym->name);
   868  		}
   869  	}
   870  		
   871  	sect->rellen = cpos() - sect->reloff;
   872  }	
   873  	
   874  void
   875  elfemitreloc(void)
   876  {
   877  	Section *sect;
   878  
   879  	while(cpos()&7)
   880  		cput(0);
   881  
   882  	elfrelocsect(segtext.sect, ctxt->textp);
   883  	for(sect=segtext.sect->next; sect!=nil; sect=sect->next)
   884  		elfrelocsect(sect, datap);	
   885  	for(sect=segrodata.sect; sect!=nil; sect=sect->next)
   886  		elfrelocsect(sect, datap);	
   887  	for(sect=segdata.sect; sect!=nil; sect=sect->next)
   888  		elfrelocsect(sect, datap);	
   889  }
   890  
   891  void
   892  doelf(void)
   893  {
   894  	LSym *s, *shstrtab, *dynstr;
   895  
   896  	if(!iself)
   897  		return;
   898  
   899  	/* predefine strings we need for section headers */
   900  	shstrtab = linklookup(ctxt, ".shstrtab", 0);
   901  	shstrtab->type = SELFROSECT;
   902  	shstrtab->reachable = 1;
   903  
   904  	addstring(shstrtab, "");
   905  	addstring(shstrtab, ".text");
   906  	addstring(shstrtab, ".noptrdata");
   907  	addstring(shstrtab, ".data");
   908  	addstring(shstrtab, ".bss");
   909  	addstring(shstrtab, ".noptrbss");
   910  	// generate .tbss section (except for OpenBSD where it's not supported)
   911  	// for dynamic internal linker or external linking, so that various
   912  	// binutils could correctly calculate PT_TLS size.
   913  	// see http://golang.org/issue/5200.
   914  	if(HEADTYPE != Hopenbsd)
   915  	if(!debug['d'] || linkmode == LinkExternal)
   916  		addstring(shstrtab, ".tbss");
   917  	if(HEADTYPE == Hnetbsd)
   918  		addstring(shstrtab, ".note.netbsd.ident");
   919  	if(HEADTYPE == Hopenbsd)
   920  		addstring(shstrtab, ".note.openbsd.ident");
   921  	if(buildinfolen > 0)
   922  		addstring(shstrtab, ".note.gnu.build-id");
   923  	addstring(shstrtab, ".elfdata");
   924  	addstring(shstrtab, ".rodata");
   925  	addstring(shstrtab, ".typelink");
   926  	addstring(shstrtab, ".gosymtab");
   927  	addstring(shstrtab, ".gopclntab");
   928  	
   929  	if(linkmode == LinkExternal) {
   930  		debug_s = debug['s'];
   931  		debug['s'] = 0;
   932  		debug['d'] = 1;
   933  
   934  		if(thechar == '6') {
   935  			addstring(shstrtab, ".rela.text");
   936  			addstring(shstrtab, ".rela.rodata");
   937  			addstring(shstrtab, ".rela.typelink");
   938  			addstring(shstrtab, ".rela.gosymtab");
   939  			addstring(shstrtab, ".rela.gopclntab");
   940  			addstring(shstrtab, ".rela.noptrdata");
   941  			addstring(shstrtab, ".rela.data");
   942  		} else {
   943  			addstring(shstrtab, ".rel.text");
   944  			addstring(shstrtab, ".rel.rodata");
   945  			addstring(shstrtab, ".rel.typelink");
   946  			addstring(shstrtab, ".rel.gosymtab");
   947  			addstring(shstrtab, ".rel.gopclntab");
   948  			addstring(shstrtab, ".rel.noptrdata");
   949  			addstring(shstrtab, ".rel.data");
   950  		}
   951  		// add a .note.GNU-stack section to mark the stack as non-executable
   952  		addstring(shstrtab, ".note.GNU-stack");
   953  	}
   954  
   955  	if(flag_shared) {
   956  		addstring(shstrtab, ".init_array");
   957  		if(thechar == '6')
   958  			addstring(shstrtab, ".rela.init_array");
   959  		else
   960  			addstring(shstrtab, ".rel.init_array");
   961  	}
   962  
   963  	if(!debug['s']) {
   964  		addstring(shstrtab, ".symtab");
   965  		addstring(shstrtab, ".strtab");
   966  		dwarfaddshstrings(shstrtab);
   967  	}
   968  	addstring(shstrtab, ".shstrtab");
   969  
   970  	if(!debug['d']) {	/* -d suppresses dynamic loader format */
   971  		addstring(shstrtab, ".interp");
   972  		addstring(shstrtab, ".hash");
   973  		addstring(shstrtab, ".got");
   974  		addstring(shstrtab, ".got.plt");
   975  		addstring(shstrtab, ".dynamic");
   976  		addstring(shstrtab, ".dynsym");
   977  		addstring(shstrtab, ".dynstr");
   978  		if(thechar == '6') {
   979  			addstring(shstrtab, ".rela");
   980  			addstring(shstrtab, ".rela.plt");
   981  		} else {
   982  			addstring(shstrtab, ".rel");
   983  			addstring(shstrtab, ".rel.plt");
   984  		}
   985  		addstring(shstrtab, ".plt");
   986  		addstring(shstrtab, ".gnu.version");
   987  		addstring(shstrtab, ".gnu.version_r");
   988  
   989  		/* dynamic symbol table - first entry all zeros */
   990  		s = linklookup(ctxt, ".dynsym", 0);
   991  		s->type = SELFROSECT;
   992  		s->reachable = 1;
   993  		if(thechar == '6')
   994  			s->size += ELF64SYMSIZE;
   995  		else
   996  			s->size += ELF32SYMSIZE;
   997  
   998  		/* dynamic string table */
   999  		s = linklookup(ctxt, ".dynstr", 0);
  1000  		s->type = SELFROSECT;
  1001  		s->reachable = 1;
  1002  		if(s->size == 0)
  1003  			addstring(s, "");
  1004  		dynstr = s;
  1005  
  1006  		/* relocation table */
  1007  		if(thechar == '6')
  1008  			s = linklookup(ctxt, ".rela", 0);
  1009  		else
  1010  			s = linklookup(ctxt, ".rel", 0);
  1011  		s->reachable = 1;
  1012  		s->type = SELFROSECT;
  1013  
  1014  		/* global offset table */
  1015  		s = linklookup(ctxt, ".got", 0);
  1016  		s->reachable = 1;
  1017  		s->type = SELFSECT; // writable
  1018  
  1019  		/* hash */
  1020  		s = linklookup(ctxt, ".hash", 0);
  1021  		s->reachable = 1;
  1022  		s->type = SELFROSECT;
  1023  
  1024  		s = linklookup(ctxt, ".got.plt", 0);
  1025  		s->reachable = 1;
  1026  		s->type = SELFSECT; // writable
  1027  
  1028  		s = linklookup(ctxt, ".plt", 0);
  1029  		s->reachable = 1;
  1030  		s->type = SELFRXSECT;
  1031  		
  1032  		elfsetupplt();
  1033  		
  1034  		if(thechar == '6')
  1035  			s = linklookup(ctxt, ".rela.plt", 0);
  1036  		else
  1037  			s = linklookup(ctxt, ".rel.plt", 0);
  1038  		s->reachable = 1;
  1039  		s->type = SELFROSECT;
  1040  		
  1041  		s = linklookup(ctxt, ".gnu.version", 0);
  1042  		s->reachable = 1;
  1043  		s->type = SELFROSECT;
  1044  		
  1045  		s = linklookup(ctxt, ".gnu.version_r", 0);
  1046  		s->reachable = 1;
  1047  		s->type = SELFROSECT;
  1048  
  1049  		/* define dynamic elf table */
  1050  		s = linklookup(ctxt, ".dynamic", 0);
  1051  		s->reachable = 1;
  1052  		s->type = SELFSECT; // writable
  1053  
  1054  		/*
  1055  		 * .dynamic table
  1056  		 */
  1057  		elfwritedynentsym(s, DT_HASH, linklookup(ctxt, ".hash", 0));
  1058  		elfwritedynentsym(s, DT_SYMTAB, linklookup(ctxt, ".dynsym", 0));
  1059  		if(thechar == '6')
  1060  			elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE);
  1061  		else
  1062  			elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE);
  1063  		elfwritedynentsym(s, DT_STRTAB, linklookup(ctxt, ".dynstr", 0));
  1064  		elfwritedynentsymsize(s, DT_STRSZ, linklookup(ctxt, ".dynstr", 0));
  1065  		if(thechar == '6') {
  1066  			elfwritedynentsym(s, DT_RELA, linklookup(ctxt, ".rela", 0));
  1067  			elfwritedynentsymsize(s, DT_RELASZ, linklookup(ctxt, ".rela", 0));
  1068  			elfwritedynent(s, DT_RELAENT, ELF64RELASIZE);
  1069  		} else {
  1070  			elfwritedynentsym(s, DT_REL, linklookup(ctxt, ".rel", 0));
  1071  			elfwritedynentsymsize(s, DT_RELSZ, linklookup(ctxt, ".rel", 0));
  1072  			elfwritedynent(s, DT_RELENT, ELF32RELSIZE);
  1073  		}
  1074  		if(rpath)
  1075  			elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath));
  1076  		
  1077  		elfwritedynentsym(s, DT_PLTGOT, linklookup(ctxt, ".got.plt", 0));
  1078  
  1079  		// Solaris dynamic linker can't handle an empty .rela.plt if
  1080  		// DT_JMPREL is emitted so we have to defer generation of DT_PLTREL,
  1081  		// DT_PLTRELSZ, and DT_JMPREL dynamic entries until after we know the
  1082  		// size of .rel(a).plt section.
  1083  		elfwritedynent(s, DT_DEBUG, 0);
  1084  
  1085  		// Do not write DT_NULL.  elfdynhash will finish it.
  1086  	}
  1087  }
  1088  
  1089  void
  1090  shsym(ElfShdr *sh, LSym *s)
  1091  {
  1092  	vlong addr;
  1093  	addr = symaddr(s);
  1094  	if(sh->flags&SHF_ALLOC)
  1095  		sh->addr = addr;
  1096  	sh->off = datoff(addr);
  1097  	sh->size = s->size;
  1098  }
  1099  
  1100  void
  1101  phsh(ElfPhdr *ph, ElfShdr *sh)
  1102  {
  1103  	ph->vaddr = sh->addr;
  1104  	ph->paddr = ph->vaddr;
  1105  	ph->off = sh->off;
  1106  	ph->filesz = sh->size;
  1107  	ph->memsz = sh->size;
  1108  	ph->align = sh->addralign;
  1109  }
  1110  
  1111  void
  1112  asmbelfsetup(void)
  1113  {
  1114  	Section *sect;
  1115  
  1116  	/* This null SHdr must appear before all others */
  1117  	elfshname("");
  1118  	
  1119  	for(sect=segtext.sect; sect!=nil; sect=sect->next)
  1120  		elfshalloc(sect);
  1121  	for(sect=segrodata.sect; sect!=nil; sect=sect->next)
  1122  		elfshalloc(sect);
  1123  	for(sect=segdata.sect; sect!=nil; sect=sect->next)
  1124  		elfshalloc(sect);
  1125  }
  1126  
  1127  void
  1128  asmbelf(vlong symo)
  1129  {
  1130  	vlong a, o;
  1131  	vlong startva, resoff;
  1132  	ElfEhdr *eh;
  1133  	ElfPhdr *ph, *pph, *pnote;
  1134  	ElfShdr *sh;
  1135  	Section *sect;
  1136  
  1137  	eh = getElfEhdr();
  1138  	switch(thechar) {
  1139  	default:
  1140  		diag("unknown architecture in asmbelf");
  1141  		errorexit();
  1142  	case '5':
  1143  		eh->machine = EM_ARM;
  1144  		break;
  1145  	case '6':
  1146  		eh->machine = EM_X86_64;
  1147  		break;
  1148  	case '8':
  1149  		eh->machine = EM_386;
  1150  		break;
  1151  	}
  1152  
  1153  	startva = INITTEXT - HEADR;
  1154  	resoff = ELFRESERVE;
  1155  	
  1156  	pph = nil;
  1157  	if(linkmode == LinkExternal) {
  1158  		/* skip program headers */
  1159  		eh->phoff = 0;
  1160  		eh->phentsize = 0;
  1161  		goto elfobj;
  1162  	}
  1163  
  1164  	/* program header info */
  1165  	pph = newElfPhdr();
  1166  	pph->type = PT_PHDR;
  1167  	pph->flags = PF_R;
  1168  	pph->off = eh->ehsize;
  1169  	pph->vaddr = INITTEXT - HEADR + pph->off;
  1170  	pph->paddr = INITTEXT - HEADR + pph->off;
  1171  	pph->align = INITRND;
  1172  
  1173  	/*
  1174  	 * PHDR must be in a loaded segment. Adjust the text
  1175  	 * segment boundaries downwards to include it.
  1176  	 * Except on NaCl where it must not be loaded.
  1177  	 */
  1178  	if(HEADTYPE != Hnacl) {
  1179  		o = segtext.vaddr - pph->vaddr;
  1180  		segtext.vaddr -= o;
  1181  		segtext.len += o;
  1182  		o = segtext.fileoff - pph->off;
  1183  		segtext.fileoff -= o;
  1184  		segtext.filelen += o;
  1185  	}
  1186  
  1187  	if(!debug['d']) {
  1188  		/* interpreter */
  1189  		sh = elfshname(".interp");
  1190  		sh->type = SHT_PROGBITS;
  1191  		sh->flags = SHF_ALLOC;
  1192  		sh->addralign = 1;
  1193  		if(interpreter == nil) {
  1194  			switch(HEADTYPE) {
  1195  			case Hlinux:
  1196  				interpreter = linuxdynld;
  1197  				break;
  1198  			case Hfreebsd:
  1199  				interpreter = freebsddynld;
  1200  				break;
  1201  			case Hnetbsd:
  1202  				interpreter = netbsddynld;
  1203  				break;
  1204  			case Hopenbsd:
  1205  				interpreter = openbsddynld;
  1206  				break;
  1207  			case Hdragonfly:
  1208  				interpreter = dragonflydynld;
  1209  				break;
  1210  			case Hsolaris:
  1211  				interpreter = solarisdynld;
  1212  				break;
  1213  			}
  1214  		}
  1215  		resoff -= elfinterp(sh, startva, resoff, interpreter);
  1216  
  1217  		ph = newElfPhdr();
  1218  		ph->type = PT_INTERP;
  1219  		ph->flags = PF_R;
  1220  		phsh(ph, sh);
  1221  	}
  1222  
  1223  	pnote = nil;
  1224  	if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd) {
  1225  		sh = nil;
  1226  		switch(HEADTYPE) {
  1227  		case Hnetbsd:
  1228  			sh = elfshname(".note.netbsd.ident");
  1229  			resoff -= elfnetbsdsig(sh, startva, resoff);
  1230  			break;
  1231  		case Hopenbsd:
  1232  			sh = elfshname(".note.openbsd.ident");
  1233  			resoff -= elfopenbsdsig(sh, startva, resoff);
  1234  			break;
  1235  		}
  1236  
  1237  		pnote = newElfPhdr();
  1238  		pnote->type = PT_NOTE;
  1239  		pnote->flags = PF_R;
  1240  		phsh(pnote, sh);
  1241  	}
  1242  
  1243  	if(buildinfolen > 0) {
  1244  		sh = elfshname(".note.gnu.build-id");
  1245  		resoff -= elfbuildinfo(sh, startva, resoff);
  1246  
  1247  		if(pnote == nil) {
  1248  			pnote = newElfPhdr();
  1249  			pnote->type = PT_NOTE;
  1250  			pnote->flags = PF_R;
  1251  		}
  1252  		phsh(pnote, sh);
  1253  	}
  1254  
  1255  	// Additions to the reserved area must be above this line.
  1256  	USED(resoff);
  1257  
  1258  	elfphload(&segtext);
  1259  	if(segrodata.sect != nil)
  1260  		elfphload(&segrodata);
  1261  	elfphload(&segdata);
  1262  
  1263  	/* Dynamic linking sections */
  1264  	if(!debug['d']) {	/* -d suppresses dynamic loader format */
  1265  		sh = elfshname(".dynsym");
  1266  		sh->type = SHT_DYNSYM;
  1267  		sh->flags = SHF_ALLOC;
  1268  		if(elf64)
  1269  			sh->entsize = ELF64SYMSIZE;
  1270  		else
  1271  			sh->entsize = ELF32SYMSIZE;
  1272  		sh->addralign = RegSize;
  1273  		sh->link = elfshname(".dynstr")->shnum;
  1274  		// sh->info = index of first non-local symbol (number of local symbols)
  1275  		shsym(sh, linklookup(ctxt, ".dynsym", 0));
  1276  
  1277  		sh = elfshname(".dynstr");
  1278  		sh->type = SHT_STRTAB;
  1279  		sh->flags = SHF_ALLOC;
  1280  		sh->addralign = 1;
  1281  		shsym(sh, linklookup(ctxt, ".dynstr", 0));
  1282  
  1283  		if(elfverneed) {
  1284  			sh = elfshname(".gnu.version");
  1285  			sh->type = SHT_GNU_VERSYM;
  1286  			sh->flags = SHF_ALLOC;
  1287  			sh->addralign = 2;
  1288  			sh->link = elfshname(".dynsym")->shnum;
  1289  			sh->entsize = 2;
  1290  			shsym(sh, linklookup(ctxt, ".gnu.version", 0));
  1291  			
  1292  			sh = elfshname(".gnu.version_r");
  1293  			sh->type = SHT_GNU_VERNEED;
  1294  			sh->flags = SHF_ALLOC;
  1295  			sh->addralign = RegSize;
  1296  			sh->info = elfverneed;
  1297  			sh->link = elfshname(".dynstr")->shnum;
  1298  			shsym(sh, linklookup(ctxt, ".gnu.version_r", 0));
  1299  		}
  1300  
  1301  		switch(eh->machine) {
  1302  		case EM_X86_64:
  1303  			sh = elfshname(".rela.plt");
  1304  			sh->type = SHT_RELA;
  1305  			sh->flags = SHF_ALLOC;
  1306  			sh->entsize = ELF64RELASIZE;
  1307  			sh->addralign = RegSize;
  1308  			sh->link = elfshname(".dynsym")->shnum;
  1309  			sh->info = elfshname(".plt")->shnum;
  1310  			shsym(sh, linklookup(ctxt, ".rela.plt", 0));
  1311  
  1312  			sh = elfshname(".rela");
  1313  			sh->type = SHT_RELA;
  1314  			sh->flags = SHF_ALLOC;
  1315  			sh->entsize = ELF64RELASIZE;
  1316  			sh->addralign = 8;
  1317  			sh->link = elfshname(".dynsym")->shnum;
  1318  			shsym(sh, linklookup(ctxt, ".rela", 0));
  1319  			break;
  1320  		
  1321  		default:
  1322  			sh = elfshname(".rel.plt");
  1323  			sh->type = SHT_REL;
  1324  			sh->flags = SHF_ALLOC;
  1325  			sh->entsize = ELF32RELSIZE;
  1326  			sh->link = elfshname(".dynsym")->shnum;
  1327  			shsym(sh, linklookup(ctxt, ".rel.plt", 0));
  1328  
  1329  			sh = elfshname(".rel");
  1330  			sh->type = SHT_REL;
  1331  			sh->flags = SHF_ALLOC;
  1332  			sh->entsize = ELF32RELSIZE;
  1333  			sh->addralign = 4;
  1334  			sh->link = elfshname(".dynsym")->shnum;
  1335  			shsym(sh, linklookup(ctxt, ".rel", 0));
  1336  			break;
  1337  		}
  1338  
  1339  		sh = elfshname(".plt");
  1340  		sh->type = SHT_PROGBITS;
  1341  		sh->flags = SHF_ALLOC+SHF_EXECINSTR;
  1342  		if(eh->machine == EM_X86_64)
  1343  			sh->entsize = 16;
  1344  		else
  1345  			sh->entsize = 4;
  1346  		sh->addralign = 4;
  1347  		shsym(sh, linklookup(ctxt, ".plt", 0));
  1348  
  1349  		sh = elfshname(".got");
  1350  		sh->type = SHT_PROGBITS;
  1351  		sh->flags = SHF_ALLOC+SHF_WRITE;
  1352  		sh->entsize = RegSize;
  1353  		sh->addralign = RegSize;
  1354  		shsym(sh, linklookup(ctxt, ".got", 0));
  1355  
  1356  		sh = elfshname(".got.plt");
  1357  		sh->type = SHT_PROGBITS;
  1358  		sh->flags = SHF_ALLOC+SHF_WRITE;
  1359  		sh->entsize = RegSize;
  1360  		sh->addralign = RegSize;
  1361  		shsym(sh, linklookup(ctxt, ".got.plt", 0));
  1362  		
  1363  		sh = elfshname(".hash");
  1364  		sh->type = SHT_HASH;
  1365  		sh->flags = SHF_ALLOC;
  1366  		sh->entsize = 4;
  1367  		sh->addralign = RegSize;
  1368  		sh->link = elfshname(".dynsym")->shnum;
  1369  		shsym(sh, linklookup(ctxt, ".hash", 0));
  1370  
  1371  		/* sh and PT_DYNAMIC for .dynamic section */
  1372  		sh = elfshname(".dynamic");
  1373  		sh->type = SHT_DYNAMIC;
  1374  		sh->flags = SHF_ALLOC+SHF_WRITE;
  1375  		sh->entsize = 2*RegSize;
  1376  		sh->addralign = RegSize;
  1377  		sh->link = elfshname(".dynstr")->shnum;
  1378  		shsym(sh, linklookup(ctxt, ".dynamic", 0));
  1379  		ph = newElfPhdr();
  1380  		ph->type = PT_DYNAMIC;
  1381  		ph->flags = PF_R + PF_W;
  1382  		phsh(ph, sh);
  1383  		
  1384  		/*
  1385  		 * Thread-local storage segment (really just size).
  1386  		 */
  1387  		// Do not emit PT_TLS for OpenBSD since ld.so(1) does
  1388  		// not currently support it. This is handled
  1389  		// appropriately in runtime/cgo.
  1390  		if(ctxt->tlsoffset != 0 && HEADTYPE != Hopenbsd) {
  1391  			ph = newElfPhdr();
  1392  			ph->type = PT_TLS;
  1393  			ph->flags = PF_R;
  1394  			ph->memsz = -ctxt->tlsoffset;
  1395  			ph->align = RegSize;
  1396  		}
  1397  	}
  1398  
  1399  	if(HEADTYPE == Hlinux) {
  1400  		ph = newElfPhdr();
  1401  		ph->type = PT_GNU_STACK;
  1402  		ph->flags = PF_W+PF_R;
  1403  		ph->align = RegSize;
  1404  		
  1405  		ph = newElfPhdr();
  1406  		ph->type = PT_PAX_FLAGS;
  1407  		ph->flags = 0x2a00; // mprotect, randexec, emutramp disabled
  1408  		ph->align = RegSize;
  1409  	}
  1410  
  1411  elfobj:
  1412  	sh = elfshname(".shstrtab");
  1413  	sh->type = SHT_STRTAB;
  1414  	sh->addralign = 1;
  1415  	shsym(sh, linklookup(ctxt, ".shstrtab", 0));
  1416  	eh->shstrndx = sh->shnum;
  1417  
  1418  	// put these sections early in the list
  1419  	if(!debug['s']) {
  1420  		elfshname(".symtab");
  1421  		elfshname(".strtab");
  1422  	}
  1423  
  1424  	for(sect=segtext.sect; sect!=nil; sect=sect->next)
  1425  		elfshbits(sect);
  1426  	for(sect=segrodata.sect; sect!=nil; sect=sect->next)
  1427  		elfshbits(sect);
  1428  	for(sect=segdata.sect; sect!=nil; sect=sect->next)
  1429  		elfshbits(sect);
  1430  
  1431  	if(linkmode == LinkExternal) {
  1432  		for(sect=segtext.sect; sect!=nil; sect=sect->next)
  1433  			elfshreloc(sect);
  1434  		for(sect=segrodata.sect; sect!=nil; sect=sect->next)
  1435  			elfshreloc(sect);
  1436  		for(sect=segdata.sect; sect!=nil; sect=sect->next)
  1437  			elfshreloc(sect);
  1438  		// add a .note.GNU-stack section to mark the stack as non-executable
  1439  		sh = elfshname(".note.GNU-stack");
  1440  		sh->type = SHT_PROGBITS;
  1441  		sh->addralign = 1;
  1442  		sh->flags = 0;
  1443  	}
  1444  
  1445  	// generate .tbss section for dynamic internal linking (except for OpenBSD)
  1446  	// external linking generates .tbss in data.c
  1447  	if(linkmode == LinkInternal && !debug['d'] && HEADTYPE != Hopenbsd) {
  1448  		sh = elfshname(".tbss");
  1449  		sh->type = SHT_NOBITS;
  1450  		sh->addralign = RegSize;
  1451  		sh->size = -ctxt->tlsoffset;
  1452  		sh->flags = SHF_ALLOC | SHF_TLS | SHF_WRITE;
  1453  	}
  1454  
  1455  	if(!debug['s']) {
  1456  		sh = elfshname(".symtab");
  1457  		sh->type = SHT_SYMTAB;
  1458  		sh->off = symo;
  1459  		sh->size = symsize;
  1460  		sh->addralign = RegSize;
  1461  		sh->entsize = 8+2*RegSize;
  1462  		sh->link = elfshname(".strtab")->shnum;
  1463  		sh->info = elfglobalsymndx;
  1464  
  1465  		sh = elfshname(".strtab");
  1466  		sh->type = SHT_STRTAB;
  1467  		sh->off = symo+symsize;
  1468  		sh->size = elfstrsize;
  1469  		sh->addralign = 1;
  1470  
  1471  		dwarfaddelfheaders();
  1472  	}
  1473  
  1474  	/* Main header */
  1475  	eh->ident[EI_MAG0] = '\177';
  1476  	eh->ident[EI_MAG1] = 'E';
  1477  	eh->ident[EI_MAG2] = 'L';
  1478  	eh->ident[EI_MAG3] = 'F';
  1479  	if(HEADTYPE == Hfreebsd)
  1480  		eh->ident[EI_OSABI] = ELFOSABI_FREEBSD;
  1481  	else if(HEADTYPE == Hnetbsd)
  1482  		eh->ident[EI_OSABI] = ELFOSABI_NETBSD;
  1483  	else if(HEADTYPE == Hopenbsd)
  1484  		eh->ident[EI_OSABI] = ELFOSABI_OPENBSD;
  1485  	else if(HEADTYPE == Hdragonfly)
  1486  		eh->ident[EI_OSABI] = ELFOSABI_NONE;
  1487  	if(elf64)
  1488  		eh->ident[EI_CLASS] = ELFCLASS64;
  1489  	else
  1490  		eh->ident[EI_CLASS] = ELFCLASS32;
  1491  	eh->ident[EI_DATA] = ELFDATA2LSB;
  1492  	eh->ident[EI_VERSION] = EV_CURRENT;
  1493  
  1494  	if(linkmode == LinkExternal)
  1495  		eh->type = ET_REL;
  1496  	else
  1497  		eh->type = ET_EXEC;
  1498  
  1499  	if(linkmode != LinkExternal)
  1500  		eh->entry = entryvalue();
  1501  
  1502  	eh->version = EV_CURRENT;
  1503  
  1504  	if(pph != nil) {
  1505  		pph->filesz = eh->phnum * eh->phentsize;
  1506  		pph->memsz = pph->filesz;
  1507  	}
  1508  
  1509  	cseek(0);
  1510  	a = 0;
  1511  	a += elfwritehdr();
  1512  	a += elfwritephdrs();
  1513  	a += elfwriteshdrs();
  1514  	if(!debug['d'])
  1515  		a += elfwriteinterp();
  1516  	if(linkmode != LinkExternal) {
  1517  		if(HEADTYPE == Hnetbsd)
  1518  			a += elfwritenetbsdsig();
  1519  		if(HEADTYPE == Hopenbsd)
  1520  			a += elfwriteopenbsdsig();
  1521  		if(buildinfolen > 0)
  1522  			a += elfwritebuildinfo();
  1523  	}
  1524  	if(a > ELFRESERVE)	
  1525  		diag("ELFRESERVE too small: %lld > %d", a, ELFRESERVE);
  1526  }