/* * 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);}
/*
* 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,
};
void
elfident(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);
}
void
elfstrtab(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);
}
void
elf32phdr(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);
}
void
elf32shdr(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 void
elf32sectab(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. */
void
elf32(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
*/
void
elf64phdr(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);
}
void
elf64shdr(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 void
elf64sectab(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. */
void
elf64(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);
}