From 639a20da908c2646de46b93ca2933651363ec22a Mon Sep 17 00:00:00 2001
From: Richard Miller
Date: Fri, 29 Apr 2016 17:39:33 +0100
Subject: [PATCH 001/267] syscall: simplify closing of extra fds in plan9
StartProcess
Reviving earlier work by @ality in https://golang.org/cl/57890043
to make the closing of extra file descriptors in syscall.StartProcess
less race-prone. Instead of making a list of open fds in the parent
before forking, the child can read through the list of open fds and
close the ones not explicitly requested. Also eliminate the
complication of keeping open any extra fds which were inherited by
the parent when it started.
This CL will be followed by one to eliminate the ForkLock in plan9,
which is now redundant.
Fixes #5605
Change-Id: I6b4b942001baa54248b656c52dced3b62021c486
Reviewed-on: https://go-review.googlesource.com/22610
Run-TryBot: David du Colombier <0intro@gmail.com>
Reviewed-by: David du Colombier <0intro@gmail.com>
---
src/syscall/exec_plan9.go | 158 +++++++++++++++++++++--------------
src/syscall/syscall_plan9.go | 1 +
2 files changed, 95 insertions(+), 64 deletions(-)
diff --git a/src/syscall/exec_plan9.go b/src/syscall/exec_plan9.go
index bccea5105cb7bb..58e5a3c623b62a 100644
--- a/src/syscall/exec_plan9.go
+++ b/src/syscall/exec_plan9.go
@@ -61,6 +61,41 @@ import (
var ForkLock sync.RWMutex
+// gstringb reads a non-empty string from b, prefixed with a 16-bit length in little-endian order.
+// It returns the string as a byte slice, or nil if b is too short to contain the length or
+// the full string.
+//go:nosplit
+func gstringb(b []byte) []byte {
+ if len(b) < 2 {
+ return nil
+ }
+ n, b := gbit16(b)
+ if int(n) > len(b) {
+ return nil
+ }
+ return b[:n]
+}
+
+// Offset of the name field in a 9P directory entry - see UnmarshalDir() in dir_plan9.go
+const nameOffset = 39
+
+// gdirname returns the first filename from a buffer of directory entries,
+// and a slice containing the remaining directory entries.
+// If the buffer doesn't start with a valid directory entry, the returned name is nil.
+//go:nosplit
+func gdirname(buf []byte) (name []byte, rest []byte) {
+ if len(buf) < 2 {
+ return
+ }
+ size, buf := gbit16(buf)
+ if size < STATFIXLEN || int(size) > len(buf) {
+ return
+ }
+ name = gstringb(buf[nameOffset:size])
+ rest = buf[size:]
+ return
+}
+
// StringSlicePtr converts a slice of strings to a slice of pointers
// to NUL-terminated byte arrays. If any string contains a NUL byte
// this function panics instead of returning an error.
@@ -104,20 +139,13 @@ func readdirnames(dirfd int) (names []string, err error) {
if n == 0 {
break
}
- for i := 0; i < n; {
- m, _ := gbit16(buf[i:])
- m += 2
-
- if m < STATFIXLEN {
+ for b := buf[:n]; len(b) > 0; {
+ var s []byte
+ s, b = gdirname(b)
+ if s == nil {
return nil, ErrBadStat
}
-
- s, _, ok := gstring(buf[i+41:])
- if !ok {
- return nil, ErrBadStat
- }
- names = append(names, s)
- i += int(m)
+ names = append(names, string(s))
}
}
return
@@ -152,16 +180,8 @@ func readdupdevice() (fds []int, err error) {
return
}
-var startupFds []int
-
-// Plan 9 does not allow clearing the OCEXEC flag
-// from the underlying channel backing an open file descriptor,
-// therefore we store a list of already opened file descriptors
-// inside startupFds and skip them when manually closing descriptors
-// not meant to be passed to a child exec.
-func init() {
- startupFds, _ = readdupdevice()
-}
+// name of the directory containing names and control files for all open file descriptors
+var dupdev, _ = BytePtrFromString("#d")
// forkAndExecInChild forks the process, calling dup onto 0..len(fd)
// and finally invoking exec(argv0, argvv, envv) in the child.
@@ -174,7 +194,7 @@ func init() {
// The calls to RawSyscall are okay because they are assembly
// functions that do not grow the stack.
//go:norace
-func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, attr *ProcAttr, fdsToClose []int, pipe int, rflag int) (pid int, err error) {
+func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, attr *ProcAttr, pipe int, rflag int) (pid int, err error) {
// Declare all variables at top in case any
// declarations require heap allocation (e.g., errbuf).
var (
@@ -184,6 +204,8 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, at
clearenv int
envfd int
errbuf [ERRMAX]byte
+ statbuf [STATMAX]byte
+ dupdevfd int
)
// Guard against side effects of shuffling fds below.
@@ -218,14 +240,39 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, at
// Fork succeeded, now in child.
// Close fds we don't need.
- for i = 0; i < len(fdsToClose); i++ {
- if fdsToClose[i] != pipe {
- RawSyscall(SYS_CLOSE, uintptr(fdsToClose[i]), 0, 0)
+ r1, _, _ = RawSyscall(SYS_OPEN, uintptr(unsafe.Pointer(dupdev)), uintptr(O_RDONLY), 0)
+ dupdevfd = int(r1)
+ if dupdevfd == -1 {
+ goto childerror
+ }
+dirloop:
+ for {
+ r1, _, _ = RawSyscall6(SYS_PREAD, uintptr(dupdevfd), uintptr(unsafe.Pointer(&statbuf[0])), uintptr(len(statbuf)), ^uintptr(0), ^uintptr(0), 0)
+ n := int(r1)
+ switch n {
+ case -1:
+ goto childerror
+ case 0:
+ break dirloop
+ }
+ for b := statbuf[:n]; len(b) > 0; {
+ var s []byte
+ s, b = gdirname(b)
+ if s == nil {
+ copy(errbuf[:], ErrBadStat.Error())
+ goto childerror1
+ }
+ if s[len(s)-1] == 'l' {
+ // control file for descriptor is named ctl
+ continue
+ }
+ closeFdExcept(int(atoi(s)), pipe, dupdevfd, fd)
}
}
+ RawSyscall(SYS_CLOSE, uintptr(dupdevfd), 0, 0)
+ // Write new environment variables.
if envv != nil {
- // Write new environment variables.
for i = 0; i < len(envv); i++ {
r1, _, _ = RawSyscall(SYS_CREATE, uintptr(unsafe.Pointer(envv[i].name)), uintptr(O_WRONLY), uintptr(0666))
@@ -313,6 +360,7 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, at
childerror:
// send error string on pipe
RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&errbuf[0])), uintptr(len(errbuf)), 0)
+childerror1:
errbuf[len(errbuf)-1] = 0
i = 0
for i < len(errbuf) && errbuf[i] != 0 {
@@ -332,6 +380,20 @@ childerror:
panic("unreached")
}
+// close the numbered file descriptor, unless it is fd1, fd2, or a member of fds.
+//go:nosplit
+func closeFdExcept(n int, fd1 int, fd2 int, fds []int) {
+ if n == fd1 || n == fd2 {
+ return
+ }
+ for _, fd := range fds {
+ if n == fd {
+ return
+ }
+ }
+ RawSyscall(SYS_CLOSE, uintptr(n), 0, 0)
+}
+
func cexecPipe(p []int) error {
e := Pipe(p)
if e != nil {
@@ -433,49 +495,15 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
// Acquire the fork lock to prevent other threads from creating new fds before we fork.
ForkLock.Lock()
- // get a list of open fds, excluding stdin,stdout and stderr that need to be closed in the child.
- // no new fds can be created while we hold the ForkLock for writing.
- openFds, e := readdupdevice()
- if e != nil {
- ForkLock.Unlock()
- return 0, e
- }
-
- fdsToClose := make([]int, 0, len(openFds))
- for _, fd := range openFds {
- doClose := true
-
- // exclude files opened at startup.
- for _, sfd := range startupFds {
- if fd == sfd {
- doClose = false
- break
- }
- }
-
- // exclude files explicitly requested by the caller.
- for _, rfd := range attr.Files {
- if fd == int(rfd) {
- doClose = false
- break
- }
- }
-
- if doClose {
- fdsToClose = append(fdsToClose, fd)
- }
- }
-
// Allocate child status pipe close on exec.
- e = cexecPipe(p[:])
+ e := cexecPipe(p[:])
if e != nil {
return 0, e
}
- fdsToClose = append(fdsToClose, p[0])
// Kick off child.
- pid, err = forkAndExecInChild(argv0p, argvp, envvParsed, dir, attr, fdsToClose, p[1], sys.Rfork)
+ pid, err = forkAndExecInChild(argv0p, argvp, envvParsed, dir, attr, p[1], sys.Rfork)
if err != nil {
if p[0] >= 0 {
@@ -493,8 +521,10 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
Close(p[0])
if err != nil || n != 0 {
- if n != 0 {
+ if n > 0 {
err = NewError(string(errbuf[:n]))
+ } else if err == nil {
+ err = NewError("failed to read exec status")
}
// Child failed; wait for it to exit, to make sure
diff --git a/src/syscall/syscall_plan9.go b/src/syscall/syscall_plan9.go
index 796870825c98dc..b511867cda51d4 100644
--- a/src/syscall/syscall_plan9.go
+++ b/src/syscall/syscall_plan9.go
@@ -56,6 +56,7 @@ func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err ErrorSt
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
+//go:nosplit
func atoi(b []byte) (n uint) {
n = 0
for i := 0; i < len(b); i++ {
From 5bf9b39acc7c4e9658190d8606b5d719678db14a Mon Sep 17 00:00:00 2001
From: Richard Miller
Date: Fri, 29 Apr 2016 21:02:59 +0100
Subject: [PATCH 002/267] os/exec: re-enable TestExtraFiles for plan9
This test should now succeed after CL 22610 which fixes issue #7118
Change-Id: Ie785a84d77b27c832a1ddd81699bf25dab24b97d
Reviewed-on: https://go-review.googlesource.com/22640
Reviewed-by: Brad Fitzpatrick
Reviewed-by: David du Colombier <0intro@gmail.com>
Run-TryBot: David du Colombier <0intro@gmail.com>
TryBot-Result: Gobot Gobot
---
src/os/exec/exec_test.go | 4 ----
1 file changed, 4 deletions(-)
diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go
index 1151ca7d0f0c26..0cff3bb9264e7f 100644
--- a/src/os/exec/exec_test.go
+++ b/src/os/exec/exec_test.go
@@ -660,10 +660,6 @@ func TestHelperProcess(*testing.T) {
// the cloned file descriptors that result from opening
// /dev/urandom.
// https://golang.org/issue/3955
- case "plan9":
- // TODO(0intro): Determine why Plan 9 is leaking
- // file descriptors.
- // https://golang.org/issue/7118
case "solaris":
// TODO(aram): This fails on Solaris because libc opens
// its own files, as it sees fit. Darwin does the same,
From 5f83bf6053763801beb84a926cde7221874bc4f7 Mon Sep 17 00:00:00 2001
From: Alan Donovan
Date: Thu, 5 May 2016 14:56:58 -0700
Subject: [PATCH 003/267] go/token: document postcondition of SetLines
Change-Id: Ie163deade396b3e298a93845b9ca4d52333ea82a
Reviewed-on: https://go-review.googlesource.com/22831
Reviewed-by: Brad Fitzpatrick
---
src/go/token/position.go | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/go/token/position.go b/src/go/token/position.go
index 33751779a3d9b5..7306083b0dd8ac 100644
--- a/src/go/token/position.go
+++ b/src/go/token/position.go
@@ -164,6 +164,7 @@ func (f *File) MergeLine(line int) {
// Each line offset must be larger than the offset for the previous line
// and smaller than the file size; otherwise SetLines fails and returns
// false.
+// Callers must not mutate the provided slice after SetLines returns.
//
func (f *File) SetLines(lines []int) bool {
// verify validity of lines table
From 6db98a3c51549eb5e1e481e9bca6ede7e8e15f54 Mon Sep 17 00:00:00 2001
From: David Chase
Date: Thu, 5 May 2016 13:35:10 -0700
Subject: [PATCH 004/267] cmd/compile: repair MININT conversion bug in arm
softfloat
Negative-case conversion code was wrong for minimum int32,
used negate-then-widen instead of widen-then-negate.
Test already exists; this fixes the failure.
Fixes #15563.
Change-Id: I4b0b3ae8f2c9714bdcc405d4d0b1502ccfba2b40
Reviewed-on: https://go-review.googlesource.com/22830
Run-TryBot: David Chase
Reviewed-by: Keith Randall
TryBot-Result: Gobot Gobot
---
src/runtime/softfloat_arm.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/runtime/softfloat_arm.go b/src/runtime/softfloat_arm.go
index 648b2e1169cffb..5f609c80d3ebae 100644
--- a/src/runtime/softfloat_arm.go
+++ b/src/runtime/softfloat_arm.go
@@ -530,7 +530,7 @@ execute:
case 0xeeb80ac0: // D[regd] = S[regm] (MOVWF)
cmp := int32(m.freglo[regm])
if cmp < 0 {
- fputf(regd, f64to32(fintto64(int64(-cmp))))
+ fputf(regd, f64to32(fintto64(-int64(cmp))))
m.freglo[regd] ^= 0x80000000
} else {
fputf(regd, f64to32(fintto64(int64(cmp))))
@@ -552,7 +552,7 @@ execute:
case 0xeeb80bc0: // D[regd] = S[regm] (MOVWD)
cmp := int32(m.freglo[regm])
if cmp < 0 {
- fputd(regd, fintto64(int64(-cmp)))
+ fputd(regd, fintto64(-int64(cmp)))
m.freghi[regd] ^= 0x80000000
} else {
fputd(regd, fintto64(int64(cmp)))
From acc757f678a42ba1ffbf8bb9886de4fe080302de Mon Sep 17 00:00:00 2001
From: Joe Tsai
Date: Tue, 5 Apr 2016 11:22:53 -0700
Subject: [PATCH 005/267] all: use SeekStart, SeekCurrent, SeekEnd
CL/19862 (f79b50b8d5bc159561c1dcf7c17e2a0db96a9a11) recently introduced the constants
SeekStart, SeekCurrent, and SeekEnd to the io package. We should use these constants
consistently throughout the code base.
Updates #15269
Change-Id: If7fcaca7676e4a51f588528f5ced28220d9639a2
Reviewed-on: https://go-review.googlesource.com/22097
Reviewed-by: Brad Fitzpatrick
Run-TryBot: Joe Tsai
TryBot-Result: Gobot Gobot
---
src/bufio/bufio_test.go | 2 +-
src/bytes/reader.go | 6 +++---
src/bytes/reader_test.go | 2 +-
src/cmd/go/note.go | 2 +-
src/cmd/internal/goobj/read.go | 8 ++++----
src/cmd/pack/pack.go | 4 ++--
src/debug/elf/file_test.go | 8 ++++----
src/debug/elf/reader.go | 6 +++---
src/go/internal/gccgoimporter/importer.go | 4 ++--
src/io/example_test.go | 2 +-
src/io/io.go | 6 +++---
src/io/io_test.go | 4 ++--
src/net/file_plan9.go | 2 +-
src/net/http/internal/chunked_test.go | 2 +-
src/net/lookup_plan9.go | 5 +++--
src/os/file_plan9.go | 3 ++-
src/os/file_windows.go | 8 ++++----
src/os/os_test.go | 18 +++++++++---------
src/runtime/runtime-lldb_test.go | 4 ++--
src/strings/reader.go | 6 +++---
src/strings/strings_test.go | 2 +-
src/syscall/fd_nacl.go | 7 ++++---
src/syscall/fs_nacl.go | 5 +++--
src/syscall/syscall_unix_test.go | 5 +++--
src/time/sys_plan9.go | 5 +++--
src/time/sys_unix.go | 5 +++--
src/time/sys_windows.go | 5 +++--
27 files changed, 72 insertions(+), 64 deletions(-)
diff --git a/src/bufio/bufio_test.go b/src/bufio/bufio_test.go
index d769a6aaa98d0e..858048696e4ed1 100644
--- a/src/bufio/bufio_test.go
+++ b/src/bufio/bufio_test.go
@@ -1475,7 +1475,7 @@ func BenchmarkReaderWriteToOptimal(b *testing.B) {
b.Fatal("ioutil.Discard doesn't support ReaderFrom")
}
for i := 0; i < b.N; i++ {
- r.Seek(0, 0)
+ r.Seek(0, io.SeekStart)
srcReader.Reset(onlyReader{r})
n, err := srcReader.WriteTo(ioutil.Discard)
if err != nil {
diff --git a/src/bytes/reader.go b/src/bytes/reader.go
index 83826c80c417af..28cfc7a97884a7 100644
--- a/src/bytes/reader.go
+++ b/src/bytes/reader.go
@@ -108,11 +108,11 @@ func (r *Reader) Seek(offset int64, whence int) (int64, error) {
r.prevRune = -1
var abs int64
switch whence {
- case 0:
+ case io.SeekStart:
abs = offset
- case 1:
+ case io.SeekCurrent:
abs = r.i + offset
- case 2:
+ case io.SeekEnd:
abs = int64(len(r.s)) + offset
default:
return 0, errors.New("bytes.Reader.Seek: invalid whence")
diff --git a/src/bytes/reader_test.go b/src/bytes/reader_test.go
index b5c78506189e50..7b3034d4e0d90c 100644
--- a/src/bytes/reader_test.go
+++ b/src/bytes/reader_test.go
@@ -188,7 +188,7 @@ var UnreadRuneErrorTests = []struct {
{"Read", func(r *Reader) { r.Read([]byte{0}) }},
{"ReadByte", func(r *Reader) { r.ReadByte() }},
{"UnreadRune", func(r *Reader) { r.UnreadRune() }},
- {"Seek", func(r *Reader) { r.Seek(0, 1) }},
+ {"Seek", func(r *Reader) { r.Seek(0, io.SeekCurrent) }},
{"WriteTo", func(r *Reader) { r.WriteTo(&Buffer{}) }},
}
diff --git a/src/cmd/go/note.go b/src/cmd/go/note.go
index ada8ddded47f28..fae9536d13fb93 100644
--- a/src/cmd/go/note.go
+++ b/src/cmd/go/note.go
@@ -110,7 +110,7 @@ func readELFGoBuildID(filename string, f *os.File, data []byte) (buildid string,
// or even the first few megabytes of the file
// due to differences in note segment placement;
// in that case, extract the note data manually.
- _, err = f.Seek(int64(p.Off), 0)
+ _, err = f.Seek(int64(p.Off), io.SeekStart)
if err != nil {
return "", err
}
diff --git a/src/cmd/internal/goobj/read.go b/src/cmd/internal/goobj/read.go
index 69fa496110db43..214f65cbc4cbdf 100644
--- a/src/cmd/internal/goobj/read.go
+++ b/src/cmd/internal/goobj/read.go
@@ -290,9 +290,9 @@ func importPathToPrefix(s string) string {
func (r *objReader) init(f io.ReadSeeker, p *Package) {
r.f = f
r.p = p
- r.offset, _ = f.Seek(0, 1)
- r.limit, _ = f.Seek(0, 2)
- f.Seek(r.offset, 0)
+ r.offset, _ = f.Seek(0, io.SeekCurrent)
+ r.limit, _ = f.Seek(0, io.SeekEnd)
+ f.Seek(r.offset, io.SeekStart)
r.b = bufio.NewReader(f)
r.pkgprefix = importPathToPrefix(p.ImportPath) + "."
}
@@ -440,7 +440,7 @@ func (r *objReader) skip(n int64) {
r.readFull(r.tmp[:n])
} else {
// Seek, giving up buffered data.
- _, err := r.f.Seek(r.offset+n, 0)
+ _, err := r.f.Seek(r.offset+n, io.SeekStart)
if err != nil {
r.error(err)
}
diff --git a/src/cmd/pack/pack.go b/src/cmd/pack/pack.go
index 5be42555d08118..1c168f946bd04e 100644
--- a/src/cmd/pack/pack.go
+++ b/src/cmd/pack/pack.go
@@ -286,7 +286,7 @@ func (ar *Archive) output(entry *Entry, w io.Writer) {
log.Fatal("short file")
}
if entry.size&1 == 1 {
- _, err := ar.fd.Seek(1, 1)
+ _, err := ar.fd.Seek(1, io.SeekCurrent)
if err != nil {
log.Fatal(err)
}
@@ -299,7 +299,7 @@ func (ar *Archive) skip(entry *Entry) {
if size&1 == 1 {
size++
}
- _, err := ar.fd.Seek(size, 1)
+ _, err := ar.fd.Seek(size, io.SeekCurrent)
if err != nil {
log.Fatal(err)
}
diff --git a/src/debug/elf/file_test.go b/src/debug/elf/file_test.go
index 2fe6febb26b024..b189219a556a21 100644
--- a/src/debug/elf/file_test.go
+++ b/src/debug/elf/file_test.go
@@ -655,7 +655,7 @@ func TestCompressedSection(t *testing.T) {
// Test Open method and seeking.
buf, have, count := make([]byte, len(b)), make([]bool, len(b)), 0
sf := sec.Open()
- if got, err := sf.Seek(0, 2); got != int64(len(b)) || err != nil {
+ if got, err := sf.Seek(0, io.SeekEnd); got != int64(len(b)) || err != nil {
t.Fatalf("want seek end %d, got %d error %v", len(b), got, err)
}
if n, err := sf.Read(buf); n != 0 || err != io.EOF {
@@ -668,11 +668,11 @@ func TestCompressedSection(t *testing.T) {
target := rand.Int63n(int64(len(buf)))
var offset int64
switch whence {
- case 0:
+ case io.SeekStart:
offset = target
- case 1:
+ case io.SeekCurrent:
offset = target - pos
- case 2:
+ case io.SeekEnd:
offset = target - int64(len(buf))
}
pos, err = sf.Seek(offset, whence)
diff --git a/src/debug/elf/reader.go b/src/debug/elf/reader.go
index 4dac6d1b2973c5..eab437318d6d3e 100644
--- a/src/debug/elf/reader.go
+++ b/src/debug/elf/reader.go
@@ -63,11 +63,11 @@ func (r *readSeekerFromReader) Read(p []byte) (n int, err error) {
func (r *readSeekerFromReader) Seek(offset int64, whence int) (int64, error) {
var newOffset int64
switch whence {
- case 0:
+ case io.SeekStart:
newOffset = offset
- case 1:
+ case io.SeekCurrent:
newOffset = r.offset + offset
- case 2:
+ case io.SeekEnd:
newOffset = r.size + offset
default:
return 0, os.ErrInvalid
diff --git a/src/go/internal/gccgoimporter/importer.go b/src/go/internal/gccgoimporter/importer.go
index aa0d01afdf3826..65cc2df6860515 100644
--- a/src/go/internal/gccgoimporter/importer.go
+++ b/src/go/internal/gccgoimporter/importer.go
@@ -90,7 +90,7 @@ func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err e
}
// reset to offset 0 - needed on Plan 9 (see issue #11265)
// TODO: remove once issue #11265 has been resolved.
- _, err = f.Seek(0, 0)
+ _, err = f.Seek(0, io.SeekStart)
if err != nil {
return
}
@@ -168,7 +168,7 @@ func GetImporter(searchpaths []string, initmap map[*types.Package]InitData) Impo
if err != nil {
return
}
- _, err = reader.Seek(0, 0)
+ _, err = reader.Seek(0, io.SeekStart)
if err != nil {
return
}
diff --git a/src/io/example_test.go b/src/io/example_test.go
index 412dfb3b921ba4..bf16de8fe2357d 100644
--- a/src/io/example_test.go
+++ b/src/io/example_test.go
@@ -189,7 +189,7 @@ func ExampleSectionReader_Seek() {
r := strings.NewReader("some io.Reader stream to be read\n")
s := io.NewSectionReader(r, 5, 16)
- if _, err := s.Seek(10, 0); err != nil {
+ if _, err := s.Seek(10, io.SeekStart); err != nil {
log.Fatal(err)
}
diff --git a/src/io/io.go b/src/io/io.go
index c36ec2afbb0915..3d0a5a485e69b7 100644
--- a/src/io/io.go
+++ b/src/io/io.go
@@ -480,11 +480,11 @@ func (s *SectionReader) Seek(offset int64, whence int) (int64, error) {
switch whence {
default:
return 0, errWhence
- case 0:
+ case SeekStart:
offset += s.base
- case 1:
+ case SeekCurrent:
offset += s.off
- case 2:
+ case SeekEnd:
offset += s.limit
}
if offset < s.base {
diff --git a/src/io/io_test.go b/src/io/io_test.go
index e892574b0b5f2e..877e8392e279a0 100644
--- a/src/io/io_test.go
+++ b/src/io/io_test.go
@@ -347,7 +347,7 @@ func TestSectionReader_Seek(t *testing.T) {
br := bytes.NewReader([]byte("foo"))
sr := NewSectionReader(br, 0, int64(len("foo")))
- for whence := 0; whence <= 2; whence++ {
+ for _, whence := range []int{SeekStart, SeekCurrent, SeekEnd} {
for offset := int64(-3); offset <= 4; offset++ {
brOff, brErr := br.Seek(offset, whence)
srOff, srErr := sr.Seek(offset, whence)
@@ -359,7 +359,7 @@ func TestSectionReader_Seek(t *testing.T) {
}
// And verify we can just seek past the end and get an EOF
- got, err := sr.Seek(100, 0)
+ got, err := sr.Seek(100, SeekStart)
if err != nil || got != 100 {
t.Errorf("Seek = %v, %v; want 100, nil", got, err)
}
diff --git a/src/net/file_plan9.go b/src/net/file_plan9.go
index 892775a024f456..24efdc5186d89f 100644
--- a/src/net/file_plan9.go
+++ b/src/net/file_plan9.go
@@ -60,7 +60,7 @@ func newFileFD(f *os.File) (net *netFD, err error) {
dir := netdir + "/" + comp[n-2]
ctl = os.NewFile(uintptr(fd), dir+"/"+file)
- ctl.Seek(0, 0)
+ ctl.Seek(0, io.SeekStart)
var buf [16]byte
n, err := ctl.Read(buf[:])
if err != nil {
diff --git a/src/net/http/internal/chunked_test.go b/src/net/http/internal/chunked_test.go
index a136dc99a65fc8..9abe1ab6d9d674 100644
--- a/src/net/http/internal/chunked_test.go
+++ b/src/net/http/internal/chunked_test.go
@@ -122,7 +122,7 @@ func TestChunkReaderAllocs(t *testing.T) {
byter := bytes.NewReader(buf.Bytes())
bufr := bufio.NewReader(byter)
mallocs := testing.AllocsPerRun(100, func() {
- byter.Seek(0, 0)
+ byter.Seek(0, io.SeekStart)
bufr.Reset(byter)
r := NewChunkedReader(bufr)
n, err := io.ReadFull(r, readBuf)
diff --git a/src/net/lookup_plan9.go b/src/net/lookup_plan9.go
index 73147a2d3f7c40..3f7af2a1747c32 100644
--- a/src/net/lookup_plan9.go
+++ b/src/net/lookup_plan9.go
@@ -7,6 +7,7 @@ package net
import (
"context"
"errors"
+ "io"
"os"
)
@@ -17,7 +18,7 @@ func query(ctx context.Context, filename, query string, bufSize int) (res []stri
}
defer file.Close()
- _, err = file.Seek(0, 0)
+ _, err = file.Seek(0, io.SeekStart)
if err != nil {
return
}
@@ -25,7 +26,7 @@ func query(ctx context.Context, filename, query string, bufSize int) (res []stri
if err != nil {
return
}
- _, err = file.Seek(0, 0)
+ _, err = file.Seek(0, io.SeekStart)
if err != nil {
return
}
diff --git a/src/os/file_plan9.go b/src/os/file_plan9.go
index 0fe1b8213dc54b..fb796a2a89bcba 100644
--- a/src/os/file_plan9.go
+++ b/src/os/file_plan9.go
@@ -5,6 +5,7 @@
package os
import (
+ "io"
"runtime"
"syscall"
"time"
@@ -123,7 +124,7 @@ func OpenFile(name string, flag int, perm FileMode) (*File, error) {
}
if append {
- if _, e = syscall.Seek(fd, 0, SEEK_END); e != nil {
+ if _, e = syscall.Seek(fd, 0, io.SeekEnd); e != nil {
return nil, &PathError{"seek", name, e}
}
}
diff --git a/src/os/file_windows.go b/src/os/file_windows.go
index 137f24a0a95979..08aff83a77510c 100644
--- a/src/os/file_windows.go
+++ b/src/os/file_windows.go
@@ -325,11 +325,11 @@ func (f *File) read(b []byte) (n int, err error) {
func (f *File) pread(b []byte, off int64) (n int, err error) {
f.l.Lock()
defer f.l.Unlock()
- curoffset, e := syscall.Seek(f.fd, 0, 1)
+ curoffset, e := syscall.Seek(f.fd, 0, io.SeekCurrent)
if e != nil {
return 0, e
}
- defer syscall.Seek(f.fd, curoffset, 0)
+ defer syscall.Seek(f.fd, curoffset, io.SeekStart)
o := syscall.Overlapped{
OffsetHigh: uint32(off >> 32),
Offset: uint32(off),
@@ -405,11 +405,11 @@ func (f *File) write(b []byte) (n int, err error) {
func (f *File) pwrite(b []byte, off int64) (n int, err error) {
f.l.Lock()
defer f.l.Unlock()
- curoffset, e := syscall.Seek(f.fd, 0, 1)
+ curoffset, e := syscall.Seek(f.fd, 0, io.SeekCurrent)
if e != nil {
return 0, e
}
- defer syscall.Seek(f.fd, curoffset, 0)
+ defer syscall.Seek(f.fd, curoffset, io.SeekStart)
o := syscall.Overlapped{
OffsetHigh: uint32(off >> 32),
Offset: uint32(off),
diff --git a/src/os/os_test.go b/src/os/os_test.go
index 8f62902a6caaf8..de25f26614d452 100644
--- a/src/os/os_test.go
+++ b/src/os/os_test.go
@@ -1182,14 +1182,14 @@ func TestSeek(t *testing.T) {
out int64
}
var tests = []test{
- {0, 1, int64(len(data))},
- {0, 0, 0},
- {5, 0, 5},
- {0, 2, int64(len(data))},
- {0, 0, 0},
- {-1, 2, int64(len(data)) - 1},
- {1 << 33, 0, 1 << 33},
- {1 << 33, 2, 1<<33 + int64(len(data))},
+ {0, io.SeekCurrent, int64(len(data))},
+ {0, io.SeekStart, 0},
+ {5, io.SeekStart, 5},
+ {0, io.SeekEnd, int64(len(data))},
+ {0, io.SeekStart, 0},
+ {-1, io.SeekEnd, int64(len(data)) - 1},
+ {1 << 33, io.SeekStart, 1 << 33},
+ {1 << 33, io.SeekEnd, 1<<33 + int64(len(data))},
}
for i, tt := range tests {
off, err := f.Seek(tt.in, tt.whence)
@@ -1726,7 +1726,7 @@ var nilFileMethodTests = []struct {
{"ReadAt", func(f *File) error { _, err := f.ReadAt(make([]byte, 0), 0); return err }},
{"Readdir", func(f *File) error { _, err := f.Readdir(1); return err }},
{"Readdirnames", func(f *File) error { _, err := f.Readdirnames(1); return err }},
- {"Seek", func(f *File) error { _, err := f.Seek(0, 0); return err }},
+ {"Seek", func(f *File) error { _, err := f.Seek(0, io.SeekStart); return err }},
{"Stat", func(f *File) error { _, err := f.Stat(); return err }},
{"Sync", func(f *File) error { return f.Sync() }},
{"Truncate", func(f *File) error { return f.Truncate(0) }},
diff --git a/src/runtime/runtime-lldb_test.go b/src/runtime/runtime-lldb_test.go
index 2bd91c1ec03893..4c379b9cdc28b7 100644
--- a/src/runtime/runtime-lldb_test.go
+++ b/src/runtime/runtime-lldb_test.go
@@ -232,7 +232,7 @@ func verifyAranges(t *testing.T, byteorder binary.ByteOrder, data io.ReadSeeker)
SegmentSize uint8
}
for {
- offset, err := data.Seek(0, 1)
+ offset, err := data.Seek(0, io.SeekCurrent)
if err != nil {
t.Fatalf("Seek error: %v", err)
}
@@ -246,7 +246,7 @@ func verifyAranges(t *testing.T, byteorder binary.ByteOrder, data io.ReadSeeker)
if lastTupleOffset%tupleSize != 0 {
t.Fatalf("Invalid arange length %d, (addr %d, seg %d)", header.UnitLength, header.AddressSize, header.SegmentSize)
}
- if _, err = data.Seek(lastTupleOffset, 0); err != nil {
+ if _, err = data.Seek(lastTupleOffset, io.SeekStart); err != nil {
t.Fatalf("Seek error: %v", err)
}
buf := make([]byte, tupleSize)
diff --git a/src/strings/reader.go b/src/strings/reader.go
index e254837c63b96a..6c1a5064c0d5ef 100644
--- a/src/strings/reader.go
+++ b/src/strings/reader.go
@@ -107,11 +107,11 @@ func (r *Reader) Seek(offset int64, whence int) (int64, error) {
r.prevRune = -1
var abs int64
switch whence {
- case 0:
+ case io.SeekStart:
abs = offset
- case 1:
+ case io.SeekCurrent:
abs = r.i + offset
- case 2:
+ case io.SeekEnd:
abs = int64(len(r.s)) + offset
default:
return 0, errors.New("strings.Reader.Seek: invalid whence")
diff --git a/src/strings/strings_test.go b/src/strings/strings_test.go
index 1ed803bf8502e7..d92dfcc8742b27 100644
--- a/src/strings/strings_test.go
+++ b/src/strings/strings_test.go
@@ -952,7 +952,7 @@ var UnreadRuneErrorTests = []struct {
{"Read", func(r *Reader) { r.Read([]byte{0}) }},
{"ReadByte", func(r *Reader) { r.ReadByte() }},
{"UnreadRune", func(r *Reader) { r.UnreadRune() }},
- {"Seek", func(r *Reader) { r.Seek(0, 1) }},
+ {"Seek", func(r *Reader) { r.Seek(0, io.SeekCurrent) }},
{"WriteTo", func(r *Reader) { r.WriteTo(&bytes.Buffer{}) }},
}
diff --git a/src/syscall/fd_nacl.go b/src/syscall/fd_nacl.go
index 715992b1bfc684..e559793c8b80e7 100644
--- a/src/syscall/fd_nacl.go
+++ b/src/syscall/fd_nacl.go
@@ -10,6 +10,7 @@
package syscall
import (
+ "io"
"sync"
)
@@ -252,15 +253,15 @@ func (f *naclFile) seek(off int64, whence int) (int64, error) {
func (f *naclFile) prw(b []byte, offset int64, rw func([]byte) (int, error)) (int, error) {
// NaCl has no pread; simulate with seek and hope for no races.
- old, err := f.seek(0, 1)
+ old, err := f.seek(0, io.SeekCurrent)
if err != nil {
return 0, err
}
- if _, err := f.seek(offset, 0); err != nil {
+ if _, err := f.seek(offset, io.SeekStart); err != nil {
return 0, err
}
n, err := rw(b)
- f.seek(old, 0)
+ f.seek(old, io.SeekStart)
return n, err
}
diff --git a/src/syscall/fs_nacl.go b/src/syscall/fs_nacl.go
index 4019fad1a5d1e6..cbd9539c92cab3 100644
--- a/src/syscall/fs_nacl.go
+++ b/src/syscall/fs_nacl.go
@@ -15,6 +15,7 @@
package syscall
import (
+ "io"
"sync"
"unsafe"
)
@@ -367,9 +368,9 @@ func (f *fsysFile) seek(offset int64, whence int) (int64, error) {
f.fsys.mu.Lock()
defer f.fsys.mu.Unlock()
switch whence {
- case 1:
+ case io.SeekCurrent:
offset += f.offset
- case 2:
+ case io.SeekEnd:
offset += f.inode.Size
}
if offset < 0 {
diff --git a/src/syscall/syscall_unix_test.go b/src/syscall/syscall_unix_test.go
index c7b4560b76bc5e..80544f331923d6 100644
--- a/src/syscall/syscall_unix_test.go
+++ b/src/syscall/syscall_unix_test.go
@@ -10,6 +10,7 @@ import (
"flag"
"fmt"
"internal/testenv"
+ "io"
"io/ioutil"
"net"
"os"
@@ -244,7 +245,7 @@ func passFDChild() {
}
f.Write([]byte("Hello from child process!\n"))
- f.Seek(0, 0)
+ f.Seek(0, io.SeekStart)
rights := syscall.UnixRights(int(f.Fd()))
dummyByte := []byte("x")
@@ -344,7 +345,7 @@ func TestRlimit(t *testing.T) {
}
func TestSeekFailure(t *testing.T) {
- _, err := syscall.Seek(-1, 0, 0)
+ _, err := syscall.Seek(-1, 0, io.SeekStart)
if err == nil {
t.Fatalf("Seek(-1, 0, 0) did not fail")
}
diff --git a/src/time/sys_plan9.go b/src/time/sys_plan9.go
index 8484729448eb96..507d1159cfe9d5 100644
--- a/src/time/sys_plan9.go
+++ b/src/time/sys_plan9.go
@@ -8,6 +8,7 @@ package time
import (
"errors"
+ "io"
"syscall"
)
@@ -55,9 +56,9 @@ func closefd(fd uintptr) {
}
func preadn(fd uintptr, buf []byte, off int) error {
- whence := 0
+ whence := io.SeekStart
if off < 0 {
- whence = 2
+ whence = io.SeekEnd
}
if _, err := syscall.Seek(int(fd), int64(off), whence); err != nil {
return err
diff --git a/src/time/sys_unix.go b/src/time/sys_unix.go
index e592415daa5161..dea03e06d51cf9 100644
--- a/src/time/sys_unix.go
+++ b/src/time/sys_unix.go
@@ -8,6 +8,7 @@ package time
import (
"errors"
+ "io"
"syscall"
)
@@ -55,9 +56,9 @@ func closefd(fd uintptr) {
}
func preadn(fd uintptr, buf []byte, off int) error {
- whence := 0
+ whence := io.SeekStart
if off < 0 {
- whence = 2
+ whence = io.SeekEnd
}
if _, err := syscall.Seek(int(fd), int64(off), whence); err != nil {
return err
diff --git a/src/time/sys_windows.go b/src/time/sys_windows.go
index de63b4bf4bb87b..4f41b1a7a3c64d 100644
--- a/src/time/sys_windows.go
+++ b/src/time/sys_windows.go
@@ -6,6 +6,7 @@ package time
import (
"errors"
+ "io"
"syscall"
)
@@ -52,9 +53,9 @@ func closefd(fd uintptr) {
}
func preadn(fd uintptr, buf []byte, off int) error {
- whence := 0
+ whence := io.SeekStart
if off < 0 {
- whence = 2
+ whence = io.SeekEnd
}
if _, err := syscall.Seek(syscall.Handle(fd), int64(off), whence); err != nil {
return err
From a633d766d1763f4f4648e423c4e8a8635b183d03 Mon Sep 17 00:00:00 2001
From: Mikio Hara
Date: Fri, 6 May 2016 08:51:16 +0900
Subject: [PATCH 006/267] Revert "net: add support for Zone of IPNet"
Updates #14518.
This reverts commit 3e9264c9ae781a2cd28127deaed6ae26f84b4b15.
Change-Id: I2531b04efc735b5b51ef675541172f2f5ae747d9
Reviewed-on: https://go-review.googlesource.com/22836
Reviewed-by: Mikio Hara
Run-TryBot: Mikio Hara
TryBot-Result: Gobot Gobot
Reviewed-by: Brad Fitzpatrick
---
src/net/interface_bsd.go | 1 -
src/net/interface_linux.go | 3 ---
src/net/interface_test.go | 6 +-----
src/net/interface_windows.go | 3 ---
src/net/ip.go | 14 ++++----------
src/net/ip_test.go | 8 --------
6 files changed, 5 insertions(+), 30 deletions(-)
diff --git a/src/net/interface_bsd.go b/src/net/interface_bsd.go
index 98d19f2d33d42f..17c6dd3dcd69df 100644
--- a/src/net/interface_bsd.go
+++ b/src/net/interface_bsd.go
@@ -166,7 +166,6 @@ func newAddr(ifi *Interface, m *syscall.InterfaceAddrMessage) (*IPNet, error) {
// link-local address as the kernel-internal form.
if ifa.IP.IsLinkLocalUnicast() {
ifa.IP[2], ifa.IP[3] = 0, 0
- ifa.Zone = ifi.Name
}
}
if ifa.IP == nil || ifa.Mask == nil {
diff --git a/src/net/interface_linux.go b/src/net/interface_linux.go
index b8f57fd7db39f0..5e391b28b0f8c4 100644
--- a/src/net/interface_linux.go
+++ b/src/net/interface_linux.go
@@ -193,9 +193,6 @@ func newAddr(ifi *Interface, ifam *syscall.IfAddrmsg, attrs []syscall.NetlinkRou
case syscall.AF_INET6:
ifa := &IPNet{IP: make(IP, IPv6len), Mask: CIDRMask(int(ifam.Prefixlen), 8*IPv6len)}
copy(ifa.IP, a.Value[:])
- if ifa.IP.IsLinkLocalUnicast() {
- ifa.Zone = ifi.Name
- }
return ifa
}
}
diff --git a/src/net/interface_test.go b/src/net/interface_test.go
index c3e1ee231ffce9..e1580134937de0 100644
--- a/src/net/interface_test.go
+++ b/src/net/interface_test.go
@@ -221,10 +221,6 @@ func testAddrs(t *testing.T, ifat []Addr) (naf4, naf6 int) {
t.Errorf("unexpected prefix length for IPv6 loopback: %d/%d", prefixLen, maxPrefixLen)
continue
}
- if ifa.IP.IsLinkLocalUnicast() && ifa.Zone == "" {
- t.Errorf("no IPv6 zone identifier found: %#v", ifa)
- continue
- }
naf6++
}
t.Logf("interface address %q", ifa.String())
@@ -243,7 +239,7 @@ func testAddrs(t *testing.T, ifat []Addr) (naf4, naf6 int) {
if ifa.IP.To16() != nil && ifa.IP.To4() == nil {
naf6++
}
- t.Logf("interface address %q", ifa.String())
+ t.Logf("interface address %s", ifa.String())
default:
t.Errorf("unexpected type: %T", ifa)
}
diff --git a/src/net/interface_windows.go b/src/net/interface_windows.go
index 69de095e667d8c..8b976e585f36aa 100644
--- a/src/net/interface_windows.go
+++ b/src/net/interface_windows.go
@@ -159,9 +159,6 @@ func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
}
ifa := &IPNet{IP: make(IP, IPv6len), Mask: CIDRMask(l, 8*IPv6len)}
copy(ifa.IP, sa.Addr[:])
- if ifa.IP.IsLinkLocalUnicast() {
- ifa.Zone = syscall.UTF16ToString((*(*[10000]uint16)(unsafe.Pointer(aa.FriendlyName)))[:])
- }
ifat = append(ifat, ifa)
}
}
diff --git a/src/net/ip.go b/src/net/ip.go
index e8b0fd990bf896..a2361bbdbfc132 100644
--- a/src/net/ip.go
+++ b/src/net/ip.go
@@ -36,7 +36,6 @@ type IPMask []byte
type IPNet struct {
IP IP // network number
Mask IPMask // network mask
- Zone string // IPv6 scoped addressing zone
}
// IPv4 returns the IP address (in 16-byte form) of the
@@ -495,15 +494,11 @@ func (n *IPNet) String() string {
if nn == nil || m == nil {
return ""
}
- ip := nn.String()
- if n.Zone != "" {
- ip = ip + "%" + n.Zone
- }
l := simpleMaskLength(m)
if l == -1 {
- return ip + "/" + m.String()
+ return nn.String() + "/" + m.String()
}
- return ip + "/" + uitoa(uint(l))
+ return nn.String() + "/" + uitoa(uint(l))
}
// Parse IPv4 address (d.d.d.d).
@@ -675,18 +670,17 @@ func ParseCIDR(s string) (IP, *IPNet, error) {
if i < 0 {
return nil, nil, &ParseError{Type: "CIDR address", Text: s}
}
- var zone string
addr, mask := s[:i], s[i+1:]
iplen := IPv4len
ip := parseIPv4(addr)
if ip == nil {
iplen = IPv6len
- ip, zone = parseIPv6(addr, true)
+ ip, _ = parseIPv6(addr, false)
}
n, i, ok := dtoi(mask, 0)
if ip == nil || !ok || i != len(mask) || n < 0 || n > 8*iplen {
return nil, nil, &ParseError{Type: "CIDR address", Text: s}
}
m := CIDRMask(n, 8*iplen)
- return ip, &IPNet{IP: ip.Mask(m), Mask: m, Zone: zone}, nil
+ return ip, &IPNet{IP: ip.Mask(m), Mask: m}, nil
}
diff --git a/src/net/ip_test.go b/src/net/ip_test.go
index 1d67057d6afbbc..87c12133c33567 100644
--- a/src/net/ip_test.go
+++ b/src/net/ip_test.go
@@ -327,9 +327,6 @@ var parseCIDRTests = []struct {
{"abcd:2345::/24", ParseIP("abcd:2345::"), &IPNet{IP: ParseIP("abcd:2300::"), Mask: IPMask(ParseIP("ffff:ff00::"))}, nil},
{"2001:DB8::/48", ParseIP("2001:DB8::"), &IPNet{IP: ParseIP("2001:DB8::"), Mask: IPMask(ParseIP("ffff:ffff:ffff::"))}, nil},
{"2001:DB8::1/48", ParseIP("2001:DB8::1"), &IPNet{IP: ParseIP("2001:DB8::"), Mask: IPMask(ParseIP("ffff:ffff:ffff::"))}, nil},
- {"fe80::%en0/64", ParseIP("fe80::"), &IPNet{IP: ParseIP("fe80::"), Mask: CIDRMask(64, 128), Zone: "en0"}, nil},
- {"fe80::1%en0/64", ParseIP("fe80::1"), &IPNet{IP: ParseIP("fe80::"), Mask: CIDRMask(64, 128), Zone: "en0"}, nil},
-
{"192.168.1.1/255.255.255.0", nil, nil, &ParseError{Type: "CIDR address", Text: "192.168.1.1/255.255.255.0"}},
{"192.168.1.1/35", nil, nil, &ParseError{Type: "CIDR address", Text: "192.168.1.1/35"}},
{"2001:db8::1/-1", nil, nil, &ParseError{Type: "CIDR address", Text: "2001:db8::1/-1"}},
@@ -376,13 +373,8 @@ var ipNetStringTests = []struct {
out string
}{
{&IPNet{IP: IPv4(192, 168, 1, 0), Mask: CIDRMask(26, 32)}, "192.168.1.0/26"},
- {&IPNet{IP: IPv4(192, 168, 1, 1), Mask: CIDRMask(26, 32)}, "192.168.1.1/26"},
{&IPNet{IP: IPv4(192, 168, 1, 0), Mask: IPv4Mask(255, 0, 255, 0)}, "192.168.1.0/ff00ff00"},
- {&IPNet{IP: ParseIP("fe80::"), Mask: CIDRMask(64, 128), Zone: "en0"}, "fe80::%en0/64"},
- {&IPNet{IP: ParseIP("fe80::1"), Mask: CIDRMask(64, 128), Zone: "en0"}, "fe80::1%en0/64"},
- {&IPNet{IP: ParseIP("fe80::"), Mask: IPMask(ParseIP("8000:f123:0:cafe::")), Zone: "en0"}, "fe80::%en0/8000f1230000cafe0000000000000000"},
{&IPNet{IP: ParseIP("2001:db8::"), Mask: CIDRMask(55, 128)}, "2001:db8::/55"},
- {&IPNet{IP: ParseIP("2001:db8::1"), Mask: CIDRMask(55, 128)}, "2001:db8::1/55"},
{&IPNet{IP: ParseIP("2001:db8::"), Mask: IPMask(ParseIP("8000:f123:0:cafe::"))}, "2001:db8::/8000f1230000cafe0000000000000000"},
}
From 88d3db0a5b5196ed45c96014d5a2d32e4e41e34e Mon Sep 17 00:00:00 2001
From: Russ Cox
Date: Wed, 6 Jan 2016 12:45:23 -0500
Subject: [PATCH 007/267] runtime: stop traceback at foreign function
This can only happen when profiling and there is foreign code
at the top of the g0 stack but we're not in cgo.
That in turn only happens with the race detector.
Fixes #13568.
Change-Id: I23775132c9c1a3a3aaae191b318539f368adf25e
Reviewed-on: https://go-review.googlesource.com/18322
Reviewed-by: Ian Lance Taylor
Run-TryBot: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
---
src/runtime/traceback.go | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go
index 7771426ef95e97..0e96a28945351b 100644
--- a/src/runtime/traceback.go
+++ b/src/runtime/traceback.go
@@ -241,6 +241,11 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
// stk is the stack containing sp.
// The caller's program counter is lr, unless lr is zero, in which case it is *(uintptr*)sp.
f = frame.fn
+ if f.pcsp == 0 {
+ // No frame information, must be external function, like race support.
+ // See golang.org/issue/13568.
+ break
+ }
// Found an actual function.
// Derive frame pointer and link register.
From 30bfafc319288e8cfe54111664e3f2f259998a0a Mon Sep 17 00:00:00 2001
From: Joe Tsai
Date: Thu, 17 Sep 2015 00:22:56 -0700
Subject: [PATCH 008/267] archive/tar: centralize all information about tar
header format
The Reader and Writer have hard-coded constants regarding the
offsets and lengths of certain fields in the tar format sprinkled
all over. This makes it harder to verify that the offsets are
correct since a reviewer would need to search for them throughout
the code. Instead, all information about the layout of header
fields should be centralized in one single file. This has the
advantage of being both centralized, and also acting as a form
of documentation about the header struct format.
This method was chosen over using "encoding/binary" since that
method would cause an allocation of a header struct every time
binary.Read was called. This method causes zero allocations and
its logic is no longer than if structs were declared.
Updates #12594
Change-Id: Ic7a0565d2a2cd95d955547ace3b6dea2b57fab34
Reviewed-on: https://go-review.googlesource.com/14669
Reviewed-by: Brad Fitzpatrick
---
src/archive/tar/common.go | 37 +------
src/archive/tar/format.go | 197 +++++++++++++++++++++++++++++++++
src/archive/tar/reader.go | 167 +++++++++++-----------------
src/archive/tar/writer.go | 100 +++++++----------
src/archive/tar/writer_test.go | 22 ++--
5 files changed, 314 insertions(+), 209 deletions(-)
create mode 100644 src/archive/tar/format.go
diff --git a/src/archive/tar/common.go b/src/archive/tar/common.go
index 36f4e23980930c..2a1e4321826195 100644
--- a/src/archive/tar/common.go
+++ b/src/archive/tar/common.go
@@ -21,10 +21,8 @@ import (
"time"
)
+// Header type flags.
const (
- blockSize = 512
-
- // Types
TypeReg = '0' // regular file
TypeRegA = '\x00' // regular file
TypeLink = '1' // hard link
@@ -61,12 +59,6 @@ type Header struct {
Xattrs map[string]string
}
-// File name constants from the tar spec.
-const (
- fileNameSize = 100 // Maximum number of bytes in a standard tar name.
- fileNamePrefixSize = 155 // Maximum number of ustar extension bytes.
-)
-
// FileInfo returns an os.FileInfo for the Header.
func (h *Header) FileInfo() os.FileInfo {
return headerFileInfo{h}
@@ -279,33 +271,6 @@ func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) {
return h, nil
}
-var zeroBlock = make([]byte, blockSize)
-
-// POSIX specifies a sum of the unsigned byte values, but the Sun tar uses signed byte values.
-// We compute and return both.
-func checksum(header []byte) (unsigned int64, signed int64) {
- for i := 0; i < len(header); i++ {
- if i == 148 {
- // The chksum field (header[148:156]) is special: it should be treated as space bytes.
- unsigned += ' ' * 8
- signed += ' ' * 8
- i += 7
- continue
- }
- unsigned += int64(header[i])
- signed += int64(int8(header[i]))
- }
- return
-}
-
-type slicer []byte
-
-func (sp *slicer) next(n int) (b []byte) {
- s := *sp
- b, *sp = s[0:n], s[n:]
- return
-}
-
func isASCII(s string) bool {
for _, c := range s {
if c >= 0x80 {
diff --git a/src/archive/tar/format.go b/src/archive/tar/format.go
new file mode 100644
index 00000000000000..c2c9910d00281f
--- /dev/null
+++ b/src/archive/tar/format.go
@@ -0,0 +1,197 @@
+// Copyright 2016 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 tar
+
+// Constants to identify various tar formats.
+const (
+ // The format is unknown.
+ formatUnknown = (1 << iota) / 2 // Sequence of 0, 1, 2, 4, 8, etc...
+
+ // The format of the original Unix V7 tar tool prior to standardization.
+ formatV7
+
+ // The old and new GNU formats, which are incompatible with USTAR.
+ // This does cover the old GNU sparse extension.
+ // This does not cover the GNU sparse extensions using PAX headers,
+ // versions 0.0, 0.1, and 1.0; these fall under the PAX format.
+ formatGNU
+
+ // Schily's tar format, which is incompatible with USTAR.
+ // This does not cover STAR extensions to the PAX format; these fall under
+ // the PAX format.
+ formatSTAR
+
+ // USTAR is the former standardization of tar defined in POSIX.1-1988.
+ // This is incompatible with the GNU and STAR formats.
+ formatUSTAR
+
+ // PAX is the latest standardization of tar defined in POSIX.1-2001.
+ // This is an extension of USTAR and is "backwards compatible" with it.
+ //
+ // Some newer formats add their own extensions to PAX, such as GNU sparse
+ // files and SCHILY extended attributes. Since they are backwards compatible
+ // with PAX, they will be labelled as "PAX".
+ formatPAX
+)
+
+// Magics used to identify various formats.
+const (
+ magicGNU, versionGNU = "ustar ", " \x00"
+ magicUSTAR, versionUSTAR = "ustar\x00", "00"
+ trailerSTAR = "tar\x00"
+)
+
+// Size constants from various tar specifications.
+const (
+ blockSize = 512 // Size of each block in a tar stream
+ nameSize = 100 // Max length of the name field in USTAR format
+ prefixSize = 155 // Max length of the prefix field in USTAR format
+)
+
+var zeroBlock block
+
+type block [blockSize]byte
+
+// Convert block to any number of formats.
+func (b *block) V7() *headerV7 { return (*headerV7)(b) }
+func (b *block) GNU() *headerGNU { return (*headerGNU)(b) }
+func (b *block) STAR() *headerSTAR { return (*headerSTAR)(b) }
+func (b *block) USTAR() *headerUSTAR { return (*headerUSTAR)(b) }
+func (b *block) Sparse() sparseArray { return (sparseArray)(b[:]) }
+
+// GetFormat checks that the block is a valid tar header based on the checksum.
+// It then attempts to guess the specific format based on magic values.
+// If the checksum fails, then formatUnknown is returned.
+func (b *block) GetFormat() (format int) {
+ // Verify checksum.
+ var p parser
+ value := p.parseOctal(b.V7().Chksum())
+ chksum1, chksum2 := b.ComputeChecksum()
+ if p.err != nil || (value != chksum1 && value != chksum2) {
+ return formatUnknown
+ }
+
+ // Guess the magic values.
+ magic := string(b.USTAR().Magic())
+ version := string(b.USTAR().Version())
+ trailer := string(b.STAR().Trailer())
+ switch {
+ case magic == magicUSTAR && trailer == trailerSTAR:
+ return formatSTAR
+ case magic == magicUSTAR:
+ return formatUSTAR
+ case magic == magicGNU && version == versionGNU:
+ return formatGNU
+ default:
+ return formatV7
+ }
+}
+
+// SetFormat writes the magic values necessary for specified format
+// and then updates the checksum accordingly.
+func (b *block) SetFormat(format int) {
+ // Set the magic values.
+ switch format {
+ case formatV7:
+ // Do nothing.
+ case formatGNU:
+ copy(b.GNU().Magic(), magicGNU)
+ copy(b.GNU().Version(), versionGNU)
+ case formatSTAR:
+ copy(b.STAR().Magic(), magicUSTAR)
+ copy(b.STAR().Version(), versionUSTAR)
+ copy(b.STAR().Trailer(), trailerSTAR)
+ case formatUSTAR, formatPAX:
+ copy(b.USTAR().Magic(), magicUSTAR)
+ copy(b.USTAR().Version(), versionUSTAR)
+ default:
+ panic("invalid format")
+ }
+
+ // Update checksum.
+ // This field is special in that it is terminated by a NULL then space.
+ var f formatter
+ field := b.V7().Chksum()
+ chksum, _ := b.ComputeChecksum() // Possible values are 256..128776
+ f.formatOctal(field[:7], chksum) // Never fails since 128776 < 262143
+ field[7] = ' '
+}
+
+// ComputeChecksum computes the checksum for the header block.
+// POSIX specifies a sum of the unsigned byte values, but the Sun tar used
+// signed byte values.
+// We compute and return both.
+func (b *block) ComputeChecksum() (unsigned, signed int64) {
+ for i, c := range b {
+ if 148 <= i && i < 156 {
+ c = ' ' // Treat the checksum field itself as all spaces.
+ }
+ unsigned += int64(uint8(c))
+ signed += int64(int8(c))
+ }
+ return unsigned, signed
+}
+
+type headerV7 [blockSize]byte
+
+func (h *headerV7) Name() []byte { return h[000:][:100] }
+func (h *headerV7) Mode() []byte { return h[100:][:8] }
+func (h *headerV7) UID() []byte { return h[108:][:8] }
+func (h *headerV7) GID() []byte { return h[116:][:8] }
+func (h *headerV7) Size() []byte { return h[124:][:12] }
+func (h *headerV7) ModTime() []byte { return h[136:][:12] }
+func (h *headerV7) Chksum() []byte { return h[148:][:8] }
+func (h *headerV7) TypeFlag() []byte { return h[156:][:1] }
+func (h *headerV7) LinkName() []byte { return h[157:][:100] }
+
+type headerGNU [blockSize]byte
+
+func (h *headerGNU) V7() *headerV7 { return (*headerV7)(h) }
+func (h *headerGNU) Magic() []byte { return h[257:][:6] }
+func (h *headerGNU) Version() []byte { return h[263:][:2] }
+func (h *headerGNU) UserName() []byte { return h[265:][:32] }
+func (h *headerGNU) GroupName() []byte { return h[297:][:32] }
+func (h *headerGNU) DevMajor() []byte { return h[329:][:8] }
+func (h *headerGNU) DevMinor() []byte { return h[337:][:8] }
+func (h *headerGNU) AccessTime() []byte { return h[345:][:12] }
+func (h *headerGNU) ChangeTime() []byte { return h[357:][:12] }
+func (h *headerGNU) Sparse() sparseArray { return (sparseArray)(h[386:][:24*4+1]) }
+func (h *headerGNU) RealSize() []byte { return h[483:][:12] }
+
+type headerSTAR [blockSize]byte
+
+func (h *headerSTAR) V7() *headerV7 { return (*headerV7)(h) }
+func (h *headerSTAR) Magic() []byte { return h[257:][:6] }
+func (h *headerSTAR) Version() []byte { return h[263:][:2] }
+func (h *headerSTAR) UserName() []byte { return h[265:][:32] }
+func (h *headerSTAR) GroupName() []byte { return h[297:][:32] }
+func (h *headerSTAR) DevMajor() []byte { return h[329:][:8] }
+func (h *headerSTAR) DevMinor() []byte { return h[337:][:8] }
+func (h *headerSTAR) Prefix() []byte { return h[345:][:131] }
+func (h *headerSTAR) AccessTime() []byte { return h[476:][:12] }
+func (h *headerSTAR) ChangeTime() []byte { return h[488:][:12] }
+func (h *headerSTAR) Trailer() []byte { return h[508:][:4] }
+
+type headerUSTAR [blockSize]byte
+
+func (h *headerUSTAR) V7() *headerV7 { return (*headerV7)(h) }
+func (h *headerUSTAR) Magic() []byte { return h[257:][:6] }
+func (h *headerUSTAR) Version() []byte { return h[263:][:2] }
+func (h *headerUSTAR) UserName() []byte { return h[265:][:32] }
+func (h *headerUSTAR) GroupName() []byte { return h[297:][:32] }
+func (h *headerUSTAR) DevMajor() []byte { return h[329:][:8] }
+func (h *headerUSTAR) DevMinor() []byte { return h[337:][:8] }
+func (h *headerUSTAR) Prefix() []byte { return h[345:][:155] }
+
+type sparseArray []byte
+
+func (s sparseArray) Entry(i int) sparseNode { return (sparseNode)(s[i*24:]) }
+func (s sparseArray) IsExtended() []byte { return s[24*s.MaxEntries():][:1] }
+func (s sparseArray) MaxEntries() int { return len(s) / 24 }
+
+type sparseNode []byte
+
+func (s sparseNode) Offset() []byte { return s[00:][:12] }
+func (s sparseNode) NumBytes() []byte { return s[12:][:12] }
diff --git a/src/archive/tar/reader.go b/src/archive/tar/reader.go
index e2a2a5440e04c2..096ef082bf8764 100644
--- a/src/archive/tar/reader.go
+++ b/src/archive/tar/reader.go
@@ -29,11 +29,11 @@ const maxNanoSecondIntSize = 9
// The Next method advances to the next file in the archive (including the first),
// and then it can be treated as an io.Reader to access the file's data.
type Reader struct {
- r io.Reader
- err error
- pad int64 // amount of padding (ignored) after current file entry
- curr numBytesReader // reader for current file entry
- hdrBuff [blockSize]byte // buffer to use in readHeader
+ r io.Reader
+ err error
+ pad int64 // amount of padding (ignored) after current file entry
+ curr numBytesReader // reader for current file entry
+ blk block // buffer to use as temporary local storage
}
type parser struct {
@@ -98,17 +98,6 @@ const (
paxGNUSparseRealSize = "GNU.sparse.realsize"
)
-// Keywords for old GNU sparse headers
-const (
- oldGNUSparseMainHeaderOffset = 386
- oldGNUSparseMainHeaderIsExtendedOffset = 482
- oldGNUSparseMainHeaderNumEntries = 4
- oldGNUSparseExtendedHeaderIsExtendedOffset = 504
- oldGNUSparseExtendedHeaderNumEntries = 21
- oldGNUSparseOffsetSize = 12
- oldGNUSparseNumBytesSize = 12
-)
-
// NewReader creates a new Reader reading from r.
func NewReader(r io.Reader) *Reader { return &Reader{r: r} }
@@ -542,17 +531,6 @@ func (tr *Reader) skipUnread() error {
return tr.err
}
-func (tr *Reader) verifyChecksum(header []byte) bool {
- if tr.err != nil {
- return false
- }
-
- var p parser
- given := p.parseOctal(header[148:156])
- unsigned, signed := checksum(header)
- return p.err == nil && (given == unsigned || given == signed)
-}
-
// readHeader reads the next block header and assumes that the underlying reader
// is already aligned to a block boundary.
//
@@ -561,19 +539,16 @@ func (tr *Reader) verifyChecksum(header []byte) bool {
// * Exactly 1 block of zeros is read and EOF is hit.
// * At least 2 blocks of zeros are read.
func (tr *Reader) readHeader() *Header {
- header := tr.hdrBuff[:]
- copy(header, zeroBlock)
-
- if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil {
+ if _, tr.err = io.ReadFull(tr.r, tr.blk[:]); tr.err != nil {
return nil // io.EOF is okay here
}
// Two blocks of zero bytes marks the end of the archive.
- if bytes.Equal(header, zeroBlock[0:blockSize]) {
- if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil {
+ if bytes.Equal(tr.blk[:], zeroBlock[:]) {
+ if _, tr.err = io.ReadFull(tr.r, tr.blk[:]); tr.err != nil {
return nil // io.EOF is okay here
}
- if bytes.Equal(header, zeroBlock[0:blockSize]) {
+ if bytes.Equal(tr.blk[:], zeroBlock[:]) {
tr.err = io.EOF
} else {
tr.err = ErrHeader // zero block and then non-zero block
@@ -581,71 +556,55 @@ func (tr *Reader) readHeader() *Header {
return nil
}
- if !tr.verifyChecksum(header) {
+ // Verify the header matches a known format.
+ format := tr.blk.GetFormat()
+ if format == formatUnknown {
tr.err = ErrHeader
return nil
}
- // Unpack
var p parser
hdr := new(Header)
- s := slicer(header)
-
- hdr.Name = p.parseString(s.next(100))
- hdr.Mode = p.parseNumeric(s.next(8))
- hdr.Uid = int(p.parseNumeric(s.next(8)))
- hdr.Gid = int(p.parseNumeric(s.next(8)))
- hdr.Size = p.parseNumeric(s.next(12))
- hdr.ModTime = time.Unix(p.parseNumeric(s.next(12)), 0)
- s.next(8) // chksum
- hdr.Typeflag = s.next(1)[0]
- hdr.Linkname = p.parseString(s.next(100))
-
- // The remainder of the header depends on the value of magic.
- // The original (v7) version of tar had no explicit magic field,
- // so its magic bytes, like the rest of the block, are NULs.
- magic := string(s.next(8)) // contains version field as well.
- var format string
- switch {
- case magic[:6] == "ustar\x00": // POSIX tar (1003.1-1988)
- if string(header[508:512]) == "tar\x00" {
- format = "star"
- } else {
- format = "posix"
- }
- case magic == "ustar \x00": // old GNU tar
- format = "gnu"
- }
- switch format {
- case "posix", "gnu", "star":
- hdr.Uname = p.parseString(s.next(32))
- hdr.Gname = p.parseString(s.next(32))
- devmajor := s.next(8)
- devminor := s.next(8)
+ // Unpack the V7 header.
+ v7 := tr.blk.V7()
+ hdr.Name = p.parseString(v7.Name())
+ hdr.Mode = p.parseNumeric(v7.Mode())
+ hdr.Uid = int(p.parseNumeric(v7.UID()))
+ hdr.Gid = int(p.parseNumeric(v7.GID()))
+ hdr.Size = p.parseNumeric(v7.Size())
+ hdr.ModTime = time.Unix(p.parseNumeric(v7.ModTime()), 0)
+ hdr.Typeflag = v7.TypeFlag()[0]
+ hdr.Linkname = p.parseString(v7.LinkName())
+
+ // Unpack format specific fields.
+ if format > formatV7 {
+ ustar := tr.blk.USTAR()
+ hdr.Uname = p.parseString(ustar.UserName())
+ hdr.Gname = p.parseString(ustar.GroupName())
if hdr.Typeflag == TypeChar || hdr.Typeflag == TypeBlock {
- hdr.Devmajor = p.parseNumeric(devmajor)
- hdr.Devminor = p.parseNumeric(devminor)
+ hdr.Devmajor = p.parseNumeric(ustar.DevMajor())
+ hdr.Devminor = p.parseNumeric(ustar.DevMinor())
}
+
var prefix string
switch format {
- case "posix", "gnu":
- prefix = p.parseString(s.next(155))
- case "star":
- prefix = p.parseString(s.next(131))
- hdr.AccessTime = time.Unix(p.parseNumeric(s.next(12)), 0)
- hdr.ChangeTime = time.Unix(p.parseNumeric(s.next(12)), 0)
+ case formatUSTAR, formatGNU:
+ // TODO(dsnet): Do not use the prefix field for the GNU format!
+ // See golang.org/issues/12594
+ ustar := tr.blk.USTAR()
+ prefix = p.parseString(ustar.Prefix())
+ case formatSTAR:
+ star := tr.blk.STAR()
+ prefix = p.parseString(star.Prefix())
+ hdr.AccessTime = time.Unix(p.parseNumeric(star.AccessTime()), 0)
+ hdr.ChangeTime = time.Unix(p.parseNumeric(star.ChangeTime()), 0)
}
if len(prefix) > 0 {
hdr.Name = prefix + "/" + hdr.Name
}
}
- if p.err != nil {
- tr.err = p.err
- return nil
- }
-
nb := hdr.Size
if isHeaderOnlyType(hdr.Typeflag) {
nb = 0
@@ -662,14 +621,14 @@ func (tr *Reader) readHeader() *Header {
// Check for old GNU sparse format entry.
if hdr.Typeflag == TypeGNUSparse {
// Get the real size of the file.
- hdr.Size = p.parseNumeric(header[483:495])
+ hdr.Size = p.parseNumeric(tr.blk.GNU().RealSize())
if p.err != nil {
tr.err = p.err
return nil
}
// Read the sparse map.
- sp := tr.readOldGNUSparseMap(header)
+ sp := tr.readOldGNUSparseMap(&tr.blk)
if tr.err != nil {
return nil
}
@@ -681,26 +640,24 @@ func (tr *Reader) readHeader() *Header {
}
}
+ if p.err != nil {
+ tr.err = p.err
+ return nil
+ }
+
return hdr
}
// readOldGNUSparseMap reads the sparse map as stored in the old GNU sparse format.
// The sparse map is stored in the tar header if it's small enough. If it's larger than four entries,
// then one or more extension headers are used to store the rest of the sparse map.
-func (tr *Reader) readOldGNUSparseMap(header []byte) []sparseEntry {
+func (tr *Reader) readOldGNUSparseMap(blk *block) []sparseEntry {
var p parser
- isExtended := header[oldGNUSparseMainHeaderIsExtendedOffset] != 0
- spCap := oldGNUSparseMainHeaderNumEntries
- if isExtended {
- spCap += oldGNUSparseExtendedHeaderNumEntries
- }
- sp := make([]sparseEntry, 0, spCap)
- s := slicer(header[oldGNUSparseMainHeaderOffset:])
-
- // Read the four entries from the main tar header
- for i := 0; i < oldGNUSparseMainHeaderNumEntries; i++ {
- offset := p.parseNumeric(s.next(oldGNUSparseOffsetSize))
- numBytes := p.parseNumeric(s.next(oldGNUSparseNumBytesSize))
+ var s sparseArray = blk.GNU().Sparse()
+ var sp = make([]sparseEntry, 0, s.MaxEntries())
+ for i := 0; i < s.MaxEntries(); i++ {
+ offset := p.parseOctal(s.Entry(i).Offset())
+ numBytes := p.parseOctal(s.Entry(i).NumBytes())
if p.err != nil {
tr.err = p.err
return nil
@@ -711,17 +668,17 @@ func (tr *Reader) readOldGNUSparseMap(header []byte) []sparseEntry {
sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes})
}
- for isExtended {
+ for s.IsExtended()[0] > 0 {
// There are more entries. Read an extension header and parse its entries.
- sparseHeader := make([]byte, blockSize)
- if _, tr.err = io.ReadFull(tr.r, sparseHeader); tr.err != nil {
+ var blk block
+ if _, tr.err = io.ReadFull(tr.r, blk[:]); tr.err != nil {
return nil
}
- isExtended = sparseHeader[oldGNUSparseExtendedHeaderIsExtendedOffset] != 0
- s = slicer(sparseHeader)
- for i := 0; i < oldGNUSparseExtendedHeaderNumEntries; i++ {
- offset := p.parseNumeric(s.next(oldGNUSparseOffsetSize))
- numBytes := p.parseNumeric(s.next(oldGNUSparseNumBytesSize))
+ s = blk.Sparse()
+
+ for i := 0; i < s.MaxEntries(); i++ {
+ offset := p.parseOctal(s.Entry(i).Offset())
+ numBytes := p.parseOctal(s.Entry(i).NumBytes())
if p.err != nil {
tr.err = p.err
return nil
diff --git a/src/archive/tar/writer.go b/src/archive/tar/writer.go
index 944b2d49529adf..426e4434eb7544 100644
--- a/src/archive/tar/writer.go
+++ b/src/archive/tar/writer.go
@@ -36,10 +36,10 @@ type Writer struct {
nb int64 // number of unwritten bytes for current file entry
pad int64 // amount of padding to write after current file entry
closed bool
- usedBinary bool // whether the binary numeric field extension was used
- preferPax bool // use pax header instead of binary numeric header
- hdrBuff [blockSize]byte // buffer to use in writeHeader when writing a regular header
- paxHdrBuff [blockSize]byte // buffer to use in writeHeader when writing a pax header
+ usedBinary bool // whether the binary numeric field extension was used
+ preferPax bool // use PAX header instead of binary numeric header
+ hdrBuff block // buffer to use in writeHeader when writing a regular header
+ paxHdrBuff block // buffer to use in writeHeader when writing a PAX header
}
type formatter struct {
@@ -153,27 +153,24 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
// a map to hold pax header records, if any are needed
paxHeaders := make(map[string]string)
- // TODO(shanemhansen): we might want to use PAX headers for
+ // TODO(dsnet): we might want to use PAX headers for
// subsecond time resolution, but for now let's just capture
// too long fields or non ascii characters
- var f formatter
- var header []byte
-
// We need to select which scratch buffer to use carefully,
// since this method is called recursively to write PAX headers.
// If allowPax is true, this is the non-recursive call, and we will use hdrBuff.
// If allowPax is false, we are being called by writePAXHeader, and hdrBuff is
// already being used by the non-recursive call, so we must use paxHdrBuff.
- header = tw.hdrBuff[:]
+ header := &tw.hdrBuff
if !allowPax {
- header = tw.paxHdrBuff[:]
+ header = &tw.paxHdrBuff
}
- copy(header, zeroBlock)
- s := slicer(header)
+ copy(header[:], zeroBlock[:])
// Wrappers around formatter that automatically sets paxHeaders if the
// argument extends beyond the capacity of the input byte slice.
+ var f formatter
var formatString = func(b []byte, s string, paxKeyword string) {
needsPaxHeader := paxKeyword != paxNone && len(s) > len(b) || !isASCII(s)
if needsPaxHeader {
@@ -202,44 +199,33 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
f.formatNumeric(b, x)
}
- // keep a reference to the filename to allow to overwrite it later if we detect that we can use ustar longnames instead of pax
- pathHeaderBytes := s.next(fileNameSize)
-
- formatString(pathHeaderBytes, hdr.Name, paxPath)
-
// Handle out of range ModTime carefully.
var modTime int64
if !hdr.ModTime.Before(minTime) && !hdr.ModTime.After(maxTime) {
modTime = hdr.ModTime.Unix()
}
- f.formatOctal(s.next(8), hdr.Mode) // 100:108
- formatNumeric(s.next(8), int64(hdr.Uid), paxUid) // 108:116
- formatNumeric(s.next(8), int64(hdr.Gid), paxGid) // 116:124
- formatNumeric(s.next(12), hdr.Size, paxSize) // 124:136
- formatNumeric(s.next(12), modTime, paxNone) // 136:148 --- consider using pax for finer granularity
- s.next(8) // chksum (148:156)
- s.next(1)[0] = hdr.Typeflag // 156:157
-
- formatString(s.next(100), hdr.Linkname, paxLinkpath)
-
- copy(s.next(8), []byte("ustar\x0000")) // 257:265
- formatString(s.next(32), hdr.Uname, paxUname) // 265:297
- formatString(s.next(32), hdr.Gname, paxGname) // 297:329
- formatNumeric(s.next(8), hdr.Devmajor, paxNone) // 329:337
- formatNumeric(s.next(8), hdr.Devminor, paxNone) // 337:345
-
- // keep a reference to the prefix to allow to overwrite it later if we detect that we can use ustar longnames instead of pax
- prefixHeaderBytes := s.next(155)
- formatString(prefixHeaderBytes, "", paxNone) // 345:500 prefix
+ v7 := header.V7()
+ formatString(v7.Name(), hdr.Name, paxPath)
+ // TODO(dsnet): The GNU format permits the mode field to be encoded in
+ // base-256 format. Thus, we can use formatNumeric instead of formatOctal.
+ f.formatOctal(v7.Mode(), hdr.Mode)
+ formatNumeric(v7.UID(), int64(hdr.Uid), paxUid)
+ formatNumeric(v7.GID(), int64(hdr.Gid), paxGid)
+ formatNumeric(v7.Size(), hdr.Size, paxSize)
+ // TODO(dsnet): Consider using PAX for finer time granularity.
+ formatNumeric(v7.ModTime(), modTime, paxNone)
+ v7.TypeFlag()[0] = hdr.Typeflag
+ formatString(v7.LinkName(), hdr.Linkname, paxLinkpath)
+
+ ustar := header.USTAR()
+ formatString(ustar.UserName(), hdr.Uname, paxUname)
+ formatString(ustar.GroupName(), hdr.Gname, paxGname)
+ formatNumeric(ustar.DevMajor(), hdr.Devmajor, paxNone)
+ formatNumeric(ustar.DevMinor(), hdr.Devminor, paxNone)
- // Use the GNU magic instead of POSIX magic if we used any GNU extensions.
- if tw.usedBinary {
- copy(header[257:265], []byte("ustar \x00"))
- }
-
- _, paxPathUsed := paxHeaders[paxPath]
// try to use a ustar header when only the name is too long
+ _, paxPathUsed := paxHeaders[paxPath]
if !tw.preferPax && len(paxHeaders) == 1 && paxPathUsed {
prefix, suffix, ok := splitUSTARPath(hdr.Name)
if ok {
@@ -247,16 +233,16 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
delete(paxHeaders, paxPath)
// Update the path fields
- formatString(pathHeaderBytes, suffix, paxNone)
- formatString(prefixHeaderBytes, prefix, paxNone)
+ formatString(v7.Name(), suffix, paxNone)
+ formatString(ustar.Prefix(), prefix, paxNone)
}
}
- // The chksum field is terminated by a NUL and a space.
- // This is different from the other octal fields.
- chksum, _ := checksum(header)
- f.formatOctal(header[148:155], chksum) // Never fails
- header[155] = ' '
+ if tw.usedBinary {
+ header.SetFormat(formatGNU)
+ } else {
+ header.SetFormat(formatUSTAR)
+ }
// Check if there were any formatting errors.
if f.err != nil {
@@ -281,7 +267,7 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
tw.nb = hdr.Size
tw.pad = (blockSize - (tw.nb % blockSize)) % blockSize
- _, tw.err = tw.w.Write(header)
+ _, tw.err = tw.w.Write(header[:])
return tw.err
}
@@ -289,10 +275,10 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
// If the path is not splittable, then it will return ("", "", false).
func splitUSTARPath(name string) (prefix, suffix string, ok bool) {
length := len(name)
- if length <= fileNameSize || !isASCII(name) {
+ if length <= nameSize || !isASCII(name) {
return "", "", false
- } else if length > fileNamePrefixSize+1 {
- length = fileNamePrefixSize + 1
+ } else if length > prefixSize+1 {
+ length = prefixSize + 1
} else if name[length-1] == '/' {
length--
}
@@ -300,7 +286,7 @@ func splitUSTARPath(name string) (prefix, suffix string, ok bool) {
i := strings.LastIndex(name[:length], "/")
nlen := len(name) - i - 1 // nlen is length of suffix
plen := i // plen is length of prefix
- if i <= 0 || nlen > fileNameSize || nlen == 0 || plen > fileNamePrefixSize {
+ if i <= 0 || nlen > nameSize || nlen == 0 || plen > prefixSize {
return "", "", false
}
return name[:i], name[i+1:], true
@@ -323,8 +309,8 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHeaders map[string]string) erro
fullName := path.Join(dir, "PaxHeaders.0", file)
ascii := toASCII(fullName)
- if len(ascii) > 100 {
- ascii = ascii[:100]
+ if len(ascii) > nameSize {
+ ascii = ascii[:nameSize]
}
ext.Name = ascii
// Construct the body
@@ -407,7 +393,7 @@ func (tw *Writer) Close() error {
// trailer: two zero blocks
for i := 0; i < 2; i++ {
- _, tw.err = tw.w.Write(zeroBlock)
+ _, tw.err = tw.w.Write(zeroBlock[:])
if tw.err != nil {
break
}
diff --git a/src/archive/tar/writer_test.go b/src/archive/tar/writer_test.go
index 6e91d907ce96bd..27aa8e5dab6724 100644
--- a/src/archive/tar/writer_test.go
+++ b/src/archive/tar/writer_test.go
@@ -587,17 +587,17 @@ func TestSplitUSTARPath(t *testing.T) {
{"", "", "", false},
{"abc", "", "", false},
{"用戶名", "", "", false},
- {sr("a", fileNameSize), "", "", false},
- {sr("a", fileNameSize) + "/", "", "", false},
- {sr("a", fileNameSize) + "/a", sr("a", fileNameSize), "a", true},
- {sr("a", fileNamePrefixSize) + "/", "", "", false},
- {sr("a", fileNamePrefixSize) + "/a", sr("a", fileNamePrefixSize), "a", true},
- {sr("a", fileNameSize+1), "", "", false},
- {sr("/", fileNameSize+1), sr("/", fileNameSize-1), "/", true},
- {sr("a", fileNamePrefixSize) + "/" + sr("b", fileNameSize),
- sr("a", fileNamePrefixSize), sr("b", fileNameSize), true},
- {sr("a", fileNamePrefixSize) + "//" + sr("b", fileNameSize), "", "", false},
- {sr("a/", fileNameSize), sr("a/", 77) + "a", sr("a/", 22), true},
+ {sr("a", nameSize), "", "", false},
+ {sr("a", nameSize) + "/", "", "", false},
+ {sr("a", nameSize) + "/a", sr("a", nameSize), "a", true},
+ {sr("a", prefixSize) + "/", "", "", false},
+ {sr("a", prefixSize) + "/a", sr("a", prefixSize), "a", true},
+ {sr("a", nameSize+1), "", "", false},
+ {sr("/", nameSize+1), sr("/", nameSize-1), "/", true},
+ {sr("a", prefixSize) + "/" + sr("b", nameSize),
+ sr("a", prefixSize), sr("b", nameSize), true},
+ {sr("a", prefixSize) + "//" + sr("b", nameSize), "", "", false},
+ {sr("a/", nameSize), sr("a/", 77) + "a", sr("a/", 22), true},
}
for _, v := range vectors {
From b90cb3f4716d3fede57bf8e798d27406fba5c294 Mon Sep 17 00:00:00 2001
From: Brad Fitzpatrick
Date: Thu, 5 May 2016 17:52:37 -0700
Subject: [PATCH 009/267] cmd/go: fail with nice error message on bad
GOOS/GOARCH pair
Fixes #12272
Change-Id: I2115ec62ed4061084c482eb385a583a1c1909888
Reviewed-on: https://go-review.googlesource.com/22838
Reviewed-by: Ian Lance Taylor
Reviewed-by: Minux Ma
---
.gitignore | 1 +
src/cmd/dist/build.go | 2 ++
src/cmd/dist/buildgo.go | 15 +++++++++++----
src/cmd/go/build.go | 6 ++++++
4 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/.gitignore b/.gitignore
index 6851e147d33877..7173067a759c6f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,6 +26,7 @@ misc/cgo/stdio/run.out
misc/cgo/testso/main
src/cmd/cgo/zdefaultcc.go
src/cmd/go/zdefaultcc.go
+src/cmd/go/zosarch.go
src/cmd/internal/obj/zbootstrap.go
src/go/build/zcgo.go
src/go/doc/headscan
diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go
index 04a13b2365ce6a..aa12aa9dc3da8c 100644
--- a/src/cmd/dist/build.go
+++ b/src/cmd/dist/build.go
@@ -464,6 +464,7 @@ var deptab = []struct {
}{
{"cmd/go", []string{
"zdefaultcc.go",
+ "zosarch.go",
}},
{"runtime/internal/sys", []string{
"zversion.go",
@@ -485,6 +486,7 @@ var gentab = []struct {
gen func(string, string)
}{
{"zdefaultcc.go", mkzdefaultcc},
+ {"zosarch.go", mkzosarch},
{"zversion.go", mkzversion},
{"zcgo.go", mkzcgo},
diff --git a/src/cmd/dist/buildgo.go b/src/cmd/dist/buildgo.go
index 2b68fc222460c8..c367c70b043089 100644
--- a/src/cmd/dist/buildgo.go
+++ b/src/cmd/dist/buildgo.go
@@ -23,9 +23,7 @@ import (
// It is invoked to write cmd/go/zdefaultcc.go
// but we also write cmd/cgo/zdefaultcc.go
func mkzdefaultcc(dir, file string) {
- var out string
-
- out = fmt.Sprintf(
+ out := fmt.Sprintf(
"// auto generated by go tool dist\n"+
"\n"+
"package main\n"+
@@ -42,7 +40,16 @@ func mkzdefaultcc(dir, file string) {
writefile(out, file, writeSkipSame)
}
-// mkzcgo writes zcgo.go for go/build package:
+// mkzcgo writes zosarch.go for cmd/go.
+func mkzosarch(dir, file string) {
+ var buf bytes.Buffer
+ buf.WriteString("// auto generated by go tool dist\n\n")
+ buf.WriteString("package main\n\n")
+ fmt.Fprintf(&buf, "var osArchSupportsCgo = %#v", cgoEnabled)
+ writefile(buf.String(), file, writeSkipSame)
+}
+
+// mkzcgo writes zcgo.go for the go/build package:
//
// package build
// var cgoEnabled = map[string]bool{}
diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go
index 0102b5e08a2272..09e2122b0cc1db 100644
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -669,6 +669,12 @@ var (
func init() {
goarch = buildContext.GOARCH
goos = buildContext.GOOS
+
+ if _, ok := osArchSupportsCgo[goos+"/"+goarch]; !ok {
+ fmt.Fprintf(os.Stderr, "cmd/go: unsupported GOOS/GOARCH pair %s/%s\n", goos, goarch)
+ os.Exit(2)
+ }
+
if goos == "windows" {
exeSuffix = ".exe"
}
From d68f800620b4295039912066970fb2be914f1d1e Mon Sep 17 00:00:00 2001
From: Robert Griesemer
Date: Thu, 5 May 2016 17:46:58 -0700
Subject: [PATCH 010/267] test: update test for issue 15548
Accidentally checked in the version of file c.go that doesn't
exhibit the bug - hence the test was not testing the bug fix.
Double-checked that this version exposes the bug w/o the fix.
Change-Id: Ie4dc455229d1ac802a80164b5d549c2ad4d971f5
Reviewed-on: https://go-review.googlesource.com/22837
Run-TryBot: Robert Griesemer
TryBot-Result: Gobot Gobot
Reviewed-by: Minux Ma
---
test/fixedbugs/issue15548.dir/c.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/fixedbugs/issue15548.dir/c.go b/test/fixedbugs/issue15548.dir/c.go
index ce6e3204b3ea2c..6d3f3be53ec2a4 100644
--- a/test/fixedbugs/issue15548.dir/c.go
+++ b/test/fixedbugs/issue15548.dir/c.go
@@ -5,6 +5,6 @@
package c
import (
- _ "./a"
_ "./b"
+ _ "./a"
)
From ef92857e27556804d66e72e2360dc2c6b6554bd7 Mon Sep 17 00:00:00 2001
From: Cherry Zhang
Date: Thu, 5 May 2016 09:10:49 -0700
Subject: [PATCH 011/267] cmd/go, cmd/cgo: pass "-mabi=64" to gcc on mips64
Change-Id: I9ac2ae57a00cee23d6255db02419b0a0f087d4f3
Reviewed-on: https://go-review.googlesource.com/22801
Reviewed-by: Minux Ma
Run-TryBot: Minux Ma
---
src/cmd/cgo/gcc.go | 2 ++
src/cmd/go/build.go | 2 ++
2 files changed, 4 insertions(+)
diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go
index 3ee4461352c30d..97ef824c9342a7 100644
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -1089,6 +1089,8 @@ func (p *Package) gccMachine() []string {
return []string{"-m31"}
case "s390x":
return []string{"-m64"}
+ case "mips64", "mips64le":
+ return []string{"-mabi=64"}
}
return nil
}
diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go
index 09e2122b0cc1db..6bef09b66b86bf 100644
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -3103,6 +3103,8 @@ func (b *builder) gccArchArgs() []string {
return []string{"-marm"} // not thumb
case "s390x":
return []string{"-m64", "-march=z196"}
+ case "mips64", "mips64le":
+ return []string{"-mabi=64"}
}
return nil
}
From 2e32efc44ac86cce3bd0808e6049d8c9b0225ba8 Mon Sep 17 00:00:00 2001
From: Shenghou Ma
Date: Fri, 6 May 2016 00:53:42 -0400
Subject: [PATCH 012/267] runtime: get randomness from AT_RANDOM AUXV on
linux/mips64x
Fixes #15148.
Change-Id: If3b628f30521adeec1625689dbc98aaf4a9ec858
Reviewed-on: https://go-review.googlesource.com/22811
Reviewed-by: Keith Randall
Run-TryBot: Minux Ma
Reviewed-by: Cherry Zhang
TryBot-Result: Gobot Gobot
---
src/runtime/os_linux_mips64x.go | 11 +++++++++++
src/runtime/os_linux_noauxv.go | 2 +-
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/src/runtime/os_linux_mips64x.go b/src/runtime/os_linux_mips64x.go
index 92b5c82af7c20f..8039b2fac9b7a3 100644
--- a/src/runtime/os_linux_mips64x.go
+++ b/src/runtime/os_linux_mips64x.go
@@ -9,6 +9,17 @@ package runtime
var randomNumber uint32
+func archauxv(tag, val uintptr) {
+ switch tag {
+ case _AT_RANDOM:
+ // sysargs filled in startupRandomData, but that
+ // pointer may not be word aligned, so we must treat
+ // it as a byte array.
+ randomNumber = uint32(startupRandomData[4]) | uint32(startupRandomData[5])<<8 |
+ uint32(startupRandomData[6])<<16 | uint32(startupRandomData[7])<<24
+ }
+}
+
//go:nosplit
func cputicks() int64 {
// Currently cputicks() is used in blocking profiler and to seed fastrand1().
diff --git a/src/runtime/os_linux_noauxv.go b/src/runtime/os_linux_noauxv.go
index 0b46f594ce0117..22522dd803dc02 100644
--- a/src/runtime/os_linux_noauxv.go
+++ b/src/runtime/os_linux_noauxv.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 !amd64,!arm,!arm64
+// +build !amd64,!arm,!arm64,!mips64,!mips64le
package runtime
From 009c002c925e391e5a7a406c9175aefafb6c9e3c Mon Sep 17 00:00:00 2001
From: Ilya Tocar
Date: Fri, 29 Apr 2016 16:14:57 +0300
Subject: [PATCH 013/267] cmd/internal/obj/x86: add AVX2 instrutions needed for
sha1/sha512/sha256 acceleration
This means: VPSHUFB, VPSHUFD, VPERM2F128, VPALIGNR, VPADDQ, VPADDD, VPSRLDQ,
VPSLLDQ, VPSRLQ, VPSLLQ, VPSRLD, VPSLLD, VPOR, VPBLENDD, VINSERTI128,
VPERM2I128, RORXL, RORXQ.
Change-Id: Ief27190ee6acfa86b109262af5d999bc101e923d
Reviewed-on: https://go-review.googlesource.com/22606
Run-TryBot: Ilya Tocar
TryBot-Result: Gobot Gobot
Reviewed-by: Russ Cox
---
src/cmd/asm/internal/arch/amd64.go | 28 ++
src/cmd/asm/internal/asm/asm.go | 28 +-
src/cmd/asm/internal/asm/testdata/amd64enc.s | 368 +++++++++----------
src/cmd/internal/obj/util.go | 9 +-
src/cmd/internal/obj/x86/a.out.go | 18 +
src/cmd/internal/obj/x86/anames.go | 18 +
src/cmd/internal/obj/x86/asm6.go | 84 ++++-
7 files changed, 364 insertions(+), 189 deletions(-)
create mode 100644 src/cmd/asm/internal/arch/amd64.go
diff --git a/src/cmd/asm/internal/arch/amd64.go b/src/cmd/asm/internal/arch/amd64.go
new file mode 100644
index 00000000000000..625e136d1db6a2
--- /dev/null
+++ b/src/cmd/asm/internal/arch/amd64.go
@@ -0,0 +1,28 @@
+// Copyright 2016 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 encapsulates some of the odd characteristics of the
+// AMD64 instruction set, to minimize its interaction
+// with the core of the assembler.
+
+package arch
+
+import (
+ "cmd/internal/obj"
+ "cmd/internal/obj/x86"
+)
+
+// IsAMD4OP reports whether the op (as defined by an ppc64.A* constant) is
+// The FMADD-like instructions behave similarly.
+func IsAMD4OP(op obj.As) bool {
+ switch op {
+ case x86.AVPERM2F128,
+ x86.AVPALIGNR,
+ x86.AVPERM2I128,
+ x86.AVINSERTI128,
+ x86.AVPBLENDD:
+ return true
+ }
+ return false
+}
diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go
index 24906e2cce200c..c9c64203ae68bd 100644
--- a/src/cmd/asm/internal/asm/asm.go
+++ b/src/cmd/asm/internal/asm/asm.go
@@ -568,6 +568,15 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
prog.To = a[2]
+ case sys.AMD64:
+ // Catch missing operand here, because we store immediate as part of From3, and can't distinguish
+ // missing operand from legal value 0 in obj/x86/asm6.
+ if arch.IsAMD4OP(op) {
+ p.errorf("4 operands required, but only 3 are provided for %s instruction", obj.Aconv(op))
+ }
+ prog.From = a[0]
+ prog.From3 = newAddr(a[1])
+ prog.To = a[2]
case sys.ARM64:
// ARM64 instructions with one input and two outputs.
if arch.IsARM64STLXR(op) {
@@ -583,7 +592,7 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
prog.To = a[2]
- case sys.AMD64, sys.I386:
+ case sys.I386:
prog.From = a[0]
prog.From3 = newAddr(a[1])
prog.To = a[2]
@@ -640,6 +649,23 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
prog.Reg = r1
break
}
+ if p.arch.Family == sys.AMD64 {
+ // 4 operand instruction have form ymm1, ymm2, ymm3/m256, imm8
+ // So From3 is always just a register, so we store imm8 in Offset field,
+ // to avoid increasing size of Prog.
+ prog.From = a[1]
+ prog.From3 = newAddr(a[2])
+ if a[0].Type != obj.TYPE_CONST {
+ p.errorf("first operand must be an immediate in %s instruction", obj.Aconv(op))
+ }
+ if prog.From3.Type != obj.TYPE_REG {
+ p.errorf("third operand must be a register in %s instruction", obj.Aconv(op))
+ }
+ prog.From3.Offset = int64(p.getImmediate(prog, op, &a[0]))
+ prog.To = a[3]
+ prog.RegTo2 = -1
+ break
+ }
if p.arch.Family == sys.ARM64 {
prog.From = a[0]
prog.Reg = p.getRegister(prog, op, &a[1])
diff --git a/src/cmd/asm/internal/asm/testdata/amd64enc.s b/src/cmd/asm/internal/asm/testdata/amd64enc.s
index 63fdcac27db840..22dfe127b3db0b 100644
--- a/src/cmd/asm/internal/asm/testdata/amd64enc.s
+++ b/src/cmd/asm/internal/asm/testdata/amd64enc.s
@@ -5008,22 +5008,22 @@ TEXT asmtest(SB),7,$0
RORB $7, (R11) // 41c00b07
RORB $7, DL // c0ca07
RORB $7, R11 // 41c0cb07
- //TODO: RORXL $7, (BX), DX // c4e37bf01307
- //TODO: RORXL $7, (R11), DX // c4c37bf01307
- //TODO: RORXL $7, DX, DX // c4e37bf0d207
- //TODO: RORXL $7, R11, DX // c4c37bf0d307
- //TODO: RORXL $7, (BX), R11 // c4637bf01b07
- //TODO: RORXL $7, (R11), R11 // c4437bf01b07
- //TODO: RORXL $7, DX, R11 // c4637bf0da07
- //TODO: RORXL $7, R11, R11 // c4437bf0db07
- //TODO: RORXQ $7, (BX), DX // c4e3fbf01307
- //TODO: RORXQ $7, (R11), DX // c4c3fbf01307
- //TODO: RORXQ $7, DX, DX // c4e3fbf0d207
- //TODO: RORXQ $7, R11, DX // c4c3fbf0d307
- //TODO: RORXQ $7, (BX), R11 // c463fbf01b07
- //TODO: RORXQ $7, (R11), R11 // c443fbf01b07
- //TODO: RORXQ $7, DX, R11 // c463fbf0da07
- //TODO: RORXQ $7, R11, R11 // c443fbf0db07
+ RORXL $7, (BX), DX // c4e37bf01307
+ RORXL $7, (R11), DX // c4c37bf01307
+ RORXL $7, DX, DX // c4e37bf0d207
+ RORXL $7, R11, DX // c4c37bf0d307
+ RORXL $7, (BX), R11 // c4637bf01b07
+ RORXL $7, (R11), R11 // c4437bf01b07
+ RORXL $7, DX, R11 // c4637bf0da07
+ RORXL $7, R11, R11 // c4437bf0db07
+ RORXQ $7, (BX), DX // c4e3fbf01307
+ RORXQ $7, (R11), DX // c4c3fbf01307
+ RORXQ $7, DX, DX // c4e3fbf0d207
+ RORXQ $7, R11, DX // c4c3fbf0d307
+ RORXQ $7, (BX), R11 // c463fbf01b07
+ RORXQ $7, (R11), R11 // c443fbf01b07
+ RORXQ $7, DX, R11 // c463fbf0da07
+ RORXQ $7, R11, R11 // c443fbf0db07
ROUNDPD $7, (BX), X2 // 660f3a091307
ROUNDPD $7, (R11), X2 // 66410f3a091307
ROUNDPD $7, X2, X2 // 660f3a09d207
@@ -7420,14 +7420,14 @@ TEXT asmtest(SB),7,$0
//TODO: VINSERTF128 $7, (R11), Y15, Y11 // c44305181b07
//TODO: VINSERTF128 $7, X2, Y15, Y11 // c4630518da07
//TODO: VINSERTF128 $7, X11, Y15, Y11 // c4430518db07
- //TODO: VINSERTI128 $7, (BX), Y15, Y2 // c4e305381307
- //TODO: VINSERTI128 $7, (R11), Y15, Y2 // c4c305381307
- //TODO: VINSERTI128 $7, X2, Y15, Y2 // c4e30538d207
- //TODO: VINSERTI128 $7, X11, Y15, Y2 // c4c30538d307
- //TODO: VINSERTI128 $7, (BX), Y15, Y11 // c46305381b07
- //TODO: VINSERTI128 $7, (R11), Y15, Y11 // c44305381b07
- //TODO: VINSERTI128 $7, X2, Y15, Y11 // c4630538da07
- //TODO: VINSERTI128 $7, X11, Y15, Y11 // c4430538db07
+ VINSERTI128 $7, (BX), Y15, Y2 // c4e305381307
+ VINSERTI128 $7, (R11), Y15, Y2 // c4c305381307
+ VINSERTI128 $7, X2, Y15, Y2 // c4e30538d207
+ VINSERTI128 $7, X11, Y15, Y2 // c4c30538d307
+ VINSERTI128 $7, (BX), Y15, Y11 // c46305381b07
+ VINSERTI128 $7, (R11), Y15, Y11 // c44305381b07
+ VINSERTI128 $7, X2, Y15, Y11 // c4630538da07
+ VINSERTI128 $7, X11, Y15, Y11 // c4430538db07
//TODO: VINSERTPS $7, (BX), X9, X2 // c4e331211307
//TODO: VINSERTPS $7, (R11), X9, X2 // c4c331211307
//TODO: VINSERTPS $7, X2, X9, X2 // c4e33121d207
@@ -8142,38 +8142,38 @@ TEXT asmtest(SB),7,$0
//TODO: VPADDB (R11), Y15, Y11 // c44105fc1b
//TODO: VPADDB Y2, Y15, Y11 // c46105fcda or c505fcda
//TODO: VPADDB Y11, Y15, Y11 // c44105fcdb
- //TODO: VPADDD (BX), X9, X2 // c4e131fe13 or c5b1fe13
- //TODO: VPADDD (R11), X9, X2 // c4c131fe13
- //TODO: VPADDD X2, X9, X2 // c4e131fed2 or c5b1fed2
- //TODO: VPADDD X11, X9, X2 // c4c131fed3
- //TODO: VPADDD (BX), X9, X11 // c46131fe1b or c531fe1b
- //TODO: VPADDD (R11), X9, X11 // c44131fe1b
- //TODO: VPADDD X2, X9, X11 // c46131feda or c531feda
- //TODO: VPADDD X11, X9, X11 // c44131fedb
- //TODO: VPADDD (BX), Y15, Y2 // c4e105fe13 or c585fe13
- //TODO: VPADDD (R11), Y15, Y2 // c4c105fe13
- //TODO: VPADDD Y2, Y15, Y2 // c4e105fed2 or c585fed2
- //TODO: VPADDD Y11, Y15, Y2 // c4c105fed3
- //TODO: VPADDD (BX), Y15, Y11 // c46105fe1b or c505fe1b
- //TODO: VPADDD (R11), Y15, Y11 // c44105fe1b
- //TODO: VPADDD Y2, Y15, Y11 // c46105feda or c505feda
- //TODO: VPADDD Y11, Y15, Y11 // c44105fedb
- //TODO: VPADDQ (BX), X9, X2 // c4e131d413 or c5b1d413
- //TODO: VPADDQ (R11), X9, X2 // c4c131d413
- //TODO: VPADDQ X2, X9, X2 // c4e131d4d2 or c5b1d4d2
- //TODO: VPADDQ X11, X9, X2 // c4c131d4d3
- //TODO: VPADDQ (BX), X9, X11 // c46131d41b or c531d41b
- //TODO: VPADDQ (R11), X9, X11 // c44131d41b
- //TODO: VPADDQ X2, X9, X11 // c46131d4da or c531d4da
- //TODO: VPADDQ X11, X9, X11 // c44131d4db
- //TODO: VPADDQ (BX), Y15, Y2 // c4e105d413 or c585d413
- //TODO: VPADDQ (R11), Y15, Y2 // c4c105d413
- //TODO: VPADDQ Y2, Y15, Y2 // c4e105d4d2 or c585d4d2
- //TODO: VPADDQ Y11, Y15, Y2 // c4c105d4d3
- //TODO: VPADDQ (BX), Y15, Y11 // c46105d41b or c505d41b
- //TODO: VPADDQ (R11), Y15, Y11 // c44105d41b
- //TODO: VPADDQ Y2, Y15, Y11 // c46105d4da or c505d4da
- //TODO: VPADDQ Y11, Y15, Y11 // c44105d4db
+ VPADDD (BX), X9, X2 // c4e131fe13 or c5b1fe13
+ VPADDD (R11), X9, X2 // c4c131fe13
+ VPADDD X2, X9, X2 // c4e131fed2 or c5b1fed2
+ VPADDD X11, X9, X2 // c4c131fed3
+ VPADDD (BX), X9, X11 // c46131fe1b or c531fe1b
+ VPADDD (R11), X9, X11 // c44131fe1b
+ VPADDD X2, X9, X11 // c46131feda or c531feda
+ VPADDD X11, X9, X11 // c44131fedb
+ VPADDD (BX), Y15, Y2 // c4e105fe13 or c585fe13
+ VPADDD (R11), Y15, Y2 // c4c105fe13
+ VPADDD Y2, Y15, Y2 // c4e105fed2 or c585fed2
+ VPADDD Y11, Y15, Y2 // c4c105fed3
+ VPADDD (BX), Y15, Y11 // c46105fe1b or c505fe1b
+ VPADDD (R11), Y15, Y11 // c44105fe1b
+ VPADDD Y2, Y15, Y11 // c46105feda or c505feda
+ VPADDD Y11, Y15, Y11 // c44105fedb
+ VPADDQ (BX), X9, X2 // c4e131d413 or c5b1d413
+ VPADDQ (R11), X9, X2 // c4c131d413
+ VPADDQ X2, X9, X2 // c4e131d4d2 or c5b1d4d2
+ VPADDQ X11, X9, X2 // c4c131d4d3
+ VPADDQ (BX), X9, X11 // c46131d41b or c531d41b
+ VPADDQ (R11), X9, X11 // c44131d41b
+ VPADDQ X2, X9, X11 // c46131d4da or c531d4da
+ VPADDQ X11, X9, X11 // c44131d4db
+ VPADDQ (BX), Y15, Y2 // c4e105d413 or c585d413
+ VPADDQ (R11), Y15, Y2 // c4c105d413
+ VPADDQ Y2, Y15, Y2 // c4e105d4d2 or c585d4d2
+ VPADDQ Y11, Y15, Y2 // c4c105d4d3
+ VPADDQ (BX), Y15, Y11 // c46105d41b or c505d41b
+ VPADDQ (R11), Y15, Y11 // c44105d41b
+ VPADDQ Y2, Y15, Y11 // c46105d4da or c505d4da
+ VPADDQ Y11, Y15, Y11 // c44105d4db
//TODO: VPADDSB (BX), X9, X2 // c4e131ec13 or c5b1ec13
//TODO: VPADDSB (R11), X9, X2 // c4c131ec13
//TODO: VPADDSB X2, X9, X2 // c4e131ecd2 or c5b1ecd2
@@ -8262,14 +8262,14 @@ TEXT asmtest(SB),7,$0
//TODO: VPALIGNR $7, (R11), X9, X11 // c443310f1b07
//TODO: VPALIGNR $7, X2, X9, X11 // c463310fda07
//TODO: VPALIGNR $7, X11, X9, X11 // c443310fdb07
- //TODO: VPALIGNR $7, (BX), Y15, Y2 // c4e3050f1307
- //TODO: VPALIGNR $7, (R11), Y15, Y2 // c4c3050f1307
- //TODO: VPALIGNR $7, Y2, Y15, Y2 // c4e3050fd207
- //TODO: VPALIGNR $7, Y11, Y15, Y2 // c4c3050fd307
- //TODO: VPALIGNR $7, (BX), Y15, Y11 // c463050f1b07
- //TODO: VPALIGNR $7, (R11), Y15, Y11 // c443050f1b07
- //TODO: VPALIGNR $7, Y2, Y15, Y11 // c463050fda07
- //TODO: VPALIGNR $7, Y11, Y15, Y11 // c443050fdb07
+ VPALIGNR $7, (BX), Y15, Y2 // c4e3050f1307
+ VPALIGNR $7, (R11), Y15, Y2 // c4c3050f1307
+ VPALIGNR $7, Y2, Y15, Y2 // c4e3050fd207
+ VPALIGNR $7, Y11, Y15, Y2 // c4c3050fd307
+ VPALIGNR $7, (BX), Y15, Y11 // c463050f1b07
+ VPALIGNR $7, (R11), Y15, Y11 // c443050f1b07
+ VPALIGNR $7, Y2, Y15, Y11 // c463050fda07
+ VPALIGNR $7, Y11, Y15, Y11 // c443050fdb07
VPAND (BX), X9, X2 // c4e131db13 or c5b1db13
VPAND (R11), X9, X2 // c4c131db13
VPAND X2, X9, X2 // c4e131dbd2 or c5b1dbd2
@@ -8342,14 +8342,14 @@ TEXT asmtest(SB),7,$0
//TODO: VPBLENDD $7, (R11), X9, X11 // c44331021b07
//TODO: VPBLENDD $7, X2, X9, X11 // c4633102da07
//TODO: VPBLENDD $7, X11, X9, X11 // c4433102db07
- //TODO: VPBLENDD $7, (BX), Y15, Y2 // c4e305021307
- //TODO: VPBLENDD $7, (R11), Y15, Y2 // c4c305021307
- //TODO: VPBLENDD $7, Y2, Y15, Y2 // c4e30502d207
- //TODO: VPBLENDD $7, Y11, Y15, Y2 // c4c30502d307
- //TODO: VPBLENDD $7, (BX), Y15, Y11 // c46305021b07
- //TODO: VPBLENDD $7, (R11), Y15, Y11 // c44305021b07
- //TODO: VPBLENDD $7, Y2, Y15, Y11 // c4630502da07
- //TODO: VPBLENDD $7, Y11, Y15, Y11 // c4430502db07
+ VPBLENDD $7, (BX), Y15, Y2 // c4e305021307
+ VPBLENDD $7, (R11), Y15, Y2 // c4c305021307
+ VPBLENDD $7, Y2, Y15, Y2 // c4e30502d207
+ VPBLENDD $7, Y11, Y15, Y2 // c4c30502d307
+ VPBLENDD $7, (BX), Y15, Y11 // c46305021b07
+ VPBLENDD $7, (R11), Y15, Y11 // c44305021b07
+ VPBLENDD $7, Y2, Y15, Y11 // c4630502da07
+ VPBLENDD $7, Y11, Y15, Y11 // c4430502db07
//TODO: VPBLENDVB XMM12, (BX), X9, X2 // c4e3314c13c0
//TODO: VPBLENDVB XMM12, (R11), X9, X2 // c4c3314c13c0
//TODO: VPBLENDVB XMM12, X2, X9, X2 // c4e3314cd2c0
@@ -8614,22 +8614,22 @@ TEXT asmtest(SB),7,$0
//TODO: VPCMPISTRM $7, (R11), X11 // c44379621b07
//TODO: VPCMPISTRM $7, X2, X11 // c4637962da07
//TODO: VPCMPISTRM $7, X11, X11 // c4437962db07
- //TODO: VPERM2F128 $7, (BX), Y15, Y2 // c4e305061307
- //TODO: VPERM2F128 $7, (R11), Y15, Y2 // c4c305061307
- //TODO: VPERM2F128 $7, Y2, Y15, Y2 // c4e30506d207
- //TODO: VPERM2F128 $7, Y11, Y15, Y2 // c4c30506d307
- //TODO: VPERM2F128 $7, (BX), Y15, Y11 // c46305061b07
- //TODO: VPERM2F128 $7, (R11), Y15, Y11 // c44305061b07
- //TODO: VPERM2F128 $7, Y2, Y15, Y11 // c4630506da07
- //TODO: VPERM2F128 $7, Y11, Y15, Y11 // c4430506db07
- //TODO: VPERM2I128 $7, (BX), Y15, Y2 // c4e305461307
- //TODO: VPERM2I128 $7, (R11), Y15, Y2 // c4c305461307
- //TODO: VPERM2I128 $7, Y2, Y15, Y2 // c4e30546d207
- //TODO: VPERM2I128 $7, Y11, Y15, Y2 // c4c30546d307
- //TODO: VPERM2I128 $7, (BX), Y15, Y11 // c46305461b07
- //TODO: VPERM2I128 $7, (R11), Y15, Y11 // c44305461b07
- //TODO: VPERM2I128 $7, Y2, Y15, Y11 // c4630546da07
- //TODO: VPERM2I128 $7, Y11, Y15, Y11 // c4430546db07
+ VPERM2F128 $7, (BX), Y15, Y2 // c4e305061307
+ VPERM2F128 $7, (R11), Y15, Y2 // c4c305061307
+ VPERM2F128 $7, Y2, Y15, Y2 // c4e30506d207
+ VPERM2F128 $7, Y11, Y15, Y2 // c4c30506d307
+ VPERM2F128 $7, (BX), Y15, Y11 // c46305061b07
+ VPERM2F128 $7, (R11), Y15, Y11 // c44305061b07
+ VPERM2F128 $7, Y2, Y15, Y11 // c4630506da07
+ VPERM2F128 $7, Y11, Y15, Y11 // c4430506db07
+ VPERM2I128 $7, (BX), Y15, Y2 // c4e305461307
+ VPERM2I128 $7, (R11), Y15, Y2 // c4c305461307
+ VPERM2I128 $7, Y2, Y15, Y2 // c4e30546d207
+ VPERM2I128 $7, Y11, Y15, Y2 // c4c30546d307
+ VPERM2I128 $7, (BX), Y15, Y11 // c46305461b07
+ VPERM2I128 $7, (R11), Y15, Y11 // c44305461b07
+ VPERM2I128 $7, Y2, Y15, Y11 // c4630546da07
+ VPERM2I128 $7, Y11, Y15, Y11 // c4430546db07
//TODO: VPERMD (BX), Y15, Y2 // c4e2053613
//TODO: VPERMD (R11), Y15, Y2 // c4c2053613
//TODO: VPERMD Y2, Y15, Y2 // c4e20536d2
@@ -9462,22 +9462,22 @@ TEXT asmtest(SB),7,$0
//TODO: VPMULUDQ (R11), Y15, Y11 // c44105f41b
//TODO: VPMULUDQ Y2, Y15, Y11 // c46105f4da or c505f4da
//TODO: VPMULUDQ Y11, Y15, Y11 // c44105f4db
- //TODO: VPOR (BX), X9, X2 // c4e131eb13 or c5b1eb13
- //TODO: VPOR (R11), X9, X2 // c4c131eb13
- //TODO: VPOR X2, X9, X2 // c4e131ebd2 or c5b1ebd2
- //TODO: VPOR X11, X9, X2 // c4c131ebd3
- //TODO: VPOR (BX), X9, X11 // c46131eb1b or c531eb1b
- //TODO: VPOR (R11), X9, X11 // c44131eb1b
- //TODO: VPOR X2, X9, X11 // c46131ebda or c531ebda
- //TODO: VPOR X11, X9, X11 // c44131ebdb
- //TODO: VPOR (BX), Y15, Y2 // c4e105eb13 or c585eb13
- //TODO: VPOR (R11), Y15, Y2 // c4c105eb13
- //TODO: VPOR Y2, Y15, Y2 // c4e105ebd2 or c585ebd2
- //TODO: VPOR Y11, Y15, Y2 // c4c105ebd3
- //TODO: VPOR (BX), Y15, Y11 // c46105eb1b or c505eb1b
- //TODO: VPOR (R11), Y15, Y11 // c44105eb1b
- //TODO: VPOR Y2, Y15, Y11 // c46105ebda or c505ebda
- //TODO: VPOR Y11, Y15, Y11 // c44105ebdb
+ VPOR (BX), X9, X2 // c4e131eb13 or c5b1eb13
+ VPOR (R11), X9, X2 // c4c131eb13
+ VPOR X2, X9, X2 // c4e131ebd2 or c5b1ebd2
+ VPOR X11, X9, X2 // c4c131ebd3
+ VPOR (BX), X9, X11 // c46131eb1b or c531eb1b
+ VPOR (R11), X9, X11 // c44131eb1b
+ VPOR X2, X9, X11 // c46131ebda or c531ebda
+ VPOR X11, X9, X11 // c44131ebdb
+ VPOR (BX), Y15, Y2 // c4e105eb13 or c585eb13
+ VPOR (R11), Y15, Y2 // c4c105eb13
+ VPOR Y2, Y15, Y2 // c4e105ebd2 or c585ebd2
+ VPOR Y11, Y15, Y2 // c4c105ebd3
+ VPOR (BX), Y15, Y11 // c46105eb1b or c505eb1b
+ VPOR (R11), Y15, Y11 // c44105eb1b
+ VPOR Y2, Y15, Y11 // c46105ebda or c505ebda
+ VPOR Y11, Y15, Y11 // c44105ebdb
//TODO: VPSADBW (BX), X9, X2 // c4e131f613 or c5b1f613
//TODO: VPSADBW (R11), X9, X2 // c4c131f613
//TODO: VPSADBW X2, X9, X2 // c4e131f6d2 or c5b1f6d2
@@ -9494,38 +9494,38 @@ TEXT asmtest(SB),7,$0
//TODO: VPSADBW (R11), Y15, Y11 // c44105f61b
//TODO: VPSADBW Y2, Y15, Y11 // c46105f6da or c505f6da
//TODO: VPSADBW Y11, Y15, Y11 // c44105f6db
- //TODO: VPSHUFB (BX), X9, X2 // c4e2310013
- //TODO: VPSHUFB (R11), X9, X2 // c4c2310013
- //TODO: VPSHUFB X2, X9, X2 // c4e23100d2
- //TODO: VPSHUFB X11, X9, X2 // c4c23100d3
- //TODO: VPSHUFB (BX), X9, X11 // c46231001b
- //TODO: VPSHUFB (R11), X9, X11 // c44231001b
- //TODO: VPSHUFB X2, X9, X11 // c4623100da
- //TODO: VPSHUFB X11, X9, X11 // c4423100db
- //TODO: VPSHUFB (BX), Y15, Y2 // c4e2050013
- //TODO: VPSHUFB (R11), Y15, Y2 // c4c2050013
- //TODO: VPSHUFB Y2, Y15, Y2 // c4e20500d2
- //TODO: VPSHUFB Y11, Y15, Y2 // c4c20500d3
- //TODO: VPSHUFB (BX), Y15, Y11 // c46205001b
- //TODO: VPSHUFB (R11), Y15, Y11 // c44205001b
- //TODO: VPSHUFB Y2, Y15, Y11 // c4620500da
- //TODO: VPSHUFB Y11, Y15, Y11 // c4420500db
- //TODO: VPSHUFD $7, (BX), X2 // c4e179701307 or c5f9701307
- //TODO: VPSHUFD $7, (R11), X2 // c4c179701307
- //TODO: VPSHUFD $7, X2, X2 // c4e17970d207 or c5f970d207
- //TODO: VPSHUFD $7, X11, X2 // c4c17970d307
- //TODO: VPSHUFD $7, (BX), X11 // c46179701b07 or c579701b07
- //TODO: VPSHUFD $7, (R11), X11 // c44179701b07
- //TODO: VPSHUFD $7, X2, X11 // c4617970da07 or c57970da07
- //TODO: VPSHUFD $7, X11, X11 // c4417970db07
- //TODO: VPSHUFD $7, (BX), Y2 // c4e17d701307 or c5fd701307
- //TODO: VPSHUFD $7, (R11), Y2 // c4c17d701307
- //TODO: VPSHUFD $7, Y2, Y2 // c4e17d70d207 or c5fd70d207
- //TODO: VPSHUFD $7, Y11, Y2 // c4c17d70d307
- //TODO: VPSHUFD $7, (BX), Y11 // c4617d701b07 or c57d701b07
- //TODO: VPSHUFD $7, (R11), Y11 // c4417d701b07
- //TODO: VPSHUFD $7, Y2, Y11 // c4617d70da07 or c57d70da07
- //TODO: VPSHUFD $7, Y11, Y11 // c4417d70db07
+ VPSHUFB (BX), X9, X2 // c4e2310013
+ VPSHUFB (R11), X9, X2 // c4c2310013
+ VPSHUFB X2, X9, X2 // c4e23100d2
+ VPSHUFB X11, X9, X2 // c4c23100d3
+ VPSHUFB (BX), X9, X11 // c46231001b
+ VPSHUFB (R11), X9, X11 // c44231001b
+ VPSHUFB X2, X9, X11 // c4623100da
+ VPSHUFB X11, X9, X11 // c4423100db
+ VPSHUFB (BX), Y15, Y2 // c4e2050013
+ VPSHUFB (R11), Y15, Y2 // c4c2050013
+ VPSHUFB Y2, Y15, Y2 // c4e20500d2
+ VPSHUFB Y11, Y15, Y2 // c4c20500d3
+ VPSHUFB (BX), Y15, Y11 // c46205001b
+ VPSHUFB (R11), Y15, Y11 // c44205001b
+ VPSHUFB Y2, Y15, Y11 // c4620500da
+ VPSHUFB Y11, Y15, Y11 // c4420500db
+ VPSHUFD $7, (BX), X2 // c4e179701307 or c5f9701307
+ VPSHUFD $7, (R11), X2 // c4c179701307
+ VPSHUFD $7, X2, X2 // c4e17970d207 or c5f970d207
+ VPSHUFD $7, X11, X2 // c4c17970d307
+ VPSHUFD $7, (BX), X11 // c46179701b07 or c579701b07
+ VPSHUFD $7, (R11), X11 // c44179701b07
+ VPSHUFD $7, X2, X11 // c4617970da07 or c57970da07
+ VPSHUFD $7, X11, X11 // c4417970db07
+ VPSHUFD $7, (BX), Y2 // c4e17d701307 or c5fd701307
+ VPSHUFD $7, (R11), Y2 // c4c17d701307
+ VPSHUFD $7, Y2, Y2 // c4e17d70d207 or c5fd70d207
+ VPSHUFD $7, Y11, Y2 // c4c17d70d307
+ VPSHUFD $7, (BX), Y11 // c4617d701b07 or c57d701b07
+ VPSHUFD $7, (R11), Y11 // c4417d701b07
+ VPSHUFD $7, Y2, Y11 // c4617d70da07 or c57d70da07
+ VPSHUFD $7, Y11, Y11 // c4417d70db07
//TODO: VPSHUFHW $7, (BX), X2 // c4e17a701307 or c5fa701307
//TODO: VPSHUFHW $7, (R11), X2 // c4c17a701307
//TODO: VPSHUFHW $7, X2, X2 // c4e17a70d207 or c5fa70d207
@@ -9606,30 +9606,30 @@ TEXT asmtest(SB),7,$0
//TODO: VPSIGNW (R11), Y15, Y11 // c44205091b
//TODO: VPSIGNW Y2, Y15, Y11 // c4620509da
//TODO: VPSIGNW Y11, Y15, Y11 // c4420509db
- //TODO: VPSLLD (BX), X9, X2 // c4e131f213 or c5b1f213
- //TODO: VPSLLD (R11), X9, X2 // c4c131f213
- //TODO: VPSLLD X2, X9, X2 // c4e131f2d2 or c5b1f2d2
- //TODO: VPSLLD X11, X9, X2 // c4c131f2d3
- //TODO: VPSLLD (BX), X9, X11 // c46131f21b or c531f21b
- //TODO: VPSLLD (R11), X9, X11 // c44131f21b
- //TODO: VPSLLD X2, X9, X11 // c46131f2da or c531f2da
- //TODO: VPSLLD X11, X9, X11 // c44131f2db
- //TODO: VPSLLD $7, X2, X9 // c4e13172f207 or c5b172f207
- //TODO: VPSLLD $7, X11, X9 // c4c13172f307
- //TODO: VPSLLDQ $7, X2, X9 // c4e13173fa07 or c5b173fa07
- //TODO: VPSLLDQ $7, X11, X9 // c4c13173fb07
- //TODO: VPSLLDQ $7, Y2, Y15 // c4e10573fa07 or c58573fa07
- //TODO: VPSLLDQ $7, Y11, Y15 // c4c10573fb07
- //TODO: VPSLLQ (BX), X9, X2 // c4e131f313 or c5b1f313
- //TODO: VPSLLQ (R11), X9, X2 // c4c131f313
- //TODO: VPSLLQ X2, X9, X2 // c4e131f3d2 or c5b1f3d2
- //TODO: VPSLLQ X11, X9, X2 // c4c131f3d3
- //TODO: VPSLLQ (BX), X9, X11 // c46131f31b or c531f31b
- //TODO: VPSLLQ (R11), X9, X11 // c44131f31b
- //TODO: VPSLLQ X2, X9, X11 // c46131f3da or c531f3da
- //TODO: VPSLLQ X11, X9, X11 // c44131f3db
- //TODO: VPSLLQ $7, X2, X9 // c4e13173f207 or c5b173f207
- //TODO: VPSLLQ $7, X11, X9 // c4c13173f307
+ VPSLLD (BX), X9, X2 // c4e131f213 or c5b1f213
+ VPSLLD (R11), X9, X2 // c4c131f213
+ VPSLLD X2, X9, X2 // c4e131f2d2 or c5b1f2d2
+ VPSLLD X11, X9, X2 // c4c131f2d3
+ VPSLLD (BX), X9, X11 // c46131f21b or c531f21b
+ VPSLLD (R11), X9, X11 // c44131f21b
+ VPSLLD X2, X9, X11 // c46131f2da or c531f2da
+ VPSLLD X11, X9, X11 // c44131f2db
+ VPSLLD $7, X2, X9 // c4e13172f207 or c5b172f207
+ VPSLLD $7, X11, X9 // c4c13172f307
+ VPSLLDQ $7, X2, X9 // c4e13173fa07 or c5b173fa07
+ VPSLLDQ $7, X11, X9 // c4c13173fb07
+ VPSLLDQ $7, Y2, Y15 // c4e10573fa07 or c58573fa07
+ VPSLLDQ $7, Y11, Y15 // c4c10573fb07
+ VPSLLQ (BX), X9, X2 // c4e131f313 or c5b1f313
+ VPSLLQ (R11), X9, X2 // c4c131f313
+ VPSLLQ X2, X9, X2 // c4e131f3d2 or c5b1f3d2
+ VPSLLQ X11, X9, X2 // c4c131f3d3
+ VPSLLQ (BX), X9, X11 // c46131f31b or c531f31b
+ VPSLLQ (R11), X9, X11 // c44131f31b
+ VPSLLQ X2, X9, X11 // c46131f3da or c531f3da
+ VPSLLQ X11, X9, X11 // c44131f3db
+ VPSLLQ $7, X2, X9 // c4e13173f207 or c5b173f207
+ VPSLLQ $7, X11, X9 // c4c13173f307
//TODO: VPSLLVD (BX), X9, X2 // c4e2314713
//TODO: VPSLLVD (R11), X9, X2 // c4c2314713
//TODO: VPSLLVD X2, X9, X2 // c4e23147d2
@@ -9738,30 +9738,30 @@ TEXT asmtest(SB),7,$0
//TODO: VPSRAW X11, Y15, Y11 // c44105e1db
//TODO: VPSRAW $7, Y2, Y15 // c4e10571e207 or c58571e207
//TODO: VPSRAW $7, Y11, Y15 // c4c10571e307
- //TODO: VPSRLD (BX), X9, X2 // c4e131d213 or c5b1d213
- //TODO: VPSRLD (R11), X9, X2 // c4c131d213
- //TODO: VPSRLD X2, X9, X2 // c4e131d2d2 or c5b1d2d2
- //TODO: VPSRLD X11, X9, X2 // c4c131d2d3
- //TODO: VPSRLD (BX), X9, X11 // c46131d21b or c531d21b
- //TODO: VPSRLD (R11), X9, X11 // c44131d21b
- //TODO: VPSRLD X2, X9, X11 // c46131d2da or c531d2da
- //TODO: VPSRLD X11, X9, X11 // c44131d2db
- //TODO: VPSRLD $7, X2, X9 // c4e13172d207 or c5b172d207
- //TODO: VPSRLD $7, X11, X9 // c4c13172d307
- //TODO: VPSRLDQ $7, X2, X9 // c4e13173da07 or c5b173da07
- //TODO: VPSRLDQ $7, X11, X9 // c4c13173db07
- //TODO: VPSRLDQ $7, Y2, Y15 // c4e10573da07 or c58573da07
- //TODO: VPSRLDQ $7, Y11, Y15 // c4c10573db07
- //TODO: VPSRLQ (BX), X9, X2 // c4e131d313 or c5b1d313
- //TODO: VPSRLQ (R11), X9, X2 // c4c131d313
- //TODO: VPSRLQ X2, X9, X2 // c4e131d3d2 or c5b1d3d2
- //TODO: VPSRLQ X11, X9, X2 // c4c131d3d3
- //TODO: VPSRLQ (BX), X9, X11 // c46131d31b or c531d31b
- //TODO: VPSRLQ (R11), X9, X11 // c44131d31b
- //TODO: VPSRLQ X2, X9, X11 // c46131d3da or c531d3da
- //TODO: VPSRLQ X11, X9, X11 // c44131d3db
- //TODO: VPSRLQ $7, X2, X9 // c4e13173d207 or c5b173d207
- //TODO: VPSRLQ $7, X11, X9 // c4c13173d307
+ VPSRLD (BX), X9, X2 // c4e131d213 or c5b1d213
+ VPSRLD (R11), X9, X2 // c4c131d213
+ VPSRLD X2, X9, X2 // c4e131d2d2 or c5b1d2d2
+ VPSRLD X11, X9, X2 // c4c131d2d3
+ VPSRLD (BX), X9, X11 // c46131d21b or c531d21b
+ VPSRLD (R11), X9, X11 // c44131d21b
+ VPSRLD X2, X9, X11 // c46131d2da or c531d2da
+ VPSRLD X11, X9, X11 // c44131d2db
+ VPSRLD $7, X2, X9 // c4e13172d207 or c5b172d207
+ VPSRLD $7, X11, X9 // c4c13172d307
+ VPSRLDQ $7, X2, X9 // c4e13173da07 or c5b173da07
+ VPSRLDQ $7, X11, X9 // c4c13173db07
+ VPSRLDQ $7, Y2, Y15 // c4e10573da07 or c58573da07
+ VPSRLDQ $7, Y11, Y15 // c4c10573db07
+ VPSRLQ (BX), X9, X2 // c4e131d313 or c5b1d313
+ VPSRLQ (R11), X9, X2 // c4c131d313
+ VPSRLQ X2, X9, X2 // c4e131d3d2 or c5b1d3d2
+ VPSRLQ X11, X9, X2 // c4c131d3d3
+ VPSRLQ (BX), X9, X11 // c46131d31b or c531d31b
+ VPSRLQ (R11), X9, X11 // c44131d31b
+ VPSRLQ X2, X9, X11 // c46131d3da or c531d3da
+ VPSRLQ X11, X9, X11 // c44131d3db
+ VPSRLQ $7, X2, X9 // c4e13173d207 or c5b173d207
+ VPSRLQ $7, X11, X9 // c4c13173d307
//TODO: VPSRLVD (BX), X9, X2 // c4e2314513
//TODO: VPSRLVD (R11), X9, X2 // c4c2314513
//TODO: VPSRLVD X2, X9, X2 // c4e23145d2
diff --git a/src/cmd/internal/obj/util.go b/src/cmd/internal/obj/util.go
index 294cedcb0a25a3..18813c35a8ea3e 100644
--- a/src/cmd/internal/obj/util.go
+++ b/src/cmd/internal/obj/util.go
@@ -140,6 +140,11 @@ func (p *Prog) String() string {
fmt.Fprintf(&buf, "%.5d (%v)\t%v%s", p.Pc, p.Line(), Aconv(p.As), sc)
sep := "\t"
+ quadOpAmd64 := p.RegTo2 == -1
+ if quadOpAmd64 {
+ fmt.Fprintf(&buf, "%s$%d", sep, p.From3.Offset)
+ sep = ", "
+ }
if p.From.Type != TYPE_NONE {
fmt.Fprintf(&buf, "%s%v", sep, Dconv(p, &p.From))
sep = ", "
@@ -153,6 +158,8 @@ func (p *Prog) String() string {
if p.From3.Type == TYPE_CONST && (p.As == ATEXT || p.As == AGLOBL) {
// Special case - omit $.
fmt.Fprintf(&buf, "%s%d", sep, p.From3.Offset)
+ } else if quadOpAmd64 {
+ fmt.Fprintf(&buf, "%s%v", sep, Rconv(int(p.From3.Reg)))
} else {
fmt.Fprintf(&buf, "%s%v", sep, Dconv(p, p.From3))
}
@@ -161,7 +168,7 @@ func (p *Prog) String() string {
if p.To.Type != TYPE_NONE {
fmt.Fprintf(&buf, "%s%v", sep, Dconv(p, &p.To))
}
- if p.RegTo2 != REG_NONE {
+ if p.RegTo2 != REG_NONE && !quadOpAmd64 {
fmt.Fprintf(&buf, "%s%v", sep, Rconv(int(p.RegTo2)))
}
return buf.String()
diff --git a/src/cmd/internal/obj/x86/a.out.go b/src/cmd/internal/obj/x86/a.out.go
index f00e4afdb8f7ac..ab1dabc2b89735 100644
--- a/src/cmd/internal/obj/x86/a.out.go
+++ b/src/cmd/internal/obj/x86/a.out.go
@@ -785,6 +785,24 @@ const (
AVPAND
AVPTEST
AVPBROADCASTB
+ AVPSHUFB
+ AVPSHUFD
+ AVPERM2F128
+ AVPALIGNR
+ AVPADDQ
+ AVPADDD
+ AVPSRLDQ
+ AVPSLLDQ
+ AVPSRLQ
+ AVPSLLQ
+ AVPSRLD
+ AVPSLLD
+ AVPOR
+ AVPBLENDD
+ AVINSERTI128
+ AVPERM2I128
+ ARORXL
+ ARORXQ
// from 386
AJCXZW
diff --git a/src/cmd/internal/obj/x86/anames.go b/src/cmd/internal/obj/x86/anames.go
index e3fef54e717510..3b301546258431 100644
--- a/src/cmd/internal/obj/x86/anames.go
+++ b/src/cmd/internal/obj/x86/anames.go
@@ -720,6 +720,24 @@ var Anames = []string{
"VPAND",
"VPTEST",
"VPBROADCASTB",
+ "VPSHUFB",
+ "VPSHUFD",
+ "VPERM2F128",
+ "VPALIGNR",
+ "VPADDQ",
+ "VPADDD",
+ "VPSRLDQ",
+ "VPSLLDQ",
+ "VPSRLQ",
+ "VPSLLQ",
+ "VPSRLD",
+ "VPSLLD",
+ "VPOR",
+ "VPBLENDD",
+ "VINSERTI128",
+ "VPERM2I128",
+ "RORXL",
+ "RORXQ",
"JCXZW",
"FCMOVCC",
"FCMOVCS",
diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go
index 8605980b94d996..9230c9fdacb1da 100644
--- a/src/cmd/internal/obj/x86/asm6.go
+++ b/src/cmd/internal/obj/x86/asm6.go
@@ -208,6 +208,9 @@ const (
Zvex_rm_v_r
Zvex_r_v_rm
Zvex_v_rm_r
+ Zvex_i_rm_r
+ Zvex_i_r_v
+ Zvex_i_rm_v_r
Zmax
)
@@ -847,6 +850,35 @@ var yvex_xy3 = []ytab{
{Yym, Yyr, Yyr, Zvex_rm_v_r, 2},
}
+var yvex_ri3 = []ytab{
+ {Yi8, Ymb, Yrl, Zvex_i_rm_r, 2},
+}
+
+var yvex_xyi3 = []ytab{
+ {Yi8, Yxm, Yxr, Zvex_i_rm_r, 2},
+ {Yi8, Yym, Yyr, Zvex_i_rm_r, 2},
+}
+
+var yvex_yyi4 = []ytab{ //TODO don't hide 4 op, some version have xmm version
+ {Yym, Yyr, Yyr, Zvex_i_rm_v_r, 2},
+}
+
+var yvex_xyi4 = []ytab{
+ {Yxm, Yyr, Yyr, Zvex_i_rm_v_r, 2},
+}
+
+var yvex_shift = []ytab{
+ {Yi8, Yxr, Yxr, Zvex_i_r_v, 3},
+ {Yi8, Yyr, Yyr, Zvex_i_r_v, 3},
+ {Yxm, Yxr, Yxr, Zvex_rm_v_r, 2},
+ {Yxm, Yyr, Yyr, Zvex_rm_v_r, 2},
+}
+
+var yvex_shift_dq = []ytab{
+ {Yi8, Yxr, Yxr, Zvex_i_r_v, 3},
+ {Yi8, Yyr, Yyr, Zvex_i_r_v, 3},
+}
+
var yvex_r3 = []ytab{
{Yml, Yrl, Yrl, Zvex_rm_v_r, 2},
{Yml, Yrl, Yrl, Zvex_rm_v_r, 2},
@@ -1679,6 +1711,24 @@ var optab =
{AVPAND, yvex_xy3, Pvex, [23]uint8{VEX_128_66_0F_WIG, 0xDB, VEX_256_66_0F_WIG, 0xDB}},
{AVPBROADCASTB, yvex_vpbroadcast, Pvex, [23]uint8{VEX_128_66_0F38_W0, 0x78, VEX_256_66_0F38_W0, 0x78}},
{AVPTEST, yvex_xy2, Pvex, [23]uint8{VEX_128_66_0F38_WIG, 0x17, VEX_256_66_0F38_WIG, 0x17}},
+ {AVPSHUFB, yvex_xy3, Pvex, [23]uint8{VEX_128_66_0F38_WIG, 0x00, VEX_256_66_0F38_WIG, 0x00}},
+ {AVPSHUFD, yvex_xyi3, Pvex, [23]uint8{VEX_128_66_0F_WIG, 0x70, VEX_256_66_0F_WIG, 0x70}},
+ {AVPOR, yvex_xy3, Pvex, [23]uint8{VEX_128_66_0F_WIG, 0xeb, VEX_256_66_0F_WIG, 0xeb}},
+ {AVPADDQ, yvex_xy3, Pvex, [23]uint8{VEX_128_66_0F_WIG, 0xd4, VEX_256_66_0F_WIG, 0xd4}},
+ {AVPADDD, yvex_xy3, Pvex, [23]uint8{VEX_128_66_0F_WIG, 0xfe, VEX_256_66_0F_WIG, 0xfe}},
+ {AVPSLLD, yvex_shift, Pvex, [23]uint8{VEX_128_66_0F_WIG, 0x72, 0xf0, VEX_256_66_0F_WIG, 0x72, 0xf0, VEX_128_66_0F_WIG, 0xf2, VEX_256_66_0F_WIG, 0xf2}},
+ {AVPSLLQ, yvex_shift, Pvex, [23]uint8{VEX_128_66_0F_WIG, 0x73, 0xf0, VEX_256_66_0F_WIG, 0x73, 0xf0, VEX_128_66_0F_WIG, 0xf3, VEX_256_66_0F_WIG, 0xf3}},
+ {AVPSRLD, yvex_shift, Pvex, [23]uint8{VEX_128_66_0F_WIG, 0x72, 0xd0, VEX_256_66_0F_WIG, 0x72, 0xd0, VEX_128_66_0F_WIG, 0xd2, VEX_256_66_0F_WIG, 0xd2}},
+ {AVPSRLQ, yvex_shift, Pvex, [23]uint8{VEX_128_66_0F_WIG, 0x73, 0xd0, VEX_256_66_0F_WIG, 0x73, 0xd0, VEX_128_66_0F_WIG, 0xd3, VEX_256_66_0F_WIG, 0xd3}},
+ {AVPSRLDQ, yvex_shift_dq, Pvex, [23]uint8{VEX_128_66_0F_WIG, 0x73, 0xd8, VEX_256_66_0F_WIG, 0x73, 0xd8}},
+ {AVPSLLDQ, yvex_shift_dq, Pvex, [23]uint8{VEX_128_66_0F_WIG, 0x73, 0xf8, VEX_256_66_0F_WIG, 0x73, 0xf8}},
+ {AVPERM2F128, yvex_yyi4, Pvex, [23]uint8{VEX_256_66_0F3A_W0, 0x06}},
+ {AVPALIGNR, yvex_yyi4, Pvex, [23]uint8{VEX_256_66_0F3A_WIG, 0x0f}},
+ {AVPBLENDD, yvex_yyi4, Pvex, [23]uint8{VEX_256_66_0F3A_WIG, 0x02}},
+ {AVINSERTI128, yvex_xyi4, Pvex, [23]uint8{VEX_256_66_0F3A_WIG, 0x38}},
+ {AVPERM2I128, yvex_yyi4, Pvex, [23]uint8{VEX_256_66_0F3A_WIG, 0x46}},
+ {ARORXL, yvex_ri3, Pvex, [23]uint8{VEX_LZ_F2_0F3A_W0, 0xf0}},
+ {ARORXQ, yvex_ri3, Pvex, [23]uint8{VEX_LZ_F2_0F3A_W1, 0xf0}},
{AXACQUIRE, ynone, Px, [23]uint8{0xf2}},
{AXRELEASE, ynone, Px, [23]uint8{0xf3}},
@@ -3189,9 +3239,16 @@ var bpduff2 = []byte{
// https://en.wikipedia.org/wiki/VEX_prefix#Technical_description
func asmvex(ctxt *obj.Link, rm, v, r *obj.Addr, vex, opcode uint8) {
ctxt.Vexflag = 1
- rexR := regrex[r.Reg] & Rxr
- rexB := regrex[rm.Reg] & Rxb
- rexX := regrex[rm.Index] & Rxx
+ rexR := 0
+ if r != nil {
+ rexR = regrex[r.Reg] & Rxr
+ }
+ rexB := 0
+ rexX := 0
+ if rm != nil {
+ rexB = regrex[rm.Reg] & Rxb
+ rexX = regrex[rm.Index] & Rxx
+ }
vexM := (vex >> 3) & 0xF
vexWLP := vex & 0x87
vexV := byte(0)
@@ -3477,6 +3534,27 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
asmvex(ctxt, &p.From, p.From3, &p.To, o.op[z], o.op[z+1])
asmand(ctxt, p, &p.From, &p.To)
+ case Zvex_i_r_v:
+ asmvex(ctxt, p.From3, &p.To, nil, o.op[z], o.op[z+1])
+ regnum := byte(0x7)
+ if p.From3.Reg >= REG_X0 && p.From3.Reg <= REG_X15 {
+ regnum &= byte(p.From3.Reg - REG_X0)
+ } else {
+ regnum &= byte(p.From3.Reg - REG_Y0)
+ }
+ ctxt.AsmBuf.Put1(byte(o.op[z+2]) | regnum)
+ ctxt.AsmBuf.Put1(byte(p.From.Offset))
+
+ case Zvex_i_rm_v_r:
+ asmvex(ctxt, &p.From, p.From3, &p.To, o.op[z], o.op[z+1])
+ asmand(ctxt, p, &p.From, &p.To)
+ ctxt.AsmBuf.Put1(byte(p.From3.Offset))
+
+ case Zvex_i_rm_r:
+ asmvex(ctxt, p.From3, nil, &p.To, o.op[z], o.op[z+1])
+ asmand(ctxt, p, p.From3, &p.To)
+ ctxt.AsmBuf.Put1(byte(p.From.Offset))
+
case Zvex_v_rm_r:
asmvex(ctxt, p.From3, &p.From, &p.To, o.op[z], o.op[z+1])
asmand(ctxt, p, p.From3, &p.To)
From e558fdbd9a3865dd383f50524bb8a18b9e6a0cb0 Mon Sep 17 00:00:00 2001
From: Elias Naur
Date: Fri, 6 May 2016 15:09:57 +0200
Subject: [PATCH 014/267] misc/cgo/testcarchive: don't force -no_pie on Darwin
Now that darwin/arm supports position independent code, allow the
binaries generated by the c-archive tests be position independent
(PIE) as well.
Change-Id: If0517f06e92349ada29a4e3e0a951f08b0fcc710
Reviewed-on: https://go-review.googlesource.com/22841
Reviewed-by: David Crawshaw
Run-TryBot: Elias Naur
TryBot-Result: Gobot Gobot
---
misc/cgo/testcarchive/carchive_test.go | 2 --
1 file changed, 2 deletions(-)
diff --git a/misc/cgo/testcarchive/carchive_test.go b/misc/cgo/testcarchive/carchive_test.go
index c0c45398cda9db..0174e310156928 100644
--- a/misc/cgo/testcarchive/carchive_test.go
+++ b/misc/cgo/testcarchive/carchive_test.go
@@ -79,8 +79,6 @@ func init() {
}
if GOOS == "darwin" {
- cc = append(cc, "-Wl,-no_pie")
-
// For Darwin/ARM.
// TODO(crawshaw): can we do better?
cc = append(cc, []string{"-framework", "CoreFoundation", "-framework", "Foundation"}...)
From 2210d88a889e0ea463bcdef2b658aaec1050cf01 Mon Sep 17 00:00:00 2001
From: Ilya Tocar
Date: Fri, 29 Apr 2016 16:19:17 +0300
Subject: [PATCH 015/267] crypto/sha256: Use AVX2 if possible
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
name old time/op new time/op delta
Hash8Bytes-4 376ns ± 0% 246ns ± 0% -34.57% (p=0.000 n=20+20)
Hash1K-4 5.21µs ± 0% 2.82µs ± 0% -45.83% (p=0.000 n=20+20)
Hash8K-4 38.6µs ± 0% 20.8µs ± 0% -46.05% (p=0.000 n=20+20)
name old speed new speed delta
Hash8Bytes-4 21.2MB/s ± 0% 32.4MB/s ± 0% +52.70% (p=0.000 n=15+19)
Hash1K-4 197MB/s ± 0% 363MB/s ± 0% +84.60% (p=0.000 n=20+20)
Hash8K-4 212MB/s ± 0% 393MB/s ± 0% +85.36% (p=0.000 n=20+20)
Change-Id: Ib50119c591074ff486d11d3566e24b691bcc6598
Reviewed-on: https://go-review.googlesource.com/22608
Run-TryBot: Russ Cox
TryBot-Result: Gobot Gobot
Reviewed-by: Russ Cox
---
src/crypto/sha256/sha256block_amd64.s | 873 ++++++++++++++++++++++++--
1 file changed, 829 insertions(+), 44 deletions(-)
diff --git a/src/crypto/sha256/sha256block_amd64.s b/src/crypto/sha256/sha256block_amd64.s
index c9f134c1069082..6ab3b52d65e163 100644
--- a/src/crypto/sha256/sha256block_amd64.s
+++ b/src/crypto/sha256/sha256block_amd64.s
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// 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.
@@ -9,7 +9,18 @@
// The algorithm is detailed in FIPS 180-4:
//
// http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
-//
+
+// The avx2-version is described in an Intel White-Paper:
+// "Fast SHA-256 Implementations on Intel Architecture Processors"
+// To find it, surf to http://www.intel.com/p/en_US/embedded
+// and search for that title.
+// AVX2 version by Intel, same algorithm as code in Linux kernel:
+// https://github.com/torvalds/linux/blob/master/arch/x86/crypto/sha256-avx2-asm.S
+// by
+// James Guilford
+// Kirk Yap
+// Tim Chen
+
// Wt = Mt; for 0 <= t <= 15
// Wt = SIGMA1(Wt-2) + SIGMA0(Wt-15) + Wt-16; for 16 <= t <= 63
//
@@ -140,29 +151,439 @@
MSGSCHEDULE1(index); \
SHA256ROUND(index, const, a, b, c, d, e, f, g, h)
-TEXT ·block(SB),0,$264-32
- MOVQ p_base+8(FP), SI
- MOVQ p_len+16(FP), DX
- SHRQ $6, DX
- SHLQ $6, DX
-
- LEAQ (SI)(DX*1), DI
- MOVQ DI, 256(SP)
- CMPQ SI, DI
- JEQ end
-
- MOVQ dig+0(FP), BP
- MOVL (0*4)(BP), R8 // a = H0
- MOVL (1*4)(BP), R9 // b = H1
- MOVL (2*4)(BP), R10 // c = H2
- MOVL (3*4)(BP), R11 // d = H3
- MOVL (4*4)(BP), R12 // e = H4
- MOVL (5*4)(BP), R13 // f = H5
- MOVL (6*4)(BP), R14 // g = H6
- MOVL (7*4)(BP), R15 // h = H7
+
+// Definitions for AVX2 version
+
+// addm (mem), reg
+// Add reg to mem using reg-mem add and store
+#define addm(P1, P2) \
+ ADDL P2, P1; \
+ MOVL P1, P2
+
+#define XDWORD0 Y4
+#define XDWORD1 Y5
+#define XDWORD2 Y6
+#define XDWORD3 Y7
+
+#define XWORD0 X4
+#define XWORD1 X5
+#define XWORD2 X6
+#define XWORD3 X7
+
+#define XTMP0 Y0
+#define XTMP1 Y1
+#define XTMP2 Y2
+#define XTMP3 Y3
+#define XTMP4 Y8
+#define XTMP5 Y11
+
+#define XFER Y9
+
+#define BYTE_FLIP_MASK Y13 // mask to convert LE -> BE
+#define X_BYTE_FLIP_MASK X13
+
+#define NUM_BYTES DX
+#define INP DI
+
+#define CTX SI // Beginning of digest in memory (a, b, c, ... , h)
+
+#define a AX
+#define b BX
+#define c CX
+#define d R8
+#define e DX
+#define f R9
+#define g R10
+#define h R11
+
+#define old_h R11
+
+#define TBL BP
+
+#define SRND SI // SRND is same register as CTX
+
+#define T1 R12
+
+#define y0 R13
+#define y1 R14
+#define y2 R15
+#define y3 DI
+
+// Offsets
+#define XFER_SIZE 2*64*4
+#define INP_END_SIZE 8
+#define INP_SIZE 8
+#define TMP_SIZE 4
+
+#define _XFER 0
+#define _INP_END _XFER + XFER_SIZE
+#define _INP _INP_END + INP_END_SIZE
+#define _TMP _INP + INP_SIZE
+#define STACK_SIZE _TMP + TMP_SIZE
+
+#define ROUND_AND_SCHED_N_0(disp, a, b, c, d, e, f, g, h, XDWORD0, XDWORD1, XDWORD2, XDWORD3) \
+ ; \ // ############################# RND N + 0 ############################//
+ MOVL a, y3; \ // y3 = a // MAJA
+ RORXL $25, e, y0; \ // y0 = e >> 25 // S1A
+ RORXL $11, e, y1; \ // y1 = e >> 11 // S1B
+ ; \
+ ADDL (disp + 0*4)(SP)(SRND*1), h; \ // h = k + w + h // disp = k + w
+ ORL c, y3; \ // y3 = a|c // MAJA
+ VPALIGNR $4, XDWORD2, XDWORD3, XTMP0; \ // XTMP0 = W[-7]
+ MOVL f, y2; \ // y2 = f // CH
+ RORXL $13, a, T1; \ // T1 = a >> 13 // S0B
+ ; \
+ XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) // S1
+ XORL g, y2; \ // y2 = f^g // CH
+ VPADDD XDWORD0, XTMP0, XTMP0; \ // XTMP0 = W[-7] + W[-16] // y1 = (e >> 6) // S1
+ RORXL $6, e, y1; \ // y1 = (e >> 6) // S1
+ ; \
+ ANDL e, y2; \ // y2 = (f^g)&e // CH
+ XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) ^ (e>>6) // S1
+ RORXL $22, a, y1; \ // y1 = a >> 22 // S0A
+ ADDL h, d; \ // d = k + w + h + d // --
+ ; \
+ ANDL b, y3; \ // y3 = (a|c)&b // MAJA
+ VPALIGNR $4, XDWORD0, XDWORD1, XTMP1; \ // XTMP1 = W[-15]
+ XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) // S0
+ RORXL $2, a, T1; \ // T1 = (a >> 2) // S0
+ ; \
+ XORL g, y2; \ // y2 = CH = ((f^g)&e)^g // CH
+ VPSRLD $7, XTMP1, XTMP2; \
+ XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) ^ (a>>2) // S0
+ MOVL a, T1; \ // T1 = a // MAJB
+ ANDL c, T1; \ // T1 = a&c // MAJB
+ ; \
+ ADDL y0, y2; \ // y2 = S1 + CH // --
+ VPSLLD $(32-7), XTMP1, XTMP3; \
+ ORL T1, y3; \ // y3 = MAJ = (a|c)&b)|(a&c) // MAJ
+ ADDL y1, h; \ // h = k + w + h + S0 // --
+ ; \
+ ADDL y2, d; \ // d = k + w + h + d + S1 + CH = d + t1 // --
+ VPOR XTMP2, XTMP3, XTMP3; \ // XTMP3 = W[-15] ror 7
+ ; \
+ VPSRLD $18, XTMP1, XTMP2; \
+ ADDL y2, h; \ // h = k + w + h + S0 + S1 + CH = t1 + S0// --
+ ADDL y3, h // h = t1 + S0 + MAJ // --
+
+#define ROUND_AND_SCHED_N_1(disp, a, b, c, d, e, f, g, h, XDWORD0, XDWORD1, XDWORD2, XDWORD3) \
+ ; \ // ################################### RND N + 1 ############################
+ ; \
+ MOVL a, y3; \ // y3 = a // MAJA
+ RORXL $25, e, y0; \ // y0 = e >> 25 // S1A
+ RORXL $11, e, y1; \ // y1 = e >> 11 // S1B
+ ADDL (disp + 1*4)(SP)(SRND*1), h; \ // h = k + w + h // --
+ ORL c, y3; \ // y3 = a|c // MAJA
+ ; \
+ VPSRLD $3, XTMP1, XTMP4; \ // XTMP4 = W[-15] >> 3
+ MOVL f, y2; \ // y2 = f // CH
+ RORXL $13, a, T1; \ // T1 = a >> 13 // S0B
+ XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) // S1
+ XORL g, y2; \ // y2 = f^g // CH
+ ; \
+ RORXL $6, e, y1; \ // y1 = (e >> 6) // S1
+ XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) ^ (e>>6) // S1
+ RORXL $22, a, y1; \ // y1 = a >> 22 // S0A
+ ANDL e, y2; \ // y2 = (f^g)&e // CH
+ ADDL h, d; \ // d = k + w + h + d // --
+ ; \
+ VPSLLD $(32-18), XTMP1, XTMP1; \
+ ANDL b, y3; \ // y3 = (a|c)&b // MAJA
+ XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) // S0
+ ; \
+ VPXOR XTMP1, XTMP3, XTMP3; \
+ RORXL $2, a, T1; \ // T1 = (a >> 2) // S0
+ XORL g, y2; \ // y2 = CH = ((f^g)&e)^g // CH
+ ; \
+ VPXOR XTMP2, XTMP3, XTMP3; \ // XTMP3 = W[-15] ror 7 ^ W[-15] ror 18
+ XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) ^ (a>>2) // S0
+ MOVL a, T1; \ // T1 = a // MAJB
+ ANDL c, T1; \ // T1 = a&c // MAJB
+ ADDL y0, y2; \ // y2 = S1 + CH // --
+ ; \
+ VPXOR XTMP4, XTMP3, XTMP1; \ // XTMP1 = s0
+ VPSHUFD $-6, XDWORD3, XTMP2; \ // XTMP2 = W[-2] {BBAA}
+ ORL T1, y3; \ // y3 = MAJ = (a|c)&b)|(a&c) // MAJ
+ ADDL y1, h; \ // h = k + w + h + S0 // --
+ ; \
+ VPADDD XTMP1, XTMP0, XTMP0; \ // XTMP0 = W[-16] + W[-7] + s0
+ ADDL y2, d; \ // d = k + w + h + d + S1 + CH = d + t1 // --
+ ADDL y2, h; \ // h = k + w + h + S0 + S1 + CH = t1 + S0// --
+ ADDL y3, h; \ // h = t1 + S0 + MAJ // --
+ ; \
+ VPSRLD $10, XTMP2, XTMP4 // XTMP4 = W[-2] >> 10 {BBAA}
+
+#define ROUND_AND_SCHED_N_2(disp, a, b, c, d, e, f, g, h, XDWORD0, XDWORD1, XDWORD2, XDWORD3) \
+ ; \ // ################################### RND N + 2 ############################
+ ; \
+ MOVL a, y3; \ // y3 = a // MAJA
+ RORXL $25, e, y0; \ // y0 = e >> 25 // S1A
+ ADDL (disp + 2*4)(SP)(SRND*1), h; \ // h = k + w + h // --
+ ; \
+ VPSRLQ $19, XTMP2, XTMP3; \ // XTMP3 = W[-2] ror 19 {xBxA}
+ RORXL $11, e, y1; \ // y1 = e >> 11 // S1B
+ ORL c, y3; \ // y3 = a|c // MAJA
+ MOVL f, y2; \ // y2 = f // CH
+ XORL g, y2; \ // y2 = f^g // CH
+ ; \
+ RORXL $13, a, T1; \ // T1 = a >> 13 // S0B
+ XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) // S1
+ VPSRLQ $17, XTMP2, XTMP2; \ // XTMP2 = W[-2] ror 17 {xBxA}
+ ANDL e, y2; \ // y2 = (f^g)&e // CH
+ ; \
+ RORXL $6, e, y1; \ // y1 = (e >> 6) // S1
+ VPXOR XTMP3, XTMP2, XTMP2; \
+ ADDL h, d; \ // d = k + w + h + d // --
+ ANDL b, y3; \ // y3 = (a|c)&b // MAJA
+ ; \
+ XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) ^ (e>>6) // S1
+ RORXL $22, a, y1; \ // y1 = a >> 22 // S0A
+ VPXOR XTMP2, XTMP4, XTMP4; \ // XTMP4 = s1 {xBxA}
+ XORL g, y2; \ // y2 = CH = ((f^g)&e)^g // CH
+ ; \
+ MOVL f, _TMP(SP); \
+ MOVQ $shuff_00BA<>(SB), f; \ // f is used to keep SHUF_00BA
+ VPSHUFB (f), XTMP4, XTMP4; \ // XTMP4 = s1 {00BA}
+ MOVL _TMP(SP), f; \ // f is restored
+ ; \
+ XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) // S0
+ RORXL $2, a, T1; \ // T1 = (a >> 2) // S0
+ VPADDD XTMP4, XTMP0, XTMP0; \ // XTMP0 = {..., ..., W[1], W[0]}
+ ; \
+ XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) ^ (a>>2) // S0
+ MOVL a, T1; \ // T1 = a // MAJB
+ ANDL c, T1; \ // T1 = a&c // MAJB
+ ADDL y0, y2; \ // y2 = S1 + CH // --
+ VPSHUFD $80, XTMP0, XTMP2; \ // XTMP2 = W[-2] {DDCC}
+ ; \
+ ORL T1, y3; \ // y3 = MAJ = (a|c)&b)|(a&c) // MAJ
+ ADDL y1, h; \ // h = k + w + h + S0 // --
+ ADDL y2, d; \ // d = k + w + h + d + S1 + CH = d + t1 // --
+ ADDL y2, h; \ // h = k + w + h + S0 + S1 + CH = t1 + S0// --
+ ; \
+ ADDL y3, h // h = t1 + S0 + MAJ // --
+
+#define ROUND_AND_SCHED_N_3(disp, a, b, c, d, e, f, g, h, XDWORD0, XDWORD1, XDWORD2, XDWORD3) \
+ ; \ // ################################### RND N + 3 ############################
+ ; \
+ MOVL a, y3; \ // y3 = a // MAJA
+ RORXL $25, e, y0; \ // y0 = e >> 25 // S1A
+ RORXL $11, e, y1; \ // y1 = e >> 11 // S1B
+ ADDL (disp + 3*4)(SP)(SRND*1), h; \ // h = k + w + h // --
+ ORL c, y3; \ // y3 = a|c // MAJA
+ ; \
+ VPSRLD $10, XTMP2, XTMP5; \ // XTMP5 = W[-2] >> 10 {DDCC}
+ MOVL f, y2; \ // y2 = f // CH
+ RORXL $13, a, T1; \ // T1 = a >> 13 // S0B
+ XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) // S1
+ XORL g, y2; \ // y2 = f^g // CH
+ ; \
+ VPSRLQ $19, XTMP2, XTMP3; \ // XTMP3 = W[-2] ror 19 {xDxC}
+ RORXL $6, e, y1; \ // y1 = (e >> 6) // S1
+ ANDL e, y2; \ // y2 = (f^g)&e // CH
+ ADDL h, d; \ // d = k + w + h + d // --
+ ANDL b, y3; \ // y3 = (a|c)&b // MAJA
+ ; \
+ VPSRLQ $17, XTMP2, XTMP2; \ // XTMP2 = W[-2] ror 17 {xDxC}
+ XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) ^ (e>>6) // S1
+ XORL g, y2; \ // y2 = CH = ((f^g)&e)^g // CH
+ ; \
+ VPXOR XTMP3, XTMP2, XTMP2; \
+ RORXL $22, a, y1; \ // y1 = a >> 22 // S0A
+ ADDL y0, y2; \ // y2 = S1 + CH // --
+ ; \
+ VPXOR XTMP2, XTMP5, XTMP5; \ // XTMP5 = s1 {xDxC}
+ XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) // S0
+ ADDL y2, d; \ // d = k + w + h + d + S1 + CH = d + t1 // --
+ ; \
+ RORXL $2, a, T1; \ // T1 = (a >> 2) // S0
+ ; \
+ MOVL f, _TMP(SP); \ // Save f
+ MOVQ $shuff_DC00<>(SB), f; \ // SHUF_00DC
+ VPSHUFB (f), XTMP5, XTMP5; \ // XTMP5 = s1 {DC00}
+ MOVL _TMP(SP), f; \ // Restore f
+ ; \
+ VPADDD XTMP0, XTMP5, XDWORD0; \ // XDWORD0 = {W[3], W[2], W[1], W[0]}
+ XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) ^ (a>>2) // S0
+ MOVL a, T1; \ // T1 = a // MAJB
+ ANDL c, T1; \ // T1 = a&c // MAJB
+ ORL T1, y3; \ // y3 = MAJ = (a|c)&b)|(a&c) // MAJ
+ ; \
+ ADDL y1, h; \ // h = k + w + h + S0 // --
+ ADDL y2, h; \ // h = k + w + h + S0 + S1 + CH = t1 + S0// --
+ ADDL y3, h // h = t1 + S0 + MAJ // --
+
+#define DO_ROUND_N_0(disp, a, b, c, d, e, f, g, h, old_h) \
+ ; \ // ################################### RND N + 0 ###########################
+ MOVL f, y2; \ // y2 = f // CH
+ RORXL $25, e, y0; \ // y0 = e >> 25 // S1A
+ RORXL $11, e, y1; \ // y1 = e >> 11 // S1B
+ XORL g, y2; \ // y2 = f^g // CH
+ ; \
+ XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) // S1
+ RORXL $6, e, y1; \ // y1 = (e >> 6) // S1
+ ANDL e, y2; \ // y2 = (f^g)&e // CH
+ ; \
+ XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) ^ (e>>6) // S1
+ RORXL $13, a, T1; \ // T1 = a >> 13 // S0B
+ XORL g, y2; \ // y2 = CH = ((f^g)&e)^g // CH
+ RORXL $22, a, y1; \ // y1 = a >> 22 // S0A
+ MOVL a, y3; \ // y3 = a // MAJA
+ ; \
+ XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) // S0
+ RORXL $2, a, T1; \ // T1 = (a >> 2) // S0
+ ADDL (disp + 0*4)(SP)(SRND*1), h; \ // h = k + w + h // --
+ ORL c, y3; \ // y3 = a|c // MAJA
+ ; \
+ XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) ^ (a>>2) // S0
+ MOVL a, T1; \ // T1 = a // MAJB
+ ANDL b, y3; \ // y3 = (a|c)&b // MAJA
+ ANDL c, T1; \ // T1 = a&c // MAJB
+ ADDL y0, y2; \ // y2 = S1 + CH // --
+ ; \
+ ADDL h, d; \ // d = k + w + h + d // --
+ ORL T1, y3; \ // y3 = MAJ = (a|c)&b)|(a&c) // MAJ
+ ADDL y1, h; \ // h = k + w + h + S0 // --
+ ADDL y2, d // d = k + w + h + d + S1 + CH = d + t1 // --
+
+#define DO_ROUND_N_1(disp, a, b, c, d, e, f, g, h, old_h) \
+ ; \ // ################################### RND N + 1 ###########################
+ ADDL y2, old_h; \ // h = k + w + h + S0 + S1 + CH = t1 + S0 // --
+ MOVL f, y2; \ // y2 = f // CH
+ RORXL $25, e, y0; \ // y0 = e >> 25 // S1A
+ RORXL $11, e, y1; \ // y1 = e >> 11 // S1B
+ XORL g, y2; \ // y2 = f^g // CH
+ ; \
+ XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) // S1
+ RORXL $6, e, y1; \ // y1 = (e >> 6) // S1
+ ANDL e, y2; \ // y2 = (f^g)&e // CH
+ ADDL y3, old_h; \ // h = t1 + S0 + MAJ // --
+ ; \
+ XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) ^ (e>>6) // S1
+ RORXL $13, a, T1; \ // T1 = a >> 13 // S0B
+ XORL g, y2; \ // y2 = CH = ((f^g)&e)^g // CH
+ RORXL $22, a, y1; \ // y1 = a >> 22 // S0A
+ MOVL a, y3; \ // y3 = a // MAJA
+ ; \
+ XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) // S0
+ RORXL $2, a, T1; \ // T1 = (a >> 2) // S0
+ ADDL (disp + 1*4)(SP)(SRND*1), h; \ // h = k + w + h // --
+ ORL c, y3; \ // y3 = a|c // MAJA
+ ; \
+ XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) ^ (a>>2) // S0
+ MOVL a, T1; \ // T1 = a // MAJB
+ ANDL b, y3; \ // y3 = (a|c)&b // MAJA
+ ANDL c, T1; \ // T1 = a&c // MAJB
+ ADDL y0, y2; \ // y2 = S1 + CH // --
+ ; \
+ ADDL h, d; \ // d = k + w + h + d // --
+ ORL T1, y3; \ // y3 = MAJ = (a|c)&b)|(a&c) // MAJ
+ ADDL y1, h; \ // h = k + w + h + S0 // --
+ ; \
+ ADDL y2, d // d = k + w + h + d + S1 + CH = d + t1 // --
+
+#define DO_ROUND_N_2(disp, a, b, c, d, e, f, g, h, old_h) \
+ ; \ // ################################### RND N + 2 ##############################
+ ADDL y2, old_h; \ // h = k + w + h + S0 + S1 + CH = t1 + S0// --
+ MOVL f, y2; \ // y2 = f // CH
+ RORXL $25, e, y0; \ // y0 = e >> 25 // S1A
+ RORXL $11, e, y1; \ // y1 = e >> 11 // S1B
+ XORL g, y2; \ // y2 = f^g // CH
+ ; \
+ XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) // S1
+ RORXL $6, e, y1; \ // y1 = (e >> 6) // S1
+ ANDL e, y2; \ // y2 = (f^g)&e // CH
+ ADDL y3, old_h; \ // h = t1 + S0 + MAJ // --
+ ; \
+ XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) ^ (e>>6) // S1
+ RORXL $13, a, T1; \ // T1 = a >> 13 // S0B
+ XORL g, y2; \ // y2 = CH = ((f^g)&e)^g // CH
+ RORXL $22, a, y1; \ // y1 = a >> 22 // S0A
+ MOVL a, y3; \ // y3 = a // MAJA
+ ; \
+ XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) // S0
+ RORXL $2, a, T1; \ // T1 = (a >> 2) // S0
+ ADDL (disp + 2*4)(SP)(SRND*1), h; \ // h = k + w + h // --
+ ORL c, y3; \ // y3 = a|c // MAJA
+ ; \
+ XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) ^ (a>>2) // S0
+ MOVL a, T1; \ // T1 = a // MAJB
+ ANDL b, y3; \ // y3 = (a|c)&b // MAJA
+ ANDL c, T1; \ // T1 = a&c // MAJB
+ ADDL y0, y2; \ // y2 = S1 + CH // --
+ ; \
+ ADDL h, d; \ // d = k + w + h + d // --
+ ORL T1, y3; \ // y3 = MAJ = (a|c)&b)|(a&c) // MAJ
+ ADDL y1, h; \ // h = k + w + h + S0 // --
+ ; \
+ ADDL y2, d // d = k + w + h + d + S1 + CH = d + t1 // --
+
+#define DO_ROUND_N_3(disp, a, b, c, d, e, f, g, h, old_h) \
+ ; \ // ################################### RND N + 3 ###########################
+ ADDL y2, old_h; \ // h = k + w + h + S0 + S1 + CH = t1 + S0// --
+ MOVL f, y2; \ // y2 = f // CH
+ RORXL $25, e, y0; \ // y0 = e >> 25 // S1A
+ RORXL $11, e, y1; \ // y1 = e >> 11 // S1B
+ XORL g, y2; \ // y2 = f^g // CH
+ ; \
+ XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) // S1
+ RORXL $6, e, y1; \ // y1 = (e >> 6) // S1
+ ANDL e, y2; \ // y2 = (f^g)&e // CH
+ ADDL y3, old_h; \ // h = t1 + S0 + MAJ // --
+ ; \
+ XORL y1, y0; \ // y0 = (e>>25) ^ (e>>11) ^ (e>>6) // S1
+ RORXL $13, a, T1; \ // T1 = a >> 13 // S0B
+ XORL g, y2; \ // y2 = CH = ((f^g)&e)^g // CH
+ RORXL $22, a, y1; \ // y1 = a >> 22 // S0A
+ MOVL a, y3; \ // y3 = a // MAJA
+ ; \
+ XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) // S0
+ RORXL $2, a, T1; \ // T1 = (a >> 2) // S0
+ ADDL (disp + 3*4)(SP)(SRND*1), h; \ // h = k + w + h // --
+ ORL c, y3; \ // y3 = a|c // MAJA
+ ; \
+ XORL T1, y1; \ // y1 = (a>>22) ^ (a>>13) ^ (a>>2) // S0
+ MOVL a, T1; \ // T1 = a // MAJB
+ ANDL b, y3; \ // y3 = (a|c)&b // MAJA
+ ANDL c, T1; \ // T1 = a&c // MAJB
+ ADDL y0, y2; \ // y2 = S1 + CH // --
+ ; \
+ ADDL h, d; \ // d = k + w + h + d // --
+ ORL T1, y3; \ // y3 = MAJ = (a|c)&b)|(a&c) // MAJ
+ ADDL y1, h; \ // h = k + w + h + S0 // --
+ ; \
+ ADDL y2, d; \ // d = k + w + h + d + S1 + CH = d + t1 // --
+ ; \
+ ADDL y2, h; \ // h = k + w + h + S0 + S1 + CH = t1 + S0// --
+ ; \
+ ADDL y3, h // h = t1 + S0 + MAJ // --
+
+TEXT ·block(SB), 0, $536-32
+ CMPB runtime·support_avx2(SB), $1
+ JE avx2
+
+ MOVQ p_base+8(FP), SI
+ MOVQ p_len+16(FP), DX
+ SHRQ $6, DX
+ SHLQ $6, DX
+
+ LEAQ (SI)(DX*1), DI
+ MOVQ DI, 256(SP)
+ CMPQ SI, DI
+ JEQ end
+
+ MOVQ dig+0(FP), BP
+ MOVL (0*4)(BP), R8 // a = H0
+ MOVL (1*4)(BP), R9 // b = H1
+ MOVL (2*4)(BP), R10 // c = H2
+ MOVL (3*4)(BP), R11 // d = H3
+ MOVL (4*4)(BP), R12 // e = H4
+ MOVL (5*4)(BP), R13 // f = H5
+ MOVL (6*4)(BP), R14 // g = H6
+ MOVL (7*4)(BP), R15 // h = H7
loop:
- MOVQ SP, BP // message schedule
+ MOVQ SP, BP
SHA256ROUND0(0, 0x428a2f98, R8, R9, R10, R11, R12, R13, R14, R15)
SHA256ROUND0(1, 0x71374491, R15, R8, R9, R10, R11, R12, R13, R14)
@@ -230,27 +651,391 @@ loop:
SHA256ROUND1(62, 0xbef9a3f7, R10, R11, R12, R13, R14, R15, R8, R9)
SHA256ROUND1(63, 0xc67178f2, R9, R10, R11, R12, R13, R14, R15, R8)
- MOVQ dig+0(FP), BP
- ADDL (0*4)(BP), R8 // H0 = a + H0
- MOVL R8, (0*4)(BP)
- ADDL (1*4)(BP), R9 // H1 = b + H1
- MOVL R9, (1*4)(BP)
- ADDL (2*4)(BP), R10 // H2 = c + H2
- MOVL R10, (2*4)(BP)
- ADDL (3*4)(BP), R11 // H3 = d + H3
- MOVL R11, (3*4)(BP)
- ADDL (4*4)(BP), R12 // H4 = e + H4
- MOVL R12, (4*4)(BP)
- ADDL (5*4)(BP), R13 // H5 = f + H5
- MOVL R13, (5*4)(BP)
- ADDL (6*4)(BP), R14 // H6 = g + H6
- MOVL R14, (6*4)(BP)
- ADDL (7*4)(BP), R15 // H7 = h + H7
- MOVL R15, (7*4)(BP)
-
- ADDQ $64, SI
- CMPQ SI, 256(SP)
- JB loop
+ MOVQ dig+0(FP), BP
+ ADDL (0*4)(BP), R8 // H0 = a + H0
+ MOVL R8, (0*4)(BP)
+ ADDL (1*4)(BP), R9 // H1 = b + H1
+ MOVL R9, (1*4)(BP)
+ ADDL (2*4)(BP), R10 // H2 = c + H2
+ MOVL R10, (2*4)(BP)
+ ADDL (3*4)(BP), R11 // H3 = d + H3
+ MOVL R11, (3*4)(BP)
+ ADDL (4*4)(BP), R12 // H4 = e + H4
+ MOVL R12, (4*4)(BP)
+ ADDL (5*4)(BP), R13 // H5 = f + H5
+ MOVL R13, (5*4)(BP)
+ ADDL (6*4)(BP), R14 // H6 = g + H6
+ MOVL R14, (6*4)(BP)
+ ADDL (7*4)(BP), R15 // H7 = h + H7
+ MOVL R15, (7*4)(BP)
+
+ ADDQ $64, SI
+ CMPQ SI, 256(SP)
+ JB loop
end:
RET
+
+avx2:
+ MOVQ dig+0(FP), CTX // d.h[8]
+ MOVQ p_base+8(FP), INP
+ MOVQ p_len+16(FP), NUM_BYTES
+
+ LEAQ -64(INP)(NUM_BYTES*1), NUM_BYTES // Pointer to the last block
+ MOVQ NUM_BYTES, _INP_END(SP)
+
+ CMPQ NUM_BYTES, INP
+ JE avx2_only_one_block
+
+ // Load initial digest
+ MOVL 0(CTX), a // a = H0
+ MOVL 4(CTX), b // b = H1
+ MOVL 8(CTX), c // c = H2
+ MOVL 12(CTX), d // d = H3
+ MOVL 16(CTX), e // e = H4
+ MOVL 20(CTX), f // f = H5
+ MOVL 24(CTX), g // g = H6
+ MOVL 28(CTX), h // h = H7
+
+avx2_loop0: // at each iteration works with one block (512 bit)
+
+ VMOVDQU (0*32)(INP), XTMP0
+ VMOVDQU (1*32)(INP), XTMP1
+ VMOVDQU (2*32)(INP), XTMP2
+ VMOVDQU (3*32)(INP), XTMP3
+
+ MOVQ $flip_mask<>(SB), BP // BYTE_FLIP_MASK
+ VMOVDQU (BP), BYTE_FLIP_MASK
+
+ // Apply Byte Flip Mask: LE -> BE
+ VPSHUFB BYTE_FLIP_MASK, XTMP0, XTMP0
+ VPSHUFB BYTE_FLIP_MASK, XTMP1, XTMP1
+ VPSHUFB BYTE_FLIP_MASK, XTMP2, XTMP2
+ VPSHUFB BYTE_FLIP_MASK, XTMP3, XTMP3
+
+ // Transpose data into high/low parts
+ VPERM2I128 $0x20, XTMP2, XTMP0, XDWORD0 // w3, w2, w1, w0
+ VPERM2I128 $0x31, XTMP2, XTMP0, XDWORD1 // w7, w6, w5, w4
+ VPERM2I128 $0x20, XTMP3, XTMP1, XDWORD2 // w11, w10, w9, w8
+ VPERM2I128 $0x31, XTMP3, XTMP1, XDWORD3 // w15, w14, w13, w12
+
+ MOVQ $K256<>(SB), TBL // Loading address of table with round-specific constants
+
+avx2_last_block_enter:
+ ADDQ $64, INP
+ MOVQ INP, _INP(SP)
+ XORQ SRND, SRND
+
+avx2_loop1: // for w0 - w47
+ // Do 4 rounds and scheduling
+ VPADDD 0*32(TBL)(SRND*1), XDWORD0, XFER
+ VMOVDQU XFER, (_XFER + 0*32)(SP)(SRND*1)
+ ROUND_AND_SCHED_N_0(_XFER + 0*32, a, b, c, d, e, f, g, h, XDWORD0, XDWORD1, XDWORD2, XDWORD3)
+ ROUND_AND_SCHED_N_1(_XFER + 0*32, h, a, b, c, d, e, f, g, XDWORD0, XDWORD1, XDWORD2, XDWORD3)
+ ROUND_AND_SCHED_N_2(_XFER + 0*32, g, h, a, b, c, d, e, f, XDWORD0, XDWORD1, XDWORD2, XDWORD3)
+ ROUND_AND_SCHED_N_3(_XFER + 0*32, f, g, h, a, b, c, d, e, XDWORD0, XDWORD1, XDWORD2, XDWORD3)
+
+ // Do 4 rounds and scheduling
+ VPADDD 1*32(TBL)(SRND*1), XDWORD1, XFER
+ VMOVDQU XFER, (_XFER + 1*32)(SP)(SRND*1)
+ ROUND_AND_SCHED_N_0(_XFER + 1*32, e, f, g, h, a, b, c, d, XDWORD1, XDWORD2, XDWORD3, XDWORD0)
+ ROUND_AND_SCHED_N_1(_XFER + 1*32, d, e, f, g, h, a, b, c, XDWORD1, XDWORD2, XDWORD3, XDWORD0)
+ ROUND_AND_SCHED_N_2(_XFER + 1*32, c, d, e, f, g, h, a, b, XDWORD1, XDWORD2, XDWORD3, XDWORD0)
+ ROUND_AND_SCHED_N_3(_XFER + 1*32, b, c, d, e, f, g, h, a, XDWORD1, XDWORD2, XDWORD3, XDWORD0)
+
+ // Do 4 rounds and scheduling
+ VPADDD 2*32(TBL)(SRND*1), XDWORD2, XFER
+ VMOVDQU XFER, (_XFER + 2*32)(SP)(SRND*1)
+ ROUND_AND_SCHED_N_0(_XFER + 2*32, a, b, c, d, e, f, g, h, XDWORD2, XDWORD3, XDWORD0, XDWORD1)
+ ROUND_AND_SCHED_N_1(_XFER + 2*32, h, a, b, c, d, e, f, g, XDWORD2, XDWORD3, XDWORD0, XDWORD1)
+ ROUND_AND_SCHED_N_2(_XFER + 2*32, g, h, a, b, c, d, e, f, XDWORD2, XDWORD3, XDWORD0, XDWORD1)
+ ROUND_AND_SCHED_N_3(_XFER + 2*32, f, g, h, a, b, c, d, e, XDWORD2, XDWORD3, XDWORD0, XDWORD1)
+
+ // Do 4 rounds and scheduling
+ VPADDD 3*32(TBL)(SRND*1), XDWORD3, XFER
+ VMOVDQU XFER, (_XFER + 3*32)(SP)(SRND*1)
+ ROUND_AND_SCHED_N_0(_XFER + 3*32, e, f, g, h, a, b, c, d, XDWORD3, XDWORD0, XDWORD1, XDWORD2)
+ ROUND_AND_SCHED_N_1(_XFER + 3*32, d, e, f, g, h, a, b, c, XDWORD3, XDWORD0, XDWORD1, XDWORD2)
+ ROUND_AND_SCHED_N_2(_XFER + 3*32, c, d, e, f, g, h, a, b, XDWORD3, XDWORD0, XDWORD1, XDWORD2)
+ ROUND_AND_SCHED_N_3(_XFER + 3*32, b, c, d, e, f, g, h, a, XDWORD3, XDWORD0, XDWORD1, XDWORD2)
+
+ ADDQ $4*32, SRND
+ CMPQ SRND, $3*4*32
+ JB avx2_loop1
+
+avx2_loop2:
+ // w48 - w63 processed with no scheduliung (last 16 rounds)
+ VPADDD 0*32(TBL)(SRND*1), XDWORD0, XFER
+ VMOVDQU XFER, (_XFER + 0*32)(SP)(SRND*1)
+ DO_ROUND_N_0(_XFER + 0*32, a, b, c, d, e, f, g, h, h)
+ DO_ROUND_N_1(_XFER + 0*32, h, a, b, c, d, e, f, g, h)
+ DO_ROUND_N_2(_XFER + 0*32, g, h, a, b, c, d, e, f, g)
+ DO_ROUND_N_3(_XFER + 0*32, f, g, h, a, b, c, d, e, f)
+
+ VPADDD 1*32(TBL)(SRND*1), XDWORD1, XFER
+ VMOVDQU XFER, (_XFER + 1*32)(SP)(SRND*1)
+ DO_ROUND_N_0(_XFER + 1*32, e, f, g, h, a, b, c, d, e)
+ DO_ROUND_N_1(_XFER + 1*32, d, e, f, g, h, a, b, c, d)
+ DO_ROUND_N_2(_XFER + 1*32, c, d, e, f, g, h, a, b, c)
+ DO_ROUND_N_3(_XFER + 1*32, b, c, d, e, f, g, h, a, b)
+
+ ADDQ $2*32, SRND
+
+ VMOVDQU XDWORD2, XDWORD0
+ VMOVDQU XDWORD3, XDWORD1
+
+ CMPQ SRND, $4*4*32
+ JB avx2_loop2
+
+ MOVQ dig+0(FP), CTX // d.h[8]
+ MOVQ _INP(SP), INP
+
+ addm( 0(CTX), a)
+ addm( 4(CTX), b)
+ addm( 8(CTX), c)
+ addm( 12(CTX), d)
+ addm( 16(CTX), e)
+ addm( 20(CTX), f)
+ addm( 24(CTX), g)
+ addm( 28(CTX), h)
+
+ CMPQ _INP_END(SP), INP
+ JB done_hash
+
+ XORQ SRND, SRND
+
+avx2_loop3: // Do second block using previously scheduled results
+ DO_ROUND_N_0(_XFER + 0*32 + 16, a, b, c, d, e, f, g, h, a)
+ DO_ROUND_N_1(_XFER + 0*32 + 16, h, a, b, c, d, e, f, g, h)
+ DO_ROUND_N_2(_XFER + 0*32 + 16, g, h, a, b, c, d, e, f, g)
+ DO_ROUND_N_3(_XFER + 0*32 + 16, f, g, h, a, b, c, d, e, f)
+
+ DO_ROUND_N_0(_XFER + 1*32 + 16, e, f, g, h, a, b, c, d, e)
+ DO_ROUND_N_1(_XFER + 1*32 + 16, d, e, f, g, h, a, b, c, d)
+ DO_ROUND_N_2(_XFER + 1*32 + 16, c, d, e, f, g, h, a, b, c)
+ DO_ROUND_N_3(_XFER + 1*32 + 16, b, c, d, e, f, g, h, a, b)
+
+ ADDQ $2*32, SRND
+ CMPQ SRND, $4*4*32
+ JB avx2_loop3
+
+ MOVQ dig+0(FP), CTX // d.h[8]
+ MOVQ _INP(SP), INP
+ ADDQ $64, INP
+
+ addm( 0(CTX), a)
+ addm( 4(CTX), b)
+ addm( 8(CTX), c)
+ addm( 12(CTX), d)
+ addm( 16(CTX), e)
+ addm( 20(CTX), f)
+ addm( 24(CTX), g)
+ addm( 28(CTX), h)
+
+ CMPQ _INP_END(SP), INP
+ JA avx2_loop0
+ JB done_hash
+
+avx2_do_last_block:
+
+ VMOVDQU 0(INP), XWORD0
+ VMOVDQU 16(INP), XWORD1
+ VMOVDQU 32(INP), XWORD2
+ VMOVDQU 48(INP), XWORD3
+
+ MOVQ $flip_mask<>(SB), BP
+ VMOVDQU (BP), X_BYTE_FLIP_MASK
+
+ VPSHUFB X_BYTE_FLIP_MASK, XWORD0, XWORD0
+ VPSHUFB X_BYTE_FLIP_MASK, XWORD1, XWORD1
+ VPSHUFB X_BYTE_FLIP_MASK, XWORD2, XWORD2
+ VPSHUFB X_BYTE_FLIP_MASK, XWORD3, XWORD3
+
+ MOVQ $K256<>(SB), TBL
+
+ JMP avx2_last_block_enter
+
+avx2_only_one_block:
+ // Load initial digest
+ MOVL 0(CTX), a // a = H0
+ MOVL 4(CTX), b // b = H1
+ MOVL 8(CTX), c // c = H2
+ MOVL 12(CTX), d // d = H3
+ MOVL 16(CTX), e // e = H4
+ MOVL 20(CTX), f // f = H5
+ MOVL 24(CTX), g // g = H6
+ MOVL 28(CTX), h // h = H7
+
+ JMP avx2_do_last_block
+
+done_hash:
+ VZEROUPPER
+ RET
+
+// shuffle byte order from LE to BE
+DATA flip_mask<>+0x00(SB)/8, $0x0405060700010203
+DATA flip_mask<>+0x08(SB)/8, $0x0c0d0e0f08090a0b
+DATA flip_mask<>+0x10(SB)/8, $0x0405060700010203
+DATA flip_mask<>+0x18(SB)/8, $0x0c0d0e0f08090a0b
+GLOBL flip_mask<>(SB), 8, $32
+
+// shuffle xBxA -> 00BA
+DATA shuff_00BA<>+0x00(SB)/8, $0x0b0a090803020100
+DATA shuff_00BA<>+0x08(SB)/8, $0xFFFFFFFFFFFFFFFF
+DATA shuff_00BA<>+0x10(SB)/8, $0x0b0a090803020100
+DATA shuff_00BA<>+0x18(SB)/8, $0xFFFFFFFFFFFFFFFF
+GLOBL shuff_00BA<>(SB), 8, $32
+
+// shuffle xDxC -> DC00
+DATA shuff_DC00<>+0x00(SB)/8, $0xFFFFFFFFFFFFFFFF
+DATA shuff_DC00<>+0x08(SB)/8, $0x0b0a090803020100
+DATA shuff_DC00<>+0x10(SB)/8, $0xFFFFFFFFFFFFFFFF
+DATA shuff_DC00<>+0x18(SB)/8, $0x0b0a090803020100
+GLOBL shuff_DC00<>(SB), 8, $32
+
+// Round specific constants
+DATA K256<>+0x00(SB)/4, $0x428a2f98 // k1
+DATA K256<>+0x04(SB)/4, $0x71374491 // k2
+DATA K256<>+0x08(SB)/4, $0xb5c0fbcf // k3
+DATA K256<>+0x0c(SB)/4, $0xe9b5dba5 // k4
+DATA K256<>+0x10(SB)/4, $0x428a2f98 // k1
+DATA K256<>+0x14(SB)/4, $0x71374491 // k2
+DATA K256<>+0x18(SB)/4, $0xb5c0fbcf // k3
+DATA K256<>+0x1c(SB)/4, $0xe9b5dba5 // k4
+
+DATA K256<>+0x20(SB)/4, $0x3956c25b // k5 - k8
+DATA K256<>+0x24(SB)/4, $0x59f111f1
+DATA K256<>+0x28(SB)/4, $0x923f82a4
+DATA K256<>+0x2c(SB)/4, $0xab1c5ed5
+DATA K256<>+0x30(SB)/4, $0x3956c25b
+DATA K256<>+0x34(SB)/4, $0x59f111f1
+DATA K256<>+0x38(SB)/4, $0x923f82a4
+DATA K256<>+0x3c(SB)/4, $0xab1c5ed5
+
+DATA K256<>+0x40(SB)/4, $0xd807aa98 // k9 - k12
+DATA K256<>+0x44(SB)/4, $0x12835b01
+DATA K256<>+0x48(SB)/4, $0x243185be
+DATA K256<>+0x4c(SB)/4, $0x550c7dc3
+DATA K256<>+0x50(SB)/4, $0xd807aa98
+DATA K256<>+0x54(SB)/4, $0x12835b01
+DATA K256<>+0x58(SB)/4, $0x243185be
+DATA K256<>+0x5c(SB)/4, $0x550c7dc3
+
+DATA K256<>+0x60(SB)/4, $0x72be5d74 // k13 - k16
+DATA K256<>+0x64(SB)/4, $0x80deb1fe
+DATA K256<>+0x68(SB)/4, $0x9bdc06a7
+DATA K256<>+0x6c(SB)/4, $0xc19bf174
+DATA K256<>+0x70(SB)/4, $0x72be5d74
+DATA K256<>+0x74(SB)/4, $0x80deb1fe
+DATA K256<>+0x78(SB)/4, $0x9bdc06a7
+DATA K256<>+0x7c(SB)/4, $0xc19bf174
+
+DATA K256<>+0x80(SB)/4, $0xe49b69c1 // k17 - k20
+DATA K256<>+0x84(SB)/4, $0xefbe4786
+DATA K256<>+0x88(SB)/4, $0x0fc19dc6
+DATA K256<>+0x8c(SB)/4, $0x240ca1cc
+DATA K256<>+0x90(SB)/4, $0xe49b69c1
+DATA K256<>+0x94(SB)/4, $0xefbe4786
+DATA K256<>+0x98(SB)/4, $0x0fc19dc6
+DATA K256<>+0x9c(SB)/4, $0x240ca1cc
+
+DATA K256<>+0xa0(SB)/4, $0x2de92c6f // k21 - k24
+DATA K256<>+0xa4(SB)/4, $0x4a7484aa
+DATA K256<>+0xa8(SB)/4, $0x5cb0a9dc
+DATA K256<>+0xac(SB)/4, $0x76f988da
+DATA K256<>+0xb0(SB)/4, $0x2de92c6f
+DATA K256<>+0xb4(SB)/4, $0x4a7484aa
+DATA K256<>+0xb8(SB)/4, $0x5cb0a9dc
+DATA K256<>+0xbc(SB)/4, $0x76f988da
+
+DATA K256<>+0xc0(SB)/4, $0x983e5152 // k25 - k28
+DATA K256<>+0xc4(SB)/4, $0xa831c66d
+DATA K256<>+0xc8(SB)/4, $0xb00327c8
+DATA K256<>+0xcc(SB)/4, $0xbf597fc7
+DATA K256<>+0xd0(SB)/4, $0x983e5152
+DATA K256<>+0xd4(SB)/4, $0xa831c66d
+DATA K256<>+0xd8(SB)/4, $0xb00327c8
+DATA K256<>+0xdc(SB)/4, $0xbf597fc7
+
+DATA K256<>+0xe0(SB)/4, $0xc6e00bf3 // k29 - k32
+DATA K256<>+0xe4(SB)/4, $0xd5a79147
+DATA K256<>+0xe8(SB)/4, $0x06ca6351
+DATA K256<>+0xec(SB)/4, $0x14292967
+DATA K256<>+0xf0(SB)/4, $0xc6e00bf3
+DATA K256<>+0xf4(SB)/4, $0xd5a79147
+DATA K256<>+0xf8(SB)/4, $0x06ca6351
+DATA K256<>+0xfc(SB)/4, $0x14292967
+
+DATA K256<>+0x100(SB)/4, $0x27b70a85
+DATA K256<>+0x104(SB)/4, $0x2e1b2138
+DATA K256<>+0x108(SB)/4, $0x4d2c6dfc
+DATA K256<>+0x10c(SB)/4, $0x53380d13
+DATA K256<>+0x110(SB)/4, $0x27b70a85
+DATA K256<>+0x114(SB)/4, $0x2e1b2138
+DATA K256<>+0x118(SB)/4, $0x4d2c6dfc
+DATA K256<>+0x11c(SB)/4, $0x53380d13
+
+DATA K256<>+0x120(SB)/4, $0x650a7354
+DATA K256<>+0x124(SB)/4, $0x766a0abb
+DATA K256<>+0x128(SB)/4, $0x81c2c92e
+DATA K256<>+0x12c(SB)/4, $0x92722c85
+DATA K256<>+0x130(SB)/4, $0x650a7354
+DATA K256<>+0x134(SB)/4, $0x766a0abb
+DATA K256<>+0x138(SB)/4, $0x81c2c92e
+DATA K256<>+0x13c(SB)/4, $0x92722c85
+
+DATA K256<>+0x140(SB)/4, $0xa2bfe8a1
+DATA K256<>+0x144(SB)/4, $0xa81a664b
+DATA K256<>+0x148(SB)/4, $0xc24b8b70
+DATA K256<>+0x14c(SB)/4, $0xc76c51a3
+DATA K256<>+0x150(SB)/4, $0xa2bfe8a1
+DATA K256<>+0x154(SB)/4, $0xa81a664b
+DATA K256<>+0x158(SB)/4, $0xc24b8b70
+DATA K256<>+0x15c(SB)/4, $0xc76c51a3
+
+DATA K256<>+0x160(SB)/4, $0xd192e819
+DATA K256<>+0x164(SB)/4, $0xd6990624
+DATA K256<>+0x168(SB)/4, $0xf40e3585
+DATA K256<>+0x16c(SB)/4, $0x106aa070
+DATA K256<>+0x170(SB)/4, $0xd192e819
+DATA K256<>+0x174(SB)/4, $0xd6990624
+DATA K256<>+0x178(SB)/4, $0xf40e3585
+DATA K256<>+0x17c(SB)/4, $0x106aa070
+
+DATA K256<>+0x180(SB)/4, $0x19a4c116
+DATA K256<>+0x184(SB)/4, $0x1e376c08
+DATA K256<>+0x188(SB)/4, $0x2748774c
+DATA K256<>+0x18c(SB)/4, $0x34b0bcb5
+DATA K256<>+0x190(SB)/4, $0x19a4c116
+DATA K256<>+0x194(SB)/4, $0x1e376c08
+DATA K256<>+0x198(SB)/4, $0x2748774c
+DATA K256<>+0x19c(SB)/4, $0x34b0bcb5
+
+DATA K256<>+0x1a0(SB)/4, $0x391c0cb3
+DATA K256<>+0x1a4(SB)/4, $0x4ed8aa4a
+DATA K256<>+0x1a8(SB)/4, $0x5b9cca4f
+DATA K256<>+0x1ac(SB)/4, $0x682e6ff3
+DATA K256<>+0x1b0(SB)/4, $0x391c0cb3
+DATA K256<>+0x1b4(SB)/4, $0x4ed8aa4a
+DATA K256<>+0x1b8(SB)/4, $0x5b9cca4f
+DATA K256<>+0x1bc(SB)/4, $0x682e6ff3
+
+DATA K256<>+0x1c0(SB)/4, $0x748f82ee
+DATA K256<>+0x1c4(SB)/4, $0x78a5636f
+DATA K256<>+0x1c8(SB)/4, $0x84c87814
+DATA K256<>+0x1cc(SB)/4, $0x8cc70208
+DATA K256<>+0x1d0(SB)/4, $0x748f82ee
+DATA K256<>+0x1d4(SB)/4, $0x78a5636f
+DATA K256<>+0x1d8(SB)/4, $0x84c87814
+DATA K256<>+0x1dc(SB)/4, $0x8cc70208
+
+DATA K256<>+0x1e0(SB)/4, $0x90befffa
+DATA K256<>+0x1e4(SB)/4, $0xa4506ceb
+DATA K256<>+0x1e8(SB)/4, $0xbef9a3f7
+DATA K256<>+0x1ec(SB)/4, $0xc67178f2
+DATA K256<>+0x1f0(SB)/4, $0x90befffa
+DATA K256<>+0x1f4(SB)/4, $0xa4506ceb
+DATA K256<>+0x1f8(SB)/4, $0xbef9a3f7
+DATA K256<>+0x1fc(SB)/4, $0xc67178f2
+
+GLOBL K256<>(SB), (NOPTR + RODATA), $512
From fafadc521ede90f8abed73e8d209e130c456e983 Mon Sep 17 00:00:00 2001
From: Ilya Tocar
Date: Fri, 29 Apr 2016 16:17:14 +0300
Subject: [PATCH 016/267] crypto/sha1: Add AVX2 version for AMD64
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
name old time/op new time/op delta
Hash8Bytes-48 271ns ± 8% 273ns ± 5% ~ (p=0.313 n=19+19)
Hash320Bytes-48 1.04µs ± 7% 0.75µs ± 8% -27.66% (p=0.000 n=20+20)
Hash1K-48 2.72µs ± 6% 1.75µs ± 6% -35.79% (p=0.000 n=19+20)
Hash8K-48 19.9µs ± 7% 11.6µs ± 6% -41.84% (p=0.000 n=20+19)
name old speed new speed delta
Hash8Bytes-48 29.5MB/s ± 8% 29.3MB/s ± 5% ~ (p=0.314 n=19+19)
Hash320Bytes-48 307MB/s ± 7% 424MB/s ± 8% +38.29% (p=0.000 n=20+20)
Hash1K-48 377MB/s ± 6% 587MB/s ± 6% +55.76% (p=0.000 n=19+20)
Hash8K-48 413MB/s ± 7% 709MB/s ± 6% +71.85% (p=0.000 n=20+19)
Change-Id: I2963cf744eeb2e8191d4e4223fbf6f533a7fd405
Reviewed-on: https://go-review.googlesource.com/22607
Run-TryBot: Ilya Tocar
Reviewed-by: Russ Cox
Run-TryBot: Russ Cox
TryBot-Result: Gobot Gobot
---
src/crypto/sha1/sha1_test.go | 5 +
src/crypto/sha1/sha1block_amd64.go | 23 +
src/crypto/sha1/sha1block_amd64.s | 1301 +++++++++++++++++++++++++++-
src/crypto/sha1/sha1block_decl.go | 2 +-
4 files changed, 1329 insertions(+), 2 deletions(-)
create mode 100644 src/crypto/sha1/sha1block_amd64.go
diff --git a/src/crypto/sha1/sha1_test.go b/src/crypto/sha1/sha1_test.go
index 9202e682a8f9b9..daab2aeaefb977 100644
--- a/src/crypto/sha1/sha1_test.go
+++ b/src/crypto/sha1/sha1_test.go
@@ -19,6 +19,7 @@ type sha1Test struct {
}
var golden = []sha1Test{
+ {"76245dbf96f661bd221046197ab8b9f063f11bad", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"},
{"da39a3ee5e6b4b0d3255bfef95601890afd80709", ""},
{"86f7e437faa5a7fce15d1ddcb9eaeaea377667b8", "a"},
{"da23614e02469a0d7c7bd1bdab5c9c474b1904dc", "ab"},
@@ -120,6 +121,10 @@ func BenchmarkHash8Bytes(b *testing.B) {
benchmarkSize(b, 8)
}
+func BenchmarkHash320Bytes(b *testing.B) {
+ benchmarkSize(b, 320)
+}
+
func BenchmarkHash1K(b *testing.B) {
benchmarkSize(b, 1024)
}
diff --git a/src/crypto/sha1/sha1block_amd64.go b/src/crypto/sha1/sha1block_amd64.go
new file mode 100644
index 00000000000000..84f8a520197db2
--- /dev/null
+++ b/src/crypto/sha1/sha1block_amd64.go
@@ -0,0 +1,23 @@
+// Copyright 2016 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 sha1
+
+//go:noescape
+
+func blockAVX2(dig *digest, p []byte)
+
+//go:noescape
+func blockAMD64(dig *digest, p []byte)
+func checkAVX2() bool
+
+var hasAVX2 = checkAVX2()
+
+func block(dig *digest, p []byte) {
+ if hasAVX2 && len(p) >= 256 {
+ blockAVX2(dig, p)
+ } else {
+ blockAMD64(dig, p)
+ }
+}
diff --git a/src/crypto/sha1/sha1block_amd64.s b/src/crypto/sha1/sha1block_amd64.s
index a504e147512c73..0cdb43b422fdcc 100644
--- a/src/crypto/sha1/sha1block_amd64.s
+++ b/src/crypto/sha1/sha1block_amd64.s
@@ -2,6 +2,15 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// AVX2 version by Intel, same algorithm as code in Linux kernel:
+// https://github.com/torvalds/linux/blob/master/arch/x86/crypto/sha1_avx2_x86_64_asm.S
+// Authors:
+// Ilya Albrekht
+// Maxim Locktyukhin
+// Ronen Zohar
+// Chandramouli Narayanan
+
+
#include "textflag.h"
// SHA1 block routine. See sha1block.go for Go equivalent.
@@ -87,7 +96,7 @@
FUNC4(a, b, c, d, e); \
MIX(a, b, c, d, e, 0xCA62C1D6)
-TEXT ·block(SB),NOSPLIT,$64-32
+TEXT ·blockAMD64(SB),NOSPLIT,$64-32
MOVQ dig+0(FP), BP
MOVQ p_base+8(FP), SI
MOVQ p_len+16(FP), DX
@@ -214,3 +223,1293 @@ end:
MOVL DX, (3*4)(DI)
MOVL BP, (4*4)(DI)
RET
+
+
+// This is the implementation using AVX2. It is based on:
+// "SHA-1 implementation with Intel(R) AVX2 instruction set extensions"
+// From http://software.intel.com/en-us/articles
+// (look for improving-the-performance-of-the-secure-hash-algorithm-1)
+// This implementation is 2x unrolled, and interleaves vector instructions,
+// used to precompute W, with scalar computation of current round
+// for optimal scheduling.
+
+// Trivial helper macros.
+#define UPDATE_HASH(A,TB,C,D,E) \
+ ADDL (R9), A \
+ MOVL A, (R9) \
+ ADDL 4(R9), TB \
+ MOVL TB, 4(R9) \
+ ADDL 8(R9), C \
+ MOVL C, 8(R9) \
+ ADDL 12(R9), D \
+ MOVL D, 12(R9) \
+ ADDL 16(R9), E \
+ MOVL E, 16(R9)
+
+
+
+// Helper macros for PRECALC, which does precomputations
+#define PRECALC_0(OFFSET) \
+ VMOVDQU OFFSET(R10),X0
+
+#define PRECALC_1(OFFSET) \
+ VINSERTI128 $1, OFFSET(R13), Y0, Y0
+
+#define PRECALC_2(YREG) \
+ VPSHUFB Y10, Y0, YREG
+
+#define PRECALC_4(YREG,K_OFFSET) \
+ VPADDD K_OFFSET(R8), YREG, Y0
+
+#define PRECALC_7(OFFSET) \
+ VMOVDQU Y0, (OFFSET*2)(R14)
+
+
+// Message scheduling pre-compute for rounds 0-15
+// R13 is a pointer to even 64-byte block
+// R10 is a pointer to odd 64-byte block
+// R14 is a pointer to temp buffer
+// X0 is used as temp register
+// YREG is clobbered as part of computation
+// OFFSET chooses 16 byte chunk within a block
+// R8 is a pointer to constants block
+// K_OFFSET chooses K constants relevant to this round
+// X10 holds swap mask
+#define PRECALC_00_15(OFFSET,YREG) \
+ PRECALC_0(OFFSET) \
+ PRECALC_1(OFFSET) \
+ PRECALC_2(YREG) \
+ PRECALC_4(YREG,0x0) \
+ PRECALC_7(OFFSET)
+
+
+// Helper macros for PRECALC_16_31
+#define PRECALC_16(REG_SUB_16,REG_SUB_12,REG_SUB_4,REG) \
+ VPALIGNR $8, REG_SUB_16, REG_SUB_12, REG \ // w[i-14]
+ VPSRLDQ $4, REG_SUB_4, Y0 // w[i-3]
+
+#define PRECALC_17(REG_SUB_16,REG_SUB_8,REG) \
+ VPXOR REG_SUB_8, REG, REG \
+ VPXOR REG_SUB_16, Y0, Y0
+
+#define PRECALC_18(REG) \
+ VPXOR Y0, REG, REG \
+ VPSLLDQ $12, REG, Y9
+
+#define PRECALC_19(REG) \
+ VPSLLD $1, REG, Y0 \
+ VPSRLD $31, REG, REG
+
+#define PRECALC_20(REG) \
+ VPOR REG, Y0, Y0 \
+ VPSLLD $2, Y9, REG
+
+#define PRECALC_21(REG) \
+ VPSRLD $30, Y9, Y9 \
+ VPXOR REG, Y0, Y0
+
+#define PRECALC_23(REG,K_OFFSET,OFFSET) \
+ VPXOR Y9, Y0, REG \
+ VPADDD K_OFFSET(R8), REG, Y0 \
+ VMOVDQU Y0, (OFFSET)(R14)
+
+// Message scheduling pre-compute for rounds 16-31
+// calculating last 32 w[i] values in 8 XMM registers
+// pre-calculate K+w[i] values and store to mem
+// for later load by ALU add instruction.
+// "brute force" vectorization for rounds 16-31 only
+// due to w[i]->w[i-3] dependency.
+// clobbers 5 input ymm registers REG_SUB*
+// uses X0 and X9 as temp registers
+// As always, R8 is a pointer to constants block
+// and R14 is a pointer to temp buffer
+#define PRECALC_16_31(REG,REG_SUB_4,REG_SUB_8,REG_SUB_12,REG_SUB_16,K_OFFSET,OFFSET) \
+ PRECALC_16(REG_SUB_16,REG_SUB_12,REG_SUB_4,REG) \
+ PRECALC_17(REG_SUB_16,REG_SUB_8,REG) \
+ PRECALC_18(REG) \
+ PRECALC_19(REG) \
+ PRECALC_20(REG) \
+ PRECALC_21(REG) \
+ PRECALC_23(REG,K_OFFSET,OFFSET)
+
+
+// Helper macros for PRECALC_32_79
+#define PRECALC_32(REG_SUB_8,REG_SUB_4) \
+ VPALIGNR $8, REG_SUB_8, REG_SUB_4, Y0
+
+#define PRECALC_33(REG_SUB_28,REG) \
+ VPXOR REG_SUB_28, REG, REG
+
+#define PRECALC_34(REG_SUB_16) \
+ VPXOR REG_SUB_16, Y0, Y0
+
+#define PRECALC_35(REG) \
+ VPXOR Y0, REG, REG
+
+#define PRECALC_36(REG) \
+ VPSLLD $2, REG, Y0
+
+#define PRECALC_37(REG) \
+ VPSRLD $30, REG, REG \
+ VPOR REG, Y0, REG
+
+#define PRECALC_39(REG,K_OFFSET,OFFSET) \
+ VPADDD K_OFFSET(R8), REG, Y0 \
+ VMOVDQU Y0, (OFFSET)(R14)
+
+// Message scheduling pre-compute for rounds 32-79
+// In SHA-1 specification we have:
+// w[i] = (w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]) rol 1
+// Which is the same as:
+// w[i] = (w[i-6] ^ w[i-16] ^ w[i-28] ^ w[i-32]) rol 2
+// This allows for more efficient vectorization,
+// since w[i]->w[i-3] dependency is broken
+#define PRECALC_32_79(REG,REG_SUB_4,REG_SUB_8,REG_SUB_16,REG_SUB_28,K_OFFSET,OFFSET) \
+ PRECALC_32(REG_SUB_8,REG_SUB_4) \
+ PRECALC_33(REG_SUB_28,REG) \
+ PRECALC_34(REG_SUB_16) \
+ PRECALC_35(REG) \
+ PRECALC_36(REG) \
+ PRECALC_37(REG) \
+ PRECALC_39(REG,K_OFFSET,OFFSET)
+
+#define PRECALC \
+ PRECALC_00_15(0,Y15) \
+ PRECALC_00_15(0x10,Y14) \
+ PRECALC_00_15(0x20,Y13) \
+ PRECALC_00_15(0x30,Y12) \
+ PRECALC_16_31(Y8,Y12,Y13,Y14,Y15,0,0x80) \
+ PRECALC_16_31(Y7,Y8,Y12,Y13,Y14,0x20,0xa0) \
+ PRECALC_16_31(Y5,Y7,Y8,Y12,Y13,0x20,0xc0) \
+ PRECALC_16_31(Y3,Y5,Y7,Y8,Y12,0x20,0xe0) \
+ PRECALC_32_79(Y15,Y3,Y5,Y8,Y14,0x20,0x100) \
+ PRECALC_32_79(Y14,Y15,Y3,Y7,Y13,0x20,0x120) \
+ PRECALC_32_79(Y13,Y14,Y15,Y5,Y12,0x40,0x140) \
+ PRECALC_32_79(Y12,Y13,Y14,Y3,Y8,0x40,0x160) \
+ PRECALC_32_79(Y8,Y12,Y13,Y15,Y7,0x40,0x180) \
+ PRECALC_32_79(Y7,Y8,Y12,Y14,Y5,0x40,0x1a0) \
+ PRECALC_32_79(Y5,Y7,Y8,Y13,Y3,0x40,0x1c0) \
+ PRECALC_32_79(Y3,Y5,Y7,Y12,Y15,0x60,0x1e0) \
+ PRECALC_32_79(Y15,Y3,Y5,Y8,Y14,0x60,0x200) \
+ PRECALC_32_79(Y14,Y15,Y3,Y7,Y13,0x60,0x220) \
+ PRECALC_32_79(Y13,Y14,Y15,Y5,Y12,0x60,0x240) \
+ PRECALC_32_79(Y12,Y13,Y14,Y3,Y8,0x60,0x260)
+
+// Macros calculating individual rounds have general forn
+// CALC_ROUND_PRE + PRECALC_ROUND + CALC_ROUND_POST
+// CALC_ROUND_{PRE,POST} macros follow
+
+#define CALC_F1_PRE(OFFSET,REG_A,REG_B,REG_C,REG_E) \
+ ADDL OFFSET(R15),REG_E \
+ ANDNL REG_C,REG_A,BP \
+ LEAL (REG_E)(REG_B*1), REG_E \ // Add F from the previous round
+ RORXL $0x1b, REG_A, R12 \
+ RORXL $2, REG_A, REG_B // for next round
+
+// Calculate F for the next round
+#define CALC_F1_POST(REG_A,REG_B,REG_E) \
+ ANDL REG_B,REG_A \ // b&c
+ XORL BP, REG_A \ // F1 = (b&c) ^ (~b&d)
+ LEAL (REG_E)(R12*1), REG_E // E += A >>> 5
+
+
+// Registers are cycleickly rotated DX -> AX -> DI -> SI -> BX -> CX
+#define CALC_0 \
+ MOVL SI, BX \ // Precalculating first round
+ RORXL $2, SI, SI \
+ ANDNL AX, BX, BP \
+ ANDL DI, BX \
+ XORL BP, BX \
+ CALC_F1_PRE(0x0,CX,BX,DI,DX) \
+ PRECALC_0(0x80) \
+ CALC_F1_POST(CX,SI,DX)
+
+#define CALC_1 \
+ CALC_F1_PRE(0x4,DX,CX,SI,AX) \
+ PRECALC_1(0x80) \
+ CALC_F1_POST(DX,BX,AX)
+
+#define CALC_2 \
+ CALC_F1_PRE(0x8,AX,DX,BX,DI) \
+ PRECALC_2(Y15) \
+ CALC_F1_POST(AX,CX,DI)
+
+#define CALC_3 \
+ CALC_F1_PRE(0xc,DI,AX,CX,SI) \
+ CALC_F1_POST(DI,DX,SI)
+
+#define CALC_4 \
+ CALC_F1_PRE(0x20,SI,DI,DX,BX) \
+ PRECALC_4(Y15,0x0) \
+ CALC_F1_POST(SI,AX,BX)
+
+#define CALC_5 \
+ CALC_F1_PRE(0x24,BX,SI,AX,CX) \
+ CALC_F1_POST(BX,DI,CX)
+
+#define CALC_6 \
+ CALC_F1_PRE(0x28,CX,BX,DI,DX) \
+ CALC_F1_POST(CX,SI,DX)
+
+#define CALC_7 \
+ CALC_F1_PRE(0x2c,DX,CX,SI,AX) \
+ PRECALC_7(0x0) \
+ CALC_F1_POST(DX,BX,AX)
+
+#define CALC_8 \
+ CALC_F1_PRE(0x40,AX,DX,BX,DI) \
+ PRECALC_0(0x90) \
+ CALC_F1_POST(AX,CX,DI)
+
+#define CALC_9 \
+ CALC_F1_PRE(0x44,DI,AX,CX,SI) \
+ PRECALC_1(0x90) \
+ CALC_F1_POST(DI,DX,SI)
+
+#define CALC_10 \
+ CALC_F1_PRE(0x48,SI,DI,DX,BX) \
+ PRECALC_2(Y14) \
+ CALC_F1_POST(SI,AX,BX)
+
+#define CALC_11 \
+ CALC_F1_PRE(0x4c,BX,SI,AX,CX) \
+ CALC_F1_POST(BX,DI,CX)
+
+#define CALC_12 \
+ CALC_F1_PRE(0x60,CX,BX,DI,DX) \
+ PRECALC_4(Y14,0x0) \
+ CALC_F1_POST(CX,SI,DX)
+
+#define CALC_13 \
+ CALC_F1_PRE(0x64,DX,CX,SI,AX) \
+ CALC_F1_POST(DX,BX,AX)
+
+#define CALC_14 \
+ CALC_F1_PRE(0x68,AX,DX,BX,DI) \
+ CALC_F1_POST(AX,CX,DI)
+
+#define CALC_15 \
+ CALC_F1_PRE(0x6c,DI,AX,CX,SI) \
+ PRECALC_7(0x10) \
+ CALC_F1_POST(DI,DX,SI)
+
+#define CALC_16 \
+ CALC_F1_PRE(0x80,SI,DI,DX,BX) \
+ PRECALC_0(0xa0) \
+ CALC_F1_POST(SI,AX,BX)
+
+#define CALC_17 \
+ CALC_F1_PRE(0x84,BX,SI,AX,CX) \
+ PRECALC_1(0xa0) \
+ CALC_F1_POST(BX,DI,CX)
+
+#define CALC_18 \
+ CALC_F1_PRE(0x88,CX,BX,DI,DX) \
+ PRECALC_2(Y13) \
+ CALC_F1_POST(CX,SI,DX)
+
+
+#define CALC_F2_PRE(OFFSET,REG_A,REG_B,REG_E) \
+ ADDL OFFSET(R15),REG_E \
+ LEAL (REG_E)(REG_B*1), REG_E \ // Add F from the previous round
+ RORXL $0x1b, REG_A, R12 \
+ RORXL $2, REG_A, REG_B // for next round
+
+#define CALC_F2_POST(REG_A,REG_B,REG_C,REG_E) \
+ XORL REG_B, REG_A \
+ ADDL R12, REG_E \
+ XORL REG_C, REG_A
+
+#define CALC_19 \
+ CALC_F2_PRE(0x8c,DX,CX,AX) \
+ CALC_F2_POST(DX,BX,SI,AX)
+
+#define CALC_20 \
+ CALC_F2_PRE(0xa0,AX,DX,DI) \
+ PRECALC_4(Y13,0x0) \
+ CALC_F2_POST(AX,CX,BX,DI)
+
+#define CALC_21 \
+ CALC_F2_PRE(0xa4,DI,AX,SI) \
+ CALC_F2_POST(DI,DX,CX,SI)
+
+#define CALC_22 \
+ CALC_F2_PRE(0xa8,SI,DI,BX) \
+ CALC_F2_POST(SI,AX,DX,BX)
+
+#define CALC_23 \
+ CALC_F2_PRE(0xac,BX,SI,CX) \
+ PRECALC_7(0x20) \
+ CALC_F2_POST(BX,DI,AX,CX)
+
+#define CALC_24 \
+ CALC_F2_PRE(0xc0,CX,BX,DX) \
+ PRECALC_0(0xb0) \
+ CALC_F2_POST(CX,SI,DI,DX)
+
+#define CALC_25 \
+ CALC_F2_PRE(0xc4,DX,CX,AX) \
+ PRECALC_1(0xb0) \
+ CALC_F2_POST(DX,BX,SI,AX)
+
+#define CALC_26 \
+ CALC_F2_PRE(0xc8,AX,DX,DI) \
+ PRECALC_2(Y12) \
+ CALC_F2_POST(AX,CX,BX,DI)
+
+#define CALC_27 \
+ CALC_F2_PRE(0xcc,DI,AX,SI) \
+ CALC_F2_POST(DI,DX,CX,SI)
+
+#define CALC_28 \
+ CALC_F2_PRE(0xe0,SI,DI,BX) \
+ PRECALC_4(Y12,0x0) \
+ CALC_F2_POST(SI,AX,DX,BX)
+
+#define CALC_29 \
+ CALC_F2_PRE(0xe4,BX,SI,CX) \
+ CALC_F2_POST(BX,DI,AX,CX)
+
+#define CALC_30 \
+ CALC_F2_PRE(0xe8,CX,BX,DX) \
+ CALC_F2_POST(CX,SI,DI,DX)
+
+#define CALC_31 \
+ CALC_F2_PRE(0xec,DX,CX,AX) \
+ PRECALC_7(0x30) \
+ CALC_F2_POST(DX,BX,SI,AX)
+
+#define CALC_32 \
+ CALC_F2_PRE(0x100,AX,DX,DI) \
+ PRECALC_16(Y15,Y14,Y12,Y8) \
+ CALC_F2_POST(AX,CX,BX,DI)
+
+#define CALC_33 \
+ CALC_F2_PRE(0x104,DI,AX,SI) \
+ PRECALC_17(Y15,Y13,Y8) \
+ CALC_F2_POST(DI,DX,CX,SI)
+
+#define CALC_34 \
+ CALC_F2_PRE(0x108,SI,DI,BX) \
+ PRECALC_18(Y8) \
+ CALC_F2_POST(SI,AX,DX,BX)
+
+#define CALC_35 \
+ CALC_F2_PRE(0x10c,BX,SI,CX) \
+ PRECALC_19(Y8) \
+ CALC_F2_POST(BX,DI,AX,CX)
+
+#define CALC_36 \
+ CALC_F2_PRE(0x120,CX,BX,DX) \
+ PRECALC_20(Y8) \
+ CALC_F2_POST(CX,SI,DI,DX)
+
+#define CALC_37 \
+ CALC_F2_PRE(0x124,DX,CX,AX) \
+ PRECALC_21(Y8) \
+ CALC_F2_POST(DX,BX,SI,AX)
+
+#define CALC_38 \
+ CALC_F2_PRE(0x128,AX,DX,DI) \
+ CALC_F2_POST(AX,CX,BX,DI)
+
+
+#define CALC_F3_PRE(OFFSET,REG_E) \
+ ADDL OFFSET(R15),REG_E
+
+#define CALC_F3_POST(REG_A,REG_B,REG_C,REG_E,REG_TB) \
+ LEAL (REG_E)(REG_TB*1), REG_E \ // Add F from the previous round
+ MOVL REG_B, BP \
+ ORL REG_A, BP \
+ RORXL $0x1b, REG_A, R12 \
+ RORXL $2, REG_A, REG_TB \
+ ANDL REG_C, BP \ // Calculate F for the next round
+ ANDL REG_B, REG_A \
+ ORL BP, REG_A \
+ ADDL R12, REG_E
+
+#define CALC_39 \
+ CALC_F3_PRE(0x12c,SI) \
+ PRECALC_23(Y8,0x0,0x80) \
+ CALC_F3_POST(DI,DX,CX,SI,AX)
+
+#define CALC_40 \
+ CALC_F3_PRE(0x140,BX) \
+ PRECALC_16(Y14,Y13,Y8,Y7) \
+ CALC_F3_POST(SI,AX,DX,BX,DI)
+
+#define CALC_41 \
+ CALC_F3_PRE(0x144,CX) \
+ PRECALC_17(Y14,Y12,Y7) \
+ CALC_F3_POST(BX,DI,AX,CX,SI)
+
+#define CALC_42 \
+ CALC_F3_PRE(0x148,DX) \
+ PRECALC_18(Y7) \
+ CALC_F3_POST(CX,SI,DI,DX,BX)
+
+#define CALC_43 \
+ CALC_F3_PRE(0x14c,AX) \
+ PRECALC_19(Y7) \
+ CALC_F3_POST(DX,BX,SI,AX,CX)
+
+#define CALC_44 \
+ CALC_F3_PRE(0x160,DI) \
+ PRECALC_20(Y7) \
+ CALC_F3_POST(AX,CX,BX,DI,DX)
+
+#define CALC_45 \
+ CALC_F3_PRE(0x164,SI) \
+ PRECALC_21(Y7) \
+ CALC_F3_POST(DI,DX,CX,SI,AX)
+
+#define CALC_46 \
+ CALC_F3_PRE(0x168,BX) \
+ CALC_F3_POST(SI,AX,DX,BX,DI)
+
+#define CALC_47 \
+ CALC_F3_PRE(0x16c,CX) \
+ VPXOR Y9, Y0, Y7 \
+ VPADDD 0x20(R8), Y7, Y0 \
+ VMOVDQU Y0, 0xa0(R14) \
+ CALC_F3_POST(BX,DI,AX,CX,SI)
+
+#define CALC_48 \
+ CALC_F3_PRE(0x180,DX) \
+ PRECALC_16(Y13,Y12,Y7,Y5) \
+ CALC_F3_POST(CX,SI,DI,DX,BX)
+
+#define CALC_49 \
+ CALC_F3_PRE(0x184,AX) \
+ PRECALC_17(Y13,Y8,Y5) \
+ CALC_F3_POST(DX,BX,SI,AX,CX)
+
+#define CALC_50 \
+ CALC_F3_PRE(0x188,DI) \
+ PRECALC_18(Y5) \
+ CALC_F3_POST(AX,CX,BX,DI,DX)
+
+#define CALC_51 \
+ CALC_F3_PRE(0x18c,SI) \
+ PRECALC_19(Y5) \
+ CALC_F3_POST(DI,DX,CX,SI,AX)
+
+#define CALC_52 \
+ CALC_F3_PRE(0x1a0,BX) \
+ PRECALC_20(Y5) \
+ CALC_F3_POST(SI,AX,DX,BX,DI)
+
+#define CALC_53 \
+ CALC_F3_PRE(0x1a4,CX) \
+ PRECALC_21(Y5) \
+ CALC_F3_POST(BX,DI,AX,CX,SI)
+
+#define CALC_54 \
+ CALC_F3_PRE(0x1a8,DX) \
+ CALC_F3_POST(CX,SI,DI,DX,BX)
+
+#define CALC_55 \
+ CALC_F3_PRE(0x1ac,AX) \
+ PRECALC_23(Y5,0x20,0xc0) \
+ CALC_F3_POST(DX,BX,SI,AX,CX)
+
+#define CALC_56 \
+ CALC_F3_PRE(0x1c0,DI) \
+ PRECALC_16(Y12,Y8,Y5,Y3) \
+ CALC_F3_POST(AX,CX,BX,DI,DX)
+
+#define CALC_57 \
+ CALC_F3_PRE(0x1c4,SI) \
+ PRECALC_17(Y12,Y7,Y3) \
+ CALC_F3_POST(DI,DX,CX,SI,AX)
+
+#define CALC_58 \
+ CALC_F3_PRE(0x1c8,BX) \
+ PRECALC_18(Y3) \
+ CALC_F3_POST(SI,AX,DX,BX,DI)
+
+#define CALC_59 \
+ CALC_F2_PRE(0x1cc,BX,SI,CX) \
+ PRECALC_19(Y3) \
+ CALC_F2_POST(BX,DI,AX,CX)
+
+#define CALC_60 \
+ CALC_F2_PRE(0x1e0,CX,BX,DX) \
+ PRECALC_20(Y3) \
+ CALC_F2_POST(CX,SI,DI,DX)
+
+#define CALC_61 \
+ CALC_F2_PRE(0x1e4,DX,CX,AX) \
+ PRECALC_21(Y3) \
+ CALC_F2_POST(DX,BX,SI,AX)
+
+#define CALC_62 \
+ CALC_F2_PRE(0x1e8,AX,DX,DI) \
+ CALC_F2_POST(AX,CX,BX,DI)
+
+#define CALC_63 \
+ CALC_F2_PRE(0x1ec,DI,AX,SI) \
+ PRECALC_23(Y3,0x20,0xe0) \
+ CALC_F2_POST(DI,DX,CX,SI)
+
+#define CALC_64 \
+ CALC_F2_PRE(0x200,SI,DI,BX) \
+ PRECALC_32(Y5,Y3) \
+ CALC_F2_POST(SI,AX,DX,BX)
+
+#define CALC_65 \
+ CALC_F2_PRE(0x204,BX,SI,CX) \
+ PRECALC_33(Y14,Y15) \
+ CALC_F2_POST(BX,DI,AX,CX)
+
+#define CALC_66 \
+ CALC_F2_PRE(0x208,CX,BX,DX) \
+ PRECALC_34(Y8) \
+ CALC_F2_POST(CX,SI,DI,DX)
+
+#define CALC_67 \
+ CALC_F2_PRE(0x20c,DX,CX,AX) \
+ PRECALC_35(Y15) \
+ CALC_F2_POST(DX,BX,SI,AX)
+
+#define CALC_68 \
+ CALC_F2_PRE(0x220,AX,DX,DI) \
+ PRECALC_36(Y15) \
+ CALC_F2_POST(AX,CX,BX,DI)
+
+#define CALC_69 \
+ CALC_F2_PRE(0x224,DI,AX,SI) \
+ PRECALC_37(Y15) \
+ CALC_F2_POST(DI,DX,CX,SI)
+
+#define CALC_70 \
+ CALC_F2_PRE(0x228,SI,DI,BX) \
+ CALC_F2_POST(SI,AX,DX,BX)
+
+#define CALC_71 \
+ CALC_F2_PRE(0x22c,BX,SI,CX) \
+ PRECALC_39(Y15,0x20,0x100) \
+ CALC_F2_POST(BX,DI,AX,CX)
+
+#define CALC_72 \
+ CALC_F2_PRE(0x240,CX,BX,DX) \
+ PRECALC_32(Y3,Y15) \
+ CALC_F2_POST(CX,SI,DI,DX)
+
+#define CALC_73 \
+ CALC_F2_PRE(0x244,DX,CX,AX) \
+ PRECALC_33(Y13,Y14) \
+ CALC_F2_POST(DX,BX,SI,AX)
+
+#define CALC_74 \
+ CALC_F2_PRE(0x248,AX,DX,DI) \
+ PRECALC_34(Y7) \
+ CALC_F2_POST(AX,CX,BX,DI)
+
+#define CALC_75 \
+ CALC_F2_PRE(0x24c,DI,AX,SI) \
+ PRECALC_35(Y14) \
+ CALC_F2_POST(DI,DX,CX,SI)
+
+#define CALC_76 \
+ CALC_F2_PRE(0x260,SI,DI,BX) \
+ PRECALC_36(Y14) \
+ CALC_F2_POST(SI,AX,DX,BX)
+
+#define CALC_77 \
+ CALC_F2_PRE(0x264,BX,SI,CX) \
+ PRECALC_37(Y14) \
+ CALC_F2_POST(BX,DI,AX,CX)
+
+#define CALC_78 \
+ CALC_F2_PRE(0x268,CX,BX,DX) \
+ CALC_F2_POST(CX,SI,DI,DX)
+
+#define CALC_79 \
+ ADDL 0x26c(R15), AX \
+ LEAL (AX)(CX*1), AX \
+ RORXL $0x1b, DX, R12 \
+ PRECALC_39(Y14,0x20,0x120) \
+ ADDL R12, AX
+
+// Similar to CALC_0
+#define CALC_80 \
+ MOVL CX, DX \
+ RORXL $2, CX, CX \
+ ANDNL SI, DX, BP \
+ ANDL BX, DX \
+ XORL BP, DX \
+ CALC_F1_PRE(0x10,AX,DX,BX,DI) \
+ PRECALC_32(Y15,Y14) \
+ CALC_F1_POST(AX,CX,DI)
+
+#define CALC_81 \
+ CALC_F1_PRE(0x14,DI,AX,CX,SI) \
+ PRECALC_33(Y12,Y13) \
+ CALC_F1_POST(DI,DX,SI)
+
+#define CALC_82 \
+ CALC_F1_PRE(0x18,SI,DI,DX,BX) \
+ PRECALC_34(Y5) \
+ CALC_F1_POST(SI,AX,BX)
+
+#define CALC_83 \
+ CALC_F1_PRE(0x1c,BX,SI,AX,CX) \
+ PRECALC_35(Y13) \
+ CALC_F1_POST(BX,DI,CX)
+
+#define CALC_84 \
+ CALC_F1_PRE(0x30,CX,BX,DI,DX) \
+ PRECALC_36(Y13) \
+ CALC_F1_POST(CX,SI,DX)
+
+#define CALC_85 \
+ CALC_F1_PRE(0x34,DX,CX,SI,AX) \
+ PRECALC_37(Y13) \
+ CALC_F1_POST(DX,BX,AX)
+
+#define CALC_86 \
+ CALC_F1_PRE(0x38,AX,DX,BX,DI) \
+ CALC_F1_POST(AX,CX,DI)
+
+#define CALC_87 \
+ CALC_F1_PRE(0x3c,DI,AX,CX,SI) \
+ PRECALC_39(Y13,0x40,0x140) \
+ CALC_F1_POST(DI,DX,SI)
+
+#define CALC_88 \
+ CALC_F1_PRE(0x50,SI,DI,DX,BX) \
+ PRECALC_32(Y14,Y13) \
+ CALC_F1_POST(SI,AX,BX)
+
+#define CALC_89 \
+ CALC_F1_PRE(0x54,BX,SI,AX,CX) \
+ PRECALC_33(Y8,Y12) \
+ CALC_F1_POST(BX,DI,CX)
+
+#define CALC_90 \
+ CALC_F1_PRE(0x58,CX,BX,DI,DX) \
+ PRECALC_34(Y3) \
+ CALC_F1_POST(CX,SI,DX)
+
+#define CALC_91 \
+ CALC_F1_PRE(0x5c,DX,CX,SI,AX) \
+ PRECALC_35(Y12) \
+ CALC_F1_POST(DX,BX,AX)
+
+#define CALC_92 \
+ CALC_F1_PRE(0x70,AX,DX,BX,DI) \
+ PRECALC_36(Y12) \
+ CALC_F1_POST(AX,CX,DI)
+
+#define CALC_93 \
+ CALC_F1_PRE(0x74,DI,AX,CX,SI) \
+ PRECALC_37(Y12) \
+ CALC_F1_POST(DI,DX,SI)
+
+#define CALC_94 \
+ CALC_F1_PRE(0x78,SI,DI,DX,BX) \
+ CALC_F1_POST(SI,AX,BX)
+
+#define CALC_95 \
+ CALC_F1_PRE(0x7c,BX,SI,AX,CX) \
+ PRECALC_39(Y12,0x40,0x160) \
+ CALC_F1_POST(BX,DI,CX)
+
+#define CALC_96 \
+ CALC_F1_PRE(0x90,CX,BX,DI,DX) \
+ PRECALC_32(Y13,Y12) \
+ CALC_F1_POST(CX,SI,DX)
+
+#define CALC_97 \
+ CALC_F1_PRE(0x94,DX,CX,SI,AX) \
+ PRECALC_33(Y7,Y8) \
+ CALC_F1_POST(DX,BX,AX)
+
+#define CALC_98 \
+ CALC_F1_PRE(0x98,AX,DX,BX,DI) \
+ PRECALC_34(Y15) \
+ CALC_F1_POST(AX,CX,DI)
+
+#define CALC_99 \
+ CALC_F2_PRE(0x9c,DI,AX,SI) \
+ PRECALC_35(Y8) \
+ CALC_F2_POST(DI,DX,CX,SI)
+
+#define CALC_100 \
+ CALC_F2_PRE(0xb0,SI,DI,BX) \
+ PRECALC_36(Y8) \
+ CALC_F2_POST(SI,AX,DX,BX)
+
+#define CALC_101 \
+ CALC_F2_PRE(0xb4,BX,SI,CX) \
+ PRECALC_37(Y8) \
+ CALC_F2_POST(BX,DI,AX,CX)
+
+#define CALC_102 \
+ CALC_F2_PRE(0xb8,CX,BX,DX) \
+ CALC_F2_POST(CX,SI,DI,DX)
+
+#define CALC_103 \
+ CALC_F2_PRE(0xbc,DX,CX,AX) \
+ PRECALC_39(Y8,0x40,0x180) \
+ CALC_F2_POST(DX,BX,SI,AX)
+
+#define CALC_104 \
+ CALC_F2_PRE(0xd0,AX,DX,DI) \
+ PRECALC_32(Y12,Y8) \
+ CALC_F2_POST(AX,CX,BX,DI)
+
+#define CALC_105 \
+ CALC_F2_PRE(0xd4,DI,AX,SI) \
+ PRECALC_33(Y5,Y7) \
+ CALC_F2_POST(DI,DX,CX,SI)
+
+#define CALC_106 \
+ CALC_F2_PRE(0xd8,SI,DI,BX) \
+ PRECALC_34(Y14) \
+ CALC_F2_POST(SI,AX,DX,BX)
+
+#define CALC_107 \
+ CALC_F2_PRE(0xdc,BX,SI,CX) \
+ PRECALC_35(Y7) \
+ CALC_F2_POST(BX,DI,AX,CX)
+
+#define CALC_108 \
+ CALC_F2_PRE(0xf0,CX,BX,DX) \
+ PRECALC_36(Y7) \
+ CALC_F2_POST(CX,SI,DI,DX)
+
+#define CALC_109 \
+ CALC_F2_PRE(0xf4,DX,CX,AX) \
+ PRECALC_37(Y7) \
+ CALC_F2_POST(DX,BX,SI,AX)
+
+#define CALC_110 \
+ CALC_F2_PRE(0xf8,AX,DX,DI) \
+ CALC_F2_POST(AX,CX,BX,DI)
+
+#define CALC_111 \
+ CALC_F2_PRE(0xfc,DI,AX,SI) \
+ PRECALC_39(Y7,0x40,0x1a0) \
+ CALC_F2_POST(DI,DX,CX,SI)
+
+#define CALC_112 \
+ CALC_F2_PRE(0x110,SI,DI,BX) \
+ PRECALC_32(Y8,Y7) \
+ CALC_F2_POST(SI,AX,DX,BX)
+
+#define CALC_113 \
+ CALC_F2_PRE(0x114,BX,SI,CX) \
+ PRECALC_33(Y3,Y5) \
+ CALC_F2_POST(BX,DI,AX,CX)
+
+#define CALC_114 \
+ CALC_F2_PRE(0x118,CX,BX,DX) \
+ PRECALC_34(Y13) \
+ CALC_F2_POST(CX,SI,DI,DX)
+
+#define CALC_115 \
+ CALC_F2_PRE(0x11c,DX,CX,AX) \
+ PRECALC_35(Y5) \
+ CALC_F2_POST(DX,BX,SI,AX)
+
+#define CALC_116 \
+ CALC_F2_PRE(0x130,AX,DX,DI) \
+ PRECALC_36(Y5) \
+ CALC_F2_POST(AX,CX,BX,DI)
+
+#define CALC_117 \
+ CALC_F2_PRE(0x134,DI,AX,SI) \
+ PRECALC_37(Y5) \
+ CALC_F2_POST(DI,DX,CX,SI)
+
+#define CALC_118 \
+ CALC_F2_PRE(0x138,SI,DI,BX) \
+ CALC_F2_POST(SI,AX,DX,BX)
+
+#define CALC_119 \
+ CALC_F3_PRE(0x13c,CX) \
+ PRECALC_39(Y5,0x40,0x1c0) \
+ CALC_F3_POST(BX,DI,AX,CX,SI)
+
+#define CALC_120 \
+ CALC_F3_PRE(0x150,DX) \
+ PRECALC_32(Y7,Y5) \
+ CALC_F3_POST(CX,SI,DI,DX,BX)
+
+#define CALC_121 \
+ CALC_F3_PRE(0x154,AX) \
+ PRECALC_33(Y15,Y3) \
+ CALC_F3_POST(DX,BX,SI,AX,CX)
+
+#define CALC_122 \
+ CALC_F3_PRE(0x158,DI) \
+ PRECALC_34(Y12) \
+ CALC_F3_POST(AX,CX,BX,DI,DX)
+
+#define CALC_123 \
+ CALC_F3_PRE(0x15c,SI) \
+ PRECALC_35(Y3) \
+ CALC_F3_POST(DI,DX,CX,SI,AX)
+
+#define CALC_124 \
+ CALC_F3_PRE(0x170,BX) \
+ PRECALC_36(Y3) \
+ CALC_F3_POST(SI,AX,DX,BX,DI)
+
+#define CALC_125 \
+ CALC_F3_PRE(0x174,CX) \
+ PRECALC_37(Y3) \
+ CALC_F3_POST(BX,DI,AX,CX,SI)
+
+#define CALC_126 \
+ CALC_F3_PRE(0x178,DX) \
+ CALC_F3_POST(CX,SI,DI,DX,BX)
+
+#define CALC_127 \
+ CALC_F3_PRE(0x17c,AX) \
+ PRECALC_39(Y3,0x60,0x1e0) \
+ CALC_F3_POST(DX,BX,SI,AX,CX)
+
+#define CALC_128 \
+ CALC_F3_PRE(0x190,DI) \
+ PRECALC_32(Y5,Y3) \
+ CALC_F3_POST(AX,CX,BX,DI,DX)
+
+#define CALC_129 \
+ CALC_F3_PRE(0x194,SI) \
+ PRECALC_33(Y14,Y15) \
+ CALC_F3_POST(DI,DX,CX,SI,AX)
+
+#define CALC_130 \
+ CALC_F3_PRE(0x198,BX) \
+ PRECALC_34(Y8) \
+ CALC_F3_POST(SI,AX,DX,BX,DI)
+
+#define CALC_131 \
+ CALC_F3_PRE(0x19c,CX) \
+ PRECALC_35(Y15) \
+ CALC_F3_POST(BX,DI,AX,CX,SI)
+
+#define CALC_132 \
+ CALC_F3_PRE(0x1b0,DX) \
+ PRECALC_36(Y15) \
+ CALC_F3_POST(CX,SI,DI,DX,BX)
+
+#define CALC_133 \
+ CALC_F3_PRE(0x1b4,AX) \
+ PRECALC_37(Y15) \
+ CALC_F3_POST(DX,BX,SI,AX,CX)
+
+#define CALC_134 \
+ CALC_F3_PRE(0x1b8,DI) \
+ CALC_F3_POST(AX,CX,BX,DI,DX)
+
+#define CALC_135 \
+ CALC_F3_PRE(0x1bc,SI) \
+ PRECALC_39(Y15,0x60,0x200) \
+ CALC_F3_POST(DI,DX,CX,SI,AX)
+
+#define CALC_136 \
+ CALC_F3_PRE(0x1d0,BX) \
+ PRECALC_32(Y3,Y15) \
+ CALC_F3_POST(SI,AX,DX,BX,DI)
+
+#define CALC_137 \
+ CALC_F3_PRE(0x1d4,CX) \
+ PRECALC_33(Y13,Y14) \
+ CALC_F3_POST(BX,DI,AX,CX,SI)
+
+#define CALC_138 \
+ CALC_F3_PRE(0x1d8,DX) \
+ PRECALC_34(Y7) \
+ CALC_F3_POST(CX,SI,DI,DX,BX)
+
+#define CALC_139 \
+ CALC_F2_PRE(0x1dc,DX,CX,AX) \
+ PRECALC_35(Y14) \
+ CALC_F2_POST(DX,BX,SI,AX)
+
+#define CALC_140 \
+ CALC_F2_PRE(0x1f0,AX,DX,DI) \
+ PRECALC_36(Y14) \
+ CALC_F2_POST(AX,CX,BX,DI)
+
+#define CALC_141 \
+ CALC_F2_PRE(0x1f4,DI,AX,SI) \
+ PRECALC_37(Y14) \
+ CALC_F2_POST(DI,DX,CX,SI)
+
+#define CALC_142 \
+ CALC_F2_PRE(0x1f8,SI,DI,BX) \
+ CALC_F2_POST(SI,AX,DX,BX)
+
+#define CALC_143 \
+ CALC_F2_PRE(0x1fc,BX,SI,CX) \
+ PRECALC_39(Y14,0x60,0x220) \
+ CALC_F2_POST(BX,DI,AX,CX)
+
+#define CALC_144 \
+ CALC_F2_PRE(0x210,CX,BX,DX) \
+ PRECALC_32(Y15,Y14) \
+ CALC_F2_POST(CX,SI,DI,DX)
+
+#define CALC_145 \
+ CALC_F2_PRE(0x214,DX,CX,AX) \
+ PRECALC_33(Y12,Y13) \
+ CALC_F2_POST(DX,BX,SI,AX)
+
+#define CALC_146 \
+ CALC_F2_PRE(0x218,AX,DX,DI) \
+ PRECALC_34(Y5) \
+ CALC_F2_POST(AX,CX,BX,DI)
+
+#define CALC_147 \
+ CALC_F2_PRE(0x21c,DI,AX,SI) \
+ PRECALC_35(Y13) \
+ CALC_F2_POST(DI,DX,CX,SI)
+
+#define CALC_148 \
+ CALC_F2_PRE(0x230,SI,DI,BX) \
+ PRECALC_36(Y13) \
+ CALC_F2_POST(SI,AX,DX,BX)
+
+#define CALC_149 \
+ CALC_F2_PRE(0x234,BX,SI,CX) \
+ PRECALC_37(Y13) \
+ CALC_F2_POST(BX,DI,AX,CX)
+
+#define CALC_150 \
+ CALC_F2_PRE(0x238,CX,BX,DX) \
+ CALC_F2_POST(CX,SI,DI,DX)
+
+#define CALC_151 \
+ CALC_F2_PRE(0x23c,DX,CX,AX) \
+ PRECALC_39(Y13,0x60,0x240) \
+ CALC_F2_POST(DX,BX,SI,AX)
+
+#define CALC_152 \
+ CALC_F2_PRE(0x250,AX,DX,DI) \
+ PRECALC_32(Y14,Y13) \
+ CALC_F2_POST(AX,CX,BX,DI)
+
+#define CALC_153 \
+ CALC_F2_PRE(0x254,DI,AX,SI) \
+ PRECALC_33(Y8,Y12) \
+ CALC_F2_POST(DI,DX,CX,SI)
+
+#define CALC_154 \
+ CALC_F2_PRE(0x258,SI,DI,BX) \
+ PRECALC_34(Y3) \
+ CALC_F2_POST(SI,AX,DX,BX)
+
+#define CALC_155 \
+ CALC_F2_PRE(0x25c,BX,SI,CX) \
+ PRECALC_35(Y12) \
+ CALC_F2_POST(BX,DI,AX,CX)
+
+#define CALC_156 \
+ CALC_F2_PRE(0x270,CX,BX,DX) \
+ PRECALC_36(Y12) \
+ CALC_F2_POST(CX,SI,DI,DX)
+
+#define CALC_157 \
+ CALC_F2_PRE(0x274,DX,CX,AX) \
+ PRECALC_37(Y12) \
+ CALC_F2_POST(DX,BX,SI,AX)
+
+#define CALC_158 \
+ CALC_F2_PRE(0x278,AX,DX,DI) \
+ CALC_F2_POST(AX,CX,BX,DI)
+
+#define CALC_159 \
+ ADDL 0x27c(R15),SI \
+ LEAL (SI)(AX*1), SI \
+ RORXL $0x1b, DI, R12 \
+ PRECALC_39(Y12,0x60,0x260) \
+ ADDL R12, SI
+
+
+
+#define CALC \
+ MOVL (R9), CX \
+ MOVL 4(R9), SI \
+ MOVL 8(R9), DI \
+ MOVL 12(R9), AX \
+ MOVL 16(R9), DX \
+ MOVQ SP, R14 \
+ LEAQ (2*4*80+32)(SP), R15 \
+ PRECALC \ // Precalc WK for first 2 blocks
+ XCHGQ R15, R14 \
+loop: \ // this loops is unrolled
+ CMPQ R10, R8 \ // we use R8 value (set below) as a signal of a last block
+ JNE begin \
+ VZEROUPPER \
+ RET \
+begin: \
+ CALC_0 \
+ CALC_1 \
+ CALC_2 \
+ CALC_3 \
+ CALC_4 \
+ CALC_5 \
+ CALC_6 \
+ CALC_7 \
+ CALC_8 \
+ CALC_9 \
+ CALC_10 \
+ CALC_11 \
+ CALC_12 \
+ CALC_13 \
+ CALC_14 \
+ CALC_15 \
+ CALC_16 \
+ CALC_17 \
+ CALC_18 \
+ CALC_19 \
+ CALC_20 \
+ CALC_21 \
+ CALC_22 \
+ CALC_23 \
+ CALC_24 \
+ CALC_25 \
+ CALC_26 \
+ CALC_27 \
+ CALC_28 \
+ CALC_29 \
+ CALC_30 \
+ CALC_31 \
+ CALC_32 \
+ CALC_33 \
+ CALC_34 \
+ CALC_35 \
+ CALC_36 \
+ CALC_37 \
+ CALC_38 \
+ CALC_39 \
+ CALC_40 \
+ CALC_41 \
+ CALC_42 \
+ CALC_43 \
+ CALC_44 \
+ CALC_45 \
+ CALC_46 \
+ CALC_47 \
+ CALC_48 \
+ CALC_49 \
+ CALC_50 \
+ CALC_51 \
+ CALC_52 \
+ CALC_53 \
+ CALC_54 \
+ CALC_55 \
+ CALC_56 \
+ CALC_57 \
+ CALC_58 \
+ CALC_59 \
+ ADDQ $128, R10 \ // move to next even-64-byte block
+ CMPQ R10, R11 \ // is current block the last one?
+ CMOVQCC R8, R10 \ // signal the last iteration smartly
+ CALC_60 \
+ CALC_61 \
+ CALC_62 \
+ CALC_63 \
+ CALC_64 \
+ CALC_65 \
+ CALC_66 \
+ CALC_67 \
+ CALC_68 \
+ CALC_69 \
+ CALC_70 \
+ CALC_71 \
+ CALC_72 \
+ CALC_73 \
+ CALC_74 \
+ CALC_75 \
+ CALC_76 \
+ CALC_77 \
+ CALC_78 \
+ CALC_79 \
+ UPDATE_HASH(AX,DX,BX,SI,DI) \
+ CMPQ R10, R8 \ // is current block the last one?
+ JE loop\
+ MOVL DX, CX \
+ CALC_80 \
+ CALC_81 \
+ CALC_82 \
+ CALC_83 \
+ CALC_84 \
+ CALC_85 \
+ CALC_86 \
+ CALC_87 \
+ CALC_88 \
+ CALC_89 \
+ CALC_90 \
+ CALC_91 \
+ CALC_92 \
+ CALC_93 \
+ CALC_94 \
+ CALC_95 \
+ CALC_96 \
+ CALC_97 \
+ CALC_98 \
+ CALC_99 \
+ CALC_100 \
+ CALC_101 \
+ CALC_102 \
+ CALC_103 \
+ CALC_104 \
+ CALC_105 \
+ CALC_106 \
+ CALC_107 \
+ CALC_108 \
+ CALC_109 \
+ CALC_110 \
+ CALC_111 \
+ CALC_112 \
+ CALC_113 \
+ CALC_114 \
+ CALC_115 \
+ CALC_116 \
+ CALC_117 \
+ CALC_118 \
+ CALC_119 \
+ CALC_120 \
+ CALC_121 \
+ CALC_122 \
+ CALC_123 \
+ CALC_124 \
+ CALC_125 \
+ CALC_126 \
+ CALC_127 \
+ CALC_128 \
+ CALC_129 \
+ CALC_130 \
+ CALC_131 \
+ CALC_132 \
+ CALC_133 \
+ CALC_134 \
+ CALC_135 \
+ CALC_136 \
+ CALC_137 \
+ CALC_138 \
+ CALC_139 \
+ ADDQ $128, R13 \ //move to next even-64-byte block
+ CMPQ R13, R11 \ //is current block the last one?
+ CMOVQCC R8, R10 \
+ CALC_140 \
+ CALC_141 \
+ CALC_142 \
+ CALC_143 \
+ CALC_144 \
+ CALC_145 \
+ CALC_146 \
+ CALC_147 \
+ CALC_148 \
+ CALC_149 \
+ CALC_150 \
+ CALC_151 \
+ CALC_152 \
+ CALC_153 \
+ CALC_154 \
+ CALC_155 \
+ CALC_156 \
+ CALC_157 \
+ CALC_158 \
+ CALC_159 \
+ UPDATE_HASH(SI,DI,DX,CX,BX) \
+ MOVL SI, R12 \ //Reset state for AVX2 reg permutation
+ MOVL DI, SI \
+ MOVL DX, DI \
+ MOVL BX, DX \
+ MOVL CX, AX \
+ MOVL R12, CX \
+ XCHGQ R15, R14 \
+ JMP loop
+
+
+
+TEXT ·blockAVX2(SB),$1408-32
+
+ MOVQ dig+0(FP), DI
+ MOVQ p_base+8(FP), SI
+ MOVQ p_len+16(FP), DX
+ SHRQ $6, DX
+ SHLQ $6, DX
+
+ MOVQ $K_XMM_AR<>(SB), R8
+
+ MOVQ DI, R9
+ MOVQ SI, R10
+ LEAQ 64(SI), R13
+
+ ADDQ SI, DX
+ ADDQ $64, DX
+ MOVQ DX, R11
+
+ CMPQ R13, R11
+ CMOVQCC R8, R13
+
+ MOVQ $BSWAP_SHUFB_CTL<>(SB), R8
+ VMOVDQU (R8), Y10
+ MOVQ $K_XMM_AR<>(SB), R8 //restore R8
+
+ CALC // RET is inside macros
+
+
+// func checkAVX2() bool
+// returns whether AVX2 is supported
+TEXT ·checkAVX2(SB),NOSPLIT,$0
+ CMPB runtime·support_avx2(SB), $1
+ JE has
+ MOVB $0, ret+0(FP)
+ RET
+has:
+ MOVB $1, ret+0(FP)
+ RET
+
+
+DATA K_XMM_AR<>+0x00(SB)/4,$0x5a827999
+DATA K_XMM_AR<>+0x04(SB)/4,$0x5a827999
+DATA K_XMM_AR<>+0x08(SB)/4,$0x5a827999
+DATA K_XMM_AR<>+0x0c(SB)/4,$0x5a827999
+DATA K_XMM_AR<>+0x10(SB)/4,$0x5a827999
+DATA K_XMM_AR<>+0x14(SB)/4,$0x5a827999
+DATA K_XMM_AR<>+0x18(SB)/4,$0x5a827999
+DATA K_XMM_AR<>+0x1c(SB)/4,$0x5a827999
+DATA K_XMM_AR<>+0x20(SB)/4,$0x6ed9eba1
+DATA K_XMM_AR<>+0x24(SB)/4,$0x6ed9eba1
+DATA K_XMM_AR<>+0x28(SB)/4,$0x6ed9eba1
+DATA K_XMM_AR<>+0x2c(SB)/4,$0x6ed9eba1
+DATA K_XMM_AR<>+0x30(SB)/4,$0x6ed9eba1
+DATA K_XMM_AR<>+0x34(SB)/4,$0x6ed9eba1
+DATA K_XMM_AR<>+0x38(SB)/4,$0x6ed9eba1
+DATA K_XMM_AR<>+0x3c(SB)/4,$0x6ed9eba1
+DATA K_XMM_AR<>+0x40(SB)/4,$0x8f1bbcdc
+DATA K_XMM_AR<>+0x44(SB)/4,$0x8f1bbcdc
+DATA K_XMM_AR<>+0x48(SB)/4,$0x8f1bbcdc
+DATA K_XMM_AR<>+0x4c(SB)/4,$0x8f1bbcdc
+DATA K_XMM_AR<>+0x50(SB)/4,$0x8f1bbcdc
+DATA K_XMM_AR<>+0x54(SB)/4,$0x8f1bbcdc
+DATA K_XMM_AR<>+0x58(SB)/4,$0x8f1bbcdc
+DATA K_XMM_AR<>+0x5c(SB)/4,$0x8f1bbcdc
+DATA K_XMM_AR<>+0x60(SB)/4,$0xca62c1d6
+DATA K_XMM_AR<>+0x64(SB)/4,$0xca62c1d6
+DATA K_XMM_AR<>+0x68(SB)/4,$0xca62c1d6
+DATA K_XMM_AR<>+0x6c(SB)/4,$0xca62c1d6
+DATA K_XMM_AR<>+0x70(SB)/4,$0xca62c1d6
+DATA K_XMM_AR<>+0x74(SB)/4,$0xca62c1d6
+DATA K_XMM_AR<>+0x78(SB)/4,$0xca62c1d6
+DATA K_XMM_AR<>+0x7c(SB)/4,$0xca62c1d6
+GLOBL K_XMM_AR<>(SB),RODATA,$128
+
+DATA BSWAP_SHUFB_CTL<>+0x00(SB)/4,$0x00010203
+DATA BSWAP_SHUFB_CTL<>+0x04(SB)/4,$0x04050607
+DATA BSWAP_SHUFB_CTL<>+0x08(SB)/4,$0x08090a0b
+DATA BSWAP_SHUFB_CTL<>+0x0c(SB)/4,$0x0c0d0e0f
+DATA BSWAP_SHUFB_CTL<>+0x10(SB)/4,$0x00010203
+DATA BSWAP_SHUFB_CTL<>+0x14(SB)/4,$0x04050607
+DATA BSWAP_SHUFB_CTL<>+0x18(SB)/4,$0x08090a0b
+DATA BSWAP_SHUFB_CTL<>+0x1c(SB)/4,$0x0c0d0e0f
+GLOBL BSWAP_SHUFB_CTL<>(SB),RODATA,$32
diff --git a/src/crypto/sha1/sha1block_decl.go b/src/crypto/sha1/sha1block_decl.go
index a85b74b8787174..6d2d073d137331 100644
--- a/src/crypto/sha1/sha1block_decl.go
+++ b/src/crypto/sha1/sha1block_decl.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 amd64 amd64p32 arm 386 s390x
+// +build amd64p32 arm 386 s390x
package sha1
From bf151cc2aa4094b4633a7e5f07a34227d58231fe Mon Sep 17 00:00:00 2001
From: Cherry Zhang
Date: Thu, 5 May 2016 16:51:54 -0700
Subject: [PATCH 017/267] cmd/compile/internal/mips64: fix large uint -> float
conversion
Re-enable TestFP in cmd/compile/internal/gc on mips64.
Fixes #15552.
Change-Id: I5c3a5564b94d28c723358f0862468fb6da371991
Reviewed-on: https://go-review.googlesource.com/22835
Reviewed-by: Brad Fitzpatrick
Reviewed-by: Minux Ma
Run-TryBot: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
---
src/cmd/compile/internal/gc/ssa_test.go | 7 +------
src/cmd/compile/internal/mips64/gsubr.go | 11 +++++++++--
2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/src/cmd/compile/internal/gc/ssa_test.go b/src/cmd/compile/internal/gc/ssa_test.go
index 8a233eafe0d6d7..c89917df88c268 100644
--- a/src/cmd/compile/internal/gc/ssa_test.go
+++ b/src/cmd/compile/internal/gc/ssa_test.go
@@ -57,12 +57,7 @@ func TestArithmetic(t *testing.T) {
}
// TestFP tests that both backends have the same result for floating point expressions.
-func TestFP(t *testing.T) {
- if runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le" {
- t.Skip("legacy mips64 compiler doesn't handle uint->float conversion correctly (issue 15552)")
- }
- runTest(t, "fp_ssa.go")
-}
+func TestFP(t *testing.T) { runTest(t, "fp_ssa.go") }
// TestArithmeticBoundary tests boundary results for arithmetic operations.
func TestArithmeticBoundary(t *testing.T) { runTest(t, "arithBoundary_ssa.go") }
diff --git a/src/cmd/compile/internal/mips64/gsubr.go b/src/cmd/compile/internal/mips64/gsubr.go
index 864fd76d121f9e..eb56d8b82e6e93 100644
--- a/src/cmd/compile/internal/mips64/gsubr.go
+++ b/src/cmd/compile/internal/mips64/gsubr.go
@@ -466,7 +466,7 @@ func gmove(f *gc.Node, t *gc.Node) {
//return;
// algorithm is:
// if small enough, use native int64 -> float64 conversion.
- // otherwise, halve (rounding to odd?), convert, and double.
+ // otherwise, halve (x -> (x>>1)|(x&1)), convert, and double.
/*
* integer to float
*/
@@ -496,9 +496,16 @@ func gmove(f *gc.Node, t *gc.Node) {
gmove(&bigi, &rtmp)
gins(mips.AAND, &r1, &rtmp)
p1 := ginsbranch(mips.ABEQ, nil, &rtmp, nil, 0)
- p2 := gins(mips.ASRLV, nil, &r1)
+ var r3 gc.Node
+ gc.Regalloc(&r3, gc.Types[gc.TUINT64], nil)
+ p2 := gins3(mips.AAND, nil, &r1, &r3)
p2.From.Type = obj.TYPE_CONST
p2.From.Offset = 1
+ p3 := gins(mips.ASRLV, nil, &r1)
+ p3.From.Type = obj.TYPE_CONST
+ p3.From.Offset = 1
+ gins(mips.AOR, &r3, &r1)
+ gc.Regfree(&r3)
gc.Patch(p1, gc.Pc)
}
From 2dc680007e35f4cb87527582eb73a653392aa8c3 Mon Sep 17 00:00:00 2001
From: Brad Fitzpatrick
Date: Fri, 6 May 2016 08:26:37 -0700
Subject: [PATCH 018/267] runtime: merge the last four os-vs-os1 files together
Change-Id: Ib0ba691c4657fe18a4659753e70d97c623cb9c1d
Reviewed-on: https://go-review.googlesource.com/22850
Run-TryBot: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
Reviewed-by: Ian Lance Taylor
---
src/runtime/os1_freebsd.go | 30 ++++++++
src/runtime/os1_nacl.go | 62 ++++++++++++++++
src/runtime/os1_openbsd.go | 33 +++++++++
src/runtime/os1_plan9.go | 143 ++++++++++++++++++++++++++++++++++++
src/runtime/os_freebsd.go | 32 --------
src/runtime/os_nacl.go | 64 ----------------
src/runtime/os_openbsd.go | 33 ---------
src/runtime/os_plan9.go | 145 -------------------------------------
8 files changed, 268 insertions(+), 274 deletions(-)
diff --git a/src/runtime/os1_freebsd.go b/src/runtime/os1_freebsd.go
index 0dafe02325b792..3a73b6627743e3 100644
--- a/src/runtime/os1_freebsd.go
+++ b/src/runtime/os1_freebsd.go
@@ -9,6 +9,36 @@ import (
"unsafe"
)
+type mOS struct{}
+
+//go:noescape
+func thr_new(param *thrparam, size int32)
+
+//go:noescape
+func sigaltstack(new, old *stackt)
+
+//go:noescape
+func sigaction(sig int32, new, old *sigactiont)
+
+//go:noescape
+func sigprocmask(how int32, new, old *sigset)
+
+//go:noescape
+func setitimer(mode int32, new, old *itimerval)
+
+//go:noescape
+func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
+
+//go:noescape
+func getrlimit(kind int32, limit unsafe.Pointer) int32
+func raise(sig int32)
+func raiseproc(sig int32)
+
+//go:noescape
+func sys_umtx_op(addr *uint32, mode int32, val uint32, ptr2, ts *timespec) int32
+
+func osyield()
+
// From FreeBSD's
const (
_CTL_HW = 6
diff --git a/src/runtime/os1_nacl.go b/src/runtime/os1_nacl.go
index feea4966529496..6cbd16de159c8c 100644
--- a/src/runtime/os1_nacl.go
+++ b/src/runtime/os1_nacl.go
@@ -6,6 +6,68 @@ package runtime
import "unsafe"
+type mOS struct {
+ waitsema int32 // semaphore for parking on locks
+ waitsemacount int32
+ waitsemalock int32
+}
+
+func nacl_exception_stack(p uintptr, size int32) int32
+func nacl_exception_handler(fn uintptr, arg unsafe.Pointer) int32
+func nacl_sem_create(flag int32) int32
+func nacl_sem_wait(sem int32) int32
+func nacl_sem_post(sem int32) int32
+func nacl_mutex_create(flag int32) int32
+func nacl_mutex_lock(mutex int32) int32
+func nacl_mutex_trylock(mutex int32) int32
+func nacl_mutex_unlock(mutex int32) int32
+func nacl_cond_create(flag int32) int32
+func nacl_cond_wait(cond, n int32) int32
+func nacl_cond_signal(cond int32) int32
+func nacl_cond_broadcast(cond int32) int32
+
+//go:noescape
+func nacl_cond_timed_wait_abs(cond, lock int32, ts *timespec) int32
+func nacl_thread_create(fn uintptr, stk, tls, xx unsafe.Pointer) int32
+
+//go:noescape
+func nacl_nanosleep(ts, extra *timespec) int32
+func nanotime() int64
+func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer
+func exit(code int32)
+func osyield()
+
+//go:noescape
+func write(fd uintptr, p unsafe.Pointer, n int32) int32
+
+//go:linkname os_sigpipe os.sigpipe
+func os_sigpipe() {
+ throw("too many writes on closed pipe")
+}
+
+func dieFromSignal(sig int32) {
+ exit(2)
+}
+
+func sigpanic() {
+ g := getg()
+ if !canpanic(g) {
+ throw("unexpected signal during runtime execution")
+ }
+
+ // Native Client only invokes the exception handler for memory faults.
+ g.sig = _SIGSEGV
+ panicmem()
+}
+
+func raiseproc(sig int32) {
+}
+
+// Stubs so tests can link correctly. These should never be called.
+func open(name *byte, mode, perm int32) int32
+func closefd(fd int32) int32
+func read(fd int32, p unsafe.Pointer, n int32) int32
+
type sigset struct{}
// Called to initialize a new m (including the bootstrap m).
diff --git a/src/runtime/os1_openbsd.go b/src/runtime/os1_openbsd.go
index 447dff81938e4a..ded6b1d4ea4a83 100644
--- a/src/runtime/os1_openbsd.go
+++ b/src/runtime/os1_openbsd.go
@@ -9,6 +9,39 @@ import (
"unsafe"
)
+type mOS struct {
+ waitsemacount uint32
+}
+
+//go:noescape
+func setitimer(mode int32, new, old *itimerval)
+
+//go:noescape
+func sigaction(sig int32, new, old *sigactiont)
+
+//go:noescape
+func sigaltstack(new, old *stackt)
+
+//go:noescape
+func sigprocmask(mode int32, new sigset) sigset
+
+//go:noescape
+func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
+
+func raise(sig int32)
+func raiseproc(sig int32)
+
+//go:noescape
+func tfork(param *tforkt, psize uintptr, mm *m, gg *g, fn uintptr) int32
+
+//go:noescape
+func thrsleep(ident uintptr, clock_id int32, tsp *timespec, lock uintptr, abort *uint32) int32
+
+//go:noescape
+func thrwakeup(ident uintptr, n int32) int32
+
+func osyield()
+
const (
_ESRCH = 3
_EAGAIN = 35
diff --git a/src/runtime/os1_plan9.go b/src/runtime/os1_plan9.go
index 6c7e36d0620a0f..2f3a0d1a19b2fd 100644
--- a/src/runtime/os1_plan9.go
+++ b/src/runtime/os1_plan9.go
@@ -9,6 +9,149 @@ import (
"unsafe"
)
+type mOS struct {
+ waitsemacount uint32
+ notesig *int8
+ errstr *byte
+}
+
+func closefd(fd int32) int32
+
+//go:noescape
+func open(name *byte, mode, perm int32) int32
+
+//go:noescape
+func pread(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
+
+//go:noescape
+func pwrite(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
+
+func seek(fd int32, offset int64, whence int32) int64
+
+//go:noescape
+func exits(msg *byte)
+
+//go:noescape
+func brk_(addr unsafe.Pointer) int32
+
+func sleep(ms int32) int32
+
+func rfork(flags int32) int32
+
+//go:noescape
+func plan9_semacquire(addr *uint32, block int32) int32
+
+//go:noescape
+func plan9_tsemacquire(addr *uint32, ms int32) int32
+
+//go:noescape
+func plan9_semrelease(addr *uint32, count int32) int32
+
+//go:noescape
+func notify(fn unsafe.Pointer) int32
+
+func noted(mode int32) int32
+
+//go:noescape
+func nsec(*int64) int64
+
+//go:noescape
+func sigtramp(ureg, msg unsafe.Pointer)
+
+func setfpmasks()
+
+//go:noescape
+func tstart_plan9(newm *m)
+
+func errstr() string
+
+type _Plink uintptr
+
+//go:linkname os_sigpipe os.sigpipe
+func os_sigpipe() {
+ throw("too many writes on closed pipe")
+}
+
+func sigpanic() {
+ g := getg()
+ if !canpanic(g) {
+ throw("unexpected signal during runtime execution")
+ }
+
+ note := gostringnocopy((*byte)(unsafe.Pointer(g.m.notesig)))
+ switch g.sig {
+ case _SIGRFAULT, _SIGWFAULT:
+ i := index(note, "addr=")
+ if i >= 0 {
+ i += 5
+ } else if i = index(note, "va="); i >= 0 {
+ i += 3
+ } else {
+ panicmem()
+ }
+ addr := note[i:]
+ g.sigcode1 = uintptr(atolwhex(addr))
+ if g.sigcode1 < 0x1000 || g.paniconfault {
+ panicmem()
+ }
+ print("unexpected fault address ", hex(g.sigcode1), "\n")
+ throw("fault")
+ case _SIGTRAP:
+ if g.paniconfault {
+ panicmem()
+ }
+ throw(note)
+ case _SIGINTDIV:
+ panicdivide()
+ case _SIGFLOAT:
+ panicfloat()
+ default:
+ panic(errorString(note))
+ }
+}
+
+func atolwhex(p string) int64 {
+ for hasprefix(p, " ") || hasprefix(p, "\t") {
+ p = p[1:]
+ }
+ neg := false
+ if hasprefix(p, "-") || hasprefix(p, "+") {
+ neg = p[0] == '-'
+ p = p[1:]
+ for hasprefix(p, " ") || hasprefix(p, "\t") {
+ p = p[1:]
+ }
+ }
+ var n int64
+ switch {
+ case hasprefix(p, "0x"), hasprefix(p, "0X"):
+ p = p[2:]
+ for ; len(p) > 0; p = p[1:] {
+ if '0' <= p[0] && p[0] <= '9' {
+ n = n*16 + int64(p[0]-'0')
+ } else if 'a' <= p[0] && p[0] <= 'f' {
+ n = n*16 + int64(p[0]-'a'+10)
+ } else if 'A' <= p[0] && p[0] <= 'F' {
+ n = n*16 + int64(p[0]-'A'+10)
+ } else {
+ break
+ }
+ }
+ case hasprefix(p, "0"):
+ for ; len(p) > 0 && '0' <= p[0] && p[0] <= '7'; p = p[1:] {
+ n = n*8 + int64(p[0]-'0')
+ }
+ default:
+ for ; len(p) > 0 && '0' <= p[0] && p[0] <= '9'; p = p[1:] {
+ n = n*10 + int64(p[0]-'0')
+ }
+ }
+ if neg {
+ n = -n
+ }
+ return n
+}
+
type sigset struct{}
// Called to initialize a new m (including the bootstrap m).
diff --git a/src/runtime/os_freebsd.go b/src/runtime/os_freebsd.go
index 44830650e12952..47bf8fc20d627d 100644
--- a/src/runtime/os_freebsd.go
+++ b/src/runtime/os_freebsd.go
@@ -3,35 +3,3 @@
// license that can be found in the LICENSE file.
package runtime
-
-import "unsafe"
-
-type mOS struct{}
-
-//go:noescape
-func thr_new(param *thrparam, size int32)
-
-//go:noescape
-func sigaltstack(new, old *stackt)
-
-//go:noescape
-func sigaction(sig int32, new, old *sigactiont)
-
-//go:noescape
-func sigprocmask(how int32, new, old *sigset)
-
-//go:noescape
-func setitimer(mode int32, new, old *itimerval)
-
-//go:noescape
-func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
-
-//go:noescape
-func getrlimit(kind int32, limit unsafe.Pointer) int32
-func raise(sig int32)
-func raiseproc(sig int32)
-
-//go:noescape
-func sys_umtx_op(addr *uint32, mode int32, val uint32, ptr2, ts *timespec) int32
-
-func osyield()
diff --git a/src/runtime/os_nacl.go b/src/runtime/os_nacl.go
index 6f126b4770505e..47bf8fc20d627d 100644
--- a/src/runtime/os_nacl.go
+++ b/src/runtime/os_nacl.go
@@ -3,67 +3,3 @@
// license that can be found in the LICENSE file.
package runtime
-
-import "unsafe"
-
-type mOS struct {
- waitsema int32 // semaphore for parking on locks
- waitsemacount int32
- waitsemalock int32
-}
-
-func nacl_exception_stack(p uintptr, size int32) int32
-func nacl_exception_handler(fn uintptr, arg unsafe.Pointer) int32
-func nacl_sem_create(flag int32) int32
-func nacl_sem_wait(sem int32) int32
-func nacl_sem_post(sem int32) int32
-func nacl_mutex_create(flag int32) int32
-func nacl_mutex_lock(mutex int32) int32
-func nacl_mutex_trylock(mutex int32) int32
-func nacl_mutex_unlock(mutex int32) int32
-func nacl_cond_create(flag int32) int32
-func nacl_cond_wait(cond, n int32) int32
-func nacl_cond_signal(cond int32) int32
-func nacl_cond_broadcast(cond int32) int32
-
-//go:noescape
-func nacl_cond_timed_wait_abs(cond, lock int32, ts *timespec) int32
-func nacl_thread_create(fn uintptr, stk, tls, xx unsafe.Pointer) int32
-
-//go:noescape
-func nacl_nanosleep(ts, extra *timespec) int32
-func nanotime() int64
-func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer
-func exit(code int32)
-func osyield()
-
-//go:noescape
-func write(fd uintptr, p unsafe.Pointer, n int32) int32
-
-//go:linkname os_sigpipe os.sigpipe
-func os_sigpipe() {
- throw("too many writes on closed pipe")
-}
-
-func dieFromSignal(sig int32) {
- exit(2)
-}
-
-func sigpanic() {
- g := getg()
- if !canpanic(g) {
- throw("unexpected signal during runtime execution")
- }
-
- // Native Client only invokes the exception handler for memory faults.
- g.sig = _SIGSEGV
- panicmem()
-}
-
-func raiseproc(sig int32) {
-}
-
-// Stubs so tests can link correctly. These should never be called.
-func open(name *byte, mode, perm int32) int32
-func closefd(fd int32) int32
-func read(fd int32, p unsafe.Pointer, n int32) int32
diff --git a/src/runtime/os_openbsd.go b/src/runtime/os_openbsd.go
index 3748ed2e514cc1..47bf8fc20d627d 100644
--- a/src/runtime/os_openbsd.go
+++ b/src/runtime/os_openbsd.go
@@ -3,36 +3,3 @@
// license that can be found in the LICENSE file.
package runtime
-
-type mOS struct {
- waitsemacount uint32
-}
-
-//go:noescape
-func setitimer(mode int32, new, old *itimerval)
-
-//go:noescape
-func sigaction(sig int32, new, old *sigactiont)
-
-//go:noescape
-func sigaltstack(new, old *stackt)
-
-//go:noescape
-func sigprocmask(mode int32, new sigset) sigset
-
-//go:noescape
-func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
-
-func raise(sig int32)
-func raiseproc(sig int32)
-
-//go:noescape
-func tfork(param *tforkt, psize uintptr, mm *m, gg *g, fn uintptr) int32
-
-//go:noescape
-func thrsleep(ident uintptr, clock_id int32, tsp *timespec, lock uintptr, abort *uint32) int32
-
-//go:noescape
-func thrwakeup(ident uintptr, n int32) int32
-
-func osyield()
diff --git a/src/runtime/os_plan9.go b/src/runtime/os_plan9.go
index 5c43a3bd854b34..47bf8fc20d627d 100644
--- a/src/runtime/os_plan9.go
+++ b/src/runtime/os_plan9.go
@@ -3,148 +3,3 @@
// license that can be found in the LICENSE file.
package runtime
-
-import "unsafe"
-
-type mOS struct {
- waitsemacount uint32
- notesig *int8
- errstr *byte
-}
-
-func closefd(fd int32) int32
-
-//go:noescape
-func open(name *byte, mode, perm int32) int32
-
-//go:noescape
-func pread(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
-
-//go:noescape
-func pwrite(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
-
-func seek(fd int32, offset int64, whence int32) int64
-
-//go:noescape
-func exits(msg *byte)
-
-//go:noescape
-func brk_(addr unsafe.Pointer) int32
-
-func sleep(ms int32) int32
-
-func rfork(flags int32) int32
-
-//go:noescape
-func plan9_semacquire(addr *uint32, block int32) int32
-
-//go:noescape
-func plan9_tsemacquire(addr *uint32, ms int32) int32
-
-//go:noescape
-func plan9_semrelease(addr *uint32, count int32) int32
-
-//go:noescape
-func notify(fn unsafe.Pointer) int32
-
-func noted(mode int32) int32
-
-//go:noescape
-func nsec(*int64) int64
-
-//go:noescape
-func sigtramp(ureg, msg unsafe.Pointer)
-
-func setfpmasks()
-
-//go:noescape
-func tstart_plan9(newm *m)
-
-func errstr() string
-
-type _Plink uintptr
-
-//go:linkname os_sigpipe os.sigpipe
-func os_sigpipe() {
- throw("too many writes on closed pipe")
-}
-
-func sigpanic() {
- g := getg()
- if !canpanic(g) {
- throw("unexpected signal during runtime execution")
- }
-
- note := gostringnocopy((*byte)(unsafe.Pointer(g.m.notesig)))
- switch g.sig {
- case _SIGRFAULT, _SIGWFAULT:
- i := index(note, "addr=")
- if i >= 0 {
- i += 5
- } else if i = index(note, "va="); i >= 0 {
- i += 3
- } else {
- panicmem()
- }
- addr := note[i:]
- g.sigcode1 = uintptr(atolwhex(addr))
- if g.sigcode1 < 0x1000 || g.paniconfault {
- panicmem()
- }
- print("unexpected fault address ", hex(g.sigcode1), "\n")
- throw("fault")
- case _SIGTRAP:
- if g.paniconfault {
- panicmem()
- }
- throw(note)
- case _SIGINTDIV:
- panicdivide()
- case _SIGFLOAT:
- panicfloat()
- default:
- panic(errorString(note))
- }
-}
-
-func atolwhex(p string) int64 {
- for hasprefix(p, " ") || hasprefix(p, "\t") {
- p = p[1:]
- }
- neg := false
- if hasprefix(p, "-") || hasprefix(p, "+") {
- neg = p[0] == '-'
- p = p[1:]
- for hasprefix(p, " ") || hasprefix(p, "\t") {
- p = p[1:]
- }
- }
- var n int64
- switch {
- case hasprefix(p, "0x"), hasprefix(p, "0X"):
- p = p[2:]
- for ; len(p) > 0; p = p[1:] {
- if '0' <= p[0] && p[0] <= '9' {
- n = n*16 + int64(p[0]-'0')
- } else if 'a' <= p[0] && p[0] <= 'f' {
- n = n*16 + int64(p[0]-'a'+10)
- } else if 'A' <= p[0] && p[0] <= 'F' {
- n = n*16 + int64(p[0]-'A'+10)
- } else {
- break
- }
- }
- case hasprefix(p, "0"):
- for ; len(p) > 0 && '0' <= p[0] && p[0] <= '7'; p = p[1:] {
- n = n*8 + int64(p[0]-'0')
- }
- default:
- for ; len(p) > 0 && '0' <= p[0] && p[0] <= '9'; p = p[1:] {
- n = n*10 + int64(p[0]-'0')
- }
- }
- if neg {
- n = -n
- }
- return n
-}
From 258a4c3daf992958f5d7dc5bccf2c5b41e236959 Mon Sep 17 00:00:00 2001
From: Richard Miller
Date: Fri, 6 May 2016 14:21:52 +0100
Subject: [PATCH 019/267] syscall,os,net: don't use ForkLock in plan9
This is the follow-on to CL 22610: now that it's the child instead of
the parent which lists unwanted fds to close in syscall.StartProcess,
plan9 no longer needs the ForkLock to protect the list from changing.
The readdupdevice function is also now unused and can be removed.
Change-Id: I904c8bbf5dbaa7022b0f1a1de0862cd3064ca8c7
Reviewed-on: https://go-review.googlesource.com/22842
Reviewed-by: David du Colombier <0intro@gmail.com>
Run-TryBot: David du Colombier <0intro@gmail.com>
Reviewed-by: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
---
src/net/fd_plan9.go | 2 -
src/net/file_plan9.go | 2 -
src/os/file_plan9.go | 5 ---
src/syscall/exec_plan9.go | 82 +--------------------------------------
4 files changed, 1 insertion(+), 90 deletions(-)
diff --git a/src/net/fd_plan9.go b/src/net/fd_plan9.go
index 329d6152b2d989..8e272b1eb85e53 100644
--- a/src/net/fd_plan9.go
+++ b/src/net/fd_plan9.go
@@ -154,9 +154,7 @@ func (l *TCPListener) dup() (*os.File, error) {
}
func (fd *netFD) file(f *os.File, s string) (*os.File, error) {
- syscall.ForkLock.RLock()
dfd, err := syscall.Dup(int(f.Fd()), -1)
- syscall.ForkLock.RUnlock()
if err != nil {
return nil, os.NewSyscallError("dup", err)
}
diff --git a/src/net/file_plan9.go b/src/net/file_plan9.go
index 24efdc5186d89f..2939c09a43097f 100644
--- a/src/net/file_plan9.go
+++ b/src/net/file_plan9.go
@@ -50,9 +50,7 @@ func newFileFD(f *os.File) (net *netFD, err error) {
name := comp[2]
switch file := comp[n-1]; file {
case "ctl", "clone":
- syscall.ForkLock.RLock()
fd, err := syscall.Dup(int(f.Fd()), -1)
- syscall.ForkLock.RUnlock()
if err != nil {
return nil, os.NewSyscallError("dup", err)
}
diff --git a/src/os/file_plan9.go b/src/os/file_plan9.go
index fb796a2a89bcba..9edb6bc0747d08 100644
--- a/src/os/file_plan9.go
+++ b/src/os/file_plan9.go
@@ -146,11 +146,9 @@ func (file *file) close() error {
return ErrInvalid
}
var err error
- syscall.ForkLock.RLock()
if e := syscall.Close(file.fd); e != nil {
err = &PathError{"close", file.name, e}
}
- syscall.ForkLock.RUnlock()
file.fd = -1 // so it can't be closed again
// no need for a finalizer anymore
@@ -420,12 +418,9 @@ func Chtimes(name string, atime time.Time, mtime time.Time) error {
func Pipe() (r *File, w *File, err error) {
var p [2]int
- syscall.ForkLock.RLock()
if e := syscall.Pipe(p[0:]); e != nil {
- syscall.ForkLock.RUnlock()
return nil, nil, NewSyscallError("pipe", e)
}
- syscall.ForkLock.RUnlock()
return NewFile(uintptr(p[0]), "|0"), NewFile(uintptr(p[1]), "|1"), nil
}
diff --git a/src/syscall/exec_plan9.go b/src/syscall/exec_plan9.go
index 58e5a3c623b62a..6551bcb1c1f215 100644
--- a/src/syscall/exec_plan9.go
+++ b/src/syscall/exec_plan9.go
@@ -12,53 +12,7 @@ import (
"unsafe"
)
-// Lock synchronizing creation of new file descriptors with fork.
-//
-// We want the child in a fork/exec sequence to inherit only the
-// file descriptors we intend. To do that, we mark all file
-// descriptors close-on-exec and then, in the child, explicitly
-// unmark the ones we want the exec'ed program to keep.
-// Unix doesn't make this easy: there is, in general, no way to
-// allocate a new file descriptor close-on-exec. Instead you
-// have to allocate the descriptor and then mark it close-on-exec.
-// If a fork happens between those two events, the child's exec
-// will inherit an unwanted file descriptor.
-//
-// This lock solves that race: the create new fd/mark close-on-exec
-// operation is done holding ForkLock for reading, and the fork itself
-// is done holding ForkLock for writing. At least, that's the idea.
-// There are some complications.
-//
-// Some system calls that create new file descriptors can block
-// for arbitrarily long times: open on a hung NFS server or named
-// pipe, accept on a socket, and so on. We can't reasonably grab
-// the lock across those operations.
-//
-// It is worse to inherit some file descriptors than others.
-// If a non-malicious child accidentally inherits an open ordinary file,
-// that's not a big deal. On the other hand, if a long-lived child
-// accidentally inherits the write end of a pipe, then the reader
-// of that pipe will not see EOF until that child exits, potentially
-// causing the parent program to hang. This is a common problem
-// in threaded C programs that use popen.
-//
-// Luckily, the file descriptors that are most important not to
-// inherit are not the ones that can take an arbitrarily long time
-// to create: pipe returns instantly, and the net package uses
-// non-blocking I/O to accept on a listening socket.
-// The rules for which file descriptor-creating operations use the
-// ForkLock are as follows:
-//
-// 1) Pipe. Does not block. Use the ForkLock.
-// 2) Socket. Does not block. Use the ForkLock.
-// 3) Accept. If using non-blocking mode, use the ForkLock.
-// Otherwise, live with the race.
-// 4) Open. Can block. Use O_CLOEXEC if available (Linux).
-// Otherwise, live with the race.
-// 5) Dup. Does not block. Use the ForkLock.
-// On Linux, could use fcntl F_DUPFD_CLOEXEC
-// instead of the ForkLock, but only for dup(fd, -1).
-
+// ForkLock is not used on plan9.
var ForkLock sync.RWMutex
// gstringb reads a non-empty string from b, prefixed with a 16-bit length in little-endian order.
@@ -151,35 +105,6 @@ func readdirnames(dirfd int) (names []string, err error) {
return
}
-// readdupdevice returns a list of currently opened fds (excluding stdin, stdout, stderr) from the dup device #d.
-// ForkLock should be write locked before calling, so that no new fds would be created while the fd list is being read.
-func readdupdevice() (fds []int, err error) {
- dupdevfd, err := Open("#d", O_RDONLY)
- if err != nil {
- return
- }
- defer Close(dupdevfd)
-
- names, err := readdirnames(dupdevfd)
- if err != nil {
- return
- }
-
- fds = make([]int, 0, len(names)/2)
- for _, name := range names {
- if n := len(name); n > 3 && name[n-3:n] == "ctl" {
- continue
- }
- fd := int(atoi([]byte(name)))
- switch fd {
- case 0, 1, 2, dupdevfd:
- continue
- }
- fds = append(fds, fd)
- }
- return
-}
-
// name of the directory containing names and control files for all open file descriptors
var dupdev, _ = BytePtrFromString("#d")
@@ -492,9 +417,6 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
}
}
- // Acquire the fork lock to prevent other threads from creating new fds before we fork.
- ForkLock.Lock()
-
// Allocate child status pipe close on exec.
e := cexecPipe(p[:])
@@ -510,10 +432,8 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
Close(p[0])
Close(p[1])
}
- ForkLock.Unlock()
return 0, err
}
- ForkLock.Unlock()
// Read child error status from pipe.
Close(p[1])
From c81a3532fea42df33dea54497dfaa96873c2d976 Mon Sep 17 00:00:00 2001
From: Aliaksandr Valialkin
Date: Fri, 15 Apr 2016 00:33:28 +0300
Subject: [PATCH 020/267] cmd/vet: check sync.* types' copying
Embed noLock struct into the following types, so `go vet -copylocks` catches
their copying additionally to types containing sync.Mutex:
- sync.Cond
- sync.WaitGroup
- sync.Pool
- atomic.Value
Fixes #14582
Change-Id: Icb543ef5ad10524ad239a15eec8a9b334b0e0660
Reviewed-on: https://go-review.googlesource.com/22015
Reviewed-by: Russ Cox
Run-TryBot: Russ Cox
TryBot-Result: Gobot Gobot
---
src/cmd/vet/testdata/copylock.go | 74 +++++++++++++++++++++++++++++++-
src/sync/atomic/value.go | 14 ++++++
src/sync/cond.go | 12 ++++++
src/sync/mutex.go | 2 +
src/sync/pool.go | 3 ++
src/sync/rwmutex.go | 2 +
src/sync/waitgroup.go | 4 ++
7 files changed, 110 insertions(+), 1 deletion(-)
diff --git a/src/cmd/vet/testdata/copylock.go b/src/cmd/vet/testdata/copylock.go
index cf56802cdbb249..d49f4686275871 100644
--- a/src/cmd/vet/testdata/copylock.go
+++ b/src/cmd/vet/testdata/copylock.go
@@ -1,6 +1,9 @@
package testdata
-import "sync"
+import (
+ "sync"
+ "sync/atomic"
+)
func OkFunc() {
var x *sync.Mutex
@@ -66,3 +69,72 @@ func BadFunc() {
new := func(interface{}) {}
new(t) // ERROR "function call copies lock value: testdata.Tlock contains sync.Once contains sync.Mutex"
}
+
+// SyncTypesCheck checks copying of sync.* types except sync.Mutex
+func SyncTypesCheck() {
+ // sync.RWMutex copying
+ var rwmuX sync.RWMutex
+ var rwmuXX = sync.RWMutex{}
+ rwmuX1 := new(sync.RWMutex)
+ rwmuY := rwmuX // ERROR "assignment copies lock value to rwmuY: sync.RWMutex"
+ rwmuY = rwmuX // ERROR "assignment copies lock value to rwmuY: sync.RWMutex"
+ var rwmuYY = rwmuX // ERROR "variable declaration copies lock value to rwmuYY: sync.RWMutex"
+ rwmuP := &rwmuX
+ rwmuZ := &sync.RWMutex{}
+
+ // sync.Cond copying
+ var condX sync.Cond
+ var condXX = sync.Cond{}
+ condX1 := new(sync.Cond)
+ condY := condX // ERROR "assignment copies lock value to condY: sync.Cond contains sync.noCopy"
+ condY = condX // ERROR "assignment copies lock value to condY: sync.Cond contains sync.noCopy"
+ var condYY = condX // ERROR "variable declaration copies lock value to condYY: sync.Cond contains sync.noCopy"
+ condP := &condX
+ condZ := &sync.Cond{
+ L: &sync.Mutex{},
+ }
+ condZ = sync.NewCond(&sync.Mutex{})
+
+ // sync.WaitGroup copying
+ var wgX sync.WaitGroup
+ var wgXX = sync.WaitGroup{}
+ wgX1 := new(sync.WaitGroup)
+ wgY := wgX // ERROR "assignment copies lock value to wgY: sync.WaitGroup contains sync.noCopy"
+ wgY = wgX // ERROR "assignment copies lock value to wgY: sync.WaitGroup contains sync.noCopy"
+ var wgYY = wgX // ERROR "variable declaration copies lock value to wgYY: sync.WaitGroup contains sync.noCopy"
+ wgP := &wgX
+ wgZ := &sync.WaitGroup{}
+
+ // sync.Pool copying
+ var poolX sync.Pool
+ var poolXX = sync.Pool{}
+ poolX1 := new(sync.Pool)
+ poolY := poolX // ERROR "assignment copies lock value to poolY: sync.Pool contains sync.noCopy"
+ poolY = poolX // ERROR "assignment copies lock value to poolY: sync.Pool contains sync.noCopy"
+ var poolYY = poolX // ERROR "variable declaration copies lock value to poolYY: sync.Pool contains sync.noCopy"
+ poolP := &poolX
+ poolZ := &sync.Pool{}
+
+ // sync.Once copying
+ var onceX sync.Once
+ var onceXX = sync.Once{}
+ onceX1 := new(sync.Once)
+ onceY := onceX // ERROR "assignment copies lock value to onceY: sync.Once contains sync.Mutex"
+ onceY = onceX // ERROR "assignment copies lock value to onceY: sync.Once contains sync.Mutex"
+ var onceYY = onceX // ERROR "variable declaration copies lock value to onceYY: sync.Once contains sync.Mutex"
+ onceP := &onceX
+ onceZ := &sync.Once{}
+}
+
+// AtomicTypesCheck checks copying of sync/atomic types
+func AtomicTypesCheck() {
+ // atomic.Value copying
+ var vX atomic.Value
+ var vXX = atomic.Value{}
+ vX1 := new(atomic.Value)
+ vY := vX // ERROR "assignment copies lock value to vY: sync/atomic.Value contains sync/atomic.noCopy"
+ vY = vX // ERROR "assignment copies lock value to vY: sync/atomic.Value contains sync/atomic.noCopy"
+ var vYY = vX // ERROR "variable declaration copies lock value to vYY: sync/atomic.Value contains sync/atomic.noCopy"
+ vP := &vX
+ vZ := &atomic.Value{}
+}
diff --git a/src/sync/atomic/value.go b/src/sync/atomic/value.go
index ab3aa11285478f..30abf726344e96 100644
--- a/src/sync/atomic/value.go
+++ b/src/sync/atomic/value.go
@@ -12,7 +12,11 @@ import (
// Values can be created as part of other data structures.
// The zero value for a Value returns nil from Load.
// Once Store has been called, a Value must not be copied.
+//
+// A Value must not be copied after first use.
type Value struct {
+ noCopy noCopy
+
v interface{}
}
@@ -83,3 +87,13 @@ func (v *Value) Store(x interface{}) {
// Disable/enable preemption, implemented in runtime.
func runtime_procPin()
func runtime_procUnpin()
+
+// noCopy may be embedded into structs which must not be copied
+// after the first use.
+//
+// See https://github.com/golang/go/issues/8005#issuecomment-190753527
+// for details.
+type noCopy struct{}
+
+// Lock is a no-op used by -copylocks checker from `go vet`.
+func (*noCopy) Lock() {}
diff --git a/src/sync/cond.go b/src/sync/cond.go
index f711c39da2d856..c070d9d84ef9e5 100644
--- a/src/sync/cond.go
+++ b/src/sync/cond.go
@@ -20,6 +20,8 @@ import (
// A Cond can be created as part of other structures.
// A Cond must not be copied after first use.
type Cond struct {
+ noCopy noCopy
+
// L is held while observing or changing the condition
L Locker
@@ -84,3 +86,13 @@ func (c *copyChecker) check() {
panic("sync.Cond is copied")
}
}
+
+// noCopy may be embedded into structs which must not be copied
+// after the first use.
+//
+// See https://github.com/golang/go/issues/8005#issuecomment-190753527
+// for details.
+type noCopy struct{}
+
+// Lock is a no-op used by -copylocks checker from `go vet`.
+func (*noCopy) Lock() {}
diff --git a/src/sync/mutex.go b/src/sync/mutex.go
index 78b115cf5a1972..90892793f0a99c 100644
--- a/src/sync/mutex.go
+++ b/src/sync/mutex.go
@@ -19,6 +19,8 @@ import (
// A Mutex is a mutual exclusion lock.
// Mutexes can be created as part of other structures;
// the zero value for a Mutex is an unlocked mutex.
+//
+// A Mutex must not be copied after first use.
type Mutex struct {
state int32
sema uint32
diff --git a/src/sync/pool.go b/src/sync/pool.go
index 2acf505f3c96b9..bf29d88c5cb6cc 100644
--- a/src/sync/pool.go
+++ b/src/sync/pool.go
@@ -40,7 +40,10 @@ import (
// that scenario. It is more efficient to have such objects implement their own
// free list.
//
+// A Pool must not be copied after first use.
type Pool struct {
+ noCopy noCopy
+
local unsafe.Pointer // local fixed-size per-P pool, actual type is [P]poolLocal
localSize uintptr // size of the local array
diff --git a/src/sync/rwmutex.go b/src/sync/rwmutex.go
index 9fc6e3bd2c5151..455d412330034e 100644
--- a/src/sync/rwmutex.go
+++ b/src/sync/rwmutex.go
@@ -16,6 +16,8 @@ import (
// RWMutexes can be created as part of other
// structures; the zero value for a RWMutex is
// an unlocked mutex.
+//
+// An RWMutex must not be copied after first use.
type RWMutex struct {
w Mutex // held if there are pending writers
writerSem uint32 // semaphore for writers to wait for completing readers
diff --git a/src/sync/waitgroup.go b/src/sync/waitgroup.go
index 029e6077cde714..b386e1fec2b61a 100644
--- a/src/sync/waitgroup.go
+++ b/src/sync/waitgroup.go
@@ -15,7 +15,11 @@ import (
// goroutines to wait for. Then each of the goroutines
// runs and calls Done when finished. At the same time,
// Wait can be used to block until all goroutines have finished.
+//
+// A WaitGroup must not be copied after first use.
type WaitGroup struct {
+ noCopy noCopy
+
// 64-bit value: high 32 bits are counter, low 32 bits are waiter count.
// 64-bit atomic operations require 64-bit alignment, but 32-bit
// compilers do not ensure it. So we allocate 12 bytes and then use
From a5c5f6ea94dcd9caad0f0df8caaf68f8659900b2 Mon Sep 17 00:00:00 2001
From: Alberto Donizetti
Date: Fri, 6 May 2016 18:16:52 +0200
Subject: [PATCH 021/267] all: fix copy-and-paste errors in tests
Fixes #15570
Change-Id: I95d1ac26e342c3bbf36ad1f0209711ea96eaf487
Reviewed-on: https://go-review.googlesource.com/22870
Reviewed-by: Brad Fitzpatrick
Run-TryBot: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
---
src/encoding/gob/codec_test.go | 4 ++--
src/net/conn_test.go | 2 +-
src/net/mockserver_test.go | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/encoding/gob/codec_test.go b/src/encoding/gob/codec_test.go
index b772171f930adc..d4002cbccab3d3 100644
--- a/src/encoding/gob/codec_test.go
+++ b/src/encoding/gob/codec_test.go
@@ -1253,7 +1253,7 @@ func TestIgnoreInterface(t *testing.T) {
if item2.I != item1.I {
t.Error("normal int did not decode correctly")
}
- if item2.F != item2.F {
+ if item2.F != item1.F {
t.Error("normal float did not decode correctly")
}
}
@@ -1280,7 +1280,7 @@ func TestUnexportedFields(t *testing.T) {
if err != nil {
t.Fatal("decode error:", err)
}
- if u0.A != u0.A || u0.B != u1.B || u0.D != u1.D {
+ if u0.A != u1.A || u0.B != u1.B || u0.D != u1.D {
t.Errorf("u1->u0: expected %v; got %v", u0, u1)
}
if u1.c != 1234. {
diff --git a/src/net/conn_test.go b/src/net/conn_test.go
index 8accbae7bb8c47..16cf69ee169eaf 100644
--- a/src/net/conn_test.go
+++ b/src/net/conn_test.go
@@ -43,7 +43,7 @@ func TestConnAndListener(t *testing.T) {
t.Fatal(err)
}
defer c.Close()
- if c.LocalAddr().Network() != network || c.LocalAddr().Network() != network {
+ if c.LocalAddr().Network() != network || c.RemoteAddr().Network() != network {
t.Fatalf("got %s->%s; want %s->%s", c.LocalAddr().Network(), c.RemoteAddr().Network(), network, network)
}
c.SetDeadline(time.Now().Add(someTimeout))
diff --git a/src/net/mockserver_test.go b/src/net/mockserver_test.go
index 9e6907c09a24cb..b67dd916506043 100644
--- a/src/net/mockserver_test.go
+++ b/src/net/mockserver_test.go
@@ -228,7 +228,7 @@ func transponder(ln Listener, ch chan<- error) {
defer c.Close()
network := ln.Addr().Network()
- if c.LocalAddr().Network() != network || c.LocalAddr().Network() != network {
+ if c.LocalAddr().Network() != network || c.RemoteAddr().Network() != network {
ch <- fmt.Errorf("got %v->%v; expected %v->%v", c.LocalAddr().Network(), c.RemoteAddr().Network(), network, network)
return
}
From 61602b0e9e1daa0490793ef9ada3a51f8f482265 Mon Sep 17 00:00:00 2001
From: Brad Fitzpatrick
Date: Fri, 6 May 2016 16:06:02 +0000
Subject: [PATCH 022/267] runtime: delete empty files
I meant to delete these in CL 22850, actually.
Change-Id: I0c286efd2b9f1caf0221aa88e3bcc03649c89517
Reviewed-on: https://go-review.googlesource.com/22851
Reviewed-by: Ian Lance Taylor
Run-TryBot: Ian Lance Taylor
TryBot-Result: Gobot Gobot
---
src/runtime/os_freebsd.go | 5 -----
src/runtime/os_nacl.go | 5 -----
src/runtime/os_openbsd.go | 5 -----
src/runtime/os_plan9.go | 5 -----
4 files changed, 20 deletions(-)
delete mode 100644 src/runtime/os_freebsd.go
delete mode 100644 src/runtime/os_nacl.go
delete mode 100644 src/runtime/os_openbsd.go
delete mode 100644 src/runtime/os_plan9.go
diff --git a/src/runtime/os_freebsd.go b/src/runtime/os_freebsd.go
deleted file mode 100644
index 47bf8fc20d627d..00000000000000
--- a/src/runtime/os_freebsd.go
+++ /dev/null
@@ -1,5 +0,0 @@
-// 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
diff --git a/src/runtime/os_nacl.go b/src/runtime/os_nacl.go
deleted file mode 100644
index 47bf8fc20d627d..00000000000000
--- a/src/runtime/os_nacl.go
+++ /dev/null
@@ -1,5 +0,0 @@
-// 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
diff --git a/src/runtime/os_openbsd.go b/src/runtime/os_openbsd.go
deleted file mode 100644
index 47bf8fc20d627d..00000000000000
--- a/src/runtime/os_openbsd.go
+++ /dev/null
@@ -1,5 +0,0 @@
-// 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
diff --git a/src/runtime/os_plan9.go b/src/runtime/os_plan9.go
deleted file mode 100644
index 47bf8fc20d627d..00000000000000
--- a/src/runtime/os_plan9.go
+++ /dev/null
@@ -1,5 +0,0 @@
-// 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
From 1ff57143af65014c80e39cc0f19cd97a455f5b49 Mon Sep 17 00:00:00 2001
From: Brad Fitzpatrick
Date: Fri, 6 May 2016 16:24:57 +0000
Subject: [PATCH 023/267] net: ignore network failures on some builders
We run the external network tests on builders, but some of our
builders have less-than-ideal DNS connectivity. This change continues
to run the tests on all builders, but marks certain builders as flaky
(network-wise), and only validates their DNS results if they got DNS
results.
Change-Id: I826dc2a6f6da55add89ae9c6db892b3b2f7b526b
Reviewed-on: https://go-review.googlesource.com/22852
Reviewed-by: Ian Lance Taylor
---
src/internal/testenv/testenv.go | 7 +++++++
src/net/lookup_test.go | 11 +++++++++--
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/src/internal/testenv/testenv.go b/src/internal/testenv/testenv.go
index 9e684e3034388e..f134f6b04a185f 100644
--- a/src/internal/testenv/testenv.go
+++ b/src/internal/testenv/testenv.go
@@ -16,6 +16,7 @@ import (
"os/exec"
"path/filepath"
"runtime"
+ "strconv"
"strings"
"testing"
)
@@ -133,3 +134,9 @@ func SkipFlaky(t *testing.T, issue int) {
t.Skipf("skipping known flaky test without the -flaky flag; see golang.org/issue/%d", issue)
}
}
+
+func SkipFlakyNet(t *testing.T) {
+ if v, _ := strconv.ParseBool(os.Getenv("GO_BUILDER_FLAKY_NET")); v {
+ t.Skip("skipping test on builder known to have frequent network failures")
+ }
+}
diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go
index 6e54fdba76d902..fb3cf18d3bd972 100644
--- a/src/net/lookup_test.go
+++ b/src/net/lookup_test.go
@@ -498,6 +498,7 @@ func TestLookupDotsWithRemoteSource(t *testing.T) {
func testDots(t *testing.T, mode string) {
names, err := LookupAddr("8.8.8.8") // Google dns server
if err != nil {
+ testenv.SkipFlakyNet(t)
t.Errorf("LookupAddr(8.8.8.8): %v (mode=%v)", err, mode)
} else {
for _, name := range names {
@@ -509,12 +510,16 @@ func testDots(t *testing.T, mode string) {
}
cname, err := LookupCNAME("www.mit.edu")
- if err != nil || !strings.HasSuffix(cname, ".") {
- t.Errorf("LookupCNAME(www.mit.edu) = %v, %v, want cname ending in . with trailing dot (mode=%v)", cname, err, mode)
+ if err != nil {
+ testenv.SkipFlakyNet(t)
+ t.Errorf("LookupCNAME(www.mit.edu, mode=%v): %v", mode, err)
+ } else if !strings.HasSuffix(cname, ".") {
+ t.Errorf("LookupCNAME(www.mit.edu) = %v, want cname ending in . with trailing dot (mode=%v)", cname, mode)
}
mxs, err := LookupMX("google.com")
if err != nil {
+ testenv.SkipFlakyNet(t)
t.Errorf("LookupMX(google.com): %v (mode=%v)", err, mode)
} else {
for _, mx := range mxs {
@@ -527,6 +532,7 @@ func testDots(t *testing.T, mode string) {
nss, err := LookupNS("google.com")
if err != nil {
+ testenv.SkipFlakyNet(t)
t.Errorf("LookupNS(google.com): %v (mode=%v)", err, mode)
} else {
for _, ns := range nss {
@@ -539,6 +545,7 @@ func testDots(t *testing.T, mode string) {
cname, srvs, err := LookupSRV("xmpp-server", "tcp", "google.com")
if err != nil {
+ testenv.SkipFlakyNet(t)
t.Errorf("LookupSRV(xmpp-server, tcp, google.com): %v (mode=%v)", err, mode)
} else {
if !strings.HasSuffix(cname, ".google.com.") {
From 131231b8db26b38c9c2fdc52fb788241f5c2de51 Mon Sep 17 00:00:00 2001
From: Brad Fitzpatrick
Date: Fri, 6 May 2016 16:07:11 +0000
Subject: [PATCH 024/267] os: rename remaining four os1_*.go files to os_*.go
Change-Id: Ice9c234960adc7857c8370b777a0b18e29d59281
Reviewed-on: https://go-review.googlesource.com/22853
Reviewed-by: Ian Lance Taylor
Run-TryBot: Ian Lance Taylor
TryBot-Result: Gobot Gobot
---
src/runtime/{os1_freebsd.go => os_freebsd.go} | 0
src/runtime/{os1_nacl.go => os_nacl.go} | 0
src/runtime/{os1_openbsd.go => os_openbsd.go} | 0
src/runtime/{os1_plan9.go => os_plan9.go} | 0
4 files changed, 0 insertions(+), 0 deletions(-)
rename src/runtime/{os1_freebsd.go => os_freebsd.go} (100%)
rename src/runtime/{os1_nacl.go => os_nacl.go} (100%)
rename src/runtime/{os1_openbsd.go => os_openbsd.go} (100%)
rename src/runtime/{os1_plan9.go => os_plan9.go} (100%)
diff --git a/src/runtime/os1_freebsd.go b/src/runtime/os_freebsd.go
similarity index 100%
rename from src/runtime/os1_freebsd.go
rename to src/runtime/os_freebsd.go
diff --git a/src/runtime/os1_nacl.go b/src/runtime/os_nacl.go
similarity index 100%
rename from src/runtime/os1_nacl.go
rename to src/runtime/os_nacl.go
diff --git a/src/runtime/os1_openbsd.go b/src/runtime/os_openbsd.go
similarity index 100%
rename from src/runtime/os1_openbsd.go
rename to src/runtime/os_openbsd.go
diff --git a/src/runtime/os1_plan9.go b/src/runtime/os_plan9.go
similarity index 100%
rename from src/runtime/os1_plan9.go
rename to src/runtime/os_plan9.go
From 670a5cda2048af8d83958af0f4b2fda8f7b4ea72 Mon Sep 17 00:00:00 2001
From: Russ Cox
Date: Fri, 6 May 2016 15:28:19 +0000
Subject: [PATCH 025/267] Revert "testing/quick: generate more map and slice
states"
This reverts commit 0ccabe2e0b42a2602e0f37ce28d5368aa811f530.
Change-Id: Ib1c230fb6801c0ee26f4a352b0c1130fa240a76a
Reviewed-on: https://go-review.googlesource.com/22860
Reviewed-by: Ian Lance Taylor
Run-TryBot: Ian Lance Taylor
TryBot-Result: Gobot Gobot
Reviewed-by: Brad Fitzpatrick
---
src/testing/quick/quick.go | 47 +++++++++++++--------------------
src/testing/quick/quick_test.go | 17 ++++++++++++
2 files changed, 35 insertions(+), 29 deletions(-)
diff --git a/src/testing/quick/quick.go b/src/testing/quick/quick.go
index 4bc8e3fc2e1479..798d41aa7d176b 100644
--- a/src/testing/quick/quick.go
+++ b/src/testing/quick/quick.go
@@ -14,7 +14,7 @@ import (
"strings"
)
-var defaultMaxCount = flag.Int("quickchecks", 100, "The default number of iterations for each check")
+var defaultMaxCount *int = flag.Int("quickchecks", 100, "The default number of iterations for each check")
// A Generator can generate random values of its own type.
type Generator interface {
@@ -98,22 +98,18 @@ func sizedValue(t reflect.Type, rand *rand.Rand, size int) (value reflect.Value,
case reflect.Uintptr:
v.SetUint(uint64(randInt64(rand)))
case reflect.Map:
- if generateNilValue(rand) {
- v.Set(reflect.Zero(concrete)) // Generate nil map.
- } else {
- numElems := rand.Intn(size)
- v.Set(reflect.MakeMap(concrete))
- for i := 0; i < numElems; i++ {
- key, ok1 := sizedValue(concrete.Key(), rand, size)
- value, ok2 := sizedValue(concrete.Elem(), rand, size)
- if !ok1 || !ok2 {
- return reflect.Value{}, false
- }
- v.SetMapIndex(key, value)
+ numElems := rand.Intn(size)
+ v.Set(reflect.MakeMap(concrete))
+ for i := 0; i < numElems; i++ {
+ key, ok1 := sizedValue(concrete.Key(), rand, size)
+ value, ok2 := sizedValue(concrete.Elem(), rand, size)
+ if !ok1 || !ok2 {
+ return reflect.Value{}, false
}
+ v.SetMapIndex(key, value)
}
case reflect.Ptr:
- if generateNilValue(rand) {
+ if rand.Intn(size) == 0 {
v.Set(reflect.Zero(concrete)) // Generate nil pointer.
} else {
elem, ok := sizedValue(concrete.Elem(), rand, size)
@@ -124,20 +120,15 @@ func sizedValue(t reflect.Type, rand *rand.Rand, size int) (value reflect.Value,
v.Elem().Set(elem)
}
case reflect.Slice:
- if generateNilValue(rand) {
- v.Set(reflect.Zero(concrete)) // Generate nil slice.
- } else {
- slCap := rand.Intn(size)
- slLen := rand.Intn(slCap + 1)
- sizeLeft := size - slCap
- v.Set(reflect.MakeSlice(concrete, slLen, slCap))
- for i := 0; i < slLen; i++ {
- elem, ok := sizedValue(concrete.Elem(), rand, sizeLeft)
- if !ok {
- return reflect.Value{}, false
- }
- v.Index(i).Set(elem)
+ numElems := rand.Intn(size)
+ sizeLeft := size - numElems
+ v.Set(reflect.MakeSlice(concrete, numElems, numElems))
+ for i := 0; i < numElems; i++ {
+ elem, ok := sizedValue(concrete.Elem(), rand, sizeLeft)
+ if !ok {
+ return reflect.Value{}, false
}
+ v.Index(i).Set(elem)
}
case reflect.Array:
for i := 0; i < v.Len(); i++ {
@@ -385,5 +376,3 @@ func toString(interfaces []interface{}) string {
}
return strings.Join(s, ", ")
}
-
-func generateNilValue(r *rand.Rand) bool { return r.Intn(20) == 0 }
diff --git a/src/testing/quick/quick_test.go b/src/testing/quick/quick_test.go
index 018ece2a5289ed..fe443592f87bed 100644
--- a/src/testing/quick/quick_test.go
+++ b/src/testing/quick/quick_test.go
@@ -290,3 +290,20 @@ func TestMutuallyRecursive(t *testing.T) {
f := func(a A) bool { return true }
Check(f, nil)
}
+
+// Some serialization formats (e.g. encoding/pem) cannot distinguish
+// between a nil and an empty map or slice, so avoid generating the
+// zero value for these.
+func TestNonZeroSliceAndMap(t *testing.T) {
+ type Q struct {
+ M map[int]int
+ S []int
+ }
+ f := func(q Q) bool {
+ return q.M != nil && q.S != nil
+ }
+ err := Check(f, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
From 31283dd4836542f94b063bfd2886fc32639358f7 Mon Sep 17 00:00:00 2001
From: Brad Fitzpatrick
Date: Fri, 6 May 2016 18:11:38 +0000
Subject: [PATCH 026/267] net/http: don't assume Response.Request is populated
after redirect errors
Fixes #15577
Change-Id: I5f023790a393b17235db2e66c02c2483773ddc1a
Reviewed-on: https://go-review.googlesource.com/22857
Reviewed-by: Russ Cox
Run-TryBot: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
---
src/net/http/client.go | 2 +-
src/net/http/client_test.go | 23 +++++++++++++++++++++++
2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/src/net/http/client.go b/src/net/http/client.go
index f8ab675a3de047..1127634beca3b9 100644
--- a/src/net/http/client.go
+++ b/src/net/http/client.go
@@ -442,7 +442,7 @@ func (c *Client) doFollowingRedirects(req *Request, shouldRedirect func(int) boo
req.closeBody()
method := valueOrDefault(reqs[0].Method, "GET")
var urlStr string
- if resp != nil {
+ if resp != nil && resp.Request != nil {
urlStr = resp.Request.URL.String()
} else {
urlStr = req.URL.String()
diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go
index a9b30b1bf5c134..6f7ab965cbcf94 100644
--- a/src/net/http/client_test.go
+++ b/src/net/http/client_test.go
@@ -1168,3 +1168,26 @@ func TestReferer(t *testing.T) {
}
}
}
+
+// issue15577Tripper returns a Response with a redirect response
+// header and doesn't populate its Response.Request field.
+type issue15577Tripper struct{}
+
+func (issue15577Tripper) RoundTrip(*Request) (*Response, error) {
+ resp := &Response{
+ StatusCode: 303,
+ Header: map[string][]string{"Location": {"http://www.example.com/"}},
+ Body: ioutil.NopCloser(strings.NewReader("")),
+ }
+ return resp, nil
+}
+
+// Issue 15577: don't assume the roundtripper's response populates its Request field.
+func TestClientRedirectResponseWithoutRequest(t *testing.T) {
+ c := &Client{
+ CheckRedirect: func(*Request, []*Request) error { return fmt.Errorf("no redirects!") },
+ Transport: issue15577Tripper{},
+ }
+ // Check that this doesn't crash:
+ c.Get("http://dummy.tld")
+}
From 4eccc77f196edfa7646b0e92a11ef8d96ef85b57 Mon Sep 17 00:00:00 2001
From: Brad Fitzpatrick
Date: Fri, 6 May 2016 18:21:22 +0000
Subject: [PATCH 027/267] net/http: wait longer for subprocess to startup in
test
Might deflake the occasional linux-amd64-race failures.
Change-Id: I273b0e32bb92236168eb99887b166e079799c1f1
Reviewed-on: https://go-review.googlesource.com/22858
Reviewed-by: Ian Lance Taylor
---
src/net/http/serve_test.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go
index 661f355d0dd709..b34875f061a062 100644
--- a/src/net/http/serve_test.go
+++ b/src/net/http/serve_test.go
@@ -4268,7 +4268,7 @@ func BenchmarkClient(b *testing.B) {
// Wait for the server process to respond.
url := "http://localhost:" + port + "/"
for i := 0; i < 100; i++ {
- time.Sleep(50 * time.Millisecond)
+ time.Sleep(100 * time.Millisecond)
if _, err := getNoBody(url); err == nil {
break
}
From f0e2d32fde77ad03616304ab42b8c7426cf3a350 Mon Sep 17 00:00:00 2001
From: Russ Cox
Date: Fri, 6 May 2016 15:34:25 +0000
Subject: [PATCH 028/267] Revert "net/url: validate ports in IPv4 addresses"
This reverts commit 9f1ccd647fcdb1b703c1042c90434e15aff75013.
For #14860.
Change-Id: I63522a4dda8915dc8b972ae2e12495553ed65f09
Reviewed-on: https://go-review.googlesource.com/22861
Reviewed-by: Brad Fitzpatrick
Run-TryBot: Russ Cox
TryBot-Result: Gobot Gobot
---
src/net/url/url.go | 6 +-----
src/net/url/url_test.go | 6 ++----
2 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/src/net/url/url.go b/src/net/url/url.go
index 05b41fa964a9cc..d9c8c49e94a483 100644
--- a/src/net/url/url.go
+++ b/src/net/url/url.go
@@ -573,12 +573,8 @@ func parseHost(host string) (string, error) {
}
return host1 + host2 + host3, nil
}
- } else if i := strings.LastIndex(host, ":"); i > 0 {
- colonPort := host[i:]
- if !validOptionalPort(colonPort) {
- return "", fmt.Errorf("invalid port %q after host", colonPort)
- }
}
+
var err error
if host, err = unescape(host, encodeHost); err != nil {
return "", err
diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go
index da6bc2843e52b0..7560f22c4a1e2a 100644
--- a/src/net/url/url_test.go
+++ b/src/net/url/url_test.go
@@ -418,10 +418,10 @@ var urltests = []URLTest{
},
// worst case host, still round trips
{
- "scheme://!$&'()*+,;=hello!:8080/path",
+ "scheme://!$&'()*+,;=hello!:port/path",
&URL{
Scheme: "scheme",
- Host: "!$&'()*+,;=hello!:8080",
+ Host: "!$&'()*+,;=hello!:port",
Path: "/path",
},
"",
@@ -636,10 +636,8 @@ var parseRequestURLTests = []struct {
{"*", true},
{"http://192.168.0.1/", true},
{"http://192.168.0.1:8080/", true},
- {"http://192.168.0.1:foo/", false},
{"http://[fe80::1]/", true},
{"http://[fe80::1]:8080/", true},
- {"http://[fe80::1]:foo/", false},
// Tests exercising RFC 6874 compliance:
{"http://[fe80::1%25en0]/", true}, // with alphanum zone identifier
From a1813ae0a091e1b880c0d3472112d2c725c2fa18 Mon Sep 17 00:00:00 2001
From: Ian Lance Taylor
Date: Fri, 6 May 2016 11:32:18 -0700
Subject: [PATCH 029/267] misc/cgo/testcarchive: avoid possible pthread_create
race
The old code assumed that the thread ID set by pthread_create would be
available in the newly created thread. While that is clearly true
eventually, it is not necessarily true immediately. Rather than try to
pass down the thread ID, just call pthread_self in the created thread.
Fixes #15576 (I hope).
Change-Id: Ic07086b00e4fd5676c04719a299c583320da64a1
Reviewed-on: https://go-review.googlesource.com/22880
Run-TryBot: Ian Lance Taylor
Reviewed-by: Brad Fitzpatrick
---
misc/cgo/testcarchive/main4.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/misc/cgo/testcarchive/main4.c b/misc/cgo/testcarchive/main4.c
index 2aaf09b7c1961e..353f980c50d47e 100644
--- a/misc/cgo/testcarchive/main4.c
+++ b/misc/cgo/testcarchive/main4.c
@@ -44,8 +44,7 @@ static void init() {
// Test raising SIGIO on a C thread with an alternate signal stack
// when there is a Go signal handler for SIGIO.
-static void* thread1(void* arg) {
- pthread_t* ptid = (pthread_t*)(arg);
+static void* thread1(void* arg __attribute__ ((unused))) {
stack_t ss;
int i;
stack_t nss;
@@ -65,7 +64,7 @@ static void* thread1(void* arg) {
// Send ourselves a SIGIO. This will be caught by the Go
// signal handler which should forward to the C signal
// handler.
- i = pthread_kill(*ptid, SIGIO);
+ i = pthread_kill(pthread_self(), SIGIO);
if (i != 0) {
fprintf(stderr, "pthread_kill: %s\n", strerror(i));
exit(EXIT_FAILURE);
@@ -101,11 +100,11 @@ static void* thread1(void* arg) {
// Test calling a Go function to raise SIGIO on a C thread with an
// alternate signal stack when there is a Go signal handler for SIGIO.
-static void* thread2(void* arg) {
- pthread_t* ptid = (pthread_t*)(arg);
+static void* thread2(void* arg __attribute__ ((unused))) {
stack_t ss;
int i;
int oldcount;
+ pthread_t tid;
stack_t nss;
// Set up an alternate signal stack for this thread.
@@ -124,7 +123,8 @@ static void* thread2(void* arg) {
// Call a Go function that will call a C function to send us a
// SIGIO.
- GoRaiseSIGIO(ptid);
+ tid = pthread_self();
+ GoRaiseSIGIO(&tid);
// Wait until the signal has been delivered.
i = 0;
@@ -161,7 +161,7 @@ int main(int argc, char **argv) {
// Tell the Go library to start looking for SIGIO.
GoCatchSIGIO();
- i = pthread_create(&tid, NULL, thread1, (void*)(&tid));
+ i = pthread_create(&tid, NULL, thread1, NULL);
if (i != 0) {
fprintf(stderr, "pthread_create: %s\n", strerror(i));
exit(EXIT_FAILURE);
@@ -173,7 +173,7 @@ int main(int argc, char **argv) {
exit(EXIT_FAILURE);
}
- i = pthread_create(&tid, NULL, thread2, (void*)(&tid));
+ i = pthread_create(&tid, NULL, thread2, NULL);
if (i != 0) {
fprintf(stderr, "pthread_create: %s\n", strerror(i));
exit(EXIT_FAILURE);
From 7c5c6645d2ac21073b146c3d1a83c9b8c6463c25 Mon Sep 17 00:00:00 2001
From: Brad Fitzpatrick
Date: Fri, 6 May 2016 18:46:35 +0000
Subject: [PATCH 030/267] net: skip more flaky net tests on flaky net builders
e.g. https://storage.googleapis.com/go-build-log/9b937dd8/linux-arm_df54a25a.log
Change-Id: Ic5864c7bd840b4f0c6341f919fcbcd5c708b14e7
Reviewed-on: https://go-review.googlesource.com/22881
Reviewed-by: Ian Lance Taylor
Run-TryBot: Ian Lance Taylor
---
src/net/lookup_test.go | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go
index fb3cf18d3bd972..7dba393cee5c9e 100644
--- a/src/net/lookup_test.go
+++ b/src/net/lookup_test.go
@@ -70,6 +70,7 @@ func TestLookupGoogleSRV(t *testing.T) {
for _, tt := range lookupGoogleSRVTests {
cname, srvs, err := LookupSRV(tt.service, tt.proto, tt.name)
if err != nil {
+ testenv.SkipFlakyNet(t)
t.Fatal(err)
}
if len(srvs) == 0 {
@@ -137,6 +138,7 @@ func TestLookupGmailNS(t *testing.T) {
for _, tt := range lookupGmailNSTests {
nss, err := LookupNS(tt.name)
if err != nil {
+ testenv.SkipFlakyNet(t)
t.Fatal(err)
}
if len(nss) == 0 {
From 83676d694b64205e80c042ca7cf61f7ad4de6c62 Mon Sep 17 00:00:00 2001
From: Brad Fitzpatrick
Date: Fri, 6 May 2016 18:33:39 +0000
Subject: [PATCH 031/267] net/url: remove RFC 3986 mention in package comment
Change-Id: Ifd707a4bbfcb1721655b4fce2045f3b043e66818
Reviewed-on: https://go-review.googlesource.com/22859
Reviewed-by: Russ Cox
---
src/net/url/url.go | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/net/url/url.go b/src/net/url/url.go
index d9c8c49e94a483..30e92779370393 100644
--- a/src/net/url/url.go
+++ b/src/net/url/url.go
@@ -3,9 +3,13 @@
// license that can be found in the LICENSE file.
// Package url parses URLs and implements query escaping.
-// See RFC 3986.
package url
+// See RFC 3986. This package generally follows RFC 3986, except where
+// it deviates for compatibility reasons. When sending changes, first
+// search old issues for history on decisions. Unit tests should also
+// contain references to issue numbers with details.
+
import (
"bytes"
"errors"
From e6ec82067a9068c93db6e7041017060a1c863452 Mon Sep 17 00:00:00 2001
From: Elias Naur
Date: Wed, 9 Mar 2016 10:00:12 +0100
Subject: [PATCH 032/267] runtime: use entire address space on 32 bit
In issue #13992, Russ mentioned that the heap bitmap footprint was
halved but that the bitmap size calculation hadn't been updated. This
presents the opportunity to either halve the bitmap size or double
the addressable virtual space. This CL doubles the addressable virtual
space. On 32 bit this can be tweaked further to allow the bitmap to
cover the entire 4GB virtual address space, removing a failure mode
if the kernel hands out memory with a too low address.
First, fix the calculation and double _MaxArena32 to cover 4GB virtual
memory space with the same bitmap size (256 MB).
Then, allow the fallback mode for the initial memory reservation
on 32 bit (or 64 bit with too little available virtual memory) to not
include space for the arena. mheap.sysAlloc will automatically reserve
additional space when the existing arena is full.
Finally, set arena_start to 0 in 32 bit mode, so that any address is
acceptable for subsequent (additional) reservations.
Before, the bitmap was always located just before arena_start, so
fix the two places relying on that assumption: Point the otherwise unused
mheap.bitmap to one byte after the end of the bitmap, and use it for
bitmap addressing instead of arena_start.
With arena_start set to 0 on 32 bit, the cgoInRange check is no longer a
sufficient check for Go pointers. Introduce and call inHeapOrStack to
check whether a pointer is to the Go heap or stack.
While we're here, remove sysReserveHigh which seems to be unused.
Fixes #13992
Change-Id: I592b513148a50b9d3967b5c5d94b86b3ec39acc2
Reviewed-on: https://go-review.googlesource.com/20471
Reviewed-by: Austin Clements
Run-TryBot: Austin Clements
TryBot-Result: Gobot Gobot
---
src/runtime/cgocall.go | 2 +-
src/runtime/malloc.go | 76 +++++++++++++++---------------------------
src/runtime/mbitmap.go | 4 +--
src/runtime/mheap.go | 24 ++++++++++++-
4 files changed, 52 insertions(+), 54 deletions(-)
diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go
index 8457fb2de73c71..1e0d4c7f19504a 100644
--- a/src/runtime/cgocall.go
+++ b/src/runtime/cgocall.go
@@ -601,7 +601,7 @@ func cgoIsGoPointer(p unsafe.Pointer) bool {
return false
}
- if cgoInRange(p, mheap_.arena_start, mheap_.arena_used) {
+ if inHeapOrStack(uintptr(p)) {
return true
}
diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go
index bb17919fd0135d..ae81b8681b90d1 100644
--- a/src/runtime/malloc.go
+++ b/src/runtime/malloc.go
@@ -170,7 +170,7 @@ const (
_MaxGcproc = 32
)
-const _MaxArena32 = 2 << 30
+const _MaxArena32 = 1<<32 - 1
// OS-defined helpers:
//
@@ -227,7 +227,7 @@ func mallocinit() {
// Set up the allocation arena, a contiguous area of memory where
// allocated data will be found. The arena begins with a bitmap large
- // enough to hold 4 bits per allocated word.
+ // enough to hold 2 bits per allocated word.
if sys.PtrSize == 8 && (limit == 0 || limit > 1<<30) {
// On a 64-bit machine, allocate from a single contiguous reservation.
// 512 GB (MaxMem) should be big enough for now.
@@ -259,7 +259,7 @@ func mallocinit() {
// translation buffers, the user address space is limited to 39 bits
// On darwin/arm64, the address space is even smaller.
arenaSize := round(_MaxMem, _PageSize)
- bitmapSize = arenaSize / (sys.PtrSize * 8 / 4)
+ bitmapSize = arenaSize / (sys.PtrSize * 8 / 2)
spansSize = arenaSize / _PageSize * sys.PtrSize
spansSize = round(spansSize, _PageSize)
for i := 0; i <= 0x7f; i++ {
@@ -284,32 +284,26 @@ func mallocinit() {
// with a giant virtual address space reservation.
// Instead we map the memory information bitmap
// immediately after the data segment, large enough
- // to handle another 2GB of mappings (256 MB),
+ // to handle the entire 4GB address space (256 MB),
// along with a reservation for an initial arena.
// When that gets used up, we'll start asking the kernel
- // for any memory anywhere and hope it's in the 2GB
- // following the bitmap (presumably the executable begins
- // near the bottom of memory, so we'll have to use up
- // most of memory before the kernel resorts to giving out
- // memory before the beginning of the text segment).
- //
- // Alternatively we could reserve 512 MB bitmap, enough
- // for 4GB of mappings, and then accept any memory the
- // kernel threw at us, but normally that's a waste of 512 MB
- // of address space, which is probably too much in a 32-bit world.
+ // for any memory anywhere.
// If we fail to allocate, try again with a smaller arena.
// This is necessary on Android L where we share a process
// with ART, which reserves virtual memory aggressively.
+ // In the worst case, fall back to a 0-sized initial arena,
+ // in the hope that subsequent reservations will succeed.
arenaSizes := []uintptr{
512 << 20,
256 << 20,
128 << 20,
+ 0,
}
for _, arenaSize := range arenaSizes {
- bitmapSize = _MaxArena32 / (sys.PtrSize * 8 / 4)
- spansSize = _MaxArena32 / _PageSize * sys.PtrSize
+ bitmapSize = (_MaxArena32 + 1) / (sys.PtrSize * 8 / 2)
+ spansSize = (_MaxArena32 + 1) / _PageSize * sys.PtrSize
if limit > 0 && arenaSize+bitmapSize+spansSize > limit {
bitmapSize = (limit / 9) &^ ((1 << _PageShift) - 1)
arenaSize = bitmapSize * 8
@@ -344,10 +338,16 @@ func mallocinit() {
p1 := round(p, _PageSize)
mheap_.spans = (**mspan)(unsafe.Pointer(p1))
- mheap_.bitmap = p1 + spansSize
- mheap_.arena_start = p1 + (spansSize + bitmapSize)
- mheap_.arena_used = mheap_.arena_start
+ mheap_.bitmap = p1 + spansSize + bitmapSize
+ if sys.PtrSize == 4 {
+ // Set arena_start such that we can accept memory
+ // reservations located anywhere in the 4GB virtual space.
+ mheap_.arena_start = 0
+ } else {
+ mheap_.arena_start = p1 + (spansSize + bitmapSize)
+ }
mheap_.arena_end = p + pSize
+ mheap_.arena_used = p1 + (spansSize + bitmapSize)
mheap_.arena_reserved = reserved
if mheap_.arena_start&(_PageSize-1) != 0 {
@@ -361,29 +361,6 @@ func mallocinit() {
_g_.m.mcache = allocmcache()
}
-// sysReserveHigh reserves space somewhere high in the address space.
-// sysReserve doesn't actually reserve the full amount requested on
-// 64-bit systems, because of problems with ulimit. Instead it checks
-// that it can get the first 64 kB and assumes it can grab the rest as
-// needed. This doesn't work well with the "let the kernel pick an address"
-// mode, so don't do that. Pick a high address instead.
-func sysReserveHigh(n uintptr, reserved *bool) unsafe.Pointer {
- if sys.PtrSize == 4 {
- return sysReserve(nil, n, reserved)
- }
-
- for i := 0; i <= 0x7f; i++ {
- p := uintptr(i)<<40 | uintptrMask&(0x00c0<<32)
- *reserved = false
- p = uintptr(sysReserve(unsafe.Pointer(p), n, reserved))
- if p != 0 {
- return unsafe.Pointer(p)
- }
- }
-
- return sysReserve(nil, n, reserved)
-}
-
// sysAlloc allocates the next n bytes from the heap arena. The
// returned pointer is always _PageSize aligned and between
// h.arena_start and h.arena_end. sysAlloc returns nil on failure.
@@ -394,7 +371,7 @@ func (h *mheap) sysAlloc(n uintptr) unsafe.Pointer {
// Reserve some more space.
p_size := round(n+_PageSize, 256<<20)
new_end := h.arena_end + p_size // Careful: can overflow
- if h.arena_end <= new_end && new_end <= h.arena_start+_MaxArena32 {
+ if h.arena_end <= new_end && new_end-h.arena_start-1 <= _MaxArena32 {
// TODO: It would be bad if part of the arena
// is reserved and part is not.
var reserved bool
@@ -405,7 +382,7 @@ func (h *mheap) sysAlloc(n uintptr) unsafe.Pointer {
if p == h.arena_end {
h.arena_end = new_end
h.arena_reserved = reserved
- } else if h.arena_start <= p && p+p_size <= h.arena_start+_MaxArena32 {
+ } else if h.arena_start <= p && p+p_size-h.arena_start-1 <= _MaxArena32 {
// Keep everything page-aligned.
// Our pages are bigger than hardware pages.
h.arena_end = p + p_size
@@ -442,23 +419,22 @@ func (h *mheap) sysAlloc(n uintptr) unsafe.Pointer {
}
// If using 64-bit, our reservation is all we have.
- if h.arena_end-h.arena_start >= _MaxArena32 {
+ if h.arena_end-h.arena_start > _MaxArena32 {
return nil
}
// On 32-bit, once the reservation is gone we can
- // try to get memory at a location chosen by the OS
- // and hope that it is in the range we allocated bitmap for.
+ // try to get memory at a location chosen by the OS.
p_size := round(n, _PageSize) + _PageSize
p := uintptr(sysAlloc(p_size, &memstats.heap_sys))
if p == 0 {
return nil
}
- if p < h.arena_start || p+p_size-h.arena_start >= _MaxArena32 {
+ if p < h.arena_start || p+p_size-h.arena_start > _MaxArena32 {
top := ^uintptr(0)
- if top-h.arena_start > _MaxArena32 {
- top = h.arena_start + _MaxArena32
+ if top-h.arena_start-1 > _MaxArena32 {
+ top = h.arena_start + _MaxArena32 + 1
}
print("runtime: memory allocated by OS (", hex(p), ") not in usable range [", hex(h.arena_start), ",", hex(top), ")\n")
sysFree(unsafe.Pointer(p), p_size, &memstats.heap_sys)
diff --git a/src/runtime/mbitmap.go b/src/runtime/mbitmap.go
index cdb36cd65145bd..e01926e71a59a0 100644
--- a/src/runtime/mbitmap.go
+++ b/src/runtime/mbitmap.go
@@ -156,7 +156,7 @@ func (h *mheap) mapBits(arena_used uintptr) {
return
}
- sysMap(unsafe.Pointer(h.arena_start-n), n-h.bitmap_mapped, h.arena_reserved, &memstats.gc_sys)
+ sysMap(unsafe.Pointer(h.bitmap-n), n-h.bitmap_mapped, h.arena_reserved, &memstats.gc_sys)
h.bitmap_mapped = n
}
@@ -364,7 +364,7 @@ func (m *markBits) advance() {
func heapBitsForAddr(addr uintptr) heapBits {
// 2 bits per work, 4 pairs per byte, and a mask is hard coded.
off := (addr - mheap_.arena_start) / sys.PtrSize
- return heapBits{(*uint8)(unsafe.Pointer(mheap_.arena_start - off/4 - 1)), uint32(off & 3)}
+ return heapBits{(*uint8)(unsafe.Pointer(mheap_.bitmap - off/4 - 1)), uint32(off & 3)}
}
// heapBitsForSpan returns the heapBits for the span base address base.
diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go
index 1f732c2111c975..46b7048c4092da 100644
--- a/src/runtime/mheap.go
+++ b/src/runtime/mheap.go
@@ -46,7 +46,7 @@ type mheap struct {
nsmallfree [_NumSizeClasses]uint64 // number of frees for small objects (<=maxsmallsize)
// range of addresses we might see in the heap
- bitmap uintptr
+ bitmap uintptr // Points to one byte past the end of the bitmap
bitmap_mapped uintptr
arena_start uintptr
arena_used uintptr // always mHeap_Map{Bits,Spans} before updating
@@ -268,6 +268,28 @@ func inheap(b uintptr) bool {
return true
}
+// inHeapOrStack is a variant of inheap that returns true for pointers into stack spans.
+//go:nowritebarrier
+//go:nosplit
+func inHeapOrStack(b uintptr) bool {
+ if b == 0 || b < mheap_.arena_start || b >= mheap_.arena_used {
+ return false
+ }
+ // Not a beginning of a block, consult span table to find the block beginning.
+ s := h_spans[(b-mheap_.arena_start)>>_PageShift]
+ if s == nil || b < s.base() {
+ return false
+ }
+ switch s.state {
+ case mSpanInUse:
+ return b < s.limit
+ case _MSpanStack:
+ return b < s.base()+s.npages<<_PageShift
+ default:
+ return false
+ }
+}
+
// TODO: spanOf and spanOfUnchecked are open-coded in a lot of places.
// Use the functions instead.
From 9d7c9b4384db01afd2acb27d3a4636b60e957f08 Mon Sep 17 00:00:00 2001
From: Tal Shprecher
Date: Thu, 5 May 2016 15:14:08 -0700
Subject: [PATCH 033/267] cmd/compile: properly handle map assignments for
OAS2DOTTYPE
The boolean destination in an OAS2DOTTYPE expression craps out during
compilation when trying to assign to a map entry because, unlike slice entries,
map entries are not directly addressable in memory. The solution is to
properly order the boolean destination node so that map entries are set
via autotmp variables.
Fixes #14678
Change-Id: If344e8f232b5bdac1b53c0f0d21eeb43ab17d3de
Reviewed-on: https://go-review.googlesource.com/22833
Reviewed-by: Matthew Dempsky
Run-TryBot: Matthew Dempsky
TryBot-Result: Gobot Gobot
---
src/cmd/compile/internal/gc/order.go | 26 ++++++++++++++++----------
test/fixedbugs/issue14678.go | 27 +++++++++++++++++++++++++++
2 files changed, 43 insertions(+), 10 deletions(-)
create mode 100644 test/fixedbugs/issue14678.go
diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go
index 7026ad79efa383..d432b43460b88f 100644
--- a/src/cmd/compile/internal/gc/order.go
+++ b/src/cmd/compile/internal/gc/order.go
@@ -569,18 +569,24 @@ func orderstmt(n *Node, order *Order) {
orderexprlist(n.List, order)
n.Rlist.First().Left = orderexpr(n.Rlist.First().Left, order, nil) // i in i.(T)
- if isblank(n.List.First()) {
- order.out = append(order.out, n)
- } else {
- typ := n.Rlist.First().Type
- tmp1 := ordertemp(typ, order, haspointers(typ))
- order.out = append(order.out, n)
- r := Nod(OAS, n.List.First(), tmp1)
- r = typecheck(r, Etop)
- ordermapassign(r, order)
- n.List.Set([]*Node{tmp1, n.List.Second()})
+
+ results := n.List.Slice()
+ var assigns [2]*Node
+
+ for r, res := range results {
+ if !isblank(res) {
+ results[r] = ordertemp(res.Type, order, haspointers(res.Type))
+ assigns[r] = Nod(OAS, res, results[r])
+ }
}
+ order.out = append(order.out, n)
+ for _, assign := range assigns {
+ if assign != nil {
+ assign = typecheck(assign, Etop)
+ ordermapassign(assign, order)
+ }
+ }
cleantemp(t, order)
// Special: use temporary variables to hold result,
diff --git a/test/fixedbugs/issue14678.go b/test/fixedbugs/issue14678.go
new file mode 100644
index 00000000000000..94ca86d26ce060
--- /dev/null
+++ b/test/fixedbugs/issue14678.go
@@ -0,0 +1,27 @@
+// run
+
+// Copyright 2016 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 main
+
+func main() {
+ m := make(map[int]bool)
+ i := interface{}(1)
+ var v int
+
+ // Ensure map is updated properly
+ _, m[1] = i.(int)
+ v, m[2] = i.(int)
+
+ if v != 1 {
+ panic("fail: v should be 1")
+ }
+ if m[1] == false {
+ panic("fail: m[1] should be true")
+ }
+ if m[2] == false {
+ panic("fail: m[2] should be true")
+ }
+}
From fa270ad98e77cd0625c97eb01ad01efe11a324e8 Mon Sep 17 00:00:00 2001
From: Elias Naur
Date: Sat, 7 May 2016 07:24:39 +0200
Subject: [PATCH 034/267] cmd/go: add -shared to darwin/arm{,64} default build
mode
Buildmode c-archive now supports position independent code for
darwin/arm (in addition to darwin/arm64). Make PIC (-shared) the
default for both platforms in the default buildmode.
Without this change, gomobile will go install the standard library
into its separate package directory without PIC support.
Also add -shared to darwin/arm64 in buildmode c-archive, for
symmetry (darwin/arm64 always generates position independent code).
Fixes #15519
Change-Id: If27d2cbea8f40982e14df25da2703cbba572b5c6
Reviewed-on: https://go-review.googlesource.com/22920
Reviewed-by: David Crawshaw
Run-TryBot: David Crawshaw
TryBot-Result: Gobot Gobot
---
misc/cgo/testcarchive/carchive_test.go | 2 +-
src/cmd/go/build.go | 5 ++++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/misc/cgo/testcarchive/carchive_test.go b/misc/cgo/testcarchive/carchive_test.go
index 0174e310156928..ab14c007a9cb52 100644
--- a/misc/cgo/testcarchive/carchive_test.go
+++ b/misc/cgo/testcarchive/carchive_test.go
@@ -84,7 +84,7 @@ func init() {
cc = append(cc, []string{"-framework", "CoreFoundation", "-framework", "Foundation"}...)
}
libgodir = GOOS + "_" + GOARCH
- if GOOS == "darwin" && GOARCH == "arm" {
+ if GOOS == "darwin" && (GOARCH == "arm" || GOARCH == "arm64") {
libgodir = GOOS + "_" + GOARCH + "_shared"
}
cc = append(cc, "-I", filepath.Join("pkg", libgodir))
diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go
index 6bef09b66b86bf..e0cb216b8c4e56 100644
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -335,7 +335,7 @@ func buildModeInit() {
return p
}
switch platform {
- case "darwin/arm":
+ case "darwin/arm", "darwin/arm64":
codegenArg = "-shared"
default:
}
@@ -361,6 +361,9 @@ func buildModeInit() {
case "android/arm", "android/arm64", "android/amd64", "android/386":
codegenArg = "-shared"
ldBuildmode = "pie"
+ case "darwin/arm", "darwin/arm64":
+ codegenArg = "-shared"
+ fallthrough
default:
ldBuildmode = "exe"
}
From 394ac818b037ab8a3714b8a23e06e17a1e05aace Mon Sep 17 00:00:00 2001
From: Robert Griesemer
Date: Thu, 5 May 2016 18:03:59 -0700
Subject: [PATCH 035/267] cmd/compile: add and enable (internal) option to only
track named types
The new export format keeps track of all types that are exported.
If a type is seen that was exported before, only a reference to
that type is emitted. The importer maintains a list of all the
seen types and uses that list to resolve type references.
The existing compiler infrastructure's invariants assumes that
only named types are referred to before they are fully set up.
Referring to unnamed incomplete types causes problems. One of
the issues was #15548.
Added a new internal flag 'trackAllTypes' to enable/disable
this type tracking. With this change only named types are
tracked.
Verified that this fix also addresses #15548, even w/o the
prior fix for that issue (in fact that prior fix is turned
off if trackAllTypes is disabled because it's not needed).
The test for #15548 covers also this change.
For #15548.
Change-Id: Id0b3ff983629703d025a442823f99649fd728a56
Reviewed-on: https://go-review.googlesource.com/22839
TryBot-Result: Gobot Gobot
Reviewed-by: Matthew Dempsky
---
src/cmd/compile/internal/gc/bexport.go | 36 +++-
src/cmd/compile/internal/gc/bimport.go | 23 +-
src/cmd/compile/internal/gc/builtin.go | 204 +++++++++---------
src/go/internal/gcimporter/bimport.go | 56 +++--
src/go/internal/gcimporter/gcimporter_test.go | 4 +-
test/fixedbugs/bug398.go | 15 +-
6 files changed, 205 insertions(+), 133 deletions(-)
diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go
index 5d037ae05e74d1..aa1915bb6f2e03 100644
--- a/src/cmd/compile/internal/gc/bexport.go
+++ b/src/cmd/compile/internal/gc/bexport.go
@@ -125,6 +125,17 @@ const exportVersion = "v0"
// Leave for debugging.
const exportInlined = true // default: true
+// trackAllTypes enables cycle tracking for all types, not just named
+// types. The existing compiler invariants assume that unnamed types
+// that are not completely set up are not used, or else there are spurious
+// errors.
+// If disabled, only named types are tracked, possibly leading to slightly
+// less efficient encoding in rare cases. It also prevents the export of
+// some corner-case type declarations (but those are not handled correctly
+// with with the textual export format either).
+// TODO(gri) enable and remove once issues caused by it are fixed
+const trackAllTypes = false
+
type exporter struct {
out *bufio.Writer
@@ -159,6 +170,10 @@ func export(out *bufio.Writer, trace bool) int {
trace: trace,
}
+ // TODO(gri) clean up the ad-hoc encoding of the file format below
+ // (we need this so we can read the builtin package export data
+ // easily w/o being affected by format changes)
+
// first byte indicates low-level encoding format
var format byte = 'c' // compact
if debugFormat {
@@ -166,6 +181,12 @@ func export(out *bufio.Writer, trace bool) int {
}
p.rawByte(format)
+ format = 'n' // track named types only
+ if trackAllTypes {
+ format = 'a'
+ }
+ p.rawByte(format)
+
// posInfo exported or not?
p.bool(p.posInfoFormat)
@@ -585,14 +606,21 @@ func (p *exporter) typ(t *Type) {
}
// otherwise, remember the type, write the type tag (< 0) and type data
- if p.trace {
- p.tracef("T%d = {>\n", len(p.typIndex))
- defer p.tracef("<\n} ")
+ if trackAllTypes {
+ if p.trace {
+ p.tracef("T%d = {>\n", len(p.typIndex))
+ defer p.tracef("<\n} ")
+ }
+ p.typIndex[t] = len(p.typIndex)
}
- p.typIndex[t] = len(p.typIndex)
// pick off named types
if tsym := t.Sym; tsym != nil {
+ if !trackAllTypes {
+ // if we don't track all types, track named types now
+ p.typIndex[t] = len(p.typIndex)
+ }
+
// Predeclared types should have been found in the type map.
if t.Orig == t {
Fatalf("exporter: predeclared type missing from type map?")
diff --git a/src/cmd/compile/internal/gc/bimport.go b/src/cmd/compile/internal/gc/bimport.go
index 6b0593cd472fc4..c4e6e5dd578afe 100644
--- a/src/cmd/compile/internal/gc/bimport.go
+++ b/src/cmd/compile/internal/gc/bimport.go
@@ -24,10 +24,11 @@ type importer struct {
buf []byte // reused for reading strings
// object lists, in order of deserialization
- strList []string
- pkgList []*Pkg
- typList []*Type
- funcList []*Node // nil entry means already declared
+ strList []string
+ pkgList []*Pkg
+ typList []*Type
+ funcList []*Node // nil entry means already declared
+ trackAllTypes bool
// for delayed type verification
cmpList []struct{ pt, t *Type }
@@ -59,6 +60,8 @@ func Import(in *bufio.Reader) {
Fatalf("importer: invalid encoding format in export data: got %q; want 'c' or 'd'", format)
}
+ p.trackAllTypes = p.rawByte() == 'a'
+
p.posInfoFormat = p.bool()
// --- generic export data ---
@@ -331,7 +334,9 @@ func (p *importer) pos() {
func (p *importer) newtyp(etype EType) *Type {
t := typ(etype)
- p.typList = append(p.typList, t)
+ if p.trackAllTypes {
+ p.typList = append(p.typList, t)
+ }
return t
}
@@ -389,7 +394,13 @@ func (p *importer) typ() *Type {
// read underlying type
// parser.go:hidden_type
t0 := p.typ()
- p.importtype(t, t0) // parser.go:hidden_import
+ if p.trackAllTypes {
+ // If we track all types, we cannot check equality of previously
+ // imported types until later. Use customized version of importtype.
+ p.importtype(t, t0)
+ } else {
+ importtype(t, t0)
+ }
// interfaces don't have associated methods
if t0.IsInterface() {
diff --git a/src/cmd/compile/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go
index cc64e73f25c1e3..b9010f4366dcce 100644
--- a/src/cmd/compile/internal/gc/builtin.go
+++ b/src/cmd/compile/internal/gc/builtin.go
@@ -3,106 +3,108 @@
package gc
const runtimeimport = "" +
- "c\x00\x03v0\x01\rruntime\x00\t\x11newobject\x00\x02\x17\"\vtyp·2\x00\x00\x01" +
- "\x17:\x00\t\x13panicindex\x00\x00\x00\t\x13panicslice\x00\x00\x00\t\x15panic" +
- "divide\x00\x00\x00\t\x15throwreturn\x00\x00\x00\t\x11throwinit\x00\x00\x00\t" +
- "\x11panicwrap\x00\x05 \x00 \x00 \x00\x00\t\rgopanic\x00\x01\x1b\x00\x00\x00\x00\t\x11gor" +
- "ecover\x00\x01\x17\b\x00\x01\x1b\x00\x00\x00\t\x11printbool\x00\x01\x00\x00\x00\t\x13printf" +
- "loat\x00\x01\x1a\x00\x00\t\x0fprintint\x00\x01\n\x00\x00\t\x0fprinthex\x00\x01\x14\x00\x00\t" +
- "\x11printuint\x00\x01\x14\x00\x00\t\x17printcomplex\x00\x01\x1e\x00\x00\t\x15prin" +
- "tstring\x00\x01 \x00\x00\t\x17printpointer\x00\x01:\x00\x00\t\x13printif" +
- "ace\x00\x01:\x00\x00\t\x13printeface\x00\x01:\x00\x00\t\x13printslice\x00\x01:" +
- "\x00\x00\t\rprintnl\x00\x00\x00\t\rprintsp\x00\x00\x00\t\x11printlock\x00\x00\x00" +
- "\t\x15printunlock\x00\x00\x00\t\x19concatstring2\x00\x05\x17\x0f@\"\x00 \x00" +
- " \x00\x01 \x00\t\x19concatstring3\x00\a\x17\x0f@\"\x00 \x00 \x00 \x00\x01 \x00\t\x19co" +
- "ncatstring4\x00\t\x17\x0f@\"\x00 \x00 \x00 \x00 \x00\x01 \x00\t\x19concatstr" +
- "ing5\x00\v\x17\x0f@\"\x00 \x00 \x00 \x00 \x00 \x00\x01 \x00\t\x19concatstrings\x00" +
- "\x03\x17\x0f@\"\x00\x11 \x00\x01 \x00\t\x11cmpstring\x00\x03 \x00 \x00\x01\x02\x00\t\x0feqstri" +
- "ng\x00\x03 \x00 \x00\x01\x00\x00\t\x11intstring\x00\x03\x17\x0f\b\"\x00\n\x00\x01 \x00\t!slic" +
- "ebytetostring\x00\x03\x17\x0f@\"\x00\x11\"\x00\x01 \x00\t'slicebytetos" +
- "tringtmp\x00\x01\x11\"\x00\x01 \x00\t!slicerunetostring\x00\x03\x17\x0f@" +
- "\"\x00\x11|S\x00\x01 \x00\t!stringtoslicebyte\x00\x03\x17\x0f@\"\x00 \x00\x01\x11\"" +
- "\x00\t'stringtoslicebytetmp\x00\x01 \x00\x01\x11\"\x00\t!stringt" +
- "oslicerune\x00\x03\x17\x0f@|S\x00 \x00\x01\x11|S\x00\t\x13stringiter\x00\x03 " +
- "\x00\x02\x00\x01\x02\x00\t\x15stringiter2\x00\x03 \x00\x02\x00\x04\x02\rretk·1\x00\x00|S\r" +
- "retv·2\x00\x00\t\x11slicecopy\x00\x06:\tto·2\x00\x00:\tfr·3\x00\x00" +
- "\x16\vwid·4\x00\x1bunsafe-uintptr\x01\x02\x00\t\x1dslicestring" +
- "copy\x00\x04:^\x00\x00:`\x00\x00\x01\x02\x00\t\rconvI2E\x00\x02:\relem·2\x00\x00\x02" +
- ":\vret·1\x00\x00\t\rconvI2I\x00\x04\x17\"\b\x00\x00:\relem·3\x00\x00\x02:l" +
- "\x00\x00\t\rconvT2E\x00\x06\x17\"\b\x00\x00>p\x00\x00>\vbuf·4\x00\x00\x02:l\x00\x00\t\rc" +
- "onvT2I\x00\x06\x17\"\vtab·2\x00\x00>p\x00\x00>t\x00\x00\x02:l\x00\x00\t\x11assert" +
- "E2E\x00\x06\x17\"\vtyp·1\x00\x00:\x0fiface·2\x00\x00>\vret·3\x00\x00\x00\t" +
- "\x13assertE2E2\x00\x06\x17\"\b\x00\x00:\x0fiface·3\x00\x00>\vret·4\x00\x00" +
- "\x01\x00\x00\t\x11assertE2I\x00\x06\x17\"||\x00\x00:~\x00\x00>\x80\x01\x00\x00\x00\t\x13assert" +
- "E2I2\x00\x06\x17\"\b\x00\x00:\x84\x01\x00\x00>\x86\x01\x00\x00\x01\x00\x00\t\x11assertE2T\x00\x06\x17\"|" +
- "|\x00\x00:~\x00\x00>\x80\x01\x00\x00\x00\t\x13assertE2T2\x00\x06\x17\"\b\x00\x00:\x84\x01\x00\x00>\x86\x01" +
- "\x00\x00\x01\x00\x00\t\x11assertI2E\x00\x06\x17\"||\x00\x00:~\x00\x00>\x80\x01\x00\x00\x00\t\x13asse" +
- "rtI2E2\x00\x06\x17\"\b\x00\x00:\x84\x01\x00\x00>\x86\x01\x00\x00\x01\x00\x00\t\x11assertI2I\x00\x06\x17" +
- "\"||\x00\x00:~\x00\x00>\x80\x01\x00\x00\x00\t\x13assertI2I2\x00\x06\x17\"\b\x00\x00:\x84\x01\x00\x00>" +
- "\x86\x01\x00\x00\x01\x00\x00\t\x11assertI2T\x00\x06\x17\"||\x00\x00:~\x00\x00>\x80\x01\x00\x00\x00\t\x13as" +
- "sertI2T2\x00\x06\x17\"\b\x00\x00:\x84\x01\x00\x00>\x86\x01\x00\x00\x01\x00\x00\t\x17panicdotty" +
- "pe\x00\x06\x17\"\rhave·1\x00\x00\x9a\x01\rwant·2\x00\x00\x9a\x01\x84\x01\x00\x00\x00\t\rifa" +
- "ceeq\x00\x04:\ti1·2\x00\x00:\ti2·3\x00\x00\x02\x00l\x00\x00\t\refaceeq\x00\x04" +
- ":\xa4\x01\x00\x00:\xa6\x01\x00\x00\x02\x00l\x00\x00\t\rmakemap\x00\b\x17\"\x13mapType·2\x00" +
- "\x00\n\rhint·3\x00\x00>\x11mapbuf·4\x00\x00>\x17bucketbuf·5\x00" +
- "\x00\x02\x1d::\rhmap·1\x00\x00\t\x13mapaccess1\x00\x06\x17\"\xac\x01\x00\x00\x1d::\rh" +
- "map·3\x00\x00>\vkey·4\x00\x00\x02>\vval·1\x00\x00\t!mapaccess" +
- "1_fast32\x00\x06\x17\"\xac\x01\x00\x00\x1d::\xb8\x01\x00\x00:\xba\x01\x00\x00\x02>\xbc\x01\x00\x00\t!mapa" +
- "ccess1_fast64\x00\x06\x17\"\xac\x01\x00\x00\x1d::\xb8\x01\x00\x00:\xba\x01\x00\x00\x02>\xbc\x01\x00\x00\t" +
- "#mapaccess1_faststr\x00\x06\x17\"\xac\x01\x00\x00\x1d::\xb8\x01\x00\x00:\xba\x01\x00\x00\x02" +
- ">\xbc\x01\x00\x00\t\x1bmapaccess1_fat\x00\b\x17\"\xac\x01\x00\x00\x1d::\xb8\x01\x00\x00>\xba\x01\x00" +
- "\x00\x17\"\rzero·5\x00\x00\x02>\xbc\x01\x00\x00\t\x13mapaccess2\x00\x06\x17\"\x13mapT" +
- "ype·3\x00\x00\x1d::\rhmap·4\x00\x00>\vkey·5\x00\x00\x04>\xbc\x01\x00\x00\x00\rp" +
- "res·2\x00\x00\t!mapaccess2_fast32\x00\x06\x17\"\xca\x01\x00\x00\x1d::\xcc\x01" +
- "\x00\x00:\xce\x01\x00\x00\x04>\xbc\x01\x00\x00\x00\xd0\x01\x00\x00\t!mapaccess2_fast64\x00\x06\x17" +
- "\"\xca\x01\x00\x00\x1d::\xcc\x01\x00\x00:\xce\x01\x00\x00\x04>\xbc\x01\x00\x00\x00\xd0\x01\x00\x00\t#mapaccess2" +
- "_faststr\x00\x06\x17\"\xca\x01\x00\x00\x1d::\xcc\x01\x00\x00:\xce\x01\x00\x00\x04>\xbc\x01\x00\x00\x00\xd0\x01\x00\x00\t" +
- "\x1bmapaccess2_fat\x00\b\x17\"\xca\x01\x00\x00\x1d::\xcc\x01\x00\x00>\xce\x01\x00\x00\x17\"\rze" +
- "ro·6\x00\x00\x04>\xbc\x01\x00\x00\x00\xd0\x01\x00\x00\t\x13mapassign1\x00\b\x17\"\x13mapTy" +
- "pe·1\x00\x00\x1d::\rhmap·2\x00\x00>\vkey·3\x00\x00>\vval·4\x00\x00" +
- "\x00\t\x15mapiterinit\x00\x06\x17\"\xde\x01\x00\x00\x1d::\xe0\x01\x00\x00>\x0fhiter·3\x00" +
- "\x00\x00\t\x11mapdelete\x00\x06\x17\"\xde\x01\x00\x00\x1d::\xe0\x01\x00\x00>\xe2\x01\x00\x00\x00\t\x15mapi" +
- "ternext\x00\x02>\x0fhiter·1\x00\x00\x00\t\x0fmakechan\x00\x04\x17\"\x15cha" +
- "nType·2\x00\x00\n\xae\x01\x00\x00\x02\x1f\x06:\x0fhchan·1\x00\x00\t\x11chanrecv" +
- "1\x00\x06\x17\"\x15chanType·1\x00\x00\x1f\x02:\x0fhchan·2\x00\x00>p\x00\x00\x00\t\x11" +
- "chanrecv2\x00\x06\x17\"\xf2\x01\x00\x00\x1f\x02:\x0fhchan·3\x00\x00>\relem·4" +
- "\x00\x00\x01\x00\x00\t\x11chansend1\x00\x06\x17\"\xf8\x01\x00\x00\x1f\x04:\xfa\x01\x00\x00>p\x00\x00\x00\t\x11cl" +
- "osechan\x00\x02:\xf4\x01\x00\x00\x00\a\x17writeBarrier\x00\x15\x06\renabled" +
- "\x00\x00\x00\vneeded\x00\x00\x00\x05cgo\x00\x00\x00\t\x1dwritebarrierptr\x00\x04>" +
- "\vdst·1\x00\x00:\vsrc·2\x00\x00\x00\t\x17typedmemmove\x00\x06\x17\"||" +
- "\x00\x00>\vdst·2\x00\x00>\vsrc·3\x00\x00\x00\t\x1btypedslicecopy\x00" +
- "\x06\x17\"\b\x00\x00:\vdst·3\x00\x00:\vsrc·4\x00\x00\x01\x02\x00\t\x17selectnbs" +
- "end\x00\x06\x17\"\xf2\x01\x00\x00\x1f\x04:\xfe\x01\x00\x00>\x80\x02\x00\x00\x01\x00\x00\t\x17selectnbrecv" +
- "\x00\x06\x17\"\xf2\x01\x00\x00>p\x00\x00\x1f\x02:\x0fhchan·4\x00\x00\x01\x00\x00\t\x19selectnbr" +
- "ecv2\x00\b\x17\"\xf2\x01\x00\x00>p\x00\x00\x17\x00\x15received·4\x00\x00\x1f\x02:\x0fhcha" +
- "n·5\x00\x00\x01\x00\x00\t\x11newselect\x00\x06\x17\"\vsel·1\x00\x00\n\x13selsi" +
- "ze·2\x00\x00\b\rsize·3\x00\x00\x00\t\x13selectsend\x00\x06\x17\"\vsel\xc2" +
- "\xb72\x00\x00\x1f\x04:\xfe\x01\x00\x00>\x80\x02\x00\x00\x02\x00\x15selected·1\x00\x00\t\x13select" +
- "recv\x00\x06\x17\"\xb6\x02\x00\x00\x1f\x02:\xfe\x01\x00\x00>\x80\x02\x00\x00\x02\x00\xb8\x02\x00\x00\t\x15selectre" +
- "cv2\x00\b\x17\"\xb6\x02\x00\x00\x1f\x02:\xfe\x01\x00\x00>\x80\x02\x00\x00\xf8\x01\x15received·5\x00\x00\x02" +
- "\x00\xb8\x02\x00\x00\t\x19selectdefault\x00\x02\x17\"\xb6\x02\x00\x00\x02\x00\xb8\x02\x00\x00\t\x0fsele" +
- "ctgo\x00\x02\x17\"\xae\x02\x00\x00\x00\t\tblock\x00\x00\x00\t\x11makeslice\x00\x06\x17\"\b\x00" +
- "\x00\n\vnel·3\x00\x00\n\vcap·4\x00\x00\x02\x11:\vary·1\x00\x00\t\x11grows" +
- "lice\x00\x06\x17\"\b\x00\x00\x11:\vold·3\x00\x00\x02\xca\x02\x00\x00\x02\x11:\xcc\x02\x00\x00\t\rmemm" +
- "ove\x00\x06>\tto·1\x00\x00>\vfrm·2\x00\x00\x16\x11length·3\x00d\x00\t\v" +
- "memclr\x00\x04\x17\"\vptr·1\x00\x00\x16\x11length·2\x00d\x00\t\x0fmemeq" +
- "ual\x00\x06>\ax·2\x00\x00>\ay·3\x00\x00\x16\rsize·4\x00d\x01\x00\x00\t\x11mem" +
- "equal8\x00\x04>\xe2\x02\x00\x00>\xe4\x02\x00\x00\x01\x00\x00\t\x13memequal16\x00\x04>\xe2\x02\x00\x00" +
- ">\xe4\x02\x00\x00\x01\x00\x00\t\x13memequal32\x00\x04>\xe2\x02\x00\x00>\xe4\x02\x00\x00\x01\x00\x00\t\x13mem" +
- "equal64\x00\x04>\xe2\x02\x00\x00>\xe4\x02\x00\x00\x01\x00\x00\t\x15memequal128\x00\x04>\xe2\x02" +
- "\x00\x00>\xe4\x02\x00\x00\x01\x00\x00\t\x0fint64div\x00\x03\n\x00\n\x00\x01\n\x00\t\x11uint64div" +
- "\x00\x03\x14\x00\x14\x00\x01\x14\x00\t\x0fint64mod\x00\x03\n\x00\n\x00\x01\n\x00\t\x11uint64mod\x00" +
- "\x03\x14\x00\x14\x00\x01\x14\x00\t\x1bfloat64toint64\x00\x01\x1a\x00\x01\n\x00\t\x1dfloat64" +
- "touint64\x00\x01\x1a\x00\x01\x14\x00\t\x1bint64tofloat64\x00\x01\n\x00\x01\x1a\x00\t\x1d" +
- "uint64tofloat64\x00\x01\x14\x00\x01\x1a\x00\t\x19complex128div\x00\x04\x1e" +
- "\vnum·2\x00\x00\x1e\vden·3\x00\x00\x02\x1e\vquo·1\x00\x00\t\x19racefunc" +
- "enter\x00\x01\x16d\x00\t\x17racefuncexit\x00\x00\x00\t\x0fraceread\x00\x01\x16" +
- "d\x00\t\x11racewrite\x00\x01\x16d\x00\t\x19racereadrange\x00\x04\x16\radd" +
- "r·1\x00d\x16\rsize·2\x00d\x00\t\x1bracewriterange\x00\x04\x16\x94\x03\x00" +
- "d\x16\x96\x03\x00d\x00\t\x0fmsanread\x00\x04\x16\x94\x03\x00d\x16\x96\x03\x00d\x00\t\x11msanwrit" +
- "e\x00\x04\x16\x94\x03\x00d\x16\x96\x03\x00d\x00\v\xf4\x01\x02\v\x00\x01\x00\n$$\n"
+ "cn\x00\x03v0\x01\rruntime\x00\t\x11newobject\x00\x02\x17\"\vtyp·2\x00\x00" +
+ "\x01\x17:\x00\t\x13panicindex\x00\x00\x00\t\x13panicslice\x00\x00\x00\t\x15pani" +
+ "cdivide\x00\x00\x00\t\x15throwreturn\x00\x00\x00\t\x11throwinit\x00\x00\x00" +
+ "\t\x11panicwrap\x00\x05 \x00 \x00 \x00\x00\t\rgopanic\x00\x01\x1b\x00\x00\x00\x00\t\x11go" +
+ "recover\x00\x01\x17\b\x00\x01\x1b\x00\x00\x00\t\x11printbool\x00\x01\x00\x00\x00\t\x13print" +
+ "float\x00\x01\x1a\x00\x00\t\x0fprintint\x00\x01\n\x00\x00\t\x0fprinthex\x00\x01\x14\x00\x00" +
+ "\t\x11printuint\x00\x01\x14\x00\x00\t\x17printcomplex\x00\x01\x1e\x00\x00\t\x15pri" +
+ "ntstring\x00\x01 \x00\x00\t\x17printpointer\x00\x01:\x00\x00\t\x13printi" +
+ "face\x00\x01:\x00\x00\t\x13printeface\x00\x01:\x00\x00\t\x13printslice\x00\x01" +
+ ":\x00\x00\t\rprintnl\x00\x00\x00\t\rprintsp\x00\x00\x00\t\x11printlock\x00\x00" +
+ "\x00\t\x15printunlock\x00\x00\x00\t\x19concatstring2\x00\x05\x17\x0f@\"\x00 " +
+ "\x00 \x00\x01 \x00\t\x19concatstring3\x00\a\x17\x0f@\"\x00 \x00 \x00 \x00\x01 \x00\t\x19c" +
+ "oncatstring4\x00\t\x17\x0f@\"\x00 \x00 \x00 \x00 \x00\x01 \x00\t\x19concatst" +
+ "ring5\x00\v\x17\x0f@\"\x00 \x00 \x00 \x00 \x00 \x00\x01 \x00\t\x19concatstrings" +
+ "\x00\x03\x17\x0f@\"\x00\x11 \x00\x01 \x00\t\x11cmpstring\x00\x03 \x00 \x00\x01\x02\x00\t\x0feqstr" +
+ "ing\x00\x03 \x00 \x00\x01\x00\x00\t\x11intstring\x00\x03\x17\x0f\b\"\x00\n\x00\x01 \x00\t!sli" +
+ "cebytetostring\x00\x03\x17\x0f@\"\x00\x11\"\x00\x01 \x00\t'slicebyteto" +
+ "stringtmp\x00\x01\x11\"\x00\x01 \x00\t!slicerunetostring\x00\x03\x17\x0f" +
+ "@\"\x00\x11|S\x00\x01 \x00\t!stringtoslicebyte\x00\x03\x17\x0f@\"\x00 \x00\x01\x11" +
+ "\"\x00\t'stringtoslicebytetmp\x00\x01 \x00\x01\x11\"\x00\t!string" +
+ "toslicerune\x00\x03\x17\x0f@|S\x00 \x00\x01\x11|S\x00\t\x13stringiter\x00\x03" +
+ " \x00\x02\x00\x01\x02\x00\t\x15stringiter2\x00\x03 \x00\x02\x00\x04\x02\rretk·1\x00\x00|S" +
+ "\rretv·2\x00\x00\t\x11slicecopy\x00\x06:\tto·2\x00\x00:\tfr·3\x00" +
+ "\x00\x16\vwid·4\x00\x1bunsafe-uintptr\x01\x02\x00\t\x1dslicestrin" +
+ "gcopy\x00\x04:^\x00\x00:`\x00\x00\x01\x02\x00\t\rconvI2E\x00\x02:\relem·2\x00\x00" +
+ "\x02:\vret·1\x00\x00\t\rconvI2I\x00\x04\x17\"\b\x00\x00:\relem·3\x00\x00\x02:" +
+ "l\x00\x00\t\rconvT2E\x00\x06\x17\"\b\x00\x00\x17:p\x00\x00\x17:\vbuf·4\x00\x00\x02:l\x00\x00" +
+ "\t\rconvT2I\x00\x06\x17\"\vtab·2\x00\x00\x17:p\x00\x00\x17:t\x00\x00\x02:l\x00\x00\t\x11a" +
+ "ssertE2E\x00\x06\x17\"\vtyp·1\x00\x00:\x0fiface·2\x00\x00\x17:\vret\xc2" +
+ "\xb73\x00\x00\x00\t\x13assertE2E2\x00\x06\x17\"\b\x00\x00:\x0fiface·3\x00\x00\x17:\vr" +
+ "et·4\x00\x00\x01\x00\x00\t\x11assertE2I\x00\x06\x17\"||\x00\x00:~\x00\x00\x17:\x80\x01\x00\x00\x00" +
+ "\t\x13assertE2I2\x00\x06\x17\"\b\x00\x00:\x84\x01\x00\x00\x17:\x86\x01\x00\x00\x01\x00\x00\t\x11asser" +
+ "tE2T\x00\x06\x17\"||\x00\x00:~\x00\x00\x17:\x80\x01\x00\x00\x00\t\x13assertE2T2\x00\x06\x17\"\b" +
+ "\x00\x00:\x84\x01\x00\x00\x17:\x86\x01\x00\x00\x01\x00\x00\t\x11assertI2E\x00\x06\x17\"||\x00\x00:~\x00\x00\x17" +
+ ":\x80\x01\x00\x00\x00\t\x13assertI2E2\x00\x06\x17\"\b\x00\x00:\x84\x01\x00\x00\x17:\x86\x01\x00\x00\x01\x00\x00\t" +
+ "\x11assertI2I\x00\x06\x17\"||\x00\x00:~\x00\x00\x17:\x80\x01\x00\x00\x00\t\x13assertI2I" +
+ "2\x00\x06\x17\"\b\x00\x00:\x84\x01\x00\x00\x17:\x86\x01\x00\x00\x01\x00\x00\t\x11assertI2T\x00\x06\x17\"||\x00" +
+ "\x00:~\x00\x00\x17:\x80\x01\x00\x00\x00\t\x13assertI2T2\x00\x06\x17\"\b\x00\x00:\x84\x01\x00\x00\x17:\x86\x01" +
+ "\x00\x00\x01\x00\x00\t\x17panicdottype\x00\x06\x17\"\rhave·1\x00\x00\x17\"\rwant" +
+ "·2\x00\x00\x17\"\x84\x01\x00\x00\x00\t\rifaceeq\x00\x04:\ti1·2\x00\x00:\ti2·3\x00" +
+ "\x00\x02\x00l\x00\x00\t\refaceeq\x00\x04:\xa4\x01\x00\x00:\xa6\x01\x00\x00\x02\x00l\x00\x00\t\rmakema" +
+ "p\x00\b\x17\"\x13mapType·2\x00\x00\n\rhint·3\x00\x00\x17:\x11mapbuf·" +
+ "4\x00\x00\x17:\x17bucketbuf·5\x00\x00\x02\x1d::\rhmap·1\x00\x00\t\x13mapa" +
+ "ccess1\x00\x06\x17\"\xac\x01\x00\x00\x1d::\rhmap·3\x00\x00\x17:\vkey·4\x00\x00\x02\x17" +
+ ":\vval·1\x00\x00\t!mapaccess1_fast32\x00\x06\x17\"\xac\x01\x00\x00\x1d::" +
+ "\xb8\x01\x00\x00:\xba\x01\x00\x00\x02\x17:\xbc\x01\x00\x00\t!mapaccess1_fast64\x00\x06\x17\"\xac" +
+ "\x01\x00\x00\x1d::\xb8\x01\x00\x00:\xba\x01\x00\x00\x02\x17:\xbc\x01\x00\x00\t#mapaccess1_fasts" +
+ "tr\x00\x06\x17\"\xac\x01\x00\x00\x1d::\xb8\x01\x00\x00:\xba\x01\x00\x00\x02\x17:\xbc\x01\x00\x00\t\x1bmapaccess" +
+ "1_fat\x00\b\x17\"\xac\x01\x00\x00\x1d::\xb8\x01\x00\x00\x17:\xba\x01\x00\x00\x17\"\rzero·5\x00\x00\x02\x17" +
+ ":\xbc\x01\x00\x00\t\x13mapaccess2\x00\x06\x17\"\x13mapType·3\x00\x00\x1d::\rhm" +
+ "ap·4\x00\x00\x17:\vkey·5\x00\x00\x04\x17:\xbc\x01\x00\x00\x00\rpres·2\x00\x00\t!ma" +
+ "paccess2_fast32\x00\x06\x17\"\xca\x01\x00\x00\x1d::\xcc\x01\x00\x00:\xce\x01\x00\x00\x04\x17:\xbc\x01" +
+ "\x00\x00\x00\xd0\x01\x00\x00\t!mapaccess2_fast64\x00\x06\x17\"\xca\x01\x00\x00\x1d::\xcc\x01\x00" +
+ "\x00:\xce\x01\x00\x00\x04\x17:\xbc\x01\x00\x00\x00\xd0\x01\x00\x00\t#mapaccess2_faststr\x00\x06" +
+ "\x17\"\xca\x01\x00\x00\x1d::\xcc\x01\x00\x00:\xce\x01\x00\x00\x04\x17:\xbc\x01\x00\x00\x00\xd0\x01\x00\x00\t\x1bmapacces" +
+ "s2_fat\x00\b\x17\"\xca\x01\x00\x00\x1d::\xcc\x01\x00\x00\x17:\xce\x01\x00\x00\x17\"\rzero·6\x00\x00\x04" +
+ "\x17:\xbc\x01\x00\x00\x00\xd0\x01\x00\x00\t\x13mapassign1\x00\b\x17\"\x13mapType·1\x00\x00" +
+ "\x1d::\rhmap·2\x00\x00\x17:\vkey·3\x00\x00\x17:\vval·4\x00\x00\x00\t\x15ma" +
+ "piterinit\x00\x06\x17\"\xde\x01\x00\x00\x1d::\xe0\x01\x00\x00\x17:\x0fhiter·3\x00\x00\x00\t\x11" +
+ "mapdelete\x00\x06\x17\"\xde\x01\x00\x00\x1d::\xe0\x01\x00\x00\x17:\xe2\x01\x00\x00\x00\t\x15mapiter" +
+ "next\x00\x02\x17:\x0fhiter·1\x00\x00\x00\t\x0fmakechan\x00\x04\x17\"\x15chanT" +
+ "ype·2\x00\x00\n\xae\x01\x00\x00\x02\x1f\x06:\x0fhchan·1\x00\x00\t\x11chanrecv1\x00" +
+ "\x06\x17\"\x15chanType·1\x00\x00\x1f\x02:\x0fhchan·2\x00\x00\x17:p\x00\x00\x00\t\x11c" +
+ "hanrecv2\x00\x06\x17\"\xf2\x01\x00\x00\x1f\x02:\x0fhchan·3\x00\x00\x17:\relem·4" +
+ "\x00\x00\x01\x00\x00\t\x11chansend1\x00\x06\x17\"\xf8\x01\x00\x00\x1f\x04:\xfa\x01\x00\x00\x17:p\x00\x00\x00\t\x11c" +
+ "losechan\x00\x02:\xf4\x01\x00\x00\x00\a\x17writeBarrier\x00\x15\x06\renable" +
+ "d\x00\x00\x00\vneeded\x00\x00\x00\x05cgo\x00\x00\x00\t\x1dwritebarrierptr\x00\x04" +
+ "\x17:\vdst·1\x00\x00:\vsrc·2\x00\x00\x00\t\x17typedmemmove\x00\x06\x17\"" +
+ "||\x00\x00\x17:\vdst·2\x00\x00\x17:\vsrc·3\x00\x00\x00\t\x1btypedslicec" +
+ "opy\x00\x06\x17\"\b\x00\x00:\vdst·3\x00\x00:\vsrc·4\x00\x00\x01\x02\x00\t\x17selec" +
+ "tnbsend\x00\x06\x17\"\xf2\x01\x00\x00\x1f\x04:\xfe\x01\x00\x00\x17:\x80\x02\x00\x00\x01\x00\x00\t\x17selectn" +
+ "brecv\x00\x06\x17\"\xf2\x01\x00\x00\x17:p\x00\x00\x1f\x02:\x0fhchan·4\x00\x00\x01\x00\x00\t\x19sel" +
+ "ectnbrecv2\x00\b\x17\"\xf2\x01\x00\x00\x17:p\x00\x00\x17\x00\x15received·4\x00\x00\x1f" +
+ "\x02:\x0fhchan·5\x00\x00\x01\x00\x00\t\x11newselect\x00\x06\x17\"\vsel·1\x00\x00" +
+ "\n\x13selsize·2\x00\x00\b\rsize·3\x00\x00\x00\t\x13selectsend\x00\x06" +
+ "\x17\"\vsel·2\x00\x00\x1f\x04:\xfe\x01\x00\x00\x17:\x80\x02\x00\x00\x02\x00\x15selected·1\x00\x00" +
+ "\t\x13selectrecv\x00\x06\x17\"\xb6\x02\x00\x00\x1f\x02:\xfe\x01\x00\x00\x17:\x80\x02\x00\x00\x02\x00\xb8\x02\x00\x00\t" +
+ "\x15selectrecv2\x00\b\x17\"\xb6\x02\x00\x00\x1f\x02:\xfe\x01\x00\x00\x17:\x80\x02\x00\x00\x17\x00\x15rece" +
+ "ived·5\x00\x00\x02\x00\xb8\x02\x00\x00\t\x19selectdefault\x00\x02\x17\"\xb6\x02\x00\x00\x02\x00" +
+ "\xb8\x02\x00\x00\t\x0fselectgo\x00\x02\x17\"\xae\x02\x00\x00\x00\t\tblock\x00\x00\x00\t\x11makes" +
+ "lice\x00\x06\x17\"\b\x00\x00\n\vnel·3\x00\x00\n\vcap·4\x00\x00\x02\x11:\vary·" +
+ "1\x00\x00\t\x11growslice\x00\x06\x17\"\b\x00\x00\x11:\vold·3\x00\x00\x02\xca\x02\x00\x00\x02\x11:" +
+ "\xcc\x02\x00\x00\t\rmemmove\x00\x06\x17:\tto·1\x00\x00\x17:\vfrm·2\x00\x00\x16\x11le" +
+ "ngth·3\x00d\x00\t\vmemclr\x00\x04\x17\"\vptr·1\x00\x00\x16\x11length\xc2" +
+ "\xb72\x00d\x00\t\x0fmemequal\x00\x06\x17:\ax·2\x00\x00\x17:\ay·3\x00\x00\x16\rsiz" +
+ "e·4\x00d\x01\x00\x00\t\x11memequal8\x00\x04\x17:\xe2\x02\x00\x00\x17:\xe4\x02\x00\x00\x01\x00\x00\t\x13m" +
+ "emequal16\x00\x04\x17:\xe2\x02\x00\x00\x17:\xe4\x02\x00\x00\x01\x00\x00\t\x13memequal32\x00\x04" +
+ "\x17:\xe2\x02\x00\x00\x17:\xe4\x02\x00\x00\x01\x00\x00\t\x13memequal64\x00\x04\x17:\xe2\x02\x00\x00\x17:\xe4\x02\x00" +
+ "\x00\x01\x00\x00\t\x15memequal128\x00\x04\x17:\xe2\x02\x00\x00\x17:\xe4\x02\x00\x00\x01\x00\x00\t\x0fint6" +
+ "4div\x00\x03\n\x00\n\x00\x01\n\x00\t\x11uint64div\x00\x03\x14\x00\x14\x00\x01\x14\x00\t\x0fint64" +
+ "mod\x00\x03\n\x00\n\x00\x01\n\x00\t\x11uint64mod\x00\x03\x14\x00\x14\x00\x01\x14\x00\t\x1bfloat6" +
+ "4toint64\x00\x01\x1a\x00\x01\n\x00\t\x1dfloat64touint64\x00\x01\x1a\x00\x01\x14\x00\t" +
+ "\x1bint64tofloat64\x00\x01\n\x00\x01\x1a\x00\t\x1duint64tofloat64\x00" +
+ "\x01\x14\x00\x01\x1a\x00\t\x19complex128div\x00\x04\x1e\vnum·2\x00\x00\x1e\vden·" +
+ "3\x00\x00\x02\x1e\vquo·1\x00\x00\t\x19racefuncenter\x00\x01\x16d\x00\t\x17race" +
+ "funcexit\x00\x00\x00\t\x0fraceread\x00\x01\x16d\x00\t\x11racewrite\x00\x01\x16" +
+ "d\x00\t\x19racereadrange\x00\x04\x16\raddr·1\x00d\x16\rsize·2\x00" +
+ "d\x00\t\x1bracewriterange\x00\x04\x16\x94\x03\x00d\x16\x96\x03\x00d\x00\t\x0fmsanrea" +
+ "d\x00\x04\x16\x94\x03\x00d\x16\x96\x03\x00d\x00\t\x11msanwrite\x00\x04\x16\x94\x03\x00d\x16\x96\x03\x00d\x00\v\xf4" +
+ "\x01\x02\v\x00\x01\x00\n$$\n"
const unsafeimport = "" +
- "c\x00\x03v0\x01\vunsafe\x00\x05\r\rPointer\x00\x16\x00\t\x0fOffsetof\x00\x01:" +
- "\x00\x01\x16\x00\t\vSizeof\x00\x01:\x00\x01\x16\x00\t\rAlignof\x00\x01:\x00\x01\x16\x00\v\b\x00\v\x00" +
- "\x01\x00\n$$\n"
+ "cn\x00\x03v0\x01\vunsafe\x00\x05\r\rPointer\x00\x16\x00\t\x0fOffsetof\x00\x01" +
+ ":\x00\x01\x16\x00\t\vSizeof\x00\x01:\x00\x01\x16\x00\t\rAlignof\x00\x01:\x00\x01\x16\x00\v\b\x00\v" +
+ "\x00\x01\x00\n$$\n"
diff --git a/src/go/internal/gcimporter/bimport.go b/src/go/internal/gcimporter/bimport.go
index eb29df77ab757b..964bf5512e080c 100644
--- a/src/go/internal/gcimporter/bimport.go
+++ b/src/go/internal/gcimporter/bimport.go
@@ -23,9 +23,10 @@ type importer struct {
buf []byte // for reading strings
// object lists
- strList []string // in order of appearance
- pkgList []*types.Package // in order of appearance
- typList []types.Type // in order of appearance
+ strList []string // in order of appearance
+ pkgList []*types.Package // in order of appearance
+ typList []types.Type // in order of appearance
+ trackAllTypes bool
// position encoding
posInfoFormat bool
@@ -59,6 +60,8 @@ func BImportData(imports map[string]*types.Package, data []byte, path string) (i
return p.read, nil, fmt.Errorf("invalid encoding format in export data: got %q; want 'c' or 'd'", format)
}
+ p.trackAllTypes = p.rawByte() == 'a'
+
p.posInfoFormat = p.int() != 0
// --- generic export data ---
@@ -93,7 +96,12 @@ func BImportData(imports map[string]*types.Package, data []byte, path string) (i
// complete interfaces
for _, typ := range p.typList {
- if it, ok := typ.(*types.Interface); ok {
+ // If we only record named types (!p.trackAllTypes),
+ // we must check the underlying types here. If we
+ // track all types, the Underlying() method call is
+ // not needed.
+ // TODO(gri) Remove if p.trackAllTypes is gone.
+ if it, ok := typ.Underlying().(*types.Interface); ok {
it.Complete()
}
}
@@ -304,7 +312,9 @@ func (p *importer) typ(parent *types.Package) types.Type {
case arrayTag:
t := new(types.Array)
- p.record(t)
+ if p.trackAllTypes {
+ p.record(t)
+ }
n := p.int64()
*t = *types.NewArray(p.typ(parent), n)
@@ -312,35 +322,45 @@ func (p *importer) typ(parent *types.Package) types.Type {
case sliceTag:
t := new(types.Slice)
- p.record(t)
+ if p.trackAllTypes {
+ p.record(t)
+ }
*t = *types.NewSlice(p.typ(parent))
return t
case dddTag:
t := new(dddSlice)
- p.record(t)
+ if p.trackAllTypes {
+ p.record(t)
+ }
t.elem = p.typ(parent)
return t
case structTag:
t := new(types.Struct)
- p.record(t)
+ if p.trackAllTypes {
+ p.record(t)
+ }
*t = *types.NewStruct(p.fieldList(parent))
return t
case pointerTag:
t := new(types.Pointer)
- p.record(t)
+ if p.trackAllTypes {
+ p.record(t)
+ }
*t = *types.NewPointer(p.typ(parent))
return t
case signatureTag:
t := new(types.Signature)
- p.record(t)
+ if p.trackAllTypes {
+ p.record(t)
+ }
params, isddd := p.paramList()
result, _ := p.paramList()
@@ -353,7 +373,9 @@ func (p *importer) typ(parent *types.Package) types.Type {
// such cycle must contain a named type which would have been
// first defined earlier.
n := len(p.typList)
- p.record(nil)
+ if p.trackAllTypes {
+ p.record(nil)
+ }
// no embedded interfaces with gc compiler
if p.int() != 0 {
@@ -361,12 +383,16 @@ func (p *importer) typ(parent *types.Package) types.Type {
}
t := types.NewInterface(p.methodList(parent), nil)
- p.typList[n] = t
+ if p.trackAllTypes {
+ p.typList[n] = t
+ }
return t
case mapTag:
t := new(types.Map)
- p.record(t)
+ if p.trackAllTypes {
+ p.record(t)
+ }
key := p.typ(parent)
val := p.typ(parent)
@@ -375,7 +401,9 @@ func (p *importer) typ(parent *types.Package) types.Type {
case chanTag:
t := new(types.Chan)
- p.record(t)
+ if p.trackAllTypes {
+ p.record(t)
+ }
var dir types.ChanDir
// tag values must match the constants in cmd/compile/internal/gc/go.go
diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go
index e56720b0d52543..8b94f9a105a6c1 100644
--- a/src/go/internal/gcimporter/gcimporter_test.go
+++ b/src/go/internal/gcimporter/gcimporter_test.go
@@ -351,9 +351,9 @@ func TestIssue13898(t *testing.T) {
}
// lookup go/types.Object.Pkg method
- m, _, _ := types.LookupFieldOrMethod(typ, false, nil, "Pkg")
+ m, index, indirect := types.LookupFieldOrMethod(typ, false, nil, "Pkg")
if m == nil {
- t.Fatal("go/types.Object.Pkg not found")
+ t.Fatalf("go/types.Object.Pkg not found (index = %v, indirect = %v)", index, indirect)
}
// the method must belong to go/types
diff --git a/test/fixedbugs/bug398.go b/test/fixedbugs/bug398.go
index a80a960394470b..81bf33c37a6df1 100644
--- a/test/fixedbugs/bug398.go
+++ b/test/fixedbugs/bug398.go
@@ -8,17 +8,20 @@
package p
-type I1 interface {
- F() interface{I1}
+type i1 interface {
+ F() interface{i1}
}
-type I2 interface {
- F() interface{I2}
+type i2 interface {
+ F() interface{i2}
}
-var v1 I1
-var v2 I2
+var v1 i1
+var v2 i2
func f() bool {
return v1 == v2
}
+
+// TODO(gri) Change test to use exported interfaces.
+// See issue #15596 for details.
\ No newline at end of file
From 0b6e5e3d733c1da53244753b42940eddb7401c6c Mon Sep 17 00:00:00 2001
From: Joel Sing
Date: Sun, 8 May 2016 01:27:45 +1000
Subject: [PATCH 036/267] cmd/link: specify correct size for dynamic symbols in
386 elf output
Currently 386 ELF binaries are generated with dynamic symbols that have
a size of zero bytes, even though the symbol in the symbol table has
the correct size. Fix this by specifying the correct size when creating
dynamic symbols.
Issue found on OpenBSD -current, where ld.so is now producing link
warnings due to mismatched symbol sizes.
Fixes #15593.
Change-Id: Ib1a12b23ff9159c61ac980bf48a983b86f3df256
Reviewed-on: https://go-review.googlesource.com/22912
Reviewed-by: Minux Ma
Run-TryBot: Minux Ma
TryBot-Result: Gobot Gobot
---
src/cmd/link/internal/ld/elf.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go
index e66de49f413373..39d3609a291f04 100644
--- a/src/cmd/link/internal/ld/elf.go
+++ b/src/cmd/link/internal/ld/elf.go
@@ -2665,8 +2665,8 @@ func Elfadddynsym(ctxt *Link, s *LSym) {
Addaddr(ctxt, d, s)
}
- /* size */
- Adduint32(ctxt, d, 0)
+ /* size of object */
+ Adduint32(ctxt, d, uint32(s.Size))
/* type */
t := STB_GLOBAL << 4
From 55546efeee9fb6104d3dfd76351e7765df0bdd71 Mon Sep 17 00:00:00 2001
From: Matthew Dempsky
Date: Sun, 8 May 2016 12:54:31 -0700
Subject: [PATCH 037/267] Revert "cmd/compile: properly handle map assignments
for OAS2DOTTYPE"
This reverts commit 9d7c9b4384db01afd2acb27d3a4636b60e957f08.
For #15602.
Change-Id: I464184b05babe4cb8dedab6161efa730cea6ee2d
Reviewed-on: https://go-review.googlesource.com/22930
Run-TryBot: Matthew Dempsky
Reviewed-by: Josh Bleecher Snyder
TryBot-Result: Gobot Gobot
---
src/cmd/compile/internal/gc/order.go | 26 ++++++++++----------------
test/fixedbugs/issue14678.go | 27 ---------------------------
2 files changed, 10 insertions(+), 43 deletions(-)
delete mode 100644 test/fixedbugs/issue14678.go
diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go
index d432b43460b88f..7026ad79efa383 100644
--- a/src/cmd/compile/internal/gc/order.go
+++ b/src/cmd/compile/internal/gc/order.go
@@ -569,24 +569,18 @@ func orderstmt(n *Node, order *Order) {
orderexprlist(n.List, order)
n.Rlist.First().Left = orderexpr(n.Rlist.First().Left, order, nil) // i in i.(T)
-
- results := n.List.Slice()
- var assigns [2]*Node
-
- for r, res := range results {
- if !isblank(res) {
- results[r] = ordertemp(res.Type, order, haspointers(res.Type))
- assigns[r] = Nod(OAS, res, results[r])
- }
+ if isblank(n.List.First()) {
+ order.out = append(order.out, n)
+ } else {
+ typ := n.Rlist.First().Type
+ tmp1 := ordertemp(typ, order, haspointers(typ))
+ order.out = append(order.out, n)
+ r := Nod(OAS, n.List.First(), tmp1)
+ r = typecheck(r, Etop)
+ ordermapassign(r, order)
+ n.List.Set([]*Node{tmp1, n.List.Second()})
}
- order.out = append(order.out, n)
- for _, assign := range assigns {
- if assign != nil {
- assign = typecheck(assign, Etop)
- ordermapassign(assign, order)
- }
- }
cleantemp(t, order)
// Special: use temporary variables to hold result,
diff --git a/test/fixedbugs/issue14678.go b/test/fixedbugs/issue14678.go
deleted file mode 100644
index 94ca86d26ce060..00000000000000
--- a/test/fixedbugs/issue14678.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// run
-
-// Copyright 2016 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 main
-
-func main() {
- m := make(map[int]bool)
- i := interface{}(1)
- var v int
-
- // Ensure map is updated properly
- _, m[1] = i.(int)
- v, m[2] = i.(int)
-
- if v != 1 {
- panic("fail: v should be 1")
- }
- if m[1] == false {
- panic("fail: m[1] should be true")
- }
- if m[2] == false {
- panic("fail: m[2] should be true")
- }
-}
From 3696e469e5f8a5531c69ffcf091deaa692e81104 Mon Sep 17 00:00:00 2001
From: Josh Bleecher Snyder
Date: Sun, 8 May 2016 14:32:48 -0700
Subject: [PATCH 038/267] test: add test for issue 15602
The problem was fixed by the rollback in CL 22930.
This CL just adds a test to prevent regressions.
Fixes #15602
Change-Id: I37453f6e18ca43081266fe7f154c6d63fbaffd9b
Reviewed-on: https://go-review.googlesource.com/22931
Run-TryBot: Josh Bleecher Snyder
TryBot-Result: Gobot Gobot
Reviewed-by: Matthew Dempsky
---
test/fixedbugs/issue15602.go | 11 +++++++++++
1 file changed, 11 insertions(+)
create mode 100644 test/fixedbugs/issue15602.go
diff --git a/test/fixedbugs/issue15602.go b/test/fixedbugs/issue15602.go
new file mode 100644
index 00000000000000..badf8133c52176
--- /dev/null
+++ b/test/fixedbugs/issue15602.go
@@ -0,0 +1,11 @@
+// compile
+
+// Copyright 2016 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 p
+
+func f(i interface{}) {
+ i, _ = i.(error)
+}
From 87a2ae1fa25677dc9097a25292c54b7b9dac2c9d Mon Sep 17 00:00:00 2001
From: Robert Griesemer
Date: Sun, 8 May 2016 20:59:53 -0700
Subject: [PATCH 039/267] cmd/compile: fix binary export of composite literals
with implicit types
Also:
- replaced remaining panics with Fatal calls
- more comments
Fixes #15572.
Change-Id: Ifb27e80b66700f5692a84078764a1e928d4b310d
Reviewed-on: https://go-review.googlesource.com/22935
Run-TryBot: Robert Griesemer
TryBot-Result: Gobot Gobot
Reviewed-by: Matthew Dempsky
---
src/cmd/compile/internal/gc/bexport.go | 43 ++++++++++++++------------
src/cmd/compile/internal/gc/bimport.go | 27 +++++++---------
test/fixedbugs/issue15572.dir/a.go | 40 ++++++++++++++++++++++++
test/fixedbugs/issue15572.dir/b.go | 27 ++++++++++++++++
test/fixedbugs/issue15572.go | 11 +++++++
5 files changed, 113 insertions(+), 35 deletions(-)
create mode 100644 test/fixedbugs/issue15572.dir/a.go
create mode 100644 test/fixedbugs/issue15572.dir/b.go
create mode 100644 test/fixedbugs/issue15572.go
diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go
index aa1915bb6f2e03..cd2963e8e64e09 100644
--- a/src/cmd/compile/internal/gc/bexport.go
+++ b/src/cmd/compile/internal/gc/bexport.go
@@ -937,7 +937,7 @@ func parName(f *Field, numbered bool) string {
// print symbol with Vargen number or not as desired
name := s.Name
if strings.Contains(name, ".") {
- panic("invalid symbol name: " + name)
+ Fatalf("invalid symbol name: %s", name)
}
// Functions that can be inlined use numbered parameters so we can distingish them
@@ -1040,6 +1040,8 @@ func (p *exporter) float(x *Mpflt) {
// but instead of emitting the information textually, emit the node tree in
// binary form.
+// TODO(gri) Improve tracing output. The current format is difficult to read.
+
// stmtList may emit more (or fewer) than len(list) nodes.
func (p *exporter) stmtList(list Nodes) {
if p.trace {
@@ -1116,6 +1118,16 @@ func (p *exporter) expr(n *Node) {
defer p.tracef(") ")
}
+ // from nodefmt (fmt.go)
+ //
+ // nodefmt reverts nodes back to their original - we don't need to do
+ // it because we are not bound to produce valid Go syntax when exporting
+ //
+ // if (fmtmode != FExp || n.Op != OLITERAL) && n.Orig != nil {
+ // n = n.Orig
+ // }
+
+ // from exprfmt (fmt.go)
for n != nil && n.Implicit && (n.Op == OIND || n.Op == OADDR) {
n = n.Left
}
@@ -1188,14 +1200,14 @@ func (p *exporter) expr(n *Node) {
p.typ(n.Type)
}
- case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
- panic("unreachable") // should have been resolved by typechecking
+ // case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
+ // should have been resolved by typechecking - handled by default case
// case OCLOSURE:
// unimplemented - handled by default case
// case OCOMPLIT:
- // unimplemented - handled by default case
+ // should have been resolved by typechecking - handled by default case
case OPTRLIT:
p.op(OPTRLIT)
@@ -1204,16 +1216,12 @@ func (p *exporter) expr(n *Node) {
case OSTRUCTLIT:
p.op(OSTRUCTLIT)
- if !p.bool(n.Implicit) {
- p.typ(n.Type)
- }
+ p.typ(n.Type)
p.elemList(n.List) // special handling of field names
case OARRAYLIT, OMAPLIT:
- p.op(op)
- if !p.bool(n.Implicit) {
- p.typ(n.Type)
- }
+ p.op(OCOMPLIT)
+ p.typ(n.Type)
p.exprList(n.List)
case OKEY:
@@ -1226,9 +1234,6 @@ func (p *exporter) expr(n *Node) {
case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
p.op(OXDOT)
p.expr(n.Left)
- if n.Sym == nil {
- panic("unreachable") // can this happen during export?
- }
p.fieldSym(n.Sym, true)
case ODOTTYPE, ODOTTYPE2:
@@ -1334,7 +1339,8 @@ func (p *exporter) expr(n *Node) {
p.op(ODCLCONST)
default:
- Fatalf("exporter: CANNOT EXPORT: %s\nPlease notify gri@\n", n.Op)
+ Fatalf("cannot export %s (%d) node\n"+
+ "==> please file an issue and assign to gri@\n", n.Op, n.Op)
}
}
@@ -1410,9 +1416,8 @@ func (p *exporter) stmt(n *Node) {
p.op(ORETURN)
p.exprList(n.List)
- case ORETJMP:
- // generated by compiler for trampolin routines - not exported
- panic("unreachable")
+ // case ORETJMP:
+ // unreachable - generated by compiler for trampolin routines
case OPROC, ODEFER:
p.op(op)
@@ -1457,7 +1462,7 @@ func (p *exporter) stmt(n *Node) {
p.exprsOrNil(n.Left, nil)
case OEMPTY:
- // nothing to emit
+ // nothing to emit
case OLABEL:
p.op(OLABEL)
diff --git a/src/cmd/compile/internal/gc/bimport.go b/src/cmd/compile/internal/gc/bimport.go
index c4e6e5dd578afe..cb375a0ac3fd5b 100644
--- a/src/cmd/compile/internal/gc/bimport.go
+++ b/src/cmd/compile/internal/gc/bimport.go
@@ -233,7 +233,7 @@ func (p *importer) pkg() *Pkg {
// an empty path denotes the package we are currently importing;
// it must be the first package we see
if (path == "") != (len(p.pkgList) == 0) {
- panic(fmt.Sprintf("package path %q for pkg index %d", path, len(p.pkgList)))
+ Fatalf("importer: package path %q for pkg index %d", path, len(p.pkgList))
}
pkg := importpkg
@@ -821,12 +821,9 @@ func (p *importer) node() *Node {
// case OCLOSURE:
// unimplemented
- // case OCOMPLIT:
- // unimplemented
-
case OPTRLIT:
n := p.expr()
- if !p.bool() /* !implicit, i.e. '&' operator*/ {
+ if !p.bool() /* !implicit, i.e. '&' operator */ {
if n.Op == OCOMPLIT {
// Special case for &T{...}: turn into (*T){...}.
n.Right = Nod(OIND, n.Right, nil)
@@ -838,18 +835,15 @@ func (p *importer) node() *Node {
return n
case OSTRUCTLIT:
- n := Nod(OCOMPLIT, nil, nil)
- if !p.bool() {
- n.Right = typenod(p.typ())
- }
- n.List.Set(p.elemList())
+ n := Nod(OCOMPLIT, nil, typenod(p.typ()))
+ n.List.Set(p.elemList()) // special handling of field names
return n
- case OARRAYLIT, OMAPLIT:
- n := Nod(OCOMPLIT, nil, nil)
- if !p.bool() {
- n.Right = typenod(p.typ())
- }
+ // case OARRAYLIT, OMAPLIT:
+ // unreachable - mapped to case OCOMPLIT below by exporter
+
+ case OCOMPLIT:
+ n := Nod(OCOMPLIT, nil, typenod(p.typ()))
n.List.Set(p.exprList())
return n
@@ -1090,7 +1084,8 @@ func (p *importer) node() *Node {
return nil
default:
- Fatalf("importer: %s (%d) node not yet supported", op, op)
+ Fatalf("cannot import %s (%d) node\n"+
+ "==> please file an issue and assign to gri@\n", op, op)
panic("unreachable") // satisfy compiler
}
}
diff --git a/test/fixedbugs/issue15572.dir/a.go b/test/fixedbugs/issue15572.dir/a.go
new file mode 100644
index 00000000000000..13566014304714
--- /dev/null
+++ b/test/fixedbugs/issue15572.dir/a.go
@@ -0,0 +1,40 @@
+// Copyright 2016 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 a
+
+type T struct {
+}
+
+func F() []T {
+ return []T{T{}}
+}
+
+func Fi() []T {
+ return []T{{}} // element with implicit composite literal type
+}
+
+func Fp() []*T {
+ return []*T{&T{}}
+}
+
+func Fip() []*T {
+ return []*T{{}} // element with implicit composite literal type
+}
+
+func Gp() map[int]*T {
+ return map[int]*T{0: &T{}}
+}
+
+func Gip() map[int]*T {
+ return map[int]*T{0: {}} // element with implicit composite literal type
+}
+
+func Hp() map[*T]int {
+ return map[*T]int{&T{}: 0}
+}
+
+func Hip() map[*T]int {
+ return map[*T]int{{}: 0} // key with implicit composite literal type
+}
diff --git a/test/fixedbugs/issue15572.dir/b.go b/test/fixedbugs/issue15572.dir/b.go
new file mode 100644
index 00000000000000..355accc88057bd
--- /dev/null
+++ b/test/fixedbugs/issue15572.dir/b.go
@@ -0,0 +1,27 @@
+// Copyright 2016 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 b
+
+import "./a"
+
+func F() {
+ a.F()
+ a.Fi()
+}
+
+func Fp() {
+ a.Fp()
+ a.Fip()
+}
+
+func Gp() {
+ a.Gp()
+ a.Gip()
+}
+
+func Hp() {
+ a.Hp()
+ a.Hip()
+}
diff --git a/test/fixedbugs/issue15572.go b/test/fixedbugs/issue15572.go
new file mode 100644
index 00000000000000..cf77778f6640ff
--- /dev/null
+++ b/test/fixedbugs/issue15572.go
@@ -0,0 +1,11 @@
+// compiledir
+
+// Copyright 2016 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.
+
+// Test that exporting composite literals with implicit
+// types doesn't crash the typechecker when running over
+// inlined function bodies containing such literals.
+
+package ignored
From aeecee8ce4cf1821dcb6b5e37e20f40696278498 Mon Sep 17 00:00:00 2001
From: Dmitry Vyukov
Date: Mon, 9 May 2016 15:11:24 +0200
Subject: [PATCH 040/267] runtime/race: deflake test
The test sometimes fails on builders.
The test uses sleeps to establish the necessary goroutine
execution order. If sleeps undersleep/oversleep
the race is still reported, but it can be reported when the
main test goroutine returns. In such case test driver
can't match the race with the test and reports failure.
Wait for both test goroutines to ensure that the race
is reported in the test scope.
Fixes #15579
Change-Id: I0b9bec0ebfb0c127d83eb5325a7fe19ef9545050
Reviewed-on: https://go-review.googlesource.com/22951
Run-TryBot: Dmitry Vyukov
TryBot-Result: Gobot Gobot
Reviewed-by: Brad Fitzpatrick
---
src/runtime/race/testdata/chan_test.go | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/runtime/race/testdata/chan_test.go b/src/runtime/race/testdata/chan_test.go
index cddd9a6e782f2a..449191639e6180 100644
--- a/src/runtime/race/testdata/chan_test.go
+++ b/src/runtime/race/testdata/chan_test.go
@@ -285,17 +285,20 @@ func TestRaceChanWrongClose(t *testing.T) {
v1 := 0
v2 := 0
c := make(chan int, 1)
+ done := make(chan bool)
go func() {
defer func() {
recover()
}()
v1 = 1
c <- 1
+ done <- true
}()
go func() {
time.Sleep(1e7)
v2 = 2
close(c)
+ done <- true
}()
time.Sleep(2e7)
if _, who := <-c; who {
@@ -303,6 +306,8 @@ func TestRaceChanWrongClose(t *testing.T) {
} else {
v1 = 2
}
+ <-done
+ <-done
}
func TestRaceChanSendClose(t *testing.T) {
From feb6131b1a4c0da098821c516e06499add886182 Mon Sep 17 00:00:00 2001
From: Russ Cox
Date: Tue, 26 Apr 2016 21:50:59 -0400
Subject: [PATCH 041/267] cmd/compile: add -linkobj flag to allow writing
object file in two parts
This flag is experimental and the semantics may change
even after Go 1.7 is released. There are no changes to code
not using the flag.
The first part is for reading by future compiles.
The second part is for reading by the final link step.
Splitting the file this way allows distributed build systems
to ship the compile-input part only to compile steps and
the linker-input part only to linker steps.
The first part is basically just the export data,
and the second part is basically everything else.
The overall files still have the same broad structure,
so that existing tools will work with both halves.
It's just that various pieces are empty in the two halves.
This also copies the two bits of data the linker needed from
export data into the object header proper, so that the linker
doesn't need any export data at all. That eliminates a TODO
that was left for switching to the binary export data.
(Now the linker doesn't need to know about the switch.)
The default is still to write out a combined output file.
Nothing changes unless you pass -linkobj to the compiler.
There is no support in the go command for -linkobj,
since the go command doesn't copy objects around.
The expectation is that other build systems (like bazel, say)
might take advantage of this.
The header adjustment and the option for the split output
was intended as part of the zip archives, but the zip archives
have been cut from Go 1.7. Doing this to the current archives
both unblocks one step in the switch to binary export data
and enables alternate build systems to experiment with the
new flag using the Go 1.7 release.
Change-Id: I8b6eab25b8a22b0a266ba0ac6d31e594f3d117f3
Reviewed-on: https://go-review.googlesource.com/22500
Run-TryBot: Russ Cox
TryBot-Result: Gobot Gobot
Reviewed-by: Ian Lance Taylor
Reviewed-by: Robert Griesemer
---
src/cmd/compile/doc.go | 7 +-
src/cmd/compile/internal/gc/go.go | 1 +
src/cmd/compile/internal/gc/main.go | 3 +-
src/cmd/compile/internal/gc/obj.go | 62 ++++++++++-
src/cmd/link/internal/ld/go.go | 82 ++++-----------
src/debug/gosym/pclntab_test.go | 16 +++
test/linkobj.go | 155 ++++++++++++++++++++++++++++
7 files changed, 260 insertions(+), 66 deletions(-)
create mode 100644 test/linkobj.go
diff --git a/src/cmd/compile/doc.go b/src/cmd/compile/doc.go
index 2b45e5b998bc10..6783c2e846a3d5 100644
--- a/src/cmd/compile/doc.go
+++ b/src/cmd/compile/doc.go
@@ -61,7 +61,12 @@ Flags:
Look for packages in $GOROOT/pkg/$GOOS_$GOARCH_suffix
instead of $GOROOT/pkg/$GOOS_$GOARCH.
-largemodel
- Generated code that assumes a large memory model.
+ Generate code that assumes a large memory model.
+ -linkobj file
+ Write linker-specific object to file and compiler-specific
+ object to usual output file (as specified by -o).
+ Without this flag, the -o output is a combination of both
+ linker and compiler input.
-memprofile file
Write memory profile for the compilation to file.
-memprofilerate rate
diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go
index f9a372dccee63d..cbb79c02618a22 100644
--- a/src/cmd/compile/internal/gc/go.go
+++ b/src/cmd/compile/internal/gc/go.go
@@ -133,6 +133,7 @@ var pragcgobuf string
var infile string
var outfile string
+var linkobj string
var bout *bio.Writer
diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go
index 54211e4892ddef..713ff13d8547d8 100644
--- a/src/cmd/compile/internal/gc/main.go
+++ b/src/cmd/compile/internal/gc/main.go
@@ -178,6 +178,7 @@ func Main() {
flag.StringVar(&flag_installsuffix, "installsuffix", "", "set pkg directory `suffix`")
obj.Flagcount("j", "debug runtime-initialized variables", &Debug['j'])
obj.Flagcount("l", "disable inlining", &Debug['l'])
+ flag.StringVar(&linkobj, "linkobj", "", "write linker-specific object to `file`")
obj.Flagcount("live", "debug liveness analysis", &debuglive)
obj.Flagcount("m", "print optimization decisions", &Debug['m'])
flag.BoolVar(&flag_msan, "msan", false, "build code compatible with C/C++ memory sanitizer")
@@ -772,7 +773,7 @@ func importfile(f *Val, indent []byte) {
if p != "empty archive" {
if !strings.HasPrefix(p, "go object ") {
- Yyerror("import %s: not a go object file", file)
+ Yyerror("import %s: not a go object file: %s", file, p)
errorexit()
}
diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go
index ae23f9557410a3..b5c06d165d4c6d 100644
--- a/src/cmd/compile/internal/gc/obj.go
+++ b/src/cmd/compile/internal/gc/obj.go
@@ -22,7 +22,34 @@ func formathdr(arhdr []byte, name string, size int64) {
copy(arhdr[:], fmt.Sprintf("%-16s%-12d%-6d%-6d%-8o%-10d`\n", name, 0, 0, 0, 0644, size))
}
+// These modes say which kind of object file to generate.
+// The default use of the toolchain is to set both bits,
+// generating a combined compiler+linker object, one that
+// serves to describe the package to both the compiler and the linker.
+// In fact the compiler and linker read nearly disjoint sections of
+// that file, though, so in a distributed build setting it can be more
+// efficient to split the output into two files, supplying the compiler
+// object only to future compilations and the linker object only to
+// future links.
+//
+// By default a combined object is written, but if -linkobj is specified
+// on the command line then the default -o output is a compiler object
+// and the -linkobj output is a linker object.
+const (
+ modeCompilerObj = 1 << iota
+ modeLinkerObj
+)
+
func dumpobj() {
+ if linkobj == "" {
+ dumpobj1(outfile, modeCompilerObj|modeLinkerObj)
+ } else {
+ dumpobj1(outfile, modeCompilerObj)
+ dumpobj1(linkobj, modeLinkerObj)
+ }
+}
+
+func dumpobj1(outfile string, mode int) {
var err error
bout, err = bio.Create(outfile)
if err != nil {
@@ -40,8 +67,27 @@ func dumpobj() {
startobj = bout.Offset()
}
- fmt.Fprintf(bout, "go object %s %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring())
- dumpexport()
+ printheader := func() {
+ fmt.Fprintf(bout, "go object %s %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring())
+ if buildid != "" {
+ fmt.Fprintf(bout, "build id %q\n", buildid)
+ }
+ if localpkg.Name == "main" {
+ fmt.Fprintf(bout, "main\n")
+ }
+ if safemode {
+ fmt.Fprintf(bout, "safe\n")
+ } else {
+ fmt.Fprintf(bout, "----\n") // room for some other tool to write "safe"
+ }
+ fmt.Fprintf(bout, "\n") // header ends with blank line
+ }
+
+ printheader()
+
+ if mode&modeCompilerObj != 0 {
+ dumpexport()
+ }
if writearchive {
bout.Flush()
@@ -53,12 +99,20 @@ func dumpobj() {
formathdr(arhdr[:], "__.PKGDEF", size)
bout.Write(arhdr[:])
bout.Flush()
-
bout.Seek(startobj+size+(size&1), 0)
+ }
+
+ if mode&modeLinkerObj == 0 {
+ bout.Close()
+ return
+ }
+
+ if writearchive {
+ // start object file
arhdr = [ArhdrSize]byte{}
bout.Write(arhdr[:])
startobj = bout.Offset()
- fmt.Fprintf(bout, "go object %s %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring())
+ printheader()
}
if pragcgobuf != "" {
diff --git a/src/cmd/link/internal/ld/go.go b/src/cmd/link/internal/ld/go.go
index 425c75571fee81..79cdae0aee898c 100644
--- a/src/cmd/link/internal/ld/go.go
+++ b/src/cmd/link/internal/ld/go.go
@@ -59,71 +59,33 @@ func ldpkg(f *bio.Reader, pkg string, length int64, filename string, whence int)
}
data := string(bdata)
- // first \n$$ marks beginning of exports - skip rest of line
- p0 = strings.Index(data, "\n$$")
- if p0 < 0 {
- if Debug['u'] != 0 && whence != ArchiveObj {
- Exitf("cannot find export data in %s", filename)
- }
- return
- }
-
- // \n$$B marks the beginning of binary export data - don't skip over the B
- p0 += 3
- for p0 < len(data) && data[p0] != '\n' && data[p0] != 'B' {
- p0++
- }
-
- // second marks end of exports / beginning of local data
- p1 = strings.Index(data[p0:], "\n$$\n")
- if p1 < 0 && whence == Pkgdef {
- p1 = len(data) - p0
- }
- if p1 < 0 {
- fmt.Fprintf(os.Stderr, "%s: cannot find end of exports in %s\n", os.Args[0], filename)
- if Debug['u'] != 0 {
- errorexit()
- }
- return
- }
- p1 += p0
-
- for p0 < p1 && data[p0] != 'B' && (data[p0] == ' ' || data[p0] == '\t' || data[p0] == '\n') {
- p0++
- }
- // don't check this section if we have binary (B) export data
- // TODO fix this eventually
- if p0 < p1 && data[p0] != 'B' {
- if !strings.HasPrefix(data[p0:], "package ") {
- fmt.Fprintf(os.Stderr, "%s: bad package section in %s - %.20s\n", os.Args[0], filename, data[p0:])
- if Debug['u'] != 0 {
- errorexit()
- }
- return
+ // process header lines
+ isSafe := false
+ isMain := false
+ for data != "" {
+ var line string
+ if i := strings.Index(data, "\n"); i >= 0 {
+ line, data = data[:i], data[i+1:]
+ } else {
+ line, data = data, ""
}
-
- p0 += 8
- for p0 < p1 && (data[p0] == ' ' || data[p0] == '\t' || data[p0] == '\n') {
- p0++
+ if line == "safe" {
+ isSafe = true
}
- pname := p0
- for p0 < p1 && data[p0] != ' ' && data[p0] != '\t' && data[p0] != '\n' {
- p0++
+ if line == "main" {
+ isMain = true
}
- if Debug['u'] != 0 && whence != ArchiveObj && (p0+6 > p1 || !strings.HasPrefix(data[p0:], " safe\n")) {
- Exitf("load of unsafe package %s", filename)
+ if line == "" {
+ break
}
+ }
- name := data[pname:p0]
- for p0 < p1 && data[p0] != '\n' {
- p0++
+ if whence == Pkgdef || whence == FileObj {
+ if pkg == "main" && !isMain {
+ Exitf("%s: not package main", filename)
}
- if p0 < p1 {
- p0++
- }
-
- if pkg == "main" && name != "main" {
- Exitf("%s: not package main (package %s)", filename, name)
+ if Debug['u'] != 0 && whence != ArchiveObj && !isSafe {
+ Exitf("load of unsafe package %s", filename)
}
}
@@ -133,7 +95,7 @@ func ldpkg(f *bio.Reader, pkg string, length int64, filename string, whence int)
}
// look for cgo section
- p0 = strings.Index(data[p1:], "\n$$ // cgo")
+ p0 = strings.Index(data, "\n$$ // cgo")
if p0 >= 0 {
p0 += p1
i := strings.IndexByte(data[p0+1:], '\n')
diff --git a/src/debug/gosym/pclntab_test.go b/src/debug/gosym/pclntab_test.go
index 1a780bf121ac4c..9f82e31ae4170a 100644
--- a/src/debug/gosym/pclntab_test.go
+++ b/src/debug/gosym/pclntab_test.go
@@ -5,6 +5,7 @@
package gosym
import (
+ "bytes"
"debug/elf"
"internal/testenv"
"io/ioutil"
@@ -42,6 +43,21 @@ func dotest(t *testing.T) {
if err := cmd.Run(); err != nil {
t.Fatal(err)
}
+
+ // stamp .o file as being 'package main' so that go tool link will accept it
+ data, err := ioutil.ReadFile(pclinetestBinary + ".o")
+ if err != nil {
+ t.Fatal(err)
+ }
+ i := bytes.IndexByte(data, '\n')
+ if i < 0 {
+ t.Fatal("bad binary")
+ }
+ data = append(append(data[:i:i], "\nmain"...), data[i:]...)
+ if err := ioutil.WriteFile(pclinetestBinary+".o", data, 0666); err != nil {
+ t.Fatal(err)
+ }
+
cmd = exec.Command("go", "tool", "link", "-H", "linux",
"-o", pclinetestBinary, pclinetestBinary+".o")
cmd.Stdout = os.Stdout
diff --git a/test/linkobj.go b/test/linkobj.go
new file mode 100644
index 00000000000000..8a86aa872f0362
--- /dev/null
+++ b/test/linkobj.go
@@ -0,0 +1,155 @@
+// +build !nacl
+// run
+
+// Copyright 2016 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.
+
+// Test the compiler -linkobj flag.
+
+package main
+
+import (
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "strings"
+)
+
+var pwd, tmpdir string
+
+func main() {
+ dir, err := ioutil.TempDir("", "go-test-linkobj-")
+ if err != nil {
+ log.Fatal(err)
+ }
+ pwd, err = os.Getwd()
+ if err != nil {
+ log.Fatal(err)
+ }
+ if err := os.Chdir(dir); err != nil {
+ os.RemoveAll(dir)
+ log.Fatal(err)
+ }
+ tmpdir = dir
+
+ writeFile("p1.go", `
+ package p1
+
+ func F() {
+ println("hello from p1")
+ }
+ `)
+ writeFile("p2.go", `
+ package p2
+
+ import "./p1"
+
+ func F() {
+ p1.F()
+ println("hello from p2")
+ }
+
+ func main() {}
+ `)
+ writeFile("p3.go", `
+ package main
+
+ import "./p2"
+
+ func main() {
+ p2.F()
+ println("hello from main")
+ }
+ `)
+
+ // two rounds: once using normal objects, again using .a files (compile -pack).
+ for round := 0; round < 2; round++ {
+ pkg := "-pack=" + fmt.Sprint(round)
+
+ // The compiler expects the files being read to have the right suffix.
+ o := "o"
+ if round == 1 {
+ o = "a"
+ }
+
+ // inlining is disabled to make sure that the link objects contain needed code.
+ run("go", "tool", "compile", pkg, "-D", ".", "-I", ".", "-l", "-o", "p1."+o, "-linkobj", "p1.lo", "p1.go")
+ run("go", "tool", "compile", pkg, "-D", ".", "-I", ".", "-l", "-o", "p2."+o, "-linkobj", "p2.lo", "p2.go")
+ run("go", "tool", "compile", pkg, "-D", ".", "-I", ".", "-l", "-o", "p3."+o, "-linkobj", "p3.lo", "p3.go")
+
+ cp("p1."+o, "p1.oo")
+ cp("p2."+o, "p2.oo")
+ cp("p3."+o, "p3.oo")
+ cp("p1.lo", "p1."+o)
+ cp("p2.lo", "p2."+o)
+ cp("p3.lo", "p3."+o)
+ out := runFail("go", "tool", "link", "p2."+o)
+ if !strings.Contains(out, "not package main") {
+ fatalf("link p2.o failed but not for package main:\n%s", out)
+ }
+
+ run("go", "tool", "link", "-L", ".", "-o", "a.out.exe", "p3."+o)
+ out = run("./a.out.exe")
+ if !strings.Contains(out, "hello from p1\nhello from p2\nhello from main\n") {
+ fatalf("running main, incorrect output:\n%s", out)
+ }
+
+ // ensure that mistaken future round can't use these
+ os.Remove("p1.o")
+ os.Remove("a.out.exe")
+ }
+
+ cleanup()
+}
+
+func run(args ...string) string {
+ out, err := exec.Command(args[0], args[1:]...).CombinedOutput()
+ if err != nil {
+ fatalf("run %v: %s\n%s", args, err, out)
+ }
+ return string(out)
+}
+
+func runFail(args ...string) string {
+ out, err := exec.Command(args[0], args[1:]...).CombinedOutput()
+ if err == nil {
+ fatalf("runFail %v: unexpected success!\n%s", args, err, out)
+ }
+ return string(out)
+}
+
+func cp(src, dst string) {
+ data, err := ioutil.ReadFile(src)
+ if err != nil {
+ fatalf("%v", err)
+ }
+ err = ioutil.WriteFile(dst, data, 0666)
+ if err != nil {
+ fatalf("%v", err)
+ }
+}
+
+func writeFile(name, data string) {
+ err := ioutil.WriteFile(name, []byte(data), 0666)
+ if err != nil {
+ fatalf("%v", err)
+ }
+}
+
+func cleanup() {
+ const debug = false
+ if debug {
+ println("TMPDIR:", tmpdir)
+ return
+ }
+ os.Chdir(pwd) // get out of tmpdir before removing it
+ os.RemoveAll(tmpdir)
+}
+
+func fatalf(format string, args ...interface{}) {
+ cleanup()
+ log.Fatalf(format, args...)
+}
From 149ac34893ad1cc5023ae2fbabd0d553f21b0313 Mon Sep 17 00:00:00 2001
From: Mikhail Gusarov
Date: Mon, 9 May 2016 19:28:28 +0200
Subject: [PATCH 042/267] doc: update number of supported instruction sets
Current number was out-of-date since adding MIPS.
Change-Id: I565342a92de3893b75cdfb76fa39f7fdf15672da
Reviewed-on: https://go-review.googlesource.com/22952
Reviewed-by: Brad Fitzpatrick
---
doc/install-source.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/doc/install-source.html b/doc/install-source.html
index d9157c2b17c761..9a817676c17bd9 100644
--- a/doc/install-source.html
+++ b/doc/install-source.html
@@ -33,7 +33,7 @@ Introduction
-The Go compilers support five instruction sets.
+The Go compilers support six instruction sets.
There are important differences in the quality of the compilers for the different
architectures.
From 3c090019172afd4517360606efc50750d3e278fa Mon Sep 17 00:00:00 2001
From: David Chase
Date: Fri, 6 May 2016 17:05:02 -0700
Subject: [PATCH 043/267] cmd/compile: correct sparseSet probes in regalloc to
avoid index error
In regalloc, a sparse map is preallocated for later use by
spill-in-loop sinking. However, variables (spills) are added
during register allocation before spill sinking, and a map
query involving any of these new variables will index out of
bounds in the map.
To fix:
1) fix the queries to use s.orig[v.ID].ID instead, to ensure
proper indexing. Note that s.orig will be nil for values
that are not eligible for spilling (like memory and flags).
2) add a test.
Fixes #15585.
Change-Id: I8f2caa93b132a0f2a9161d2178320d5550583075
Reviewed-on: https://go-review.googlesource.com/22911
Reviewed-by: Keith Randall
Run-TryBot: David Chase
TryBot-Result: Gobot Gobot
---
src/cmd/compile/internal/ssa/regalloc.go | 15 +++++---
test/fixedbugs/issue15585.go | 45 ++++++++++++++++++++++++
2 files changed, 55 insertions(+), 5 deletions(-)
create mode 100644 test/fixedbugs/issue15585.go
diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go
index 1b12c6f300cee3..6c391aba2994bc 100644
--- a/src/cmd/compile/internal/ssa/regalloc.go
+++ b/src/cmd/compile/internal/ssa/regalloc.go
@@ -1311,20 +1311,25 @@ func (s *regAllocState) regalloc(f *Func) {
// Start with live at end.
for _, li := range s.live[ss.ID] {
if s.isLoopSpillCandidate(loop, s.orig[li.ID]) {
+ // s.live contains original IDs, use s.orig above to map back to *Value
entryCandidates.setBit(li.ID, uint(whichExit))
}
}
// Control can also be live.
- if ss.Control != nil && s.isLoopSpillCandidate(loop, ss.Control) {
- entryCandidates.setBit(ss.Control.ID, uint(whichExit))
+ if ss.Control != nil && s.orig[ss.Control.ID] != nil && s.isLoopSpillCandidate(loop, s.orig[ss.Control.ID]) {
+ entryCandidates.setBit(s.orig[ss.Control.ID].ID, uint(whichExit))
}
// Walk backwards, filling in locally live values, removing those defined.
for i := len(ss.Values) - 1; i >= 0; i-- {
v := ss.Values[i]
- entryCandidates.remove(v.ID) // Cannot be an issue, only keeps the sets smaller.
+ vorig := s.orig[v.ID]
+ if vorig != nil {
+ entryCandidates.remove(vorig.ID) // Cannot be an issue, only keeps the sets smaller.
+ }
for _, a := range v.Args {
- if s.isLoopSpillCandidate(loop, a) {
- entryCandidates.setBit(a.ID, uint(whichExit))
+ aorig := s.orig[a.ID]
+ if aorig != nil && s.isLoopSpillCandidate(loop, aorig) {
+ entryCandidates.setBit(aorig.ID, uint(whichExit))
}
}
}
diff --git a/test/fixedbugs/issue15585.go b/test/fixedbugs/issue15585.go
new file mode 100644
index 00000000000000..79eb13f90db45f
--- /dev/null
+++ b/test/fixedbugs/issue15585.go
@@ -0,0 +1,45 @@
+// compile
+
+// Copyright 2016 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 bug
+
+func example(n int) (rc int) {
+ var cc, ll, pp, rr [27]int
+ for q0 := 0; q0 < n-2; q0++ {
+ for q1 := q0 + 2; q1 < n; q1++ {
+ var c, d, l, p, r int
+ b0 := 1 << uint(q0)
+ b1 := 1 << uint(q1)
+ l = ((b0 << 1) | b1) << 1
+ c = b0 | b1 | (-1 << uint(n))
+ r = ((b0 >> 1) | b1) >> 1
+ E:
+ if c != -1 {
+ p = ^(l | c | r)
+ } else {
+ rc++
+ goto R
+ }
+ L:
+ if p != 0 {
+ lsb := p & -p
+ p &^= lsb
+ ll[d], cc[d], rr[d], pp[d] = l, c, r, p
+ l, c, r = (l|lsb)<<1, c|lsb, (r|lsb)>>1
+ d++
+ goto E
+ }
+ R:
+ d--
+ if d >= 0 {
+ l, c, r, p = ll[d], cc[d], rr[d], pp[d]
+ goto L
+ }
+ }
+ }
+ rc <<= 1
+ return
+}
From 5934523e75e2aa3725c4e709be56d9e84c472bfe Mon Sep 17 00:00:00 2001
From: Shenghou Ma
Date: Sun, 8 May 2016 22:31:09 -0400
Subject: [PATCH 044/267] cmd/compile: document -l in godoc
Fixes #15607.
Change-Id: I3e68ad00ebe72027d064238d4e77f1ad6a52f533
Reviewed-on: https://go-review.googlesource.com/22940
Reviewed-by: Brad Fitzpatrick
---
src/cmd/compile/doc.go | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/cmd/compile/doc.go b/src/cmd/compile/doc.go
index 6783c2e846a3d5..2e77f702e353f5 100644
--- a/src/cmd/compile/doc.go
+++ b/src/cmd/compile/doc.go
@@ -60,6 +60,8 @@ Flags:
-installsuffix suffix
Look for packages in $GOROOT/pkg/$GOOS_$GOARCH_suffix
instead of $GOROOT/pkg/$GOOS_$GOARCH.
+ -l
+ Disable inlining.
-largemodel
Generate code that assumes a large memory model.
-linkobj file
From 7ba54d45732219af86bde9a5b73c145db82b70c6 Mon Sep 17 00:00:00 2001
From: Joe Tsai
Date: Mon, 28 Mar 2016 02:29:18 -0700
Subject: [PATCH 045/267] compress: update documentation regarding footer
verification
Address two documentation issues:
1) Document that the GZIP and ZLIB footer is only verified when the
reader has been fully consumed.
2) The zlib reader is guaranteed to not read past the EOF if the
input io.Reader is also a io.ByteReader. This functionality was
documented in the flate and gzip packages but not on zlib.
Fixes #14867
Change-Id: I43d46b93e38f98a04901dc7d4f18ed2f9e09f6fb
Reviewed-on: https://go-review.googlesource.com/21218
Reviewed-by: Brad Fitzpatrick
---
src/compress/gzip/gunzip.go | 2 ++
src/compress/zlib/reader.go | 5 ++++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/compress/gzip/gunzip.go b/src/compress/gzip/gunzip.go
index 926bae88c70bda..7e640692f3f265 100644
--- a/src/compress/gzip/gunzip.go
+++ b/src/compress/gzip/gunzip.go
@@ -282,4 +282,6 @@ func (z *Reader) Read(p []byte) (n int, err error) {
}
// Close closes the Reader. It does not close the underlying io.Reader.
+// In order for the GZIP checksum to be verified, the reader must be
+// fully consumed until the io.EOF.
func (z *Reader) Close() error { return z.decompressor.Close() }
diff --git a/src/compress/zlib/reader.go b/src/compress/zlib/reader.go
index 30535fd980e55b..2efa1930354585 100644
--- a/src/compress/zlib/reader.go
+++ b/src/compress/zlib/reader.go
@@ -62,7 +62,8 @@ type Resetter interface {
// NewReader creates a new ReadCloser.
// Reads from the returned ReadCloser read and decompress data from r.
-// The implementation buffers input and may read more data than necessary from r.
+// If r does not implement io.ByteReader, the decompressor may read more
+// data than necessary from r.
// It is the caller's responsibility to call Close on the ReadCloser when done.
//
// The ReadCloser returned by NewReader also implements Resetter.
@@ -115,6 +116,8 @@ func (z *reader) Read(p []byte) (int, error) {
}
// Calling Close does not close the wrapped io.Reader originally passed to NewReader.
+// In order for the ZLIB checksum to be verified, the reader must be
+// fully consumed until the io.EOF.
func (z *reader) Close() error {
if z.err != nil && z.err != io.EOF {
return z.err
From 256a9670cc9a0acd1fd70ad53ba7ab032d5b2933 Mon Sep 17 00:00:00 2001
From: Austin Clements
Date: Mon, 9 May 2016 15:03:15 -0400
Subject: [PATCH 046/267] runtime: fix some out of date comments in bitmap code
Change-Id: I4613aa6d62baba01686bbab10738a7de23daae30
Reviewed-on: https://go-review.googlesource.com/22971
Reviewed-by: Rick Hudson
---
src/runtime/mbitmap.go | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/runtime/mbitmap.go b/src/runtime/mbitmap.go
index e01926e71a59a0..27f8e66d50ce1c 100644
--- a/src/runtime/mbitmap.go
+++ b/src/runtime/mbitmap.go
@@ -498,7 +498,6 @@ func (h heapBits) morePointers() bool {
}
// isPointer reports whether the heap bits describe a pointer word.
-// h must describe the initial word of the object.
//
// nosplit because it is used during write barriers and must not be preempted.
//go:nosplit
@@ -507,8 +506,7 @@ func (h heapBits) isPointer() bool {
}
// hasPointers reports whether the given object has any pointers.
-// It must be told how large the object at h is, so that it does not read too
-// far into the bitmap.
+// It must be told how large the object at h is for efficiency.
// h must describe the initial word of the object.
func (h heapBits) hasPointers(size uintptr) bool {
if size == sys.PtrSize { // 1-word objects are always pointers
From 561c94884477f568bdb68aacebfeb4d0411a874b Mon Sep 17 00:00:00 2001
From: Hana Kim
Date: Mon, 9 May 2016 15:14:07 -0400
Subject: [PATCH 047/267] os: skip Lchown test on Android if symlink doesn't
work
After upgrading builder device (android/arm) to android 5.0.2,
the test started failing. Running 'ln -s' from shell fails with
permission error.
Change-Id: I5b9e312806d58532b41ea3560ff079dabbc6424e
Reviewed-on: https://go-review.googlesource.com/22962
Reviewed-by: Brad Fitzpatrick
---
src/os/os_unix_test.go | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/os/os_unix_test.go b/src/os/os_unix_test.go
index c47f5462ab56c8..5c10154760cbe7 100644
--- a/src/os/os_unix_test.go
+++ b/src/os/os_unix_test.go
@@ -145,6 +145,9 @@ func TestLchown(t *testing.T) {
linkname := f.Name() + "2"
if err := Symlink(f.Name(), linkname); err != nil {
+ if runtime.GOOS == "android" && IsPermission(err) {
+ t.Skip("skipping test on Android; permission error creating symlink")
+ }
t.Fatalf("link %s -> %s: %v", f.Name(), linkname, err)
}
defer Remove(linkname)
From d88261fb6581106e4e7d8d6c63f0e33c2a24361e Mon Sep 17 00:00:00 2001
From: Brad Fitzpatrick
Date: Mon, 9 May 2016 17:21:11 +0000
Subject: [PATCH 048/267] time: don't depend on the io package
The time package has never depended on the io package until
a recent change during Go 1.7 to use the io.Seek* constants.
The go/build dependency check didn't catch this because "time" was
allowed to depend on meta package group "L0", which included "io".
Adding the "io" package broke one of Dmitry's tools. The tool is
fixable, but it's also not necessary for us to depend on "io" at all
for some constants. Mirror the constants instead, and change
deps_test.go to prevent an io dependency in the future.
Change-Id: I74325228565279a74fa4a2f419643f5710e3e09f
Reviewed-on: https://go-review.googlesource.com/22960
Run-TryBot: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
Reviewed-by: Ian Lance Taylor
---
src/go/build/deps_test.go | 14 +++++++++++++-
src/time/sys_plan9.go | 5 ++---
src/time/sys_unix.go | 5 ++---
src/time/sys_windows.go | 5 ++---
src/time/zoneinfo_read.go | 7 +++++++
5 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index 8a8c4be2174af0..d0d4fbba162967 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -136,7 +136,19 @@ var pkgDeps = map[string][]string{
"internal/syscall/unix": {"L0", "syscall"},
"internal/syscall/windows": {"L0", "syscall", "internal/syscall/windows/sysdll"},
"internal/syscall/windows/registry": {"L0", "syscall", "internal/syscall/windows/sysdll", "unicode/utf16"},
- "time": {"L0", "syscall", "internal/syscall/windows/registry"},
+ "time": {
+ // "L0" without the "io" package:
+ "errors",
+ "runtime",
+ "runtime/internal/atomic",
+ "sync",
+ "sync/atomic",
+ "unsafe",
+ // Other time dependencies:
+ "internal/syscall/windows/registry",
+ "syscall",
+ },
+
"os": {"L1", "os", "syscall", "time", "internal/syscall/windows"},
"path/filepath": {"L2", "os", "syscall"},
"io/ioutil": {"L2", "os", "path/filepath", "time"},
diff --git a/src/time/sys_plan9.go b/src/time/sys_plan9.go
index 507d1159cfe9d5..11365a791f7dfc 100644
--- a/src/time/sys_plan9.go
+++ b/src/time/sys_plan9.go
@@ -8,7 +8,6 @@ package time
import (
"errors"
- "io"
"syscall"
)
@@ -56,9 +55,9 @@ func closefd(fd uintptr) {
}
func preadn(fd uintptr, buf []byte, off int) error {
- whence := io.SeekStart
+ whence := seekStart
if off < 0 {
- whence = io.SeekEnd
+ whence = seekEnd
}
if _, err := syscall.Seek(int(fd), int64(off), whence); err != nil {
return err
diff --git a/src/time/sys_unix.go b/src/time/sys_unix.go
index dea03e06d51cf9..91d54c9ffd0a9e 100644
--- a/src/time/sys_unix.go
+++ b/src/time/sys_unix.go
@@ -8,7 +8,6 @@ package time
import (
"errors"
- "io"
"syscall"
)
@@ -56,9 +55,9 @@ func closefd(fd uintptr) {
}
func preadn(fd uintptr, buf []byte, off int) error {
- whence := io.SeekStart
+ whence := seekStart
if off < 0 {
- whence = io.SeekEnd
+ whence = seekEnd
}
if _, err := syscall.Seek(int(fd), int64(off), whence); err != nil {
return err
diff --git a/src/time/sys_windows.go b/src/time/sys_windows.go
index 4f41b1a7a3c64d..a4a068f78494c1 100644
--- a/src/time/sys_windows.go
+++ b/src/time/sys_windows.go
@@ -6,7 +6,6 @@ package time
import (
"errors"
- "io"
"syscall"
)
@@ -53,9 +52,9 @@ func closefd(fd uintptr) {
}
func preadn(fd uintptr, buf []byte, off int) error {
- whence := io.SeekStart
+ whence := seekStart
if off < 0 {
- whence = io.SeekEnd
+ whence = seekEnd
}
if _, err := syscall.Seek(syscall.Handle(fd), int64(off), whence); err != nil {
return err
diff --git a/src/time/zoneinfo_read.go b/src/time/zoneinfo_read.go
index 66777f6d736151..19cd40d8477297 100644
--- a/src/time/zoneinfo_read.go
+++ b/src/time/zoneinfo_read.go
@@ -11,6 +11,13 @@ package time
import "errors"
+// Copies of io.Seek* constants to avoid importing "io":
+const (
+ seekStart = 0
+ seekCurrent = 1
+ seekEnd = 2
+)
+
// Simple I/O interface to binary blob of data.
type data struct {
p []byte
From 9af83462c6f432b77a846a24b4d8efae9bdf0567 Mon Sep 17 00:00:00 2001
From: Tilman Dilo
Date: Mon, 9 May 2016 23:37:07 +0200
Subject: [PATCH 049/267] crypto/cipher: execute AES-GCM decryption example
The decryption example for AES-GCM was not executed, hiding the fact
that the provided ciphertext could not be authenticated.
This commit adds the required output comment, replaces the ciphertext
with a working example, and removes an unnecessary string conversion
along the way.
Change-Id: Ie6729ca76cf4a56c48b33fb3b39872105faa604b
Reviewed-on: https://go-review.googlesource.com/22953
Reviewed-by: Brad Fitzpatrick
Run-TryBot: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
---
src/crypto/cipher/example_test.go | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/crypto/cipher/example_test.go b/src/crypto/cipher/example_test.go
index f6cc38650610ad..9abe782bca54ae 100644
--- a/src/crypto/cipher/example_test.go
+++ b/src/crypto/cipher/example_test.go
@@ -44,9 +44,9 @@ func ExampleNewGCMDecrypter() {
// The key argument should be the AES key, either 16 or 32 bytes
// to select AES-128 or AES-256.
key := []byte("AES256Key-32Characters1234567890")
- ciphertext, _ := hex.DecodeString("f90fbef747e7212ad7410d0eee2d965de7e890471695cddd2a5bc0ef5da1d04ad8147b62141ad6e4914aee8c512f64fba9037603d41de0d50b718bd665f019cdcd")
+ ciphertext, _ := hex.DecodeString("1019aa66cd7c024f9efd0038899dae1973ee69427f5a6579eba292ffe1b5a260")
- nonce, _ := hex.DecodeString("bb8ef84243d2ee95a41c6c57")
+ nonce, _ := hex.DecodeString("37b8e8a308c354048d245f6d")
block, err := aes.NewCipher(key)
if err != nil {
@@ -63,7 +63,8 @@ func ExampleNewGCMDecrypter() {
panic(err.Error())
}
- fmt.Printf("%s\n", string(plaintext))
+ fmt.Printf("%s\n", plaintext)
+ // Output: exampleplaintext
}
func ExampleNewCBCDecrypter() {
From f05c3aa24d815cd3869153750c9875e35fc48a6e Mon Sep 17 00:00:00 2001
From: Caleb Spare
Date: Wed, 13 Apr 2016 16:51:25 -0700
Subject: [PATCH 050/267] encoding/json: support maps with integer keys
This change makes encoding and decoding support integer types in map
keys, converting to/from JSON string keys.
JSON object keys are still sorted lexically, even though the keys may be
integer strings.
For backwards-compatibility, the existing Text(Un)Marshaler support for
map keys (added in CL 20356) does not take precedence over the default
encoding for string types. There is no such concern for integer types,
so integer map key encoding is only used as a fallback if the map key
type is not a Text(Un)Marshaler.
Fixes #12529.
Change-Id: I7e68c34f9cd19704b1d233a9862da15fabf0908a
Reviewed-on: https://go-review.googlesource.com/22060
Reviewed-by: Brad Fitzpatrick
---
src/encoding/json/decode.go | 52 +++++++++++++-----
src/encoding/json/decode_test.go | 91 +++++++++++++++++++++++++++++++-
src/encoding/json/encode.go | 37 ++++++++++---
3 files changed, 158 insertions(+), 22 deletions(-)
diff --git a/src/encoding/json/decode.go b/src/encoding/json/decode.go
index 434edf8ea45096..2eda875bfdee8a 100644
--- a/src/encoding/json/decode.go
+++ b/src/encoding/json/decode.go
@@ -62,10 +62,10 @@ import (
// the additional Go array elements are set to zero values.
//
// To unmarshal a JSON object into a map, Unmarshal first establishes a map to
-// use, If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal
+// use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal
// reuses the existing map, keeping existing entries. Unmarshal then stores key-
-// value pairs from the JSON object into the map. The map's key type must
-// either be a string or implement encoding.TextUnmarshaler.
+// value pairs from the JSON object into the map. The map's key type must
+// either be a string, an integer, or implement encoding.TextUnmarshaler.
//
// If a JSON value is not appropriate for a given target type,
// or if a JSON number overflows the target type, Unmarshal
@@ -581,17 +581,24 @@ func (d *decodeState) object(v reflect.Value) {
// Check type of target:
// struct or
- // map[string]T or map[encoding.TextUnmarshaler]T
+ // map[T1]T2 where T1 is string, an integer type,
+ // or an encoding.TextUnmarshaler
switch v.Kind() {
case reflect.Map:
- // Map key must either have string kind or be an encoding.TextUnmarshaler.
+ // Map key must either have string kind, have an integer kind,
+ // or be an encoding.TextUnmarshaler.
t := v.Type()
- if t.Key().Kind() != reflect.String &&
- !reflect.PtrTo(t.Key()).Implements(textUnmarshalerType) {
- d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
- d.off--
- d.next() // skip over { } in input
- return
+ switch t.Key().Kind() {
+ case reflect.String,
+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ default:
+ if !reflect.PtrTo(t.Key()).Implements(textUnmarshalerType) {
+ d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
+ d.off--
+ d.next() // skip over { } in input
+ return
+ }
}
if v.IsNil() {
v.Set(reflect.MakeMap(t))
@@ -696,13 +703,32 @@ func (d *decodeState) object(v reflect.Value) {
var kv reflect.Value
switch {
case kt.Kind() == reflect.String:
- kv = reflect.ValueOf(key).Convert(v.Type().Key())
+ kv = reflect.ValueOf(key).Convert(kt)
case reflect.PtrTo(kt).Implements(textUnmarshalerType):
kv = reflect.New(v.Type().Key())
d.literalStore(item, kv, true)
kv = kv.Elem()
default:
- panic("json: Unexpected key type") // should never occur
+ switch kt.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ s := string(key)
+ n, err := strconv.ParseInt(s, 10, 64)
+ if err != nil || reflect.Zero(kt).OverflowInt(n) {
+ d.saveError(&UnmarshalTypeError{"number " + s, kt, int64(start + 1)})
+ return
+ }
+ kv = reflect.ValueOf(n).Convert(kt)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ s := string(key)
+ n, err := strconv.ParseUint(s, 10, 64)
+ if err != nil || reflect.Zero(kt).OverflowUint(n) {
+ d.saveError(&UnmarshalTypeError{"number " + s, kt, int64(start + 1)})
+ return
+ }
+ kv = reflect.ValueOf(n).Convert(kt)
+ default:
+ panic("json: Unexpected key type") // should never occur
+ }
}
v.SetMapIndex(kv, subv)
}
diff --git a/src/encoding/json/decode_test.go b/src/encoding/json/decode_test.go
index 30e46ca44f07bd..7c388c0c272ff6 100644
--- a/src/encoding/json/decode_test.go
+++ b/src/encoding/json/decode_test.go
@@ -10,8 +10,10 @@ import (
"errors"
"fmt"
"image"
+ "math"
"net"
"reflect"
+ "strconv"
"strings"
"testing"
"time"
@@ -53,6 +55,8 @@ type tx struct {
x int
}
+type u8 uint8
+
// A type that can unmarshal itself.
type unmarshaler struct {
@@ -92,6 +96,29 @@ type ustructText struct {
M unmarshalerText
}
+// u8marshal is an integer type that can marshal/unmarshal itself.
+type u8marshal uint8
+
+func (u8 u8marshal) MarshalText() ([]byte, error) {
+ return []byte(fmt.Sprintf("u%d", u8)), nil
+}
+
+var errMissingU8Prefix = errors.New("missing 'u' prefix")
+
+func (u8 *u8marshal) UnmarshalText(b []byte) error {
+ if !bytes.HasPrefix(b, []byte{'u'}) {
+ return errMissingU8Prefix
+ }
+ n, err := strconv.Atoi(string(b[1:]))
+ if err != nil {
+ return err
+ }
+ *u8 = u8marshal(n)
+ return nil
+}
+
+var _ encoding.TextUnmarshaler = (*u8marshal)(nil)
+
var (
um0, um1 unmarshaler // target2 of unmarshaling
ump = &um1
@@ -320,7 +347,69 @@ var unmarshalTests = []unmarshalTest{
{in: `["x:y"]`, ptr: &umslicepType, out: &umsliceXY},
{in: `{"M":"x:y"}`, ptr: umstructType, out: umstructXY},
- // Map keys can be encoding.TextUnmarshalers
+ // integer-keyed map test
+ {
+ in: `{"-1":"a","0":"b","1":"c"}`,
+ ptr: new(map[int]string),
+ out: map[int]string{-1: "a", 0: "b", 1: "c"},
+ },
+ {
+ in: `{"0":"a","10":"c","9":"b"}`,
+ ptr: new(map[u8]string),
+ out: map[u8]string{0: "a", 9: "b", 10: "c"},
+ },
+ {
+ in: `{"-9223372036854775808":"min","9223372036854775807":"max"}`,
+ ptr: new(map[int64]string),
+ out: map[int64]string{math.MinInt64: "min", math.MaxInt64: "max"},
+ },
+ {
+ in: `{"18446744073709551615":"max"}`,
+ ptr: new(map[uint64]string),
+ out: map[uint64]string{math.MaxUint64: "max"},
+ },
+ {
+ in: `{"0":false,"10":true}`,
+ ptr: new(map[uintptr]bool),
+ out: map[uintptr]bool{0: false, 10: true},
+ },
+
+ // Check that MarshalText and UnmarshalText take precedence
+ // over default integer handling in map keys.
+ {
+ in: `{"u2":4}`,
+ ptr: new(map[u8marshal]int),
+ out: map[u8marshal]int{2: 4},
+ },
+ {
+ in: `{"2":4}`,
+ ptr: new(map[u8marshal]int),
+ err: errMissingU8Prefix,
+ },
+
+ // integer-keyed map errors
+ {
+ in: `{"abc":"abc"}`,
+ ptr: new(map[int]string),
+ err: &UnmarshalTypeError{"number abc", reflect.TypeOf(0), 2},
+ },
+ {
+ in: `{"256":"abc"}`,
+ ptr: new(map[uint8]string),
+ err: &UnmarshalTypeError{"number 256", reflect.TypeOf(uint8(0)), 2},
+ },
+ {
+ in: `{"128":"abc"}`,
+ ptr: new(map[int8]string),
+ err: &UnmarshalTypeError{"number 128", reflect.TypeOf(int8(0)), 2},
+ },
+ {
+ in: `{"-1":"abc"}`,
+ ptr: new(map[uint8]string),
+ err: &UnmarshalTypeError{"number -1", reflect.TypeOf(uint8(0)), 2},
+ },
+
+ // Map keys can be encoding.TextUnmarshalers.
{in: `{"x:y":true}`, ptr: &ummapType, out: ummapXY},
// If multiple values for the same key exists, only the most recent value is used.
{in: `{"x:y":false,"x:y":true}`, ptr: &ummapType, out: ummapXY},
diff --git a/src/encoding/json/encode.go b/src/encoding/json/encode.go
index d8c779869b33f8..8b967471ce70fc 100644
--- a/src/encoding/json/encode.go
+++ b/src/encoding/json/encode.go
@@ -117,9 +117,13 @@ import (
// an anonymous struct field in both current and earlier versions, give the field
// a JSON tag of "-".
//
-// Map values encode as JSON objects. The map's key type must either be a string
-// or implement encoding.TextMarshaler. The map keys are used as JSON object
-// keys, subject to the UTF-8 coercion described for string values above.
+// Map values encode as JSON objects. The map's key type must either be a
+// string, an integer type, or implement encoding.TextMarshaler. The map keys
+// are used as JSON object keys by applying the following rules, subject to the
+// UTF-8 coercion described for string values above:
+// - string keys are used directly
+// - encoding.TextMarshalers are marshaled
+// - integer keys are converted to strings
//
// Pointer values encode as the value pointed to.
// A nil pointer encodes as the null JSON value.
@@ -644,8 +648,14 @@ func (me *mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
}
func newMapEncoder(t reflect.Type) encoderFunc {
- if t.Key().Kind() != reflect.String && !t.Key().Implements(textMarshalerType) {
- return unsupportedTypeEncoder
+ switch t.Key().Kind() {
+ case reflect.String,
+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ default:
+ if !t.Key().Implements(textMarshalerType) {
+ return unsupportedTypeEncoder
+ }
}
me := &mapEncoder{typeEncoder(t.Elem())}
return me.encode
@@ -806,9 +816,20 @@ func (w *reflectWithString) resolve() error {
w.s = w.v.String()
return nil
}
- buf, err := w.v.Interface().(encoding.TextMarshaler).MarshalText()
- w.s = string(buf)
- return err
+ if tm, ok := w.v.Interface().(encoding.TextMarshaler); ok {
+ buf, err := tm.MarshalText()
+ w.s = string(buf)
+ return err
+ }
+ switch w.v.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ w.s = strconv.FormatInt(w.v.Int(), 10)
+ return nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ w.s = strconv.FormatUint(w.v.Uint(), 10)
+ return nil
+ }
+ panic("unexpected map key type")
}
// byString is a slice of reflectWithString where the reflect.Value is either
From 3d82432288885696b01357e921ec00116291a790 Mon Sep 17 00:00:00 2001
From: David du Colombier <0intro@gmail.com>
Date: Tue, 19 Apr 2016 20:59:03 +0200
Subject: [PATCH 051/267] os: add TestReadAtOffset
In the Plan 9 kernel, there used to be a bug in the implementation of
the pread syscall, where the channel offset was erroneously updated after
calling pread on a file.
This test verifies that ReadAt is behaving as expected.
Fixes #14534.
Change-Id: Ifc9fd40a1f94879ee7eb09b2ffc369aa2bec2926
Reviewed-on: https://go-review.googlesource.com/22244
Run-TryBot: David du Colombier <0intro@gmail.com>
Reviewed-by: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
---
src/os/os_test.go | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/src/os/os_test.go b/src/os/os_test.go
index de25f26614d452..baa2f07fd2b0f3 100644
--- a/src/os/os_test.go
+++ b/src/os/os_test.go
@@ -1376,6 +1376,38 @@ func TestReadAt(t *testing.T) {
}
}
+// Verify that ReadAt doesn't affect seek offset.
+// In the Plan 9 kernel, there used to be a bug in the implementation of
+// the pread syscall, where the channel offset was erroneously updated after
+// calling pread on a file.
+func TestReadAtOffset(t *testing.T) {
+ f := newFile("TestReadAtOffset", t)
+ defer Remove(f.Name())
+ defer f.Close()
+
+ const data = "hello, world\n"
+ io.WriteString(f, data)
+
+ f.Seek(0, 0)
+ b := make([]byte, 5)
+
+ n, err := f.ReadAt(b, 7)
+ if err != nil || n != len(b) {
+ t.Fatalf("ReadAt 7: %d, %v", n, err)
+ }
+ if string(b) != "world" {
+ t.Fatalf("ReadAt 7: have %q want %q", string(b), "world")
+ }
+
+ n, err = f.Read(b)
+ if err != nil || n != len(b) {
+ t.Fatalf("Read: %d, %v", n, err)
+ }
+ if string(b) != "hello" {
+ t.Fatalf("Read: have %q want %q", string(b), "hello")
+ }
+}
+
func TestWriteAt(t *testing.T) {
f := newFile("TestWriteAt", t)
defer Remove(f.Name())
From a677724edfc465193d2f79ee48d2c06defbc916b Mon Sep 17 00:00:00 2001
From: David du Colombier <0intro@gmail.com>
Date: Mon, 18 Apr 2016 03:18:13 +0200
Subject: [PATCH 052/267] os: enable TestGetppid on Plan 9
Fixes #8206.
Change-Id: Iec1026ecc586495f5c9562cc84b3240c71d53da5
Reviewed-on: https://go-review.googlesource.com/22164
Run-TryBot: David du Colombier <0intro@gmail.com>
TryBot-Result: Gobot Gobot
Reviewed-by: Brad Fitzpatrick
---
src/os/os_test.go | 5 -----
1 file changed, 5 deletions(-)
diff --git a/src/os/os_test.go b/src/os/os_test.go
index baa2f07fd2b0f3..545bc1c8b0d25f 100644
--- a/src/os/os_test.go
+++ b/src/os/os_test.go
@@ -1705,11 +1705,6 @@ func TestKillStartProcess(t *testing.T) {
}
func TestGetppid(t *testing.T) {
- if runtime.GOOS == "plan9" {
- // TODO: golang.org/issue/8206
- t.Skipf("skipping test on plan9; see issue 8206")
- }
-
testenv.MustHaveExec(t)
if Getenv("GO_WANT_HELPER_PROCESS") == "1" {
From 42b647bde669ffa1d6f056eac20a683b9d02a786 Mon Sep 17 00:00:00 2001
From: David du Colombier <0intro@gmail.com>
Date: Tue, 10 May 2016 07:50:09 +0200
Subject: [PATCH 053/267] go/internal/gccgoimporter: remove workaround on Plan
9
We fixed the implementation of the pread syscall in
the Plan 9 kernel, so calling pread doesn't update the
channel offset when reading a file.
Fixes #11194.
Change-Id: Ie4019e445542a73479728af861a50bb54caea3f6
Reviewed-on: https://go-review.googlesource.com/22245
Reviewed-by: Minux Ma
Run-TryBot: David du Colombier <0intro@gmail.com>
TryBot-Result: Gobot Gobot
---
src/go/internal/gccgoimporter/importer.go | 6 ------
1 file changed, 6 deletions(-)
diff --git a/src/go/internal/gccgoimporter/importer.go b/src/go/internal/gccgoimporter/importer.go
index 65cc2df6860515..19b9c73568605f 100644
--- a/src/go/internal/gccgoimporter/importer.go
+++ b/src/go/internal/gccgoimporter/importer.go
@@ -88,12 +88,6 @@ func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err e
if err != nil {
return
}
- // reset to offset 0 - needed on Plan 9 (see issue #11265)
- // TODO: remove once issue #11265 has been resolved.
- _, err = f.Seek(0, io.SeekStart)
- if err != nil {
- return
- }
var elfreader io.ReaderAt
switch string(magic[:]) {
From 9edb27e76f297c034e9383ad2d1bf48b23e1a25b Mon Sep 17 00:00:00 2001
From: Emmanuel Odeke
Date: Tue, 10 May 2016 07:06:47 -0700
Subject: [PATCH 054/267] reflect: make Field panic when out of bounds, as
documented
Fixes #15046.
Change-Id: Iba7216297735be8e1ec550ce5336d17dcd3fd6b7
Reviewed-on: https://go-review.googlesource.com/22992
Reviewed-by: Brad Fitzpatrick
Run-TryBot: Brad Fitzpatrick
Reviewed-by: Ian Lance Taylor
TryBot-Result: Gobot Gobot
---
src/reflect/all_test.go | 35 +++++++++++++++++++++++++++++++++++
src/reflect/type.go | 2 +-
2 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index d4c3e4e588a89d..1a7952d7892d83 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -5221,6 +5221,41 @@ func TestLargeGCProg(t *testing.T) {
fv.Call([]Value{ValueOf([256]*byte{})})
}
+func fieldIndexRecover(t Type, i int) (recovered interface{}) {
+ defer func() {
+ recovered = recover()
+ }()
+
+ t.Field(i)
+ return
+}
+
+// Issue 15046.
+func TestTypeFieldOutOfRangePanic(t *testing.T) {
+ typ := TypeOf(struct{ X int }{10})
+ testIndices := [...]struct {
+ i int
+ mustPanic bool
+ }{
+ 0: {-2, true},
+ 1: {0, false},
+ 2: {1, true},
+ 3: {1 << 10, true},
+ }
+ for i, tt := range testIndices {
+ recoveredErr := fieldIndexRecover(typ, tt.i)
+ if tt.mustPanic {
+ if recoveredErr == nil {
+ t.Errorf("#%d: fieldIndex %d expected to panic", i, tt.i)
+ }
+ } else {
+ if recoveredErr != nil {
+ t.Errorf("#%d: got err=%v, expected no panic", i, recoveredErr)
+ }
+ }
+ }
+}
+
// Issue 9179.
func TestCallGC(t *testing.T) {
f := func(a, b, c, d, e string) {
diff --git a/src/reflect/type.go b/src/reflect/type.go
index 2ceb3d3f661726..b499d01a2c7346 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -1178,7 +1178,7 @@ func (tag StructTag) Lookup(key string) (value string, ok bool) {
// Field returns the i'th struct field.
func (t *structType) Field(i int) (f StructField) {
if i < 0 || i >= len(t.fields) {
- return
+ panic("reflect: Field index out of bounds")
}
p := &t.fields[i]
f.Type = toType(p.typ)
From 636670b8db9b72c80ec89da0a666be0d686269fd Mon Sep 17 00:00:00 2001
From: Scott Bell
Date: Sun, 8 May 2016 18:17:59 -0700
Subject: [PATCH 055/267] net: use contexts for cgo-based DNS resolution
Although calls to getaddrinfo can't be portably interrupted,
we still benefit from more granular resource management by
pushing the context downwards.
Fixes #15321
Change-Id: I5506195fc6493080410e3d46aaa3fe02018a24fe
Reviewed-on: https://go-review.googlesource.com/22961
Reviewed-by: Brad Fitzpatrick
Run-TryBot: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
---
src/net/cgo_stub.go | 12 ++--
src/net/cgo_unix.go | 136 +++++++++++++++++++++++++++++--------
src/net/cgo_unix_test.go | 61 ++++++++++++++++-
src/net/lookup_unix.go | 12 ++--
src/net/netgo_unix_test.go | 5 +-
5 files changed, 180 insertions(+), 46 deletions(-)
diff --git a/src/net/cgo_stub.go b/src/net/cgo_stub.go
index 52d1dfd3460e6c..51259722aec8e6 100644
--- a/src/net/cgo_stub.go
+++ b/src/net/cgo_stub.go
@@ -6,6 +6,8 @@
package net
+import "context"
+
func init() { netGo = true }
type addrinfoErrno int
@@ -14,22 +16,22 @@ func (eai addrinfoErrno) Error() string { return "" }
func (eai addrinfoErrno) Temporary() bool { return false }
func (eai addrinfoErrno) Timeout() bool { return false }
-func cgoLookupHost(name string) (addrs []string, err error, completed bool) {
+func cgoLookupHost(ctx context.Context, name string) (addrs []string, err error, completed bool) {
return nil, nil, false
}
-func cgoLookupPort(network, service string) (port int, err error, completed bool) {
+func cgoLookupPort(ctx context.Context, network, service string) (port int, err error, completed bool) {
return 0, nil, false
}
-func cgoLookupIP(name string) (addrs []IPAddr, err error, completed bool) {
+func cgoLookupIP(ctx context.Context, name string) (addrs []IPAddr, err error, completed bool) {
return nil, nil, false
}
-func cgoLookupCNAME(name string) (cname string, err error, completed bool) {
+func cgoLookupCNAME(ctx context.Context, name string) (cname string, err error, completed bool) {
return "", nil, false
}
-func cgoLookupPTR(addr string) (ptrs []string, err error, completed bool) {
+func cgoLookupPTR(ctx context.Context, addr string) (ptrs []string, err error, completed bool) {
return nil, nil, false
}
diff --git a/src/net/cgo_unix.go b/src/net/cgo_unix.go
index 59c40c8d8a7f0c..5a1eed843751a4 100644
--- a/src/net/cgo_unix.go
+++ b/src/net/cgo_unix.go
@@ -19,6 +19,7 @@ package net
import "C"
import (
+ "context"
"syscall"
"unsafe"
)
@@ -32,18 +33,31 @@ func (eai addrinfoErrno) Error() string { return C.GoString(C.gai_strerror(C.i
func (eai addrinfoErrno) Temporary() bool { return eai == C.EAI_AGAIN }
func (eai addrinfoErrno) Timeout() bool { return false }
-func cgoLookupHost(name string) (hosts []string, err error, completed bool) {
- addrs, err, completed := cgoLookupIP(name)
+type portLookupResult struct {
+ port int
+ err error
+}
+
+type ipLookupResult struct {
+ addrs []IPAddr
+ cname string
+ err error
+}
+
+type reverseLookupResult struct {
+ names []string
+ err error
+}
+
+func cgoLookupHost(ctx context.Context, name string) (hosts []string, err error, completed bool) {
+ addrs, err, completed := cgoLookupIP(ctx, name)
for _, addr := range addrs {
hosts = append(hosts, addr.String())
}
return
}
-func cgoLookupPort(network, service string) (port int, err error, completed bool) {
- acquireThread()
- defer releaseThread()
-
+func cgoLookupPort(ctx context.Context, network, service string) (port int, err error, completed bool) {
var hints C.struct_addrinfo
switch network {
case "": // no hints
@@ -64,11 +78,27 @@ func cgoLookupPort(network, service string) (port int, err error, completed bool
hints.ai_family = C.AF_INET6
}
}
+ if ctx.Done() == nil {
+ port, err := cgoLookupServicePort(&hints, network, service)
+ return port, err, true
+ }
+ result := make(chan portLookupResult, 1)
+ go cgoPortLookup(result, &hints, network, service)
+ select {
+ case r := <-result:
+ return r.port, r.err, true
+ case <-ctx.Done():
+ // Since there isn't a portable way to cancel the lookup,
+ // we just let it finish and write to the buffered channel.
+ return 0, mapErr(ctx.Err()), false
+ }
+}
+func cgoLookupServicePort(hints *C.struct_addrinfo, network, service string) (port int, err error) {
s := C.CString(service)
var res *C.struct_addrinfo
defer C.free(unsafe.Pointer(s))
- gerrno, err := C.getaddrinfo(nil, s, &hints, &res)
+ gerrno, err := C.getaddrinfo(nil, s, hints, &res)
if gerrno != 0 {
switch gerrno {
case C.EAI_SYSTEM:
@@ -78,7 +108,7 @@ func cgoLookupPort(network, service string) (port int, err error, completed bool
default:
err = addrinfoErrno(gerrno)
}
- return 0, &DNSError{Err: err.Error(), Name: network + "/" + service}, true
+ return 0, &DNSError{Err: err.Error(), Name: network + "/" + service}
}
defer C.freeaddrinfo(res)
@@ -87,17 +117,22 @@ func cgoLookupPort(network, service string) (port int, err error, completed bool
case C.AF_INET:
sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(r.ai_addr))
p := (*[2]byte)(unsafe.Pointer(&sa.Port))
- return int(p[0])<<8 | int(p[1]), nil, true
+ return int(p[0])<<8 | int(p[1]), nil
case C.AF_INET6:
sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(r.ai_addr))
p := (*[2]byte)(unsafe.Pointer(&sa.Port))
- return int(p[0])<<8 | int(p[1]), nil, true
+ return int(p[0])<<8 | int(p[1]), nil
}
}
- return 0, &DNSError{Err: "unknown port", Name: network + "/" + service}, true
+ return 0, &DNSError{Err: "unknown port", Name: network + "/" + service}
}
-func cgoLookupIPCNAME(name string) (addrs []IPAddr, cname string, err error, completed bool) {
+func cgoPortLookup(result chan<- portLookupResult, hints *C.struct_addrinfo, network, service string) {
+ port, err := cgoLookupServicePort(hints, network, service)
+ result <- portLookupResult{port, err}
+}
+
+func cgoLookupIPCNAME(name string) (addrs []IPAddr, cname string, err error) {
acquireThread()
defer releaseThread()
@@ -127,7 +162,7 @@ func cgoLookupIPCNAME(name string) (addrs []IPAddr, cname string, err error, com
default:
err = addrinfoErrno(gerrno)
}
- return nil, "", &DNSError{Err: err.Error(), Name: name}, true
+ return nil, "", &DNSError{Err: err.Error(), Name: name}
}
defer C.freeaddrinfo(res)
@@ -156,17 +191,42 @@ func cgoLookupIPCNAME(name string) (addrs []IPAddr, cname string, err error, com
addrs = append(addrs, addr)
}
}
- return addrs, cname, nil, true
+ return addrs, cname, nil
}
-func cgoLookupIP(name string) (addrs []IPAddr, err error, completed bool) {
- addrs, _, err, completed = cgoLookupIPCNAME(name)
- return
+func cgoIPLookup(result chan<- ipLookupResult, name string) {
+ addrs, cname, err := cgoLookupIPCNAME(name)
+ result <- ipLookupResult{addrs, cname, err}
}
-func cgoLookupCNAME(name string) (cname string, err error, completed bool) {
- _, cname, err, completed = cgoLookupIPCNAME(name)
- return
+func cgoLookupIP(ctx context.Context, name string) (addrs []IPAddr, err error, completed bool) {
+ if ctx.Done() == nil {
+ addrs, _, err = cgoLookupIPCNAME(name)
+ return addrs, err, true
+ }
+ result := make(chan ipLookupResult, 1)
+ go cgoIPLookup(result, name)
+ select {
+ case r := <-result:
+ return r.addrs, r.err, true
+ case <-ctx.Done():
+ return nil, mapErr(ctx.Err()), false
+ }
+}
+
+func cgoLookupCNAME(ctx context.Context, name string) (cname string, err error, completed bool) {
+ if ctx.Done() == nil {
+ _, cname, err = cgoLookupIPCNAME(name)
+ return cname, err, true
+ }
+ result := make(chan ipLookupResult, 1)
+ go cgoIPLookup(result, name)
+ select {
+ case r := <-result:
+ return r.cname, r.err, true
+ case <-ctx.Done():
+ return "", mapErr(ctx.Err()), false
+ }
}
// These are roughly enough for the following:
@@ -182,10 +242,7 @@ const (
maxNameinfoLen = 4096
)
-func cgoLookupPTR(addr string) ([]string, error, bool) {
- acquireThread()
- defer releaseThread()
-
+func cgoLookupPTR(ctx context.Context, addr string) (names []string, err error, completed bool) {
var zone string
ip := parseIPv4(addr)
if ip == nil {
@@ -198,9 +255,26 @@ func cgoLookupPTR(addr string) ([]string, error, bool) {
if sa == nil {
return nil, &DNSError{Err: "invalid address " + ip.String(), Name: addr}, true
}
- var err error
- var b []byte
+ if ctx.Done() == nil {
+ names, err := cgoLookupAddrPTR(addr, sa, salen)
+ return names, err, true
+ }
+ result := make(chan reverseLookupResult, 1)
+ go cgoReverseLookup(result, addr, sa, salen)
+ select {
+ case r := <-result:
+ return r.names, r.err, true
+ case <-ctx.Done():
+ return nil, mapErr(ctx.Err()), false
+ }
+}
+
+func cgoLookupAddrPTR(addr string, sa *C.struct_sockaddr, salen C.socklen_t) (names []string, err error) {
+ acquireThread()
+ defer releaseThread()
+
var gerrno int
+ var b []byte
for l := nameinfoLen; l <= maxNameinfoLen; l *= 2 {
b = make([]byte, l)
gerrno, err = cgoNameinfoPTR(b, sa, salen)
@@ -217,16 +291,20 @@ func cgoLookupPTR(addr string) ([]string, error, bool) {
default:
err = addrinfoErrno(gerrno)
}
- return nil, &DNSError{Err: err.Error(), Name: addr}, true
+ return nil, &DNSError{Err: err.Error(), Name: addr}
}
-
for i := 0; i < len(b); i++ {
if b[i] == 0 {
b = b[:i]
break
}
}
- return []string{absDomainName(b)}, nil, true
+ return []string{absDomainName(b)}, nil
+}
+
+func cgoReverseLookup(result chan<- reverseLookupResult, addr string, sa *C.struct_sockaddr, salen C.socklen_t) {
+ names, err := cgoLookupAddrPTR(addr, sa, salen)
+ result <- reverseLookupResult{names, err}
}
func cgoSockaddr(ip IP, zone string) (*C.struct_sockaddr, C.socklen_t) {
diff --git a/src/net/cgo_unix_test.go b/src/net/cgo_unix_test.go
index 5dc7b1a62d4663..e861c7aa1f90d8 100644
--- a/src/net/cgo_unix_test.go
+++ b/src/net/cgo_unix_test.go
@@ -13,15 +13,70 @@ import (
)
func TestCgoLookupIP(t *testing.T) {
- host := "localhost"
- _, err, ok := cgoLookupIP(host)
+ ctx := context.Background()
+ _, err, ok := cgoLookupIP(ctx, "localhost")
if !ok {
t.Errorf("cgoLookupIP must not be a placeholder")
}
if err != nil {
t.Error(err)
}
- if _, err := goLookupIP(context.Background(), host); err != nil {
+}
+
+func TestCgoLookupIPWithCancel(t *testing.T) {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+ _, err, ok := cgoLookupIP(ctx, "localhost")
+ if !ok {
+ t.Errorf("cgoLookupIP must not be a placeholder")
+ }
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+func TestCgoLookupPort(t *testing.T) {
+ ctx := context.Background()
+ _, err, ok := cgoLookupPort(ctx, "tcp", "smtp")
+ if !ok {
+ t.Errorf("cgoLookupPort must not be a placeholder")
+ }
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+func TestCgoLookupPortWithCancel(t *testing.T) {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+ _, err, ok := cgoLookupPort(ctx, "tcp", "smtp")
+ if !ok {
+ t.Errorf("cgoLookupPort must not be a placeholder")
+ }
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+func TestCgoLookupPTR(t *testing.T) {
+ ctx := context.Background()
+ _, err, ok := cgoLookupPTR(ctx, "127.0.0.1")
+ if !ok {
+ t.Errorf("cgoLookupPTR must not be a placeholder")
+ }
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+func TestCgoLookupPTRWithCancel(t *testing.T) {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+ _, err, ok := cgoLookupPTR(ctx, "127.0.0.1")
+ if !ok {
+ t.Errorf("cgoLookupPTR must not be a placeholder")
+ }
+ if err != nil {
t.Error(err)
}
}
diff --git a/src/net/lookup_unix.go b/src/net/lookup_unix.go
index 5461fe8a411e8d..15397e8105a92e 100644
--- a/src/net/lookup_unix.go
+++ b/src/net/lookup_unix.go
@@ -55,7 +55,7 @@ func lookupProtocol(_ context.Context, name string) (int, error) {
func lookupHost(ctx context.Context, host string) (addrs []string, err error) {
order := systemConf().hostLookupOrder(host)
if order == hostLookupCgo {
- if addrs, err, ok := cgoLookupHost(host); ok {
+ if addrs, err, ok := cgoLookupHost(ctx, host); ok {
return addrs, err
}
// cgo not available (or netgo); fall back to Go's DNS resolver
@@ -67,8 +67,7 @@ func lookupHost(ctx context.Context, host string) (addrs []string, err error) {
func lookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) {
order := systemConf().hostLookupOrder(host)
if order == hostLookupCgo {
- // TODO(bradfitz): push down ctx, or at least its deadline to start
- if addrs, err, ok := cgoLookupIP(host); ok {
+ if addrs, err, ok := cgoLookupIP(ctx, host); ok {
return addrs, err
}
// cgo not available (or netgo); fall back to Go's DNS resolver
@@ -84,7 +83,7 @@ func lookupPort(ctx context.Context, network, service string) (int, error) {
// files might be on a remote filesystem, though. This should
// probably race goroutines if ctx != context.Background().
if systemConf().canUseCgo() {
- if port, err, ok := cgoLookupPort(network, service); ok {
+ if port, err, ok := cgoLookupPort(ctx, network, service); ok {
return port, err
}
}
@@ -93,8 +92,7 @@ func lookupPort(ctx context.Context, network, service string) (int, error) {
func lookupCNAME(ctx context.Context, name string) (string, error) {
if systemConf().canUseCgo() {
- // TODO: use ctx. issue 15321. Or race goroutines.
- if cname, err, ok := cgoLookupCNAME(name); ok {
+ if cname, err, ok := cgoLookupCNAME(ctx, name); ok {
return cname, err
}
}
@@ -161,7 +159,7 @@ func lookupTXT(ctx context.Context, name string) ([]string, error) {
func lookupAddr(ctx context.Context, addr string) ([]string, error) {
if systemConf().canUseCgo() {
- if ptrs, err, ok := cgoLookupPTR(addr); ok {
+ if ptrs, err, ok := cgoLookupPTR(ctx, addr); ok {
return ptrs, err
}
}
diff --git a/src/net/netgo_unix_test.go b/src/net/netgo_unix_test.go
index 0a118874c25aef..5f1eb19e1240bd 100644
--- a/src/net/netgo_unix_test.go
+++ b/src/net/netgo_unix_test.go
@@ -14,14 +14,15 @@ import (
func TestGoLookupIP(t *testing.T) {
host := "localhost"
- _, err, ok := cgoLookupIP(host)
+ ctx := context.Background()
+ _, err, ok := cgoLookupIP(ctx, host)
if ok {
t.Errorf("cgoLookupIP must be a placeholder")
}
if err != nil {
t.Error(err)
}
- if _, err := goLookupIP(context.Background(), host); err != nil {
+ if _, err := goLookupIP(ctx, host); err != nil {
t.Error(err)
}
}
From 9e96ad851d9fb3feb7ee3f7b72213c5b7a9977aa Mon Sep 17 00:00:00 2001
From: Keith Randall
Date: Tue, 10 May 2016 09:10:43 -0700
Subject: [PATCH 056/267] test: add test for unlowered ITab
See #15604. This was a bug in a CL that has since been
rolled back. Adding a test to challenge the next attempter.
Change-Id: Ic43be254ea6eaab0071018cdc61d9b1c21f19cbf
Reviewed-on: https://go-review.googlesource.com/23000
Reviewed-by: Brad Fitzpatrick
Reviewed-by: Matthew Dempsky
---
test/fixedbugs/issue15604.go | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 test/fixedbugs/issue15604.go
diff --git a/test/fixedbugs/issue15604.go b/test/fixedbugs/issue15604.go
new file mode 100644
index 00000000000000..4dc0b0b0541308
--- /dev/null
+++ b/test/fixedbugs/issue15604.go
@@ -0,0 +1,17 @@
+// compile
+
+// Copyright 2016 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 bug
+
+import "os"
+
+func f(err error) {
+ var ok bool
+ if err, ok = err.(*os.PathError); ok {
+ if err == os.ErrNotExist {
+ }
+ }
+}
From 78ff74375930d5ae391beae562c91da40e5d92a4 Mon Sep 17 00:00:00 2001
From: Brad Fitzpatrick
Date: Tue, 10 May 2016 09:24:57 -0700
Subject: [PATCH 057/267] crypto/sha1: disable crashing AVX2 optimizations for
now
Updates #15617
Change-Id: I2104776f8e789d987b4f2f7f08f2ebe979b747a1
Reviewed-on: https://go-review.googlesource.com/23001
Run-TryBot: Brad Fitzpatrick
Reviewed-by: Dmitry Vyukov
Reviewed-by: Minux Ma
---
src/crypto/sha1/sha1block_amd64.go | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/crypto/sha1/sha1block_amd64.go b/src/crypto/sha1/sha1block_amd64.go
index 84f8a520197db2..a36f334b115d5b 100644
--- a/src/crypto/sha1/sha1block_amd64.go
+++ b/src/crypto/sha1/sha1block_amd64.go
@@ -12,7 +12,9 @@ func blockAVX2(dig *digest, p []byte)
func blockAMD64(dig *digest, p []byte)
func checkAVX2() bool
-var hasAVX2 = checkAVX2()
+// TODO(TocarIP): fix AVX2 crash (golang.org/issue/15617) and
+// then re-enable this:
+var hasAVX2 = false // checkAVX2()
func block(dig *digest, p []byte) {
if hasAVX2 && len(p) >= 256 {
From f77f22b2bf43f565ac0933c8e1068c387e4007c3 Mon Sep 17 00:00:00 2001
From: Brad Fitzpatrick
Date: Tue, 10 May 2016 09:46:39 -0700
Subject: [PATCH 058/267] net/http: update bundled x/net/http2
Updates x/net/http2 to git rev 96dbb961 for golang.org/cl/23002
Fixes #15366
Updates #15134 (server part remains)
Change-Id: I29336e624706f906b754da66381a620ae3293c6c
Reviewed-on: https://go-review.googlesource.com/23003
Reviewed-by: Andrew Gerrand
Run-TryBot: Andrew Gerrand
TryBot-Result: Gobot Gobot
---
src/net/http/clientserver_test.go | 11 ----
src/net/http/h2_bundle.go | 91 +++++++++++++++++++++++++------
2 files changed, 75 insertions(+), 27 deletions(-)
diff --git a/src/net/http/clientserver_test.go b/src/net/http/clientserver_test.go
index 9c3949fc3970f8..39c1eaa04afadb 100644
--- a/src/net/http/clientserver_test.go
+++ b/src/net/http/clientserver_test.go
@@ -229,11 +229,6 @@ func (tt h12Compare) normalizeRes(t *testing.T, res *Response, wantProto string)
}
slurp, err := ioutil.ReadAll(res.Body)
- // TODO(bradfitz): short-term hack. Fix the
- // http2 side of golang.org/issue/15366 once
- // the http1 part is submitted.
- res.Uncompressed = false
-
res.Body.Close()
res.Body = slurpResult{
ReadCloser: ioutil.NopCloser(bytes.NewReader(slurp)),
@@ -1176,12 +1171,6 @@ func TestH12_AutoGzipWithDumpResponse(t *testing.T) {
io.WriteString(w, "\x1f\x8b\b\x00\x00\x00\x00\x00\x00\x00s\xf3\xf7\a\x00\xab'\xd4\x1a\x03\x00\x00\x00")
},
EarlyCheckResponse: func(proto string, res *Response) {
- if proto == "HTTP/2.0" {
- // TODO(bradfitz): Fix the http2 side
- // of golang.org/issue/15366 once the
- // http1 part is submitted.
- return
- }
if !res.Uncompressed {
t.Errorf("%s: expected Uncompressed to be set", proto)
}
diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go
index 7cfe72a5dc8475..c2a2d37f6dfaa8 100644
--- a/src/net/http/h2_bundle.go
+++ b/src/net/http/h2_bundle.go
@@ -20,6 +20,7 @@ import (
"bufio"
"bytes"
"compress/gzip"
+ "context"
"crypto/tls"
"encoding/binary"
"errors"
@@ -1086,7 +1087,14 @@ func http2parseDataFrame(fh http2FrameHeader, payload []byte) (http2Frame, error
return f, nil
}
-var http2errStreamID = errors.New("invalid streamid")
+var (
+ http2errStreamID = errors.New("invalid stream ID")
+ http2errDepStreamID = errors.New("invalid dependent stream ID")
+)
+
+func http2validStreamIDOrZero(streamID uint32) bool {
+ return streamID&(1<<31) == 0
+}
func http2validStreamID(streamID uint32) bool {
return streamID != 0 && streamID&(1<<31) == 0
@@ -1452,8 +1460,8 @@ func (f *http2Framer) WriteHeaders(p http2HeadersFrameParam) error {
}
if !p.Priority.IsZero() {
v := p.Priority.StreamDep
- if !http2validStreamID(v) && !f.AllowIllegalWrites {
- return errors.New("invalid dependent stream id")
+ if !http2validStreamIDOrZero(v) && !f.AllowIllegalWrites {
+ return http2errDepStreamID
}
if p.Priority.Exclusive {
v |= 1 << 31
@@ -1521,6 +1529,9 @@ func (f *http2Framer) WritePriority(streamID uint32, p http2PriorityParam) error
if !http2validStreamID(streamID) && !f.AllowIllegalWrites {
return http2errStreamID
}
+ if !http2validStreamIDOrZero(p.StreamDep) {
+ return http2errDepStreamID
+ }
f.startWrite(http2FramePriority, 0, streamID)
v := p.StreamDep
if p.Exclusive {
@@ -1962,7 +1973,9 @@ func http2summarizeFrame(f http2Frame) string {
return buf.String()
}
-func http2requestCancel(req *Request) <-chan struct{} { return req.Cancel }
+func http2reqContext(r *Request) context.Context { return r.Context() }
+
+func http2setResponseUncompressed(res *Response) { res.Uncompressed = true }
var http2DebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1"
@@ -2476,7 +2489,7 @@ func http2mustUint31(v int32) uint32 {
}
// bodyAllowedForStatus reports whether a given response status code
-// permits a body. See RFC2616, section 4.4.
+// permits a body. See RFC 2616, section 4.4.
func http2bodyAllowedForStatus(status int) bool {
switch {
case status >= 100 && status <= 199:
@@ -3989,6 +4002,8 @@ func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error {
if f.Truncated {
handler = http2handleHeaderListTooLong
+ } else if err := http2checkValidHTTP2Request(req); err != nil {
+ handler = http2new400Handler(err)
}
go sc.runHandler(rw, req, handler)
@@ -4707,6 +4722,37 @@ func http2foreachHeaderElement(v string, fn func(string)) {
}
}
+// From http://httpwg.org/specs/rfc7540.html#rfc.section.8.1.2.2
+var http2connHeaders = []string{
+ "Connection",
+ "Keep-Alive",
+ "Proxy-Connection",
+ "Transfer-Encoding",
+ "Upgrade",
+}
+
+// checkValidHTTP2Request checks whether req is a valid HTTP/2 request,
+// per RFC 7540 Section 8.1.2.2.
+// The returned error is reported to users.
+func http2checkValidHTTP2Request(req *Request) error {
+ for _, h := range http2connHeaders {
+ if _, ok := req.Header[h]; ok {
+ return fmt.Errorf("request header %q is not valid in HTTP/2", h)
+ }
+ }
+ te := req.Header["Te"]
+ if len(te) > 0 && (len(te) > 1 || (te[0] != "trailers" && te[0] != "")) {
+ return errors.New(`request header "TE" may only be "trailers" in HTTP/2`)
+ }
+ return nil
+}
+
+func http2new400Handler(err error) HandlerFunc {
+ return func(w ResponseWriter, r *Request) {
+ Error(w, err.Error(), StatusBadRequest)
+ }
+}
+
const (
// transportDefaultConnFlow is how many connection-level flow control
// tokens we give the server at start-up, past the default 64k.
@@ -4875,18 +4921,22 @@ type http2clientStream struct {
}
// awaitRequestCancel runs in its own goroutine and waits for the user
-// to either cancel a RoundTrip request (using the provided
-// Request.Cancel channel), or for the request to be done (any way it
-// might be removed from the cc.streams map: peer reset, successful
-// completion, TCP connection breakage, etc)
-func (cs *http2clientStream) awaitRequestCancel(cancel <-chan struct{}) {
- if cancel == nil {
+// to cancel a RoundTrip request, its context to expire, or for the
+// request to be done (any way it might be removed from the cc.streams
+// map: peer reset, successful completion, TCP connection breakage,
+// etc)
+func (cs *http2clientStream) awaitRequestCancel(req *Request) {
+ ctx := http2reqContext(req)
+ if req.Cancel == nil && ctx.Done() == nil {
return
}
select {
- case <-cancel:
+ case <-req.Cancel:
cs.bufPipe.CloseWithError(http2errRequestCanceled)
cs.cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil)
+ case <-ctx.Done():
+ cs.bufPipe.CloseWithError(ctx.Err())
+ cs.cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil)
case <-cs.done:
}
}
@@ -5334,8 +5384,8 @@ func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) {
}
readLoopResCh := cs.resc
- requestCanceledCh := http2requestCancel(req)
bodyWritten := false
+ ctx := http2reqContext(req)
for {
select {
@@ -5360,7 +5410,15 @@ func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) {
cs.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel)
}
return nil, http2errTimeout
- case <-requestCanceledCh:
+ case <-ctx.Done():
+ cc.forgetStreamID(cs.ID)
+ if !hasBody || bodyWritten {
+ cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil)
+ } else {
+ cs.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel)
+ }
+ return nil, ctx.Err()
+ case <-req.Cancel:
cc.forgetStreamID(cs.ID)
if !hasBody || bodyWritten {
cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil)
@@ -5568,7 +5626,7 @@ func (cc *http2ClientConn) encodeHeaders(req *Request, addGzipHeader bool, trail
case "host", "content-length":
continue
- case "connection", "proxy-connection", "transfer-encoding", "upgrade":
+ case "connection", "proxy-connection", "transfer-encoding", "upgrade", "keep-alive":
continue
case "user-agent":
@@ -5892,13 +5950,14 @@ func (rl *http2clientConnReadLoop) handleResponse(cs *http2clientStream, f *http
cs.bufPipe = http2pipe{b: buf}
cs.bytesRemain = res.ContentLength
res.Body = http2transportResponseBody{cs}
- go cs.awaitRequestCancel(http2requestCancel(cs.req))
+ go cs.awaitRequestCancel(cs.req)
if cs.requestedGzip && res.Header.Get("Content-Encoding") == "gzip" {
res.Header.Del("Content-Encoding")
res.Header.Del("Content-Length")
res.ContentLength = -1
res.Body = &http2gzipReader{body: res.Body}
+ http2setResponseUncompressed(res)
}
return res, nil
}
From 81a89606ef7e1334a0a23dab2eaa295b381caebc Mon Sep 17 00:00:00 2001
From: Andrew Gerrand
Date: Tue, 10 May 2016 11:48:48 -0700
Subject: [PATCH 059/267] doc: remove mention of %HOME% from installation
instructions
Fixes #15598
Change-Id: I4cfb8799dab0e9e34cae2e61839911fd65e4cfa3
Reviewed-on: https://go-review.googlesource.com/23004
Reviewed-by: Brad Fitzpatrick
---
doc/install.html | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/doc/install.html b/doc/install.html
index 96a7672778bb69..0e6b86fdaf5d15 100644
--- a/doc/install.html
+++ b/doc/install.html
@@ -221,7 +221,7 @@ Test your installation
Create a directory to contain your workspace,
$HOME/work
-%HOME%\work
+C:\work
for example, and set the GOPATH
environment
variable to point to that location.
@@ -231,7 +231,7 @@ Test your installation
-C:\> set GOPATH=%HOME%\work
+C:\> set GOPATH=C:\work
From 9780bf2a9587b6aa0c92526cc1d6d6d1ed4c7210 Mon Sep 17 00:00:00 2001
From: Ian Lance Taylor
Date: Tue, 10 May 2016 14:27:32 -0700
Subject: [PATCH 060/267] os/user: don't create C function mygetgrouplist
Instead of exporting the C function mygetgrouplist as a global symbol to
conflict with other symbols of the same name, use trivial Go code and a
static C function.
Change-Id: I98dd667814d0a0ed8f7b1d4cfc6483d5a6965b26
Reviewed-on: https://go-review.googlesource.com/23008
Run-TryBot: Ian Lance Taylor
TryBot-Result: Gobot Gobot
Reviewed-by: Brad Fitzpatrick
---
...{getgrouplist_darwin.c => getgrouplist_darwin.go} | 11 +++++++++--
.../{getgrouplist_unix.c => getgrouplist_unix.go} | 12 ++++++++++--
src/os/user/listgroups_unix.go | 6 ++----
3 files changed, 21 insertions(+), 8 deletions(-)
rename src/os/user/{getgrouplist_darwin.c => getgrouplist_darwin.go} (64%)
rename src/os/user/{getgrouplist_unix.c => getgrouplist_unix.go} (56%)
diff --git a/src/os/user/getgrouplist_darwin.c b/src/os/user/getgrouplist_darwin.go
similarity index 64%
rename from src/os/user/getgrouplist_darwin.c
rename to src/os/user/getgrouplist_darwin.go
index 6ad561489829ea..54a2da3610434c 100644
--- a/src/os/user/getgrouplist_darwin.c
+++ b/src/os/user/getgrouplist_darwin.go
@@ -2,13 +2,14 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build cgo
+package user
+/*
#include
#include
#include
-int mygetgrouplist(const char* user, gid_t group, gid_t* groups, int* ngroups) {
+static int mygetgrouplist(const char* user, gid_t group, gid_t* groups, int* ngroups) {
int* buf = malloc(*ngroups * sizeof(int));
int rv = getgrouplist(user, (int) group, buf, ngroups);
int i;
@@ -20,3 +21,9 @@ int mygetgrouplist(const char* user, gid_t group, gid_t* groups, int* ngroups) {
free(buf);
return rv;
}
+*/
+import "C"
+
+func getGroupList(name *C.char, userGID C.gid_t, gids *C.gid_t, n *C.int) C.int {
+ return C.mygetgrouplist(name, userGID, gids, n)
+}
diff --git a/src/os/user/getgrouplist_unix.c b/src/os/user/getgrouplist_unix.go
similarity index 56%
rename from src/os/user/getgrouplist_unix.c
rename to src/os/user/getgrouplist_unix.go
index eb14f9ab8a0ac1..14da7c00a2b55d 100644
--- a/src/os/user/getgrouplist_unix.c
+++ b/src/os/user/getgrouplist_unix.go
@@ -2,13 +2,21 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build cgo
// +build dragonfly freebsd !android,linux netbsd openbsd
+package user
+
+/*
#include
#include
#include
-int mygetgrouplist(const char* user, gid_t group, gid_t* groups, int* ngroups) {
+static int mygetgrouplist(const char* user, gid_t group, gid_t* groups, int* ngroups) {
return getgrouplist(user, group, groups, ngroups);
}
+*/
+import "C"
+
+func getGroupList(name *C.char, userGID C.gid_t, gids *C.gid_t, n *C.int) C.int {
+ return C.mygetgrouplist(name, userGID, gids, n)
+}
diff --git a/src/os/user/listgroups_unix.go b/src/os/user/listgroups_unix.go
index f78baaac1e27f7..db952c64bffdb3 100644
--- a/src/os/user/listgroups_unix.go
+++ b/src/os/user/listgroups_unix.go
@@ -16,8 +16,6 @@ import (
#include
#include
#include
-
-extern int mygetgrouplist(const char* user, gid_t group, gid_t* groups, int* ngroups);
*/
import "C"
@@ -32,7 +30,7 @@ func listGroups(u *User) ([]string, error) {
n := C.int(256)
gidsC := make([]C.gid_t, n)
- rv := C.mygetgrouplist(nameC, userGID, &gidsC[0], &n)
+ rv := getGroupList(nameC, userGID, &gidsC[0], &n)
if rv == -1 {
// More than initial buffer, but now n contains the correct size.
const maxGroups = 2048
@@ -40,7 +38,7 @@ func listGroups(u *User) ([]string, error) {
return nil, fmt.Errorf("user: list groups for %s: member of more than %d groups", u.Username, maxGroups)
}
gidsC = make([]C.gid_t, n)
- rv := C.mygetgrouplist(nameC, userGID, &gidsC[0], &n)
+ rv := getGroupList(nameC, userGID, &gidsC[0], &n)
if rv == -1 {
return nil, fmt.Errorf("user: list groups for %s failed (changed groups?)", u.Username)
}
From 9628e6fd1d1afeedce7c4b45454e0bc5cbd0d5ff Mon Sep 17 00:00:00 2001
From: Brad Fitzpatrick
Date: Tue, 10 May 2016 15:32:00 -0700
Subject: [PATCH 061/267] runtime/testdata/testprogcgo: fix Windows C compiler
warning
Noticed and fix by Alex Brainman.
Tested in https://golang.org/cl/23005 (which makes all compiler
warnings fatal during development)
Fixes #15623
Change-Id: Ic19999fce8bb8640d963965cc328574efadd7855
Reviewed-on: https://go-review.googlesource.com/23010
Reviewed-by: Alex Brainman
---
src/runtime/testdata/testprogcgo/threadpanic_windows.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/runtime/testdata/testprogcgo/threadpanic_windows.c b/src/runtime/testdata/testprogcgo/threadpanic_windows.c
index 6f896634a6d946..ba66d0f5c9564f 100644
--- a/src/runtime/testdata/testprogcgo/threadpanic_windows.c
+++ b/src/runtime/testdata/testprogcgo/threadpanic_windows.c
@@ -8,7 +8,7 @@
void gopanic(void);
-static unsigned int
+static unsigned int __attribute__((__stdcall__))
die(void* x)
{
gopanic();
From b6712946c1b46eb629fb010e65e5b3735f94d171 Mon Sep 17 00:00:00 2001
From: Alex Brainman
Date: Thu, 7 Apr 2016 15:12:32 +1000
Subject: [PATCH 062/267] runtime: make mksyscall_windows.go flags do what they
say they do
The -systemdll and -xsys flags generate broken code in some situations
(see issue for details). Fix all that.
This CL only fixes bugs in existing code, but I have more changes comming:
golang.org/x/sys/windows is not the only package that uses mksyscall_windows.go.
golang.org/x/exp/shiny and github.com/derekparker/delve do too. I also have
few personal packages that use mksyscall_windows.go. None of those packages
are aware of new -xsys flag. I would like to change mksyscall_windows.go, so
external packages do not need to use -xsys flag. I would love to get rid of
-xsys flag altogether, but I don't see how it is possible. So I will, probably,
replace -xsys with a flag that means opposite to -xsys, and use new flag
everywhere in standard libraries. Flag name suggestions are welcome.
-systemdll flag makes users code more "secure". I would like to make -systemdll
behaviour a default for all mksyscall_windows.go users. We use that already in
standard library. If we think "secure" is important, we should encourage it in
all users code. If mksyscall_windows.go user insist on using old code, provide
-use_old_loaddll (need good name here) flag for that. So -systemdll flag will
be replaced with -use_old_loaddll.
Fixes #15167
Change-Id: I516369507867358ba1b66aabe00a17a7b477016e
Reviewed-on: https://go-review.googlesource.com/21645
Reviewed-by: Brad Fitzpatrick
---
src/syscall/mksyscall_windows.go | 47 ++++++++++++++++++++++----------
1 file changed, 32 insertions(+), 15 deletions(-)
diff --git a/src/syscall/mksyscall_windows.go b/src/syscall/mksyscall_windows.go
index a6cef6fca79e93..a0663073090faf 100644
--- a/src/syscall/mksyscall_windows.go
+++ b/src/syscall/mksyscall_windows.go
@@ -617,9 +617,6 @@ func ParseFiles(fs []string) (*Source, error) {
"unsafe",
},
}
- if *systemDLL {
- src.Import("internal/syscall/windows/sysdll")
- }
for _, file := range fs {
if err := src.ParseFile(file); err != nil {
return nil, err
@@ -691,8 +688,29 @@ func (src *Source) ParseFile(path string) error {
// Generate output source file from a source set src.
func (src *Source) Generate(w io.Writer) error {
- if *sysRepo && packageName != "windows" {
- src.Import("golang.org/x/sys/windows")
+ const (
+ pkgStd = iota // any package in std library
+ pkgXSysWindows // x/sys/windows package
+ pkgOther
+ )
+ var pkgtype int
+ switch {
+ case !*sysRepo:
+ pkgtype = pkgStd
+ case packageName == "windows":
+ // TODO: this needs better logic than just using package name
+ pkgtype = pkgXSysWindows
+ default:
+ pkgtype = pkgOther
+ }
+ if *systemDLL {
+ switch pkgtype {
+ case pkgStd:
+ src.Import("internal/syscall/windows/sysdll")
+ case pkgXSysWindows:
+ default:
+ src.Import("golang.org/x/sys/windows")
+ }
}
if packageName != "syscall" {
src.Import("syscall")
@@ -702,18 +720,17 @@ func (src *Source) Generate(w io.Writer) error {
"syscalldot": syscalldot,
"newlazydll": func(dll string) string {
arg := "\"" + dll + ".dll\""
- if *systemDLL {
- arg = "sysdll.Add(" + arg + ")"
- }
- if *sysRepo {
- if packageName == "windows" {
- return "NewLazySystemDLL(" + arg + ")"
- } else {
- return "windows.NewLazySystemDLL(" + arg + ")"
- }
- } else {
+ if !*systemDLL {
return syscalldot() + "NewLazyDLL(" + arg + ")"
}
+ switch pkgtype {
+ case pkgStd:
+ return syscalldot() + "NewLazyDLL(sysdll.Add(" + arg + "))"
+ case pkgXSysWindows:
+ return "NewLazySystemDLL(" + arg + ")"
+ default:
+ return "windows.NewLazySystemDLL(" + arg + ")"
+ }
},
}
t := template.Must(template.New("main").Funcs(funcMap).Parse(srcTemplate))
From d958dab095febfe542c6209b023d15f1d0de7128 Mon Sep 17 00:00:00 2001
From: Robert Griesemer
Date: Tue, 10 May 2016 17:06:19 -0700
Subject: [PATCH 063/267] go/importer: use correct path when checking if
package was already imported
The importer uses a global (shared) package map across multiple imports
to determine if a package was imported before. That package map is usually
indexed by package (import) path ('id' in this code). However, the binary
importer was using the incoming (possibly unclean) path.
Fixes #15517.
Change-Id: I0c32a708dfccf345e0353fbda20ad882121e437c
Reviewed-on: https://go-review.googlesource.com/23012
Run-TryBot: Robert Griesemer
TryBot-Result: Gobot Gobot
Reviewed-by: Matthew Dempsky
---
src/go/internal/gcimporter/bimport.go | 2 +-
src/go/internal/gcimporter/gcimporter.go | 2 +-
src/go/internal/gcimporter/gcimporter_test.go | 39 +++++++++++++++++++
src/go/internal/gcimporter/testdata/p.go | 13 +++++++
4 files changed, 54 insertions(+), 2 deletions(-)
create mode 100644 src/go/internal/gcimporter/testdata/p.go
diff --git a/src/go/internal/gcimporter/bimport.go b/src/go/internal/gcimporter/bimport.go
index 964bf5512e080c..341358287a1ffd 100644
--- a/src/go/internal/gcimporter/bimport.go
+++ b/src/go/internal/gcimporter/bimport.go
@@ -170,7 +170,7 @@ func (p *importer) declare(obj types.Object) {
// imported.
// (See also the comment in cmd/compile/internal/gc/bimport.go importer.obj,
// switch case importing functions).
- panic(fmt.Sprintf("%s already declared", alt.Name()))
+ panic(fmt.Sprintf("inconsistent import:\n\t%v\npreviously imported as:\n\t%v\n", alt, obj))
}
}
diff --git a/src/go/internal/gcimporter/gcimporter.go b/src/go/internal/gcimporter/gcimporter.go
index b2848c3023696a..2c6e676225fb14 100644
--- a/src/go/internal/gcimporter/gcimporter.go
+++ b/src/go/internal/gcimporter/gcimporter.go
@@ -163,7 +163,7 @@ func Import(packages map[string]*types.Package, path, srcDir string) (pkg *types
var data []byte
data, err = ioutil.ReadAll(buf)
if err == nil {
- _, pkg, err = BImportData(packages, data, path)
+ _, pkg, err = BImportData(packages, data, id)
return
}
default:
diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go
index 8b94f9a105a6c1..8de36c713c1453 100644
--- a/src/go/internal/gcimporter/gcimporter_test.go
+++ b/src/go/internal/gcimporter/gcimporter_test.go
@@ -361,3 +361,42 @@ func TestIssue13898(t *testing.T) {
t.Fatalf("found %v; want go/types", m.Pkg())
}
}
+
+func TestIssue15517(t *testing.T) {
+ skipSpecialPlatforms(t)
+
+ // This package only handles gc export data.
+ if runtime.Compiler != "gc" {
+ t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+ return
+ }
+
+ // On windows, we have to set the -D option for the compiler to avoid having a drive
+ // letter and an illegal ':' in the import path - just skip it (see also issue #3483).
+ if runtime.GOOS == "windows" {
+ t.Skip("avoid dealing with relative paths/drive letters on windows")
+ }
+
+ if f := compile(t, "testdata", "p.go"); f != "" {
+ defer os.Remove(f)
+ }
+
+ // Multiple imports of p must succeed without redeclaration errors.
+ // We use an import path that's not cleaned up so that the eventual
+ // file path for the package is different from the package path; this
+ // will expose the error if it is present.
+ //
+ // (Issue: Both the textual and the binary importer used the file path
+ // of the package to be imported as key into the shared packages map.
+ // However, the binary importer then used the package path to identify
+ // the imported package to mark it as complete; effectively marking the
+ // wrong package as complete. By using an "unclean" package path, the
+ // file and package path are different, exposing the problem if present.
+ // The same issue occurs with vendoring.)
+ imports := make(map[string]*types.Package)
+ for i := 0; i < 3; i++ {
+ if _, err := Import(imports, "./././testdata/p", "."); err != nil {
+ t.Fatal(err)
+ }
+ }
+}
diff --git a/src/go/internal/gcimporter/testdata/p.go b/src/go/internal/gcimporter/testdata/p.go
new file mode 100644
index 00000000000000..9e2e7057653725
--- /dev/null
+++ b/src/go/internal/gcimporter/testdata/p.go
@@ -0,0 +1,13 @@
+// Copyright 2016 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.
+
+// Input for TestIssue15517
+
+package p
+
+const C = 0
+
+var V int
+
+func F() {}
From 0efc16284bc4fd5b8b31d3f6b6763f98700c5664 Mon Sep 17 00:00:00 2001
From: Alex Brainman
Date: Wed, 11 May 2016 15:19:32 +1000
Subject: [PATCH 064/267] syscall: remove mksyscall_windows.go -xsys flag
Also run "go generate" in
internal/syscall/windows and internal/syscall/windows/registry
Updates #15167
Change-Id: I0109226962f81857fe11d308b869d561ea8ed9f9
Reviewed-on: https://go-review.googlesource.com/23021
Reviewed-by: Brad Fitzpatrick
Run-TryBot: Alex Brainman
TryBot-Result: Gobot Gobot
---
.../windows/registry/zsyscall_windows.go | 8 ++++--
.../syscall/windows/zsyscall_windows.go | 8 ++++--
src/syscall/mksyscall_windows.go | 28 +++++++++++++++++--
3 files changed, 35 insertions(+), 9 deletions(-)
diff --git a/src/internal/syscall/windows/registry/zsyscall_windows.go b/src/internal/syscall/windows/registry/zsyscall_windows.go
index 7e473d4e1de7b2..62affc0b50baf4 100644
--- a/src/internal/syscall/windows/registry/zsyscall_windows.go
+++ b/src/internal/syscall/windows/registry/zsyscall_windows.go
@@ -2,9 +2,11 @@
package registry
-import "unsafe"
-import "syscall"
-import "internal/syscall/windows/sysdll"
+import (
+ "internal/syscall/windows/sysdll"
+ "syscall"
+ "unsafe"
+)
var _ unsafe.Pointer
diff --git a/src/internal/syscall/windows/zsyscall_windows.go b/src/internal/syscall/windows/zsyscall_windows.go
index d599258976b81d..6929acfa7283f5 100644
--- a/src/internal/syscall/windows/zsyscall_windows.go
+++ b/src/internal/syscall/windows/zsyscall_windows.go
@@ -2,9 +2,11 @@
package windows
-import "unsafe"
-import "syscall"
-import "internal/syscall/windows/sysdll"
+import (
+ "internal/syscall/windows/sysdll"
+ "syscall"
+ "unsafe"
+)
var _ unsafe.Pointer
diff --git a/src/syscall/mksyscall_windows.go b/src/syscall/mksyscall_windows.go
index a0663073090faf..4ccbb04908c7a5 100644
--- a/src/syscall/mksyscall_windows.go
+++ b/src/syscall/mksyscall_windows.go
@@ -57,6 +57,8 @@ import (
"io/ioutil"
"log"
"os"
+ "path/filepath"
+ "runtime"
"sort"
"strconv"
"strings"
@@ -67,7 +69,6 @@ var (
filename = flag.String("output", "", "output file name (standard output if omitted)")
printTraceFlag = flag.Bool("trace", false, "generate print statement after every syscall")
systemDLL = flag.Bool("systemdll", false, "whether all DLLs should be loaded from the Windows system directory")
- sysRepo = flag.Bool("xsys", false, "whether this code is for the x/sys subrepo")
)
func trim(s string) string {
@@ -686,6 +687,23 @@ func (src *Source) ParseFile(path string) error {
return nil
}
+// IsStdRepo returns true if src is part of standard library.
+func (src *Source) IsStdRepo() (bool, error) {
+ if len(src.Files) == 0 {
+ return false, errors.New("no input files provided")
+ }
+ abspath, err := filepath.Abs(src.Files[0])
+ if err != nil {
+ return false, err
+ }
+ goroot := runtime.GOROOT()
+ if runtime.GOOS == "windows" {
+ abspath = strings.ToLower(abspath)
+ goroot = strings.ToLower(goroot)
+ }
+ return strings.HasPrefix(abspath, goroot), nil
+}
+
// Generate output source file from a source set src.
func (src *Source) Generate(w io.Writer) error {
const (
@@ -693,9 +711,13 @@ func (src *Source) Generate(w io.Writer) error {
pkgXSysWindows // x/sys/windows package
pkgOther
)
+ isStdRepo, err := src.IsStdRepo()
+ if err != nil {
+ return err
+ }
var pkgtype int
switch {
- case !*sysRepo:
+ case isStdRepo:
pkgtype = pkgStd
case packageName == "windows":
// TODO: this needs better logic than just using package name
@@ -734,7 +756,7 @@ func (src *Source) Generate(w io.Writer) error {
},
}
t := template.Must(template.New("main").Funcs(funcMap).Parse(srcTemplate))
- err := t.Execute(w, src)
+ err = t.Execute(w, src)
if err != nil {
return errors.New("Failed to execute template: " + err.Error())
}
From b4538d7aaa1a600dc1d3724f9aecb5c8039e1324 Mon Sep 17 00:00:00 2001
From: David du Colombier <0intro@gmail.com>
Date: Tue, 10 May 2016 07:43:17 +0000
Subject: [PATCH 065/267] Revert "os: enable TestGetppid on Plan 9"
This reverts commit a677724edfc465193d2f79ee48d2c06defbc916b.
Change-Id: I6a54ac26a6deca5b2a39ec9f899469a88b543d3d
Reviewed-on: https://go-review.googlesource.com/22980
Reviewed-by: Brad Fitzpatrick
---
src/os/os_test.go | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/os/os_test.go b/src/os/os_test.go
index 545bc1c8b0d25f..baa2f07fd2b0f3 100644
--- a/src/os/os_test.go
+++ b/src/os/os_test.go
@@ -1705,6 +1705,11 @@ func TestKillStartProcess(t *testing.T) {
}
func TestGetppid(t *testing.T) {
+ if runtime.GOOS == "plan9" {
+ // TODO: golang.org/issue/8206
+ t.Skipf("skipping test on plan9; see issue 8206")
+ }
+
testenv.MustHaveExec(t)
if Getenv("GO_WANT_HELPER_PROCESS") == "1" {
From d1981ac313f6858cf1ec163dac94ea0d6904a731 Mon Sep 17 00:00:00 2001
From: Mikio Hara
Date: Tue, 10 May 2016 04:29:32 +0900
Subject: [PATCH 066/267] net: reorganize interface tests to avoid vague
flakiness
This change reorganizes test cases for surveying network interfaces and
address prefixes to make sure which part of the functionality is broken.
Updates #7849.
Change-Id: If6918075802eef69a7f1ee040010b3c46f4f4b97
Reviewed-on: https://go-review.googlesource.com/22990
Reviewed-by: Brad Fitzpatrick
---
src/net/interface_test.go | 292 +++++++++++++++++++++-----------------
1 file changed, 165 insertions(+), 127 deletions(-)
diff --git a/src/net/interface_test.go b/src/net/interface_test.go
index e1580134937de0..2603311d24ba29 100644
--- a/src/net/interface_test.go
+++ b/src/net/interface_test.go
@@ -5,6 +5,7 @@
package net
import (
+ "fmt"
"internal/testenv"
"reflect"
"runtime"
@@ -48,24 +49,16 @@ func ipv6LinkLocalUnicastAddr(ifi *Interface) string {
return ""
}
-type routeStats struct {
- loop int // # of active loopback interfaces
- other int // # of active other interfaces
-
- uni4, uni6 int // # of active connected unicast, anycast routes
- multi4, multi6 int // # of active connected multicast route clones
-}
-
func TestInterfaces(t *testing.T) {
if runtime.GOOS == "freebsd" && runtime.GOARCH == "arm" {
- // 100% flaky, actually, at least on some FreeBSD versions
- testenv.SkipFlaky(t, 15262)
+ // 100% flaky on FreeBSD 11-CURRENT and above.
+ testenv.SkipFlaky(t, 7849)
}
+
ift, err := Interfaces()
if err != nil {
t.Fatal(err)
}
- var stats routeStats
for _, ifi := range ift {
ifxi, err := InterfaceByIndex(ifi.Index)
if err != nil {
@@ -81,196 +74,241 @@ func TestInterfaces(t *testing.T) {
if !reflect.DeepEqual(ifxn, &ifi) {
t.Errorf("got %v; want %v", ifxn, ifi)
}
- t.Logf("%q: flags %q, ifindex %v, mtu %v", ifi.Name, ifi.Flags.String(), ifi.Index, ifi.MTU)
- t.Logf("hardware address %q", ifi.HardwareAddr.String())
- if ifi.Flags&FlagUp != 0 {
- if ifi.Flags&FlagLoopback != 0 {
- stats.loop++
- } else {
- stats.other++
- }
- }
- n4, n6 := testInterfaceAddrs(t, &ifi)
- stats.uni4 += n4
- stats.uni6 += n6
- n4, n6 = testInterfaceMulticastAddrs(t, &ifi)
- stats.multi4 += n4
- stats.multi6 += n6
- }
- switch runtime.GOOS {
- case "nacl", "plan9", "solaris":
- default:
- // Test the existence of connected unicast routes for
- // IPv4.
- if supportsIPv4 && stats.loop+stats.other > 0 && stats.uni4 == 0 {
- t.Errorf("num IPv4 unicast routes = 0; want >0; summary: %+v", stats)
- }
- // Test the existence of connected unicast routes for
- // IPv6. We can assume the existence of ::1/128 when
- // at least one loopback interface is installed.
- if supportsIPv6 && stats.loop > 0 && stats.uni6 == 0 {
- t.Errorf("num IPv6 unicast routes = 0; want >0; summary: %+v", stats)
- }
- }
- switch runtime.GOOS {
- case "dragonfly", "nacl", "netbsd", "openbsd", "plan9", "solaris":
- default:
- // Test the existence of connected multicast route
- // clones for IPv4. Unlike IPv6, IPv4 multicast
- // capability is not a mandatory feature, and so this
- // test is disabled.
- //if supportsIPv4 && stats.loop > 0 && stats.uni4 > 1 && stats.multi4 == 0 {
- // t.Errorf("num IPv4 multicast route clones = 0; want >0; summary: %+v", stats)
- //}
- // Test the existence of connected multicast route
- // clones for IPv6. Some platform never uses loopback
- // interface as the nexthop for multicast routing.
- // We can assume the existence of connected multicast
- // route clones when at least two connected unicast
- // routes, ::1/128 and other, are installed.
- if supportsIPv6 && stats.loop > 0 && stats.uni6 > 1 && stats.multi6 == 0 {
- t.Errorf("num IPv6 multicast route clones = 0; want >0; summary: %+v", stats)
- }
+ t.Logf("%s: flags=%v index=%d mtu=%d hwaddr=%v", ifi.Name, ifi.Flags, ifi.Index, ifi.MTU, ifi.HardwareAddr)
}
}
func TestInterfaceAddrs(t *testing.T) {
+ if runtime.GOOS == "freebsd" && runtime.GOARCH == "arm" {
+ // 100% flaky on FreeBSD 11-CURRENT and above.
+ testenv.SkipFlaky(t, 7849)
+ }
+
ift, err := Interfaces()
if err != nil {
t.Fatal(err)
}
- var stats routeStats
- for _, ifi := range ift {
- if ifi.Flags&FlagUp != 0 {
- if ifi.Flags&FlagLoopback != 0 {
- stats.loop++
- } else {
- stats.other++
- }
- }
- }
+ ifStats := interfaceStats(ift)
ifat, err := InterfaceAddrs()
if err != nil {
t.Fatal(err)
}
- stats.uni4, stats.uni6 = testAddrs(t, ifat)
- // Test the existence of connected unicast routes for IPv4.
- if supportsIPv4 && stats.loop+stats.other > 0 && stats.uni4 == 0 {
- t.Errorf("num IPv4 unicast routes = 0; want >0; summary: %+v", stats)
+ uniStats, err := validateInterfaceUnicastAddrs(ifat)
+ if err != nil {
+ t.Fatal(err)
}
- // Test the existence of connected unicast routes for IPv6.
- // We can assume the existence of ::1/128 when at least one
- // loopback interface is installed.
- if supportsIPv6 && stats.loop > 0 && stats.uni6 == 0 {
- t.Errorf("num IPv6 unicast routes = 0; want >0; summary: %+v", stats)
+ if err := checkUnicastStats(ifStats, uniStats); err != nil {
+ t.Fatal(err)
}
}
-func testInterfaceAddrs(t *testing.T, ifi *Interface) (naf4, naf6 int) {
- ifat, err := ifi.Addrs()
+func TestInterfaceUnicastAddrs(t *testing.T) {
+ if runtime.GOOS == "freebsd" && runtime.GOARCH == "arm" {
+ // 100% flaky on FreeBSD 11-CURRENT and above.
+ testenv.SkipFlaky(t, 7849)
+ }
+
+ ift, err := Interfaces()
+ if err != nil {
+ t.Fatal(err)
+ }
+ ifStats := interfaceStats(ift)
if err != nil {
t.Fatal(err)
}
- return testAddrs(t, ifat)
+ var uniStats routeStats
+ for _, ifi := range ift {
+ ifat, err := ifi.Addrs()
+ if err != nil {
+ t.Fatal(ifi, err)
+ }
+ stats, err := validateInterfaceUnicastAddrs(ifat)
+ if err != nil {
+ t.Fatal(ifi, err)
+ }
+ uniStats.ipv4 += stats.ipv4
+ uniStats.ipv6 += stats.ipv6
+ }
+ if err := checkUnicastStats(ifStats, &uniStats); err != nil {
+ t.Fatal(err)
+ }
}
-func testInterfaceMulticastAddrs(t *testing.T, ifi *Interface) (nmaf4, nmaf6 int) {
- ifmat, err := ifi.MulticastAddrs()
+func TestInterfaceMulticastAddrs(t *testing.T) {
+ if runtime.GOOS == "freebsd" && runtime.GOARCH == "arm" {
+ // 100% flaky on FreeBSD 11-CURRENT and above.
+ testenv.SkipFlaky(t, 7849)
+ }
+
+ ift, err := Interfaces()
if err != nil {
t.Fatal(err)
}
- return testMulticastAddrs(t, ifmat)
+ ifStats := interfaceStats(ift)
+ ifat, err := InterfaceAddrs()
+ if err != nil {
+ t.Fatal(err)
+ }
+ uniStats, err := validateInterfaceUnicastAddrs(ifat)
+ if err != nil {
+ t.Fatal(err)
+ }
+ var multiStats routeStats
+ for _, ifi := range ift {
+ ifmat, err := ifi.MulticastAddrs()
+ if err != nil {
+ t.Fatal(ifi, err)
+ }
+ stats, err := validateInterfaceMulticastAddrs(ifmat)
+ if err != nil {
+ t.Fatal(ifi, err)
+ }
+ multiStats.ipv4 += stats.ipv4
+ multiStats.ipv6 += stats.ipv6
+ }
+ if err := checkMulticastStats(ifStats, uniStats, &multiStats); err != nil {
+ t.Fatal(err)
+ }
+}
+
+type ifStats struct {
+ loop int // # of active loopback interfaces
+ other int // # of active other interfaces
+}
+
+func interfaceStats(ift []Interface) *ifStats {
+ var stats ifStats
+ for _, ifi := range ift {
+ if ifi.Flags&FlagUp != 0 {
+ if ifi.Flags&FlagLoopback != 0 {
+ stats.loop++
+ } else {
+ stats.other++
+ }
+ }
+ }
+ return &stats
}
-func testAddrs(t *testing.T, ifat []Addr) (naf4, naf6 int) {
+type routeStats struct {
+ ipv4, ipv6 int // # of active connected unicast, anycast or multicast routes
+}
+
+func validateInterfaceUnicastAddrs(ifat []Addr) (*routeStats, error) {
// Note: BSD variants allow assigning any IPv4/IPv6 address
// prefix to IP interface. For example,
// - 0.0.0.0/0 through 255.255.255.255/32
// - ::/0 through ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128
// In other words, there is no tightly-coupled combination of
// interface address prefixes and connected routes.
+ stats := new(routeStats)
for _, ifa := range ifat {
switch ifa := ifa.(type) {
case *IPNet:
if ifa == nil || ifa.IP == nil || ifa.IP.IsMulticast() || ifa.Mask == nil {
- t.Errorf("unexpected value: %#v", ifa)
- continue
+ return nil, fmt.Errorf("unexpected value: %#v", ifa)
}
if len(ifa.IP) != IPv6len {
- t.Errorf("should be internal representation either IPv6 or IPv6 IPv4-mapped address: %#v", ifa)
- continue
+ return nil, fmt.Errorf("should be internal representation either IPv6 or IPv4-mapped IPv6 address: %#v", ifa)
}
prefixLen, maxPrefixLen := ifa.Mask.Size()
if ifa.IP.To4() != nil {
if 0 >= prefixLen || prefixLen > 8*IPv4len || maxPrefixLen != 8*IPv4len {
- t.Errorf("unexpected prefix length: %d/%d", prefixLen, maxPrefixLen)
- continue
+ return nil, fmt.Errorf("unexpected prefix length: %d/%d for %#v", prefixLen, maxPrefixLen, ifa)
}
if ifa.IP.IsLoopback() && (prefixLen != 8 && prefixLen != 8*IPv4len) { // see RFC 1122
- t.Errorf("unexpected prefix length for IPv4 loopback: %d/%d", prefixLen, maxPrefixLen)
- continue
+ return nil, fmt.Errorf("unexpected prefix length: %d/%d for %#v", prefixLen, maxPrefixLen, ifa)
}
- naf4++
+ stats.ipv4++
}
if ifa.IP.To16() != nil && ifa.IP.To4() == nil {
if 0 >= prefixLen || prefixLen > 8*IPv6len || maxPrefixLen != 8*IPv6len {
- t.Errorf("unexpected prefix length: %d/%d", prefixLen, maxPrefixLen)
- continue
+ return nil, fmt.Errorf("unexpected prefix length: %d/%d for %#v", prefixLen, maxPrefixLen, ifa)
}
if ifa.IP.IsLoopback() && prefixLen != 8*IPv6len { // see RFC 4291
- t.Errorf("unexpected prefix length for IPv6 loopback: %d/%d", prefixLen, maxPrefixLen)
- continue
+ return nil, fmt.Errorf("unexpected prefix length: %d/%d for %#v", prefixLen, maxPrefixLen, ifa)
}
- naf6++
+ stats.ipv6++
}
- t.Logf("interface address %q", ifa.String())
case *IPAddr:
if ifa == nil || ifa.IP == nil || ifa.IP.IsMulticast() {
- t.Errorf("unexpected value: %#v", ifa)
- continue
+ return nil, fmt.Errorf("unexpected value: %#v", ifa)
}
if len(ifa.IP) != IPv6len {
- t.Errorf("should be internal representation either IPv6 or IPv6 IPv4-mapped address: %#v", ifa)
- continue
+ return nil, fmt.Errorf("should be internal representation either IPv6 or IPv4-mapped IPv6 address: %#v", ifa)
}
if ifa.IP.To4() != nil {
- naf4++
+ stats.ipv4++
}
if ifa.IP.To16() != nil && ifa.IP.To4() == nil {
- naf6++
+ stats.ipv6++
}
- t.Logf("interface address %s", ifa.String())
default:
- t.Errorf("unexpected type: %T", ifa)
+ return nil, fmt.Errorf("unexpected type: %T", ifa)
}
}
- return
+ return stats, nil
}
-func testMulticastAddrs(t *testing.T, ifmat []Addr) (nmaf4, nmaf6 int) {
- for _, ifma := range ifmat {
- switch ifma := ifma.(type) {
+func validateInterfaceMulticastAddrs(ifat []Addr) (*routeStats, error) {
+ stats := new(routeStats)
+ for _, ifa := range ifat {
+ switch ifa := ifa.(type) {
case *IPAddr:
- if ifma == nil || ifma.IP == nil || ifma.IP.IsUnspecified() || !ifma.IP.IsMulticast() {
- t.Errorf("unexpected value: %+v", ifma)
- continue
+ if ifa == nil || ifa.IP == nil || ifa.IP.IsUnspecified() || !ifa.IP.IsMulticast() {
+ return nil, fmt.Errorf("unexpected value: %#v", ifa)
}
- if len(ifma.IP) != IPv6len {
- t.Errorf("should be internal representation either IPv6 or IPv6 IPv4-mapped address: %#v", ifma)
- continue
+ if len(ifa.IP) != IPv6len {
+ return nil, fmt.Errorf("should be internal representation either IPv6 or IPv4-mapped IPv6 address: %#v", ifa)
}
- if ifma.IP.To4() != nil {
- nmaf4++
+ if ifa.IP.To4() != nil {
+ stats.ipv4++
}
- if ifma.IP.To16() != nil && ifma.IP.To4() == nil {
- nmaf6++
+ if ifa.IP.To16() != nil && ifa.IP.To4() == nil {
+ stats.ipv6++
}
- t.Logf("joined group address %q", ifma.String())
default:
- t.Errorf("unexpected type: %T", ifma)
+ return nil, fmt.Errorf("unexpected type: %T", ifa)
}
}
- return
+ return stats, nil
+}
+
+func checkUnicastStats(ifStats *ifStats, uniStats *routeStats) error {
+ // Test the existence of connected unicast routes for IPv4.
+ if supportsIPv4 && ifStats.loop+ifStats.other > 0 && uniStats.ipv4 == 0 {
+ return fmt.Errorf("num IPv4 unicast routes = 0; want >0; summary: %+v, %+v", ifStats, uniStats)
+ }
+ // Test the existence of connected unicast routes for IPv6.
+ // We can assume the existence of ::1/128 when at least one
+ // loopback interface is installed.
+ if supportsIPv6 && ifStats.loop > 0 && uniStats.ipv6 == 0 {
+ return fmt.Errorf("num IPv6 unicast routes = 0; want >0; summary: %+v, %+v", ifStats, uniStats)
+ }
+ return nil
+}
+
+func checkMulticastStats(ifStats *ifStats, uniStats, multiStats *routeStats) error {
+ switch runtime.GOOS {
+ case "dragonfly", "nacl", "netbsd", "openbsd", "plan9", "solaris":
+ default:
+ // Test the existence of connected multicast route
+ // clones for IPv4. Unlike IPv6, IPv4 multicast
+ // capability is not a mandatory feature, and so IPv4
+ // multicast validation is ignored and we only check
+ // IPv6 below.
+ //
+ // Test the existence of connected multicast route
+ // clones for IPv6. Some platform never uses loopback
+ // interface as the nexthop for multicast routing.
+ // We can assume the existence of connected multicast
+ // route clones when at least two connected unicast
+ // routes, ::1/128 and other, are installed.
+ if supportsIPv6 && ifStats.loop > 0 && uniStats.ipv6 > 1 && multiStats.ipv6 == 0 {
+ return fmt.Errorf("num IPv6 multicast route clones = 0; want >0; summary: %+v, %+v, %+v", ifStats, uniStats, multiStats)
+ }
+ }
+ return nil
}
func BenchmarkInterfaces(b *testing.B) {
From c1e88920606e78b06e936c9c249bd55f06dd8c51 Mon Sep 17 00:00:00 2001
From: Mikio Hara
Date: Wed, 11 May 2016 13:04:22 +0900
Subject: [PATCH 067/267] net: fix nits found by vet
Change-Id: I323231f31c4e1e7415661ebd943a90b2f1e9da1c
Reviewed-on: https://go-review.googlesource.com/23020
Reviewed-by: Ian Lance Taylor
---
src/net/dnsclient_unix_test.go | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go
index c1ef5a32d3dcd6..09bbd488660673 100644
--- a/src/net/dnsclient_unix_test.go
+++ b/src/net/dnsclient_unix_test.go
@@ -582,11 +582,11 @@ func TestIgnoreLameReferrals(t *testing.T) {
}
if got := len(addrs); got != 1 {
- t.Fatal("got %d addresses, want 1", got)
+ t.Fatalf("got %d addresses, want 1", got)
}
if got, want := addrs[0].String(), "192.0.2.1"; got != want {
- t.Fatal("got address %v, want %v", got, want)
+ t.Fatalf("got address %v, want %v", got, want)
}
}
@@ -721,6 +721,6 @@ func TestIgnoreDNSForgeries(t *testing.T) {
}
if got := resp.answer[0].(*dnsRR_A).A; got != TestAddr {
- t.Error("got address %v, want %v", got, TestAddr)
+ t.Errorf("got address %v, want %v", got, TestAddr)
}
}
From 80423f1e64f1e939cddc455a29e5111527cd16f8 Mon Sep 17 00:00:00 2001
From: Hiroshi Ioka
Date: Sat, 26 Dec 2015 16:50:01 +0900
Subject: [PATCH 068/267] os/exec: cleanup and remove duplicated code
Change-Id: Ia2f61427b1cc09064ac4c0563bccbd9b98767a0e
Reviewed-on: https://go-review.googlesource.com/18118
Reviewed-by: Brad Fitzpatrick
Run-TryBot: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
---
src/os/exec/lp_plan9.go | 8 ++--
src/os/exec/lp_unix.go | 10 ++---
src/os/exec/lp_windows.go | 69 ++++++++++------------------------
src/os/exec/lp_windows_test.go | 2 +-
4 files changed, 29 insertions(+), 60 deletions(-)
diff --git a/src/os/exec/lp_plan9.go b/src/os/exec/lp_plan9.go
index 82678802a96483..142f87ed32b3b5 100644
--- a/src/os/exec/lp_plan9.go
+++ b/src/os/exec/lp_plan9.go
@@ -7,6 +7,7 @@ package exec
import (
"errors"
"os"
+ "path/filepath"
"strings"
)
@@ -44,9 +45,10 @@ func LookPath(file string) (string, error) {
}
path := os.Getenv("path")
- for _, dir := range strings.Split(path, "\000") {
- if err := findExecutable(dir + "/" + file); err == nil {
- return dir + "/" + file, nil
+ for _, dir := range filepath.SplitList(path) {
+ path := filepath.Join(dir, file)
+ if err := findExecutable(path); err == nil {
+ return path, nil
}
}
return "", &Error{file, ErrNotFound}
diff --git a/src/os/exec/lp_unix.go b/src/os/exec/lp_unix.go
index 32e3046cb87401..7a302752a8974d 100644
--- a/src/os/exec/lp_unix.go
+++ b/src/os/exec/lp_unix.go
@@ -9,6 +9,7 @@ package exec
import (
"errors"
"os"
+ "path/filepath"
"strings"
)
@@ -42,16 +43,13 @@ func LookPath(file string) (string, error) {
}
return "", &Error{file, err}
}
- pathenv := os.Getenv("PATH")
- if pathenv == "" {
- return "", &Error{file, ErrNotFound}
- }
- for _, dir := range strings.Split(pathenv, ":") {
+ path := os.Getenv("PATH")
+ for _, dir := range filepath.SplitList(path) {
if dir == "" {
// Unix shell semantics: path element "" means "."
dir = "."
}
- path := dir + "/" + file
+ path := filepath.Join(dir, file)
if err := findExecutable(path); err == nil {
return path, nil
}
diff --git a/src/os/exec/lp_windows.go b/src/os/exec/lp_windows.go
index 1c005220d01bc3..793d4d98b3a6ae 100644
--- a/src/os/exec/lp_windows.go
+++ b/src/os/exec/lp_windows.go
@@ -7,6 +7,7 @@ package exec
import (
"errors"
"os"
+ "path/filepath"
"strings"
)
@@ -56,20 +57,22 @@ func findExecutable(file string, exts []string) (string, error) {
// a suitable candidate.
// The result may be an absolute path or a path relative to the current directory.
func LookPath(file string) (string, error) {
+ var exts []string
x := os.Getenv(`PATHEXT`)
- if x == "" {
- x = `.COM;.EXE;.BAT;.CMD`
- }
- exts := []string{}
- for _, e := range strings.Split(strings.ToLower(x), `;`) {
- if e == "" {
- continue
- }
- if e[0] != '.' {
- e = "." + e
+ if x != "" {
+ for _, e := range strings.Split(strings.ToLower(x), `;`) {
+ if e == "" {
+ continue
+ }
+ if e[0] != '.' {
+ e = "." + e
+ }
+ exts = append(exts, e)
}
- exts = append(exts, e)
+ } else {
+ exts = []string{".com", ".exe", ".bat", ".cmd"}
}
+
if strings.ContainsAny(file, `:\/`) {
if f, err := findExecutable(file, exts); err == nil {
return f, nil
@@ -77,48 +80,14 @@ func LookPath(file string) (string, error) {
return "", &Error{file, err}
}
}
- if f, err := findExecutable(`.\`+file, exts); err == nil {
+ if f, err := findExecutable(filepath.Join(".", file), exts); err == nil {
return f, nil
}
- if pathenv := os.Getenv(`PATH`); pathenv != "" {
- for _, dir := range splitList(pathenv) {
- if f, err := findExecutable(dir+`\`+file, exts); err == nil {
- return f, nil
- }
+ path := os.Getenv("path")
+ for _, dir := range filepath.SplitList(path) {
+ if f, err := findExecutable(filepath.Join(dir, file), exts); err == nil {
+ return f, nil
}
}
return "", &Error{file, ErrNotFound}
}
-
-func splitList(path string) []string {
- // The same implementation is used in SplitList in path/filepath;
- // consider changing path/filepath when changing this.
-
- if path == "" {
- return []string{}
- }
-
- // Split path, respecting but preserving quotes.
- list := []string{}
- start := 0
- quo := false
- for i := 0; i < len(path); i++ {
- switch c := path[i]; {
- case c == '"':
- quo = !quo
- case c == os.PathListSeparator && !quo:
- list = append(list, path[start:i])
- start = i + 1
- }
- }
- list = append(list, path[start:])
-
- // Remove quotes.
- for i, s := range list {
- if strings.Contains(s, `"`) {
- list[i] = strings.Replace(s, `"`, "", -1)
- }
- }
-
- return list
-}
diff --git a/src/os/exec/lp_windows_test.go b/src/os/exec/lp_windows_test.go
index 042e5a1389eb7d..96a22d843f8544 100644
--- a/src/os/exec/lp_windows_test.go
+++ b/src/os/exec/lp_windows_test.go
@@ -107,7 +107,7 @@ func createEnv(dir, PATH, PATHEXT string) []string {
env := os.Environ()
env = updateEnv(env, "PATHEXT", PATHEXT)
// Add dir in front of every directory in the PATH.
- dirs := splitList(PATH)
+ dirs := filepath.SplitList(PATH)
for i := range dirs {
dirs[i] = filepath.Join(dir, dirs[i])
}
From 9a57fa31ff35024b9f628e7eae39bfd35bf90d77 Mon Sep 17 00:00:00 2001
From: Brad Fitzpatrick
Date: Tue, 10 May 2016 16:09:16 -0700
Subject: [PATCH 069/267] net/http: document ResponseWriter read-vs-write
concurrency rules
Summary: Go's HTTP/1.x server closes the request body once writes are
flushed. Go's HTTP/2 server supports concurrent read & write.
Added a TODO to make the HTTP/1.x server also support concurrent
read+write. But for now, document it.
Updates #15527
Change-Id: I81f7354923d37bfc1632629679c75c06a62bb584
Reviewed-on: https://go-review.googlesource.com/23011
Reviewed-by: Andrew Gerrand
---
src/net/http/server.go | 25 +++++++++++++++++++++----
1 file changed, 21 insertions(+), 4 deletions(-)
diff --git a/src/net/http/server.go b/src/net/http/server.go
index 23fb84fcdabf41..e24777421cf341 100644
--- a/src/net/http/server.go
+++ b/src/net/http/server.go
@@ -91,10 +91,24 @@ type ResponseWriter interface {
Header() Header
// Write writes the data to the connection as part of an HTTP reply.
- // If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK)
- // before writing the data. If the Header does not contain a
- // Content-Type line, Write adds a Content-Type set to the result of passing
- // the initial 512 bytes of written data to DetectContentType.
+ //
+ // If WriteHeader has not yet been called, Write calls
+ // WriteHeader(http.StatusOK) before writing the data. If the Header
+ // does not contain a Content-Type line, Write adds a Content-Type set
+ // to the result of passing the initial 512 bytes of written data to
+ // DetectContentType.
+ //
+ // Depending on the HTTP protocol version and the client, calling
+ // Write or WriteHeader may prevent future reads on the
+ // Request.Body. For HTTP/1.x requests, handlers should read any
+ // needed request body data before writing the response. Once the
+ // headers have been flushed (due to either an explicit Flusher.Flush
+ // call or writing enough data to trigger a flush), the request body
+ // may be unavailable. For HTTP/2 requests, the Go HTTP server permits
+ // handlers to continue to read the request body while concurrently
+ // writing the response. However, such behavior may not be supported
+ // by all HTTP/2 clients. Handlers should read before writing if
+ // possible to maximize compatibility.
Write([]byte) (int, error)
// WriteHeader sends an HTTP response header with status code.
@@ -1027,6 +1041,9 @@ func (cw *chunkWriter) writeHeader(p []byte) {
// replying, if the handler hasn't already done so. But we
// don't want to do an unbounded amount of reading here for
// DoS reasons, so we only try up to a threshold.
+ // TODO(bradfitz): where does RFC 2616 say that? See Issue 15527
+ // about HTTP/1.x Handlers concurrently reading and writing, like
+ // HTTP/2 handlers can do. Maybe this code should be relaxed?
if w.req.ContentLength != 0 && !w.closeAfterReply {
var discard, tooBig bool
From 20e362dae73b84e7b9dba9959444e5bc9d513ff1 Mon Sep 17 00:00:00 2001
From: Ian Lance Taylor
Date: Wed, 11 May 2016 09:37:46 -0700
Subject: [PATCH 070/267] cmd/cgo: remove //extern for check functions in gccgo
Go prologue
The //extern comments are incorrect and cause undefined symbol
errorswhen building cgo code with -compiler=gccgo. The code is already
designed to use weak references, and that support relies on the cgo
check functions being treated as local functions.
Change-Id: Ib38a640cc4ce6eba74cfbf41ba7147ec88769ec0
Reviewed-on: https://go-review.googlesource.com/23014
Run-TryBot: Ian Lance Taylor
Reviewed-by: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
---
src/cmd/cgo/out.go | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index 5eab3a71b49e29..265a3bbe6f71c4 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -1360,10 +1360,8 @@ func _cgoCheckResult(interface{})
`
const gccgoGoProlog = `
-//extern runtime.cgoCheckPointer
func _cgoCheckPointer(interface{}, ...interface{}) interface{}
-//extern runtime.cgoCheckResult
func _cgoCheckResult(interface{})
`
From 4d8031cf3c179d8682b62feae1d5a9109d14b382 Mon Sep 17 00:00:00 2001
From: Brad Fitzpatrick
Date: Tue, 10 May 2016 15:09:23 -0700
Subject: [PATCH 071/267] net/http: make the MaxBytesReader.Read error sticky
Fixes #14981
Change-Id: I39b906d119ca96815801a0fbef2dbe524a3246ff
Reviewed-on: https://go-review.googlesource.com/23009
Reviewed-by: Andrew Gerrand
Run-TryBot: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
---
src/net/http/request.go | 90 ++++++++++++++++--------------------
src/net/http/request_test.go | 40 ++++++++++++++++
2 files changed, 79 insertions(+), 51 deletions(-)
diff --git a/src/net/http/request.go b/src/net/http/request.go
index 1bde114909c38e..45507d23d14beb 100644
--- a/src/net/http/request.go
+++ b/src/net/http/request.go
@@ -885,68 +885,56 @@ func MaxBytesReader(w ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser {
}
type maxBytesReader struct {
- w ResponseWriter
- r io.ReadCloser // underlying reader
- n int64 // max bytes remaining
- stopped bool
- sawEOF bool
+ w ResponseWriter
+ r io.ReadCloser // underlying reader
+ n int64 // max bytes remaining
+ err error // sticky error
}
func (l *maxBytesReader) tooLarge() (n int, err error) {
- if !l.stopped {
- l.stopped = true
-
- // The server code and client code both use
- // maxBytesReader. This "requestTooLarge" check is
- // only used by the server code. To prevent binaries
- // which only using the HTTP Client code (such as
- // cmd/go) from also linking in the HTTP server, don't
- // use a static type assertion to the server
- // "*response" type. Check this interface instead:
- type requestTooLarger interface {
- requestTooLarge()
- }
- if res, ok := l.w.(requestTooLarger); ok {
- res.requestTooLarge()
- }
- }
- return 0, errors.New("http: request body too large")
+ l.err = errors.New("http: request body too large")
+ return 0, l.err
}
func (l *maxBytesReader) Read(p []byte) (n int, err error) {
- toRead := l.n
- if l.n == 0 {
- if l.sawEOF {
- return l.tooLarge()
- }
- // The underlying io.Reader may not return (0, io.EOF)
- // at EOF if the requested size is 0, so read 1 byte
- // instead. The io.Reader docs are a bit ambiguous
- // about the return value of Read when 0 bytes are
- // requested, and {bytes,strings}.Reader gets it wrong
- // too (it returns (0, nil) even at EOF).
- toRead = 1
+ if l.err != nil {
+ return 0, l.err
+ }
+ if len(p) == 0 {
+ return 0, nil
}
- if int64(len(p)) > toRead {
- p = p[:toRead]
+ // If they asked for a 32KB byte read but only 5 bytes are
+ // remaining, no need to read 32KB. 6 bytes will answer the
+ // question of the whether we hit the limit or go past it.
+ if int64(len(p)) > l.n+1 {
+ p = p[:l.n+1]
}
n, err = l.r.Read(p)
- if err == io.EOF {
- l.sawEOF = true
- }
- if l.n == 0 {
- // If we had zero bytes to read remaining (but hadn't seen EOF)
- // and we get a byte here, that means we went over our limit.
- if n > 0 {
- return l.tooLarge()
- }
- return 0, err
+
+ if int64(n) <= l.n {
+ l.n -= int64(n)
+ l.err = err
+ return n, err
}
- l.n -= int64(n)
- if l.n < 0 {
- l.n = 0
+
+ n = int(l.n)
+ l.n = 0
+
+ // The server code and client code both use
+ // maxBytesReader. This "requestTooLarge" check is
+ // only used by the server code. To prevent binaries
+ // which only using the HTTP Client code (such as
+ // cmd/go) from also linking in the HTTP server, don't
+ // use a static type assertion to the server
+ // "*response" type. Check this interface instead:
+ type requestTooLarger interface {
+ requestTooLarge()
}
- return
+ if res, ok := l.w.(requestTooLarger); ok {
+ res.requestTooLarge()
+ }
+ l.err = errors.New("http: request body too large")
+ return n, l.err
}
func (l *maxBytesReader) Close() error {
diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go
index 82c7af3cda8dbe..a4c88c02915ccd 100644
--- a/src/net/http/request_test.go
+++ b/src/net/http/request_test.go
@@ -679,6 +679,46 @@ func TestIssue10884_MaxBytesEOF(t *testing.T) {
}
}
+// Issue 14981: MaxBytesReader's return error wasn't sticky. It
+// doesn't technically need to be, but people expected it to be.
+func TestMaxBytesReaderStickyError(t *testing.T) {
+ isSticky := func(r io.Reader) error {
+ var log bytes.Buffer
+ buf := make([]byte, 1000)
+ var firstErr error
+ for {
+ n, err := r.Read(buf)
+ fmt.Fprintf(&log, "Read(%d) = %d, %v\n", len(buf), n, err)
+ if err == nil {
+ continue
+ }
+ if firstErr == nil {
+ firstErr = err
+ continue
+ }
+ if !reflect.DeepEqual(err, firstErr) {
+ return fmt.Errorf("non-sticky error. got log:\n%s", log.Bytes())
+ }
+ t.Logf("Got log: %s", log.Bytes())
+ return nil
+ }
+ }
+ tests := [...]struct {
+ readable int
+ limit int64
+ }{
+ 0: {99, 100},
+ 1: {100, 100},
+ 2: {101, 100},
+ }
+ for i, tt := range tests {
+ rc := MaxBytesReader(nil, ioutil.NopCloser(bytes.NewReader(make([]byte, tt.readable))), tt.limit)
+ if err := isSticky(rc); err != nil {
+ t.Errorf("%d. error: %v", i, err)
+ }
+ }
+}
+
func testMissingFile(t *testing.T, req *Request) {
f, fh, err := req.FormFile("missing")
if f != nil {
From 2ffb3e5d905b5622204d199128dec06cefd57790 Mon Sep 17 00:00:00 2001
From: Marc-Antoine Ruel
Date: Thu, 7 Apr 2016 14:24:24 -0400
Subject: [PATCH 072/267] os: fix Remove for file with read only attribute on
Windows
Include integration test. Confirmed that without the fix, the test case
TestDeleteReadOnly fails.
This permits to revert "cmd/go: reset read-only flag during TestIssue10952"
This reverts commit 3b7841b3aff9204f054ffabbe4dd39d3e3dd3e91.
Fixes #9606
Change-Id: Ib55c151a8cf1a1da02ab18c34a9b58f615c34254
Reviewed-on: https://go-review.googlesource.com/18235
Reviewed-by: Brad Fitzpatrick
Run-TryBot: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
---
src/cmd/go/go_test.go | 28 ----------------------------
src/os/file_windows.go | 6 ++++++
src/os/os_windows_test.go | 22 ++++++++++++++++++++++
3 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go
index ac82b2ffeb467b..b6673967619374 100644
--- a/src/cmd/go/go_test.go
+++ b/src/cmd/go/go_test.go
@@ -580,32 +580,6 @@ func (tg *testgoData) cleanup() {
}
}
-// resetReadOnlyFlagAll resets windows read-only flag
-// set on path and any children it contains.
-// The flag is set by git and has to be removed.
-// os.Remove refuses to remove files with read-only flag set.
-func (tg *testgoData) resetReadOnlyFlagAll(path string) {
- fi, err := os.Stat(path)
- if err != nil {
- tg.t.Fatalf("resetReadOnlyFlagAll(%q) failed: %v", path, err)
- }
- if !fi.IsDir() {
- err := os.Chmod(path, 0666)
- if err != nil {
- tg.t.Fatalf("resetReadOnlyFlagAll(%q) failed: %v", path, err)
- }
- }
- fd, err := os.Open(path)
- if err != nil {
- tg.t.Fatalf("resetReadOnlyFlagAll(%q) failed: %v", path, err)
- }
- defer fd.Close()
- names, _ := fd.Readdirnames(-1)
- for _, name := range names {
- tg.resetReadOnlyFlagAll(path + string(filepath.Separator) + name)
- }
-}
-
// failSSH puts an ssh executable in the PATH that always fails.
// This is to stub out uses of ssh by go get.
func (tg *testgoData) failSSH() {
@@ -1192,7 +1166,6 @@ func TestIssue10952(t *testing.T) {
const importPath = "github.com/zombiezen/go-get-issue-10952"
tg.run("get", "-d", "-u", importPath)
repoDir := tg.path("src/" + importPath)
- defer tg.resetReadOnlyFlagAll(repoDir)
tg.runGit(repoDir, "remote", "set-url", "origin", "https://"+importPath+".git")
tg.run("get", "-d", "-u", importPath)
}
@@ -1216,7 +1189,6 @@ func TestGetGitDefaultBranch(t *testing.T) {
tg.run("get", "-d", importPath)
repoDir := tg.path("src/" + importPath)
- defer tg.resetReadOnlyFlagAll(repoDir)
tg.runGit(repoDir, "branch", "--contains", "HEAD")
tg.grepStdout(`\* another-branch`, "not on correct default branch")
diff --git a/src/os/file_windows.go b/src/os/file_windows.go
index 08aff83a77510c..f470fc4315cc2b 100644
--- a/src/os/file_windows.go
+++ b/src/os/file_windows.go
@@ -474,6 +474,12 @@ func Remove(name string) error {
} else {
if a&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
e = e1
+ } else if a&syscall.FILE_ATTRIBUTE_READONLY != 0 {
+ if e1 = syscall.SetFileAttributes(p, a&^syscall.FILE_ATTRIBUTE_READONLY); e1 == nil {
+ if e = syscall.DeleteFile(p); e == nil {
+ return nil
+ }
+ }
}
}
}
diff --git a/src/os/os_windows_test.go b/src/os/os_windows_test.go
index 2f7d48d5bdf06c..05d7a8f34e9a9f 100644
--- a/src/os/os_windows_test.go
+++ b/src/os/os_windows_test.go
@@ -223,3 +223,25 @@ func TestOpenVolumeName(t *testing.T) {
t.Fatalf("unexpected file list %q, want %q", have, want)
}
}
+
+func TestDeleteReadOnly(t *testing.T) {
+ tmpdir, err := ioutil.TempDir("", "TestDeleteReadOnly")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tmpdir)
+ p := filepath.Join(tmpdir, "a")
+ // This sets FILE_ATTRIBUTE_READONLY.
+ f, err := os.OpenFile(p, os.O_CREATE, 0400)
+ if err != nil {
+ t.Fatal(err)
+ }
+ f.Close()
+
+ if err = os.Chmod(p, 0400); err != nil {
+ t.Fatal(err)
+ }
+ if err = os.Remove(p); err != nil {
+ t.Fatal(err)
+ }
+}
From e9407ae514df7d18e162ce03ebd530fe21aed16d Mon Sep 17 00:00:00 2001
From: Joe Tsai
Date: Wed, 11 May 2016 10:23:37 -0700
Subject: [PATCH 073/267] cmd/pprof: remove tempDir when no longer needed
The pprof tools properly cleans up all files it creates, but forgets
to clean up the temporary directory itself. This CL fixes that.
Fixes #13863
Change-Id: I1151c36cdad5ace7cc97e7e04001cf0149ef0f63
Reviewed-on: https://go-review.googlesource.com/23019
Reviewed-by: Brad Fitzpatrick
Run-TryBot: Joe Tsai
TryBot-Result: Gobot Gobot
---
src/cmd/internal/pprof/commands/commands.go | 1 +
src/cmd/internal/pprof/tempfile/tempfile.go | 9 +++++----
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/cmd/internal/pprof/commands/commands.go b/src/cmd/internal/pprof/commands/commands.go
index 5018c02af185e7..5dfbbd4a5dc8ac 100644
--- a/src/cmd/internal/pprof/commands/commands.go
+++ b/src/cmd/internal/pprof/commands/commands.go
@@ -197,6 +197,7 @@ func makeVizTmpDir() error {
if err != nil {
return err
}
+ tempfile.DeferDelete(name)
vizTmpDir = name
return nil
}
diff --git a/src/cmd/internal/pprof/tempfile/tempfile.go b/src/cmd/internal/pprof/tempfile/tempfile.go
index 31c117690a1c1f..a5706345e43954 100644
--- a/src/cmd/internal/pprof/tempfile/tempfile.go
+++ b/src/cmd/internal/pprof/tempfile/tempfile.go
@@ -27,18 +27,19 @@ func New(dir, prefix, suffix string) (*os.File, error) {
var tempFiles []string
var tempFilesMu = sync.Mutex{}
-// DeferDelete marks a file to be deleted by next call to Cleanup()
+// DeferDelete marks a file or directory to be deleted by next call to Cleanup.
func DeferDelete(path string) {
tempFilesMu.Lock()
tempFiles = append(tempFiles, path)
tempFilesMu.Unlock()
}
-// Cleanup removes any temporary files selected for deferred cleaning.
+// Cleanup removes any temporary files or directories selected for deferred cleaning.
+// Similar to defer semantics, the nodes are deleted in LIFO order.
func Cleanup() {
tempFilesMu.Lock()
- for _, f := range tempFiles {
- os.Remove(f)
+ for i := len(tempFiles) - 1; i >= 0; i-- {
+ os.Remove(tempFiles[i])
}
tempFiles = nil
tempFilesMu.Unlock()
From aff4889089f970fb739acf5e3a5bddd3491a908b Mon Sep 17 00:00:00 2001
From: Robert Griesemer
Date: Wed, 11 May 2016 11:28:36 -0700
Subject: [PATCH 074/267] cmd/compile: clean up encoding of method expressions
and add test
Fixes #15646.
Change-Id: Ic13d1adc0a358149209195cdb03811eeee506fb8
Reviewed-on: https://go-review.googlesource.com/23052
TryBot-Result: Gobot Gobot
Reviewed-by: Matthew Dempsky
---
src/cmd/compile/internal/gc/bexport.go | 22 ++++++++++------------
src/cmd/compile/internal/gc/bimport.go | 11 +++--------
test/fixedbugs/issue15646.dir/a.go | 23 +++++++++++++++++++++++
test/fixedbugs/issue15646.dir/b.go | 16 ++++++++++++++++
test/fixedbugs/issue15646.go | 9 +++++++++
5 files changed, 61 insertions(+), 20 deletions(-)
create mode 100644 test/fixedbugs/issue15646.dir/a.go
create mode 100644 test/fixedbugs/issue15646.dir/b.go
create mode 100644 test/fixedbugs/issue15646.go
diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go
index cd2963e8e64e09..3fe729618b4885 100644
--- a/src/cmd/compile/internal/gc/bexport.go
+++ b/src/cmd/compile/internal/gc/bexport.go
@@ -1157,9 +1157,9 @@ func (p *exporter) expr(n *Node) {
// Special case: name used as local variable in export.
// _ becomes ~b%d internally; print as _ for export
if n.Sym != nil && n.Sym.Name[0] == '~' && n.Sym.Name[1] == 'b' {
- // case 0: mapped to ONAME
- p.op(ONAME)
- p.bool(true) // indicate blank identifier
+ // case 0: mapped to OPACK
+ p.op(OPACK)
+ p.string("_") // inlined and customized version of p.sym(n)
break
}
@@ -1174,22 +1174,18 @@ func (p *exporter) expr(n *Node) {
// but for export, this should be rendered as (*pkg.T).meth.
// These nodes have the special property that they are names with a left OTYPE and a right ONAME.
if n.Left != nil && n.Left.Op == OTYPE && n.Right != nil && n.Right.Op == ONAME {
- // case 2: mapped to ONAME
- p.op(ONAME)
- // TODO(gri) can we map this case directly to OXDOT
- // and then get rid of the bool here?
- p.bool(false) // indicate non-blank identifier
- p.typ(n.Left.Type)
+ // case 2: mapped to OXDOT
+ p.op(OXDOT)
+ p.expr(n.Left) // n.Left.Op == OTYPE
p.fieldSym(n.Right.Sym, true)
break
}
// case 3: mapped to OPACK
- p.op(OPACK)
- p.sym(n) // fallthrough inlined here
+ fallthrough
case OPACK, ONONAME:
- p.op(op)
+ p.op(OPACK)
p.sym(n)
case OTYPE:
@@ -1508,6 +1504,8 @@ func (p *exporter) fieldSym(s *Sym, short bool) {
}
}
+// sym must encode the _ (blank) identifier as a single string "_" since
+// encoding for some nodes is based on this assumption (e.g. ONAME nodes).
func (p *exporter) sym(n *Node) {
s := n.Sym
if s.Pkg != nil {
diff --git a/src/cmd/compile/internal/gc/bimport.go b/src/cmd/compile/internal/gc/bimport.go
index cb375a0ac3fd5b..c161c4ffb10c93 100644
--- a/src/cmd/compile/internal/gc/bimport.go
+++ b/src/cmd/compile/internal/gc/bimport.go
@@ -798,15 +798,10 @@ func (p *importer) node() *Node {
}
return n
- case ONAME:
- if p.bool() {
- // "_"
- // TODO(gri) avoid repeated "_" lookup
- return mkname(Pkglookup("_", localpkg))
- }
- return NodSym(OXDOT, typenod(p.typ()), p.fieldSym())
+ // case ONAME, OPACK, ONONAME:
+ // unreachable - mapped to case OPACK below by exporter
- case OPACK, ONONAME:
+ case OPACK:
return mkname(p.sym())
case OTYPE:
diff --git a/test/fixedbugs/issue15646.dir/a.go b/test/fixedbugs/issue15646.dir/a.go
new file mode 100644
index 00000000000000..842f19685fd282
--- /dev/null
+++ b/test/fixedbugs/issue15646.dir/a.go
@@ -0,0 +1,23 @@
+// Copyright 2016 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 a
+
+type T struct{}
+
+func (T) m() string {
+ return "m"
+}
+
+func (*T) mp() string {
+ return "mp"
+}
+
+func F() func(T) string {
+ return T.m // method expression
+}
+
+func Fp() func(*T) string {
+ return (*T).mp // method expression
+}
diff --git a/test/fixedbugs/issue15646.dir/b.go b/test/fixedbugs/issue15646.dir/b.go
new file mode 100644
index 00000000000000..3d011ba30195b8
--- /dev/null
+++ b/test/fixedbugs/issue15646.dir/b.go
@@ -0,0 +1,16 @@
+// Copyright 2016 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 main
+
+import "./a" // import must succeed
+
+func main() {
+ if a.F()(a.T{}) != "m" {
+ panic(0)
+ }
+ if a.Fp()(nil) != "mp" {
+ panic(1)
+ }
+}
diff --git a/test/fixedbugs/issue15646.go b/test/fixedbugs/issue15646.go
new file mode 100644
index 00000000000000..cd4ba9d4e52035
--- /dev/null
+++ b/test/fixedbugs/issue15646.go
@@ -0,0 +1,9 @@
+// rundir
+
+// Copyright 2016 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.
+
+// Test that method expressions are correctly encoded
+// in binary export data and can be imported again.
+package ignore
\ No newline at end of file
From ef62f641c37431a870fa093c43b3ee51a06db0da Mon Sep 17 00:00:00 2001
From: Robert Griesemer
Date: Wed, 11 May 2016 12:40:17 -0700
Subject: [PATCH 075/267] cmd/compile: use ONAME instead of OPACK in binary
export format
This is addressing feedback given on golang.org/cl/23052;
we do it in a separate CL to separate the functional from
the rename change.
ONAME was not used in the export data, but it's the natural node op
where we used OPACK instead. Renamed.
Furthermore, OPACK and ONONAME nodes are replaced by the type checker
with ONAME nodes, so OPACK nodes cannot occur when exporting type-checked
code. Removed a special-case for OPACK nodes since they don't appear.
Change-Id: I78b01a1badbf60e9283eaadeca2578a65d28cbd2
Reviewed-on: https://go-review.googlesource.com/23053
Run-TryBot: Robert Griesemer
TryBot-Result: Gobot Gobot
Reviewed-by: Matthew Dempsky
---
src/cmd/compile/internal/gc/bexport.go | 21 +++++++--------------
src/cmd/compile/internal/gc/bimport.go | 17 +++++------------
2 files changed, 12 insertions(+), 26 deletions(-)
diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go
index 3fe729618b4885..48b2b201562cab 100644
--- a/src/cmd/compile/internal/gc/bexport.go
+++ b/src/cmd/compile/internal/gc/bexport.go
@@ -1157,15 +1157,13 @@ func (p *exporter) expr(n *Node) {
// Special case: name used as local variable in export.
// _ becomes ~b%d internally; print as _ for export
if n.Sym != nil && n.Sym.Name[0] == '~' && n.Sym.Name[1] == 'b' {
- // case 0: mapped to OPACK
- p.op(OPACK)
+ p.op(ONAME)
p.string("_") // inlined and customized version of p.sym(n)
break
}
if n.Sym != nil && !isblank(n) && n.Name.Vargen > 0 {
- // case 1: mapped to OPACK
- p.op(OPACK)
+ p.op(ONAME)
p.sym(n)
break
}
@@ -1174,20 +1172,18 @@ func (p *exporter) expr(n *Node) {
// but for export, this should be rendered as (*pkg.T).meth.
// These nodes have the special property that they are names with a left OTYPE and a right ONAME.
if n.Left != nil && n.Left.Op == OTYPE && n.Right != nil && n.Right.Op == ONAME {
- // case 2: mapped to OXDOT
p.op(OXDOT)
p.expr(n.Left) // n.Left.Op == OTYPE
p.fieldSym(n.Right.Sym, true)
break
}
- // case 3: mapped to OPACK
- fallthrough
-
- case OPACK, ONONAME:
- p.op(OPACK)
+ p.op(ONAME)
p.sym(n)
+ // case OPACK, ONONAME:
+ // should have been resolved by typechecking - handled by default case
+
case OTYPE:
p.op(OTYPE)
if p.bool(n.Type == nil) {
@@ -1400,10 +1396,7 @@ func (p *exporter) stmt(n *Node) {
p.expr(n.Right)
}
- case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
- fallthrough
-
- case OAS2:
+ case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
p.op(OAS2)
p.exprList(n.List)
p.exprList(n.Rlist)
diff --git a/src/cmd/compile/internal/gc/bimport.go b/src/cmd/compile/internal/gc/bimport.go
index c161c4ffb10c93..1bc184f7a43070 100644
--- a/src/cmd/compile/internal/gc/bimport.go
+++ b/src/cmd/compile/internal/gc/bimport.go
@@ -798,12 +798,12 @@ func (p *importer) node() *Node {
}
return n
- // case ONAME, OPACK, ONONAME:
- // unreachable - mapped to case OPACK below by exporter
-
- case OPACK:
+ case ONAME:
return mkname(p.sym())
+ // case OPACK, ONONAME:
+ // unreachable - should have been resolved by typechecking
+
case OTYPE:
if p.bool() {
return mkname(p.sym())
@@ -854,14 +854,7 @@ func (p *importer) node() *Node {
case OXDOT:
// see parser.new_dotname
- obj := p.expr()
- sel := p.fieldSym()
- if obj.Op == OPACK {
- s := restrictlookup(sel.Name, obj.Name.Pkg)
- obj.Used = true
- return oldname(s)
- }
- return NodSym(OXDOT, obj, sel)
+ return NodSym(OXDOT, p.expr(), p.fieldSym())
// case ODOTTYPE, ODOTTYPE2:
// unreachable - mapped to case ODOTTYPE below by exporter
From 114051aa1d5da5dec1b2707b1403261a3135b9b5 Mon Sep 17 00:00:00 2001
From: Johan Sageryd
Date: Sun, 8 May 2016 18:06:03 +0200
Subject: [PATCH 076/267] text/template: fix typo in documentation
Change-Id: I4ccfaa16e153aad001d670891b3848264e63cf6f
Reviewed-on: https://go-review.googlesource.com/23031
Reviewed-by: Brad Fitzpatrick
---
src/text/template/doc.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/text/template/doc.go b/src/text/template/doc.go
index df8c95f8c8949e..48e9aa7395cec9 100644
--- a/src/text/template/doc.go
+++ b/src/text/template/doc.go
@@ -220,7 +220,7 @@ value (argument) or a function or method call, possibly with multiple arguments:
Functions and function names are described below.
A pipeline may be "chained" by separating a sequence of commands with pipeline
-characters '|'. In a chained pipeline, the result of the each command is
+characters '|'. In a chained pipeline, the result of each command is
passed as the last argument of the following command. The output of the final
command in the pipeline is the value of the pipeline.
From eb9062b7bf77a5051b3db6f3e944739a486ca1e4 Mon Sep 17 00:00:00 2001
From: Brad Fitzpatrick
Date: Wed, 11 May 2016 15:01:28 -0700
Subject: [PATCH 077/267] net/http: keep HTTP/1.0 keep-alive conns open if
response can't have a body
Fixes #15647
Change-Id: I588bfa4eb336d1da1fcda8d06e32ed13c0b51c70
Reviewed-on: https://go-review.googlesource.com/23061
Run-TryBot: Brad Fitzpatrick
Reviewed-by: Andrew Gerrand
TryBot-Result: Gobot Gobot
---
src/net/http/serve_test.go | 43 ++++++++++++++++++++++++++++++++++++++
src/net/http/server.go | 2 +-
2 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go
index b34875f061a062..95983e4b02e756 100644
--- a/src/net/http/serve_test.go
+++ b/src/net/http/serve_test.go
@@ -714,6 +714,31 @@ func testTCPConnectionCloses(t *testing.T, req string, h Handler) {
}
}
+func testTCPConnectionStaysOpen(t *testing.T, req string, handler Handler) {
+ defer afterTest(t)
+ ts := httptest.NewServer(handler)
+ defer ts.Close()
+ conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer conn.Close()
+ br := bufio.NewReader(conn)
+ for i := 0; i < 2; i++ {
+ if _, err := io.WriteString(conn, req); err != nil {
+ t.Fatal(err)
+ }
+ res, err := ReadResponse(br, nil)
+ if err != nil {
+ t.Fatalf("res %d: %v", i+1, err)
+ }
+ if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
+ t.Fatalf("res %d body copy: %v", i+1, err)
+ }
+ res.Body.Close()
+ }
+}
+
// TestServeHTTP10Close verifies that HTTP/1.0 requests won't be kept alive.
func TestServeHTTP10Close(t *testing.T) {
testTCPConnectionCloses(t, "GET / HTTP/1.0\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -749,6 +774,24 @@ func TestHTTP2UpgradeClosesConnection(t *testing.T) {
}))
}
+func send204(w ResponseWriter, r *Request) { w.WriteHeader(204) }
+func send304(w ResponseWriter, r *Request) { w.WriteHeader(304) }
+
+// Issue 15647: 204 responses can't have bodies, so HTTP/1.0 keep-alive conns should stay open.
+func TestHTTP10KeepAlive204Response(t *testing.T) {
+ testTCPConnectionStaysOpen(t, "GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n", HandlerFunc(send204))
+}
+
+func TestHTTP11KeepAlive204Response(t *testing.T) {
+ testTCPConnectionStaysOpen(t, "GET / HTTP/1.1\r\nHost: foo\r\n\r\n", HandlerFunc(send204))
+}
+
+func TestHTTP10KeepAlive304Response(t *testing.T) {
+ testTCPConnectionStaysOpen(t,
+ "GET / HTTP/1.0\r\nConnection: keep-alive\r\nIf-Modified-Since: Mon, 02 Jan 2006 15:04:05 GMT\r\n\r\n",
+ HandlerFunc(send304))
+}
+
func TestSetsRemoteAddr_h1(t *testing.T) { testSetsRemoteAddr(t, h1Mode) }
func TestSetsRemoteAddr_h2(t *testing.T) { testSetsRemoteAddr(t, h2Mode) }
diff --git a/src/net/http/server.go b/src/net/http/server.go
index e24777421cf341..d0be7d01dbd0aa 100644
--- a/src/net/http/server.go
+++ b/src/net/http/server.go
@@ -1008,7 +1008,7 @@ func (cw *chunkWriter) writeHeader(p []byte) {
// Check for a explicit (and valid) Content-Length header.
hasCL := w.contentLength != -1
- if w.wants10KeepAlive && (isHEAD || hasCL) {
+ if w.wants10KeepAlive && (isHEAD || hasCL || !bodyAllowedForStatus(w.status)) {
_, connectionHeaderSet := header["Connection"]
if !connectionHeaderSet {
setHeader.connection = "keep-alive"
From 21d781070cea6001ee541933ed76dc6da96bde4c Mon Sep 17 00:00:00 2001
From: Robert Griesemer
Date: Wed, 11 May 2016 13:39:36 -0700
Subject: [PATCH 078/267] cmd/compile: use one format for exporting calls of
builtin functions
Minor cleanup. Each of these cases appears both during export and
import when running all.bash and thus is tested by all.bash.
Change-Id: Iaa4a5a5b163cefe33e43d08d396e02a02e5c22a5
Reviewed-on: https://go-review.googlesource.com/23060
Reviewed-by: Matthew Dempsky
Run-TryBot: Matthew Dempsky
TryBot-Result: Gobot Gobot
---
src/cmd/compile/internal/gc/bexport.go | 17 +++++++++++++----
src/cmd/compile/internal/gc/bimport.go | 19 ++++---------------
2 files changed, 17 insertions(+), 19 deletions(-)
diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go
index 48b2b201562cab..2e5731e2b8c580 100644
--- a/src/cmd/compile/internal/gc/bexport.go
+++ b/src/cmd/compile/internal/gc/bexport.go
@@ -1256,26 +1256,35 @@ func (p *exporter) expr(n *Node) {
p.expr(max)
case OCOPY, OCOMPLEX:
+ // treated like other builtin calls (see e.g., OREAL)
p.op(op)
p.expr(n.Left)
p.expr(n.Right)
+ p.op(OEND)
case OCONV, OCONVIFACE, OCONVNOP, OARRAYBYTESTR, OARRAYRUNESTR, OSTRARRAYBYTE, OSTRARRAYRUNE, ORUNESTR:
p.op(OCONV)
p.typ(n.Type)
- if p.bool(n.Left != nil) {
+ if n.Left != nil {
p.expr(n.Left)
+ p.op(OEND)
} else {
- p.exprList(n.List)
+ p.exprList(n.List) // emits terminating OEND
}
case OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN:
p.op(op)
- if p.bool(n.Left != nil) {
+ if n.Left != nil {
p.expr(n.Left)
+ p.op(OEND)
} else {
- p.exprList(n.List)
+ p.exprList(n.List) // emits terminating OEND
+ }
+ // only append() calls may contain '...' arguments
+ if op == OAPPEND {
p.bool(n.Isddd)
+ } else if n.Isddd {
+ Fatalf("exporter: unexpected '...' with %s call", opnames[op])
}
case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG:
diff --git a/src/cmd/compile/internal/gc/bimport.go b/src/cmd/compile/internal/gc/bimport.go
index 1bc184f7a43070..51847538961eec 100644
--- a/src/cmd/compile/internal/gc/bimport.go
+++ b/src/cmd/compile/internal/gc/bimport.go
@@ -884,29 +884,18 @@ func (p *importer) node() *Node {
n.SetSliceBounds(low, high, max)
return n
- case OCOPY, OCOMPLEX:
- n := builtinCall(op)
- n.List.Set([]*Node{p.expr(), p.expr()})
- return n
-
// case OCONV, OCONVIFACE, OCONVNOP, OARRAYBYTESTR, OARRAYRUNESTR, OSTRARRAYBYTE, OSTRARRAYRUNE, ORUNESTR:
// unreachable - mapped to OCONV case below by exporter
case OCONV:
n := Nod(OCALL, typenod(p.typ()), nil)
- if p.bool() {
- n.List.Set1(p.expr())
- } else {
- n.List.Set(p.exprList())
- }
+ n.List.Set(p.exprList())
return n
- case OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN:
+ case OCOPY, OCOMPLEX, OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN:
n := builtinCall(op)
- if p.bool() {
- n.List.Set1(p.expr())
- } else {
- n.List.Set(p.exprList())
+ n.List.Set(p.exprList())
+ if op == OAPPEND {
n.Isddd = p.bool()
}
return n
From 81b70f3751374ccd1eda2f536156dd91cd9f9c9b Mon Sep 17 00:00:00 2001
From: Alex Brainman
Date: Wed, 11 May 2016 16:16:37 +1000
Subject: [PATCH 079/267] syscall: make mksyscall_windows.go -systemdll flag
true by default
Updates #15167
Change-Id: I826f67e75011ba79325a1294ac0d70d7c6a3e32f
Reviewed-on: https://go-review.googlesource.com/23022
Reviewed-by: Brad Fitzpatrick
Run-TryBot: Alex Brainman
TryBot-Result: Gobot Gobot
---
src/internal/syscall/windows/registry/syscall.go | 2 +-
src/internal/syscall/windows/syscall_windows.go | 2 +-
src/syscall/mksyscall_windows.go | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/internal/syscall/windows/registry/syscall.go b/src/internal/syscall/windows/registry/syscall.go
index 02d985cec90b0f..5426cae9096330 100644
--- a/src/internal/syscall/windows/registry/syscall.go
+++ b/src/internal/syscall/windows/registry/syscall.go
@@ -8,7 +8,7 @@ package registry
import "syscall"
-//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go -systemdll syscall.go
+//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall.go
const (
_REG_OPTION_NON_VOLATILE = 0
diff --git a/src/internal/syscall/windows/syscall_windows.go b/src/internal/syscall/windows/syscall_windows.go
index 2eae5e75f9e411..7b2bc79cebe4a4 100644
--- a/src/internal/syscall/windows/syscall_windows.go
+++ b/src/internal/syscall/windows/syscall_windows.go
@@ -6,7 +6,7 @@ package windows
import "syscall"
-//go:generate go run ../../../syscall/mksyscall_windows.go -output zsyscall_windows.go -systemdll syscall_windows.go
+//go:generate go run ../../../syscall/mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go
const GAA_FLAG_INCLUDE_PREFIX = 0x00000010
diff --git a/src/syscall/mksyscall_windows.go b/src/syscall/mksyscall_windows.go
index 4ccbb04908c7a5..84747962ab559e 100644
--- a/src/syscall/mksyscall_windows.go
+++ b/src/syscall/mksyscall_windows.go
@@ -68,7 +68,7 @@ import (
var (
filename = flag.String("output", "", "output file name (standard output if omitted)")
printTraceFlag = flag.Bool("trace", false, "generate print statement after every syscall")
- systemDLL = flag.Bool("systemdll", false, "whether all DLLs should be loaded from the Windows system directory")
+ systemDLL = flag.Bool("systemdll", true, "whether all DLLs should be loaded from the Windows system directory")
)
func trim(s string) string {
From 5bd37b8e78980beed2861bbdc7f8f28fc3f72671 Mon Sep 17 00:00:00 2001
From: Joel Sing
Date: Mon, 9 May 2016 02:13:03 +1000
Subject: [PATCH 080/267] runtime: stop using sigreturn on openbsd/386
In future releases of OpenBSD, the sigreturn syscall will no longer
exist. As such, stop using sigreturn on openbsd/386 and just return
from the signal trampoline (as we already do for openbsd/amd64 and
openbsd/arm).
Change-Id: Ic4de1795bbfbfb062a685832aea0d597988c6985
Reviewed-on: https://go-review.googlesource.com/23024
Reviewed-by: Ian Lance Taylor
Run-TryBot: Ian Lance Taylor
TryBot-Result: Gobot Gobot
---
src/runtime/sys_openbsd_386.s | 8 --------
1 file changed, 8 deletions(-)
diff --git a/src/runtime/sys_openbsd_386.s b/src/runtime/sys_openbsd_386.s
index f80a85fb67767b..2bb818f456ea2e 100644
--- a/src/runtime/sys_openbsd_386.s
+++ b/src/runtime/sys_openbsd_386.s
@@ -214,14 +214,6 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$12
MOVL context+8(FP), BX
MOVL BX, 8(SP)
CALL runtime·sigtrampgo(SB)
-
- // call sigreturn
- MOVL context+8(FP), AX
- MOVL $0, 0(SP) // syscall gap
- MOVL AX, 4(SP) // arg 1 - sigcontext
- MOVL $103, AX // sys_sigreturn
- INT $0x80
- MOVL $0xf1, 0xf1 // crash
RET
// int32 tfork(void *param, uintptr psize, M *mp, G *gp, void (*fn)(void));
From a71584975dedd4f4975d65047ec7660191a49613 Mon Sep 17 00:00:00 2001
From: Aliaksandr Valialkin
Date: Thu, 12 May 2016 15:00:10 +0300
Subject: [PATCH 081/267] reflect: fix vet warnings
Updated #11041
Change-Id: I4a110ba8fefb367a1049b4a65dd20c39eb890ea2
Reviewed-on: https://go-review.googlesource.com/23080
Reviewed-by: Brad Fitzpatrick
Run-TryBot: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
---
src/reflect/all_test.go | 8 ++++----
src/reflect/type.go | 1 -
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index 1a7952d7892d83..5beec63273b526 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -4210,7 +4210,7 @@ func TestStructOfExportRules(t *testing.T) {
}
exported := isExported(n)
if exported != test.exported {
- t.Errorf("test-%d: got exported=%v want exported=%v", exported, test.exported)
+ t.Errorf("test-%d: got exported=%v want exported=%v", i, exported, test.exported)
}
})
}
@@ -4520,7 +4520,7 @@ func TestStructOfWithInterface(t *testing.T) {
if table.impl {
t.Errorf("test-%d: type=%v fails to implement Iface.\n", i, table.typ)
} else {
- t.Errorf("test-%d: type=%v should NOT implement Iface\n", table.typ)
+ t.Errorf("test-%d: type=%v should NOT implement Iface\n", i, table.typ)
}
continue
}
@@ -4748,7 +4748,7 @@ func TestFuncOf(t *testing.T) {
if len(args) != 1 {
t.Errorf("args == %v, want exactly one arg", args)
} else if args[0].Type() != TypeOf(K("")) {
- t.Errorf("args[0] is type %v, want %v", args[0].Type, TypeOf(K("")))
+ t.Errorf("args[0] is type %v, want %v", args[0].Type(), TypeOf(K("")))
} else if args[0].String() != "gopher" {
t.Errorf("args[0] = %q, want %q", args[0].String(), "gopher")
}
@@ -4760,7 +4760,7 @@ func TestFuncOf(t *testing.T) {
if len(outs) != 1 {
t.Fatalf("v.Call returned %v, want exactly one result", outs)
} else if outs[0].Type() != TypeOf(V(0)) {
- t.Fatalf("c.Call[0] is type %v, want %v", outs[0].Type, TypeOf(V(0)))
+ t.Fatalf("c.Call[0] is type %v, want %v", outs[0].Type(), TypeOf(V(0)))
}
f := outs[0].Float()
if f != 3.14 {
diff --git a/src/reflect/type.go b/src/reflect/type.go
index b499d01a2c7346..5c6e3d55009d7e 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -2758,7 +2758,6 @@ func typeptrdata(t *rtype) uintptr {
default:
panic("reflect.typeptrdata: unexpected type, " + t.String())
}
- return 0
}
// See cmd/compile/internal/gc/reflect.go for derivation of constant.
From 376e6415402b4e62f96fb7f8f7a99d352aa9c1b3 Mon Sep 17 00:00:00 2001
From: Aliaksandr Valialkin
Date: Thu, 12 May 2016 15:13:22 +0300
Subject: [PATCH 082/267] cmd: fixed certain vet warnings
Updates #11041
Change-Id: I7f2583d08f344d6622027c5e8a5de1f5d2f2881c
Reviewed-on: https://go-review.googlesource.com/23082
Reviewed-by: Brad Fitzpatrick
Run-TryBot: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
---
src/cmd/cover/cover.go | 2 +-
src/cmd/dist/test.go | 2 +-
src/cmd/internal/pprof/report/report.go | 4 +++-
src/cmd/link/internal/ld/objfile.go | 2 +-
4 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/cmd/cover/cover.go b/src/cmd/cover/cover.go
index 46495950e98f53..a9ed66eea06cd5 100644
--- a/src/cmd/cover/cover.go
+++ b/src/cmd/cover/cover.go
@@ -388,7 +388,7 @@ func trimComments(file *ast.File, fset *token.FileSet) []*ast.CommentGroup {
}
}
if list != nil {
- comments = append(comments, &ast.CommentGroup{list})
+ comments = append(comments, &ast.CommentGroup{List: list})
}
}
return comments
diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go
index 3d123c2c8641da..1a1f7d961bea77 100644
--- a/src/cmd/dist/test.go
+++ b/src/cmd/dist/test.go
@@ -699,7 +699,7 @@ func (t *tester) supportedBuildmode(mode string) bool {
}
return false
default:
- log.Fatal("internal error: unknown buildmode %s", mode)
+ log.Fatalf("internal error: unknown buildmode %s", mode)
return false
}
}
diff --git a/src/cmd/internal/pprof/report/report.go b/src/cmd/internal/pprof/report/report.go
index c492b752b96fbb..b11ad2ab3606e7 100644
--- a/src/cmd/internal/pprof/report/report.go
+++ b/src/cmd/internal/pprof/report/report.go
@@ -205,7 +205,9 @@ func nodesPerSymbol(ns nodes, symbols []*objSymbol) map[*objSymbol]nodes {
// offset to adjust the sample addresses.
func annotateAssembly(insns []plugin.Inst, samples nodes, base uint64) nodes {
// Add end marker to simplify printing loop.
- insns = append(insns, plugin.Inst{^uint64(0), "", "", 0})
+ insns = append(insns, plugin.Inst{
+ Addr: ^uint64(0),
+ })
// Ensure samples are sorted by address.
samples.sort(addressOrder)
diff --git a/src/cmd/link/internal/ld/objfile.go b/src/cmd/link/internal/ld/objfile.go
index d16431ddaa29ad..be9832dc454830 100644
--- a/src/cmd/link/internal/ld/objfile.go
+++ b/src/cmd/link/internal/ld/objfile.go
@@ -538,7 +538,7 @@ func (r *objReader) readSymName() string {
origName = make([]byte, n)
r.readFull(origName)
} else if err != nil {
- log.Fatalf("%s: error reading symbol: %v", err)
+ log.Fatalf("%s: error reading symbol: %v", r.pn, err)
}
adjName := r.rdBuf[:0]
for {
From e54dfc2ec4a057aa1bf06f9bef5cdb2e769a669d Mon Sep 17 00:00:00 2001
From: Aliaksandr Valialkin
Date: Thu, 12 May 2016 15:03:22 +0300
Subject: [PATCH 083/267] testing: fix vet warning
Updates #11041
Change-Id: I32a381854e6a4fd791db380150efab57e6dfc38c
Reviewed-on: https://go-review.googlesource.com/23081
Reviewed-by: Brad Fitzpatrick
---
src/testing/match_test.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/testing/match_test.go b/src/testing/match_test.go
index d19036c72d1001..8c1c5f4452c5c0 100644
--- a/src/testing/match_test.go
+++ b/src/testing/match_test.go
@@ -135,8 +135,8 @@ func TestMatcher(t *T) {
parent.level = 1
}
if n, ok := m.fullName(parent, tc.sub); ok != tc.ok {
- t.Errorf("pattern: %q, parent: %q, sub %q: got %v; want %v",
- tc.pattern, tc.parent, tc.sub, ok, tc.ok, n)
+ t.Errorf("for pattern %q, fullName(parent=%q, sub=%q) = %q, ok %v; want ok %v",
+ tc.pattern, tc.parent, tc.sub, n, ok, tc.ok)
}
}
}
From a8a2b38fb9e3886b6942621bf4b24ae062f0460b Mon Sep 17 00:00:00 2001
From: Michael Munday
Date: Thu, 12 May 2016 12:09:18 -0400
Subject: [PATCH 084/267] cmd/compile/internal/gc: minor cleanup of init.go
comments
Step 5 was deleted in f3575a9 however the numbering of the other
steps wasn't adjusted accordingly.
While we're here: clean up the whitespace, add curly braces where
appropriate and delete semicolons.
Change-Id: I4e77b2d3ee8460abe4bfb993674f83e35be8ff17
Reviewed-on: https://go-review.googlesource.com/23066
Reviewed-by: Brad Fitzpatrick
---
src/cmd/compile/internal/gc/init.go | 39 +++++++++++++++--------------
1 file changed, 20 insertions(+), 19 deletions(-)
diff --git a/src/cmd/compile/internal/gc/init.go b/src/cmd/compile/internal/gc/init.go
index 6c9223b57a1b25..67a050a9cad136 100644
--- a/src/cmd/compile/internal/gc/init.go
+++ b/src/cmd/compile/internal/gc/init.go
@@ -31,21 +31,22 @@ func renameinit() *Sym {
}
// hand-craft the following initialization code
-// var initdone· uint8 (1)
-// func init() (2)
+// var initdone· uint8 (1)
+// func init() { (2)
// if initdone· > 1 { (3)
// return (3a)
-// if initdone· == 1 { (4)
-// throw(); (4a)
-// }
-// initdone· = 1; (6)
-// // over all matching imported symbols
-// .init() (7)
-// { } (8)
-// init.() // if any (9)
-// initdone· = 2; (10)
-// return (11)
-// }
+// }
+// if initdone· == 1 { (4)
+// throw() (4a)
+// }
+// initdone· = 1 (5)
+// // over all matching imported symbols
+// .init() (6)
+// { } (7)
+// init.() // if any (8)
+// initdone· = 2 (9)
+// return (10)
+// }
func anyinit(n []*Node) bool {
// are there any interesting init statements
for _, ln := range n {
@@ -132,12 +133,12 @@ func fninit(n []*Node) {
// (4a)
b.Nbody.Set1(Nod(OCALL, syslook("throwinit"), nil))
- // (6)
+ // (5)
a = Nod(OAS, gatevar, Nodintconst(1))
r = append(r, a)
- // (7)
+ // (6)
for _, s := range initSyms {
if s.Def != nil && s != initsym {
// could check that it is fn of no args/returns
@@ -146,10 +147,10 @@ func fninit(n []*Node) {
}
}
- // (8)
+ // (7)
r = append(r, nf...)
- // (9)
+ // (8)
// could check that it is fn of no args/returns
for i := 1; ; i++ {
s := LookupN("init.", i)
@@ -160,12 +161,12 @@ func fninit(n []*Node) {
r = append(r, a)
}
- // (10)
+ // (9)
a = Nod(OAS, gatevar, Nodintconst(2))
r = append(r, a)
- // (11)
+ // (10)
a = Nod(ORETURN, nil, nil)
r = append(r, a)
From ccf2c019921999f49ba2ab8cbfe70ebecc986f46 Mon Sep 17 00:00:00 2001
From: Aliaksandr Valialkin
Date: Thu, 12 May 2016 15:27:30 +0300
Subject: [PATCH 085/267] go/types: fix certain vet warnings
Updates #11041
Change-Id: I4e1c670d2b7fc04927d77c6f933cee39b7d48b6e
Reviewed-on: https://go-review.googlesource.com/23083
Reviewed-by: Brad Fitzpatrick
Run-TryBot: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
---
src/go/types/resolver.go | 2 +-
src/go/types/stmt.go | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go
index 1536df5bf1bebc..992188f0ff47b5 100644
--- a/src/go/types/resolver.go
+++ b/src/go/types/resolver.go
@@ -67,7 +67,7 @@ func (check *Checker) arityMatch(s, init *ast.ValueSpec) {
// TODO(gri) avoid declared but not used error here
} else {
// init exprs "inherited"
- check.errorf(s.Pos(), "extra init expr at %s", init.Pos())
+ check.errorf(s.Pos(), "extra init expr at %s", check.fset.Position(init.Pos()))
// TODO(gri) avoid declared but not used error here
}
case l > r && (init != nil || r != 1):
diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go
index e301f711590ff4..5764430b1bf337 100644
--- a/src/go/types/stmt.go
+++ b/src/go/types/stmt.go
@@ -123,7 +123,7 @@ func (check *Checker) multipleDefaults(list []ast.Stmt) {
}
if d != nil {
if first != nil {
- check.errorf(d.Pos(), "multiple defaults (first at %s)", first.Pos())
+ check.errorf(d.Pos(), "multiple defaults (first at %s)", check.fset.Position(first.Pos()))
} else {
first = d
}
From 7ae273923cdd5d00b72c293b57ade8a1e290a4a3 Mon Sep 17 00:00:00 2001
From: Dmitry Vyukov
Date: Tue, 3 May 2016 16:44:25 +0200
Subject: [PATCH 086/267] cmd/trace: split large traces into parts
Trace viewer cannot handle traces larger than 256MB (limit on js string size):
https://github.com/catapult-project/catapult/issues/627
And even that is problematic (chrome hangs and crashes).
Split large traces into 100MB parts. Somewhat clumsy, but I don't see any other
solution (other than rewriting trace viewer). At least it works reliably now.
Fixes #15482
Change-Id: I993b5f43d22072c6f5bd041ab5888ce176f272b2
Reviewed-on: https://go-review.googlesource.com/22731
Reviewed-by: Hyang-Ah Hana Kim
---
src/cmd/trace/main.go | 44 ++++++++++++++++----
src/cmd/trace/trace.go | 92 ++++++++++++++++++++++++++++++++++++------
2 files changed, 116 insertions(+), 20 deletions(-)
diff --git a/src/cmd/trace/main.go b/src/cmd/trace/main.go
index 2735bf13ea23e9..893719edbf8fdc 100644
--- a/src/cmd/trace/main.go
+++ b/src/cmd/trace/main.go
@@ -22,7 +22,9 @@ import (
"bufio"
"flag"
"fmt"
+ "html/template"
"internal/trace"
+ "log"
"net"
"net/http"
"os"
@@ -76,20 +78,36 @@ func main() {
if err != nil {
dief("failed to create server socket: %v\n", err)
}
- // Open browser.
+
+ log.Printf("Parsing trace...")
+ events, err := parseEvents()
+ if err != nil {
+ dief("%v\n", err)
+ }
+
+ log.Printf("Serializing trace...")
+ params := &traceParams{
+ events: events,
+ endTime: int64(1<<63 - 1),
+ }
+ data := generateTrace(params)
+
+ log.Printf("Splitting trace...")
+ ranges = splitTrace(data)
+
+ log.Printf("Opening browser")
if !startBrowser("http://" + ln.Addr().String()) {
fmt.Fprintf(os.Stderr, "Trace viewer is listening on http://%s\n", ln.Addr().String())
}
- // Parse and symbolize trace asynchronously while browser opens.
- go parseEvents()
-
// Start http server.
http.HandleFunc("/", httpMain)
err = http.Serve(ln, nil)
dief("failed to start http server: %v\n", err)
}
+var ranges []Range
+
var loader struct {
once sync.Once
events []*trace.Event
@@ -118,13 +136,23 @@ func parseEvents() ([]*trace.Event, error) {
// httpMain serves the starting page.
func httpMain(w http.ResponseWriter, r *http.Request) {
- w.Write(templMain)
+ if err := templMain.Execute(w, ranges); err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
}
-var templMain = []byte(`
+var templMain = template.Must(template.New("").Parse(`
-View trace
+{{if $}}
+ {{range $e := $}}
+ View trace ({{$e.Name}})
+ {{end}}
+
+{{else}}
+ View trace
+{{end}}
Goroutine analysis
Network blocking profile
Synchronization blocking profile
@@ -132,7 +160,7 @@ var templMain = []byte(`
Scheduler latency profile
-`)
+`))
// startBrowser tries to open the URL in a browser
// and reports whether it succeeds.
diff --git a/src/cmd/trace/trace.go b/src/cmd/trace/trace.go
index 7782a5efc8dd33..2b6a37bfd8dbcb 100644
--- a/src/cmd/trace/trace.go
+++ b/src/cmd/trace/trace.go
@@ -14,6 +14,7 @@ import (
"runtime"
"strconv"
"strings"
+ "time"
)
func init() {
@@ -29,17 +30,11 @@ func httpTrace(w http.ResponseWriter, r *http.Request) {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
-
- params := ""
- if goids := r.FormValue("goid"); goids != "" {
- goid, err := strconv.ParseUint(goids, 10, 64)
- if err != nil {
- http.Error(w, fmt.Sprintf("failed to parse goid parameter '%v': %v", goids, err), http.StatusInternalServerError)
- return
- }
- params = fmt.Sprintf("?goid=%v", goid)
+ if err := r.ParseForm(); err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
}
- html := strings.Replace(templTrace, "{{PARAMS}}", params, -1)
+ html := strings.Replace(templTrace, "{{PARAMS}}", r.Form.Encode(), -1)
w.Write([]byte(html))
}
@@ -118,7 +113,7 @@ var templTrace = `
viewer.globalMode = true;
document.body.appendChild(viewer);
- url = '/jsontrace{{PARAMS}}';
+ url = '/jsontrace?{{PARAMS}}';
load();
});
}());
@@ -150,6 +145,7 @@ func httpJsonTrace(w http.ResponseWriter, r *http.Request) {
}
if goids := r.FormValue("goid"); goids != "" {
+ // If goid argument is present, we are rendering a trace for this particular goroutine.
goid, err := strconv.ParseUint(goids, 10, 64)
if err != nil {
log.Printf("failed to parse goid parameter '%v': %v", goids, err)
@@ -164,13 +160,81 @@ func httpJsonTrace(w http.ResponseWriter, r *http.Request) {
params.gs = trace.RelatedGoroutines(events, goid)
}
- err = json.NewEncoder(w).Encode(generateTrace(params))
+ data := generateTrace(params)
+
+ if startStr, endStr := r.FormValue("start"), r.FormValue("end"); startStr != "" && endStr != "" {
+ // If start/end arguments are present, we are rendering a range of the trace.
+ start, err := strconv.ParseUint(startStr, 10, 64)
+ if err != nil {
+ log.Printf("failed to parse start parameter '%v': %v", startStr, err)
+ return
+ }
+ end, err := strconv.ParseUint(endStr, 10, 64)
+ if err != nil {
+ log.Printf("failed to parse end parameter '%v': %v", endStr, err)
+ return
+ }
+ if start >= uint64(len(data.Events)) || end <= start || end > uint64(len(data.Events)) {
+ log.Printf("bogus start/end parameters: %v/%v, trace size %v", start, end, len(data.Events))
+ return
+ }
+ data.Events = append(data.Events[start:end], data.Events[data.footer:]...)
+ }
+ err = json.NewEncoder(w).Encode(data)
if err != nil {
log.Printf("failed to serialize trace: %v", err)
return
}
}
+type Range struct {
+ Name string
+ Start int
+ End int
+}
+
+// splitTrace splits the trace into a number of ranges,
+// each resulting in approx 100MB of json output (trace viewer can hardly handle more).
+func splitTrace(data ViewerData) []Range {
+ const rangeSize = 100 << 20
+ var ranges []Range
+ cw := new(countingWriter)
+ enc := json.NewEncoder(cw)
+ // First calculate size of the mandatory part of the trace.
+ // This includes stack traces and thread names.
+ data1 := data
+ data1.Events = data.Events[data.footer:]
+ enc.Encode(data1)
+ auxSize := cw.size
+ cw.size = 0
+ // Then calculate size of each individual event and group them into ranges.
+ for i, start := 0, 0; i < data.footer; i++ {
+ enc.Encode(data.Events[i])
+ if cw.size+auxSize > rangeSize || i == data.footer-1 {
+ ranges = append(ranges, Range{
+ Name: fmt.Sprintf("%v-%v", time.Duration(data.Events[start].Time*1000), time.Duration(data.Events[i].Time*1000)),
+ Start: start,
+ End: i + 1,
+ })
+ start = i + 1
+ cw.size = 0
+ }
+ }
+ if len(ranges) == 1 {
+ ranges = nil
+ }
+ return ranges
+}
+
+type countingWriter struct {
+ size int
+}
+
+func (cw *countingWriter) Write(data []byte) (int, error) {
+ cw.size += len(data)
+ return len(data), nil
+}
+
type traceParams struct {
events []*trace.Event
gtrace bool
@@ -204,6 +268,9 @@ type ViewerData struct {
Events []*ViewerEvent `json:"traceEvents"`
Frames map[string]ViewerFrame `json:"stackFrames"`
TimeUnit string `json:"displayTimeUnit"`
+
+ // This is where mandatory part of the trace starts (e.g. thread names)
+ footer int
}
type ViewerEvent struct {
@@ -355,6 +422,7 @@ func generateTrace(params *traceParams) ViewerData {
}
}
+ ctx.data.footer = len(ctx.data.Events)
ctx.emit(&ViewerEvent{Name: "process_name", Phase: "M", Pid: 0, Arg: &NameArg{"PROCS"}})
ctx.emit(&ViewerEvent{Name: "process_sort_index", Phase: "M", Pid: 0, Arg: &SortIndexArg{1}})
From 7af2ce3f159760033c903b3730bfb5995b4edd40 Mon Sep 17 00:00:00 2001
From: Emmanuel Odeke
Date: Tue, 10 May 2016 21:28:30 -0700
Subject: [PATCH 087/267] cmd/build: reject non-existant directories in
ImportDir
Re-apply @adg's CL https://golang.org/cl/7129048 that was
previously disabled in https://golang.org/cl/7235052 because
it broke `godoc net/http` for go1.1.
Currently `godoc net/http` seems to work fine with this CL.
Fixes #3428.
Change-Id: I7df06df02fd62dededac6ec60bea62561be59cf1
Reviewed-on: https://go-review.googlesource.com/23013
Run-TryBot: Andrew Gerrand
TryBot-Result: Gobot Gobot
Reviewed-by: Andrew Gerrand
---
src/go/build/build.go | 6 +++++-
src/go/build/build_test.go | 11 +++++++++++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/src/go/build/build.go b/src/go/build/build.go
index fa258d3dc671a4..0818aa050178b9 100644
--- a/src/go/build/build.go
+++ b/src/go/build/build.go
@@ -403,7 +403,11 @@ func (p *Package) IsCommand() bool {
// ImportDir is like Import but processes the Go package found in
// the named directory.
func (ctxt *Context) ImportDir(dir string, mode ImportMode) (*Package, error) {
- return ctxt.Import(".", dir, mode)
+ p, err := ctxt.Import(".", dir, mode)
+ if err == nil && !ctxt.isDir(p.Dir) {
+ err = fmt.Errorf("%q is not a directory", p.Dir)
+ }
+ return p, err
}
// NoGoError is the error used by Import to describe a directory
diff --git a/src/go/build/build_test.go b/src/go/build/build_test.go
index c9f906a7da6d0a..6bade1d318c6e7 100644
--- a/src/go/build/build_test.go
+++ b/src/go/build/build_test.go
@@ -5,6 +5,7 @@
package build
import (
+ "fmt"
"internal/testenv"
"io"
"os"
@@ -345,3 +346,13 @@ func TestImportVendorParentFailure(t *testing.T) {
t.Fatalf("error on failed import does not mention GOROOT/src/vendor directory:\n%s", e)
}
}
+
+// Issue 3248
+func TestBogusDirectory(t *testing.T) {
+ const dir = "/foo/bar/baz/gopher"
+ _, err := ImportDir(dir, FindOnly)
+ want := fmt.Sprintf("%q is not a directory", filepath.FromSlash(dir))
+ if err == nil || err.Error() != want {
+ t.Errorf("got error %q, want %q", err, want)
+ }
+}
From 8f48efb31c7cdddeec7d4221174254466b0891dd Mon Sep 17 00:00:00 2001
From: Mohit Agarwal
Date: Fri, 13 May 2016 02:05:48 +0530
Subject: [PATCH 088/267] fmt: remove extra space in too few arguments example
Change-Id: Iae4855c52c4da9755277251d22121226507ea26a
Reviewed-on: https://go-review.googlesource.com/23074
Reviewed-by: Brad Fitzpatrick
---
src/fmt/doc.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/fmt/doc.go b/src/fmt/doc.go
index fefc10c19de8ad..c312914b44a48b 100644
--- a/src/fmt/doc.go
+++ b/src/fmt/doc.go
@@ -210,7 +210,7 @@
Too many arguments: %!(EXTRA type=value)
Printf("hi", "guys"): hi%!(EXTRA string=guys)
Too few arguments: %!verb(MISSING)
- Printf("hi%d"): hi %!d(MISSING)
+ Printf("hi%d"): hi%!d(MISSING)
Non-int for width or precision: %!(BADWIDTH) or %!(BADPREC)
Printf("%*s", 4.5, "hi"): %!(BADWIDTH)hi
Printf("%.*s", 4.5, "hi"): %!(BADPREC)hi
From eb69476c66339ca494f98e65a78d315da99a9c79 Mon Sep 17 00:00:00 2001
From: Andrew Gerrand
Date: Thu, 12 May 2016 13:55:46 -0700
Subject: [PATCH 089/267] text/template: detect pathologically recursive
template invocations
Return an error message instead of eating memory and eventually
triggering a stack overflow.
Fixes #15618
Change-Id: I3dcf1d669104690a17847a20fbfeb6d7e39e8751
Reviewed-on: https://go-review.googlesource.com/23091
Reviewed-by: Rob Pike
---
src/text/template/exec.go | 19 +++++++++++++++----
src/text/template/exec_test.go | 13 +++++++++++++
2 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/src/text/template/exec.go b/src/text/template/exec.go
index 22881c685279f6..8e5ad93ca6b5b8 100644
--- a/src/text/template/exec.go
+++ b/src/text/template/exec.go
@@ -15,14 +15,21 @@ import (
"text/template/parse"
)
+// maxExecDepth specifies the maximum stack depth of templates within
+// templates. This limit is only practically reached by accidentally
+// recursive template invocations. This limit allows us to return
+// an error instead of triggering a stack overflow.
+const maxExecDepth = 100000
+
// state represents the state of an execution. It's not part of the
// template so that multiple executions of the same template
// can execute in parallel.
type state struct {
- tmpl *Template
- wr io.Writer
- node parse.Node // current node, for errors
- vars []variable // push-down stack of variable values.
+ tmpl *Template
+ wr io.Writer
+ node parse.Node // current node, for errors
+ vars []variable // push-down stack of variable values.
+ depth int // the height of the stack of executing templates.
}
// variable holds the dynamic value of a variable such as $, $x etc.
@@ -363,9 +370,13 @@ func (s *state) walkTemplate(dot reflect.Value, t *parse.TemplateNode) {
if tmpl == nil {
s.errorf("template %q not defined", t.Name)
}
+ if s.depth == maxExecDepth {
+ s.errorf("exceeded maximum template depth (%v)", maxExecDepth)
+ }
// Variables declared by the pipeline persist.
dot = s.evalPipeline(dot, t.Pipe)
newState := *s
+ newState.depth++
newState.tmpl = tmpl
// No dynamic scoping: template invocations inherit no variables.
newState.vars = []variable{{"$", dot}}
diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go
index bc2aa683ec9a06..3ef065edcfdebe 100644
--- a/src/text/template/exec_test.go
+++ b/src/text/template/exec_test.go
@@ -1297,3 +1297,16 @@ func TestMissingFieldOnNil(t *testing.T) {
t.Errorf("got error %q, want %q", got, want)
}
}
+
+func TestMaxExecDepth(t *testing.T) {
+ tmpl := Must(New("tmpl").Parse(`{{template "tmpl" .}}`))
+ err := tmpl.Execute(ioutil.Discard, nil)
+ got := ""
+ if err != nil {
+ got = err.Error()
+ }
+ const want = "exceeded maximum template depth"
+ if !strings.Contains(got, want) {
+ t.Errorf("got error %q; want %q", got, want)
+ }
+}
From 4cffe44e361deb39e3274774a7984ab78a5b3931 Mon Sep 17 00:00:00 2001
From: Alex Brainman
Date: Thu, 12 May 2016 15:04:05 +1000
Subject: [PATCH 090/267] syscall: separate stdlib imports from others in
mksyscall_windows.go
Change-Id: I6610b872578d161e535565258039d9f064f01456
Reviewed-on: https://go-review.googlesource.com/23070
Reviewed-by: Nigel Tao
Run-TryBot: Alex Brainman
TryBot-Result: Gobot Gobot
---
src/syscall/mksyscall_windows.go | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/src/syscall/mksyscall_windows.go b/src/syscall/mksyscall_windows.go
index 84747962ab559e..1e0d9401e746f4 100644
--- a/src/syscall/mksyscall_windows.go
+++ b/src/syscall/mksyscall_windows.go
@@ -597,14 +597,20 @@ func (f *Fn) HelperName() string {
// Source files and functions.
type Source struct {
- Funcs []*Fn
- Files []string
- Imports []string
+ Funcs []*Fn
+ Files []string
+ StdLibImports []string
+ ExternalImports []string
}
func (src *Source) Import(pkg string) {
- src.Imports = append(src.Imports, pkg)
- sort.Strings(src.Imports)
+ src.StdLibImports = append(src.StdLibImports, pkg)
+ sort.Strings(src.StdLibImports)
+}
+
+func (src *Source) ExternalImport(pkg string) {
+ src.ExternalImports = append(src.ExternalImports, pkg)
+ sort.Strings(src.ExternalImports)
}
// ParseFiles parses files listed in fs and extracts all syscall
@@ -614,9 +620,10 @@ func ParseFiles(fs []string) (*Source, error) {
src := &Source{
Funcs: make([]*Fn, 0),
Files: make([]string, 0),
- Imports: []string{
+ StdLibImports: []string{
"unsafe",
},
+ ExternalImports: make([]string, 0),
}
for _, file := range fs {
if err := src.ParseFile(file); err != nil {
@@ -731,7 +738,7 @@ func (src *Source) Generate(w io.Writer) error {
src.Import("internal/syscall/windows/sysdll")
case pkgXSysWindows:
default:
- src.Import("golang.org/x/sys/windows")
+ src.ExternalImport("golang.org/x/sys/windows")
}
}
if packageName != "syscall" {
@@ -809,7 +816,10 @@ const srcTemplate = `
package {{packagename}}
import (
-{{range .Imports}}"{{.}}"
+{{range .StdLibImports}}"{{.}}"
+{{end}}
+
+{{range .ExternalImports}}"{{.}}"
{{end}}
)
From 15f2d0e45227f68024f3415d9466055877b70426 Mon Sep 17 00:00:00 2001
From: Brad Fitzpatrick
Date: Thu, 12 May 2016 22:12:11 +0000
Subject: [PATCH 091/267] net, net/http: don't trace UDP dials
The httptrace.ConnectStart and ConnectDone hooks are just about the
post-DNS connection to the host. We were accidentally also firing on
the UDP dials to DNS. Exclude those for now. We can add them back
later as separate hooks if desired. (but they'd only work for pure Go
DNS)
This wasn't noticed earlier because I was developing on a Mac at the
time, which always uses cgo for DNS. When running other tests on
Linux, I started seeing UDP dials.
Updates #12580
Change-Id: I2b2403f2483e227308fe008019f1100f6300250b
Reviewed-on: https://go-review.googlesource.com/23069
Reviewed-by: Andrew Gerrand
Run-TryBot: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
---
src/internal/nettrace/nettrace.go | 12 +++++++-----
src/net/dial.go | 12 +++++++++++-
src/net/http/transport_test.go | 4 ++++
3 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/src/internal/nettrace/nettrace.go b/src/internal/nettrace/nettrace.go
index 51a8b2cc5ae645..0f85d727c605bd 100644
--- a/src/internal/nettrace/nettrace.go
+++ b/src/internal/nettrace/nettrace.go
@@ -32,12 +32,14 @@ type Trace struct {
// actually be for circular dependency reasons.
DNSDone func(netIPs []interface{}, coalesced bool, err error)
- // ConnectStart is called before a Dial. In the case of
- // DualStack (Happy Eyeballs) dialing, this may be called
- // multiple times, from multiple goroutines.
+ // ConnectStart is called before a TCPAddr or UnixAddr
+ // Dial. In the case of DualStack (Happy Eyeballs) dialing,
+ // this may be called multiple times, from multiple
+ // goroutines.
ConnectStart func(network, addr string)
- // ConnectStart is called after a Dial with the results. It
- // may also be called multiple times, like ConnectStart.
+ // ConnectStart is called after a TCPAddr or UnixAddr Dial
+ // with the results. It may also be called multiple times,
+ // like ConnectStart.
ConnectDone func(network, addr string, err error)
}
diff --git a/src/net/dial.go b/src/net/dial.go
index 256ef3806147c4..5985421b0661a9 100644
--- a/src/net/dial.go
+++ b/src/net/dial.go
@@ -472,11 +472,21 @@ func dialSerial(ctx context.Context, dp *dialParam, ras addrList) (Conn, error)
return nil, firstErr
}
+// traceDialType reports whether ra is an address type for which
+// nettrace.Trace should trace.
+func traceDialType(ra Addr) bool {
+ switch ra.(type) {
+ case *TCPAddr, *UnixAddr:
+ return true
+ }
+ return false
+}
+
// dialSingle attempts to establish and returns a single connection to
// the destination address.
func dialSingle(ctx context.Context, dp *dialParam, ra Addr) (c Conn, err error) {
trace, _ := ctx.Value(nettrace.TraceKey{}).(*nettrace.Trace)
- if trace != nil {
+ if trace != nil && traceDialType(ra) {
raStr := ra.String()
if trace.ConnectStart != nil {
trace.ConnectStart(dp.network, raStr)
diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go
index bde052524cb8da..ab26de2e9526a4 100644
--- a/src/net/http/transport_test.go
+++ b/src/net/http/transport_test.go
@@ -3292,6 +3292,7 @@ func testTransportEventTrace(t *testing.T, noHooks bool) {
wantSub("Getting conn for dns-is-faked.golang:" + port)
wantSub("DNS start: {Host:dns-is-faked.golang}")
wantSub("DNS done: {Addrs:[{IP:" + ip + " Zone:}] Err: Coalesced:false}")
+ wantSub("Connecting to tcp " + ts.Listener.Addr().String())
wantSub("connected to tcp " + ts.Listener.Addr().String() + " = ")
wantSub("Reused:false WasIdle:false IdleTime:0s")
wantSub("first response byte")
@@ -3299,6 +3300,9 @@ func testTransportEventTrace(t *testing.T, noHooks bool) {
wantSub("WroteRequest: {Err:}")
wantSub("Wait100Continue")
wantSub("Got100Continue")
+ if strings.Contains(got, " to udp ") {
+ t.Errorf("should not see UDP (DNS) connections")
+ }
if t.Failed() {
t.Errorf("Output:\n%s", got)
}
From be5782c330f2c743f81942f5bc1b9c1e04296d44 Mon Sep 17 00:00:00 2001
From: Dmitry Vyukov
Date: Fri, 13 May 2016 09:25:25 +0200
Subject: [PATCH 092/267] doc/go1.7.txt: add cmd/trace changes
Change-Id: Iaf455d1a2863ff752e0c398e1c364373b4d36614
Reviewed-on: https://go-review.googlesource.com/23084
Reviewed-by: Dmitry Vyukov
---
doc/go1.7.txt | 3 +++
1 file changed, 3 insertions(+)
diff --git a/doc/go1.7.txt b/doc/go1.7.txt
index adac6a367a83fd..d50f1f1032ec96 100644
--- a/doc/go1.7.txt
+++ b/doc/go1.7.txt
@@ -7,6 +7,9 @@ cmd/compile: smaller binaries (many CLs)
cmd/go, go/build: add support for Fortran (CL 19670, CL 4114)
cmd/doc: group constructors with types (CL 22354)
cmd/go, go/build: binary-only package support (CL 22433)
+cmd/trace: file:line is embed into traces (CL 21732) which makes binary argument optional (CL 22410)
+cmd/trace: now supports visualization of very large traces by splitting them into parts (CL 22731)
+cmd/trace: tracing has become significantly faster (CL 21512)
Ports:
From 2cc0f2209653f9f6931e0c3a1fb63e581a0fe87f Mon Sep 17 00:00:00 2001
From: Mikio Hara
Date: Fri, 13 May 2016 11:10:29 +0900
Subject: [PATCH 093/267] Revert "cmd/build: reject non-existant directories in
ImportDir"
This reverts commit 7af2ce3f159760033c903b3730bfb5995b4edd40.
The commit had a wrong prefix in the description line, probably
misreconginized something. As a result it broke golang.org/x/tools/godoc
and golang.org/x/tools/cmd/godoc like the following:
--- FAIL: TestCLI (10.90s)
--- FAIL: TestWeb (13.74s)
FAIL
FAIL golang.org/x/tools/cmd/godoc 36.428s
--- FAIL: TestCommandLine (0.00s)
FAIL
FAIL golang.org/x/tools/godoc 0.068s
Change-Id: I362a862a4ded8592dec7488a28e7a256adee148f
Reviewed-on: https://go-review.googlesource.com/23076
Run-TryBot: Mikio Hara
Reviewed-by: Andrew Gerrand
---
src/go/build/build.go | 6 +-----
src/go/build/build_test.go | 11 -----------
2 files changed, 1 insertion(+), 16 deletions(-)
diff --git a/src/go/build/build.go b/src/go/build/build.go
index 0818aa050178b9..fa258d3dc671a4 100644
--- a/src/go/build/build.go
+++ b/src/go/build/build.go
@@ -403,11 +403,7 @@ func (p *Package) IsCommand() bool {
// ImportDir is like Import but processes the Go package found in
// the named directory.
func (ctxt *Context) ImportDir(dir string, mode ImportMode) (*Package, error) {
- p, err := ctxt.Import(".", dir, mode)
- if err == nil && !ctxt.isDir(p.Dir) {
- err = fmt.Errorf("%q is not a directory", p.Dir)
- }
- return p, err
+ return ctxt.Import(".", dir, mode)
}
// NoGoError is the error used by Import to describe a directory
diff --git a/src/go/build/build_test.go b/src/go/build/build_test.go
index 6bade1d318c6e7..c9f906a7da6d0a 100644
--- a/src/go/build/build_test.go
+++ b/src/go/build/build_test.go
@@ -5,7 +5,6 @@
package build
import (
- "fmt"
"internal/testenv"
"io"
"os"
@@ -346,13 +345,3 @@ func TestImportVendorParentFailure(t *testing.T) {
t.Fatalf("error on failed import does not mention GOROOT/src/vendor directory:\n%s", e)
}
}
-
-// Issue 3248
-func TestBogusDirectory(t *testing.T) {
- const dir = "/foo/bar/baz/gopher"
- _, err := ImportDir(dir, FindOnly)
- want := fmt.Sprintf("%q is not a directory", filepath.FromSlash(dir))
- if err == nil || err.Error() != want {
- t.Errorf("got error %q, want %q", err, want)
- }
-}
From 0cc710dca63b79ed2dd6ce9375502e76e5fc0484 Mon Sep 17 00:00:00 2001
From: David Crawshaw
Date: Fri, 13 May 2016 12:33:27 -0400
Subject: [PATCH 094/267] reflect: fix method type string
By picking up a spurious tFlagExtraStar, the method type was printing
as unc instead of func.
Updates #15673
Change-Id: I0c2c189b99bdd4caeb393693be7520b8e3f342bf
Reviewed-on: https://go-review.googlesource.com/23103
Reviewed-by: Ian Lance Taylor
Run-TryBot: Ian Lance Taylor
TryBot-Result: Gobot Gobot
---
src/reflect/all_test.go | 21 +++++++++++++++++++++
src/reflect/type.go | 1 +
2 files changed, 22 insertions(+)
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index 5beec63273b526..9799fee3573557 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -5782,3 +5782,24 @@ func TestMethodPkgPathReadable(t *testing.T) {
t.Errorf(`PkgPath=%q, want "reflect"`, m.PkgPath)
}
}
+
+func TestTypeStrings(t *testing.T) {
+ type stringTest struct {
+ typ Type
+ want string
+ }
+ stringTests := []stringTest{
+ {TypeOf(func(int) {}), "func(int)"},
+ {FuncOf([]Type{TypeOf(int(0))}, nil, false), "func(int)"},
+ {TypeOf(XM{}), "reflect_test.XM"},
+ {TypeOf(new(XM)), "*reflect_test.XM"},
+ {TypeOf(new(XM).String), "func() string"},
+ {TypeOf(new(XM)).Method(0).Type, "func(*reflect_test.XM) string"},
+ }
+
+ for i, test := range stringTests {
+ if got, want := test.typ.String(), test.want; got != want {
+ t.Errorf("type %d String()=%q, want %q", i, got, want)
+ }
+ }
+}
diff --git a/src/reflect/type.go b/src/reflect/type.go
index 5c6e3d55009d7e..3bfff4a7cc6aa0 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -1985,6 +1985,7 @@ func FuncOf(in, out []Type, variadic bool) Type {
if len(args) > 50 {
panic("reflect.FuncOf does not support more than 50 arguments")
}
+ ft.tflag = 0
ft.hash = hash
ft.inCount = uint16(len(in))
ft.outCount = uint16(len(out))
From 19619c21c36d1695000f5b798241971dfdb2cc2d Mon Sep 17 00:00:00 2001
From: Tom Bergan
Date: Thu, 12 May 2016 22:03:46 -0700
Subject: [PATCH 095/267] net, net/http: don't trace DNS dials
This fixes change https://go-review.googlesource.com/#/c/23069/, which
assumes all DNS requests are UDP. This is not true -- DNS requests can
be TCP in some cases. See:
https://tip.golang.org/src/net/dnsclient_unix.go#L154
https://en.wikipedia.org/wiki/Domain_Name_System#Protocol_transport
Also, the test code added by the above change doesn't actually test
anything because the test uses a faked DNS resolver that doesn't
actually make any DNS queries. I fixed that by adding another test
that uses the system DNS resolver.
Updates #12580
Change-Id: I6c24c03ebab84d437d3ac610fd6eb5353753c490
Reviewed-on: https://go-review.googlesource.com/23101
Reviewed-by: Brad Fitzpatrick
Run-TryBot: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
---
src/internal/nettrace/nettrace.go | 12 ++++----
src/net/dial.go | 23 ++++++++--------
src/net/http/transport_test.go | 46 +++++++++++++++++++++++++++++++
3 files changed, 63 insertions(+), 18 deletions(-)
diff --git a/src/internal/nettrace/nettrace.go b/src/internal/nettrace/nettrace.go
index 0f85d727c605bd..de3254df589f0e 100644
--- a/src/internal/nettrace/nettrace.go
+++ b/src/internal/nettrace/nettrace.go
@@ -32,14 +32,14 @@ type Trace struct {
// actually be for circular dependency reasons.
DNSDone func(netIPs []interface{}, coalesced bool, err error)
- // ConnectStart is called before a TCPAddr or UnixAddr
- // Dial. In the case of DualStack (Happy Eyeballs) dialing,
- // this may be called multiple times, from multiple
+ // ConnectStart is called before a Dial, excluding Dials made
+ // during DNS lookups. In the case of DualStack (Happy Eyeballs)
+ // dialing, this may be called multiple times, from multiple
// goroutines.
ConnectStart func(network, addr string)
- // ConnectStart is called after a TCPAddr or UnixAddr Dial
- // with the results. It may also be called multiple times,
- // like ConnectStart.
+ // ConnectStart is called after a Dial with the results, excluding
+ // Dials made during DNS lookups. It may also be called multiple
+ // times, like ConnectStart.
ConnectDone func(network, addr string, err error)
}
diff --git a/src/net/dial.go b/src/net/dial.go
index 5985421b0661a9..16f67a2f337427 100644
--- a/src/net/dial.go
+++ b/src/net/dial.go
@@ -317,7 +317,16 @@ func (d *Dialer) DialContext(ctx context.Context, network, address string) (Conn
ctx = subCtx
}
- addrs, err := resolveAddrList(ctx, "dial", network, address, d.LocalAddr)
+ // Shadow the nettrace (if any) during resolve so Connect events don't fire for DNS lookups.
+ resolveCtx := ctx
+ if trace, _ := ctx.Value(nettrace.TraceKey{}).(*nettrace.Trace); trace != nil {
+ shadow := *trace
+ shadow.ConnectStart = nil
+ shadow.ConnectDone = nil
+ resolveCtx = context.WithValue(resolveCtx, nettrace.TraceKey{}, &shadow)
+ }
+
+ addrs, err := resolveAddrList(resolveCtx, "dial", network, address, d.LocalAddr)
if err != nil {
return nil, &OpError{Op: "dial", Net: network, Source: nil, Addr: nil, Err: err}
}
@@ -472,21 +481,11 @@ func dialSerial(ctx context.Context, dp *dialParam, ras addrList) (Conn, error)
return nil, firstErr
}
-// traceDialType reports whether ra is an address type for which
-// nettrace.Trace should trace.
-func traceDialType(ra Addr) bool {
- switch ra.(type) {
- case *TCPAddr, *UnixAddr:
- return true
- }
- return false
-}
-
// dialSingle attempts to establish and returns a single connection to
// the destination address.
func dialSingle(ctx context.Context, dp *dialParam, ra Addr) (c Conn, err error) {
trace, _ := ctx.Value(nettrace.TraceKey{}).(*nettrace.Trace)
- if trace != nil && traceDialType(ra) {
+ if trace != nil {
raStr := ra.String()
if trace.ConnectStart != nil {
trace.ConnectStart(dp.network, raStr)
diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go
index ab26de2e9526a4..328fd5727b9e6b 100644
--- a/src/net/http/transport_test.go
+++ b/src/net/http/transport_test.go
@@ -3308,6 +3308,52 @@ func testTransportEventTrace(t *testing.T, noHooks bool) {
}
}
+func TestTransportEventTraceRealDNS(t *testing.T) {
+ defer afterTest(t)
+ tr := &Transport{}
+ defer tr.CloseIdleConnections()
+ c := &Client{Transport: tr}
+
+ var mu sync.Mutex
+ var buf bytes.Buffer
+ logf := func(format string, args ...interface{}) {
+ mu.Lock()
+ defer mu.Unlock()
+ fmt.Fprintf(&buf, format, args...)
+ buf.WriteByte('\n')
+ }
+
+ req, _ := NewRequest("GET", "http://dns-should-not-resolve.golang:80", nil)
+ trace := &httptrace.ClientTrace{
+ DNSStart: func(e httptrace.DNSStartInfo) { logf("DNSStart: %+v", e) },
+ DNSDone: func(e httptrace.DNSDoneInfo) { logf("DNSDone: %+v", e) },
+ ConnectStart: func(network, addr string) { logf("ConnectStart: %s %s", network, addr) },
+ ConnectDone: func(network, addr string, err error) { logf("ConnectDone: %s %s %v", network, addr, err) },
+ }
+ req = req.WithContext(httptrace.WithClientTrace(context.Background(), trace))
+
+ resp, err := c.Do(req)
+ if err == nil {
+ resp.Body.Close()
+ t.Fatal("expected error during DNS lookup")
+ }
+
+ got := buf.String()
+ wantSub := func(sub string) {
+ if !strings.Contains(got, sub) {
+ t.Errorf("expected substring %q in output.", sub)
+ }
+ }
+ wantSub("DNSStart: {Host:dns-should-not-resolve.golang}")
+ wantSub("DNSDone: {Addrs:[] Err:")
+ if strings.Contains(got, "ConnectStart") || strings.Contains(got, "ConnectDone") {
+ t.Errorf("should not see Connect events")
+ }
+ if t.Failed() {
+ t.Errorf("Output:\n%s", got)
+ }
+}
+
func TestTransportMaxIdleConns(t *testing.T) {
defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
From 041cc148faae23714c38ec9e4388715d99aef518 Mon Sep 17 00:00:00 2001
From: Mikio Hara
Date: Fri, 13 May 2016 05:02:00 +0900
Subject: [PATCH 096/267] net: deflake TestPointToPointInterface and
TestInterfaceArrivalAndDeparture
Fixes #6879.
Change-Id: I9ed2460cf14cb9322d9521e7af910efa48abdaf0
Reviewed-on: https://go-review.googlesource.com/23112
Run-TryBot: Mikio Hara
TryBot-Result: Gobot Gobot
Reviewed-by: Ian Lance Taylor
---
src/net/interface_bsd_test.go | 9 +++++++--
src/net/interface_unix_test.go | 17 +++++++++++------
2 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/src/net/interface_bsd_test.go b/src/net/interface_bsd_test.go
index ed1af554ad4294..69b0fbcab3de30 100644
--- a/src/net/interface_bsd_test.go
+++ b/src/net/interface_bsd_test.go
@@ -9,10 +9,15 @@ package net
import (
"fmt"
"os/exec"
+ "runtime"
)
-func (ti *testInterface) setBroadcast(suffix int) error {
- ti.name = fmt.Sprintf("vlan%d", suffix)
+func (ti *testInterface) setBroadcast(vid int) error {
+ if runtime.GOOS == "openbsd" {
+ ti.name = fmt.Sprintf("vether%d", vid)
+ } else {
+ ti.name = fmt.Sprintf("vlan%d", vid)
+ }
xname, err := exec.LookPath("ifconfig")
if err != nil {
return err
diff --git a/src/net/interface_unix_test.go b/src/net/interface_unix_test.go
index 2ebf0897360be9..36510ebf080fbf 100644
--- a/src/net/interface_unix_test.go
+++ b/src/net/interface_unix_test.go
@@ -7,6 +7,7 @@
package net
import (
+ "fmt"
"os"
"os/exec"
"runtime"
@@ -24,8 +25,8 @@ type testInterface struct {
func (ti *testInterface) setup() error {
for _, cmd := range ti.setupCmds {
- if err := cmd.Run(); err != nil {
- return err
+ if out, err := cmd.CombinedOutput(); err != nil {
+ return fmt.Errorf("args=%v out=%q err=%v", cmd.Args, string(out), err)
}
}
return nil
@@ -33,8 +34,8 @@ func (ti *testInterface) setup() error {
func (ti *testInterface) teardown() error {
for _, cmd := range ti.teardownCmds {
- if err := cmd.Run(); err != nil {
- return err
+ if out, err := cmd.CombinedOutput(); err != nil {
+ return fmt.Errorf("args=%v out=%q err=%v ", cmd.Args, string(out), err)
}
}
return nil
@@ -51,6 +52,8 @@ func TestPointToPointInterface(t *testing.T) {
t.Skip("must be root")
}
+ // We suppose that using IPv4 link-local addresses doesn't
+ // harm anyone.
local, remote := "169.254.0.1", "169.254.0.254"
ip := ParseIP(remote)
for i := 0; i < 3; i++ {
@@ -100,15 +103,17 @@ func TestInterfaceArrivalAndDeparture(t *testing.T) {
t.Skip("must be root")
}
+ // We suppose that using IPv4 link-local addresses and the
+ // dot1Q ID for Token Ring and FDDI doesn't harm anyone.
local, remote := "169.254.0.1", "169.254.0.254"
ip := ParseIP(remote)
- for i := 0; i < 3; i++ {
+ for _, vid := range []int{1002, 1003, 1004, 1005} {
ift1, err := Interfaces()
if err != nil {
t.Fatal(err)
}
ti := &testInterface{local: local, remote: remote}
- if err := ti.setBroadcast(5682 + i); err != nil {
+ if err := ti.setBroadcast(vid); err != nil {
t.Skipf("test requires external command: %v", err)
}
if err := ti.setup(); err != nil {
From d8b08c3aa49d9aaac6ff34dbb8516040cc88a13a Mon Sep 17 00:00:00 2001
From: Austin Clements
Date: Wed, 11 May 2016 14:57:33 -0400
Subject: [PATCH 097/267] runtime: perform publication barrier even for noscan
objects
Currently we only execute a publication barrier for scan objects (and
skip it for noscan objects). This used to be okay because GC would
never consult the object itself (so it wouldn't observe uninitialized
memory even if it found a pointer to a noscan object), and the heap
bitmap was pre-initialized to noscan.
However, now we explicitly initialize the heap bitmap for noscan
objects when we allocate them. While the GC will still never consult
the contents of a noscan object, it does need to see the initialized
heap bitmap. Hence, we need to execute a publication barrier to make
the bitmap visible before user code can expose a pointer to the newly
allocated object even for noscan objects.
Change-Id: Ie4133c638db0d9055b4f7a8061a634d970627153
Reviewed-on: https://go-review.googlesource.com/23043
Run-TryBot: Austin Clements
TryBot-Result: Gobot Gobot
Reviewed-by: Rick Hudson
---
src/runtime/malloc.go | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go
index ae81b8681b90d1..b079a07d518456 100644
--- a/src/runtime/malloc.go
+++ b/src/runtime/malloc.go
@@ -699,16 +699,16 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
scanSize = typ.ptrdata
}
c.local_scan += scanSize
-
- // Ensure that the stores above that initialize x to
- // type-safe memory and set the heap bits occur before
- // the caller can make x observable to the garbage
- // collector. Otherwise, on weakly ordered machines,
- // the garbage collector could follow a pointer to x,
- // but see uninitialized memory or stale heap bits.
- publicationBarrier()
}
+ // Ensure that the stores above that initialize x to
+ // type-safe memory and set the heap bits occur before
+ // the caller can make x observable to the garbage
+ // collector. Otherwise, on weakly ordered machines,
+ // the garbage collector could follow a pointer to x,
+ // but see uninitialized memory or stale heap bits.
+ publicationBarrier()
+
// Allocate black during GC.
// All slots hold nil so no scanning is needed.
// This may be racing with GC so do it atomically if there can be
From 6181db53dbfec513300a236debbdc01735f00c07 Mon Sep 17 00:00:00 2001
From: Austin Clements
Date: Thu, 12 May 2016 18:10:03 -0400
Subject: [PATCH 098/267] runtime: improve heapBitsSetType documentation
Currently the heapBitsSetType documentation says that there are no
races on the heap bitmap, but that isn't exactly true. There are no
*write-write* races, but there are read-write races. Expand the
documentation to explain this and why it's okay.
Change-Id: Ibd92b69bcd6524a40a9dd4ec82422b50831071ed
Reviewed-on: https://go-review.googlesource.com/23092
Reviewed-by: Rick Hudson
---
src/runtime/mbitmap.go | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/src/runtime/mbitmap.go b/src/runtime/mbitmap.go
index 27f8e66d50ce1c..ccefbcd8d62df2 100644
--- a/src/runtime/mbitmap.go
+++ b/src/runtime/mbitmap.go
@@ -847,10 +847,20 @@ func (s *mspan) countFree() int {
// malloc does not call heapBitsSetType when there are no pointers,
// because all free objects are marked as noscan during
// heapBitsSweepSpan.
+//
// There can only be one allocation from a given span active at a time,
-// so this code is not racing with other instances of itself, and
-// the bitmap for a span always falls on byte boundaries.
-// Hence, it can access the bitmap with racing.
+// and the bitmap for a span always falls on byte boundaries,
+// so there are no write-write races for access to the heap bitmap.
+// Hence, heapBitsSetType can access the bitmap without atomics.
+//
+// There can be read-write races between heapBitsSetType and things
+// that read the heap bitmap like scanobject. However, since
+// heapBitsSetType is only used for objects that have not yet been
+// made reachable, readers will ignore bits being modified by this
+// function. This does mean this function cannot transiently modify
+// bits that belong to neighboring objects. Also, on weakly-ordered
+// machines, callers must execute a store/store (publication) barrier
+// between calling this function and making the object reachable.
//
// TODO: This still has atomic accesses left over from when it could
// race with GC accessing mark bits in the bitmap. Remove these.
From 094afe0cf1aa4182d62a3aea6970933b7ae4a27d Mon Sep 17 00:00:00 2001
From: Konstantin Shaposhnikov
Date: Sat, 14 May 2016 10:27:31 +0800
Subject: [PATCH 099/267] cmd/vendor: move cmd/internal/unvendor packages to
cmd/vendor
Updates #14047
Change-Id: I4b150533393bfb90e840497095ac32bcca4f04c2
Reviewed-on: https://go-review.googlesource.com/23114
Run-TryBot: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
Reviewed-by: Brad Fitzpatrick
---
misc/nacl/testzip.proto | 24 +++++++++----------
src/cmd/internal/objfile/disasm.go | 4 ++--
.../golang.org/x/arch/arm/armasm/Makefile | 0
.../golang.org/x/arch/arm/armasm/decode.go | 0
.../x/arch/arm/armasm/decode_test.go | 0
.../golang.org/x/arch/arm/armasm/ext_test.go | 0
.../golang.org/x/arch/arm/armasm/gnu.go | 0
.../golang.org/x/arch/arm/armasm/inst.go | 0
.../x/arch/arm/armasm/objdump_test.go | 0
.../x/arch/arm/armasm/objdumpext_test.go | 0
.../golang.org/x/arch/arm/armasm/plan9x.go | 0
.../golang.org/x/arch/arm/armasm/tables.go | 0
.../x/arch/arm/armasm/testdata/Makefile | 0
.../x/arch/arm/armasm/testdata/decode.txt | 0
.../golang.org/x/arch/x86/x86asm/Makefile | 0
.../golang.org/x/arch/x86/x86asm/decode.go | 0
.../x/arch/x86/x86asm/decode_test.go | 0
.../golang.org/x/arch/x86/x86asm/ext_test.go | 0
.../golang.org/x/arch/x86/x86asm/gnu.go | 0
.../golang.org/x/arch/x86/x86asm/inst.go | 0
.../golang.org/x/arch/x86/x86asm/inst_test.go | 0
.../golang.org/x/arch/x86/x86asm/intel.go | 0
.../x/arch/x86/x86asm/objdump_test.go | 0
.../x/arch/x86/x86asm/objdumpext_test.go | 0
.../x/arch/x86/x86asm/plan9ext_test.go | 0
.../golang.org/x/arch/x86/x86asm/plan9x.go | 0
.../x/arch/x86/x86asm/plan9x_test.go | 0
.../golang.org/x/arch/x86/x86asm/tables.go | 0
.../x/arch/x86/x86asm/testdata/Makefile | 0
.../x/arch/x86/x86asm/testdata/decode.txt | 0
.../x/arch/x86/x86asm/testdata/libmach8db.c | 0
.../golang.org/x/arch/x86/x86asm/xed_test.go | 0
.../x/arch/x86/x86asm/xedext_test.go | 0
.../{internal/unvendor => vendor}/vendor.json | 0
34 files changed, 14 insertions(+), 14 deletions(-)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/arm/armasm/Makefile (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/arm/armasm/decode.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/arm/armasm/decode_test.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/arm/armasm/ext_test.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/arm/armasm/gnu.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/arm/armasm/inst.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/arm/armasm/objdump_test.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/arm/armasm/objdumpext_test.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/arm/armasm/plan9x.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/arm/armasm/tables.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/arm/armasm/testdata/Makefile (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/arm/armasm/testdata/decode.txt (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/x86/x86asm/Makefile (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/x86/x86asm/decode.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/x86/x86asm/decode_test.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/x86/x86asm/ext_test.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/x86/x86asm/gnu.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/x86/x86asm/inst.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/x86/x86asm/inst_test.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/x86/x86asm/intel.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/x86/x86asm/objdump_test.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/x86/x86asm/objdumpext_test.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/x86/x86asm/plan9ext_test.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/x86/x86asm/plan9x.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/x86/x86asm/plan9x_test.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/x86/x86asm/tables.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/x86/x86asm/testdata/Makefile (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/x86/x86asm/testdata/decode.txt (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/x86/x86asm/xed_test.go (100%)
rename src/cmd/{internal/unvendor => vendor}/golang.org/x/arch/x86/x86asm/xedext_test.go (100%)
rename src/cmd/{internal/unvendor => vendor}/vendor.json (100%)
diff --git a/misc/nacl/testzip.proto b/misc/nacl/testzip.proto
index 8c14b87f0a5299..8a8784c8be011c 100644
--- a/misc/nacl/testzip.proto
+++ b/misc/nacl/testzip.proto
@@ -27,23 +27,23 @@ go src=..
internal
objfile
objfile.go
- unvendor
- golang.org
- x
- arch
- arm
- armasm
- testdata
- +
- x86
- x86asm
- testdata
- +
gofmt
gofmt.go
gofmt_test.go
testdata
+
+ vendor
+ golang.org
+ x
+ arch
+ arm
+ armasm
+ testdata
+ +
+ x86
+ x86asm
+ testdata
+ +
archive
tar
testdata
diff --git a/src/cmd/internal/objfile/disasm.go b/src/cmd/internal/objfile/disasm.go
index d63f8f616f189e..25c3301ab88805 100644
--- a/src/cmd/internal/objfile/disasm.go
+++ b/src/cmd/internal/objfile/disasm.go
@@ -15,8 +15,8 @@ import (
"strings"
"text/tabwriter"
- "cmd/internal/unvendor/golang.org/x/arch/arm/armasm"
- "cmd/internal/unvendor/golang.org/x/arch/x86/x86asm"
+ "golang.org/x/arch/arm/armasm"
+ "golang.org/x/arch/x86/x86asm"
)
// Disasm is a disassembler for a given File.
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/Makefile b/src/cmd/vendor/golang.org/x/arch/arm/armasm/Makefile
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/Makefile
rename to src/cmd/vendor/golang.org/x/arch/arm/armasm/Makefile
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode.go b/src/cmd/vendor/golang.org/x/arch/arm/armasm/decode.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode.go
rename to src/cmd/vendor/golang.org/x/arch/arm/armasm/decode.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode_test.go b/src/cmd/vendor/golang.org/x/arch/arm/armasm/decode_test.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode_test.go
rename to src/cmd/vendor/golang.org/x/arch/arm/armasm/decode_test.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/ext_test.go b/src/cmd/vendor/golang.org/x/arch/arm/armasm/ext_test.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/ext_test.go
rename to src/cmd/vendor/golang.org/x/arch/arm/armasm/ext_test.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/gnu.go b/src/cmd/vendor/golang.org/x/arch/arm/armasm/gnu.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/gnu.go
rename to src/cmd/vendor/golang.org/x/arch/arm/armasm/gnu.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/inst.go b/src/cmd/vendor/golang.org/x/arch/arm/armasm/inst.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/inst.go
rename to src/cmd/vendor/golang.org/x/arch/arm/armasm/inst.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdump_test.go b/src/cmd/vendor/golang.org/x/arch/arm/armasm/objdump_test.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdump_test.go
rename to src/cmd/vendor/golang.org/x/arch/arm/armasm/objdump_test.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdumpext_test.go b/src/cmd/vendor/golang.org/x/arch/arm/armasm/objdumpext_test.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdumpext_test.go
rename to src/cmd/vendor/golang.org/x/arch/arm/armasm/objdumpext_test.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/plan9x.go b/src/cmd/vendor/golang.org/x/arch/arm/armasm/plan9x.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/plan9x.go
rename to src/cmd/vendor/golang.org/x/arch/arm/armasm/plan9x.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/tables.go b/src/cmd/vendor/golang.org/x/arch/arm/armasm/tables.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/tables.go
rename to src/cmd/vendor/golang.org/x/arch/arm/armasm/tables.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/testdata/Makefile b/src/cmd/vendor/golang.org/x/arch/arm/armasm/testdata/Makefile
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/testdata/Makefile
rename to src/cmd/vendor/golang.org/x/arch/arm/armasm/testdata/Makefile
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/testdata/decode.txt b/src/cmd/vendor/golang.org/x/arch/arm/armasm/testdata/decode.txt
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/testdata/decode.txt
rename to src/cmd/vendor/golang.org/x/arch/arm/armasm/testdata/decode.txt
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/Makefile b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/Makefile
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/Makefile
rename to src/cmd/vendor/golang.org/x/arch/x86/x86asm/Makefile
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/decode.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode.go
rename to src/cmd/vendor/golang.org/x/arch/x86/x86asm/decode.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode_test.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/decode_test.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode_test.go
rename to src/cmd/vendor/golang.org/x/arch/x86/x86asm/decode_test.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/ext_test.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/ext_test.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/ext_test.go
rename to src/cmd/vendor/golang.org/x/arch/x86/x86asm/ext_test.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/gnu.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/gnu.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/gnu.go
rename to src/cmd/vendor/golang.org/x/arch/x86/x86asm/gnu.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/inst.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/inst.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/inst.go
rename to src/cmd/vendor/golang.org/x/arch/x86/x86asm/inst.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/inst_test.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/inst_test.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/inst_test.go
rename to src/cmd/vendor/golang.org/x/arch/x86/x86asm/inst_test.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/intel.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/intel.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/intel.go
rename to src/cmd/vendor/golang.org/x/arch/x86/x86asm/intel.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdump_test.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/objdump_test.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdump_test.go
rename to src/cmd/vendor/golang.org/x/arch/x86/x86asm/objdump_test.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdumpext_test.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/objdumpext_test.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdumpext_test.go
rename to src/cmd/vendor/golang.org/x/arch/x86/x86asm/objdumpext_test.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9ext_test.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9ext_test.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9ext_test.go
rename to src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9ext_test.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9x.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9x.go
rename to src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9x_test.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x_test.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9x_test.go
rename to src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x_test.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/tables.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/tables.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/tables.go
rename to src/cmd/vendor/golang.org/x/arch/x86/x86asm/tables.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/Makefile b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/Makefile
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/Makefile
rename to src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/Makefile
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/decode.txt b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/decode.txt
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/decode.txt
rename to src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/decode.txt
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c
rename to src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/xed_test.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/xed_test.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/xed_test.go
rename to src/cmd/vendor/golang.org/x/arch/x86/x86asm/xed_test.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/xedext_test.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/xedext_test.go
similarity index 100%
rename from src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/xedext_test.go
rename to src/cmd/vendor/golang.org/x/arch/x86/x86asm/xedext_test.go
diff --git a/src/cmd/internal/unvendor/vendor.json b/src/cmd/vendor/vendor.json
similarity index 100%
rename from src/cmd/internal/unvendor/vendor.json
rename to src/cmd/vendor/vendor.json
From 5f833121cb8e7722667d17dcf07bb32e4e524f23 Mon Sep 17 00:00:00 2001
From: Kevin Burke
Date: Sat, 14 May 2016 10:23:09 -0700
Subject: [PATCH 100/267] archive/zip: use HTTPS for documentation link
The resource is available over (and redirects to) HTTPS, it seems like a good
idea to save a redirect and ensure an encrypted connection.
Change-Id: I262c7616ae289cdd756b6f67573ba6bd7e3e0ca6
Reviewed-on: https://go-review.googlesource.com/23104
Reviewed-by: Brad Fitzpatrick
---
src/archive/zip/struct.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/archive/zip/struct.go b/src/archive/zip/struct.go
index 5ee4f88f8036ba..e92d02f8a2e872 100644
--- a/src/archive/zip/struct.go
+++ b/src/archive/zip/struct.go
@@ -5,7 +5,7 @@
/*
Package zip provides support for reading and writing ZIP archives.
-See: http://www.pkware.com/documents/casestudies/APPNOTE.TXT
+See: https://www.pkware.com/documents/casestudies/APPNOTE.TXT
This package does not support disk spanning.
From 2699da180967e5d5dab2cc64deeca4680bf2b2fb Mon Sep 17 00:00:00 2001
From: Alex Brainman
Date: Fri, 13 May 2016 14:26:30 +1000
Subject: [PATCH 101/267] time: set Local.name on windows
Local.String() returns "Local" on every OS, but windows.
Change windows code to do like others.
Updates #15568
Change-Id: I7a4d2713d940e2a01cff9d7f5cefc89def07546a
Reviewed-on: https://go-review.googlesource.com/23078
Reviewed-by: Brad Fitzpatrick
---
src/time/zoneinfo_test.go | 9 +++++++++
src/time/zoneinfo_windows.go | 2 ++
2 files changed, 11 insertions(+)
diff --git a/src/time/zoneinfo_test.go b/src/time/zoneinfo_test.go
index 0b7584ab9c2ffd..4b50dc509002f0 100644
--- a/src/time/zoneinfo_test.go
+++ b/src/time/zoneinfo_test.go
@@ -61,3 +61,12 @@ func TestFirstZone(t *testing.T) {
}
}
}
+
+func TestLocationNames(t *testing.T) {
+ if time.Local.String() != "Local" {
+ t.Errorf(`invalid Local location name: got %q want "Local"`, time.Local)
+ }
+ if time.UTC.String() != "UTC" {
+ t.Errorf(`invalid UTC location name: got %q want "UTC"`, time.UTC)
+ }
+}
diff --git a/src/time/zoneinfo_windows.go b/src/time/zoneinfo_windows.go
index c753119d5db765..a6546f54b86ac7 100644
--- a/src/time/zoneinfo_windows.go
+++ b/src/time/zoneinfo_windows.go
@@ -140,6 +140,8 @@ func pseudoUnix(year int, d *syscall.Systemtime) int64 {
func initLocalFromTZI(i *syscall.Timezoneinformation) {
l := &localLoc
+ l.name = "Local"
+
nzone := 1
if i.StandardDate.Month > 0 {
nzone++
From aba7b3e91cea1c95a1803357bcf219b0591d3c12 Mon Sep 17 00:00:00 2001
From: Mikio Hara
Date: Sat, 23 Apr 2016 22:36:41 +0900
Subject: [PATCH 102/267] vendor: import golang.org/x/net/route
golang.org/x/net/route becomes vendor/golang.org/x/net/route.
At git rev 30be488 (golang.org/cl/22446)
Updates #14724.
Change-Id: I41cfb5443aeecac4c71e843c09eb8c1d4b7413ea
Reviewed-on: https://go-review.googlesource.com/22450
Reviewed-by: Brad Fitzpatrick
---
src/vendor/golang.org/x/net/route/address.go | 269 ++++++++++++
.../x/net/route/address_darwin_test.go | 63 +++
.../golang.org/x/net/route/address_test.go | 103 +++++
src/vendor/golang.org/x/net/route/binary.go | 90 ++++
.../golang.org/x/net/route/defs_darwin.go | 106 +++++
.../golang.org/x/net/route/defs_dragonfly.go | 105 +++++
.../golang.org/x/net/route/defs_freebsd.go | 329 +++++++++++++++
.../golang.org/x/net/route/defs_netbsd.go | 104 +++++
.../golang.org/x/net/route/defs_openbsd.go | 93 +++++
.../golang.org/x/net/route/interface.go | 64 +++
.../x/net/route/interface_announce.go | 32 ++
.../x/net/route/interface_classic.go | 66 +++
.../x/net/route/interface_freebsd.go | 78 ++++
.../x/net/route/interface_multicast.go | 30 ++
.../x/net/route/interface_openbsd.go | 83 ++++
src/vendor/golang.org/x/net/route/message.go | 70 ++++
.../x/net/route/message_darwin_test.go | 27 ++
.../x/net/route/message_freebsd_test.go | 106 +++++
.../golang.org/x/net/route/message_test.go | 95 +++++
src/vendor/golang.org/x/net/route/route.go | 74 ++++
.../golang.org/x/net/route/route_classic.go | 31 ++
.../golang.org/x/net/route/route_openbsd.go | 28 ++
.../golang.org/x/net/route/route_test.go | 385 ++++++++++++++++++
src/vendor/golang.org/x/net/route/sys.go | 40 ++
.../golang.org/x/net/route/sys_darwin.go | 80 ++++
.../golang.org/x/net/route/sys_dragonfly.go | 71 ++++
.../golang.org/x/net/route/sys_freebsd.go | 150 +++++++
.../golang.org/x/net/route/sys_netbsd.go | 67 +++
.../golang.org/x/net/route/sys_openbsd.go | 72 ++++
src/vendor/golang.org/x/net/route/syscall.go | 33 ++
src/vendor/golang.org/x/net/route/syscall.s | 8 +
.../golang.org/x/net/route/zsys_darwin.go | 93 +++++
.../golang.org/x/net/route/zsys_dragonfly.go | 92 +++++
.../x/net/route/zsys_freebsd_386.go | 120 ++++++
.../x/net/route/zsys_freebsd_amd64.go | 117 ++++++
.../x/net/route/zsys_freebsd_arm.go | 117 ++++++
.../golang.org/x/net/route/zsys_netbsd.go | 91 +++++
.../golang.org/x/net/route/zsys_openbsd.go | 80 ++++
38 files changed, 3662 insertions(+)
create mode 100644 src/vendor/golang.org/x/net/route/address.go
create mode 100644 src/vendor/golang.org/x/net/route/address_darwin_test.go
create mode 100644 src/vendor/golang.org/x/net/route/address_test.go
create mode 100644 src/vendor/golang.org/x/net/route/binary.go
create mode 100644 src/vendor/golang.org/x/net/route/defs_darwin.go
create mode 100644 src/vendor/golang.org/x/net/route/defs_dragonfly.go
create mode 100644 src/vendor/golang.org/x/net/route/defs_freebsd.go
create mode 100644 src/vendor/golang.org/x/net/route/defs_netbsd.go
create mode 100644 src/vendor/golang.org/x/net/route/defs_openbsd.go
create mode 100644 src/vendor/golang.org/x/net/route/interface.go
create mode 100644 src/vendor/golang.org/x/net/route/interface_announce.go
create mode 100644 src/vendor/golang.org/x/net/route/interface_classic.go
create mode 100644 src/vendor/golang.org/x/net/route/interface_freebsd.go
create mode 100644 src/vendor/golang.org/x/net/route/interface_multicast.go
create mode 100644 src/vendor/golang.org/x/net/route/interface_openbsd.go
create mode 100644 src/vendor/golang.org/x/net/route/message.go
create mode 100644 src/vendor/golang.org/x/net/route/message_darwin_test.go
create mode 100644 src/vendor/golang.org/x/net/route/message_freebsd_test.go
create mode 100644 src/vendor/golang.org/x/net/route/message_test.go
create mode 100644 src/vendor/golang.org/x/net/route/route.go
create mode 100644 src/vendor/golang.org/x/net/route/route_classic.go
create mode 100644 src/vendor/golang.org/x/net/route/route_openbsd.go
create mode 100644 src/vendor/golang.org/x/net/route/route_test.go
create mode 100644 src/vendor/golang.org/x/net/route/sys.go
create mode 100644 src/vendor/golang.org/x/net/route/sys_darwin.go
create mode 100644 src/vendor/golang.org/x/net/route/sys_dragonfly.go
create mode 100644 src/vendor/golang.org/x/net/route/sys_freebsd.go
create mode 100644 src/vendor/golang.org/x/net/route/sys_netbsd.go
create mode 100644 src/vendor/golang.org/x/net/route/sys_openbsd.go
create mode 100644 src/vendor/golang.org/x/net/route/syscall.go
create mode 100644 src/vendor/golang.org/x/net/route/syscall.s
create mode 100644 src/vendor/golang.org/x/net/route/zsys_darwin.go
create mode 100644 src/vendor/golang.org/x/net/route/zsys_dragonfly.go
create mode 100644 src/vendor/golang.org/x/net/route/zsys_freebsd_386.go
create mode 100644 src/vendor/golang.org/x/net/route/zsys_freebsd_amd64.go
create mode 100644 src/vendor/golang.org/x/net/route/zsys_freebsd_arm.go
create mode 100644 src/vendor/golang.org/x/net/route/zsys_netbsd.go
create mode 100644 src/vendor/golang.org/x/net/route/zsys_openbsd.go
diff --git a/src/vendor/golang.org/x/net/route/address.go b/src/vendor/golang.org/x/net/route/address.go
new file mode 100644
index 00000000000000..206a8371d43565
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/address.go
@@ -0,0 +1,269 @@
+// Copyright 2016 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 darwin dragonfly freebsd netbsd openbsd
+
+package route
+
+import "runtime"
+
+// An Addr represents an address associated with packet routing.
+type Addr interface {
+ // Family returns an address family.
+ Family() int
+}
+
+// A LinkAddr represents a link-layer address.
+type LinkAddr struct {
+ Index int // interface index when attached
+ Name string // interface name when attached
+ Addr []byte // link-layer address when attached
+}
+
+// Family implements the Family method of Addr interface.
+func (a *LinkAddr) Family() int { return sysAF_LINK }
+
+func parseLinkAddr(b []byte) (Addr, error) {
+ if len(b) < 8 {
+ return nil, errInvalidAddr
+ }
+ _, a, err := parseKernelLinkAddr(sysAF_LINK, b[4:])
+ if err != nil {
+ return nil, err
+ }
+ a.(*LinkAddr).Index = int(nativeEndian.Uint16(b[2:4]))
+ return a, nil
+}
+
+// parseKernelLinkAddr parses b as a link-layer address in
+// conventional BSD kernel form.
+func parseKernelLinkAddr(_ int, b []byte) (int, Addr, error) {
+ // The encoding looks like the following:
+ // +----------------------------+
+ // | Type (1 octet) |
+ // +----------------------------+
+ // | Name length (1 octet) |
+ // +----------------------------+
+ // | Address length (1 octet) |
+ // +----------------------------+
+ // | Selector length (1 octet) |
+ // +----------------------------+
+ // | Data (variable) |
+ // +----------------------------+
+ //
+ // On some platforms, all-bit-one of length field means "don't
+ // care".
+ nlen, alen, slen := int(b[1]), int(b[2]), int(b[3])
+ if nlen == 0xff {
+ nlen = 0
+ }
+ if alen == 0xff {
+ alen = 0
+ }
+ if slen == 0xff {
+ slen = 0
+ }
+ l := 4 + nlen + alen + slen
+ if len(b) < l {
+ return 0, nil, errInvalidAddr
+ }
+ data := b[4:]
+ var name string
+ var addr []byte
+ if nlen > 0 {
+ name = string(data[:nlen])
+ data = data[nlen:]
+ }
+ if alen > 0 {
+ addr = data[:alen]
+ data = data[alen:]
+ }
+ return l, &LinkAddr{Name: name, Addr: addr}, nil
+}
+
+// An Inet4Addr represents an internet address for IPv4.
+type Inet4Addr struct {
+ IP [4]byte // IP address
+}
+
+// Family implements the Family method of Addr interface.
+func (a *Inet4Addr) Family() int { return sysAF_INET }
+
+// An Inet6Addr represents an internet address for IPv6.
+type Inet6Addr struct {
+ IP [16]byte // IP address
+ ZoneID int // zone identifier
+}
+
+// Family implements the Family method of Addr interface.
+func (a *Inet6Addr) Family() int { return sysAF_INET6 }
+
+// parseInetAddr parses b as an internet address for IPv4 or IPv6.
+func parseInetAddr(af int, b []byte) (Addr, error) {
+ switch af {
+ case sysAF_INET:
+ if len(b) < 16 {
+ return nil, errInvalidAddr
+ }
+ a := &Inet4Addr{}
+ copy(a.IP[:], b[4:8])
+ return a, nil
+ case sysAF_INET6:
+ if len(b) < 28 {
+ return nil, errInvalidAddr
+ }
+ a := &Inet6Addr{ZoneID: int(nativeEndian.Uint32(b[24:28]))}
+ copy(a.IP[:], b[8:24])
+ if a.IP[0] == 0xfe && a.IP[1]&0xc0 == 0x80 || a.IP[0] == 0xff && (a.IP[1]&0x0f == 0x01 || a.IP[1]&0x0f == 0x02) {
+ // KAME based IPv6 protocol stack usually
+ // embeds the interface index in the
+ // interface-local or link-local address as
+ // the kernel-internal form.
+ id := int(bigEndian.Uint16(a.IP[2:4]))
+ if id != 0 {
+ a.ZoneID = id
+ a.IP[2], a.IP[3] = 0, 0
+ }
+ }
+ return a, nil
+ default:
+ return nil, errInvalidAddr
+ }
+}
+
+// parseKernelInetAddr parses b as an internet address in conventional
+// BSD kernel form.
+func parseKernelInetAddr(af int, b []byte) (int, Addr, error) {
+ // The encoding looks similar to the NLRI encoding.
+ // +----------------------------+
+ // | Length (1 octet) |
+ // +----------------------------+
+ // | Address prefix (variable) |
+ // +----------------------------+
+ //
+ // The differences between the kernel form and the NLRI
+ // encoding are:
+ //
+ // - The length field of the kernel form indicates the prefix
+ // length in bytes, not in bits
+ //
+ // - In the kernel form, zero value of the length field
+ // doesn't mean 0.0.0.0/0 or ::/0
+ //
+ // - The kernel form appends leading bytes to the prefix field
+ // to make the tuple to be conformed with
+ // the routing message boundary
+ l := int(b[0])
+ if runtime.GOOS == "darwin" {
+ // On Darwn, an address in the kernel form is also
+ // used as a message filler.
+ if l == 0 || len(b) > roundup(l) {
+ l = roundup(l)
+ }
+ } else {
+ l = roundup(l)
+ }
+ if len(b) < l {
+ return 0, nil, errInvalidAddr
+ }
+ // Don't reorder case expressions.
+ // The case expressions for IPv6 must come first.
+ const (
+ off4 = 4 // offset of in_addr
+ off6 = 8 // offset of in6_addr
+ )
+ switch {
+ case b[0] == 28: // size of sockaddr_in6
+ a := &Inet6Addr{}
+ copy(a.IP[:], b[off6:off6+16])
+ return int(b[0]), a, nil
+ case af == sysAF_INET6:
+ a := &Inet6Addr{}
+ if l-1 < off6 {
+ copy(a.IP[:], b[1:l])
+ } else {
+ copy(a.IP[:], b[l-off6:l])
+ }
+ return int(b[0]), a, nil
+ case b[0] == 16: // size of sockaddr_in
+ a := &Inet4Addr{}
+ copy(a.IP[:], b[off4:off4+4])
+ return int(b[0]), a, nil
+ default: // an old fashion, AF_UNSPEC or unknown means AF_INET
+ a := &Inet4Addr{}
+ if l-1 < off4 {
+ copy(a.IP[:], b[1:l])
+ } else {
+ copy(a.IP[:], b[l-off4:l])
+ }
+ return int(b[0]), a, nil
+ }
+}
+
+// A DefaultAddr represents an address of various operating
+// system-specific features.
+type DefaultAddr struct {
+ af int
+ Raw []byte // raw format of address
+}
+
+// Family implements the Family method of Addr interface.
+func (a *DefaultAddr) Family() int { return a.af }
+
+func parseDefaultAddr(b []byte) (Addr, error) {
+ if len(b) < 2 || len(b) < int(b[0]) {
+ return nil, errInvalidAddr
+ }
+ a := &DefaultAddr{af: int(b[1]), Raw: b[:b[0]]}
+ return a, nil
+}
+
+func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) ([]Addr, error) {
+ var as [sysRTAX_MAX]Addr
+ af := int(sysAF_UNSPEC)
+ for i := uint(0); i < sysRTAX_MAX && len(b) >= roundup(0); i++ {
+ if attrs&(1<> 8)
+}
+
+func (binaryLittleEndian) Uint32(b []byte) uint32 {
+ _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+}
+
+func (binaryLittleEndian) PutUint32(b []byte, v uint32) {
+ _ = b[3] // early bounds check to guarantee safety of writes below
+ b[0] = byte(v)
+ b[1] = byte(v >> 8)
+ b[2] = byte(v >> 16)
+ b[3] = byte(v >> 24)
+}
+
+func (binaryLittleEndian) Uint64(b []byte) uint64 {
+ _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
+ uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
+}
+
+type binaryBigEndian struct{}
+
+func (binaryBigEndian) Uint16(b []byte) uint16 {
+ _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint16(b[1]) | uint16(b[0])<<8
+}
+
+func (binaryBigEndian) PutUint16(b []byte, v uint16) {
+ _ = b[1] // early bounds check to guarantee safety of writes below
+ b[0] = byte(v >> 8)
+ b[1] = byte(v)
+}
+
+func (binaryBigEndian) Uint32(b []byte) uint32 {
+ _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
+}
+
+func (binaryBigEndian) PutUint32(b []byte, v uint32) {
+ _ = b[3] // early bounds check to guarantee safety of writes below
+ b[0] = byte(v >> 24)
+ b[1] = byte(v >> 16)
+ b[2] = byte(v >> 8)
+ b[3] = byte(v)
+}
+
+func (binaryBigEndian) Uint64(b []byte) uint64 {
+ _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
+ uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
+}
diff --git a/src/vendor/golang.org/x/net/route/defs_darwin.go b/src/vendor/golang.org/x/net/route/defs_darwin.go
new file mode 100644
index 00000000000000..f452ad14ce6c00
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/defs_darwin.go
@@ -0,0 +1,106 @@
+// Copyright 2016 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
+
+package route
+
+/*
+#include
+#include
+
+#include
+#include
+#include
+*/
+import "C"
+
+const (
+ sysAF_UNSPEC = C.AF_UNSPEC
+ sysAF_INET = C.AF_INET
+ sysAF_ROUTE = C.AF_ROUTE
+ sysAF_LINK = C.AF_LINK
+ sysAF_INET6 = C.AF_INET6
+
+ sysNET_RT_DUMP = C.NET_RT_DUMP
+ sysNET_RT_FLAGS = C.NET_RT_FLAGS
+ sysNET_RT_IFLIST = C.NET_RT_IFLIST
+ sysNET_RT_STAT = C.NET_RT_STAT
+ sysNET_RT_TRASH = C.NET_RT_TRASH
+ sysNET_RT_IFLIST2 = C.NET_RT_IFLIST2
+ sysNET_RT_DUMP2 = C.NET_RT_DUMP2
+ sysNET_RT_MAXID = C.NET_RT_MAXID
+)
+
+const (
+ sysCTL_MAXNAME = C.CTL_MAXNAME
+
+ sysCTL_UNSPEC = C.CTL_UNSPEC
+ sysCTL_KERN = C.CTL_KERN
+ sysCTL_VM = C.CTL_VM
+ sysCTL_VFS = C.CTL_VFS
+ sysCTL_NET = C.CTL_NET
+ sysCTL_DEBUG = C.CTL_DEBUG
+ sysCTL_HW = C.CTL_HW
+ sysCTL_MACHDEP = C.CTL_MACHDEP
+ sysCTL_USER = C.CTL_USER
+ sysCTL_MAXID = C.CTL_MAXID
+)
+
+const (
+ sysRTM_VERSION = C.RTM_VERSION
+
+ sysRTM_ADD = C.RTM_ADD
+ sysRTM_DELETE = C.RTM_DELETE
+ sysRTM_CHANGE = C.RTM_CHANGE
+ sysRTM_GET = C.RTM_GET
+ sysRTM_LOSING = C.RTM_LOSING
+ sysRTM_REDIRECT = C.RTM_REDIRECT
+ sysRTM_MISS = C.RTM_MISS
+ sysRTM_LOCK = C.RTM_LOCK
+ sysRTM_OLDADD = C.RTM_OLDADD
+ sysRTM_OLDDEL = C.RTM_OLDDEL
+ sysRTM_RESOLVE = C.RTM_RESOLVE
+ sysRTM_NEWADDR = C.RTM_NEWADDR
+ sysRTM_DELADDR = C.RTM_DELADDR
+ sysRTM_IFINFO = C.RTM_IFINFO
+ sysRTM_NEWMADDR = C.RTM_NEWMADDR
+ sysRTM_DELMADDR = C.RTM_DELMADDR
+ sysRTM_IFINFO2 = C.RTM_IFINFO2
+ sysRTM_NEWMADDR2 = C.RTM_NEWMADDR2
+ sysRTM_GET2 = C.RTM_GET2
+
+ sysRTA_DST = C.RTA_DST
+ sysRTA_GATEWAY = C.RTA_GATEWAY
+ sysRTA_NETMASK = C.RTA_NETMASK
+ sysRTA_GENMASK = C.RTA_GENMASK
+ sysRTA_IFP = C.RTA_IFP
+ sysRTA_IFA = C.RTA_IFA
+ sysRTA_AUTHOR = C.RTA_AUTHOR
+ sysRTA_BRD = C.RTA_BRD
+
+ sysRTAX_DST = C.RTAX_DST
+ sysRTAX_GATEWAY = C.RTAX_GATEWAY
+ sysRTAX_NETMASK = C.RTAX_NETMASK
+ sysRTAX_GENMASK = C.RTAX_GENMASK
+ sysRTAX_IFP = C.RTAX_IFP
+ sysRTAX_IFA = C.RTAX_IFA
+ sysRTAX_AUTHOR = C.RTAX_AUTHOR
+ sysRTAX_BRD = C.RTAX_BRD
+ sysRTAX_MAX = C.RTAX_MAX
+)
+
+const (
+ sizeofIfMsghdrDarwin15 = C.sizeof_struct_if_msghdr
+ sizeofIfaMsghdrDarwin15 = C.sizeof_struct_ifa_msghdr
+ sizeofIfmaMsghdrDarwin15 = C.sizeof_struct_ifma_msghdr
+ sizeofIfMsghdr2Darwin15 = C.sizeof_struct_if_msghdr2
+ sizeofIfmaMsghdr2Darwin15 = C.sizeof_struct_ifma_msghdr2
+ sizeofIfDataDarwin15 = C.sizeof_struct_if_data
+ sizeofIfData64Darwin15 = C.sizeof_struct_if_data64
+
+ sizeofRtMsghdrDarwin15 = C.sizeof_struct_rt_msghdr
+ sizeofRtMsghdr2Darwin15 = C.sizeof_struct_rt_msghdr2
+ sizeofRtMetricsDarwin15 = C.sizeof_struct_rt_metrics
+)
diff --git a/src/vendor/golang.org/x/net/route/defs_dragonfly.go b/src/vendor/golang.org/x/net/route/defs_dragonfly.go
new file mode 100644
index 00000000000000..c737751d76df92
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/defs_dragonfly.go
@@ -0,0 +1,105 @@
+// Copyright 2016 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
+
+package route
+
+/*
+#include
+#include
+
+#include
+#include
+#include
+*/
+import "C"
+
+const (
+ sysAF_UNSPEC = C.AF_UNSPEC
+ sysAF_INET = C.AF_INET
+ sysAF_ROUTE = C.AF_ROUTE
+ sysAF_LINK = C.AF_LINK
+ sysAF_INET6 = C.AF_INET6
+
+ sysNET_RT_DUMP = C.NET_RT_DUMP
+ sysNET_RT_FLAGS = C.NET_RT_FLAGS
+ sysNET_RT_IFLIST = C.NET_RT_IFLIST
+ sysNET_RT_MAXID = C.NET_RT_MAXID
+)
+
+const (
+ sysCTL_MAXNAME = C.CTL_MAXNAME
+
+ sysCTL_UNSPEC = C.CTL_UNSPEC
+ sysCTL_KERN = C.CTL_KERN
+ sysCTL_VM = C.CTL_VM
+ sysCTL_VFS = C.CTL_VFS
+ sysCTL_NET = C.CTL_NET
+ sysCTL_DEBUG = C.CTL_DEBUG
+ sysCTL_HW = C.CTL_HW
+ sysCTL_MACHDEP = C.CTL_MACHDEP
+ sysCTL_USER = C.CTL_USER
+ sysCTL_P1003_1B = C.CTL_P1003_1B
+ sysCTL_LWKT = C.CTL_LWKT
+ sysCTL_MAXID = C.CTL_MAXID
+)
+
+const (
+ sysRTM_VERSION = C.RTM_VERSION
+
+ sysRTM_ADD = C.RTM_ADD
+ sysRTM_DELETE = C.RTM_DELETE
+ sysRTM_CHANGE = C.RTM_CHANGE
+ sysRTM_GET = C.RTM_GET
+ sysRTM_LOSING = C.RTM_LOSING
+ sysRTM_REDIRECT = C.RTM_REDIRECT
+ sysRTM_MISS = C.RTM_MISS
+ sysRTM_LOCK = C.RTM_LOCK
+ sysRTM_OLDADD = C.RTM_OLDADD
+ sysRTM_OLDDEL = C.RTM_OLDDEL
+ sysRTM_RESOLVE = C.RTM_RESOLVE
+ sysRTM_NEWADDR = C.RTM_NEWADDR
+ sysRTM_DELADDR = C.RTM_DELADDR
+ sysRTM_IFINFO = C.RTM_IFINFO
+ sysRTM_NEWMADDR = C.RTM_NEWMADDR
+ sysRTM_DELMADDR = C.RTM_DELMADDR
+ sysRTM_IFANNOUNCE = C.RTM_IFANNOUNCE
+ sysRTM_IEEE80211 = C.RTM_IEEE80211
+
+ sysRTA_DST = C.RTA_DST
+ sysRTA_GATEWAY = C.RTA_GATEWAY
+ sysRTA_NETMASK = C.RTA_NETMASK
+ sysRTA_GENMASK = C.RTA_GENMASK
+ sysRTA_IFP = C.RTA_IFP
+ sysRTA_IFA = C.RTA_IFA
+ sysRTA_AUTHOR = C.RTA_AUTHOR
+ sysRTA_BRD = C.RTA_BRD
+ sysRTA_MPLS1 = C.RTA_MPLS1
+ sysRTA_MPLS2 = C.RTA_MPLS2
+ sysRTA_MPLS3 = C.RTA_MPLS3
+
+ sysRTAX_DST = C.RTAX_DST
+ sysRTAX_GATEWAY = C.RTAX_GATEWAY
+ sysRTAX_NETMASK = C.RTAX_NETMASK
+ sysRTAX_GENMASK = C.RTAX_GENMASK
+ sysRTAX_IFP = C.RTAX_IFP
+ sysRTAX_IFA = C.RTAX_IFA
+ sysRTAX_AUTHOR = C.RTAX_AUTHOR
+ sysRTAX_BRD = C.RTAX_BRD
+ sysRTAX_MPLS1 = C.RTAX_MPLS1
+ sysRTAX_MPLS2 = C.RTAX_MPLS2
+ sysRTAX_MPLS3 = C.RTAX_MPLS3
+ sysRTAX_MAX = C.RTAX_MAX
+)
+
+const (
+ sizeofIfMsghdrDragonFlyBSD4 = C.sizeof_struct_if_msghdr
+ sizeofIfaMsghdrDragonFlyBSD4 = C.sizeof_struct_ifa_msghdr
+ sizeofIfmaMsghdrDragonFlyBSD4 = C.sizeof_struct_ifma_msghdr
+ sizeofIfAnnouncemsghdrDragonFlyBSD4 = C.sizeof_struct_if_announcemsghdr
+
+ sizeofRtMsghdrDragonFlyBSD4 = C.sizeof_struct_rt_msghdr
+ sizeofRtMetricsDragonFlyBSD4 = C.sizeof_struct_rt_metrics
+)
diff --git a/src/vendor/golang.org/x/net/route/defs_freebsd.go b/src/vendor/golang.org/x/net/route/defs_freebsd.go
new file mode 100644
index 00000000000000..8f834e81db5557
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/defs_freebsd.go
@@ -0,0 +1,329 @@
+// Copyright 2016 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
+
+package route
+
+/*
+#include
+#include
+
+#include
+#include
+#include
+
+struct if_data_freebsd7 {
+ u_char ifi_type;
+ u_char ifi_physical;
+ u_char ifi_addrlen;
+ u_char ifi_hdrlen;
+ u_char ifi_link_state;
+ u_char ifi_spare_char1;
+ u_char ifi_spare_char2;
+ u_char ifi_datalen;
+ u_long ifi_mtu;
+ u_long ifi_metric;
+ u_long ifi_baudrate;
+ u_long ifi_ipackets;
+ u_long ifi_ierrors;
+ u_long ifi_opackets;
+ u_long ifi_oerrors;
+ u_long ifi_collisions;
+ u_long ifi_ibytes;
+ u_long ifi_obytes;
+ u_long ifi_imcasts;
+ u_long ifi_omcasts;
+ u_long ifi_iqdrops;
+ u_long ifi_noproto;
+ u_long ifi_hwassist;
+ time_t __ifi_epoch;
+ struct timeval __ifi_lastchange;
+};
+
+struct if_data_freebsd8 {
+ u_char ifi_type;
+ u_char ifi_physical;
+ u_char ifi_addrlen;
+ u_char ifi_hdrlen;
+ u_char ifi_link_state;
+ u_char ifi_spare_char1;
+ u_char ifi_spare_char2;
+ u_char ifi_datalen;
+ u_long ifi_mtu;
+ u_long ifi_metric;
+ u_long ifi_baudrate;
+ u_long ifi_ipackets;
+ u_long ifi_ierrors;
+ u_long ifi_opackets;
+ u_long ifi_oerrors;
+ u_long ifi_collisions;
+ u_long ifi_ibytes;
+ u_long ifi_obytes;
+ u_long ifi_imcasts;
+ u_long ifi_omcasts;
+ u_long ifi_iqdrops;
+ u_long ifi_noproto;
+ u_long ifi_hwassist;
+ time_t __ifi_epoch;
+ struct timeval __ifi_lastchange;
+};
+
+struct if_data_freebsd9 {
+ u_char ifi_type;
+ u_char ifi_physical;
+ u_char ifi_addrlen;
+ u_char ifi_hdrlen;
+ u_char ifi_link_state;
+ u_char ifi_spare_char1;
+ u_char ifi_spare_char2;
+ u_char ifi_datalen;
+ u_long ifi_mtu;
+ u_long ifi_metric;
+ u_long ifi_baudrate;
+ u_long ifi_ipackets;
+ u_long ifi_ierrors;
+ u_long ifi_opackets;
+ u_long ifi_oerrors;
+ u_long ifi_collisions;
+ u_long ifi_ibytes;
+ u_long ifi_obytes;
+ u_long ifi_imcasts;
+ u_long ifi_omcasts;
+ u_long ifi_iqdrops;
+ u_long ifi_noproto;
+ u_long ifi_hwassist;
+ time_t __ifi_epoch;
+ struct timeval __ifi_lastchange;
+};
+
+struct if_data_freebsd10 {
+ u_char ifi_type;
+ u_char ifi_physical;
+ u_char ifi_addrlen;
+ u_char ifi_hdrlen;
+ u_char ifi_link_state;
+ u_char ifi_vhid;
+ u_char ifi_baudrate_pf;
+ u_char ifi_datalen;
+ u_long ifi_mtu;
+ u_long ifi_metric;
+ u_long ifi_baudrate;
+ u_long ifi_ipackets;
+ u_long ifi_ierrors;
+ u_long ifi_opackets;
+ u_long ifi_oerrors;
+ u_long ifi_collisions;
+ u_long ifi_ibytes;
+ u_long ifi_obytes;
+ u_long ifi_imcasts;
+ u_long ifi_omcasts;
+ u_long ifi_iqdrops;
+ u_long ifi_noproto;
+ uint64_t ifi_hwassist;
+ time_t __ifi_epoch;
+ struct timeval __ifi_lastchange;
+};
+
+struct if_data_freebsd11 {
+ uint8_t ifi_type;
+ uint8_t ifi_physical;
+ uint8_t ifi_addrlen;
+ uint8_t ifi_hdrlen;
+ uint8_t ifi_link_state;
+ uint8_t ifi_vhid;
+ uint16_t ifi_datalen;
+ uint32_t ifi_mtu;
+ uint32_t ifi_metric;
+ uint64_t ifi_baudrate;
+ uint64_t ifi_ipackets;
+ uint64_t ifi_ierrors;
+ uint64_t ifi_opackets;
+ uint64_t ifi_oerrors;
+ uint64_t ifi_collisions;
+ uint64_t ifi_ibytes;
+ uint64_t ifi_obytes;
+ uint64_t ifi_imcasts;
+ uint64_t ifi_omcasts;
+ uint64_t ifi_iqdrops;
+ uint64_t ifi_oqdrops;
+ uint64_t ifi_noproto;
+ uint64_t ifi_hwassist;
+ union {
+ time_t tt;
+ uint64_t ph;
+ } __ifi_epoch;
+ union {
+ struct timeval tv;
+ struct {
+ uint64_t ph1;
+ uint64_t ph2;
+ } ph;
+ } __ifi_lastchange;
+};
+
+struct if_msghdr_freebsd7 {
+ u_short ifm_msglen;
+ u_char ifm_version;
+ u_char ifm_type;
+ int ifm_addrs;
+ int ifm_flags;
+ u_short ifm_index;
+ struct if_data_freebsd7 ifm_data;
+};
+
+struct if_msghdr_freebsd8 {
+ u_short ifm_msglen;
+ u_char ifm_version;
+ u_char ifm_type;
+ int ifm_addrs;
+ int ifm_flags;
+ u_short ifm_index;
+ struct if_data_freebsd8 ifm_data;
+};
+
+struct if_msghdr_freebsd9 {
+ u_short ifm_msglen;
+ u_char ifm_version;
+ u_char ifm_type;
+ int ifm_addrs;
+ int ifm_flags;
+ u_short ifm_index;
+ struct if_data_freebsd9 ifm_data;
+};
+
+struct if_msghdr_freebsd10 {
+ u_short ifm_msglen;
+ u_char ifm_version;
+ u_char ifm_type;
+ int ifm_addrs;
+ int ifm_flags;
+ u_short ifm_index;
+ struct if_data_freebsd10 ifm_data;
+};
+
+struct if_msghdr_freebsd11 {
+ u_short ifm_msglen;
+ u_char ifm_version;
+ u_char ifm_type;
+ int ifm_addrs;
+ int ifm_flags;
+ u_short ifm_index;
+ struct if_data_freebsd11 ifm_data;
+};
+*/
+import "C"
+
+const (
+ sysAF_UNSPEC = C.AF_UNSPEC
+ sysAF_INET = C.AF_INET
+ sysAF_ROUTE = C.AF_ROUTE
+ sysAF_LINK = C.AF_LINK
+ sysAF_INET6 = C.AF_INET6
+
+ sysNET_RT_DUMP = C.NET_RT_DUMP
+ sysNET_RT_FLAGS = C.NET_RT_FLAGS
+ sysNET_RT_IFLIST = C.NET_RT_IFLIST
+ sysNET_RT_IFMALIST = C.NET_RT_IFMALIST
+ sysNET_RT_IFLISTL = C.NET_RT_IFLISTL
+)
+
+const (
+ sysCTL_MAXNAME = C.CTL_MAXNAME
+
+ sysCTL_UNSPEC = C.CTL_UNSPEC
+ sysCTL_KERN = C.CTL_KERN
+ sysCTL_VM = C.CTL_VM
+ sysCTL_VFS = C.CTL_VFS
+ sysCTL_NET = C.CTL_NET
+ sysCTL_DEBUG = C.CTL_DEBUG
+ sysCTL_HW = C.CTL_HW
+ sysCTL_MACHDEP = C.CTL_MACHDEP
+ sysCTL_USER = C.CTL_USER
+ sysCTL_P1003_1B = C.CTL_P1003_1B
+)
+
+const (
+ sysRTM_VERSION = C.RTM_VERSION
+
+ sysRTM_ADD = C.RTM_ADD
+ sysRTM_DELETE = C.RTM_DELETE
+ sysRTM_CHANGE = C.RTM_CHANGE
+ sysRTM_GET = C.RTM_GET
+ sysRTM_LOSING = C.RTM_LOSING
+ sysRTM_REDIRECT = C.RTM_REDIRECT
+ sysRTM_MISS = C.RTM_MISS
+ sysRTM_LOCK = C.RTM_LOCK
+ sysRTM_RESOLVE = C.RTM_RESOLVE
+ sysRTM_NEWADDR = C.RTM_NEWADDR
+ sysRTM_DELADDR = C.RTM_DELADDR
+ sysRTM_IFINFO = C.RTM_IFINFO
+ sysRTM_NEWMADDR = C.RTM_NEWMADDR
+ sysRTM_DELMADDR = C.RTM_DELMADDR
+ sysRTM_IFANNOUNCE = C.RTM_IFANNOUNCE
+ sysRTM_IEEE80211 = C.RTM_IEEE80211
+
+ sysRTA_DST = C.RTA_DST
+ sysRTA_GATEWAY = C.RTA_GATEWAY
+ sysRTA_NETMASK = C.RTA_NETMASK
+ sysRTA_GENMASK = C.RTA_GENMASK
+ sysRTA_IFP = C.RTA_IFP
+ sysRTA_IFA = C.RTA_IFA
+ sysRTA_AUTHOR = C.RTA_AUTHOR
+ sysRTA_BRD = C.RTA_BRD
+
+ sysRTAX_DST = C.RTAX_DST
+ sysRTAX_GATEWAY = C.RTAX_GATEWAY
+ sysRTAX_NETMASK = C.RTAX_NETMASK
+ sysRTAX_GENMASK = C.RTAX_GENMASK
+ sysRTAX_IFP = C.RTAX_IFP
+ sysRTAX_IFA = C.RTAX_IFA
+ sysRTAX_AUTHOR = C.RTAX_AUTHOR
+ sysRTAX_BRD = C.RTAX_BRD
+ sysRTAX_MAX = C.RTAX_MAX
+)
+
+const (
+ sizeofIfMsghdrlFreeBSD10 = C.sizeof_struct_if_msghdrl
+ sizeofIfaMsghdrFreeBSD10 = C.sizeof_struct_ifa_msghdr
+ sizeofIfaMsghdrlFreeBSD10 = C.sizeof_struct_ifa_msghdrl
+ sizeofIfmaMsghdrFreeBSD10 = C.sizeof_struct_ifma_msghdr
+ sizeofIfAnnouncemsghdrFreeBSD10 = C.sizeof_struct_if_announcemsghdr
+
+ sizeofRtMsghdrFreeBSD10 = C.sizeof_struct_rt_msghdr
+ sizeofRtMetricsFreeBSD10 = C.sizeof_struct_rt_metrics
+
+ sizeofIfMsghdrFreeBSD7 = C.sizeof_struct_if_msghdr_freebsd7
+ sizeofIfMsghdrFreeBSD8 = C.sizeof_struct_if_msghdr_freebsd8
+ sizeofIfMsghdrFreeBSD9 = C.sizeof_struct_if_msghdr_freebsd9
+ sizeofIfMsghdrFreeBSD10 = C.sizeof_struct_if_msghdr_freebsd10
+ sizeofIfMsghdrFreeBSD11 = C.sizeof_struct_if_msghdr_freebsd11
+
+ sizeofIfDataFreeBSD7 = C.sizeof_struct_if_data_freebsd7
+ sizeofIfDataFreeBSD8 = C.sizeof_struct_if_data_freebsd8
+ sizeofIfDataFreeBSD9 = C.sizeof_struct_if_data_freebsd9
+ sizeofIfDataFreeBSD10 = C.sizeof_struct_if_data_freebsd10
+ sizeofIfDataFreeBSD11 = C.sizeof_struct_if_data_freebsd11
+
+ sizeofIfMsghdrlFreeBSD10Emu = C.sizeof_struct_if_msghdrl
+ sizeofIfaMsghdrFreeBSD10Emu = C.sizeof_struct_ifa_msghdr
+ sizeofIfaMsghdrlFreeBSD10Emu = C.sizeof_struct_ifa_msghdrl
+ sizeofIfmaMsghdrFreeBSD10Emu = C.sizeof_struct_ifma_msghdr
+ sizeofIfAnnouncemsghdrFreeBSD10Emu = C.sizeof_struct_if_announcemsghdr
+
+ sizeofRtMsghdrFreeBSD10Emu = C.sizeof_struct_rt_msghdr
+ sizeofRtMetricsFreeBSD10Emu = C.sizeof_struct_rt_metrics
+
+ sizeofIfMsghdrFreeBSD7Emu = C.sizeof_struct_if_msghdr_freebsd7
+ sizeofIfMsghdrFreeBSD8Emu = C.sizeof_struct_if_msghdr_freebsd8
+ sizeofIfMsghdrFreeBSD9Emu = C.sizeof_struct_if_msghdr_freebsd9
+ sizeofIfMsghdrFreeBSD10Emu = C.sizeof_struct_if_msghdr_freebsd10
+ sizeofIfMsghdrFreeBSD11Emu = C.sizeof_struct_if_msghdr_freebsd11
+
+ sizeofIfDataFreeBSD7Emu = C.sizeof_struct_if_data_freebsd7
+ sizeofIfDataFreeBSD8Emu = C.sizeof_struct_if_data_freebsd8
+ sizeofIfDataFreeBSD9Emu = C.sizeof_struct_if_data_freebsd9
+ sizeofIfDataFreeBSD10Emu = C.sizeof_struct_if_data_freebsd10
+ sizeofIfDataFreeBSD11Emu = C.sizeof_struct_if_data_freebsd11
+)
diff --git a/src/vendor/golang.org/x/net/route/defs_netbsd.go b/src/vendor/golang.org/x/net/route/defs_netbsd.go
new file mode 100644
index 00000000000000..b18d85e0165db9
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/defs_netbsd.go
@@ -0,0 +1,104 @@
+// Copyright 2016 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
+
+package route
+
+/*
+#include
+#include
+
+#include
+#include
+#include
+*/
+import "C"
+
+const (
+ sysAF_UNSPEC = C.AF_UNSPEC
+ sysAF_INET = C.AF_INET
+ sysAF_ROUTE = C.AF_ROUTE
+ sysAF_LINK = C.AF_LINK
+ sysAF_INET6 = C.AF_INET6
+
+ sysNET_RT_DUMP = C.NET_RT_DUMP
+ sysNET_RT_FLAGS = C.NET_RT_FLAGS
+ sysNET_RT_IFLIST = C.NET_RT_IFLIST
+ sysNET_RT_MAXID = C.NET_RT_MAXID
+)
+
+const (
+ sysCTL_MAXNAME = C.CTL_MAXNAME
+
+ sysCTL_UNSPEC = C.CTL_UNSPEC
+ sysCTL_KERN = C.CTL_KERN
+ sysCTL_VM = C.CTL_VM
+ sysCTL_VFS = C.CTL_VFS
+ sysCTL_NET = C.CTL_NET
+ sysCTL_DEBUG = C.CTL_DEBUG
+ sysCTL_HW = C.CTL_HW
+ sysCTL_MACHDEP = C.CTL_MACHDEP
+ sysCTL_USER = C.CTL_USER
+ sysCTL_DDB = C.CTL_DDB
+ sysCTL_PROC = C.CTL_PROC
+ sysCTL_VENDOR = C.CTL_VENDOR
+ sysCTL_EMUL = C.CTL_EMUL
+ sysCTL_SECURITY = C.CTL_SECURITY
+ sysCTL_MAXID = C.CTL_MAXID
+)
+
+const (
+ sysRTM_VERSION = C.RTM_VERSION
+
+ sysRTM_ADD = C.RTM_ADD
+ sysRTM_DELETE = C.RTM_DELETE
+ sysRTM_CHANGE = C.RTM_CHANGE
+ sysRTM_GET = C.RTM_GET
+ sysRTM_LOSING = C.RTM_LOSING
+ sysRTM_REDIRECT = C.RTM_REDIRECT
+ sysRTM_MISS = C.RTM_MISS
+ sysRTM_LOCK = C.RTM_LOCK
+ sysRTM_OLDADD = C.RTM_OLDADD
+ sysRTM_OLDDEL = C.RTM_OLDDEL
+ sysRTM_RESOLVE = C.RTM_RESOLVE
+ sysRTM_NEWADDR = C.RTM_NEWADDR
+ sysRTM_DELADDR = C.RTM_DELADDR
+ sysRTM_IFANNOUNCE = C.RTM_IFANNOUNCE
+ sysRTM_IEEE80211 = C.RTM_IEEE80211
+ sysRTM_SETGATE = C.RTM_SETGATE
+ sysRTM_LLINFO_UPD = C.RTM_LLINFO_UPD
+ sysRTM_IFINFO = C.RTM_IFINFO
+ sysRTM_CHGADDR = C.RTM_CHGADDR
+
+ sysRTA_DST = C.RTA_DST
+ sysRTA_GATEWAY = C.RTA_GATEWAY
+ sysRTA_NETMASK = C.RTA_NETMASK
+ sysRTA_GENMASK = C.RTA_GENMASK
+ sysRTA_IFP = C.RTA_IFP
+ sysRTA_IFA = C.RTA_IFA
+ sysRTA_AUTHOR = C.RTA_AUTHOR
+ sysRTA_BRD = C.RTA_BRD
+ sysRTA_TAG = C.RTA_TAG
+
+ sysRTAX_DST = C.RTAX_DST
+ sysRTAX_GATEWAY = C.RTAX_GATEWAY
+ sysRTAX_NETMASK = C.RTAX_NETMASK
+ sysRTAX_GENMASK = C.RTAX_GENMASK
+ sysRTAX_IFP = C.RTAX_IFP
+ sysRTAX_IFA = C.RTAX_IFA
+ sysRTAX_AUTHOR = C.RTAX_AUTHOR
+ sysRTAX_BRD = C.RTAX_BRD
+ sysRTAX_TAG = C.RTAX_TAG
+ sysRTAX_MAX = C.RTAX_MAX
+)
+
+const (
+ sizeofIfMsghdrNetBSD7 = C.sizeof_struct_if_msghdr
+ sizeofIfaMsghdrNetBSD7 = C.sizeof_struct_ifa_msghdr
+ sizeofIfAnnouncemsghdrNetBSD7 = C.sizeof_struct_if_announcemsghdr
+
+ sizeofRtMsghdrNetBSD7 = C.sizeof_struct_rt_msghdr
+ sizeofRtMetricsNetBSD7 = C.sizeof_struct_rt_metrics
+)
diff --git a/src/vendor/golang.org/x/net/route/defs_openbsd.go b/src/vendor/golang.org/x/net/route/defs_openbsd.go
new file mode 100644
index 00000000000000..5df7a43bc3ee64
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/defs_openbsd.go
@@ -0,0 +1,93 @@
+// Copyright 2016 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
+
+package route
+
+/*
+#include
+#include
+
+#include
+#include
+#include
+*/
+import "C"
+
+const (
+ sysAF_UNSPEC = C.AF_UNSPEC
+ sysAF_INET = C.AF_INET
+ sysAF_ROUTE = C.AF_ROUTE
+ sysAF_LINK = C.AF_LINK
+ sysAF_INET6 = C.AF_INET6
+
+ sysNET_RT_DUMP = C.NET_RT_DUMP
+ sysNET_RT_FLAGS = C.NET_RT_FLAGS
+ sysNET_RT_IFLIST = C.NET_RT_IFLIST
+ sysNET_RT_STATS = C.NET_RT_STATS
+ sysNET_RT_TABLE = C.NET_RT_TABLE
+ sysNET_RT_IFNAMES = C.NET_RT_IFNAMES
+ sysNET_RT_MAXID = C.NET_RT_MAXID
+)
+
+const (
+ sysCTL_MAXNAME = C.CTL_MAXNAME
+
+ sysCTL_UNSPEC = C.CTL_UNSPEC
+ sysCTL_KERN = C.CTL_KERN
+ sysCTL_VM = C.CTL_VM
+ sysCTL_FS = C.CTL_FS
+ sysCTL_NET = C.CTL_NET
+ sysCTL_DEBUG = C.CTL_DEBUG
+ sysCTL_HW = C.CTL_HW
+ sysCTL_MACHDEP = C.CTL_MACHDEP
+ sysCTL_DDB = C.CTL_DDB
+ sysCTL_VFS = C.CTL_VFS
+ sysCTL_MAXID = C.CTL_MAXID
+)
+
+const (
+ sysRTM_VERSION = C.RTM_VERSION
+
+ sysRTM_ADD = C.RTM_ADD
+ sysRTM_DELETE = C.RTM_DELETE
+ sysRTM_CHANGE = C.RTM_CHANGE
+ sysRTM_GET = C.RTM_GET
+ sysRTM_LOSING = C.RTM_LOSING
+ sysRTM_REDIRECT = C.RTM_REDIRECT
+ sysRTM_MISS = C.RTM_MISS
+ sysRTM_LOCK = C.RTM_LOCK
+ sysRTM_RESOLVE = C.RTM_RESOLVE
+ sysRTM_NEWADDR = C.RTM_NEWADDR
+ sysRTM_DELADDR = C.RTM_DELADDR
+ sysRTM_IFINFO = C.RTM_IFINFO
+ sysRTM_IFANNOUNCE = C.RTM_IFANNOUNCE
+ sysRTM_DESYNC = C.RTM_DESYNC
+
+ sysRTA_DST = C.RTA_DST
+ sysRTA_GATEWAY = C.RTA_GATEWAY
+ sysRTA_NETMASK = C.RTA_NETMASK
+ sysRTA_GENMASK = C.RTA_GENMASK
+ sysRTA_IFP = C.RTA_IFP
+ sysRTA_IFA = C.RTA_IFA
+ sysRTA_AUTHOR = C.RTA_AUTHOR
+ sysRTA_BRD = C.RTA_BRD
+ sysRTA_SRC = C.RTA_SRC
+ sysRTA_SRCMASK = C.RTA_SRCMASK
+ sysRTA_LABEL = C.RTA_LABEL
+
+ sysRTAX_DST = C.RTAX_DST
+ sysRTAX_GATEWAY = C.RTAX_GATEWAY
+ sysRTAX_NETMASK = C.RTAX_NETMASK
+ sysRTAX_GENMASK = C.RTAX_GENMASK
+ sysRTAX_IFP = C.RTAX_IFP
+ sysRTAX_IFA = C.RTAX_IFA
+ sysRTAX_AUTHOR = C.RTAX_AUTHOR
+ sysRTAX_BRD = C.RTAX_BRD
+ sysRTAX_SRC = C.RTAX_SRC
+ sysRTAX_SRCMASK = C.RTAX_SRCMASK
+ sysRTAX_LABEL = C.RTAX_LABEL
+ sysRTAX_MAX = C.RTAX_MAX
+)
diff --git a/src/vendor/golang.org/x/net/route/interface.go b/src/vendor/golang.org/x/net/route/interface.go
new file mode 100644
index 00000000000000..854906d9c42913
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/interface.go
@@ -0,0 +1,64 @@
+// Copyright 2016 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 darwin dragonfly freebsd netbsd openbsd
+
+package route
+
+// An InterfaceMessage represents an interface message.
+type InterfaceMessage struct {
+ Version int // message version
+ Type int // message type
+ Flags int // interface flags
+ Index int // interface index
+ Name string // interface name
+ Addrs []Addr // addresses
+
+ extOff int // offset of header extension
+ raw []byte // raw message
+}
+
+// An InterfaceAddrMessage represents an interface address message.
+type InterfaceAddrMessage struct {
+ Version int // message version
+ Type int // message type
+ Flags int // interface flags
+ Index int // interface index
+ Addrs []Addr // addresses
+
+ raw []byte // raw message
+}
+
+// Sys implements the Sys method of Message interface.
+func (m *InterfaceAddrMessage) Sys() []Sys { return nil }
+
+// An InterfaceMulticastAddrMessage represents an interface multicast
+// address message.
+type InterfaceMulticastAddrMessage struct {
+ Version int // message version
+ Type int // messsage type
+ Flags int // interface flags
+ Index int // interface index
+ Addrs []Addr // addresses
+
+ raw []byte // raw message
+}
+
+// Sys implements the Sys method of Message interface.
+func (m *InterfaceMulticastAddrMessage) Sys() []Sys { return nil }
+
+// An InterfaceAnnounceMessage represents an interface announcement
+// message.
+type InterfaceAnnounceMessage struct {
+ Version int // message version
+ Type int // message type
+ Index int // interface index
+ Name string // interface name
+ What int // what type of announcement
+
+ raw []byte // raw message
+}
+
+// Sys implements the Sys method of Message interface.
+func (m *InterfaceAnnounceMessage) Sys() []Sys { return nil }
diff --git a/src/vendor/golang.org/x/net/route/interface_announce.go b/src/vendor/golang.org/x/net/route/interface_announce.go
new file mode 100644
index 00000000000000..520d657b578fce
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/interface_announce.go
@@ -0,0 +1,32 @@
+// Copyright 2016 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 netbsd
+
+package route
+
+func (w *wireFormat) parseInterfaceAnnounceMessage(_ RIBType, b []byte) (Message, error) {
+ if len(b) < w.bodyOff {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ m := &InterfaceAnnounceMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Index: int(nativeEndian.Uint16(b[4:6])),
+ What: int(nativeEndian.Uint16(b[22:24])),
+ raw: b[:l],
+ }
+ for i := 0; i < 16; i++ {
+ if b[6+i] != 0 {
+ continue
+ }
+ m.Name = string(b[6 : 6+i])
+ break
+ }
+ return m, nil
+}
diff --git a/src/vendor/golang.org/x/net/route/interface_classic.go b/src/vendor/golang.org/x/net/route/interface_classic.go
new file mode 100644
index 00000000000000..ac4e7a6805afdf
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/interface_classic.go
@@ -0,0 +1,66 @@
+// Copyright 2016 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 darwin dragonfly netbsd
+
+package route
+
+import "runtime"
+
+func (w *wireFormat) parseInterfaceMessage(_ RIBType, b []byte) (Message, error) {
+ if len(b) < w.bodyOff {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ attrs := uint(nativeEndian.Uint32(b[4:8]))
+ if attrs&sysRTA_IFP == 0 {
+ return nil, nil
+ }
+ m := &InterfaceMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Addrs: make([]Addr, sysRTAX_MAX),
+ Flags: int(nativeEndian.Uint32(b[8:12])),
+ Index: int(nativeEndian.Uint16(b[12:14])),
+ extOff: w.extOff,
+ raw: b[:l],
+ }
+ a, err := parseLinkAddr(b[w.bodyOff:])
+ if err != nil {
+ return nil, err
+ }
+ m.Addrs[sysRTAX_IFP] = a
+ m.Name = a.(*LinkAddr).Name
+ return m, nil
+}
+
+func (w *wireFormat) parseInterfaceAddrMessage(_ RIBType, b []byte) (Message, error) {
+ if len(b) < w.bodyOff {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ m := &InterfaceAddrMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Flags: int(nativeEndian.Uint32(b[8:12])),
+ raw: b[:l],
+ }
+ if runtime.GOOS == "netbsd" {
+ m.Index = int(nativeEndian.Uint16(b[16:18]))
+ } else {
+ m.Index = int(nativeEndian.Uint16(b[12:14]))
+ }
+ var err error
+ m.Addrs, err = parseAddrs(uint(nativeEndian.Uint32(b[4:8])), parseKernelInetAddr, b[w.bodyOff:])
+ if err != nil {
+ return nil, err
+ }
+ return m, nil
+}
diff --git a/src/vendor/golang.org/x/net/route/interface_freebsd.go b/src/vendor/golang.org/x/net/route/interface_freebsd.go
new file mode 100644
index 00000000000000..c83053915da52b
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/interface_freebsd.go
@@ -0,0 +1,78 @@
+// Copyright 2016 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 route
+
+func (w *wireFormat) parseInterfaceMessage(typ RIBType, b []byte) (Message, error) {
+ var extOff, bodyOff int
+ if typ == sysNET_RT_IFLISTL {
+ if len(b) < 20 {
+ return nil, errMessageTooShort
+ }
+ extOff = int(nativeEndian.Uint16(b[18:20]))
+ bodyOff = int(nativeEndian.Uint16(b[16:18]))
+ } else {
+ if len(b) < w.bodyOff {
+ return nil, errMessageTooShort
+ }
+ extOff = w.extOff
+ bodyOff = w.bodyOff
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ attrs := uint(nativeEndian.Uint32(b[4:8]))
+ if attrs&sysRTA_IFP == 0 {
+ return nil, nil
+ }
+ m := &InterfaceMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Flags: int(nativeEndian.Uint32(b[8:12])),
+ Index: int(nativeEndian.Uint16(b[12:14])),
+ Addrs: make([]Addr, sysRTAX_MAX),
+ extOff: extOff,
+ raw: b[:l],
+ }
+ a, err := parseLinkAddr(b[bodyOff:])
+ if err != nil {
+ return nil, err
+ }
+ m.Addrs[sysRTAX_IFP] = a
+ m.Name = a.(*LinkAddr).Name
+ return m, nil
+}
+
+func (w *wireFormat) parseInterfaceAddrMessage(typ RIBType, b []byte) (Message, error) {
+ var bodyOff int
+ if typ == sysNET_RT_IFLISTL {
+ if len(b) < 24 {
+ return nil, errMessageTooShort
+ }
+ bodyOff = int(nativeEndian.Uint16(b[16:18]))
+ } else {
+ if len(b) < w.bodyOff {
+ return nil, errMessageTooShort
+ }
+ bodyOff = w.bodyOff
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ m := &InterfaceAddrMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Flags: int(nativeEndian.Uint32(b[8:12])),
+ Index: int(nativeEndian.Uint16(b[12:14])),
+ raw: b[:l],
+ }
+ var err error
+ m.Addrs, err = parseAddrs(uint(nativeEndian.Uint32(b[4:8])), parseKernelInetAddr, b[bodyOff:])
+ if err != nil {
+ return nil, err
+ }
+ return m, nil
+}
diff --git a/src/vendor/golang.org/x/net/route/interface_multicast.go b/src/vendor/golang.org/x/net/route/interface_multicast.go
new file mode 100644
index 00000000000000..1e99a9cc64b9ad
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/interface_multicast.go
@@ -0,0 +1,30 @@
+// Copyright 2016 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 darwin dragonfly freebsd
+
+package route
+
+func (w *wireFormat) parseInterfaceMulticastAddrMessage(_ RIBType, b []byte) (Message, error) {
+ if len(b) < w.bodyOff {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ m := &InterfaceMulticastAddrMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Flags: int(nativeEndian.Uint32(b[8:12])),
+ Index: int(nativeEndian.Uint16(b[12:14])),
+ raw: b[:l],
+ }
+ var err error
+ m.Addrs, err = parseAddrs(uint(nativeEndian.Uint32(b[4:8])), parseKernelInetAddr, b[w.bodyOff:])
+ if err != nil {
+ return nil, err
+ }
+ return m, nil
+}
diff --git a/src/vendor/golang.org/x/net/route/interface_openbsd.go b/src/vendor/golang.org/x/net/route/interface_openbsd.go
new file mode 100644
index 00000000000000..24451d8ca12067
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/interface_openbsd.go
@@ -0,0 +1,83 @@
+// Copyright 2016 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 route
+
+func (*wireFormat) parseInterfaceMessage(_ RIBType, b []byte) (Message, error) {
+ if len(b) < 32 {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ attrs := uint(nativeEndian.Uint32(b[12:16]))
+ if attrs&sysRTA_IFP == 0 {
+ return nil, nil
+ }
+ m := &InterfaceMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Flags: int(nativeEndian.Uint32(b[16:20])),
+ Index: int(nativeEndian.Uint16(b[6:8])),
+ Addrs: make([]Addr, sysRTAX_MAX),
+ raw: b[:l],
+ }
+ a, err := parseLinkAddr(b[int(nativeEndian.Uint16(b[4:6])):])
+ if err != nil {
+ return nil, err
+ }
+ m.Addrs[sysRTAX_IFP] = a
+ m.Name = a.(*LinkAddr).Name
+ return m, nil
+}
+
+func (*wireFormat) parseInterfaceAddrMessage(_ RIBType, b []byte) (Message, error) {
+ if len(b) < 24 {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ bodyOff := int(nativeEndian.Uint16(b[4:6]))
+ m := &InterfaceAddrMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Flags: int(nativeEndian.Uint32(b[12:16])),
+ Index: int(nativeEndian.Uint16(b[6:8])),
+ raw: b[:l],
+ }
+ var err error
+ m.Addrs, err = parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[bodyOff:])
+ if err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+func (*wireFormat) parseInterfaceAnnounceMessage(_ RIBType, b []byte) (Message, error) {
+ if len(b) < 26 {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ m := &InterfaceAnnounceMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Index: int(nativeEndian.Uint16(b[6:8])),
+ What: int(nativeEndian.Uint16(b[8:10])),
+ raw: b[:l],
+ }
+ for i := 0; i < 16; i++ {
+ if b[10+i] != 0 {
+ continue
+ }
+ m.Name = string(b[10 : 10+i])
+ break
+ }
+ return m, nil
+}
diff --git a/src/vendor/golang.org/x/net/route/message.go b/src/vendor/golang.org/x/net/route/message.go
new file mode 100644
index 00000000000000..27cbf6b77ace75
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/message.go
@@ -0,0 +1,70 @@
+// Copyright 2016 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 darwin dragonfly freebsd netbsd openbsd
+
+package route
+
+// A Message represents a routing message.
+//
+// Note: This interface will be changed to support Marshal method in
+// future version.
+type Message interface {
+ // Sys returns operating system-specific information.
+ Sys() []Sys
+}
+
+// A Sys reprensents operating system-specific information.
+type Sys interface {
+ // SysType returns a type of operating system-specific
+ // information.
+ SysType() SysType
+}
+
+// A SysType represents a type of operating system-specific
+// information.
+type SysType int
+
+const (
+ SysMetrics SysType = iota
+ SysStats
+)
+
+// ParseRIB parses b as a routing information base and returns a list
+// of routing messages.
+func ParseRIB(typ RIBType, b []byte) ([]Message, error) {
+ if !typ.parseable() {
+ return nil, errUnsupportedMessage
+ }
+ var msgs []Message
+ nmsgs, nskips := 0, 0
+ for len(b) > 4 {
+ nmsgs++
+ l := int(nativeEndian.Uint16(b[:2]))
+ if b[2] != sysRTM_VERSION {
+ b = b[l:]
+ continue
+ }
+ mtyp := int(b[3])
+ if fn, ok := parseFns[mtyp]; !ok {
+ nskips++
+ } else {
+ m, err := fn(typ, b)
+ if err != nil {
+ return nil, err
+ }
+ if m == nil {
+ nskips++
+ } else {
+ msgs = append(msgs, m)
+ }
+ }
+ b = b[l:]
+ }
+ // We failed to parse any of the messages - version mismatch?
+ if nmsgs != len(msgs)+nskips {
+ return nil, errMessageMismatch
+ }
+ return msgs, nil
+}
diff --git a/src/vendor/golang.org/x/net/route/message_darwin_test.go b/src/vendor/golang.org/x/net/route/message_darwin_test.go
new file mode 100644
index 00000000000000..3fdd12df5537e2
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/message_darwin_test.go
@@ -0,0 +1,27 @@
+// Copyright 2016 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 route
+
+import "testing"
+
+func TestFetchAndParseRIBOnDarwin(t *testing.T) {
+ for _, af := range []int{sysAF_UNSPEC, sysAF_INET, sysAF_INET6} {
+ for _, typ := range []RIBType{sysNET_RT_FLAGS, sysNET_RT_DUMP2, sysNET_RT_IFLIST2} {
+ ms, err := fetchAndParseRIB(af, typ)
+ if err != nil {
+ t.Error(err)
+ continue
+ }
+ ss, err := msgs(ms).validate()
+ if err != nil {
+ t.Errorf("%v %d %v", addrFamily(af), typ, err)
+ continue
+ }
+ for _, s := range ss {
+ t.Log(s)
+ }
+ }
+ }
+}
diff --git a/src/vendor/golang.org/x/net/route/message_freebsd_test.go b/src/vendor/golang.org/x/net/route/message_freebsd_test.go
new file mode 100644
index 00000000000000..6d03d000a82fda
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/message_freebsd_test.go
@@ -0,0 +1,106 @@
+// Copyright 2016 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 route
+
+import (
+ "testing"
+ "time"
+ "unsafe"
+)
+
+func TestFetchAndParseRIBOnFreeBSD(t *testing.T) {
+ for _, af := range []int{sysAF_UNSPEC, sysAF_INET, sysAF_INET6} {
+ for _, typ := range []RIBType{sysNET_RT_IFMALIST} {
+ ms, err := fetchAndParseRIB(af, typ)
+ if err != nil {
+ t.Error(err)
+ continue
+ }
+ ss, err := msgs(ms).validate()
+ if err != nil {
+ t.Errorf("%v %d %v", addrFamily(af), typ, err)
+ continue
+ }
+ for _, s := range ss {
+ t.Log(s)
+ }
+ }
+ }
+}
+
+func TestFetchAndParseRIBOnFreeBSD10AndAbove(t *testing.T) {
+ if _, err := FetchRIB(sysAF_UNSPEC, sysNET_RT_IFLISTL, 0); err != nil {
+ t.Skip("NET_RT_LISTL not supported")
+ }
+ var p uintptr
+ if kernelAlign != int(unsafe.Sizeof(p)) {
+ t.Skip("NET_RT_LIST vs. NET_RT_LISTL doesn't work for 386 emulation on amd64")
+ }
+
+ var tests = [2]struct {
+ typ RIBType
+ b []byte
+ msgs []Message
+ ss []string
+ }{
+ {typ: sysNET_RT_IFLIST},
+ {typ: sysNET_RT_IFLISTL},
+ }
+ for _, af := range []int{sysAF_UNSPEC, sysAF_INET, sysAF_INET6} {
+ var lastErr error
+ for i := 0; i < 3; i++ {
+ for j := range tests {
+ var err error
+ if tests[j].b, err = FetchRIB(af, tests[j].typ, 0); err != nil {
+ lastErr = err
+ time.Sleep(10 * time.Millisecond)
+ }
+ }
+ if lastErr == nil {
+ break
+ }
+ }
+ if lastErr != nil {
+ t.Error(af, lastErr)
+ continue
+ }
+ for i := range tests {
+ var err error
+ if tests[i].msgs, err = ParseRIB(tests[i].typ, tests[i].b); err != nil {
+ lastErr = err
+ t.Error(af, err)
+ }
+ }
+ if lastErr != nil {
+ continue
+ }
+ for i := range tests {
+ var err error
+ tests[i].ss, err = msgs(tests[i].msgs).validate()
+ if err != nil {
+ lastErr = err
+ t.Error(af, err)
+ }
+ for _, s := range tests[i].ss {
+ t.Log(s)
+ }
+ }
+ if lastErr != nil {
+ continue
+ }
+ for i := len(tests) - 1; i > 0; i-- {
+ if len(tests[i].ss) != len(tests[i-1].ss) {
+ t.Errorf("got %v; want %v", tests[i].ss, tests[i-1].ss)
+ continue
+ }
+ for j, s1 := range tests[i].ss {
+ s0 := tests[i-1].ss[j]
+ if s1 != s0 {
+ t.Errorf("got %s; want %s", s1, s0)
+ }
+ }
+ }
+ }
+}
diff --git a/src/vendor/golang.org/x/net/route/message_test.go b/src/vendor/golang.org/x/net/route/message_test.go
new file mode 100644
index 00000000000000..a1263d8f25e4dc
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/message_test.go
@@ -0,0 +1,95 @@
+// Copyright 2016 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 darwin dragonfly freebsd netbsd openbsd
+
+package route
+
+import (
+ "os"
+ "syscall"
+ "testing"
+ "time"
+)
+
+func TestFetchAndParseRIB(t *testing.T) {
+ for _, af := range []int{sysAF_UNSPEC, sysAF_INET, sysAF_INET6} {
+ for _, typ := range []RIBType{sysNET_RT_DUMP, sysNET_RT_IFLIST} {
+ ms, err := fetchAndParseRIB(af, typ)
+ if err != nil {
+ t.Error(err)
+ continue
+ }
+ ss, err := msgs(ms).validate()
+ if err != nil {
+ t.Errorf("%v %d %v", addrFamily(af), typ, err)
+ continue
+ }
+ for _, s := range ss {
+ t.Log(s)
+ }
+ }
+ }
+}
+
+func TestMonitorAndParseRIB(t *testing.T) {
+ if testing.Short() || os.Getuid() != 0 {
+ t.Skip("must be root")
+ }
+
+ // We suppose that using an IPv4 link-local address and the
+ // dot1Q ID for Token Ring and FDDI doesn't harm anyone.
+ pv := &propVirtual{addr: "169.254.0.1", mask: "255.255.255.0"}
+ if err := pv.configure(1002); err != nil {
+ t.Skip(err)
+ }
+ if err := pv.setup(); err != nil {
+ t.Skip(err)
+ }
+ pv.teardown()
+
+ s, err := syscall.Socket(syscall.AF_ROUTE, syscall.SOCK_RAW, syscall.AF_UNSPEC)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer syscall.Close(s)
+
+ go func() {
+ b := make([]byte, os.Getpagesize())
+ for {
+ n, err := syscall.Read(s, b)
+ if err != nil {
+ return
+ }
+ ms, err := ParseRIB(0, b[:n])
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ ss, err := msgs(ms).validate()
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ for _, s := range ss {
+ t.Log(s)
+ }
+ }
+ }()
+
+ for _, vid := range []int{1002, 1003, 1004, 1005} {
+ pv := &propVirtual{addr: "169.254.0.1", mask: "255.255.255.0"}
+ if err := pv.configure(vid); err != nil {
+ t.Fatal(err)
+ }
+ if err := pv.setup(); err != nil {
+ t.Fatal(err)
+ }
+ time.Sleep(200 * time.Millisecond)
+ if err := pv.teardown(); err != nil {
+ t.Fatal(err)
+ }
+ time.Sleep(200 * time.Millisecond)
+ }
+}
diff --git a/src/vendor/golang.org/x/net/route/route.go b/src/vendor/golang.org/x/net/route/route.go
new file mode 100644
index 00000000000000..c986e29ebc94c3
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/route.go
@@ -0,0 +1,74 @@
+// Copyright 2016 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 darwin dragonfly freebsd netbsd openbsd
+
+// Package route provides basic functions for the manipulation of
+// packet routing facilities on BSD variants.
+//
+// The package supports any version of Darwin, any version of
+// DragonFly BSD, FreeBSD 7 through 11, NetBSD 6 and above, and
+// OpenBSD 5.6 and above.
+package route
+
+import (
+ "errors"
+ "os"
+ "syscall"
+)
+
+var (
+ errUnsupportedMessage = errors.New("unsupported message")
+ errMessageMismatch = errors.New("message mismatch")
+ errMessageTooShort = errors.New("message too short")
+ errInvalidMessage = errors.New("invalid message")
+ errInvalidAddr = errors.New("invalid address")
+)
+
+// A RouteMessage represents a message conveying an address prefix, a
+// nexthop address and an output interface.
+type RouteMessage struct {
+ Version int // message version
+ Type int // message type
+ Flags int // route flags
+ Index int // interface index when atatched
+ Addrs []Addr // addresses
+
+ extOff int // offset of header extension
+ raw []byte // raw message
+}
+
+// A RIBType reprensents a type of routing information base.
+type RIBType int
+
+const (
+ RIBTypeRoute RIBType = syscall.NET_RT_DUMP
+ RIBTypeInterface RIBType = syscall.NET_RT_IFLIST
+)
+
+// FetchRIB fetches a routing information base from the operating
+// system.
+//
+// The provided af must be an address family.
+//
+// The provided arg must be a RIBType-specific argument.
+// When RIBType is related to routes, arg might be a set of route
+// flags. When RIBType is related to network interfaces, arg might be
+// an interface index or a set of interface flags. In most cases, zero
+// means a wildcard.
+func FetchRIB(af int, typ RIBType, arg int) ([]byte, error) {
+ mib := [6]int32{sysCTL_NET, sysAF_ROUTE, 0, int32(af), int32(typ), int32(arg)}
+ n := uintptr(0)
+ if err := sysctl(mib[:], nil, &n, nil, 0); err != nil {
+ return nil, os.NewSyscallError("sysctl", err)
+ }
+ if n == 0 {
+ return nil, nil
+ }
+ b := make([]byte, n)
+ if err := sysctl(mib[:], &b[0], &n, nil, 0); err != nil {
+ return nil, os.NewSyscallError("sysctl", err)
+ }
+ return b[:n], nil
+}
diff --git a/src/vendor/golang.org/x/net/route/route_classic.go b/src/vendor/golang.org/x/net/route/route_classic.go
new file mode 100644
index 00000000000000..d333c6aa526b19
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/route_classic.go
@@ -0,0 +1,31 @@
+// Copyright 2016 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 darwin dragonfly freebsd netbsd
+
+package route
+
+func (w *wireFormat) parseRouteMessage(typ RIBType, b []byte) (Message, error) {
+ if len(b) < w.bodyOff {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ m := &RouteMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Flags: int(nativeEndian.Uint32(b[8:12])),
+ Index: int(nativeEndian.Uint16(b[4:6])),
+ extOff: w.extOff,
+ raw: b[:l],
+ }
+ var err error
+ m.Addrs, err = parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[w.bodyOff:])
+ if err != nil {
+ return nil, err
+ }
+ return m, nil
+}
diff --git a/src/vendor/golang.org/x/net/route/route_openbsd.go b/src/vendor/golang.org/x/net/route/route_openbsd.go
new file mode 100644
index 00000000000000..b07862f04d3f50
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/route_openbsd.go
@@ -0,0 +1,28 @@
+// Copyright 2016 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 route
+
+func (*wireFormat) parseRouteMessage(_ RIBType, b []byte) (Message, error) {
+ if len(b) < 40 {
+ return nil, errMessageTooShort
+ }
+ l := int(nativeEndian.Uint16(b[:2]))
+ if len(b) < l {
+ return nil, errInvalidMessage
+ }
+ m := &RouteMessage{
+ Version: int(b[2]),
+ Type: int(b[3]),
+ Flags: int(nativeEndian.Uint32(b[16:20])),
+ Index: int(nativeEndian.Uint16(b[6:8])),
+ raw: b[:l],
+ }
+ as, err := parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[int(nativeEndian.Uint16(b[4:6])):])
+ if err != nil {
+ return nil, err
+ }
+ m.Addrs = as
+ return m, nil
+}
diff --git a/src/vendor/golang.org/x/net/route/route_test.go b/src/vendor/golang.org/x/net/route/route_test.go
new file mode 100644
index 00000000000000..99f57b712d9c38
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/route_test.go
@@ -0,0 +1,385 @@
+// Copyright 2016 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 darwin dragonfly freebsd netbsd openbsd
+
+package route
+
+import (
+ "fmt"
+ "os/exec"
+ "runtime"
+ "time"
+)
+
+func (m *RouteMessage) String() string {
+ return fmt.Sprintf("%s", addrAttrs(nativeEndian.Uint32(m.raw[12:16])))
+}
+
+func (m *InterfaceMessage) String() string {
+ var attrs addrAttrs
+ if runtime.GOOS == "openbsd" {
+ attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
+ } else {
+ attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
+ }
+ return fmt.Sprintf("%s", attrs)
+}
+
+func (m *InterfaceAddrMessage) String() string {
+ var attrs addrAttrs
+ if runtime.GOOS == "openbsd" {
+ attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
+ } else {
+ attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
+ }
+ return fmt.Sprintf("%s", attrs)
+}
+
+func (m *InterfaceMulticastAddrMessage) String() string {
+ return fmt.Sprintf("%s", addrAttrs(nativeEndian.Uint32(m.raw[4:8])))
+}
+
+func (m *InterfaceAnnounceMessage) String() string {
+ what := ""
+ switch m.What {
+ case 0:
+ what = "arrival"
+ case 1:
+ what = "departure"
+ }
+ return fmt.Sprintf("(%d %s %s)", m.Index, m.Name, what)
+}
+
+func (m *InterfaceMetrics) String() string {
+ return fmt.Sprintf("(type=%d mtu=%d)", m.Type, m.MTU)
+}
+
+func (m *RouteMetrics) String() string {
+ return fmt.Sprintf("(pmtu=%d)", m.PathMTU)
+}
+
+type addrAttrs uint
+
+var addrAttrNames = [...]string{
+ "dst",
+ "gateway",
+ "netmask",
+ "genmask",
+ "ifp",
+ "ifa",
+ "author",
+ "brd",
+ "df:mpls1-n:tag-o:src", // mpls1 for dragonfly, tag for netbsd, src for openbsd
+ "df:mpls2-o:srcmask", // mpls2 for dragonfly, srcmask for openbsd
+ "df:mpls3-o:label", // mpls3 for dragonfly, label for openbsd
+}
+
+func (attrs addrAttrs) String() string {
+ var s string
+ for i, name := range addrAttrNames {
+ if attrs&(1<"
+ }
+ return s
+}
+
+type msgs []Message
+
+func (ms msgs) validate() ([]string, error) {
+ var ss []string
+ for _, m := range ms {
+ switch m := m.(type) {
+ case *RouteMessage:
+ if err := addrs(m.Addrs).match(addrAttrs(nativeEndian.Uint32(m.raw[12:16]))); err != nil {
+ return nil, err
+ }
+ sys := m.Sys()
+ if sys == nil {
+ return nil, fmt.Errorf("no sys for %s", m.String())
+ }
+ ss = append(ss, m.String()+" "+syss(sys).String()+" "+addrs(m.Addrs).String())
+ case *InterfaceMessage:
+ var attrs addrAttrs
+ if runtime.GOOS == "openbsd" {
+ attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
+ } else {
+ attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
+ }
+ if err := addrs(m.Addrs).match(attrs); err != nil {
+ return nil, err
+ }
+ sys := m.Sys()
+ if sys == nil {
+ return nil, fmt.Errorf("no sys for %s", m.String())
+ }
+ ss = append(ss, m.String()+" "+syss(sys).String()+" "+addrs(m.Addrs).String())
+ case *InterfaceAddrMessage:
+ var attrs addrAttrs
+ if runtime.GOOS == "openbsd" {
+ attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
+ } else {
+ attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
+ }
+ if err := addrs(m.Addrs).match(attrs); err != nil {
+ return nil, err
+ }
+ ss = append(ss, m.String()+" "+addrs(m.Addrs).String())
+ case *InterfaceMulticastAddrMessage:
+ if err := addrs(m.Addrs).match(addrAttrs(nativeEndian.Uint32(m.raw[4:8]))); err != nil {
+ return nil, err
+ }
+ ss = append(ss, m.String()+" "+addrs(m.Addrs).String())
+ case *InterfaceAnnounceMessage:
+ ss = append(ss, m.String())
+ default:
+ ss = append(ss, fmt.Sprintf("%+v", m))
+ }
+ }
+ return ss, nil
+}
+
+type syss []Sys
+
+func (sys syss) String() string {
+ var s string
+ for _, sy := range sys {
+ switch sy := sy.(type) {
+ case *InterfaceMetrics:
+ if len(s) > 0 {
+ s += " "
+ }
+ s += sy.String()
+ case *RouteMetrics:
+ if len(s) > 0 {
+ s += " "
+ }
+ s += sy.String()
+ }
+ }
+ return s
+}
+
+type addrFamily int
+
+func (af addrFamily) String() string {
+ switch af {
+ case sysAF_UNSPEC:
+ return "unspec"
+ case sysAF_LINK:
+ return "link"
+ case sysAF_INET:
+ return "inet4"
+ case sysAF_INET6:
+ return "inet6"
+ default:
+ return fmt.Sprintf("%d", af)
+ }
+}
+
+const hexDigit = "0123456789abcdef"
+
+type llAddr []byte
+
+func (a llAddr) String() string {
+ if len(a) == 0 {
+ return ""
+ }
+ buf := make([]byte, 0, len(a)*3-1)
+ for i, b := range a {
+ if i > 0 {
+ buf = append(buf, ':')
+ }
+ buf = append(buf, hexDigit[b>>4])
+ buf = append(buf, hexDigit[b&0xF])
+ }
+ return string(buf)
+}
+
+type ipAddr []byte
+
+func (a ipAddr) String() string {
+ if len(a) == 0 {
+ return ""
+ }
+ if len(a) == 4 {
+ return fmt.Sprintf("%d.%d.%d.%d", a[0], a[1], a[2], a[3])
+ }
+ if len(a) == 16 {
+ return fmt.Sprintf("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15])
+ }
+ s := make([]byte, len(a)*2)
+ for i, tn := range a {
+ s[i*2], s[i*2+1] = hexDigit[tn>>4], hexDigit[tn&0xf]
+ }
+ return string(s)
+}
+
+func (a *LinkAddr) String() string {
+ name := a.Name
+ if name == "" {
+ name = ""
+ }
+ lla := llAddr(a.Addr).String()
+ if lla == "" {
+ lla = ""
+ }
+ return fmt.Sprintf("(%v %d %s %s)", addrFamily(a.Family()), a.Index, name, lla)
+}
+
+func (a Inet4Addr) String() string {
+ return fmt.Sprintf("(%v %v)", addrFamily(a.Family()), ipAddr(a.IP[:]))
+}
+
+func (a *Inet6Addr) String() string {
+ return fmt.Sprintf("(%v %v %d)", addrFamily(a.Family()), ipAddr(a.IP[:]), a.ZoneID)
+}
+
+func (a *DefaultAddr) String() string {
+ return fmt.Sprintf("(%v %s)", addrFamily(a.Family()), ipAddr(a.Raw[2:]).String())
+}
+
+type addrs []Addr
+
+func (as addrs) String() string {
+ var s string
+ for _, a := range as {
+ if a == nil {
+ continue
+ }
+ if len(s) > 0 {
+ s += " "
+ }
+ switch a := a.(type) {
+ case *LinkAddr:
+ s += a.String()
+ case *Inet4Addr:
+ s += a.String()
+ case *Inet6Addr:
+ s += a.String()
+ case *DefaultAddr:
+ s += a.String()
+ }
+ }
+ if s == "" {
+ return ""
+ }
+ return s
+}
+
+func (as addrs) match(attrs addrAttrs) error {
+ var ts addrAttrs
+ af := sysAF_UNSPEC
+ for i := range as {
+ if as[i] != nil {
+ ts |= 1 << uint(i)
+ }
+ switch as[i].(type) {
+ case *Inet4Addr:
+ if af == sysAF_UNSPEC {
+ af = sysAF_INET
+ }
+ if af != sysAF_INET {
+ return fmt.Errorf("got %v; want %v", addrs(as), addrFamily(af))
+ }
+ case *Inet6Addr:
+ if af == sysAF_UNSPEC {
+ af = sysAF_INET6
+ }
+ if af != sysAF_INET6 {
+ return fmt.Errorf("got %v; want %v", addrs(as), addrFamily(af))
+ }
+ }
+ }
+ if ts != attrs && ts > attrs {
+ return fmt.Errorf("%v not included in %v", ts, attrs)
+ }
+ return nil
+}
+
+func fetchAndParseRIB(af int, typ RIBType) ([]Message, error) {
+ var err error
+ var b []byte
+ for i := 0; i < 3; i++ {
+ if b, err = FetchRIB(af, typ, 0); err != nil {
+ time.Sleep(10 * time.Millisecond)
+ continue
+ }
+ break
+ }
+ if err != nil {
+ return nil, fmt.Errorf("%v %d %v", addrFamily(af), typ, err)
+ }
+ ms, err := ParseRIB(typ, b)
+ if err != nil {
+ return nil, fmt.Errorf("%v %d %v", addrFamily(af), typ, err)
+ }
+ return ms, nil
+}
+
+type propVirtual struct {
+ name string
+ addr, mask string
+ setupCmds []*exec.Cmd
+ teardownCmds []*exec.Cmd
+}
+
+func (ti *propVirtual) setup() error {
+ for _, cmd := range ti.setupCmds {
+ if err := cmd.Run(); err != nil {
+ ti.teardown()
+ return err
+ }
+ }
+ return nil
+}
+
+func (ti *propVirtual) teardown() error {
+ for _, cmd := range ti.teardownCmds {
+ if err := cmd.Run(); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (ti *propVirtual) configure(suffix int) error {
+ if runtime.GOOS == "openbsd" {
+ ti.name = fmt.Sprintf("vether%d", suffix)
+ } else {
+ ti.name = fmt.Sprintf("vlan%d", suffix)
+ }
+ xname, err := exec.LookPath("ifconfig")
+ if err != nil {
+ return err
+ }
+ ti.setupCmds = append(ti.setupCmds, &exec.Cmd{
+ Path: xname,
+ Args: []string{"ifconfig", ti.name, "create"},
+ })
+ if runtime.GOOS == "netbsd" {
+ // NetBSD requires an underlying dot1Q-capable network
+ // interface.
+ ti.setupCmds = append(ti.setupCmds, &exec.Cmd{
+ Path: xname,
+ Args: []string{"ifconfig", ti.name, "vlan", fmt.Sprintf("%d", suffix&0xfff), "vlanif", "wm0"},
+ })
+ }
+ ti.setupCmds = append(ti.setupCmds, &exec.Cmd{
+ Path: xname,
+ Args: []string{"ifconfig", ti.name, "inet", ti.addr, "netmask", ti.mask},
+ })
+ ti.teardownCmds = append(ti.teardownCmds, &exec.Cmd{
+ Path: xname,
+ Args: []string{"ifconfig", ti.name, "destroy"},
+ })
+ return nil
+}
diff --git a/src/vendor/golang.org/x/net/route/sys.go b/src/vendor/golang.org/x/net/route/sys.go
new file mode 100644
index 00000000000000..80ca83ae1378fe
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/sys.go
@@ -0,0 +1,40 @@
+// Copyright 2016 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 darwin dragonfly freebsd netbsd openbsd
+
+package route
+
+import "unsafe"
+
+var (
+ nativeEndian binaryByteOrder
+ kernelAlign int
+ parseFns map[int]parseFn
+)
+
+func init() {
+ i := uint32(1)
+ b := (*[4]byte)(unsafe.Pointer(&i))
+ if b[0] == 1 {
+ nativeEndian = littleEndian
+ } else {
+ nativeEndian = bigEndian
+ }
+ kernelAlign, parseFns = probeRoutingStack()
+}
+
+func roundup(l int) int {
+ if l == 0 {
+ return kernelAlign
+ }
+ return (l + kernelAlign - 1) & ^(kernelAlign - 1)
+}
+
+type parseFn func(RIBType, []byte) (Message, error)
+
+type wireFormat struct {
+ extOff int // offset of header extension
+ bodyOff int // offset of message body
+}
diff --git a/src/vendor/golang.org/x/net/route/sys_darwin.go b/src/vendor/golang.org/x/net/route/sys_darwin.go
new file mode 100644
index 00000000000000..fff3a0fd1db29a
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/sys_darwin.go
@@ -0,0 +1,80 @@
+// Copyright 2016 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 route
+
+func (typ RIBType) parseable() bool {
+ switch typ {
+ case sysNET_RT_STAT, sysNET_RT_TRASH:
+ return false
+ default:
+ return true
+ }
+}
+
+// A RouteMetrics represents route metrics.
+type RouteMetrics struct {
+ PathMTU int // path maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (rmx *RouteMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *RouteMessage) Sys() []Sys {
+ return []Sys{
+ &RouteMetrics{
+ PathMTU: int(nativeEndian.Uint32(m.raw[m.extOff+4 : m.extOff+8])),
+ },
+ }
+}
+
+// A InterfaceMetrics represents interface metrics.
+type InterfaceMetrics struct {
+ Type int // interface type
+ MTU int // maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (imx *InterfaceMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *InterfaceMessage) Sys() []Sys {
+ return []Sys{
+ &InterfaceMetrics{
+ Type: int(m.raw[m.extOff]),
+ MTU: int(nativeEndian.Uint32(m.raw[m.extOff+8 : m.extOff+12])),
+ },
+ }
+}
+
+func probeRoutingStack() (int, map[int]parseFn) {
+ rtm := &wireFormat{extOff: 36, bodyOff: sizeofRtMsghdrDarwin15}
+ rtm2 := &wireFormat{extOff: 36, bodyOff: sizeofRtMsghdr2Darwin15}
+ ifm := &wireFormat{extOff: 16, bodyOff: sizeofIfMsghdrDarwin15}
+ ifm2 := &wireFormat{extOff: 32, bodyOff: sizeofIfMsghdr2Darwin15}
+ ifam := &wireFormat{extOff: sizeofIfaMsghdrDarwin15, bodyOff: sizeofIfaMsghdrDarwin15}
+ ifmam := &wireFormat{extOff: sizeofIfmaMsghdrDarwin15, bodyOff: sizeofIfmaMsghdrDarwin15}
+ ifmam2 := &wireFormat{extOff: sizeofIfmaMsghdr2Darwin15, bodyOff: sizeofIfmaMsghdr2Darwin15}
+ // Darwin kernels require 32-bit aligned access to routing facilities.
+ return 4, map[int]parseFn{
+ sysRTM_ADD: rtm.parseRouteMessage,
+ sysRTM_DELETE: rtm.parseRouteMessage,
+ sysRTM_CHANGE: rtm.parseRouteMessage,
+ sysRTM_GET: rtm.parseRouteMessage,
+ sysRTM_LOSING: rtm.parseRouteMessage,
+ sysRTM_REDIRECT: rtm.parseRouteMessage,
+ sysRTM_MISS: rtm.parseRouteMessage,
+ sysRTM_LOCK: rtm.parseRouteMessage,
+ sysRTM_RESOLVE: rtm.parseRouteMessage,
+ sysRTM_NEWADDR: ifam.parseInterfaceAddrMessage,
+ sysRTM_DELADDR: ifam.parseInterfaceAddrMessage,
+ sysRTM_IFINFO: ifm.parseInterfaceMessage,
+ sysRTM_NEWMADDR: ifmam.parseInterfaceMulticastAddrMessage,
+ sysRTM_DELMADDR: ifmam.parseInterfaceMulticastAddrMessage,
+ sysRTM_IFINFO2: ifm2.parseInterfaceMessage,
+ sysRTM_NEWMADDR2: ifmam2.parseInterfaceMulticastAddrMessage,
+ sysRTM_GET2: rtm2.parseRouteMessage,
+ }
+}
diff --git a/src/vendor/golang.org/x/net/route/sys_dragonfly.go b/src/vendor/golang.org/x/net/route/sys_dragonfly.go
new file mode 100644
index 00000000000000..da848b3d076e5d
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/sys_dragonfly.go
@@ -0,0 +1,71 @@
+// Copyright 2016 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 route
+
+import "unsafe"
+
+func (typ RIBType) parseable() bool { return true }
+
+// A RouteMetrics represents route metrics.
+type RouteMetrics struct {
+ PathMTU int // path maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (rmx *RouteMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *RouteMessage) Sys() []Sys {
+ return []Sys{
+ &RouteMetrics{
+ PathMTU: int(nativeEndian.Uint64(m.raw[m.extOff+8 : m.extOff+16])),
+ },
+ }
+}
+
+// A InterfaceMetrics represents interface metrics.
+type InterfaceMetrics struct {
+ Type int // interface type
+ MTU int // maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (imx *InterfaceMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *InterfaceMessage) Sys() []Sys {
+ return []Sys{
+ &InterfaceMetrics{
+ Type: int(m.raw[m.extOff]),
+ MTU: int(nativeEndian.Uint32(m.raw[m.extOff+8 : m.extOff+12])),
+ },
+ }
+}
+
+func probeRoutingStack() (int, map[int]parseFn) {
+ var p uintptr
+ rtm := &wireFormat{extOff: 40, bodyOff: sizeofRtMsghdrDragonFlyBSD4}
+ ifm := &wireFormat{extOff: 16, bodyOff: sizeofIfMsghdrDragonFlyBSD4}
+ ifam := &wireFormat{extOff: sizeofIfaMsghdrDragonFlyBSD4, bodyOff: sizeofIfaMsghdrDragonFlyBSD4}
+ ifmam := &wireFormat{extOff: sizeofIfmaMsghdrDragonFlyBSD4, bodyOff: sizeofIfmaMsghdrDragonFlyBSD4}
+ ifanm := &wireFormat{extOff: sizeofIfAnnouncemsghdrDragonFlyBSD4, bodyOff: sizeofIfAnnouncemsghdrDragonFlyBSD4}
+ return int(unsafe.Sizeof(p)), map[int]parseFn{
+ sysRTM_ADD: rtm.parseRouteMessage,
+ sysRTM_DELETE: rtm.parseRouteMessage,
+ sysRTM_CHANGE: rtm.parseRouteMessage,
+ sysRTM_GET: rtm.parseRouteMessage,
+ sysRTM_LOSING: rtm.parseRouteMessage,
+ sysRTM_REDIRECT: rtm.parseRouteMessage,
+ sysRTM_MISS: rtm.parseRouteMessage,
+ sysRTM_LOCK: rtm.parseRouteMessage,
+ sysRTM_RESOLVE: rtm.parseRouteMessage,
+ sysRTM_NEWADDR: ifam.parseInterfaceAddrMessage,
+ sysRTM_DELADDR: ifam.parseInterfaceAddrMessage,
+ sysRTM_IFINFO: ifm.parseInterfaceMessage,
+ sysRTM_NEWMADDR: ifmam.parseInterfaceMulticastAddrMessage,
+ sysRTM_DELMADDR: ifmam.parseInterfaceMulticastAddrMessage,
+ sysRTM_IFANNOUNCE: ifanm.parseInterfaceAnnounceMessage,
+ }
+}
diff --git a/src/vendor/golang.org/x/net/route/sys_freebsd.go b/src/vendor/golang.org/x/net/route/sys_freebsd.go
new file mode 100644
index 00000000000000..7b05c1a5a05c11
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/sys_freebsd.go
@@ -0,0 +1,150 @@
+// Copyright 2016 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 route
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+func (typ RIBType) parseable() bool { return true }
+
+// A RouteMetrics represents route metrics.
+type RouteMetrics struct {
+ PathMTU int // path maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (rmx *RouteMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *RouteMessage) Sys() []Sys {
+ if kernelAlign == 8 {
+ return []Sys{
+ &RouteMetrics{
+ PathMTU: int(nativeEndian.Uint64(m.raw[m.extOff+8 : m.extOff+16])),
+ },
+ }
+ }
+ return []Sys{
+ &RouteMetrics{
+ PathMTU: int(nativeEndian.Uint32(m.raw[m.extOff+4 : m.extOff+8])),
+ },
+ }
+}
+
+// A InterfaceMetrics represents interface metrics.
+type InterfaceMetrics struct {
+ Type int // interface type
+ MTU int // maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (imx *InterfaceMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *InterfaceMessage) Sys() []Sys {
+ return []Sys{
+ &InterfaceMetrics{
+ Type: int(m.raw[m.extOff]),
+ MTU: int(nativeEndian.Uint32(m.raw[m.extOff+8 : m.extOff+12])),
+ },
+ }
+}
+
+func probeRoutingStack() (int, map[int]parseFn) {
+ var p uintptr
+ wordSize := int(unsafe.Sizeof(p))
+ align := int(unsafe.Sizeof(p))
+ // In the case of kern.supported_archs="amd64 i386", we need
+ // to know the underlying kernel's architecture because the
+ // alignment for routing facilities are set at the build time
+ // of the kernel.
+ conf, _ := syscall.Sysctl("kern.conftxt")
+ for i, j := 0, 0; j < len(conf); j++ {
+ if conf[j] != '\n' {
+ continue
+ }
+ s := conf[i:j]
+ i = j + 1
+ if len(s) > len("machine") && s[:len("machine")] == "machine" {
+ s = s[len("machine"):]
+ for k := 0; k < len(s); k++ {
+ if s[k] == ' ' || s[k] == '\t' {
+ s = s[1:]
+ }
+ break
+ }
+ if s == "amd64" {
+ align = 8
+ }
+ break
+ }
+ }
+ var rtm, ifm, ifam, ifmam, ifanm *wireFormat
+ if align != wordSize { // 386 emulation on amd64
+ rtm = &wireFormat{extOff: sizeofRtMsghdrFreeBSD10Emu - sizeofRtMetricsFreeBSD10Emu, bodyOff: sizeofRtMsghdrFreeBSD10Emu}
+ ifm = &wireFormat{extOff: 16}
+ ifam = &wireFormat{extOff: sizeofIfaMsghdrFreeBSD10Emu, bodyOff: sizeofIfaMsghdrFreeBSD10Emu}
+ ifmam = &wireFormat{extOff: sizeofIfmaMsghdrFreeBSD10Emu, bodyOff: sizeofIfmaMsghdrFreeBSD10Emu}
+ ifanm = &wireFormat{extOff: sizeofIfAnnouncemsghdrFreeBSD10Emu, bodyOff: sizeofIfAnnouncemsghdrFreeBSD10Emu}
+ } else {
+ rtm = &wireFormat{extOff: sizeofRtMsghdrFreeBSD10 - sizeofRtMetricsFreeBSD10, bodyOff: sizeofRtMsghdrFreeBSD10}
+ ifm = &wireFormat{extOff: 16}
+ ifam = &wireFormat{extOff: sizeofIfaMsghdrFreeBSD10, bodyOff: sizeofIfaMsghdrFreeBSD10}
+ ifmam = &wireFormat{extOff: sizeofIfmaMsghdrFreeBSD10, bodyOff: sizeofIfmaMsghdrFreeBSD10}
+ ifanm = &wireFormat{extOff: sizeofIfAnnouncemsghdrFreeBSD10, bodyOff: sizeofIfAnnouncemsghdrFreeBSD10}
+ }
+ rel, _ := syscall.SysctlUint32("kern.osreldate")
+ switch {
+ case rel < 800000:
+ if align != wordSize { // 386 emulation on amd64
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD7Emu
+ } else {
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD7
+ }
+ case 800000 <= rel && rel < 900000:
+ if align != wordSize { // 386 emulation on amd64
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD8Emu
+ } else {
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD8
+ }
+ case 900000 <= rel && rel < 1000000:
+ if align != wordSize { // 386 emulation on amd64
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD9Emu
+ } else {
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD9
+ }
+ case 1000000 <= rel && rel < 1100000:
+ if align != wordSize { // 386 emulation on amd64
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD10Emu
+ } else {
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD10
+ }
+ default:
+ if align != wordSize { // 386 emulation on amd64
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD11Emu
+ } else {
+ ifm.bodyOff = sizeofIfMsghdrFreeBSD11
+ }
+ }
+ return align, map[int]parseFn{
+ sysRTM_ADD: rtm.parseRouteMessage,
+ sysRTM_DELETE: rtm.parseRouteMessage,
+ sysRTM_CHANGE: rtm.parseRouteMessage,
+ sysRTM_GET: rtm.parseRouteMessage,
+ sysRTM_LOSING: rtm.parseRouteMessage,
+ sysRTM_REDIRECT: rtm.parseRouteMessage,
+ sysRTM_MISS: rtm.parseRouteMessage,
+ sysRTM_LOCK: rtm.parseRouteMessage,
+ sysRTM_RESOLVE: rtm.parseRouteMessage,
+ sysRTM_NEWADDR: ifam.parseInterfaceAddrMessage,
+ sysRTM_DELADDR: ifam.parseInterfaceAddrMessage,
+ sysRTM_IFINFO: ifm.parseInterfaceMessage,
+ sysRTM_NEWMADDR: ifmam.parseInterfaceMulticastAddrMessage,
+ sysRTM_DELMADDR: ifmam.parseInterfaceMulticastAddrMessage,
+ sysRTM_IFANNOUNCE: ifanm.parseInterfaceAnnounceMessage,
+ }
+}
diff --git a/src/vendor/golang.org/x/net/route/sys_netbsd.go b/src/vendor/golang.org/x/net/route/sys_netbsd.go
new file mode 100644
index 00000000000000..4d8076b518d5b2
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/sys_netbsd.go
@@ -0,0 +1,67 @@
+// Copyright 2016 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 route
+
+func (typ RIBType) parseable() bool { return true }
+
+// A RouteMetrics represents route metrics.
+type RouteMetrics struct {
+ PathMTU int // path maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (rmx *RouteMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *RouteMessage) Sys() []Sys {
+ return []Sys{
+ &RouteMetrics{
+ PathMTU: int(nativeEndian.Uint64(m.raw[m.extOff+8 : m.extOff+16])),
+ },
+ }
+}
+
+// A InterfaceMetrics represents interface metrics.
+type InterfaceMetrics struct {
+ Type int // interface type
+ MTU int // maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (imx *InterfaceMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *InterfaceMessage) Sys() []Sys {
+ return []Sys{
+ &InterfaceMetrics{
+ Type: int(m.raw[m.extOff]),
+ MTU: int(nativeEndian.Uint32(m.raw[m.extOff+8 : m.extOff+12])),
+ },
+ }
+}
+
+func probeRoutingStack() (int, map[int]parseFn) {
+ rtm := &wireFormat{extOff: 40, bodyOff: sizeofRtMsghdrNetBSD7}
+ ifm := &wireFormat{extOff: 16, bodyOff: sizeofIfMsghdrNetBSD7}
+ ifam := &wireFormat{extOff: sizeofIfaMsghdrNetBSD7, bodyOff: sizeofIfaMsghdrNetBSD7}
+ ifanm := &wireFormat{extOff: sizeofIfAnnouncemsghdrNetBSD7, bodyOff: sizeofIfAnnouncemsghdrNetBSD7}
+ // NetBSD 6 and above kernels require 64-bit aligned access to
+ // routing facilities.
+ return 8, map[int]parseFn{
+ sysRTM_ADD: rtm.parseRouteMessage,
+ sysRTM_DELETE: rtm.parseRouteMessage,
+ sysRTM_CHANGE: rtm.parseRouteMessage,
+ sysRTM_GET: rtm.parseRouteMessage,
+ sysRTM_LOSING: rtm.parseRouteMessage,
+ sysRTM_REDIRECT: rtm.parseRouteMessage,
+ sysRTM_MISS: rtm.parseRouteMessage,
+ sysRTM_LOCK: rtm.parseRouteMessage,
+ sysRTM_RESOLVE: rtm.parseRouteMessage,
+ sysRTM_NEWADDR: ifam.parseInterfaceAddrMessage,
+ sysRTM_DELADDR: ifam.parseInterfaceAddrMessage,
+ sysRTM_IFANNOUNCE: ifanm.parseInterfaceAnnounceMessage,
+ sysRTM_IFINFO: ifm.parseInterfaceMessage,
+ }
+}
diff --git a/src/vendor/golang.org/x/net/route/sys_openbsd.go b/src/vendor/golang.org/x/net/route/sys_openbsd.go
new file mode 100644
index 00000000000000..26d043869610ea
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/sys_openbsd.go
@@ -0,0 +1,72 @@
+// Copyright 2016 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 route
+
+import "unsafe"
+
+func (typ RIBType) parseable() bool {
+ switch typ {
+ case sysNET_RT_STATS, sysNET_RT_TABLE:
+ return false
+ default:
+ return true
+ }
+}
+
+// A RouteMetrics represents route metrics.
+type RouteMetrics struct {
+ PathMTU int // path maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (rmx *RouteMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *RouteMessage) Sys() []Sys {
+ return []Sys{
+ &RouteMetrics{
+ PathMTU: int(nativeEndian.Uint32(m.raw[60:64])),
+ },
+ }
+}
+
+// A InterfaceMetrics represents interface metrics.
+type InterfaceMetrics struct {
+ Type int // interface type
+ MTU int // maximum transmission unit
+}
+
+// SysType implements the SysType method of Sys interface.
+func (imx *InterfaceMetrics) SysType() SysType { return SysMetrics }
+
+// Sys implements the Sys method of Message interface.
+func (m *InterfaceMessage) Sys() []Sys {
+ return []Sys{
+ &InterfaceMetrics{
+ Type: int(m.raw[24]),
+ MTU: int(nativeEndian.Uint32(m.raw[28:32])),
+ },
+ }
+}
+
+func probeRoutingStack() (int, map[int]parseFn) {
+ var p uintptr
+ nooff := &wireFormat{extOff: -1, bodyOff: -1}
+ return int(unsafe.Sizeof(p)), map[int]parseFn{
+ sysRTM_ADD: nooff.parseRouteMessage,
+ sysRTM_DELETE: nooff.parseRouteMessage,
+ sysRTM_CHANGE: nooff.parseRouteMessage,
+ sysRTM_GET: nooff.parseRouteMessage,
+ sysRTM_LOSING: nooff.parseRouteMessage,
+ sysRTM_REDIRECT: nooff.parseRouteMessage,
+ sysRTM_MISS: nooff.parseRouteMessage,
+ sysRTM_LOCK: nooff.parseRouteMessage,
+ sysRTM_RESOLVE: nooff.parseRouteMessage,
+ sysRTM_NEWADDR: nooff.parseInterfaceAddrMessage,
+ sysRTM_DELADDR: nooff.parseInterfaceAddrMessage,
+ sysRTM_IFINFO: nooff.parseInterfaceMessage,
+ sysRTM_IFANNOUNCE: nooff.parseInterfaceAnnounceMessage,
+ }
+}
diff --git a/src/vendor/golang.org/x/net/route/syscall.go b/src/vendor/golang.org/x/net/route/syscall.go
new file mode 100644
index 00000000000000..d136325a30a258
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/syscall.go
@@ -0,0 +1,33 @@
+// Copyright 2016 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 darwin dragonfly freebsd netbsd openbsd
+
+package route
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+// TODO: replace with runtime.KeepAlive when available
+//go:noescape
+func keepAlive(p unsafe.Pointer)
+
+var zero uintptr
+
+func sysctl(mib []int32, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error {
+ var p unsafe.Pointer
+ if len(mib) > 0 {
+ p = unsafe.Pointer(&mib[0])
+ } else {
+ p = unsafe.Pointer(&zero)
+ }
+ _, _, errno := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(p), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
+ keepAlive(p)
+ if errno != 0 {
+ return error(errno)
+ }
+ return nil
+}
diff --git a/src/vendor/golang.org/x/net/route/syscall.s b/src/vendor/golang.org/x/net/route/syscall.s
new file mode 100644
index 00000000000000..fa6297f0aa127d
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/syscall.s
@@ -0,0 +1,8 @@
+// Copyright 2016 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 ·keepAlive(SB),NOSPLIT,$0
+ RET
diff --git a/src/vendor/golang.org/x/net/route/zsys_darwin.go b/src/vendor/golang.org/x/net/route/zsys_darwin.go
new file mode 100644
index 00000000000000..265b81cd50e695
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/zsys_darwin.go
@@ -0,0 +1,93 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_darwin.go
+
+package route
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_ROUTE = 0x11
+ sysAF_LINK = 0x12
+ sysAF_INET6 = 0x1e
+
+ sysNET_RT_DUMP = 0x1
+ sysNET_RT_FLAGS = 0x2
+ sysNET_RT_IFLIST = 0x3
+ sysNET_RT_STAT = 0x4
+ sysNET_RT_TRASH = 0x5
+ sysNET_RT_IFLIST2 = 0x6
+ sysNET_RT_DUMP2 = 0x7
+ sysNET_RT_MAXID = 0xa
+)
+
+const (
+ sysCTL_MAXNAME = 0xc
+
+ sysCTL_UNSPEC = 0x0
+ sysCTL_KERN = 0x1
+ sysCTL_VM = 0x2
+ sysCTL_VFS = 0x3
+ sysCTL_NET = 0x4
+ sysCTL_DEBUG = 0x5
+ sysCTL_HW = 0x6
+ sysCTL_MACHDEP = 0x7
+ sysCTL_USER = 0x8
+ sysCTL_MAXID = 0x9
+)
+
+const (
+ sysRTM_VERSION = 0x5
+
+ sysRTM_ADD = 0x1
+ sysRTM_DELETE = 0x2
+ sysRTM_CHANGE = 0x3
+ sysRTM_GET = 0x4
+ sysRTM_LOSING = 0x5
+ sysRTM_REDIRECT = 0x6
+ sysRTM_MISS = 0x7
+ sysRTM_LOCK = 0x8
+ sysRTM_OLDADD = 0x9
+ sysRTM_OLDDEL = 0xa
+ sysRTM_RESOLVE = 0xb
+ sysRTM_NEWADDR = 0xc
+ sysRTM_DELADDR = 0xd
+ sysRTM_IFINFO = 0xe
+ sysRTM_NEWMADDR = 0xf
+ sysRTM_DELMADDR = 0x10
+ sysRTM_IFINFO2 = 0x12
+ sysRTM_NEWMADDR2 = 0x13
+ sysRTM_GET2 = 0x14
+
+ sysRTA_DST = 0x1
+ sysRTA_GATEWAY = 0x2
+ sysRTA_NETMASK = 0x4
+ sysRTA_GENMASK = 0x8
+ sysRTA_IFP = 0x10
+ sysRTA_IFA = 0x20
+ sysRTA_AUTHOR = 0x40
+ sysRTA_BRD = 0x80
+
+ sysRTAX_DST = 0x0
+ sysRTAX_GATEWAY = 0x1
+ sysRTAX_NETMASK = 0x2
+ sysRTAX_GENMASK = 0x3
+ sysRTAX_IFP = 0x4
+ sysRTAX_IFA = 0x5
+ sysRTAX_AUTHOR = 0x6
+ sysRTAX_BRD = 0x7
+ sysRTAX_MAX = 0x8
+)
+
+const (
+ sizeofIfMsghdrDarwin15 = 0x70
+ sizeofIfaMsghdrDarwin15 = 0x14
+ sizeofIfmaMsghdrDarwin15 = 0x10
+ sizeofIfMsghdr2Darwin15 = 0xa0
+ sizeofIfmaMsghdr2Darwin15 = 0x14
+ sizeofIfDataDarwin15 = 0x60
+ sizeofIfData64Darwin15 = 0x80
+
+ sizeofRtMsghdrDarwin15 = 0x5c
+ sizeofRtMsghdr2Darwin15 = 0x5c
+ sizeofRtMetricsDarwin15 = 0x38
+)
diff --git a/src/vendor/golang.org/x/net/route/zsys_dragonfly.go b/src/vendor/golang.org/x/net/route/zsys_dragonfly.go
new file mode 100644
index 00000000000000..dd36dece0f6dbf
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/zsys_dragonfly.go
@@ -0,0 +1,92 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_dragonfly.go
+
+package route
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_ROUTE = 0x11
+ sysAF_LINK = 0x12
+ sysAF_INET6 = 0x1c
+
+ sysNET_RT_DUMP = 0x1
+ sysNET_RT_FLAGS = 0x2
+ sysNET_RT_IFLIST = 0x3
+ sysNET_RT_MAXID = 0x4
+)
+
+const (
+ sysCTL_MAXNAME = 0xc
+
+ sysCTL_UNSPEC = 0x0
+ sysCTL_KERN = 0x1
+ sysCTL_VM = 0x2
+ sysCTL_VFS = 0x3
+ sysCTL_NET = 0x4
+ sysCTL_DEBUG = 0x5
+ sysCTL_HW = 0x6
+ sysCTL_MACHDEP = 0x7
+ sysCTL_USER = 0x8
+ sysCTL_P1003_1B = 0x9
+ sysCTL_LWKT = 0xa
+ sysCTL_MAXID = 0xb
+)
+
+const (
+ sysRTM_VERSION = 0x6
+
+ sysRTM_ADD = 0x1
+ sysRTM_DELETE = 0x2
+ sysRTM_CHANGE = 0x3
+ sysRTM_GET = 0x4
+ sysRTM_LOSING = 0x5
+ sysRTM_REDIRECT = 0x6
+ sysRTM_MISS = 0x7
+ sysRTM_LOCK = 0x8
+ sysRTM_OLDADD = 0x9
+ sysRTM_OLDDEL = 0xa
+ sysRTM_RESOLVE = 0xb
+ sysRTM_NEWADDR = 0xc
+ sysRTM_DELADDR = 0xd
+ sysRTM_IFINFO = 0xe
+ sysRTM_NEWMADDR = 0xf
+ sysRTM_DELMADDR = 0x10
+ sysRTM_IFANNOUNCE = 0x11
+ sysRTM_IEEE80211 = 0x12
+
+ sysRTA_DST = 0x1
+ sysRTA_GATEWAY = 0x2
+ sysRTA_NETMASK = 0x4
+ sysRTA_GENMASK = 0x8
+ sysRTA_IFP = 0x10
+ sysRTA_IFA = 0x20
+ sysRTA_AUTHOR = 0x40
+ sysRTA_BRD = 0x80
+ sysRTA_MPLS1 = 0x100
+ sysRTA_MPLS2 = 0x200
+ sysRTA_MPLS3 = 0x400
+
+ sysRTAX_DST = 0x0
+ sysRTAX_GATEWAY = 0x1
+ sysRTAX_NETMASK = 0x2
+ sysRTAX_GENMASK = 0x3
+ sysRTAX_IFP = 0x4
+ sysRTAX_IFA = 0x5
+ sysRTAX_AUTHOR = 0x6
+ sysRTAX_BRD = 0x7
+ sysRTAX_MPLS1 = 0x8
+ sysRTAX_MPLS2 = 0x9
+ sysRTAX_MPLS3 = 0xa
+ sysRTAX_MAX = 0xb
+)
+
+const (
+ sizeofIfMsghdrDragonFlyBSD4 = 0xb0
+ sizeofIfaMsghdrDragonFlyBSD4 = 0x14
+ sizeofIfmaMsghdrDragonFlyBSD4 = 0x10
+ sizeofIfAnnouncemsghdrDragonFlyBSD4 = 0x18
+
+ sizeofRtMsghdrDragonFlyBSD4 = 0x98
+ sizeofRtMetricsDragonFlyBSD4 = 0x70
+)
diff --git a/src/vendor/golang.org/x/net/route/zsys_freebsd_386.go b/src/vendor/golang.org/x/net/route/zsys_freebsd_386.go
new file mode 100644
index 00000000000000..9bac2e3900fbdb
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/zsys_freebsd_386.go
@@ -0,0 +1,120 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_freebsd.go
+
+package route
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_ROUTE = 0x11
+ sysAF_LINK = 0x12
+ sysAF_INET6 = 0x1c
+
+ sysNET_RT_DUMP = 0x1
+ sysNET_RT_FLAGS = 0x2
+ sysNET_RT_IFLIST = 0x3
+ sysNET_RT_IFMALIST = 0x4
+ sysNET_RT_IFLISTL = 0x5
+)
+
+const (
+ sysCTL_MAXNAME = 0x18
+
+ sysCTL_UNSPEC = 0x0
+ sysCTL_KERN = 0x1
+ sysCTL_VM = 0x2
+ sysCTL_VFS = 0x3
+ sysCTL_NET = 0x4
+ sysCTL_DEBUG = 0x5
+ sysCTL_HW = 0x6
+ sysCTL_MACHDEP = 0x7
+ sysCTL_USER = 0x8
+ sysCTL_P1003_1B = 0x9
+)
+
+const (
+ sysRTM_VERSION = 0x5
+
+ sysRTM_ADD = 0x1
+ sysRTM_DELETE = 0x2
+ sysRTM_CHANGE = 0x3
+ sysRTM_GET = 0x4
+ sysRTM_LOSING = 0x5
+ sysRTM_REDIRECT = 0x6
+ sysRTM_MISS = 0x7
+ sysRTM_LOCK = 0x8
+ sysRTM_RESOLVE = 0xb
+ sysRTM_NEWADDR = 0xc
+ sysRTM_DELADDR = 0xd
+ sysRTM_IFINFO = 0xe
+ sysRTM_NEWMADDR = 0xf
+ sysRTM_DELMADDR = 0x10
+ sysRTM_IFANNOUNCE = 0x11
+ sysRTM_IEEE80211 = 0x12
+
+ sysRTA_DST = 0x1
+ sysRTA_GATEWAY = 0x2
+ sysRTA_NETMASK = 0x4
+ sysRTA_GENMASK = 0x8
+ sysRTA_IFP = 0x10
+ sysRTA_IFA = 0x20
+ sysRTA_AUTHOR = 0x40
+ sysRTA_BRD = 0x80
+
+ sysRTAX_DST = 0x0
+ sysRTAX_GATEWAY = 0x1
+ sysRTAX_NETMASK = 0x2
+ sysRTAX_GENMASK = 0x3
+ sysRTAX_IFP = 0x4
+ sysRTAX_IFA = 0x5
+ sysRTAX_AUTHOR = 0x6
+ sysRTAX_BRD = 0x7
+ sysRTAX_MAX = 0x8
+)
+
+const (
+ sizeofIfMsghdrlFreeBSD10 = 0x68
+ sizeofIfaMsghdrFreeBSD10 = 0x14
+ sizeofIfaMsghdrlFreeBSD10 = 0x6c
+ sizeofIfmaMsghdrFreeBSD10 = 0x10
+ sizeofIfAnnouncemsghdrFreeBSD10 = 0x18
+
+ sizeofRtMsghdrFreeBSD10 = 0x5c
+ sizeofRtMetricsFreeBSD10 = 0x38
+
+ sizeofIfMsghdrFreeBSD7 = 0x60
+ sizeofIfMsghdrFreeBSD8 = 0x60
+ sizeofIfMsghdrFreeBSD9 = 0x60
+ sizeofIfMsghdrFreeBSD10 = 0x64
+ sizeofIfMsghdrFreeBSD11 = 0xa8
+
+ sizeofIfDataFreeBSD7 = 0x50
+ sizeofIfDataFreeBSD8 = 0x50
+ sizeofIfDataFreeBSD9 = 0x50
+ sizeofIfDataFreeBSD10 = 0x54
+ sizeofIfDataFreeBSD11 = 0x98
+
+ // MODIFIED BY HAND FOR 386 EMULATION ON AMD64
+ // 386 EMULATION USES THE UNDERLYING RAW DATA LAYOUT
+
+ sizeofIfMsghdrlFreeBSD10Emu = 0xb0
+ sizeofIfaMsghdrFreeBSD10Emu = 0x14
+ sizeofIfaMsghdrlFreeBSD10Emu = 0xb0
+ sizeofIfmaMsghdrFreeBSD10Emu = 0x10
+ sizeofIfAnnouncemsghdrFreeBSD10Emu = 0x18
+
+ sizeofRtMsghdrFreeBSD10Emu = 0x98
+ sizeofRtMetricsFreeBSD10Emu = 0x70
+
+ sizeofIfMsghdrFreeBSD7Emu = 0xa8
+ sizeofIfMsghdrFreeBSD8Emu = 0xa8
+ sizeofIfMsghdrFreeBSD9Emu = 0xa8
+ sizeofIfMsghdrFreeBSD10Emu = 0xa8
+ sizeofIfMsghdrFreeBSD11Emu = 0xa8
+
+ sizeofIfDataFreeBSD7Emu = 0x98
+ sizeofIfDataFreeBSD8Emu = 0x98
+ sizeofIfDataFreeBSD9Emu = 0x98
+ sizeofIfDataFreeBSD10Emu = 0x98
+ sizeofIfDataFreeBSD11Emu = 0x98
+)
diff --git a/src/vendor/golang.org/x/net/route/zsys_freebsd_amd64.go b/src/vendor/golang.org/x/net/route/zsys_freebsd_amd64.go
new file mode 100644
index 00000000000000..b1920d7ac16be8
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/zsys_freebsd_amd64.go
@@ -0,0 +1,117 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_freebsd.go
+
+package route
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_ROUTE = 0x11
+ sysAF_LINK = 0x12
+ sysAF_INET6 = 0x1c
+
+ sysNET_RT_DUMP = 0x1
+ sysNET_RT_FLAGS = 0x2
+ sysNET_RT_IFLIST = 0x3
+ sysNET_RT_IFMALIST = 0x4
+ sysNET_RT_IFLISTL = 0x5
+)
+
+const (
+ sysCTL_MAXNAME = 0x18
+
+ sysCTL_UNSPEC = 0x0
+ sysCTL_KERN = 0x1
+ sysCTL_VM = 0x2
+ sysCTL_VFS = 0x3
+ sysCTL_NET = 0x4
+ sysCTL_DEBUG = 0x5
+ sysCTL_HW = 0x6
+ sysCTL_MACHDEP = 0x7
+ sysCTL_USER = 0x8
+ sysCTL_P1003_1B = 0x9
+)
+
+const (
+ sysRTM_VERSION = 0x5
+
+ sysRTM_ADD = 0x1
+ sysRTM_DELETE = 0x2
+ sysRTM_CHANGE = 0x3
+ sysRTM_GET = 0x4
+ sysRTM_LOSING = 0x5
+ sysRTM_REDIRECT = 0x6
+ sysRTM_MISS = 0x7
+ sysRTM_LOCK = 0x8
+ sysRTM_RESOLVE = 0xb
+ sysRTM_NEWADDR = 0xc
+ sysRTM_DELADDR = 0xd
+ sysRTM_IFINFO = 0xe
+ sysRTM_NEWMADDR = 0xf
+ sysRTM_DELMADDR = 0x10
+ sysRTM_IFANNOUNCE = 0x11
+ sysRTM_IEEE80211 = 0x12
+
+ sysRTA_DST = 0x1
+ sysRTA_GATEWAY = 0x2
+ sysRTA_NETMASK = 0x4
+ sysRTA_GENMASK = 0x8
+ sysRTA_IFP = 0x10
+ sysRTA_IFA = 0x20
+ sysRTA_AUTHOR = 0x40
+ sysRTA_BRD = 0x80
+
+ sysRTAX_DST = 0x0
+ sysRTAX_GATEWAY = 0x1
+ sysRTAX_NETMASK = 0x2
+ sysRTAX_GENMASK = 0x3
+ sysRTAX_IFP = 0x4
+ sysRTAX_IFA = 0x5
+ sysRTAX_AUTHOR = 0x6
+ sysRTAX_BRD = 0x7
+ sysRTAX_MAX = 0x8
+)
+
+const (
+ sizeofIfMsghdrlFreeBSD10 = 0xb0
+ sizeofIfaMsghdrFreeBSD10 = 0x14
+ sizeofIfaMsghdrlFreeBSD10 = 0xb0
+ sizeofIfmaMsghdrFreeBSD10 = 0x10
+ sizeofIfAnnouncemsghdrFreeBSD10 = 0x18
+
+ sizeofRtMsghdrFreeBSD10 = 0x98
+ sizeofRtMetricsFreeBSD10 = 0x70
+
+ sizeofIfMsghdrFreeBSD7 = 0xa8
+ sizeofIfMsghdrFreeBSD8 = 0xa8
+ sizeofIfMsghdrFreeBSD9 = 0xa8
+ sizeofIfMsghdrFreeBSD10 = 0xa8
+ sizeofIfMsghdrFreeBSD11 = 0xa8
+
+ sizeofIfDataFreeBSD7 = 0x98
+ sizeofIfDataFreeBSD8 = 0x98
+ sizeofIfDataFreeBSD9 = 0x98
+ sizeofIfDataFreeBSD10 = 0x98
+ sizeofIfDataFreeBSD11 = 0x98
+
+ sizeofIfMsghdrlFreeBSD10Emu = 0xb0
+ sizeofIfaMsghdrFreeBSD10Emu = 0x14
+ sizeofIfaMsghdrlFreeBSD10Emu = 0xb0
+ sizeofIfmaMsghdrFreeBSD10Emu = 0x10
+ sizeofIfAnnouncemsghdrFreeBSD10Emu = 0x18
+
+ sizeofRtMsghdrFreeBSD10Emu = 0x98
+ sizeofRtMetricsFreeBSD10Emu = 0x70
+
+ sizeofIfMsghdrFreeBSD7Emu = 0xa8
+ sizeofIfMsghdrFreeBSD8Emu = 0xa8
+ sizeofIfMsghdrFreeBSD9Emu = 0xa8
+ sizeofIfMsghdrFreeBSD10Emu = 0xa8
+ sizeofIfMsghdrFreeBSD11Emu = 0xa8
+
+ sizeofIfDataFreeBSD7Emu = 0x98
+ sizeofIfDataFreeBSD8Emu = 0x98
+ sizeofIfDataFreeBSD9Emu = 0x98
+ sizeofIfDataFreeBSD10Emu = 0x98
+ sizeofIfDataFreeBSD11Emu = 0x98
+)
diff --git a/src/vendor/golang.org/x/net/route/zsys_freebsd_arm.go b/src/vendor/golang.org/x/net/route/zsys_freebsd_arm.go
new file mode 100644
index 00000000000000..a034d6fcbf215c
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/zsys_freebsd_arm.go
@@ -0,0 +1,117 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_freebsd.go
+
+package route
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_ROUTE = 0x11
+ sysAF_LINK = 0x12
+ sysAF_INET6 = 0x1c
+
+ sysNET_RT_DUMP = 0x1
+ sysNET_RT_FLAGS = 0x2
+ sysNET_RT_IFLIST = 0x3
+ sysNET_RT_IFMALIST = 0x4
+ sysNET_RT_IFLISTL = 0x5
+)
+
+const (
+ sysCTL_MAXNAME = 0x18
+
+ sysCTL_UNSPEC = 0x0
+ sysCTL_KERN = 0x1
+ sysCTL_VM = 0x2
+ sysCTL_VFS = 0x3
+ sysCTL_NET = 0x4
+ sysCTL_DEBUG = 0x5
+ sysCTL_HW = 0x6
+ sysCTL_MACHDEP = 0x7
+ sysCTL_USER = 0x8
+ sysCTL_P1003_1B = 0x9
+)
+
+const (
+ sysRTM_VERSION = 0x5
+
+ sysRTM_ADD = 0x1
+ sysRTM_DELETE = 0x2
+ sysRTM_CHANGE = 0x3
+ sysRTM_GET = 0x4
+ sysRTM_LOSING = 0x5
+ sysRTM_REDIRECT = 0x6
+ sysRTM_MISS = 0x7
+ sysRTM_LOCK = 0x8
+ sysRTM_RESOLVE = 0xb
+ sysRTM_NEWADDR = 0xc
+ sysRTM_DELADDR = 0xd
+ sysRTM_IFINFO = 0xe
+ sysRTM_NEWMADDR = 0xf
+ sysRTM_DELMADDR = 0x10
+ sysRTM_IFANNOUNCE = 0x11
+ sysRTM_IEEE80211 = 0x12
+
+ sysRTA_DST = 0x1
+ sysRTA_GATEWAY = 0x2
+ sysRTA_NETMASK = 0x4
+ sysRTA_GENMASK = 0x8
+ sysRTA_IFP = 0x10
+ sysRTA_IFA = 0x20
+ sysRTA_AUTHOR = 0x40
+ sysRTA_BRD = 0x80
+
+ sysRTAX_DST = 0x0
+ sysRTAX_GATEWAY = 0x1
+ sysRTAX_NETMASK = 0x2
+ sysRTAX_GENMASK = 0x3
+ sysRTAX_IFP = 0x4
+ sysRTAX_IFA = 0x5
+ sysRTAX_AUTHOR = 0x6
+ sysRTAX_BRD = 0x7
+ sysRTAX_MAX = 0x8
+)
+
+const (
+ sizeofIfMsghdrlFreeBSD10 = 0x68
+ sizeofIfaMsghdrFreeBSD10 = 0x14
+ sizeofIfaMsghdrlFreeBSD10 = 0x6c
+ sizeofIfmaMsghdrFreeBSD10 = 0x10
+ sizeofIfAnnouncemsghdrFreeBSD10 = 0x18
+
+ sizeofRtMsghdrFreeBSD10 = 0x5c
+ sizeofRtMetricsFreeBSD10 = 0x38
+
+ sizeofIfMsghdrFreeBSD7 = 0x70
+ sizeofIfMsghdrFreeBSD8 = 0x70
+ sizeofIfMsghdrFreeBSD9 = 0x70
+ sizeofIfMsghdrFreeBSD10 = 0x70
+ sizeofIfMsghdrFreeBSD11 = 0xa8
+
+ sizeofIfDataFreeBSD7 = 0x60
+ sizeofIfDataFreeBSD8 = 0x60
+ sizeofIfDataFreeBSD9 = 0x60
+ sizeofIfDataFreeBSD10 = 0x60
+ sizeofIfDataFreeBSD11 = 0x98
+
+ sizeofIfMsghdrlFreeBSD10Emu = 0x68
+ sizeofIfaMsghdrFreeBSD10Emu = 0x14
+ sizeofIfaMsghdrlFreeBSD10Emu = 0x6c
+ sizeofIfmaMsghdrFreeBSD10Emu = 0x10
+ sizeofIfAnnouncemsghdrFreeBSD10Emu = 0x18
+
+ sizeofRtMsghdrFreeBSD10Emu = 0x5c
+ sizeofRtMetricsFreeBSD10Emu = 0x38
+
+ sizeofIfMsghdrFreeBSD7Emu = 0x70
+ sizeofIfMsghdrFreeBSD8Emu = 0x70
+ sizeofIfMsghdrFreeBSD9Emu = 0x70
+ sizeofIfMsghdrFreeBSD10Emu = 0x70
+ sizeofIfMsghdrFreeBSD11Emu = 0xa8
+
+ sizeofIfDataFreeBSD7Emu = 0x60
+ sizeofIfDataFreeBSD8Emu = 0x60
+ sizeofIfDataFreeBSD9Emu = 0x60
+ sizeofIfDataFreeBSD10Emu = 0x60
+ sizeofIfDataFreeBSD11Emu = 0x98
+)
diff --git a/src/vendor/golang.org/x/net/route/zsys_netbsd.go b/src/vendor/golang.org/x/net/route/zsys_netbsd.go
new file mode 100644
index 00000000000000..aa4aad1613e22f
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/zsys_netbsd.go
@@ -0,0 +1,91 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_netbsd.go
+
+package route
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_ROUTE = 0x22
+ sysAF_LINK = 0x12
+ sysAF_INET6 = 0x18
+
+ sysNET_RT_DUMP = 0x1
+ sysNET_RT_FLAGS = 0x2
+ sysNET_RT_IFLIST = 0x5
+ sysNET_RT_MAXID = 0x6
+)
+
+const (
+ sysCTL_MAXNAME = 0xc
+
+ sysCTL_UNSPEC = 0x0
+ sysCTL_KERN = 0x1
+ sysCTL_VM = 0x2
+ sysCTL_VFS = 0x3
+ sysCTL_NET = 0x4
+ sysCTL_DEBUG = 0x5
+ sysCTL_HW = 0x6
+ sysCTL_MACHDEP = 0x7
+ sysCTL_USER = 0x8
+ sysCTL_DDB = 0x9
+ sysCTL_PROC = 0xa
+ sysCTL_VENDOR = 0xb
+ sysCTL_EMUL = 0xc
+ sysCTL_SECURITY = 0xd
+ sysCTL_MAXID = 0xe
+)
+
+const (
+ sysRTM_VERSION = 0x4
+
+ sysRTM_ADD = 0x1
+ sysRTM_DELETE = 0x2
+ sysRTM_CHANGE = 0x3
+ sysRTM_GET = 0x4
+ sysRTM_LOSING = 0x5
+ sysRTM_REDIRECT = 0x6
+ sysRTM_MISS = 0x7
+ sysRTM_LOCK = 0x8
+ sysRTM_OLDADD = 0x9
+ sysRTM_OLDDEL = 0xa
+ sysRTM_RESOLVE = 0xb
+ sysRTM_NEWADDR = 0xc
+ sysRTM_DELADDR = 0xd
+ sysRTM_IFANNOUNCE = 0x10
+ sysRTM_IEEE80211 = 0x11
+ sysRTM_SETGATE = 0x12
+ sysRTM_LLINFO_UPD = 0x13
+ sysRTM_IFINFO = 0x14
+ sysRTM_CHGADDR = 0x15
+
+ sysRTA_DST = 0x1
+ sysRTA_GATEWAY = 0x2
+ sysRTA_NETMASK = 0x4
+ sysRTA_GENMASK = 0x8
+ sysRTA_IFP = 0x10
+ sysRTA_IFA = 0x20
+ sysRTA_AUTHOR = 0x40
+ sysRTA_BRD = 0x80
+ sysRTA_TAG = 0x100
+
+ sysRTAX_DST = 0x0
+ sysRTAX_GATEWAY = 0x1
+ sysRTAX_NETMASK = 0x2
+ sysRTAX_GENMASK = 0x3
+ sysRTAX_IFP = 0x4
+ sysRTAX_IFA = 0x5
+ sysRTAX_AUTHOR = 0x6
+ sysRTAX_BRD = 0x7
+ sysRTAX_TAG = 0x8
+ sysRTAX_MAX = 0x9
+)
+
+const (
+ sizeofIfMsghdrNetBSD7 = 0x98
+ sizeofIfaMsghdrNetBSD7 = 0x18
+ sizeofIfAnnouncemsghdrNetBSD7 = 0x18
+
+ sizeofRtMsghdrNetBSD7 = 0x78
+ sizeofRtMetricsNetBSD7 = 0x50
+)
diff --git a/src/vendor/golang.org/x/net/route/zsys_openbsd.go b/src/vendor/golang.org/x/net/route/zsys_openbsd.go
new file mode 100644
index 00000000000000..4fadc4e8fa1e54
--- /dev/null
+++ b/src/vendor/golang.org/x/net/route/zsys_openbsd.go
@@ -0,0 +1,80 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_openbsd.go
+
+package route
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_ROUTE = 0x11
+ sysAF_LINK = 0x12
+ sysAF_INET6 = 0x18
+
+ sysNET_RT_DUMP = 0x1
+ sysNET_RT_FLAGS = 0x2
+ sysNET_RT_IFLIST = 0x3
+ sysNET_RT_STATS = 0x4
+ sysNET_RT_TABLE = 0x5
+ sysNET_RT_IFNAMES = 0x6
+ sysNET_RT_MAXID = 0x7
+)
+
+const (
+ sysCTL_MAXNAME = 0xc
+
+ sysCTL_UNSPEC = 0x0
+ sysCTL_KERN = 0x1
+ sysCTL_VM = 0x2
+ sysCTL_FS = 0x3
+ sysCTL_NET = 0x4
+ sysCTL_DEBUG = 0x5
+ sysCTL_HW = 0x6
+ sysCTL_MACHDEP = 0x7
+ sysCTL_DDB = 0x9
+ sysCTL_VFS = 0xa
+ sysCTL_MAXID = 0xb
+)
+
+const (
+ sysRTM_VERSION = 0x5
+
+ sysRTM_ADD = 0x1
+ sysRTM_DELETE = 0x2
+ sysRTM_CHANGE = 0x3
+ sysRTM_GET = 0x4
+ sysRTM_LOSING = 0x5
+ sysRTM_REDIRECT = 0x6
+ sysRTM_MISS = 0x7
+ sysRTM_LOCK = 0x8
+ sysRTM_RESOLVE = 0xb
+ sysRTM_NEWADDR = 0xc
+ sysRTM_DELADDR = 0xd
+ sysRTM_IFINFO = 0xe
+ sysRTM_IFANNOUNCE = 0xf
+ sysRTM_DESYNC = 0x10
+
+ sysRTA_DST = 0x1
+ sysRTA_GATEWAY = 0x2
+ sysRTA_NETMASK = 0x4
+ sysRTA_GENMASK = 0x8
+ sysRTA_IFP = 0x10
+ sysRTA_IFA = 0x20
+ sysRTA_AUTHOR = 0x40
+ sysRTA_BRD = 0x80
+ sysRTA_SRC = 0x100
+ sysRTA_SRCMASK = 0x200
+ sysRTA_LABEL = 0x400
+
+ sysRTAX_DST = 0x0
+ sysRTAX_GATEWAY = 0x1
+ sysRTAX_NETMASK = 0x2
+ sysRTAX_GENMASK = 0x3
+ sysRTAX_IFP = 0x4
+ sysRTAX_IFA = 0x5
+ sysRTAX_AUTHOR = 0x6
+ sysRTAX_BRD = 0x7
+ sysRTAX_SRC = 0x8
+ sysRTAX_SRCMASK = 0x9
+ sysRTAX_LABEL = 0xa
+ sysRTAX_MAX = 0xb
+)
From 0bc14f57ec7e5518af711a64103ca2ac72f19a6e Mon Sep 17 00:00:00 2001
From: Keith Randall
Date: Sat, 14 May 2016 17:33:23 -0700
Subject: [PATCH 103/267] strings: fix Contains on amd64
The 17-31 byte code is broken. Disabled it.
Added a bunch of tests to at least cover the cases
in indexShortStr. I'll channel Brad and wonder why
this CL ever got in without any tests.
Fixes #15679
Change-Id: I84a7b283a74107db865b9586c955dcf5f2d60161
Reviewed-on: https://go-review.googlesource.com/23106
Reviewed-by: Brad Fitzpatrick
Run-TryBot: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
---
src/runtime/asm_amd64.s | 1 +
src/strings/strings_amd64.go | 2 +-
src/strings/strings_test.go | 64 ++++++++++++++++++++++++++++++++++++
3 files changed, 66 insertions(+), 1 deletion(-)
diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s
index 6cd31f951bda74..d6e54941805b4a 100644
--- a/src/runtime/asm_amd64.s
+++ b/src/runtime/asm_amd64.s
@@ -1800,6 +1800,7 @@ loop16:
CMPQ DI,DX
JB loop16
JMP fail
+//TODO: the code below is wrong. Fix it. See #15679.
_17_to_31:
LEAQ 1(DI)(DX*1), DX
SUBQ AX, DX
diff --git a/src/strings/strings_amd64.go b/src/strings/strings_amd64.go
index 55bf2d2f6fc77a..91b29ce358fa6d 100644
--- a/src/strings/strings_amd64.go
+++ b/src/strings/strings_amd64.go
@@ -7,7 +7,7 @@ package strings
// indexShortStr returns the index of the first instance of c in s, or -1 if c is not present in s.
// indexShortStr requires 2 <= len(c) <= shortStringLen
func indexShortStr(s, c string) int // ../runtime/asm_$GOARCH.s
-const shortStringLen = 31
+const shortStringLen = 16 // TODO: restore to 31 when #15679 is fixed
// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
func Index(s, sep string) int {
diff --git a/src/strings/strings_test.go b/src/strings/strings_test.go
index d92dfcc8742b27..6bd6fb5443d31f 100644
--- a/src/strings/strings_test.go
+++ b/src/strings/strings_test.go
@@ -1036,6 +1036,70 @@ var ContainsTests = []struct {
{"abc", "bcd", false},
{"abc", "", true},
{"", "a", false},
+
+ // cases to cover code in runtime/asm_amd64.s:indexShortStr
+ // 2-byte needle
+ {"xxxxxx", "01", false},
+ {"01xxxx", "01", true},
+ {"xx01xx", "01", true},
+ {"xxxx01", "01", true},
+ {"01xxxxx"[1:], "01", false},
+ {"xxxxx01"[:6], "01", false},
+ // 3-byte needle
+ {"xxxxxxx", "012", false},
+ {"012xxxx", "012", true},
+ {"xx012xx", "012", true},
+ {"xxxx012", "012", true},
+ {"012xxxxx"[1:], "012", false},
+ {"xxxxx012"[:7], "012", false},
+ // 4-byte needle
+ {"xxxxxxxx", "0123", false},
+ {"0123xxxx", "0123", true},
+ {"xx0123xx", "0123", true},
+ {"xxxx0123", "0123", true},
+ {"0123xxxxx"[1:], "0123", false},
+ {"xxxxx0123"[:8], "0123", false},
+ // 5-7-byte needle
+ {"xxxxxxxxx", "01234", false},
+ {"01234xxxx", "01234", true},
+ {"xx01234xx", "01234", true},
+ {"xxxx01234", "01234", true},
+ {"01234xxxxx"[1:], "01234", false},
+ {"xxxxx01234"[:9], "01234", false},
+ // 8-byte needle
+ {"xxxxxxxxxxxx", "01234567", false},
+ {"01234567xxxx", "01234567", true},
+ {"xx01234567xx", "01234567", true},
+ {"xxxx01234567", "01234567", true},
+ {"01234567xxxxx"[1:], "01234567", false},
+ {"xxxxx01234567"[:12], "01234567", false},
+ // 9-15-byte needle
+ {"xxxxxxxxxxxxx", "012345678", false},
+ {"012345678xxxx", "012345678", true},
+ {"xx012345678xx", "012345678", true},
+ {"xxxx012345678", "012345678", true},
+ {"012345678xxxxx"[1:], "012345678", false},
+ {"xxxxx012345678"[:13], "012345678", false},
+ // 16-byte needle
+ {"xxxxxxxxxxxxxxxxxxxx", "0123456789ABCDEF", false},
+ {"0123456789ABCDEFxxxx", "0123456789ABCDEF", true},
+ {"xx0123456789ABCDEFxx", "0123456789ABCDEF", true},
+ {"xxxx0123456789ABCDEF", "0123456789ABCDEF", true},
+ {"0123456789ABCDEFxxxxx"[1:], "0123456789ABCDEF", false},
+ {"xxxxx0123456789ABCDEF"[:20], "0123456789ABCDEF", false},
+ // 17-31-byte needle
+ {"xxxxxxxxxxxxxxxxxxxxx", "0123456789ABCDEFG", false},
+ {"0123456789ABCDEFGxxxx", "0123456789ABCDEFG", true},
+ {"xx0123456789ABCDEFGxx", "0123456789ABCDEFG", true},
+ {"xxxx0123456789ABCDEFG", "0123456789ABCDEFG", true},
+ {"0123456789ABCDEFGxxxxx"[1:], "0123456789ABCDEFG", false},
+ {"xxxxx0123456789ABCDEFG"[:21], "0123456789ABCDEFG", false},
+
+ // partial match cases
+ {"xx01x", "012", false}, // 3
+ {"xx0123x", "01234", false}, // 5-7
+ {"xx01234567x", "012345678", false}, // 9-15
+ {"xx0123456789ABCDEFx", "0123456789ABCDEFG", false}, // 17-31, issue 15679
}
func TestContains(t *testing.T) {
From b4bf0663fa3334d053981f222eed5015a0a1b8df Mon Sep 17 00:00:00 2001
From: Mikio Hara
Date: Sat, 23 Apr 2016 22:36:41 +0900
Subject: [PATCH 104/267] net: golang.org/x/net/route plumbing
This change makes use of new routing message APIs for BSD variants to
support FreeBSD 11 and newer versions of other BSDs.
Fixes #7849.
Fixes #14724.
Change-Id: I56c7886d6622cdeddd7cc29c8a8062dcc06216d5
Reviewed-on: https://go-review.googlesource.com/22451
Reviewed-by: Ian Lance Taylor
Run-TryBot: Mikio Hara
TryBot-Result: Gobot Gobot
---
src/go/build/deps_test.go | 7 +-
src/net/interface_bsd.go | 167 ++++++------------
...rface_dragonfly.go => interface_bsdvar.go} | 16 ++
src/net/interface_darwin.go | 67 +++----
src/net/interface_freebsd.go | 72 ++++----
src/net/interface_netbsd.go | 12 --
src/net/interface_openbsd.go | 12 --
src/net/interface_test.go | 21 ---
8 files changed, 141 insertions(+), 233 deletions(-)
rename src/net/{interface_dragonfly.go => interface_bsdvar.go} (54%)
delete mode 100644 src/net/interface_netbsd.go
delete mode 100644 src/net/interface_openbsd.go
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index d0d4fbba162967..958e410dd95120 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -292,10 +292,13 @@ var pkgDeps = map[string][]string{
// Basic networking.
// Because net must be used by any package that wants to
// do networking portably, it must have a small dependency set: just L0+basic os.
- "net": {"L0", "CGO",
+ "net": {
+ "L0", "CGO",
"context", "math/rand", "os", "sort", "syscall", "time",
"internal/nettrace",
- "internal/syscall/windows", "internal/singleflight", "internal/race"},
+ "internal/syscall/windows", "internal/singleflight", "internal/race",
+ "golang.org/x/net/route",
+ },
// NET enables use of basic network-related packages.
"NET": {
diff --git a/src/net/interface_bsd.go b/src/net/interface_bsd.go
index 17c6dd3dcd69df..1ca2f36e772790 100644
--- a/src/net/interface_bsd.go
+++ b/src/net/interface_bsd.go
@@ -7,74 +7,58 @@
package net
import (
- "os"
"syscall"
- "unsafe"
+
+ "golang.org/x/net/route"
)
// If the ifindex is zero, interfaceTable returns mappings of all
// network interfaces. Otherwise it returns a mapping of a specific
// interface.
func interfaceTable(ifindex int) ([]Interface, error) {
- tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex)
- if err != nil {
- return nil, os.NewSyscallError("routerib", err)
- }
- msgs, err := syscall.ParseRoutingMessage(tab)
+ msgs, err := interfaceMessages(ifindex)
if err != nil {
- return nil, os.NewSyscallError("parseroutingmessage", err)
+ return nil, err
}
return parseInterfaceTable(ifindex, msgs)
}
-func parseInterfaceTable(ifindex int, msgs []syscall.RoutingMessage) ([]Interface, error) {
- var ift []Interface
-loop:
+func parseInterfaceTable(ifindex int, msgs []route.Message) ([]Interface, error) {
+ n := len(msgs)
+ if ifindex != 0 {
+ n = 1
+ }
+ ift := make([]Interface, n)
+ n = 0
for _, m := range msgs {
switch m := m.(type) {
- case *syscall.InterfaceMessage:
- if ifindex == 0 || ifindex == int(m.Header.Index) {
- ifi, err := newLink(m)
- if err != nil {
- return nil, err
- }
- ift = append(ift, *ifi)
- if ifindex == int(m.Header.Index) {
- break loop
+ case *route.InterfaceMessage:
+ if ifindex != 0 && ifindex != m.Index {
+ continue
+ }
+ ift[n].Index = m.Index
+ ift[n].Name = m.Name
+ ift[n].Flags = linkFlags(m.Flags)
+ if sa, ok := m.Addrs[syscall.RTAX_IFP].(*route.LinkAddr); ok && len(sa.Addr) > 0 {
+ ift[n].HardwareAddr = make([]byte, len(sa.Addr))
+ copy(ift[n].HardwareAddr, sa.Addr)
+ }
+ for _, sys := range m.Sys() {
+ if imx, ok := sys.(*route.InterfaceMetrics); ok {
+ ift[n].MTU = imx.MTU
+ break
}
}
+ n++
+ if ifindex == m.Index {
+ return ift[:n], nil
+ }
}
}
- return ift, nil
-}
-
-func newLink(m *syscall.InterfaceMessage) (*Interface, error) {
- sas, err := syscall.ParseRoutingSockaddr(m)
- if err != nil {
- return nil, os.NewSyscallError("parseroutingsockaddr", err)
- }
- ifi := &Interface{Index: int(m.Header.Index), Flags: linkFlags(m.Header.Flags)}
- sa, _ := sas[syscall.RTAX_IFP].(*syscall.SockaddrDatalink)
- if sa != nil {
- // NOTE: SockaddrDatalink.Data is minimum work area,
- // can be larger.
- m.Data = m.Data[unsafe.Offsetof(sa.Data):]
- var name [syscall.IFNAMSIZ]byte
- for i := 0; i < int(sa.Nlen); i++ {
- name[i] = m.Data[i]
- }
- ifi.Name = string(name[:sa.Nlen])
- ifi.MTU = int(m.Header.Data.Mtu)
- addr := make([]byte, sa.Alen)
- for i := 0; i < int(sa.Alen); i++ {
- addr[i] = m.Data[int(sa.Nlen)+i]
- }
- ifi.HardwareAddr = addr[:sa.Alen]
- }
- return ifi, nil
+ return ift[:n], nil
}
-func linkFlags(rawFlags int32) Flags {
+func linkFlags(rawFlags int) Flags {
var f Flags
if rawFlags&syscall.IFF_UP != 0 {
f |= FlagUp
@@ -102,74 +86,37 @@ func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
if ifi != nil {
index = ifi.Index
}
- tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, index)
- if err != nil {
- return nil, os.NewSyscallError("routerib", err)
- }
- msgs, err := syscall.ParseRoutingMessage(tab)
+ msgs, err := interfaceMessages(index)
if err != nil {
- return nil, os.NewSyscallError("parseroutingmessage", err)
+ return nil, err
}
- var ift []Interface
- if index == 0 {
- ift, err = parseInterfaceTable(index, msgs)
- if err != nil {
- return nil, err
- }
- }
- var ifat []Addr
+ ifat := make([]Addr, 0, len(msgs))
for _, m := range msgs {
switch m := m.(type) {
- case *syscall.InterfaceAddrMessage:
- if index == 0 || index == int(m.Header.Index) {
- if index == 0 {
- var err error
- ifi, err = interfaceByIndex(ift, int(m.Header.Index))
- if err != nil {
- return nil, err
- }
- }
- ifa, err := newAddr(ifi, m)
- if err != nil {
- return nil, err
- }
- if ifa != nil {
- ifat = append(ifat, ifa)
- }
+ case *route.InterfaceAddrMessage:
+ if index != 0 && index != m.Index {
+ continue
+ }
+ var mask IPMask
+ switch sa := m.Addrs[syscall.RTAX_NETMASK].(type) {
+ case *route.Inet4Addr:
+ mask = IPv4Mask(sa.IP[0], sa.IP[1], sa.IP[2], sa.IP[3])
+ case *route.Inet6Addr:
+ mask = make(IPMask, IPv6len)
+ copy(mask, sa.IP[:])
+ }
+ var ip IP
+ switch sa := m.Addrs[syscall.RTAX_IFA].(type) {
+ case *route.Inet4Addr:
+ ip = IPv4(sa.IP[0], sa.IP[1], sa.IP[2], sa.IP[3])
+ case *route.Inet6Addr:
+ ip = make(IP, IPv6len)
+ copy(ip, sa.IP[:])
+ }
+ if ip != nil && mask != nil { // NetBSD may contain route.LinkAddr
+ ifat = append(ifat, &IPNet{IP: ip, Mask: mask})
}
}
}
return ifat, nil
}
-
-func newAddr(ifi *Interface, m *syscall.InterfaceAddrMessage) (*IPNet, error) {
- sas, err := syscall.ParseRoutingSockaddr(m)
- if err != nil {
- return nil, os.NewSyscallError("parseroutingsockaddr", err)
- }
- ifa := &IPNet{}
- switch sa := sas[syscall.RTAX_NETMASK].(type) {
- case *syscall.SockaddrInet4:
- ifa.Mask = IPv4Mask(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])
- case *syscall.SockaddrInet6:
- ifa.Mask = make(IPMask, IPv6len)
- copy(ifa.Mask, sa.Addr[:])
- }
- switch sa := sas[syscall.RTAX_IFA].(type) {
- case *syscall.SockaddrInet4:
- ifa.IP = IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])
- case *syscall.SockaddrInet6:
- ifa.IP = make(IP, IPv6len)
- copy(ifa.IP, sa.Addr[:])
- // NOTE: KAME based IPv6 protocol stack usually embeds
- // the interface index in the interface-local or
- // link-local address as the kernel-internal form.
- if ifa.IP.IsLinkLocalUnicast() {
- ifa.IP[2], ifa.IP[3] = 0, 0
- }
- }
- if ifa.IP == nil || ifa.Mask == nil {
- return nil, nil // Sockaddrs contain syscall.SockaddrDatalink on NetBSD
- }
- return ifa, nil
-}
diff --git a/src/net/interface_dragonfly.go b/src/net/interface_bsdvar.go
similarity index 54%
rename from src/net/interface_dragonfly.go
rename to src/net/interface_bsdvar.go
index cb7a34ab166004..a809b5f5ce49e6 100644
--- a/src/net/interface_dragonfly.go
+++ b/src/net/interface_bsdvar.go
@@ -2,8 +2,24 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build dragonfly netbsd openbsd
+
package net
+import (
+ "syscall"
+
+ "golang.org/x/net/route"
+)
+
+func interfaceMessages(ifindex int) ([]route.Message, error) {
+ rib, err := route.FetchRIB(syscall.AF_UNSPEC, syscall.NET_RT_IFLIST, ifindex)
+ if err != nil {
+ return nil, err
+ }
+ return route.ParseRIB(syscall.NET_RT_IFLIST, rib)
+}
+
// interfaceMulticastAddrTable returns addresses for a specific
// interface.
func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
diff --git a/src/net/interface_darwin.go b/src/net/interface_darwin.go
index 72fb9443c07d49..bb4fd73a987670 100644
--- a/src/net/interface_darwin.go
+++ b/src/net/interface_darwin.go
@@ -5,58 +5,49 @@
package net
import (
- "os"
"syscall"
+
+ "golang.org/x/net/route"
)
+func interfaceMessages(ifindex int) ([]route.Message, error) {
+ rib, err := route.FetchRIB(syscall.AF_UNSPEC, syscall.NET_RT_IFLIST, ifindex)
+ if err != nil {
+ return nil, err
+ }
+ return route.ParseRIB(syscall.NET_RT_IFLIST, rib)
+}
+
// interfaceMulticastAddrTable returns addresses for a specific
// interface.
func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
- tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST2, ifi.Index)
+ rib, err := route.FetchRIB(syscall.AF_UNSPEC, syscall.NET_RT_IFLIST2, ifi.Index)
if err != nil {
- return nil, os.NewSyscallError("routerib", err)
+ return nil, err
}
- msgs, err := syscall.ParseRoutingMessage(tab)
+ msgs, err := route.ParseRIB(syscall.NET_RT_IFLIST2, rib)
if err != nil {
- return nil, os.NewSyscallError("parseroutingmessage", err)
+ return nil, err
}
- var ifmat []Addr
+ ifmat := make([]Addr, 0, len(msgs))
for _, m := range msgs {
switch m := m.(type) {
- case *syscall.InterfaceMulticastAddrMessage:
- if ifi.Index == int(m.Header.Index) {
- ifma, err := newMulticastAddr(ifi, m)
- if err != nil {
- return nil, err
- }
- if ifma != nil {
- ifmat = append(ifmat, ifma)
- }
+ case *route.InterfaceMulticastAddrMessage:
+ if ifi.Index != m.Index {
+ continue
+ }
+ var ip IP
+ switch sa := m.Addrs[syscall.RTAX_IFA].(type) {
+ case *route.Inet4Addr:
+ ip = IPv4(sa.IP[0], sa.IP[1], sa.IP[2], sa.IP[3])
+ case *route.Inet6Addr:
+ ip = make(IP, IPv6len)
+ copy(ip, sa.IP[:])
+ }
+ if ip != nil {
+ ifmat = append(ifmat, &IPAddr{IP: ip})
}
}
}
return ifmat, nil
}
-
-func newMulticastAddr(ifi *Interface, m *syscall.InterfaceMulticastAddrMessage) (*IPAddr, error) {
- sas, err := syscall.ParseRoutingSockaddr(m)
- if err != nil {
- return nil, os.NewSyscallError("parseroutingsockaddr", err)
- }
- switch sa := sas[syscall.RTAX_IFA].(type) {
- case *syscall.SockaddrInet4:
- return &IPAddr{IP: IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])}, nil
- case *syscall.SockaddrInet6:
- ifma := IPAddr{IP: make(IP, IPv6len)}
- copy(ifma.IP, sa.Addr[:])
- // NOTE: KAME based IPv6 protocol stack usually embeds
- // the interface index in the interface-local or
- // link-local address as the kernel-internal form.
- if ifma.IP.IsInterfaceLocalMulticast() || ifma.IP.IsLinkLocalMulticast() {
- ifma.IP[2], ifma.IP[3] = 0, 0
- }
- return &ifma, nil
- default:
- return nil, nil
- }
-}
diff --git a/src/net/interface_freebsd.go b/src/net/interface_freebsd.go
index bddee8bacb75f2..45badd64954a17 100644
--- a/src/net/interface_freebsd.go
+++ b/src/net/interface_freebsd.go
@@ -5,58 +5,54 @@
package net
import (
- "os"
"syscall"
+
+ "golang.org/x/net/route"
)
+func interfaceMessages(ifindex int) ([]route.Message, error) {
+ typ := route.RIBType(syscall.NET_RT_IFLISTL)
+ rib, err := route.FetchRIB(syscall.AF_UNSPEC, typ, ifindex)
+ if err != nil {
+ typ = route.RIBType(syscall.NET_RT_IFLIST)
+ rib, err = route.FetchRIB(syscall.AF_UNSPEC, typ, ifindex)
+ }
+ if err != nil {
+ return nil, err
+ }
+ return route.ParseRIB(typ, rib)
+}
+
// interfaceMulticastAddrTable returns addresses for a specific
// interface.
func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
- tab, err := syscall.RouteRIB(syscall.NET_RT_IFMALIST, ifi.Index)
+ rib, err := route.FetchRIB(syscall.AF_UNSPEC, syscall.NET_RT_IFMALIST, ifi.Index)
if err != nil {
- return nil, os.NewSyscallError("routerib", err)
+ return nil, err
}
- msgs, err := syscall.ParseRoutingMessage(tab)
+ msgs, err := route.ParseRIB(syscall.NET_RT_IFMALIST, rib)
if err != nil {
- return nil, os.NewSyscallError("parseroutingmessage", err)
+ return nil, err
}
- var ifmat []Addr
+ ifmat := make([]Addr, 0, len(msgs))
for _, m := range msgs {
switch m := m.(type) {
- case *syscall.InterfaceMulticastAddrMessage:
- if ifi.Index == int(m.Header.Index) {
- ifma, err := newMulticastAddr(ifi, m)
- if err != nil {
- return nil, err
- }
- if ifma != nil {
- ifmat = append(ifmat, ifma)
- }
+ case *route.InterfaceMulticastAddrMessage:
+ if ifi.Index != m.Index {
+ continue
+ }
+ var ip IP
+ switch sa := m.Addrs[syscall.RTAX_IFA].(type) {
+ case *route.Inet4Addr:
+ ip = IPv4(sa.IP[0], sa.IP[1], sa.IP[2], sa.IP[3])
+ case *route.Inet6Addr:
+ ip = make(IP, IPv6len)
+ copy(ip, sa.IP[:])
+ }
+ if ip != nil {
+ ifmat = append(ifmat, &IPAddr{IP: ip})
}
}
}
return ifmat, nil
}
-
-func newMulticastAddr(ifi *Interface, m *syscall.InterfaceMulticastAddrMessage) (*IPAddr, error) {
- sas, err := syscall.ParseRoutingSockaddr(m)
- if err != nil {
- return nil, os.NewSyscallError("parseroutingsockaddr", err)
- }
- switch sa := sas[syscall.RTAX_IFA].(type) {
- case *syscall.SockaddrInet4:
- return &IPAddr{IP: IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])}, nil
- case *syscall.SockaddrInet6:
- ifma := IPAddr{IP: make(IP, IPv6len)}
- copy(ifma.IP, sa.Addr[:])
- // NOTE: KAME based IPv6 protocol stack usually embeds
- // the interface index in the interface-local or
- // link-local address as the kernel-internal form.
- if ifma.IP.IsInterfaceLocalMulticast() || ifma.IP.IsLinkLocalMulticast() {
- ifma.IP[2], ifma.IP[3] = 0, 0
- }
- return &ifma, nil
- default:
- return nil, nil
- }
-}
diff --git a/src/net/interface_netbsd.go b/src/net/interface_netbsd.go
deleted file mode 100644
index cb7a34ab166004..00000000000000
--- a/src/net/interface_netbsd.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// 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
-
-// interfaceMulticastAddrTable returns addresses for a specific
-// interface.
-func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
- // TODO(mikio): Implement this like other platforms.
- return nil, nil
-}
diff --git a/src/net/interface_openbsd.go b/src/net/interface_openbsd.go
deleted file mode 100644
index cb7a34ab166004..00000000000000
--- a/src/net/interface_openbsd.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// 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
-
-// interfaceMulticastAddrTable returns addresses for a specific
-// interface.
-func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
- // TODO(mikio): Implement this like other platforms.
- return nil, nil
-}
diff --git a/src/net/interface_test.go b/src/net/interface_test.go
index 2603311d24ba29..4c695b902a226c 100644
--- a/src/net/interface_test.go
+++ b/src/net/interface_test.go
@@ -6,7 +6,6 @@ package net
import (
"fmt"
- "internal/testenv"
"reflect"
"runtime"
"testing"
@@ -50,11 +49,6 @@ func ipv6LinkLocalUnicastAddr(ifi *Interface) string {
}
func TestInterfaces(t *testing.T) {
- if runtime.GOOS == "freebsd" && runtime.GOARCH == "arm" {
- // 100% flaky on FreeBSD 11-CURRENT and above.
- testenv.SkipFlaky(t, 7849)
- }
-
ift, err := Interfaces()
if err != nil {
t.Fatal(err)
@@ -79,11 +73,6 @@ func TestInterfaces(t *testing.T) {
}
func TestInterfaceAddrs(t *testing.T) {
- if runtime.GOOS == "freebsd" && runtime.GOARCH == "arm" {
- // 100% flaky on FreeBSD 11-CURRENT and above.
- testenv.SkipFlaky(t, 7849)
- }
-
ift, err := Interfaces()
if err != nil {
t.Fatal(err)
@@ -103,11 +92,6 @@ func TestInterfaceAddrs(t *testing.T) {
}
func TestInterfaceUnicastAddrs(t *testing.T) {
- if runtime.GOOS == "freebsd" && runtime.GOARCH == "arm" {
- // 100% flaky on FreeBSD 11-CURRENT and above.
- testenv.SkipFlaky(t, 7849)
- }
-
ift, err := Interfaces()
if err != nil {
t.Fatal(err)
@@ -135,11 +119,6 @@ func TestInterfaceUnicastAddrs(t *testing.T) {
}
func TestInterfaceMulticastAddrs(t *testing.T) {
- if runtime.GOOS == "freebsd" && runtime.GOARCH == "arm" {
- // 100% flaky on FreeBSD 11-CURRENT and above.
- testenv.SkipFlaky(t, 7849)
- }
-
ift, err := Interfaces()
if err != nil {
t.Fatal(err)
From 6cc6ef82ea1ea5c904bb44c14bb6f4eb33937bb1 Mon Sep 17 00:00:00 2001
From: David du Colombier <0intro@gmail.com>
Date: Sun, 15 May 2016 20:12:34 +0200
Subject: [PATCH 105/267] mime: fix mime type file name on Plan 9
There was a typo introduced in the initial
implementation of the Plan 9 support of
the mime package.
On Plan 9, the mime type file name should be
/sys/lib/mimetype instead of /sys/lib/mimetypes.
Change-Id: If0f0a9b6f3fbfa8dde551f790e83bdd05e8f0acb
Reviewed-on: https://go-review.googlesource.com/23087
Run-TryBot: Minux Ma
Reviewed-by: Minux Ma
TryBot-Result: Gobot Gobot
---
src/mime/type_plan9.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/mime/type_plan9.go b/src/mime/type_plan9.go
index c3ba186e7c6b48..14ff9734051863 100644
--- a/src/mime/type_plan9.go
+++ b/src/mime/type_plan9.go
@@ -21,7 +21,7 @@ func initMimePlan9() {
}
var typeFiles = []string{
- "/sys/lib/mimetypes",
+ "/sys/lib/mimetype",
}
func initMimeForTests() map[string]string {
From 6d66819587b9de3d7602721830884fd92a0f7090 Mon Sep 17 00:00:00 2001
From: Mikio Hara
Date: Sat, 23 Apr 2016 22:36:41 +0900
Subject: [PATCH 106/267] syscall: deprecate routing message APIs for BSD
variants
Also removes unnecessary test cases for avoiding unexpected failures on
newer operating systems.
Updates #14724.
Change-Id: I2291585d951fb70383da68293a6ac1ff3524c7f7
Reviewed-on: https://go-review.googlesource.com/22452
Run-TryBot: Mikio Hara
TryBot-Result: Gobot Gobot
Reviewed-by: Brad Fitzpatrick