--- /sys/man/1/8c Thu Sep 27 01:05:45 2012 +++ /sys/man/1/8c Fri Mar 8 21:14:03 2013 @@ -109,6 +109,11 @@ .B -w Print warning messages about unused variables, etc. .TP +.B -W +Print all the messages that +.B -w +would print as warnings, but make them errors. +.TP .B -B Accept functions without a new-style ANSI C function prototype. --- /sys/man/1/8l Sat Feb 23 00:23:43 2013 +++ /sys/man/1/8l Fri Mar 8 21:12:36 2013 @@ -35,6 +35,11 @@ .BR 386 , etc. as listed in .IR 8c (1). +If the environment variable +.B ccroot +is defined, the library is sought in +.BR $ccroot/$objtype/lib +instead. The libraries must have tables of contents (see .IR ar (1)). @@ -201,6 +206,17 @@ (if .I r is nonzero). +.TP +.BI -L dir +For a library reference +.BI -l ext, +search +.I dir +before looking in the standard library directory. +If more than one +.B -L +option is given, +directories will be searched in order of appearance. .PP The numbers in the above options can begin with .L 0x --- /sys/man/1/pcc Fri Jan 25 00:41:29 2013 +++ /sys/man/1/pcc Fri Mar 8 21:14:03 2013 @@ -59,6 +59,11 @@ .B -w Print compiler warning messages. .TP +.B -W +Print all the messages that +.B -w +would print as warnings, but make them errors. +.TP .BI -l lib Include .BI / $objtype /lib/ape/lib lib .a @@ -77,6 +82,10 @@ .B -v Echo the preprocessing, compiling, and loading commands before they are executed. +.TP +.BI -x " file" +Produce an export file in the executable, as described in +.IR 8l (1). .TP .BI -D name=def .br --- /sys/man/2/mach Thu Sep 27 01:05:28 2012 +++ /sys/man/2/mach Fri Mar 8 21:26:28 2013 @@ -1,7 +1,7 @@ .TH MACH 2 .SH NAME crackhdr, machbytype, machbyname, newmap, setmap, findseg, unusemap, -loadmap, attachproc, get1, get2, get4, get8, geta, put1, put2, put4, put8, puta +loadmap, attachproc, get1, get2, get4, get8, geta, put1, put2, put4, put8, puta, beswab, beswal, beswav, leswab, leswal, leswav \- machine-independent access to executable files .SH SYNOPSIS .B #include --- /sys/man/8/9boot Mon Feb 25 02:56:36 2013 +++ /sys/man/8/9boot Fri Mar 8 21:47:35 2013 @@ -188,7 +188,7 @@ may be a Plan 9 boot image compressed with .IR gzip (1). In all cases, -the uncompressed kernel must be in Plan 9 boot image or ELF format. +the uncompressed kernel must be in Plan 9 boot image, ELF or ELF64 format. If the .B plan9.ini file contains multiple --- /sys/src/9/pc/sdiahci.c Tue Nov 6 01:37:29 2012 +++ /sys/src/9/pc/sdiahci.c Thu Mar 7 23:13:50 2013 @@ -271,11 +271,11 @@ } static void -aesleep(Aportm *m, Asleep *a, int ms) +aesleep(Aportm *pm, Asleep *a, int ms) { if(waserror()) return; - tsleep(m, ahciclear, a, ms); + tsleep(pm, ahciclear, a, ms); poperror(); } @@ -511,15 +511,15 @@ { int i, sig; vlong s; - Aportm *m; + Aportm *pm; - m = pc->m; - m->feat = 0; - m->smart = 0; + pm = pc->m; + pm->feat = 0; + pm->smart = 0; i = 0; sig = pc->p->sig >> 16; if(sig == 0xeb14){ - m->feat |= Datapi; + pm->feat |= Datapi; i = 1; } if(ahciidentify0(pc, id, i) == -1) @@ -527,26 +527,26 @@ i = gbit16(id+83) | gbit16(id+86); if(i & (1<<10)){ - m->feat |= Dllba; + pm->feat |= Dllba; s = gbit64(id+100); }else s = gbit32(id+60); - if(m->feat&Datapi){ + if(pm->feat&Datapi){ i = gbit16(id+0); if(i&1) - m->feat |= Datapi16; + pm->feat |= Datapi16; } i = gbit16(id+83); if((i>>14) == 1) { if(i & (1<<3)) - m->feat |= Dpower; + pm->feat |= Dpower; i = gbit16(id+82); if(i & 1) - m->feat |= Dsmart; + pm->feat |= Dsmart; if(i & (1<<14)) - m->feat |= Dnop; + pm->feat |= Dnop; } return s; } @@ -723,15 +723,15 @@ char *name; Ahba *h; Aport *p; - Aportm *m; + Aportm *pm; h = d->ctlr->hba; p = d->portc.p; - m = d->portc.m; - if(m->list == 0){ - setupfis(&m->fis); - m->list = malign(sizeof *m->list, 1024); - m->ctab = malign(sizeof *m->ctab, 128); + pm = d->portc.m; + if(pm->list == 0){ + setupfis(&pm->fis); + pm->list = malign(sizeof *pm->list, 1024); + pm->ctab = malign(sizeof *pm->ctab, 128); } if (d->unit) @@ -748,9 +748,9 @@ p->serror = SerrAll; - p->list = PCIWADDR(m->list); + p->list = PCIWADDR(pm->list); p->listhi = 0; - p->fis = PCIWADDR(m->fis.base); + p->fis = PCIWADDR(pm->fis.base); p->fishi = 0; p->cmd |= Afre|Ast; @@ -1073,10 +1073,10 @@ { char *name; Aportc *c; - Aportm *m; + Aportm *pm; c = &d->portc; - m = &d->portm; + pm = &d->portm; name = d->unit->name; if(name == 0) @@ -1093,8 +1093,8 @@ dprint("%s: identify failure\n", name); goto lose; } - if(m->feat & Dpower && setfeatures(c, 0x85) == -1){ - m->feat &= ~Dpower; + if(pm->feat & Dpower && setfeatures(c, 0x85) == -1){ + pm->feat &= ~Dpower; if(ahcirecover(c) == -1) goto lose; } @@ -1104,7 +1104,7 @@ qunlock(c->m); idprint("%s: %sLBA %,llud sectors: %s %s %s %s\n", d->unit->name, - (m->feat & Dllba? "L": ""), d->sectors, d->model, d->firmware, + (pm->feat & Dllba? "L": ""), d->sectors, d->model, d->firmware, d->serial, d->mediachange? "[mediachange]": ""); return 0; @@ -1322,7 +1322,7 @@ iainterrupt(Ureg*, void *a) { int i; - ulong cause, m; + ulong cause, mask; Ctlr *c; Drive *d; @@ -1336,18 +1336,18 @@ return; } for(i = 0; cause && i <= c->mport; i++){ - m = 1 << i; - if((cause & m) == 0) + mask = 1 << i; + if((cause & mask) == 0) continue; d = c->rawdrive + i; ilock(d); isdrivejabbering(d); - if(d->port->isr && c->hba->pi & m) + if(d->port->isr && c->hba->pi & mask) updatedrive(d); - c->hba->isr = m; + c->hba->isr = mask; iunlock(d); - cause &= ~m; + cause &= ~mask; } if (cause) { isctlrjabbering(c, cause); @@ -1514,17 +1514,17 @@ uchar *c, acmd, dir, llba; Alist *l; Actab *t; - Aportm *m; + Aportm *pm; Aprdt *p; static uchar tab[2][2] = { 0xc8, 0x25, 0xca, 0x35, }; - m = &d->portm; + pm = &d->portm; dir = *cmd != 0x28; - llba = m->feat&Dllba? 1: 0; + llba = pm->feat&Dllba? 1: 0; acmd = tab[dir][llba]; - qlock(m); - l = m->list; - t = m->ctab; + qlock(pm); + l = pm->list; + t = pm->ctab; c = t->cfis; c[0] = 0x27; @@ -1569,7 +1569,7 @@ } static Alist* -ahcibuildpkt(Aportm *m, SDreq *r, void *data, int n) +ahcibuildpkt(Aportm *pm, SDreq *r, void *data, int n) { int fill, len; uchar *c; @@ -1577,12 +1577,12 @@ Actab *t; Aprdt *p; - qlock(m); - l = m->list; - t = m->ctab; + qlock(pm); + l = pm->list; + t = pm->ctab; c = t->cfis; - fill = m->feat&Datapi16? 16: 12; + fill = pm->feat&Datapi16? 16: 12; if((len = r->clen) > fill) len = fill; memmove(t->atapi, r->cmd, len); --- /sys/src/9/pcboot/bootld.c Wed May 16 20:57:11 2012 +++ /sys/src/9/pcboot/bootld.c Fri Mar 8 21:47:21 2013 @@ -18,22 +18,27 @@ #undef KADDR #undef PADDR -// #define PADDR(a) (paddr)((void *)(a)) #define KADDR(a) ((void*)((ulong)(a) | KZERO)) #define PADDR(a) ((ulong)(a) & ~KSEGM) extern int debug; + extern void pagingoff(ulong); -static uchar elfident[7] = { - '\177', 'E', 'L', 'F', '\1', '\1', '\1' +static uchar elfident[] = { + '\177', 'E', 'L', 'F', }; static Ehdr ehdr, rehdr; +static E64hdr e64hdr; static Phdr *phdr; +static P64hdr *p64hdr; + static int curphdr; static ulong curoff; static ulong elftotal; + +static uvlong (*swav)(uvlong); static long (*swal)(long); static ushort (*swab)(ushort); @@ -101,6 +106,21 @@ } /* + * little-endian vlong + */ +uvlong +leswav(uvlong v) +{ + uchar *p; + + p = (uchar*)&v; + return ((uvlong)p[7]<<56) | ((uvlong)p[6]<<48) | ((uvlong)p[5]<<40) + | ((uvlong)p[4]<<32) | ((uvlong)p[3]<<24) + | ((uvlong)p[2]<<16) | ((uvlong)p[1]<<8) + | (uvlong)p[0]; +} + +/* * Convert header to canonical form */ static void @@ -112,6 +132,15 @@ } } +static void +hswav(uvlong *lp, int n, uvlong (*swap)(uvlong)) +{ + while (n--) { + *lp = (*swap)(*lp); + lp++; + } +} + static int readehdr(Boot *b) { @@ -132,7 +161,7 @@ print("bad ELF encoding - not big or little endian\n"); return 0; } - memmove(&rehdr, &ehdr, sizeof(Ehdr)); + memmove(&rehdr, &ehdr, sizeof(Ehdr)); /* copy; never used */ ehdr.type = swab(ehdr.type); ehdr.machine = swab(ehdr.machine); @@ -161,6 +190,7 @@ b->bp = (char*)smalloc(i); b->wp = b->bp; b->ep = b->wp + i; + elftotal = 0; phdr = (Phdr*)(b->bp + ehdr.phoff-sizeof(Ehdr)); if(debug) print("phdr..."); @@ -169,10 +199,69 @@ } static int +reade64hdr(Boot *b) +{ + int i; + + /* bitswap the header according to the DATA format */ + if(e64hdr.ident[CLASS] != ELFCLASS64) { + print("bad ELF class - not 64 bit\n"); + return 0; + } + if(e64hdr.ident[DATA] == ELFDATA2LSB) { + swab = leswab; + swal = leswal; + swav = leswav; + } else if(e64hdr.ident[DATA] == ELFDATA2MSB) { + swab = beswab; + swal = beswal; + swav = beswav; + } else { + print("bad ELF encoding - not big or little endian\n"); + return 0; + } +// memmove(&rehdr, &ehdr, sizeof(Ehdr)); /* copy; never used */ + + e64hdr.type = swab(e64hdr.type); + e64hdr.machine = swab(e64hdr.machine); + e64hdr.version = swal(e64hdr.version); + e64hdr.elfentry = swav(e64hdr.elfentry); + e64hdr.phoff = swav(e64hdr.phoff); + e64hdr.shoff = swav(e64hdr.shoff); + e64hdr.flags = swal(e64hdr.flags); + e64hdr.ehsize = swab(e64hdr.ehsize); + e64hdr.phentsize = swab(e64hdr.phentsize); + e64hdr.phnum = swab(e64hdr.phnum); + e64hdr.shentsize = swab(e64hdr.shentsize); + e64hdr.shnum = swab(e64hdr.shnum); + e64hdr.shstrndx = swab(e64hdr.shstrndx); + if(e64hdr.type != EXEC || e64hdr.version != CURRENT) + return 0; + if(e64hdr.phentsize != sizeof(P64hdr)) + return 0; + + if(debug) + print("reade64hdr OK entry %#llux\n", e64hdr.elfentry); + + curoff = sizeof(E64hdr); + i = e64hdr.phoff + e64hdr.phentsize*e64hdr.phnum - curoff; + b->state = READ64PHDR; + b->bp = (char*)smalloc(i); + b->wp = b->bp; + b->ep = b->wp + i; + elftotal = 0; + p64hdr = (P64hdr*)(b->bp + e64hdr.phoff-sizeof(E64hdr)); + if(debug) + print("p64hdr..."); + + return 1; +} + +static int nextphdr(Boot *b) { Phdr *php; - ulong entry, offset; + ulong offset; char *physaddr; if(debug) @@ -217,8 +306,64 @@ if(curphdr != 0){ print("=%lud\n", elftotal); b->state = TRYEBOOT; - entry = ehdr.elfentry & ~KSEGM; - PLLONG(b->hdr.entry, entry); + b->entry = ehdr.elfentry; + // PLLONG(b->hdr.entry, b->entry); + return 1; + } + + return 0; +} + +static int +nextp64hdr(Boot *b) +{ + P64hdr *php; + uvlong offset; + char *physaddr; + + if(debug) + print("reade64data %d\n", curphdr); + + for(; curphdr < e64hdr.phnum; curphdr++){ + php = p64hdr+curphdr; + if(php->type != LOAD) + continue; + offset = php->offset; + physaddr = (char*)KADDR(PADDR(php->paddr)); + if(offset < curoff){ + /* + * Can't (be bothered to) rewind the + * input, it might be from tftp. If we + * did then we could boot FreeBSD kernels + * too maybe. + */ + return 0; + } + if(php->offset > curoff){ + b->state = READE64PAD; + b->bp = (char*)smalloc(offset - curoff); + b->wp = b->bp; + b->ep = b->wp + offset - curoff; + if(debug) + print("nextp64hdr %llud...\n", offset - curoff); + return 1; + } + b->state = READE64DATA; + b->bp = physaddr; + b->wp = b->bp; + b->ep = b->wp+php->filesz; + print("%llud+", php->filesz); + elftotal += php->filesz; + if(debug) + print("nextp64hdr %llud@%#p\n", php->filesz, physaddr); + + return 1; + } + + if(curphdr != 0){ + print("=%lud\n", elftotal); + b->state = TRYE64BOOT; + b->entry = e64hdr.elfentry; return 1; } @@ -239,6 +384,19 @@ } static int +reade64pad(Boot *b) +{ + P64hdr *php; + + php = p64hdr+curphdr; + if(debug) + print("reade64pad %d\n", curphdr); + curoff = php->offset; + + return nextp64hdr(b); +} + +static int readedata(Boot *b) { Phdr *php; @@ -259,6 +417,26 @@ } static int +reade64data(Boot *b) +{ + P64hdr *php; + + php = p64hdr+curphdr; + if(debug) + print("reade64data %d\n", curphdr); + if(php->filesz < php->memsz){ + print("%llud", php->memsz - php->filesz); + elftotal += php->memsz - php->filesz; + memset((char*)KADDR(PADDR(php->paddr) + php->filesz), 0, + php->memsz - php->filesz); + } + curoff = php->offset + php->filesz; + curphdr++; + + return nextp64hdr(b); +} + +static int readphdr(Boot *b) { Phdr *php; @@ -276,17 +454,38 @@ } static int +readp64hdr(Boot *b) +{ + int hdr; + P64hdr *php, *p; + + php = p = p64hdr; + for (hdr = 0; hdr < e64hdr.phnum; hdr++, p++) { + hswal((long*)p, 2, swal); + hswav((uvlong*)&p->offset, 6, swav); + } + if(debug) + print("p64hdr curoff %lud vaddr %#llux paddr %#llux\n", + curoff, php->vaddr, php->paddr); + + curoff = e64hdr.phoff + e64hdr.phentsize*e64hdr.phnum; + curphdr = 0; + + return nextp64hdr(b); +} + +static int addbytes(char **dbuf, char *edbuf, char **sbuf, char *esbuf) { int n; n = edbuf - *dbuf; if(n <= 0) - return 0; + return 0; /* dest buffer is full */ if(n > esbuf - *sbuf) n = esbuf - *sbuf; if(n <= 0) - return -1; + return -1; /* src buffer is empty */ memmove(*dbuf, *sbuf, n); *sbuf += n; @@ -338,13 +537,156 @@ pagingoff(PADDR(entry)); } +static int +bootfail(Boot *b) +{ + b->state = FAILED; + return FAIL; +} + +static int +isgzipped(uchar *p) +{ + return p[0] == 0x1F && p[1] == 0x8B && p[2] == 0x08; +} + +static int +readexec(Boot *b) +{ + Exechdr *hdr; + ulong pentry, text, data, magic; + + hdr = &b->hdr; + magic = GLLONG(hdr->magic); + if(magic == I_MAGIC || magic == S_MAGIC) { + pentry = PADDR(GLLONG(hdr->entry)); + text = GLLONG(hdr->text); + data = GLLONG(hdr->data); + if (pentry < MB) + panic("kernel entry %#p below 1 MB", pentry); + if (PGROUND(pentry + text) + data > MB + Kernelmax) + panic("kernel larger than %d bytes", Kernelmax); + b->state = READ9TEXT; + b->bp = (char*)KADDR(pentry); + b->wp = b->bp; + b->ep = b->wp+text; + + if(magic == I_MAGIC){ + memmove(b->bp, b->hdr.uvl, sizeof(b->hdr.uvl)); + b->wp += sizeof(b->hdr.uvl); + } + + print("%lud", text); + } else if(memcmp(b->bp, elfident, 4) == 0 && + (uchar)b->bp[4] == ELFCLASS32){ + b->state = READEHDR; + b->bp = (char*)&ehdr; + b->wp = b->bp; + b->ep = b->wp + sizeof(Ehdr); + memmove(b->bp, &b->hdr, sizeof(Exechdr)); + b->wp += sizeof(Exechdr); + print("elf..."); + } else if(memcmp(b->bp, elfident, 4) == 0 && + (uchar)b->bp[4] == ELFCLASS64){ + b->state = READE64HDR; + b->bp = (char*)&e64hdr; + b->wp = b->bp; + b->ep = b->wp + sizeof(E64hdr); + memmove(b->bp, &b->hdr, sizeof(Exechdr)); + b->wp += sizeof(Exechdr); + print("elf64..."); + } else if(isgzipped((uchar *)b->bp)) { + b->state = READGZIP; + /* could use Unzipbuf instead of smalloc() */ + b->bp = (char*)smalloc(Kernelmax); + b->wp = b->bp; + b->ep = b->wp + Kernelmax; + memmove(b->bp, &b->hdr, sizeof(Exechdr)); + b->wp += sizeof(Exechdr); + print("gz..."); + } else { + print("bad kernel format (magic %#lux)\n", magic); + return bootfail(b); + } + return MORE; +} + +static void +boot9(Boot *b, ulong magic, ulong entry) +{ + if(magic == I_MAGIC){ + print("entry: %#lux\n", entry); + warp9(PADDR(entry)); + } + else if(magic == S_MAGIC) + warp64(beswav(b->hdr.uvl[0])); + else + print("bad magic %#lux\n", magic); +} + +/* only returns upon failure */ +static void +readgzip(Boot *b) +{ + ulong entry, text, data, bss, magic, all, pentry; + uchar *sdata; + Exechdr *hdr; + + /* the whole gzipped kernel is now at b->bp */ + hdr = &b->hdr; + if(!isgzipped((uchar *)b->bp)) { + print("lost magic\n"); + return; + } + print("%ld => ", b->wp - b->bp); + /* just fill hdr from gzipped b->bp, to get various sizes */ + if(gunzip((uchar*)hdr, sizeof *hdr, (uchar*)b->bp, b->wp - b->bp) + < sizeof *hdr) { + print("error uncompressing kernel exec header\n"); + return; + } + + /* assume uncompressed kernel is a plan 9 boot image */ + magic = GLLONG(hdr->magic); + entry = GLLONG(hdr->entry); + text = GLLONG(hdr->text); + data = GLLONG(hdr->data); + bss = GLLONG(hdr->bss); + print("%lud+%lud+%lud=%lud\n", text, data, bss, text+data+bss); + + pentry = PADDR(entry); + if (pentry < MB) + panic("kernel entry %#p below 1 MB", pentry); + if (PGROUND(pentry + text) + data > MB + Kernelmax) + panic("kernel larger than %d bytes", Kernelmax); + + /* fill entry from gzipped b->bp */ + all = sizeof(Exec) + text + data; + if(gunzip((uchar *)KADDR(PADDR(entry)) - sizeof(Exec), all, + (uchar*)b->bp, b->wp - b->bp) < all) { + print("error uncompressing kernel\n"); + return; + } + + /* relocate data to start at page boundary */ + sdata = KADDR(PADDR(entry+text)); + memmove((void*)PGROUND((uintptr)sdata), sdata, data); + + boot9(b, magic, entry); +} + +/* + * if nbuf is zero, boot. + * else add nbuf bytes from vbuf to b->wp (if there is room) + * and advance the state machine, which may reset b's pointers + * and return to the top. + */ int bootpass(Boot *b, void *vbuf, int nbuf) { char *buf, *ebuf; - uchar *sdata; Exechdr *hdr; - ulong entry, pentry, text, data, bss, magic; + ulong entry, bss; uvlong entry64; if(b->state == FAILED) @@ -355,7 +697,9 @@ buf = vbuf; ebuf = buf+nbuf; + /* possibly copy into b->wp from buf (not first time) */ while(addbytes(&b->wp, b->ep, &buf, ebuf) == 0) { + /* b->bp is full, so advance the state machine */ switch(b->state) { case INITKERNEL: b->state = READEXEC; @@ -364,54 +708,7 @@ b->ep = b->bp+sizeof(Exechdr); break; case READEXEC: - hdr = &b->hdr; - magic = GLLONG(hdr->magic); - if(magic == I_MAGIC || magic == S_MAGIC) { - pentry = PADDR(GLLONG(hdr->entry)); - text = GLLONG(hdr->text); - data = GLLONG(hdr->data); - if (pentry < MB) - panic("kernel entry %#p below 1 MB", - pentry); - if (PGROUND(pentry + text) + data > - MB + Kernelmax) - panic("kernel larger than %d bytes", - Kernelmax); - b->state = READ9TEXT; - b->bp = (char*)KADDR(pentry); - b->wp = b->bp; - b->ep = b->wp+text; - - if(magic == I_MAGIC){ - memmove(b->bp, b->hdr.uvl, sizeof(b->hdr.uvl)); - b->wp += sizeof(b->hdr.uvl); - } - - print("%lud", text); - } else if(memcmp(b->bp, elfident, 4) == 0){ - b->state = READEHDR; - b->bp = (char*)&ehdr; - b->wp = b->bp; - b->ep = b->wp + sizeof(Ehdr); - memmove(b->bp, &b->hdr, sizeof(Exechdr)); - b->wp += sizeof(Exechdr); - print("elf..."); - } else if(b->bp[0] == 0x1F && (uchar)b->bp[1] == 0x8B && - b->bp[2] == 0x08) { - b->state = READGZIP; - /* could use Unzipbuf instead of smalloc() */ - b->bp = (char*)smalloc(Kernelmax); - b->wp = b->bp; - b->ep = b->wp + Kernelmax; - memmove(b->bp, &b->hdr, sizeof(Exechdr)); - b->wp += sizeof(Exechdr); - print("gz..."); - } else { - print("bad kernel format (magic %#lux)\n", - magic); - b->state = FAILED; - return FAIL; - } + readexec(b); break; case READ9TEXT: @@ -434,39 +731,47 @@ b->state = TRYBOOT; return ENOUGH; + /* + * elf + */ case READEHDR: - if(!readehdr(b)){ + if(!readehdr(b)) print("readehdr failed\n"); - b->state = FAILED; - return FAIL; - } break; - case READPHDR: - if(!readphdr(b)){ - b->state = FAILED; - return FAIL; - } + readphdr(b); break; - case READEPAD: - if(!readepad(b)){ - b->state = FAILED; - return FAIL; - } + readepad(b); break; - case READEDATA: - if(!readedata(b)){ - b->state = FAILED; - return FAIL; - } - if(b->state == TRYBOOT) + readedata(b); + if(b->state == TRYEBOOT) + return ENOUGH; + break; + + /* + * elf64 + */ + case READE64HDR: + if(!reade64hdr(b)) + print("reade64hdr failed\n"); + break; + case READ64PHDR: + readp64hdr(b); + break; + case READE64PAD: + reade64pad(b); + break; + case READE64DATA: + reade64data(b); + if(b->state == TRYE64BOOT) return ENOUGH; break; case TRYBOOT: case TRYEBOOT: + case TRYE64BOOT: case READGZIP: return ENOUGH; @@ -477,10 +782,11 @@ default: panic("bootstate"); } + if(b->state == FAILED) + return FAIL; } return MORE; - Endofinput: /* end of input */ switch(b->state) { @@ -492,80 +798,45 @@ case READPHDR: case READEPAD: case READEDATA: + case READE64HDR: + case READ64PHDR: + case READE64PAD: + case READE64DATA: print("premature EOF\n"); - b->state = FAILED; - return FAIL; + break; case TRYBOOT: - entry = GLLONG(b->hdr.entry); - magic = GLLONG(b->hdr.magic); - if(magic == I_MAGIC){ - print("entry: %#lux\n", entry); - warp9(PADDR(entry)); - } - else if(magic == S_MAGIC){ - entry64 = beswav(b->hdr.uvl[0]); - warp64(entry64); - } - b->state = FAILED; - return FAIL; + boot9(b, GLLONG(b->hdr.magic), GLLONG(b->hdr.entry)); + break; case TRYEBOOT: - entry = GLLONG(b->hdr.entry); + entry = b->entry; if(ehdr.machine == I386){ print("entry: %#lux\n", entry); warp9(PADDR(entry)); } - else if(ehdr.machine == AMD64){ - print("entry: %#lux\n", entry); + else if(ehdr.machine == AMD64) warp64(entry); - } - b->state = FAILED; - return FAIL; - - case READGZIP: - /* apparently the whole gzipped kernel is now at b->bp */ - hdr = &b->hdr; - if(b->bp[0] != 0x1F || (uchar)b->bp[1] != 0x8B || b->bp[2] != 0x08) - print("lost magic\n"); - - print("%ld => ", b->wp - b->bp); - /* fill hdr from gzipped b->bp to get various sizes */ - if(gunzip((uchar*)hdr, sizeof *hdr, (uchar*)b->bp, b->wp - b->bp) - < sizeof *hdr) { - print("badly compressed kernel\n"); - return FAIL; - } - - magic = GLLONG(hdr->magic); - entry = GLLONG(hdr->entry); - text = GLLONG(hdr->text); - data = GLLONG(hdr->data); - bss = GLLONG(hdr->bss); - print("%lud+%lud+%lud=%lud\n", text, data, bss, text+data+bss); - - /* fill entry from gzipped b->bp */ - if(gunzip((uchar *)KADDR(PADDR(entry)) - sizeof(Exec), - sizeof(Exec)+text+data, - (uchar*)b->bp, b->wp-b->bp) < sizeof(Exec)+text+data) { - print("error uncompressing kernel\n"); - return FAIL; + else + panic("elf boot: ehdr.machine %d unknown", ehdr.machine); + break; + + case TRYE64BOOT: + entry64 = b->entry; + if(e64hdr.machine == I386){ + print("entry: %#llux\n", entry64); + warp9(PADDR(entry64)); } - /* relocate data to start at page boundary */ - sdata = KADDR(PADDR(entry+text)); - memmove((void*)PGROUND((uintptr)sdata), sdata, data); - - if(magic == I_MAGIC){ - print("entry: %#lux\n", entry); - warp9(PADDR(entry)); - } - else if(magic == S_MAGIC){ - entry64 = beswav(hdr->uvl[0]); + else if(e64hdr.machine == AMD64) warp64(entry64); - } else - print("bad magic %#lux\n", magic); - b->state = FAILED; - return FAIL; + else + panic("elf64 boot: e64hdr.machine %d unknown", + e64hdr.machine); + break; + + case READGZIP: + readgzip(b); + break; case INIT9LOAD: case READ9LOAD: @@ -574,6 +845,5 @@ default: panic("bootdone"); } - b->state = FAILED; - return FAIL; + return bootfail(b); } --- /sys/src/9/pcboot/bootmkfile Wed May 16 00:57:20 2012 +++ /sys/src/9/pcboot/bootmkfile Fri Mar 8 21:46:43 2013 @@ -67,10 +67,9 @@ $p$CONF:Q: $CONF.c $OBJ $LIB $CC $CFLAGS '-DKERNDATE='`{date -n} $CONF.c - echo linking bootstraps + echo linking $p$CONF^'*' $LD -o $target -H3 -T$KTZERO -l $OBJ $CONF.$O $LIB # dos .com $LD -o $target^debug -T$KTZERO -l $OBJ $CONF.$O $LIB -# $LD -o $target.exe -H4 -T$KTZERO -l $OBJ $CONF.$O $LIB # dos .exe # $LD -o $target.elf -H5 -R4096 -T$KTZERO -l $OBJ $CONF.$O $LIB size $target^debug --- /sys/src/9/pcboot/dat.h Fri Aug 17 22:11:39 2012 +++ /sys/src/9/pcboot/dat.h Fri Mar 8 21:46:43 2013 @@ -52,11 +52,16 @@ #define NAMELEN 28 #define GSHORT(p) (((p)[1]<<8)|(p)[0]) -#define GLONG(p) ((GSHORT(p+2)<<16)|GSHORT(p)) #define GLSHORT(p) (((p)[0]<<8)|(p)[1]) + +#define GLONG(p) ((GSHORT(p+2)<<16)|GSHORT(p)) #define GLLONG(p) (((ulong)GLSHORT(p)<<16)|GLSHORT(p+2)) #define PLLONG(p,v) (p)[3]=(v);(p)[2]=(v)>>8;(p)[1]=(v)>>16;(p)[0]=(v)>>24 +#define PLVLONG(p,v) (p)[7]=(v);(p)[6]=(v)>>8;(p)[5]=(v)>>16;(p)[4]=(v)>>24;\ + (p)[3]=(v)>>32; (p)[2]=(v)>>40;\ + (p)[1]=(v)>>48; (p)[0]=(v)>>56; + enum { Stkpat = 0, }; @@ -477,12 +482,17 @@ READ9TEXT, READ9DATA, READGZIP, - READEHDR, + READEHDR, /* elf states ... */ READPHDR, READEPAD, - READEDATA, + READEDATA, /* through here */ + READE64HDR, /* elf64 states ... */ + READ64PHDR, + READE64PAD, + READE64DATA, /* through here */ TRYBOOT, - TRYEBOOT, + TRYEBOOT, /* another elf state */ + TRYE64BOOT, /* another elf state */ INIT9LOAD, READ9LOAD, FAILED @@ -511,6 +521,7 @@ int state; Exechdr hdr; + uvlong entry; char *bp; /* base ptr */ char *wp; /* write ptr */ --- /sys/src/9/port/devaoe.c Tue Jun 21 23:35:08 2011 +++ /sys/src/9/port/devaoe.c Thu Mar 7 22:52:26 2013 @@ -1,6 +1,6 @@ /* * © 2005-2010 coraid - * aoe storage initiator + * ATA-over-Ethernet (AoE) storage initiator */ #include "u.h" @@ -1216,13 +1216,11 @@ static char * pflag(char *s, char *e, uchar f) { - uchar i, m; + uchar i; - for(i = 0; i < 8; i++){ - m = 1 << i; - if(f & m) + for(i = 0; i < 8; i++) + if(f & (1 << i)) s = seprint(s, e, "%s ", flagname[i]? flagname[i]: "oops"); - } return seprint(s, e, "\n"); } @@ -1471,9 +1469,9 @@ static int getmtu(Chan*); static int -devmaxdata(Aoedev *d) +devmaxdata(Aoedev *d) /* return aoe mtu (excluding headers) */ { - int i, m, mtu; + int i, nmtu, mtu; Devlink *l; Netlink *n; @@ -1483,22 +1481,29 @@ n = l->nl; if((l->flag & Dup) == 0 || (n->flag & Dup) == 0) continue; - m = getmtu(n->mtu); - if(m < mtu) - mtu = m; + nmtu = getmtu(n->mtu); + if(mtu > nmtu) + mtu = nmtu; } if(mtu == 100000) - mtu = 0; + mtu = ETHERMAXTU; /* normal ethernet mtu */ mtu -= AOEATASZ; + mtu -= (uint)mtu % Aoesectsz; + if(mtu < 2*Aoesectsz) /* sanity */ + mtu = 2*Aoesectsz; return mtu; } static int -toggle(char *s, int init) +toggle(char *s, int f, int bit) { if(s == nil) - return init ^ 1; - return strcmp(s, "on") == 0; + f ^= bit; + else if(strcmp(s, "on") == 0) + f |= bit; + else + f &= ~bit; + return f; } static void ataident(Aoedev*); @@ -1506,7 +1511,7 @@ static long unitctlwrite(Aoedev *d, void *db, long n) { - uint maxbcnt, m; + uint maxbcnt, mtu; uvlong bsize; enum { Failio, @@ -1545,14 +1550,7 @@ ataident(d); break; case Jumbo: - m = 0; - if(d->flag & Djumbo) - m = 1; - toggle(cb->f[1], m); - if(m) - d->flag |= Djumbo; - else - d->flag &= ~Djumbo; + d->flag = toggle(cb->f[1], d->flag, Djumbo); break; case Maxbno: case Mtu: @@ -1560,24 +1558,21 @@ if(cb->nf > 2) error(Ecmdargs); if(cb->nf == 2){ - m = strtoul(cb->f[1], 0, 0); + mtu = strtoul(cb->f[1], 0, 0); if(ct->index == Maxbno) - m *= Aoesectsz; + mtu *= Aoesectsz; else{ - m -= AOEATASZ; - m &= ~(Aoesectsz-1); + mtu -= AOEATASZ; + mtu &= ~(Aoesectsz-1); } - if(m == 0 || m > maxbcnt) + if(mtu == 0 || mtu > maxbcnt) cmderror(cb, "mtu out of legal range"); - maxbcnt = m; + maxbcnt = mtu; } d->maxbcnt = maxbcnt; break; case Nofailf: - if (toggle(cb->f[1], (d->flag & Dnofail) != 0)) - d->flag |= Dnofail; - else - d->flag &= ~Dnofail; + d->flag = toggle(cb->f[1], d->flag, Dnofail); break; case Setsize: bsize = d->realbsize; @@ -1823,15 +1818,15 @@ } static int -getmtu(Chan *m) +getmtu(Chan *mtuch) { int n, mtu; char buf[36]; - mtu = 1514; - if(m == nil || waserror()) + mtu = ETHERMAXTU; + if(mtuch == nil || waserror()) return mtu; - n = devtab[m->type]->read(m, buf, sizeof buf - 1, 0); + n = devtab[mtuch->type]->read(mtuch, buf, sizeof buf - 1, 0); if(n > 12){ buf[n] = 0; mtu = strtoul(buf + 12, 0, 0); @@ -2523,19 +2518,19 @@ f = cb->f[1]; switch(ct->index){ case Autodiscover: - autodiscover = toggle(f, autodiscover); + autodiscover = toggle(f, autodiscover, 1); break; case Bind: netbind(f); break; case Debug: - debug = toggle(f, debug); + debug = toggle(f, debug, 1); break; case Discover: discoverstr(f); break; case Rediscover: - rediscover = toggle(f, rediscover); + rediscover = toggle(f, rediscover, 1); break; case Remove: removedev(f); --- /sys/src/9/port/sdaoe.c Fri Dec 7 20:49:28 2012 +++ /sys/src/9/port/sdaoe.c Thu Mar 7 22:59:56 2013 @@ -520,13 +520,11 @@ static char * pflag(char *s, char *e, uchar f) { - uchar i, m; + uchar i; - for(i = 0; i < 8; i++){ - m = 1 << i; - if(f & m) + for(i = 0; i < 8; i++) + if(f & (1 << i)) s = seprint(s, e, "%s ", flagname[i]); - } return seprint(s, e, "\n"); } --- /sys/src/cmd/ld/elf.c Tue Mar 5 22:52:01 2013 +++ /sys/src/cmd/ld/elf.c Thu Jan 1 01:00:00 1970 @@ -1,266 +0,0 @@ -/* - * 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['P']){ /* 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); -} --- /sys/src/cmd/ld/elf.h Tue Mar 5 22:50:31 2013 +++ /sys/src/cmd/ld/elf.h Thu Jan 1 01:00:00 1970 @@ -1,96 +0,0 @@ -enum { - Ehdr32sz = 52, - Phdr32sz = 32, - Shdr32sz = 40, - - Ehdr64sz = 64, - Phdr64sz = 56, - Shdr64sz = 64, -}; - -/* from /sys/src/libmach/elf.h */ -enum { - /* Ehdr codes */ - MAG0 = 0, /* ident[] indexes */ - MAG1 = 1, - MAG2 = 2, - MAG3 = 3, - CLASS = 4, - DATA = 5, - VERSION = 6, - - ELFCLASSNONE = 0, /* ident[CLASS] */ - ELFCLASS32 = 1, - ELFCLASS64 = 2, - ELFCLASSNUM = 3, - - ELFDATANONE = 0, /* ident[DATA] */ - ELFDATA2LSB = 1, - ELFDATA2MSB = 2, - ELFDATANUM = 3, - - NOETYPE = 0, /* type */ - REL = 1, - EXEC = 2, - DYN = 3, - CORE = 4, - - NONE = 0, /* machine */ - M32 = 1, /* AT&T WE 32100 */ - SPARC = 2, /* Sun SPARC */ - I386 = 3, /* Intel 80386 */ - M68K = 4, /* Motorola 68000 */ - M88K = 5, /* Motorola 88000 */ - I486 = 6, /* Intel 80486 */ - I860 = 7, /* Intel i860 */ - MIPS = 8, /* Mips R2000 */ - S370 = 9, /* Amdhal */ - SPARC64 = 18, /* Sun SPARC v9 */ - POWER = 20, /* PowerPC */ - POWER64 = 21, /* PowerPC64 */ - ARM = 40, /* ARM */ - AMD64 = 62, /* Amd64 */ - ARM64 = 183, /* ARM64 */ - - NO_VERSION = 0, /* version, ident[VERSION] */ - CURRENT = 1, - - /* Phdr Codes */ - NOPTYPE = 0, /* type */ - PT_LOAD = 1, - DYNAMIC = 2, - INTERP = 3, - NOTE = 4, - SHLIB = 5, - PHDR = 6, - - R = 0x4, /* flags */ - W = 0x2, - X = 0x1, - - /* Shdr Codes */ - Progbits = 1, /* section types */ - Strtab = 3, - Nobits = 8, - - Swrite = 1, /* section attributes (flags) */ - Salloc = 2, - Sexec = 4, -}; - -typedef void (*Putl)(long); - -void elf32(int mach, int bo, int addpsects, void (*putpsects)(Putl)); -void elf32phdr(void (*putl)(long), ulong type, ulong off, ulong vaddr, - ulong paddr, ulong filesz, ulong memsz, ulong prots, ulong 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); - -void elf64(int mach, int bo, int addpsects, void (*putpsects)(Putl)); -void elf64phdr(void (*putl)(long), void (*putll)(vlong), ulong type, - uvlong off, uvlong vaddr, uvlong paddr, uvlong filesz, uvlong memsz, - ulong prots, uvlong 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); --- /sys/src/cmd/ld/mkfile Tue Mar 5 22:50:32 2013 +++ /sys/src/cmd/ld/mkfile Thu Jan 1 01:00:00 1970 @@ -1,2 +0,0 @@ -all clean nuke install installall safeinstall safeinstallall:V: - date --- /sys/src/cmd/ndb/dn.c Thu Mar 29 01:07:19 2012 +++ /sys/src/cmd/ndb/dn.c Sun Mar 10 06:16:47 2013 @@ -10,19 +10,20 @@ * be larger on large servers'. dns at Bell Labs starts off with * about 1780 names. * - * aging seems to corrupt the cache, so raise the trigger from 4000 until we - * figure it out. + * aging corrupts the cache, so raise the trigger to avoid it. */ enum { Deftarget = 1<<30, /* effectively disable aging */ Minage = 1<<30, Defagefreq = 1<<30, /* age names this often (seconds) */ - Restartmins = 600, /* these settings will trigger frequent aging */ // Deftarget = 4000, // Minage = 5*60, // Defagefreq = 15*60, /* age names this often (seconds) */ + + Restartmins = 0, +// Restartmins = 600, }; /* @@ -721,7 +722,7 @@ /* if we've been running for long enough, restart */ if(start == 0) start = time(nil); - if(0 && time(nil) - start > Restartmins*60){ // TODO + if(Restartmins > 0 && time(nil) - start > Restartmins*60){ dnslog("killing all dns procs for timed restart"); postnote(PNGROUP, getpid(), "die"); dnvars.mutex = 0; --- /sys/src/cmd/pcc.c Fri Jan 25 00:46:19 2013 +++ /sys/src/cmd/pcc.c Fri Mar 8 21:11:47 2013 @@ -83,6 +83,7 @@ case 'S': case 'T': case 'V': + case 'W': append(&cc, smprint("-%c", ARGC())); break; case 's': @@ -111,6 +112,12 @@ case 'f': if(strcmp(ot->name, "arm") == 0) append(&ldargs, "-f"); + break; + case 'x': + s = ARGF(); + if(s == nil || *s == '-') + fatal("no -x argument"); + append(&ldargs, smprint("-x %s", s)); break; case 'a': /* hacky look inside ARGBEGIN insides, to see if we have -aa */