diff --git a/misc/nacl/naclrun b/misc/nacl/naclrun
new file mode 100755
index 0000000000000000000000000000000000000000..1cdcf876c27fa09067140f8231a8a5852b65014b
--- /dev/null
+++ b/misc/nacl/naclrun
@@ -0,0 +1,15 @@
+#!/bin/sh
+# Copyright 2010 The Go Authors.  All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# Run nacl binary in debug mode (allow file access)
+# and then grep away the chatter.
+# See ../../src/pkg/exp/nacl/README for more on
+# how to configure NaCl.
+
+nacl -d "$@" >/tmp/nacl.out.$$ 2>&1
+status=$?
+egrep -v 'DEBUG MODE ENABLED|^\[[0-9]+,' /tmp/nacl.out.$$
+rm -f /tmp/nacl.out.$$
+exit $status
diff --git a/src/all-nacl.bash b/src/all-nacl.bash
index 23107d25e34e2a33cc6b22ed9414fe5a54898de5..817b911c07725629ecf931fd97e860b4a9f57c06 100755
--- a/src/all-nacl.bash
+++ b/src/all-nacl.bash
@@ -7,6 +7,7 @@
 
 export GOARCH=386
 export GOOS=nacl
+export GORUN="$GOROOT/misc/nacl/naclrun"
 
 set -e
 bash make.bash
@@ -17,6 +18,11 @@ xcd() {
 	builtin cd $1
 }
 
+(xcd pkg
+make install
+make test
+) || exit $?
+
 (xcd pkg/exp/nacl/srpc
 make clean
 make install
@@ -38,5 +44,5 @@ make
 ) || exit $?
 
 (xcd ../test
-./run-nacl
+./run
 ) || exit $?
diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c
index c1cad74bee18defb4c6dbfa27d0155e3b808244c..110446a0d772217ee2d235c5549f51030b533425 100644
--- a/src/cmd/8g/ggen.c
+++ b/src/cmd/8g/ggen.c
@@ -8,6 +8,7 @@
 #include "opt.h"
 
 static Prog *pret;
+static Node *naclnop;
 
 void
 compile(Node *fn)
@@ -23,6 +24,7 @@ compile(Node *fn)
 		newproc = sysfunc("newproc");
 		deferproc = sysfunc("deferproc");
 		deferreturn = sysfunc("deferreturn");
+		naclnop = sysfunc("naclnop");
 		panicindex = sysfunc("panicindex");
 		panicslice = sysfunc("panicslice");
 		throwreturn = sysfunc("throwreturn");
@@ -95,8 +97,16 @@ compile(Node *fn)
 	gclean();
 	if(nerrors != 0)
 		goto ret;
-	if(hasdefer)
+	if(hasdefer) {
+		// On Native client, insert call to no-op function
+		// to force alignment immediately before call to deferreturn,
+		// so that when jmpdefer subtracts 5 from the second CALL's
+		// return address and then the return masks off the low bits,
+		// we'll back up to the NOPs immediately after the dummy CALL.
+		if(strcmp(getgoos(), "nacl") == 0)
+			ginscall(naclnop, 0);
 		ginscall(deferreturn, 0);
+	}
 	pc->as = ARET;	// overwrite AEND
 	pc->lineno = lineno;
 
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index 4e8c0560d9b1e16ae01708ac05c7ff9b776e102a..0fca6fa0f87f65688ea8fd358796d27f0f68a9ee 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -226,8 +226,11 @@ addsize(Sym *s, Sym *t)
 vlong
 datoff(vlong addr)
 {
-	if(addr >= INITDAT)
+	if(addr >= INITDAT) {
+		if(HEADTYPE == 8)
+			return addr - INITDAT + rnd(HEADR+textsize, 4096);
 		return addr - INITDAT + rnd(HEADR+textsize, INITRND);
+	}
 	diag("datoff %#llx", addr);
 	return 0;
 }
@@ -548,6 +551,14 @@ asmb(void)
 		}
 		cflush();
 		break;
+	case 8:
+		// Native Client only needs to round
+		// text segment file address to 4096 bytes,
+		// but text segment memory address rounds
+		// to INITRND (65536).
+		v = rnd(HEADR+textsize, 4096);
+		seek(cout, v, 0);
+		break;
 	Elfseek:
 	case 10:
 		v = rnd(HEADR+textsize, INITRND);
@@ -829,15 +840,25 @@ asmb(void)
 		ph = newElfPhdr();
 		ph->type = PT_LOAD;
 		ph->flags = PF_X+PF_R;
-		ph->vaddr = va - fo;
-		ph->paddr = va - fo;
-		ph->off = 0;
-		ph->filesz = w + fo;
-		ph->memsz = w + fo;
+		if(HEADTYPE != 8) {	// Include header, but not on Native Client.
+			va -= fo;
+			w += fo;
+			fo = 0;
+		}
+		ph->vaddr = va;
+		ph->paddr = va;
+		ph->off = fo;
+		ph->filesz = w;
+		ph->memsz = INITDAT - va;
 		ph->align = INITRND;
 
-		fo = rnd(fo+w, INITRND);
-		va = rnd(va+w, INITRND);
+		// NaCl text segment file address rounds to 4096;
+		// only memory address rounds to INITRND.
+		if(HEADTYPE == 8)
+			fo = rnd(fo+w, 4096);
+		else
+			fo = rnd(fo+w, INITRND);
+		va = INITDAT;
 		w = datsize;
 
 		ph = newElfPhdr();
@@ -941,7 +962,7 @@ asmb(void)
 		ph->flags = PF_W+PF_R;
 		ph->align = 4;
 
-		fo = ELFRESERVE;
+		fo = HEADR;
 		va = startva + fo;
 		w = textsize;
 
@@ -953,7 +974,12 @@ asmb(void)
 		sh->size = w;
 		sh->addralign = 4;
 
-		fo = rnd(fo+w, INITRND);
+		// NaCl text segment file address rounds to 4096;
+		// only memory address rounds to INITRND.
+		if(HEADTYPE == 8)
+			fo = rnd(fo+w, 4096);
+		else
+			fo = rnd(fo+w, INITRND);
 		va = rnd(va+w, INITRND);
 		w = datsize;
 
