[dev.boringcrypto.go1.11] all: merge go1.11.11 into dev.boringcrypto.go1.11

Change-Id: Ib34dd423b6d83a7e5d0c1f9d7be638aa892fa28c
diff --git a/doc/devel/release.html b/doc/devel/release.html
index 3b6a635..98e0513 100644
--- a/doc/devel/release.html
+++ b/doc/devel/release.html
@@ -81,6 +81,39 @@
 1.11.6 milestone</a> on our issue tracker for details.
 </p>
 
+<p>
+go1.11.7 (released 2019/04/05) includes fixes to the runtime and the
+<code>net</code> packages. See the
+<a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.7">Go
+1.11.7 milestone</a> on our issue tracker for details.
+</p>
+
+<p>
+go1.11.8 (released 2019/04/08) was accidentally released without its
+intended fix. It is identical to go1.11.7, except for its version
+number. The intended fix is in go1.11.9.
+</p>
+
+<p>
+go1.11.9 (released 2019/04/11) fixes an issue where using the prebuilt binary
+releases on older versions of GNU/Linux
+<a href="https://golang.org/issues/31293">led to failures</a>
+when linking programs that used cgo.
+Only Linux users who hit this issue need to update.
+</p>
+
+<p>
+go1.11.10 (released 2019/05/06) includes fixes to the runtime and the linker.
+See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.10">Go
+1.11.10 milestone</a> on our issue tracker for details.
+</p>
+
+<p>
+go1.11.11 (released 2019/06/11) includes a fix to the <code>crypto/x509</code> package.
+See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.11">Go
+1.11.11 milestone</a> on our issue tracker for details.
+</p>
+
 <h2 id="go1.10">go1.10 (released 2018/02/16)</h2>
 
 <p>
diff --git a/src/cmd/link/elf_test.go b/src/cmd/link/elf_test.go
new file mode 100644
index 0000000..3df9869
--- /dev/null
+++ b/src/cmd/link/elf_test.go
@@ -0,0 +1,113 @@
+// Copyright 2019 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 dragonfly freebsd linux netbsd openbsd
+
+package main
+
+import (
+	"internal/testenv"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+	"testing"
+)
+
+var asmSource = `
+	.section .text1,"ax"
+s1:
+	.byte 0
+	.section .text2,"ax"
+s2:
+	.byte 0
+`
+
+var goSource = `
+package main
+func main() {}
+`
+
+// The linker used to crash if an ELF input file had multiple text sections
+// with the same name.
+func TestSectionsWithSameName(t *testing.T) {
+	testenv.MustHaveGoBuild(t)
+	testenv.MustHaveCGO(t)
+	t.Parallel()
+
+	objcopy, err := exec.LookPath("objcopy")
+	if err != nil {
+		t.Skipf("can't find objcopy: %v", err)
+	}
+
+	dir, err := ioutil.TempDir("", "go-link-TestSectionsWithSameName")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(dir)
+
+	gopath := filepath.Join(dir, "GOPATH")
+	env := append(os.Environ(), "GOPATH="+gopath)
+
+	if err := ioutil.WriteFile(filepath.Join(dir, "go.mod"), []byte("module elf_test\n"), 0666); err != nil {
+		t.Fatal(err)
+	}
+
+	asmFile := filepath.Join(dir, "x.s")
+	if err := ioutil.WriteFile(asmFile, []byte(asmSource), 0444); err != nil {
+		t.Fatal(err)
+	}
+
+	goTool := testenv.GoToolPath(t)
+	cmd := exec.Command(goTool, "env", "CC")
+	cmd.Env = env
+	ccb, err := cmd.Output()
+	if err != nil {
+		t.Fatal(err)
+	}
+	cc := strings.TrimSpace(string(ccb))
+
+	cmd = exec.Command(goTool, "env", "GOGCCFLAGS")
+	cmd.Env = env
+	cflagsb, err := cmd.Output()
+	if err != nil {
+		t.Fatal(err)
+	}
+	cflags := strings.Fields(string(cflagsb))
+
+	asmObj := filepath.Join(dir, "x.o")
+	t.Logf("%s %v -c -o %s %s", cc, cflags, asmObj, asmFile)
+	if out, err := exec.Command(cc, append(cflags, "-c", "-o", asmObj, asmFile)...).CombinedOutput(); err != nil {
+		t.Logf("%s", out)
+		t.Fatal(err)
+	}
+
+	asm2Obj := filepath.Join(dir, "x2.syso")
+	t.Logf("%s --rename-section .text2=.text1 %s %s", objcopy, asmObj, asm2Obj)
+	if out, err := exec.Command(objcopy, "--rename-section", ".text2=.text1", asmObj, asm2Obj).CombinedOutput(); err != nil {
+		t.Logf("%s", out)
+		t.Fatal(err)
+	}
+
+	for _, s := range []string{asmFile, asmObj} {
+		if err := os.Remove(s); err != nil {
+			t.Fatal(err)
+		}
+	}
+
+	goFile := filepath.Join(dir, "main.go")
+	if err := ioutil.WriteFile(goFile, []byte(goSource), 0444); err != nil {
+		t.Fatal(err)
+	}
+
+	cmd = exec.Command(goTool, "build")
+	cmd.Dir = dir
+	cmd.Env = env
+	t.Logf("%s build", goTool)
+	if out, err := cmd.CombinedOutput(); err != nil {
+		t.Logf("%s", out)
+		t.Fatal(err)
+	}
+}
diff --git a/src/cmd/link/internal/loadelf/ldelf.go b/src/cmd/link/internal/loadelf/ldelf.go
index 8e32e7d..57d000a 100644
--- a/src/cmd/link/internal/loadelf/ldelf.go
+++ b/src/cmd/link/internal/loadelf/ldelf.go
@@ -678,6 +678,8 @@
 	// as well use one large chunk.
 
 	// create symbols for elfmapped sections
