From 4b3acaf327dcb3d5b6ffe35f4f82a4b8a8af9cb9 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Mon, 29 Oct 2018 22:59:38 +0000
Subject: cmd: build for Haiku amd64.


diff --git a/src/cmd/5l/asm.c b/src/cmd/5l/asm.c
index 9c1c04e..7af74ea 100644
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -38,6 +38,7 @@
 
 char linuxdynld[] = "/lib/ld-linux.so.3"; // 2 for OABI, 3 for EABI
 char freebsddynld[] = "/usr/libexec/ld-elf.so.1";
+char haikudynld[] = "XXX";
 char openbsddynld[] = "XXX";
 char netbsddynld[] = "/libexec/ld.elf_so";
 char dragonflydynld[] = "XXX";
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index 18b5aa3..18b27cf 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -41,6 +41,7 @@
 
 char linuxdynld[] = "/lib64/ld-linux-x86-64.so.2";
 char freebsddynld[] = "/libexec/ld-elf.so.1";
+char haikudynld[] = "/system/runtime_loader";
 char openbsddynld[] = "/usr/libexec/ld.so";
 char netbsddynld[] = "/libexec/ld.elf_so";
 char dragonflydynld[] = "/usr/libexec/ld-elf.so.2";
@@ -301,7 +302,15 @@ elfreloc1(Reloc *r, vlong sectoff)
 
 	case R_PCREL:
 		if(r->siz == 4) {
-			VPUT(R_X86_64_PC32 | (uint64)elfsym<<32);
+			// HACK to fix relocation issue with Haiku //
+			if(HEADTYPE == Hhaiku) {
+				if(r->xsym->type == SDYNIMPORT)
+					VPUT(R_X86_64_GOTPCREL | (uint64)elfsym<<32);
+				else
+					VPUT(R_X86_64_PC32 | (uint64)elfsym<<32);
+			////
+			} else
+				VPUT(R_X86_64_PC32 | (uint64)elfsym<<32);
 		} else
 			return -1;
 		break;
@@ -674,6 +683,7 @@ asmb(void)
 		break;
 	case Hlinux:
 	case Hfreebsd:
+	case Hhaiku:
 	case Hnetbsd:
 	case Hopenbsd:
 	case Hdragonfly:
@@ -705,6 +715,7 @@ asmb(void)
 			break;
 		case Hlinux:
 		case Hfreebsd:
+		case Hhaiku:
 		case Hnetbsd:
 		case Hopenbsd:
 		case Hdragonfly:
@@ -787,6 +798,7 @@ asmb(void)
 		break;
 	case Hlinux:
 	case Hfreebsd:
+	case Hhaiku:
 	case Hnetbsd:
 	case Hopenbsd:
 	case Hdragonfly:
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index 3b8e8f4..9641f70 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -72,6 +72,7 @@ archinit(void)
 	case Hdarwin:
 	case Hdragonfly:
 	case Hfreebsd:
+	case Hhaiku:
 	case Hlinux:
 	case Hnacl:
 	case Hnetbsd:
@@ -114,6 +115,7 @@ archinit(void)
 		break;
 	case Hlinux:		/* elf64 executable */
 	case Hfreebsd:		/* freebsd */
+	case Hhaiku:		/* haiku */
 	case Hnetbsd:		/* netbsd */
 	case Hopenbsd:		/* openbsd */
 	case Hdragonfly:	/* dragonfly */
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index 98c0424..3282dbc 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -39,6 +39,7 @@
 
 char linuxdynld[] = "/lib/ld-linux.so.2";
 char freebsddynld[] = "/usr/libexec/ld-elf.so.1";
+char haikudynld[] = "/system/runtime_loader";
 char openbsddynld[] = "/usr/libexec/ld.so";
 char netbsddynld[] = "/usr/libexec/ld.elf_so";
 char dragonflydynld[] = "/usr/libexec/ld-elf.so.2";
diff --git a/src/cmd/cc/lex.c b/src/cmd/cc/lex.c
index 7c9f718..4ae1422 100644
--- a/src/cmd/cc/lex.c
+++ b/src/cmd/cc/lex.c
@@ -129,7 +129,7 @@ main(int argc, char *argv[])
 		ewidth[TIND] = 4;
 		
 	nacl = strcmp(getgoos(), "nacl") == 0;
-	if(nacl)
+	if(nacl || strcmp(getgoos(), "haiku") == 0)
 		flag_largemodel = 1;
 
 	quotefmtinstall(); // before cinit, which overrides %Q
diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c
index 8d82167..6319c00 100644
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -58,6 +58,7 @@ static char *okgoos[] = {
 	"android",
 	"solaris",
 	"freebsd",
+	"haiku",
 	"nacl",
 	"netbsd",
 	"openbsd",
@@ -1103,8 +1104,14 @@ install(char *dir)
 	if(!islib && !isgo) {
 		// C binaries need the libraries explicitly, and -lm.
 		vcopy(&link, lib.p, lib.len);
-		if(!streq(gohostos, "plan9"))
+		if(!streq(gohostos, "plan9") && !streq(gohostos, "haiku"))
 			vadd(&link, "-lm");
+		
+		// Haiku needs -lbsd for wait4().
+		// TODO(bga): Revisit this as it is probably overkill to link against
+		// -lbsd just for wait4().
+		if(streq(gohostos, "haiku"))
+			vadd(&link, "-lbsd");
 	}
 
 	// Remove target before writing it.
diff --git a/src/cmd/dist/unix.c b/src/cmd/dist/unix.c
index 4a78684..93b640e 100644
--- a/src/cmd/dist/unix.c
+++ b/src/cmd/dist/unix.c
@@ -466,7 +466,11 @@ xworkdir(void)
 
 	xgetenv(&b, "TMPDIR");
 	if(b.len == 0)
+#if defined(__HAIKU__)
+		bwritestr(&b, "/tmp");
+#else
 		bwritestr(&b, "/var/tmp");
+#endif
 	if(b.p[b.len-1] != '/')
 		bwrite(&b, "/", 1);
 	bwritestr(&b, "go-cbuild-XXXXXX");
@@ -695,6 +699,14 @@ main(int argc, char **argv)
 		gohostarch = "amd64";
 	if(contains(bstr(&b), "i386"))
 		gohostarch = "386";
+#elif defined(__HAIKU__)
+	gohostos = "haiku";
+	// Under a Haiku PC, uname -m will always print BePC.
+	run(&b, nil, 0, "uname", "-p", nil);
+	if(contains(bstr(&b), "x86_64"))
+		gohostarch = "amd64";
+	else if(contains(bstr(&b), "x86"))
+		gohostarch = "386";	 
 #else
 	fatal("unknown operating system");
 #endif
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 523ba37..bb954fc 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -267,7 +267,7 @@ main(int argc, char *argv[])
 	goos = getgoos();
 
 	nacl = strcmp(goos, "nacl") == 0;
-	if(nacl)
+	if(nacl || strcmp(goos, "haiku") == 0)
 		flag_largemodel = 1;
 
 	setexp();
diff --git a/src/cmd/go/signal_unix.go b/src/cmd/go/signal_unix.go
index e86cd46..9e2fe0e 100644
--- a/src/cmd/go/signal_unix.go
+++ b/src/cmd/go/signal_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris
 
 package main
 
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c
index 6184754..d8168a3 100644
--- a/src/cmd/ld/data.c
+++ b/src/cmd/ld/data.c
@@ -155,7 +155,7 @@ relocsym(LSym *s)
 			continue;
 
 		// Solaris needs the ability to reference dynimport symbols.
-		if(HEADTYPE != Hsolaris && r->sym != S && r->sym->type == SDYNIMPORT)
+		if(HEADTYPE != Hsolaris && HEADTYPE != Hhaiku && r->sym != S && r->sym->type == SDYNIMPORT)
 			diag("unhandled relocation for %s (type %d rtype %d)", r->sym->name, r->sym->type, r->type);
 		if(r->sym != S && r->sym->type != STLSBSS && !r->sym->reachable)
 			diag("unreachable sym in relocation: %s %s", s->name, r->sym->name);
@@ -188,7 +188,7 @@ relocsym(LSym *s)
 				o = r->add;
 			break;
 		case R_TLS_LE:
-			if(linkmode == LinkExternal && iself && HEADTYPE != Hopenbsd) {
+			if(linkmode == LinkExternal && iself && HEADTYPE != Hopenbsd && HEADTYPE != Hhaiku) {
 				r->done = 0;
 				r->sym = ctxt->tlsg;
 				r->xsym = ctxt->tlsg;
@@ -202,7 +202,7 @@ relocsym(LSym *s)
 			break;
 
 		case R_TLS_IE:
-			if(linkmode == LinkExternal && iself && HEADTYPE != Hopenbsd) {
+			if(linkmode == LinkExternal && iself && HEADTYPE != Hopenbsd && HEADTYPE != Hhaiku) {
 				r->done = 0;
 				r->sym = ctxt->tlsg;
 				r->xsym = ctxt->tlsg;
@@ -1088,7 +1088,7 @@ dodata(void)
 		diag("data or bss segment too large");
 	}
 	
-	if(iself && linkmode == LinkExternal && s != nil && s->type == STLSBSS && HEADTYPE != Hopenbsd) {
+	if(iself && linkmode == LinkExternal && s != nil && s->type == STLSBSS && HEADTYPE != Hopenbsd && HEADTYPE != Hhaiku) {
 		sect = addsection(&segdata, ".tbss", 06);
 		sect->align = PtrSize;
 		sect->vaddr = 0;
diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c
index 3196961..b34a227 100644
--- a/src/cmd/ld/elf.c
+++ b/src/cmd/ld/elf.c
@@ -911,7 +911,7 @@ doelf(void)
 	// for dynamic internal linker or external linking, so that various
 	// binutils could correctly calculate PT_TLS size.
 	// see http://golang.org/issue/5200.
-	if(HEADTYPE != Hopenbsd)
+	if(HEADTYPE != Hopenbsd && HEADTYPE != Hhaiku)
 	if(!debug['d'] || linkmode == LinkExternal)
 		addstring(shstrtab, ".tbss");
 	if(HEADTYPE == Hnetbsd)
@@ -1198,6 +1198,9 @@ asmbelf(vlong symo)
 			case Hfreebsd:
 				interpreter = freebsddynld;
 				break;
+			case Hhaiku:
+				interpreter = haikudynld;
+				break;
 			case Hnetbsd:
 				interpreter = netbsddynld;
 				break;
@@ -1387,7 +1390,7 @@ asmbelf(vlong symo)
 		// Do not emit PT_TLS for OpenBSD since ld.so(1) does
 		// not currently support it. This is handled
 		// appropriately in runtime/cgo.
-		if(ctxt->tlsoffset != 0 && HEADTYPE != Hopenbsd) {
+		if(ctxt->tlsoffset != 0 && HEADTYPE != Hopenbsd && HEADTYPE != Hhaiku) {
 			ph = newElfPhdr();
 			ph->type = PT_TLS;
 			ph->flags = PF_R;
@@ -1444,7 +1447,7 @@ elfobj:
 
 	// generate .tbss section for dynamic internal linking (except for OpenBSD)
 	// external linking generates .tbss in data.c
-	if(linkmode == LinkInternal && !debug['d'] && HEADTYPE != Hopenbsd) {
+	if(linkmode == LinkInternal && !debug['d'] && HEADTYPE != Hopenbsd && HEADTYPE != Hhaiku) {
 		sh = elfshname(".tbss");
 		sh->type = SHT_NOBITS;
 		sh->addralign = RegSize;
diff --git a/src/cmd/ld/elf.h b/src/cmd/ld/elf.h
index e84d996..3796967 100644
--- a/src/cmd/ld/elf.h
+++ b/src/cmd/ld/elf.h
@@ -1007,6 +1007,7 @@ void	asmbelf(vlong symo);
 void	asmbelfsetup(void);
 extern char linuxdynld[];
 extern char freebsddynld[];
+extern char haikudynld[];
 extern char netbsddynld[];
 extern char openbsddynld[];
 extern char dragonflydynld[];
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index f889aba..abfd4b7 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -208,7 +208,9 @@ loadlib(void)
 		// The startup code uses an import of runtime/cgo to decide
 		// whether to initialize the TLS.  So give it one.  This could
 		// be handled differently but it's an unusual case.
-		loadinternal("runtime/cgo");
+		if(HEADTYPE != Hhaiku)
+			loadinternal("runtime/cgo");
+
 		if(i < ctxt->libraryp)
 			objfile(ctxt->library[i].file, ctxt->library[i].pkg);
 
@@ -290,7 +292,7 @@ loadlib(void)
 	// binaries, so leave it enabled on OS X (Mach-O) binaries.
 	// Also leave it enabled on Solaris which doesn't support
 	// statically linked binaries.
-	if(!flag_shared && !havedynamic && HEADTYPE != Hdarwin && HEADTYPE != Hsolaris)
+	if(!flag_shared && !havedynamic && HEADTYPE != Hdarwin && HEADTYPE != Hsolaris && HEADTYPE != Hhaiku)
 		debug['d'] = 1;
 	
 	importcycles();
@@ -622,6 +624,9 @@ hostlink(void)
 	
 	if(rpath)
 		argv[argc++] = smprint("-Wl,-rpath,%s", rpath);
+	
+	if(iself && HEADTYPE != Hhaiku)
+		argv[argc++] = "-rdynamic";
 
 	// Force global symbols to be exported for dlopen, etc.
 	if(iself)
diff --git a/src/cmd/ld/pobj.c b/src/cmd/ld/pobj.c
index 63460df..4e8152e 100644
--- a/src/cmd/ld/pobj.c
+++ b/src/cmd/ld/pobj.c
@@ -150,6 +150,8 @@ main(int argc, char *argv[])
 	ctxt->headtype = HEADTYPE;
 	if(headstring == nil)
 		headstring = headstr(HEADTYPE);
+	if(HEADTYPE == Hhaiku)
+		linkmode = LinkExternal;
 
 	archinit();
 	ctxt->debugfloat = debug['F'];
diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c
index 156270c..53e9160 100644
--- a/src/cmd/ld/symtab.c
+++ b/src/cmd/ld/symtab.c
@@ -197,7 +197,7 @@ asmelfsym(void)
 	elfbind = STB_LOCAL;
 	genasmsym(putelfsym);
 	
-	if(linkmode == LinkExternal && HEADTYPE != Hopenbsd) {
+	if(linkmode == LinkExternal && HEADTYPE != Hopenbsd && HEADTYPE != Hhaiku) {
 		s = linklookup(ctxt, "runtime.tlsg", 0);
 		if(s->sect == nil) {
 			ctxt->cursym = nil;
-- 
2.19.1


From 3da5197df7c37a612a066acde216bef71406a033 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Mon, 29 Oct 2018 23:01:38 +0000
Subject: lib9: get lib9 building


diff --git a/src/lib9/run_unix.c b/src/lib9/run_unix.c
index 1acaefe..6c32872 100644
--- a/src/lib9/run_unix.c
+++ b/src/lib9/run_unix.c
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 #include <u.h>
 #include <errno.h>
diff --git a/src/lib9/tempdir_unix.c b/src/lib9/tempdir_unix.c
index 269d538..f4fa6dc 100644
--- a/src/lib9/tempdir_unix.c
+++ b/src/lib9/tempdir_unix.c
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 #include <u.h>
 #include <dirent.h>
@@ -17,8 +17,11 @@ mktempdir(void)
 	
 	tmp = getenv("TMPDIR");
 	if(tmp == nil || strlen(tmp) == 0)
+#ifdef __HAIKU__
+		tmp = "/tmp";
+#else
 		tmp = "/var/tmp";
-	p = smprint("%s/go-link-XXXXXX", tmp);
+#endif	p = smprint("%s/go-link-XXXXXX", tmp);
 	if(mkdtemp(p) == nil)
 		return nil;
 	return p;
-- 
2.19.1


From ac70c1ca0c29b6c4d7380c6785dcf6adca297fa3 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Mon, 29 Oct 2018 23:04:06 +0000
Subject: liblink: get liblink building on Haiku


diff --git a/src/liblink/asm6.c b/src/liblink/asm6.c
index 428eb94..44c0ec1 100644
--- a/src/liblink/asm6.c
+++ b/src/liblink/asm6.c
@@ -1545,7 +1545,12 @@ isextern(LSym *s)
 {
 	// All the Solaris dynamic imports from libc.so begin with "libc·", which
 	// the compiler rewrites to "libc." by the time liblink gets it.
+	// Haiku also uses this for dynamic imports but from libroot instead.
+#if defined(__HAIKU__)
+	return strncmp(s->name, "libroot.", 9) == 0;
+#else
 	return strncmp(s->name, "libc.", 5) == 0;
+#endif
 }
 
 // single-instruction no-ops of various lengths.
@@ -3415,6 +3420,19 @@ mfound:
 			*ctxt->andptr++ = 0x8B;
 			asmand(ctxt, &pp.from, &p->to);
 			break;
+		
+		case Hhaiku:
+			// Haiku TLS base is 0(FS).
+			pp.from = p->from;
+			pp.from.type = D_INDIR+D_GS;
+			pp.from.offset = 0;
+			pp.from.index = D_NONE;
+			pp.from.scale = 0;
+			ctxt->rexflag |= Pw;
+			*ctxt->andptr++ = 0x64; // FS
+			*ctxt->andptr++ = 0x8B;
+			asmand(ctxt, &pp.from, &p->to);
+			break;
 		}
 		break;
 	}
diff --git a/src/liblink/obj6.c b/src/liblink/obj6.c
index 2acfd2f..2d699b7 100644
--- a/src/liblink/obj6.c
+++ b/src/liblink/obj6.c
@@ -103,6 +103,7 @@ static int
 canuselocaltls(Link *ctxt)
 {
 	switch(ctxt->headtype) {
+	case Hhaiku:
 	case Hplan9:
 	case Hwindows:
 		return 0;
diff --git a/src/liblink/sym.c b/src/liblink/sym.c
index bd85518..acda518 100644
--- a/src/liblink/sym.c
+++ b/src/liblink/sym.c
@@ -48,6 +48,7 @@ static struct {
 	{"darwin",	Hdarwin},
 	{"dragonfly",	Hdragonfly},
 	{"elf",		Helf},
+	{"haiku",	Hhaiku},
 	{"freebsd",	Hfreebsd},
 	{"linux",	Hlinux},
 	{"nacl",		Hnacl},
@@ -130,6 +131,12 @@ linknew(LinkArch *arch)
 	case Hplan9:
 	case Hwindows:
 		break;
+	case Hhaiku: /* FIXME */
+		// on 64-bit we use the last two regular TLS slots
+		if(ctxt->arch->thechar == '6') {
+			ctxt->tlsoffset = (64 - 2) * 8;
+		}
+		break;
 	case Hlinux:
 	case Hfreebsd:
 	case Hnetbsd:
-- 
2.19.1


From ba8a8ba6eb058d84bc0923fdbe884dfed44a3b65 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Mon, 29 Oct 2018 23:04:58 +0000
Subject: go: Add strings to syslist for Haiku


diff --git a/include/link.h b/include/link.h
index 05e117c..50c8120 100644
--- a/include/link.h
+++ b/include/link.h
@@ -495,6 +495,7 @@ enum {
 	Hdragonfly,
 	Helf,
 	Hfreebsd,
+	Hhaiku,
 	Hlinux,
 	Hnacl,
 	Hnetbsd,
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index b74595e..61641e4 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -361,7 +361,7 @@ func allowed(pkg string) map[string]bool {
 }
 
 var bools = []bool{false, true}
-var geese = []string{"android", "darwin", "dragonfly", "freebsd", "linux", "nacl", "netbsd", "openbsd", "plan9", "solaris", "windows"}
+var geese = []string{"android", "darwin", "dragonfly", "freebsd", "haiku", "linux", "nacl", "netbsd", "openbsd", "plan9", "solaris", "windows"}
 var goarches = []string{"386", "amd64", "arm"}
 
 type osPkg struct {
diff --git a/src/go/build/syslist.go b/src/go/build/syslist.go
index 965f873..4d5906f 100644
--- a/src/go/build/syslist.go
+++ b/src/go/build/syslist.go
@@ -4,5 +4,5 @@
 
 package build
 
-const goosList = "android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows "
+const goosList = "android darwin dragonfly haiku freebsd linux nacl netbsd openbsd plan9 solaris windows "
 const goarchList = "386 amd64 amd64p32 arm "
-- 
2.19.1


From 182ec679bfe70d93bb48378acbcf5c123c98c230 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Mon, 29 Oct 2018 23:06:29 +0000
Subject: runtime: Add initial Haiku definitions to relevant packages


diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s
index 39d7c78..7e25985 100644
--- a/src/runtime/asm_amd64.s
+++ b/src/runtime/asm_amd64.s
@@ -60,6 +60,9 @@ needtls:
 	// skip TLS setup on Solaris
 	CMPL	runtime·issolaris(SB), $1
 	JEQ ok
+	// skip TLS setup on Haiku
+	CMPL	runtime·ishaiku(SB), $1
+	JEQ ok
 
 	LEAQ	runtime·tls0(SB), DI
 	CALL	runtime·settls(SB)
diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go
index 7fd9146..5e58db5 100644
--- a/src/runtime/cgocall.go
+++ b/src/runtime/cgocall.go
@@ -89,7 +89,7 @@ func cgocall(fn, arg unsafe.Pointer) {
 
 //go:nosplit
 func cgocall_errno(fn, arg unsafe.Pointer) int32 {
-	if !iscgo && GOOS != "solaris" && GOOS != "windows" {
+	if !iscgo && GOOS != "solaris" && GOOS != "windows" && GOOS != "haiku" {
 		gothrow("cgocall unavailable")
 	}
 
diff --git a/src/runtime/env_posix.go b/src/runtime/env_posix.go
index dd57872..ef9c294 100644
--- a/src/runtime/env_posix.go
+++ b/src/runtime/env_posix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris windows
 
 package runtime
 
diff --git a/src/runtime/lock_sema.go b/src/runtime/lock_sema.go
index d136b82..0604f13 100644
--- a/src/runtime/lock_sema.go
+++ b/src/runtime/lock_sema.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin nacl netbsd openbsd plan9 solaris windows
+// +build darwin haiku nacl netbsd openbsd plan9 solaris windows
 
 package runtime
 
@@ -200,7 +200,9 @@ func notetsleep_internal(n *note, ns int64, gp *g, deadline int64) bool {
 	for {
 		// Registered.  Sleep.
 		gp.m.blocked = true
-		if semasleep(ns) >= 0 {
+		// HACK for Haiku support.
+		if semasleep(deadline) >= 0 {
+			//if semasleep(ns) >= 0 {
 			gp.m.blocked = false
 			// Acquired semaphore, semawakeup unregistered us.
 			// Done.
diff --git a/src/runtime/mheap.c b/src/runtime/mheap.c
index bb203d5..67de821 100644
--- a/src/runtime/mheap.c
+++ b/src/runtime/mheap.c
@@ -608,6 +608,8 @@ scavengelist(MSpan *list, uint64 now, uint64 limit)
 void
 runtime·MHeap_Scavenge(int32 k, uint64 now, uint64 limit)
 {
+	//HACK: Disable GC for Haiku
+	/*
 	uint32 i;
 	uintptr sumreleased;
 	MHeap *h;
@@ -629,6 +631,7 @@ runtime·MHeap_Scavenge(int32 k, uint64 now, uint64 limit)
 			k, mstats.heap_inuse>>20, mstats.heap_idle>>20, mstats.heap_sys>>20,
 			mstats.heap_released>>20, (mstats.heap_sys - mstats.heap_released)>>20);
 	}
+	*/
 }
 
 void
diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go
index 8677cb3..3da28f9 100644
--- a/src/runtime/pprof/pprof_test.go
+++ b/src/runtime/pprof/pprof_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !nacl
+// +build !haiku !nacl
 
 package pprof_test
 
diff --git a/src/runtime/proc.c b/src/runtime/proc.c
index 8462c4b..d8377ac 100644
--- a/src/runtime/proc.c
+++ b/src/runtime/proc.c
@@ -902,7 +902,7 @@ runtime·allocm(P *p)
 
 	// In case of cgo or Solaris, pthread_create will make us a stack.
 	// Windows and Plan 9 will layout sched stack on OS stack.
-	if(runtime·iscgo || Solaris || Windows || Plan9)
+	if(runtime·iscgo || Haiku || Solaris || Windows || Plan9)
 		mp->g0 = runtime·malg(-1);
 	else
 		mp->g0 = runtime·malg(8192);
diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c
index c823691..25408c3 100644
--- a/src/runtime/runtime.c
+++ b/src/runtime/runtime.c
@@ -80,6 +80,7 @@ runtime·args(int32 c, uint8 **v)
 		runtime·sysargs(c, v);
 }
 
+int32 runtime·ishaiku;
 int32 runtime·isplan9;
 int32 runtime·issolaris;
 int32 runtime·iswindows;
diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h
index 177a128..c24d5d9 100644
--- a/src/runtime/runtime.h
+++ b/src/runtime/runtime.h
@@ -392,6 +392,19 @@ struct	M
 		uintptr v[6];
 	} scratch;
 #endif
+#ifdef GOOS_haiku
+	int32*	perrno; 	// pointer to TLS errno
+	// these are here because they are too large to be on the stack
+	// of low-level NOSPLIT functions.
+	LibCall	libcall;
+	struct MTs {
+		int64	tv_sec;
+		int64	tv_nsec;
+	} ts;
+	struct MScratch {
+		uintptr v[6];
+	} scratch;
+#endif
 #ifdef GOOS_plan9
 	int8*	notesig;
 	byte*	errstr;
@@ -559,6 +572,15 @@ enum {
    Solaris = 0
 };
 #endif
+#ifdef GOOS_haiku
+enum {
+   Haiku = 1
+};
+#else
+enum {
+   Haiku = 0
+};
+#endif
 #ifdef GOOS_plan9
 enum {
    Plan9 = 1
diff --git a/src/runtime/signal_amd64x.c b/src/runtime/signal_amd64x.c
index feb4afc..26d0680 100644
--- a/src/runtime/signal_amd64x.c
+++ b/src/runtime/signal_amd64x.c
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // +build amd64 amd64p32
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris
 
 #include "runtime.h"
 #include "defs_GOOS_GOARCH.h"
diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go
index ba77b6e..f75eb92 100644
--- a/src/runtime/signal_unix.go
+++ b/src/runtime/signal_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 package runtime
 
diff --git a/src/runtime/sigpanic_unix.go b/src/runtime/sigpanic_unix.go
index 6807985..5cd9a2a 100644
--- a/src/runtime/sigpanic_unix.go
+++ b/src/runtime/sigpanic_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 package runtime
 
-- 
2.19.1


From a08b9cba21ee1a00629e8808c0b117ab60922207 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Mon, 29 Oct 2018 23:07:50 +0000
Subject: runtime: Add Haiku specific patches for building runtime


diff --git a/src/runtime/defs_haiku.go b/src/runtime/defs_haiku.go
new file mode 100644
index 0000000..d0ea4fe
--- /dev/null
+++ b/src/runtime/defs_haiku.go
@@ -0,0 +1,160 @@
+// 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.
+
+// +build ignore
+
+/*
+Input to cgo.
+
+GOARCH=amd64 go tool cgo -cdefs defs_haiku.go >defs_haiku_amd64.h
+GOARCH=386 go tool cgo -cdefs defs_haiku.go >defs_haiku_386.h
+GOARCH=arm go tool cgo -cdefs defs_haiku.go >defs_haiku_arm.h
+*/
+
+package runtime
+
+/*
+#include <sys/types.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <semaphore.h>
+#include <pthread.h>
+
+#include <kernel/OS.h>
+
+#ifdef __x86_64__
+struct extended_regs {
+	// not used anywhere; just to make this file compile (stub of struct used in the 386 version)
+};
+#else
+struct xmm_regs {
+	// not used anywhere, just to make this compile (stub of struct used in x86_64)
+}
+struct fpu_state {
+	// ditto
+}
+#endif
+*/
+import "C"
+
+const (
+	EINTR     = C.EINTR
+	EFAULT    = C.EFAULT
+	EAGAIN    = C.EAGAIN
+	ENOMEM    = C.ENOMEM
+	ETIMEDOUT = C.ETIMEDOUT
+	EACCES    = C.EACCES
+
+	PROT_NONE  = C.PROT_NONE
+	PROT_READ  = C.PROT_READ
+	PROT_WRITE = C.PROT_WRITE
+	PROT_EXEC  = C.PROT_EXEC
+
+	MAP_ANON    = C.MAP_ANON
+	MAP_PRIVATE = C.MAP_PRIVATE
+	MAP_FIXED   = C.MAP_FIXED
+
+	SA_SIGINFO = C.SA_SIGINFO
+	SA_RESTART = C.SA_RESTART
+	SA_ONSTACK = C.SA_ONSTACK
+
+	SIGHUP    = C.SIGHUP
+	SIGINT    = C.SIGINT
+	SIGQUIT   = C.SIGQUIT
+	SIGILL    = C.SIGILL
+	SIGTRAP   = C.SIGTRAP
+	SIGABRT   = C.SIGABRT
+	SIGFPE    = C.SIGFPE
+	SIGKILL   = C.SIGKILL
+	SIGBUS    = C.SIGBUS
+	SIGSEGV   = C.SIGSEGV
+	SIGSYS    = C.SIGSYS
+	SIGPIPE   = C.SIGPIPE
+	SIGALRM   = C.SIGALRM
+	SIGTERM   = C.SIGTERM
+	SIGURG    = C.SIGURG
+	SIGSTOP   = C.SIGSTOP
+	SIGTSTP   = C.SIGTSTP
+	SIGCONT   = C.SIGCONT
+	SIGCHLD   = C.SIGCHLD
+	SIGTTIN   = C.SIGTTIN
+	SIGTTOU   = C.SIGTTOU
+	SIGXCPU   = C.SIGXCPU
+	SIGXFSZ   = C.SIGXFSZ
+	SIGVTALRM = C.SIGVTALRM
+	SIGPROF   = C.SIGPROF
+	SIGWINCH  = C.SIGWINCH
+	SIGUSR1   = C.SIGUSR1
+	SIGUSR2   = C.SIGUSR2
+
+	FPE_INTDIV = C.FPE_INTDIV
+	FPE_INTOVF = C.FPE_INTOVF
+	FPE_FLTDIV = C.FPE_FLTDIV
+	FPE_FLTOVF = C.FPE_FLTOVF
+	FPE_FLTUND = C.FPE_FLTUND
+	FPE_FLTRES = C.FPE_FLTRES
+	FPE_FLTINV = C.FPE_FLTINV
+	FPE_FLTSUB = C.FPE_FLTSUB
+
+	BUS_ADRALN = C.BUS_ADRALN
+	BUS_ADRERR = C.BUS_ADRERR
+	BUS_OBJERR = C.BUS_OBJERR
+
+	SEGV_MAPERR = C.SEGV_MAPERR
+	SEGV_ACCERR = C.SEGV_ACCERR
+
+	ITIMER_REAL    = C.ITIMER_REAL
+	ITIMER_VIRTUAL = C.ITIMER_VIRTUAL
+	ITIMER_PROF    = C.ITIMER_PROF
+
+	PTHREAD_CREATE_DETACHED = C.PTHREAD_CREATE_DETACHED
+
+	HOST_NAME_MAX = C.HOST_NAME_MAX
+
+	O_NONBLOCK = C.O_NONBLOCK
+	FD_CLOEXEC = C.FD_CLOEXEC
+	F_GETFL    = C.F_GETFL
+	F_SETFL    = C.F_SETFL
+	F_SETFD    = C.F_SETFD
+
+	_SC_NPROCESSORS_ONLN = C._SC_NPROCESSORS_ONLN
+
+	_MAXHOSTNAMELEN = C.MAXHOSTNAMELEN
+
+	B_PAGE_SIZE = C.B_PAGE_SIZE
+
+	B_ERROR = C.B_ERROR
+)
+
+type SemT C.sem_t
+
+type Sigset C.sigset_t
+type StackT C.stack_t
+type SigaltstackT StackT
+
+type Siginfo C.siginfo_t
+type Sigaction C.struct_sigaction
+
+// needed by Mcontext
+// for 386
+type ExtendedRegs C.struct_extended_regs
+
+// for amd64
+type XmmRegs C.struct_xmm_regs
+type FpuState C.struct_fpu_state
+
+type Mcontext C.mcontext_t
+type Ucontext C.ucontext_t
+
+type Timespec C.struct_timespec
+type Timeval C.struct_timeval
+type Itimerval C.struct_itimerval
+
+type Pthread C.pthread_t
+type PthreadAttr C.pthread_attr_t
+
+// depends on Timespec, must appear below
+type Stat C.struct_stat
diff --git a/src/runtime/defs_haiku_amd64.h b/src/runtime/defs_haiku_amd64.h
new file mode 100644
index 0000000..fd4f2bf
--- /dev/null
+++ b/src/runtime/defs_haiku_amd64.h
@@ -0,0 +1,244 @@
+// Created by cgo -cdefs - DO NOT EDIT
+// cgo -cdefs defs_haiku.go
+
+
+enum {
+	EINTR		= -0x7ffffff6,
+	EFAULT		= -0x7fffecff,
+	EAGAIN		= -0x7ffffff5,
+	ENOMEM		= -0x80000000,
+	ETIMEDOUT	= -0x7ffffff7,
+	EACCES		= -0x7ffffffe,
+
+	PROT_NONE	= 0x0,
+	PROT_READ	= 0x1,
+	PROT_WRITE	= 0x2,
+	PROT_EXEC	= 0x4,
+
+	MAP_ANON	= 0x8,
+	MAP_PRIVATE	= 0x2,
+	MAP_FIXED	= 0x4,
+
+	SA_SIGINFO	= 0x40,
+	SA_RESTART	= 0x10,
+	SA_ONSTACK	= 0x20,
+
+	SIGHUP		= 0x1,
+	SIGINT		= 0x2,
+	SIGQUIT		= 0x3,
+	SIGILL		= 0x4,
+	SIGTRAP		= 0x16,
+	SIGABRT		= 0x6,
+	SIGFPE		= 0x8,
+	SIGKILL		= 0x9,
+	SIGBUS		= 0x1e,
+	SIGSEGV		= 0xb,
+	SIGSYS		= 0x19,
+	SIGPIPE		= 0x7,
+	SIGALRM		= 0xe,
+	SIGTERM		= 0xf,
+	SIGURG		= 0x1a,
+	SIGSTOP		= 0xa,
+	SIGTSTP		= 0xd,
+	SIGCONT		= 0xc,
+	SIGCHLD		= 0x5,
+	SIGTTIN		= 0x10,
+	SIGTTOU		= 0x11,
+	SIGXCPU		= 0x1c,
+	SIGXFSZ		= 0x1d,
+	SIGVTALRM	= 0x1b,
+	SIGPROF		= 0x18,
+	SIGWINCH	= 0x14,
+	SIGUSR1		= 0x12,
+	SIGUSR2		= 0x13,
+
+	FPE_INTDIV	= 0x14,
+	FPE_INTOVF	= 0x15,
+	FPE_FLTDIV	= 0x16,
+	FPE_FLTOVF	= 0x17,
+	FPE_FLTUND	= 0x18,
+	FPE_FLTRES	= 0x19,
+	FPE_FLTINV	= 0x1a,
+	FPE_FLTSUB	= 0x1b,
+
+	BUS_ADRALN	= 0x28,
+	BUS_ADRERR	= 0x29,
+	BUS_OBJERR	= 0x2a,
+
+	SEGV_MAPERR	= 0x1e,
+	SEGV_ACCERR	= 0x1f,
+
+	ITIMER_REAL	= 0x1,
+	ITIMER_VIRTUAL	= 0x2,
+	ITIMER_PROF	= 0x3,
+
+	PTHREAD_CREATE_DETACHED	= 0x1,
+
+	HOST_NAME_MAX	= 0xff,
+
+	O_NONBLOCK	= 0x80,
+	FD_CLOEXEC	= 0x1,
+	F_GETFL		= 0x8,
+	F_SETFL		= 0x10,
+	F_SETFD		= 0x4,
+
+	_SC_NPROCESSORS_ONLN	= 0x23,
+
+	_MAXHOSTNAMELEN	= 0x100,
+
+	B_PAGE_SIZE	= 0x1000,
+
+	B_ERROR	= -0x1,
+};
+
+typedef struct SemT SemT;
+typedef struct StackT StackT;
+typedef struct Siginfo Siginfo;
+typedef struct SigactionT SigactionT;
+typedef struct ExtendedRegs ExtendedRegs;
+typedef struct XmmRegs XmmRegs;
+typedef struct FpuState FpuState;
+typedef struct Mcontext Mcontext;
+typedef struct Ucontext Ucontext;
+typedef struct Timespec Timespec;
+typedef struct Timeval Timeval;
+typedef struct Itimerval Itimerval;
+typedef struct Stat Stat;
+
+#pragma pack on
+
+struct SemT {
+	int32	id;
+	int32	_padding[3];
+};
+
+typedef	uint64	Sigset;
+struct StackT {
+	byte	*ss_sp;
+	uint64	ss_size;
+	int32	ss_flags;
+	byte	Pad_cgo_0[4];
+};
+typedef	StackT	SigaltstackT;
+
+struct Siginfo {
+	int32	si_signo;
+	int32	si_code;
+	int32	si_errno;
+	int32	si_pid;
+	uint32	si_uid;
+	byte	Pad_cgo_0[4];
+	byte	*si_addr;
+	int32	si_status;
+	byte	Pad_cgo_1[4];
+	int64	si_band;
+	byte	si_value[8];
+};
+struct SigactionT {
+	byte	anon0[8];
+	uint64	sa_mask;
+	int32	sa_flags;
+	byte	Pad_cgo_0[4];
+	byte	*sa_userdata;
+};
+
+
+struct XmmRegs {
+	uint8	xmm0[16];
+	uint8	xmm1[16];
+	uint8	xmm2[16];
+	uint8	xmm3[16];
+	uint8	xmm4[16];
+	uint8	xmm5[16];
+	uint8	xmm6[16];
+	uint8	xmm7[16];
+	uint8	xmm8[16];
+	uint8	xmm9[16];
+	uint8	xmm10[16];
+	uint8	xmm11[16];
+	uint8	xmm12[16];
+	uint8	xmm13[16];
+	uint8	xmm14[16];
+	uint8	xmm15[16];
+};
+struct FpuState {
+	uint16	control;
+	uint16	status;
+	uint16	tag;
+	uint16	opcode;
+	uint64	rip;
+	uint64	rdp;
+	uint32	mxcsr;
+	uint32	mscsr_mask;
+	byte	anon0[128];
+	XmmRegs	xmm;
+	uint8	_reserved_416_511[96];
+};
+
+struct Mcontext {
+	uint64	rax;
+	uint64	rbx;
+	uint64	rcx;
+	uint64	rdx;
+	uint64	rdi;
+	uint64	rsi;
+	uint64	rbp;
+	uint64	r8;
+	uint64	r9;
+	uint64	r10;
+	uint64	r11;
+	uint64	r12;
+	uint64	r13;
+	uint64	r14;
+	uint64	r15;
+	uint64	rsp;
+	uint64	rip;
+	uint64	rflags;
+	FpuState	fpu;
+};
+struct Ucontext {
+	Ucontext	*uc_link;
+	uint64	uc_sigmask;
+	StackT	uc_stack;
+	Mcontext	uc_mcontext;
+};
+
+struct Timespec {
+	int32	tv_sec;
+	byte	Pad_cgo_0[4];
+	int64	tv_nsec;
+};
+struct Timeval {
+	int32	tv_sec;
+	int32	tv_usec;
+};
+struct Itimerval {
+	Timeval	it_interval;
+	Timeval	it_value;
+};
+
+typedef	void	*Pthread;
+typedef	void	*PthreadAttr;
+
+struct Stat {
+	int32	st_dev;
+	byte	Pad_cgo_0[4];
+	int64	st_ino;
+	uint32	st_mode;
+	int32	st_nlink;
+	uint32	st_uid;
+	uint32	st_gid;
+	int64	st_size;
+	int32	st_rdev;
+	int32	st_blksize;
+	Timespec	st_atim;
+	Timespec	st_mtim;
+	Timespec	st_ctim;
+	Timespec	st_crtim;
+	uint32	st_type;
+	byte	Pad_cgo_1[4];
+	int64	st_blocks;
+};
+
+
+#pragma pack off
diff --git a/src/runtime/mem_haiku.c b/src/runtime/mem_haiku.c
new file mode 100644
index 0000000..0d59b5d
--- /dev/null
+++ b/src/runtime/mem_haiku.c
@@ -0,0 +1,160 @@
+// 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.
+
+#include "runtime.h"
+#include "arch_GOARCH.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "malloc.h"
+#include "textflag.h"
+
+uintptr runtime·area_for(void* addr);
+
+static int32
+addrspace_free(void *v, uintptr n)
+{
+	uintptr errval;
+	uintptr chunk;
+	uintptr off;
+
+	for(off = 0; off < n; off += chunk) {
+		chunk = B_PAGE_SIZE;
+		if(chunk > (n - off))
+			chunk = n - off;
+		errval = runtime·area_for((void*)((uintptr) v + off));
+		// B_ERROR means unmapped, which is what we want.
+		// Anything else we assume means the pages are mapped.
+		if (errval != B_ERROR)
+			return 0;
+	}
+	return 1;
+}
+
+static void *
+mmap_fixed(byte *v, uintptr n, int32 prot, int32 flags, int32 fd, uint32 offset)
+{
+	void *p;
+
+	p = runtime·mmap(v, n, prot, flags, fd, offset);
+	if(p != v && addrspace_free(v, n)) {
+		// On some systems, mmap ignores v without
+		// MAP_FIXED, so retry if the address space is free.
+		if(p > (void*)4096)
+			runtime·munmap(p, n);
+		p = runtime·mmap(v, n, prot, flags|MAP_FIXED, fd, offset);
+	}
+	return p;
+}
+
+#pragma textflag NOSPLIT
+void*
+runtime·sysAlloc(uintptr n, uint64 *stat)
+{
+	void *p;
+
+	p = runtime·mmap(nil, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
+	if(p < (void*)4096) {
+		if(p == (void*)EACCES) {
+			runtime·printf("runtime: mmap: access denied\n");
+			runtime·printf("if you're running SELinux, enable execmem for this process.\n");
+			runtime·exit(2);
+		}
+		if(p == (void*)EAGAIN) {
+			runtime·printf("runtime: mmap: too much locked memory (check 'ulimit -l').\n");
+			runtime·exit(2);
+		}
+		return nil;
+	}
+	runtime·xadd64(stat, n);
+	return p;
+}
+
+void
+runtime·SysUnused(void *v, uintptr n)
+{
+	/*runtime·madvise(v, n, MADV_DONTNEED);*/
+}
+
+void
+runtime·SysUsed(void *v, uintptr n)
+{
+	USED(v);
+	USED(n);
+}
+
+void
+runtime·SysFree(void *v, uintptr n, uint64 *stat)
+{
+	runtime·xadd64(stat, -(uint64)n);
+	runtime·munmap(v, n);
+}
+
+void
+runtime·SysFault(void *v, uintptr n)
+{
+	runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
+}
+
+int32 runtime·kern_reserve_address_range(void* v, int32 address_spec, uintptr n);
+
+void*
+runtime·SysReserve(void *v, uintptr n, bool *reserved)
+{
+	void *p;
+
+	// On 64-bit, people with ulimit -v set complain if we reserve too
+	// much address space.  Instead, assume that the reservation is okay
+	// if we can reserve at least 64K and check the assumption in SysMap.
+	// Only user-mode Linux (UML) rejects these requests.
+	if(sizeof(void*) == 8 && n > 1LL<<32) {
+		p = mmap_fixed(v, 64<<10, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
+		if (p != v) {
+			if(p >= (void*)4096)
+				runtime·munmap(p, 64<<10);
+			return nil;
+		}
+		runtime·munmap(p, 64<<10);
+		*reserved = false;
+		return v;
+	}
+
+	//int32 status = runtime·kern_reserve_address_range(&p, 0x7 /* B_RANDOMIZED_BASE_ADDRESS */, 64<<10);
+	*reserved = false;
+	p = runtime·mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
+	//that doesn't work: PROT_NONE still reserves physical memory
+	//so immediately unmap it and mark it as unreserved
+	if((uintptr)p < 4096)
+		return nil;
+	//if (status) {
+	//	return nil;
+	//}
+	runtime·munmap(p, n);
+	return p;
+}
+
+void
+runtime·SysMap(void *v, uintptr n, bool reserved, uint64 *stat)
+{
+	void *p;
+
+	runtime·xadd64(stat, n);
+
+	// On 64-bit, we don't actually have v reserved, so tread carefully.
+	if(!reserved) {
+		p = mmap_fixed(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
+		if(p == (void*)ENOMEM)
+			runtime·throw("runtime: out of memory");
+		if(p != v) {
+			runtime·printf("runtime: address space conflict: map(%p) = %p\n", v, p);
+			runtime·throw("runtime: address space conflict");
+		}
+		return;
+	}
+
+	p = runtime·mmap(v, n, PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0);
+	if(p == (void*)ENOMEM)
+		runtime·throw("runtime: out of memory");
+	if(p != v)
+		runtime·throw("runtime: cannot map pages in arena address space");
+}
diff --git a/src/runtime/os_haiku.c b/src/runtime/os_haiku.c
new file mode 100644
index 0000000..188c0ea
--- /dev/null
+++ b/src/runtime/os_haiku.c
@@ -0,0 +1,583 @@
+// Copyright 2011 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.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "signal_unix.h"
+#include "stack.h"
+#include "textflag.h"
+
+// dynimport is broken in 386: one needs the address instead of the value
+// contained in each imported variable
+#ifdef GOARCH_386
+#define FUNC(a) ((uintptr) &a)
+#else
+#define FUNC(a) (a)
+#endif
+
+#pragma dynexport runtime·end _end
+#pragma dynexport runtime·etext _etext
+#pragma dynexport runtime·edata _edata
+
+#pragma dynimport libc·_errnop _errnop "libroot.so"
+#pragma dynimport libc·clock_gettime clock_gettime "libroot.so"
+#pragma dynimport libc·close close "libroot.so"
+#pragma dynimport libc·exit exit "libroot.so"
+#pragma dynimport libc·fstat fstat "libroot.so"
+#pragma dynimport libc·getcontext getcontext "libroot.so"
+#pragma dynimport libc·getrlimit getrlimit "libroot.so"
+#pragma dynimport libc·malloc malloc "libroot.so"
+#pragma dynimport libc·mmap mmap "libroot.so"
+#pragma dynimport libc·munmap munmap "libroot.so"
+#pragma dynimport libc·open open "libroot.so"
+#pragma dynimport libc·pthread_attr_destroy pthread_attr_destroy "libroot.so"
+#pragma dynimport libc·pthread_attr_getstacksize pthread_attr_getstacksize "libroot.so"
+#pragma dynimport libc·pthread_attr_init pthread_attr_init "libroot.so"
+#pragma dynimport libc·pthread_attr_setdetachstate pthread_attr_setdetachstate "libroot.so"
+#pragma dynimport libc·pthread_attr_setstack pthread_attr_setstack "libroot.so"
+#pragma dynimport libc·pthread_create pthread_create "libroot.so"
+#pragma dynimport libc·raise raise "libroot.so"
+#pragma dynimport libc·read read "libroot.so"
+#pragma dynimport libc·select select "libroot.so"
+#pragma dynimport libc·sched_yield sched_yield "libroot.so"
+#pragma dynimport libc·sem_init sem_init "libroot.so"
+#pragma dynimport libc·sem_post sem_post "libroot.so"
+#pragma dynimport libc·sem_timedwait sem_timedwait "libroot.so"
+#pragma dynimport libc·sem_wait sem_wait "libroot.so"
+#pragma dynimport libc·setitimer setitimer "libroot.so"
+#pragma dynimport libc·sigaction sigaction "libroot.so"
+#pragma dynimport libc·sigaltstack sigaltstack "libroot.so"
+#pragma dynimport libc·sigprocmask sigprocmask "libroot.so"
+#pragma dynimport libc·sysconf sysconf "libroot.so"
+#pragma dynimport libc·usleep usleep "libroot.so"
+#pragma dynimport libc·write write "libroot.so"
+#pragma dynimport libc·area_for area_for "libroot.so"
+
+extern uintptr libc·_errnop;
+extern uintptr libc·clock_gettime;
+extern uintptr libc·close;
+extern uintptr libc·exit;
+extern uintptr libc·fstat;
+extern uintptr libc·getcontext;
+extern uintptr libc·getrlimit;
+extern uintptr libc·malloc;
+extern uintptr libc·mmap;
+extern uintptr libc·munmap;
+extern uintptr libc·open;
+extern uintptr libc·pthread_attr_destroy;
+extern uintptr libc·pthread_attr_getstacksize;
+extern uintptr libc·pthread_attr_init;
+extern uintptr libc·pthread_attr_setdetachstate;
+extern uintptr libc·pthread_attr_setstack;
+extern uintptr libc·pthread_create;
+extern uintptr libc·raise;
+extern uintptr libc·read;
+extern uintptr libc·sched_yield;
+extern uintptr libc·select;
+extern uintptr libc·sem_init;
+extern uintptr libc·sem_post;
+extern uintptr libc·sem_timedwait;
+extern uintptr libc·sem_wait;
+extern uintptr libc·setitimer;
+extern uintptr libc·sigaction;
+extern uintptr libc·sigaltstack;
+extern uintptr libc·sigprocmask;
+extern uintptr libc·sysconf;
+extern uintptr libc·usleep;
+extern uintptr libc·write;
+extern uintptr libc·area_for;
+
+void	runtime·getcontext(Ucontext *context);
+int32	runtime·pthread_attr_destroy(PthreadAttr* attr);
+int32	runtime·pthread_attr_init(PthreadAttr* attr);
+//TODO: uint32/uint64 problem needs to be solved
+int32	runtime·pthread_attr_getstacksize(PthreadAttr* attr, uintptr* size);
+int32	runtime·pthread_attr_setdetachstate(PthreadAttr* attr, int32 state);
+int32	runtime·pthread_attr_setstack(PthreadAttr* attr, void* addr, uint32 size);
+int32	runtime·pthread_create(Pthread* thread, PthreadAttr* attr, void(*fn)(void), void *arg);
+uint32	runtime·tstart_sysvicall(M *newm);
+int32	runtime·sem_init(SemT* sem, int32 pshared, uint32 value);
+int32	runtime·sem_post(SemT* sem);
+//int32	runtime·sem_reltimedwait(SemT* sem, Timespec* timeout);
+int32	runtime·sem_wait(SemT* sem);
+int64	runtime·sysconf(int32 name);
+
+extern SigTab runtime·sigtab[];
+static Sigset sigset_none = 0;
+static Sigset sigset_all = 0;
+
+static int32
+getncpu(void)
+{
+	int32 n;
+
+	n = (int32)runtime·sysconf(_SC_NPROCESSORS_ONLN);
+	if(n < 1)
+		return 1;
+	return n;
+}
+
+void
+runtime·osinit(void)
+{
+	runtime·ncpu = getncpu();
+}
+
+void
+runtime·newosproc(M *mp, void *stk)
+{
+	PthreadAttr attr;
+	Sigset oset;
+	Pthread tid;
+	int32 ret;
+	uint64 size;
+
+	USED(stk);
+	if(runtime·pthread_attr_init(&attr) != 0)
+		runtime·throw("pthread_attr_init");
+	//if(runtime·pthread_attr_setstack(&attr, 0, 0x200000) != 0)
+	//	runtime·throw("pthread_attr_setstack");
+	//if(runtime·pthread_attr_getstack(&attr, (void**)&mp->g0->stackbase, &mp->g0->stacksize) != 0)
+	//	runtime·throw("pthread_attr_getstack");
+	
+	if(runtime·pthread_attr_getstacksize(&attr, &mp->g0->stack.hi) != 0)
+		runtime·throw("pthread_attr_getstacksize");
+	if(runtime·pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
+		runtime·throw("pthread_attr_setdetachstate");
+
+	// Disable signals during create, so that the new thread starts
+	// with signals disabled.  It will enable them in minit.
+	runtime·sigprocmask(SIG_SETMASK, &sigset_all, &oset);
+	mp->g0->stack.hi = 0xdeadf00d;
+	ret = runtime·pthread_create(&tid, &attr, (void (*)(void))runtime·tstart_sysvicall, mp);
+	runtime·sigprocmask(SIG_SETMASK, &oset, nil);
+	if(ret != 0) {
+		runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), ret);
+		runtime·throw("runtime.newosproc");
+	}
+}
+
+#pragma textflag NOSPLIT
+void
+runtime·get_random_data(byte **rnd, int32 *rnd_len)
+{
+	static byte urandom_data[HashRandomBytes];
+	int32 fd;
+	fd = runtime·open("/dev/urandom", 0 /* O_RDONLY */, 0);
+	if(runtime·read(fd, urandom_data, HashRandomBytes) == HashRandomBytes) {
+		*rnd = urandom_data;
+		*rnd_len = HashRandomBytes;
+	} else {
+		*rnd = nil;
+		*rnd_len = 0;
+	}
+	runtime·close(fd);
+}
+
+void
+runtime·goenvs(void)
+{
+	runtime·goenvs_unix();
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+void
+runtime·mpreinit(M *mp)
+{
+	mp->gsignal = runtime·malg(32*1024);
+	mp->gsignal->m = mp;
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
+void
+runtime·minit(void)
+{
+	runtime·asmcgocall(runtime·miniterrno, (void *) FUNC(libc·_errnop));
+	// Initialize signal handling
+	runtime·signalstack((byte*)g->m->gsignal->stack.lo, 32*1024);
+	runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
+}
+
+// Called from dropm to undo the effect of an minit.
+void
+runtime·unminit(void)
+{
+	runtime·signalstack(nil, 0);
+}
+
+#pragma textflag NOSPLIT
+int8*
+runtime·signame(int32 sig)
+{
+	return runtime·sigtab[sig].name;
+}
+
+uintptr
+runtime·memlimit(void)
+{
+	/*Rlimit rl;
+	extern byte runtime·text[], runtime·end[];
+	uintptr used;
+
+	if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
+		return 0;
+	if(rl.rlim_cur >= 0x7fffffff)
+		return 0;
+
+	// Estimate our VM footprint excluding the heap.
+	// Not an exact science: use size of binary plus
+	// some room for thread stacks.
+	used = runtime·end - runtime·text + (64<<20);
+	if(used >= rl.rlim_cur)
+		return 0;
+
+	// If there's not at least 16 MB left, we're probably
+	// not going to be able to do much.  Treat as no limit.
+	rl.rlim_cur -= used;
+	if(rl.rlim_cur < (16<<20))
+		return 0;
+
+	return rl.rlim_cur - used;
+	*/
+	return 0;
+}
+
+void
+runtime·setprof(bool on)
+{
+	USED(on);
+}
+
+extern void runtime·sigtramp(void);
+
+void
+runtime·setsig(int32 i, GoSighandler *fn, bool restart)
+{
+	SigactionT sa;
+
+	runtime·memclr((byte*)&sa, sizeof sa);
+	sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
+	if(restart)
+		sa.sa_flags |= SA_RESTART;
+	sa.sa_mask = ~(uint64)0;
+	if(fn == runtime·sighandler)
+		fn = (void*)runtime·sigtramp;
+	*((void**)&sa.anon0[0]) = (void*)fn;
+	runtime·sigaction(i, &sa, nil);
+}
+
+GoSighandler*
+runtime·getsig(int32 i)
+{
+	SigactionT sa;
+
+	runtime·memclr((byte*)&sa, sizeof sa);
+	runtime·sigaction(i, nil, &sa);
+	if(*((void**)&sa.anon0[0]) == runtime·sigtramp)
+		return runtime·sighandler;
+	return *((void**)&sa.anon0[0]);
+}
+
+void
+runtime·signalstack(byte *p, int32 n)
+{
+	StackT st;
+
+	st.ss_sp = (void*)p;
+	st.ss_size = n;
+	st.ss_flags = 0;
+	if(p == nil)
+		st.ss_flags = SS_DISABLE;
+	runtime·sigaltstack(&st, nil);
+}
+
+void
+runtime·unblocksignals(void)
+{
+	runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
+}
+
+#pragma textflag NOSPLIT
+uintptr
+runtime·semacreate(void)
+{
+	SemT* sem;
+
+	// Call libc's malloc rather than runtime·malloc.  This will
+	// allocate space on the C heap.  We can't call runtime·malloc
+	// here because it could cause a deadlock.
+	g->m->libcall.fn = (uintptr)(void*) FUNC(libc·malloc);
+	g->m->libcall.n = 1;
+	runtime·memclr((byte*)&g->m->scratch, sizeof(g->m->scratch));
+	g->m->scratch.v[0] = (uintptr)sizeof(*sem);
+	g->m->libcall.args = (uintptr)(uintptr*)&g->m->scratch;
+	runtime·asmcgocall(runtime·asmsysvicall6, &g->m->libcall);
+	sem = (void*)g->m->libcall.r1;
+	if(runtime·sem_init(sem, 0, 0) != 0)
+		runtime·throw("sem_init");
+	return (uintptr)sem;
+}
+
+int32   _div64by32(int64 numerator, int32 denominator, int32* pointerToRemainder);
+
+#pragma textflag NOSPLIT
+int32
+runtime·semasleep(int64 ns)
+{
+	M *m;
+
+	m = g->m;
+
+	if(ns >= 0) {
+#ifdef GOARCH_amd64
+		m->ts.tv_sec = ns / 1000000000LL;
+		m->ts.tv_nsec = ns % 1000000000LL;
+#else
+		// because 64-bit divide generates a call to a split stack method, which we can't call
+		m->ts.tv_sec = _div64by32(ns, 1000000000, &(m->ts.tv_nsec));
+#endif
+
+		m->libcall.fn = (uintptr)(void*) FUNC(libc·sem_timedwait);
+		m->libcall.n = 2;
+		runtime·memclr((byte*)&m->scratch, sizeof(m->scratch));
+		m->scratch.v[0] = m->waitsema;
+		m->scratch.v[1] = (uintptr)&m->ts;
+		m->libcall.args = (uintptr)(uintptr*)&m->scratch;
+		runtime·asmcgocall(runtime·asmsysvicall6, &m->libcall);
+		if(*m->perrno != 0) {
+			if(*m->perrno == ETIMEDOUT || *m->perrno == EAGAIN || *m->perrno == EINTR)
+				return -1;
+			runtime·throw("sem_reltimedwait");
+		}
+		return 0;
+	}
+	for(;;) {
+		m->libcall.fn = (uintptr)(void*) FUNC(libc·sem_wait);
+		m->libcall.n = 1;
+		runtime·memclr((byte*)&m->scratch, sizeof(m->scratch));
+		m->scratch.v[0] = m->waitsema;
+		m->libcall.args = (uintptr)(uintptr*)&m->scratch;
+		runtime·asmcgocall(runtime·asmsysvicall6, &m->libcall);
+		if(m->libcall.r1 == 0)
+			break;
+		if(*m->perrno == EINTR)
+			continue;
+		runtime·throw("sem_wait");
+	}
+	return 0;
+}
+
+#pragma textflag NOSPLIT
+void
+runtime·semawakeup(M *mp)
+{
+	SemT* sem = (SemT*)mp->waitsema;
+	if(runtime·sem_post(sem) != 0)
+		runtime·throw("sem_post");
+}
+
+int32
+runtime·close(int32 fd)
+{
+	return runtime·sysvicall1(FUNC(libc·close), (uintptr)fd);
+}
+
+void
+runtime·exit(int32 r)
+{
+	runtime·sysvicall1(FUNC(libc·exit), (uintptr)r);
+}
+
+/* int32 */ void
+runtime·getcontext(Ucontext* context)
+{
+	runtime·sysvicall1(FUNC(libc·getcontext), (uintptr)context);
+}
+
+int32
+runtime·getrlimit(int32 res, Rlimit* rlp)
+{
+	return runtime·sysvicall2(FUNC(libc·getrlimit), (uintptr)res, (uintptr)rlp);
+}
+
+uint8*
+runtime·mmap(byte* addr, uintptr len, int32 prot, int32 flags, int32 fildes, uint32 off)
+{
+	return (uint8*)runtime·sysvicall6(FUNC(libc·mmap), (uintptr)addr, (uintptr)len, (uintptr)prot, (uintptr)flags, (uintptr)fildes, (uintptr)off);
+}
+
+void
+runtime·munmap(byte* addr, uintptr len)
+{
+	runtime·sysvicall2(FUNC(libc·munmap), (uintptr)addr, (uintptr)len);
+}
+
+extern void runtime·nanotime1(void);
+#pragma textflag NOSPLIT
+int64
+runtime·nanotime(void)
+{
+	M *m;
+
+	m = g->m;
+
+	runtime·sysvicall0((uintptr)runtime·nanotime1);
+	if (sizeof(void*) == 8) { // on 64-bit the assembly wrapper does the multiplication
+		return m->libcall.r1;
+	}
+	return (m->libcall.r1 * 1000000000LL) + m->libcall.r2;
+}
+
+// void
+// time·now(int64 sec, int32 usec)
+// {
+// 	int64 ns;
+
+// 	ns = runtime·nanotime();
+// 	sec = ns / 1000000000LL;
+// 	usec = ns - sec * 1000000000LL;
+// 	FLUSH(&sec);
+// 	FLUSH(&usec);
+// }
+
+int32
+runtime·open(int8* path, int32 oflag, int32 mode)
+{
+	return runtime·sysvicall3(FUNC(libc·open), (uintptr)path, (uintptr)oflag, (uintptr)mode);
+}
+
+int32
+runtime·pthread_attr_destroy(PthreadAttr* attr)
+{
+	return runtime·sysvicall1(FUNC(libc·pthread_attr_destroy), (uintptr)attr);
+}
+
+int32
+runtime·pthread_attr_getstacksize(PthreadAttr* attr, uintptr* size)
+{
+	return runtime·sysvicall2(FUNC(libc·pthread_attr_getstacksize), (uintptr)attr, (uintptr)size);
+}
+
+int32
+runtime·pthread_attr_init(PthreadAttr* attr)
+{
+	return runtime·sysvicall1(FUNC(libc·pthread_attr_init), (uintptr)attr);
+}
+
+int32
+runtime·pthread_attr_setdetachstate(PthreadAttr* attr, int32 state)
+{
+	return runtime·sysvicall2(FUNC(libc·pthread_attr_setdetachstate), (uintptr)attr, (uintptr)state);
+}
+
+int32
+runtime·pthread_attr_setstack(PthreadAttr* attr, void* addr, uint32 size)
+{
+	return runtime·sysvicall3(FUNC(libc·pthread_attr_setstack), (uintptr)attr, (uintptr)addr, (uintptr)size);
+}
+
+int32
+runtime·pthread_create(Pthread* thread, PthreadAttr* attr, void(*fn)(void), void *arg)
+{
+	return runtime·sysvicall4(FUNC(libc·pthread_create), (uintptr)thread, (uintptr)attr, (uintptr)fn, (uintptr)arg);
+}
+
+/* int32 */ void
+runtime·raise(int32 sig)
+{
+	runtime·sysvicall1(FUNC(libc·raise), (uintptr)sig);
+}
+
+int32
+runtime·read(int32 fd, void* buf, int32 nbyte)
+{
+	return runtime·sysvicall3(FUNC(libc·read), (uintptr)fd, (uintptr)buf, (uintptr)nbyte);
+}
+
+#pragma textflag NOSPLIT
+int32
+runtime·sem_init(SemT* sem, int32 pshared, uint32 value)
+{
+	return runtime·sysvicall3(FUNC(libc·sem_init), (uintptr)sem, (uintptr)pshared, (uintptr)value);
+}
+
+#pragma textflag NOSPLIT
+int32
+runtime·sem_post(SemT* sem)
+{
+	return runtime·sysvicall1(FUNC(libc·sem_post), (uintptr)sem);
+}
+
+#pragma textflag NOSPLIT
+int32
+runtime·sem_wait(SemT* sem)
+{
+	return runtime·sysvicall1(FUNC(libc·sem_wait), (uintptr)sem);
+}
+
+/* int32 */ void
+runtime·setitimer(int32 which, Itimerval* value, Itimerval* ovalue)
+{
+	runtime·sysvicall3(FUNC(libc·setitimer), (uintptr)which, (uintptr)value, (uintptr)ovalue);
+}
+
+/* int32 */ void
+runtime·sigaction(int32 sig, struct SigactionT* act, struct SigactionT* oact)
+{
+	runtime·sysvicall3(FUNC(libc·sigaction), (uintptr)sig, (uintptr)act, (uintptr)oact);
+}
+
+/* int32 */ void
+runtime·sigaltstack(SigaltstackT* ss, SigaltstackT* oss)
+{
+	runtime·sysvicall2(FUNC(libc·sigaltstack), (uintptr)ss, (uintptr)oss);
+}
+
+/* int32 */ void
+runtime·sigprocmask(int32 how, Sigset* set, Sigset* oset)
+{
+	runtime·sysvicall3(FUNC(libc·sigprocmask), (uintptr)how, (uintptr)set, (uintptr)oset);
+}
+
+int64
+runtime·sysconf(int32 name)
+{
+	return runtime·sysvicall1(FUNC(libc·sysconf), (uintptr)name);
+}
+
+void
+runtime·usleep(uint32 us)
+{
+	runtime·sysvicall1(FUNC(libc·usleep), (uintptr)us);
+}
+
+int32
+runtime·write(uintptr fd, void* buf, int32 nbyte)
+{
+	return runtime·sysvicall3(FUNC(libc·write), (uintptr)fd, (uintptr)buf, (uintptr)nbyte);
+}
+
+void
+runtime·osyield(void)
+{
+	runtime·sysvicall0(FUNC(libc·sched_yield));
+}
+
+uintptr
+runtime·area_for(void* addr)
+{
+	return (uintptr)runtime·sysvicall1(FUNC(libc·area_for), (uintptr)addr);
+}
+
+#ifndef GOARCH_amd64
+// STUB
+void
+runtime·pipe1(void)
+{
+	runtime·throw("Pipe not implemented");
+}
+#endif
diff --git a/src/runtime/os_haiku.go b/src/runtime/os_haiku.go
new file mode 100644
index 0000000..f843205
--- /dev/null
+++ b/src/runtime/os_haiku.go
@@ -0,0 +1,102 @@
+// Copyright 2014 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.
+
+package runtime
+
+import "unsafe"
+
+func rt_sigaction(sig uintptr, new, old unsafe.Pointer, size uintptr) int32
+
+func sigaltstack(new, old unsafe.Pointer)
+func setitimer(mode int32, new, old unsafe.Pointer)
+func rtsigprocmask(sig int32, new, old unsafe.Pointer, size int32)
+func getrlimit(kind int32, limit unsafe.Pointer) int32
+func raise(sig int32)
+func sched_getaffinity(pid, len uintptr, buf *uintptr) int32
+
+func sigaction(sig int32, new, old unsafe.Pointer)
+func sigprocmask(mode int32, new, old unsafe.Pointer)
+func miniterrno(fn unsafe.Pointer)
+
+func getcontext(ctxt unsafe.Pointer)
+func tstart_sysvicall(mm unsafe.Pointer) uint32
+func nanotime1() int64
+func usleep1(usec uint32)
+func osyield1()
+
+type libcFunc byte
+
+var asmsysvicall6 libcFunc
+
+//go:nosplit
+func sysvicall0(fn *libcFunc) uintptr {
+	libcall := &getg().m.libcall
+	libcall.fn = uintptr(unsafe.Pointer(fn))
+	libcall.n = 0
+	// TODO(rsc): Why is noescape necessary here and below?
+	libcall.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
+	return libcall.r1
+}
+
+//go:nosplit
+func sysvicall1(fn *libcFunc, a1 uintptr) uintptr {
+	libcall := &getg().m.libcall
+	libcall.fn = uintptr(unsafe.Pointer(fn))
+	libcall.n = 1
+	libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
+	return libcall.r1
+}
+
+//go:nosplit
+func sysvicall2(fn *libcFunc, a1, a2 uintptr) uintptr {
+	libcall := &getg().m.libcall
+	libcall.fn = uintptr(unsafe.Pointer(fn))
+	libcall.n = 2
+	libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
+	return libcall.r1
+}
+
+//go:nosplit
+func sysvicall3(fn *libcFunc, a1, a2, a3 uintptr) uintptr {
+	libcall := &getg().m.libcall
+	libcall.fn = uintptr(unsafe.Pointer(fn))
+	libcall.n = 3
+	libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
+	return libcall.r1
+}
+
+//go:nosplit
+func sysvicall4(fn *libcFunc, a1, a2, a3, a4 uintptr) uintptr {
+	libcall := &getg().m.libcall
+	libcall.fn = uintptr(unsafe.Pointer(fn))
+	libcall.n = 4
+	libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
+	return libcall.r1
+}
+
+//go:nosplit
+func sysvicall5(fn *libcFunc, a1, a2, a3, a4, a5 uintptr) uintptr {
+	libcall := &getg().m.libcall
+	libcall.fn = uintptr(unsafe.Pointer(fn))
+	libcall.n = 5
+	libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
+	return libcall.r1
+}
+
+//go:nosplit
+func sysvicall6(fn *libcFunc, a1, a2, a3, a4, a5, a6 uintptr) uintptr {
+	libcall := &getg().m.libcall
+	libcall.fn = uintptr(unsafe.Pointer(fn))
+	libcall.n = 6
+	libcall.args = uintptr(noescape(unsafe.Pointer(&a1)))
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
+	return libcall.r1
+}
+
diff --git a/src/runtime/os_haiku.h b/src/runtime/os_haiku.h
new file mode 100644
index 0000000..b611b13
--- /dev/null
+++ b/src/runtime/os_haiku.h
@@ -0,0 +1,45 @@
+// 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.
+
+// Linux-specific system calls
+//int32	runtime·futex(uint32*, int32, uint32, Timespec*, uint32*, uint32);
+//int32	runtime·clone(int32, void*, M*, G*, void(*)(void));
+
+struct SigactionT;
+void	runtime·sigaction(int32, struct SigactionT*, struct SigactionT*);
+
+void	runtime·sigaltstack(SigaltstackT*, SigaltstackT*);
+void	runtime·sigpanic(void);
+void runtime·setitimer(int32, Itimerval*, Itimerval*);
+
+enum {
+	SS_DISABLE = 2,
+	NSIG = 65,
+	SI_USER = 0,
+	SIG_SETMASK = 3, // Modified for Haiku support
+	RLIMIT_AS = 6, // Modified for Haiku support
+};
+
+void	runtime·sigprocmask(int32, Sigset*, Sigset*);
+void	runtime·unblocksignals(void);
+
+typedef struct Rlimit Rlimit;
+struct Rlimit {
+	uintptr	rlim_cur;
+	uintptr	rlim_max;
+};
+int32	runtime·getrlimit(int32, Rlimit*);
+
+// Call an external library function described by {fn, a0, ..., an}, with
+// SysV conventions, switching to os stack during the call, if necessary.
+
+uintptr	runtime·sysvicall0(uintptr fn);
+uintptr	runtime·sysvicall1(uintptr fn, uintptr a1);
+uintptr	runtime·sysvicall2(uintptr fn, uintptr a1, uintptr a2);
+uintptr	runtime·sysvicall3(uintptr fn, uintptr a1, uintptr a2, uintptr a3);
+uintptr	runtime·sysvicall4(uintptr fn, uintptr a1, uintptr a2, uintptr a3, uintptr a4);
+uintptr	runtime·sysvicall5(uintptr fn, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5);
+uintptr	runtime·sysvicall6(uintptr fn, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5, uintptr a6);
+void	runtime·asmsysvicall6(void *c);
+void	runtime·miniterrno(void *fn);
diff --git a/src/runtime/rt0_haiku_amd64.s b/src/runtime/rt0_haiku_amd64.s
new file mode 100644
index 0000000..daff034
--- /dev/null
+++ b/src/runtime/rt0_haiku_amd64.s
@@ -0,0 +1,18 @@
+// 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.
+
+#include "textflag.h"
+
+TEXT _rt0_amd64_haiku(SB),NOSPLIT,$-8
+	LEAQ	8(SP), SI // argv
+	MOVQ	0(SP), DI // argc
+	MOVQ	$main(SB), AX
+	JMP	AX
+
+TEXT main(SB),NOSPLIT,$-8
+	MOVQ	$runtime·rt0_go(SB), AX
+	JMP	AX
+
+DATA runtime·ishaiku(SB)/4, $1
+GLOBL runtime·ishaiku(SB), $4
diff --git a/src/runtime/signal_haiku_amd64.h b/src/runtime/signal_haiku_amd64.h
new file mode 100644
index 0000000..b8c330a
--- /dev/null
+++ b/src/runtime/signal_haiku_amd64.h
@@ -0,0 +1,33 @@
+// Copyright 2013 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.
+
+#define SIG_REGS(ctxt) (((Ucontext*)(ctxt))->uc_mcontext)
+
+#define SIG_RAX(info, ctxt) (SIG_REGS(ctxt).rax)
+#define SIG_RBX(info, ctxt) (SIG_REGS(ctxt).rbx)
+#define SIG_RCX(info, ctxt) (SIG_REGS(ctxt).rcx)
+#define SIG_RDX(info, ctxt) (SIG_REGS(ctxt).rdx)
+#define SIG_RDI(info, ctxt) (SIG_REGS(ctxt).rdi)
+#define SIG_RSI(info, ctxt) (SIG_REGS(ctxt).rsi)
+#define SIG_RBP(info, ctxt) (SIG_REGS(ctxt).rbp)
+#define SIG_RSP(info, ctxt) (SIG_REGS(ctxt).rsp)
+#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).r8)
+#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).r9)
+#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).r10)
+#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).r11)
+#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).r12)
+#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).r13)
+#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).r14)
+#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).r15)
+#define SIG_RIP(info, ctxt) (SIG_REGS(ctxt).rip)
+#define SIG_RFLAGS(info, ctxt) ((uint64)SIG_REGS(ctxt).rflags)
+
+// FIXME: haiku: cs, fs, gs
+#define SIG_CS(info, ctxt) (-1)
+#define SIG_FS(info, ctxt) (-1)
+#define SIG_GS(info, ctxt) (-1)
+
+#define SIG_CODE0(info, ctxt) ((info)->si_code)
+#define SIG_CODE1(info, ctxt) (((uintptr*)(info))[2])
+
diff --git a/src/runtime/sys_haiku_amd64.s b/src/runtime/sys_haiku_amd64.s
new file mode 100644
index 0000000..8273cd4
--- /dev/null
+++ b/src/runtime/sys_haiku_amd64.s
@@ -0,0 +1,351 @@
+// Copyright 2014 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.
+//
+// System calls and other sys.stuff for AMD64, SunOS
+// /usr/include/sys/syscall.h for syscall numbers.
+//
+
+#include "zasm_GOOS_GOARCH.h"
+#include "textflag.h"
+
+// This is needed by asm_amd64.s
+TEXT runtime·settls(SB),NOSPLIT,$8
+	RET
+
+// void libc·miniterrno(void *(*_errnop)(void));
+//
+// Set the TLS errno pointer in M.
+//
+// Called using runtime·asmcgocall from os_haiku.c:/minit.
+// NOT USING GO CALLING CONVENTION.
+TEXT runtime·miniterrno(SB),NOSPLIT,$0
+	// asmcgocall will put first argument into DI.
+	CALL	DI	// SysV ABI so returns in AX
+	get_tls(CX)
+	MOVQ	g(CX), BX
+	MOVQ	g_m(BX), BX
+	MOVQ	AX,	m_perrno(BX)
+	RET
+
+// int64 runtime·nanotime1(void);
+//
+// clock_gettime(3c) wrapper because Timespec is too large for
+// runtime·nanotime stack.
+//
+// Called using runtime·sysvicall6 from os_haiku.c:/nanotime.
+// NOT USING GO CALLING CONVENTION.
+TEXT runtime·nanotime1(SB),NOSPLIT,$0
+	// need space for the timespec argument.
+	SUBQ	$64, SP	// 16 bytes will do, but who knows in the future?
+	MOVQ	$0xffffffffffffffff, DI	// CLOCK_REALTIME from <sys/time_impl.h>
+	MOVQ	SP, SI
+	MOVQ	libc·clock_gettime(SB), AX
+	CALL	AX
+	MOVL	(SP), AX	// tv_sec from struct timespec
+	IMULQ	$1000000000, AX	// multiply into nanoseconds
+	ADDQ	8(SP), AX	// tv_nsec, offset should be stable.
+	ADDQ	$64, SP
+	RET
+
+// pipe(3c) wrapper that returns fds in AX, DX.
+// NOT USING GO CALLING CONVENTION.
+TEXT runtime·pipe1(SB),NOSPLIT,$0
+	SUBQ	$16, SP // 8 bytes will do, but stack has to be 16-byte alligned
+	MOVQ	SP, DI
+	MOVQ	libc·pipe(SB), AX
+	CALL	AX
+	MOVL	0(SP), AX
+	MOVL	4(SP), DX
+	ADDQ	$16, SP
+	RET
+
+// Call a library function with SysV calling conventions.
+// The called function can take a maximum of 6 INTEGER class arguments,
+// see 
+//   Michael Matz, Jan Hubicka, Andreas Jaeger, and Mark Mitchell
+//   System V Application Binary Interface 
+//   AMD64 Architecture Processor Supplement
+// section 3.2.3.
+//
+// Called by runtime·asmcgocall or runtime·cgocall.
+// NOT USING GO CALLING CONVENTION.
+TEXT runtime·asmsysvicall6(SB),NOSPLIT,$0
+	// asmcgocall will put first argument into DI.
+	PUSHQ	DI			// save for later
+	MOVQ	libcall_fn(DI), AX
+	MOVQ	libcall_args(DI), R11
+	MOVQ	libcall_n(DI), R10
+
+	get_tls(CX)
+	MOVQ	g(CX), BX
+	MOVQ	g_m(BX), BX
+	MOVQ	m_perrno(BX), DX
+	CMPQ	DX, $0
+	JEQ	skiperrno1
+	MOVL	$0, 0(DX)
+
+skiperrno1:
+	CMPQ	R11, $0
+	JEQ	skipargs
+	// Load 6 args into correspondent registers.
+	MOVQ	0(R11), DI
+	MOVQ	8(R11), SI
+	MOVQ	16(R11), DX
+	MOVQ	24(R11), CX
+	MOVQ	32(R11), R8
+	MOVQ	40(R11), R9
+skipargs:
+
+	// Call SysV function
+	CALL	AX
+
+	// Return result
+	POPQ	DI
+	MOVQ	AX, libcall_r1(DI)
+	MOVQ	DX, libcall_r2(DI)
+
+	get_tls(CX)
+	MOVQ	g(CX), BX
+	MOVQ	g_m(BX), BX
+	MOVQ	m_perrno(BX), AX
+	CMPQ	AX, $0
+	JEQ	skiperrno2
+	MOVL	0(AX), AX
+	MOVQ	AX, libcall_err(DI)
+
+skiperrno2:	
+	RET
+
+// uint32 tstart_sysvicall(M *newm);
+TEXT runtime·tstart_sysvicall(SB),NOSPLIT,$0
+	// DI contains first arg newm
+	MOVQ	m_g0(DI), DX		// g
+
+	// Make TLS entries point at g and m.
+	get_tls(BX)
+	MOVQ	DX, g(BX)
+	MOVQ	DI, g_m(DX)
+
+	// Layout new m scheduler stack on os stack.
+	MOVQ	SP, AX
+	MOVQ	AX, (g_stack+stack_hi)(DX)
+	SUBQ	$(0x100000), AX		// stack size
+	MOVQ	AX, (g_stack+stack_lo)(DX)
+	ADDQ	$const_StackGuard, AX
+	MOVQ	AX, g_stackguard0(DX)
+	MOVQ	AX, g_stackguard1(DX)
+
+	// Someday the convention will be D is always cleared.
+	CLD
+
+	CALL	runtime·stackcheck(SB)	// clobbers AX,CX
+	CALL	runtime·mstart(SB)
+
+	XORL	AX, AX			// return 0 == success
+	MOVL	AX, ret+8(FP)
+	RET
+
+// Careful, this is called by __sighndlr, a libc function. We must preserve
+// registers as per AMD 64 ABI.
+TEXT runtime·sigtramp(SB),NOSPLIT,$0
+	// Note that we are executing on altsigstack here, so we have
+	// more stack available than NOSPLIT would have us believe.
+	// To defeat the linker, we make our own stack frame with
+	// more space:
+	SUBQ    $184, SP
+
+	// save registers
+	MOVQ    BX, 32(SP)
+	MOVQ    BP, 40(SP)
+	MOVQ	R12, 48(SP)
+	MOVQ	R13, 56(SP)
+	MOVQ	R14, 64(SP)
+	MOVQ	R15, 72(SP)
+
+	get_tls(BX)
+	// check that g exists
+	MOVQ	g(BX), R10
+	CMPQ	R10, $0
+	JNE	allgood
+	MOVQ	DI, 0(SP)
+	MOVQ	$runtime·badsignal(SB), AX
+	CALL	AX
+	JMP	exit
+
+allgood:
+	// save g
+	MOVQ	R10, 80(SP)
+
+	// Save m->libcall and m->scratch. We need to do this because we
+	// might get interrupted by a signal in runtime·asmcgocall.
+
+	// save m->libcall 
+	MOVQ	g_m(R10), BP
+	LEAQ	m_libcall(BP), R11
+	MOVQ	libcall_fn(R11), R10
+	MOVQ	R10, 88(SP)
+	MOVQ	libcall_args(R11), R10
+	MOVQ	R10, 96(SP)
+	MOVQ	libcall_n(R11), R10
+	MOVQ	R10, 104(SP)
+	MOVQ    libcall_r1(R11), R10
+	MOVQ    R10, 168(SP)
+	MOVQ    libcall_r2(R11), R10
+	MOVQ    R10, 176(SP)
+
+	// save m->scratch
+	LEAQ	m_scratch(BP), R11
+	MOVQ	0(R11), R10
+	MOVQ	R10, 112(SP)
+	MOVQ	8(R11), R10
+	MOVQ	R10, 120(SP)
+	MOVQ	16(R11), R10
+	MOVQ	R10, 128(SP)
+	MOVQ	24(R11), R10
+	MOVQ	R10, 136(SP)
+	MOVQ	32(R11), R10
+	MOVQ	R10, 144(SP)
+	MOVQ	40(R11), R10
+	MOVQ	R10, 152(SP)
+
+	// save errno, it might be EINTR; stuff we do here might reset it.
+	MOVQ	m_perrno(BP), R10
+	MOVL	0(R10), R10
+	MOVQ	R10, 160(SP)
+
+	MOVQ	g(BX), R10
+	// g = m->gsignal
+	MOVQ	m_gsignal(BP), BP
+	MOVQ	BP, g(BX)
+
+	// prepare call
+	MOVQ	DI, 0(SP)
+	MOVQ	SI, 8(SP)
+	MOVQ	DX, 16(SP)
+	MOVQ	R10, 24(SP)
+	CALL	runtime·sighandler(SB)
+
+	get_tls(BX)
+	MOVQ	g(BX), BP
+	MOVQ	g_m(BP), BP
+	// restore libcall
+	LEAQ	m_libcall(BP), R11
+	MOVQ	88(SP), R10
+	MOVQ	R10, libcall_fn(R11)
+	MOVQ	96(SP), R10
+	MOVQ	R10, libcall_args(R11)
+	MOVQ	104(SP), R10
+	MOVQ	R10, libcall_n(R11)
+	MOVQ    168(SP), R10
+	MOVQ    R10, libcall_r1(R11)
+	MOVQ    176(SP), R10
+	MOVQ    R10, libcall_r2(R11)
+
+	// restore scratch
+	LEAQ	m_scratch(BP), R11
+	MOVQ	112(SP), R10
+	MOVQ	R10, 0(R11)
+	MOVQ	120(SP), R10
+	MOVQ	R10, 8(R11)
+	MOVQ	128(SP), R10
+	MOVQ	R10, 16(R11)
+	MOVQ	136(SP), R10
+	MOVQ	R10, 24(R11)
+	MOVQ	144(SP), R10
+	MOVQ	R10, 32(R11)
+	MOVQ	152(SP), R10
+	MOVQ	R10, 40(R11)
+
+	// restore errno
+	MOVQ	m_perrno(BP), R11
+	MOVQ	160(SP), R10
+	MOVL	R10, 0(R11)
+
+	// restore g
+	MOVQ	80(SP), R10
+	MOVQ	R10, g(BX)
+
+exit:
+	// restore registers
+	MOVQ	32(SP), BX
+	MOVQ	40(SP), BP
+	MOVQ	48(SP), R12
+	MOVQ	56(SP), R13
+	MOVQ	64(SP), R14
+	MOVQ	72(SP), R15
+
+	ADDQ    $184, SP
+	RET
+
+// Called from runtime·usleep (Go). Can be called on Go stack, on OS stack,
+// can also be called in cgo callback path without a g->m.
+TEXT runtime·usleep1(SB),NOSPLIT,$0
+	MOVL	usec+0(FP), DI
+	MOVQ	$runtime·usleep2(SB), AX // to hide from 6l
+
+	// Execute call on m->g0.
+	get_tls(R15)
+	CMPQ	R15, $0
+	JE	usleep1_noswitch
+
+	MOVQ	g(R15), R13
+	CMPQ	R13, $0
+	JE	usleep1_noswitch
+	MOVQ	g_m(R13), R13
+	CMPQ	R13, $0
+	JE	usleep1_noswitch
+	// TODO(aram): do something about the cpu profiler here.
+
+	MOVQ	m_g0(R13), R14
+	CMPQ	g(R15), R14
+	JNE	usleep1_switch
+	// executing on m->g0 already
+	CALL	AX
+	RET
+
+usleep1_switch:
+	// Switch to m->g0 stack and back.
+	MOVQ	(g_sched+gobuf_sp)(R14), R14
+	MOVQ	SP, -8(R14)
+	LEAQ	-8(R14), SP
+	CALL	AX
+	MOVQ	0(SP), SP
+	RET
+
+usleep1_noswitch:
+	// Not a Go-managed thread. Do not switch stack.
+	CALL	AX
+	RET
+
+// Runs on OS stack. duration (in µs units) is in DI.
+TEXT runtime·usleep2(SB),NOSPLIT,$0
+	MOVQ	libc·usleep(SB), AX
+	CALL	AX
+	RET
+
+// Runs on OS stack, called from runtime·osyield.
+TEXT runtime·osyield1(SB),NOSPLIT,$0
+	MOVQ	libc·sched_yield(SB), AX
+	CALL	AX
+	RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB),NOSPLIT,$8-12
+	CALL	runtime·nanotime(SB)
+	MOVQ	0(SP), AX
+
+	// generated code for
+	//	func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 }
+	// adapted to reduce duplication
+	MOVQ	AX, CX
+	MOVQ	$1360296554856532783, AX
+	MULQ	CX
+	ADDQ	CX, DX
+	RCRQ	$1, DX
+	SHRQ	$29, DX
+	MOVQ	DX, sec+0(FP)
+	IMULQ	$1000000000, DX
+	SUBQ	DX, CX
+	MOVL	CX, nsec+8(FP)
+	RET 
diff --git a/src/runtime/syscall_haiku.c b/src/runtime/syscall_haiku.c
new file mode 100644
index 0000000..d049ba7
--- /dev/null
+++ b/src/runtime/syscall_haiku.c
@@ -0,0 +1,25 @@
+// Copyright 2014 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.
+
+#pragma dynimport libc·chdir chdir "libroot.so"
+#pragma dynimport libc·chroot chroot "libroot.so"
+#pragma dynimport libc·close close "libroot.so"
+#pragma dynimport libc·dlclose dlclose "libroot.so"
+#pragma dynimport libc·dlopen dlopen "libroot.so"
+#pragma dynimport libc·dlsym dlsym "libroot.so"
+#pragma dynimport libc·dup2 dup2 "libroot.so"
+#pragma dynimport libc·execve execve "libroot.so"
+#pragma dynimport libc·fcntl fcntl "libroot.so"
+#pragma dynimport libc·gethostname gethostname "libroot.so"
+#pragma dynimport libc·ioctl ioctl "libroot.so"
+#pragma dynimport libc·mmap mmap "libroot.so"
+#pragma dynimport libc·pipe pipe "libroot.so"
+#pragma dynimport libc·setgid setgid "libroot.so"
+#pragma dynimport libc·setgroups setgroups "libroot.so"
+#pragma dynimport libc·setsid setsid "libroot.so"
+#pragma dynimport libc·setuid setuid "libroot.so"
+#pragma dynimport libc·setpgid setsid "libroot.so"
+#pragma dynimport libc·_kern_generic_syscall _kern_generic_syscall "libroot.so"
+#pragma dynimport libc·fork fork "libroot.so"
+#pragma dynimport libc·waitpid waitpid "libroot.so"
diff --git a/src/runtime/syscall_haiku.go b/src/runtime/syscall_haiku.go
new file mode 100644
index 0000000..68ee1d1
--- /dev/null
+++ b/src/runtime/syscall_haiku.go
@@ -0,0 +1,348 @@
+// Copyright 2014 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.
+
+package runtime
+
+import "unsafe"
+
+var (
+	libc_chdir,
+	libc_chroot,
+	libc_close,
+	libc_dlclose,
+	libc_dlopen,
+	libc_dlsym,
+	libc_dup2,
+	libc_execve,
+	libc_exit,
+	libc_fcntl,
+	libc_gethostname,
+	libc_ioctl,
+	libc_mmap,
+	libc_pipe,
+	libc_setgid,
+	libc_setgroups,
+	libc_setsid,
+	libc_setuid,
+	libc_setpgid,
+	libc__kern_generic_syscall,
+	libc_fork,
+	libc_waitpid,
+	libc_write,
+	pipe1 libcFunc
+)
+
+//go:nosplit
+func syscall_sysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+	call := libcall{
+		fn:   fn,
+		n:    nargs,
+		args: uintptr(unsafe.Pointer(&a1)),
+	}
+	entersyscallblock()
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	exitsyscall()
+	return call.r1, call.r2, call.err
+}
+
+// TODO(aram): Once we remove all instances of C calling sysvicallN, make
+// sysvicallN return errors and replace the body of the following functions
+// with calls to sysvicallN.
+
+//go:nosplit
+func syscall_chdir(path uintptr) (err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc_chdir)),
+		n:    1,
+		args: uintptr(unsafe.Pointer(&path)),
+	}
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	return call.err
+}
+
+//go:nosplit
+func syscall_chroot(path uintptr) (err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc_chroot)),
+		n:    1,
+		args: uintptr(unsafe.Pointer(&path)),
+	}
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	return call.err
+}
+
+// like close, but must not split stack, for forkx.
+//go:nosplit
+func syscall_close(fd int32) int32 {
+	return int32(sysvicall1(&libc_close, uintptr(fd)))
+}
+
+func syscall_dlopen(name *byte, mode uintptr) (handle uintptr, err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc_dlopen)),
+		n:    2,
+		args: uintptr(unsafe.Pointer(&name)),
+	}
+	entersyscallblock()
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	exitsyscall()
+	if call.r1 == 0 {
+		return call.r1, call.err
+	}
+	return call.r1, 0
+}
+
+func syscall_dlclose(handle uintptr) (err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc_dlclose)),
+		n:    1,
+		args: uintptr(unsafe.Pointer(&handle)),
+	}
+	entersyscallblock()
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	exitsyscall()
+	return call.r1
+}
+
+func syscall_dlsym(handle uintptr, name *byte) (proc uintptr, err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc_dlsym)),
+		n:    2,
+		args: uintptr(unsafe.Pointer(&handle)),
+	}
+	entersyscallblock()
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	exitsyscall()
+	if call.r1 == 0 {
+		return call.r1, call.err
+	}
+	return call.r1, 0
+}
+
+//go:nosplit
+func syscall_dup2(fd1 uintptr, fd2 uintptr) (val uintptr, err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc_dup2)),
+		n:    2,
+		args: uintptr(unsafe.Pointer(&fd1)),
+	}
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	return call.r1, call.err
+}
+
+//go:nosplit
+func syscall_execve(path, argv, envp uintptr) (err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc_execve)),
+		n:    3,
+		args: uintptr(unsafe.Pointer(&path)),
+	}
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	return call.err
+}
+
+// like exit, but must not split stack, for forkx.
+//go:nosplit
+func syscall_exit(code uintptr) {
+	sysvicall1(&libc_exit, code)
+}
+
+//go:nosplit
+func syscall_fcntl(fd, cmd, arg uintptr) (val, err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc_fcntl)),
+		n:    3,
+		args: uintptr(unsafe.Pointer(&fd)),
+	}
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	return call.r1, call.err
+}
+
+//go:nosplit
+func syscall_fork(flags uintptr) (pid uintptr, err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc_fork)),
+		n:    0,
+		args: uintptr(unsafe.Pointer(nil)),
+	}
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	return call.r1, call.err
+}
+
+func syscall_gethostname() (name string, err uintptr) {
+	cname := new([_MAXHOSTNAMELEN]byte)
+	var args = [2]uintptr{uintptr(unsafe.Pointer(&cname[0])), _MAXHOSTNAMELEN}
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc_gethostname)),
+		n:    2,
+		args: uintptr(unsafe.Pointer(&args[0])),
+	}
+	entersyscallblock()
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	exitsyscall()
+	if call.r1 != 0 {
+		return "", call.err
+	}
+	cname[_MAXHOSTNAMELEN-1] = 0
+	return gostringnocopy(&cname[0]), 0
+}
+
+//go:nosplit
+func syscall_ioctl(fd, req, arg uintptr) (err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc_ioctl)),
+		n:    3,
+		args: uintptr(unsafe.Pointer(&fd)),
+	}
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	return call.err
+}
+
+func syscall_pipe() (r, w, err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&pipe1)),
+		n:    0,
+		args: uintptr(unsafe.Pointer(&pipe1)), // it's unused but must be non-nil, otherwise crashes
+	}
+	entersyscallblock()
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	exitsyscall()
+	return call.r1, call.r2, call.err
+}
+
+// FIXME: haiku: can we fix the auto generator so we won't have to handcode this?
+func syscall_mmap(addr, length, prot, flag, fd uintptr, pos int64) (err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc_mmap)),
+		n:    7,
+		args: uintptr(unsafe.Pointer(&addr)), // it's unused but must be non-nil, otherwise crashes
+	}
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	return call.err
+}
+
+//go:nosplit
+func syscall_rawsysvicall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+	call := libcall{
+		fn:   fn,
+		n:    nargs,
+		args: uintptr(unsafe.Pointer(&a1)),
+	}
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	return call.r1, call.r2, call.err
+}
+
+// This is syscall.RawSyscall, it exists to satisfy some build dependency,
+// but it doesn't work correctly.
+//
+// DO NOT USE!
+//
+// TODO(aram): make this panic once we stop calling fcntl(2) in net using it.
+func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc__kern_generic_syscall)),
+		n:    4,
+		args: uintptr(unsafe.Pointer(&trap)),
+	}
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	return call.r1, call.r2, call.err
+}
+
+//go:nosplit
+func syscall_setgid(gid uintptr) (err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc_setgid)),
+		n:    1,
+		args: uintptr(unsafe.Pointer(&gid)),
+	}
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	return call.err
+}
+
+//go:nosplit
+func syscall_setgroups(ngid, gid uintptr) (err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc_setgroups)),
+		n:    2,
+		args: uintptr(unsafe.Pointer(&ngid)),
+	}
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	return call.err
+}
+
+//go:nosplit
+func syscall_setsid() (pid, err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc_setsid)),
+		n:    0,
+		args: uintptr(unsafe.Pointer(&libc_setsid)), // it's unused but must be non-nil, otherwise crashes
+	}
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	return call.r1, call.err
+}
+
+//go:nosplit
+func syscall_setuid(uid uintptr) (err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc_setuid)),
+		n:    1,
+		args: uintptr(unsafe.Pointer(&uid)),
+	}
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	return call.err
+}
+
+//go:nosplit
+func syscall_setpgid(pid, pgid uintptr) (err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc_setpgid)),
+		n:    2,
+		args: uintptr(unsafe.Pointer(&pid)),
+	}
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	return call.err
+}
+
+// This is syscall.Syscall, it exists to satisfy some build dependency,
+// but it doesn't work correctly.
+//
+// DO NOT USE!
+//
+// TODO(aram): make this panic once we stop calling fcntl(2) in net using it.
+func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc__kern_generic_syscall)),
+		n:    4,
+		args: uintptr(unsafe.Pointer(&trap)),
+	}
+	entersyscallblock()
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	exitsyscall()
+	return call.r1, call.r2, call.err
+}
+
+//go:nosplit
+func syscall_wait4(pid uintptr, wstatus *uint32, options uintptr, rusage unsafe.Pointer) (wpid int, err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc_waitpid)),
+		n:    4,
+		args: uintptr(unsafe.Pointer(&pid)),
+	}
+	//entersyscallblock()
+	//asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	//exitsyscall()
+	return int(call.r1), call.err
+}
+
+//go:nosplit
+func syscall_write(fd, buf, nbyte uintptr) (n, err uintptr) {
+	call := libcall{
+		fn:   uintptr(unsafe.Pointer(&libc_write)),
+		n:    3,
+		args: uintptr(unsafe.Pointer(&fd)),
+	}
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	return call.r1, call.err
+}
-- 
2.19.1