@@ -1013,7 +1039,7 @@ asmb(void)
 		switch(HEADTYPE) {
 		case 8:
 			eh->ident[EI_OSABI] = ELFOSABI_NACL;
-			eh->ident[EI_ABIVERSION] = 6;
+			eh->ident[EI_ABIVERSION] = 7;
 			eh->flags = 0x200000;	// aligned mod 32
 			break;
 		case 9:
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index 8f02bdefda0a614fa2e01e5c0ca0993d5d9ab865..5b0f307233eb826447cbca42fc8d9532c9ec30f7 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -302,6 +302,7 @@ EXTERN	Sym*	symlist;
 EXTERN	int32	symsize;
 EXTERN	Prog*	textp;
 EXTERN	int32	textsize;
+EXTERN	int32	textpad;
 EXTERN	int	version;
 EXTERN	Prog	zprg;
 EXTERN	int	dtype;
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index cd7984d7158264e11252f4fc44a53ba8cbf0e2c0..82f4e47b7c0dd81392513cf4f51d3d02375566a3 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -280,7 +280,12 @@ main(int argc, char *argv[])
 		if(INITDAT == -1)
 			INITDAT = 0;
 		if(INITRND == -1)
-			INITRND = 4096;
+			INITRND = 65536;
+		
+		// 512 kB of address space for closures.
+		// (Doesn't take any space in the binary file.)
+		// Closures are 64 bytes each, so this is 8,192 closures.
+		textpad = 512*1024;
 		break;
 	case 10: /* PE executable */
 		peinit();
diff --git a/src/cmd/8l/span.c b/src/cmd/8l/span.c
index f649777ec39b60c74377b35740660613bdff105e..0245d72b9bf0504d7ddd8d3f696d4a20efb795bd 100644
--- a/src/cmd/8l/span.c
+++ b/src/cmd/8l/span.c
@@ -108,7 +108,7 @@ start:
 	}while(again);
 
 	if(INITRND) {
-		INITDAT = rnd(c, INITRND);
+		INITDAT = rnd(c+textpad, INITRND);
 		if(INITDAT != idat) {
 			idat = INITDAT;
 			goto start;
diff --git a/src/cmd/gotest/gotest b/src/cmd/gotest/gotest
index 3fca81b6a575e145ce7b2303643167f435e3c7c9..0a0aafc3440622de762feee05e7b64e74d469f4c 100755
--- a/src/cmd/gotest/gotest
+++ b/src/cmd/gotest/gotest
@@ -29,11 +29,7 @@ if [ -z "$O" ]; then
 	exit 2
 fi
 
-E=""
-case "$GOOS" in
-nacl)
-	E="nacl"
-esac
+E="$GORUN"
 
 # TODO(kaib): proper emulator strategy
 case x"$GOARCH" in
diff --git a/src/pkg/Makefile b/src/pkg/Makefile
index 4057ed97d183d5dbff562be0599fdc41bca2ac3f..a9c400a9ceef896ab1a2d973addd5dc6b7ed0e53 100644
--- a/src/pkg/Makefile
+++ b/src/pkg/Makefile
@@ -150,6 +150,25 @@ TEST=\
 BENCH=\
 	$(filter-out $(NOBENCH),$(TEST))
 
+# Disable tests that NaCl cannot run yet.
+ifeq ($(GOOS),nacl)
+NOTEST+=archive/tar  # no pipe
+NOTEST+=debug/dwarf  # no pread
+NOTEST+=debug/macho  # no pread
+NOTEST+=debug/elf    # no pread
+NOTEST+=exec         # no pipe
+NOTEST+=http         # no network
+NOTEST+=log          # no runtime.Caller
+NOTEST+=net          # no network
+NOTEST+=os           # many things unimplemented
+NOTEST+=os/signal    # no signals
+NOTEST+=path         # tree walking does not work
+NOTEST+=rpc          # no network
+NOTEST+=syslog       # no network
+NOTEST+=time         # no syscall.Kill, syscall.SIGCHLD for sleep tests
+NOTEST+=websocket    # no network
+endif
+
 clean.dirs: $(addsuffix .clean, $(DIRS))
 install.dirs: $(addsuffix .install, $(DIRS))
 nuke.dirs: $(addsuffix .nuke, $(DIRS))
diff --git a/src/pkg/os/stat_nacl.go b/src/pkg/os/stat_nacl.go
index be693e81478c90b694e270a91628cfb3ab611251..a44d0b0b6ec66f91673c71afb0af4249402a8e54 100644
--- a/src/pkg/os/stat_nacl.go
+++ b/src/pkg/os/stat_nacl.go
@@ -15,15 +15,15 @@ func fileInfoFromStat(name string, fi *FileInfo, lstat, stat *syscall.Stat_t) *F
 	fi.Ino = uint64(stat.Ino)
 	fi.Nlink = uint64(stat.Nlink)
 	fi.Mode = stat.Mode
-	fi.Uid = stat.Uid
-	fi.Gid = stat.Gid
+	fi.Uid = int(stat.Uid)
+	fi.Gid = int(stat.Gid)
 	fi.Rdev = uint64(stat.Rdev)
-	fi.Size = uint64(stat.Size)
-	fi.Blksize = uint64(stat.Blksize)
-	fi.Blocks = uint64(stat.Blocks)
-	fi.Atime_ns = uint64(stat.Atime) * 1e9
-	fi.Mtime_ns = uint64(stat.Mtime) * 1e9
-	fi.Ctime_ns = uint64(stat.Ctime) * 1e9
+	fi.Size = int64(stat.Size)
+	fi.Blksize = int64(stat.Blksize)
+	fi.Blocks = int64(stat.Blocks)
+	fi.Atime_ns = int64(stat.Atime) * 1e9
+	fi.Mtime_ns = int64(stat.Mtime) * 1e9
+	fi.Ctime_ns = int64(stat.Ctime) * 1e9
 	for i := len(name) - 1; i >= 0; i-- {
 		if name[i] == '/' {
 			name = name[i+1:]
diff --git a/src/pkg/runtime/Makefile b/src/pkg/runtime/Makefile
index f7da0251e55d782f09c4272e785b2efce3a476f3..6b3ab21e35422c9d0374721e035e10a3b266d854 100644
--- a/src/pkg/runtime/Makefile
+++ b/src/pkg/runtime/Makefile
@@ -154,8 +154,12 @@ runtime.acid.$(GOARCH): runtime.h proc.c
 
 # 386 traceback is really amd64 traceback
 ifeq ($(GOARCH),386)
-
 traceback.$O:	amd64/traceback.c
 	$(QUOTED_GOBIN)/$(CC) $(CFLAGS) $<
+endif
 
+# NaCl closure is special.
+ifeq ($(GOOS),nacl)
+closure.$O: nacl/$(GOARCH)/closure.c
+	$(QUOTED_GOBIN)/$(CC) $(CFLAGS) $<
 endif
diff --git a/src/pkg/runtime/malloc.h b/src/pkg/runtime/malloc.h
index 8b733b6a4af80eccf4227a65258849b30eb765a2..473e8a836fdd680f9f29a0067ce9760e8f687f70 100644
--- a/src/pkg/runtime/malloc.h
+++ b/src/pkg/runtime/malloc.h
@@ -324,6 +324,10 @@ struct MHeap
 	// range of addresses we might see in the heap
 	byte *min;
 	byte *max;
+	
+	// range of addresses we might see in a Native Client closure
+	byte *closure_min;
+	byte *closure_max;
 
 	// central free lists for small size classes.
 	// the union makes sure that the MCentrals are
diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c
index f78dabf88b1231c1afdba223de1bf284c19eaa99..2324eff29014842a11a832fd5bf0e1cfc11bfbfc 100644
--- a/src/pkg/runtime/mgc0.c
+++ b/src/pkg/runtime/mgc0.c
@@ -56,18 +56,36 @@ scanblock(int32 depth, byte *b, int64 n)
 	n /= PtrSize;
 	for(i=0; i<n; i++) {
 		obj = vp[i];
-		if(obj == nil || (byte*)obj < mheap.min || (byte*)obj >= mheap.max)
+		if(obj == nil)
 			continue;
-		if(mlookup(obj, &obj, &size, nil, &refp)) {
-			ref = *refp;
-			switch(ref & ~RefFlags) {
-			case RefNone:
-				if(Debug > 1)
-					printf("%d found at %p: ", depth, &vp[i]);
-				*refp = RefSome | (ref & RefFlags);
-				if(!(ref & RefNoPointers))
-					scanblock(depth+1, obj, size);
-				break;
+		if(mheap.closure_min != nil && mheap.closure_min <= (byte*)obj && (byte*)obj < mheap.closure_max) {
+			if((((uintptr)obj) & 63) != 0)
+				continue;
+
+			// Looks like a Native Client closure.
+			// Actual pointer is pointed at by address in first instruction.
+			// Embedded pointer starts at byte 2.
+			// If it is f4f4f4f4 then that space hasn't been
+			// used for a closure yet (f4 is the HLT instruction).
+			// See nacl/386/closure.c for more.
+			void **pp;
+			pp = *(void***)((byte*)obj+2);
+			if(pp == (void**)0xf4f4f4f4)	// HLT... - not a closure after all
+				continue;
+			obj = *pp;
+		}
+		if(mheap.min <= (byte*)obj && (byte*)obj < mheap.max) {
+			if(mlookup(obj, &obj, &size, nil, &refp)) {
+				ref = *refp;
+				switch(ref & ~RefFlags) {
+				case RefNone:
+					if(Debug > 1)
+						printf("%d found at %p: ", depth, &vp[i]);
+					*refp = RefSome | (ref & RefFlags);
+					if(!(ref & RefNoPointers))
+						scanblock(depth+1, obj, size);
+					break;
+				}
 			}
 		}
 	}
@@ -310,8 +328,8 @@ gc(int32 force)
 		if(fing == nil)
 			fing = newproc1((byte*)runfinq, nil, 0, 0);
 		else if(fingwait) {
-			ready(fing);
 			fingwait = 0;
+			ready(fing);
 		}
 	}
 	m->locks--;
@@ -359,6 +377,7 @@ runfinq(void)
 			f->fn = nil;
 			f->arg = nil;
 			f->next = nil;
+			free(f);
 		}
 		gc(1);	// trigger another gc to clean up the finalized objects, if possible
 	}
diff --git a/src/pkg/runtime/nacl/386/closure.c b/src/pkg/runtime/nacl/386/closure.c
new file mode 100644
index 0000000000000000000000000000000000000000..6a27d6ec6f94abaee7cda96799de658f960adf1e
--- /dev/null
+++ b/src/pkg/runtime/nacl/386/closure.c
@@ -0,0 +1,247 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+ * Closure implementation for Native Client.
+ * Native Client imposes some interesting restrictions.
+ *
+ * First, we can only add new code to the code segment
+ * through a special system call, and we have to pick the
+ * maximum amount of code we're going to add that way
+ * at link time (8l reserves 512 kB for us).
+ *
+ * Second, once we've added the code we can't ever
+ * change it or delete it.  If we want to garbage collect
+ * the memory and then reuse it for another closure,
+ * we have to do so without editing the code.
+ *
+ * To address both of these, we fill the code segment pieces
+ * with very stylized closures.  Each has the form given below
+ * in the comments on the closasm array, with ** replaced by
+ * a pointer to a single word of memory.  The garbage collector
+ * treats a pointer to such a closure as equivalent to the value
+ * held in **.  This tiled run of closures is called the closure array.
+ *
+ * The ptr points at a ClosureData structure, defined below,
+ * which gives the function, arguments, and size for the
+ * closuretramp function.  The ClosureData structure has
+ * in it a pointer to a ClosureFreeList structure holding the index
+ * of the closure in the closure array (but not a pointer to it). 
+ * That structure has a finalizer: when the garbage collector
+ * notices that the ClosureFreeList structure is not referenced
+ * anymore, that means the closure is not referenced, so it
+ * can be reused.  To do that, the ClosureFreeList entry is put
+ * onto an actual free list.
+ */
+#include "runtime.h"
+#include "malloc.h"
+
+// NaCl system call to copy data into text segment.
+extern int32 dyncode_copy(void*, void*, int32);
+
+enum{
+	// Allocate chunks of 4096 bytes worth of closures:
+	// at 64 bytes each, that's 64 closures.
+	ClosureChunk = 4096,
+	ClosureSize = 64,
+};
+
+typedef struct ClosureFreeList ClosureFreeList;
+struct ClosureFreeList
+{
+	ClosureFreeList *next;
+	int32 index;	// into closure array
+};
+
+// Known to closasm
+typedef struct ClosureData ClosureData;
+struct ClosureData
+{
+	ClosureFreeList *free;
+	byte *fn;
+	int32 siz;
+	// then args
+};
+
+// List of the closure data pointer blocks we've allocated
+// and hard-coded in the closure text segments.
+// The list keeps the pointer blocks from getting collected.
+typedef struct ClosureDataList ClosureDataList;
+struct ClosureDataList
+{
+	ClosureData **block;
+	ClosureDataList *next;
+};
+
+static struct {
+	Lock;
+	byte *code;
+	byte *ecode;
+	ClosureFreeList *free;
+	ClosureDataList *datalist;
+	byte buf[ClosureChunk];
+} clos;
+
+static byte closasm[64] = {
+	0x8b, 0x1d, 0, 0, 0, 0,	// MOVL **, BX
+	0x8b, 0x4b, 8,		// MOVL 8(BX), CX
+	0x8d, 0x73, 12,		// LEAL 12(BX), SI
+	0x29, 0xcc,		// SUBL CX, SP
+	0x89, 0xe7,		// MOVL SP, DI
+	0xc1, 0xe9, 2,		// SHRL $2, CX
+	0xf3, 0xa5,		// REP MOVSL
+	0x8b, 0x5b, 4,		// MOVL 4(BX), BX
+	0x90, 0x90, 0x90,	// NOP...
+	0x83, 0xe3, ~31,	// ANDL $~31, BX
+	0xff, 0xd3,		// CALL *BX
+	// --- 32-byte boundary
+	0x8b, 0x1d, 0, 0, 0, 0,	// MOVL **, BX
+	0x03, 0x63, 8,		// ADDL 8(BX), SP
+	0x5b,			// POPL BX
+	0x83, 0xe3, ~31,	// ANDL $~31, BX
+	0xff, 0xe3,		// JMP *BX
+	0xf4,			// HLT...
+	0xf4, 0xf4, 0xf4, 0xf4,
+	0xf4, 0xf4, 0xf4, 0xf4,
+	0xf4, 0xf4, 0xf4, 0xf4,
+	0xf4, 0xf4, 0xf4, 0xf4,
+	// --- 32-byte boundary
+};
+
+// Returns immediate pointer from closure code block.
+// Triple pointer:
+//	p is the instruction stream
+//	p+2 is the location of the immediate value
+//	*(p+2) is the immediate value, a word in the pointer block
+//		permanently associated with this closure.
+//	**(p+2) is the ClosureData* pointer temporarily associated
+//		with this closure.
+//
+#define codeptr(p) *(ClosureData***)((byte*)(p)+2)
+
+void
+finclosure(void *v)
+{
+	byte *p;
+	ClosureFreeList *f;
+
+	f = v;
+	p = clos.code + f->index*ClosureSize;
+	*codeptr(p) = nil;
+
+	lock(&clos);
+	f->next = clos.free;
+	clos.free = f;
+	unlock(&clos);
+}
+
+#pragma textflag 7
+// func closure(siz int32,
+//	fn func(arg0, arg1, arg2 *ptr, callerpc uintptr, xxx) yyy,
+//	arg0, arg1, arg2 *ptr) (func(xxx) yyy)
+void
+·closure(int32 siz, byte *fn, byte *arg0)
+{
+	byte *p, **ret;
+	int32 e, i, n, off;
+	extern byte data[], etext[];
+	ClosureData *d, **block;
+	ClosureDataList *l;
+	ClosureFreeList *f;
+
+	if(siz < 0 || siz%4 != 0)
+		throw("bad closure size");
+
+	ret = (byte**)((byte*)&arg0 + siz);
+
+	if(siz > 100) {
+		// TODO(rsc): implement stack growth preamble?
+		throw("closure too big");
+	}
+
+	lock(&clos);
+	if(clos.free == nil) {
+		// Allocate more closures.
+		if(clos.code == nil) {
+			// First time: find closure space, between end of text
+			// segment and beginning of data.
+			clos.code = (byte*)(((uintptr)etext + 65535) & ~65535);
+			clos.ecode = clos.code;
+			mheap.closure_min = clos.code;
+			mheap.closure_max = data;
+		}
+		if(clos.ecode+ClosureChunk > data) {
+			// Last ditch effort: garbage collect and hope.
+			unlock(&clos);
+			gc(1);
+			lock(&clos);
+			if(clos.free != nil)
+				goto alloc;
+			throw("ran out of room for closures in text segment");
+		}
+
+		n = ClosureChunk/ClosureSize;
+		
+		// Allocate the pointer block as opaque to the
+		// garbage collector.  Finalizers will clean up.
+		block = mallocgc(n*sizeof block[0], RefNoPointers, 1, 1);
+
+		// Pointers into the pointer block are getting added
+		// to the text segment; keep a pointer here in the data
+		// segment so that the garbage collector doesn't free
+		// the block itself.
+		l = mal(sizeof *l);
+		l->block = block;
+		l->next = clos.datalist;
+		clos.datalist = l;
+
+		p = clos.buf;
+		off = (clos.ecode - clos.code)/ClosureSize;
+		for(i=0; i<n; i++) {
+			f = mal(sizeof *f);
+			f->index = off++;
+			f->next = clos.free;
+			clos.free = f;
+
+			// There are two hard-coded immediate values in
+			// the assembly that need to be pp+i, one 2 bytes in
+			// and one 2 bytes after the 32-byte boundary.
+			mcpy(p, closasm, ClosureSize);
+			*(ClosureData***)(p+2) = block+i;
+			*(ClosureData***)(p+32+2) = block+i;
+			p += ClosureSize;
+		}
+
+		if(p != clos.buf+sizeof clos.buf)
+			throw("bad buf math in closure");
+
+		e = dyncode_copy(clos.ecode, clos.buf, ClosureChunk);
+		if(e != 0) {
+			fd = 2;
+			printf("dyncode_copy: error %d\n", e);
+			throw("dyncode_copy");
+		}
+		clos.ecode += ClosureChunk;
+	}
+
+alloc:
+	// Grab a free closure and save the data pointer in its indirect pointer.
+	f = clos.free;
+	clos.free = f->next;
+	f->next = nil;
+	p = clos.code + f->index*ClosureSize;
+
+	d = mal(sizeof(*d)+siz);
+	d->free = f;
+	d->fn = fn;
+	d->siz = siz;
+	mcpy((byte*)(d+1), (byte*)&arg0, siz);
+	*codeptr(p) = d;
+	addfinalizer(f, finclosure, 0);
+	unlock(&clos);
+
+	*ret = p;
+}
+
+
diff --git a/src/pkg/runtime/nacl/386/sys.s b/src/pkg/runtime/nacl/386/sys.s
index 356d85eff00b55518cdcf5362838e83759140156..e855351b92739627ea47f8093c33bec581a2c2d6 100644
--- a/src/pkg/runtime/nacl/386/sys.s
+++ b/src/pkg/runtime/nacl/386/sys.s
@@ -20,6 +20,8 @@
 #define SYS_mutex_lock  71
 #define SYS_mutex_unlock 73
 #define SYS_gettimeofday 40
+#define SYS_dyncode_copy 104
+
 
 #define SYSCALL(x)	$(0x10000+SYS_/**/x * 32)
 
@@ -55,6 +57,15 @@ TEXT	mutex_unlock(SB),7,$0
 TEXT thread_create(SB),7,$0
 	JMP	SYSCALL(thread_create)
 
+TEXT dyncode_copy(SB),7,$0
+	JMP	SYSCALL(dyncode_copy)
+
+// For Native Client: a simple no-op function.
+// Inserting a call to this no-op is a simple way
+// to trigger an alignment.
+TEXT ·naclnop(SB),7,$0
+	RET
+
 TEXT ·mmap(SB),7,$24
 	MOVL	a1+0(FP), BX
 	MOVL	a2+4(FP), CX	// round up to 64 kB boundary; silences nacl warning
diff --git a/src/pkg/runtime/nacl/thread.c b/src/pkg/runtime/nacl/thread.c
index 4112eaa993cece39e0831d8874a93ba6a26da67c..392be870ff4e18720a43fca44411b27deaba95dd 100644
--- a/src/pkg/runtime/nacl/thread.c
+++ b/src/pkg/runtime/nacl/thread.c
@@ -88,7 +88,7 @@ unlock(Lock *l)
 }
 
 void
-destroylock(Lock *l)
+destroylock(Lock*)
 {
 }
 
diff --git a/src/pkg/syscall/syscall_nacl.go b/src/pkg/syscall/syscall_nacl.go
index 6a5d9c2d6900124129f042a7d371b9d9f4cb48a6..7b40a22ad05a3e7d4f2bf7e8154cd3d865be5eec 100644
--- a/src/pkg/syscall/syscall_nacl.go
+++ b/src/pkg/syscall/syscall_nacl.go
@@ -131,7 +131,7 @@ func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
 func Mkdir(path string, mode int) (errno int) { return ENACL }
 
 func Lstat(path string, stat *Stat_t) (errno int) {
-	return ENACL
+	return Stat(path, stat)
 }
 
 func Chdir(path string) (errno int) { return ENACL }
diff --git a/test/env.go b/test/env.go
index 2cf9ddf381373f74ce8f3542a23b7665d80e8583..b12a72973b49e05c4b944a1aeb3966439c742801 100644
--- a/test/env.go
+++ b/test/env.go
@@ -1,3 +1,4 @@
+// [ $GOOS != nacl ] || exit 0  # NaCl runner does not expose environment
 // $G $F.go && $L $F.$A && ./$A.out
 
 // Copyright 2009 The Go Authors. All rights reserved.
diff --git a/test/fixedbugs/bug243.go b/test/fixedbugs/bug243.go
index 01112dae73a30e1d5a45d846c4279514349adc65..837b91035f704915152758aac61c6c90863b3324 100644
--- a/test/fixedbugs/bug243.go
+++ b/test/fixedbugs/bug243.go
@@ -1,3 +1,4 @@
+// [ $GOOS != nacl ] || exit 0  # no network
 // $G $D/$F.go && $L $F.$A && ./$A.out
 
 // Copyright 2010 The Go Authors.  All rights reserved.
diff --git a/test/nacl-pass.txt b/test/nacl-pass.txt
deleted file mode 100644
index 91a9cc8df984be0f77bf171ac4adcfa4ac4d0063..0000000000000000000000000000000000000000
--- a/test/nacl-pass.txt
+++ /dev/null
@@ -1,355 +0,0 @@
-./64bit.go
-./args.go
-./assign.go
-./bigalg.go
-./blank.go
-./blank1.go
-./chancap.go
-./char_lit.go
-./closedchan.go
-./cmp1.go
-./complit.go
-./compos.go
-./const.go
-./const1.go
-./const2.go
-./const3.go
-./convert.go
-./convert3.go
-./convlit.go
-./convlit1.go
-./copy.go
-./ddd1.go
-./ddd2.go
-./ddd3.go
-./decl.go
-./declbad.go
-./defer.go
-./empty.go
-./escape.go
-./escape1.go
-./float_lit.go
-./floatcmp.go
-./for.go
-./func.go
-./func1.go
-./func2.go
-./func3.go
-./func4.go
-./gc.go
-./gc1.go
-./hashmap.go
-./hilbert.go
-./if.go
-./if1.go
-./import.go
-./import1.go
-./import2.go
-./import3.go
-./indirect.go
-./indirect1.go
-./initcomma.go
-./initialize.go
-./initializerr.go
-./initsyscall.go
-./int_lit.go
-./intcvt.go
-./iota.go
-./literal.go
-./map.go
-./method.go
-./method1.go
-./method2.go
-./method3.go
-./named.go
-./named1.go
-./nil.go
-./parentype.go
-./range.go
-./rename.go
-./rename1.go
-./runtime.go
-./sieve.go
-./simassign.go
-./string_lit.go
-./stringrange.go
-./switch.go
-./switch1.go
-./test0.go
-./typeswitch.go
-./typeswitch1.go
-./typeswitch2.go
-./utf.go
-./varinit.go
-./vectors.go
-ken/array.go
-ken/chan.go
-ken/chan1.go
-ken/complit.go
-ken/divconst.go
-ken/divmod.go
-ken/embed.go
-ken/for.go
-ken/interbasic.go
-ken/interfun.go
-ken/mfunc.go
-ken/modconst.go
-ken/ptrfun.go
-ken/ptrvar.go
-ken/range.go
-ken/robfor.go
-ken/robfunc.go
-ken/robif.go
-ken/shift.go
-ken/simparray.go
-ken/simpbool.go
-ken/simpconv.go
-ken/simpfun.go
-ken/simpvar.go
-ken/slicearray.go
-ken/sliceslice.go
-ken/strvar.go
-chan/fifo.go
-chan/perm.go
-chan/select.go
-chan/sieve.go
-interface/bigdata.go
-interface/convert.go
-interface/convert1.go
-interface/convert2.go
-interface/embed.go
-interface/embed0.go
-interface/embed1.go
-interface/explicit.go
-interface/fake.go
-interface/pointer.go
-interface/receiver.go
-interface/receiver1.go
-interface/recursive.go
-interface/struct.go
-syntax/forvar.go
-syntax/import.go
-syntax/interface.go
-syntax/semi1.go
-syntax/semi2.go
-syntax/semi3.go
-syntax/semi4.go
-syntax/semi5.go
-syntax/semi6.go
-syntax/semi7.go
-syntax/slice.go
-fixedbugs/bug000.go
-fixedbugs/bug001.go
-fixedbugs/bug002.go
-fixedbugs/bug003.go
-fixedbugs/bug004.go
-fixedbugs/bug005.go
-fixedbugs/bug006.go
-fixedbugs/bug007.go
-fixedbugs/bug008.go
-fixedbugs/bug009.go
-fixedbugs/bug010.go
-fixedbugs/bug011.go
-fixedbugs/bug012.go
-fixedbugs/bug013.go
-fixedbugs/bug014.go
-fixedbugs/bug015.go
-fixedbugs/bug017.go
-fixedbugs/bug020.go
-fixedbugs/bug021.go
-fixedbugs/bug022.go
-fixedbugs/bug023.go
-fixedbugs/bug024.go
-fixedbugs/bug026.go
-fixedbugs/bug028.go
-fixedbugs/bug030.go
-fixedbugs/bug031.go
-fixedbugs/bug035.go
-fixedbugs/bug036.go
-fixedbugs/bug037.go
-fixedbugs/bug038.go
-fixedbugs/bug039.go
-fixedbugs/bug040.go
-fixedbugs/bug045.go
-fixedbugs/bug046.go
-fixedbugs/bug047.go
-fixedbugs/bug048.go
-fixedbugs/bug049.go
-fixedbugs/bug050.go
-fixedbugs/bug051.go
-fixedbugs/bug052.go
-fixedbugs/bug053.go
-fixedbugs/bug054.go
-fixedbugs/bug055.go
-fixedbugs/bug056.go
-fixedbugs/bug057.go
-fixedbugs/bug058.go
-fixedbugs/bug059.go
-fixedbugs/bug060.go
-fixedbugs/bug061.go
-fixedbugs/bug062.go
-fixedbugs/bug063.go
-fixedbugs/bug064.go
-fixedbugs/bug065.go
-fixedbugs/bug066.go
-fixedbugs/bug068.go
-fixedbugs/bug069.go
-fixedbugs/bug071.go
-fixedbugs/bug072.go
-fixedbugs/bug073.go
-fixedbugs/bug074.go
-fixedbugs/bug075.go
-fixedbugs/bug076.go
-fixedbugs/bug077.go
-fixedbugs/bug078.go
-fixedbugs/bug080.go
-fixedbugs/bug082.go
-fixedbugs/bug083.go
-fixedbugs/bug084.go
-fixedbugs/bug085.go
-fixedbugs/bug086.go
-fixedbugs/bug087.go
-fixedbugs/bug088.go
-fixedbugs/bug089.go
-fixedbugs/bug090.go
-fixedbugs/bug091.go
-fixedbugs/bug092.go
-fixedbugs/bug094.go
-fixedbugs/bug096.go
-fixedbugs/bug097.go
-fixedbugs/bug098.go
-fixedbugs/bug099.go
-fixedbugs/bug101.go
-fixedbugs/bug102.go
-fixedbugs/bug103.go
-fixedbugs/bug104.go
-fixedbugs/bug106.go
-fixedbugs/bug107.go
-fixedbugs/bug108.go
-fixedbugs/bug109.go
-fixedbugs/bug110.go
-fixedbugs/bug111.go
-fixedbugs/bug112.go
-fixedbugs/bug114.go
-fixedbugs/bug115.go
-fixedbugs/bug116.go
-fixedbugs/bug117.go
-fixedbugs/bug118.go
-fixedbugs/bug119.go
-fixedbugs/bug120.go
-fixedbugs/bug121.go
-fixedbugs/bug122.go
-fixedbugs/bug123.go
-fixedbugs/bug126.go
-fixedbugs/bug127.go
-fixedbugs/bug128.go
-fixedbugs/bug129.go
-fixedbugs/bug130.go
-fixedbugs/bug131.go
-fixedbugs/bug132.go
-fixedbugs/bug133.go
-fixedbugs/bug135.go
-fixedbugs/bug136.go
-fixedbugs/bug137.go
-fixedbugs/bug139.go
-fixedbugs/bug140.go
-fixedbugs/bug141.go
-fixedbugs/bug142.go
-fixedbugs/bug143.go
-fixedbugs/bug144.go
-fixedbugs/bug145.go
-fixedbugs/bug146.go
-fixedbugs/bug149.go
-fixedbugs/bug150.go
-fixedbugs/bug151.go
-fixedbugs/bug152.go
-fixedbugs/bug153.go
-fixedbugs/bug154.go
-fixedbugs/bug155.go
-fixedbugs/bug156.go
-fixedbugs/bug157.go
-fixedbugs/bug158.go
-fixedbugs/bug160.go
-fixedbugs/bug161.go
-fixedbugs/bug163.go
-fixedbugs/bug164.go
-fixedbugs/bug165.go
-fixedbugs/bug167.go
-fixedbugs/bug168.go
-fixedbugs/bug169.go
-fixedbugs/bug170.go
-fixedbugs/bug171.go
-fixedbugs/bug172.go
-fixedbugs/bug173.go
-fixedbugs/bug174.go
-fixedbugs/bug175.go
-fixedbugs/bug176.go
-fixedbugs/bug177.go
-fixedbugs/bug178.go
-fixedbugs/bug179.go
-fixedbugs/bug180.go
-fixedbugs/bug181.go
-fixedbugs/bug182.go
-fixedbugs/bug183.go
-fixedbugs/bug184.go
-fixedbugs/bug185.go
-fixedbugs/bug186.go
-fixedbugs/bug187.go
-fixedbugs/bug188.go
-fixedbugs/bug189.go
-fixedbugs/bug190.go
-fixedbugs/bug191.go
-fixedbugs/bug192.go
-fixedbugs/bug193.go
-fixedbugs/bug194.go
-fixedbugs/bug195.go
-fixedbugs/bug196.go
-fixedbugs/bug197.go
-fixedbugs/bug198.go
-fixedbugs/bug199.go
-fixedbugs/bug200.go
-fixedbugs/bug201.go
-fixedbugs/bug202.go
-fixedbugs/bug203.go
-fixedbugs/bug204.go
-fixedbugs/bug205.go
-fixedbugs/bug206.go
-fixedbugs/bug207.go
-fixedbugs/bug208.go
-fixedbugs/bug209.go
-fixedbugs/bug211.go
-fixedbugs/bug212.go
-fixedbugs/bug213.go
-fixedbugs/bug214.go
-fixedbugs/bug215.go
-fixedbugs/bug216.go
-fixedbugs/bug217.go
-fixedbugs/bug218.go
-fixedbugs/bug219.go
-fixedbugs/bug220.go
-fixedbugs/bug221.go
-fixedbugs/bug222.go
-fixedbugs/bug223.go
-fixedbugs/bug224.go
-fixedbugs/bug225.go
-fixedbugs/bug226.go
-fixedbugs/bug227.go
-fixedbugs/bug228.go
-fixedbugs/bug229.go
-fixedbugs/bug230.go
-fixedbugs/bug231.go
-fixedbugs/bug232.go
-fixedbugs/bug233.go
-fixedbugs/bug234.go
-fixedbugs/bug235.go
-fixedbugs/bug236.go
-fixedbugs/bug237.go
-fixedbugs/bug238.go
-fixedbugs/bug239.go
-fixedbugs/bug240.go
-fixedbugs/bug241.go
-fixedbugs/bug244.go
-fixedbugs/bug245.go
-fixedbugs/bug247.go
-fixedbugs/bug248.go
-fixedbugs/bug249.go
diff --git a/test/nilptr/arrayindex.go b/test/nilptr/arrayindex.go
index c42dedee8144d8814b9a3742fa240aed7e621bce..1767acc275e640471287f74c378140f446f7d849 100644
--- a/test/nilptr/arrayindex.go
+++ b/test/nilptr/arrayindex.go
@@ -1,3 +1,4 @@
+// [ $GOOS != nacl ] || exit 0  # do not bother on NaCl
 // $G $D/$F.go && $L $F.$A &&
 //	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
 
diff --git a/test/nilptr/arrayindex1.go b/test/nilptr/arrayindex1.go
index 59126f82d5eb605d5fe0c2cceed28a009d9f80b2..c16cac4053e96fa50d44c7ab687585104b6dd6bb 100644
--- a/test/nilptr/arrayindex1.go
+++ b/test/nilptr/arrayindex1.go
@@ -1,3 +1,4 @@
+// [ $GOOS != nacl ] || exit 0  # do not bother on NaCl
 // $G $D/$F.go && $L $F.$A &&
 //	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
 
diff --git a/test/nilptr/arraytoslice.go b/test/nilptr/arraytoslice.go
index 4864d6855270ef46cf0eac0a8929b0a82d786695..65b2f8a765e7783ee341869e0597a7bd65c2badc 100644
--- a/test/nilptr/arraytoslice.go
+++ b/test/nilptr/arraytoslice.go
@@ -1,3 +1,4 @@
+// [ $GOOS != nacl ] || exit 0  # do not bother on NaCl
 // $G $D/$F.go && $L $F.$A &&
 //	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
 
diff --git a/test/nilptr/arraytoslice1.go b/test/nilptr/arraytoslice1.go
index 1a479dcdb2b8a4dbf067cbb5ddeabce5dc856618..b5240a803a9f963536a345055c04ed2dca4e0c31 100644
--- a/test/nilptr/arraytoslice1.go
+++ b/test/nilptr/arraytoslice1.go
@@ -1,3 +1,4 @@
+// [ $GOOS != nacl ] || exit 0  # do not bother on NaCl
 // $G $D/$F.go && $L $F.$A &&
 //	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
 
diff --git a/test/nilptr/arraytoslice2.go b/test/nilptr/arraytoslice2.go
index 0990b899ddab875d2bd94342de52b9106a3b3e35..38e1a5cb2821034eec45d225b73d9550b0ff376d 100644
--- a/test/nilptr/arraytoslice2.go
+++ b/test/nilptr/arraytoslice2.go
@@ -1,3 +1,4 @@
+// [ $GOOS != nacl ] || exit 0  # do not bother on NaCl
 // $G $D/$F.go && $L $F.$A &&
 //	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
 
diff --git a/test/nilptr/slicearray.go b/test/nilptr/slicearray.go
index 7a156b5e64c609c0fd877f98da4ae03292627785..5f88010df849d1f1c99c2b8c592a01230e588a71 100644
--- a/test/nilptr/slicearray.go
+++ b/test/nilptr/slicearray.go
@@ -1,3 +1,4 @@
+// [ $GOOS != nacl ] || exit 0  # do not bother on NaCl
 // $G $D/$F.go && $L $F.$A &&
 //	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
 
diff --git a/test/nilptr/structfield.go b/test/nilptr/structfield.go
index 22db500d7d1561094f42f118db6a0abaed3d2aa4..9f70ecc70f7d48e4fb815171e78d3f9166cd8a3b 100644
--- a/test/nilptr/structfield.go
+++ b/test/nilptr/structfield.go
@@ -1,3 +1,4 @@
+// [ $GOOS != nacl ] || exit 0  # do not bother on NaCl
 // $G $D/$F.go && $L $F.$A &&
 //	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
 
diff --git a/test/nilptr/structfield1.go b/test/nilptr/structfield1.go
index 520136805fb6f60d47a4ed484c6be58e402fd457..1a120890a0717cba477936f144dbb992a50072a6 100644
--- a/test/nilptr/structfield1.go
+++ b/test/nilptr/structfield1.go
@@ -1,3 +1,4 @@
+// [ $GOOS != nacl ] || exit 0  # do not bother on NaCl
 // $G $D/$F.go && $L $F.$A &&
 //	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
 
diff --git a/test/nilptr/structfield2.go b/test/nilptr/structfield2.go
index a0a552c933394dd37e31a9c3aff73bc211b79e26..25ea8f665c36b55de4cb3e2db17308960f111b02 100644
--- a/test/nilptr/structfield2.go
+++ b/test/nilptr/structfield2.go
@@ -1,3 +1,4 @@
+// [ $GOOS != nacl ] || exit 0  # do not bother on NaCl
 // $G $D/$F.go && $L $F.$A &&
 //	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
 
diff --git a/test/nilptr/structfieldaddr.go b/test/nilptr/structfieldaddr.go
index 32e9f79315a83597f22943013db3441f59fe6fca..b5d370ca8b88b9986c944a77b4ebaf415edace41 100644
--- a/test/nilptr/structfieldaddr.go
+++ b/test/nilptr/structfieldaddr.go
@@ -1,3 +1,4 @@
+// [ $GOOS != nacl ] || exit 0  # do not bother on NaCl
 // $G $D/$F.go && $L $F.$A &&
 //	((! sh -c ./$A.out) >/dev/null 2>&1 || echo BUG: should fail)
 
diff --git a/test/nul1.go b/test/nul1.go
index 026d397544a02319a097956fdbfd9b90723e9ba5..5e459633124c1476a59793a6d2279a999d776336 100644
--- a/test/nul1.go
+++ b/test/nul1.go
@@ -1,3 +1,4 @@
+// [ $GOOS != nacl ] || exit 0  # NaCl runner elides NUL in output
 // $G $D/$F.go && $L $F.$A && ./$A.out >tmp.go &&
 // errchk $G -e tmp.go
 // rm -f tmp.go
diff --git a/test/recover3.go b/test/recover3.go
index f719b0ced1a5c6bc004928c4ff38025e9685c3a3..b982ec8fa5431332c138f67b063366b07cb79acc 100644
--- a/test/recover3.go
+++ b/test/recover3.go
@@ -1,3 +1,4 @@
+// [ $GOOS != nacl ] || exit 0  # NaCl cannot recover from signals
 // $G $D/$F.go && $L $F.$A && ./$A.out
 
 // Copyright 2010 The Go Authors.  All rights reserved.
diff --git a/test/run b/test/run
index 78014c867f6222f43e6e96203bd14188afbbdcb7..b3f54f12f24cdf2d1c5f9bcc10e92781700a13e1 100755
--- a/test/run
+++ b/test/run
@@ -22,7 +22,7 @@ esac
 
 case X"$GOOS" in
 Xnacl)