+	sectsymNames := make(map[string]bool)
+	counter := 0
 	for i := 0; uint(i) < elfobj.nsect; i++ {
 		sect = &elfobj.sect[i]
 		if sect.type_ == SHT_ARM_ATTRIBUTES && sect.name == ".ARM.attributes" {
@@ -709,6 +711,12 @@
 		}
 
 		name := fmt.Sprintf("%s(%s)", pkg, sect.name)
+		for sectsymNames[name] {
+			counter++
+			name = fmt.Sprintf("%s(%s%d)", pkg, sect.name, counter)
+		}
+		sectsymNames[name] = true
+
 		s := syms.Lookup(name, localSymVersion)
 
 		switch int(sect.flags) & (ElfSectFlagAlloc | ElfSectFlagWrite | ElfSectFlagExec) {
diff --git a/src/crypto/x509/root_cgo_darwin.go b/src/crypto/x509/root_cgo_darwin.go
index e633207..1c20f26 100644
--- a/src/crypto/x509/root_cgo_darwin.go
+++ b/src/crypto/x509/root_cgo_darwin.go
@@ -16,7 +16,7 @@
 #include <CoreFoundation/CoreFoundation.h>
 #include <Security/Security.h>
 
-static bool isSSLPolicy(SecPolicyRef policyRef) {
+static Boolean isSSLPolicy(SecPolicyRef policyRef) {
 	if (!policyRef) {
 		return false;
 	}
@@ -24,13 +24,13 @@
 	if (properties == NULL) {
 		return false;
 	}
+	Boolean isSSL = false;
 	CFTypeRef value = NULL;
 	if (CFDictionaryGetValueIfPresent(properties, kSecPolicyOid, (const void **)&value)) {
-		CFRelease(properties);
-		return CFEqual(value, kSecPolicyAppleSSL);
+		isSSL = CFEqual(value, kSecPolicyAppleSSL);
 	}
 	CFRelease(properties);
-	return false;
+	return isSSL;
 }
 
 // sslTrustSettingsResult obtains the final kSecTrustSettingsResult value
diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go
index f2adbc1..a2e3318 100644
--- a/src/net/lookup_test.go
+++ b/src/net/lookup_test.go
@@ -250,14 +250,11 @@
 	}
 }
 
-var lookupGooglePublicDNSAddrTests = []struct {
-	addr, name string
-}{
-	{"8.8.8.8", ".google.com."},
-	{"8.8.4.4", ".google.com."},
-
-	{"2001:4860:4860::8888", ".google.com."},
-	{"2001:4860:4860::8844", ".google.com."},
+var lookupGooglePublicDNSAddrTests = []string{
+	"8.8.8.8",
+	"8.8.4.4",
+	"2001:4860:4860::8888",
+	"2001:4860:4860::8844",
 }
 
 func TestLookupGooglePublicDNSAddr(t *testing.T) {
@@ -269,8 +266,8 @@
 
 	defer dnsWaitGroup.Wait()
 
-	for _, tt := range lookupGooglePublicDNSAddrTests {
-		names, err := LookupAddr(tt.addr)
+	for _, ip := range lookupGooglePublicDNSAddrTests {
+		names, err := LookupAddr(ip)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -278,8 +275,8 @@
 			t.Error("got no record")
 		}
 		for _, name := range names {
-			if !strings.HasSuffix(name, tt.name) {
-				t.Errorf("got %s; want a record containing %s", name, tt.name)
+			if !strings.HasSuffix(name, ".google.com.") && !strings.HasSuffix(name, ".google.") {
+				t.Errorf("got %q; want a record ending in .google.com. or .google.", name)
 			}
 		}
 	}
@@ -652,8 +649,8 @@
 		t.Errorf("LookupAddr(8.8.8.8): %v (mode=%v)", err, mode)
 	} else {
 		for _, name := range names {
-			if !strings.HasSuffix(name, ".google.com.") {
-				t.Errorf("LookupAddr(8.8.8.8) = %v, want names ending in .google.com. with trailing dot (mode=%v)", names, mode)
+			if !strings.HasSuffix(name, ".google.com.") && !strings.HasSuffix(name, ".google.") {
+				t.Errorf("LookupAddr(8.8.8.8) = %v, want names ending in .google.com or .google with trailing dot (mode=%v)", names, mode)
 				break
 			}
 		}
diff --git a/src/runtime/asm_wasm.s b/src/runtime/asm_wasm.s
index baf840d..cb08922 100644
--- a/src/runtime/asm_wasm.s
+++ b/src/runtime/asm_wasm.s
@@ -446,7 +446,7 @@
 	// Record value
 	MOVD R1, 0(R5)
 	// Record *slot
-	MOVD R0, 8(R5)
+	MOVD (R0), 8(R5)
 
 	// Increment wbBuf.next
 	Get R5
diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go
index 5607bf9..a3d0bcc 100644
--- a/src/runtime/os_windows.go
+++ b/src/runtime/os_windows.go
@@ -29,6 +29,7 @@
 //go:cgo_import_dynamic runtime._GetProcessAffinityMask GetProcessAffinityMask%3 "kernel32.dll"
 //go:cgo_import_dynamic runtime._GetQueuedCompletionStatus GetQueuedCompletionStatus%5 "kernel32.dll"
 //go:cgo_import_dynamic runtime._GetStdHandle GetStdHandle%1 "kernel32.dll"
+//go:cgo_import_dynamic runtime._GetSystemDirectoryA GetSystemDirectoryA%2 "kernel32.dll"
 //go:cgo_import_dynamic runtime._GetSystemInfo GetSystemInfo%1 "kernel32.dll"
 //go:cgo_import_dynamic runtime._GetThreadContext GetThreadContext%2 "kernel32.dll"
 //go:cgo_import_dynamic runtime._LoadLibraryW LoadLibraryW%1 "kernel32.dll"
@@ -46,12 +47,9 @@
 //go:cgo_import_dynamic runtime._VirtualAlloc VirtualAlloc%4 "kernel32.dll"
 //go:cgo_import_dynamic runtime._VirtualFree VirtualFree%3 "kernel32.dll"
 //go:cgo_import_dynamic runtime._VirtualQuery VirtualQuery%3 "kernel32.dll"
-//go:cgo_import_dynamic runtime._WSAGetOverlappedResult WSAGetOverlappedResult%5 "ws2_32.dll"
 //go:cgo_import_dynamic runtime._WaitForSingleObject WaitForSingleObject%2 "kernel32.dll"
 //go:cgo_import_dynamic runtime._WriteConsoleW WriteConsoleW%5 "kernel32.dll"
 //go:cgo_import_dynamic runtime._WriteFile WriteFile%5 "kernel32.dll"
-//go:cgo_import_dynamic runtime._timeBeginPeriod timeBeginPeriod%1 "winmm.dll"
-//go:cgo_import_dynamic runtime._timeEndPeriod timeEndPeriod%1 "winmm.dll"
 
 type stdFunction unsafe.Pointer
 
@@ -74,6 +72,7 @@
 	_GetProcessAffinityMask,
 	_GetQueuedCompletionStatus,
 	_GetStdHandle,
+	_GetSystemDirectoryA,
 	_GetSystemInfo,
 	_GetSystemTimeAsFileTime,
 	_GetThreadContext,
@@ -94,12 +93,9 @@
 	_VirtualAlloc,
 	_VirtualFree,
 	_VirtualQuery,
-	_WSAGetOverlappedResult,
 	_WaitForSingleObject,
 	_WriteConsoleW,
 	_WriteFile,
-	_timeBeginPeriod,
-	_timeEndPeriod,
 	_ stdFunction
 
 	// Following syscalls are only available on some Windows PCs.
@@ -107,6 +103,7 @@
 	_AddDllDirectory,
 	_AddVectoredContinueHandler,
 	_GetQueuedCompletionStatusEx,
+	_LoadLibraryExA,
 	_LoadLibraryExW,
 	_ stdFunction
 
@@ -124,6 +121,12 @@
 	// links wrong printf function to cgo executable (see issue
 	// 12030 for details).
 	_NtWaitForSingleObject stdFunction
+
+	// These are from non-kernel32.dll, so we prefer to LoadLibraryEx them.
+	_timeBeginPeriod,
+	_timeEndPeriod,
+	_WSAGetOverlappedResult,
+	_ stdFunction
 )
 
 // Function to be called by windows CreateThread
@@ -171,6 +174,26 @@
 	return stdFunction(unsafe.Pointer(f))
 }
 
+var sysDirectory [521]byte
+var sysDirectoryLen uintptr
+
+func windowsLoadSystemLib(name []byte) uintptr {
+	if useLoadLibraryEx {
+		return stdcall3(_LoadLibraryExA, uintptr(unsafe.Pointer(&name[0])), 0, _LOAD_LIBRARY_SEARCH_SYSTEM32)
+	} else {
+		if sysDirectoryLen == 0 {
+			l := stdcall2(_GetSystemDirectoryA, uintptr(unsafe.Pointer(&sysDirectory[0])), uintptr(len(sysDirectory)-1))
+			if l == 0 || l > uintptr(len(sysDirectory)-1) {
+				throw("Unable to determine system directory")
+			}
+			sysDirectory[l] = '\\'
+			sysDirectoryLen = l + 1
+		}
+		absName := append(sysDirectory[:sysDirectoryLen], name...)
+		return stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&absName[0])))
+	}
+}
+
 func loadOptionalSyscalls() {
 	var kernel32dll = []byte("kernel32.dll\000")
 	k32 := stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&kernel32dll[0])))
