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