summaryrefslogtreecommitdiff
path: root/sys/src/9/xen/xenelf.c
diff options
context:
space:
mode:
authormischief <mischief@offblast.org>2014-06-24 18:02:25 -0700
committermischief <mischief@offblast.org>2014-06-24 18:02:25 -0700
commit5ba95fdb07ddc2c32111a1b2f57f17aa27fcbbf5 (patch)
treec1ec54cb9ecff85b0b820a26d26a10a32a118d0c /sys/src/9/xen/xenelf.c
parentfa03455b5057675b18d1c87aef2d1071b2088de0 (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.c157
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);
+}