@@ -180,22 +203,45 @@
 	_AddDllDirectory = windowsFindfunc(k32, []byte("AddDllDirectory\000"))
 	_AddVectoredContinueHandler = windowsFindfunc(k32, []byte("AddVectoredContinueHandler\000"))
 	_GetQueuedCompletionStatusEx = windowsFindfunc(k32, []byte("GetQueuedCompletionStatusEx\000"))
+	_LoadLibraryExA = windowsFindfunc(k32, []byte("LoadLibraryExA\000"))
 	_LoadLibraryExW = windowsFindfunc(k32, []byte("LoadLibraryExW\000"))
+	useLoadLibraryEx = (_LoadLibraryExW != nil && _LoadLibraryExA != nil && _AddDllDirectory != nil)
 
 	var advapi32dll = []byte("advapi32.dll\000")
-	a32 := stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&advapi32dll[0])))
+	a32 := windowsLoadSystemLib(advapi32dll)
 	if a32 == 0 {
 		throw("advapi32.dll not found")
 	}
 	_RtlGenRandom = windowsFindfunc(a32, []byte("SystemFunction036\000"))
 
 	var ntdll = []byte("ntdll.dll\000")
-	n32 := stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&ntdll[0])))
+	n32 := windowsLoadSystemLib(ntdll)
 	if n32 == 0 {
 		throw("ntdll.dll not found")
 	}
 	_NtWaitForSingleObject = windowsFindfunc(n32, []byte("NtWaitForSingleObject\000"))
 
