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