From 7b5189ba69d35cc284e87961b1b979698a973dd4 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Mon, 29 Oct 2018 23:08:40 +0000
Subject: syscall: Initial Haiku amd64 support.


diff --git a/src/syscall/env_unix.go b/src/syscall/env_unix.go
index b5ded9c..32a2d83 100644
--- a/src/syscall/env_unix.go
+++ b/src/syscall/env_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris
 
 // Unix environment variables.
 
diff --git a/src/syscall/exec_unix.go b/src/syscall/exec_unix.go
index 890bfdc..400ddb8 100644
--- a/src/syscall/exec_unix.go
+++ b/src/syscall/exec_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 // Fork, exec, wait, etc.
 
diff --git a/src/syscall/mmap_unix_test.go b/src/syscall/mmap_unix_test.go
index 01f7783..a5c3a84 100644
--- a/src/syscall/mmap_unix_test.go
+++ b/src/syscall/mmap_unix_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd
 
 package syscall_test
 
diff --git a/src/syscall/sockcmsg_unix.go b/src/syscall/sockcmsg_unix.go
index 045a012..de57ae2 100644
--- a/src/syscall/sockcmsg_unix.go
+++ b/src/syscall/sockcmsg_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 // Socket control messages
 
diff --git a/src/syscall/syscall_unix.go b/src/syscall/syscall_unix.go
index a06bd7d..0d5132e 100644
--- a/src/syscall/syscall_unix.go
+++ b/src/syscall/syscall_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 package syscall
 
-- 
2.19.1


From 4299bb92fa3eb28f64af197e130426ddd68ce328 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Mon, 29 Oct 2018 23:14:59 +0000
Subject: syscall: Add Haiku specific definitions for syscall package


diff --git a/src/syscall/asm_haiku_amd64.s b/src/syscall/asm_haiku_amd64.s
new file mode 100644
index 0000000..19e742b
--- /dev/null
+++ b/src/syscall/asm_haiku_amd64.s
@@ -0,0 +1,87 @@
+// Copyright 2014 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.
+
+#include "textflag.h"
+
+//
+// System calls for solaris/amd64 are implemented in ../runtime/syscall_haiku.go
+//
+
+TEXT ·sysvicall6(SB),NOSPLIT,$0
+	JMP	runtime·syscall_sysvicall6(SB)
+
+TEXT ·rawSysvicall6(SB),NOSPLIT,$0
+	JMP	runtime·syscall_rawsysvicall6(SB)
+
+TEXT ·chdir(SB),NOSPLIT,$0
+	JMP	runtime·syscall_chdir(SB)
+
+TEXT ·chroot1(SB),NOSPLIT,$0
+	JMP	runtime·syscall_chroot(SB)
+
+TEXT ·close(SB),NOSPLIT,$0
+	JMP	runtime·syscall_close(SB)
+
+TEXT ·dlopen(SB),NOSPLIT,$0
+	JMP	runtime·syscall_dlopen(SB)
+
+TEXT ·dlclose(SB),NOSPLIT,$0
+	JMP	runtime·syscall_dlclose(SB)
+
+TEXT ·dlsym(SB),NOSPLIT,$0
+	JMP	runtime·syscall_dlsym(SB)
+
+TEXT ·execve(SB),NOSPLIT,$0
+	JMP	runtime·syscall_execve(SB)
+
+TEXT ·exit(SB),NOSPLIT,$0
+	JMP	runtime·syscall_exit(SB)
+
+TEXT ·fcntl1(SB),NOSPLIT,$0
+	JMP	runtime·syscall_fcntl(SB)
+
+TEXT ·forkx(SB),NOSPLIT,$0
+	JMP	runtime·syscall_fork(SB)
+
+TEXT ·gethostname(SB),NOSPLIT,$0
+	JMP	runtime·syscall_gethostname(SB)
+
+TEXT ·ioctl(SB),NOSPLIT,$0
+	JMP	runtime·syscall_ioctl(SB)
+
+TEXT ·pipe(SB),NOSPLIT,$0
+	JMP	runtime·syscall_pipe(SB)
+
+TEXT ·mmap(SB),NOSPLIT,$0
+	JMP	runtime·syscall_mmap(SB)
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0
+	JMP	runtime·syscall_rawsyscall(SB)
+
+TEXT ·setgid(SB),NOSPLIT,$0
+	JMP	runtime·syscall_setgid(SB)
+
+TEXT ·setgroups1(SB),NOSPLIT,$0
+	JMP	runtime·syscall_setgroups(SB)
+
+TEXT ·setsid(SB),NOSPLIT,$0
+	JMP	runtime·syscall_setsid(SB)
+
+TEXT ·setuid(SB),NOSPLIT,$0
+	JMP	runtime·syscall_setuid(SB)
+
+TEXT ·setpgid(SB),NOSPLIT,$0
+	JMP	runtime·syscall_setpgid(SB)
+
+TEXT ·Syscall(SB),NOSPLIT,$0
+	JMP	runtime·syscall_syscall(SB)
+
+TEXT ·wait4(SB),NOSPLIT,$0
+	JMP	runtime·syscall_wait4(SB)
+
+TEXT ·dup2(SB),NOSPLIT,$0
+	JMP	runtime·syscall_dup2(SB)
+
+TEXT ·write1(SB),NOSPLIT,$0
+	JMP	runtime·syscall_write(SB)
diff --git a/src/syscall/exec_haiku.go b/src/syscall/exec_haiku.go
new file mode 100644
index 0000000..2db25eb
--- /dev/null
+++ b/src/syscall/exec_haiku.go
@@ -0,0 +1,245 @@
+// Copyright 2011 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.
+
+package syscall
+
+import (
+	"unsafe"
+)
+
+type SysProcAttr struct {
+	Chroot     string      // Chroot.
+	Credential *Credential // Credential.
+	Setsid     bool        // Create session.
+	Setpgid    bool        // Set process group ID to new pid (SYSV setpgrp)
+	Setctty    bool        // Set controlling terminal to fd 0
+	Noctty     bool        // Detach fd 0 from controlling terminal
+}
+
+// Implemented in runtime package.
+func runtime_BeforeFork()
+func runtime_AfterFork()
+
+func chdir(path uintptr) (err Errno)
+func chroot1(path uintptr) (err Errno)
+func close(fd uintptr) (err Errno)
+func dup2(fd1 uintptr, fd2 uintptr) (val uintptr, err Errno)
+func execve(path uintptr, argv uintptr, envp uintptr) (err Errno)
+func exit(code uintptr)
+func fcntl1(fd uintptr, cmd uintptr, arg uintptr) (val uintptr, err Errno)
+func forkx(flags uintptr) (pid uintptr, err Errno)
+func ioctl(fd uintptr, req uintptr, arg uintptr) (err Errno)
+func setgid(gid uintptr) (err Errno)
+func setgroups1(ngid uintptr, gid uintptr) (err Errno)
+func setsid() (pid uintptr, err Errno)
+func setuid(uid uintptr) (err Errno)
+func setpgid(pid uintptr, pgid uintptr) (err Errno)
+func write1(fd uintptr, buf uintptr, nbyte uintptr) (n uintptr, err Errno)
+
+// Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
+// If a dup or exec fails, write the errno error to pipe.
+// (Pipe is close-on-exec so if exec succeeds, it will be closed.)
+// In the child, this function must not acquire any locks, because
+// they might have been locked at the time of the fork.  This means
+// no rescheduling, no malloc calls, and no new stack segments.
+//
+// We call hand-crafted syscalls, implemented in
+// ../runtime/syscall_solaris.goc, rather than generated libc wrappers
+// because we need to avoid lazy-loading the functions (might malloc,
+// split the stack, or acquire mutexes). We can't call RawSyscall
+// because it's not safe even for BSD-subsystem calls.
+func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
+	// Declare all variables at top in case any
+	// declarations require heap allocation (e.g., err1).
+	var (
+		r1     uintptr
+		err1   Errno
+		nextfd int
+		i      int
+	)
+
+	// guard against side effects of shuffling fds below.
+	// Make sure that nextfd is beyond any currently open files so
+	// that we can't run the risk of overwriting any of them.
+	fd := make([]int, len(attr.Files))
+	nextfd = len(attr.Files)
+	for i, ufd := range attr.Files {
+		if nextfd < int(ufd) {
+			nextfd = int(ufd)
+		}
+		fd[i] = int(ufd)
+	}
+	nextfd++
+
+	// About to call fork.
+	// No more allocation or calls of non-assembly functions.
+	runtime_BeforeFork()
+	r1, err1 = forkx(0x1) // FORK_NOSIGCHLD
+	if err1 != 0 {
+		runtime_AfterFork()
+		return 0, err1
+	}
+
+	if r1 != 0 {
+		// parent; return PID
+		runtime_AfterFork()
+		return int(r1), 0
+	}
+
+	// Fork succeeded, now in child.
+	/*
+
+		// Session ID
+		if sys.Setsid {
+			_, err1 = setsid()
+			if err1 != 0 {
+				goto childerror
+			}
+		}
+
+		// Set process group
+		if sys.Setpgid {
+			err1 = setpgid(0, 0)
+			if err1 != 0 {
+				goto childerror
+			}
+		}
+
+		// Chroot
+		if chroot != nil {
+			err1 = chroot1(uintptr(unsafe.Pointer(chroot)))
+			if err1 != 0 {
+				goto childerror
+			}
+		}
+
+		// User and groups
+		if cred := sys.Credential; cred != nil {
+			ngroups := uintptr(len(cred.Groups))
+			groups := uintptr(0)
+			if ngroups > 0 {
+				groups = uintptr(unsafe.Pointer(&cred.Groups[0]))
+			}
+			err1 = setgroups1(ngroups, groups)
+			if err1 != 0 {
+				goto childerror
+			}
+			err1 = setgid(uintptr(cred.Gid))
+			if err1 != 0 {
+				goto childerror
+			}
+			err1 = setuid(uintptr(cred.Uid))
+			if err1 != 0 {
+				goto childerror
+			}
+		}
+
+		// Chdir
+		if dir != nil {
+			err1 = chdir(uintptr(unsafe.Pointer(dir)))
+			if err1 != 0 {
+				goto childerror
+			}
+		}
+	*/
+	// Pass 1: look for fd[i] < i and move those up above len(fd)
+	// so that pass 2 won't stomp on an fd it needs later.
+	if pipe < nextfd {
+		_, err1 = dup2(uintptr(pipe), uintptr(nextfd))
+		if err1 != 0 {
+			goto childerror
+		}
+		fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC)
+		pipe = nextfd
+		nextfd++
+	}
+	for i = 0; i < len(fd); i++ {
+		if fd[i] >= 0 && fd[i] < int(i) {
+			_, err1 = dup2(uintptr(pipe), uintptr(nextfd))
+			if err1 != 0 {
+				goto childerror
+			}
+			fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC)
+			fd[i] = nextfd
+			nextfd++
+			if nextfd == pipe { // don't stomp on pipe
+				nextfd++
+			}
+		}
+	}
+
+	// Pass 2: dup fd[i] down onto i.
+	for i = 0; i < len(fd); i++ {
+		if fd[i] == -1 {
+			close(uintptr(i))
+			continue
+		}
+		if fd[i] == int(i) {
+			// dup2(i, i) won't clear close-on-exec flag on Linux,
+			// probably not elsewhere either.
+			_, err1 = fcntl1(uintptr(fd[i]), F_SETFD, 0)
+			if err1 != 0 {
+				goto childerror
+			}
+			continue
+		}
+		// The new fd is created NOT close-on-exec,
+		// which is exactly what we want.
+		_, err1 = dup2(uintptr(fd[i]), uintptr(i))
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// By convention, we don't close-on-exec the fds we are
+	// started with, so if len(fd) < 3, close 0, 1, 2 as needed.
+	// Programs that know they inherit fds >= 3 will need
+	// to set them close-on-exec.
+	for i = len(fd); i < 3; i++ {
+		close(uintptr(i))
+	}
+
+	/*// Detach fd 0 from tty
+	if sys.Noctty {
+		err1 = ioctl(0, uintptr(TIOCNOTTY), 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}
+
+	// Make fd 0 the tty
+	if sys.Setctty {
+		err1 = ioctl(0, uintptr(TIOCSCTTY), 0)
+		if err1 != 0 {
+			goto childerror
+		}
+	}*/
+
+	// Time to exec.
+	err1 = execve(
+		uintptr(unsafe.Pointer(argv0)),
+		uintptr(unsafe.Pointer(&argv[0])),
+		uintptr(unsafe.Pointer(&envv[0])))
+
+childerror:
+	// send error code on pipe
+	write1(uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
+	for {
+		exit(253)
+	}
+}
+
+// Try to open a pipe with O_CLOEXEC set on both file descriptors.
+func forkExecPipe(p []int) error {
+	err := Pipe(p)
+	if err != nil {
+		return err
+	}
+	_, err = fcntl(p[0], F_SETFD, FD_CLOEXEC)
+	if err != nil {
+		return err
+	}
+	_, err = fcntl(p[1], F_SETFD, FD_CLOEXEC)
+	return err
+}
diff --git a/src/syscall/so_haiku.go b/src/syscall/so_haiku.go
new file mode 100644
index 0000000..b01f6b7
--- /dev/null
+++ b/src/syscall/so_haiku.go
@@ -0,0 +1,260 @@
+// Copyright 2011 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.
+
+package syscall
+
+import (
+	"sync"
+	"sync/atomic"
+	"unsafe"
+)
+
+// soError describes reasons for shared library load failures.
+type soError struct {
+	Err     error
+	ObjName string
+	Msg     string
+}
+
+func (e *soError) Error() string { return e.Msg }
+
+// Implemented in asm_haiku_amd64.s.
+func rawSysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
+func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
+func dlclose(handle uintptr) (err Errno)
+func dlopen(name *uint8, mode uintptr) (handle uintptr, err Errno)
+func dlsym(handle uintptr, name *uint8) (proc uintptr, err Errno)
+
+// A so implements access to a single shared library object.
+type so struct {
+	Name   string
+	Handle uintptr
+}
+
+// loadSO loads shared library file into memory.
+func loadSO(name string) (*so, error) {
+	namep, err := BytePtrFromString(name)
+	if err != nil {
+		return nil, err
+	}
+	h, e := dlopen(namep, 1) // RTLD_LAZY
+	if e != 0 {
+		return nil, &soError{
+			Err:     e,
+			ObjName: name,
+			Msg:     "Failed to load " + name + ": " + e.Error(),
+		}
+	}
+	d := &so{
+		Name:   name,
+		Handle: uintptr(h),
+	}
+	return d, nil
+}
+
+// mustLoadSO is like loadSO but panics if load operation fails.
+func mustLoadSO(name string) *so {
+	d, e := loadSO(name)
+	if e != nil {
+		panic(e)
+	}
+	return d
+}
+
+// FindProc searches shared library d for procedure named name and returns
+// *proc if found. It returns an error if the search fails.
+func (d *so) FindProc(name string) (*proc, error) {
+	namep, err := BytePtrFromString(name)
+	if err != nil {
+		return nil, err
+	}
+	a, _ := dlsym(uintptr(d.Handle), namep)
+	if a == 0 {
+		return nil, &soError{
+			Err:     ENOSYS,
+			ObjName: name,
+			Msg:     "Failed to find " + name + " procedure in " + d.Name,
+		}
+	}
+	p := &proc{
+		SO:   d,
+		Name: name,
+		addr: a,
+	}
+	return p, nil
+}
+
+// MustFindProc is like FindProc but panics if search fails.
+func (d *so) MustFindProc(name string) *proc {
+	p, e := d.FindProc(name)
+	if e != nil {
+		panic(e)
+	}
+	return p
+}
+
+// Release unloads shared library d from memory.
+func (d *so) Release() (err error) {
+	return dlclose(d.Handle)
+}
+
+// A proc implements access to a procedure inside a shared library.
+type proc struct {
+	SO   *so
+	Name string
+	addr uintptr
+}
+
+// Addr returns the address of the procedure represented by p.
+// The return value can be passed to Syscall to run the procedure.
+func (p *proc) Addr() uintptr {
+	return p.addr
+}
+
+// Call executes procedure p with arguments a. It will panic, if more then
+// 6 arguments are supplied.
+//
+// The returned error is always non-nil, constructed from the result of
+// GetLastError.  Callers must inspect the primary return value to decide
+// whether an error occurred (according to the semantics of the specific
+// function being called) before consulting the error. The error will be
+// guaranteed to contain syscall.Errno.
+func (p *proc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
+	switch len(a) {
+	case 0:
+		return sysvicall6(p.Addr(), uintptr(len(a)), 0, 0, 0, 0, 0, 0)
+	case 1:
+		return sysvicall6(p.Addr(), uintptr(len(a)), a[0], 0, 0, 0, 0, 0)
+	case 2:
+		return sysvicall6(p.Addr(), uintptr(len(a)), a[0], a[1], 0, 0, 0, 0)
+	case 3:
+		return sysvicall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], 0, 0, 0)
+	case 4:
+		return sysvicall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], 0, 0)
+	case 5:
+		return sysvicall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], 0)
+	case 6:
+		return sysvicall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5])
+	default:
+		panic("Call " + p.Name + " with too many arguments " + itoa(len(a)) + ".")
+	}
+	return
+}
+
+// A lazySO implements access to a single shared library.  It will delay
+// the load of the shared library until the first call to its Handle method
+// or to one of its lazyProc's Addr method.
+type lazySO struct {
+	mu   sync.Mutex
+	so   *so // non nil once SO is loaded
+	Name string
+}
+
+// Load loads single shared file d.Name into memory. It returns an error if
+// fails.  Load will not try to load SO, if it is already loaded into memory.
+func (d *lazySO) Load() error {
+	// Non-racy version of:
+	// if d.so == nil {
+	if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.so))) == nil {
+		d.mu.Lock()
+		defer d.mu.Unlock()
+		if d.so == nil {
+			so, e := loadSO(d.Name)
+			if e != nil {
+				return e
+			}
+			// Non-racy version of:
+			// d.so = so
+			atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.so)), unsafe.Pointer(so))
+		}
+	}
+	return nil
+}
+
+// mustLoad is like Load but panics if search fails.
+func (d *lazySO) mustLoad() {
+	e := d.Load()
+	if e != nil {
+		panic(e)
+	}
+}
+
+// Handle returns d's module handle.
+func (d *lazySO) Handle() uintptr {
+	d.mustLoad()
+	return uintptr(d.so.Handle)
+}
+
+// NewProc returns a lazyProc for accessing the named procedure in the SO d.
+func (d *lazySO) NewProc(name string) *lazyProc {
+	return &lazyProc{l: d, Name: name}
+}
+
+// newLazySO creates new lazySO associated with SO file.
+func newLazySO(name string) *lazySO {
+	return &lazySO{Name: name}
+}
+
+// A lazyProc implements access to a procedure inside a lazySO.
+// It delays the lookup until the Addr method is called.
+type lazyProc struct {
+	mu   sync.Mutex
+	Name string
+	l    *lazySO
+	proc *proc
+}
+
+// Find searches the shared library for procedure named p.Name. It returns an
+// error if search fails. Find will not search procedure, if it is already
+// found and loaded into memory.
+func (p *lazyProc) Find() error {
+	// Non-racy version of:
+	// if p.proc == nil {
+	if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc))) == nil {
+		p.mu.Lock()
+		defer p.mu.Unlock()
+		if p.proc == nil {
+			e := p.l.Load()
+			if e != nil {
+				return e
+			}
+			proc, e := p.l.so.FindProc(p.Name)
+			if e != nil {
+				return e
+			}
+			// Non-racy version of:
+			// p.proc = proc
+			atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc)), unsafe.Pointer(proc))
+		}
+	}
+	return nil
+}
+
+// mustFind is like Find but panics if search fails.
+func (p *lazyProc) mustFind() {
+	e := p.Find()
+	if e != nil {
+		panic(e)
+	}
+}
+
+// Addr returns the address of the procedure represented by p.
+// The return value can be passed to Syscall to run the procedure.
+func (p *lazyProc) Addr() uintptr {
+	p.mustFind()
+	return p.proc.Addr()
+}
+
+// Call executes procedure p with arguments a. It will panic, if more then
+// 6 arguments are supplied.
+//
+// The returned error is always non-nil, constructed from the result of
+// GetLastError.  Callers must inspect the primary return value to decide
+// whether an error occurred (according to the semantics of the specific
+// function being called) before consulting the error. The error will be
+// guaranteed to contain syscall.Errno.
+func (p *lazyProc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
+	p.mustFind()
+	return p.proc.Call(a...)
+}
diff --git a/src/syscall/syscall_haiku.go b/src/syscall/syscall_haiku.go
new file mode 100644
index 0000000..0147b5c
--- /dev/null
+++ b/src/syscall/syscall_haiku.go
@@ -0,0 +1,548 @@
+// 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.
+
+// Solaris system calls.
+// This file is compiled as ordinary Go code,
+// but it is also input to mksyscall,
+// which parses the //sys lines and generates system call stubs.
+// Note that sometimes we use a lowercase //sys name and wrap
+// it in our own nicer implementation, either here or in
+// syscall_solaris.go or syscall_unix.go.
+
+package syscall
+
+import "runtime"
+import "unsafe"
+
+/*type SockaddrDatalink struct {
+	Family uint16
+	Index  uint16
+	Type   uint8
+	Nlen   uint8
+	Alen   uint8
+	Slen   uint8
+	Data   [244]int8
+	raw    RawSockaddrDatalink
+}*/
+
+func clen(n []byte) int {
+	for i := 0; i < len(n); i++ {
+		if n[i] == 0 {
+			return i
+		}
+	}
+	return len(n)
+}
+
+// ParseDirent parses up to max directory entries in buf,
+// appending the names to names.  It returns the number
+// bytes consumed from buf, the number of entries added
+// to names, and the new names slice.
+func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
+	origlen := len(buf)
+	for max != 0 && len(buf) > 0 {
+		dirent := (*Dirent)(unsafe.Pointer(&buf[0]))
+		if dirent.Reclen == 0 {
+			buf = nil
+			break
+		}
+		buf = buf[dirent.Reclen:]
+		if dirent.Ino == 0 { // File absent in directory.
+			continue
+		}
+		bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
+		var name = string(bytes[0:clen(bytes[:])])
+		if name == "." || name == ".." { // Useless names
+			continue
+		}
+		max--
+		count++
+		names = append(names, name)
+	}
+	return origlen - len(buf), count, names
+}
+
+func pipe() (r uintptr, w uintptr, err uintptr)
+
+//sys	pipe2(fds []int) (err error) = libroot.pipe
+
+func Pipe(p []int) (err error) {
+	if len(p) != 2 {
+		return EINVAL
+	}
+	if runtime.GOARCH == "386" {
+		return pipe2(p)
+	}
+	r0, w0, e1 := pipe()
+	if e1 != 0 {
+		err = Errno(e1)
+	}
+	p[0], p[1] = int(r0), int(w0)
+	return
+}
+
+func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
+	if sa.Port < 0 || sa.Port > 0xFFFF {
+		return nil, 0, EINVAL
+	}
+	sa.raw.Family = AF_INET
+	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
+	p[0] = byte(sa.Port >> 8)
+	p[1] = byte(sa.Port)
+	for i := 0; i < len(sa.Addr); i++ {
+		sa.raw.Addr[i] = sa.Addr[i]
+	}
+	return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
+}
+
+func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
+	if sa.Port < 0 || sa.Port > 0xFFFF {
+		return nil, 0, EINVAL
+	}
+	sa.raw.Family = AF_INET6
+	p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
+	p[0] = byte(sa.Port >> 8)
+	p[1] = byte(sa.Port)
+	sa.raw.Scope_id = sa.ZoneId
+	for i := 0; i < len(sa.Addr); i++ {
+		sa.raw.Addr[i] = sa.Addr[i]
+	}
+	return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
+}
+
+func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
+	name := sa.Name
+	n := len(name)
+	if n >= len(sa.raw.Path) {
+		return nil, 0, EINVAL
+	}
+	sa.raw.Family = AF_UNIX
+	for i := 0; i < n; i++ {
+		sa.raw.Path[i] = int8(name[i])
+	}
+	// length is family (uint16), name, NUL.
+	sl := _Socklen(2)
+	if n > 0 {
+		sl += _Socklen(n) + 1
+	}
+	if sa.raw.Path[0] == '@' {
+		sa.raw.Path[0] = 0
+		// Don't count trailing NUL for abstract address.
+		sl--
+	}
+
+	return unsafe.Pointer(&sa.raw), sl, nil
+}
+
+func Getsockname(fd int) (sa Sockaddr, err error) {
+	var rsa RawSockaddrAny
+	var len _Socklen = SizeofSockaddrAny
+	if err = getsockname(fd, &rsa, &len); err != nil {
+		return
+	}
+	return anyToSockaddr(&rsa)
+}
+
+// The const provides a compile-time constant so clients
+// can adjust to whether there is a working Getwd and avoid
+// even linking this function into the binary.  See ../os/getwd.go.
+const ImplementsGetwd = false
+
+func Getwd() (string, error) { return "", ENOTSUP }
+
+/*
+ * Wrapped
+ */
+
+//sysnb	getgroups(ngid int, gid *_Gid_t) (n int, err error)
+//sysnb	setgroups(ngid int, gid *_Gid_t) (err error)
+
+func Getgroups() (gids []int, err error) {
+	n, err := getgroups(0, nil)
+	if err != nil {
+		return nil, err
+	}
+	if n == 0 {
+		return nil, nil
+	}
+
+	// Sanity check group count.  Max is 16 on BSD.
+	if n < 0 || n > 1000 {
+		return nil, EINVAL
+	}
+
+	a := make([]_Gid_t, n)
+	n, err = getgroups(n, &a[0])
+	if err != nil {
+		return nil, err
+	}
+	gids = make([]int, n)
+	for i, v := range a[0:n] {
+		gids[i] = int(v)
+	}
+	return
+}
+
+func Setgroups(gids []int) (err error) {
+	if len(gids) == 0 {
+		return setgroups(0, nil)
+	}
+
+	a := make([]_Gid_t, len(gids))
+	for i, v := range gids {
+		a[i] = _Gid_t(v)
+	}
+	return setgroups(len(a), &a[0])
+}
+
+func ReadDirent(fd int, buf []byte) (n int, err error) {
+	panic("Not implemented")
+}
+
+// Wait status: 8 bits at the bottom is exit status
+// If all bits other than the 8 bottom are empty, then exited
+// next 8 bits are signal number that caused exit
+// next 8 bits are signal that caused stop
+// core is 0x10000
+// continued is 0x20000
+
+type WaitStatus uint32
+
+const (
+	mask      = 0xFF
+	core      = 0x10000
+	continued = 0x20000
+	shift     = 8
+
+	exited = 0
+)
+
+func (w WaitStatus) Exited() bool { return w&^mask == exited }
+
+func (w WaitStatus) ExitStatus() int {
+	if w&^mask != exited {
+		return -1
+	}
+	return int(w & mask)
+}
+
+func (w WaitStatus) Signaled() bool { return ((w >> 8) & mask) != 0 }
+
+func (w WaitStatus) Signal() Signal {
+	sig := Signal((w >> 8) & mask)
+	if sig == 0 {
+		return -1
+	}
+	return sig
+}
+
+func (w WaitStatus) CoreDump() bool { return w&core != 0 }
+
+func (w WaitStatus) Stopped() bool { return (w>>16)&mask != 0 }
+
+func (w WaitStatus) Continued() bool { return w&continued != 0 }
+
+func (w WaitStatus) StopSignal() Signal {
+	if !w.Stopped() {
+		return -1
+	}
+	return Signal(w>>16) & mask
+}
+
+func (w WaitStatus) TrapCause() int { return -1 }
+
+func wait4(pid uintptr, wstatus *WaitStatus, options uintptr, rusage *Rusage) (wpid uintptr, err uintptr)
+
+func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
+	r0, e1 := wait4(uintptr(pid), wstatus, uintptr(options), rusage)
+	if e1 != 0 {
+		err = Errno(e1)
+	}
+	return int(r0), err
+}
+
+func gethostname() (name string, err uintptr)
+
+func Gethostname() (name string, err error) {
+	name, e1 := gethostname()
+	if e1 != 0 {
+		err = Errno(e1)
+	}
+	return name, err
+}
+
+func UtimesNano(path string, ts []Timespec) (err error) {
+	if len(ts) != 2 {
+		return EINVAL
+	}
+	var tv [2]Timeval
+	for i := 0; i < 2; i++ {
+		tv[i].Sec = ts[i].Sec
+		tv[i].Usec = int32(ts[i].Nsec / 1000)
+	}
+	return Utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
+}
+
+//sys	fcntl(fd int, cmd int, arg int) (val int, err error)
+
+// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
+func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
+	_, _, e1 := sysvicall6(procfcntl.Addr(), 3, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(lk)), 0, 0, 0)
+	if e1 != 0 {
+		return e1
+	}
+	return nil
+}
+
+func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
+	switch rsa.Addr.Family {
+	case AF_UNIX:
+		pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
+		sa := new(SockaddrUnix)
+		// Assume path ends at NUL.
+		// This is not technically the Solaris semantics for
+		// abstract Unix domain sockets -- they are supposed
+		// to be uninterpreted fixed-size binary blobs -- but
+		// everyone uses this convention.
+		n := 0
+		for n < len(pp.Path) && pp.Path[n] != 0 {
+			n++
+		}
+		bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
+		sa.Name = string(bytes)
+		return sa, nil
+
+	case AF_INET:
+		pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
+		sa := new(SockaddrInet4)
+		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
+		sa.Port = int(p[0])<<8 + int(p[1])
+		for i := 0; i < len(sa.Addr); i++ {
+			sa.Addr[i] = pp.Addr[i]
+		}
+		return sa, nil
+
+	case AF_INET6:
+		pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
+		sa := new(SockaddrInet6)
+		p := (*[2]byte)(unsafe.Pointer(&pp.Port))
+		sa.Port = int(p[0])<<8 + int(p[1])
+		sa.ZoneId = pp.Scope_id
+		for i := 0; i < len(sa.Addr); i++ {
+			sa.Addr[i] = pp.Addr[i]
+		}
+		return sa, nil
+	}
+	return nil, EAFNOSUPPORT
+}
+
+//sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = libnetwork.accept
+
+func Accept(fd int) (nfd int, sa Sockaddr, err error) {
+	var rsa RawSockaddrAny
+	var len _Socklen = SizeofSockaddrAny
+	nfd, err = accept(fd, &rsa, &len)
+	if err != nil {
+		return
+	}
+	sa, err = anyToSockaddr(&rsa)
+	if err != nil {
+		Close(nfd)
+		nfd = 0
+	}
+	return
+}
+
+func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
+	var msg Msghdr
+	var rsa RawSockaddrAny
+	msg.Name = (*byte)(unsafe.Pointer(&rsa))
+	msg.Namelen = uint32(SizeofSockaddrAny)
+	var iov Iovec
+	if len(p) > 0 {
+		iov.Base = (*byte)(unsafe.Pointer(&p[0]))
+		iov.SetLen(len(p))
+	}
+	var dummy byte
+	if len(oob) > 0 {
+		// receive at least one normal byte
+		if len(p) == 0 {
+			iov.Base = &dummy
+			iov.SetLen(1)
+		}
+		//msg.Accrights = (*int8)(unsafe.Pointer(&oob[0]))
+	}
+	msg.Iov = &iov
+	msg.Iovlen = 1
+	if n, err = recvmsg(fd, &msg, flags); err != nil {
+		return
+	}
+	oobn = 0 //int(msg.Accrightslen)
+	// source address is only specified if the socket is unconnected
+	if rsa.Addr.Family != AF_UNSPEC {
+		from, err = anyToSockaddr(&rsa)
+	}
+	return
+}
+
+func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
+	_, err = SendmsgN(fd, p, oob, to, flags)
+	return
+}
+
+//sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libnetwork.sendmsg
+
+func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
+	var ptr unsafe.Pointer
+	var salen _Socklen
+	if to != nil {
+		ptr, salen, err = to.sockaddr()
+		if err != nil {
+			return 0, err
+		}
+	}
+	var msg Msghdr
+	msg.Name = (*byte)(unsafe.Pointer(ptr))
+	msg.Namelen = uint32(salen)
+	var iov Iovec
+	if len(p) > 0 {
+		iov.Base = (*byte)(unsafe.Pointer(&p[0]))
+		iov.SetLen(len(p))
+	}
+	var dummy byte
+	if len(oob) > 0 {
+		// send at least one normal byte
+		if len(p) == 0 {
+			iov.Base = &dummy
+			iov.SetLen(1)
+		}
+		//msg.Accrights = (*int8)(unsafe.Pointer(&oob[0]))
+	}
+	msg.Iov = &iov
+	msg.Iovlen = 1
+	if n, err = sendmsg(fd, &msg, flags); err != nil {
+		return 0, err
+	}
+	if len(oob) > 0 && len(p) == 0 {
+		n = 0
+	}
+	return n, nil
+}
+
+// FIXME: haiku: fix the auto generator so that it can deal with more than 6 params
+func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
+
+/*
+ * Exposed directly
+ */
+//sys	Access(path string, mode uint32) (err error)
+//sys	Adjtime(delta *Timeval, olddelta *Timeval) (err error)
+//sys	Chdir(path string) (err error)
+//sys	Chmod(path string, mode uint32) (err error)
+//sys	Chown(path string, uid int, gid int) (err error)
+//sys	Chroot(path string) (err error)
+//sys	Close(fd int) (err error)
+//sys	Dup(fd int) (nfd int, err error)
+//sys	Exit(code int)
+//sys	Fchdir(fd int) (err error)
+//sys	Fchmod(fd int, mode uint32) (err error)
+//sys	Fchown(fd int, uid int, gid int) (err error)
+//sys	Fpathconf(fd int, name int) (val int, err error)
+//sys	Fstat(fd int, stat *Stat_t) (err error)
+//sysnb	Getgid() (gid int)
+//sysnb	Getpid() (pid int)
+//sys	Geteuid() (euid int)
+//sys	Getegid() (egid int)
+//sys	Getppid() (ppid int)
+//sys	Getpriority(which int, who int) (n int, err error)
+//sysnb	Getrlimit(which int, lim *Rlimit) (err error)
+//sysnb	Gettimeofday(tv *Timeval) (err error)
+//sysnb	Getuid() (uid int)
+//sys	Kill(pid int, signum Signal) (err error)
+//sys	Lchown(path string, uid int, gid int) (err error)
+//sys	Link(path string, link string) (err error)
+//sys	Listen(s int, backlog int) (err error) = libnetwork.listen
+//sys	Lstat(path string, stat *Stat_t) (err error)
+//sys	Mkdir(path string, mode uint32) (err error)
+//sys	Mknod(path string, mode uint32, dev int) (err error)
+//sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
+//sys	Open(path string, mode int, perm uint32) (fd int, err error)
+//sys	Pathconf(path string, name int) (val int, err error)
+//sys	Pread(fd int, p []byte, offset int64) (n int, err error)
+//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
+//sys	read(fd int, p []byte) (n int, err error)
+//sys	Readlink(path string, buf []byte) (n int, err error)
+//sys	Rename(from string, to string) (err error)
+//sys	Rmdir(path string) (err error)
+//sys	Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek
+//sysnb	Setegid(egid int) (err error)
+//sysnb	Seteuid(euid int) (err error)
+//sysnb	Setgid(gid int) (err error)
+//sysnb	Setpgid(pid int, pgid int) (err error)
+//sys	Setpriority(which int, who int, prio int) (err error)
+//sysnb	Setregid(rgid int, egid int) (err error)
+//sysnb	Setreuid(ruid int, euid int) (err error)
+//sysnb	Setrlimit(which int, lim *Rlimit) (err error)
+//sysnb	Setsid() (pid int, err error)
+//sysnb	Setuid(uid int) (err error)
+//sys	Shutdown(s int, how int) (err error) = libnetwork.shutdown
+//sys	Stat(path string, stat *Stat_t) (err error)
+//sys	Symlink(path string, link string) (err error)
+//sys	Sync() (err error)
+//sys	Truncate(path string, length int64) (err error)
+//sys	Fsync(fd int) (err error)
+//sys	Ftruncate(fd int, length int64) (err error)
+//sys	Umask(newmask int) (oldmask int)
+//sys	Unlink(path string) (err error)
+//sys	Utimes(path string, times *[2]Timeval) (err error)
+//sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libnetwork.bind
+//sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libnetwork.connect
+/*//sys	mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)*/
+//sys	munmap(addr uintptr, length uintptr) (err error)
+//sys	sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = libnetwork.sendto
+//sys	socket(domain int, typ int, proto int) (fd int, err error) = libnetwork.socket
+//sysnb	socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) = libnetwork.socketpair
+//sys	write(fd int, p []byte) (n int, err error)
+//sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) = libnetwork.getsockopt
+//sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libnetwork.getpeername
+//sys	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libnetwork.getsockname
+//sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) = libnetwork.setsockopt
+//sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = libnetwork.recvfrom
+//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libnetwork.recvmsg
+
+//sys	Fdopendir(fd int) (dir unsafe.Pointer, err error)
+//sys	Readdir_r(dir unsafe.Pointer, entry *Dirent, result **Dirent) (status int)
+//sys	Closedir(dir unsafe.Pointer) (status int, err error)
+
+func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
+	r0, _, e1 := sysvicall6(procread.Addr(), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
+	r0, _, e1 := sysvicall6(procwrite.Addr(), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+var mapper = &mmapper{
+	active: make(map[*byte][]byte),
+	mmap:   mmap,
+	munmap: munmap,
+}
+
+func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
+	return mapper.Mmap(fd, offset, length, prot, flags)
+}
+
+func Munmap(b []byte) (err error) {
+	return mapper.Munmap(b)
+}
diff --git a/src/syscall/syscall_haiku_amd64.go b/src/syscall/syscall_haiku_amd64.go
new file mode 100644
index 0000000..2c0cd69
--- /dev/null
+++ b/src/syscall/syscall_haiku_amd64.go
@@ -0,0 +1,37 @@
+// 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.
+
+package syscall
+
+func Getpagesize() int { return 4096 }
+
+func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
+
+func NsecToTimespec(nsec int64) (ts Timespec) {
+	ts.Sec = int32(nsec / 1e9)
+	ts.Nsec = nsec % 1e9
+	return
+}
+
+func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
+
+func NsecToTimeval(nsec int64) (tv Timeval) {
+	nsec += 999 // round up to microsecond
+	tv.Usec = int32(nsec % 1e9 / 1e3)
+	tv.Sec = int32(nsec / 1e9)
+	return
+}
+
+func (iov *Iovec) SetLen(length int) {
+	iov.Len = uint64(length)
+}
+
+func (cmsg *Cmsghdr) SetLen(length int) {
+	cmsg.Len = uint32(length)
+}
+
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+	// TODO(aram): implement this, see issue 5847.
+	panic("unimplemented")
+}
diff --git a/src/syscall/types_haiku.go b/src/syscall/types_haiku.go
new file mode 100644
index 0000000..7f4cb70
--- /dev/null
+++ b/src/syscall/types_haiku.go
@@ -0,0 +1,170 @@
+// 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.
+
+// +build ignore
+
+/*
+Input to cgo -godefs.  See also mkerrors.sh and mkall.sh
+*/
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package syscall
+
+/*
+#define KERNEL
+#include <dirent.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <termios.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/resource.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/icmp6.h>
+#include <netinet/tcp.h>
+
+enum {
+	sizeofPtr = sizeof(void*),
+};
+
+union sockaddr_all {
+	struct sockaddr s1;	// this one gets used for fields
+	struct sockaddr_in s2;	// these pad it out
+	struct sockaddr_in6 s3;
+	struct sockaddr_un s4;
+	struct sockaddr_dl s5;
+};
+
+struct sockaddr_any {
+	struct sockaddr addr;
+	char pad[sizeof(union sockaddr_all) - sizeof(struct sockaddr)];
+};
+
+*/
+import "C"
+
+// Machine characteristics; for internal use.
+
+const (
+	sizeofPtr      = C.sizeofPtr
+	sizeofShort    = C.sizeof_short
+	sizeofInt      = C.sizeof_int
+	sizeofLong     = C.sizeof_long
+	sizeofLongLong = C.sizeof_longlong
+)
+
+// Basic types
+
+type (
+	_C_short     C.short
+	_C_int       C.int
+	_C_long      C.long
+	_C_long_long C.longlong
+)
+
+// Time
+
+type Timespec C.struct_timespec
+
+type Timeval C.struct_timeval
+
+// Processes
+
+type Rusage C.struct_rusage
+
+type Rlimit C.struct_rlimit
+
+type _Gid_t C.gid_t
+
+// Files
+
+type Stat_t C.struct_stat
+
+type Flock_t C.struct_flock
+
+// FIXME: haiku: Manual declaration because Dirent needs the padding
+type Dirent struct {
+	Dev       int32
+	Pdev      int32
+	Ino       int64
+	Pino      int64
+	Reclen    uint16
+	Name      [1 + 256]int8
+	Pad_cgo_0 [1]byte
+}
+
+// Sockets
+
+type RawSockaddrInet4 C.struct_sockaddr_in
+
+type RawSockaddrInet6 C.struct_sockaddr_in6
+
+type RawSockaddrUnix C.struct_sockaddr_un
+
+type RawSockaddrDatalink C.struct_sockaddr_dl
+
+type RawSockaddr C.struct_sockaddr
+
+type RawSockaddrAny C.struct_sockaddr_any
+
+type _Socklen C.socklen_t
+
+type Linger C.struct_linger
+
+type Iovec C.struct_iovec
+
+type IPMreq C.struct_ip_mreq
+
+type IPv6Mreq C.struct_ipv6_mreq
+
+type Msghdr C.struct_msghdr
+
+type Cmsghdr C.struct_cmsghdr
+
+type Inet6Pktinfo C.struct_in6_pktinfo
+
+type ICMPv6Filter C.struct_icmp6_filter
+
+const (
+	SizeofSockaddrInet4    = C.sizeof_struct_sockaddr_in
+	SizeofSockaddrInet6    = C.sizeof_struct_sockaddr_in6
+	SizeofSockaddrAny      = C.sizeof_struct_sockaddr_any
+	SizeofSockaddrUnix     = C.sizeof_struct_sockaddr_un
+	SizeofSockaddrDatalink = C.sizeof_struct_sockaddr_dl
+	SizeofLinger           = C.sizeof_struct_linger
+	SizeofIPMreq           = C.sizeof_struct_ip_mreq
+	SizeofIPv6Mreq         = C.sizeof_struct_ipv6_mreq
+	SizeofMsghdr           = C.sizeof_struct_msghdr
+	SizeofCmsghdr          = C.sizeof_struct_cmsghdr
+	SizeofInet6Pktinfo     = C.sizeof_struct_in6_pktinfo
+	SizeofICMPv6Filter     = C.sizeof_struct_icmp6_filter
+)
+
+// Select
+
+type FdSet C.fd_set
+
+// Terminal handling
+
+type Termios C.struct_termios
+
+// Fake constant needed by net package
+
+const (
+	F_DUPFD_CLOEXEC = 0xdeadf00d
+)
diff --git a/src/syscall/zerrors_haiku_amd64.go b/src/syscall/zerrors_haiku_amd64.go
new file mode 100644
index 0000000..6fd2ed2
--- /dev/null
+++ b/src/syscall/zerrors_haiku_amd64.go
@@ -0,0 +1,640 @@
+// mkerrors.sh -m64
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs -- -m64 _const.go
+
+package syscall
+
+const (
+	AF_APPLETALK              = 0x2
+	AF_BLUETOOTH              = 0xa
+	AF_DLI                    = 0x6
+	AF_INET                   = 0x1
+	AF_INET6                  = 0x5
+	AF_IPX                    = 0x7
+	AF_LINK                   = 0x4
+	AF_LOCAL                  = 0x9
+	AF_MAX                    = 0xb
+	AF_NOTIFY                 = 0x8
+	AF_ROUTE                  = 0x3
+	AF_UNIX                   = 0x9
+	AF_UNSPEC                 = 0x0
+	B0                        = 0x0
+	B110                      = 0x3
+	B115200                   = 0x11
+	B1200                     = 0x9
+	B134                      = 0x4
+	B150                      = 0x5
+	B1800                     = 0xa
+	B19200                    = 0xe
+	B200                      = 0x6
+	B230400                   = 0x12
+	B2400                     = 0xb
+	B300                      = 0x7
+	B31250                    = 0x13
+	B38400                    = 0xf
+	B4800                     = 0xc
+	B50                       = 0x1
+	B57600                    = 0x10
+	B600                      = 0x8
+	B75                       = 0x2
+	B9600                     = 0xd
+	BRKINT                    = 0x2
+	CLOCAL                    = 0x800
+	CREAD                     = 0x80
+	CS5                       = 0x0
+	CS6                       = 0x0
+	CS7                       = 0x0
+	CS8                       = 0x20
+	CSIZE                     = 0x20
+	CSTOPB                    = 0x40
+	ECHO                      = 0x8
+	ECHOCTL                   = 0x400
+	ECHOE                     = 0x10
+	ECHOK                     = 0x20
+	ECHOKE                    = 0x1000
+	ECHONL                    = 0x40
+	ECHOPRT                   = 0x800
+	EV_BREAK                  = 0x2
+	EV_CARRIER                = 0x4
+	EV_CARRIERLOST            = 0x8
+	EV_RING                   = 0x1
+	FD_CLOEXEC                = 0x1
+	FD_SETSIZE                = 0x400
+	FLUSHO                    = 0x2000
+	F_DUPFD                   = 0x1
+	F_GETFD                   = 0x2
+	F_GETFL                   = 0x8
+	F_GETLK                   = 0x20
+	F_LOCK                    = 0x1
+	F_OK                      = 0x0
+	F_RDLCK                   = 0x40
+	F_SETFD                   = 0x4
+	F_SETFL                   = 0x10
+	F_SETLK                   = 0x80
+	F_SETLKW                  = 0x100
+	F_TEST                    = 0x3
+	F_TLOCK                   = 0x2
+	F_ULOCK                   = 0x0
+	F_UNLCK                   = 0x200
+	F_WRLCK                   = 0x400
+	HUPCL                     = 0x400
+	ICANON                    = 0x2
+	ICRNL                     = 0x100
+	IEXTEN                    = 0x200
+	IFF_ALLMULTI              = 0x200
+	IFF_AUTOUP                = 0x80
+	IFF_AUTO_CONFIGURED       = 0x2000
+	IFF_BROADCAST             = 0x2
+	IFF_CONFIGURING           = 0x4000
+	IFF_LINK                  = 0x1000
+	IFF_LOOPBACK              = 0x8
+	IFF_MULTICAST             = 0x8000
+	IFF_NOARP                 = 0x40
+	IFF_POINTOPOINT           = 0x10
+	IFF_PROMISC               = 0x100
+	IFF_SIMPLEX               = 0x800
+	IFF_UP                    = 0x1
+	IFNAMSIZ                  = 0x20
+	IGNBRK                    = 0x1
+	IGNCR                     = 0x80
+	IGNPAR                    = 0x4
+	INLCR                     = 0x40
+	INPCK                     = 0x10
+	IN_CLASSA_HOST            = 0xffffff
+	IN_CLASSA_MAX             = 0x80
+	IN_CLASSA_NET             = 0xff000000
+	IN_CLASSA_NSHIFT          = 0x18
+	IN_CLASSB_HOST            = 0xffff
+	IN_CLASSB_MAX             = 0x10000
+	IN_CLASSB_NET             = 0xffff0000
+	IN_CLASSB_NSHIFT          = 0x10
+	IN_CLASSC_HOST            = 0xff
+	IN_CLASSC_NET             = 0xffffff00
+	IN_CLASSC_NSHIFT          = 0x8
+	IN_CLASSD_HOST            = 0xfffffff
+	IN_CLASSD_NET             = 0xf0000000
+	IN_CLASSD_NSHIFT          = 0x1c
+	IN_LOOPBACKNET            = 0x7f
+	IPPROTO_AH                = 0x33
+	IPPROTO_DSTOPTS           = 0x3c
+	IPPROTO_ESP               = 0x32
+	IPPROTO_ETHERIP           = 0x61
+	IPPROTO_FRAGMENT          = 0x2c
+	IPPROTO_HOPOPTS           = 0x0
+	IPPROTO_ICMP              = 0x1
+	IPPROTO_ICMPV6            = 0x3a
+	IPPROTO_IGMP              = 0x2
+	IPPROTO_IP                = 0x0
+	IPPROTO_IPV6              = 0x29
+	IPPROTO_MAX               = 0x100
+	IPPROTO_NONE              = 0x3b
+	IPPROTO_RAW               = 0xff
+	IPPROTO_ROUTING           = 0x2b
+	IPPROTO_TCP               = 0x6
+	IPPROTO_UDP               = 0x11
+	IPV6_DEFHLIM              = 0x40
+	IPV6_DSTOPTS              = 0x24
+	IPV6_FLOWINFO_MASK        = 0xffffff0f
+	IPV6_FLOWLABEL_MASK       = 0xffff0f00
+	IPV6_FRAGTTL              = 0x78
+	IPV6_HLIMDEC              = 0x1
+	IPV6_HOPLIMIT             = 0x21
+	IPV6_HOPOPTS              = 0x23
+	IPV6_JOIN_GROUP           = 0x1c
+	IPV6_LEAVE_GROUP          = 0x1d
+	IPV6_MAXHLIM              = 0xff
+	IPV6_MAXOPTHDR            = 0x800
+	IPV6_MAXPACKET            = 0xffff
+	IPV6_MMTU                 = 0x500
+	IPV6_MULTICAST_HOPS       = 0x19
+	IPV6_MULTICAST_IF         = 0x18
+	IPV6_MULTICAST_LOOP       = 0x1a
+	IPV6_PKTINFO              = 0x1f
+	IPV6_RECVHOPLIMIT         = 0x22
+	IPV6_RECVPKTINFO          = 0x20
+	IPV6_RTHDR                = 0x25
+	IPV6_UNICAST_HOPS         = 0x1b
+	IPV6_V6ONLY               = 0x1e
+	IPV6_VERSION              = 0x60
+	IPV6_VERSION_MASK         = 0xf0
+	IP_ADD_MEMBERSHIP         = 0xc
+	IP_ADD_SOURCE_MEMBERSHIP  = 0x10
+	IP_BLOCK_SOURCE           = 0xe
+	IP_DF                     = 0x4000
+	IP_DROP_MEMBERSHIP        = 0xd
+	IP_DROP_SOURCE_MEMBERSHIP = 0x11
+	IP_HDRINCL                = 0x2
+	IP_MAXPACKET              = 0xffff
+	IP_MAX_MEMBERSHIPS        = 0x14
+	IP_MF                     = 0x2000
+	IP_MSS                    = 0x240
+	IP_MULTICAST_IF           = 0x9
+	IP_MULTICAST_LOOP         = 0xb
+	IP_MULTICAST_TTL          = 0xa
+	IP_OFFMASK                = 0x1fff
+	IP_OPTIONS                = 0x1
+	IP_RECVDSTADDR            = 0x7
+	IP_RECVOPTS               = 0x5
+	IP_RECVRETOPTS            = 0x6
+	IP_RETOPTS                = 0x8
+	IP_TOS                    = 0x3
+	IP_TTL                    = 0x4
+	IP_UNBLOCK_SOURCE         = 0xf
+	ISIG                      = 0x1
+	ISTRIP                    = 0x20
+	IXANY                     = 0x800
+	IXOFF                     = 0x1000
+	IXON                      = 0x400
+	LOCK_EX                   = 0x2
+	LOCK_NB                   = 0x4
+	LOCK_SH                   = 0x1
+	LOCK_UN                   = 0x8
+	MAP_ANON                  = 0x8
+	MAP_ANONYMOUS             = 0x8
+	MAP_FIXED                 = 0x4
+	MAP_PRIVATE               = 0x2
+	MAP_SHARED                = 0x1
+	MSG_BCAST                 = 0x100
+	MSG_CTRUNC                = 0x20
+	MSG_DONTROUTE             = 0x4
+	MSG_DONTWAIT              = 0x80
+	MSG_EOF                   = 0x400
+	MSG_EOR                   = 0x8
+	MSG_MCAST                 = 0x200
+	MSG_OOB                   = 0x1
+	MSG_PEEK                  = 0x2
+	MSG_TRUNC                 = 0x10
+	MSG_WAITALL               = 0x40
+	MS_ASYNC                  = 0x1
+	MS_INVALIDATE             = 0x4
+	MS_SYNC                   = 0x2
+	NAME_MAX                  = 0x100
+	NOFLSH                    = 0x80
+	OCRNL                     = 0x8
+	OFDEL                     = 0x80
+	OFILL                     = 0x40
+	ONLCR                     = 0x4
+	ONLRET                    = 0x20
+	ONOCR                     = 0x10
+	OPOST                     = 0x1
+	O_ACCMODE                 = 0x3
+	O_APPEND                  = 0x800
+	O_CLOEXEC                 = 0x40
+	O_CREAT                   = 0x200
+	O_DIRECT                  = 0x100000
+	O_DIRECTORY               = 0x200000
+	O_DSYNC                   = 0x40000
+	O_EXCL                    = 0x100
+	O_NDELAY                  = 0x80
+	O_NOCACHE                 = 0x100000
+	O_NOCTTY                  = 0x1000
+	O_NOFOLLOW                = 0x80000
+	O_NONBLOCK                = 0x80
+	O_NOTRAVERSE              = 0x2000
+	O_RDONLY                  = 0x0
+	O_RDWR                    = 0x2
+	O_RSYNC                   = 0x20000
+	O_RWMASK                  = 0x3
+	O_SYNC                    = 0x10000
+	O_TRUNC                   = 0x400
+	O_WRONLY                  = 0x1
+	PARENB                    = 0x100
+	PARMRK                    = 0x8
+	PARODD                    = 0x200
+	PENDIN                    = 0x4000
+	PRIO_PGRP                 = 0x1
+	PRIO_PROCESS              = 0x0
+	PRIO_USER                 = 0x2
+	PROT_EXEC                 = 0x4
+	PROT_NONE                 = 0x0
+	PROT_READ                 = 0x1
+	PROT_WRITE                = 0x2
+	RLIMIT_AS                 = 0x6
+	RLIMIT_CORE               = 0x0
+	RLIMIT_CPU                = 0x1
+	RLIMIT_DATA               = 0x2
+	RLIMIT_FSIZE              = 0x3
+	RLIMIT_NOFILE             = 0x4
+	RLIMIT_STACK              = 0x5
+	RLIM_INFINITY             = 0xffffffff
+	RTF_BLACKHOLE             = 0x1000
+	RTF_DEFAULT               = 0x80
+	RTF_DYNAMIC               = 0x10
+	RTF_GATEWAY               = 0x2
+	RTF_HOST                  = 0x4
+	RTF_LOCAL                 = 0x200000
+	RTF_MODIFIED              = 0x20
+	RTF_REJECT                = 0x8
+	RTF_STATIC                = 0x800
+	RTF_UP                    = 0x1
+	RUSAGE_CHILDREN           = -0x1
+	RUSAGE_SELF               = 0x0
+	SCM_RIGHTS                = 0x1
+	SHUT_RD                   = 0x0
+	SHUT_RDWR                 = 0x2
+	SHUT_WR                   = 0x1
+	SOCK_DGRAM                = 0x2
+	SOCK_MISC                 = 0xff
+	SOCK_RAW                  = 0x3
+	SOCK_SEQPACKET            = 0x5
+	SOCK_STREAM               = 0x1
+	SOL_SOCKET                = -0x1
+	SOMAXCONN                 = 0x20
+	SO_ACCEPTCONN             = 0x1
+	SO_BINDTODEVICE           = 0x4000000a
+	SO_BROADCAST              = 0x2
+	SO_DEBUG                  = 0x4
+	SO_DONTROUTE              = 0x8
+	SO_ERROR                  = 0x40000007
+	SO_KEEPALIVE              = 0x10
+	SO_LINGER                 = 0x200
+	SO_NONBLOCK               = 0x40000009
+	SO_OOBINLINE              = 0x20
+	SO_PEERCRED               = 0x4000000b
+	SO_RCVBUF                 = 0x40000004
+	SO_RCVLOWAT               = 0x40000005
+	SO_RCVTIMEO               = 0x40000006
+	SO_REUSEADDR              = 0x40
+	SO_REUSEPORT              = 0x80
+	SO_SNDBUF                 = 0x40000001
+	SO_SNDLOWAT               = 0x40000002
+	SO_SNDTIMEO               = 0x40000003
+	SO_TYPE                   = 0x40000008
+	SO_USELOOPBACK            = 0x100
+	S_ALLOW_DUPS              = 0x80000
+	S_ATTR                    = 0x10000000
+	S_ATTR_DIR                = 0x8000000
+	S_DOUBLE_INDEX            = 0x40000
+	S_FLOAT_INDEX             = 0x800000
+	S_IEXEC                   = 0x40
+	S_IFBLK                   = 0x6000
+	S_IFCHR                   = 0x2000
+	S_IFDIR                   = 0x4000
+	S_IFIFO                   = 0x1000
+	S_IFLNK                   = 0xa000
+	S_IFMT                    = 0xf000
+	S_IFREG                   = 0x8000
+	S_IFSOCK                  = 0xc000
+	S_INDEX_DIR               = 0x20000000
+	S_INT_INDEX               = 0x2000000
+	S_IREAD                   = 0x100
+	S_IRGRP                   = 0x20
+	S_IROTH                   = 0x4
+	S_IRUSR                   = 0x100
+	S_IRWXG                   = 0x38
+	S_IRWXO                   = 0x7
+	S_IRWXU                   = 0x1c0
+	S_ISGID                   = 0x400
+	S_ISUID                   = 0x800
+	S_ISVTX                   = 0x200
+	S_IUMSK                   = 0xfff
+	S_IWGRP                   = 0x10
+	S_IWOTH                   = 0x2
+	S_IWRITE                  = 0x80
+	S_IWUSR                   = 0x80
+	S_IXGRP                   = 0x8
+	S_IXOTH                   = 0x1
+	S_IXUSR                   = 0x40
+	S_LINK_AUTO_DELETE        = 0x80000
+	S_LINK_SELF_HEALING       = 0x40000
+	S_LONG_LONG_INDEX         = 0x200000
+	S_STR_INDEX               = 0x1000000
+	S_UINT_INDEX              = 0x4000000
+	S_ULONG_LONG_INDEX        = 0x400000
+	TCFLSH                    = 0x8006
+	TCIFLUSH                  = 0x1
+	TCIOFLUSH                 = 0x3
+	TCOFLUSH                  = 0x2
+	TCP_MAXSEG                = 0x2
+	TCP_NODELAY               = 0x1
+	TCP_NOOPT                 = 0x8
+	TCP_NOPUSH                = 0x4
+	TCSAFLUSH                 = 0x4
+	TIOCCBRK                  = 0x8015
+	TIOCGPGRP                 = 0x800f
+	TIOCGWINSZ                = 0x800c
+	TIOCMGET                  = 0x8012
+	TIOCMSET                  = 0x8013
+	TIOCM_CD                  = 0x8
+	TIOCM_CTS                 = 0x1
+	TIOCM_DSR                 = 0x2
+	TIOCM_DTR                 = 0x10
+	TIOCM_RI                  = 0x4
+	TIOCM_RTS                 = 0x20
+	TIOCSBRK                  = 0x8014
+	TIOCSCTTY                 = 0x8011
+	TIOCSPGRP                 = 0x8010
+	TIOCSWINSZ                = 0x800d
+	TOSTOP                    = 0x100
+	VEOF                      = 0x4
+	VEOL                      = 0x5
+	VEOL2                     = 0x6
+	VERASE                    = 0x2
+	VINTR                     = 0x0
+	VKILL                     = 0x3
+	VMIN                      = 0x4
+	VQUIT                     = 0x1
+	VSTART                    = 0x8
+	VSTOP                     = 0x9
+	VSUSP                     = 0xa
+	VSWTCH                    = 0x7
+	VT0                       = 0x0
+	VT1                       = 0x4000
+	VTDLY                     = 0x4000
+	VTIME                     = 0x5
+)
+
+// Errors
+const (
+	E2BIG           = Errno(-0x7fff8fff & 0xffffffff)
+	EACCES          = Errno(-0x7ffffffe & 0xffffffff)
+	EADDRINUSE      = Errno(-0x7fff8fea & 0xffffffff)
+	EADDRNOTAVAIL   = Errno(-0x7fff8fe9 & 0xffffffff)
+	EAFNOSUPPORT    = Errno(-0x7fff8feb & 0xffffffff)
+	EAGAIN          = Errno(-0x7ffffff5 & 0xffffffff)
+	EALREADY        = Errno(-0x7fff8fdb & 0xffffffff)
+	EBADF           = Errno(-0x7fffa000 & 0xffffffff)
+	EBADMSG         = Errno(-0x7fff8fd2 & 0xffffffff)
+	EBUSY           = Errno(-0x7ffffff2 & 0xffffffff)
+	ECANCELED       = Errno(-0x7fff8fd1 & 0xffffffff)
+	ECHILD          = Errno(-0x7fff8ffe & 0xffffffff)
+	ECONNABORTED    = Errno(-0x7fff8fe5 & 0xffffffff)
+	ECONNREFUSED    = Errno(-0x7fff8fe0 & 0xffffffff)
+	ECONNRESET      = Errno(-0x7fff8fe4 & 0xffffffff)
+	EDEADLK         = Errno(-0x7fff8ffd & 0xffffffff)
+	EDESTADDRREQ    = Errno(-0x7fff8fd0 & 0xffffffff)
+	EDOM            = Errno(-0x7fff8ff0 & 0xffffffff)
+	EDOOFUS         = Errno(-0x7ffffffb & 0xffffffff)
+	EDQUOT          = Errno(-0x7fff8fcf & 0xffffffff)
+	EEXIST          = Errno(-0x7fff9ffe & 0xffffffff)
+	EFAULT          = Errno(-0x7fffecff & 0xffffffff)
+	EFBIG           = Errno(-0x7fff8ffc & 0xffffffff)
+	EFPOS           = Errno(-0x7fff8ff2 & 0xffffffff)
+	EHOSTDOWN       = Errno(-0x7fff8fd3 & 0xffffffff)
+	EHOSTUNREACH    = Errno(-0x7fff8fdf & 0xffffffff)
+	EIDRM           = Errno(-0x7fff8fce & 0xffffffff)
+	EILSEQ          = Errno(-0x7fff8fda & 0xffffffff)
+	EINPROGRESS     = Errno(-0x7fff8fdc & 0xffffffff)
+	EINTR           = Errno(-0x7ffffff6 & 0xffffffff)
+	EINVAL          = Errno(-0x7ffffffb & 0xffffffff)
+	EIO             = Errno(-0x7fffffff & 0xffffffff)
+	EISCONN         = Errno(-0x7fff8fe3 & 0xffffffff)
+	EISDIR          = Errno(-0x7fff9ff7 & 0xffffffff)
+	ELOOP           = Errno(-0x7fff9ff4 & 0xffffffff)
+	EMFILE          = Errno(-0x7fff9ff6 & 0xffffffff)
+	EMLINK          = Errno(-0x7fff8ffb & 0xffffffff)
+	EMSGSIZE        = Errno(-0x7fff8fd6 & 0xffffffff)
+	EMULTIHOP       = Errno(-0x7fff8fcd & 0xffffffff)
+	ENAMETOOLONG    = Errno(-0x7fff9ffc & 0xffffffff)
+	ENETDOWN        = Errno(-0x7fff8fe8 & 0xffffffff)
+	ENETRESET       = Errno(-0x7fff8fe6 & 0xffffffff)
+	ENETUNREACH     = Errno(-0x7fff8fe7 & 0xffffffff)
+	ENFILE          = Errno(-0x7fff8ffa & 0xffffffff)
+	ENOATTR         = Errno(-0x7fff8fc4 & 0xffffffff)
+	ENOBUFS         = Errno(-0x7fff8fdd & 0xffffffff)
+	ENODATA         = Errno(-0x7fff8fcc & 0xffffffff)
+	ENODEV          = Errno(-0x7fff8ff9 & 0xffffffff)
+	ENOENT          = Errno(-0x7fff9ffd & 0xffffffff)
+	ENOERR          = Errno(0x0 & 0xffffffff)
+	ENOEXEC         = Errno(-0x7fffecfe & 0xffffffff)
+	ENOLCK          = Errno(-0x7fff8ff8 & 0xffffffff)
+	ENOLINK         = Errno(-0x7fff8fcb & 0xffffffff)
+	ENOMEM          = Errno(-0x80000000 & 0xffffffff)
+	ENOMSG          = Errno(-0x7fff8fd9 & 0xffffffff)
+	ENOPROTOOPT     = Errno(-0x7fff8fde & 0xffffffff)
+	ENOSPC          = Errno(-0x7fff9ff9 & 0xffffffff)
+	ENOSR           = Errno(-0x7fff8fca & 0xffffffff)
+	ENOSTR          = Errno(-0x7fff8fc9 & 0xffffffff)
+	ENOSYS          = Errno(-0x7fff8ff7 & 0xffffffff)
+	ENOTCONN        = Errno(-0x7fff8fe2 & 0xffffffff)
+	ENOTDIR         = Errno(-0x7fff9ffb & 0xffffffff)
+	ENOTEMPTY       = Errno(-0x7fff9ffa & 0xffffffff)
+	ENOTSOCK        = Errno(-0x7fff8fd4 & 0xffffffff)
+	ENOTSUP         = Errno(-0x7fff8fc8 & 0xffffffff)
+	ENOTTY          = Errno(-0x7fff8ff6 & 0xffffffff)
+	ENXIO           = Errno(-0x7fff8ff5 & 0xffffffff)
+	EOK             = Errno(0x0 & 0xffffffff)
+	EOPNOTSUPP      = Errno(-0x7fff8fd5 & 0xffffffff)
+	EOVERFLOW       = Errno(-0x7fff8fd7 & 0xffffffff)
+	EPERM           = Errno(-0x7ffffff1 & 0xffffffff)
+	EPFNOSUPPORT    = Errno(-0x7fff8fec & 0xffffffff)
+	EPIPE           = Errno(-0x7fff9ff3 & 0xffffffff)
+	EPROTO          = Errno(-0x7fff8fc7 & 0xffffffff)
+	EPROTONOSUPPORT = Errno(-0x7fff8fed & 0xffffffff)
+	EPROTOTYPE      = Errno(-0x7fff8fee & 0xffffffff)
+	ERANGE          = Errno(-0x7fff8fef & 0xffffffff)
+	EROFS           = Errno(-0x7fff9ff8 & 0xffffffff)
+	ESHUTDOWN       = Errno(-0x7fff8fe1 & 0xffffffff)
+	ESIGPARM        = Errno(-0x7fff8ff1 & 0xffffffff)
+	ESPIPE          = Errno(-0x7fff8ff4 & 0xffffffff)
+	ESRCH           = Errno(-0x7fff8ff3 & 0xffffffff)
+	ESTALE          = Errno(-0x7fff8fd8 & 0xffffffff)
+	ETIME           = Errno(-0x7fff8fc6 & 0xffffffff)
+	ETIMEDOUT       = Errno(-0x7ffffff7 & 0xffffffff)
+	ETXTBSY         = Errno(-0x7fff8fc5 & 0xffffffff)
+	EWOULDBLOCK     = Errno(-0x7ffffff5 & 0xffffffff)
+	EXDEV           = Errno(-0x7fff9ff5 & 0xffffffff)
+)
+
+// Signals
+const (
+	SIGABRT      = Signal(0x6)
+	SIGALRM      = Signal(0xe)
+	SIGBUS       = Signal(0x1e)
+	SIGCHLD      = Signal(0x5)
+	SIGCONT      = Signal(0xc)
+	SIGFPE       = Signal(0x8)
+	SIGHUP       = Signal(0x1)
+	SIGILL       = Signal(0x4)
+	SIGINT       = Signal(0x2)
+	SIGKILL      = Signal(0x9)
+	SIGKILLTHR   = Signal(0x15)
+	SIGPIPE      = Signal(0x7)
+	SIGPOLL      = Signal(0x17)
+	SIGPROF      = Signal(0x18)
+	SIGQUIT      = Signal(0x3)
+	SIGRESERVED1 = Signal(0x1f)
+	SIGRESERVED2 = Signal(0x20)
+	SIGSEGV      = Signal(0xb)
+	SIGSTOP      = Signal(0xa)
+	SIGSYS       = Signal(0x19)
+	SIGTERM      = Signal(0xf)
+	SIGTRAP      = Signal(0x16)
+	SIGTSTP      = Signal(0xd)
+	SIGTTIN      = Signal(0x10)
+	SIGTTOU      = Signal(0x11)
+	SIGURG       = Signal(0x1a)
+	SIGUSR1      = Signal(0x12)
+	SIGUSR2      = Signal(0x13)
+	SIGVTALRM    = Signal(0x1b)
+	SIGWINCH     = Signal(0x14)
+	SIGXCPU      = Signal(0x1c)
+	SIGXFSZ      = Signal(0x1d)
+)
+
+// Error table
+var errors = [...]string{
+	1:     "out of memory",
+	2:     "I/O error",
+	3:     "permission denied",
+	6:     "invalid Argument",
+	10:    "operation timed out",
+	11:    "interrupted system call",
+	12:    "operation would block",
+	15:    "device/File/Resource busy",
+	16:    "operation not allowed",
+	4866:  "bad address",
+	4867:  "not an executable",
+	24577: "bad file descriptor",
+	24579: "file or Directory already exists",
+	24580: "no such file or directory",
+	24581: "file name too long",
+	24582: "not a directory",
+	24583: "directory not empty",
+	24584: "no space left on device",
+	24585: "read-only file system",
+	24586: "is a directory",
+	24587: "too many open files",
+	24588: "cross-device link",
+	24589: "too many symbolic links",
+	24590: "broken pipe",
+	28674: "argument too big",
+	28675: "no child process",
+	28676: "resource deadlock",
+	28677: "file too large",
+	28678: "too many links",
+	28679: "file table overflow",
+	28680: "no such device",
+	28681: "no record locks available",
+	28682: "function not implemented",
+	28683: "not a tty",
+	28684: "device not accessible",
+	28685: "seek not allowed on file descriptor",
+	28686: "no such process",
+	28687: "file Position Error",
+	28688: "signal Error",
+	28689: "numerical argument out of range",
+	28690: "range Error",
+	28691: "protocol wrong type for socket",
+	28692: "protocol not supported",
+	28693: "protocol family not supported",
+	28694: "address family not supported by protocol family",
+	28695: "address already in use",
+	28696: "can't assign requested address",
+	28697: "network is down",
+	28698: "network is unreachable",
+	28699: "network dropped connection on reset",
+	28700: "software caused connection abort",
+	28701: "connection reset by peer",
+	28702: "socket is already connected",
+	28703: "socket is not connected",
+	28704: "can't send after socket shutdown",
+	28705: "connection refused",
+	28706: "no route to host",
+	28707: "protocol option not available",
+	28708: "no buffer space available",
+	28709: "operation now in progress",
+	28710: "operation already in progress",
+	28711: "illegal byte sequence",
+	28712: "no message of desired type",
+	28713: "stale file handle",
+	28714: "value too large for defined type",
+	28715: "message too long",
+	28716: "operation not supported",
+	28717: "socket operation on non-socket",
+	28718: "unknown POSIX Error (-2147454931)",
+	28719: "bad message",
+	28720: "operation canceled",
+	28721: "destination address required",
+	28722: "reserved",
+	28723: "identifier removed",
+	28724: "reserved",
+	28725: "no message available",
+	28726: "reserved",
+	28727: "no STREAM resources",
+	28728: "not a STREAM",
+	28729: "not supported",
+	28730: "protocol error",
+	28731: "STREAM ioctl() timeout",
+	28732: "text file busy",
+	28733: "no such attribute",
+	0:     "no error",
+}
+
+// Signal table
+var signals = [...]string{
+	1:  "hangup",
+	2:  "interrupt",
+	3:  "quit",
+	4:  "illegal instruction",
+	5:  "child exited",
+	6:  "abort",
+	7:  "broken pipe",
+	8:  "floating point exception",
+	9:  "killed (by death)",
+	10: "stopped",
+	11: "segmentation violation",
+	12: "continued",
+	13: "stopped (tty output)",
+	14: "alarm",
+	15: "termination requested",
+	16: "stopped (tty input)",
+	17: "stopped (tty output)",
+	18: "user defined signal 1",
+	19: "user defined signal 2",
+	20: "window size changed",
+	21: "kill Thread",
+	22: "trace/breakpoint trap",
+	23: "pollable event",
+	24: "profiling timer expired",
+	25: "bad system call",
+	26: "high bandwidth data is available at socket",
+	27: "virtual timer expired",
+	28: "CPU time limit exceeded",
+	29: "file size limit exceeded",
+	30: "bus error",
+	31: "reserved signal 1",
+	32: "reserved signal 2",
+}
diff --git a/src/syscall/zsyscall_haiku_amd64.go b/src/syscall/zsyscall_haiku_amd64.go
new file mode 100644
index 0000000..7b59275
--- /dev/null
+++ b/src/syscall/zsyscall_haiku_amd64.go
@@ -0,0 +1,922 @@
+// mksyscall_haiku.pl -modname libroot syscall_haiku.go syscall_haiku_amd64.go
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+package syscall
+
+import "unsafe"
+
+var (
+	modlibroot    = newLazySO("libroot.so")
+	modlibnetwork = newLazySO("libnetwork.so")
+
+	procpipe         = modlibroot.NewProc("pipe")
+	procgetgroups    = modlibroot.NewProc("getgroups")
+	procsetgroups    = modlibroot.NewProc("setgroups")
+	procfcntl        = modlibroot.NewProc("fcntl")
+	procaccept       = modlibnetwork.NewProc("accept")
+	procsendmsg      = modlibnetwork.NewProc("sendmsg")
+	procAccess       = modlibroot.NewProc("access")
+	procAdjtime      = modlibroot.NewProc("adjtime")
+	procChdir        = modlibroot.NewProc("chdir")
+	procChmod        = modlibroot.NewProc("chmod")
+	procChown        = modlibroot.NewProc("chown")
+	procChroot       = modlibroot.NewProc("chroot")
+	procClose        = modlibroot.NewProc("close")
+	procDup          = modlibroot.NewProc("dup")
+	procExit         = modlibroot.NewProc("exit")
+	procFchdir       = modlibroot.NewProc("fchdir")
+	procFchmod       = modlibroot.NewProc("fchmod")
+	procFchown       = modlibroot.NewProc("fchown")
+	procFpathconf    = modlibroot.NewProc("fpathconf")
+	procFstat        = modlibroot.NewProc("fstat")
+	procGetgid       = modlibroot.NewProc("getgid")
+	procGetpid       = modlibroot.NewProc("getpid")
+	procGeteuid      = modlibroot.NewProc("geteuid")
+	procGetegid      = modlibroot.NewProc("getegid")
+	procGetppid      = modlibroot.NewProc("getppid")
+	procGetpriority  = modlibroot.NewProc("getpriority")
+	procGetrlimit    = modlibroot.NewProc("getrlimit")
+	procGettimeofday = modlibroot.NewProc("gettimeofday")
+	procGetuid       = modlibroot.NewProc("getuid")
+	procKill         = modlibroot.NewProc("kill")
+	procLchown       = modlibroot.NewProc("lchown")
+	procLink         = modlibroot.NewProc("link")
+	proclisten       = modlibnetwork.NewProc("listen")
+	procLstat        = modlibroot.NewProc("lstat")
+	procMkdir        = modlibroot.NewProc("mkdir")
+	procMknod        = modlibroot.NewProc("mknod")
+	procNanosleep    = modlibroot.NewProc("nanosleep")
+	procOpen         = modlibroot.NewProc("open")
+	procPathconf     = modlibroot.NewProc("pathconf")
+	procPread        = modlibroot.NewProc("pread")
+	procPwrite       = modlibroot.NewProc("pwrite")
+	procread         = modlibroot.NewProc("read")
+	procReadlink     = modlibroot.NewProc("readlink")
+	procRename       = modlibroot.NewProc("rename")
+	procRmdir        = modlibroot.NewProc("rmdir")
+	proclseek        = modlibroot.NewProc("lseek")
+	procSetegid      = modlibroot.NewProc("setegid")
+	procSeteuid      = modlibroot.NewProc("seteuid")
+	procSetgid       = modlibroot.NewProc("setgid")
+	procSetpgid      = modlibroot.NewProc("setpgid")
+	procSetpriority  = modlibroot.NewProc("setpriority")
+	procSetregid     = modlibroot.NewProc("setregid")
+	procSetreuid     = modlibroot.NewProc("setreuid")
+	procSetrlimit    = modlibroot.NewProc("setrlimit")
+	procSetsid       = modlibroot.NewProc("setsid")
+	procSetuid       = modlibroot.NewProc("setuid")
+	procshutdown     = modlibnetwork.NewProc("shutdown")
+	procStat         = modlibroot.NewProc("stat")
+	procSymlink      = modlibroot.NewProc("symlink")
+	procSync         = modlibroot.NewProc("sync")
+	procTruncate     = modlibroot.NewProc("truncate")
+	procFsync        = modlibroot.NewProc("fsync")
+	procFtruncate    = modlibroot.NewProc("ftruncate")
+	procUmask        = modlibroot.NewProc("umask")
+	procUnlink       = modlibroot.NewProc("unlink")
+	procUtimes       = modlibroot.NewProc("utimes")
+	procbind         = modlibnetwork.NewProc("bind")
+	procconnect      = modlibnetwork.NewProc("connect")
+	procmunmap       = modlibroot.NewProc("munmap")
+	procsendto       = modlibnetwork.NewProc("sendto")
+	procsocket       = modlibnetwork.NewProc("socket")
+	procsocketpair   = modlibnetwork.NewProc("socketpair")
+	procwrite        = modlibroot.NewProc("write")
+	procgetsockopt   = modlibnetwork.NewProc("getsockopt")
+	procgetpeername  = modlibnetwork.NewProc("getpeername")
+	procgetsockname  = modlibnetwork.NewProc("getsockname")
+	procsetsockopt   = modlibnetwork.NewProc("setsockopt")
+	procrecvfrom     = modlibnetwork.NewProc("recvfrom")
+	procrecvmsg      = modlibnetwork.NewProc("recvmsg")
+	procFdopendir    = modlibroot.NewProc("fdopendir")
+	procReaddir_r    = modlibroot.NewProc("readdir_r")
+	procClosedir     = modlibroot.NewProc("closedir")
+)
+
+func pipe2(fds []int) (err error) {
+	var _p0 *int
+	if len(fds) > 0 {
+		_p0 = &fds[0]
+	}
+	_, _, e1 := sysvicall6(procpipe.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(len(fds)), 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func getgroups(ngid int, gid *_Gid_t) (n int, err error) {
+	r0, _, e1 := rawSysvicall6(procgetgroups.Addr(), 2, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0, 0, 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func setgroups(ngid int, gid *_Gid_t) (err error) {
+	_, _, e1 := rawSysvicall6(procsetgroups.Addr(), 2, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func fcntl(fd int, cmd int, arg int) (val int, err error) {
+	r0, _, e1 := sysvicall6(procfcntl.Addr(), 3, uintptr(fd), uintptr(cmd), uintptr(arg), 0, 0, 0)
+	val = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
+	r0, _, e1 := sysvicall6(procaccept.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) {
+	r0, _, e1 := sysvicall6(procsendmsg.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Access(path string, mode uint32) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := sysvicall6(procAccess.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0, 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Adjtime(delta *Timeval, olddelta *Timeval) (err error) {
+	_, _, e1 := sysvicall6(procAdjtime.Addr(), 2, uintptr(unsafe.Pointer(delta)), uintptr(unsafe.Pointer(olddelta)), 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Chdir(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := sysvicall6(procChdir.Addr(), 1, uintptr(unsafe.Pointer(_p0)), 0, 0, 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Chmod(path string, mode uint32) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := sysvicall6(procChmod.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0, 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Chown(path string, uid int, gid int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := sysvicall6(procChown.Addr(), 3, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Chroot(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := sysvicall6(procChroot.Addr(), 1, uintptr(unsafe.Pointer(_p0)), 0, 0, 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Close(fd int) (err error) {
+	_, _, e1 := sysvicall6(procClose.Addr(), 1, uintptr(fd), 0, 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Dup(fd int) (nfd int, err error) {
+	r0, _, e1 := sysvicall6(procDup.Addr(), 1, uintptr(fd), 0, 0, 0, 0, 0)
+	nfd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Exit(code int) {
+	sysvicall6(procExit.Addr(), 1, uintptr(code), 0, 0, 0, 0, 0)
+	return
+}
+
+func Fchdir(fd int) (err error) {
+	_, _, e1 := sysvicall6(procFchdir.Addr(), 1, uintptr(fd), 0, 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Fchmod(fd int, mode uint32) (err error) {
+	_, _, e1 := sysvicall6(procFchmod.Addr(), 2, uintptr(fd), uintptr(mode), 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Fchown(fd int, uid int, gid int) (err error) {
+	_, _, e1 := sysvicall6(procFchown.Addr(), 3, uintptr(fd), uintptr(uid), uintptr(gid), 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Fpathconf(fd int, name int) (val int, err error) {
+	r0, _, e1 := sysvicall6(procFpathconf.Addr(), 2, uintptr(fd), uintptr(name), 0, 0, 0, 0)
+	val = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Fstat(fd int, stat *Stat_t) (err error) {
+	_, _, e1 := sysvicall6(procFstat.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Getgid() (gid int) {
+	r0, _, _ := rawSysvicall6(procGetgid.Addr(), 0, 0, 0, 0, 0, 0, 0)
+	gid = int(r0)
+	return
+}
+
+func Getpid() (pid int) {
+	r0, _, _ := rawSysvicall6(procGetpid.Addr(), 0, 0, 0, 0, 0, 0, 0)
+	pid = int(r0)
+	return
+}
+
+func Geteuid() (euid int) {
+	r0, _, _ := sysvicall6(procGeteuid.Addr(), 0, 0, 0, 0, 0, 0, 0)
+	euid = int(r0)
+	return
+}
+
+func Getegid() (egid int) {
+	r0, _, _ := sysvicall6(procGetegid.Addr(), 0, 0, 0, 0, 0, 0, 0)
+	egid = int(r0)
+	return
+}
+
+func Getppid() (ppid int) {
+	r0, _, _ := sysvicall6(procGetppid.Addr(), 0, 0, 0, 0, 0, 0, 0)
+	ppid = int(r0)
+	return
+}
+
+func Getpriority(which int, who int) (n int, err error) {
+	r0, _, e1 := sysvicall6(procGetpriority.Addr(), 2, uintptr(which), uintptr(who), 0, 0, 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Getrlimit(which int, lim *Rlimit) (err error) {
+	_, _, e1 := rawSysvicall6(procGetrlimit.Addr(), 2, uintptr(which), uintptr(unsafe.Pointer(lim)), 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Gettimeofday(tv *Timeval) (err error) {
+	_, _, e1 := rawSysvicall6(procGettimeofday.Addr(), 1, uintptr(unsafe.Pointer(tv)), 0, 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Getuid() (uid int) {
+	r0, _, _ := rawSysvicall6(procGetuid.Addr(), 0, 0, 0, 0, 0, 0, 0)
+	uid = int(r0)
+	return
+}
+
+func Kill(pid int, signum Signal) (err error) {
+	_, _, e1 := sysvicall6(procKill.Addr(), 2, uintptr(pid), uintptr(signum), 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Lchown(path string, uid int, gid int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := sysvicall6(procLchown.Addr(), 3, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Link(path string, link string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := sysvicall6(procLink.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	use(unsafe.Pointer(_p1))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Listen(s int, backlog int) (err error) {
+	_, _, e1 := sysvicall6(proclisten.Addr(), 2, uintptr(s), uintptr(backlog), 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Lstat(path string, stat *Stat_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := sysvicall6(procLstat.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0, 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Mkdir(path string, mode uint32) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := sysvicall6(procMkdir.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0, 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Mknod(path string, mode uint32, dev int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := sysvicall6(procMknod.Addr(), 3, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
+	_, _, e1 := sysvicall6(procNanosleep.Addr(), 2, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Open(path string, mode int, perm uint32) (fd int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := sysvicall6(procOpen.Addr(), 3, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm), 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Pathconf(path string, name int) (val int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := sysvicall6(procPathconf.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(name), 0, 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	val = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
+	var _p0 *byte
+	if len(p) > 0 {
+		_p0 = &p[0]
+	}
+	r0, _, e1 := sysvicall6(procPread.Addr(), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+	var _p0 *byte
+	if len(p) > 0 {
+		_p0 = &p[0]
+	}
+	r0, _, e1 := sysvicall6(procPwrite.Addr(), 4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(offset), 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func read(fd int, p []byte) (n int, err error) {
+	var _p0 *byte
+	if len(p) > 0 {
+		_p0 = &p[0]
+	}
+	r0, _, e1 := sysvicall6(procread.Addr(), 3, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), 0, 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Readlink(path string, buf []byte) (n int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	if len(buf) > 0 {
+		_p1 = &buf[0]
+	}
+	r0, _, e1 := sysvicall6(procReadlink.Addr(), 3, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(len(buf)), 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Rename(from string, to string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(from)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(to)
+	if err != nil {
+		return
+	}
+	_, _, e1 := sysvicall6(procRename.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	use(unsafe.Pointer(_p1))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Rmdir(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := sysvicall6(procRmdir.Addr(), 1, uintptr(unsafe.Pointer(_p0)), 0, 0, 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
+	r0, _, e1 := sysvicall6(proclseek.Addr(), 3, uintptr(fd), uintptr(offset), uintptr(whence), 0, 0, 0)
+	newoffset = int64(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Setegid(egid int) (err error) {
+	_, _, e1 := rawSysvicall6(procSetegid.Addr(), 1, uintptr(egid), 0, 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Seteuid(euid int) (err error) {
+	_, _, e1 := rawSysvicall6(procSeteuid.Addr(), 1, uintptr(euid), 0, 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Setgid(gid int) (err error) {
+	_, _, e1 := rawSysvicall6(procSetgid.Addr(), 1, uintptr(gid), 0, 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Setpgid(pid int, pgid int) (err error) {
+	_, _, e1 := rawSysvicall6(procSetpgid.Addr(), 2, uintptr(pid), uintptr(pgid), 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Setpriority(which int, who int, prio int) (err error) {
+	_, _, e1 := sysvicall6(procSetpriority.Addr(), 3, uintptr(which), uintptr(who), uintptr(prio), 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Setregid(rgid int, egid int) (err error) {
+	_, _, e1 := rawSysvicall6(procSetregid.Addr(), 2, uintptr(rgid), uintptr(egid), 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Setreuid(ruid int, euid int) (err error) {
+	_, _, e1 := rawSysvicall6(procSetreuid.Addr(), 2, uintptr(ruid), uintptr(euid), 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Setrlimit(which int, lim *Rlimit) (err error) {
+	_, _, e1 := rawSysvicall6(procSetrlimit.Addr(), 2, uintptr(which), uintptr(unsafe.Pointer(lim)), 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Setsid() (pid int, err error) {
+	r0, _, e1 := rawSysvicall6(procSetsid.Addr(), 0, 0, 0, 0, 0, 0, 0)
+	pid = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Setuid(uid int) (err error) {
+	_, _, e1 := rawSysvicall6(procSetuid.Addr(), 1, uintptr(uid), 0, 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Shutdown(s int, how int) (err error) {
+	_, _, e1 := sysvicall6(procshutdown.Addr(), 2, uintptr(s), uintptr(how), 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Stat(path string, stat *Stat_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := sysvicall6(procStat.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0, 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Symlink(path string, link string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(link)
+	if err != nil {
+		return
+	}
+	_, _, e1 := sysvicall6(procSymlink.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0, 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	use(unsafe.Pointer(_p1))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Sync() (err error) {
+	_, _, e1 := sysvicall6(procSync.Addr(), 0, 0, 0, 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Truncate(path string, length int64) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := sysvicall6(procTruncate.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0, 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Fsync(fd int) (err error) {
+	_, _, e1 := sysvicall6(procFsync.Addr(), 1, uintptr(fd), 0, 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Ftruncate(fd int, length int64) (err error) {
+	_, _, e1 := sysvicall6(procFtruncate.Addr(), 2, uintptr(fd), uintptr(length), 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Umask(newmask int) (oldmask int) {
+	r0, _, _ := sysvicall6(procUmask.Addr(), 1, uintptr(newmask), 0, 0, 0, 0, 0)
+	oldmask = int(r0)
+	return
+}
+
+func Unlink(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := sysvicall6(procUnlink.Addr(), 1, uintptr(unsafe.Pointer(_p0)), 0, 0, 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Utimes(path string, times *[2]Timeval) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := sysvicall6(procUtimes.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), 0, 0, 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
+	_, _, e1 := sysvicall6(procbind.Addr(), 3, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
+	_, _, e1 := sysvicall6(procconnect.Addr(), 3, uintptr(s), uintptr(addr), uintptr(addrlen), 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func munmap(addr uintptr, length uintptr) (err error) {
+	_, _, e1 := sysvicall6(procmunmap.Addr(), 2, uintptr(addr), uintptr(length), 0, 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) {
+	var _p0 *byte
+	if len(buf) > 0 {
+		_p0 = &buf[0]
+	}
+	_, _, e1 := sysvicall6(procsendto.Addr(), 6, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func socket(domain int, typ int, proto int) (fd int, err error) {
+	r0, _, e1 := sysvicall6(procsocket.Addr(), 3, uintptr(domain), uintptr(typ), uintptr(proto), 0, 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
+	_, _, e1 := rawSysvicall6(procsocketpair.Addr(), 4, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func write(fd int, p []byte) (n int, err error) {
+	var _p0 *byte
+	if len(p) > 0 {
+		_p0 = &p[0]
+	}
+	r0, _, e1 := sysvicall6(procwrite.Addr(), 3, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), 0, 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) {
+	_, _, e1 := sysvicall6(procgetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+	_, _, e1 := rawSysvicall6(procgetpeername.Addr(), 3, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+	_, _, e1 := sysvicall6(procgetsockname.Addr(), 3, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) {
+	_, _, e1 := sysvicall6(procsetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) {
+	var _p0 *byte
+	if len(p) > 0 {
+		_p0 = &p[0]
+	}
+	r0, _, e1 := sysvicall6(procrecvfrom.Addr(), 6, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
+	r0, _, e1 := sysvicall6(procrecvmsg.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags), 0, 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Fdopendir(fd int) (dir unsafe.Pointer, err error) {
+	r0, _, e1 := sysvicall6(procFdopendir.Addr(), 1, uintptr(fd), 0, 0, 0, 0, 0)
+	dir = unsafe.Pointer(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Readdir_r(dir unsafe.Pointer, entry *Dirent, result **Dirent) (status int) {
+	r0, _, _ := sysvicall6(procReaddir_r.Addr(), 3, uintptr(dir), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result)), 0, 0, 0)
+	status = int(r0)
+	return
+}
+
+func Closedir(dir unsafe.Pointer) (status int, err error) {
+	r0, _, e1 := sysvicall6(procClosedir.Addr(), 1, uintptr(dir), 0, 0, 0, 0, 0)
+	status = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
diff --git a/src/syscall/zsysnum_haiku_amd64.go b/src/syscall/zsysnum_haiku_amd64.go
new file mode 100644
index 0000000..43b3d8b
--- /dev/null
+++ b/src/syscall/zsysnum_haiku_amd64.go
@@ -0,0 +1,11 @@
+// Copyright 2014 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.
+
+package syscall
+
+// TODO(aram): remove these before Go 1.3.
+const (
+	SYS_EXECVE = 59
+	SYS_FCNTL  = 62
+)
diff --git a/src/syscall/ztypes_haiku_amd64.go b/src/syscall/ztypes_haiku_amd64.go
new file mode 100644
index 0000000..12f2012
--- /dev/null
+++ b/src/syscall/ztypes_haiku_amd64.go
@@ -0,0 +1,217 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_haiku.go
+
+package syscall
+
+const (
+	sizeofPtr      = 0x8
+	sizeofShort    = 0x2
+	sizeofInt      = 0x4
+	sizeofLong     = 0x8
+	sizeofLongLong = 0x8
+)
+
+type (
+	_C_short     int16
+	_C_int       int32
+	_C_long      int64
+	_C_long_long int64
+)
+
+type Timespec struct {
+	Sec       int32
+	Pad_cgo_0 [4]byte
+	Nsec      int64
+}
+
+type Timeval struct {
+	Sec  int32
+	Usec int32
+}
+
+type Rusage struct {
+	Utime Timeval
+	Stime Timeval
+}
+
+type Rlimit struct {
+	Cur uint64
+	Max uint64
+}
+
+type _Gid_t uint32
+
+type Stat_t struct {
+	Dev       int32
+	Pad_cgo_0 [4]byte
+	Ino       int64
+	Mode      uint32
+	Nlink     int32
+	Uid       uint32
+	Gid       uint32
+	Size      int64
+	Rdev      int32
+	Blksize   int32
+	Atim      Timespec
+	Mtim      Timespec
+	Ctim      Timespec
+	Crtim     Timespec
+	Type      uint32
+	Pad_cgo_1 [4]byte
+	Blocks    int64
+}
+
+type Flock_t struct {
+	Type      int16
+	Whence    int16
+	Pad_cgo_0 [4]byte
+	Start     int64
+	Len       int64
+	Pid       int32
+	Pad_cgo_1 [4]byte
+}
+
+type Dirent struct {
+	Dev       int32
+	Pdev      int32
+	Ino       int64
+	Pino      int64
+	Reclen    uint16
+	Name      [1 + 256]int8
+	Pad_cgo_0 [1]byte
+}
+
+type RawSockaddrInet4 struct {
+	Len    uint8
+	Family uint8
+	Port   uint16
+	Addr   [4]byte /* in_addr */
+	Zero   [24]int8
+}
+
+type RawSockaddrInet6 struct {
+	Len      uint8
+	Family   uint8
+	Port     uint16
+	Flowinfo uint32
+	Addr     [16]byte /* in6_addr */
+	Scope_id uint32
+}
+
+type RawSockaddrUnix struct {
+	Len    uint8
+	Family uint8
+	Path   [126]int8
+}
+
+type RawSockaddrDatalink struct {
+	Len    uint8
+	Family uint8
+	E_type uint16
+	Index  uint32
+	Type   uint8
+	Nlen   uint8
+	Alen   uint8
+	Slen   uint8
+	Data   [20]uint8
+}
+
+type RawSockaddr struct {
+	Len    uint8
+	Family uint8
+	Data   [30]uint8
+}
+
+type RawSockaddrAny struct {
+	Addr RawSockaddr
+	Pad  [96]int8
+}
+
+type _Socklen uint32
+
+type Linger struct {
+	Onoff  int32
+	Linger int32
+}
+
+type Iovec struct {
+	Base *byte
+	Len  uint64
+}
+
+type IPMreq struct {
+	Multiaddr [4]byte /* in_addr */
+	Interface [4]byte /* in_addr */
+}
+
+type IPv6Mreq struct {
+	Multiaddr [16]byte /* in6_addr */
+	Interface uint32
+}
+
+type Msghdr struct {
+	Name       *byte
+	Namelen    uint32
+	Pad_cgo_0  [4]byte
+	Iov        *Iovec
+	Iovlen     int32
+	Pad_cgo_1  [4]byte
+	Control    *byte
+	Controllen uint32
+	Flags      int32
+}
+
+type Cmsghdr struct {
+	Len   uint32
+	Level int32
+	Type  int32
+}
+type IPv6MTUInfo struct {
+	Addr RawSockaddrInet6
+	Mtu  uint32
+}
+
+type Inet6Pktinfo struct {
+	Addr    [16]byte /* in6_addr */
+	Ifindex uint32
+}
+
+type ICMPv6Filter struct {
+	Filt [8]uint32
+}
+
+const (
+	SizeofSockaddrInet4    = 0x20
+	SizeofSockaddrInet6    = 0x1c
+	SizeofSockaddrAny      = 0x80
+	SizeofSockaddrUnix     = 0x80
+	SizeofSockaddrDatalink = 0x20
+	SizeofLinger           = 0x8
+	SizeofIPMreq           = 0x8
+	SizeofIPv6Mreq         = 0x14
+	SizeofMsghdr           = 0x30
+	SizeofCmsghdr          = 0xc
+	SizeofIPv6MTUInfo      = 0x20
+	SizeofInet6Pktinfo     = 0x14
+	SizeofICMPv6Filter     = 0x20
+)
+
+type FdSet struct {
+	Bits [32]uint32
+}
+
+type Termios struct {
+	Iflag     uint32
+	Oflag     uint32
+	Cflag     uint32
+	Lflag     uint32
+	Line      int8
+	Ispeed    uint8
+	Ospeed    uint8
+	Cc        [11]uint8
+	Pad_cgo_0 [2]byte
+}
+
+const (
+	F_DUPFD_CLOEXEC = 0xdeadf00d
+)
-- 
2.19.1


From a9af9c4ec71c0bbeca608a10ce3e054405224b7f Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Mon, 29 Oct 2018 23:16:07 +0000
Subject: runtime: apply additional patches for Haiku runtime support.


diff --git a/src/runtime/signals_haiku.h b/src/runtime/signals_haiku.h
new file mode 100644
index 0000000..c7f29df
--- /dev/null
+++ b/src/runtime/signals_haiku.h
@@ -0,0 +1,86 @@
+// 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.
+
+#include "textflag.h"
+
+#define N SigNotify
+#define K SigKill
+#define T SigThrow
+#define P SigPanic
+#define D SigDefault
+
+#pragma dataflag NOPTR
+SigTab runtime·sigtab[] = {
+	/* 0 */	0, "SIGNONE: no trap",
+	/* 1 */	N+K, "SIGHUP: hangup",
+	/* 2 */	N+K, "SIGINT: interrupt",
+	/* 3 */	N+T, "SIGQUIT: quit",
+	/* 4 */	T, "SIGILL: illegal instruction",
+	/* 5 */	N, "SIGCHLD: child exited",
+	/* 6 */	N+T, "SIGABRT: abort",
+	/* 7 */	N, "SIGPIPE: broken pipe",
+	/* 8 */	P, "SIGFPE: floating point exception",
+	/* 9 */	0, "SIGKILL: killed (by death)",
+	/* 10 */	0, "SIGSTOP: stopped",
+	/* 11 */	P, "SIGSEGV: segmentation violation",
+	/* 12 */	0, "SIGCONT: continued",
+	/* 13 */	N+D, "SIGTSTP: stopped (tty output)",
+	/* 14 */	N, "SIGALRM: alarm",
+	/* 15 */	N+K, "SIGTERM: termination requested",
+	/* 16 */	N+D, "SIGTTIN: stopped (tty input)",
+	/* 17 */	N+D, "SIGTTOU: stopped (tty output)",
+	/* 18 */	N, "SIGUSR1: user defined signal 1",
+	/* 19 */	N, "SIGUSR2: user defined signal 2",
+	/* 20 */	N, "SIGWINCH: window size changed",
+	/* 21 */	N+K, "SIGKILLTHR: kill Thread",
+	/* 22 */	T, "SIGTRAP: trace/breakpoint trap",
+	/* 23 */	N, "SIGPOLL: pollable event",
+	/* 24 */	N, "SIGPROF: profiling timer expired",
+	/* 25 */	N, "SIGSYS: bad system call",
+	/* 26 */	N, "SIGURG: high bandwidth data is available at socket",
+	/* 27 */	N, "SIGVTALRM: virtual timer expired",
+	/* 28 */	N, "SIGXCPU: CPU time limit exceeded",
+	/* 29 */	N, "SIGXFSZ: file size limit exceeded",
+	/* 30 */	P, "SIGBUS: bus error",
+	/* 31 */	N, "SIGRESERVED1: reserved signal 1",
+	/* 32 */	N, "SIGRESERVED2: reserved signal 2",
+	/* 33 */	N, "signal 33",
+	/* 34 */	N, "signal 34",
+	/* 35 */	N, "signal 35",
+	/* 36 */	N, "signal 36",
+	/* 37 */	N, "signal 37",
+	/* 38 */	N, "signal 38",
+	/* 39 */	N, "signal 39",
+	/* 40 */	N, "signal 40",
+	/* 41 */	N, "signal 41",
+	/* 42 */	N, "signal 42",
+	/* 43 */	N, "signal 43",
+	/* 44 */	N, "signal 44",
+	/* 45 */	N, "signal 45",
+	/* 46 */	N, "signal 46",
+	/* 47 */	N, "signal 47",
+	/* 48 */	N, "signal 48",
+	/* 49 */	N, "signal 49",
+	/* 50 */	N, "signal 50",
+	/* 51 */	N, "signal 51",
+	/* 52 */	N, "signal 52",
+	/* 53 */	N, "signal 53",
+	/* 54 */	N, "signal 54",
+	/* 55 */	N, "signal 55",
+	/* 56 */	N, "signal 56",
+	/* 57 */	N, "signal 57",
+	/* 58 */	N, "signal 58",
+	/* 59 */	N, "signal 59",
+	/* 60 */	N, "signal 60",
+	/* 61 */	N, "signal 61",
+	/* 62 */	N, "signal 62",
+	/* 63 */	N, "signal 63",
+	/* 64 */	N, "signal 64",
+};
+
+#undef N
+#undef K
+#undef T
+#undef P
+#undef D
diff --git a/src/runtime/thunk_haiku_amd64.s b/src/runtime/thunk_haiku_amd64.s
new file mode 100644
index 0000000..8e10618
--- /dev/null
+++ b/src/runtime/thunk_haiku_amd64.s
@@ -0,0 +1,96 @@
+// Copyright 2014 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.
+
+// This file exposes various external library functions to Go code in the runtime.
+
+#include "zasm_GOOS_GOARCH.h"
+#include "textflag.h"
+
+TEXT runtime·libc_chdir(SB),NOSPLIT,$0
+	MOVQ	libc·chdir(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_chroot(SB),NOSPLIT,$0
+	MOVQ	libc·chroot(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_close(SB),NOSPLIT,$0
+	MOVQ	libc·close(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_dlopen(SB),NOSPLIT,$0
+	MOVQ	libc·dlopen(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_dlclose(SB),NOSPLIT,$0
+	MOVQ	libc·dlclose(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_dlsym(SB),NOSPLIT,$0
+	MOVQ	libc·dlsym(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_execve(SB),NOSPLIT,$0
+	MOVQ	libc·execve(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_exit(SB),NOSPLIT,$0
+	MOVQ	libc·exit(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_fcntl(SB),NOSPLIT,$0
+	MOVQ	libc·fcntl(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_fork(SB),NOSPLIT,$0
+	MOVQ	libc·fork(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_gethostname(SB),NOSPLIT,$0
+	MOVQ	libc·gethostname(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_ioctl(SB),NOSPLIT,$0
+	MOVQ	libc·ioctl(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_setgid(SB),NOSPLIT,$0
+	MOVQ	libc·setgid(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_setgroups(SB),NOSPLIT,$0
+	MOVQ	libc·setgroups(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_setsid(SB),NOSPLIT,$0
+	MOVQ	libc·setsid(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_setuid(SB),NOSPLIT,$0
+	MOVQ	libc·setuid(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_setpgid(SB),NOSPLIT,$0
+	MOVQ	libc·setpgid(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_syscall(SB),NOSPLIT,$0
+	MOVQ	libc·_kern_generic_syscall(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_wait4(SB),NOSPLIT,$0
+	MOVQ	libc·waitpid(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_write(SB),NOSPLIT,$0
+	MOVQ	libc·write(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_mmap(SB),NOSPLIT,$0
+	MOVQ	libc·mmap(SB), AX
+	JMP	AX
+
+TEXT runtime·libc_dup2(SB),NOSPLIT,$0
+	MOVQ	libc·dup2(SB), AX
+	JMP	AX
-- 
2.19.1


From 4ca5a25a526e9bd9cbe3175e968ff9f854b2d035 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Mon, 29 Oct 2018 23:16:53 +0000
Subject: net: Initial support for Haiku


diff --git a/src/net/dnsclient_unix.go b/src/net/dnsclient_unix.go
index 7511083..03a36d4 100644
--- a/src/net/dnsclient_unix.go
+++ b/src/net/dnsclient_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 // DNS client: see RFC 1035.
 // Has to be linked into package net for Dial.
diff --git a/src/net/dnsconfig_unix.go b/src/net/dnsconfig_unix.go
index 66ab7c4..0d7d816 100644
--- a/src/net/dnsconfig_unix.go
+++ b/src/net/dnsconfig_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 // Read system DNS config from /etc/resolv.conf
 
diff --git a/src/net/fd_poll_runtime.go b/src/net/fd_poll_runtime.go
index 2bddc83..71cb6e3 100644
--- a/src/net/fd_poll_runtime.go
+++ b/src/net/fd_poll_runtime.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd windows solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd windows solaris
 
 package net
 
diff --git a/src/net/fd_unix.go b/src/net/fd_unix.go
index 7fa43f6..e845a9b 100644
--- a/src/net/fd_unix.go
+++ b/src/net/fd_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris
 
 package net
 
diff --git a/src/net/fd_unix_test.go b/src/net/fd_unix_test.go
index fe8e8ff..2f0ab5e 100644
--- a/src/net/fd_unix_test.go
+++ b/src/net/fd_unix_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 package net
 
diff --git a/src/net/file_unix.go b/src/net/file_unix.go
index 214a419..561893b 100644
--- a/src/net/file_unix.go
+++ b/src/net/file_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 package net
 
diff --git a/src/net/interface_stub.go b/src/net/interface_stub.go
index c38fb7f..0b43b4a 100644
--- a/src/net/interface_stub.go
+++ b/src/net/interface_stub.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build nacl plan9 solaris
+// +build haiku nacl plan9 solaris
 
 package net
 
diff --git a/src/net/iprawsock_posix.go b/src/net/iprawsock_posix.go
index 99b081b..8fb5cbf 100644
--- a/src/net/iprawsock_posix.go
+++ b/src/net/iprawsock_posix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris windows
 
 package net
 
diff --git a/src/net/ipsock_posix.go b/src/net/ipsock_posix.go
index f9ebe40..82ebf37 100644
--- a/src/net/ipsock_posix.go
+++ b/src/net/ipsock_posix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris windows
 
 // Internet protocol family sockets for POSIX
 
diff --git a/src/net/lookup_unix.go b/src/net/lookup_unix.go
index a545784..f4469d9 100644
--- a/src/net/lookup_unix.go
+++ b/src/net/lookup_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 package net
 
diff --git a/src/net/port_unix.go b/src/net/port_unix.go
index 348c771..363225e 100644
--- a/src/net/port_unix.go
+++ b/src/net/port_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 // Read system port mappings from /etc/services
 
diff --git a/src/net/sendfile_stub.go b/src/net/sendfile_stub.go
index 03426ef..aaf82bf 100644
--- a/src/net/sendfile_stub.go
+++ b/src/net/sendfile_stub.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin nacl netbsd openbsd solaris
+// +build darwin haiku nacl netbsd openbsd solaris
 
 package net
 
diff --git a/src/net/sock_posix.go b/src/net/sock_posix.go
index 3f956df..db3b6c4 100644
--- a/src/net/sock_posix.go
+++ b/src/net/sock_posix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris windows
 
 package net
 
diff --git a/src/net/sockopt_haiku.go b/src/net/sockopt_haiku.go
new file mode 100644
index 0000000..54c20b1
--- /dev/null
+++ b/src/net/sockopt_haiku.go
@@ -0,0 +1,32 @@
+// Copyright 2011 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.
+
+package net
+
+import (
+	"os"
+	"syscall"
+)
+
+func setDefaultSockopts(s, family, sotype int, ipv6only bool) error {
+	if family == syscall.AF_INET6 && sotype != syscall.SOCK_RAW {
+		// Allow both IP versions even if the OS default
+		// is otherwise.  Note that some operating systems
+		// never admit this option.
+		syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, boolint(ipv6only))
+	}
+	// Allow broadcast.
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1))
+}
+
+func setDefaultListenerSockopts(s int) error {
+	// Allow reuse of recently-used addresses.
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1))
+}
+
+func setDefaultMulticastSockopts(s int) error {
+	// Allow multicast UDP and raw IP datagram sockets to listen
+	// concurrently across multiple listeners.
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1))
+}
diff --git a/src/net/sockopt_posix.go b/src/net/sockopt_posix.go
index 1654d1b..79875c3 100644
--- a/src/net/sockopt_posix.go
+++ b/src/net/sockopt_posix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris windows
 
 package net
 
diff --git a/src/net/sockoptip_stub.go b/src/net/sockoptip_stub.go
index 32ec5dd..e11c4bb 100644
--- a/src/net/sockoptip_stub.go
+++ b/src/net/sockoptip_stub.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build nacl solaris
+// +build haiku nacl solaris
 
 package net
 
diff --git a/src/net/sys_cloexec.go b/src/net/sys_cloexec.go
index 898fb7c..242b418 100644
--- a/src/net/sys_cloexec.go
+++ b/src/net/sys_cloexec.go
@@ -5,7 +5,7 @@
 // This file implements sysSocket and accept for platforms that do not
 // provide a fast path for setting SetNonblock and CloseOnExec.
 
-// +build darwin dragonfly nacl netbsd openbsd solaris
+// +build darwin dragonfly haiku nacl netbsd openbsd solaris
 
 package net
 
diff --git a/src/net/tcpsock_posix.go b/src/net/tcpsock_posix.go
index dd78aef..e471206 100644
--- a/src/net/tcpsock_posix.go
+++ b/src/net/tcpsock_posix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris windows
 
 package net
 
diff --git a/src/net/tcpsockopt_haiku.go b/src/net/tcpsockopt_haiku.go
new file mode 100644
index 0000000..eaab6b6
--- /dev/null
+++ b/src/net/tcpsockopt_haiku.go
@@ -0,0 +1,27 @@
+// Copyright 2013 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.
+
+// TCP socket options for solaris
+
+package net
+
+import (
+	"os"
+	"syscall"
+	"time"
+)
+
+// Set keep alive period.
+func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
+	if err := fd.incref(); err != nil {
+		return err
+	}
+	defer fd.decref()
+
+	// The kernel expects seconds so round to next highest second.
+	d += (time.Second - time.Nanosecond)
+	secs := int(d.Seconds())
+
+	return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.SO_KEEPALIVE, secs))
+}
diff --git a/src/net/tcpsockopt_posix.go b/src/net/tcpsockopt_posix.go
index 0abf3f9..d408110 100644
--- a/src/net/tcpsockopt_posix.go
+++ b/src/net/tcpsockopt_posix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris windows
 
 package net
 
diff --git a/src/net/udpsock_posix.go b/src/net/udpsock_posix.go
index a053336..2fd2c3b 100644
--- a/src/net/udpsock_posix.go
+++ b/src/net/udpsock_posix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris windows
 
 package net
 
diff --git a/src/net/unixsock_posix.go b/src/net/unixsock_posix.go
index 3c2e78b..0499934 100644
--- a/src/net/unixsock_posix.go
+++ b/src/net/unixsock_posix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris windows
 
 package net
 
-- 
2.19.1


From 178033d652b963f544f9d8adc4525d3779c1f886 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Mon, 29 Oct 2018 23:17:21 +0000
Subject: time: Add Haiku support


diff --git a/src/time/sys_unix.go b/src/time/sys_unix.go
index 379e13d..c38d334 100644
--- a/src/time/sys_unix.go
+++ b/src/time/sys_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris
 
 package time
 
diff --git a/src/time/zoneinfo_unix.go b/src/time/zoneinfo_unix.go
index ab7e461..f43c459 100644
--- a/src/time/zoneinfo_unix.go
+++ b/src/time/zoneinfo_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris
 
 // Parse "zoneinfo" time zone file.
 // This is a fairly standard file format used on OS X, Linux, BSD, Sun, and others.
-- 
2.19.1


From 8796e9df70ed34913d013c0bfded620b645e9ad6 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Mon, 29 Oct 2018 23:18:24 +0000
Subject: os: Initial Haiku support


diff --git a/src/os/dir_unix.go b/src/os/dir_unix.go
index 589db85..fee27c2 100644
--- a/src/os/dir_unix.go
+++ b/src/os/dir_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris
 
 package os
 
diff --git a/src/os/env_unix_test.go b/src/os/env_unix_test.go
index 5ec07ee..12b89f6 100644
--- a/src/os/env_unix_test.go
+++ b/src/os/env_unix_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 package os_test
 
diff --git a/src/os/error_unix.go b/src/os/error_unix.go
index f2aabbb..0747f90 100644
--- a/src/os/error_unix.go
+++ b/src/os/error_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris
 
 package os
 
diff --git a/src/os/exec/lp_unix.go b/src/os/exec/lp_unix.go
index 3f895d5..51bf920 100644
--- a/src/os/exec/lp_unix.go
+++ b/src/os/exec/lp_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris
 
 package exec
 
diff --git a/src/os/exec/lp_unix_test.go b/src/os/exec/lp_unix_test.go
index 051db66..0e344d6 100644
--- a/src/os/exec/lp_unix_test.go
+++ b/src/os/exec/lp_unix_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 package exec
 
diff --git a/src/os/exec_posix.go b/src/os/exec_posix.go
index fb9d291..78e3b30 100644
--- a/src/os/exec_posix.go
+++ b/src/os/exec_posix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris windows
 
 package os
 
diff --git a/src/os/exec_unix.go b/src/os/exec_unix.go
index ed97f85..20843b8 100644
--- a/src/os/exec_unix.go
+++ b/src/os/exec_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris
 
 package os
 
diff --git a/src/os/file_posix.go b/src/os/file_posix.go
index fbb3b5e..6bbd8f1 100644
--- a/src/os/file_posix.go
+++ b/src/os/file_posix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris windows
 
 package os
 
diff --git a/src/os/file_unix.go b/src/os/file_unix.go
index ff4fc7d..da53148 100644
--- a/src/os/file_unix.go
+++ b/src/os/file_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris
 
 package os
 
diff --git a/src/os/os_unix_test.go b/src/os/os_unix_test.go
index 21d40cc..a9e0735 100644
--- a/src/os/os_unix_test.go
+++ b/src/os/os_unix_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 package os_test
 
diff --git a/src/os/path_unix.go b/src/os/path_unix.go
index 0211107..333a863 100644
--- a/src/os/path_unix.go
+++ b/src/os/path_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris
 
 package os
 
diff --git a/src/os/pipe_bsd.go b/src/os/pipe_bsd.go
index 3b81ed2..f6eda49 100644
--- a/src/os/pipe_bsd.go
+++ b/src/os/pipe_bsd.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku nacl netbsd openbsd solaris
 
 package os
 
diff --git a/src/os/signal/signal_test.go b/src/os/signal/signal_test.go
index 22337a7..34dfe2e 100644
--- a/src/os/signal/signal_test.go
+++ b/src/os/signal/signal_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 package signal
 
diff --git a/src/os/signal/signal_unix.go b/src/os/signal/signal_unix.go
index 94b8ab3..98d22f7 100644
--- a/src/os/signal/signal_unix.go
+++ b/src/os/signal/signal_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris windows
 
 package signal
 
diff --git a/src/os/stat_haiku.go b/src/os/stat_haiku.go
new file mode 100644
index 0000000..605c1d9
--- /dev/null
+++ b/src/os/stat_haiku.go
@@ -0,0 +1,61 @@
+// 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.
+
+package os
+
+import (
+	"syscall"
+	"time"
+)
+
+func sameFile(fs1, fs2 *fileStat) bool {
+	stat1 := fs1.sys.(*syscall.Stat_t)
+	stat2 := fs2.sys.(*syscall.Stat_t)
+	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
+}
+
+func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
+	fs := &fileStat{
+		name:    basename(name),
+		size:    int64(st.Size),
+		modTime: timespecToTime(st.Mtim),
+		sys:     st,
+	}
+	fs.mode = FileMode(st.Mode & 0777)
+	switch st.Mode & syscall.S_IFMT {
+	case syscall.S_IFBLK:
+		fs.mode |= ModeDevice
+	case syscall.S_IFCHR:
+		fs.mode |= ModeDevice | ModeCharDevice
+	case syscall.S_IFDIR:
+		fs.mode |= ModeDir
+	case syscall.S_IFIFO:
+		fs.mode |= ModeNamedPipe
+	case syscall.S_IFLNK:
+		fs.mode |= ModeSymlink
+	case syscall.S_IFREG:
+		// nothing to do
+	case syscall.S_IFSOCK:
+		fs.mode |= ModeSocket
+	}
+	if st.Mode&syscall.S_ISGID != 0 {
+		fs.mode |= ModeSetgid
+	}
+	if st.Mode&syscall.S_ISUID != 0 {
+		fs.mode |= ModeSetuid
+	}
+	if st.Mode&syscall.S_ISVTX != 0 {
+		fs.mode |= ModeSticky
+	}
+	return fs
+}
+
+func timespecToTime(ts syscall.Timespec) time.Time {
+	return time.Unix(int64(ts.Sec), int64(ts.Nsec))
+}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+	return timespecToTime(fi.Sys().(*syscall.Stat_t).Atim)
+}
diff --git a/src/os/sys_haiku.go b/src/os/sys_haiku.go
new file mode 100644
index 0000000..86a8bbd
--- /dev/null
+++ b/src/os/sys_haiku.go
@@ -0,0 +1,9 @@
+// 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.
+
+package os
+
+func hostname() (name string, err error) {
+	panic("Not implemented")
+}
diff --git a/src/os/sys_unix.go b/src/os/sys_unix.go
index 39c20dc..6bdff82 100644
--- a/src/os/sys_unix.go
+++ b/src/os/sys_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build dragonfly linux netbsd openbsd solaris
+// +build dragonfly haiku linux netbsd openbsd solaris
 
 package os
 
-- 
2.19.1


From 3d7cd70f8cb6f68b9a8c8fad16aaabeb8fe09fb7 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Mon, 29 Oct 2018 23:19:11 +0000
Subject: crypto: Haiku support


diff --git a/src/crypto/rand/rand_unix.go b/src/crypto/rand/rand_unix.go
index 62d0fbd..cf90cde 100644
--- a/src/crypto/rand/rand_unix.go
+++ b/src/crypto/rand/rand_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd plan9 solaris
 
 // Unix cryptographically secure pseudorandom number
 // generator.
diff --git a/src/crypto/x509/root_unix.go b/src/crypto/x509/root_unix.go
index f77d6c0..fee8232 100644
--- a/src/crypto/x509/root_unix.go
+++ b/src/crypto/x509/root_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build dragonfly freebsd haiku linux nacl netbsd openbsd solaris
 
 package x509
 
@@ -10,13 +10,14 @@ import "io/ioutil"
 
 // Possible certificate files; stop after finding one.
 var certFiles = []string{
-	"/etc/ssl/certs/ca-certificates.crt",     // Debian/Ubuntu/Gentoo etc.
-	"/etc/pki/tls/certs/ca-bundle.crt",       // Fedora/RHEL
-	"/etc/ssl/ca-bundle.pem",                 // OpenSUSE
-	"/etc/ssl/cert.pem",                      // OpenBSD
-	"/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly
-	"/etc/pki/tls/cacert.pem",                // OpenELEC
-	"/etc/certs/ca-certificates.crt",         // Solaris 11.2+
+	"/etc/ssl/certs/ca-certificates.crt",           // Debian/Ubuntu/Gentoo etc.
+	"/etc/pki/tls/certs/ca-bundle.crt",             // Fedora/RHEL
+	"/etc/ssl/ca-bundle.pem",                       // OpenSUSE
+	"/etc/ssl/cert.pem",                            // OpenBSD
+	"/usr/local/share/certs/ca-root-nss.crt",       // FreeBSD/DragonFly
+	"/etc/pki/tls/cacert.pem",                      // OpenELEC
+	"/etc/certs/ca-certificates.crt",               // Solaris 11.2+
+	"/boot/system/data/ssl/CARootCertificates.pem", // Haiku
 }
 
 // Possible directories with certificate files; stop after successfully
-- 
2.19.1


From c85dc8fa6468c8d01fcd432d7cba351222d5ad46 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Mon, 29 Oct 2018 23:20:13 +0000
Subject: path/mime: build on Haiku


diff --git a/src/mime/type_unix.go b/src/mime/type_unix.go
index 3e404cf..7ee5185 100644
--- a/src/mime/type_unix.go
+++ b/src/mime/type_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris
 
 package mime
 
diff --git a/src/path/filepath/path_unix.go b/src/path/filepath/path_unix.go
index 4e7d0d1..524b9b6 100644
--- a/src/path/filepath/path_unix.go
+++ b/src/path/filepath/path_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris
 
 package filepath
 
-- 
2.19.1


From d17adc1b02ce0abaf627dc43020c06cb07a8ba3f Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Mon, 29 Oct 2018 23:21:31 +0000
Subject: lib9: Add small tmpdir hack to prevent crash.


diff --git a/src/lib9/tempdir_unix.c b/src/lib9/tempdir_unix.c
index f4fa6dc..c0a1307 100644
--- a/src/lib9/tempdir_unix.c
+++ b/src/lib9/tempdir_unix.c
@@ -17,11 +17,12 @@ mktempdir(void)
 	
 	tmp = getenv("TMPDIR");
 	if(tmp == nil || strlen(tmp) == 0)
-#ifdef __HAIKU__
-		tmp = "/tmp";
-#else
-		tmp = "/var/tmp";
-#endif	p = smprint("%s/go-link-XXXXXX", tmp);
+		tmp = "/tmp/";
+//#ifdef __HAIKU__
+//#else
+//		tmp = "/var/tmp";
+//#endif	
+	p = smprint("%s/go-link-XXXXXX", tmp);
 	if(mkdtemp(p) == nil)
 		return nil;
 	return p;
-- 
2.19.1


From 0d9e8bb988e7d33d105ce1325a5a30c4c83c5740 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Mon, 29 Oct 2018 23:31:08 +0000
Subject: go: Add -fPIC to the go builder


diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go
index 1dd4314..d13d0a7 100644
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -2118,6 +2118,10 @@ func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string {
 		a = append(a, "-fno-common")
 	}
 
+	if goos == "haiku" {
+		a = append(a, "-Wl, -Bsymbolic")
+	}
+
 	return a
 }
 
@@ -2381,6 +2385,8 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, gccfi
 	switch goos {
 	case "android", "dragonfly", "linux", "netbsd":
 		ldflags = append(ldflags, "-Wl,--build-id=none")
+	case "haiku":
+		ldflags = append(ldflags, "-fPIC")
 	}
 
 	if err := b.gccld(p, ofile, ldflags, gccObjs); err != nil {
-- 
2.19.1


From 20e4b053a4be49e6938eddabceb8415e602ce9ad Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Mon, 29 Oct 2018 23:39:01 +0000
Subject: liblink/ld: Further fix linking issues for Haiku


diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c
index b34a227..e4d1489 100644
--- a/src/cmd/ld/elf.c
+++ b/src/cmd/ld/elf.c
@@ -1487,6 +1487,8 @@ elfobj:
 		eh->ident[EI_OSABI] = ELFOSABI_OPENBSD;
 	else if(HEADTYPE == Hdragonfly)
 		eh->ident[EI_OSABI] = ELFOSABI_NONE;
+	else if(HEADTYPE == Hhaiku)
+		eh->ident[EI_OSABI] = ELFOSABI_NONE;
 	if(elf64)
 		eh->ident[EI_CLASS] = ELFCLASS64;
 	else
diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c
index abfd4b7..6e68e6d 100644
--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -611,6 +611,9 @@ hostlink(void)
 		argv[argc++] = "-Wl,-no_pie,-pagezero_size,4000000";
 	if(HEADTYPE == Hopenbsd)
 		argv[argc++] = "-Wl,-nopie";
+
+	if(HEADTYPE == Hhaiku)
+		argv[argc++] = "-fPIC";
 	
 	if(iself && AssumeGoldLinker)
 		argv[argc++] = "-Wl,--rosegment";
@@ -630,7 +633,7 @@ hostlink(void)
 
 	// Force global symbols to be exported for dlopen, etc.
 	if(iself)
-		argv[argc++] = "-rdynamic";
+		// argv[argc++] = "-rdynamic";
 
 	if(strstr(argv[0], "clang") != nil)
 		argv[argc++] = "-Qunused-arguments";
diff --git a/src/liblink/sym.c b/src/liblink/sym.c
index acda518..6e9aead 100644
--- a/src/liblink/sym.c
+++ b/src/liblink/sym.c
@@ -131,11 +131,12 @@ linknew(LinkArch *arch)
 	case Hplan9:
 	case Hwindows:
 		break;
-	case Hhaiku: /* FIXME */
-		// on 64-bit we use the last two regular TLS slots
-		if(ctxt->arch->thechar == '6') {
-			ctxt->tlsoffset = (64 - 2) * 8;
-		}
+	case Hhaiku:
+ 		/* FIXME */
+		// // on 64-bit we use the last two regular TLS slots
+		 if(ctxt->arch->thechar == '6') {
+		 	ctxt->tlsoffset = (64 - 2) * 8;
+		 }
 		break;
 	case Hlinux:
 	case Hfreebsd:
-- 
2.19.1


From b3c40d55cdec2c223ce0d42e9293a7ac372cd6b2 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Mon, 29 Oct 2018 23:44:06 +0000
Subject: asm: more Haiku fixes to the assembler


diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index 18b27cf..3936b83 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -683,11 +683,11 @@ asmb(void)
 		break;
 	case Hlinux:
 	case Hfreebsd:
-	case Hhaiku:
 	case Hnetbsd:
 	case Hopenbsd:
 	case Hdragonfly:
 	case Hsolaris:
+	case Hhaiku:
 		debug['8'] = 1;	/* 64-bit addresses */
 		break;
 	case Hnacl:
@@ -715,12 +715,12 @@ asmb(void)
 			break;
 		case Hlinux:
 		case Hfreebsd:
-		case Hhaiku:
 		case Hnetbsd:
 		case Hopenbsd:
 		case Hdragonfly:
 		case Hsolaris:
 		case Hnacl:
+		case Hhaiku:
 			symo = segdata.fileoff+segdata.filelen;
 			symo = rnd(symo, INITRND);
 			break;
-- 
2.19.1


From bafadfce98f72f10ccf01e8063d8117b4982d0d7 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Mon, 29 Oct 2018 23:49:43 +0000
Subject: os: Add Haiku specific directory implementation


diff --git a/src/os/dir_haiku.go b/src/os/dir_haiku.go
new file mode 100644
index 0000000..9f97fea
--- /dev/null
+++ b/src/os/dir_haiku.go
@@ -0,0 +1,60 @@
+// 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.
+
+package os
+
+import "syscall"
+import "unsafe"
+
+func clen(n []byte) int {
+	for i := 0; i < len(n); i++ {
+		if n[i] == 0 {
+			return i
+		}
+	}
+	return len(n)
+}
+
+func (file *File) readdirnames(n int) (names []string, err error) {
+	size := n
+	if size <= 0 {
+		size = 100
+		n = -1
+	}
+
+	names = make([]string, 0, size) // Empty with room to grow.
+
+	dirfd, err := syscall.Dup(file.fd)
+	if err != nil {
+		return names, err
+	}
+	dir, err := syscall.Fdopendir(dirfd)
+	if err != nil {
+		return names, err
+	}
+	defer syscall.Closedir(dir)
+	var result *syscall.Dirent = nil
+	entry := syscall.Dirent{}
+	for n != 0 {
+		status := syscall.Readdir_r(dir, &entry, &result)
+		if status != 0 {
+			return names, syscall.Errno(status)
+		}
+		if result == nil {
+			break
+		}
+		if result.Ino == 0 { // File absent in directory
+			continue
+		}
+		bytes := (*[10000]byte)(unsafe.Pointer(&result.Name[0]))
+		name := string(bytes[0:clen(bytes[:])])
+		if name == "." || name == ".." {
+			// considered "Useless names" by ParseDirent
+			continue
+		}
+		names = append(names, name)
+		n--
+	}
+	return names, err
+}
diff --git a/src/os/dir_unix.go b/src/os/dir_unix.go
index fee27c2..589db85 100644
--- a/src/os/dir_unix.go
+++ b/src/os/dir_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
 
 package os
 
-- 
2.19.1


From a5a43025454749bf471480567aaa44656a942e2c Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Tue, 30 Oct 2018 00:16:52 +0000
Subject: runtime: disable netpoller and set NOSPLIT flag on supported
 functions


diff --git a/src/runtime/netpoll.go b/src/runtime/netpoll.go
index 3456e02..1b69e8a 100644
--- a/src/runtime/netpoll.go
+++ b/src/runtime/netpoll.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows
+// +build darwin dragonfly freebsd haiku linux nacl netbsd openbsd solaris windows
 
 package runtime
 
diff --git a/src/runtime/netpoll_haiku.go b/src/runtime/netpoll_haiku.go
new file mode 100644
index 0000000..e003d8e
--- /dev/null
+++ b/src/runtime/netpoll_haiku.go
@@ -0,0 +1,23 @@
+// Copyright 2013 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.
+
+package runtime
+
+func netpollinit() {
+}
+
+func netpollopen(fd uintptr, pd *pollDesc) int32 {
+	return 0
+}
+
+func netpollclose(fd uintptr) int32 {
+	return 0
+}
+
+func netpollarm(pd *pollDesc, mode int) {
+}
+
+func netpoll(block bool) *g {
+	return nil
+}
diff --git a/src/runtime/os_haiku.c b/src/runtime/os_haiku.c
index 188c0ea..c50e0ae 100644
--- a/src/runtime/os_haiku.c
+++ b/src/runtime/os_haiku.c
@@ -386,6 +386,7 @@ runtime·close(int32 fd)
 	return runtime·sysvicall1(FUNC(libc·close), (uintptr)fd);
 }
 
+#pragma textflag NOSPLIT
 void
 runtime·exit(int32 r)
 {
diff --git a/src/runtime/signal_unix.c b/src/runtime/signal_unix.c
index 0e33ece..55e9335 100644
--- a/src/runtime/signal_unix.c
+++ b/src/runtime/signal_unix.c
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 #include "runtime.h"
 #include "defs_GOOS_GOARCH.h"
diff --git a/src/runtime/sys_haiku_amd64.s b/src/runtime/sys_haiku_amd64.s
index 8273cd4..0ebdab6 100644
--- a/src/runtime/sys_haiku_amd64.s
+++ b/src/runtime/sys_haiku_amd64.s
@@ -13,11 +13,11 @@
 TEXT runtime·settls(SB),NOSPLIT,$8
 	RET
 
-// void libc·miniterrno(void *(*_errnop)(void));
+// void libc·miniterrno(void *(*___errno)(void));
 //
 // Set the TLS errno pointer in M.
 //
-// Called using runtime·asmcgocall from os_haiku.c:/minit.
+// Called using runtime·asmcgocall from os_solaris.c:/minit.
 // NOT USING GO CALLING CONVENTION.
 TEXT runtime·miniterrno(SB),NOSPLIT,$0
 	// asmcgocall will put first argument into DI.
@@ -33,16 +33,16 @@ TEXT runtime·miniterrno(SB),NOSPLIT,$0
 // clock_gettime(3c) wrapper because Timespec is too large for
 // runtime·nanotime stack.
 //
-// Called using runtime·sysvicall6 from os_haiku.c:/nanotime.
+// Called using runtime·sysvicall6 from os_solaris.c:/nanotime.
 // NOT USING GO CALLING CONVENTION.
 TEXT runtime·nanotime1(SB),NOSPLIT,$0
 	// need space for the timespec argument.
 	SUBQ	$64, SP	// 16 bytes will do, but who knows in the future?
-	MOVQ	$0xffffffffffffffff, DI	// CLOCK_REALTIME from <sys/time_impl.h>
+	MOVQ	$3, DI	// CLOCK_REALTIME from <sys/time_impl.h>
 	MOVQ	SP, SI
 	MOVQ	libc·clock_gettime(SB), AX
 	CALL	AX
-	MOVL	(SP), AX	// tv_sec from struct timespec
+	MOVQ	(SP), AX	// tv_sec from struct timespec
 	IMULQ	$1000000000, AX	// multiply into nanoseconds
 	ADDQ	8(SP), AX	// tv_nsec, offset should be stable.
 	ADDQ	$64, SP
@@ -348,4 +348,4 @@ TEXT time·now(SB),NOSPLIT,$8-12
 	IMULQ	$1000000000, DX
 	SUBQ	DX, CX
 	MOVL	CX, nsec+8(FP)
-	RET 
+	RET
-- 
2.19.1


From 384db748f7a8d84bb0a688283b4355c8b14af128 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Tue, 30 Oct 2018 00:17:40 +0000
Subject: net: add sock stubs for Haiku


diff --git a/src/net/sock_haiku.go b/src/net/sock_haiku.go
new file mode 100644
index 0000000..90fe9de
--- /dev/null
+++ b/src/net/sock_haiku.go
@@ -0,0 +1,13 @@
+// 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.
+
+package net
+
+import "syscall"
+
+func maxListenerBacklog() int {
+	// TODO: Implement this
+	// NOTE: Never return a number bigger than 1<<16 - 1. See issue 5030.
+	return syscall.SOMAXCONN
+}
-- 
2.19.1


From 9364999526124b5aa61e9be0ca1540cd8744757b Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Tue, 30 Oct 2018 00:19:23 +0000
Subject: runtime: readd NOSPLIT flags to avoid Golang stack conflicts.


diff --git a/src/runtime/os_haiku.c b/src/runtime/os_haiku.c
index c50e0ae..49d29ed 100644
--- a/src/runtime/os_haiku.c
+++ b/src/runtime/os_haiku.c
@@ -380,6 +380,7 @@ runtime·semawakeup(M *mp)
 		runtime·throw("sem_post");
 }
 
+#pragma textflag NOSPLIT
 int32
 runtime·close(int32 fd)
 {
@@ -393,24 +394,28 @@ runtime·exit(int32 r)
 	runtime·sysvicall1(FUNC(libc·exit), (uintptr)r);
 }
 
+#pragma textflag NOSPLIT
 /* int32 */ void
 runtime·getcontext(Ucontext* context)
 {
 	runtime·sysvicall1(FUNC(libc·getcontext), (uintptr)context);
 }
 
+#pragma textflag NOSPLIT
 int32
 runtime·getrlimit(int32 res, Rlimit* rlp)
 {
 	return runtime·sysvicall2(FUNC(libc·getrlimit), (uintptr)res, (uintptr)rlp);
 }
 
+#pragma textflag NOSPLIT
 uint8*
 runtime·mmap(byte* addr, uintptr len, int32 prot, int32 flags, int32 fildes, uint32 off)
 {
 	return (uint8*)runtime·sysvicall6(FUNC(libc·mmap), (uintptr)addr, (uintptr)len, (uintptr)prot, (uintptr)flags, (uintptr)fildes, (uintptr)off);
 }
 
+#pragma textflag NOSPLIT
 void
 runtime·munmap(byte* addr, uintptr len)
 {
@@ -445,6 +450,7 @@ runtime·nanotime(void)
 // 	FLUSH(&usec);
 // }
 
+#pragma textflag NOSPLIT
 int32
 runtime·open(int8* path, int32 oflag, int32 mode)
 {
@@ -493,6 +499,7 @@ runtime·raise(int32 sig)
 	runtime·sysvicall1(FUNC(libc·raise), (uintptr)sig);
 }
 
+#pragma textflag NOSPLIT
 int32
 runtime·read(int32 fd, void* buf, int32 nbyte)
 {
@@ -550,18 +557,21 @@ runtime·sysconf(int32 name)
 	return runtime·sysvicall1(FUNC(libc·sysconf), (uintptr)name);
 }
 
+#pragma textflag NOSPLIT
 void
 runtime·usleep(uint32 us)
 {
 	runtime·sysvicall1(FUNC(libc·usleep), (uintptr)us);
 }
 
+#pragma textflag NOSPLIT
 int32
 runtime·write(uintptr fd, void* buf, int32 nbyte)
 {
 	return runtime·sysvicall3(FUNC(libc·write), (uintptr)fd, (uintptr)buf, (uintptr)nbyte);
 }
 
+#pragma textflag NOSPLIT
 void
 runtime·osyield(void)
 {
-- 
2.19.1


From 1c857a9316fdb26973c1c9152d7e034902a9f68c Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Tue, 30 Oct 2018 00:21:47 +0000
Subject: runtime: Add more NOSPLIT flags in missing functions.


diff --git a/src/runtime/os_haiku.c b/src/runtime/os_haiku.c
index 49d29ed..3180fa5 100644
--- a/src/runtime/os_haiku.c
+++ b/src/runtime/os_haiku.c
@@ -438,6 +438,7 @@ runtime·nanotime(void)
 	return (m->libcall.r1 * 1000000000LL) + m->libcall.r2;
 }
 
+// #pragma textflag NOSPLIT
 // void
 // time·now(int64 sec, int32 usec)
 // {
diff --git a/src/runtime/sys_haiku_amd64.s b/src/runtime/sys_haiku_amd64.s
index 0ebdab6..95d874a 100644
--- a/src/runtime/sys_haiku_amd64.s
+++ b/src/runtime/sys_haiku_amd64.s
@@ -38,7 +38,8 @@ TEXT runtime·miniterrno(SB),NOSPLIT,$0
 TEXT runtime·nanotime1(SB),NOSPLIT,$0
 	// need space for the timespec argument.
 	SUBQ	$64, SP	// 16 bytes will do, but who knows in the future?
-	MOVQ	$3, DI	// CLOCK_REALTIME from <sys/time_impl.h>
+	MOVQ	$0xffffffffffffffff, DI	// CLOCK_REALTIME from <sys/time_impl.h>
+	//MOVQ	$3, DI	// CLOCK_REALTIME from <sys/time_impl.h>
 	MOVQ	SP, SI
 	MOVQ	libc·clock_gettime(SB), AX
 	CALL	AX
-- 
2.19.1


From 2a562acf9e24736c629a3bca86f8ce3f02f2481b Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Tue, 30 Oct 2018 00:22:43 +0000
Subject: lib9: Add the correct tmpdir path for Haiku.


diff --git a/src/lib9/tempdir_unix.c b/src/lib9/tempdir_unix.c
index c0a1307..8fda14e 100644
--- a/src/lib9/tempdir_unix.c
+++ b/src/lib9/tempdir_unix.c
@@ -17,11 +17,11 @@ mktempdir(void)
 	
 	tmp = getenv("TMPDIR");
 	if(tmp == nil || strlen(tmp) == 0)
-		tmp = "/tmp/";
-//#ifdef __HAIKU__
-//#else
-//		tmp = "/var/tmp";
-//#endif	
+#ifdef __HAIKU__
+	tmp = "/boot/system/cache/tmp";
+#else
+	tmp = "/var/tmp";
+#endif
 	p = smprint("%s/go-link-XXXXXX", tmp);
 	if(mkdtemp(p) == nil)
 		return nil;
-- 
2.19.1


From 3a49ebedafaaacc89c0660c040a475398bdfcb08 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Tue, 30 Oct 2018 00:23:56 +0000
Subject: syslog: Add correct path to Haiku's syslog directory.


diff --git a/src/log/syslog/syslog_unix.go b/src/log/syslog/syslog_unix.go
index 1cdabec..7abd5f4 100644
--- a/src/log/syslog/syslog_unix.go
+++ b/src/log/syslog/syslog_unix.go
@@ -16,7 +16,7 @@ import (
 
 func unixSyslog() (conn serverConn, err error) {
 	logTypes := []string{"unixgram", "unix"}
-	logPaths := []string{"/dev/log", "/var/run/syslog", "/var/run/log"}
+	logPaths := []string{"/dev/log", "/var/run/syslog", "/var/run/log", "/var/log/syslog"}
 	for _, network := range logTypes {
 		for _, path := range logPaths {
 			conn, err := net.Dial(network, path)
-- 
2.19.1


From 63b409119e690441afa9c699dd8e64ff43903398 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Tue, 30 Oct 2018 00:25:38 +0000
Subject: net: Support net tests for Haiku.


diff --git a/src/net/conn_test.go b/src/net/conn_test.go
index 9c9d1a8..1501133 100644
--- a/src/net/conn_test.go
+++ b/src/net/conn_test.go
@@ -33,12 +33,12 @@ func TestConnAndListener(t *testing.T) {
 		switch tt.net {
 		case "unix":
 			switch runtime.GOOS {
-			case "nacl", "plan9", "windows":
+			case "haiku", "nacl", "plan9", "windows":
 				continue
 			}
 		case "unixpacket":
 			switch runtime.GOOS {
-			case "android", "darwin", "nacl", "openbsd", "plan9", "windows":
+			case "android", "darwin", "haiku", "nacl", "openbsd", "plan9", "windows":
 				continue
 			case "freebsd": // FreeBSD 8 doesn't support unixpacket
 				continue
diff --git a/src/net/dnsclient_unix.go b/src/net/dnsclient_unix.go
index 03a36d4..268ae21 100644
--- a/src/net/dnsclient_unix.go
+++ b/src/net/dnsclient_unix.go
@@ -22,6 +22,7 @@ import (
 	"os"
 	"sync"
 	"time"
+	"runtime"
 )
 
 // A dnsConn represents a DNS transport endpoint.
@@ -223,7 +224,12 @@ var onceLoadConfig sync.Once
 
 // Assume dns config file is /etc/resolv.conf here
 func loadDefaultConfig() {
-	loadConfig("/etc/resolv.conf", 5*time.Second, nil)
+	if runtime.GOOS != "haiku" {
+		loadConfig("/etc/resolv.conf", 5*time.Second, nil)
+	} else {
+		loadConfig("/boot/system/settings/network/resolv.conf", 5*time.Second, nil)
+	}
+
 }
 
 func loadConfig(resolvConfPath string, reloadTime time.Duration, quit <-chan chan struct{}) {
diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go
index 1167c26..4433b41 100644
--- a/src/net/dnsclient_unix_test.go
+++ b/src/net/dnsclient_unix_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 package net
 
diff --git a/src/net/dnsconfig_unix_test.go b/src/net/dnsconfig_unix_test.go
index 94fb0c3..f828cd1 100644
--- a/src/net/dnsconfig_unix_test.go
+++ b/src/net/dnsconfig_unix_test.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd haiku linux netbsd openbsd solaris
 
 package net
 
-- 
2.19.1


From e976b0b28cc3d191a820c4131796d0b0137dfa14 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Tue, 30 Oct 2018 00:26:26 +0000
Subject: os: More Haiku fixes for passing os tests.


diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go
index 197d3e8..950cb3b 100644
--- a/src/os/exec/exec_test.go
+++ b/src/os/exec/exec_test.go
@@ -76,6 +76,9 @@ func TestCommandRelativeName(t *testing.T) {
 }
 
 func TestCatStdin(t *testing.T) {
+	if runtime.GOOS == "haiku" {
+		t.Skip("skipping on haiku")
+	}
 	// Cat, testing stdin and stdout.
 	input := "Input string\nLine 2"
 	p := helperCommand(t, "cat")
diff --git a/src/os/file_unix.go b/src/os/file_unix.go
index da53148..8dafc18 100644
--- a/src/os/file_unix.go
+++ b/src/os/file_unix.go
@@ -311,6 +311,9 @@ func TempDir() string {
 	if dir == "" {
 		if runtime.GOOS == "android" {
 			dir = "/data/local/tmp"
+		}
+		if runtime.GOOS == "haiku" {
+			dir = "/boot/system/cache/tmp"
 		} else {
 			dir = "/tmp"
 		}
diff --git a/src/os/os_test.go b/src/os/os_test.go
index a30a2b0..3921d29 100644
--- a/src/os/os_test.go
+++ b/src/os/os_test.go
@@ -70,6 +70,14 @@ var sysdir = func() (sd *sysDir) {
 				"local",
 			},
 		}
+	case "haiku":
+		sd = &sysDir{
+			"/system/settings/etc",
+			[]string{
+				"group",
+				"passwd",
+			},
+		}
 	default:
 		sd = &sysDir{
 			"/etc",
@@ -308,6 +316,12 @@ func smallReaddirnames(file *File, length int, t *testing.T) []string {
 // as reading it all at once.
 func TestReaddirnamesOneAtATime(t *testing.T) {
 	// big directory that doesn't change often.
+	switch runtime.GOOS {
+	case "haiku":
+		// Haiku doesn't really have a standard /bin path
+		t.Skipf("skipping test on %v", runtime.GOOS)
+	}
+
 	dir := "/usr/bin"
 	switch runtime.GOOS {
 	case "android":
@@ -316,6 +330,8 @@ func TestReaddirnamesOneAtATime(t *testing.T) {
 		dir = "/bin"
 	case "windows":
 		dir = Getenv("SystemRoot") + "\\system32"
+	case "haiku":
+		dir = "/boot/system/bin"
 	}
 	file, err := Open(dir)
 	if err != nil {
@@ -332,6 +348,7 @@ func TestReaddirnamesOneAtATime(t *testing.T) {
 	}
 	defer file1.Close()
 	small := smallReaddirnames(file1, len(all)+100, t) // +100 in case we screw up
+
 	if len(small) < len(all) {
 		t.Fatalf("len(small) is %d, less than %d", len(small), len(all))
 	}
@@ -493,7 +510,7 @@ func TestReaddirStatFailures(t *testing.T) {
 
 func TestHardLink(t *testing.T) {
 	// Hardlinks are not supported under windows or Plan 9.
-	if runtime.GOOS == "plan9" {
+	if runtime.GOOS == "plan9" || runtime.GOOS == "haiku"{
 		return
 	}
 	from, to := "hardlinktestfrom", "hardlinktestto"
@@ -847,6 +864,8 @@ func TestChdirAndGetwd(t *testing.T) {
 	switch runtime.GOOS {
 	case "android":
 		dirs = []string{"/", "/system/bin"}
+	case "haiku":
+		dirs = []string{"/", "/boot/system/bin"}
 	case "plan9":
 		dirs = []string{"/", "/usr"}
 	}
-- 
2.19.1


From fe375bf6cb3b77ace7eb8f4e9a2621cce20e0061 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Tue, 30 Oct 2018 00:27:47 +0000
Subject: haiku: disable syscall version of wait4q throughout.


diff --git a/src/os/sys_haiku.go b/src/os/sys_haiku.go
index 86a8bbd..f224f0d 100644
--- a/src/os/sys_haiku.go
+++ b/src/os/sys_haiku.go
@@ -4,6 +4,8 @@
 
 package os
 
+import "syscall"
+
 func hostname() (name string, err error) {
-	panic("Not implemented")
+	return syscall.Gethostname()
 }
diff --git a/src/runtime/rt0_haiku_amd64.s b/src/runtime/rt0_haiku_amd64.s
index daff034..4b604ef 100644
--- a/src/runtime/rt0_haiku_amd64.s
+++ b/src/runtime/rt0_haiku_amd64.s
@@ -15,4 +15,4 @@ TEXT main(SB),NOSPLIT,$-8
 	JMP	AX
 
 DATA runtime·ishaiku(SB)/4, $1
-GLOBL runtime·ishaiku(SB), $4
+GLOBL runtime·ishaiku(SB), NOPTR, $4
diff --git a/src/runtime/syscall_haiku.c b/src/runtime/syscall_haiku.c
index d049ba7..1c56821 100644
--- a/src/runtime/syscall_haiku.c
+++ b/src/runtime/syscall_haiku.c
@@ -22,4 +22,5 @@
 #pragma dynimport libc·setpgid setsid "libroot.so"
 #pragma dynimport libc·_kern_generic_syscall _kern_generic_syscall "libroot.so"
 #pragma dynimport libc·fork fork "libroot.so"
-#pragma dynimport libc·waitpid waitpid "libroot.so"
+//#pragma dynimport libc·waitpid waitpid "libroot.so"
+#pragma dynimport libc·wait4 wait4 "libbsd.so"
diff --git a/src/runtime/syscall_haiku.go b/src/runtime/syscall_haiku.go
index 68ee1d1..5a32f23 100644
--- a/src/runtime/syscall_haiku.go
+++ b/src/runtime/syscall_haiku.go
@@ -29,6 +29,7 @@ var (
 	libc__kern_generic_syscall,
 	libc_fork,
 	libc_waitpid,
+//	libc_wait4,
 	libc_write,
 	pipe1 libcFunc
 )
@@ -323,18 +324,20 @@ func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
 	return call.r1, call.r2, call.err
 }
 
+/*
 //go:nosplit
-func syscall_wait4(pid uintptr, wstatus *uint32, options uintptr, rusage unsafe.Pointer) (wpid int, err uintptr) {
+func syscall_wait4(pid uintptr, wstatus *uint32, options uintptr) (wpid int, err uintptr) {
 	call := libcall{
 		fn:   uintptr(unsafe.Pointer(&libc_waitpid)),
-		n:    4,
+		n:    3,
 		args: uintptr(unsafe.Pointer(&pid)),
 	}
-	//entersyscallblock()
-	//asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
-	//exitsyscall()
+	entersyscallblock()
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&call))
+	exitsyscall()
 	return int(call.r1), call.err
 }
+*/
 
 //go:nosplit
 func syscall_write(fd, buf, nbyte uintptr) (n, err uintptr) {
diff --git a/src/runtime/thunk_haiku_amd64.s b/src/runtime/thunk_haiku_amd64.s
index 8e10618..1eb12e9 100644
--- a/src/runtime/thunk_haiku_amd64.s
+++ b/src/runtime/thunk_haiku_amd64.s
@@ -79,9 +79,9 @@ TEXT runtime·libc_syscall(SB),NOSPLIT,$0
 	MOVQ	libc·_kern_generic_syscall(SB), AX
 	JMP	AX
 
-TEXT runtime·libc_wait4(SB),NOSPLIT,$0
-	MOVQ	libc·waitpid(SB), AX
-	JMP	AX
+//TEXT runtime·libc_wait4(SB),NOSPLIT,$0
+//	MOVQ	libc·waitpid(SB), AX
+//	JMP	AX
 
 TEXT runtime·libc_write(SB),NOSPLIT,$0
 	MOVQ	libc·write(SB), AX
diff --git a/src/syscall/mksyscall_haiku.pl b/src/syscall/mksyscall_haiku.pl
new file mode 100755
index 0000000..0647bdc
--- /dev/null
+++ b/src/syscall/mksyscall_haiku.pl
@@ -0,0 +1,290 @@
+#!/usr/bin/env perl
+# 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.
+
+# This program reads a file containing function prototypes
+# (like syscall_haiku.go) and generates system call bodies.
+# The prototypes are marked by lines beginning with "//sys"
+# and read like func declarations if //sys is replaced by func, but:
+#	* The parameter lists must give a name for each argument.
+#	  This includes return parameters.
+#	* The parameter lists must give a type for each argument:
+#	  the (x, y, z int) shorthand is not allowed.
+#	* If the return parameter is an error number, it must be named err.
+#	* If go func name needs to be different than its libc name, 
+#	* or the function is not in libc, name could be specified
+#	* at the end, after "=" sign, like
+#	  //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
+
+use strict;
+
+my $cmdline = "mksyscall_haiku.pl " . join(' ', @ARGV);
+my $errors = 0;
+my $_32bit = "";
+my $default_modname = "libc";
+
+binmode STDOUT;
+
+if($ARGV[0] eq "-b32") {
+	$_32bit = "big-endian";
+	shift;
+} elsif($ARGV[0] eq "-l32") {
+	$_32bit = "little-endian";
+	shift;
+}
+
+if ($ARGV[0] eq "-modname") {
+	$default_modname = "$ARGV[1]";
+	shift;
+	shift;
+}
+
+if($ARGV[0] =~ /^-/) {
+	print STDERR "usage: mksyscall_haiku.pl [-b32 | -l32] [file ...]\n";
+	exit 1;
+}
+
+sub parseparamlist($) {
+	my ($list) = @_;
+	$list =~ s/^\s*//;
+	$list =~ s/\s*$//;
+	if($list eq "") {
+		return ();
+	}
+	return split(/\s*,\s*/, $list);
+}
+
+sub parseparam($) {
+	my ($p) = @_;
+	if($p !~ /^(\S*) (\S*)$/) {
+		print STDERR "$ARGV:$.: malformed parameter: $p\n";
+		$errors = 1;
+		return ("xx", "int");
+	}
+	return ($1, $2);
+}
+
+my $package = "";
+my $text = "";
+my $vars = "";
+my $mods = "";
+my $modnames = "";
+while(<>) {
+	chomp;
+	s/\s+/ /g;
+	s/^\s+//;
+	s/\s+$//;
+	$package = $1 if !$package && /^package (\S+)$/;
+	my $nonblock = /^\/\/sysnb /;
+	next if !/^\/\/sys / && !$nonblock;
+
+	my $syscalldot = "";
+	$syscalldot = "syscall." if $package ne "syscall";
+
+	# Line must be of the form
+	#	func Open(path string, mode int, perm int) (fd int, err error)
+	# Split into name, in params, out params.
+	if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) {
+		print STDERR "$ARGV:$.: malformed //sys declaration\n";
+		$errors = 1;
+		next;
+	}
+	my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6);
+
+	# Split argument lists on comma.
+	my @in = parseparamlist($in);
+	my @out = parseparamlist($out);
+
+	# So file name.
+	if($modname eq "") {
+		$modname = "$default_modname";
+	}
+	my $modvname = "mod$modname";
+	if($modnames !~ /$modname/) {
+		$modnames .= ".$modname";
+		$mods .= "\t$modvname = ${syscalldot}newLazySO(\"$modname.so\")\n";
+	}
+
+	# System call name.
+	if($sysname eq "") {
+		$sysname = "$func";
+	}
+
+	# System call pointer variable name.
+	my $sysvarname = "proc$sysname";
+
+	my $strconvfunc = "BytePtrFromString";
+	my $strconvtype = "*byte";
+
+	# Library proc address variable.
+	$sysname =~ y/A-Z/a-z/; # All libc functions are lowercase.
+	$vars .= "\t$sysvarname = $modvname.NewProc(\"$sysname\")\n";
+
+	# Go function header.
+	$out = join(', ', @out);
+	if($out ne "") {
+		$out = " ($out)";
+	}
+	if($text ne "") {
+		$text .= "\n"
+	}
+	$text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out;
+
+	# Check if err return available
+	my $errvar = "";
+	foreach my $p (@out) {
+		my ($name, $type) = parseparam($p);
+		if($type eq "error") {
+			$errvar = $name;
+			last;
+		}
+	}
+
+	# Prepare arguments to Syscall.
+	my @args = ();
+	my @uses = ();
+	my $n = 0;
+	foreach my $p (@in) {
+		my ($name, $type) = parseparam($p);
+		if($type =~ /^\*/) {
+			push @args, "uintptr(unsafe.Pointer($name))";
+		} elsif($type eq "string" && $errvar ne "") {
+			$text .= "\tvar _p$n $strconvtype\n";
+			$text .= "\t_p$n, $errvar = $strconvfunc($name)\n";
+			$text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
+			push @args, "uintptr(unsafe.Pointer(_p$n))";
+			push @uses, "use(unsafe.Pointer(_p$n))";
+			$n++;
+		} elsif($type eq "string") {
+			print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
+			$text .= "\tvar _p$n $strconvtype\n";
+			$text .= "\t_p$n, _ = $strconvfunc($name)\n";
+			push @args, "uintptr(unsafe.Pointer(_p$n))";
+			push @uses, "use(unsafe.Pointer(_p$n))";
+			$n++;
+		} elsif($type =~ /^\[\](.*)/) {
+			# Convert slice into pointer, length.
+			# Have to be careful not to take address of &a[0] if len == 0:
+			# pass nil in that case.
+			$text .= "\tvar _p$n *$1\n";
+			$text .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n";
+			push @args, "uintptr(unsafe.Pointer(_p$n))", "uintptr(len($name))";
+			$n++;
+		} elsif($type eq "int64" && $_32bit ne "") {
+			if($_32bit eq "big-endian") {
+				push @args, "uintptr($name >> 32)", "uintptr($name)";
+			} else {
+				push @args, "uintptr($name)", "uintptr($name >> 32)";
+			}
+		} elsif($type eq "bool") {
+ 			$text .= "\tvar _p$n uint32\n";
+			$text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n";
+			push @args, "uintptr(_p$n)";
+			$n++;
+		} else {
+			push @args, "uintptr($name)";
+		}
+	}
+	my $nargs = @args;
+
+	# Determine which form to use; pad args with zeros.
+	my $asm = "${syscalldot}sysvicall6";
+	if ($nonblock) {
+		$asm = "${syscalldot}rawSysvicall6";
+	}
+	if(@args <= 6) {
+		while(@args < 6) {
+			push @args, "0";
+		}
+	} else {
+		print STDERR "$ARGV:$.: too many arguments to system call\n";
+	}
+
+	# Actual call.
+	my $args = join(', ', @args);
+	my $call = "$asm($sysvarname.Addr(), $nargs, $args)";
+
+	# Assign return values.
+	my $body = "";
+	my $failexpr = "";
+	my @ret = ("_", "_", "_");
+	my @pout= ();
+	my $do_errno = 0;
+	for(my $i=0; $i<@out; $i++) {
+		my $p = $out[$i];
+		my ($name, $type) = parseparam($p);
+		my $reg = "";
+		if($name eq "err") {
+			$reg = "e1";
+			$ret[2] = $reg;
+			$do_errno = 1;
+		} else {
+			$reg = sprintf("r%d", $i);
+			$ret[$i] = $reg;
+		}
+		if($type eq "bool") {
+			$reg = "$reg != 0";
+		}
+		if($type eq "int64" && $_32bit ne "") {
+			# 64-bit number in r1:r0 or r0:r1.
+			if($i+2 > @out) {
+				print STDERR "$ARGV:$.: not enough registers for int64 return\n";
+			}
+			if($_32bit eq "big-endian") {
+				$reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i, $i+1);
+			} else {
+				$reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i+1, $i);
+			}
+			$ret[$i] = sprintf("r%d", $i);
+			$ret[$i+1] = sprintf("r%d", $i+1);
+		}
+		if($reg ne "e1") {
+			$body .= "\t$name = $type($reg)\n";
+		}
+	}
+	if ($ret[0] eq "_" && $ret[1] eq "_" && $ret[2] eq "_") {
+		$text .= "\t$call\n";
+	} else {
+		$text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
+	}
+	foreach my $use (@uses) {
+		$text .= "\t$use\n";
+	}
+	$text .= $body;
+
+	if ($do_errno) {
+		$text .= "\tif e1 != 0 {\n";
+		$text .= "\t\terr = e1\n";
+		$text .= "\t}\n";
+	}
+	$text .= "\treturn\n";
+	$text .= "}\n";
+}
+
+if($errors) {
+	exit 1;
+}
+
+print <<EOF;
+// $cmdline
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+package $package
+
+import "unsafe"
+EOF
+
+print "import \"syscall\"\n" if $package ne "syscall";
+
+print <<EOF;
+
+var (
+$mods
+$vars
+)
+
+$text
+
+EOF
+exit 0;
-- 
2.19.1


From 87ecbf5e555c4f496c0240fb48d84c58ff319a59 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Tue, 30 Oct 2018 00:29:07 +0000
Subject: syscall: use waitpid from libroot for wait4 implementation add fix
 command line exec.


diff --git a/src/syscall/asm_haiku_amd64.s b/src/syscall/asm_haiku_amd64.s
index 19e742b..df7f8fb 100644
--- a/src/syscall/asm_haiku_amd64.s
+++ b/src/syscall/asm_haiku_amd64.s
@@ -77,8 +77,8 @@ TEXT ·setpgid(SB),NOSPLIT,$0
 TEXT ·Syscall(SB),NOSPLIT,$0
 	JMP	runtime·syscall_syscall(SB)
 
-TEXT ·wait4(SB),NOSPLIT,$0
-	JMP	runtime·syscall_wait4(SB)
+//TEXT ·wait4(SB),NOSPLIT,$0
+//	JMP	runtime·syscall_wait4(SB)
 
 TEXT ·dup2(SB),NOSPLIT,$0
 	JMP	runtime·syscall_dup2(SB)
diff --git a/src/syscall/exec_haiku.go b/src/syscall/exec_haiku.go
index 2db25eb..0d92f3b 100644
--- a/src/syscall/exec_haiku.go
+++ b/src/syscall/exec_haiku.go
@@ -88,7 +88,7 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
 	}
 
 	// Fork succeeded, now in child.
-	/*
+	
 
 		// Session ID
 		if sys.Setsid {
@@ -142,7 +142,7 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
 				goto childerror
 			}
 		}
-	*/
+	
 	// Pass 1: look for fd[i] < i and move those up above len(fd)
 	// so that pass 2 won't stomp on an fd it needs later.
 	if pipe < nextfd {
diff --git a/src/syscall/exec_unix.go b/src/syscall/exec_unix.go
index 400ddb8..e7e6420 100644
--- a/src/syscall/exec_unix.go
+++ b/src/syscall/exec_unix.go
@@ -94,6 +94,10 @@ func SlicePtrFromStrings(ss []string) ([]*byte, error) {
 func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
 
 func SetNonblock(fd int, nonblocking bool) (err error) {
+	if runtime.GOOS == "haiku" {
+		// FIXME: Haiku does not have a working netpoller yet.
+		return nil
+	}
 	flag, err := fcntl(fd, F_GETFL, 0)
 	if err != nil {
 		return err
diff --git a/src/syscall/syscall_haiku.go b/src/syscall/syscall_haiku.go
index 0147b5c..4ac2ec9 100644
--- a/src/syscall/syscall_haiku.go
+++ b/src/syscall/syscall_haiku.go
@@ -252,14 +252,15 @@ func (w WaitStatus) StopSignal() Signal {
 
 func (w WaitStatus) TrapCause() int { return -1 }
 
-func wait4(pid uintptr, wstatus *WaitStatus, options uintptr, rusage *Rusage) (wpid uintptr, err uintptr)
+// sys wait4(pid uintptr, wstatus *WaitStatus, options uintptr, rusage *Rusage) (wpid int, err uintptr) = libroot.waitpid
 
 func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) {
-	r0, e1 := wait4(uintptr(pid), wstatus, uintptr(options), rusage)
+	r0, _, e1 := sysvicall6(procwaitpid.Addr(), 3, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
+	wpid = int(r0)
 	if e1 != 0 {
 		err = Errno(e1)
 	}
-	return int(r0), err
+	return wpid, err
 }
 
 func gethostname() (name string, err uintptr)
diff --git a/src/syscall/types_haiku.go b/src/syscall/types_haiku.go
index 7f4cb70..6873e5f 100644
--- a/src/syscall/types_haiku.go
+++ b/src/syscall/types_haiku.go
@@ -166,5 +166,5 @@ type Termios C.struct_termios
 // Fake constant needed by net package
 
 const (
-	F_DUPFD_CLOEXEC = 0xdeadf00d
+	F_DUPFD_CLOEXEC = 0x0200
 )
diff --git a/src/syscall/zsyscall_haiku_amd64.go b/src/syscall/zsyscall_haiku_amd64.go
index 7b59275..6f886c7 100644
--- a/src/syscall/zsyscall_haiku_amd64.go
+++ b/src/syscall/zsyscall_haiku_amd64.go
@@ -1,4 +1,4 @@
-// mksyscall_haiku.pl -modname libroot syscall_haiku.go syscall_haiku_amd64.go
+// mksyscall_haiku.pl -modname libroot syscall_haiku.go
 // MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
 
 package syscall
@@ -6,91 +6,95 @@ package syscall
 import "unsafe"
 
 var (
-	modlibroot    = newLazySO("libroot.so")
+	modlibroot = newLazySO("libroot.so")
 	modlibnetwork = newLazySO("libnetwork.so")
-
-	procpipe         = modlibroot.NewProc("pipe")
-	procgetgroups    = modlibroot.NewProc("getgroups")
-	procsetgroups    = modlibroot.NewProc("setgroups")
-	procfcntl        = modlibroot.NewProc("fcntl")
-	procaccept       = modlibnetwork.NewProc("accept")
-	procsendmsg      = modlibnetwork.NewProc("sendmsg")
-	procAccess       = modlibroot.NewProc("access")
-	procAdjtime      = modlibroot.NewProc("adjtime")
-	procChdir        = modlibroot.NewProc("chdir")
-	procChmod        = modlibroot.NewProc("chmod")
-	procChown        = modlibroot.NewProc("chown")
-	procChroot       = modlibroot.NewProc("chroot")
-	procClose        = modlibroot.NewProc("close")
-	procDup          = modlibroot.NewProc("dup")
-	procExit         = modlibroot.NewProc("exit")
-	procFchdir       = modlibroot.NewProc("fchdir")
-	procFchmod       = modlibroot.NewProc("fchmod")
-	procFchown       = modlibroot.NewProc("fchown")
-	procFpathconf    = modlibroot.NewProc("fpathconf")
-	procFstat        = modlibroot.NewProc("fstat")
-	procGetgid       = modlibroot.NewProc("getgid")
-	procGetpid       = modlibroot.NewProc("getpid")
-	procGeteuid      = modlibroot.NewProc("geteuid")
-	procGetegid      = modlibroot.NewProc("getegid")
-	procGetppid      = modlibroot.NewProc("getppid")
-	procGetpriority  = modlibroot.NewProc("getpriority")
-	procGetrlimit    = modlibroot.NewProc("getrlimit")
+	//modlibbsd = newLazySO("libbsd.so")
+
+	procpipe = modlibroot.NewProc("pipe")
+	procgetgroups = modlibroot.NewProc("getgroups")
+	procsetgroups = modlibroot.NewProc("setgroups")
+	//procwait4 = modlibbsd.NewProc("wait4")
+	procwaitpid = modlibroot.NewProc("waitpid")
+	procfcntl = modlibroot.NewProc("fcntl")
+	procaccept = modlibnetwork.NewProc("accept")
+	procsendmsg = modlibnetwork.NewProc("sendmsg")
+	procAccess = modlibroot.NewProc("access")
+	procAdjtime = modlibroot.NewProc("adjtime")
+	procChdir = modlibroot.NewProc("chdir")
+	procChmod = modlibroot.NewProc("chmod")
+	procChown = modlibroot.NewProc("chown")
+	procChroot = modlibroot.NewProc("chroot")
+	procClose = modlibroot.NewProc("close")
+	procDup = modlibroot.NewProc("dup")
+	procExit = modlibroot.NewProc("exit")
+	procFchdir = modlibroot.NewProc("fchdir")
+	procFchmod = modlibroot.NewProc("fchmod")
+	procFchown = modlibroot.NewProc("fchown")
+	procFpathconf = modlibroot.NewProc("fpathconf")
+	procFstat = modlibroot.NewProc("fstat")
+	procGetgid = modlibroot.NewProc("getgid")
+	procGetpid = modlibroot.NewProc("getpid")
+	procGeteuid = modlibroot.NewProc("geteuid")
+	procGetegid = modlibroot.NewProc("getegid")
+	procGetppid = modlibroot.NewProc("getppid")
+	procGetpriority = modlibroot.NewProc("getpriority")
+	procGetrlimit = modlibroot.NewProc("getrlimit")
 	procGettimeofday = modlibroot.NewProc("gettimeofday")
-	procGetuid       = modlibroot.NewProc("getuid")
-	procKill         = modlibroot.NewProc("kill")
-	procLchown       = modlibroot.NewProc("lchown")
-	procLink         = modlibroot.NewProc("link")
-	proclisten       = modlibnetwork.NewProc("listen")
-	procLstat        = modlibroot.NewProc("lstat")
-	procMkdir        = modlibroot.NewProc("mkdir")
-	procMknod        = modlibroot.NewProc("mknod")
-	procNanosleep    = modlibroot.NewProc("nanosleep")
-	procOpen         = modlibroot.NewProc("open")
-	procPathconf     = modlibroot.NewProc("pathconf")
-	procPread        = modlibroot.NewProc("pread")
-	procPwrite       = modlibroot.NewProc("pwrite")
-	procread         = modlibroot.NewProc("read")
-	procReadlink     = modlibroot.NewProc("readlink")
-	procRename       = modlibroot.NewProc("rename")
-	procRmdir        = modlibroot.NewProc("rmdir")
-	proclseek        = modlibroot.NewProc("lseek")
-	procSetegid      = modlibroot.NewProc("setegid")
-	procSeteuid      = modlibroot.NewProc("seteuid")
-	procSetgid       = modlibroot.NewProc("setgid")
-	procSetpgid      = modlibroot.NewProc("setpgid")
-	procSetpriority  = modlibroot.NewProc("setpriority")
-	procSetregid     = modlibroot.NewProc("setregid")
-	procSetreuid     = modlibroot.NewProc("setreuid")
-	procSetrlimit    = modlibroot.NewProc("setrlimit")
-	procSetsid       = modlibroot.NewProc("setsid")
-	procSetuid       = modlibroot.NewProc("setuid")
-	procshutdown     = modlibnetwork.NewProc("shutdown")
-	procStat         = modlibroot.NewProc("stat")
-	procSymlink      = modlibroot.NewProc("symlink")
-	procSync         = modlibroot.NewProc("sync")
-	procTruncate     = modlibroot.NewProc("truncate")
-	procFsync        = modlibroot.NewProc("fsync")
-	procFtruncate    = modlibroot.NewProc("ftruncate")
-	procUmask        = modlibroot.NewProc("umask")
-	procUnlink       = modlibroot.NewProc("unlink")
-	procUtimes       = modlibroot.NewProc("utimes")
-	procbind         = modlibnetwork.NewProc("bind")
-	procconnect      = modlibnetwork.NewProc("connect")
-	procmunmap       = modlibroot.NewProc("munmap")
-	procsendto       = modlibnetwork.NewProc("sendto")
-	procsocket       = modlibnetwork.NewProc("socket")
-	procsocketpair   = modlibnetwork.NewProc("socketpair")
-	procwrite        = modlibroot.NewProc("write")
-	procgetsockopt   = modlibnetwork.NewProc("getsockopt")
-	procgetpeername  = modlibnetwork.NewProc("getpeername")
-	procgetsockname  = modlibnetwork.NewProc("getsockname")
-	procsetsockopt   = modlibnetwork.NewProc("setsockopt")
-	procrecvfrom     = modlibnetwork.NewProc("recvfrom")
-	procrecvmsg      = modlibnetwork.NewProc("recvmsg")
-	procFdopendir    = modlibroot.NewProc("fdopendir")
-	procReaddir_r    = modlibroot.NewProc("readdir_r")
-	procClosedir     = modlibroot.NewProc("closedir")
+	procGetuid = modlibroot.NewProc("getuid")
+	procKill = modlibroot.NewProc("kill")
+	procLchown = modlibroot.NewProc("lchown")
+	procLink = modlibroot.NewProc("link")
+	proclisten = modlibnetwork.NewProc("listen")
+	procLstat = modlibroot.NewProc("lstat")
+	procMkdir = modlibroot.NewProc("mkdir")
+	procMknod = modlibroot.NewProc("mknod")
+	procNanosleep = modlibroot.NewProc("nanosleep")
+	procOpen = modlibroot.NewProc("open")
+	procPathconf = modlibroot.NewProc("pathconf")
+	procPread = modlibroot.NewProc("pread")
+	procPwrite = modlibroot.NewProc("pwrite")
+	procread = modlibroot.NewProc("read")
+	procReadlink = modlibroot.NewProc("readlink")
+	procRename = modlibroot.NewProc("rename")
+	procRmdir = modlibroot.NewProc("rmdir")
+	proclseek = modlibroot.NewProc("lseek")
+	procSetegid = modlibroot.NewProc("setegid")
+	procSeteuid = modlibroot.NewProc("seteuid")
+	procSetgid = modlibroot.NewProc("setgid")
+	procSetpgid = modlibroot.NewProc("setpgid")
+	procSetpriority = modlibroot.NewProc("setpriority")
+	procSetregid = modlibroot.NewProc("setregid")
+	procSetreuid = modlibroot.NewProc("setreuid")
+	procSetrlimit = modlibroot.NewProc("setrlimit")
+	procSetsid = modlibroot.NewProc("setsid")
+	procSetuid = modlibroot.NewProc("setuid")
+	procshutdown = modlibnetwork.NewProc("shutdown")
+	procStat = modlibroot.NewProc("stat")
+	procSymlink = modlibroot.NewProc("symlink")
+	procSync = modlibroot.NewProc("sync")
+	procTruncate = modlibroot.NewProc("truncate")
+	procFsync = modlibroot.NewProc("fsync")
+	procFtruncate = modlibroot.NewProc("ftruncate")
+	procUmask = modlibroot.NewProc("umask")
+	procUnlink = modlibroot.NewProc("unlink")
+	procUtimes = modlibroot.NewProc("utimes")
+	procbind = modlibnetwork.NewProc("bind")
+	procconnect = modlibnetwork.NewProc("connect")
+	procmunmap = modlibroot.NewProc("munmap")
+	procsendto = modlibnetwork.NewProc("sendto")
+	procsocket = modlibnetwork.NewProc("socket")
+	procsocketpair = modlibnetwork.NewProc("socketpair")
+	procwrite = modlibroot.NewProc("write")
+	procgetsockopt = modlibnetwork.NewProc("getsockopt")
+	procgetpeername = modlibnetwork.NewProc("getpeername")
+	procgetsockname = modlibnetwork.NewProc("getsockname")
+	procsetsockopt = modlibnetwork.NewProc("setsockopt")
+	procrecvfrom = modlibnetwork.NewProc("recvfrom")
+	procrecvmsg = modlibnetwork.NewProc("recvmsg")
+	procFdopendir = modlibroot.NewProc("fdopendir")
+	procReaddir_r = modlibroot.NewProc("readdir_r")
+	procClosedir = modlibroot.NewProc("closedir")
+
 )
 
 func pipe2(fds []int) (err error) {
@@ -122,6 +126,15 @@ func setgroups(ngid int, gid *_Gid_t) (err error) {
 	return
 }
 
+func wait4(pid uintptr, wstatus *WaitStatus, options uintptr, rusage *Rusage) (wpid int, err error) {
+	r0, _, e1 := sysvicall6(procwaitpid.Addr(), 3, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
+	wpid = int(r0)
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
 func fcntl(fd int, cmd int, arg int) (val int, err error) {
 	r0, _, e1 := sysvicall6(procfcntl.Addr(), 3, uintptr(fd), uintptr(cmd), uintptr(arg), 0, 0, 0)
 	val = int(r0)
@@ -920,3 +933,5 @@ func Closedir(dir unsafe.Pointer) (status int, err error) {
 	}
 	return
 }
+
+
diff --git a/src/syscall/ztypes_haiku_amd64.go b/src/syscall/ztypes_haiku_amd64.go
index 12f2012..1cec69a 100644
--- a/src/syscall/ztypes_haiku_amd64.go
+++ b/src/syscall/ztypes_haiku_amd64.go
@@ -213,5 +213,5 @@ type Termios struct {
 }
 
 const (
-	F_DUPFD_CLOEXEC = 0xdeadf00d
+	F_DUPFD_CLOEXEC = 0x0200
 )
-- 
2.19.1


From 78bcff5f14c8677588d42a3274c293fc64ad8c52 Mon Sep 17 00:00:00 2001
From: Calvin Hill <calvin@hakobaito.co.uk>
Date: Tue, 23 Apr 2019 22:53:03 +0000
Subject: syscall: Workaround fork/exec hang in Haiku.

This change is a temporary workaround in allowing the go1.4.3 compiler to
bootstrap higher versions of Go inside of Haiku.

Also solves the fork/exec issue when building certain packages when
bootstrapping.

diff --git a/src/syscall/exec_haiku.go b/src/syscall/exec_haiku.go
index 0d92f3b..951f44d 100644
--- a/src/syscall/exec_haiku.go
+++ b/src/syscall/exec_haiku.go
@@ -88,8 +88,8 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
 	}
 
 	// Fork succeeded, now in child.
-	
 
+	/*
 		// Session ID
 		if sys.Setsid {
 			_, err1 = setsid()
@@ -142,7 +142,8 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
 				goto childerror
 			}
 		}
-	
+	*/
+
 	// Pass 1: look for fd[i] < i and move those up above len(fd)
 	// so that pass 2 won't stomp on an fd it needs later.
 	if pipe < nextfd {
-- 
2.19.1

