Commit a30edb80 authored by Russ Cox's avatar Russ Cox

[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
parents 0d20a61e fa87cf83
......@@ -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>
......
......@@ -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>
......
......@@ -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>
......
......@@ -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>
......@@ -522,14 +523,6 @@ A new <code>-buildmode</code> build option
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,
......@@ -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.
......
......@@ -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>
......
......@@ -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)
......
......@@ -40,8 +40,6 @@ const (
NREGVAR = 32
)
var reg [x86.MAXREG]uint8
var regname = []string{
".AX",
".CX",
......
......@@ -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.
......
......@@ -39,8 +39,6 @@ const (
NREGVAR = 64 /* 32 general + 32 floating */
)
var reg [arm64.NREG + arm64.NFREG]uint8
var regname = []string{
".R0",
".R1",
......
......@@ -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
......
......@@ -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] {
......
......@@ -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)
}
......
......@@ -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
......
......@@ -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)
}
......
......@@ -37,8 +37,6 @@ const (
NREGVAR = 16 /* 8 integer + 8 floating */
)
var reg [x86.MAXREG]uint8
var regname = []string{
".ax",
".cx",
......
......@@ -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
......
......@@ -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
......
......@@ -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")
}
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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)
}
}
}
......@@ -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
......
......@@ -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
......
......@@ -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},
......
......@@ -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, " "))
......
......@@ -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")
}
......@@ -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 {
......
......@@ -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.
......
......@@ -63,8 +63,8 @@ var (
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}
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':
......
......@@ -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 */
......
......@@ -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)
......
......@@ -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)
}
}
......@@ -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
}
......
......@@ -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 {
......
......@@ -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"}
}
......
......@@ -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,
}
}
......@@ -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()
}
......@@ -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 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 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 goLookupPTR(addr)
}
......@@ -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
......
......@@ -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()
......
......@@ -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
......
// 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 }
......@@ -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
}
......@@ -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
......
......@@ -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
}
......
......@@ -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")
......
......@@ -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
......
......@@ -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
......
......@@ -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 {
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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.
......
......@@ -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()
}
......
......@@ -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.
......
......@@ -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
......
......@@ -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",
......
// 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))
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment