diff --git a/sys/man/6/a.out b/sys/man/6/a.out index 50ceb892a..f3ffa6dbd 100644 --- a/sys/man/6/a.out +++ b/sys/man/6/a.out @@ -25,7 +25,7 @@ typedef struct Exec { long pcsz; /* size of pc/line number table */ } Exec; -#define HDR_MAGIC 0x00008000 +#define HDR_MAGIC 0x00008000 /* header expansion */ #define _MAGIC(f, b) ((f)|((((4*(b))+0)*(b))+7)) #define A_MAGIC _MAGIC(0, 8) /* 68020 */ @@ -62,7 +62,18 @@ The text segment consists of the header and the first bytes of the binary file. The .B entry -field gives the virtual address of the entry point of the program. +field gives the virtual address of the entry point of the program +unless +.B HDR_MAGIC +flag is present in the +.B magic +field. +In that case, the header is expanded +by 8 bytes containing the 64-bit virtual address of the +program entry point and the 32-bit +.B entry +field is reserved for physical kernel entry point. +.PP The data segment starts at the first page-rounded virtual address after the text segment. It consists of the next diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h index d1b81a2e6..307fe7609 100644 --- a/sys/src/9/port/portfns.h +++ b/sys/src/9/port/portfns.h @@ -10,6 +10,8 @@ Block* allocb(int); int anyhigher(void); int anyready(void); Image* attachimage(int, Chan*, uintptr, ulong); +ulong beswal(ulong); +uvlong beswav(uvlong); int blocklen(Block*); void bootlinks(void); void cachedel(Image*, uintptr); diff --git a/sys/src/9/port/rebootcmd.c b/sys/src/9/port/rebootcmd.c index 517d25a03..4f3b8fb03 100644 --- a/sys/src/9/port/rebootcmd.c +++ b/sys/src/9/port/rebootcmd.c @@ -6,16 +6,6 @@ #include "../port/error.h" #include "a.out.h" -static ulong -l2be(long l) -{ - uchar *cp; - - cp = (uchar*)&l; - return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3]; -} - - static void readn(Chan *c, void *vp, long n) { @@ -35,8 +25,11 @@ readn(Chan *c, void *vp, long n) void rebootcmd(int argc, char *argv[]) { + struct { + Exec; + uvlong hdr[1]; + } ehdr; Chan *c; - Exec exec; ulong magic, text, rtext, entry, data, size, align; uchar *p; @@ -49,11 +42,11 @@ rebootcmd(int argc, char *argv[]) nexterror(); } - readn(c, &exec, sizeof(Exec)); - magic = l2be(exec.magic); - entry = l2be(exec.entry); - text = l2be(exec.text); - data = l2be(exec.data); + readn(c, &ehdr, sizeof(Exec)); + magic = beswal(ehdr.magic); + entry = beswal(ehdr.entry); + text = beswal(ehdr.text); + data = beswal(ehdr.data); if(!(magic == AOUT_MAGIC)){ switch(magic){ @@ -66,7 +59,7 @@ rebootcmd(int argc, char *argv[]) } } if(magic & HDR_MAGIC) - readn(c, &exec, 8); + readn(c, ehdr.hdr, sizeof(ehdr.hdr)); switch(magic){ case R_MAGIC: diff --git a/sys/src/9/port/sysproc.c b/sys/src/9/port/sysproc.c index a6466e40b..6e0af5332 100644 --- a/sys/src/9/port/sysproc.c +++ b/sys/src/9/port/sysproc.c @@ -234,6 +234,8 @@ shargs(char *s, int n, char **ap) { int i; + if(n <= 2 || s[0] != '#' || s[1] != '!') + return -1; s += 2; n -= 2; /* skip #! */ for(i=0;; i++){ @@ -261,27 +263,42 @@ shargs(char *s, int n, char **ap) return i; } -static ulong -l2be(long l) +ulong +beswal(ulong l) { - uchar *cp; + uchar *p; - cp = (uchar*)&l; - return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3]; + p = (uchar*)&l; + return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3]; +} + +uvlong +beswav(uvlong v) +{ + uchar *p; + + p = (uchar*)&v; + return ((uvlong)p[0]<<56) | ((uvlong)p[1]<<48) | ((uvlong)p[2]<<40) + | ((uvlong)p[3]<<32) | ((uvlong)p[4]<<24) + | ((uvlong)p[5]<<16) | ((uvlong)p[6]<<8) + | (uvlong)p[7]; } uintptr sysexec(va_list list) { - Exec exec; - char line[sizeof(Exec)]; + struct { + Exec; + uvlong hdr[1]; + } ehdr; + char line[sizeof(ehdr)]; char *progarg[sizeof(line)/2+1]; volatile char *args, *elem, *file0; char **argv, **argp, **argp0; char *a, *e, *charp, *file; int i, n, indir; ulong magic, ssize, nargs, nbytes; - uintptr t, d, b, entry, bssend, text, data, bss, tstk, align; + uintptr t, d, b, entry, text, data, bss, bssend, tstk, align; Segment *s, *ts; Image *img; Tos *tos; @@ -311,7 +328,7 @@ sysexec(va_list list) } nexterror(); } - align = BY2PG; + align = BY2PG-1; indir = 0; file = file0; for(;;){ @@ -323,39 +340,47 @@ sysexec(va_list list) if(!indir) kstrdup(&elem, up->genbuf); - n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0); - if(n <= 2) - error(Ebadexec); - magic = l2be(exec.magic); - if(n == sizeof(Exec) && (magic == AOUT_MAGIC)){ - entry = l2be(exec.entry); - text = l2be(exec.text); - if(magic & HDR_MAGIC) - text += 8; - switch(magic){ - case S_MAGIC: /* 2MB segment alignment for amd64 */ - align = 0x200000; - break; - case V_MAGIC: /* 16K segment alignment for mips */ - align = 0x4000; - break; - case R_MAGIC: /* 64K segment alignment for arm64 */ - align = 0x10000; - break; + n = devtab[tc->type]->read(tc, &ehdr, sizeof(ehdr), 0); + if(n >= sizeof(Exec)) { + magic = beswal(ehdr.magic); + if(magic == AOUT_MAGIC) { + if(magic & HDR_MAGIC) { + if(n < sizeof(ehdr)) + error(Ebadexec); + entry = beswav(ehdr.hdr[0]); + text = UTZERO+sizeof(ehdr); + } else { + entry = beswal(ehdr.entry); + text = UTZERO+sizeof(Exec); + } + if(entry < text) + error(Ebadexec); + text += beswal(ehdr.text); + if(text <= entry || text >= (USTKTOP-USTKSIZE)) + error(Ebadexec); + + switch(magic){ + case S_MAGIC: /* 2MB segment alignment for amd64 */ + align = 0x1fffff; + break; + case V_MAGIC: /* 16K segment alignment for mips */ + align = 0x3fff; + break; + case R_MAGIC: /* 64K segment alignment for arm64 */ + align = 0xffff; + break; + } + break; /* for binary */ } - if(text >= (USTKTOP-USTKSIZE)-(UTZERO+sizeof(Exec)) - || entry < UTZERO+sizeof(Exec) - || entry >= UTZERO+sizeof(Exec)+text) - error(Ebadexec); - break; /* for binary */ } + if(indir++) + error(Ebadexec); + /* * Process #! /bin/sh args ... */ - memmove(line, &exec, n); - if(line[0]!='#' || line[1]!='!' || indir++) - error(Ebadexec); + memmove(line, &ehdr, n); n = shargs(line, n, progarg); if(n < 1) error(Ebadexec); @@ -371,10 +396,10 @@ sysexec(va_list list) cclose(tc); } - data = l2be(exec.data); - bss = l2be(exec.bss); - align--; - t = (UTZERO+sizeof(Exec)+text+align) & ~align; + t = (text+align) & ~align; + text -= UTZERO; + data = beswal(ehdr.data); + bss = beswal(ehdr.bss); align = BY2PG-1; d = (t + data + align) & ~align; bssend = t + data + bss; @@ -518,7 +543,7 @@ sysexec(va_list list) up->seg[TSEG] = ts; ts->flushme = 1; ts->fstart = 0; - ts->flen = sizeof(Exec)+text; + ts->flen = text; unlock(img); /* Data. Shared. */