Example #1
0
void
doelf(void)
{
	Sym *s, *shstrtab, *dynstr;

	if(!iself)
		return;

	/* predefine strings we need for section headers */
	shstrtab = lookup(".shstrtab", 0);
	shstrtab->type = SELFROSECT;
	shstrtab->reachable = 1;

	addstring(shstrtab, "");
	addstring(shstrtab, ".text");
	addstring(shstrtab, ".noptrdata");
	addstring(shstrtab, ".data");
	addstring(shstrtab, ".bss");
	addstring(shstrtab, ".noptrbss");
	if(HEADTYPE == Hnetbsd)
		addstring(shstrtab, ".note.netbsd.ident");
	if(HEADTYPE == Hopenbsd)
		addstring(shstrtab, ".note.openbsd.ident");
	if(buildinfolen > 0)
		addstring(shstrtab, ".note.gnu.build-id");
	addstring(shstrtab, ".elfdata");
	addstring(shstrtab, ".rodata");
	addstring(shstrtab, ".typelink");
	if(flag_shared)
		addstring(shstrtab, ".data.rel.ro");
	addstring(shstrtab, ".gcdata");
	addstring(shstrtab, ".gcbss");
	addstring(shstrtab, ".gosymtab");
	addstring(shstrtab, ".gopclntab");
	
	if(isobj) {
		debug['s'] = 0;
		debug['d'] = 1;

		if(thechar == '6') {
			addstring(shstrtab, ".rela.text");
			addstring(shstrtab, ".rela.rodata");
			addstring(shstrtab, ".rela.typelink");
			addstring(shstrtab, ".rela.gcdata");
			addstring(shstrtab, ".rela.gcbss");
			addstring(shstrtab, ".rela.gosymtab");
			addstring(shstrtab, ".rela.gopclntab");
			addstring(shstrtab, ".rela.noptrdata");
			addstring(shstrtab, ".rela.data");
		} else {
			addstring(shstrtab, ".rel.text");
			addstring(shstrtab, ".rel.rodata");
			addstring(shstrtab, ".rel.typelink");
			addstring(shstrtab, ".rel.gcdata");
			addstring(shstrtab, ".rel.gcbss");
			addstring(shstrtab, ".rel.gosymtab");
			addstring(shstrtab, ".rel.gopclntab");
			addstring(shstrtab, ".rel.noptrdata");
			addstring(shstrtab, ".rel.data");
		}
	}

	if(!debug['s']) {
		addstring(shstrtab, ".symtab");
		addstring(shstrtab, ".strtab");
		dwarfaddshstrings(shstrtab);
	}
	addstring(shstrtab, ".shstrtab");

	if(!debug['d']) {	/* -d suppresses dynamic loader format */
		addstring(shstrtab, ".interp");
		addstring(shstrtab, ".hash");
		addstring(shstrtab, ".got");
		addstring(shstrtab, ".got.plt");
		addstring(shstrtab, ".dynamic");
		addstring(shstrtab, ".dynsym");
		addstring(shstrtab, ".dynstr");
		if(thechar == '6') {
			addstring(shstrtab, ".rela");
			addstring(shstrtab, ".rela.plt");
		} else {
			addstring(shstrtab, ".rel");
			addstring(shstrtab, ".rel.plt");
		}
		addstring(shstrtab, ".plt");
		addstring(shstrtab, ".gnu.version");
		addstring(shstrtab, ".gnu.version_r");

		/* dynamic symbol table - first entry all zeros */
		s = lookup(".dynsym", 0);
		s->type = SELFROSECT;
		s->reachable = 1;
		if(thechar == '6')
			s->size += ELF64SYMSIZE;
		else
			s->size += ELF32SYMSIZE;

		/* dynamic string table */
		s = lookup(".dynstr", 0);
		s->type = SELFROSECT;
		s->reachable = 1;
		if(s->size == 0)
			addstring(s, "");
		dynstr = s;

		/* relocation table */
		if(thechar == '6')
			s = lookup(".rela", 0);
		else
			s = lookup(".rel", 0);
		s->reachable = 1;
		s->type = SELFROSECT;

		/* global offset table */
		s = lookup(".got", 0);
		s->reachable = 1;
		s->type = SELFSECT; // writable

		/* hash */
		s = lookup(".hash", 0);
		s->reachable = 1;
		s->type = SELFROSECT;

		s = lookup(".got.plt", 0);
		s->reachable = 1;
		s->type = SELFSECT; // writable

		s = lookup(".plt", 0);
		s->reachable = 1;
		s->type = SELFROSECT;
		
		elfsetupplt();
		
		if(thechar == '6')
			s = lookup(".rela.plt", 0);
		else
			s = lookup(".rel.plt", 0);
		s->reachable = 1;
		s->type = SELFROSECT;
		
		s = lookup(".gnu.version", 0);
		s->reachable = 1;
		s->type = SELFROSECT;
		
		s = lookup(".gnu.version_r", 0);
		s->reachable = 1;
		s->type = SELFROSECT;

		/* define dynamic elf table */
		s = lookup(".dynamic", 0);
		s->reachable = 1;
		s->type = SELFSECT; // writable

		/*
		 * .dynamic table
		 */
		elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
		elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
		if(thechar == '6')
			elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE);
		else
			elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE);
		elfwritedynentsym(s, DT_STRTAB, lookup(".dynstr", 0));
		elfwritedynentsymsize(s, DT_STRSZ, lookup(".dynstr", 0));
		if(thechar == '6') {
			elfwritedynentsym(s, DT_RELA, lookup(".rela", 0));
			elfwritedynentsymsize(s, DT_RELASZ, lookup(".rela", 0));
			elfwritedynent(s, DT_RELAENT, ELF64RELASIZE);
		} else {
			elfwritedynentsym(s, DT_REL, lookup(".rel", 0));
			elfwritedynentsymsize(s, DT_RELSZ, lookup(".rel", 0));
			elfwritedynent(s, DT_RELENT, ELF32RELSIZE);
		}
		if(rpath)
			elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath));
		
		elfwritedynentsym(s, DT_PLTGOT, lookup(".got.plt", 0));

		if(thechar == '6') {
			elfwritedynent(s, DT_PLTREL, DT_RELA);
			elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rela.plt", 0));
			elfwritedynentsym(s, DT_JMPREL, lookup(".rela.plt", 0));
		} else {
			elfwritedynent(s, DT_PLTREL, DT_REL);
			elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rel.plt", 0));
			elfwritedynentsym(s, DT_JMPREL, lookup(".rel.plt", 0));
		}
		
		elfwritedynent(s, DT_DEBUG, 0);

		if(flag_shared) {
			Sym *init_sym = lookup(LIBINITENTRY, 0);
			if(init_sym->type != STEXT)
				diag("entry not text: %s", init_sym->name);
			elfwritedynentsym(s, DT_INIT, init_sym);
		}

		// Do not write DT_NULL.  elfdynhash will finish it.
	}
}
Example #2
0
void
elfdynhash(void)
{
	Sym *s, *sy, *dynstr;
	int i, j, nbucket, b, nfile;
	uint32 hc, *chain, *buckets;
	int nsym;
	char *name;
	Elfaux **need;
	Elflib *needlib;
	Elflib *l;
	Elfaux *x;
	
	if(!iself)
		return;

	nsym = nelfsym;
	s = lookup(".hash", 0);
	s->type = SELFROSECT;
	s->reachable = 1;

	i = nsym;
	nbucket = 1;
	while(i > 0) {
		++nbucket;
		i >>= 1;
	}

	needlib = nil;
	need = malloc(nsym * sizeof need[0]);
	chain = malloc(nsym * sizeof chain[0]);
	buckets = malloc(nbucket * sizeof buckets[0]);
	if(need == nil || chain == nil || buckets == nil) {
		cursym = nil;
		diag("out of memory");
		errorexit();
	}
	memset(need, 0, nsym * sizeof need[0]);
	memset(chain, 0, nsym * sizeof chain[0]);
	memset(buckets, 0, nbucket * sizeof buckets[0]);
	for(sy=allsym; sy!=S; sy=sy->allsym) {
		if (sy->dynid <= 0)
			continue;

		if(sy->dynimpvers)
			need[sy->dynid] = addelflib(&needlib, sy->dynimplib, sy->dynimpvers);

		name = sy->dynimpname;
		if(name == nil)
			name = sy->name;
		hc = elfhash((uchar*)name);

		b = hc % nbucket;
		chain[sy->dynid] = buckets[b];
		buckets[b] = sy->dynid;
	}

	adduint32(s, nbucket);
	adduint32(s, nsym);
	for(i = 0; i<nbucket; i++)
		adduint32(s, buckets[i]);
	for(i = 0; i<nsym; i++)
		adduint32(s, chain[i]);

	free(chain);
	free(buckets);
	
	// version symbols
	dynstr = lookup(".dynstr", 0);
	s = lookup(".gnu.version_r", 0);
	i = 2;
	nfile = 0;
	for(l=needlib; l; l=l->next) {
		nfile++;
		// header
		adduint16(s, 1);  // table version
		j = 0;
		for(x=l->aux; x; x=x->next)
			j++;
		adduint16(s, j);	// aux count
		adduint32(s, addstring(dynstr, l->file));  // file string offset
		adduint32(s, 16);  // offset from header to first aux
		if(l->next)
			adduint32(s, 16+j*16);  // offset from this header to next
		else
			adduint32(s, 0);
		
		for(x=l->aux; x; x=x->next) {
			x->num = i++;
			// aux struct
			adduint32(s, elfhash((uchar*)x->vers));  // hash
			adduint16(s, 0);  // flags
			adduint16(s, x->num);  // other - index we refer to this by
			adduint32(s, addstring(dynstr, x->vers));  // version string offset
			if(x->next)
				adduint32(s, 16);  // offset from this aux to next
			else
				adduint32(s, 0);
		}
	}

	// version references
	s = lookup(".gnu.version", 0);
	for(i=0; i<nsym; i++) {
		if(i == 0)
			adduint16(s, 0); // first entry - no symbol
		else if(need[i] == nil)
			adduint16(s, 1); // global
		else
			adduint16(s, need[i]->num);
	}

	free(need);

	s = lookup(".dynamic", 0);
	elfverneed = nfile;
	if(elfverneed) {
		elfwritedynentsym(s, DT_VERNEED, lookup(".gnu.version_r", 0));
		elfwritedynent(s, DT_VERNEEDNUM, nfile);
		elfwritedynentsym(s, DT_VERSYM, lookup(".gnu.version", 0));
	}
	elfwritedynent(s, DT_NULL, 0);
}
Example #3
0
File: elf.c Project: rosrad/go-rep
void
doelf(void)
{
	LSym *s, *shstrtab, *dynstr;

	if(!iself)
		return;

	/* predefine strings we need for section headers */
	shstrtab = linklookup(ctxt, ".shstrtab", 0);
	shstrtab->type = SELFROSECT;
	shstrtab->reachable = 1;

	addstring(shstrtab, "");
	addstring(shstrtab, ".text");
	addstring(shstrtab, ".noptrdata");
	addstring(shstrtab, ".data");
	addstring(shstrtab, ".bss");
	addstring(shstrtab, ".noptrbss");
	// generate .tbss section (except for OpenBSD where it's not supported)
	// for dynamic internal linker or external linking, so that various
	// binutils could correctly calculate PT_TLS size.
	// see http://golang.org/issue/5200.
	if(HEADTYPE != Hopenbsd)
	if(!debug['d'] || linkmode == LinkExternal)
		addstring(shstrtab, ".tbss");
	if(HEADTYPE == Hnetbsd)
		addstring(shstrtab, ".note.netbsd.ident");
	if(HEADTYPE == Hopenbsd)
		addstring(shstrtab, ".note.openbsd.ident");
	if(buildinfolen > 0)
		addstring(shstrtab, ".note.gnu.build-id");
	addstring(shstrtab, ".elfdata");
	addstring(shstrtab, ".rodata");
	addstring(shstrtab, ".typelink");
	addstring(shstrtab, ".gosymtab");
	addstring(shstrtab, ".gopclntab");
	
	if(linkmode == LinkExternal) {
		debug_s = debug['s'];
		debug['s'] = 0;
		debug['d'] = 1;

		if(thechar == '6') {
			addstring(shstrtab, ".rela.text");
			addstring(shstrtab, ".rela.rodata");
			addstring(shstrtab, ".rela.typelink");
			addstring(shstrtab, ".rela.gosymtab");
			addstring(shstrtab, ".rela.gopclntab");
			addstring(shstrtab, ".rela.noptrdata");
			addstring(shstrtab, ".rela.data");
		} else {
			addstring(shstrtab, ".rel.text");
			addstring(shstrtab, ".rel.rodata");
			addstring(shstrtab, ".rel.typelink");
			addstring(shstrtab, ".rel.gosymtab");
			addstring(shstrtab, ".rel.gopclntab");
			addstring(shstrtab, ".rel.noptrdata");
			addstring(shstrtab, ".rel.data");
		}
		// add a .note.GNU-stack section to mark the stack as non-executable
		addstring(shstrtab, ".note.GNU-stack");
	}

	if(flag_shared) {
		addstring(shstrtab, ".init_array");
		if(thechar == '6')
			addstring(shstrtab, ".rela.init_array");
		else
			addstring(shstrtab, ".rel.init_array");
	}

	if(!debug['s']) {
		addstring(shstrtab, ".symtab");
		addstring(shstrtab, ".strtab");
		dwarfaddshstrings(shstrtab);
	}
	addstring(shstrtab, ".shstrtab");

	if(!debug['d']) {	/* -d suppresses dynamic loader format */
		addstring(shstrtab, ".interp");
		addstring(shstrtab, ".hash");
		addstring(shstrtab, ".got");
		addstring(shstrtab, ".got.plt");
		addstring(shstrtab, ".dynamic");
		addstring(shstrtab, ".dynsym");
		addstring(shstrtab, ".dynstr");
		if(thechar == '6') {
			addstring(shstrtab, ".rela");
			addstring(shstrtab, ".rela.plt");
		} else {
			addstring(shstrtab, ".rel");
			addstring(shstrtab, ".rel.plt");
		}
		addstring(shstrtab, ".plt");
		addstring(shstrtab, ".gnu.version");
		addstring(shstrtab, ".gnu.version_r");

		/* dynamic symbol table - first entry all zeros */
		s = linklookup(ctxt, ".dynsym", 0);
		s->type = SELFROSECT;
		s->reachable = 1;
		if(thechar == '6')
			s->size += ELF64SYMSIZE;
		else
			s->size += ELF32SYMSIZE;

		/* dynamic string table */
		s = linklookup(ctxt, ".dynstr", 0);
		s->type = SELFROSECT;
		s->reachable = 1;
		if(s->size == 0)
			addstring(s, "");
		dynstr = s;

		/* relocation table */
		if(thechar == '6')
			s = linklookup(ctxt, ".rela", 0);
		else
			s = linklookup(ctxt, ".rel", 0);
		s->reachable = 1;
		s->type = SELFROSECT;

		/* global offset table */
		s = linklookup(ctxt, ".got", 0);
		s->reachable = 1;
		s->type = SELFSECT; // writable

		/* hash */
		s = linklookup(ctxt, ".hash", 0);
		s->reachable = 1;
		s->type = SELFROSECT;

		s = linklookup(ctxt, ".got.plt", 0);
		s->reachable = 1;
		s->type = SELFSECT; // writable

		s = linklookup(ctxt, ".plt", 0);
		s->reachable = 1;
		s->type = SELFRXSECT;
		
		elfsetupplt();
		
		if(thechar == '6')
			s = linklookup(ctxt, ".rela.plt", 0);
		else
			s = linklookup(ctxt, ".rel.plt", 0);
		s->reachable = 1;
		s->type = SELFROSECT;
		
		s = linklookup(ctxt, ".gnu.version", 0);
		s->reachable = 1;
		s->type = SELFROSECT;
		
		s = linklookup(ctxt, ".gnu.version_r", 0);
		s->reachable = 1;
		s->type = SELFROSECT;

		/* define dynamic elf table */
		s = linklookup(ctxt, ".dynamic", 0);
		s->reachable = 1;
		s->type = SELFSECT; // writable

		/*
		 * .dynamic table
		 */
		elfwritedynentsym(s, DT_HASH, linklookup(ctxt, ".hash", 0));
		elfwritedynentsym(s, DT_SYMTAB, linklookup(ctxt, ".dynsym", 0));
		if(thechar == '6')
			elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE);
		else
			elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE);
		elfwritedynentsym(s, DT_STRTAB, linklookup(ctxt, ".dynstr", 0));
		elfwritedynentsymsize(s, DT_STRSZ, linklookup(ctxt, ".dynstr", 0));
		if(thechar == '6') {
			elfwritedynentsym(s, DT_RELA, linklookup(ctxt, ".rela", 0));
			elfwritedynentsymsize(s, DT_RELASZ, linklookup(ctxt, ".rela", 0));
			elfwritedynent(s, DT_RELAENT, ELF64RELASIZE);
		} else {
			elfwritedynentsym(s, DT_REL, linklookup(ctxt, ".rel", 0));
			elfwritedynentsymsize(s, DT_RELSZ, linklookup(ctxt, ".rel", 0));
			elfwritedynent(s, DT_RELENT, ELF32RELSIZE);
		}
		if(rpath)
			elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath));
		
		elfwritedynentsym(s, DT_PLTGOT, linklookup(ctxt, ".got.plt", 0));

		// Solaris dynamic linker can't handle an empty .rela.plt if
		// DT_JMPREL is emitted so we have to defer generation of DT_PLTREL,
		// DT_PLTRELSZ, and DT_JMPREL dynamic entries until after we know the
		// size of .rel(a).plt section.
		elfwritedynent(s, DT_DEBUG, 0);

		// Do not write DT_NULL.  elfdynhash will finish it.
	}
}
Example #4
0
File: asm.c Project: timnau/golang
void
doelf(void)
{
    Sym *s, *shstrtab, *dynstr;

    if(!iself)
        return;

    /* predefine strings we need for section headers */
    shstrtab = lookup(".shstrtab", 0);
    shstrtab->type = SELFROSECT;
    shstrtab->reachable = 1;

    elfstr[ElfStrEmpty] = addstring(shstrtab, "");
    elfstr[ElfStrText] = addstring(shstrtab, ".text");
    elfstr[ElfStrNoPtrData] = addstring(shstrtab, ".noptrdata");
    elfstr[ElfStrData] = addstring(shstrtab, ".data");
    elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
    elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss");
    if(HEADTYPE == Hnetbsd)
        elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
    if(HEADTYPE == Hopenbsd)
        elfstr[ElfStrNoteOpenbsdIdent] = addstring(shstrtab, ".note.openbsd.ident");
    if(buildinfolen > 0)
        elfstr[ElfStrNoteBuildInfo] = addstring(shstrtab, ".note.gnu.build-id");
    addstring(shstrtab, ".elfdata");
    addstring(shstrtab, ".rodata");
    addstring(shstrtab, ".typelink");
    addstring(shstrtab, ".gcdata");
    addstring(shstrtab, ".gcbss");
    addstring(shstrtab, ".gosymtab");
    addstring(shstrtab, ".gopclntab");
    if(!debug['s']) {
        elfstr[ElfStrSymtab] = addstring(shstrtab, ".symtab");
        elfstr[ElfStrStrtab] = addstring(shstrtab, ".strtab");
        dwarfaddshstrings(shstrtab);
    }
    elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab");

    if(!debug['d']) {	/* -d suppresses dynamic loader format */
        elfstr[ElfStrInterp] = addstring(shstrtab, ".interp");
        elfstr[ElfStrHash] = addstring(shstrtab, ".hash");
        elfstr[ElfStrGot] = addstring(shstrtab, ".got");
        elfstr[ElfStrGotPlt] = addstring(shstrtab, ".got.plt");
        elfstr[ElfStrDynamic] = addstring(shstrtab, ".dynamic");
        elfstr[ElfStrDynsym] = addstring(shstrtab, ".dynsym");
        elfstr[ElfStrDynstr] = addstring(shstrtab, ".dynstr");
        elfstr[ElfStrRel] = addstring(shstrtab, ".rel");
        elfstr[ElfStrRelPlt] = addstring(shstrtab, ".rel.plt");
        elfstr[ElfStrPlt] = addstring(shstrtab, ".plt");
        elfstr[ElfStrGnuVersion] = addstring(shstrtab, ".gnu.version");
        elfstr[ElfStrGnuVersionR] = addstring(shstrtab, ".gnu.version_r");

        /* dynamic symbol table - first entry all zeros */
        s = lookup(".dynsym", 0);
        s->type = SELFROSECT;
        s->reachable = 1;
        s->size += ELF32SYMSIZE;

        /* dynamic string table */
        s = lookup(".dynstr", 0);
        s->reachable = 1;
        s->type = SELFROSECT;
        if(s->size == 0)
            addstring(s, "");
        dynstr = s;

        /* relocation table */
        s = lookup(".rel", 0);
        s->reachable = 1;
        s->type = SELFROSECT;

        /* global offset table */
        s = lookup(".got", 0);
        s->reachable = 1;
        s->type = SELFSECT; // writable

        /* hash */
        s = lookup(".hash", 0);
        s->reachable = 1;
        s->type = SELFROSECT;

        /* got.plt */
        s = lookup(".got.plt", 0);
        s->reachable = 1;
        s->type = SELFSECT; // writable

        s = lookup(".plt", 0);
        s->reachable = 1;
        s->type = SELFROSECT;

        s = lookup(".rel.plt", 0);
        s->reachable = 1;
        s->type = SELFROSECT;

        s = lookup(".gnu.version", 0);
        s->reachable = 1;
        s->type = SELFROSECT;

        s = lookup(".gnu.version_r", 0);
        s->reachable = 1;
        s->type = SELFROSECT;

        elfsetupplt();

        /* define dynamic elf table */
        s = lookup(".dynamic", 0);
        s->reachable = 1;
        s->type = SELFSECT; // writable

        /*
         * .dynamic table
         */
        elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
        elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
        elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE);
        elfwritedynentsym(s, DT_STRTAB, lookup(".dynstr", 0));
        elfwritedynentsymsize(s, DT_STRSZ, lookup(".dynstr", 0));
        elfwritedynentsym(s, DT_REL, lookup(".rel", 0));
        elfwritedynentsymsize(s, DT_RELSZ, lookup(".rel", 0));
        elfwritedynent(s, DT_RELENT, ELF32RELSIZE);
        if(rpath)
            elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath));
        elfwritedynentsym(s, DT_PLTGOT, lookup(".got.plt", 0));
        elfwritedynent(s, DT_PLTREL, DT_REL);
        elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rel.plt", 0));
        elfwritedynentsym(s, DT_JMPREL, lookup(".rel.plt", 0));

        elfwritedynent(s, DT_DEBUG, 0);

        // Do not write DT_NULL.  elfdynhash will finish it.
    }
}
Example #5
0
File: asm.c Project: machinaut/go
void
doelf(void)
{
	Sym *s, *shstrtab, *dynstr;

	if(!iself)
		return;

	/* predefine strings we need for section headers */
	shstrtab = lookup(".shstrtab", 0);
	shstrtab->type = SELFDATA;
	shstrtab->reachable = 1;

	elfstr[ElfStrEmpty] = addstring(shstrtab, "");
	elfstr[ElfStrText] = addstring(shstrtab, ".text");
	elfstr[ElfStrData] = addstring(shstrtab, ".data");
	elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
	addstring(shstrtab, ".rodata");
	addstring(shstrtab, ".gosymtab");
	addstring(shstrtab, ".gopclntab");
	if(!debug['s']) {	
		elfstr[ElfStrSymtab] = addstring(shstrtab, ".symtab");
		elfstr[ElfStrStrtab] = addstring(shstrtab, ".strtab");
	}
	elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab");

	if(!debug['d']) {	/* -d suppresses dynamic loader format */
		elfstr[ElfStrInterp] = addstring(shstrtab, ".interp");
		elfstr[ElfStrHash] = addstring(shstrtab, ".hash");
		elfstr[ElfStrGot] = addstring(shstrtab, ".got");
		elfstr[ElfStrGotPlt] = addstring(shstrtab, ".got.plt");
		elfstr[ElfStrDynamic] = addstring(shstrtab, ".dynamic");
		elfstr[ElfStrDynsym] = addstring(shstrtab, ".dynsym");
		elfstr[ElfStrDynstr] = addstring(shstrtab, ".dynstr");
		elfstr[ElfStrRel] = addstring(shstrtab, ".rel");
		elfstr[ElfStrRelPlt] = addstring(shstrtab, ".rel.plt");
		elfstr[ElfStrPlt] = addstring(shstrtab, ".plt");

		/* interpreter string */
		s = lookup(".interp", 0);
		s->reachable = 1;
		s->type = SELFDATA;	// TODO: rodata

		/* dynamic symbol table - first entry all zeros */
		s = lookup(".dynsym", 0);
		s->type = SELFDATA;
		s->reachable = 1;
		s->value += ELF32SYMSIZE;

		/* dynamic string table */
		s = lookup(".dynstr", 0);
		s->type = SELFDATA;
		s->reachable = 1;
		if(s->size == 0)
			addstring(s, "");
		dynstr = s;

		/* relocation table */
		s = lookup(".rel", 0);
		s->reachable = 1;
		s->type = SELFDATA;

		/* global offset table */
		s = lookup(".got", 0);
		s->reachable = 1;
		s->type = SELFDATA;
		
		/* hash */
		s = lookup(".hash", 0);
		s->reachable = 1;
		s->type = SELFDATA;

		/* got.plt */
		s = lookup(".got.plt", 0);
		s->reachable = 1;
		s->type = SDATA;	// writable, so not SELFDATA
		
		s = lookup(".plt", 0);
		s->reachable = 1;
		s->type = SELFDATA;

		s = lookup(".rel.plt", 0);
		s->reachable = 1;
		s->type = SELFDATA;
		
		elfsetupplt();

		/* define dynamic elf table */
		s = lookup(".dynamic", 0);
		s->reachable = 1;
		s->type = SELFDATA;

		/*
		 * .dynamic table
		 */
		elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
		elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
		elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE);
		elfwritedynentsym(s, DT_STRTAB, lookup(".dynstr", 0));
		elfwritedynentsymsize(s, DT_STRSZ, lookup(".dynstr", 0));
		elfwritedynentsym(s, DT_REL, lookup(".rel", 0));
		elfwritedynentsymsize(s, DT_RELSZ, lookup(".rel", 0));
		elfwritedynent(s, DT_RELENT, ELF32RELSIZE);
		if(rpath)
			elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath));
		elfwritedynentsym(s, DT_PLTGOT, lookup(".got.plt", 0));
		elfwritedynent(s, DT_PLTREL, DT_REL);
		elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rel.plt", 0));
		elfwritedynentsym(s, DT_JMPREL, lookup(".rel.plt", 0));
		elfwritedynent(s, DT_NULL, 0);
	}
}