github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/ld/elf.c (about)

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