275 lines · 6.2 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * emit 32- or 64-bit elf headers for any architecture. * this is a component of ?l. */#include "l.h" enum {	/* offsets into string table */	Stitext		= 1,	Stidata		= 7,	Stistrtab	= 13,}; voidelfident(int bo, int class){	strnput("\177ELF", 4);		/* e_ident */	cput(class);	cput(bo);			/* byte order */	cput(1);			/* version = CURRENT */	if(debug['k']){			/* boot/embedded/standalone */		cput(255);		cput(0);	}	else{		cput(0);		/* osabi = SYSV */		cput(0);		/* abiversion = 3 */	}	strnput("", 7);} voidelfstrtab(void){	/* string table */	cput(0);	strnput(".text", 5);		/* +1 */	cput(0);	strnput(".data", 5);		/* +7 */	cput(0);	strnput(".strtab", 7);		/* +13 */	cput(0);	cput(0);} voidelf32phdr(void (*putl)(long), ulong type, ulong off, ulong vaddr, ulong paddr,	ulong filesz, ulong memsz, ulong prots, ulong align){	putl(type);	putl(off);	putl(vaddr);	putl(paddr);	putl(filesz);	putl(memsz);	putl(prots);	putl(align);} voidelf32shdr(void (*putl)(long), ulong name, ulong type, ulong flags, ulong vaddr,	ulong off, ulong sectsz, ulong link, ulong addnl, ulong align,	ulong entsz){	putl(name);	putl(type);	putl(flags);	putl(vaddr);	putl(off);	putl(sectsz);	putl(link);	putl(addnl);	putl(align);	putl(entsz);} static voidelf32sectab(void (*putl)(long)){	seek(cout, HEADR+textsize+datsize+symsize, 0);	elf32shdr(putl, Stitext, Progbits, Salloc|Sexec, INITTEXT,		HEADR, textsize, 0, 0, 0x10000, 0);	elf32shdr(putl, Stidata, Progbits, Salloc|Swrite, INITDAT,		HEADR+textsize, datsize, 0, 0, 0x10000, 0);	elf32shdr(putl, Stistrtab, Strtab, 1 << 5, 0,		HEADR+textsize+datsize+symsize+3*Shdr32sz, 14, 0, 0, 1, 0);	elfstrtab();} /* if addpsects > 0, putpsects must emit exactly that many psects. */voidelf32(int mach, int bo, int addpsects, void (*putpsects)(Putl)){	ulong phydata;	void (*putw)(long), (*putl)(long); 	if(bo == ELFDATA2MSB){		putw = wput;		putl = lput;	}else if(bo == ELFDATA2LSB){		putw = wputl;		putl = lputl;	}else{		print("elf32 byte order is mixed-endian\n");		errorexit();		return;	} 	elfident(bo, ELFCLASS32);	putw(EXEC);	putw(mach);	putl(1L);			/* version = CURRENT */	putl(entryvalue());		/* entry vaddr */	putl(Ehdr32sz);			/* offset to first phdr */	if(debug['S'])		putl(HEADR+textsize+datsize+symsize); /* offset to first shdr */	else		putl(0);	putl(0L);			/* flags */	putw(Ehdr32sz);	putw(Phdr32sz);	putw(3 + addpsects);		/* # of Phdrs */	putw(Shdr32sz);	if(debug['S']){		putw(3);		/* # of Shdrs */		putw(2);		/* Shdr table index */	}else{		putw(0);		putw(0);	} 	/*	 * could include ELF headers in text -- 8l doesn't,	 * but in theory it aids demand loading.	 */	elf32phdr(putl, PT_LOAD, HEADR, INITTEXT, INITTEXTP,		textsize, textsize, R|X, INITRND);	/* text */	/*	 * we need INITDATP, but it has to be computed.	 * assume distance between INITTEXT & INITTEXTP is also	 * correct for INITDAT and INITDATP.	 */	phydata = INITDAT - (INITTEXT - INITTEXTP);	elf32phdr(putl, PT_LOAD, HEADR+textsize, INITDAT, phydata,		datsize, datsize+bsssize, R|W|X, INITRND); /* data */	elf32phdr(putl, NOPTYPE, HEADR+textsize+datsize, 0, 0,		symsize, lcsize, R, 4);			/* symbol table */	if (addpsects > 0)		putpsects(putl);	cflush(); 	if(debug['S'])		elf32sectab(putl);} /* * elf64 */ voidelf64phdr(void (*putl)(long), void (*putll)(vlong), ulong type, uvlong off,	uvlong vaddr, uvlong paddr, uvlong filesz, uvlong memsz, ulong prots,	uvlong align){	putl(type);			putl(prots);			putll(off);			putll(vaddr);		putll(paddr);		putll(filesz);		putll(memsz);		putll(align);		} voidelf64shdr(void (*putl)(long), void (*putll)(vlong), ulong name, ulong type,	uvlong flags, uvlong vaddr, uvlong off, uvlong sectsz, ulong link,	ulong addnl, uvlong align, uvlong entsz){	putl(name);	putl(type);	putll(flags);	putll(vaddr);	putll(off);	putll(sectsz);	putl(link);	putl(addnl);	putll(align);	putll(entsz);} static voidelf64sectab(void (*putl)(long), void (*putll)(vlong)){	seek(cout, HEADR+textsize+datsize+symsize, 0);	elf64shdr(putl, putll, Stitext, Progbits, Salloc|Sexec, INITTEXT,		HEADR, textsize, 0, 0, 0x10000, 0);	elf64shdr(putl, putll, Stidata, Progbits, Salloc|Swrite, INITDAT,		HEADR+textsize, datsize, 0, 0, 0x10000, 0);	elf64shdr(putl, putll, Stistrtab, Strtab, 1 << 5, 0,		HEADR+textsize+datsize+symsize+3*Shdr64sz, 14, 0, 0, 1, 0);	elfstrtab();} /* if addpsects > 0, putpsects must emit exactly that many psects. */voidelf64(int mach, int bo, int addpsects, void (*putpsects)(Putl)){	uvlong phydata;	void (*putw)(long), (*putl)(long);	void (*putll)(vlong); 	if(bo == ELFDATA2MSB){		putw = wput;		putl = lput;		putll = llput;	}else if(bo == ELFDATA2LSB){		putw = wputl;		putl = lputl;		putll = llputl;	}else{		print("elf64 byte order is mixed-endian\n");		errorexit();		return;	} 	elfident(bo, ELFCLASS64);	putw(EXEC);	putw(mach);	putl(1L);			/* version = CURRENT */	putll(entryvalue());		/* entry vaddr */	putll(Ehdr64sz);		/* offset to first phdr */	if(debug['S'])		putll(HEADR+textsize+datsize+symsize); /* offset to 1st shdr */	else		putll(0);	putl(0L);			/* flags */	putw(Ehdr64sz);	putw(Phdr64sz);	putw(3 + addpsects);		/* # of Phdrs */	putw(Shdr64sz);	if(debug['S']){		putw(3);		/* # of Shdrs */		putw(2);		/* Shdr table index */	}else{		putw(0);		putw(0);	} 	elf64phdr(putl, putll, PT_LOAD, HEADR, INITTEXT, INITTEXTP,		textsize, textsize, R|X, INITRND);	/* text */	/*	 * see 32-bit ELF case for physical data address computation.	 */	phydata = INITDAT - (INITTEXT - INITTEXTP);	elf64phdr(putl, putll, PT_LOAD, HEADR+textsize, INITDAT, phydata,		datsize, datsize+bsssize, R|W, INITRND); /* data */	elf64phdr(putl, putll, NOPTYPE, HEADR+textsize+datsize, 0, 0,		symsize, lcsize, R, 4);			/* symbol table */	if (addpsects > 0)		putpsects(putl);	cflush(); 	if(debug['S'])		elf64sectab(putl, putll);}