diff options
author | mischief <mischief@offblast.org> | 2014-06-24 18:02:25 -0700 |
---|---|---|
committer | mischief <mischief@offblast.org> | 2014-06-24 18:02:25 -0700 |
commit | 5ba95fdb07ddc2c32111a1b2f57f17aa27fcbbf5 (patch) | |
tree | c1ec54cb9ecff85b0b820a26d26a10a32a118d0c /sys/src/9/xen/xenelf.c | |
parent | fa03455b5057675b18d1c87aef2d1071b2088de0 (diff) |
import xen 32 bit paravirtual kernel from /n/sources/xen.
Diffstat (limited to 'sys/src/9/xen/xenelf.c')
-rw-r--r-- | sys/src/9/xen/xenelf.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/sys/src/9/xen/xenelf.c b/sys/src/9/xen/xenelf.c new file mode 100644 index 000000000..130d4b201 --- /dev/null +++ b/sys/src/9/xen/xenelf.c @@ -0,0 +1,157 @@ +#include <u.h> +#include <libc.h> +#include "/sys/src/libmach/elf.h" + +enum { + Page = 4096, +}; + +#define ROUND(n) ((n+Page-1)&~(Page-1)) + +Shdr isect, csect; + +static ushort +GETS(void *a) +{ + uchar *p = a; + return p[0] | p[1]<<8; +} + +static ulong +GETL(void *a) +{ + uchar *p = a; + return p[0] | p[1]<<8 | p[2]<<16 | p[3]<<24; +} + +static void +PUTS(void *a, ushort v) +{ + uchar *p = a; + p[0] = v; + p[1] = v>>8; +} + +static void +PUTL(void *a, ulong v) +{ + uchar *p = a; + p[0] = v; + p[1] = v>>8; + p[2] = v>>16; + p[3] = v>>24; +} + +void +copy(int fin, int fout, ulong src, ulong dst, ulong size) +{ + char buf[Page]; + int n; + + seek(fin, src, 0); + seek(fout, dst, 0); + n = Page; + while (size > 0) { + if (n > size) + n = size; + read(fin, buf, n); + write(fout, buf, n); + size -= n; + } +} + +void +main(int argc, char **argv) +{ + Ehdr e; + Shdr s; + Phdr p; + int efd, ofd, ns, i, n; + ulong shoff, off, noff, size, msize; + char *sname, *sval; + + if (argc != 5) + sysfatal("Usage: xenelf input-elf-file output-elf-file section-name section-contents"); + efd = open(argv[1], OREAD); + if (efd < 0) + sysfatal("%s: %r", argv[1]); + ofd = create(argv[2], OWRITE, 0666); + if (ofd < 0) + sysfatal("%s: %r", argv[2]); + sname = argv[3]; + sval = argv[4]; + + read(efd, &e, sizeof e); + //if (e.shstrndx) + // sysfatal("section header string index already present"); + + /* page-align loadable segments in file */ + ns = GETS(&e.phnum); + shoff = GETL(&e.phoff); + noff = shoff+ns*sizeof(Phdr); + noff = ROUND(noff); + for (i = 0; i < ns; i++) { + seek(efd, shoff+i*sizeof(Phdr), 0); + read(efd, &p, sizeof p); + off = GETL(&p.offset); + PUTL(&p.offset, noff); + size = GETL(&p.filesz); + copy(efd, ofd, off, noff, size); + if (GETL(&p.type) == LOAD) { + size = ROUND(size); + PUTL(&p.filesz, size); + if ((msize = GETL(&p.memsz)) != 0 && size > msize) + PUTL(&p.memsz, size); + } else { + /* memory size for symtab segment is actually line number table size */ + msize = GETL(&p.memsz); + copy(efd, ofd, off+size, noff+size, msize); + noff += msize; + } + noff += size; + seek(ofd, shoff+i*sizeof(Phdr), 0); + write(ofd, &p, sizeof p); + } + + /* append single-entry shstrndx */ + PUTL(&isect.offset, seek(ofd, noff, 0)); + n = strlen(sname); + PUTL(&isect.size, n+2); + write(ofd, sname+n, 1); + write(ofd, sname, n+1); + + /* append comment section contents */ + PUTL(&csect.name, 1); + PUTL(&csect.offset, seek(ofd, 0, 2)); + n = strlen(sval); + PUTL(&csect.size, n+1); + write(ofd, sval, n+1); + + /* copy existing section headers to end */ + ns = 0; //GETS(&e.shnum); + shoff = GETL(&e.shoff); + PUTL(&e.shoff, seek(ofd, 0, 2)); + for (i = 0; i < ns; i++) { + seek(efd, shoff+i*sizeof(Shdr), 0); + read(efd, &s, sizeof s); + seek(ofd, 0, 2); + write(ofd, &s, sizeof s); + } + + /* append section header for comment section */ + write(ofd, &csect, sizeof csect); + ++ns; + + /* append section header for shstrndx */ + PUTS(&e.shstrndx, ns); + ++ns; + write(ofd, &isect, sizeof isect); + + /* rewrite elf header */ + PUTS(&e.shentsize, sizeof(Shdr)); + PUTS(&e.shnum, ns); + seek(ofd, 0, 0); + write(ofd, &e, sizeof e); + + exits(0); +} |