+	var winmmdll = []byte("winmm.dll\000")
+	m32 := windowsLoadSystemLib(winmmdll)
+	if m32 == 0 {
+		throw("winmm.dll not found")
+	}
+	_timeBeginPeriod = windowsFindfunc(m32, []byte("timeBeginPeriod\000"))
+	_timeEndPeriod = windowsFindfunc(m32, []byte("timeEndPeriod\000"))
+	if _timeBeginPeriod == nil || _timeEndPeriod == nil {
+		throw("timeBegin/EndPeriod not found")
+	}
+
+	var ws232dll = []byte("ws2_32.dll\000")
+	ws232 := windowsLoadSystemLib(ws232dll)
+	if ws232 == 0 {
+		throw("ws2_32.dll not found")
+	}
+	_WSAGetOverlappedResult = windowsFindfunc(ws232, []byte("WSAGetOverlappedResult\000"))
+	if _WSAGetOverlappedResult == nil {
+		throw("WSAGetOverlappedResult not found")
+	}
+
 	if windowsFindfunc(n32, []byte("wine_get_version\000")) != nil {
 		// running on Wine
 		initWine(k32)
@@ -302,8 +348,6 @@
 
 	loadOptionalSyscalls()
 
-	useLoadLibraryEx = (_LoadLibraryExW != nil && _AddDllDirectory != nil)
-
 	disableWER()
 
 	initExceptionHandler()
diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go
index 8264070..ee931ce 100644
--- a/src/runtime/syscall_windows.go
+++ b/src/runtime/syscall_windows.go
@@ -90,9 +90,13 @@
 
 const _LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
 
+// When available, this function will use LoadLibraryEx with the filename
+// parameter and the important SEARCH_SYSTEM32 argument. But on systems that
+// do not have that option, absoluteFilepath should contain a fallback
+// to the full path inside of system32 for use with vanilla LoadLibrary.
 //go:linkname syscall_loadsystemlibrary syscall.loadsystemlibrary
 //go:nosplit
-func syscall_loadsystemlibrary(filename *uint16) (handle, err uintptr) {
+func syscall_loadsystemlibrary(filename *uint16, absoluteFilepath *uint16) (handle, err uintptr) {
 	lockOSThread()
 	defer unlockOSThread()
 	c := &getg().m.syscall
@@ -107,15 +111,9 @@
 		}{filename, 0, _LOAD_LIBRARY_SEARCH_SYSTEM32}
 		c.args = uintptr(noescape(unsafe.Pointer(&args)))
 	} else {
-		// User doesn't have KB2533623 installed. The caller
-		// wanted to only load the filename DLL from the
-		// System32 directory but that facility doesn't exist,
-		// so just load it the normal way. This is a potential
-		// security risk, but so is not installing security
-		// updates.
 		c.fn = getLoadLibrary()
 		c.n = 1
-		c.args = uintptr(noescape(unsafe.Pointer(&filename)))
+		c.args = uintptr(noescape(unsafe.Pointer(&absoluteFilepath)))
 	}
 
 	cgocall(asmstdcallAddr, unsafe.Pointer(c))
diff --git a/src/syscall/dll_windows.go b/src/syscall/dll_windows.go
index 2ee85a0..577ca96 100644
--- a/src/syscall/dll_windows.go
+++ b/src/syscall/dll_windows.go
@@ -27,7 +27,7 @@
 func Syscall12(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2 uintptr, err Errno)
 func Syscall15(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2 uintptr, err Errno)
 func loadlibrary(filename *uint16) (handle uintptr, err Errno)
-func loadsystemlibrary(filename *uint16) (handle uintptr, err Errno)
+func loadsystemlibrary(filename *uint16, absoluteFilepath *uint16) (handle uintptr, err Errno)
 func getprocaddress(handle uintptr, procname *uint8) (proc uintptr, err Errno)
 
 // A DLL implements access to a single DLL.
@@ -36,6 +36,26 @@
 	Handle Handle
 }
 
