doc/asm.html | 4 ++--
doc/contrib.html | 1 +
doc/devel/release.html | 7 +++++++
doc/go1.5.html | 54 +++++++++++++++++++++++------------------------------
doc/install.html | 16 ++++++++--------
src/cmd/compile/internal/amd64/ggen.go | 8 ++++----
src/cmd/compile/internal/amd64/reg.go | 2 --
src/cmd/compile/internal/arm64/ggen.go | 9 ++-------
src/cmd/compile/internal/arm64/reg.go | 2 --
src/cmd/compile/internal/gc/gsubr.go | 7 +++++++
src/cmd/compile/internal/gc/typecheck.go | 2 +-
src/cmd/compile/internal/gc/walk.go | 2 +-
src/cmd/compile/internal/ppc64/ggen.go | 10 ++++++++--
src/cmd/compile/internal/x86/ggen.go | 4 ++--
src/cmd/compile/internal/x86/reg.go | 2 --
src/cmd/go/alldocs.go | 9 +++++----
src/cmd/go/build.go | 2 +-
src/cmd/go/go_test.go | 35 +++++++++++++++++++++++++++++++++++
src/cmd/go/help.go | 2 +-
src/cmd/go/list.go | 7 ++++---
src/cmd/go/main.go | 5 ++---
src/cmd/go/note_test.go | 26 +++++++++++++++++++++++++-
src/cmd/go/pkg.go | 12 ++++++------
src/cmd/go/test.go | 2 +-
src/cmd/go/testdata/testvendor2/src/p/p.go | 3 +++
src/cmd/go/testdata/testvendor2/vendor/x/x.go | 1 +
src/cmd/go/testflag.go | 1 +
src/cmd/go/vcs.go | 2 +-
src/cmd/go/vendor_test.go | 12 ++++++++++++
src/cmd/link/internal/ld/data.go | 13 +++++--------
src/cmd/trace/trace.go | 4 ++--
src/cmd/vet/asmdecl.go | 24 ++++++++++++------------
src/cmd/yacc/yacc.go | 11 +++++++----
src/fmt/scan.go | 1 -
src/fmt/scan_test.go | 28 ++++++++++++++++++++++++++++
src/net/cgo_unix.go | 5 +++++
src/net/conf.go | 8 +++++++-
src/net/http/server.go | 7 ++-----
src/net/http/transport.go | 80 ++++++++++++++++++++++++++++++++++++++++++++++-------
src/net/lookup_test.go | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/net/lookup_unix.go | 27 +++++++++++++++------------
src/net/mail/message.go | 9 ++++++++-
src/net/mail/message_test.go | 8 ++++++++
src/net/net.go | 40 ++++++++++++++++++++++++++++++++++++++++
src/net/non_unix_test.go | 11 +++++++++++
src/net/unix_test.go | 25 +++++++++++++++++++++++++
src/runtime/asm_arm.s | 5 +++++
src/runtime/mbitmap.go | 9 +++++++++
src/runtime/os1_darwin.go | 9 +++++++--
src/runtime/os_darwin_arm.go | 9 ++++++++-
src/runtime/os_freebsd_arm.go | 9 ++++++++-
src/runtime/os_linux_arm.go | 1 -
src/runtime/os_nacl_arm.go | 8 +++++++-
src/runtime/os_netbsd_arm.go | 9 ++++++++-
src/runtime/os_openbsd_arm.go | 9 ++++++++-
src/runtime/panic.go | 2 +-
src/runtime/proc1.go | 18 +++++++++++++++++-
src/runtime/runtime2.go | 2 ++
src/runtime/stubs.go | 15 ++++++++++++++-
src/sort/sort.go | 2 +-
test/fixedbugs/issue12133.go | 26 ++++++++++++++++++++++++++
diff --git a/doc/asm.html b/doc/asm.html
index ba888118b9efa3324c28089e04f977af93c0ff7c..c992e14ade592275d5bb4c6c8e4fdc50e1cbd241 100644
--- a/doc/asm.html
+++ b/doc/asm.html
@@ -741,10 +741,10 @@
-
Power 64, a.k.a. ppc64
+64-bit PowerPC, a.k.a. ppc64
-The Power 64 port is in an experimental state.
+The 64-bit PowerPC port is in an experimental state.
diff --git a/doc/contrib.html b/doc/contrib.html
index c286abc9b8476651aaa7a7343860f3d33d9005b4..48390353d15b9e4356419199530132bb709b28a6 100644
--- a/doc/contrib.html
+++ b/doc/contrib.html
@@ -34,6 +34,7 @@
A summary of the changes between Go releases. Notes for the major releases:
+ - Go 1.5 (August 2015)
- Go 1.4 (December 2014)
- Go 1.3 (June 2014)
- Go 1.2 (December 2013)
diff --git a/doc/devel/release.html b/doc/devel/release.html
index ee6d3e0729c1f4a016a8bb2361efe962ff44f315..7d72c8d9336806bc9bc92e04c028a1dbaaed8454 100644
--- a/doc/devel/release.html
+++ b/doc/devel/release.html
@@ -12,6 +12,13 @@ git pull
git checkout release-branch
+go1.5 (released 2015/08/19)
+
+
+Go 1.5 is a major release of Go.
+Read the Go 1.5 Release Notes for more information.
+
+
go1.4 (released 2014/12/10)
diff --git a/doc/go1.5.html b/doc/go1.5.html
index 70ce94e9ad73cb30828922f979f70f39d3531e3d..4e5832db3ac855ead0d58b9aba5876384d7a81cc 100644
--- a/doc/go1.5.html
+++ b/doc/go1.5.html
@@ -83,7 +83,8 @@
Due to an oversight, the rule that allowed the element type to be elided from slice literals was not
applied to map keys.
This has been corrected in Go 1.5.
-An example will make this clear: as of Go 1.5, this map literal,
+An example will make this clear.
+As of Go 1.5, this map literal,
@@ -182,7 +183,7 @@
In Go 1.5, the order in which goroutines are scheduled has been changed.
The properties of the scheduler were never defined by the language,
-but programs that depended on the scheduling order may be broken
+but programs that depend on the scheduling order may be broken
by this change.
We have seen a few (erroneous) programs affected by this change.
If you have programs that implicitly depend on the scheduling
@@ -194,7 +195,7 @@ Another potentially breaking change is that the runtime now
sets the default number of threads to run simultaneously,
defined by GOMAXPROCS, to the number
of cores available on the CPU.
-In prior releases it defaulted to 1.
+In prior releases the default was 1.
Programs that do not expect to run with multiple cores may
break inadvertently.
They can be updated by removing the restriction or by setting
@@ -236,8 +237,8 @@ is only supported using external linking.
-Also available as experiments are ppc64 (IBM Power 64)
-and ppc64le (IBM Power 64, little-endian).
+Also available as experiments are ppc64
+and ppc64le (64-bit PowerPC, big- and little-endian).
Both these ports support cgo but
only with internal linking.
@@ -247,8 +248,8 @@ On FreeBSD, Go 1.5 requires FreeBSD 8-STABLE+ because of its new use of the SYSCALL instruction.
-On NaCl, Go 1.5 requires SDK version pepper-39 or above because it now uses the
-get_random_bytes system call.
+On NaCl, Go 1.5 requires SDK version pepper-41. Later pepper versions are not
+compatible due to the removal of the sRPC subsystem from the NaCl runtime.
@@ -292,7 +293,7 @@ The old names are gone; the new tools are available through the go tool
mechanism as go tool compile,
go tool asm,
and go tool link.
-Also, the file suffixes .6, .8 etc. for the
+Also, the file suffixes .6, .8, etc. for the
intermediate object files are also gone; now they are just plain .o files.
@@ -512,7 +513,7 @@
A new -asmflags build option
sets flags to pass to the assembler.
-However,
+However,
the -ccflags build option has been dropped;
it was specific to the old, now deleted C compiler .
@@ -520,14 +521,6 @@
A new -buildmode build option
sets the build mode, described above.
-
-
-
-An -asmflags build option has been added to provide
-flags to the assembler.
-However,
-the -ccflags build option has been dropped;
-it was specific to the old, now deleted C compiler .
@@ -546,7 +539,7 @@
The test subcommand now has a -count
flag to specify how many times to run each test and benchmark.
-testing package
+The testing package
does the work here, through by the -test.count flag.
@@ -823,7 +816,7 @@ method to discard data from the input.
-Also in the bytes package,
+In the bytes package,
the Buffer type
now has a Cap method
that reports the number of bytes allocated within the buffer.
@@ -960,7 +953,7 @@
The debug/elf
-package now has support for the 64-bit Power architecture.
+package now has support for the 64-bit PowerPC architecture.
@@ -1032,14 +1025,14 @@
In the image package,
the Rectangle type
now implements the Image interface,
-mask image when drawing.
+so a Rectangle can serve as a mask when drawing.
Also in the image package,
to assist in the handling of some JPEG images,
there is now support for 4:1:1 and 4:1:0 YCbCr subsampling and basic
-CMYK support, represented by the new image.CMYK struct.
+CMYK support, represented by the new image.CMYK struct.
@@ -1062,7 +1055,7 @@ uint8(r) to extract an 8-bit red value worked, but is incorrect.
In Go 1.5, that operation may yield a different value.
The correct code is, and always was, to select the high 8 bits:
uint8(r>>8).
-Incidentally, image/draw package
+Incidentally, the image/draw package
provides better support for such conversions; see
this blog post
for more information.
@@ -1095,9 +1088,8 @@
The log package
has a new LUTC flag
that causes time stamps to be printed in the UTC time zone.
-It also adds a SetOutput function
-to set the output destination for the standard logger
-and a corresponding method for user-created loggers.
+It also adds a SetOutput method
+for user-created loggers.
@@ -1109,7 +1101,7 @@
The math/big package
adds a new Jacobi
-function for integers and a new method
+function for integers and a new
ModSqrt
method for the Int type.
@@ -1201,7 +1193,7 @@
The net/mail package
-adds a AddressParser
+adds an AddressParser
type that can parse mail addresses.
@@ -1252,11 +1244,11 @@ but is otherwise unnecessary as strings support comparison natively.
-The WaitGroup function in
+The WaitGroup implementation in
package sync
now diagnoses code that races a call to Add
against a return from Wait.
-If it detects this condition, WaitGroup panics.
+If it detects this condition, the implementation panics.
@@ -1288,7 +1280,7 @@
Also in the text/template and
html/template packages,
-a new Option type
+a new Option method
allows customization of the behavior of the template during execution.
The sole implemented option allows control over how a missing key is
handled when indexing a map.
diff --git a/doc/install.html b/doc/install.html
index 9264f3a0d07a02e5a9c5abd500280b00d9d179af..e9f0f0dc095c5c920aab6d855196dbdda2c5d449 100644
--- a/doc/install.html
+++ b/doc/install.html
@@ -33,11 +33,11 @@
System requirements
-The gc compiler supports the following operating systems and
-architectures. Please ensure your system meets these requirements before
-proceeding. If your OS or architecture is not on the list, it's possible that
-gccgo might support your setup; see
-Setting up and using gccgo for details.
+Go binary distributions are available for these supported operating systems and architectures.
+Please ensure your system meets these requirements before proceeding.
+If your OS or architecture is not on the list, you may be able to
+install from source or
+use gccgo instead.
@@ -47,9 +47,9 @@ | Architectures |
Notes |
|
-| FreeBSD 8-STABLE or later | amd64, 386, arm | Debian GNU/kFreeBSD not supported; FreeBSD/ARM needs FreeBSD 10 or later |
-| Linux 2.6.23 or later with glibc | amd64, 386, arm | CentOS/RHEL 5.x not supported; no binary distribution for ARM yet |
-| Mac OS X 10.7 or later | amd64 | use the gcc† that comes with Xcode‡ |
+| FreeBSD 8-STABLE or later | amd64 | Debian GNU/kFreeBSD not supported |
+| Linux 2.6.23 or later with glibc | amd64, 386, arm | CentOS/RHEL 5.x not supported; install from source for ARM |
+| Mac OS X 10.7 or later | amd64 | use the clang or gcc† that comes with Xcode‡ |
| Windows XP or later | amd64, 386 | use MinGW gcc†. No need for cygwin or msys. |
diff --git a/src/cmd/compile/internal/amd64/ggen.go b/src/cmd/compile/internal/amd64/ggen.go
index 6425633818ce4552736444c374a6c6221fa4b492..65cf6947bed6db24ae4a934b1ddd40c4c07384aa 100644
--- a/src/cmd/compile/internal/amd64/ggen.go
+++ b/src/cmd/compile/internal/amd64/ggen.go
@@ -306,7 +306,7 @@ * the move is not necessary if dr == res, because res is
* known to be dead.
*/
func savex(dr int, x *gc.Node, oldx *gc.Node, res *gc.Node, t *gc.Type) {
- r := reg[dr]
+ r := uint8(gc.GetReg(dr))
// save current ax and dx if they are live
// and not the destination
@@ -319,14 +319,14 @@ x.Type = gc.Types[gc.TINT64]
gmove(x, oldx)
x.Type = t
oldx.Etype = r // squirrel away old r value
- reg[dr] = 1
+ gc.SetReg(dr, 1)
}
}
func restx(x *gc.Node, oldx *gc.Node) {
if oldx.Op != 0 {
x.Type = gc.Types[gc.TINT64]
- reg[x.Reg] = oldx.Etype
+ gc.SetReg(int(x.Reg), int(oldx.Etype))
gmove(oldx, x)
gc.Regfree(oldx)
}
@@ -411,7 +411,7 @@ gc.Cgen(nr, &n5)
nr = &n5
}
- rcx := int(reg[x86.REG_CX])
+ rcx := gc.GetReg(x86.REG_CX)
var n1 gc.Node
gc.Nodreg(&n1, gc.Types[gc.TUINT32], x86.REG_CX)
diff --git a/src/cmd/compile/internal/amd64/reg.go b/src/cmd/compile/internal/amd64/reg.go
index 7d4f40641de72f14b7f5d2c1013ad446516b52c3..8fab6399b1d88c86a08ca92b980eade55f7b0b95 100644
--- a/src/cmd/compile/internal/amd64/reg.go
+++ b/src/cmd/compile/internal/amd64/reg.go
@@ -40,8 +40,6 @@ const (
NREGVAR = 32
)
-var reg [x86.MAXREG]uint8
-
var regname = []string{
".AX",
".CX",
diff --git a/src/cmd/compile/internal/arm64/ggen.go b/src/cmd/compile/internal/arm64/ggen.go
index 6b0b40efbdb08b5b20f5df217cbafb73279dd6b3..cba4d991513216120dbeb13baa129daf0fd77fad 100644
--- a/src/cmd/compile/internal/arm64/ggen.go
+++ b/src/cmd/compile/internal/arm64/ggen.go
@@ -418,15 +418,12 @@
c := uint64(w % 8) // bytes
q := uint64(w / 8) // dwords
- if reg[arm64.REGRT1-arm64.REG_R0] > 0 {
- gc.Fatal("R%d in use during clearfat", arm64.REGRT1-arm64.REG_R0)
- }
-
var r0 gc.Node
gc.Nodreg(&r0, gc.Types[gc.TUINT64], arm64.REGZERO)
var dst gc.Node
+
+ // REGRT1 is reserved on arm64, see arm64/gsubr.go.
gc.Nodreg(&dst, gc.Types[gc.Tptr], arm64.REGRT1)
- reg[arm64.REGRT1-arm64.REG_R0]++
gc.Agen(nl, &dst)
var boff uint64
@@ -484,8 +481,6 @@ p = gins(arm64.AMOVB, &r0, &dst)
p.To.Type = obj.TYPE_MEM
p.To.Offset = int64(t + boff)
}
-
- reg[arm64.REGRT1-arm64.REG_R0]--
}
// Called after regopt and peep have run.
diff --git a/src/cmd/compile/internal/arm64/reg.go b/src/cmd/compile/internal/arm64/reg.go
index 7bc756b7bf0361112fc7bcf409fdd39422b1b750..b84359a63764297bab882636f1bb71798a2ef89f 100644
--- a/src/cmd/compile/internal/arm64/reg.go
+++ b/src/cmd/compile/internal/arm64/reg.go
@@ -39,8 +39,6 @@ const (
NREGVAR = 64 /* 32 general + 32 floating */
)
-var reg [arm64.NREG + arm64.NFREG]uint8
-
var regname = []string{
".R0",
".R1",
diff --git a/src/cmd/compile/internal/gc/gsubr.go b/src/cmd/compile/internal/gc/gsubr.go
index 14dc927442cce67d48321cc88dd78abb41978bfa..2c575f3d789a21b47379d15fb5fededde903f5fe 100644
--- a/src/cmd/compile/internal/gc/gsubr.go
+++ b/src/cmd/compile/internal/gc/gsubr.go
@@ -602,6 +602,13 @@
var reg [100]int // count of references to reg
var regstk [100][]byte // allocation sites, when -v is given
+func GetReg(r int) int {
+ return reg[r-Thearch.REGMIN]
+}
+func SetReg(r, v int) {
+ reg[r-Thearch.REGMIN] = v
+}
+
func ginit() {
for r := range reg {
reg[r] = 1
diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
index dc2ba75e69b1a29673d15659811d0980f7c7cbfb..befe3b26523251d0498bc4af4ef38710cc68d566 100644
--- a/src/cmd/compile/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -2532,7 +2532,7 @@ }
n.Xoffset = f1.Width
n.Type = f1.Type
if obj.Fieldtrack_enabled > 0 {
- dotField[typeSym{t, s}] = f1
+ dotField[typeSym{t.Orig, s}] = f1
}
if t.Etype == TINTER {
if Isptr[n.Left.Type.Etype] {
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index 91c0a47b2aef57fed22f436507e89f7375895753..ce73018b8b01a08d0eb075d78fbc11e4cd7846b1 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -3873,7 +3873,7 @@ t := n.Left.Type
if Isptr[t.Etype] {
t = t.Type
}
- field := dotField[typeSym{t, n.Right.Sym}]
+ field := dotField[typeSym{t.Orig, n.Right.Sym}]
if field == nil {
Fatal("usefield %v %v without paramfld", n.Left.Type, n.Right.Sym)
}
diff --git a/src/cmd/compile/internal/ppc64/ggen.go b/src/cmd/compile/internal/ppc64/ggen.go
index 1b936b8a5f60002f84f271bc217070d3655cd09a..5b282eb2f250423f14a84dda7e3801968ad533db 100644
--- a/src/cmd/compile/internal/ppc64/ggen.go
+++ b/src/cmd/compile/internal/ppc64/ggen.go
@@ -71,7 +71,10 @@ if cnt < int64(4*gc.Widthptr) {
for i := int64(0); i < cnt; i += int64(gc.Widthptr) {
p = appendpp(p, ppc64.AMOVD, obj.TYPE_REG, ppc64.REGZERO, 0, obj.TYPE_MEM, ppc64.REGSP, 8+frame+lo+i)
}
- } else if cnt <= int64(128*gc.Widthptr) {
+ // TODO(dfc): https://golang.org/issue/12108
+ // If DUFFZERO is used inside a tail call (see genwrapper) it will
+ // overwrite the link register.
+ } else if false && cnt <= int64(128*gc.Widthptr) {
p = appendpp(p, ppc64.AADD, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, ppc64.REGRT1, 0)
p.Reg = ppc64.REGSP
p = appendpp(p, obj.ADUFFZERO, obj.TYPE_NONE, 0, 0, obj.TYPE_MEM, 0, 0)
@@ -442,7 +445,10 @@ gc.Regfree(&end)
// The loop leaves R3 on the last zeroed dword
boff = 8
- } else if q >= 4 {
+ // TODO(dfc): https://golang.org/issue/12108
+ // If DUFFZERO is used inside a tail call (see genwrapper) it will
+ // overwrite the link register.
+ } else if false && q >= 4 {
p := gins(ppc64.ASUB, nil, &dst)
p.From.Type = obj.TYPE_CONST
p.From.Offset = 8
diff --git a/src/cmd/compile/internal/x86/ggen.go b/src/cmd/compile/internal/x86/ggen.go
index dabc139f302030e755c0775d39e58ab567534db0..ae9881d2739f7d476f9e1ba3b47921ad398a48ae 100644
--- a/src/cmd/compile/internal/x86/ggen.go
+++ b/src/cmd/compile/internal/x86/ggen.go
@@ -319,7 +319,7 @@ }
}
func savex(dr int, x *gc.Node, oldx *gc.Node, res *gc.Node, t *gc.Type) {
- r := int(reg[dr])
+ r := gc.GetReg(dr)
gc.Nodreg(x, gc.Types[gc.TINT32], dr)
// save current ax and dx if they are live
@@ -408,7 +408,7 @@
var oldcx gc.Node
var cx gc.Node
gc.Nodreg(&cx, gc.Types[gc.TUINT32], x86.REG_CX)
- if reg[x86.REG_CX] > 1 && !gc.Samereg(&cx, res) {
+ if gc.GetReg(x86.REG_CX) > 1 && !gc.Samereg(&cx, res) {
gc.Tempname(&oldcx, gc.Types[gc.TUINT32])
gmove(&cx, &oldcx)
}
diff --git a/src/cmd/compile/internal/x86/reg.go b/src/cmd/compile/internal/x86/reg.go
index 8c97171e47dfe8e374360afd9d5c5c2a0077f77f..b3a5fdf4e054385ba21412b74efdd7265ae42d93 100644
--- a/src/cmd/compile/internal/x86/reg.go
+++ b/src/cmd/compile/internal/x86/reg.go
@@ -37,8 +37,6 @@ const (
NREGVAR = 16 /* 8 integer + 8 floating */
)
-var reg [x86.MAXREG]uint8
-
var regname = []string{
".ax",
".cx",
diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go
index 512ed61cd3d28abc9e877977230c3b28831fa855..6077d93a436f4a440bdb9b955095625900ef90b9 100644
--- a/src/cmd/go/alldocs.go
+++ b/src/cmd/go/alldocs.go
@@ -521,9 +521,10 @@ List lists the packages named by the import paths, one per line.
The default output shows the package import path:
- code.google.com/p/google-api-go-client/books/v1
- code.google.com/p/goauth2/oauth
- code.google.com/p/sqlite
+ bytes
+ encoding/json
+ github.com/gorilla/mux
+ golang.org/x/net/html
The -f flag specifies an alternate format for the list, using the
syntax of package template. The default output is equivalent to -f
@@ -1284,7 +1285,7 @@ By convention, this is arranged by starting each path with a
unique prefix that belongs to you. For example, paths used
internally at Google all begin with 'google', and paths
denoting remote repositories begin with the path to the code,
-such as 'code.google.com/p/project'.
+such as 'github.com/user/repo'.
As a special case, if the package list is a list of .go files from a
single directory, the command is applied to a single synthesized
diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go
index 718edd2f77fdb1163c0d2785b5a0bee9299d53f6..b7c7e0584fc84c66a9ccc59026b4364d28779644 100644
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -1880,7 +1880,7 @@ cmd := exec.Command(cmdline[0], cmdline[1:]...)
cmd.Stdout = &buf
cmd.Stderr = &buf
cmd.Dir = dir
- cmd.Env = mergeEnvLists(env, envForDir(cmd.Dir))
+ cmd.Env = mergeEnvLists(env, envForDir(cmd.Dir, os.Environ()))
err := cmd.Run()
// cmd.Run will fail on Unix if some other process has the binary
diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go
index 5b0f2783f358a5b45d9a6f88e5e3d5da79805011..77b2628982bb81675d07d2705017aa1dd7c1efe4 100644
--- a/src/cmd/go/go_test.go
+++ b/src/cmd/go/go_test.go
@@ -2294,6 +2294,21 @@ tg.unsetenv("TERM")
tg.run("run", tg.path("run.go"))
}
+func TestIssue12096(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.tempFile("test_test.go", `
+ package main
+ import ("os"; "testing")
+ func TestEnv(t *testing.T) {
+ if os.Getenv("TERM") != "" {
+ t.Fatal("TERM is set")
+ }
+ }`)
+ tg.unsetenv("TERM")
+ tg.run("test", tg.path("test_test.go"))
+}
+
func TestGoBuildOutput(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
@@ -2352,3 +2367,23 @@
tg.runFail("build", "-o", "whatever", "cmd/gofmt", "sync/atomic")
tg.grepStderr("multiple packages", "did not reject -o with multiple packages")
}
+
+func TestGoBuildARM(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping cross-compile in short mode")
+ }
+
+ tg := testgo(t)
+ defer tg.cleanup()
+
+ tg.makeTempdir()
+ tg.cd(tg.path("."))
+
+ tg.setenv("GOARCH", "arm")
+ tg.setenv("GOOS", "linux")
+ tg.setenv("GOARM", "5")
+ tg.tempFile("hello.go", `package main
+ func main() {}`)
+ tg.run("build", "hello.go")
+ tg.grepStderrNot("unable to find math.a", "did not build math.a correctly")
+}
diff --git a/src/cmd/go/help.go b/src/cmd/go/help.go
index 0bc5ef95fbd8b5f9a56fd8aa5eef739d8e27f8cc..5dff2670f1b990471dee5a4338fee5e3ee9ab6a8 100644
--- a/src/cmd/go/help.go
+++ b/src/cmd/go/help.go
@@ -77,7 +77,7 @@ By convention, this is arranged by starting each path with a
unique prefix that belongs to you. For example, paths used
internally at Google all begin with 'google', and paths
denoting remote repositories begin with the path to the code,
-such as 'code.google.com/p/project'.
+such as 'github.com/user/repo'.
As a special case, if the package list is a list of .go files from a
single directory, the command is applied to a single synthesized
diff --git a/src/cmd/go/list.go b/src/cmd/go/list.go
index f59c82eadfd9c2126a2c26aa9a835be52e1d3d41..35c7cc4f2a73a8168570695625c88f6a2b56700e 100644
--- a/src/cmd/go/list.go
+++ b/src/cmd/go/list.go
@@ -21,9 +21,10 @@ List lists the packages named by the import paths, one per line.
The default output shows the package import path:
- code.google.com/p/google-api-go-client/books/v1
- code.google.com/p/goauth2/oauth
- code.google.com/p/sqlite
+ bytes
+ encoding/json
+ github.com/gorilla/mux
+ golang.org/x/net/html
The -f flag specifies an alternate format for the list, using the
syntax of package template. The default output is equivalent to -f
diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go
index 88a94417d74a85eabe4abb6889ed814421351e2b..8ebde8925990dc5a4ad1f19a7da298d20302fd8b 100644
--- a/src/cmd/go/main.go
+++ b/src/cmd/go/main.go
@@ -446,11 +446,10 @@ // suitable for running in the given directory.
// The environment is the current process's environment
// but with an updated $PWD, so that an os.Getwd in the
// child will be faster.
-func envForDir(dir string) []string {
- env := os.Environ()
+func envForDir(dir string, base []string) []string {
// Internally we only use rooted paths, so dir is rooted.
// Even if dir is not rooted, no harm done.
- return mergeEnvLists([]string{"PWD=" + dir}, env)
+ return mergeEnvLists([]string{"PWD=" + dir}, base)
}
// mergeEnvLists merges the two environment lists such that
diff --git a/src/cmd/go/note_test.go b/src/cmd/go/note_test.go
index fb25f94ec31c91ce73c98b0d15884ea634baff62..3d644518c6897de348b57f8928f1b2e06b139769 100644
--- a/src/cmd/go/note_test.go
+++ b/src/cmd/go/note_test.go
@@ -5,7 +5,8 @@
package main_test
import (
- "cmd/go"
+ main "cmd/go"
+ "runtime"
"testing"
)
@@ -21,5 +22,28 @@ t.Fatalf("reading build ID from hello binary: %v", err)
}
if id != buildID {
t.Fatalf("buildID in hello binary = %q, want %q", id, buildID)
+ }
+
+ if runtime.GOOS == "linux" && runtime.GOARCH == "ppc64le" {
+ t.Skipf("skipping - golang.org/issue/11184")
+ }
+
+ switch runtime.GOOS {
+ case "plan9":
+ // no external linking
+ t.Logf("no external linking - skipping linkmode=external test")
+
+ case "solaris":
+ t.Logf("skipping - golang.org/issue/12178")
+
+ default:
+ tg.run("build", "-ldflags", "-buildid="+buildID+" -linkmode=external", "-o", tg.path("hello.exe"), tg.path("hello.go"))
+ id, err := main.ReadBuildIDFromBinary(tg.path("hello.exe"))
+ if err != nil {
+ t.Fatalf("reading build ID from hello binary (linkmode=external): %v", err)
+ }
+ if id != buildID {
+ t.Fatalf("buildID in hello binary = %q, want %q (linkmode=external)", id, buildID)
+ }
}
}
diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go
index 6b78a479394cd5f0715bb21facfb6108fb963632..61e3d8dc702ca06f31e778b900c344fb7f18fa7f 100644
--- a/src/cmd/go/pkg.go
+++ b/src/cmd/go/pkg.go
@@ -416,7 +416,7 @@ if parent == nil || parent.Root == "" || !go15VendorExperiment {
return path, nil
}
dir := filepath.Clean(parent.Dir)
- root := filepath.Clean(parent.Root)
+ root := filepath.Join(parent.Root, "src")
if !hasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator {
fatalf("invalid vendoredImportPath: dir=%q root=%q separator=%q", dir, root, string(filepath.Separator))
}
@@ -836,7 +836,7 @@ if buildRace && (!p.Standard || !raceExclude[p.ImportPath]) {
importPaths = append(importPaths, "runtime/race")
}
// On ARM with GOARM=5, everything depends on math for the link.
- if p.ImportPath == "main" && goarch == "arm" {
+ if p.Name == "main" && goarch == "arm" {
importPaths = append(importPaths, "math")
}
}
@@ -1796,10 +1796,10 @@ if filename == "" {
return "", &os.PathError{Op: "parse", Path: filename, Err: errBuildIDUnknown}
}
- // Read the first 8 kB of the binary file.
+ // Read the first 16 kB of the binary file.
// That should be enough to find the build ID.
// In ELF files, the build ID is in the leading headers,
- // which are typically less than 4 kB, not to mention 8 kB.
+ // which are typically less than 4 kB, not to mention 16 kB.
// On other systems, we're trying to read enough that
// we get the beginning of the text segment in the read.
// The offset where the text segment begins in a hello
@@ -1807,7 +1807,7 @@ // world compiled for each different object format today:
//
// Plan 9: 0x20
// Windows: 0x600
- // Mach-O: 0x1000
+ // Mach-O: 0x2000
//
f, err := os.Open(filename)
if err != nil {
@@ -1815,7 +1815,7 @@ return "", err
}
defer f.Close()
- data := make([]byte, 8192)
+ data := make([]byte, 16*1024)
_, err = io.ReadFull(f, data)
if err == io.ErrUnexpectedEOF {
err = nil
diff --git a/src/cmd/go/test.go b/src/cmd/go/test.go
index 0ba18837143a2c24d96a0c927a2440c2ead7488e..ba1ab82680d9c06112d18c7b79f1d9ea9200298e 100644
--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -1027,7 +1027,7 @@ }
cmd := exec.Command(args[0], args[1:]...)
cmd.Dir = a.p.Dir
- cmd.Env = envForDir(cmd.Dir)
+ cmd.Env = envForDir(cmd.Dir, origEnv)
var buf bytes.Buffer
if testStreamOutput {
cmd.Stdout = os.Stdout
diff --git a/src/cmd/go/testdata/testvendor2/src/p/p.go b/src/cmd/go/testdata/testvendor2/src/p/p.go
new file mode 100644
index 0000000000000000000000000000000000000000..220b2b2a0712eabd10461cb354842501785282d6
--- /dev/null
+++ b/src/cmd/go/testdata/testvendor2/src/p/p.go
@@ -0,0 +1,3 @@
+package p
+
+import "x"
diff --git a/src/cmd/go/testdata/testvendor2/vendor/x/x.go b/src/cmd/go/testdata/testvendor2/vendor/x/x.go
new file mode 100644
index 0000000000000000000000000000000000000000..823aafd0712b6c533df84b17d9b7ac6ae43e66fa
--- /dev/null
+++ b/src/cmd/go/testdata/testvendor2/vendor/x/x.go
@@ -0,0 +1 @@
+package x
diff --git a/src/cmd/go/testflag.go b/src/cmd/go/testflag.go
index ee4ab187e0bef76aacb00a15df5b5581a9835709..1f3e3d316af5a8794e8746e6617d9a943a5fc3a3 100644
--- a/src/cmd/go/testflag.go
+++ b/src/cmd/go/testflag.go
@@ -36,6 +36,7 @@ {name: "o"},
{name: "cover", boolVar: &testCover},
{name: "covermode"},
{name: "coverpkg"},
+ {name: "exec"},
// passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v.
{name: "bench", passToTest: true},
diff --git a/src/cmd/go/vcs.go b/src/cmd/go/vcs.go
index 2ee1057a5839cf192571532291c47b1ee54f4296..28a7540dfe43c0b14f929e94051a74eb6b1ae399 100644
--- a/src/cmd/go/vcs.go
+++ b/src/cmd/go/vcs.go
@@ -344,7 +344,7 @@ }
cmd := exec.Command(v.cmd, args...)
cmd.Dir = dir
- cmd.Env = envForDir(cmd.Dir)
+ cmd.Env = envForDir(cmd.Dir, os.Environ())
if buildX {
fmt.Printf("cd %s\n", dir)
fmt.Printf("%s %s\n", v.cmd, strings.Join(args, " "))
diff --git a/src/cmd/go/vendor_test.go b/src/cmd/go/vendor_test.go
index 611aceb999db811b4d97e326784c8f88a12b1c93..1e8cf9c8d26d7531fbc5520f5819362c5b21e2a3 100644
--- a/src/cmd/go/vendor_test.go
+++ b/src/cmd/go/vendor_test.go
@@ -244,3 +244,15 @@
tg.run("list", "-f", `{{join .XTestImports "\n"}}`, "github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3")
tg.grepStdout("go-get-issue-11864/vendor/vendor.org/tx3", "did not find vendor-expanded tx3")
}
+
+func TestVendor12156(t *testing.T) {
+ // Former index out of range panic.
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/testvendor2"))
+ tg.setenv("GO15VENDOREXPERIMENT", "1")
+ tg.cd(filepath.Join(tg.pwd(), "testdata/testvendor2/src/p"))
+ tg.runFail("build", "p.go")
+ tg.grepStderrNot("panic", "panicked")
+ tg.grepStderr(`cannot find package "x"`, "wrong error")
+}
diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go
index 33f250da48c761ac847b3d01c0f7c47117aac986..55b12e5ececa36f511943f182b170f485235caa7 100644
--- a/src/cmd/link/internal/ld/data.go
+++ b/src/cmd/link/internal/ld/data.go
@@ -778,7 +778,6 @@ }
}
eaddr := addr + size
- var n int64
var q []byte
for ; sym != nil; sym = sym.Next {
if !sym.Reachable {
@@ -797,20 +796,18 @@ fmt.Fprintf(&Bso, "\n")
}
fmt.Fprintf(&Bso, "%.6x\t%-20s\n", uint64(int64(addr)), sym.Name)
- n = sym.Size
q = sym.P
- for n >= 16 {
- fmt.Fprintf(&Bso, "%.6x\t%-20.16I\n", uint64(addr), q)
+ for len(q) >= 16 {
+ fmt.Fprintf(&Bso, "%.6x\t% x\n", uint64(addr), q[:16])
addr += 16
q = q[16:]
- n -= 16
}
- if n > 0 {
- fmt.Fprintf(&Bso, "%.6x\t%-20.*I\n", uint64(addr), int(n), q)
+ if len(q) > 0 {
+ fmt.Fprintf(&Bso, "%.6x\t% x\n", uint64(addr), q)
+ addr += int64(len(q))
}
- addr += n
}
if addr < eaddr {
diff --git a/src/cmd/trace/trace.go b/src/cmd/trace/trace.go
index 0d2451b4ecec40b9b7d8a73c3601ffdf5c1ffede..e6eb320aa23b83ef78a741460d9582b4823d4cce 100644
--- a/src/cmd/trace/trace.go
+++ b/src/cmd/trace/trace.go
@@ -10,8 +10,8 @@ "fmt"
"internal/trace"
"log"
"net/http"
- "os"
"path/filepath"
+ "runtime"
"strconv"
"strings"
)
@@ -63,7 +63,7 @@
// httpTraceViewerHTML serves static part of trace-viewer.
// This URL is queried from templTrace HTML.
func httpTraceViewerHTML(w http.ResponseWriter, r *http.Request) {
- http.ServeFile(w, r, filepath.Join(os.Getenv("GOROOT"), "misc", "trace", "trace_viewer_lean.html"))
+ http.ServeFile(w, r, filepath.Join(runtime.GOROOT(), "misc", "trace", "trace_viewer_lean.html"))
}
// httpJsonTrace serves json trace, requested from within templTrace HTML.
diff --git a/src/cmd/vet/asmdecl.go b/src/cmd/vet/asmdecl.go
index 6bdfdbf3be1b2cdf3de37b9873a3f7d6a0a672ca..e4a9871a2146ddfd17f5318ec5bd5e46ae334a6e 100644
--- a/src/cmd/vet/asmdecl.go
+++ b/src/cmd/vet/asmdecl.go
@@ -58,13 +58,13 @@ inner []*asmVar
}
var (
- asmArch386 = asmArch{"386", 4, 4, 4, false, "SP", false}
- asmArchArm = asmArch{"arm", 4, 4, 4, false, "R13", true}
- asmArchArm64 = asmArch{"arm64", 8, 8, 8, false, "RSP", true}
- asmArchAmd64 = asmArch{"amd64", 8, 8, 8, false, "SP", false}
- asmArchAmd64p32 = asmArch{"amd64p32", 4, 4, 8, false, "SP", false}
- asmArchPower64 = asmArch{"power64", 8, 8, 8, true, "R1", true}
- asmArchPower64LE = asmArch{"power64le", 8, 8, 8, false, "R1", true}
+ asmArch386 = asmArch{"386", 4, 4, 4, false, "SP", false}
+ asmArchArm = asmArch{"arm", 4, 4, 4, false, "R13", true}
+ asmArchArm64 = asmArch{"arm64", 8, 8, 8, false, "RSP", true}
+ asmArchAmd64 = asmArch{"amd64", 8, 8, 8, false, "SP", false}
+ asmArchAmd64p32 = asmArch{"amd64p32", 4, 4, 8, false, "SP", false}
+ asmArchPpc64 = asmArch{"ppc64", 8, 8, 8, true, "R1", true}
+ asmArchPpc64LE = asmArch{"ppc64le", 8, 8, 8, false, "R1", true}
arches = []*asmArch{
&asmArch386,
@@ -72,8 +72,8 @@ &asmArchArm,
&asmArchArm64,
&asmArchAmd64,
&asmArchAmd64p32,
- &asmArchPower64,
- &asmArchPower64LE,
+ &asmArchPpc64,
+ &asmArchPpc64LE,
}
)
@@ -86,7 +86,7 @@ asmNamedFP = re(`([a-zA-Z0-9_\xFF-\x{10FFFF}]+)(?:\+([0-9]+))\(FP\)`)
asmUnnamedFP = re(`[^+\-0-9](([0-9]+)\(FP\))`)
asmSP = re(`[^+\-0-9](([0-9]+)\(([A-Z0-9]+)\))`)
asmOpcode = re(`^\s*(?:[A-Z0-9a-z_]+:)?\s*([A-Z]+)\s*([^,]*)(?:,\s*(.*))?`)
- power64Suff = re(`([BHWD])(ZU|Z|U|BR)?$`)
+ ppc64Suff = re(`([BHWD])(ZU|Z|U|BR)?$`)
)
func asmCheck(pkg *Package) {
@@ -589,9 +589,9 @@ src = 4
case 'D', 'Q':
src = 8
}
- case "power64", "power64le":
+ case "ppc64", "ppc64le":
// Strip standard suffixes to reveal size letter.
- m := power64Suff.FindStringSubmatch(op)
+ m := ppc64Suff.FindStringSubmatch(op)
if m != nil {
switch m[1][0] {
case 'B':
diff --git a/src/cmd/yacc/yacc.go b/src/cmd/yacc/yacc.go
index 53c0fab17451556cea79caf3100ade24c65d2bb1..4f83f50e4606aafe939c5cec3aa8186236b2b7bd 100644
--- a/src/cmd/yacc/yacc.go
+++ b/src/cmd/yacc/yacc.go
@@ -699,18 +699,20 @@ fmt.Fprintf(ftable, "const %v = %v\n", tokset[i].name, tokset[i].value)
}
}
- // put out names of token names
+ // put out names of tokens
ftable.WriteRune('\n')
fmt.Fprintf(ftable, "var %sToknames = [...]string{\n", prefix)
for i := 1; i <= ntokens; i++ {
- fmt.Fprintf(ftable, "\t\"%v\",\n", tokset[i].name)
+ fmt.Fprintf(ftable, "\t%q,\n", tokset[i].name)
}
fmt.Fprintf(ftable, "}\n")
- // put out names of state names
+ // put out names of states.
+ // commented out to avoid a huge table just for debugging.
+ // re-enable to have the names in the binary.
fmt.Fprintf(ftable, "var %sStatenames = [...]string{", prefix)
// for i:=TOKSTART; i<=ntokens; i++ {
- // fmt.Fprintf(ftable, "\t\"%v\",\n", tokset[i].name);
+ // fmt.Fprintf(ftable, "\t%q,\n", tokset[i].name);
// }
fmt.Fprintf(ftable, "}\n")
@@ -3471,6 +3473,7 @@ var $$n int
var $$lval $$SymType
var $$VAL $$SymType
var $$Dollar []$$SymType
+ _ = $$Dollar // silence set and not used
$$S := make([]$$SymType, $$MaxDepth)
Nerrs := 0 /* number of errors */
diff --git a/src/fmt/scan.go b/src/fmt/scan.go
index 21ed091d80f6068b0d5df93f8d815e27574eddf8..5b9b516353b94c18ff3bf7538f61aac7b7acf897 100644
--- a/src/fmt/scan.go
+++ b/src/fmt/scan.go
@@ -888,7 +888,6 @@ // If the first byte is hex and the second is not, processing stops.
func (s *ss) hexByte() (b byte, ok bool) {
rune1 := s.getRune()
if rune1 == eof {
- s.UnreadRune()
return
}
value1, ok := hexDigit(rune1)
diff --git a/src/fmt/scan_test.go b/src/fmt/scan_test.go
index 694f93e1aeb0a544a7f8fbc3351ce1b6eb36cb53..a3784364e630329d9b9214dd8af80dd426e92321 100644
--- a/src/fmt/scan_test.go
+++ b/src/fmt/scan_test.go
@@ -1128,3 +1128,31 @@ t.Errorf("%s: expected error; got none", test.name)
}
}
}
+
+// Test for issue 12090: Was unreading at EOF, double-scanning a byte.
+
+type hexBytes [2]byte
+
+func (h *hexBytes) Scan(ss ScanState, verb rune) error {
+ var b []byte
+ _, err := Fscanf(ss, "%4x", &b)
+ if err != nil {
+ panic(err) // Really shouldn't happen.
+ }
+ copy((*h)[:], b)
+ return err
+}
+
+func TestHexByte(t *testing.T) {
+ var h hexBytes
+ n, err := Sscanln("0123\n", &h)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if n != 1 {
+ t.Fatalf("expected 1 item; scanned %d", n)
+ }
+ if h[0] != 0x01 || h[1] != 0x23 {
+ t.Fatalf("expected 0123 got %x", h)
+ }
+}
diff --git a/src/net/cgo_unix.go b/src/net/cgo_unix.go
index d9d5f0377cd82a709d9a694af870da8e8b296ca4..cb89d65457918ad1d05a605d635bdf5913ba75d4 100644
--- a/src/net/cgo_unix.go
+++ b/src/net/cgo_unix.go
@@ -222,6 +222,11 @@ b = b[:i]
break
}
}
+ // Add trailing dot to match pure Go reverse resolver
+ // and all other lookup routines. See golang.org/issue/12189.
+ if len(b) > 0 && b[len(b)-1] != '.' {
+ b = append(b, '.')
+ }
return []string{string(b)}, nil, true
}
diff --git a/src/net/conf.go b/src/net/conf.go
index 01bb585ce673b5c02527e67f080f41b5236ec82d..c92e579d7e6852e4e929a2c1dc8a1e7dfe69789d 100644
--- a/src/net/conf.go
+++ b/src/net/conf.go
@@ -19,7 +19,7 @@ type conf struct {
// forceCgoLookupHost forces CGO to always be used, if available.
forceCgoLookupHost bool
- netGo bool // "netgo" build tag in use (or no cgo)
+ netGo bool // go DNS resolution forced
netCgo bool // cgo DNS resolution forced
// machine has an /etc/mdns.allow file
@@ -110,6 +110,12 @@
if _, err := os.Stat("/etc/mdns.allow"); err == nil {
confVal.hasMDNSAllow = true
}
+}
+
+// canUseCgo reports whether calling cgo functions is allowed
+// for non-hostname lookups.
+func (c *conf) canUseCgo() bool {
+ return c.hostLookupOrder("") == hostLookupCgo
}
// hostLookupOrder determines which strategy to use to resolve hostname.
diff --git a/src/net/http/server.go b/src/net/http/server.go
index 1b292ea2de39e248becfafa8cf0c41d4aa3c6985..a3e43555bb37b4f120deeec2e5bd16277976b29d 100644
--- a/src/net/http/server.go
+++ b/src/net/http/server.go
@@ -473,7 +473,7 @@ c.w = rwc
if debugServerConnections {
c.rwc = newLoggingConn("server", c.rwc)
}
- c.sr = liveSwitchReader{r: c.rwc}
+ c.sr.r = c.rwc
c.lr = io.LimitReader(&c.sr, noLimit).(*io.LimitedReader)
br := newBufioReader(c.lr)
bw := newBufioWriterSize(checkConnErrorWriter{c}, 4<<10)
@@ -2015,10 +2015,7 @@ addr := srv.Addr
if addr == "" {
addr = ":https"
}
- config := &tls.Config{}
- if srv.TLSConfig != nil {
- *config = *srv.TLSConfig
- }
+ config := cloneTLSConfig(srv.TLSConfig)
if config.NextProtos == nil {
config.NextProtos = []string{"http/1.1"}
}
diff --git a/src/net/http/transport.go b/src/net/http/transport.go
index 09434f1234406ecd519f14a74ae09258bf7b8c1b..70d1864605993f5a46ab908251da112581d070ed 100644
--- a/src/net/http/transport.go
+++ b/src/net/http/transport.go
@@ -645,16 +645,9 @@ }
if cm.targetScheme == "https" && !tlsDial {
// Initiate TLS and check remote host name against certificate.
- cfg := t.TLSClientConfig
- if cfg == nil || cfg.ServerName == "" {
- host := cm.tlsHost()
- if cfg == nil {
- cfg = &tls.Config{ServerName: host}
- } else {
- clone := *cfg // shallow clone
- clone.ServerName = host
- cfg = &clone
- }
+ cfg := cloneTLSClientConfig(t.TLSClientConfig)
+ if cfg.ServerName == "" {
+ cfg.ServerName = cm.tlsHost()
}
plainConn := pconn.conn
tlsConn := tls.Client(plainConn, cfg)
@@ -1399,3 +1392,70 @@ default:
return false
}
}
+
+// cloneTLSConfig returns a shallow clone of the exported
+// fields of cfg, ignoring the unexported sync.Once, which
+// contains a mutex and must not be copied.
+//
+// The cfg must not be in active use by tls.Server, or else
+// there can still be a race with tls.Server updating SessionTicketKey
+// and our copying it, and also a race with the server setting
+// SessionTicketsDisabled=false on failure to set the random
+// ticket key.
+//
+// If cfg is nil, a new zero tls.Config is returned.
+func cloneTLSConfig(cfg *tls.Config) *tls.Config {
+ if cfg == nil {
+ return &tls.Config{}
+ }
+ return &tls.Config{
+ Rand: cfg.Rand,
+ Time: cfg.Time,
+ Certificates: cfg.Certificates,
+ NameToCertificate: cfg.NameToCertificate,
+ GetCertificate: cfg.GetCertificate,
+ RootCAs: cfg.RootCAs,
+ NextProtos: cfg.NextProtos,
+ ServerName: cfg.ServerName,
+ ClientAuth: cfg.ClientAuth,
+ ClientCAs: cfg.ClientCAs,
+ InsecureSkipVerify: cfg.InsecureSkipVerify,
+ CipherSuites: cfg.CipherSuites,
+ PreferServerCipherSuites: cfg.PreferServerCipherSuites,
+ SessionTicketsDisabled: cfg.SessionTicketsDisabled,
+ SessionTicketKey: cfg.SessionTicketKey,
+ ClientSessionCache: cfg.ClientSessionCache,
+ MinVersion: cfg.MinVersion,
+ MaxVersion: cfg.MaxVersion,
+ CurvePreferences: cfg.CurvePreferences,
+ }
+}
+
+// cloneTLSClientConfig is like cloneTLSConfig but omits
+// the fields SessionTicketsDisabled and SessionTicketKey.
+// This makes it safe to call cloneTLSClientConfig on a config
+// in active use by a server.
+func cloneTLSClientConfig(cfg *tls.Config) *tls.Config {
+ if cfg == nil {
+ return &tls.Config{}
+ }
+ return &tls.Config{
+ Rand: cfg.Rand,
+ Time: cfg.Time,
+ Certificates: cfg.Certificates,
+ NameToCertificate: cfg.NameToCertificate,
+ GetCertificate: cfg.GetCertificate,
+ RootCAs: cfg.RootCAs,
+ NextProtos: cfg.NextProtos,
+ ServerName: cfg.ServerName,
+ ClientAuth: cfg.ClientAuth,
+ ClientCAs: cfg.ClientCAs,
+ InsecureSkipVerify: cfg.InsecureSkipVerify,
+ CipherSuites: cfg.CipherSuites,
+ PreferServerCipherSuites: cfg.PreferServerCipherSuites,
+ ClientSessionCache: cfg.ClientSessionCache,
+ MinVersion: cfg.MinVersion,
+ MaxVersion: cfg.MaxVersion,
+ CurvePreferences: cfg.CurvePreferences,
+ }
+}
diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go
index a42ae298ef13103e4a1c9480bad8a1b8acf5f7b9..86957b557566e64c42d604da6d4242149baa3975 100644
--- a/src/net/lookup_test.go
+++ b/src/net/lookup_test.go
@@ -5,6 +5,7 @@
package net
import (
+ "bytes"
"fmt"
"strings"
"testing"
@@ -392,3 +393,111 @@ // As a rule, unknown must not be shown but it might possibly
// happen due to issue 4856 for now.
t.Logf("%v succeeded, %v failed (%v timeout, %v temporary, %v other, %v unknown)", qstats.succeeded, qstats.failed, qstats.timeout, qstats.temporary, qstats.other, qstats.unknown)
}
+
+func TestLookupDots(t *testing.T) {
+ if testing.Short() || !*testExternal {
+ t.Skipf("skipping external network test")
+ }
+
+ fixup := forceGoDNS()
+ defer fixup()
+ testDots(t, "go")
+
+ if forceCgoDNS() {
+ testDots(t, "cgo")
+ }
+}
+
+func testDots(t *testing.T, mode string) {
+ names, err := LookupAddr("8.8.8.8") // Google dns server
+ if err != nil {
+ t.Errorf("LookupAddr(8.8.8.8): %v (mode=%v)", err, mode)
+ } else {
+ for _, name := range names {
+ if !strings.HasSuffix(name, ".google.com.") {
+ t.Errorf("LookupAddr(8.8.8.8) = %v, want names ending in .google.com. with trailing dot (mode=%v)", names, mode)
+ break
+ }
+ }
+ }
+
+ 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)
+ }
+
+ mxs, err := LookupMX("google.com")
+ if err != nil {
+ t.Errorf("LookupMX(google.com): %v (mode=%v)", err, mode)
+ } else {
+ for _, mx := range mxs {
+ if !strings.HasSuffix(mx.Host, ".google.com.") {
+ t.Errorf("LookupMX(google.com) = %v, want names ending in .google.com. with trailing dot (mode=%v)", mxString(mxs), mode)
+ break
+ }
+ }
+ }
+
+ nss, err := LookupNS("google.com")
+ if err != nil {
+ t.Errorf("LookupNS(google.com): %v (mode=%v)", err, mode)
+ } else {
+ for _, ns := range nss {
+ if !strings.HasSuffix(ns.Host, ".google.com.") {
+ t.Errorf("LookupNS(google.com) = %v, want names ending in .google.com. with trailing dot (mode=%v)", nsString(nss), mode)
+ break
+ }
+ }
+ }
+
+ cname, srvs, err := LookupSRV("xmpp-server", "tcp", "google.com")
+ if err != nil {
+ t.Errorf("LookupSRV(xmpp-server, tcp, google.com): %v (mode=%v)", err, mode)
+ } else {
+ if !strings.HasSuffix(cname, ".google.com.") {
+ t.Errorf("LookupSRV(xmpp-server, tcp, google.com) returned cname=%v, want name ending in .google.com. with trailing dot (mode=%v)", cname, mode)
+ }
+ for _, srv := range srvs {
+ if !strings.HasSuffix(srv.Target, ".google.com.") {
+ t.Errorf("LookupSRV(xmpp-server, tcp, google.com) returned addrs=%v, want names ending in .google.com. with trailing dot (mode=%v)", srvString(srvs), mode)
+ break
+ }
+ }
+ }
+}
+
+func mxString(mxs []*MX) string {
+ var buf bytes.Buffer
+ sep := ""
+ fmt.Fprintf(&buf, "[")
+ for _, mx := range mxs {
+ fmt.Fprintf(&buf, "%s%s:%d", sep, mx.Host, mx.Pref)
+ sep = " "
+ }
+ fmt.Fprintf(&buf, "]")
+ return buf.String()
+}
+
+func nsString(nss []*NS) string {
+ var buf bytes.Buffer
+ sep := ""
+ fmt.Fprintf(&buf, "[")
+ for _, ns := range nss {
+ fmt.Fprintf(&buf, "%s%s", sep, ns.Host)
+ sep = " "
+ }
+ fmt.Fprintf(&buf, "]")
+ return buf.String()
+}
+
+func srvString(srvs []*SRV) string {
+ var buf bytes.Buffer
+ sep := ""
+ fmt.Fprintf(&buf, "[")
+ for _, srv := range srvs {
+ fmt.Fprintf(&buf, "%s%s:%d:%d:%d", sep, srv.Target, srv.Port, srv.Priority, srv.Weight)
+ sep = " "
+ }
+ fmt.Fprintf(&buf, "]")
+ return buf.String()
+}
diff --git a/src/net/lookup_unix.go b/src/net/lookup_unix.go
index 1c811d268330a1d0d4911ee1bed9c2d9446fb4fb..a64da8bcb5053c93c27a8cca3d89d2a518e4196a 100644
--- a/src/net/lookup_unix.go
+++ b/src/net/lookup_unix.go
@@ -74,19 +74,21 @@ return goLookupIPOrder(host, order)
}
func lookupPort(network, service string) (int, error) {
- port, err, ok := cgoLookupPort(network, service)
- if !ok {
- port, err = goLookupPort(network, service)
+ if systemConf().canUseCgo() {
+ if port, err, ok := cgoLookupPort(network, service); ok {
+ return port, err
+ }
}
- return port, err
+ return goLookupPort(network, service)
}
func lookupCNAME(name string) (string, error) {
- cname, err, ok := cgoLookupCNAME(name)
- if !ok {
- cname, err = goLookupCNAME(name)
+ if systemConf().canUseCgo() {
+ if cname, err, ok := cgoLookupCNAME(name); ok {
+ return cname, err
+ }
}
- return cname, err
+ return goLookupCNAME(name)
}
func lookupSRV(service, proto, name string) (string, []*SRV, error) {
@@ -148,9 +150,10 @@ return txts, nil
}
func lookupAddr(addr string) ([]string, error) {
- ptrs, err, ok := cgoLookupPTR(addr)
- if !ok {
- ptrs, err = goLookupPTR(addr)
+ if systemConf().canUseCgo() {
+ if ptrs, err, ok := cgoLookupPTR(addr); ok {
+ return ptrs, err
+ }
}
- return ptrs, err
+ return goLookupPTR(addr)
}
diff --git a/src/net/mail/message.go b/src/net/mail/message.go
index 8ddb313b47a73ccb33fbfa898d59796ca007f9f4..266ac50a38dee1b82b8effbdc65b90a4dc008a64 100644
--- a/src/net/mail/message.go
+++ b/src/net/mail/message.go
@@ -171,7 +171,14 @@ func (a *Address) String() string {
// Format address local@domain
at := strings.LastIndex(a.Address, "@")
- local, domain := a.Address[:at], a.Address[at+1:]
+ var local, domain string
+ if at < 0 {
+ // This is a malformed address ("@" is required in addr-spec);
+ // treat the whole address as local-part.
+ local = a.Address
+ } else {
+ local, domain = a.Address[:at], a.Address[at+1:]
+ }
// Add quotes if needed
// TODO: rendering quoted local part and rendering printable name
diff --git a/src/net/mail/message_test.go b/src/net/mail/message_test.go
index ffe9af9bf639ac87b077e0d2d6943f245fca648c..1b422743f95fb4656265d5695529dee0ae6757c9 100644
--- a/src/net/mail/message_test.go
+++ b/src/net/mail/message_test.go
@@ -483,6 +483,14 @@ {
&Address{Name: "Böb Jacöb", Address: "bob@example.com"},
`=?utf-8?q?B=C3=B6b_Jac=C3=B6b?= `,
},
+ { // https://golang.org/issue/12098
+ &Address{Name: "Rob", Address: ""},
+ `"Rob" <@>`,
+ },
+ { // https://golang.org/issue/12098
+ &Address{Name: "Rob", Address: "@"},
+ `"Rob" <@>`,
+ },
}
for _, test := range tests {
s := test.addr.String()
diff --git a/src/net/net.go b/src/net/net.go
index 75510a22232d741e8497ee05753d20f18fc4b02b..6e84c3a100e5af76563f50e2d114c423550a52ba 100644
--- a/src/net/net.go
+++ b/src/net/net.go
@@ -35,6 +35,46 @@ // handle error
}
go handleConnection(conn)
}
+
+Name Resolution
+
+The method for resolving domain names, whether indirectly with functions like Dial
+or directly with functions like LookupHost and LookupAddr, varies by operating system.
+
+On Unix systems, the resolver has two options for resolving names.
+It can use a pure Go resolver that sends DNS requests directly to the servers
+listed in /etc/resolv.conf, or it can use a cgo-based resolver that calls C
+library routines such as getaddrinfo and getnameinfo.
+
+By default the pure Go resolver is used, because a blocked DNS request consumes
+only a goroutine, while a blocked C call consumes an operating system thread.
+When cgo is available, the cgo-based resolver is used instead under a variety of
+conditions: on systems that do not let programs make direct DNS requests (OS X),
+when the LOCALDOMAIN environment variable is present (even if empty),
+when the RES_OPTIONS or HOSTALIASES environment variable is non-empty,
+when the ASR_CONFIG environment variable is non-empty (OpenBSD only),
+when /etc/resolv.conf or /etc/nsswitch.conf specify the use of features that the
+Go resolver does not implement, and when the name being looked up ends in .local
+or is an mDNS name.
+
+The resolver decision can be overridden by setting the netdns value of the
+GODEBUG environment variable (see package runtime) to go or cgo, as in:
+
+ export GODEBUG=netdns=go # force pure Go resolver
+ export GODEBUG=netdns=cgo # force cgo resolver
+
+The decision can also be forced while building the Go source tree
+by setting the netgo or netcgo build tag.
+
+A numeric netdns setting, as in GODEBUG=netdns=1, causes the resolver
+to print debugging information about its decisions.
+To force a particular resolver while also printing debugging information,
+join the two settings by a plus sign, as in GODEBUG=netdns=go+1.
+
+On Plan 9, the resolver always accesses /net/cs and /net/dns.
+
+On Windows, the resolver always uses C library functions, such as GetAddrInfo and DnsQuery.
+
*/
package net
diff --git a/src/net/non_unix_test.go b/src/net/non_unix_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..eddca562f9833939f7ec330d3f642f5db65027dd
--- /dev/null
+++ b/src/net/non_unix_test.go
@@ -0,0 +1,11 @@
+// Copyright 2015 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 nacl plan9 windows
+
+package net
+
+// See unix_test.go for what these (don't) do.
+func forceGoDNS() func() { return func() {} }
+func forceCgoDNS() bool { return false }
diff --git a/src/net/unix_test.go b/src/net/unix_test.go
index 59f5c2d85bb7df1dd7d176d2e4853b984b6ebde4..358ff310725de29b2dc26254546bab01059fde9c 100644
--- a/src/net/unix_test.go
+++ b/src/net/unix_test.go
@@ -404,3 +404,28 @@ }
}
}
}
+
+// forceGoDNS forces the resolver configuration to use the pure Go resolver
+// and returns a fixup function to restore the old settings.
+func forceGoDNS() func() {
+ c := systemConf()
+ oldGo := c.netGo
+ oldCgo := c.netCgo
+ fixup := func() {
+ c.netGo = oldGo
+ c.netCgo = oldCgo
+ }
+ c.netGo = true
+ c.netCgo = false
+ return fixup
+}
+
+// forceCgoDNS forces the resolver configuration to use the cgo resolver
+// and returns true to indicate that it did so.
+// (On non-Unix systems forceCgoDNS returns false.)
+func forceCgoDNS() bool {
+ c := systemConf()
+ c.netGo = false
+ c.netCgo = true
+ return true
+}
diff --git a/src/runtime/asm_arm.s b/src/runtime/asm_arm.s
index 91dccdc3811aaee8132c078c936c5857618d4205..9c32e42afd701148e16f8491b07bfb0e650f2779 100644
--- a/src/runtime/asm_arm.s
+++ b/src/runtime/asm_arm.s
@@ -752,6 +752,8 @@ TEXT runtime·atomicstoreuintptr(SB),NOSPLIT,$0-8
B runtime·atomicstore(SB)
// armPublicationBarrier is a native store/store barrier for ARMv7+.
+// On earlier ARM revisions, armPublicationBarrier is a no-op.
+// This will not work on SMP ARMv6 machines, if any are in use.
// To implement publiationBarrier in sys_$GOOS_arm.s using the native
// instructions, use:
//
@@ -759,6 +761,9 @@ // TEXT ·publicationBarrier(SB),NOSPLIT,$-4-0
// B runtime·armPublicationBarrier(SB)
//
TEXT runtime·armPublicationBarrier(SB),NOSPLIT,$-4-0
+ MOVB runtime·goarm(SB), R11
+ CMP $7, R11
+ BLT 2(PC)
WORD $0xf57ff05e // DMB ST
RET
diff --git a/src/runtime/mbitmap.go b/src/runtime/mbitmap.go
index c439158f078080f50d43685838cd24e6df01677d..fd6b4b11a2f8e31eada566981e03cf9f1968c369 100644
--- a/src/runtime/mbitmap.go
+++ b/src/runtime/mbitmap.go
@@ -109,6 +109,9 @@ }
// subtract1 returns the byte pointer p-1.
//go:nowritebarrier
+//
+// nosplit because it is used during write barriers and must not be preempted.
+//go:nosplit
func subtract1(p *byte) *byte {
// Note: wrote out full expression instead of calling subtractb(p, 1)
// to reduce the number of temporaries generated by the
@@ -245,6 +248,9 @@
// next returns the heapBits describing the next pointer-sized word in memory.
// That is, if h describes address p, h.next() describes p+ptrSize.
// Note that next does not modify h. The caller must record the result.
+//
+// nosplit because it is used during write barriers and must not be preempted.
+//go:nosplit
func (h heapBits) next() heapBits {
if h.shift < 3*heapBitsShift {
return heapBits{h.bitp, h.shift + heapBitsShift}
@@ -293,6 +299,9 @@ }
// 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
func (h heapBits) isPointer() bool {
return (*h.bitp>>h.shift)&bitPointer != 0
}
diff --git a/src/runtime/os1_darwin.go b/src/runtime/os1_darwin.go
index 08ec611d431469c3960d6bfa30184aaf015e237c..e07022997c81b56b79e150a154e8b81325afb75b 100644
--- a/src/runtime/os1_darwin.go
+++ b/src/runtime/os1_darwin.go
@@ -34,14 +34,19 @@ func osinit() {
// bsdthread_register delayed until end of goenvs so that we
// can look at the environment first.
+ ncpu = getncpu()
+}
+
+func getncpu() int32 {
// Use sysctl to fetch hw.ncpu.
mib := [2]uint32{6, 3}
out := uint32(0)
nout := unsafe.Sizeof(out)
ret := sysctl(&mib[0], 2, (*byte)(unsafe.Pointer(&out)), &nout, nil, 0)
- if ret >= 0 {
- ncpu = int32(out)
+ if ret >= 0 && int32(out) > 0 {
+ return int32(out)
}
+ return 1
}
var urandom_dev = []byte("/dev/urandom\x00")
diff --git a/src/runtime/os_darwin_arm.go b/src/runtime/os_darwin_arm.go
index d3336c012a0b73720c42bb96ff364400748af5da..1ccc9592da8647c0856aba3f622a893138ee8be6 100644
--- a/src/runtime/os_darwin_arm.go
+++ b/src/runtime/os_darwin_arm.go
@@ -5,7 +5,14 @@
package runtime
func checkgoarm() {
- return // TODO(minux)
+ // TODO(minux): FP checks like in os_linux_arm.go.
+
+ // osinit not called yet, so ncpu not set: must use getncpu directly.
+ if getncpu() > 1 && goarm < 7 {
+ print("runtime: this system has multiple CPUs and must use\n")
+ print("atomic synchronization instructions. Recompile using GOARM=7.\n")
+ exit(1)
+ }
}
//go:nosplit
diff --git a/src/runtime/os_freebsd_arm.go b/src/runtime/os_freebsd_arm.go
index e049cbf9a1ee5aaf8738b2e016f64fdf4582bdfb..1f2add279f214b00fed221fe66aefdcff99a62a1 100644
--- a/src/runtime/os_freebsd_arm.go
+++ b/src/runtime/os_freebsd_arm.go
@@ -5,7 +5,14 @@
package runtime
func checkgoarm() {
- // TODO(minux)
+ // TODO(minux): FP checks like in os_linux_arm.go.
+
+ // osinit not called yet, so ncpu not set: must use getncpu directly.
+ if getncpu() > 1 && goarm < 7 {
+ print("runtime: this system has multiple CPUs and must use\n")
+ print("atomic synchronization instructions. Recompile using GOARM=7.\n")
+ exit(1)
+ }
}
//go:nosplit
diff --git a/src/runtime/os_linux_arm.go b/src/runtime/os_linux_arm.go
index 6c74c818595f747379ac4c0b4c7a1582938eb663..3749640ee52182c125ea3b5035bab64c3ff3194c 100644
--- a/src/runtime/os_linux_arm.go
+++ b/src/runtime/os_linux_arm.go
@@ -19,7 +19,6 @@
var randomNumber uint32
var armArch uint8 = 6 // we default to ARMv6
var hwcap uint32 // set by setup_auxv
-var goarm uint8 // set by 5l
func checkgoarm() {
if goarm > 5 && hwcap&_HWCAP_VFP == 0 {
diff --git a/src/runtime/os_nacl_arm.go b/src/runtime/os_nacl_arm.go
index a43e7c47b7a5fac9d4b7de0148f10f2fba2e3a2d..f94c183e87684c59b9f5ba65ec340c668f6918af 100644
--- a/src/runtime/os_nacl_arm.go
+++ b/src/runtime/os_nacl_arm.go
@@ -5,7 +5,13 @@
package runtime
func checkgoarm() {
- return // NaCl/ARM only supports ARMv7
+ // TODO(minux): FP checks like in os_linux_arm.go.
+
+ // NaCl/ARM only supports ARMv7
+ if goarm != 7 {
+ print("runtime: NaCl requires ARMv7. Recompile using GOARM=7.\n")
+ exit(1)
+ }
}
//go:nosplit
diff --git a/src/runtime/os_netbsd_arm.go b/src/runtime/os_netbsd_arm.go
index 83c4c06cf93597661e6ae6b5e39521282343463d..03032e8bea53bf492b221a63c4ed4fd9349b7f3b 100644
--- a/src/runtime/os_netbsd_arm.go
+++ b/src/runtime/os_netbsd_arm.go
@@ -16,7 +16,14 @@ mc.__gregs[_REG_R2] = uint32(fn)
}
func checkgoarm() {
- // TODO(minux)
+ // TODO(minux): FP checks like in os_linux_arm.go.
+
+ // osinit not called yet, so ncpu not set: must use getncpu directly.
+ if getncpu() > 1 && goarm < 7 {
+ print("runtime: this system has multiple CPUs and must use\n")
+ print("atomic synchronization instructions. Recompile using GOARM=7.\n")
+ exit(1)
+ }
}
//go:nosplit
diff --git a/src/runtime/os_openbsd_arm.go b/src/runtime/os_openbsd_arm.go
index be3f330dfb0b6e27a2e13c9f0ccec2f436915106..b46fef0090d23d39325326e052b04c9ea066723a 100644
--- a/src/runtime/os_openbsd_arm.go
+++ b/src/runtime/os_openbsd_arm.go
@@ -5,7 +5,14 @@
package runtime
func checkgoarm() {
- // TODO(minux)
+ // TODO(minux): FP checks like in os_linux_arm.go.
+
+ // osinit not called yet, so ncpu not set: must use getncpu directly.
+ if getncpu() > 1 && goarm < 7 {
+ print("runtime: this system has multiple CPUs and must use\n")
+ print("atomic synchronization instructions. Recompile using GOARM=7.\n")
+ exit(1)
+ }
}
//go:nosplit
diff --git a/src/runtime/panic.go b/src/runtime/panic.go
index c8158b9decea4b254acb1c487f1e3c78ab4defd5..a1662812de8c4dc1ae8322f1dd2697ada717dd05 100644
--- a/src/runtime/panic.go
+++ b/src/runtime/panic.go
@@ -327,7 +327,7 @@ gp._defer = d.link
freedefer(d)
// Note: we ignore recovers here because Goexit isn't a panic
}
- goexit()
+ goexit1()
}
// Print all currently active panics. Used when crashing.
diff --git a/src/runtime/proc1.go b/src/runtime/proc1.go
index 23beaf537c83f3d6946920001c2372913b8ae977..09cb775f0dee9b49c5164b039506462a6119567c 100644
--- a/src/runtime/proc1.go
+++ b/src/runtime/proc1.go
@@ -1348,7 +1348,23 @@ if trace.enabled {
// GoSysExit has to happen when we have a P, but before GoStart.
// So we emit it here.
if gp.syscallsp != 0 && gp.sysblocktraced {
- traceGoSysExit(gp.sysexitseq, gp.sysexitticks)
+ // Since gp.sysblocktraced is true, we must emit an event.
+ // There is a race between the code that initializes sysexitseq
+ // and sysexitticks (in exitsyscall, which runs without a P,
+ // and therefore is not stopped with the rest of the world)
+ // and the code that initializes a new trace.
+ // The recorded sysexitseq and sysexitticks must therefore
+ // be treated as "best effort". If they are valid for this trace,
+ // then great, use them for greater accuracy.
+ // But if they're not valid for this trace, assume that the
+ // trace was started after the actual syscall exit (but before
+ // we actually managed to start the goroutine, aka right now),
+ // and assign a fresh time stamp to keep the log consistent.
+ seq, ts := gp.sysexitseq, gp.sysexitticks
+ if seq == 0 || int64(seq)-int64(trace.seqStart) < 0 {
+ seq, ts = tracestamp()
+ }
+ traceGoSysExit(seq, ts)
}
traceGoStart()
}
diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go
index a157f016d162c5282f131709c2483f8f0d5f3e10..57cd869d88c0c795b9bcde49165c5d487a1ef721 100644
--- a/src/runtime/runtime2.go
+++ b/src/runtime/runtime2.go
@@ -645,6 +645,8 @@ // Set on startup in asm_{x86,amd64}.s.
cpuid_ecx uint32
cpuid_edx uint32
lfenceBeforeRdtsc bool
+
+ goarm uint8 // set by cmd/link on arm systems
)
// Set by the linker so the runtime can determine the buildmode.
diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go
index e6b015684be74375d91c4c8d46310a8f1cd705eb..d725bb11f5ad10e0c1e7cf1ffd57f5753d25e00d 100644
--- a/src/runtime/stubs.go
+++ b/src/runtime/stubs.go
@@ -128,7 +128,20 @@ // site for justification.
func reflectcall(argtype *_type, fn, arg unsafe.Pointer, argsize uint32, retoffset uint32)
func procyield(cycles uint32)
-func goexit()
+
+type neverCallThisFunction struct{}
+
+// goexit is the return stub at the top of every goroutine call stack.
+// Each goroutine stack is constructed as if goexit called the
+// goroutine's entry point function, so that when the entry point
+// function returns, it will return to goexit, which will call goexit1
+// to perform the actual exit.
+//
+// This function must never be called directly. Call goexit1 instead.
+// gentraceback assumes that goexit terminates the stack. A direct
+// call on the stack will cause gentraceback to stop walking the stack
+// prematurely and if there are leftover stack barriers it may panic.
+func goexit(neverCallThisFunction)
// Not all cgocallback_gofunc frames are actually cgocallback_gofunc,
// so not all have these arguments. Mark them uintptr so that the GC
diff --git a/src/sort/sort.go b/src/sort/sort.go
index 0a446c825563b1aacaa1c30b6cef3500503e5192..c7c30426aec138ec56f20348d51136d467b1e400 100644
--- a/src/sort/sort.go
+++ b/src/sort/sort.go
@@ -300,7 +300,7 @@ // - "Fast Stable In-Place Sorting with O(n) Data Moves" J.I. Munro and
// V. Raman in Algorithmica (1996) 16, 115-160:
// This algorithm either needs additional 2n bits or works only if there
// are enough different elements available to encode some permutations
-// which have to be undone later (so not stable an any input).
+// which have to be undone later (so not stable on any input).
// - All the optimal in-place sorting/merging algorithms I found are either
// unstable or rely on enough different elements in each step to encode the
// performed block rearrangements. See also "In-Place Merging Algorithms",
diff --git a/test/fixedbugs/issue12133.go b/test/fixedbugs/issue12133.go
new file mode 100644
index 0000000000000000000000000000000000000000..0b66c56a5164dc84b7ec77ef28afdc847d86b60c
--- /dev/null
+++ b/test/fixedbugs/issue12133.go
@@ -0,0 +1,26 @@
+// run
+
+// Copyright 2015 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.
+
+// Issue 12133. The CX register was getting clobbered
+// because we did not keep track of its allocation correctly.
+
+package main
+
+import "fmt"
+
+func main() {
+ want := uint(48)
+ got := f1(48)
+ if got != want {
+ fmt.Println("got", got, ", wanted", want)
+ panic("bad")
+ }
+}
+func f1(v1 uint) uint {
+ switch {
+ } // prevent inlining
+ return v1 >> ((1 >> v1) + (1 >> v1))
+}