-	export E="nacl"
+	export E=${GORUN:-$GOROOT/misc/nacl/naclrun}
 esac
 
 export G=${A}g
diff --git a/test/run-nacl b/test/run-nacl
deleted file mode 100755
index 2f5b7ba26f082399773f5479e74d15bf6c698237..0000000000000000000000000000000000000000
--- a/test/run-nacl
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/bin/sh
-# Copyright 2009 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-case X"$GOARCH" in
-X386)
-	# After downloading the Native Client binary distribution,
-	# copy build/native_client/scons-out/opt-*/obj/src/trusted/service_runtime/sel_ldr
-	# into your path as "nacl".  You might need to wrap it to get rid of the
-	# 'Exit syscall handler' print.  To do that, install the binary as nacl.bin and
-	# make this script nacl: 
-	#	#!/bin/sh
-	#	nacl.bin "$@" 2>&1 | grep -v 'Exit syscall handler: 0'
-	#	exit 0
-	export A=8
-	export E=nacl
-	;;
-*)
-	echo 1>&2 run: unsupported '$GOARCH'
-	exit 1
-esac
-
-export G=${A}g
-export L=${A}l
-export GOTRACEBACK=0
-
-failed=0
-
-export PATH=/bin:/usr/bin:/usr/local/bin:${GOBIN:-$HOME/bin}:$HOME/bin:$(pwd)
-
-RUNFILE=/tmp/gorun-$$-$USER
-TMP1FILE=/tmp/gotest1-$$-$USER
-TMP2FILE=/tmp/gotest2-$$-$USER
-
-# don't run the machine out of memory: limit individual processes to 4GB.
-# on thresher, 3GB suffices to run the tests; with 2GB, peano fails.
-ulimit -v 4000000
-
-for i in $(cat nacl-pass.txt)
-do
-	export F=$(basename $i .go)
-	dir=$(dirname $i)
-	export D=$dir
-	sed '/^\/\//!q; s|//||g; s|./\$A.out|$E &|' $i >$RUNFILE
-	if ! sh $RUNFILE >$TMP1FILE 2>$TMP2FILE
-	then
-		echo
-		echo "===========" $i
-		cat $TMP1FILE
-		cat $TMP2FILE
-		echo >&2 fail: $i
-	elif test -s $TMP1FILE || test -s $TMP2FILE
-	then
-		echo
-		echo "===========" $i
-		cat $TMP1FILE
-		cat $TMP2FILE
-	elif [ $dir = "bugs" ]
-	then
-		echo $i succeeded with no output.
-	fi
-done | # clean up some stack noise
-	egrep -v '^(r[0-9a-z]+|[cfg]s)  +0x'  |
-	sed '/tmp.*Bus error/s/.*Bus/Bus/; /tmp.*Trace.BPT/s/.*Trace/Trace/
-		s!'$RUNFILE'!$RUNFILE!g
-		s/ PC=0x[0-9a-f]*/ PC=xxx/
-		s/^pc: 0x[0-9a-f]*/pc: xxx/
-		/^Trace\/breakpoint trap/d
-		/^Trace\/BPT trap/d
-		/RUNFILE/ s/line 1: *[0-9][0-9]* /line 1: PID /
-		/^\$RUNFILE: line 1: PID Trace\/breakpoint trap/d
-		/^qemu: uncaught target signal 11 (Segmentation fault) - exiting/d' > run.out
-
-case $failed in
-0)
-	echo PASS
-	;;
-1)
-	echo FAIL
-esac
-rm  -f $RUNFILE $TMP1FILE $TMP2FILE *.$A $A.out
-
-exit $failed
diff --git a/test/sigchld.go b/test/sigchld.go
index 5b95314df643ddad02269b9b686e05eefc692c0e..3887e2d024c693f2ac75be2089cfcdb109a77d85 100644
--- a/test/sigchld.go
+++ b/test/sigchld.go
@@ -1,3 +1,4 @@
+// if [ $GOOS == nacl ]; then echo survived SIGCHLD; exit 0; fi  # NaCl has no signals.
 // $G $D/$F.go && $L $F.$A && ./$A.out
 
 // Copyright 2009 The Go Authors. All rights reserved.
diff --git a/test/stack.go b/test/stack.go
index 168830f70ae34662eb54a5b61402142797dce047..816b555a4c8849618a26ad9498fead3878c52d6b 100644
--- a/test/stack.go
+++ b/test/stack.go
@@ -68,5 +68,5 @@ func main() {
 	for i := 0; i < len(t); i++ {
 		t[i] = 1
 	}
-	recur(10000)
+	recur(8000)
 }