+// We use this for computing the absolute path for system DLLs on systems
+// where SEARCH_SYSTEM32 is not available.
+var systemDirectoryPrefix string
+
+func init() {
+	n := uint32(MAX_PATH)
+	for {
+		b := make([]uint16, n)
+		l, e := getSystemDirectory(&b[0], n)
+		if e != nil {
+			panic("Unable to determine system directory: " + e.Error())
+		}
+		if l <= n {
+			systemDirectoryPrefix = UTF16ToString(b[:l]) + "\\"
+			break
+		}
+		n = l
+	}
+}
+
 // LoadDLL loads the named DLL file into memory.
 //
 // If name is not an absolute path and is not a known system DLL used by
@@ -52,7 +72,11 @@
 	var h uintptr
 	var e Errno
 	if sysdll.IsSystemDLL[name] {
-		h, e = loadsystemlibrary(namep)
+		absoluteFilepathp, err := UTF16PtrFromString(systemDirectoryPrefix + name)
+		if err != nil {
+			return nil, err
+		}
+		h, e = loadsystemlibrary(namep, absoluteFilepathp)
 	} else {
 		h, e = loadlibrary(namep)
 	}
diff --git a/src/syscall/security_windows.go b/src/syscall/security_windows.go
index ae8b3a1..db80d98 100644
--- a/src/syscall/security_windows.go
+++ b/src/syscall/security_windows.go
@@ -290,6 +290,7 @@
 //sys	OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
 //sys	GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
 //sys	GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
+//sys	getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW
 
 // An access token contains the security information for a logon session.
 // The system creates an access token when a user logs on, and every
diff --git a/src/syscall/zsyscall_windows.go b/src/syscall/zsyscall_windows.go
index de2d4f3..2348f65 100644
--- a/src/syscall/zsyscall_windows.go
+++ b/src/syscall/zsyscall_windows.go
@@ -190,6 +190,7 @@
 	procOpenProcessToken                   = modadvapi32.NewProc("OpenProcessToken")
 	procGetTokenInformation                = modadvapi32.NewProc("GetTokenInformation")
 	procGetUserProfileDirectoryW           = moduserenv.NewProc("GetUserProfileDirectoryW")
+	procGetSystemDirectoryW                = modkernel32.NewProc("GetSystemDirectoryW")
 )
 
 func GetLastError() (lasterr error) {
@@ -1916,3 +1917,16 @@
 	}
 	return
 }
+
+func getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) {
+	r0, _, e1 := Syscall(procGetSystemDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0)
+	len = uint32(r0)
+	if len == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = EINVAL
+		}
+	}
+	return
+}