aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2015-08-19 00:37:55 -0400
committerRuss Cox <rsc@golang.org>2015-08-19 00:39:48 -0400
commita30edb80715ea5c7bbed6083859d3c54632d6b4b (patch)
tree4cc4d7f474ab8fa4bcde8417ae93e1aef81b9ea5
parent0d20a61e68ba22fb416fe2aa8b6532026822bad0 (diff)
parentfa87cf83a64edf30b9da867a96ee83d9f24af867 (diff)
downloadgo-a30edb80715ea5c7bbed6083859d3c54632d6b4b.tar.gz
go-a30edb80715ea5c7bbed6083859d3c54632d6b4b.zip
[release-branch.go1.5] release: merge master branch into release-branch.go1.5.
Using merge instead of cherry-picks to simplify initial release. Minor releases like Go 1.5.1 will have to use cherry-picks. Fixes #12093. Change-Id: If00393c58ace0da6f359b387cea9b779b123b920
-rw-r--r--doc/asm.html4
-rw-r--r--doc/contrib.html1
-rw-r--r--doc/devel/release.html7
-rw-r--r--doc/go1.5.html54
-rw-r--r--doc/install.html16
-rw-r--r--src/cmd/compile/internal/amd64/ggen.go8
-rw-r--r--src/cmd/compile/internal/amd64/reg.go2
-rw-r--r--src/cmd/compile/internal/arm64/ggen.go9
-rw-r--r--src/cmd/compile/internal/arm64/reg.go2
-rw-r--r--src/cmd/compile/internal/gc/gsubr.go7
-rw-r--r--src/cmd/compile/internal/gc/typecheck.go2
-rw-r--r--src/cmd/compile/internal/gc/walk.go2
-rw-r--r--src/cmd/compile/internal/ppc64/ggen.go10
-rw-r--r--src/cmd/compile/internal/x86/ggen.go4
-rw-r--r--src/cmd/compile/internal/x86/reg.go2
-rw-r--r--src/cmd/go/alldocs.go9
-rw-r--r--src/cmd/go/build.go2
-rw-r--r--src/cmd/go/go_test.go35
-rw-r--r--src/cmd/go/help.go2
-rw-r--r--src/cmd/go/list.go7
-rw-r--r--src/cmd/go/main.go5
-rw-r--r--src/cmd/go/note_test.go26
-rw-r--r--src/cmd/go/pkg.go12
-rw-r--r--src/cmd/go/test.go2
-rw-r--r--src/cmd/go/testdata/testvendor2/src/p/p.go3
-rw-r--r--src/cmd/go/testdata/testvendor2/vendor/x/x.go1
-rw-r--r--src/cmd/go/testflag.go1
-rw-r--r--src/cmd/go/vcs.go2
-rw-r--r--src/cmd/go/vendor_test.go12
-rw-r--r--src/cmd/link/internal/ld/data.go13
-rw-r--r--src/cmd/trace/trace.go4
-rw-r--r--src/cmd/vet/asmdecl.go24
-rw-r--r--src/cmd/yacc/yacc.go11
-rw-r--r--src/fmt/scan.go1
-rw-r--r--src/fmt/scan_test.go28
-rw-r--r--src/net/cgo_unix.go5
-rw-r--r--src/net/conf.go8
-rw-r--r--src/net/http/server.go7
-rw-r--r--src/net/http/transport.go80
-rw-r--r--src/net/lookup_test.go109
-rw-r--r--src/net/lookup_unix.go27
-rw-r--r--src/net/mail/message.go9
-rw-r--r--src/net/mail/message_test.go8
-rw-r--r--src/net/net.go40
-rw-r--r--src/net/non_unix_test.go11
-rw-r--r--src/net/unix_test.go25
-rw-r--r--src/runtime/asm_arm.s5
-rw-r--r--src/runtime/mbitmap.go9
-rw-r--r--src/runtime/os1_darwin.go9
-rw-r--r--src/runtime/os_darwin_arm.go9
-rw-r--r--src/runtime/os_freebsd_arm.go9
-rw-r--r--src/runtime/os_linux_arm.go1
-rw-r--r--src/runtime/os_nacl_arm.go8
-rw-r--r--src/runtime/os_netbsd_arm.go9
-rw-r--r--src/runtime/os_openbsd_arm.go9
-rw-r--r--src/runtime/panic.go2
-rw-r--r--src/runtime/proc1.go18
-rw-r--r--src/runtime/runtime2.go2
-rw-r--r--src/runtime/stubs.go15
-rw-r--r--src/sort/sort.go2
-rw-r--r--test/fixedbugs/issue12133.go26
61 files changed, 639 insertions, 153 deletions
diff --git a/doc/asm.html b/doc/asm.html
index ba888118b9..c992e14ade 100644
--- a/doc/asm.html
+++ b/doc/asm.html
@@ -741,10 +741,10 @@ Addressing modes:
</ul>
-<h3 id="ppc64">Power 64, a.k.a. ppc64</h3>
+<h3 id="ppc64">64-bit PowerPC, a.k.a. ppc64</h3>
<p>
-The Power 64 port is in an experimental state.
+The 64-bit PowerPC port is in an experimental state.
</p>
<p>
diff --git a/doc/contrib.html b/doc/contrib.html
index c286abc9b8..48390353d1 100644
--- a/doc/contrib.html
+++ b/doc/contrib.html
@@ -34,6 +34,7 @@ We encourage all Go users to subscribe to
<p>A <a href="/doc/devel/release.html">summary</a> of the changes between Go releases. Notes for the major releases:</p>
<ul>
+ <li><a href="/doc/go1.5">Go 1.5</a> <small>(August 2015)</small></li>
<li><a href="/doc/go1.4">Go 1.4</a> <small>(December 2014)</small></li>
<li><a href="/doc/go1.3">Go 1.3</a> <small>(June 2014)</small></li>
<li><a href="/doc/go1.2">Go 1.2</a> <small>(December 2013)</small></li>
diff --git a/doc/devel/release.html b/doc/devel/release.html
index ee6d3e0729..7d72c8d933 100644
--- a/doc/devel/release.html
+++ b/doc/devel/release.html
@@ -12,6 +12,13 @@ git pull
git checkout <i>release-branch</i>
</pre>
+<h2 id="go1.5">go1.5 (released 2015/08/19)</h2>
+
+<p>
+Go 1.5 is a major release of Go.
+Read the <a href="/doc/go1.5">Go 1.5 Release Notes</a> for more information.
+</p>
+
<h2 id="go1.4">go1.4 (released 2014/12/10)</h2>
<p>
diff --git a/doc/go1.5.html b/doc/go1.5.html
index 70ce94e9ad..4e5832db3a 100644
--- a/doc/go1.5.html
+++ b/doc/go1.5.html
@@ -83,7 +83,8 @@ time the release dates more conveniently.
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 <a href="/cl/2591">corrected</a> 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,
</p>
<pre>
@@ -182,7 +183,7 @@ Details of the new collector were presented in a
<p>
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 <code>GOMAXPROCS</code>, 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.
</p>
<p>
-Also available as experiments are <code>ppc64</code> (IBM Power 64)
-and <code>ppc64le</code> (IBM Power 64, little-endian).
+Also available as experiments are <code>ppc64</code>
+and <code>ppc64le</code> (64-bit PowerPC, big- and little-endian).
Both these ports support <code>cgo</code> but
only with internal linking.
</p>
@@ -247,8 +248,8 @@ On FreeBSD, Go 1.5 requires FreeBSD 8-STABLE+ because of its new use of the <cod
</p>
<p>
-On NaCl, Go 1.5 requires SDK version pepper-39 or above because it now uses the
-<code>get_random_bytes</code> 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.
</p>
<p>
@@ -292,7 +293,7 @@ The old names are gone; the new tools are available through the <code>go</code>
mechanism as <code>go tool compile</code>,
<code>go tool asm</code>,
<code>and go tool link</code>.
-Also, the file suffixes <code>.6</code>, <code>.8</code> etc. for the
+Also, the file suffixes <code>.6</code>, <code>.8</code>, etc. for the
intermediate object files are also gone; now they are just plain <code>.o</code> files.
</p>
@@ -512,7 +513,7 @@ A new <code>cmd</code> wildcard covers the commands.
<li>
A new <code>-asmflags</code> build option
sets flags to pass to the assembler.
-However,
+However,
the <code>-ccflags</code> build option has been dropped;
it was specific to the old, now deleted C compiler .
</li>
@@ -523,14 +524,6 @@ sets the build mode, described above.
</li>
<li>
-An <code>-asmflags</code> build option has been added to provide
-flags to the assembler.
-However,
-the <code>-ccflags</code> build option has been dropped;
-it was specific to the old, now deleted C compiler .
-</li>
-
-<li>
A new <code>-pkgdir</code> build option
sets the location of installed package archives,
to help isolate custom builds.
@@ -546,7 +539,7 @@ This acts as a custom replacement for <code>go tool</code>.
<li>
The <code>test</code> subcommand now has a <code>-count</code>
flag to specify how many times to run each test and benchmark.
-<a href="/pkg/testing/"><code>testing</code></a> package
+The <a href="/pkg/testing/"><code>testing</code></a> package
does the work here, through by the <code>-test.count</code> flag.
</li>
@@ -823,7 +816,7 @@ method to discard data from the input.
</li>
<li>
-Also in the <a href="/pkg/bytes/"><code>bytes</code></a> package,
+In the <a href="/pkg/bytes/"><code>bytes</code></a> package,
the <a href="/pkg/bytes/#Buffer"><code>Buffer</code></a> type
now has a <a href="/pkg/bytes/#Buffer.Cap"><code>Cap</code></a> method
that reports the number of bytes allocated within the buffer.
@@ -960,7 +953,7 @@ also now supports decoding of DWARF line tables.
<li>
The <a href="/pkg/debug/elf/"><code>debug/elf</code></a>
-package now has support for the 64-bit Power architecture.
+package now has support for the 64-bit PowerPC architecture.
</li>
<li>
@@ -1032,14 +1025,14 @@ To update, run
In the <a href="/pkg/image/"><code>image</code></a> package,
the <a href="/pkg/image/#Rectangle"><code>Rectangle</code></a> type
now implements the <a href="/pkg/image/#Image"><code>Image</code></a> interface,
-mask image when drawing.
+so a <code>Rectangle</code> can serve as a mask when drawing.
</li>
<li>
Also in the <a href="/pkg/image/"><code>image</code></a> 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 <code>image.CMYK</code> struct.
</li>
<li>
@@ -1062,7 +1055,7 @@ Because of the echo property of the old code, the operation
In Go 1.5, that operation may yield a different value.
The correct code is, and always was, to select the high 8 bits:
<code>uint8(r&gt;&gt;8)</code>.
-Incidentally, <code>image/draw</code> package
+Incidentally, the <code>image/draw</code> package
provides better support for such conversions; see
<a href="https://blog.golang.org/go-imagedraw-package">this blog post</a>
for more information.
@@ -1095,9 +1088,8 @@ uses a caller-provided buffer, permitting control of allocation and buffer size.
The <a href="/pkg/log/"><code>log</code></a> package
has a new <a href="/pkg/log/#LUTC"><code>LUTC</code></a> flag
that causes time stamps to be printed in the UTC time zone.
-It also adds a <a href="/pkg/log/#SetOutput"><code>SetOutput</code></a> function
-to set the output destination for the standard logger
-and a corresponding method for user-created loggers.
+It also adds a <a href="/pkg/log/#Logger.SetOutput"><code>SetOutput</code></a> method
+for user-created loggers.
</li>
<li>
@@ -1109,7 +1101,7 @@ but now correctly according to the IEEE754 definition of NaNs.
<li>
The <a href="/pkg/math/big/"><code>math/big</code></a> package
adds a new <a href="/pkg/math/big/#Jacobi"><code>Jacobi</code></a>
-function for integers and a new method
+function for integers and a new
<a href="/pkg/math/big/#Int.ModSqrt"><code>ModSqrt</code></a>
method for the <a href="/pkg/math/big/#Int"><code>Int</code></a> type.
</li>
@@ -1201,7 +1193,7 @@ variable.
<li>
The <a href="/pkg/net/mail/"><code>net/mail</code></a> package
-adds a <a href="/pkg/net/mail/#AddressParser"><code>AddressParser</code></a>
+adds an <a href="/pkg/net/mail/#AddressParser"><code>AddressParser</code></a>
type that can parse mail addresses.
</li>
@@ -1252,11 +1244,11 @@ but is otherwise unnecessary as strings support comparison natively.
</li>
<li>
-The <a href="/pkg/sync/#WaitGroup"><code>WaitGroup</code></a> function in
+The <a href="/pkg/sync/#WaitGroup"><code>WaitGroup</code></a> implementation in
package <a href="/pkg/sync/"><code>sync</code></a>
now diagnoses code that races a call to <a href="/pkg/sync/#WaitGroup.Add"><code>Add</code></a>
against a return from <a href="/pkg/sync/#WaitGroup.Wait"><code>Wait</code></a>.
-If it detects this condition, <code>WaitGroup</code> panics.
+If it detects this condition, the implementation panics.
</li>
<li>
@@ -1288,7 +1280,7 @@ precision.
<li>
Also in the <a href="/pkg/text/template/"><code>text/template</code></a> and
<a href="/pkg/html/template/"><code>html/template</code></a> packages,
-a new <a href="/pkg/text/template/#Option"><code>Option</code></a> type
+a new <a href="/pkg/text/template/#Template.Option"><code>Option</code></a> 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 9264f3a0d0..e9f0f0dc09 100644
--- a/doc/install.html
+++ b/doc/install.html
@@ -33,11 +33,11 @@ system and architecture, try
<h2 id="requirements">System requirements</h2>
<p>
-The <code>gc</code> 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
-<code>gccgo</code> might support your setup; see
-<a href="/doc/install/gccgo">Setting up and using gccgo</a> 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
+<a href="/doc/install/source">install from source</a> or
+<a href="/doc/install/gccgo">use gccgo instead</a>.
</p>
<table class="codetable" frame="border" summary="requirements">
@@ -47,9 +47,9 @@ proceeding. If your OS or architecture is not on the list, it's possible that
<th align="center">Notes</th>
</tr>
<tr><td colspan="3"><hr></td></tr>
-<tr><td>FreeBSD 8-STABLE or later</td> <td>amd64, 386, arm</td> <td>Debian GNU/kFreeBSD not supported; FreeBSD/ARM needs FreeBSD 10 or later</td></tr>
-<tr><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm</td> <td>CentOS/RHEL 5.x not supported; no binary distribution for ARM yet</td></tr>
-<tr><td>Mac OS X 10.7 or later</td> <td>amd64</td> <td>use the gcc<sup>&#8224;</sup> that comes with Xcode<sup>&#8225;</sup></td></tr>
+<tr><td>FreeBSD 8-STABLE or later</td> <td>amd64</td> <td>Debian GNU/kFreeBSD not supported</td></tr>
+<tr><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm</td> <td>CentOS/RHEL 5.x not supported; install from source for ARM</td></tr>
+<tr><td>Mac OS X 10.7 or later</td> <td>amd64</td> <td>use the clang or gcc<sup>&#8224;</sup> that comes with Xcode<sup>&#8225;</sup></td></tr>
<tr><td>Windows XP or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>&#8224;</sup>. No need for cygwin or msys.</td></tr>
</table>
diff --git a/src/cmd/compile/internal/amd64/ggen.go b/src/cmd/compile/internal/amd64/ggen.go
index 6425633818..65cf6947be 100644
--- a/src/cmd/compile/internal/amd64/ggen.go
+++ b/src/cmd/compile/internal/amd64/ggen.go
@@ -306,7 +306,7 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
* 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 @@ func savex(dr int, x *gc.Node, oldx *gc.Node, res *gc.Node, t *gc.Type) {
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 @@ func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
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 7d4f40641d..8fab6399b1 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 6b0b40efbd..cba4d99151 100644
--- a/src/cmd/compile/internal/arm64/ggen.go
+++ b/src/cmd/compile/internal/arm64/ggen.go
@@ -418,15 +418,12 @@ func clearfat(nl *gc.Node) {
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 @@ func clearfat(nl *gc.Node) {
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 7bc756b7bf..b84359a637 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 14dc927442..2c575f3d78 100644
--- a/src/cmd/compile/internal/gc/gsubr.go
+++ b/src/cmd/compile/internal/gc/gsubr.go
@@ -602,6 +602,13 @@ func unpatch(p *obj.Prog) *obj.Prog {
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 dc2ba75e69..befe3b2652 100644
--- a/src/cmd/compile/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -2532,7 +2532,7 @@ func lookdot(n *Node, t *Type, dostrcmp int) *Type {
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 91c0a47b2a..ce73018b8b 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -3873,7 +3873,7 @@ func usefield(n *Node) {
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 1b936b8a5f..5b282eb2f2 100644
--- a/src/cmd/compile/internal/ppc64/ggen.go
+++ b/src/cmd/compile/internal/ppc64/ggen.go
@@ -71,7 +71,10 @@ func zerorange(p *obj.Prog, frame int64, lo int64, hi int64) *obj.Prog {
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 @@ func clearfat(nl *gc.Node) {
// 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 dabc139f30..ae9881d273 100644
--- a/src/cmd/compile/internal/x86/ggen.go
+++ b/src/cmd/compile/internal/x86/ggen.go
@@ -319,7 +319,7 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node, ax *gc.Node, dx *gc.N
}
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 @@ func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
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 8c97171e47..b3a5fdf4e0 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 512ed61cd3..6077d93a43 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 718edd2f77..b7c7e0584f 100644
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -1880,7 +1880,7 @@ func (b *builder) runOut(dir string, desc string, env []string, cmdargs ...inter
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 5b0f2783f3..77b2628982 100644
--- a/src/cmd/go/go_test.go
+++ b/src/cmd/go/go_test.go
@@ -2294,6 +2294,21 @@ func TestIssue11709(t *testing.T) {
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 @@ func TestGoBuildOutput(t *testing.T) {
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 0bc5ef95fb..5dff2670f1 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 f59c82eadf..35c7cc4f2a 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 88a94417d7..8ebde89259 100644
--- a/src/cmd/go/main.go
+++ b/src/cmd/go/main.go
@@ -446,11 +446,10 @@ func runOut(dir string, cmdargs ...interface{}) []byte {
// 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 fb25f94ec3..3d644518c6 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"
)
@@ -22,4 +23,27 @@ func TestNoteReading(t *testing.T) {
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 6b78a47939..61e3d8dc70 100644
--- a/src/cmd/go/pkg.go
+++ b/src/cmd/go/pkg.go
@@ -416,7 +416,7 @@ func vendoredImportPath(parent *Package, path string) (found string, searched []
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 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
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 @@ func ReadBuildIDFromBinary(filename string) (id string, err error) {
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 @@ func ReadBuildIDFromBinary(filename string) (id string, err error) {
//
// Plan 9: 0x20
// Windows: 0x600
- // Mach-O: 0x1000
+ // Mach-O: 0x2000
//
f, err := os.Open(filename)
if err != nil {
@@ -1815,7 +1815,7 @@ func ReadBuildIDFromBinary(filename string) (id string, err error) {
}
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 0ba1883714..ba1ab82680 100644
--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -1027,7 +1027,7 @@ func (b *builder) runTest(a *action) error {
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 0000000000..220b2b2a07
--- /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 0000000000..823aafd071
--- /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 ee4ab187e0..1f3e3d316a 100644
--- a/src/cmd/go/testflag.go
+++ b/src/cmd/go/testflag.go
@@ -36,6 +36,7 @@ var testFlagDefn = []*testFlagSpec{
{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 2ee1057a58..28a7540dfe 100644
--- a/src/cmd/go/vcs.go
+++ b/src/cmd/go/vcs.go
@@ -344,7 +344,7 @@ func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool)
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 611aceb999..1e8cf9c8d2 100644
--- a/src/cmd/go/vendor_test.go
+++ b/src/cmd/go/vendor_test.go
@@ -244,3 +244,15 @@ func TestVendorList(t *testing.T) {
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 33f250da48..55b12e5ece 100644
--- a/src/cmd/link/internal/ld/data.go
+++ b/src/cmd/link/internal/ld/data.go
@@ -778,7 +778,6 @@ func Codeblk(addr int64, size int64) {
}
eaddr := addr + size
- var n int64
var q []byte
for ; sym != nil; sym = sym.Next {
if !sym.Reachable {
@@ -797,20 +796,18 @@ func Codeblk(addr int64, size int64) {
}
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 0d2451b4ec..e6eb320aa2 100644
--- a/src/cmd/trace/trace.go
+++ b/src/cmd/trace/trace.go
@@ -10,8 +10,8 @@ import (
"internal/trace"
"log"
"net/http"
- "os"
"path/filepath"
+ "runtime"
"strconv"
"strings"
)
@@ -63,7 +63,7 @@ var templTrace = `
// 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 6bdfdbf3be..e4a9871a21 100644
--- a/src/cmd/vet/asmdecl.go
+++ b/src/cmd/vet/asmdecl.go
@@ -58,13 +58,13 @@ type asmVar struct {
}
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 @@ var (
&asmArchArm64,
&asmArchAmd64,
&asmArchAmd64p32,
- &asmArchPower64,
- &asmArchPower64LE,
+ &asmArchPpc64,
+ &asmArchPpc64LE,
}
)
@@ -86,7 +86,7 @@ var (
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 @@ func asmCheckVar(badf func(string, ...interface{}), fn *asmFunc, line, expr stri
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 53c0fab174..4f83f50e46 100644
--- a/src/cmd/yacc/yacc.go
+++ b/src/cmd/yacc/yacc.go
@@ -699,18 +699,20 @@ outer:
}
}
- // 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 @@ func ($$rcvr *$$ParserImpl) Parse($$lex $$Lexer) 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 21ed091d80..5b9b516353 100644
--- a/src/fmt/scan.go
+++ b/src/fmt/scan.go
@@ -888,7 +888,6 @@ func hexDigit(d rune) (int, bool) {
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 694f93e1ae..a3784364e6 100644
--- a/src/fmt/scan_test.go
+++ b/src/fmt/scan_test.go
@@ -1128,3 +1128,31 @@ func TestScanfNewlineMatchFormat(t *testing.T) {
}
}
}
+
+// 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 d9d5f0377c..cb89d65457 100644
--- a/src/net/cgo_unix.go
+++ b/src/net/cgo_unix.go
@@ -222,6 +222,11 @@ func cgoLookupPTR(addr string) ([]string, error, bool) {
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 01bb585ce6..c92e579d7e 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
@@ -112,6 +112,12 @@ func initConfVal() {
}
}
+// 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.
func (c *conf) hostLookupOrder(hostname string) (ret hostLookupOrder) {
if c.dnsDebugLevel > 1 {
diff --git a/src/net/http/server.go b/src/net/http/server.go
index 1b292ea2de..a3e43555bb 100644
--- a/src/net/http/server.go
+++ b/src/net/http/server.go
@@ -473,7 +473,7 @@ func (srv *Server) newConn(rwc net.Conn) (c *conn, err error) {
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 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
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 09434f1234..70d1864605 100644
--- a/src/net/http/transport.go
+++ b/src/net/http/transport.go
@@ -645,16 +645,9 @@ func (t *Transport) dialConn(cm connectMethod) (*persistConn, error) {
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 @@ func isNetWriteError(err error) bool {
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 a42ae298ef..86957b5575 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 @@ func TestLookupIPDeadline(t *testing.T) {
// 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 1c811d2683..a64da8bcb5 100644
--- a/src/net/lookup_unix.go
+++ b/src/net/lookup_unix.go
@@ -74,19 +74,21 @@ func lookupIP(host string) (addrs []IPAddr, err error) {
}
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 @@ func lookupTXT(name string) ([]string, error) {
}
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 8ddb313b47..266ac50a38 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 ffe9af9bf6..1b422743f9 100644
--- a/src/net/mail/message_test.go
+++ b/src/net/mail/message_test.go
@@ -483,6 +483,14 @@ func TestAddressFormatting(t *testing.T) {
&Address{Name: "Böb Jacöb", Address: "bob@example.com"},
`=?utf-8?q?B=C3=B6b_Jac=C3=B6b?= <bob@example.com>`,
},
+ { // 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 75510a2223..6e84c3a100 100644
--- a/src/net/net.go
+++ b/src/net/net.go
@@ -35,6 +35,46 @@ The Listen function creates servers:
}
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 0000000000..eddca562f9
--- /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 59f5c2d85b..358ff31072 100644
--- a/src/net/unix_test.go
+++ b/src/net/unix_test.go
@@ -404,3 +404,28 @@ func TestUnixgramConnLocalAndRemoteNames(t *testing.T) {
}
}
}
+
+// 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 91dccdc381..9c32e42afd 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 runtime·atomicstoreuintptr(SB),NOSPLIT,$0-8
// 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 c439158f07..fd6b4b11a2 100644
--- a/src/runtime/mbitmap.go
+++ b/src/runtime/mbitmap.go
@@ -109,6 +109,9 @@ func add1(p *byte) *byte {
// 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 @@ func (h heapBits) prefetch() {
// 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 @@ func (h heapBits) setMarkedNonAtomic() {
// 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 08ec611d43..e07022997c 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 d3336c012a..1ccc9592da 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 e049cbf9a1..1f2add279f 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 6c74c81859..3749640ee5 100644
--- a/src/runtime/os_linux_arm.go
+++ b/src/runtime/os_linux_arm.go
@@ -19,7 +19,6 @@ const (
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 a43e7c47b7..f94c183e87 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 83c4c06cf9..03032e8bea 100644
--- a/src/runtime/os_netbsd_arm.go
+++ b/src/runtime/os_netbsd_arm.go
@@ -16,7 +16,14 @@ func lwp_mcontext_init(mc *mcontextt, stk unsafe.Pointer, mp *m, gp *g, fn uintp
}
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 be3f330dfb..b46fef0090 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 c8158b9dec..a1662812de 100644
--- a/src/runtime/panic.go
+++ b/src/runtime/panic.go
@@ -327,7 +327,7 @@ func Goexit() {
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 23beaf537c..09cb775f0d 100644
--- a/src/runtime/proc1.go
+++ b/src/runtime/proc1.go
@@ -1348,7 +1348,23 @@ func execute(gp *g, inheritTime bool) {
// 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 a157f016d1..57cd869d88 100644
--- a/src/runtime/runtime2.go
+++ b/src/runtime/runtime2.go
@@ -645,6 +645,8 @@ var (
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 e6b015684b..d725bb11f5 100644
--- a/src/runtime/stubs.go
+++ b/src/runtime/stubs.go
@@ -128,7 +128,20 @@ func breakpoint()
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 0a446c8255..c7c30426ae 100644
--- a/src/sort/sort.go
+++ b/src/sort/sort.go
@@ -300,7 +300,7 @@ func StringsAreSorted(a []string) bool { return IsSorted(StringSlice(a)) }
// 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 0000000000..0b66c56a51
--- /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))
+}