Compare commits

...

62 Commits

Author SHA1 Message Date
Andrew Gerrand
883bc6ed0e [release-branch.go1.4] go1.4.2
Change-Id: I0f198e4a94c50a11228c15d6aaac0cea890b5b58
Reviewed-on: https://go-review.googlesource.com/5111
Reviewed-by: Rob Pike <r@golang.org>
2015-02-18 04:24:51 +00:00
Andrew Gerrand
5e9b6cac52 [release-branch.go1.4] doc: document Go 1.4.2
Change-Id: Ia87047cbc720fb03d2f67aec48abe18bce8dbf78
Reviewed-on: https://go-review.googlesource.com/5112
Reviewed-by: Russ Cox <rsc@golang.org>
Reviewed-on: https://go-review.googlesource.com/5113
Reviewed-by: Andrew Gerrand <adg@golang.org>
2015-02-18 03:43:35 +00:00
Keith Randall
e4acac3dfb [release-branch.go1.4] runtime: don't fail if we find a pointer to an invalid span on 32 bit
The 32-bit heap may have holes in it.  Pointers to (non-heap) objects
in those holes shouldn't cause the GC to throw.

This change is somewhat of a band-aid fix for 1.4.2.  We should do
a more thorough fix for tip (keep track of the holes in the heap
with special MSpans, say).

Update #9872

Change-Id: Ife9ba27b77ae6ac5a6792d249c68893b3df62134
Reviewed-on: https://go-review.googlesource.com/4920
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
2015-02-17 23:37:56 +00:00
Ian Lance Taylor
3e5977f99d [release-branch.go1.4] cmd/gc: treat non-local vars inlined into wrapper as escaping
The compiler has a phase ordering problem.  Escape analysis runs
before wrapper generation.  When a generated wrapper calls a method
defined in a different package, if that call is inlined, there will be
no escape information for the variables defined in the inlined call.
Those variables will be placed on the stack, which fails if they
actually do escape.

There are probably various complex ways to fix this.  This is a simple
way to avoid it: when a generated wrapper calls a method defined in a
different package, treat all local variables as escaping.

Fixes #9537.

Change-Id: I530f39346de16ad173371c6c3f69cc189351a4e9
Reviewed-on: https://go-review.googlesource.com/3092
Reviewed-by: Russ Cox <rsc@golang.org>
(cherry picked from commit ec0ebc2281)
Reviewed-on: https://go-review.googlesource.com/5003
Run-TryBot: Andrew Gerrand <adg@golang.org>
Reviewed-by: Andrew Gerrand <adg@golang.org>
2015-02-17 23:36:32 +00:00
Shenghou Ma
02cf0526bf [release-branch.go1.4] cmd/gc: don't recurse infinitely when a recursive type references itself more than once
Fixes #9432

Change-Id: I08c92481afa7c7fac890aa780efc1cb2fabad528
Reviewed-on: https://go-review.googlesource.com/2115
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: Russ Cox <rsc@golang.org>
(cherry picked from commit fcff3ba740)
Reviewed-on: https://go-review.googlesource.com/5004
Run-TryBot: Andrew Gerrand <adg@golang.org>
Reviewed-by: Andrew Gerrand <adg@golang.org>
2015-02-17 23:36:26 +00:00
Shenghou Ma
3124622303 [release-branch.go1.4] runtime: don't panic when given a callback with no input params on windows
Fixes #9871 for Go 1.4.

Change-Id: I550a5bdb29e9a872652e0dd468a434227d7d9502
Reviewed-on: https://go-review.googlesource.com/4937
Run-TryBot: Minux Ma <minux@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Reviewed-by: Andrew Gerrand <adg@golang.org>
2015-02-17 06:51:18 +00:00
Chris Manghane
a255645770 [release-branch.go1.4] cmd/gc: don't unpack struct arguments to append
Fixes #9634.

Change-Id: I7b18f26c2fb812978fc7adc5bfd39ebfffe48701
Reviewed-on: https://go-review.googlesource.com/3080
Reviewed-by: Minux Ma <minux@golang.org>
(cherry picked from commit f5b8813e93)
Reviewed-on: https://go-review.googlesource.com/5000
Run-TryBot: Andrew Gerrand <adg@golang.org>
2015-02-17 06:49:27 +00:00
Keith Randall
2b7d0b4c0d [release-branch.go1.4] cmd/5g: make sure we normalize after unary ops on small types
We were failing ^uint16(0xffff) == 0, as we computed 0xffff0000 instead.

I could only trigger a failure for the above case, the other two tests
^uint16(0xfffe) == 1 and -uint16(0xffff) == 1 didn't seem to fail
previously.  Somehow they get MOVHUs inserted for other reasons (used
by CMP instead of TST?).  I fixed OMINUS anyway, better safe than
sorry.

Fixes #9604

Change-Id: I4c2d5bdc667742873ac029fdbe3db0cf12893c27
Reviewed-on: https://go-review.googlesource.com/2940
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Minux Ma <minux@golang.org>
(cherry picked from commit daa64ddfe6)
Reviewed-on: https://go-review.googlesource.com/5002
2015-02-17 06:48:55 +00:00
Keith Randall
5caa9d15f2 [release-branch.go1.4] math/big: bug in AndNot(x,y) for x>0,y<0.
The comment says to use (y-1), but then we did add(y.abs, natOne).  We meant sub.

Fixes #9609

Change-Id: I4fe4783326ca082c05588310a0af7895a48fc779
Reviewed-on: https://go-review.googlesource.com/2961
Reviewed-by: Robert Griesemer <gri@golang.org>
(cherry picked from commit c6ddca2aec)
Reviewed-on: https://go-review.googlesource.com/5001
2015-02-17 06:48:38 +00:00
Rob Pike
b64f8f8764 [release-branch.go1.4] cmd/go: handle \r in input text
Remove carriage returns from //go:generate lines.
Carriage returns are the predecessor of BOMs and still
live on Windows.

Fixes #9264

Change-Id: I637748c74335c696b3630f52f2100061153fcdb4
Reviewed-on: https://go-review.googlesource.com/1564
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Andrew Gerrand <adg@golang.org>
(cherry picked from commit fde3ab843f)
Reviewed-on: https://go-review.googlesource.com/4999
Reviewed-by: David Symonds <dsymonds@golang.org>
2015-02-17 06:48:22 +00:00
Rob Pike
15ce943f15 [release-branch.go1.4] cmd/go: document that -run isn't implemented
I am an idiot but the failure to implement this means we can decide
exactly what its design should be for 1.5

Change-Id: Ie2b025fcd899d306ddeddd09d1d0e8f9a99ab7a8
Reviewed-on: https://go-review.googlesource.com/4291
Reviewed-by: Minux Ma <minux@golang.org>
(cherry picked from commit 1e5d8bb544)
Reviewed-on: https://go-review.googlesource.com/4998
Reviewed-by: David Symonds <dsymonds@golang.org>
2015-02-17 06:46:10 +00:00
Andrew Gerrand
886b02d705 [release-branch.go1.4] go1.4.1
Change-Id: If275a5caa07cfd16b7052ad50709e1d0f1258223
Reviewed-on: https://go-review.googlesource.com/2856
Reviewed-by: Rob Pike <r@golang.org>
2015-01-15 21:04:23 +00:00
Andrew Gerrand
590548d7bd [release-branch.go1.4] doc: document Go 1.4.1
Change-Id: I4e9737497f4995657c46e52e0722d921499f8d17
Reviewed-on: https://go-review.googlesource.com/2854
Reviewed-by: Rob Pike <r@golang.org>
(cherry picked from commit 7785be8f22)
Reviewed-on: https://go-review.googlesource.com/2855
2015-01-15 04:50:52 +00:00
Andrew Gerrand
00d88f68bb [release-branch.go1.4] doc: update source install instruction to use tag 'go1.4.1'
Change-Id: I12e531fc0d92d3b6fc7ec2bbd8c029f63f55fbe1
Reviewed-on: https://go-review.googlesource.com/2798
Reviewed-by: Russ Cox <rsc@golang.org>
2015-01-15 03:55:30 +00:00
Mikio Hara
cece1bd03f [release-branch.go1.4] syscall: fix the deprecated way of parsing routing message on openbsd
OpenBSD 5.5 changed its kernel ABI and OpenBSD 5.6 enabled it.
This CL works on both 5.5 and 5.6.

Fixes #9102.

Change-Id: I4a295be9ab8acbc99e550d8cb7e8f8dacf3a03c5
Reviewed-on: https://go-review.googlesource.com/1932
Reviewed-by: Ian Lance Taylor <iant@golang.org>
(cherry picked from commit 13e16b39fc)
Reviewed-on: https://go-review.googlesource.com/2826
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2015-01-14 23:54:43 +00:00
Keith Randall
ac15ad8a38 [release-branch.go1.4] runtime: fix nacl build, hashmap overflow field offset was incorrect.
Change-Id: Ieb305b2a4d4ef28d70a8b8ece703f495c5af0529
Reviewed-on: https://go-review.googlesource.com/2051
Reviewed-by: Keith Randall <khr@golang.org>
(cherry picked from commit c6669e7af5)
Reviewed-on: https://go-review.googlesource.com/2820
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2015-01-14 20:44:03 +00:00
Russ Cox
7df87f5066 [release-branch.go1.4] cmd/go: adjust error for custom import checkout mismatch
Before:

	...
	imports golang.org/x/net/context: /Users/rsc/g/src/golang.org/x/net is from https://code.google.com/p/go.net, should be from https://go.googlesource.com/net

After:

	...
	imports golang.org/x/net/context: golang.org/x/net is a custom import path for https://go.googlesource.com/net, but /Users/rsc/g/src/golang.org/x/net is checked out from https://code.google.com/p/go.net

Change-Id: I93c35b85f955c7de684f71fbd4baecc717405318
Reviewed-on: https://go-review.googlesource.com/2808
Reviewed-by: Andrew Gerrand <adg@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
(cherry picked from commit b8d67596f6)
Reviewed-on: https://go-review.googlesource.com/2813
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2015-01-14 20:30:19 +00:00
Keith Randall
97b84fc4c8 [release-branch.go1.4] runtime: fix deadlock in runtime.Stack
It shouldn't semacquire() inside an acquirem(), the runtime
thinks that means deadlock.  It actually isn't a deadlock, but it
looks like it because acquirem() does m.locks++.

Candidate for inclusion in 1.4.1.  runtime.Stack with all=true
is pretty unuseable in GOMAXPROCS>1 environment.

fixes #9321

Change-Id: Iac6b664217d24763b9878c20e49229a1ecffc805
Reviewed-on: https://go-review.googlesource.com/1600
Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
(cherry picked from commit 50bc3d5bbc)
Reviewed-on: https://go-review.googlesource.com/2807
Reviewed-by: Andrew Gerrand <adg@golang.org>
2015-01-14 06:16:34 +00:00
Russ Cox
add1ee0ed5 [release-branch.go1.4] runtime: fix SIGPROF change
CL 2789 backported a change that required a barrage of followup CLs.
This CL backports all the followup CLs together.

There are manual edits to os_plan9.go and syscall_windows.go to take
the place of edits to defs_windows_{amd64,386}.go and os2_plan9.go
in the original. Those files do not exist in the release branch, but the
definition being added must go somewhere.

Original change descriptions below.

---

runtime/cgo: initialize our pthread_create wrapper earlier on openbsd

This is a genuine bug exposed by our test for issue 9456: our wrapper
for pthread_create is not initialized until we initialize cgo itself,
but it is possible that a static constructor could call pthread_create,
and in that case, it will be calling a nil function pointer.

Fix that by also initializing the sys_pthread_create function pointer
inside our pthread_create wrapper function, and use a pthread_once to
make sure it is only initialized once.

Fix build for openbsd.

Change-Id: Ica4da2c21fcaec186fdd3379128ef46f0e767ed7
Reviewed-on: https://go-review.googlesource.com/2232
Reviewed-by: David Crawshaw <crawshaw@golang.org>
(cherry picked from commit 77cd6197d7)

---

runtime: provide a dummy value of _SIGPROF on plan9 and windows

Fixes build on plan9 and windows.

Change-Id: Ic9b02c641ab84e4f6d8149de71b9eb495e3343b2
Reviewed-on: https://go-review.googlesource.com/2233
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
(cherry picked from commit 1f28238557)

---

runtime/cgo: remove unused variable

I missed this one in golang.org/cl/2232 and only tested the patch
on openbsd/amd64.

Change-Id: I4ff437ae0bfc61c989896c01904b6d33f9bdf0ec
Reviewed-on: https://go-review.googlesource.com/2234
Reviewed-by: Minux Ma <minux@golang.org>
(cherry picked from commit 0b2a74e89c)

---

runtime: skip TestCgoExternalThreadSIGPROF on OS X 10.6

The test program requires static constructor, which in turn needs
external linking to work, but external linking never works on 10.6.

This should fix the darwin-{386,amd64} builders.

Change-Id: I714fdd3e35f9a7e5f5659cf26367feec9412444f
Reviewed-on: https://go-review.googlesource.com/2235
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
(cherry picked from commit 2cbe27a272)

---

runtime: fix TestCgoExternalThreadSIGPROF again

Shell out to `uname -r` this time, so that the test will compile
even if the platform doesn't have syscall.Sysctl.

Change-Id: I3a19ab5d820bdb94586a97f4507b3837d7040525
Reviewed-on: https://go-review.googlesource.com/2271
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
(cherry picked from commit 865e5e98b6)

---

runtime: remove unnecessary GOOS switch

Change-Id: I8f518e273c02110042b08f7c50c3d38a648c8b6e
Reviewed-on: https://go-review.googlesource.com/2281
Reviewed-by: Minux Ma <minux@golang.org>
(cherry picked from commit 1ebfb082a7)

---

Change-Id: Ifee9667ca90eda2b074817c319b1b7c66d4f741d
Reviewed-on: https://go-review.googlesource.com/2805
Reviewed-by: Minux Ma <minux@golang.org>
Reviewed-by: Andrew Gerrand <adg@golang.org>
2015-01-14 06:14:09 +00:00
Russ Cox
d9e0ca4055 [release-branch.go1.4] all: copy master .gitattributes and .gitignore
Change-Id: I10e60fb6bf2cf3daa2bc1184df7ded0a712a1905
Reviewed-on: https://go-review.googlesource.com/2806
Reviewed-by: Andrew Gerrand <adg@golang.org>
2015-01-14 06:13:56 +00:00
Shenghou Ma
ff2ab29914 [release-branch.go1.4] cmd/ld: put .bss from external objects into real .bss section
Fixes #9359.

Change-Id: Iba62935b5a14de23d914f433a09a40417d7e88ed
Signed-off-by: Shenghou Ma <minux@golang.org>
Reviewed-on: https://go-review.googlesource.com/1889
Reviewed-by: Russ Cox <rsc@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
(cherry picked from commit 1c0c611fc2)
Reviewed-on: https://go-review.googlesource.com/2802
Reviewed-by: Andrew Gerrand <adg@golang.org>
2015-01-14 05:42:14 +00:00
Keith Randall
6609baf2f7 [release-branch.go1.4] runtime: hashmap: move overflow pointer to end of bucket
Pointers to zero-sized values may end up pointing to the next
object in memory, and possibly off the end of a span.  This
can cause memory leaks and/or confuse the garbage collector.

By putting the overflow pointer at the end of the bucket, we
make sure that pointers to any zero-sized keys or values don't
accidentally point to the next object in memory.

fixes #9384

Change-Id: I5d434df176984cb0210b4d0195dd106d6eb28f73
Reviewed-on: https://go-review.googlesource.com/1869
Reviewed-by: Russ Cox <rsc@golang.org>
(cherry picked from commit fbc56cf050)
Reviewed-on: https://go-review.googlesource.com/2801
Reviewed-by: Andrew Gerrand <adg@golang.org>
2015-01-14 05:42:05 +00:00
Keith Randall
957ed90d0e [release-branch.go1.4] reflect: add kindNoPointers if a function layout has no pointers.
malloc checks kindNoPointers and if it is not set and the object
is one pointer in size, it assumes it contains a pointer.  So we
must set kindNoPointers correctly; it isn't just a hint.

Fixes #9425

Change-Id: Ia43da23cc3298d6e3d6dbdf66d32e9678f0aedcf
Reviewed-on: https://go-review.googlesource.com/2055
Reviewed-by: Russ Cox <rsc@golang.org>
(cherry picked from commit d11f411181)
Reviewed-on: https://go-review.googlesource.com/2800
Reviewed-by: Andrew Gerrand <adg@golang.org>
2015-01-14 05:41:52 +00:00
Shenghou Ma
cc7bbb0ae9 [release-branch.go1.4] runtime: ignore SIGPROF to foreign threads before cgocallback is fully initialized
Some libraries, for example, OpenBLAS, create work threads in a global constructor.
If we're doing cpu profiling, it's possible that SIGPROF might come to some of the
worker threads before we make our first cgo call. Cgocallback used to terminate the
process when that happens, but it's better to miss a couple profiling signals than
to abort in this case.

Fixes #9456.

Change-Id: I112b8e1a6e10e6cc8ac695a4b518c0f577309b6b
Reviewed-on: https://go-review.googlesource.com/2141
Reviewed-by: Ian Lance Taylor <iant@golang.org>
(cherry picked from commit 5da9c8cd0a)
Reviewed-on: https://go-review.googlesource.com/2789
Reviewed-by: Andrew Gerrand <adg@golang.org>
2015-01-14 05:25:22 +00:00
Russ Cox
4482c7b1a1 [release-branch.go1.4] doc: copy contribute.html and install-source.html from master
This incorporates the various git-related updates that have
happened since the Go 1.4 release. Since Go 1.4.1 will be issued
from Git, it is appropriate to replace the Mercurial instructions
with Git instructions.

Change-Id: Idec041002c7f325c4eee6f25c50423b088b11468
Reviewed-on: https://go-review.googlesource.com/2788
Reviewed-by: Andrew Gerrand <adg@golang.org>
2015-01-14 05:25:09 +00:00
David Symonds
7cb53b8ca2 cmd/dist: convert dist from Hg to Git.
Change-Id: Ic25d46df6a79c4a18ed3f0a7e900591a115e48e3
Reviewed-on: https://go-review.googlesource.com/1403
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2014-12-12 04:05:44 +00:00
Andrew Gerrand
c303df658d go1.4
LGTM=bradfitz, minux, dsymonds
R=rsc, bradfitz, iant, dsymonds, minux
CC=golang-codereviews
https://golang.org/cl/188920043
2014-12-11 11:27:56 +11:00
Andrew Gerrand
75b53641f2 doc: tweak Go 1.4 release notes
LGTM=dave, dsymonds
R=golang-codereviews, dave, dsymonds
CC=golang-codereviews
https://golang.org/cl/184350043
2014-12-11 11:22:54 +11:00
Andrew Gerrand
7412503a43 doc: document go1.4
LGTM=bradfitz
R=rsc, bradfitz
CC=golang-codereviews
https://golang.org/cl/189810043
2014-12-11 09:16:41 +11:00
Andrew Gerrand
aec78b7a61 doc: remove TODO from go1.4 release notes
LGTM=bradfitz
R=iant, rsc, bradfitz
CC=golang-codereviews
https://golang.org/cl/191750043
2014-12-11 09:11:08 +11:00
Andrew Gerrand
031850b689 misc/makerelease: handle git sub-repositories
Also: checkout sub-repos from Mercurial manually
instead of using "go get". (for the 1.4 release)

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/190720043
2014-12-10 13:04:06 +11:00
Russ Cox
f9ae81edca [release-branch.go1.4] api: create go1.4.txt
I read through and vetted these but others should look too.

LGTM=bradfitz, adg
R=r, minux, bradfitz, adg
CC=adg, golang-codereviews, gri, iant
https://golang.org/cl/182560043
2014-12-10 11:07:40 +11:00
Andrew Gerrand
9820fbcf7b [release-branch.go1.4] [release-branch.go1.4] doc: scrub references to code.google.com
These are the references that affect current Go users.
I left intact references in older release notes;
we can figure out what to do with them later.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/186140043
2014-12-10 11:01:55 +11:00
Andrew Gerrand
d88fe6146d [release-branch.go1.4] [release-branch.go1.4] doc: update contribution guidelines
LGTM=minux, adg, rsc
R=rsc, r, dsymonds, minux, bradfitz, adg, dave, iant
CC=golang-codereviews
https://golang.org/cl/185190043
2014-12-10 09:29:35 +11:00
Andrew Gerrand
c089afbbd7 [release-branch.go1.4] [release-branch.go1.4] misc/cgo/test: skip test8694 on ARM.
««« CL 185130043 / 586738173884
misc/cgo/test: skip test8694 on ARM.

LGTM=dave, bradfitz, rsc
R=golang-codereviews, dave, bradfitz, rsc
CC=golang-codereviews
https://golang.org/cl/185130043

»»»

LGTM=minux
R=golang-codereviews, minux, bradfitz
CC=golang-codereviews
https://golang.org/cl/188870043
2014-12-10 09:13:58 +11:00
Russ Cox
05560adf62 [release-branch.go1.4] cmd/go: document import path checking
LGTM=adg
R=adg
CC=golang-codereviews
https://golang.org/cl/189760043
2014-12-08 22:25:51 -05:00
Russ Cox
c139772a39 [release-branch.go1.4] [release-branch.go1.4] encoding/xml: remove SyntaxError.Byte
««« CL 182580043 / 2d1ab17a670a
encoding/xml: remove SyntaxError.Byte

It is unused. It was introduced in the CL that added InputOffset.
I suspect it was an editing mistake.

LGTM=bradfitz
R=bradfitz
CC=golang-codereviews
https://golang.org/cl/182580043
»»»

TBR=bradfitz
CC=golang-codereviews
https://golang.org/cl/180630043
2014-12-05 22:19:13 -05:00
Russ Cox
c009bcdd8b [release-branch.go1.4] codereview: add release-branch.go1.4 prefix, like for dev branches
TBR=bradfitz
R=bradfitz
CC=golang-codereviews
https://golang.org/cl/178710043
2014-12-05 15:27:48 -05:00
Russ Cox
75c8a78e61 [release-branch.go1.4] cmd/api: make API check fail for undeclared API in release branch
We forgot to do the usual API review.
Make that not possible in the future.
I'll pull this change over to the main
branch too, but it's more important
(and only testable) here.

LGTM=bradfitz
R=bradfitz
CC=golang-codereviews
https://golang.org/cl/185050043
2014-12-05 14:04:17 -05:00
Russ Cox
f42f5263ad codereview: release-branch.go1.4 is now a work branch
(That is, changes can originate in the branch.
The main branch has diverged enough that this
may be necessary.)

LGTM=bradfitz
R=adg, bradfitz
CC=golang-codereviews
https://golang.org/cl/187810043
2014-12-05 14:02:51 -05:00
Russ Cox
59730b3343 [release-branch.go1.4] cmd/go: fix build
««« CL 182480043 / 8d42099cdc23
cmd/go: fix build
The new semantics of split require the newline be present.
The test was stale.

LGTM=adg
R=golang-codereviews, adg
CC=golang-codereviews
https://golang.org/cl/182480043
»»»

TBR=r
CC=golang-codereviews
https://golang.org/cl/178690043
2014-12-04 23:43:01 -05:00
Russ Cox
7aead4c6fd [release-branch.go1.4] cmd/go: avoid use of bufio.Scanner in generate
««« CL 182970043 / 573a7b5178c4
cmd/go: avoid use of bufio.Scanner in generate

Scanner can't handle stupid long lines and there are
reports of stupid long lines in production.

Note the issue isn't long "//go:generate" lines, but
any long line in any Go source file.

To be fair, if you're going to have a stupid long line
it's not a bad bet you'll want to run it through go
generate, because it's some embeddable asset that
has been machine generated. (One could ask why
that generation process didn't add a newline or two,
but we should cope anyway.)

Rewrite the file scanner in "go generate" so it can
handle arbitrarily long lines, and only stores in memory
those lines that start "//go:generate".

Also: Adjust the documentation to make clear that it
does not parse the file.

Fixes #9143.
Fixes #9196.

LGTM=rsc, dominik.honnef
R=rsc, cespare, minux, dominik.honnef
CC=golang-codereviews
https://golang.org/cl/182970043
»»»

TBR=r
CC=golang-codereviews
https://golang.org/cl/183060044
2014-12-04 23:42:16 -05:00
Russ Cox
19bbff8a32 [release-branch.go1.4] cmd/pprof/internal/commands: add command to open browser on windows
««« CL 180380043 / d56c648b069f
cmd/pprof/internal/commands: add command to open browser on windows

While we're at there, also add a message to prompt the user to install
Graphviz if "dot" command is not found.

Fixes #9178.

LGTM=adg, alex.brainman, cookieo9, rsc
R=rsc, adg, bradfitz, alex.brainman, cookieo9, smyrman
CC=golang-codereviews
https://golang.org/cl/180380043

»»»

TBR=minux
CC=golang-codereviews
https://golang.org/cl/186760043
2014-12-04 11:25:25 -05:00
Andrew Gerrand
c29baa647e [release-branch.go1.4] lib/time: update to ICANN time zone database 2014j
««« CL 178660043 / ac865d86fc2a
lib/time: update to ICANN time zone database 2014j

Fixes #9189.

LGTM=dsymonds
R=golang-codereviews, dsymonds
CC=golang-codereviews
https://golang.org/cl/178660043
»»»

LGTM=minux, dsymonds
R=dsymonds, r, minux
CC=golang-codereviews
https://golang.org/cl/182460043
2014-12-04 15:32:30 +11:00
Russ Cox
4d1f720b70 [release-branch.go1.4] cmd/pprof: fix symbol resolution for remote profiles
««« CL 183080043 / b663cc7e6c15
cmd/pprof: fix symbol resolution for remote profiles

Fixes #9199.

LGTM=iant
R=golang-codereviews, iant
CC=austin, golang-codereviews, minux
https://golang.org/cl/183080043
»»»

TBR=iant
CC=golang-codereviews
https://golang.org/cl/176680043
2014-12-03 14:14:50 -05:00
Andrew Gerrand
79a3df47aa [release-branch.go1.4] cmd/go: regenerate doc.go
««« CL 183000043 / 871468f5ceaf
cmd/go: regenerate doc.go

Move change from CL 170770043 to correct file and regenerate docs
for changes from CL 164120043.

LGTM=adg
R=golang-codereviews, adg, bradfitz
CC=golang-codereviews
https://golang.org/cl/183000043

»»»

LGTM=minux
R=bradfitz, minux
CC=golang-codereviews
https://golang.org/cl/181490043
2014-12-03 10:50:28 +11:00
Andrew Gerrand
3d34461177 go1.4rc2
LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/179700043
2014-12-02 13:43:43 +11:00
Russ Cox
28208eb8e3 [release-branch.go1.4] runtime: fix hang in GC due to shrinkstack vs netpoll race
««« CL 179680043 / 752cd9199639
runtime: fix hang in GC due to shrinkstack vs netpoll race

During garbage collection, after scanning a stack, we think about
shrinking it to reclaim some memory. The shrinking code (called
while the world is stopped) checked that the status was Gwaiting
or Grunnable and then changed the state to Gcopystack, to essentially
lock the stack so that no other GC thread is scanning it.
The same locking happens for stack growth (and is more necessary there).

        oldstatus = runtime·readgstatus(gp);
        oldstatus &= ~Gscan;
        if(oldstatus == Gwaiting || oldstatus == Grunnable)
                runtime·casgstatus(gp, oldstatus, Gcopystack); // oldstatus is Gwaiting or Grunnable
        else
                runtime·throw("copystack: bad status, not Gwaiting or Grunnable");

Unfortunately, "stop the world" doesn't stop everything. It stops all
normal goroutine execution, but the network polling thread is still
blocked in epoll and may wake up. If it does, and it chooses a goroutine
to mark runnable, and that goroutine is the one whose stack is shrinking,
then it can happen that between readgstatus and casgstatus, the status
changes from Gwaiting to Grunnable.

casgstatus assumes that if the status is not what is expected, it is a
transient change (like from Gwaiting to Gscanwaiting and back, or like
from Gwaiting to Gcopystack and back), and it loops until the status
has been restored to the expected value. In this case, the status has
changed semi-permanently from Gwaiting to Grunnable - it won't
change again until the GC is done and the world can continue, but the
GC is waiting for the status to change back. This wedges the program.

To fix, call a special variant of casgstatus that accepts either Gwaiting
or Grunnable as valid statuses.

Without the fix bug with the extra check+throw in casgstatus, the
program below dies in a few seconds (2-10) with GOMAXPROCS=8
on a 2012 Retina MacBook Pro. With the fix, it runs for minutes
and minutes.

package main

import (
        "io"
        "log"
        "net"
        "runtime"
)

func main() {
        const N = 100
        for i := 0; i < N; i++ {
                l, err := net.Listen("tcp", "127.0.0.1:0")
                if err != nil {
                        log.Fatal(err)
                }
                ch := make(chan net.Conn, 1)
                go func() {
                        var err error
                        c1, err := net.Dial("tcp", l.Addr().String())
                        if err != nil {
                                log.Fatal(err)
                        }
                        ch <- c1
                }()
                c2, err := l.Accept()
                if err != nil {
                        log.Fatal(err)
                }
                c1 := <-ch
                l.Close()
                go netguy(c1, c2)
                go netguy(c2, c1)
                c1.Write(make([]byte, 100))
        }
        for {
                runtime.GC()
        }
}

func netguy(r, w net.Conn) {
        buf := make([]byte, 100)
        for {
                bigstack(1000)
                _, err := io.ReadFull(r, buf)
                if err != nil {
                        log.Fatal(err)
                }
                w.Write(buf)
        }
}

var g int

func bigstack(n int) {
        var buf [100]byte
        if n > 0 {
                bigstack(n - 1)
        }
        g = int(buf[0]) + int(buf[99])
}

Fixes #9186.

LGTM=rlh
R=austin, rlh
CC=dvyukov, golang-codereviews, iant, khr, r
https://golang.org/cl/179680043
»»»

TBR=rlh
CC=golang-codereviews
https://golang.org/cl/184030043
2014-12-01 16:42:41 -05:00
Russ Cox
95e92ac420 [release-branch.go1.4] reflect: Fix reflect.funcLayout. The GC bitmap has two bits per
««« CL 182160043 / 321d04dea9d6
reflect: Fix reflect.funcLayout.  The GC bitmap has two bits per
pointer, not one.

Fixes #9179

LGTM=iant, rsc
R=golang-codereviews, iant, rsc
CC=golang-codereviews
https://golang.org/cl/182160043
»»»

TBR=khr
CC=golang-codereviews
https://golang.org/cl/180440044
2014-12-01 11:18:47 -05:00
Andrew Gerrand
783ad67982 [release-branch.go1.4] doc: tidy up "Projects" page; add Go 1.4
««« CL 182750043 / ffe33f1f1f17
doc: tidy up "Projects" page; add Go 1.4

LGTM=r
R=r
CC=golang-codereviews
https://golang.org/cl/182750043
»»»

TBR=r
CC=golang-codereviews
https://golang.org/cl/176350043
2014-11-26 07:57:03 +11:00
Russ Cox
d3ae115c41 [release-branch.go1.4] go/build: build $GOOS_test.go always
««« CL 176290043 / 8025b7d1e6c9
go/build: build $GOOS_test.go always

We decided to build $GOOS.go always
but forgot to test $GOOS_test.go.

Fixes #9159.

LGTM=r
R=r
CC=golang-codereviews
https://golang.org/cl/176290043
»»»

LGTM=r
R=r
CC=golang-codereviews
https://golang.org/cl/182740043
2014-11-24 22:00:01 -05:00
Russ Cox
738ccf32d9 [release-branch.go1.4] image/jpeg: handle Read returning n > 0, err != nil in d.fill
««« CL 178120043 / 95f5614b4648
image/jpeg: handle Read returning n > 0, err != nil in d.fill

Fixes #9127.

LGTM=r
R=bradfitz, r
CC=golang-codereviews, nigeltao
https://golang.org/cl/178120043
»»»

TBR=r
CC=golang-codereviews
https://golang.org/cl/181870043
2014-11-23 11:15:26 -05:00
Russ Cox
f6818121ed [release-branch.go1.4] cmd/go: fix running pprof on windows.
««« CL 176170043 / 61bbf19823d5
cmd/go: fix running pprof on windows.

Fixes #9149.

LGTM=alex.brainman, rsc
R=rsc, dave, alex.brainman
CC=golang-codereviews
https://golang.org/cl/176170043

»»»

TBR=minux
CC=golang-codereviews
https://golang.org/cl/175550043
2014-11-22 13:38:29 -05:00
Russ Cox
791fec05e4 [release-branch.go1.4] runtime: fix atomic operations on non-heap addresses
««« CL 179030043 / e4ab8f908aac
runtime: fix atomic operations on non-heap addresses
Race detector runtime does not tolerate operations on addresses
that was not previously declared with __tsan_map_shadow
(namely, data, bss and heap). The corresponding address
checks for atomic operations were removed in
https://golang.org/cl/111310044
Restore these checks.
It's tricker than just not calling into race runtime,
because it is the race runtime that makes the atomic
operations themselves (if we do not call into race runtime
we skip the atomic operation itself as well). So instead we call
__tsan_go_ignore_sync_start/end around the atomic operation.
This forces race runtime to skip all other processing
except than doing the atomic operation itself.
Fixes #9136.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/179030043

»»»

TBR=dvyukov
CC=golang-codereviews
https://golang.org/cl/180030043
2014-11-20 10:14:49 -05:00
Russ Cox
a791780bfd [release-branch.go1.4] build: disable race external linking test on OS X 10.6 and earlier
««« CL 176070043 / 500cb52e08e6
build: disable race external linking test on OS X 10.6 and earlier

External linking doesn't work there at all.

LGTM=bradfitz
R=adg, bradfitz
CC=golang-codereviews
https://golang.org/cl/176070043
»»»

LGTM=bradfitz, adg
R=adg, bradfitz
CC=golang-codereviews
https://golang.org/cl/175400043
2014-11-19 21:25:07 -05:00
Russ Cox
427ee80413 [release-branch.go1.4] runtime: remove assumption that noptrdata data bss noptrbss are ordered and contiguous
««« CL 179980043 / d71cc7e8a0e0
runtime: remove assumption that noptrdata data bss noptrbss are ordered and contiguous

The assumption can be violated by external linkers reordering them or
inserting non-Go sections in between them. I looked briefly at trying
to write out the _go_.o in external linking mode in a way that forced
the ordering, but no matter what there's no way to force Go's data
and Go's bss to be next to each other. If there is any data or bss from
non-Go objects, it's very likely to get stuck in between them.

Instead, rewrite the two places we know about that make the assumption.
I grepped for noptrdata to look for more and didn't find any.

The added race test (os/exec in external linking mode) fails without
the changes in the runtime. It crashes with an invalid pointer dereference.

Fixes #9133.

LGTM=dneil
R=dneil
CC=dvyukov, golang-codereviews, iant
https://golang.org/cl/179980043
»»»

LGTM=dneil
R=dneil
CC=golang-codereviews
https://golang.org/cl/173510043
2014-11-19 15:31:31 -05:00
Russ Cox
b4df0154c2 [release-branch.go1.4] undo CL 131750044 / 2d6d44ceb80e
««« CL 174450043 / 699cc091a16d
undo CL 131750044 / 2d6d44ceb80e

Breaks reading from stdin in parent after exec with SysProcAttr{Setpgid: true}.

package main

import (
        "fmt"
        "os"
        "os/exec"
        "syscall"
)

func main() {
        cmd := exec.Command("true")
        cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
        cmd.Run()

        fmt.Printf("Hit enter:")
        os.Stdin.Read(make([]byte, 100))
        fmt.Printf("Bye\n")
}

In go1.3, I type enter at the prompt and the program exits.
With the CL being rolled back, the program wedges at the
prompt.

««« original CL description
syscall: SysProcAttr job control changes

Making the child's process group the foreground process group and
placing the child in a specific process group involves co-ordination
between the parent and child that must be done post-fork but pre-exec.

LGTM=iant
R=golang-codereviews, gobot, iant, mikioh.mikioh
CC=golang-codereviews
https://golang.org/cl/131750044

»»»

LGTM=minux, dneil
R=dneil, minux
CC=golang-codereviews, iant, michael.p.macinnis
https://golang.org/cl/174450043
»»»

LGTM=minux
R=dneil, minux
CC=golang-codereviews
https://golang.org/cl/179970043
2014-11-19 14:38:22 -05:00
Andrew Gerrand
c9e183e781 [release-branch.go1.4] doc/go1.4.html: rewrite first sentence to make it clearer
««« CL 178910043 / 3916b070c5f3
doc/go1.4.html: rewrite first sentence to make it clearer
The grammar was atrocious, probably the victim of an editing error.

LGTM=bradfitz
R=bradfitz
CC=golang-codereviews
https://golang.org/cl/178910043
»»»

LGTM=r
R=r
CC=golang-codereviews
https://golang.org/cl/175310043
2014-11-19 09:47:56 +11:00
Andrew Gerrand
30ef146819 [release-branch.go1.4] remove cmd/link from nacl test zip
LGTM=dsymonds
R=rsc, dsymonds
CC=golang-codereviews
https://golang.org/cl/179830043
2014-11-17 13:55:59 +11:00
Andrew Gerrand
daf5d41471 [release-branch.go1.4] remove cmd/link
LGTM=dsymonds, minux
R=rsc, dsymonds, minux
CC=golang-codereviews
https://golang.org/cl/176910043
2014-11-17 13:46:45 +11:00
Andrew Gerrand
c1fc059b08 [release-branch.go1.4] debug/goobj: move to cmd/internal/goobj
««« CL 174250043 / c16349455e05
debug/goobj: move to cmd/internal/goobj

debug/goobj is not ready to be published but it is
needed for the various binary-reading commands.
Move to cmd/internal/goobj.

(The Go 1.3 release branch deleted it, but that's not
an option anymore due to the command dependencies.
The API is still not vetted nor terribly well designed.)

LGTM=adg, dsymonds
R=adg, dsymonds
CC=golang-codereviews
https://golang.org/cl/174250043
»»»

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/177890043
2014-11-17 12:56:35 +11:00
Andrew Gerrand
335ad3db99 go1.4rc1 2014-11-17 09:37:04 +11:00
123 changed files with 2210 additions and 6079 deletions

10
.gitattributes vendored Normal file
View File

@@ -0,0 +1,10 @@
# Treat all files in the Go repo as binary, with no git magic updating
# line endings. Windows users contributing to Go will need to use a
# modern version of git and editors capable of LF line endings.
#
# We'll prevent accidental CRLF line endings from entering the repo
# via the git-review gofmt checks.
#
# See golang.org/issue/9281
* -text

53
.gitignore vendored Normal file
View File

@@ -0,0 +1,53 @@
.DS_Store
*.[5689ao]
*.a[5689o]
*.so
*.pyc
._*
.nfs.*
[5689a].out
*~
*.orig
*.rej
*.exe
.*.swp
core
*.cgo*.go
*.cgo*.c
_cgo_*
_obj
_test
_testmain.go
build.out
test.out
doc/articles/wiki/*.bin
include/plan9/libc_plan9.h
misc/cgo/life/run.out
misc/cgo/stdio/run.out
misc/cgo/testso/main
misc/dashboard/builder/builder
src/cmd/?a/y.output
src/liblink/anames?.c
src/cmd/cc/y.output
src/cmd/cgo/zdefaultcc.go
src/cmd/dist/dist.dSYM
src/cmd/gc/mkbuiltin1
src/cmd/gc/opnames.h
src/cmd/gc/y.output
src/cmd/go/zdefaultcc.go
src/go/doc/headscan
src/runtime/mkversion
src/runtime/zaexperiment.h
src/runtime/zversion.go
src/unicode/maketables
src/*.*/
test/pass.out
test/run.out
test/times.out
test/garbage/*.out
goinstall.log
last-change
VERSION.cache
bin/
pkg/

1
VERSION Normal file
View File

@@ -0,0 +1 @@
go1.4.2

604
api/go1.4.txt Normal file
View File

@@ -0,0 +1,604 @@
# CL 134210043 archive/zip: add Writer.Flush, Brad Fitzpatrick <bradfitz@golang.org>
pkg archive/zip, method (*Writer) Flush() error
# CL 97140043 compress/flate: add Reset() to allow reusing large buffers to compress multiple buffers, James Robinson <jamesr@google.com>
pkg compress/flate, type Resetter interface { Reset }
pkg compress/flate, type Resetter interface, Reset(io.Reader, []uint8) error
pkg compress/zlib, type Resetter interface { Reset }
pkg compress/zlib, type Resetter interface, Reset(io.Reader, []uint8) error
# CL 159120044 compress/gzip: allow stopping at end of first stream, Russ Cox <rsc@golang.org>
pkg compress/gzip, method (*Reader) Multistream(bool)
# CL 138800043 crypto: Add SHA3 functions in go.crypto/sha3 to the Hash enum., David Leon Gil <coruus@gmail.com>
pkg crypto, const SHA3_224 = 10
pkg crypto, const SHA3_224 Hash
pkg crypto, const SHA3_256 = 11
pkg crypto, const SHA3_256 Hash
pkg crypto, const SHA3_384 = 12
pkg crypto, const SHA3_384 Hash
pkg crypto, const SHA3_512 = 13
pkg crypto, const SHA3_512 Hash
# CL 114680043 crypto: add Signer, Adam Langley <agl@golang.org>
pkg crypto, method (Hash) HashFunc() Hash
pkg crypto, type Signer interface { Public, Sign }
pkg crypto, type Signer interface, Public() PublicKey
pkg crypto, type Signer interface, Sign(io.Reader, []uint8, SignerOpts) ([]uint8, error)
pkg crypto, type SignerOpts interface { HashFunc }
pkg crypto, type SignerOpts interface, HashFunc() Hash
pkg crypto/ecdsa, method (*PrivateKey) Public() crypto.PublicKey
pkg crypto/ecdsa, method (*PrivateKey) Sign(io.Reader, []uint8, crypto.SignerOpts) ([]uint8, error)
pkg crypto/rsa, method (*PSSOptions) HashFunc() crypto.Hash
pkg crypto/rsa, method (*PrivateKey) Public() crypto.PublicKey
pkg crypto/rsa, method (*PrivateKey) Sign(io.Reader, []uint8, crypto.SignerOpts) ([]uint8, error)
pkg crypto/rsa, type PSSOptions struct, Hash crypto.Hash
# CL 157090043 crypto/tls: support TLS_FALLBACK_SCSV as a server., Adam Langley <agl@golang.org>
pkg crypto/tls, const TLS_FALLBACK_SCSV = 22016
pkg crypto/tls, const TLS_FALLBACK_SCSV uint16
# CL 107400043 crypto/tls: Added dynamic alternative to NameToCertificate map for SNI, Percy Wegmann <ox.to.a.cart@gmail.com>
pkg crypto/tls, type ClientHelloInfo struct
pkg crypto/tls, type ClientHelloInfo struct, CipherSuites []uint16
pkg crypto/tls, type ClientHelloInfo struct, ServerName string
pkg crypto/tls, type ClientHelloInfo struct, SupportedCurves []CurveID
pkg crypto/tls, type ClientHelloInfo struct, SupportedPoints []uint8
pkg crypto/tls, type Config struct, GetCertificate func(*ClientHelloInfo) (*Certificate, error)
pkg crypto/tls, type ConnectionState struct, TLSUnique []uint8
# CL 153420045 crypto/x509: continue to recognise MaxPathLen of zero as "no value"., Adam Langley <agl@golang.org>
pkg crypto/x509, type Certificate struct, MaxPathLenZero bool
# CL 158950043 database/sql: add Drivers, returning list of registered drivers, Russ Cox <rsc@golang.org>
pkg database/sql, func Drivers() []string
# CL 117280043 debug/dwarf: fix Reader panic on DW_TAG_unspecified_type, Derek Parker <parkerderek86@gmail.com>
pkg debug/dwarf, method (*UnspecifiedType) Basic() *BasicType
pkg debug/dwarf, method (*UnspecifiedType) Common() *CommonType
pkg debug/dwarf, method (*UnspecifiedType) Size() int64
pkg debug/dwarf, method (*UnspecifiedType) String() string
pkg debug/dwarf, type UnspecifiedType struct
pkg debug/dwarf, type UnspecifiedType struct, embedded BasicType
# CL 132000043 debug/elf: support arm64 relocations, Michael Hudson-Doyle <michael.hudson@linaro.org>
pkg debug/elf, const EM_AARCH64 = 183
pkg debug/elf, const EM_AARCH64 Machine
pkg debug/elf, const R_AARCH64_ABS16 = 259
pkg debug/elf, const R_AARCH64_ABS16 R_AARCH64
pkg debug/elf, const R_AARCH64_ABS32 = 258
pkg debug/elf, const R_AARCH64_ABS32 R_AARCH64
pkg debug/elf, const R_AARCH64_ABS64 = 257
pkg debug/elf, const R_AARCH64_ABS64 R_AARCH64
pkg debug/elf, const R_AARCH64_ADD_ABS_LO12_NC = 277
pkg debug/elf, const R_AARCH64_ADD_ABS_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_ADR_GOT_PAGE = 311
pkg debug/elf, const R_AARCH64_ADR_GOT_PAGE R_AARCH64
pkg debug/elf, const R_AARCH64_ADR_PREL_LO21 = 274
pkg debug/elf, const R_AARCH64_ADR_PREL_LO21 R_AARCH64
pkg debug/elf, const R_AARCH64_ADR_PREL_PG_HI21 = 275
pkg debug/elf, const R_AARCH64_ADR_PREL_PG_HI21 R_AARCH64
pkg debug/elf, const R_AARCH64_ADR_PREL_PG_HI21_NC = 276
pkg debug/elf, const R_AARCH64_ADR_PREL_PG_HI21_NC R_AARCH64
pkg debug/elf, const R_AARCH64_CALL26 = 283
pkg debug/elf, const R_AARCH64_CALL26 R_AARCH64
pkg debug/elf, const R_AARCH64_CONDBR19 = 280
pkg debug/elf, const R_AARCH64_CONDBR19 R_AARCH64
pkg debug/elf, const R_AARCH64_COPY = 1024
pkg debug/elf, const R_AARCH64_COPY R_AARCH64
pkg debug/elf, const R_AARCH64_GLOB_DAT = 1025
pkg debug/elf, const R_AARCH64_GLOB_DAT R_AARCH64
pkg debug/elf, const R_AARCH64_GOT_LD_PREL19 = 309
pkg debug/elf, const R_AARCH64_GOT_LD_PREL19 R_AARCH64
pkg debug/elf, const R_AARCH64_IRELATIVE = 1032
pkg debug/elf, const R_AARCH64_IRELATIVE R_AARCH64
pkg debug/elf, const R_AARCH64_JUMP26 = 282
pkg debug/elf, const R_AARCH64_JUMP26 R_AARCH64
pkg debug/elf, const R_AARCH64_JUMP_SLOT = 1026
pkg debug/elf, const R_AARCH64_JUMP_SLOT R_AARCH64
pkg debug/elf, const R_AARCH64_LD64_GOT_LO12_NC = 312
pkg debug/elf, const R_AARCH64_LD64_GOT_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_LDST128_ABS_LO12_NC = 299
pkg debug/elf, const R_AARCH64_LDST128_ABS_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_LDST16_ABS_LO12_NC = 284
pkg debug/elf, const R_AARCH64_LDST16_ABS_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_LDST32_ABS_LO12_NC = 285
pkg debug/elf, const R_AARCH64_LDST32_ABS_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_LDST64_ABS_LO12_NC = 286
pkg debug/elf, const R_AARCH64_LDST64_ABS_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_LDST8_ABS_LO12_NC = 278
pkg debug/elf, const R_AARCH64_LDST8_ABS_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_LD_PREL_LO19 = 273
pkg debug/elf, const R_AARCH64_LD_PREL_LO19 R_AARCH64
pkg debug/elf, const R_AARCH64_MOVW_SABS_G0 = 270
pkg debug/elf, const R_AARCH64_MOVW_SABS_G0 R_AARCH64
pkg debug/elf, const R_AARCH64_MOVW_SABS_G1 = 271
pkg debug/elf, const R_AARCH64_MOVW_SABS_G1 R_AARCH64
pkg debug/elf, const R_AARCH64_MOVW_SABS_G2 = 272
pkg debug/elf, const R_AARCH64_MOVW_SABS_G2 R_AARCH64
pkg debug/elf, const R_AARCH64_MOVW_UABS_G0 = 263
pkg debug/elf, const R_AARCH64_MOVW_UABS_G0 R_AARCH64
pkg debug/elf, const R_AARCH64_MOVW_UABS_G0_NC = 264
pkg debug/elf, const R_AARCH64_MOVW_UABS_G0_NC R_AARCH64
pkg debug/elf, const R_AARCH64_MOVW_UABS_G1 = 265
pkg debug/elf, const R_AARCH64_MOVW_UABS_G1 R_AARCH64
pkg debug/elf, const R_AARCH64_MOVW_UABS_G1_NC = 266
pkg debug/elf, const R_AARCH64_MOVW_UABS_G1_NC R_AARCH64
pkg debug/elf, const R_AARCH64_MOVW_UABS_G2 = 267
pkg debug/elf, const R_AARCH64_MOVW_UABS_G2 R_AARCH64
pkg debug/elf, const R_AARCH64_MOVW_UABS_G2_NC = 268
pkg debug/elf, const R_AARCH64_MOVW_UABS_G2_NC R_AARCH64
pkg debug/elf, const R_AARCH64_MOVW_UABS_G3 = 269
pkg debug/elf, const R_AARCH64_MOVW_UABS_G3 R_AARCH64
pkg debug/elf, const R_AARCH64_NONE = 0
pkg debug/elf, const R_AARCH64_NONE R_AARCH64
pkg debug/elf, const R_AARCH64_NULL = 256
pkg debug/elf, const R_AARCH64_NULL R_AARCH64
pkg debug/elf, const R_AARCH64_P32_ABS16 = 2
pkg debug/elf, const R_AARCH64_P32_ABS16 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_ABS32 = 1
pkg debug/elf, const R_AARCH64_P32_ABS32 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_ADD_ABS_LO12_NC = 12
pkg debug/elf, const R_AARCH64_P32_ADD_ABS_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_P32_ADR_GOT_PAGE = 26
pkg debug/elf, const R_AARCH64_P32_ADR_GOT_PAGE R_AARCH64
pkg debug/elf, const R_AARCH64_P32_ADR_PREL_LO21 = 10
pkg debug/elf, const R_AARCH64_P32_ADR_PREL_LO21 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_ADR_PREL_PG_HI21 = 11
pkg debug/elf, const R_AARCH64_P32_ADR_PREL_PG_HI21 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_CALL26 = 21
pkg debug/elf, const R_AARCH64_P32_CALL26 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_CONDBR19 = 19
pkg debug/elf, const R_AARCH64_P32_CONDBR19 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_COPY = 180
pkg debug/elf, const R_AARCH64_P32_COPY R_AARCH64
pkg debug/elf, const R_AARCH64_P32_GLOB_DAT = 181
pkg debug/elf, const R_AARCH64_P32_GLOB_DAT R_AARCH64
pkg debug/elf, const R_AARCH64_P32_GOT_LD_PREL19 = 25
pkg debug/elf, const R_AARCH64_P32_GOT_LD_PREL19 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_IRELATIVE = 188
pkg debug/elf, const R_AARCH64_P32_IRELATIVE R_AARCH64
pkg debug/elf, const R_AARCH64_P32_JUMP26 = 20
pkg debug/elf, const R_AARCH64_P32_JUMP26 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_JUMP_SLOT = 182
pkg debug/elf, const R_AARCH64_P32_JUMP_SLOT R_AARCH64
pkg debug/elf, const R_AARCH64_P32_LD32_GOT_LO12_NC = 27
pkg debug/elf, const R_AARCH64_P32_LD32_GOT_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_P32_LDST128_ABS_LO12_NC = 17
pkg debug/elf, const R_AARCH64_P32_LDST128_ABS_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_P32_LDST16_ABS_LO12_NC = 14
pkg debug/elf, const R_AARCH64_P32_LDST16_ABS_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_P32_LDST32_ABS_LO12_NC = 15
pkg debug/elf, const R_AARCH64_P32_LDST32_ABS_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_P32_LDST64_ABS_LO12_NC = 16
pkg debug/elf, const R_AARCH64_P32_LDST64_ABS_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_P32_LDST8_ABS_LO12_NC = 13
pkg debug/elf, const R_AARCH64_P32_LDST8_ABS_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_P32_LD_PREL_LO19 = 9
pkg debug/elf, const R_AARCH64_P32_LD_PREL_LO19 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_MOVW_SABS_G0 = 8
pkg debug/elf, const R_AARCH64_P32_MOVW_SABS_G0 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_MOVW_UABS_G0 = 5
pkg debug/elf, const R_AARCH64_P32_MOVW_UABS_G0 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_MOVW_UABS_G0_NC = 6
pkg debug/elf, const R_AARCH64_P32_MOVW_UABS_G0_NC R_AARCH64
pkg debug/elf, const R_AARCH64_P32_MOVW_UABS_G1 = 7
pkg debug/elf, const R_AARCH64_P32_MOVW_UABS_G1 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_PREL16 = 4
pkg debug/elf, const R_AARCH64_P32_PREL16 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_PREL32 = 3
pkg debug/elf, const R_AARCH64_P32_PREL32 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_RELATIVE = 183
pkg debug/elf, const R_AARCH64_P32_RELATIVE R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLSDESC = 187
pkg debug/elf, const R_AARCH64_P32_TLSDESC R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLSDESC_ADD_LO12_NC = 126
pkg debug/elf, const R_AARCH64_P32_TLSDESC_ADD_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLSDESC_ADR_PAGE21 = 124
pkg debug/elf, const R_AARCH64_P32_TLSDESC_ADR_PAGE21 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLSDESC_ADR_PREL21 = 123
pkg debug/elf, const R_AARCH64_P32_TLSDESC_ADR_PREL21 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLSDESC_CALL = 127
pkg debug/elf, const R_AARCH64_P32_TLSDESC_CALL R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLSDESC_LD32_LO12_NC = 125
pkg debug/elf, const R_AARCH64_P32_TLSDESC_LD32_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLSDESC_LD_PREL19 = 122
pkg debug/elf, const R_AARCH64_P32_TLSDESC_LD_PREL19 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLSGD_ADD_LO12_NC = 82
pkg debug/elf, const R_AARCH64_P32_TLSGD_ADD_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLSGD_ADR_PAGE21 = 81
pkg debug/elf, const R_AARCH64_P32_TLSGD_ADR_PAGE21 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLSIE_ADR_GOTTPREL_PAGE21 = 103
pkg debug/elf, const R_AARCH64_P32_TLSIE_ADR_GOTTPREL_PAGE21 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLSIE_LD32_GOTTPREL_LO12_NC = 104
pkg debug/elf, const R_AARCH64_P32_TLSIE_LD32_GOTTPREL_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLSIE_LD_GOTTPREL_PREL19 = 105
pkg debug/elf, const R_AARCH64_P32_TLSIE_LD_GOTTPREL_PREL19 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLSLE_ADD_TPREL_HI12 = 109
pkg debug/elf, const R_AARCH64_P32_TLSLE_ADD_TPREL_HI12 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLSLE_ADD_TPREL_LO12 = 110
pkg debug/elf, const R_AARCH64_P32_TLSLE_ADD_TPREL_LO12 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLSLE_ADD_TPREL_LO12_NC = 111
pkg debug/elf, const R_AARCH64_P32_TLSLE_ADD_TPREL_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLSLE_MOVW_TPREL_G0 = 107
pkg debug/elf, const R_AARCH64_P32_TLSLE_MOVW_TPREL_G0 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLSLE_MOVW_TPREL_G0_NC = 108
pkg debug/elf, const R_AARCH64_P32_TLSLE_MOVW_TPREL_G0_NC R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLSLE_MOVW_TPREL_G1 = 106
pkg debug/elf, const R_AARCH64_P32_TLSLE_MOVW_TPREL_G1 R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLS_DTPMOD = 184
pkg debug/elf, const R_AARCH64_P32_TLS_DTPMOD R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLS_DTPREL = 185
pkg debug/elf, const R_AARCH64_P32_TLS_DTPREL R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TLS_TPREL = 186
pkg debug/elf, const R_AARCH64_P32_TLS_TPREL R_AARCH64
pkg debug/elf, const R_AARCH64_P32_TSTBR14 = 18
pkg debug/elf, const R_AARCH64_P32_TSTBR14 R_AARCH64
pkg debug/elf, const R_AARCH64_PREL16 = 262
pkg debug/elf, const R_AARCH64_PREL16 R_AARCH64
pkg debug/elf, const R_AARCH64_PREL32 = 261
pkg debug/elf, const R_AARCH64_PREL32 R_AARCH64
pkg debug/elf, const R_AARCH64_PREL64 = 260
pkg debug/elf, const R_AARCH64_PREL64 R_AARCH64
pkg debug/elf, const R_AARCH64_RELATIVE = 1027
pkg debug/elf, const R_AARCH64_RELATIVE R_AARCH64
pkg debug/elf, const R_AARCH64_TLSDESC = 1031
pkg debug/elf, const R_AARCH64_TLSDESC R_AARCH64
pkg debug/elf, const R_AARCH64_TLSDESC_ADD = 568
pkg debug/elf, const R_AARCH64_TLSDESC_ADD R_AARCH64
pkg debug/elf, const R_AARCH64_TLSDESC_ADD_LO12_NC = 564
pkg debug/elf, const R_AARCH64_TLSDESC_ADD_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_TLSDESC_ADR_PAGE21 = 562
pkg debug/elf, const R_AARCH64_TLSDESC_ADR_PAGE21 R_AARCH64
pkg debug/elf, const R_AARCH64_TLSDESC_ADR_PREL21 = 561
pkg debug/elf, const R_AARCH64_TLSDESC_ADR_PREL21 R_AARCH64
pkg debug/elf, const R_AARCH64_TLSDESC_CALL = 569
pkg debug/elf, const R_AARCH64_TLSDESC_CALL R_AARCH64
pkg debug/elf, const R_AARCH64_TLSDESC_LD64_LO12_NC = 563
pkg debug/elf, const R_AARCH64_TLSDESC_LD64_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_TLSDESC_LDR = 567
pkg debug/elf, const R_AARCH64_TLSDESC_LDR R_AARCH64
pkg debug/elf, const R_AARCH64_TLSDESC_LD_PREL19 = 560
pkg debug/elf, const R_AARCH64_TLSDESC_LD_PREL19 R_AARCH64
pkg debug/elf, const R_AARCH64_TLSDESC_OFF_G0_NC = 566
pkg debug/elf, const R_AARCH64_TLSDESC_OFF_G0_NC R_AARCH64
pkg debug/elf, const R_AARCH64_TLSDESC_OFF_G1 = 565
pkg debug/elf, const R_AARCH64_TLSDESC_OFF_G1 R_AARCH64
pkg debug/elf, const R_AARCH64_TLSGD_ADD_LO12_NC = 514
pkg debug/elf, const R_AARCH64_TLSGD_ADD_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_TLSGD_ADR_PAGE21 = 513
pkg debug/elf, const R_AARCH64_TLSGD_ADR_PAGE21 R_AARCH64
pkg debug/elf, const R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 541
pkg debug/elf, const R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 R_AARCH64
pkg debug/elf, const R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 542
pkg debug/elf, const R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 = 543
pkg debug/elf, const R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 R_AARCH64
pkg debug/elf, const R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC = 540
pkg debug/elf, const R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC R_AARCH64
pkg debug/elf, const R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 = 539
pkg debug/elf, const R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 R_AARCH64
pkg debug/elf, const R_AARCH64_TLSLE_ADD_TPREL_HI12 = 549
pkg debug/elf, const R_AARCH64_TLSLE_ADD_TPREL_HI12 R_AARCH64
pkg debug/elf, const R_AARCH64_TLSLE_ADD_TPREL_LO12 = 550
pkg debug/elf, const R_AARCH64_TLSLE_ADD_TPREL_LO12 R_AARCH64
pkg debug/elf, const R_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 551
pkg debug/elf, const R_AARCH64_TLSLE_ADD_TPREL_LO12_NC R_AARCH64
pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G0 = 547
pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G0 R_AARCH64
pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G0_NC = 548
pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G0_NC R_AARCH64
pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G1 = 545
pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G1 R_AARCH64
pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G1_NC = 546
pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G1_NC R_AARCH64
pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G2 = 544
pkg debug/elf, const R_AARCH64_TLSLE_MOVW_TPREL_G2 R_AARCH64
pkg debug/elf, const R_AARCH64_TLS_DTPMOD64 = 1028
pkg debug/elf, const R_AARCH64_TLS_DTPMOD64 R_AARCH64
pkg debug/elf, const R_AARCH64_TLS_DTPREL64 = 1029
pkg debug/elf, const R_AARCH64_TLS_DTPREL64 R_AARCH64
pkg debug/elf, const R_AARCH64_TLS_TPREL64 = 1030
pkg debug/elf, const R_AARCH64_TLS_TPREL64 R_AARCH64
pkg debug/elf, const R_AARCH64_TSTBR14 = 279
pkg debug/elf, const R_AARCH64_TSTBR14 R_AARCH64
pkg debug/elf, method (R_AARCH64) GoString() string
pkg debug/elf, method (R_AARCH64) String() string
pkg debug/elf, type R_AARCH64 int
# CL 107530043 debug/elf: add (*File).DynamicSymbols, ErrNoSymbols, and tests for (*File).Symbols and (*File).DynamicSymbols, and formalize symbol order., Pietro Gagliardi <pietro10@mac.com>
pkg debug/elf, method (*File) DynamicSymbols() ([]Symbol, error)
pkg debug/elf, var ErrNoSymbols error
# CL 106460044 debug/plan9obj, cmd/addr2line: on Plan 9 use a.out header, Aram Hăvărneanu <aram@mgk.ro>
pkg debug/plan9obj, type FileHeader struct, HdrSize uint64
pkg debug/plan9obj, type FileHeader struct, LoadAddress uint64
# CL 122960043 encoding/xml: add InputOffset method to Decoder, Russ Cox <rsc@golang.org>
pkg encoding/xml, method (*Decoder) InputOffset() int64
# CL 124940043 cmd/go, go/build: implement import comment checking, Russ Cox <rsc@golang.org>
pkg go/build, const ImportComment = 4
pkg go/build, const ImportComment ImportMode
pkg go/build, type Package struct, ImportComment string
# CL 155050043 go/build: Return MultiplePackageError on importing a dir containing multiple packages, Jens Frederich <jfrederich@gmail.com>
pkg go/build, method (*MultiplePackageError) Error() string
pkg go/build, type MultiplePackageError struct
pkg go/build, type MultiplePackageError struct, Dir string
pkg go/build, type MultiplePackageError struct, Files []string
pkg go/build, type MultiplePackageError struct, Packages []string
# CL 135110044 go/token: implement PositionFor accessors, Robert Griesemer <gri@golang.org>
pkg go/token, method (*File) PositionFor(Pos, bool) Position
pkg go/token, method (*FileSet) PositionFor(Pos, bool) Position
# CL 109000049 image: add RGBAAt, Gray16At, etc., ChaiShushan <chaishushan@gmail.com>
pkg image, method (*Alpha) AlphaAt(int, int) color.Alpha
pkg image, method (*Alpha16) Alpha16At(int, int) color.Alpha16
pkg image, method (*Gray) GrayAt(int, int) color.Gray
pkg image, method (*Gray16) Gray16At(int, int) color.Gray16
pkg image, method (*NRGBA) NRGBAAt(int, int) color.NRGBA
pkg image, method (*NRGBA64) NRGBA64At(int, int) color.NRGBA64
pkg image, method (*RGBA) RGBAAt(int, int) color.RGBA
pkg image, method (*RGBA64) RGBA64At(int, int) color.RGBA64
pkg image, method (*YCbCr) YCbCrAt(int, int) color.YCbCr
# CL 129190043 png: make the encoder configurable, Jeff R. Allen <jra@nella.org>
pkg image/png, const BestCompression = -3
pkg image/png, const BestCompression CompressionLevel
pkg image/png, const BestSpeed = -2
pkg image/png, const BestSpeed CompressionLevel
pkg image/png, const DefaultCompression = 0
pkg image/png, const DefaultCompression CompressionLevel
pkg image/png, const NoCompression = -1
pkg image/png, const NoCompression CompressionLevel
pkg image/png, method (*Encoder) Encode(io.Writer, image.Image) error
pkg image/png, type CompressionLevel int
pkg image/png, type Encoder struct
pkg image/png, type Encoder struct, CompressionLevel CompressionLevel
# CL 101750048 math: implement Nextafter32, Robert Griesemer <gri@golang.org>
pkg math, func Nextafter32(float32, float32) float32
# CL 93550043 math/big: implement Rat.Float32, Robert Griesemer <gri@golang.org>
pkg math/big, method (*Rat) Float32() (float32, bool)
# CL 76540043 net/http: add BasicAuth method to *http.Request, Kelsey Hightower <kelsey.hightower@gmail.com>
pkg net/http, method (*Request) BasicAuth() (string, string, bool)
# CL 137940043 net/http: add Transport.DialTLS hook, Brad Fitzpatrick <bradfitz@golang.org>
pkg net/http, type Transport struct, DialTLS func(string, string) (net.Conn, error)
# CL 132750043 net/http/httputil: Pass a Logger to ReverseProxy, allowing the user to control logging., Mark Theunissen <mark.theunissen@gmail.com>
pkg net/http/httputil, type ReverseProxy struct, ErrorLog *log.Logger
# CL 148370043 os, syscall: add Unsetenv, Brad Fitzpatrick <bradfitz@golang.org>
pkg os, func Unsetenv(string) error
pkg syscall, func Unsetenv(string) error
# CL 144020043 reflect: add Type.Comparable, Russ Cox <rsc@golang.org>
pkg reflect, type Type interface, Comparable() bool
# CL 153670043 runtime: add PauseEnd array to MemStats and GCStats, Jens Frederich <jfrederich@gmail.com>
pkg runtime, type MemStats struct, PauseEnd [256]uint64
pkg runtime/debug, type GCStats struct, PauseEnd []time.Time
# CL 136710045 sync/atomic: add Value, Dmitriy Vyukov <dvyukov@google.com>
pkg sync/atomic, method (*Value) Load() interface{}
pkg sync/atomic, method (*Value) Store(interface{})
pkg sync/atomic, type Value struct
# CL 126190043 syscall: support UID/GID map files for Linux user namespaces, Mrunal Patel <mrunalp@gmail.com>
pkg syscall (linux-386), type SysProcAttr struct, GidMappings []SysProcIDMap
pkg syscall (linux-386), type SysProcAttr struct, UidMappings []SysProcIDMap
pkg syscall (linux-386), type SysProcIDMap struct
pkg syscall (linux-386), type SysProcIDMap struct, ContainerID int
pkg syscall (linux-386), type SysProcIDMap struct, HostID int
pkg syscall (linux-386), type SysProcIDMap struct, Size int
pkg syscall (linux-386-cgo), type SysProcAttr struct, GidMappings []SysProcIDMap
pkg syscall (linux-386-cgo), type SysProcAttr struct, UidMappings []SysProcIDMap
pkg syscall (linux-386-cgo), type SysProcIDMap struct
pkg syscall (linux-386-cgo), type SysProcIDMap struct, ContainerID int
pkg syscall (linux-386-cgo), type SysProcIDMap struct, HostID int
pkg syscall (linux-386-cgo), type SysProcIDMap struct, Size int
pkg syscall (linux-amd64), type SysProcAttr struct, GidMappings []SysProcIDMap
pkg syscall (linux-amd64), type SysProcAttr struct, UidMappings []SysProcIDMap
pkg syscall (linux-amd64), type SysProcIDMap struct
pkg syscall (linux-amd64), type SysProcIDMap struct, ContainerID int
pkg syscall (linux-amd64), type SysProcIDMap struct, HostID int
pkg syscall (linux-amd64), type SysProcIDMap struct, Size int
pkg syscall (linux-amd64-cgo), type SysProcAttr struct, GidMappings []SysProcIDMap
pkg syscall (linux-amd64-cgo), type SysProcAttr struct, UidMappings []SysProcIDMap
pkg syscall (linux-amd64-cgo), type SysProcIDMap struct
pkg syscall (linux-amd64-cgo), type SysProcIDMap struct, ContainerID int
pkg syscall (linux-amd64-cgo), type SysProcIDMap struct, HostID int
pkg syscall (linux-amd64-cgo), type SysProcIDMap struct, Size int
pkg syscall (linux-arm), type SysProcAttr struct, GidMappings []SysProcIDMap
pkg syscall (linux-arm), type SysProcAttr struct, UidMappings []SysProcIDMap
pkg syscall (linux-arm), type SysProcIDMap struct
pkg syscall (linux-arm), type SysProcIDMap struct, ContainerID int
pkg syscall (linux-arm), type SysProcIDMap struct, HostID int
pkg syscall (linux-arm), type SysProcIDMap struct, Size int
pkg syscall (linux-arm-cgo), type SysProcAttr struct, GidMappings []SysProcIDMap
pkg syscall (linux-arm-cgo), type SysProcAttr struct, UidMappings []SysProcIDMap
pkg syscall (linux-arm-cgo), type SysProcIDMap struct
pkg syscall (linux-arm-cgo), type SysProcIDMap struct, ContainerID int
pkg syscall (linux-arm-cgo), type SysProcIDMap struct, HostID int
pkg syscall (linux-arm-cgo), type SysProcIDMap struct, Size int
# CL 122200043 net: fix CNAME resolving on Windows, Egon Elbre <egonelbre@gmail.com>
pkg syscall (windows-386), const DNS_INFO_NO_RECORDS = 9501
pkg syscall (windows-386), const DNS_INFO_NO_RECORDS ideal-int
pkg syscall (windows-386), const DnsSectionAdditional = 3
pkg syscall (windows-386), const DnsSectionAdditional ideal-int
pkg syscall (windows-386), const DnsSectionAnswer = 1
pkg syscall (windows-386), const DnsSectionAnswer ideal-int
pkg syscall (windows-386), const DnsSectionAuthority = 2
pkg syscall (windows-386), const DnsSectionAuthority ideal-int
pkg syscall (windows-386), const DnsSectionQuestion = 0
pkg syscall (windows-386), const DnsSectionQuestion ideal-int
pkg syscall (windows-386), func DnsNameCompare(*uint16, *uint16) bool
pkg syscall (windows-amd64), const DNS_INFO_NO_RECORDS = 9501
pkg syscall (windows-amd64), const DNS_INFO_NO_RECORDS ideal-int
pkg syscall (windows-amd64), const DnsSectionAdditional = 3
pkg syscall (windows-amd64), const DnsSectionAdditional ideal-int
pkg syscall (windows-amd64), const DnsSectionAnswer = 1
pkg syscall (windows-amd64), const DnsSectionAnswer ideal-int
pkg syscall (windows-amd64), const DnsSectionAuthority = 2
pkg syscall (windows-amd64), const DnsSectionAuthority ideal-int
pkg syscall (windows-amd64), const DnsSectionQuestion = 0
pkg syscall (windows-amd64), const DnsSectionQuestion ideal-int
pkg syscall (windows-amd64), func DnsNameCompare(*uint16, *uint16) bool
# CL 86160044 os: Implement symlink support for Windows, Michael Fraenkel <michael.fraenkel@gmail.com>
pkg syscall (windows-386), const ERROR_PRIVILEGE_NOT_HELD = 1314
pkg syscall (windows-386), const ERROR_PRIVILEGE_NOT_HELD Errno
pkg syscall (windows-amd64), const ERROR_PRIVILEGE_NOT_HELD = 1314
pkg syscall (windows-amd64), const ERROR_PRIVILEGE_NOT_HELD Errno
# CL 86160044 os: Implement symlink support for Windows, Michael Fraenkel <michael.fraenkel@gmail.com>
pkg syscall (windows-386), const FILE_ATTRIBUTE_REPARSE_POINT = 1024
pkg syscall (windows-386), const FILE_ATTRIBUTE_REPARSE_POINT ideal-int
pkg syscall (windows-386), const FILE_FLAG_OPEN_REPARSE_POINT = 2097152
pkg syscall (windows-386), const FILE_FLAG_OPEN_REPARSE_POINT ideal-int
pkg syscall (windows-386), const FSCTL_GET_REPARSE_POINT = 589992
pkg syscall (windows-386), const FSCTL_GET_REPARSE_POINT ideal-int
pkg syscall (windows-386), const IO_REPARSE_TAG_SYMLINK = 2684354572
pkg syscall (windows-386), const IO_REPARSE_TAG_SYMLINK ideal-int
pkg syscall (windows-386), const MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16384
pkg syscall (windows-386), const MAXIMUM_REPARSE_DATA_BUFFER_SIZE ideal-int
pkg syscall (windows-386), const SYMBOLIC_LINK_FLAG_DIRECTORY = 1
pkg syscall (windows-386), const SYMBOLIC_LINK_FLAG_DIRECTORY ideal-int
pkg syscall (windows-386), func CreateHardLink(*uint16, *uint16, uintptr) error
pkg syscall (windows-386), func CreateSymbolicLink(*uint16, *uint16, uint32) error
pkg syscall (windows-386), func DeviceIoControl(Handle, uint32, *uint8, uint32, *uint8, uint32, *uint32, *Overlapped) error
pkg syscall (windows-386), func LoadCreateSymbolicLink() error
pkg syscall (windows-amd64), const FILE_ATTRIBUTE_REPARSE_POINT = 1024
pkg syscall (windows-amd64), const FILE_ATTRIBUTE_REPARSE_POINT ideal-int
pkg syscall (windows-amd64), const FILE_FLAG_OPEN_REPARSE_POINT = 2097152
pkg syscall (windows-amd64), const FILE_FLAG_OPEN_REPARSE_POINT ideal-int
pkg syscall (windows-amd64), const FSCTL_GET_REPARSE_POINT = 589992
pkg syscall (windows-amd64), const FSCTL_GET_REPARSE_POINT ideal-int
pkg syscall (windows-amd64), const IO_REPARSE_TAG_SYMLINK = 2684354572
pkg syscall (windows-amd64), const IO_REPARSE_TAG_SYMLINK ideal-int
pkg syscall (windows-amd64), const MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16384
pkg syscall (windows-amd64), const MAXIMUM_REPARSE_DATA_BUFFER_SIZE ideal-int
pkg syscall (windows-amd64), const SYMBOLIC_LINK_FLAG_DIRECTORY = 1
pkg syscall (windows-amd64), const SYMBOLIC_LINK_FLAG_DIRECTORY ideal-int
pkg syscall (windows-amd64), func CreateHardLink(*uint16, *uint16, uintptr) error
pkg syscall (windows-amd64), func CreateSymbolicLink(*uint16, *uint16, uint32) error
pkg syscall (windows-amd64), func DeviceIoControl(Handle, uint32, *uint8, uint32, *uint8, uint32, *uint32, *Overlapped) error
pkg syscall (windows-amd64), func LoadCreateSymbolicLink() error
# CL 149510043 net: disable SIO_UDP_CONNRESET behavior on windows., Ron Hashimoto <mail@h2so5.net>
pkg syscall (windows-386), const SIO_UDP_CONNRESET = 2550136844
pkg syscall (windows-386), const SIO_UDP_CONNRESET ideal-int
pkg syscall (windows-amd64), const SIO_UDP_CONNRESET = 2550136844
pkg syscall (windows-amd64), const SIO_UDP_CONNRESET ideal-int
# CL 102320044 syscall: implement syscall.Getppid() on Windows, Alan Shreve <alan@inconshreveable.com>
pkg syscall (windows-386), const TH32CS_INHERIT = 2147483648
pkg syscall (windows-386), const TH32CS_INHERIT ideal-int
pkg syscall (windows-386), const TH32CS_SNAPALL = 15
pkg syscall (windows-386), const TH32CS_SNAPALL ideal-int
pkg syscall (windows-386), const TH32CS_SNAPHEAPLIST = 1
pkg syscall (windows-386), const TH32CS_SNAPHEAPLIST ideal-int
pkg syscall (windows-386), const TH32CS_SNAPMODULE = 8
pkg syscall (windows-386), const TH32CS_SNAPMODULE ideal-int
pkg syscall (windows-386), const TH32CS_SNAPMODULE32 = 16
pkg syscall (windows-386), const TH32CS_SNAPMODULE32 ideal-int
pkg syscall (windows-386), const TH32CS_SNAPPROCESS = 2
pkg syscall (windows-386), const TH32CS_SNAPPROCESS ideal-int
pkg syscall (windows-386), const TH32CS_SNAPTHREAD = 4
pkg syscall (windows-386), const TH32CS_SNAPTHREAD ideal-int
pkg syscall (windows-386), func CreateToolhelp32Snapshot(uint32, uint32) (Handle, error)
pkg syscall (windows-386), func Process32First(Handle, *ProcessEntry32) error
pkg syscall (windows-386), func Process32Next(Handle, *ProcessEntry32) error
pkg syscall (windows-386), type ProcessEntry32 struct
pkg syscall (windows-386), type ProcessEntry32 struct, DefaultHeapID uintptr
pkg syscall (windows-386), type ProcessEntry32 struct, ExeFile [260]uint16
pkg syscall (windows-386), type ProcessEntry32 struct, Flags uint32
pkg syscall (windows-386), type ProcessEntry32 struct, ModuleID uint32
pkg syscall (windows-386), type ProcessEntry32 struct, ParentProcessID uint32
pkg syscall (windows-386), type ProcessEntry32 struct, PriClassBase int32
pkg syscall (windows-386), type ProcessEntry32 struct, ProcessID uint32
pkg syscall (windows-386), type ProcessEntry32 struct, Size uint32
pkg syscall (windows-386), type ProcessEntry32 struct, Threads uint32
pkg syscall (windows-386), type ProcessEntry32 struct, Usage uint32
pkg syscall (windows-amd64), const TH32CS_INHERIT = 2147483648
pkg syscall (windows-amd64), const TH32CS_INHERIT ideal-int
pkg syscall (windows-amd64), const TH32CS_SNAPALL = 15
pkg syscall (windows-amd64), const TH32CS_SNAPALL ideal-int
pkg syscall (windows-amd64), const TH32CS_SNAPHEAPLIST = 1
pkg syscall (windows-amd64), const TH32CS_SNAPHEAPLIST ideal-int
pkg syscall (windows-amd64), const TH32CS_SNAPMODULE = 8
pkg syscall (windows-amd64), const TH32CS_SNAPMODULE ideal-int
pkg syscall (windows-amd64), const TH32CS_SNAPMODULE32 = 16
pkg syscall (windows-amd64), const TH32CS_SNAPMODULE32 ideal-int
pkg syscall (windows-amd64), const TH32CS_SNAPPROCESS = 2
pkg syscall (windows-amd64), const TH32CS_SNAPPROCESS ideal-int
pkg syscall (windows-amd64), const TH32CS_SNAPTHREAD = 4
pkg syscall (windows-amd64), const TH32CS_SNAPTHREAD ideal-int
pkg syscall (windows-amd64), func CreateToolhelp32Snapshot(uint32, uint32) (Handle, error)
pkg syscall (windows-amd64), func Process32First(Handle, *ProcessEntry32) error
pkg syscall (windows-amd64), func Process32Next(Handle, *ProcessEntry32) error
pkg syscall (windows-amd64), type ProcessEntry32 struct
pkg syscall (windows-amd64), type ProcessEntry32 struct, DefaultHeapID uintptr
pkg syscall (windows-amd64), type ProcessEntry32 struct, ExeFile [260]uint16
pkg syscall (windows-amd64), type ProcessEntry32 struct, Flags uint32
pkg syscall (windows-amd64), type ProcessEntry32 struct, ModuleID uint32
pkg syscall (windows-amd64), type ProcessEntry32 struct, ParentProcessID uint32
pkg syscall (windows-amd64), type ProcessEntry32 struct, PriClassBase int32
pkg syscall (windows-amd64), type ProcessEntry32 struct, ProcessID uint32
pkg syscall (windows-amd64), type ProcessEntry32 struct, Size uint32
pkg syscall (windows-amd64), type ProcessEntry32 struct, Threads uint32
pkg syscall (windows-amd64), type ProcessEntry32 struct, Usage uint32
# CL 127740043 os: make SameFile handle paths like c:a.txt properly, Alex Brainman <alex.brainman@gmail.com>
pkg syscall (windows-386), func FullPath(string) (string, error)
pkg syscall (windows-amd64), func FullPath(string) (string, error)
# CL 98150043 testing: add Coverage function, Russ Cox <rsc@golang.org>
pkg testing, func Coverage() float64
# CL 148770043 cmd/go, testing: add TestMain support, Russ Cox <rsc@golang.org>
pkg testing, func MainStart(func(string, string) (bool, error), []InternalTest, []InternalBenchmark, []InternalExample) *M
pkg testing, method (*M) Run() int
pkg testing, type M struct
# CL 108030044 text/scanner: provide facility for custom identifiers, Robert Griesemer <gri@golang.org>
pkg text/scanner, type Scanner struct, IsIdentRune func(int32, int) bool
# CL 130620043 text/template: add back pointer to Nodes for better error generation, Rob Pike <r@golang.org>
pkg text/template/parse, type DotNode struct, embedded NodeType
pkg text/template/parse, type NilNode struct, embedded NodeType
pkg text/template/parse, method (*BranchNode) Copy() Node
pkg text/template/parse, method (*IdentifierNode) SetTree(*Tree) *IdentifierNode
pkg html/template, type Error struct, Node parse.Node
# CL 127470043 unicode: strconv: regexp: Upgrade to Unicode 7.0.0., Marcel van Lohuizen <mpvl@golang.org>
pkg unicode, const Version = "7.0.0"
pkg unicode, var Bassa_Vah *RangeTable
pkg unicode, var Caucasian_Albanian *RangeTable
pkg unicode, var Duployan *RangeTable
pkg unicode, var Elbasan *RangeTable
pkg unicode, var Grantha *RangeTable
pkg unicode, var Khojki *RangeTable
pkg unicode, var Khudawadi *RangeTable
pkg unicode, var Linear_A *RangeTable
pkg unicode, var Mahajani *RangeTable
pkg unicode, var Manichaean *RangeTable
pkg unicode, var Mende_Kikakui *RangeTable
pkg unicode, var Modi *RangeTable
pkg unicode, var Mro *RangeTable
pkg unicode, var Nabataean *RangeTable
pkg unicode, var Old_North_Arabian *RangeTable
pkg unicode, var Old_Permic *RangeTable
pkg unicode, var Pahawh_Hmong *RangeTable
pkg unicode, var Palmyrene *RangeTable
pkg unicode, var Pau_Cin_Hau *RangeTable
pkg unicode, var Psalter_Pahlavi *RangeTable
pkg unicode, var Siddham *RangeTable
pkg unicode, var Tirhuta *RangeTable
pkg unicode, var Warang_Citi *RangeTable

View File

@@ -578,7 +578,7 @@ import "github.com/golang/example/stringutil"
<p>
This convention is the easiest way to make your Go packages available for
others to use.
The <a href="//code.google.com/p/go-wiki/wiki/Projects">Go Wiki</a>
The <a href="//golang.org/wiki/Projects">Go Wiki</a>
and <a href="//godoc.org/">godoc.org</a>
provide lists of external Go projects.
</p>
@@ -627,5 +627,5 @@ The official mailing list for discussion of the Go language is
<p>
Report bugs using the
<a href="//code.google.com/p/go/issues/list">Go issue tracker</a>.
<a href="//golang.org/issue">Go issue tracker</a>.
</p>

View File

@@ -30,21 +30,16 @@ We encourage all Go users to subscribe to
<h2 id="go1">Version history</h2>
<h3 id="release"><a href="/doc/devel/release.html">Release History</a></h3>
<p>A summary of the changes between Go releases.</p>
<h4 id="go1notes"><a href="/doc/go1">Go 1 Release Notes</a></h4>
<p>
A guide for updating your code to work with Go 1.
</p>
<p>A <a href="/doc/devel/release.html">summary</a> of the changes between Go releases. Notes for the major releases:</p>
<h4 id="release notes"><a href="/doc/go1.1">Go 1.1 Release Notes</a></h4>
<p>
A list of significant changes in Go 1.1, with instructions for updating
your code where necessary.
Each point release includes a similar document appropriate for that
release: <a href="/doc/go1.2">Go 1.2</a>, <a href="/doc/go1.3">Go 1.3</a>,
and so on.
</p>
<ul>
<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>
<li><a href="/doc/go1.1">Go 1.1</a> <small>(May 2013)</small></li>
<li><a href="/doc/go1">Go 1</a> <small>(March 2012)</small></li>
</ul>
<h3 id="go1compat"><a href="/doc/go1compat">Go 1 and the Future of Go Programs</a></h3>
<p>
@@ -55,7 +50,7 @@ Go 1 matures.
<h2 id="resources">Developer Resources</h2>
<h3 id="source"><a href="https://code.google.com/p/go/source">Source Code</a></h3>
<h3 id="source"><a href="https://golang.org/change">Source Code</a></h3>
<p>Check out the Go source code.</p>
<h3 id="golang-dev"><a href="https://groups.google.com/group/golang-dev">Developer</a> and
@@ -81,13 +76,13 @@ systems and architectures.</p>
<h2 id="howto">How you can help</h2>
<h3><a href="https://code.google.com/p/go/issues">Reporting issues</a></h3>
<h3><a href="//golang.org/issue">Reporting issues</a></h3>
<p>
If you spot bugs, mistakes, or inconsistencies in the Go project's code or
documentation, please let us know by
<a href="https://code.google.com/p/go/issues/entry">filing a ticket</a>
on our <a href="https://code.google.com/p/go/issues">issue tracker</a>.
<a href="//golang.org/issue/new">filing a ticket</a>
on our <a href="//golang.org/issue">issue tracker</a>.
(Of course, you should check it's not an existing issue before creating
a new one.)
</p>
@@ -106,8 +101,8 @@ To get started, read these <a href="/doc/contribute.html">contribution
guidelines</a> for information on design, testing, and our code review process.
</p>
<p>
Check <a href="https://code.google.com/p/go/issues">the tracker</a> for
Check <a href="//golang.org/issue">the tracker</a> for
open issues that interest you. Those labeled
<a href="https://code.google.com/p/go/issues/list?q=status=HelpWanted">HelpWanted</a>
<a href="https://github.com/golang/go/issues?q=is%3Aopen+is%3Aissue+label%3Ahelpwanted">helpwanted</a>
are particularly in need of outside help.
</p>

View File

@@ -6,9 +6,12 @@
<p>
This document explains how to contribute changes to the Go project.
It assumes you have installed Go using the
It assumes you have followed the
<a href="/doc/install/source">installation instructions</a> and
have <a href="code.html">written and tested your code</a>.
</p>
<p>
(Note that the <code>gccgo</code> frontend lives elsewhere;
see <a href="gccgo_contribute.html">Contributing to gccgo</a>.)
</p>
@@ -54,7 +57,8 @@ $ ./all.bash
</p>
<p>
After running for a while, the command should print "<code>ALL TESTS PASSED</code>".
After running for a while, the command should print
"<code>ALL</code> <code>TESTS</code> <code>PASSED</code>".
</p>
<h2 id="Code_review">Code review</h2>
@@ -64,208 +68,230 @@ Changes to Go must be reviewed before they are submitted,
no matter who makes the change.
(In exceptional cases, such as fixing a build, the review can
follow shortly after submitting.)
A Mercurial extension helps manage the code review process.
The extension is included in the Go source tree but needs
to be added to your Mercurial configuration.
A custom git command called <code>git-codereview</code>,
discussed below, helps manage the code review process through a Google-hosted
<a href="https://go-review.googlesource.com/">instance</a> of the code review
system called <a href="https://code.google.com/p/gerrit/">Gerrit</a>.
</p>
<h3>Caveat for Mercurial aficionados</h3>
<h3>Set up authentication for code review</h3>
<p>
<i>Using Mercurial with the code review extension is not the same
as using standard Mercurial.</i>
</p>
<p>
The Go repository is maintained as a single line of reviewed changes;
we prefer to avoid the complexity of Mercurial's arbitrary change graph.
The code review extension helps here: its <code>hg submit</code> command
automatically checks for and warns about the local repository
being out of date compared to the remote one.
The <code>hg submit</code> command also verifies other
properties about the Go repository.
For example,
it checks that Go code being checked in is formatted in the standard style,
as defined by <a href="/cmd/gofmt">gofmt</a>,
and it checks that the author of the code is properly recorded for
<a href="#copyright">copyright purposes</a>.
</p>
<p>
To help ensure changes are only created by <code>hg submit</code>,
the code review extension disables the standard <code>hg commit</code>
command.
</p>
<h3>Configure the extension</h3>
<p>Edit <code>.hg/hgrc</code> in the root of your Go checkout to add:</p>
<pre>
[extensions]
codereview = /path/to/go/lib/codereview/codereview.py
[ui]
username = Your Name &lt;you@server.dom&gt;
</pre>
<p>
The <code>username</code> information will not be used unless
you are a committer (see below), but Mercurial complains if it is missing.
</p>
<p>
As the codereview extension is only enabled for your Go checkout, the remainder of this document assumes you
are inside the go directory when issuing commands.
</p>
<p>To contribute to subrepositories, edit the <code>.hg/hgrc</code> for each
subrepository in the same way. For example, add the codereview extension to
<code>golang.org/x/tools/.hg/hgrc</code>.
</p>
<h3>Understanding the extension</h3>
<p>After adding the code review extension, you can run</p>
<pre>
$ hg help codereview
</pre>
<p>to learn more about its commands. To learn about a specific code-review-specific
command such as <code>change</code>, run</p>
<pre>
$ hg help change
</pre>
<p>
Windows users may need to perform extra steps to get the code review
extension working. See the
<a href="https://code.google.com/p/go-wiki/wiki/CodeReview">CodeReview page</a>
on the <a href="https://code.google.com/p/go-wiki/wiki">Go Wiki</a> for details.
</p>
<h3>Log in to the code review site.</h3>
<p>
The code review server uses a Google Account to authenticate.
The Git code hosting server and Gerrit code review server both use a Google
Account to authenticate. You therefore need a Google Account to proceed.
(If you can use the account to
<a href="https://www.google.com/accounts/Login?hl=en&amp;continue=http://www.google.com/">sign in at google.com</a>,
<a href="https://www.google.com/accounts/Login">sign in at google.com</a>,
you can use it to sign in to the code review server.)
The email address you use on the Code Review site
will be recorded in the <a href="https://code.google.com/p/go/source/list">Mercurial change log</a>
The email address you use with the code review system
will be recorded in the <a href="https://go.googlesource.com/go">change log</a>
and in the <a href="/CONTRIBUTORS"><code>CONTRIBUTORS</code></a> file.
You can <a href="https://www.google.com/accounts/NewAccount">create a Google Account</a>
associated with any address where you receive email.
If you've enabled the two-step verification feature, don't forget to generate an
application-specific password and use that when prompted for a password.
</p>
<p>
Visit the site <a href="https://go.googlesource.com">go.googlesource.com</a>
and log in using your Google Account.
Click on the "Generate Password" link that appears at the top of the page.
</p>
<p>
Click the radio button that says "Only <code>go.googlesource.com</code>"
to use this authentication token only for the Go project.
</p>
<p>
Further down the page is a box containing commands to install
the authentication cookie in file called <code>.gitcookies</code> in your home
directory.
Copy the text for the commands into a Unix shell window to execute it.
That will install the authentication token.
</p>
<p>
(If you are on a Windows computer, you should instead follow the instructions
in the yellow box to run the command.)
</p>
<h3>Register with Gerrit</h3>
<p>
Now that you have a Google account and the authentication token,
you need to register your account with Gerrit, the code review system.
To do this, visit <a href="https://golang.org/cl">golang.org/cl</a>
and log in using the same Google Account you used above.
That is all that is required.
</p>
<h3>Install the git-codereview command</h3>
<p>
Now install the <code>git-codereview</code> command by running,
</p>
<pre>
$ hg code-login
Email (login for uploading to codereview.appspot.com): rsc@golang.org
Password for rsc@golang.org:
Saving authentication cookies to /Users/rsc/.codereview_upload_cookies_codereview.appspot.com
go get -u golang.org/x/review/git-codereview
</pre>
<h3>Configure your account settings.</h3>
<p>Edit your <a href="https://codereview.appspot.com/settings">code review settings</a>.
Grab a nickname.
Many people prefer to set the Context option to
&ldquo;Whole file&rdquo; to see more context when reviewing changes.
<p>
Make sure <code>git-codereview</code> is installed in your shell path, so that the
<code>git</code> command can find it. Check that
</p>
<p>Once you have chosen a nickname in the settings page, others
can use that nickname as a shorthand for naming reviewers and the CC list.
For example, <code>rsc</code> is an alias for <code>rsc@golang.org</code>.
<pre>
$ git codereview help
</pre>
<p>
prints help text, not an error.
</p>
<h3>Switch to the default branch</h3>
<p>
Note to Git aficionados: The <code>git-codereview</code> command is not required to
upload and manage Gerrit code reviews. For those who prefer plain Git, the text
below gives the Git equivalent of each git-codereview command. If you do use plain
Git, note that you still need the commit hooks that the git-codereview command
configures; those hooks add a Gerrit <code>Change-Id</code> line to the commit
message and check that all Go source files have been formatted with gofmt. Even
if you intend to use plain Git for daily work, install the hooks in a new Git
checkout by running <code>git-codereview</code> <code>hooks</code>.
</p>
<h3>Set up git aliases</h3>
<p>
The <code>git-codereview</code> command can be run directly from the shell
by typing, for instance,
</p>
<pre>
$ git codereview sync
</pre>
<p>
but it is more convenient to set up aliases for <code>git-codereview</code>'s own
subcommands, so that the above becomes,
</p>
<pre>
$ git sync
</pre>
<p>
The <code>git-codereview</code> subcommands have been chosen to be distinct from
Git's own, so it's safe to do so.
</p>
<p>
The aliases are optional, but in the rest of this document we will assume
they are installed.
To install them, copy this text into your Git configuration file
(usually <code>.gitconfig</code> in your home directory):
</p>
<pre>
[alias]
change = codereview change
gofmt = codereview gofmt
mail = codereview mail
pending = codereview pending
submit = codereview submit
sync = codereview sync
</pre>
<h3>Understanding the git-codereview command</h3>
<p>After installing the <code>git-codereview</code> command, you can run</p>
<pre>
$ git codereview help
</pre>
<p>
to learn more about its commands.
You can also read the <a href="https://godoc.org/golang.org/x/review/git-codereview">command documentation</a>.
</p>
<h3>Switch to the master branch</h3>
<p>
Most Go installations use a release branch, but new changes should
only be made to the default branch. (They may be applied later to a release
branch as part of the release process.)
Before making a change, make sure you use the default branch:
only be made based on the master branch.
(They may be applied later to a release branch as part of the release process,
but most contributors won't do this themselves.)
Before making a change, make sure you start on the master branch:
</p>
<pre>
$ hg update default
$ git checkout master
$ git sync
</pre>
<p>
(In Git terms, <code>git</code> <code>sync</code> runs
<code>git</code> <code>pull</code> <code>-r</code>.)
</p>
<h3>Make a change</h3>
<p>
The entire checked-out tree is writable.
If you need to edit files, just edit them: Mercurial will figure out which ones changed.
You do need to inform Mercurial of added, removed, copied, or renamed files,
by running
<code>hg add</code>,
<code>hg rm</code>,
<code>hg cp</code>,
or
<code>hg mv</code>.
Once you have edited files, you must tell Git that they have been modified.
You must also tell Git about any files that are added, removed, or renamed files.
These operations are done with the usual Git commands,
<code>git</code> <code>add</code>,
<code>git</code> <code>rm</code>,
and
<code>git</code> <code>mv</code>.
</p>
<p>When you are ready to send a change out for review, run</p>
<p>
If you wish to checkpoint your work, or are ready to send the code out for review, run</p>
<pre>
$ hg change
$ git change <i>&lt;branch&gt;</i>
</pre>
<p>from any directory in your Go repository.
Mercurial will open a change description file in your editor.
(It uses the editor named by the <code>$EDITOR</code> environment variable, <code>vi</code> by default.)
<p>
from any directory in your Go repository to commit the changes so far.
The name <i>&lt;branch&gt;</i> is an arbitrary one you choose to identify the
local branch containing your changes.
</p>
<p>
(In Git terms, <code>git</code> <code>change</code> <code>&lt;branch&gt;</code>
runs <code>git</code> <code>checkout</code> <code>-b</code> <code>branch</code>,
then <code>git</code> <code>branch</code> <code>--set-upstream-to</code> <code>origin/master</code>,
then <code>git</code> <code>commit</code>.)
</p>
<p>
Git will open a change description file in your editor.
(It uses the editor named by the <code>$EDITOR</code> environment variable,
<code>vi</code> by default.)
The file will look like:
</p>
<pre>
# Change list.
# Lines beginning with # are ignored.
# Multi-line values should be indented.
Reviewer:
CC:
Description:
&lt;enter description here&gt;
Files:
src/math/sin.go
src/math/tan.go
src/regexp/regexp.go
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch foo
# Changes not staged for commit:
# modified: editedfile.go
#
</pre>
<p>
The <code>Reviewer</code> line lists the reviewers assigned
to this change, and the <code>CC</code> line lists people to
notify about the change.
These can be code review nicknames or arbitrary email addresses.
Unless explicitly told otherwise, such as in the discussion leading
up to sending in the change list, leave the reviewer field blank.
This means that the
<a href="https://groups.google.com/group/golang-codereviews">golang-codereviews@googlegroups.com</a>
mailing list will be used as the reviewer.
</p>
<p>
Replace &ldquo;<code>&lt;enter description here&gt;</code>&rdquo;
with a description of your change.
At the beginning of this file is a blank line; replace it
with a thorough description of your change.
The first line of the change description is conventionally a one-line
summary of the change, prefixed by the primary affected package,
and is used as the subject for code review mail; the rest of the
description elaborates.
</p>
<p>
The <code>Files</code> section lists all the modified files
in your client.
It is best to keep unrelated changes in different change lists.
In this example, we can include just the changes to package <code>math</code>
by deleting the line mentioning <code>regexp.go</code>.
and is used as the subject for code review mail.
The rest of the
description elaborates and should provide context for the
change and explain what it does.
If there is a helpful reference, mention it here.
</p>
<p>
@@ -273,343 +299,314 @@ After editing, the template might now read:
</p>
<pre>
# Change list.
# Lines beginning with # are ignored.
# Multi-line values should be indented.
math: improved Sin, Cos and Tan precision for very large arguments
Reviewer: golang-codereviews@googlegroups.com
CC: math-nuts@swtch.com
The existing implementation has poor numerical properties for
large arguments, so use the McGillicutty algorithm to improve
accuracy above 1e10.
Description:
math: improved Sin, Cos and Tan precision for very large arguments.
The algorithm is described at http://wikipedia.org/wiki/McGillicutty_Algorithm
See Bimmler and Shaney, ``Extreme sinusoids,'' J. Math 3(14).
Fixes issue 159.
Fixes #159
Files:
src/math/sin.go
src/math/tan.go
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch foo
# Changes not staged for commit:
# modified: editedfile.go
#
</pre>
<p>
The special sentence &ldquo;Fixes issue 159.&rdquo; associates
the change with issue 159 in the <a href="https://code.google.com/p/go/issues/list">Go issue tracker</a>.
When this change is eventually submitted, the issue
tracker will automatically mark the issue as fixed.
(These conventions are described in detail by the
<a href="https://code.google.com/p/support/wiki/IssueTracker#Integration_with_version_control">Google Project Hosting Issue Tracker documentation</a>.)
The commented section of the file lists all the modified files in your client.
It is best to keep unrelated changes in different change lists,
so if you see a file listed that should not be included, abort
the command and move that file to a different branch.
</p>
<p>
Save the file and exit the editor.</p>
The special notation "Fixes #159" associates the change with issue 159 in the
<a href="https://golang.org/issue/159">Go issue tracker</a>.
When this change is eventually submitted, the issue
tracker will automatically mark the issue as fixed.
(There are several such conventions, described in detail in the
<a href="https://help.github.com/articles/closing-issues-via-commit-messages/">GitHub Issue Tracker documentation</a>.)
</p>
<p>
The code review server assigns your change an issue number and URL,
which <code>hg change</code> will print, something like:
Once you have finished writing the commit message,
save the file and exit the editor.
</p>
<p>
If you wish to do more editing, re-stage your changes using
<code>git</code> <code>add</code>, and then run
</p>
<pre>
CL created: https://codereview.appspot.com/99999
$ git change
</pre>
<p>
to update the change description and incorporate the staged changes. The
change description contains a <code>Change-Id</code> line near the bottom,
added by a Git commit hook during the initial
<code>git</code> <code>change</code>.
That line is used by Gerrit to match successive uploads of the same change.
Do not edit or delete it.
</p>
<p>
(In Git terms, <code>git</code> <code>change</code> with no branch name
runs <code>git</code> <code>commit</code> <code>--amend</code>.)
</p>
<h3>Mail the change for review</h3>
<p>
Creating or uploading the change uploads a copy of the diff to the code review server,
but it does not notify anyone about it. To do that, you need to run <code>hg mail</code>
(see below).
</p>
<p>To send out a change for review, run <code>hg mail</code> using the change list number
assigned during <code>hg change</code>:</p>
<pre>
$ hg mail 99999
</pre>
<p>You can add to the <code>Reviewer:</code> and <code>CC:</code> lines
using the <code>-r</code> or <code>--cc</code> options.
In the above example, we could have left the <code>Reviewer</code> and <code>CC</code>
lines blank and then run:
Once the change is ready, mail it out for review:
</p>
<pre>
$ hg mail -r golang-codereviews@googlegroups.com --cc math-nuts@swtch.com 99999
$ git mail
</pre>
<p>to achieve the same effect.</p>
<p>
You can specify a reviewer or CC interested parties
using the <code>-r</code> or <code>-cc</code> options.
Both accept a comma-separated list of email addresses:
</p>
<p>Note that <code>-r</code> and <code>--cc</code> cannot be spelled <code>--r</code> or <code>-cc</code>.</p>
<pre>
$ git mail -r joe@golang.org -cc mabel@example.com,math-nuts@swtch.com
</pre>
<p>
Unless explicitly told otherwise, such as in the discussion leading
up to sending in the change list, it's better not to specify a reviewer.
All changes are automatically CC'ed to the
<a href="https://groups.google.com/group/golang-codereviews">golang-codereviews@googlegroups.com</a>
mailing list.
</p>
<p>
(In Git terms, <code>git</code> <code>mail</code> pushes the local committed
changes to Gerrit using <code>git</code> <code>push</code> <code>origin</code>
<code>HEAD:refs/for/master</code>.)
</p>
<p>
If your change relates to an open issue, please add a comment to the issue
announcing your proposed fix, including a link to your CL.
</p>
<p>
The code review server assigns your change an issue number and URL,
which <code>git</code> <code>mail</code> will print, something like:
</p>
<pre>
remote: New Changes:
remote: https://go-review.googlesource.com/99999 math: improved Sin, Cos and Tan precision for very large arguments
</pre>
<h3>Reviewing code</h3>
<p>
Running <code>hg mail</code> will send an email to you and the reviewers
asking them to visit the issue's URL and make comments on the change.
When done, the reviewer clicks &ldquo;Publish and Mail comments&rdquo;
to send comments back.
Running <code>git</code> <code>mail</code> will send an email to you and the
reviewers asking them to visit the issue's URL and make comments on the change.
When done, the reviewer adds comments through the Gerrit user interface
and clicks "Reply" to send comments back.
You will receive a mail notification when this happens.
You must reply through the web interface.
(Unlike with the old Rietveld review system, replying by mail has no effect.)
</p>
<h3>Revise and upload</h3>
<p>
You must respond to review comments through the web interface.
(Unlike with the old Rietveld review system, responding by mail has no effect.)
</p>
<p>
When you have revised the code and are ready for another round of review,
you can upload your change and send mail asking the reviewers to
please take another look (<code>PTAL</code>). Use the change list number
assigned during <code>hg change</code>
</p>
<pre>
$ hg mail 99999
</pre>
<p>
Or to upload your change without sending a notification, run
</p>
<pre>
$ hg upload 99999
</pre>
<p>
You will probably revise your code in response to the reviewer comments.
You might also visit the code review web page and reply to the comments,
letting the reviewer know that you've addressed them or explain why you
haven't. When you're done replying, click &ldquo;Publish and Mail comments&rdquo;
to send the line-by-line replies and any other comments.
stage those changes and use <code>git</code> <code>change</code> to update the
commit.
To send the update change list for another round of review,
run <code>git</code> <code>mail</code> again.
</p>
<p>
The reviewer can comment on the new copy, and the process repeats.
The reviewer approves the change by replying with a mail that says
<code>LGTM</code>: looks good to me.
The reviewer approves the change by giving it a positive score
(+1 or +2) and replying <code>LGTM</code>: looks good to me.
</p>
<p>
You can see a list of your pending changes by running <code>hg pending</code> (<code>hg p</code> for short).
</p>
<h3>Adding or removing files from an existing change</h3>
<p>
If you need to re-edit the change description, or change the files included in the CL,
run <code>hg change 99999</code>.
</p>
<p>
Alternatively, you can use
</p>
<pre>
$ hg file 99999 somefile
</pre>
<p>
to add <code>somefile</code> to CL 99999, and
</p>
<pre>
$ hg file -d 99999 somefile
</pre>
<p>
to remove <code>somefile</code> from the CL.
</p>
<p>
A file may only belong to a single active CL at a time. <code>hg file</code>
will issue a warning if a file is moved between changes.
You can see a list of your pending changes by running <code>git</code>
<code>pending</code>, and switch between change branches with <code>git</code>
<code>change</code> <code><i>&lt;branch&gt;</i></code>.
</p>
<h3>Synchronize your client</h3>
<p>While you were working, others might have submitted changes
to the repository. To update your client, run</p>
<p>
While you were working, others might have submitted changes to the repository.
To update your local branch, run
</p>
<pre>
$ hg sync
$ git sync
</pre>
<p>(For Mercurial fans, <code>hg sync</code> runs <code>hg pull -u</code>
but then also synchronizes the local change list state against the new data.)</p>
<p>
If files you were editing have changed, Mercurial does its best to merge the
remote changes into your local changes. It may leave some files to merge by hand.
(In git terms, <code>git</code> <code>sync</code> runs
<code>git</code> <code>pull</code> <code>-r</code>.)
</p>
<p>
For example, suppose you have edited <code>flag_test.go</code> but
If files you were editing have changed, Git does its best to merge the
remote changes into your local changes.
It may leave some files to merge by hand.
</p>
<p>
For example, suppose you have edited <code>sin.go</code> but
someone else has committed an independent change.
When you run <code>hg sync</code>, you will get the (scary-looking) output
(emphasis added):
When you run <code>git</code> <code>sync</code>,
you will get the (scary-looking) output:
<pre>
$ hg sync
adding changesets
adding manifests
adding file changes
added 1 changeset with 2 changes to 2 files
getting src/flag/flag.go
couldn't find merge tool hgmerge
merging src/flag/flag_test.go
warning: conflicts during merge.
<i>merging src/flag/flag_test.go failed!</i>
1 file updated, 0 files merged, 0 files removed, 1 file unresolved
use 'hg resolve' to retry unresolved file merges
$
$ git sync
Failed to merge in the changes.
Patch failed at 0023 math: improved Sin, Cos and Tan precision for very large arguments
The copy of the patch that failed is found in:
   /home/you/repo/.git/rebase-apply/patch
When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".
</pre>
<p>
The only important part in that transcript is the italicized line:
Mercurial failed to merge your changes with the independent change.
When this happens, Mercurial leaves both edits in the file,
marked by <code>&lt;&lt;&lt;&lt;&lt;&lt;&lt;</code> and
If this happens, run
</p>
<pre>
$ git status
</pre>
<p>
to see which files failed to merge.
The output will look something like this:
</p>
<pre>
rebase in progress; onto a24c3eb
You are currently rebasing branch 'mcgillicutty' on 'a24c3eb'.
  (fix conflicts and then run "git rebase --continue")
  (use "git rebase --skip" to skip this patch)
  (use "git rebase --abort" to check out the original branch)
Unmerged paths:
  (use "git reset HEAD &lt;file&gt;..." to unstage)
  (use "git add &lt;file&gt;..." to mark resolution)
<i>both modified:   sin.go</i>
</pre>
<p>
The only important part in that transcript is the italicized "both modified"
line: Git failed to merge your changes with the conflicting change.
When this happens, Git leaves both sets of edits in the file,
with conflicts marked by <code>&lt;&lt;&lt;&lt;&lt;&lt;&lt;</code> and
<code>&gt;&gt;&gt;&gt;&gt;&gt;&gt;</code>.
It is now your job to edit the file to combine them.
Continuing the example, searching for those strings in <code>flag_test.go</code>
Continuing the example, searching for those strings in <code>sin.go</code>
might turn up:
</p>
<pre>
VisitAll(visitor);
&lt;&lt;&lt;&lt;&lt;&lt;&lt; local
if len(m) != 7 {
arg = scale(arg)
&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD
if arg > 1e9 {
=======
if len(m) != 8 {
&gt;&gt;&gt;&gt;&gt;&gt;&gt; other
t.Error("VisitAll misses some flags");
if arg > 1e10 {
&gt;&gt;&gt;&gt;&gt;&gt;&gt; mcgillicutty
largeReduce(arg)
</pre>
<p>
Mercurial doesn't show it, but suppose the original text that both edits
started with was 6; you added 1 and the other change added 2,
so the correct answer might now be 9. First, edit the section
Git doesn't show it, but suppose the original text that both edits
started with was 1e8; you changed it to 1e10 and the other change to 1e9,
so the correct answer might now be 1e10. First, edit the section
to remove the markers and leave the correct code:
</p>
<pre>
VisitAll(visitor);
if len(m) != 9 {
t.Error("VisitAll misses some flags");
arg = scale(arg)
if arg > 1e10 {
largeReduce(arg)
</pre>
<p>
Then ask Mercurial to mark the conflict as resolved:
Then tell Git that the conflict is resolved by running
</p>
<pre>
$ hg resolve -m flag_test.go
$ git add sin.go
</pre>
<p>
If you had been editing the file, say for debugging, but do not
care to preserve your changes, you can run
<code>hg revert flag_test.go</code> to abandon your
changes, but you may still need to run
<code>hg resolve -m</code> to mark the conflict resolved.
<code>git</code> <code>reset</code> <code>HEAD</code> <code>sin.go</code>
to abandon your changes.
Then run <code>git</code> <code>rebase</code> <code>--continue</code> to
restore the change commit.
</p>
<h3>Reviewing code by others</h3>
<p>
You can import a CL proposed by someone else into your local Mercurial client
by using the <code>hg clpatch</code> command. Running
You can import a change proposed by someone else into your local Git repository.
On the Gerrit review page, click the "Download ▼" link in the upper right
corner, copy the "Checkout" command and run it from your local Git repo.
It should look something like this:
</p>
<pre>
$ hg clpatch 99999
$ git fetch https://go.googlesource.com/review refs/changes/21/1221/1 && git checkout FETCH_HEAD
</pre>
<p>
will apply the latest diff for CL 99999 to your working copy. If any of the
files referenced in CL 99999 have local modifications, <code>clpatch</code>
will refuse to apply the whole diff. Once applied, CL 99999 will show up in
the output of <code>hg pending</code> and others.
</p>
<p>
To revert a CL you have applied locally, use the <code>hg revert</code>
command. Running
</p>
<pre>
$ hg revert @99999
</pre>
<p>
will revert any files mentioned on CL 99999 to their original state. This can
be an effective way of reverting one CL revision and applying another.
</p>
<p>
Once the CL has been submitted, the next time you run <code>hg sync</code>
it will be removed from your local pending list. Occasionally the pending list
can get out of sync leaving stale references to closed or abandoned CLs.
You can use <code>hg change -D 99999</code> to remove the reference to CL 99999.
To revert, change back to the branch you were working in.
</p>
<h3>Submit the change after the review</h3>
<p>
After the code has been <code>LGTM</code>'ed, it is time to submit
it to the Mercurial repository.
After the code has been <code>LGTM</code>'ed, an approver may
submit it to the master branch using the Gerrit UI.
There is a "Submit" button on the web page for the change
that appears once the change is approved (marked +2).
</p>
<p>
If you are not a committer, you cannot submit the change directly.
Instead a committer, usually the reviewer who said <code>LGTM</code>,
will run:
</p>
<pre>
$ hg clpatch 99999
$ hg submit 99999
</pre>
<p>
The <code>submit</code> command submits the code. You will be listed as the
author, but the change message will also indicate who the committer was.
Your local client will notice that the change has been submitted
when you next run <code>hg sync</code>.
</p>
<p>
If you are a committer, you can run:
</p>
<pre>
$ hg submit 99999
</pre>
<p>
This checks the change into the repository.
The change description will include a link to the code review,
and the code review will be updated with a link to the change
in the repository.
Since the method used to integrate the changes is "Cherry Pick",
the commit hashes in the repository will be changed by
the submit operation.
</p>
<p>
If your local copy of the repository is out of date,
<code>hg submit</code> will refuse the change:
</p>
<pre>
$ hg submit 99999
local repository out of date; must sync before submit
</pre>
<h3>More information</h3>
<p>
In addition to the information here, the Go community maintains a <a href="https://code.google.com/p/go-wiki/wiki/CodeReview">CodeReview</a> wiki page.
In addition to the information here, the Go community maintains a <a href="https://golang.org/wiki/CodeReview">CodeReview</a> wiki page.
Feel free to contribute to this page as you learn the review process.
</p>
@@ -617,7 +614,8 @@ Feel free to contribute to this page as you learn the review process.
<p>Files in the Go repository don't list author names,
both to avoid clutter and to avoid having to keep the lists up to date.
Instead, your name will appear in the <a href="https://code.google.com/p/go/source/list">Mercurial change log</a>
Instead, your name will appear in the
<a href="https://golang.org/change">change log</a>
and in the <a href="/CONTRIBUTORS"><code>CONTRIBUTORS</code></a> file
and perhaps the <a href="/AUTHORS"><code>AUTHORS</code></a> file.
</p>
@@ -654,7 +652,7 @@ This rigmarole needs to be done only for your first submission.
<p>Code that you contribute should use the standard copyright header:</p>
<pre>
// Copyright 2014 The Go Authors. All rights reserved.
// 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.
</pre>

View File

@@ -3,8 +3,7 @@
}-->
<p>This page summarizes the changes between official stable releases of Go.
The <a href="//code.google.com/p/go/source/list">Mercurial change log</a>
has the full details.</p>
The <a href="//golang.org/change">change log</a> has the full details.</p>
<p>To update to a specific release, use:</p>
@@ -13,6 +12,25 @@ hg pull
hg update <i>tag</i>
</pre>
<h2 id="go1.4">go1.4 (released 2014/12/10)</h2>
<p>
Go 1.4 is a major release of Go.
Read the <a href="/doc/go1.4">Go 1.4 Release Notes</a> for more information.
</p>
<h3 id="go1.4.minor">Minor revisions</h3>
<p>
go1.4.1 (released 2015/01/15) includes bug fixes to the linker and the <code>log</code>, <code>syscall</code>, and <code>runtime</code> packages.
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.4.1">Go 1.4.1 milestone on our issue tracker</a> for details.
</p>
<p>
go1.4.2 (released 2015/02/17) includes bug fixes to the <code>go</code> command, the compiler and linker, and the <code>runtime</code>, <code>syscall</code>, <code>reflect</code>, and <code>math/big</code> packages.
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.4.2">Go 1.4.2 milestone on our issue tracker</a> for details.
</p>
<h2 id="go1.3">go1.3 (released 2014/06/18)</h2>
<p>

View File

@@ -5,7 +5,7 @@
<p>This page summarizes the changes between tagged weekly snapshots of Go.
Such snapshots are no longer created. This page remains as a historical reference only.</p>
<p>For recent information, see the <a href="//code.google.com/p/go/source/list">Mercurial change log</a> and <a href="//groups.google.com/group/golang-dev/">development mailing list</a>.</p>
<p>For recent information, see the <a href="//golang.org/change">change log</a> and <a href="//groups.google.com/group/golang-dev/">development mailing list</a>.</p>
<h2 id="2012-03-27">2012-03-27 (<a href="release.html#go1">Go 1</a>)</h2>

View File

@@ -298,7 +298,7 @@ For example,
<h3 id="godoc">Changes to godoc</h3>
<p>
When invoked with the <code>-analysis</code> flag,
<a href="//godoc.org/code.google.com/p/go.tools/cmd/godoc">godoc</a>
<a href="//godoc.org/golang.org/x/tools/cmd/godoc">godoc</a>
now performs sophisticated <a href="/lib/godoc/analysis/help.html">static
analysis</a> of the code it indexes.
The results of analysis are presented in both the source view and the
@@ -318,7 +318,7 @@ call sites and their callees.
The program <code>misc/benchcmp</code> that compares
performance across benchmarking runs has been rewritten.
Once a shell and awk script in the main repository, it is now a Go program in the <code>go.tools</code> repo.
Documentation is <a href="//godoc.org/code.google.com/p/go.tools/cmd/benchcmp">here</a>.
Documentation is <a href="//godoc.org/golang.org/x/tools/cmd/benchcmp">here</a>.
</p>
<p>

View File

@@ -7,10 +7,16 @@
<h2 id="introduction">Introduction to Go 1.4</h2>
<p>
The latest Go release, version 1.4, arrives as scheduled six months after 1.3
and contains only one tiny language change,
a possibly breaking change to the compiler,
a backwards-compatible simple form of <code>for</code>-<code>range</code> loop.
The latest Go release, version 1.4, arrives as scheduled six months after 1.3.
</p>
<p>
It contains only one tiny language change,
in the form of a backwards-compatible simple variant of <code>for</code>-<code>range</code> loop,
and a possibly breaking change to the compiler involving methods on pointers-to-pointers.
</p>
<p>
The release focuses primarily on implementation work, improving the garbage collector
and preparing the ground for a fully concurrent collector to be rolled out in the
next few releases.
@@ -20,7 +26,10 @@ this release therefore eliminates the notorious "hot stack split" problem.
There are some new tools available including support in the <code>go</code> command
for build-time source code generation.
The release also adds support for ARM processors on Android and Native Client (NaCl)
and AMD64 on Plan 9.
and for AMD64 on Plan 9.
</p>
<p>
As always, Go 1.4 keeps the <a href="/doc/go1compat.html">promise
of compatibility</a>,
and almost everything
@@ -35,7 +44,7 @@ Up until Go 1.3, <code>for</code>-<code>range</code> loop had two forms
</p>
<pre>
for k, v := range x {
for i, v := range x {
...
}
</pre>
@@ -45,7 +54,7 @@ and
</p>
<pre>
for k := range x {
for i := range x {
...
}
</pre>
@@ -172,7 +181,7 @@ of the documentation.
<h3 id="runtime">Changes to the runtime</h3>
<p>
Up to Go 1.4, the runtime (garbage collector, concurrency support, interface management,
Prior to Go 1.4, the runtime (garbage collector, concurrency support, interface management,
maps, slices, strings, ...) was mostly written in C, with some assembler support.
In 1.4, much of the code has been translated to Go so that the garbage collector can scan
the stacks of programs in the runtime and get accurate information about what variables
@@ -198,7 +207,7 @@ Details are available in <a href="https://golang.org/s/contigstacks">the design
<p>
The use of contiguous stacks means that stacks can start smaller without triggering performance issues,
so the default starting size for a goroutine's stack in 1.4 has been reduced to 2048 bytes from 8192 bytes.
so the default starting size for a goroutine's stack in 1.4 has been reduced from 8192 bytes to 2048 bytes.
</p>
<p>
@@ -513,10 +522,7 @@ have been updated.
<h3 id="swig">SWIG</h3>
<p>
Due to the runtime changes in this release, Go 1.4 will require SWIG 3.0.3.
At time of writing that has not yet been released, but we expect it to be by
Go 1.4's release date.
TODO
Due to runtime changes in this release, Go 1.4 requires SWIG 3.0.3.
</p>
<h3 id="misc">Miscellany</h3>
@@ -535,7 +541,7 @@ editor, even for editors we do not use.
The Go community at large is much better suited to managing this information.
In Go 1.4, therefore, this support has been removed from the repository.
Instead, there is a curated, informative list of what's available on
a <a href="https://code.google.com/p/go-wiki/wiki/IDEsAndTextEditorPlugins">wiki page</a>.
a <a href="//golang.org/wiki/IDEsAndTextEditorPlugins">wiki page</a>.
</p>
<h2 id="performance">Performance</h2>

View File

@@ -228,7 +228,7 @@ document server running in a production configuration on
</p>
<p>
Other examples include the <a href="https://code.google.com/p/vitess/">Vitess</a>
Other examples include the <a href="//code.google.com/p/vitess/">Vitess</a>
system for large-scale SQL installations and Google's download server, <code>dl.google.com</code>,
which delivers Chrome binaries and other large installables such as <code>apt-get</code>
packages.
@@ -986,32 +986,6 @@ See the document
for more information about how to proceed.
</p>
<h3 id="Why_does_the_project_use_Mercurial_and_not_git">
Why does the project use Mercurial and not git?</h3>
<p>
The Go project, hosted by Google Code at
<a href="//code.google.com/p/go">code.google.com/p/go</a>,
uses Mercurial as its version control system.
When the project launched,
Google Code supported only Subversion and Mercurial.
Mercurial was a better choice because of its plugin mechanism
that allowed us to create the "codereview" plugin to connect
the project to the excellent code review tools at
<a href="//codereview.appspot.com">codereview.appspot.com</a>.
</p>
<p>
Programmers who work
with the Go project's source rather than release downloads sometimes
ask for the project to switch to git.
That would be possible, but it would be a lot of work and
would also require reimplementing the codereview plugin.
Given that Mercurial works today, with code review support,
combined with the Go project's mostly linear, non-branching use of
version control, a switch to git doesn't seem worthwhile.
</p>
<h3 id="git_https">
Why does "go get" use HTTPS when cloning a repository?</h3>

View File

@@ -24,7 +24,7 @@ Need help with Go? Try these resources.
<p>
Search the <a href="//groups.google.com/group/golang-nuts">golang-nuts</a>
archives and consult the <a href="/doc/go_faq.html">FAQ</a> and
<a href="//code.google.com/p/go-wiki/wiki">wiki</a> before posting.
<a href="//golang.org/wiki">wiki</a> before posting.
</p>
<h3 id="irc"><a href="irc:irc.freenode.net/go-nuts">Go IRC Channel</a></h3>

View File

@@ -81,38 +81,21 @@ The full set of supported combinations is listed in the discussion of
<p>
The Go tool chain is written in C. To build it, you need a C compiler installed.
Please refer to the <a href="//golang.org/wiki/InstallFromSource#Install_C_tools">InstallFromSource</a>
Please refer to the <a href="//golang.org/wiki/InstallFromSource#install-c-tools">InstallFromSource</a>
page on the Go community Wiki for operating system specific instructions.
</p>
<h2 id="mercurial">Install Mercurial, if needed</h2>
<h2 id="git">Install Git, if needed</h2>
<p>
To perform the next step you must have Mercurial installed. (Check that you
have an <code>hg</code> command.)
To perform the next step you must have Git installed. (Check that you
have a <code>git</code> command before proceeding.)
</p>
<p>
If you do not have a working Mercurial installation,
If you do not have a working Git installation,
follow the instructions on the
<a href="http://mercurial.selenic.com/downloads">Mercurial downloads</a> page.
</p>
<p>
Mercurial versions 1.7.x and up require the configuration of
<a href="http://mercurial.selenic.com/wiki/CACertificates">Certification Authorities</a>
(CAs). Error messages of the form:
</p>
<pre>
warning: code.google.com certificate with fingerprint b1:af: ... bc not verified (check hostfingerprints or web.cacerts config setting)
</pre>
<p>
when using Mercurial indicate that the CAs are missing.
Check your Mercurial version (<code>hg --version</code>) and
<a href="http://mercurial.selenic.com/wiki/CACertificates#Configuration_of_HTTPS_certificate_authorities">configure the CAs</a>
if necessary.
<a href="http://git-scm.com/downloads">Git downloads</a> page.
</p>
@@ -121,22 +104,24 @@ if necessary.
<p>Go will install to a directory named <code>go</code>.
Change to the directory that will be its parent
and make sure the <code>go</code> directory does not exist.
Then check out the repository:</p>
Then clone the repository and check out the latest release tag:</p>
<pre>
$ hg clone -u release https://code.google.com/p/go
$ git clone https://go.googlesource.com/go
$ cd go
$ git checkout go1.4.1
</pre>
<h2 id="head">(Optional) Switch to the default branch</h2>
<h2 id="head">(Optional) Switch to the master branch</h2>
<p>If you intend to modify the go source code, and
<a href="/doc/contribute.html">contribute your changes</a>
to the project, then move your repository
off the release branch, and onto the default (development) branch.
off the release branch, and onto the master (development) branch.
Otherwise, skip this step.</p>
<pre>
$ hg update default
$ git checkout master
</pre>
<h2 id="install">Install Go</h2>
@@ -259,7 +244,7 @@ $ go get golang.org/x/tools/cmd/godoc
<p>
To install these tools, the <code>go</code> <code>get</code> command requires
that <a href="#mercurial">Mercurial</a> be installed locally.
that <a href="#git">Git</a> be installed locally.
</p>
<p>
@@ -292,22 +277,18 @@ that receives a message summarizing each checkin to the Go repository.
</p>
<p>
Bugs can be reported using the <a href="//code.google.com/p/go/issues/list">Go issue tracker</a>.
Bugs can be reported using the <a href="//golang.org/issue/new">Go issue tracker</a>.
</p>
<h2 id="releases">Keeping up with releases</h2>
<p>
The Go project maintains a stable tag in its Mercurial repository:
<code>release</code>.
</p>
<p>
The <code>release</code> tag refers to the current stable release of Go.
Most Go users should use this version. New releases are announced on the
New releases are announced on the
<a href="//groups.google.com/group/golang-announce">golang-announce</a>
mailing list.
Each announcement mentions the latest release tag, for instance,
<code>go1.4</code>.
</p>
<p>
@@ -316,11 +297,13 @@ To update an existing tree to the latest release, you can run:
<pre>
$ cd go/src
$ hg pull
$ hg update release
$ git fetch
$ git checkout <i>&lt;tag&gt;</i>
$ ./all.bash
</pre>
Where <code>&lt;tag&gt;</code> is the version string of the release.
<h2 id="environment">Optional environment variables</h2>

View File

@@ -314,7 +314,11 @@ class CL(object):
if self.name != "new":
s = "code review %s: %s" % (self.name, s)
typecheck(s, str)
return branch_prefix(ui, repo) + s
s = branch_prefix(ui, repo) + s
# Rietveld does a hard reject on any subject > 100 chars. Be sure.
if len(s) >= 100:
s = s[0:95] + "..."
return s
def Upload(self, ui, repo, send_mail=False, gofmt=True, gofmt_just_warn=False, creating=False, quiet=False):
if not self.files and not creating:
@@ -409,7 +413,7 @@ class CL(object):
if not self.mailed:
pmsg += "I'd like you to review this change to"
branch = repo[None].branch()
if branch.startswith("dev."):
if workbranch(branch) and branch != "default":
pmsg += " the " + branch + " branch of"
pmsg += "\n" + repourl + "\n"
else:
@@ -1921,7 +1925,7 @@ def need_sync():
def branch_prefix(ui, repo):
prefix = ""
branch = repo[None].branch()
if branch.startswith("dev."):
if workbranch(branch) and branch != "default":
prefix = "[" + branch + "] "
return prefix
@@ -2726,7 +2730,7 @@ def RietveldSetup(ui, repo):
releaseBranch = t
def workbranch(name):
return name == "default" or name.startswith('dev.')
return name == "default" or name.startswith('dev.') or name == 'release-branch.go1.4'
#######################################################################
# http://codereview.appspot.com/static/upload.py, heavily edited.

View File

@@ -7,8 +7,8 @@
# downloaded from the ICANN/IANA distribution.
# Versions to use.
CODE=2014d
DATA=2014d
CODE=2014j
DATA=2014j
set -e
rm -rf work

Binary file not shown.

View File

@@ -12,9 +12,15 @@ complex double complexDoubleSquared(complex double a) { return a*a; }
*/
import "C"
import "testing"
import (
"runtime"
"testing"
)
func test8694(t *testing.T) {
if runtime.GOARCH == "arm" {
t.Skip("test8694 is disabled on ARM because 5l cannot handle thumb library.")
}
// Really just testing that this compiles, but check answer anyway.
x := complex64(2 + 3i)
x2 := x * x

View File

@@ -14,6 +14,7 @@ import (
"compress/gzip"
"crypto/sha1"
"encoding/json"
"errors"
"flag"
"fmt"
"io"
@@ -30,7 +31,7 @@ import (
"strings"
"code.google.com/p/goauth2/oauth"
storage "code.google.com/p/google-api-go-client/storage/v1beta2"
storage "code.google.com/p/google-api-go-client/storage/v1"
)
var (
@@ -56,8 +57,8 @@ const (
blogPath = "golang.org/x/blog"
toolPath = "golang.org/x/tools"
tourPath = "code.google.com/p/go-tour"
defaultToolTag = "release-branch.go1.3"
defaultTourTag = "release-branch.go1.3"
defaultToolTag = "release-branch.go1.4"
defaultTourTag = "release-branch.go1.4"
)
// Import paths for tool commands.
@@ -504,16 +505,38 @@ func (b *Build) extras() error {
}
func (b *Build) get(repoPath, revision string) error {
// Fetch the packages (without building/installing).
_, err := b.run(b.gopath, filepath.Join(b.root, "bin", "go"),
"get", "-d", repoPath+"/...")
if err != nil {
return err
dest := filepath.Join(b.gopath, "src", filepath.FromSlash(repoPath))
if strings.HasPrefix(repoPath, "golang.org/x/") {
// For sub-repos, fetch the old Mercurial repo; bypass "go get".
// DO NOT import this special case into the git tree.
if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil {
return err
}
repo := strings.Replace(repoPath, "golang.org/x/", "https://code.google.com/p/go.", 1)
if _, err := b.run(b.gopath, "hg", "clone", repo, dest); err != nil {
return err
}
} else {
// Fetch the packages (without building/installing).
_, err := b.run(b.gopath, filepath.Join(b.root, "bin", "go"),
"get", "-d", repoPath+"/...")
if err != nil {
return err
}
}
// Update the repo to the specified revision.
p := filepath.Join(b.gopath, "src", filepath.FromSlash(repoPath))
_, err = b.run(p, "hg", "update", revision)
var err error
switch {
case exists(filepath.Join(dest, ".git")):
_, err = b.run(dest, "git", "checkout", revision)
case exists(filepath.Join(dest, ".hg")):
_, err = b.run(dest, "hg", "update", revision)
default:
err = errors.New("unknown version control system")
}
return err
}

View File

@@ -18,9 +18,6 @@ go src=..
gofmt_test.go
testdata
+
link
testdata
+
archive
tar
testdata

View File

@@ -236,18 +236,14 @@ cgen(Node *n, Node *res)
cgen(nl, &n1);
nodconst(&n2, nl->type, -1);
gins(a, &n2, &n1);
gmove(&n1, res);
regfree(&n1);
goto ret;
goto norm;
case OMINUS:
regalloc(&n1, nl->type, N);
cgen(nl, &n1);
nodconst(&n2, nl->type, 0);
gins(optoas(OMINUS, nl->type), &n2, &n1);
gmove(&n1, res);
regfree(&n1);
goto ret;
goto norm;
// symmetric binary
case OAND:
@@ -483,12 +479,15 @@ abop: // asymmetric binary
cgen(nl, &n1);
}
gins(a, &n2, &n1);
norm:
// Normalize result for types smaller than word.
if(n->type->width < widthptr) {
switch(n->op) {
case OADD:
case OSUB:
case OMUL:
case OCOM:
case OMINUS:
gins(optoas(OAS, n->type), &n1, &n1);
break;
}

View File

@@ -283,7 +283,7 @@ func compareAPI(w io.Writer, features, required, optional, exception []string) (
delete(optionalSet, newFeature)
} else {
fmt.Fprintf(w, "+%s\n", newFeature)
if !*allowNew {
if !*allowNew || !strings.Contains(runtime.Version(), "devel") {
ok = false // we're in lock-down mode for next release
}
}
@@ -313,11 +313,15 @@ func fileFeatures(filename string) []string {
if err != nil {
log.Fatalf("Error reading file %s: %v", filename, err)
}
text := strings.TrimSpace(string(bs))
if text == "" {
return nil
lines := strings.Split(string(bs), "\n")
var nonblank []string
for _, line := range lines {
line = strings.TrimSpace(line)
if line != "" && !strings.HasPrefix(line, "#") {
nonblank = append(nonblank, line)
}
}
return strings.Split(text, "\n")
return nonblank
}
var fset = token.NewFileSet()

View File

@@ -21,6 +21,7 @@ import (
"os/exec"
"os/user"
"path/filepath"
"runtime"
"strings"
)
@@ -53,7 +54,7 @@ func main() {
}
out, err = exec.Command("go", "tool", "api",
"-c", file("go1", "go1.1", "go1.2", "go1.3"),
"-c", file("go1", "go1.1", "go1.2", "go1.3", "go1.4"),
"-next", file("next"),
"-except", file("except")).CombinedOutput()
if err != nil {
@@ -105,7 +106,7 @@ func prepGoPath() string {
}
// The GOPATH we'll return
gopath := filepath.Join(os.TempDir(), "gopath-api-"+cleanUsername(username), goToolsVersion)
gopath := filepath.Join(os.TempDir(), "gopath-api-"+cleanUsername(username)+"-"+cleanUsername(strings.Fields(runtime.Version())[0]), goToolsVersion)
// cloneDir is where we run "hg clone".
cloneDir := filepath.Join(gopath, "src", "code.google.com", "p")

100
src/cmd/dist/build.c vendored
View File

@@ -235,24 +235,65 @@ chomp(Buf *b)
b->len--;
}
static char*
branchtag(char *branch, bool *precise)
{
char *tag, *p, *q;
int i;
Buf b, arg;
Vec tags;
binit(&b);
binit(&arg);
vinit(&tags);
bprintf(&arg, "master..%s", branch);
run(&b, goroot, CheckExit, "git", "log", "--decorate=full", "--format=format:%d", bstr(&arg), nil);
splitlines(&tags, bstr(&b));
tag = branch;
for(i=0; i < tags.len; i++) {
// Each line is either blank, or looks like
// (tag: refs/tags/go1.4rc2, refs/remotes/origin/release-branch.go1.4, refs/heads/release-branch.go1.4)
// We need to find an element starting with refs/tags/.
p = xstrstr(tags.p[i], " refs/tags/");
if(p == nil)
continue;
p += xstrlen(" refs/tags/");
// The tag name ends at a comma or paren (prefer the first).
q = xstrstr(p, ",");
if(q == nil)
q = xstrstr(p, ")");
if(q == nil)
continue; // malformed line; ignore it
*q = '\0';
tag = xstrdup(p);
if(i == 0)
*precise = 1; // tag denotes HEAD
break;
}
bfree(&b);
bfree(&arg);
vfree(&tags);
return tag;
}
// findgoversion determines the Go version to use in the version string.
static char*
findgoversion(void)
{
char *tag, *rev, *p;
int i, nrev;
char *tag, *p;
bool precise;
Buf b, path, bmore, branch;
Vec tags;
binit(&b);
binit(&path);
binit(&bmore);
binit(&branch);
vinit(&tags);
// The $GOROOT/VERSION file takes priority, for distributions
// without the Mercurial repo.
// without the source repo.
bpathf(&path, "%s/VERSION", goroot);
if(isfile(bstr(&path))) {
readfile(&b, bstr(&path));
@@ -266,7 +307,7 @@ findgoversion(void)
}
// The $GOROOT/VERSION.cache file is a cache to avoid invoking
// hg every time we run this command. Unlike VERSION, it gets
// git every time we run this command. Unlike VERSION, it gets
// deleted by the clean command.
bpathf(&path, "%s/VERSION.cache", goroot);
if(isfile(bstr(&path))) {
@@ -275,49 +316,27 @@ findgoversion(void)
goto done;
}
// Otherwise, use Mercurial.
// Otherwise, use Git.
// What is the current branch?
run(&branch, goroot, CheckExit, "hg", "identify", "-b", nil);
run(&branch, goroot, CheckExit, "git", "rev-parse", "--abbrev-ref", "HEAD", nil);
chomp(&branch);
// What are the tags along the current branch?
tag = "devel";
rev = ".";
run(&b, goroot, CheckExit, "hg", "log", "-b", bstr(&branch), "-r", ".:0", "--template", "{tags} + ", nil);
splitfields(&tags, bstr(&b));
nrev = 0;
for(i=0; i<tags.len; i++) {
p = tags.p[i];
if(streq(p, "+"))
nrev++;
// Only show the beta tag for the exact revision.
if(hasprefix(p, "go") && (!contains(p, "beta") || nrev == 0)) {
tag = xstrdup(p);
// If this tag matches the current checkout
// exactly (no "+" yet), don't show extra
// revision information.
if(nrev == 0)
rev = "";
break;
}
}
precise = 0;
if(tag[0] == '\0') {
// Did not find a tag; use branch name.
bprintf(&b, "branch.%s", bstr(&branch));
tag = btake(&b);
}
if(rev[0]) {
// Tag is before the revision we're building.
// Add extra information.
run(&bmore, goroot, CheckExit, "hg", "log", "--template", " +{node|short} {date|date}", "-r", rev, nil);
chomp(&bmore);
}
// If we're on a release branch, use the closest matching tag
// that is on the release branch (and not on the master branch).
if(hasprefix(bstr(&branch), "release-branch."))
tag = branchtag(bstr(&branch), &precise);
bprintf(&b, "%s", tag);
if(bmore.len > 0)
if(!precise) {
// Tag does not point at HEAD; add hash and date to version.
run(&bmore, goroot, CheckExit, "git", "log", "-n", "1", "--format=format: +%h %cd", "HEAD", nil);
chomp(&bmore);
bwriteb(&b, &bmore);
}
// Cache version.
writefile(&b, bstr(&path), 0);
@@ -330,7 +349,6 @@ done:
bfree(&path);
bfree(&bmore);
bfree(&branch);
vfree(&tags);
return p;
}

View File

@@ -128,6 +128,11 @@ dowidth(Type *t)
return;
}
// break infinite recursion if the broken recursive type
// is referenced again
if(t->broke && t->width == 0)
return;
// defer checkwidth calls until after we're done
defercalc++;

View File

@@ -974,6 +974,7 @@ EXTERN int funcdepth;
EXTERN int typecheckok;
EXTERN int compiling_runtime;
EXTERN int compiling_wrappers;
EXTERN int inl_nonlocal;
EXTERN int use_writebarrier;
EXTERN int pure_go;
EXTERN char* flag_installsuffix;

View File

@@ -804,9 +804,12 @@ inlvar(Node *var)
n->curfn = curfn; // the calling function, not the called one
n->addrtaken = var->addrtaken;
// esc pass wont run if we're inlining into a iface wrapper
// luckily, we can steal the results from the target func
if(var->esc == EscHeap)
// Esc pass wont run if we're inlining into a iface wrapper.
// Luckily, we can steal the results from the target func.
// If inlining a function defined in another package after
// escape analysis is done, treat all local vars as escaping.
// See issue 9537.
if(var->esc == EscHeap || (inl_nonlocal && var->op == ONAME))
addrescapes(n);
curfn->dcl = list(curfn->dcl, n);

View File

@@ -143,18 +143,6 @@ mapbucket(Type *t)
// We don't need to encode it as GC doesn't care about it.
offset = BUCKETSIZE * 1;
overflowfield = typ(TFIELD);
overflowfield->type = ptrto(bucket);
overflowfield->width = offset; // "width" is offset in structure
overflowfield->sym = mal(sizeof(Sym)); // not important but needs to be set to give this type a name
overflowfield->sym->name = "overflow";
offset += widthptr;
// The keys are padded to the native integer alignment.
// This is usually the same as widthptr; the exception (as usual) is nacl/amd64.
if(widthreg > widthptr)
offset += widthreg - widthptr;
keysfield = typ(TFIELD);
keysfield->type = typ(TARRAY);
keysfield->type->type = keytype;
@@ -175,11 +163,23 @@ mapbucket(Type *t)
valuesfield->sym->name = "values";
offset += BUCKETSIZE * valtype->width;
overflowfield = typ(TFIELD);
overflowfield->type = ptrto(bucket);
overflowfield->width = offset; // "width" is offset in structure
overflowfield->sym = mal(sizeof(Sym)); // not important but needs to be set to give this type a name
overflowfield->sym->name = "overflow";
offset += widthptr;
// Pad to the native integer alignment.
// This is usually the same as widthptr; the exception (as usual) is nacl/amd64.
if(widthreg > widthptr)
offset += widthreg - widthptr;
// link up fields
bucket->type = overflowfield;
overflowfield->down = keysfield;
bucket->type = keysfield;
keysfield->down = valuesfield;
valuesfield->down = T;
valuesfield->down = overflowfield;
overflowfield->down = T;
bucket->width = offset;
bucket->local = t->local;

View File

@@ -2614,7 +2614,16 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
fn->dupok = 1;
typecheck(&fn, Etop);
typechecklist(fn->nbody, Etop);
// Set inl_nonlocal to whether we are calling a method on a
// type defined in a different package. Checked in inlvar.
if(!methodrcvr->local)
inl_nonlocal = 1;
inlcalls(fn);
inl_nonlocal = 0;
curfn = nil;
funccompile(fn, 0);
}

View File

@@ -1335,7 +1335,7 @@ reswitch:
goto error;
// Unpack multiple-return result before type-checking.
if(istype(t, TSTRUCT)) {
if(istype(t, TSTRUCT) && t->funarg) {
t = t->type;
if(istype(t, TFIELD))
t = t->type;

View File

@@ -234,17 +234,24 @@ create or update Go source files, for instance by running yacc.
Go generate is never run automatically by go build, go get, go test,
and so on. It must be run explicitly.
Directives are written as a whole-line comment of the form
Go generate scans the file for directives, which are lines of
the form,
//go:generate command argument...
(note: no space in "//go") where command is the generator to be
run, corresponding to an executable file that can be run locally.
It must either be in the shell path (gofmt), a fully qualified path
(/usr/you/bin/mytool), or a command alias, described below.
(note: no leading spaces and no space in "//go") where command
is the generator to be run, corresponding to an executable file
that can be run locally. It must either be in the shell path
(gofmt), a fully qualified path (/usr/you/bin/mytool), or a
command alias, described below.
The arguments are space-separated tokens or double-quoted strings
passed to the generator as individual arguments when it is run.
Note that go generate does not parse the file, so lines that look
like directives in comments or multiline strings will be treated
as directives.
The arguments to the directive are space-separated tokens or
double-quoted strings passed to the generator as individual
arguments when it is run.
Quoted strings use Go syntax and are evaluated before execution; a
quoted string appears as a single argument to the generator.
@@ -301,6 +308,7 @@ The generator is run in the package's source directory.
Go generate accepts one specific flag:
-run=""
TODO: This flag is unimplemented.
if non-empty, specifies a regular expression to
select directives whose command matches the expression.
@@ -317,7 +325,7 @@ Download and install packages and dependencies
Usage:
go get [-d] [-fix] [-t] [-u] [build flags] [packages]
go get [-d] [-f] [-fix] [-t] [-u] [build flags] [packages]
Get downloads and installs the packages named by the import paths,
along with their dependencies.
@@ -325,6 +333,11 @@ along with their dependencies.
The -d flag instructs get to stop after downloading the packages; that is,
it instructs get not to install the packages.
The -f flag, valid only when -u is set, forces get -u not to verify that
each package has been checked out from the source control repository
implied by its import path. This can be useful if the source is a local fork
of the original.
The -fix flag instructs get to run the fix tool on the downloaded packages
before resolving dependencies or building the code.
@@ -863,7 +876,26 @@ listed in the GOPATH environment variable (see 'go help gopath').
The go command attempts to download the version of the
package appropriate for the Go release being used.
Run 'go help install' for more.
Run 'go help get' for more.
Import path checking
When the custom import path feature described above redirects to a
known code hosting site, each of the resulting packages has two possible
import paths, using the custom domain or the known hosting site.
A package statement is said to have an "import comment" if it is immediately
followed (before the next newline) by a comment of one of these two forms:
package math // import "path"
package math /* import "path" * /
The go command will refuse to install a package with an import comment
unless it is being referred to by that import path. In this way, import comments
let package authors make sure the custom import path is used and not a
direct path to the underlying code hosting site.
See https://golang.org/s/go14customimport for details.
Description of package lists

View File

@@ -32,20 +32,27 @@ create or update Go source files, for instance by running yacc.
Go generate is never run automatically by go build, go get, go test,
and so on. It must be run explicitly.
Directives are written as a whole-line comment of the form
Go generate scans the file for directives, which are lines of
the form,
//go:generate command argument...
(note: no space in "//go") where command is the generator to be
run, corresponding to an executable file that can be run locally.
It must either be in the shell path (gofmt), a fully qualified path
(/usr/you/bin/mytool), or a command alias, described below.
(note: no leading spaces and no space in "//go") where command
is the generator to be run, corresponding to an executable file
that can be run locally. It must either be in the shell path
(gofmt), a fully qualified path (/usr/you/bin/mytool), or a
command alias, described below.
The arguments are space-separated tokens or double-quoted strings
passed to the generator as individual arguments when it is run.
Note that go generate does not parse the file, so lines that look
like directives in comments or multiline strings will be treated
as directives.
The arguments to the directive are space-separated tokens or
double-quoted strings passed to the generator as individual
arguments when it is run.
Quoted strings use Go syntax and are evaluated before execution; a
quoted string appears a single argument to the generator.
quoted string appears as a single argument to the generator.
Go generate sets several variables when it runs the generator:
@@ -99,6 +106,7 @@ The generator is run in the package's source directory.
Go generate accepts one specific flag:
-run=""
TODO: This flag is unimplemented.
if non-empty, specifies a regular expression to
select directives whose command matches the expression.
@@ -178,13 +186,43 @@ func (g *Generator) run() (ok bool) {
fmt.Fprintf(os.Stderr, "%s\n", shortPath(g.path))
}
s := bufio.NewScanner(g.r)
for s.Scan() {
g.lineNum++
if !bytes.HasPrefix(s.Bytes(), []byte("//go:generate ")) && !bytes.HasPrefix(s.Bytes(), []byte("//go:generate\t")) {
// Scan for lines that start "//go:generate".
// Can't use bufio.Scanner because it can't handle long lines,
// which are likely to appear when using generate.
input := bufio.NewReader(g.r)
var err error
// One line per loop.
for {
g.lineNum++ // 1-indexed.
var buf []byte
buf, err = input.ReadSlice('\n')
if err == bufio.ErrBufferFull {
// Line too long - consume and ignore.
if isGoGenerate(buf) {
g.errorf("directive too long")
}
for err == bufio.ErrBufferFull {
_, err = input.ReadSlice('\n')
}
if err != nil {
break
}
continue
}
words := g.split(s.Text())
if err != nil {
// Check for marker at EOF without final \n.
if err == io.EOF && isGoGenerate(buf) {
err = io.ErrUnexpectedEOF
}
break
}
if !isGoGenerate(buf) {
continue
}
words := g.split(string(buf))
if len(words) == 0 {
g.errorf("no arguments to directive")
}
@@ -201,19 +239,27 @@ func (g *Generator) run() (ok bool) {
}
g.exec(words)
}
if s.Err() != nil {
g.errorf("error reading %s: %s", shortPath(g.path), s.Err())
if err != nil && err != io.EOF {
g.errorf("error reading %s: %s", shortPath(g.path), err)
}
return true
}
func isGoGenerate(buf []byte) bool {
return bytes.HasPrefix(buf, []byte("//go:generate ")) || bytes.HasPrefix(buf, []byte("//go:generate\t"))
}
// split breaks the line into words, evaluating quoted
// strings and evaluating environment variables.
// The initial //go:generate element is dropped.
// The initial //go:generate element is present in line.
func (g *Generator) split(line string) []string {
// Parse line, obeying quoted strings.
var words []string
line = line[len("//go:generate "):]
line = line[len("//go:generate ") : len(line)-1] // Drop preamble and final newline.
// There may still be a carriage return.
if len(line) > 0 && line[len(line)-1] == '\r' {
line = line[:len(line)-1]
}
// One (possibly quoted) word per iteration.
Words:
for {

View File

@@ -40,7 +40,13 @@ func TestGenerateCommandParse(t *testing.T) {
}
g.setShorthand([]string{"-command", "yacc", "go", "tool", "yacc"})
for _, test := range splitTests {
got := g.split("//go:generate " + test.in)
// First with newlines.
got := g.split("//go:generate " + test.in + "\n")
if !reflect.DeepEqual(got, test.out) {
t.Errorf("split(%q): got %q expected %q", test.in, got, test.out)
}
// Then with CRLFs, thank you Windows.
got = g.split("//go:generate " + test.in + "\r\n")
if !reflect.DeepEqual(got, test.out) {
t.Errorf("split(%q): got %q expected %q", test.in, got, test.out)
}

View File

@@ -290,7 +290,7 @@ func downloadPackage(p *Package) error {
}
}
if remote != repo {
return fmt.Errorf("%s is from %s, should be from %s", dir, remote, repo)
return fmt.Errorf("%s is a custom import path for %s, but %s is checked out from %s", rr.root, repo, dir, remote)
}
}
}

View File

@@ -235,7 +235,26 @@ listed in the GOPATH environment variable (see 'go help gopath').
The go command attempts to download the version of the
package appropriate for the Go release being used.
Run 'go help install' for more.
Run 'go help get' for more.
Import path checking
When the custom import path feature described above redirects to a
known code hosting site, each of the resulting packages has two possible
import paths, using the custom domain or the known hosting site.
A package statement is said to have an "import comment" if it is immediately
followed (before the next newline) by a comment of one of these two forms:
package math // import "path"
package math /* import "path" */
The go command will refuse to install a package with an import comment
unless it is being referred to by that import path. In this way, import comments
let package authors make sure the custom import path is used and not a
direct path to the underlying code hosting site.
See https://golang.org/s/go14customimport for details.
`,
}

View File

@@ -4,6 +4,6 @@
# license that can be found in the LICENSE file.
go install # So the next line will produce updated documentation.
go help documentation > doc.go
go help documentation | sed 's; \*/; * /;' >doc.go
gofmt -w doc.go

View File

@@ -47,7 +47,7 @@ const toolWindowsExtension = ".exe"
func tool(toolName string) string {
toolPath := filepath.Join(toolDir, toolName)
if toolIsWindows && toolName != "pprof" {
if toolIsWindows {
toolPath += toolWindowsExtension
}
// Give a nice message if there is no tool with that name.
@@ -91,16 +91,6 @@ func runTool(cmd *Command, args []string) {
if toolPath == "" {
return
}
if toolIsWindows && toolName == "pprof" {
args = append([]string{"perl", toolPath}, args[1:]...)
var err error
toolPath, err = exec.LookPath("perl")
if err != nil {
fmt.Fprintf(os.Stderr, "go tool: perl not found\n")
setExitStatus(3)
return
}
}
if toolN {
fmt.Printf("%s %s\n", toolPath, strings.Join(args[1:], " "))
return

View File

@@ -7,7 +7,7 @@
package objfile
import (
"debug/goobj"
"cmd/internal/goobj"
"fmt"
"os"
)

View File

@@ -1281,12 +1281,19 @@ synthesizemaptypes(DWDie *die)
fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "keys");
newrefattr(fld, DW_AT_type, dwhk);
newmemberoffsetattr(fld, BucketSize + PtrSize);
newmemberoffsetattr(fld, BucketSize);
fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "values");
newrefattr(fld, DW_AT_type, dwhv);
newmemberoffsetattr(fld, BucketSize + PtrSize + BucketSize * keysize);
newattr(dwhb, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize + PtrSize + BucketSize * keysize + BucketSize * valsize, 0);
substitutetype(dwhb, "overflow", defptrto(dwhb));
newmemberoffsetattr(fld, BucketSize + BucketSize * keysize);
fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "overflow");
newrefattr(fld, DW_AT_type, defptrto(dwhb));
newmemberoffsetattr(fld, BucketSize + BucketSize * (keysize + valsize));
if(RegSize > PtrSize) {
fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "pad");
newrefattr(fld, DW_AT_type, find_or_diag(&dwtypes, "uintptr"));
newmemberoffsetattr(fld, BucketSize + BucketSize * (keysize + valsize) + PtrSize);
}
newattr(dwhb, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize + BucketSize * keysize + BucketSize * valsize + RegSize, 0);
// Construct hash<K,V>
dwh = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,

View File

@@ -539,7 +539,10 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
s->type = SRODATA;
break;
case ElfSectFlagAlloc + ElfSectFlagWrite:
s->type = SNOPTRDATA;
if(sect->type == ElfSectNobits)
s->type = SNOPTRBSS;
else
s->type = SNOPTRDATA;
break;
case ElfSectFlagAlloc + ElfSectFlagExec:
s->type = STEXT;

View File

@@ -1,117 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Automatic symbol generation.
// TODO(rsc): Handle go.typelink, go.track symbols.
// TODO(rsc): Do not handle $f64. and $f32. symbols. Instead, generate those
// from the compiler and assemblers as dupok data, and then remove autoData below.
package main
import (
"debug/goobj"
"strconv"
"strings"
)
// linkerDefined lists the symbols supplied by other parts of the linker
// (runtime.go and layout.go).
var linkerDefined = map[string]bool{
"runtime.bss": true,
"runtime.data": true,
"runtime.ebss": true,
"runtime.edata": true,
"runtime.efunctab": true,
"runtime.end": true,
"runtime.enoptrbss": true,
"runtime.enoptrdata": true,
"runtime.erodata": true,
"runtime.etext": true,
"runtime.etypelink": true,
"runtime.functab": true,
"runtime.gcbss": true,
"runtime.gcdata": true,
"runtime.noptrbss": true,
"runtime.noptrdata": true,
"runtime.pclntab": true,
"runtime.rodata": true,
"runtime.text": true,
"runtime.typelink": true,
}
// isAuto reports whether sym is an automatically-generated data or constant symbol.
func (p *Prog) isAuto(sym goobj.SymID) bool {
return strings.HasPrefix(sym.Name, "go.weak.") ||
strings.HasPrefix(sym.Name, "$f64.") ||
strings.HasPrefix(sym.Name, "$f32.") ||
linkerDefined[sym.Name]
}
// autoData defines the automatically generated data symbols needed by p.
func (p *Prog) autoData() {
for sym := range p.Missing {
switch {
// Floating-point constants that need to be loaded from memory are
// written as $f64.{16 hex digits} or $f32.{8 hex digits}; the hex digits
// give the IEEE bit pattern of the constant. As far as the layout into
// memory is concerned, we interpret these as uint64 or uint32 constants.
case strings.HasPrefix(sym.Name, "$f64."), strings.HasPrefix(sym.Name, "$f32."):
size := 64
if sym.Name[2:4] == "32" {
size = 32
}
delete(p.Missing, sym)
fbits, err := strconv.ParseUint(sym.Name[len("$f64."):], 16, size)
if err != nil {
p.errorf("unexpected floating point symbol %s", sym)
continue
}
data := make([]byte, size/8)
if size == 64 {
p.byteorder.PutUint64(data, fbits)
} else {
p.byteorder.PutUint32(data, uint32(fbits))
}
p.addSym(&Sym{
Sym: &goobj.Sym{
SymID: sym,
Kind: goobj.SRODATA,
Size: size / 8,
},
Bytes: data,
})
}
}
}
// autoConst defines the automatically generated constant symbols needed by p.
func (p *Prog) autoConst() {
for sym := range p.Missing {
switch {
case strings.HasPrefix(sym.Name, "go.weak."):
// weak symbol resolves to actual symbol if present, or else nil.
delete(p.Missing, sym)
targ := sym
targ.Name = sym.Name[len("go.weak."):]
var addr Addr
if s := p.Syms[targ]; s != nil {
addr = s.Addr
}
p.defineConst(sym.Name, addr)
}
}
}
// defineConst defines a new symbol with the given name and constant address.
func (p *Prog) defineConst(name string, addr Addr) {
sym := goobj.SymID{Name: name}
p.addSym(&Sym{
Sym: &goobj.Sym{
SymID: sym,
Kind: goobj.SCONST,
},
Package: nil,
Addr: addr,
})
}

View File

@@ -1,72 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test for auto-generated symbols.
// There is no test for $f64. and $f32. symbols, because those are
// not possible to write in the assembler syntax. Instead of changing
// the assembler to allow that, we plan to change the compilers
// not to generate such symbols (plain dupok data is sufficient).
package main
import (
"bytes"
"debug/goobj"
"testing"
)
// Each test case is an object file, generated from a corresponding .s file.
// The image of the autotab symbol should be a sequence of pairs of
// identical 8-byte sequences.
var autoTests = []string{
"testdata/autosection.6",
"testdata/autoweak.6",
}
func TestAuto(t *testing.T) {
for _, obj := range autoTests {
p := Prog{GOOS: "darwin", GOARCH: "amd64", StartSym: "start"}
p.omitRuntime = true
p.Error = func(s string) { t.Error(s) }
var buf bytes.Buffer
p.link(&buf, obj)
if p.NumError > 0 {
continue // already reported
}
const name = "autotab"
sym := p.Syms[goobj.SymID{Name: name}]
if sym == nil {
t.Errorf("%s is missing %s symbol", obj, name)
return
}
if sym.Size == 0 {
return
}
seg := sym.Section.Segment
off := sym.Addr - seg.VirtAddr
data := seg.Data[off : off+Addr(sym.Size)]
if len(data)%16 != 0 {
t.Errorf("%s: %s.Size = %d, want multiple of 16", obj, name, len(data))
return
}
Data:
for i := 0; i < len(data); i += 16 {
have := p.byteorder.Uint64(data[i : i+8])
want := p.byteorder.Uint64(data[i+8 : i+16])
if have != want {
// Look for relocation so we can explain what went wrong.
for _, r := range sym.Reloc {
if r.Offset == i {
t.Errorf("%s: %s+%#x: %s: have %#x want %#x", obj, name, i, r.Sym, have, want)
continue Data
}
}
t.Errorf("%s: %s+%#x: have %#x want %#x", obj, name, i, have, want)
}
}
}
}

View File

@@ -1,74 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Removal of dead code and data.
package main
import "debug/goobj"
// dead removes unreachable code and data from the program.
// It is basically a mark-sweep garbage collection: traverse all the
// symbols reachable from the entry (startSymID) and then delete
// the rest.
func (p *Prog) dead() {
p.Dead = make(map[goobj.SymID]bool)
reachable := make(map[goobj.SymID]bool)
p.walkDead(p.startSym, reachable)
for sym := range p.Syms {
if !reachable[sym] {
delete(p.Syms, sym)
p.Dead[sym] = true
}
}
for sym := range p.Missing {
if !reachable[sym] {
delete(p.Missing, sym)
p.Dead[sym] = true
}
}
p.SymOrder = removeDead(p.SymOrder, reachable)
for _, pkg := range p.Packages {
pkg.Syms = removeDead(pkg.Syms, reachable)
}
}
// walkDead traverses the symbols reachable from sym, adding them to reachable.
// The caller has verified that reachable[sym] = false.
func (p *Prog) walkDead(sym goobj.SymID, reachable map[goobj.SymID]bool) {
reachable[sym] = true
s := p.Syms[sym]
if s == nil {
return
}
for i := range s.Reloc {
r := &s.Reloc[i]
if !reachable[r.Sym] {
p.walkDead(r.Sym, reachable)
}
}
if s.Func != nil {
for _, fdata := range s.Func.FuncData {
if fdata.Sym.Name != "" && !reachable[fdata.Sym] {
p.walkDead(fdata.Sym, reachable)
}
}
}
}
// removeDead removes unreachable (dead) symbols from syms,
// returning a shortened slice using the same underlying array.
func removeDead(syms []*Sym, reachable map[goobj.SymID]bool) []*Sym {
keep := syms[:0]
for _, sym := range syms {
if reachable[sym.SymID] {
keep = append(keep, sym)
}
}
return keep
}

View File

@@ -1,97 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"debug/goobj"
"reflect"
"strings"
"testing"
)
// Each test case is an object file, generated from a corresponding .s file.
// The symbols in the object file with a dead_ prefix are the ones that
// should be removed from the program.
var deadTests = []string{
"testdata/dead.6",
}
func TestDead(t *testing.T) {
for _, obj := range deadTests {
p := Prog{GOOS: "darwin", GOARCH: "amd64", StartSym: "start"}
p.omitRuntime = true
p.Error = func(s string) { t.Error(s) }
p.init()
p.scan(obj)
if p.NumError > 0 {
continue // already reported
}
origSyms := copyMap(p.Syms)
origMissing := copyMap(p.Missing)
origSymOrder := copySlice(p.SymOrder)
origPkgSyms := copySlice(p.Packages["main"].Syms)
p.dead()
checkDeadMap(t, obj, "p.Syms", origSyms, p.Syms)
checkDeadMap(t, obj, "p.Missing", origMissing, p.Missing)
checkDeadSlice(t, obj, "p.SymOrder", origSymOrder, p.SymOrder)
checkDeadSlice(t, obj, `p.Packages["main"].Syms`, origPkgSyms, p.Packages["main"].Syms)
}
}
func copyMap(m interface{}) interface{} {
v := reflect.ValueOf(m)
out := reflect.MakeMap(v.Type())
for _, key := range v.MapKeys() {
out.SetMapIndex(key, v.MapIndex(key))
}
return out.Interface()
}
func checkDeadMap(t *testing.T, obj, name string, old, new interface{}) {
vold := reflect.ValueOf(old)
vnew := reflect.ValueOf(new)
for _, vid := range vold.MapKeys() {
id := vid.Interface().(goobj.SymID)
if strings.HasPrefix(id.Name, "dead_") {
if vnew.MapIndex(vid).IsValid() {
t.Errorf("%s: %s contains unnecessary symbol %s", obj, name, id)
}
} else {
if !vnew.MapIndex(vid).IsValid() {
t.Errorf("%s: %s is missing symbol %s", obj, name, id)
}
}
}
for _, vid := range vnew.MapKeys() {
id := vid.Interface().(goobj.SymID)
if !vold.MapIndex(vid).IsValid() {
t.Errorf("%s: %s contains unexpected symbol %s", obj, name, id)
}
}
}
func copySlice(x []*Sym) (out []*Sym) {
return append(out, x...)
}
func checkDeadSlice(t *testing.T, obj, name string, old, new []*Sym) {
for i, s := range old {
if strings.HasPrefix(s.Name, "dead_") {
continue
}
if len(new) == 0 {
t.Errorf("%s: %s is missing symbol %s\nhave%v\nwant%v", obj, name, s, new, old[i:])
return
}
if new[0].SymID != s.SymID {
t.Errorf("%s: %s is incorrect: have %s, want %s\nhave%v\nwant%v", obj, name, new[0].SymID, s.SymID, new, old[i:])
return
}
new = new[1:]
}
if len(new) > 0 {
t.Errorf("%s: %s has unexpected symbols: %v", obj, name, new)
}
}

View File

@@ -1,11 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Generation of debug data structures (in the executable but not mapped at run time).
// See also runtime.go.
package main
func (p *Prog) debug() {
}

View File

@@ -1,74 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"encoding/hex"
"fmt"
"io/ioutil"
"regexp"
"strconv"
"strings"
"testing"
)
// mustParseHexdumpFile returns a block of data generated by
// parsing the hex dump in the named file.
// If the file cannot be read or does not contain a valid hex dump,
// mustParseHexdumpFile calls t.Fatal.
func mustParseHexdumpFile(t *testing.T, file string) []byte {
hex, err := ioutil.ReadFile(file)
if err != nil {
t.Fatal(err)
}
data, err := parseHexdump(string(hex))
if err != nil {
t.Fatal(err)
}
return data
}
// parseHexdump parses the hex dump in text, which should be the
// output of "hexdump -C" or Plan 9's "xd -b",
// and returns the original data used to produce the dump.
// It is meant to enable storing golden binary files as text, so that
// changes to the golden files can be seen during code reviews.
func parseHexdump(text string) ([]byte, error) {
var out []byte
for _, line := range strings.Split(text, "\n") {
if i := strings.Index(line, "|"); i >= 0 { // remove text dump
line = line[:i]
}
f := strings.Fields(line)
if len(f) > 1+16 {
return nil, fmt.Errorf("parsing hex dump: too many fields on line %q", line)
}
if len(f) == 0 || len(f) == 1 && f[0] == "*" { // all zeros block omitted
continue
}
addr64, err := strconv.ParseUint(f[0], 16, 0)
if err != nil {
return nil, fmt.Errorf("parsing hex dump: invalid address %q", f[0])
}
addr := int(addr64)
if len(out) < addr {
out = append(out, make([]byte, addr-len(out))...)
}
for _, x := range f[1:] {
val, err := strconv.ParseUint(x, 16, 8)
if err != nil {
return nil, fmt.Errorf("parsing hexdump: invalid hex byte %q", x)
}
out = append(out, byte(val))
}
}
return out, nil
}
func hexdump(data []byte) string {
text := hex.Dump(data) + fmt.Sprintf("%08x\n", len(data))
text = regexp.MustCompile(`\n([0-9a-f]+(\s+00){16}.*\n)+`).ReplaceAllString(text, "\n*\n")
return text
}

View File

@@ -1,180 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Executable image layout - address assignment.
package main
import (
"debug/goobj"
)
// A layoutSection describes a single section to add to the
// final executable. Go binaries only have a fixed set of possible
// sections, and the symbol kind determines the section.
type layoutSection struct {
Segment string
Section string
Kind goobj.SymKind
Index int
}
// layout defines the layout of the generated Go executable.
// The order of entries here is the order in the executable.
// Entries with the same Segment name must be contiguous.
var layout = []layoutSection{
{Segment: "text", Section: "text", Kind: goobj.STEXT},
{Segment: "rodata", Section: "rodata", Kind: goobj.SRODATA},
{Segment: "rodata", Section: "functab", Kind: goobj.SPCLNTAB},
{Segment: "rodata", Section: "typelink", Kind: goobj.STYPELINK},
{Segment: "data", Section: "noptrdata", Kind: goobj.SNOPTRDATA},
{Segment: "data", Section: "data", Kind: goobj.SDATA},
{Segment: "data", Section: "bss", Kind: goobj.SBSS},
{Segment: "data", Section: "noptrbss", Kind: goobj.SNOPTRBSS},
// Later:
// {"rodata", "type", goobj.STYPE},
// {"rodata", "string", goobj.SSTRING},
// {"rodata", "gostring", goobj.SGOSTRING},
// {"rodata", "gofunc", goobj.SGOFUNC},
}
// layoutByKind maps from SymKind to an entry in layout.
var layoutByKind []*layoutSection
func init() {
// Build index from symbol type to layout entry.
max := 0
for _, sect := range layout {
if max <= int(sect.Kind) {
max = int(sect.Kind) + 1
}
}
layoutByKind = make([]*layoutSection, max)
for i := range layout {
sect := &layout[i]
layoutByKind[sect.Kind] = sect
sect.Index = i
}
}
// layout arranges symbols into sections and sections into segments,
// and then it assigns addresses to segments, sections, and symbols.
func (p *Prog) layout() {
sections := make([]*Section, len(layout))
// Assign symbols to sections using index, creating sections as needed.
// Could keep sections separated by type during input instead.
for _, sym := range p.SymOrder {
kind := sym.Kind
if kind < 0 || int(kind) >= len(layoutByKind) || layoutByKind[kind] == nil {
p.errorf("%s: unexpected symbol kind %v", sym.SymID, kind)
continue
}
lsect := layoutByKind[kind]
sect := sections[lsect.Index]
if sect == nil {
sect = &Section{
Name: lsect.Section,
Align: 1,
}
sections[lsect.Index] = sect
}
if sym.Data.Size > 0 || len(sym.Bytes) > 0 {
sect.InFile = true
}
sym.Section = sect
sect.Syms = append(sect.Syms, sym)
// TODO(rsc): Incorporate alignment information.
// First that information needs to be added to the object files.
//
// if sect.Align < Addr(sym.Align) {
// sect.Align = Addr(sym.Align)
// }
}
// Assign sections to segments, creating segments as needed.
var seg *Segment
for i, sect := range sections {
if sect == nil {
continue
}
segName := layout[i].Segment
// Special case: Mach-O does not support "rodata" segment,
// so store read-only data in text segment.
if p.GOOS == "darwin" && segName == "rodata" {
segName = "text"
}
if seg == nil || seg.Name != segName {
seg = &Segment{
Name: segName,
}
p.Segments = append(p.Segments, seg)
}
sect.Segment = seg
seg.Sections = append(seg.Sections, sect)
}
// Assign addresses.
// TODO(rsc): This choice needs to be informed by both
// the formatter and the target architecture.
// And maybe eventually a command line flag (sigh).
const segAlign = 4096
// TODO(rsc): Use a larger amount on most systems, which will let the
// compiler eliminate more nil checks.
if p.UnmappedSize == 0 {
p.UnmappedSize = segAlign
}
// TODO(rsc): addr := Addr(0) when generating a shared library or PIE.
addr := p.UnmappedSize
// Account for initial file header.
hdrVirt, hdrFile := p.formatter.headerSize(p)
addr += hdrVirt
// Assign addresses to segments, sections, symbols.
// Assign sizes to segments, sections.
startVirt := addr
startFile := hdrFile
for _, seg := range p.Segments {
addr = round(addr, segAlign)
seg.VirtAddr = addr
seg.FileOffset = startFile + seg.VirtAddr - startVirt
for _, sect := range seg.Sections {
addr = round(addr, sect.Align)
sect.VirtAddr = addr
for _, sym := range sect.Syms {
// TODO(rsc): Respect alignment once we have that information.
sym.Addr = addr
addr += Addr(sym.Size)
}
sect.Size = addr - sect.VirtAddr
if sect.InFile {
seg.FileSize = addr - seg.VirtAddr
}
}
seg.VirtSize = addr - seg.VirtAddr
}
// Define symbols for section names.
var progEnd Addr
for i, sect := range sections {
name := layout[i].Section
var start, end Addr
if sect != nil {
start = sect.VirtAddr
end = sect.VirtAddr + sect.Size
}
p.defineConst("runtime."+name, start)
p.defineConst("runtime.e"+name, end)
progEnd = end
}
p.defineConst("runtime.end", progEnd)
}

View File

@@ -1,45 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"bytes"
"strings"
"testing"
)
func TestLayout(t *testing.T) {
p := Prog{GOOS: "darwin", GOARCH: "amd64", StartSym: "text_start"}
p.omitRuntime = true
p.Error = func(s string) { t.Error(s) }
var buf bytes.Buffer
const obj = "testdata/layout.6"
p.link(&buf, obj)
if p.NumError > 0 {
return // already reported
}
if len(p.Dead) > 0 {
t.Errorf("%s: unexpected dead symbols %v", obj, p.Dead)
return
}
for _, sym := range p.SymOrder {
if p.isAuto(sym.SymID) {
continue
}
if sym.Section == nil {
t.Errorf("%s: symbol %s is missing section", obj, sym)
continue
}
i := strings.Index(sym.Name, "_")
if i < 0 {
t.Errorf("%s: unexpected symbol %s", obj, sym)
continue
}
if sym.Section.Name != sym.Name[:i] {
t.Errorf("%s: symbol %s in section %s, want %s", obj, sym, sym.Section.Name, sym.Name[:i])
}
}
}

View File

@@ -1,35 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"bytes"
"debug/goobj"
"io/ioutil"
"testing"
)
func TestLinkHello(t *testing.T) {
p := &Prog{
GOOS: "darwin",
GOARCH: "amd64",
Error: func(s string) { t.Error(s) },
StartSym: "_rt0_go",
}
var buf bytes.Buffer
p.link(&buf, "testdata/hello.6")
if p.NumError > 0 {
return
}
if p.Syms[goobj.SymID{"_rt0_go", 0}] == nil || p.Syms[goobj.SymID{"hello", 1}] == nil {
t.Errorf("Syms = %v, want at least [_rt0_go hello<1>]", p.Syms)
}
// uncomment to leave file behind for execution:
if false {
ioutil.WriteFile("a.out", buf.Bytes(), 0777)
}
checkGolden(t, buf.Bytes(), "testdata/link.hello.darwin.amd64")
}

View File

@@ -1,116 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Loading of code and data fragments from package files into final image.
package main
import "os"
// load allocates segment images, populates them with data
// read from package files, and applies relocations to the data.
func (p *Prog) load() {
// TODO(rsc): mmap the output file and store the data directly.
// That will make writing the output file more efficient.
for _, seg := range p.Segments {
seg.Data = make([]byte, seg.FileSize)
}
for _, pkg := range p.Packages {
p.loadPackage(pkg)
}
}
// loadPackage loads and relocates data for all the
// symbols needed in the given package.
func (p *Prog) loadPackage(pkg *Package) {
if pkg.File == "" {
// This "package" contains internally generated symbols only.
// All such symbols have a sym.Bytes field holding the actual data
// (if any), plus relocations.
for _, sym := range pkg.Syms {
if sym.Bytes == nil {
continue
}
seg := sym.Section.Segment
off := sym.Addr - seg.VirtAddr
data := seg.Data[off : off+Addr(sym.Size)]
copy(data, sym.Bytes)
p.relocateSym(sym, data)
}
return
}
// Package stored in file.
f, err := os.Open(pkg.File)
if err != nil {
p.errorf("%v", err)
return
}
defer f.Close()
// TODO(rsc): Mmap file into memory.
for _, sym := range pkg.Syms {
if sym.Data.Size == 0 {
continue
}
// TODO(rsc): If not using mmap, at least coalesce nearby reads.
if sym.Section == nil {
p.errorf("internal error: missing section for %s", sym.Name)
}
seg := sym.Section.Segment
off := sym.Addr - seg.VirtAddr
if off >= Addr(len(seg.Data)) || off+Addr(sym.Data.Size) > Addr(len(seg.Data)) {
p.errorf("internal error: allocated space for %s too small: %d bytes for %d+%d (%d)", sym, len(seg.Data), off, sym.Data.Size, sym.Size)
}
data := seg.Data[off : off+Addr(sym.Data.Size)]
_, err := f.ReadAt(data, sym.Data.Offset)
if err != nil {
p.errorf("reading %v: %v", sym.SymID, err)
}
p.relocateSym(sym, data)
}
}
// TODO(rsc): Define full enumeration for relocation types.
const (
R_ADDR = 1
R_SIZE = 2
R_CALL = 3
R_CALLARM = 4
R_CALLIND = 5
R_CONST = 6
R_PCREL = 7
)
// relocateSym applies relocations to sym's data.
func (p *Prog) relocateSym(sym *Sym, data []byte) {
for i := range sym.Reloc {
r := &sym.Reloc[i]
targ := p.Syms[r.Sym]
if targ == nil {
p.errorf("%v: reference to undefined symbol %v", sym, r.Sym)
continue
}
val := targ.Addr + Addr(r.Add)
switch r.Type {
default:
p.errorf("%v: unknown relocation type %d", sym, r.Type)
case R_ADDR, R_CALLIND:
// ok
case R_PCREL, R_CALL:
val -= sym.Addr + Addr(r.Offset+r.Size)
}
frag := data[r.Offset : r.Offset+r.Size]
switch r.Size {
default:
p.errorf("%v: unknown relocation size %d", sym, r.Size)
case 4:
// TODO(rsc): Check for overflow?
p.byteorder.PutUint32(frag, uint32(val))
case 8:
p.byteorder.PutUint64(frag, uint64(val))
}
}
}

View File

@@ -1,380 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Mach-O (Darwin) object file writing.
package main
import (
"debug/macho"
"encoding/binary"
"io"
"strings"
)
// machoFormat is the implementation of formatter.
type machoFormat struct{}
// machoHeader and friends are data structures
// corresponding to the Mach-O file header
// to be written to disk.
const (
macho64Bit = 1 << 24
machoSubCPU386 = 3
)
// machoArch describes a Mach-O target architecture.
type machoArch struct {
CPU uint32
SubCPU uint32
}
// machoHeader is the Mach-O file header.
type machoHeader struct {
machoArch
FileType uint32
Loads []*machoLoad
Segments []*machoSegment
p *Prog // for reporting errors
}
// machoLoad is a Mach-O load command.
type machoLoad struct {
Type uint32
Data []uint32
}
// machoSegment is a Mach-O segment.
type machoSegment struct {
Name string
VirtAddr Addr
VirtSize Addr
FileOffset Addr
FileSize Addr
Prot1 uint32
Prot2 uint32
Flags uint32
Sections []*machoSection
}
// machoSection is a Mach-O section, inside a segment.
type machoSection struct {
Name string
Segment string
Addr Addr
Size Addr
Offset uint32
Align uint32
Reloc uint32
Nreloc uint32
Flags uint32
Res1 uint32
Res2 uint32
}
// layout positions the segments and sections in p
// to make room for the Mach-O file header.
// That is, it edits their VirtAddr fields to adjust for the presence
// of the Mach-O header at the beginning of the address space.
func (machoFormat) headerSize(p *Prog) (virt, file Addr) {
var h machoHeader
h.init(p)
size := Addr(h.size())
size = round(size, 4096)
p.HeaderSize = size
return size, size
}
// write writes p to w as a Mach-O executable.
// layout(p) must have already been called,
// and the number, sizes, and addresses of the segments
// and sections must not have been modified since the call.
func (machoFormat) write(w io.Writer, p *Prog) {
var h machoHeader
h.init(p)
off := Addr(0)
enc := h.encode()
w.Write(enc)
off += Addr(len(enc))
for _, seg := range p.Segments {
if seg.FileOffset < off {
h.p.errorf("mach-o error: invalid file offset")
}
w.Write(make([]byte, int(seg.FileOffset-off)))
if seg.FileSize != Addr(len(seg.Data)) {
h.p.errorf("mach-o error: invalid file size")
}
w.Write(seg.Data)
off = seg.FileOffset + Addr(len(seg.Data))
}
}
// Conversion of Prog to macho data structures.
// machoArches maps from GOARCH to machoArch.
var machoArches = map[string]machoArch{
"amd64": {
CPU: uint32(macho.CpuAmd64),
SubCPU: uint32(machoSubCPU386),
},
}
// init initializes the header h to describe p.
func (h *machoHeader) init(p *Prog) {
h.p = p
h.Segments = nil
h.Loads = nil
var ok bool
h.machoArch, ok = machoArches[p.GOARCH]
if !ok {
p.errorf("mach-o: unknown target GOARCH %q", p.GOARCH)
return
}
h.FileType = uint32(macho.TypeExec)
mseg := h.addSegment(p, "__PAGEZERO", nil)
mseg.VirtSize = p.UnmappedSize
for _, seg := range p.Segments {
h.addSegment(p, "__"+strings.ToUpper(seg.Name), seg)
}
var data []uint32
switch h.CPU {
default:
p.errorf("mach-o: unknown cpu %#x for GOARCH %q", h.CPU, p.GOARCH)
case uint32(macho.CpuAmd64):
data = make([]uint32, 2+42)
data[0] = 4 // thread type
data[1] = 42 // word count
data[2+32] = uint32(p.Entry) // RIP register, in two parts
data[2+32+1] = uint32(p.Entry >> 32)
}
h.Loads = append(h.Loads, &machoLoad{
Type: uint32(macho.LoadCmdUnixThread),
Data: data,
})
}
// addSegment adds to h a Mach-O segment like seg with the given name.
func (h *machoHeader) addSegment(p *Prog, name string, seg *Segment) *machoSegment {
mseg := &machoSegment{
Name: name,
}
h.Segments = append(h.Segments, mseg)
if seg == nil {
return mseg
}
mseg.VirtAddr = seg.VirtAddr
mseg.VirtSize = seg.VirtSize
mseg.FileOffset = round(seg.FileOffset, 4096)
mseg.FileSize = seg.FileSize
if name == "__TEXT" {
// Initially RWX, then just RX
mseg.Prot1 = 7
mseg.Prot2 = 5
// Text segment maps Mach-O header, needed by dynamic linker.
mseg.VirtAddr -= p.HeaderSize
mseg.VirtSize += p.HeaderSize
mseg.FileOffset -= p.HeaderSize
mseg.FileSize += p.HeaderSize
} else {
// RW
mseg.Prot1 = 3
mseg.Prot2 = 3
}
for _, sect := range seg.Sections {
h.addSection(mseg, seg, sect)
}
return mseg
}
// addSection adds to mseg a Mach-O section like sect, inside seg, with the given name.
func (h *machoHeader) addSection(mseg *machoSegment, seg *Segment, sect *Section) {
msect := &machoSection{
Name: "__" + sect.Name,
Segment: mseg.Name,
// Reloc: sect.RelocOffset,
// NumReloc: sect.RelocLen / 8,
Addr: sect.VirtAddr,
Size: sect.Size,
}
mseg.Sections = append(mseg.Sections, msect)
for 1<<msect.Align < sect.Align {
msect.Align++
}
if off := sect.VirtAddr - seg.VirtAddr; off < seg.FileSize {
// Data in file.
if sect.Size > seg.FileSize-off {
h.p.errorf("mach-o error: section crosses file boundary")
}
msect.Offset = uint32(seg.FileOffset + off)
} else {
// Zero filled.
msect.Flags |= 1
}
if sect.Name == "text" {
msect.Flags |= 0x400 // contains executable instructions
}
}
// A machoWriter helps write Mach-O headers.
// It is basically a buffer with some helper routines for writing integers.
type machoWriter struct {
dst []byte
tmp [8]byte
order binary.ByteOrder
is64 bool
p *Prog
}
// if64 returns x if w is writing a 64-bit object file; otherwise it returns y.
func (w *machoWriter) if64(x, y interface{}) interface{} {
if w.is64 {
return x
}
return y
}
// encode encodes each of the given arguments into the writer.
// It encodes uint32, []uint32, uint64, and []uint64 by writing each value
// in turn in the correct byte order for the output file.
// It encodes an Addr as a uint64 if writing a 64-bit output file, or else as a uint32.
// It encodes []byte and string by writing the raw bytes (no length prefix).
// It skips nil values in the args list.
func (w *machoWriter) encode(args ...interface{}) {
for _, arg := range args {
switch arg := arg.(type) {
default:
w.p.errorf("mach-o error: cannot encode %T", arg)
case nil:
// skip
case []byte:
w.dst = append(w.dst, arg...)
case string:
w.dst = append(w.dst, arg...)
case uint32:
w.order.PutUint32(w.tmp[:], arg)
w.dst = append(w.dst, w.tmp[:4]...)
case []uint32:
for _, x := range arg {
w.order.PutUint32(w.tmp[:], x)
w.dst = append(w.dst, w.tmp[:4]...)
}
case uint64:
w.order.PutUint64(w.tmp[:], arg)
w.dst = append(w.dst, w.tmp[:8]...)
case Addr:
if w.is64 {
w.order.PutUint64(w.tmp[:], uint64(arg))
w.dst = append(w.dst, w.tmp[:8]...)
} else {
if Addr(uint32(arg)) != arg {
w.p.errorf("mach-o error: truncating address %#x to uint32", arg)
}
w.order.PutUint32(w.tmp[:], uint32(arg))
w.dst = append(w.dst, w.tmp[:4]...)
}
}
}
}
// segmentSize returns the size of the encoding of seg in bytes.
func (w *machoWriter) segmentSize(seg *machoSegment) int {
if w.is64 {
return 18*4 + 20*4*len(seg.Sections)
}
return 14*4 + 22*4*len(seg.Sections)
}
// zeroPad returns the string s truncated or padded with NULs to n bytes.
func zeroPad(s string, n int) string {
if len(s) >= n {
return s[:n]
}
return s + strings.Repeat("\x00", n-len(s))
}
// size returns the encoded size of the header.
func (h *machoHeader) size() int {
// Could write separate code, but encoding is cheap; encode and throw it away.
return len(h.encode())
}
// encode returns the Mach-O encoding of the header.
func (h *machoHeader) encode() []byte {
w := &machoWriter{p: h.p}
w.is64 = h.CPU&macho64Bit != 0
w.order = w.p.byteorder
loadSize := 0
for _, seg := range h.Segments {
loadSize += w.segmentSize(seg)
}
for _, l := range h.Loads {
loadSize += 4 * (2 + len(l.Data))
}
w.encode(
w.if64(macho.Magic64, macho.Magic32),
uint32(h.CPU),
uint32(h.SubCPU),
uint32(h.FileType),
uint32(len(h.Loads)+len(h.Segments)),
uint32(loadSize),
uint32(1),
w.if64(uint32(0), nil),
)
for _, seg := range h.Segments {
w.encode(
w.if64(uint32(macho.LoadCmdSegment64), uint32(macho.LoadCmdSegment)),
uint32(w.segmentSize(seg)),
zeroPad(seg.Name, 16),
seg.VirtAddr,
seg.VirtSize,
seg.FileOffset,
seg.FileSize,
seg.Prot1,
seg.Prot2,
uint32(len(seg.Sections)),
seg.Flags,
)
for _, sect := range seg.Sections {
w.encode(
zeroPad(sect.Name, 16),
zeroPad(seg.Name, 16),
sect.Addr,
sect.Size,
sect.Offset,
sect.Align,
sect.Reloc,
sect.Nreloc,
sect.Flags,
sect.Res1,
sect.Res2,
w.if64(uint32(0), nil),
)
}
}
for _, load := range h.Loads {
w.encode(
load.Type,
uint32(4*(2+len(load.Data))),
load.Data,
)
}
return w.dst
}

View File

@@ -1,407 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"bytes"
"debug/macho"
"encoding/binary"
"fmt"
"io/ioutil"
"strings"
"testing"
)
// Test macho writing by checking that each generated prog can be written
// and then read back using debug/macho to get the same prog.
// Also check against golden testdata file.
var machoWriteTests = []struct {
name string
golden bool
prog *Prog
}{
// amd64 exit 9
{
name: "exit9",
golden: true,
prog: &Prog{
GOARCH: "amd64",
GOOS: "darwin",
UnmappedSize: 0x1000,
Entry: 0x1000,
Segments: []*Segment{
{
Name: "text",
VirtAddr: 0x1000,
VirtSize: 13,
FileOffset: 0,
FileSize: 13,
Data: []byte{
0xb8, 0x01, 0x00, 0x00, 0x02, // MOVL $0x2000001, AX
0xbf, 0x09, 0x00, 0x00, 0x00, // MOVL $9, DI
0x0f, 0x05, // SYSCALL
0xf4, // HLT
},
Sections: []*Section{
{
Name: "text",
VirtAddr: 0x1000,
Size: 13,
Align: 64,
},
},
},
},
},
},
// amd64 write hello world & exit 9
{
name: "hello",
golden: true,
prog: &Prog{
GOARCH: "amd64",
GOOS: "darwin",
UnmappedSize: 0x1000,
Entry: 0x1000,
Segments: []*Segment{
{
Name: "text",
VirtAddr: 0x1000,
VirtSize: 35,
FileOffset: 0,
FileSize: 35,
Data: []byte{
0xb8, 0x04, 0x00, 0x00, 0x02, // MOVL $0x2000001, AX
0xbf, 0x01, 0x00, 0x00, 0x00, // MOVL $1, DI
0xbe, 0x00, 0x30, 0x00, 0x00, // MOVL $0x3000, SI
0xba, 0x0c, 0x00, 0x00, 0x00, // MOVL $12, DX
0x0f, 0x05, // SYSCALL
0xb8, 0x01, 0x00, 0x00, 0x02, // MOVL $0x2000001, AX
0xbf, 0x09, 0x00, 0x00, 0x00, // MOVL $9, DI
0x0f, 0x05, // SYSCALL
0xf4, // HLT
},
Sections: []*Section{
{
Name: "text",
VirtAddr: 0x1000,
Size: 35,
Align: 64,
},
},
},
{
Name: "data",
VirtAddr: 0x2000,
VirtSize: 12,
FileOffset: 0x1000,
FileSize: 12,
Data: []byte("hello world\n"),
Sections: []*Section{
{
Name: "data",
VirtAddr: 0x2000,
Size: 12,
Align: 64,
},
},
},
},
},
},
// amd64 write hello world from rodata & exit 0
{
name: "helloro",
golden: true,
prog: &Prog{
GOARCH: "amd64",
GOOS: "darwin",
UnmappedSize: 0x1000,
Entry: 0x1000,
Segments: []*Segment{
{
Name: "text",
VirtAddr: 0x1000,
VirtSize: 0x100c,
FileOffset: 0,
FileSize: 0x100c,
Data: concat(
[]byte{
0xb8, 0x04, 0x00, 0x00, 0x02, // MOVL $0x2000001, AX
0xbf, 0x01, 0x00, 0x00, 0x00, // MOVL $1, DI
0xbe, 0x00, 0x30, 0x00, 0x00, // MOVL $0x3000, SI
0xba, 0x0c, 0x00, 0x00, 0x00, // MOVL $12, DX
0x0f, 0x05, // SYSCALL
0xb8, 0x01, 0x00, 0x00, 0x02, // MOVL $0x2000001, AX
0xbf, 0x00, 0x00, 0x00, 0x00, // MOVL $0, DI
0x0f, 0x05, // SYSCALL
0xf4, // HLT
},
make([]byte, 0x1000-35),
[]byte("hello world\n"),
),
Sections: []*Section{
{
Name: "text",
VirtAddr: 0x1000,
Size: 35,
Align: 64,
},
{
Name: "rodata",
VirtAddr: 0x2000,
Size: 12,
Align: 64,
},
},
},
},
},
},
}
func concat(xs ...[]byte) []byte {
var out []byte
for _, x := range xs {
out = append(out, x...)
}
return out
}
func TestMachoWrite(t *testing.T) {
for _, tt := range machoWriteTests {
name := tt.prog.GOARCH + "." + tt.name
prog := cloneProg(tt.prog)
prog.init()
var f machoFormat
vsize, fsize := f.headerSize(prog)
shiftProg(prog, vsize, fsize)
var buf bytes.Buffer
f.write(&buf, prog)
if false { // enable to debug
ioutil.WriteFile("a.out", buf.Bytes(), 0777)
}
read, err := machoRead(machoArches[tt.prog.GOARCH], buf.Bytes())
if err != nil {
t.Errorf("%s: reading mach-o output:\n\t%v", name, err)
continue
}
diffs := diffProg(read, prog)
if diffs != nil {
t.Errorf("%s: mismatched prog:\n\t%s", name, strings.Join(diffs, "\n\t"))
continue
}
if !tt.golden {
continue
}
checkGolden(t, buf.Bytes(), "testdata/macho."+name)
}
}
// machoRead reads the mach-o file in data and returns a corresponding prog.
func machoRead(arch machoArch, data []byte) (*Prog, error) {
f, err := macho.NewFile(bytes.NewReader(data))
if err != nil {
return nil, err
}
var errors []string
errorf := func(format string, args ...interface{}) {
errors = append(errors, fmt.Sprintf(format, args...))
}
magic := uint32(0xFEEDFACE)
if arch.CPU&macho64Bit != 0 {
magic |= 1
}
if f.Magic != magic {
errorf("header: Magic = %#x, want %#x", f.Magic, magic)
}
if f.Cpu != macho.CpuAmd64 {
errorf("header: CPU = %#x, want %#x", f.Cpu, macho.CpuAmd64)
}
if f.SubCpu != 3 {
errorf("header: SubCPU = %#x, want %#x", f.SubCpu, 3)
}
if f.Type != 2 {
errorf("header: FileType = %d, want %d", f.Type, 2)
}
if f.Flags != 1 {
errorf("header: Flags = %d, want %d", f.Flags, 1)
}
msects := f.Sections
var limit uint64
prog := new(Prog)
for _, load := range f.Loads {
switch load := load.(type) {
default:
errorf("unexpected macho load %T %x", load, load.Raw())
case macho.LoadBytes:
if len(load) < 8 || len(load)%4 != 0 {
errorf("unexpected load length %d", len(load))
continue
}
cmd := f.ByteOrder.Uint32(load)
switch macho.LoadCmd(cmd) {
default:
errorf("unexpected macho load cmd %s", macho.LoadCmd(cmd))
case macho.LoadCmdUnixThread:
data := make([]uint32, len(load[8:])/4)
binary.Read(bytes.NewReader(load[8:]), f.ByteOrder, data)
if len(data) != 44 {
errorf("macho thread len(data) = %d, want 42", len(data))
continue
}
if data[0] != 4 {
errorf("macho thread type = %d, want 4", data[0])
}
if data[1] != uint32(len(data))-2 {
errorf("macho thread desc len = %d, want %d", data[1], uint32(len(data))-2)
continue
}
for i, val := range data[2:] {
switch i {
default:
if val != 0 {
errorf("macho thread data[%d] = %#x, want 0", i, val)
}
case 32:
prog.Entry = Addr(val)
case 33:
prog.Entry |= Addr(val) << 32
}
}
}
case *macho.Segment:
if load.Addr < limit {
errorf("segments out of order: %q at %#x after %#x", load.Name, load.Addr, limit)
}
limit = load.Addr + load.Memsz
if load.Name == "__PAGEZERO" || load.Addr == 0 && load.Filesz == 0 {
if load.Name != "__PAGEZERO" {
errorf("segment with Addr=0, Filesz=0 is named %q, want %q", load.Name, "__PAGEZERO")
} else if load.Addr != 0 || load.Filesz != 0 {
errorf("segment %q has Addr=%#x, Filesz=%d, want Addr=%#x, Filesz=%d", load.Name, load.Addr, load.Filesz, 0, 0)
}
prog.UnmappedSize = Addr(load.Memsz)
continue
}
if !strings.HasPrefix(load.Name, "__") {
errorf("segment name %q does not begin with %q", load.Name, "__")
}
if strings.ToUpper(load.Name) != load.Name {
errorf("segment name %q is not all upper case", load.Name)
}
seg := &Segment{
Name: strings.ToLower(strings.TrimPrefix(load.Name, "__")),
VirtAddr: Addr(load.Addr),
VirtSize: Addr(load.Memsz),
FileOffset: Addr(load.Offset),
FileSize: Addr(load.Filesz),
}
prog.Segments = append(prog.Segments, seg)
data, err := load.Data()
if err != nil {
errorf("loading data from %q: %v", load.Name, err)
}
seg.Data = data
var maxprot, prot uint32
if load.Name == "__TEXT" {
maxprot, prot = 7, 5
} else {
maxprot, prot = 3, 3
}
if load.Maxprot != maxprot || load.Prot != prot {
errorf("segment %q protection is %d, %d, want %d, %d",
load.Name, load.Maxprot, load.Prot, maxprot, prot)
}
for len(msects) > 0 && msects[0].Addr < load.Addr+load.Memsz {
msect := msects[0]
msects = msects[1:]
if msect.Offset > 0 && prog.HeaderSize == 0 {
prog.HeaderSize = Addr(msect.Offset)
if seg.FileOffset != 0 {
errorf("initial segment %q does not map header", load.Name)
}
seg.VirtAddr += prog.HeaderSize
seg.VirtSize -= prog.HeaderSize
seg.FileOffset += prog.HeaderSize
seg.FileSize -= prog.HeaderSize
seg.Data = seg.Data[prog.HeaderSize:]
}
if msect.Addr < load.Addr {
errorf("section %q at address %#x is missing segment", msect.Name, msect.Addr)
continue
}
if !strings.HasPrefix(msect.Name, "__") {
errorf("section name %q does not begin with %q", msect.Name, "__")
}
if strings.ToLower(msect.Name) != msect.Name {
errorf("section name %q is not all lower case", msect.Name)
}
if msect.Seg != load.Name {
errorf("section %q is lists segment name %q, want %q",
msect.Name, msect.Seg, load.Name)
}
if uint64(msect.Offset) != uint64(load.Offset)+msect.Addr-load.Addr {
errorf("section %q file offset is %#x, want %#x",
msect.Name, msect.Offset, load.Offset+msect.Addr-load.Addr)
}
if msect.Reloff != 0 || msect.Nreloc != 0 {
errorf("section %q has reloff %d,%d, want %d,%d",
msect.Name, msect.Reloff, msect.Nreloc, 0, 0)
}
flags := uint32(0)
if msect.Name == "__text" {
flags = 0x400
}
if msect.Offset == 0 {
flags = 1
}
if msect.Flags != flags {
errorf("section %q flags = %#x, want %#x", msect.Name, msect.Flags, flags)
}
sect := &Section{
Name: strings.ToLower(strings.TrimPrefix(msect.Name, "__")),
VirtAddr: Addr(msect.Addr),
Size: Addr(msect.Size),
Align: 1 << msect.Align,
}
seg.Sections = append(seg.Sections, sect)
}
}
}
for _, msect := range msects {
errorf("section %q has no segment", msect.Name)
}
limit = 0
for _, msect := range f.Sections {
if msect.Addr < limit {
errorf("sections out of order: %q at %#x after %#x", msect.Name, msect.Addr, limit)
}
limit = msect.Addr + msect.Size
}
err = nil
if errors != nil {
err = fmt.Errorf("%s", strings.Join(errors, "\n\t"))
}
return prog, err
}

View File

@@ -1,9 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Placeholder to keep build building.
package main
func main() {}

View File

@@ -1,479 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Generation of runtime function information (pclntab).
package main
import (
"debug/goobj"
"encoding/binary"
"os"
"sort"
)
var zerofunc goobj.Func
// pclntab collects the runtime function data for each function that will
// be listed in the binary and builds a single table describing all functions.
// This table is used at run time for stack traces and to look up PC-specific
// information during garbage collection. The symbol created is named
// "pclntab" for historical reasons; the scope of the table has grown to
// include more than just PC/line number correspondences.
// The table format is documented at http://golang.org/s/go12symtab.
func (p *Prog) pclntab() {
// Count number of functions going into the binary,
// so that we can size the initial index correctly.
nfunc := 0
for _, sym := range p.SymOrder {
if sym.Kind != goobj.STEXT {
continue
}
nfunc++
}
// Table header.
buf := new(SymBuffer)
buf.Init(p)
buf.SetSize(8 + p.ptrsize)
off := 0
off = buf.Uint32(off, 0xfffffffb)
off = buf.Uint8(off, 0)
off = buf.Uint8(off, 0)
off = buf.Uint8(off, uint8(p.pcquantum))
off = buf.Uint8(off, uint8(p.ptrsize))
off = buf.Uint(off, uint64(nfunc), p.ptrsize)
indexOff := off
off += (nfunc*2 + 1) * p.ptrsize // function index, to be filled in
off += 4 // file table start offset, to be filled in
buf.SetSize(off)
// One-file cache for reading PCData tables from package files.
// TODO(rsc): Better I/O strategy.
var (
file *os.File
fname string
)
// Files gives the file numbering for source file names recorded
// in the binary.
files := make(map[string]int)
// Build the table, build the index, and build the file name numbering.
// The loop here must visit functions in the same order that they will
// be stored in the binary, or else binary search over the index will fail.
// The runtime checks that the index is sorted properly at program start time.
var lastSym *Sym
for _, sym := range p.SymOrder {
if sym.Kind != goobj.STEXT {
continue
}
lastSym = sym
// Treat no recorded function information same as all zeros.
f := sym.Func
if f == nil {
f = &zerofunc
}
// Open package file if needed, for reading PC data.
if fname != sym.Package.File {
if file != nil {
file.Close()
}
var err error
file, err = os.Open(sym.Package.File)
if err != nil {
p.errorf("%v: %v", sym, err)
return
}
fname = sym.Package.File
}
// off is the offset of the table entry where we're going to write
// the encoded form of Func.
// indexOff is the current position in the table index;
// we add an entry in the index pointing at off.
off = (buf.Size() + p.ptrsize - 1) &^ (p.ptrsize - 1)
indexOff = buf.Addr(indexOff, sym.SymID, 0)
indexOff = buf.Uint(indexOff, uint64(off), p.ptrsize)
// The Func encoding starts with a header giving offsets
// to data blobs, and then the data blobs themselves.
// end gives the current write position for the data blobs.
end := off + p.ptrsize + 3*4 + 5*4 + len(f.PCData)*4 + len(f.FuncData)*p.ptrsize
if len(f.FuncData) > 0 {
end += -end & (p.ptrsize - 1)
}
buf.SetSize(end)
// entry uintptr
// name int32
// args int32
// frame int32
//
// The frame recorded in the object file is
// the frame size used in an assembly listing, which does
// not include the caller PC on the stack.
// The frame size we want to list here is the delta from
// this function's SP to its caller's SP, which does include
// the caller PC. Add p.ptrsize to f.Frame to adjust.
// TODO(rsc): Record the same frame size in the object file.
off = buf.Addr(off, sym.SymID, 0)
off = buf.Uint32(off, uint32(addString(buf, sym.Name)))
off = buf.Uint32(off, uint32(f.Args))
off = buf.Uint32(off, uint32(f.Frame+p.ptrsize))
// pcdata
off = buf.Uint32(off, uint32(addPCTable(p, buf, file, f.PCSP)))
off = buf.Uint32(off, uint32(addPCFileTable(p, buf, file, f.PCFile, sym, files)))
off = buf.Uint32(off, uint32(addPCTable(p, buf, file, f.PCLine)))
off = buf.Uint32(off, uint32(len(f.PCData)))
off = buf.Uint32(off, uint32(len(f.FuncData)))
for _, pcdata := range f.PCData {
off = buf.Uint32(off, uint32(addPCTable(p, buf, file, pcdata)))
}
// funcdata
if len(f.FuncData) > 0 {
off += -off & (p.ptrsize - 1) // must be pointer-aligned
for _, funcdata := range f.FuncData {
if funcdata.Sym.Name == "" {
off = buf.Uint(off, uint64(funcdata.Offset), p.ptrsize)
} else {
off = buf.Addr(off, funcdata.Sym, funcdata.Offset)
}
}
}
if off != end {
p.errorf("internal error: invalid math in pclntab: off=%#x end=%#x", off, end)
break
}
}
if file != nil {
file.Close()
}
// Final entry of index is end PC of last function.
indexOff = buf.Addr(indexOff, lastSym.SymID, int64(lastSym.Size))
// Start file table.
// Function index is immediately followed by offset to file table.
off = (buf.Size() + p.ptrsize - 1) &^ (p.ptrsize - 1)
buf.Uint32(indexOff, uint32(off))
// File table is an array of uint32s.
// The first entry gives 1+n, the size of the array.
// The following n entries hold offsets to string data.
// File number n uses the string pointed at by entry n.
// File number 0 is invalid.
buf.SetSize(off + (1+len(files))*4)
buf.Uint32(off, uint32(1+len(files)))
var filestr []string
for file := range files {
filestr = append(filestr, file)
}
sort.Strings(filestr)
for _, file := range filestr {
id := files[file]
buf.Uint32(off+4*id, uint32(addString(buf, file)))
}
pclntab := &Sym{
Sym: &goobj.Sym{
SymID: goobj.SymID{Name: "runtime.pclntab"},
Kind: goobj.SPCLNTAB,
Size: buf.Size(),
Reloc: buf.Reloc(),
},
Bytes: buf.Bytes(),
}
p.addSym(pclntab)
}
// addString appends the string s to the buffer b.
// It returns the offset of the beginning of the string in the buffer.
func addString(b *SymBuffer, s string) int {
off := b.Size()
b.SetSize(off + len(s) + 1)
copy(b.data[off:], s)
return off
}
// addPCTable appends the PC-data table stored in the file f at the location loc
// to the symbol buffer b. It returns the offset of the beginning of the table
// in the buffer.
func addPCTable(p *Prog, b *SymBuffer, f *os.File, loc goobj.Data) int {
if loc.Size == 0 {
return 0
}
off := b.Size()
b.SetSize(off + int(loc.Size))
_, err := f.ReadAt(b.data[off:off+int(loc.Size)], loc.Offset)
if err != nil {
p.errorf("%v", err)
}
return off
}
// addPCFileTable is like addPCTable, but it renumbers the file names referred to by the table
// to use the global numbering maintained in the files map. It adds new files to the
// map as necessary.
func addPCFileTable(p *Prog, b *SymBuffer, f *os.File, loc goobj.Data, sym *Sym, files map[string]int) int {
if loc.Size == 0 {
return 0
}
off := b.Size()
src := make([]byte, loc.Size)
_, err := f.ReadAt(src, loc.Offset)
if err != nil {
p.errorf("%v", err)
return 0
}
filenum := make([]int, len(sym.Func.File))
for i, name := range sym.Func.File {
num := files[name]
if num == 0 {
num = len(files) + 1
files[name] = num
}
filenum[i] = num
}
var dst []byte
newval := int32(-1)
var it PCIter
for it.Init(p, src); !it.Done; it.Next() {
// value delta
oldval := it.Value
val := oldval
if oldval != -1 {
if oldval < 0 || int(oldval) >= len(filenum) {
p.errorf("%s: corrupt pc-file table", sym)
break
}
val = int32(filenum[oldval])
}
dv := val - newval
newval = val
uv := uint32(dv<<1) ^ uint32(dv>>31)
dst = appendVarint(dst, uv)
// pc delta
dst = appendVarint(dst, it.NextPC-it.PC)
}
if it.Corrupt {
p.errorf("%s: corrupt pc-file table", sym)
}
// terminating value delta
dst = appendVarint(dst, 0)
b.SetSize(off + len(dst))
copy(b.data[off:], dst)
return off
}
// A SymBuffer is a buffer for preparing the data image of a
// linker-generated symbol.
type SymBuffer struct {
data []byte
reloc []goobj.Reloc
order binary.ByteOrder
ptrsize int
}
// Init initializes the buffer for writing.
func (b *SymBuffer) Init(p *Prog) {
b.data = nil
b.reloc = nil
b.order = p.byteorder
b.ptrsize = p.ptrsize
}
// Bytes returns the buffer data.
func (b *SymBuffer) Bytes() []byte {
return b.data
}
// SetSize sets the buffer's data size to n bytes.
func (b *SymBuffer) SetSize(n int) {
for cap(b.data) < n {
b.data = append(b.data[:cap(b.data)], 0)
}
b.data = b.data[:n]
}
// Size returns the buffer's data size.
func (b *SymBuffer) Size() int {
return len(b.data)
}
// Reloc returns the buffered relocations.
func (b *SymBuffer) Reloc() []goobj.Reloc {
return b.reloc
}
// Uint8 sets the uint8 at offset off to v.
// It returns the offset just beyond v.
func (b *SymBuffer) Uint8(off int, v uint8) int {
b.data[off] = v
return off + 1
}
// Uint16 sets the uint16 at offset off to v.
// It returns the offset just beyond v.
func (b *SymBuffer) Uint16(off int, v uint16) int {
b.order.PutUint16(b.data[off:], v)
return off + 2
}
// Uint32 sets the uint32 at offset off to v.
// It returns the offset just beyond v.
func (b *SymBuffer) Uint32(off int, v uint32) int {
b.order.PutUint32(b.data[off:], v)
return off + 4
}
// Uint64 sets the uint64 at offset off to v.
// It returns the offset just beyond v.
func (b *SymBuffer) Uint64(off int, v uint64) int {
b.order.PutUint64(b.data[off:], v)
return off + 8
}
// Uint sets the size-byte unsigned integer at offset off to v.
// It returns the offset just beyond v.
func (b *SymBuffer) Uint(off int, v uint64, size int) int {
switch size {
case 1:
return b.Uint8(off, uint8(v))
case 2:
return b.Uint16(off, uint16(v))
case 4:
return b.Uint32(off, uint32(v))
case 8:
return b.Uint64(off, v)
}
panic("invalid use of SymBuffer.SetUint")
}
// Addr sets the pointer-sized address at offset off to refer
// to symoff bytes past the start of sym. It returns the offset
// just beyond the address.
func (b *SymBuffer) Addr(off int, sym goobj.SymID, symoff int64) int {
b.reloc = append(b.reloc, goobj.Reloc{
Offset: off,
Size: b.ptrsize,
Sym: sym,
Add: int(symoff),
Type: R_ADDR,
})
return off + b.ptrsize
}
// A PCIter implements iteration over PC-data tables.
//
// var it PCIter
// for it.Init(p, data); !it.Done; it.Next() {
// it.Value holds from it.PC up to (but not including) it.NextPC
// }
// if it.Corrupt {
// data was malformed
// }
//
type PCIter struct {
PC uint32
NextPC uint32
Value int32
Done bool
Corrupt bool
p []byte
start bool
pcquantum uint32
}
// Init initializes the iteration.
// On return, if it.Done is true, the iteration is over.
// Otherwise it.Value applies in the pc range [it.PC, it.NextPC).
func (it *PCIter) Init(p *Prog, buf []byte) {
it.p = buf
it.PC = 0
it.NextPC = 0
it.Value = -1
it.start = true
it.pcquantum = uint32(p.pcquantum)
it.Done = false
it.Next()
}
// Next steps forward one entry in the table.
// On return, if it.Done is true, the iteration is over.
// Otherwise it.Value applies in the pc range [it.PC, it.NextPC).
func (it *PCIter) Next() {
it.PC = it.NextPC
if it.Done {
return
}
if len(it.p) == 0 {
it.Done = true
return
}
// value delta
uv, p, ok := decodeVarint(it.p)
if !ok {
it.Done = true
it.Corrupt = true
return
}
it.p = p
if uv == 0 && !it.start {
it.Done = true
return
}
it.start = false
sv := int32(uv>>1) ^ int32(uv<<31)>>31
it.Value += sv
// pc delta
uv, it.p, ok = decodeVarint(it.p)
if !ok {
it.Done = true
it.Corrupt = true
return
}
it.NextPC = it.PC + uv*it.pcquantum
}
// decodeVarint decodes an unsigned varint from p,
// reporting the value, the remainder of the data, and
// whether the decoding was successful.
func decodeVarint(p []byte) (v uint32, rest []byte, ok bool) {
for shift := uint(0); ; shift += 7 {
if len(p) == 0 {
return
}
c := uint32(p[0])
p = p[1:]
v |= (c & 0x7F) << shift
if c&0x80 == 0 {
break
}
}
return v, p, true
}
// appendVarint appends an unsigned varint encoding of v to p
// and returns the resulting slice.
func appendVarint(p []byte, v uint32) []byte {
for ; v >= 0x80; v >>= 7 {
p = append(p, byte(v)|0x80)
}
p = append(p, byte(v))
return p
}

View File

@@ -1,340 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"bytes"
"debug/goobj"
"fmt"
"math/rand"
"sort"
"strings"
"testing"
)
// Test of pcln table encoding.
// testdata/genpcln.go generates an assembly file with
// pseudorandom values for the data that pclntab stores.
// This test recomputes the same pseudorandom stream
// and checks that the final linked binary uses those values
// as well.
func TestPclntab(t *testing.T) {
p := &Prog{
GOOS: "darwin",
GOARCH: "amd64",
Error: func(s string) { t.Error(s) },
StartSym: "start",
omitRuntime: true,
}
var buf bytes.Buffer
p.link(&buf, "testdata/pclntab.6")
if p.NumError > 0 {
return
}
// The algorithm for computing values here must match
// the one in testdata/genpcln.go.
for f := 0; f < 3; f++ {
file := "input"
line := 1
rnd := rand.New(rand.NewSource(int64(f)))
args := rnd.Intn(100) * 8
frame := 32 + rnd.Intn(32)/8*8
size := 200 + rnd.Intn(100)*8
name := fmt.Sprintf("func%d", f)
r, off, fargs, fframe, ok := findFunc(t, p, name)
if !ok {
continue // error already printed
}
if fargs != args {
t.Errorf("%s: args=%d, want %d", name, fargs, args)
}
if fframe != frame+8 {
t.Errorf("%s: frame=%d, want %d", name, fframe, frame+8)
}
// Check FUNCDATA 1.
fdata, ok := loadFuncdata(t, r, name, off, 1)
if ok {
fsym := p.Syms[goobj.SymID{Name: fmt.Sprintf("funcdata%d", f)}]
if fsym == nil {
t.Errorf("funcdata%d is missing in binary", f)
} else if fdata != fsym.Addr {
t.Errorf("%s: funcdata 1 = %#x, want %#x", name, fdata, fsym.Addr)
}
}
// Walk code checking pcdata values.
spadj := 0
pcdata1 := -1
pcdata2 := -1
checkPCSP(t, r, name, off, 0, 0)
checkPCData(t, r, name, off, 0, 0, -1)
checkPCData(t, r, name, off, 0, 1, -1)
checkPCData(t, r, name, off, 0, 2, -1)
firstpc := 4
for i := 0; i < size; i++ {
pc := firstpc + i // skip SP adjustment to allocate frame
if i >= 0x100 && t.Failed() {
break
}
// Possible SP adjustment.
checkPCSP(t, r, name, off, pc, frame+spadj)
if rnd.Intn(100) == 0 {
checkPCFileLine(t, r, name, off, pc, file, line)
checkPCData(t, r, name, off, pc, 1, pcdata1)
checkPCData(t, r, name, off, pc, 2, pcdata2)
i += 1
pc = firstpc + i
checkPCFileLine(t, r, name, off, pc-1, file, line)
checkPCData(t, r, name, off, pc-1, 1, pcdata1)
checkPCData(t, r, name, off, pc-1, 2, pcdata2)
checkPCSP(t, r, name, off, pc-1, frame+spadj)
if spadj <= -32 || spadj < 32 && rnd.Intn(2) == 0 {
spadj += 8
} else {
spadj -= 8
}
checkPCSP(t, r, name, off, pc, frame+spadj)
}
// Possible PCFile change.
if rnd.Intn(100) == 0 {
file = fmt.Sprintf("file%d.s", rnd.Intn(10))
line = rnd.Intn(100) + 1
}
// Possible PCLine change.
if rnd.Intn(10) == 0 {
line = rnd.Intn(1000) + 1
}
// Possible PCData $1 change.
if rnd.Intn(100) == 0 {
pcdata1 = rnd.Intn(1000)
}
// Possible PCData $2 change.
if rnd.Intn(100) == 0 {
pcdata2 = rnd.Intn(1000)
}
if i == 0 {
checkPCFileLine(t, r, name, off, 0, file, line)
checkPCFileLine(t, r, name, off, pc-1, file, line)
}
checkPCFileLine(t, r, name, off, pc, file, line)
checkPCData(t, r, name, off, pc, 1, pcdata1)
checkPCData(t, r, name, off, pc, 2, pcdata2)
}
}
}
// findFunc finds the function information in the pclntab of p
// for the function with the given name.
// It returns a symbol reader for pclntab, the offset of the function information
// within that symbol, and the args and frame values read out of the information.
func findFunc(t *testing.T, p *Prog, name string) (r *SymReader, off, args, frame int, ok bool) {
tabsym := p.Syms[goobj.SymID{Name: "runtime.pclntab"}]
if tabsym == nil {
t.Errorf("pclntab is missing in binary")
return
}
r = new(SymReader)
r.Init(p, tabsym)
// pclntab must with 8-byte header
if r.Uint32(0) != 0xfffffffb || r.Uint8(4) != 0 || r.Uint8(5) != 0 || r.Uint8(6) != uint8(p.pcquantum) || r.Uint8(7) != uint8(p.ptrsize) {
t.Errorf("pclntab has incorrect header %.8x", r.data[:8])
return
}
sym := p.Syms[goobj.SymID{Name: name}]
if sym == nil {
t.Errorf("%s is missing in the binary", name)
return
}
// index is nfunc addr0 off0 addr1 off1 ... addr_nfunc (sentinel)
nfunc := int(r.Addr(8))
i := sort.Search(nfunc, func(i int) bool {
return r.Addr(8+p.ptrsize*(1+2*i)) >= sym.Addr
})
if entry := r.Addr(8 + p.ptrsize*(1+2*i)); entry != sym.Addr {
indexTab := make([]Addr, 2*nfunc+1)
for j := range indexTab {
indexTab[j] = r.Addr(8 + p.ptrsize*(1+j))
}
t.Errorf("pclntab is missing entry for %s (%#x): %#x", name, sym.Addr, indexTab)
return
}
off = int(r.Addr(8 + p.ptrsize*(1+2*i+1)))
// func description at off is
// entry addr
// nameoff uint32
// args uint32
// frame uint32
// pcspoff uint32
// pcfileoff uint32
// pclineoff uint32
// npcdata uint32
// nfuncdata uint32
// pcdata npcdata*uint32
// funcdata nfuncdata*addr
//
if entry := r.Addr(off); entry != sym.Addr {
t.Errorf("pclntab inconsistent: entry for %s addr=%#x has entry=%#x", name, sym.Addr, entry)
return
}
nameoff := int(r.Uint32(off + p.ptrsize))
args = int(r.Uint32(off + p.ptrsize + 1*4))
frame = int(r.Uint32(off + p.ptrsize + 2*4))
fname := r.String(nameoff)
if fname != name {
t.Errorf("pclntab inconsistent: entry for %s addr=%#x has name %q", name, sym.Addr, fname)
}
ok = true // off, args, frame are usable
return
}
// loadFuncdata returns the funcdata #fnum value
// loaded from the function information for name.
func loadFuncdata(t *testing.T, r *SymReader, name string, off int, fnum int) (Addr, bool) {
npcdata := int(r.Uint32(off + r.p.ptrsize + 6*4))
nfuncdata := int(r.Uint32(off + r.p.ptrsize + 7*4))
if fnum >= nfuncdata {
t.Errorf("pclntab(%s): no funcdata %d (only < %d)", name, fnum, nfuncdata)
return 0, false
}
fdataoff := off + r.p.ptrsize + (8+npcdata)*4 + fnum*r.p.ptrsize
fdataoff += fdataoff & 4
return r.Addr(fdataoff), true
}
// checkPCSP checks that the PCSP table in the function information at off
// lists spadj as the sp delta for pc.
func checkPCSP(t *testing.T, r *SymReader, name string, off, pc, spadj int) {
pcoff := r.Uint32(off + r.p.ptrsize + 3*4)
pcval, ok := readPCData(t, r, name, "PCSP", pcoff, pc)
if !ok {
return
}
if pcval != spadj {
t.Errorf("pclntab(%s): at pc=+%#x, pcsp=%d, want %d", name, pc, pcval, spadj)
}
}
// checkPCSP checks that the PCFile and PCLine tables in the function information at off
// list file, line as the file name and line number for pc.
func checkPCFileLine(t *testing.T, r *SymReader, name string, off, pc int, file string, line int) {
pcfileoff := r.Uint32(off + r.p.ptrsize + 4*4)
pclineoff := r.Uint32(off + r.p.ptrsize + 5*4)
pcfilenum, ok1 := readPCData(t, r, name, "PCFile", pcfileoff, pc)
pcline, ok2 := readPCData(t, r, name, "PCLine", pclineoff, pc)
if !ok1 || !ok2 {
return
}
nfunc := int(r.Addr(8))
filetaboff := r.Uint32(8 + r.p.ptrsize*2*(nfunc+1))
nfile := int(r.Uint32(int(filetaboff)))
if pcfilenum <= 0 || pcfilenum >= nfile {
t.Errorf("pclntab(%s): at pc=+%#x, filenum=%d (invalid; nfile=%d)", name, pc, pcfilenum, nfile)
}
pcfile := r.String(int(r.Uint32(int(filetaboff) + pcfilenum*4)))
if !strings.HasSuffix(pcfile, file) {
t.Errorf("pclntab(%s): at pc=+%#x, file=%q, want %q", name, pc, pcfile, file)
}
if pcline != line {
t.Errorf("pclntab(%s): at pc=+%#x, line=%d, want %d", name, pc, pcline, line)
}
}
// checkPCData checks that the PCData#pnum table in the function information at off
// list val as the value for pc.
func checkPCData(t *testing.T, r *SymReader, name string, off, pc, pnum, val int) {
pcoff := r.Uint32(off + r.p.ptrsize + (8+pnum)*4)
pcval, ok := readPCData(t, r, name, fmt.Sprintf("PCData#%d", pnum), pcoff, pc)
if !ok {
return
}
if pcval != val {
t.Errorf("pclntab(%s): at pc=+%#x, pcdata#%d=%d, want %d", name, pc, pnum, pcval, val)
}
}
// readPCData reads the PCData table offset off
// to obtain and return the value associated with pc.
func readPCData(t *testing.T, r *SymReader, name, pcdataname string, pcoff uint32, pc int) (int, bool) {
// "If pcsp, pcfile, pcln, or any of the pcdata offsets is zero,
// that table is considered missing, and all PCs take value -1."
if pcoff == 0 {
return -1, true
}
var it PCIter
for it.Init(r.p, r.data[pcoff:]); !it.Done; it.Next() {
if it.PC <= uint32(pc) && uint32(pc) < it.NextPC {
return int(it.Value), true
}
}
if it.Corrupt {
t.Errorf("pclntab(%s): %s: corrupt pcdata table", name, pcdataname)
}
return 0, false
}
// A SymReader provides typed access to the data for a symbol.
type SymReader struct {
p *Prog
data []byte
}
func (r *SymReader) Init(p *Prog, sym *Sym) {
seg := sym.Section.Segment
off := sym.Addr - seg.VirtAddr
data := seg.Data[off : off+Addr(sym.Size)]
r.p = p
r.data = data
}
func (r *SymReader) Uint8(off int) uint8 {
return r.data[off]
}
func (r *SymReader) Uint16(off int) uint16 {
return r.p.byteorder.Uint16(r.data[off:])
}
func (r *SymReader) Uint32(off int) uint32 {
return r.p.byteorder.Uint32(r.data[off:])
}
func (r *SymReader) Uint64(off int) uint64 {
return r.p.byteorder.Uint64(r.data[off:])
}
func (r *SymReader) Addr(off int) Addr {
if r.p.ptrsize == 4 {
return Addr(r.Uint32(off))
}
return Addr(r.Uint64(off))
}
func (r *SymReader) String(off int) string {
end := off
for r.data[end] != '\x00' {
end++
}
return string(r.data[off:end])
}

View File

@@ -1,220 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"debug/goobj"
"encoding/binary"
"fmt"
"go/build"
"io"
"os"
"runtime"
)
// A Prog holds state for constructing an executable (program) image.
//
// The usual sequence of operations on a Prog is:
//
// p.init()
// p.scan(file)
// p.dead()
// p.runtime()
// p.layout()
// p.load()
// p.debug()
// p.write(w)
//
// p.init is in this file. The rest of the methods are in files
// named for the method. The convenience method p.link runs
// this sequence.
//
type Prog struct {
// Context
GOOS string // target operating system
GOARCH string // target architecture
Format string // desired file format ("elf", "macho", ...)
Error func(string) // called to report an error (if set)
NumError int // number of errors printed
StartSym string
// Derived context
arch
formatter formatter
startSym goobj.SymID
pkgdir string
omitRuntime bool // do not load runtime package
// Input
Packages map[string]*Package // loaded packages, by import path
Syms map[goobj.SymID]*Sym // defined symbols, by symbol ID
Missing map[goobj.SymID]bool // missing symbols
Dead map[goobj.SymID]bool // symbols removed as dead
SymOrder []*Sym // order syms were scanned
MaxVersion int // max SymID.Version, for generating fresh symbol IDs
// Output
UnmappedSize Addr // size of unmapped region at address 0
HeaderSize Addr // size of object file header
Entry Addr // virtual address where execution begins
Segments []*Segment // loaded memory segments
}
// An arch describes architecture-dependent settings.
type arch struct {
byteorder binary.ByteOrder
ptrsize int
pcquantum int
}
// A formatter takes care of the details of generating a particular
// kind of executable file.
type formatter interface {
// headerSize returns the footprint of the header for p
// in both virtual address space and file bytes.
// The footprint does not include any bytes stored at the
// end of the file.
headerSize(p *Prog) (virt, file Addr)
// write writes the executable file for p to w.
write(w io.Writer, p *Prog)
}
// An Addr represents a virtual memory address, a file address, or a size.
// It must be a uint64, not a uintptr, so that a 32-bit linker can still generate a 64-bit binary.
// It must be unsigned in order to link programs placed at very large start addresses.
// Math involving Addrs must be checked carefully not to require negative numbers.
type Addr uint64
// A Package is a Go package loaded from a file.
type Package struct {
*goobj.Package // table of contents
File string // file name for reopening
Syms []*Sym // symbols defined by this package
}
// A Sym is a symbol defined in a loaded package.
type Sym struct {
*goobj.Sym // symbol metadata from package file
Package *Package // package defining symbol
Section *Section // section where symbol is placed in output program
Addr Addr // virtual address of symbol in output program
Bytes []byte // symbol data, for internally defined symbols
}
// A Segment is a loaded memory segment.
// A Prog is expected to have segments named "text" and optionally "data",
// in that order, before any other segments.
type Segment struct {
Name string // name of segment: "text", "data", ...
VirtAddr Addr // virtual memory address of segment base
VirtSize Addr // size of segment in memory
FileOffset Addr // file offset of segment base
FileSize Addr // size of segment in file; can be less than VirtSize
Sections []*Section // sections inside segment
Data []byte // raw data of segment image
}
// A Section is part of a loaded memory segment.
type Section struct {
Name string // name of section: "text", "rodata", "noptrbss", and so on
VirtAddr Addr // virtual memory address of section base
Size Addr // size of section in memory
Align Addr // required alignment
InFile bool // section has image data in file (like data, unlike bss)
Syms []*Sym // symbols stored in section
Segment *Segment // segment containing section
}
func (p *Prog) errorf(format string, args ...interface{}) {
if p.Error != nil {
p.Error(fmt.Sprintf(format, args...))
} else {
fmt.Fprintf(os.Stderr, format+"\n", args...)
}
p.NumError++
}
// link is the one-stop convenience method for running a link.
// It writes to w the object file generated from using mainFile as the main package.
func (p *Prog) link(w io.Writer, mainFile string) {
p.init()
p.scan(mainFile)
if p.NumError > 0 {
return
}
p.dead()
p.runtime()
p.autoData()
p.layout()
p.autoConst()
if p.NumError > 0 {
return
}
p.load()
if p.NumError > 0 {
return
}
p.debug()
if p.NumError > 0 {
return
}
p.write(w)
}
// init initializes p for use by the other methods.
func (p *Prog) init() {
// Set default context if not overridden.
if p.GOOS == "" {
p.GOOS = build.Default.GOOS
}
if p.GOARCH == "" {
p.GOARCH = build.Default.GOARCH
}
if p.Format == "" {
p.Format = goosFormat[p.GOOS]
if p.Format == "" {
p.errorf("no default file format for GOOS %q", p.GOOS)
return
}
}
if p.StartSym == "" {
p.StartSym = fmt.Sprintf("_rt0_%s_%s", p.GOARCH, p.GOOS)
}
// Derive internal context.
p.formatter = formatters[p.Format]
if p.formatter == nil {
p.errorf("unknown output file format %q", p.Format)
return
}
p.startSym = goobj.SymID{Name: p.StartSym}
arch, ok := arches[p.GOARCH]
if !ok {
p.errorf("unknown GOOS %q", p.GOOS)
return
}
p.arch = arch
p.pkgdir = fmt.Sprintf("%s/pkg/%s_%s", runtime.GOROOT(), p.GOOS, p.GOARCH)
}
// goosFormat records the default format for each known GOOS value.
var goosFormat = map[string]string{
"darwin": "darwin",
}
// formatters records the format implementation for each known format value.
var formatters = map[string]formatter{
"darwin": machoFormat{},
}
var arches = map[string]arch{
"amd64": {
byteorder: binary.LittleEndian,
ptrsize: 8,
pcquantum: 1,
},
}

View File

@@ -1,163 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"bytes"
"fmt"
"io/ioutil"
"testing"
)
// shiftProg adjusts the addresses in p.
// It adds vdelta to all virtual addresses and fdelta to all file offsets.
func shiftProg(p *Prog, vdelta Addr, fdelta Addr) {
p.Entry += vdelta
for _, seg := range p.Segments {
seg.FileOffset += fdelta
seg.VirtAddr += vdelta
for _, sect := range seg.Sections {
sect.VirtAddr += vdelta
for _, sym := range sect.Syms {
sym.Addr += vdelta
}
}
}
}
// diffProg returns a list of differences between p and q,
// assuming p is being checked and q is the correct answer.
func diffProg(p, q *Prog) []string {
var errors []string
if p.UnmappedSize != q.UnmappedSize {
errors = append(errors, fmt.Sprintf("p.UnmappedSize = %#x, want %#x", p.UnmappedSize, q.UnmappedSize))
}
if p.HeaderSize != q.HeaderSize {
errors = append(errors, fmt.Sprintf("p.HeaderSize = %#x, want %#x", p.HeaderSize, q.HeaderSize))
}
if p.Entry != q.Entry {
errors = append(errors, fmt.Sprintf("p.Entry = %#x, want %#x", p.Entry, q.Entry))
}
for i := 0; i < len(p.Segments) || i < len(q.Segments); i++ {
if i >= len(p.Segments) {
errors = append(errors, fmt.Sprintf("p missing segment %q", q.Segments[i].Name))
continue
}
if i >= len(q.Segments) {
errors = append(errors, fmt.Sprintf("p has extra segment %q", p.Segments[i].Name))
continue
}
pseg := p.Segments[i]
qseg := q.Segments[i]
if pseg.Name != qseg.Name {
errors = append(errors, fmt.Sprintf("segment %d Name = %q, want %q", i, pseg.Name, qseg.Name))
continue // probably out of sync
}
if pseg.VirtAddr != qseg.VirtAddr {
errors = append(errors, fmt.Sprintf("segment %q VirtAddr = %#x, want %#x", pseg.Name, pseg.VirtAddr, qseg.VirtAddr))
}
if pseg.VirtSize != qseg.VirtSize {
errors = append(errors, fmt.Sprintf("segment %q VirtSize = %#x, want %#x", pseg.Name, pseg.VirtSize, qseg.VirtSize))
}
if pseg.FileOffset != qseg.FileOffset {
errors = append(errors, fmt.Sprintf("segment %q FileOffset = %#x, want %#x", pseg.Name, pseg.FileOffset, qseg.FileOffset))
}
if pseg.FileSize != qseg.FileSize {
errors = append(errors, fmt.Sprintf("segment %q FileSize = %#x, want %#x", pseg.Name, pseg.FileSize, qseg.FileSize))
}
if len(pseg.Data) != len(qseg.Data) {
errors = append(errors, fmt.Sprintf("segment %q len(Data) = %d, want %d", pseg.Name, len(pseg.Data), len(qseg.Data)))
} else if !bytes.Equal(pseg.Data, qseg.Data) {
errors = append(errors, fmt.Sprintf("segment %q Data mismatch:\n\thave %x\n\twant %x", pseg.Name, pseg.Data, qseg.Data))
}
for j := 0; j < len(pseg.Sections) || j < len(qseg.Sections); j++ {
if j >= len(pseg.Sections) {
errors = append(errors, fmt.Sprintf("segment %q missing section %q", pseg.Name, qseg.Sections[i].Name))
continue
}
if j >= len(qseg.Sections) {
errors = append(errors, fmt.Sprintf("segment %q has extra section %q", pseg.Name, pseg.Sections[i].Name))
continue
}
psect := pseg.Sections[j]
qsect := qseg.Sections[j]
if psect.Name != qsect.Name {
errors = append(errors, fmt.Sprintf("segment %q, section %d Name = %q, want %q", pseg.Name, j, psect.Name, qsect.Name))
continue // probably out of sync
}
if psect.VirtAddr != qsect.VirtAddr {
errors = append(errors, fmt.Sprintf("segment %q section %q VirtAddr = %#x, want %#x", pseg.Name, psect.Name, psect.VirtAddr, qsect.VirtAddr))
}
if psect.Size != qsect.Size {
errors = append(errors, fmt.Sprintf("segment %q section %q Size = %#x, want %#x", pseg.Name, psect.Name, psect.Size, qsect.Size))
}
if psect.Align != qsect.Align {
errors = append(errors, fmt.Sprintf("segment %q section %q Align = %#x, want %#x", pseg.Name, psect.Name, psect.Align, qsect.Align))
}
}
}
return errors
}
// cloneProg returns a deep copy of p.
func cloneProg(p *Prog) *Prog {
q := new(Prog)
*q = *p
q.Segments = make([]*Segment, len(p.Segments))
for i, seg := range p.Segments {
q.Segments[i] = cloneSegment(seg)
}
return q
}
// cloneSegment returns a deep copy of seg.
func cloneSegment(seg *Segment) *Segment {
t := new(Segment)
*t = *seg
t.Sections = make([]*Section, len(seg.Sections))
for i, sect := range seg.Sections {
t.Sections[i] = cloneSection(sect)
}
t.Data = make([]byte, len(seg.Data))
copy(t.Data, seg.Data)
return t
}
// cloneSection returns a deep copy of section.
func cloneSection(sect *Section) *Section {
// At the moment, there's nothing we need to make a deep copy of.
t := new(Section)
*t = *sect
return t
}
const saveMismatch = true
// checkGolden checks that data matches the named file.
// If not, it reports the error to the test.
func checkGolden(t *testing.T, data []byte, name string) {
golden := mustParseHexdumpFile(t, name)
if !bytes.Equal(data, golden) {
if saveMismatch {
ioutil.WriteFile(name+".raw", data, 0666)
ioutil.WriteFile(name+".hex", []byte(hexdump(data)), 0666)
}
// TODO(rsc): A better diff would be nice, as needed.
i := 0
for i < len(data) && i < len(golden) && data[i] == golden[i] {
i++
}
if i >= len(data) {
t.Errorf("%s: output file shorter than expected: have %d bytes, want %d", name, len(data), len(golden))
} else if i >= len(golden) {
t.Errorf("%s: output file larger than expected: have %d bytes, want %d", name, len(data), len(golden))
} else {
t.Errorf("%s: output file differs at byte %d: have %#02x, want %#02x", name, i, data[i], golden[i])
}
}
}

View File

@@ -1,28 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Generation of runtime-accessible data structures.
// See also debug.go.
package main
import "debug/goobj"
func (p *Prog) runtime() {
p.pclntab()
// TODO: Implement garbage collection data.
p.addSym(&Sym{
Sym: &goobj.Sym{
SymID: goobj.SymID{Name: "runtime.gcdata"},
Kind: goobj.SRODATA,
},
})
p.addSym(&Sym{
Sym: &goobj.Sym{
SymID: goobj.SymID{Name: "runtime.gcbss"},
Kind: goobj.SRODATA,
},
})
}

View File

@@ -1,187 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Initial scan of packages making up a program.
// TODO(rsc): Rename goobj.SymID.Version to StaticID to avoid confusion with the ELF meaning of version.
// TODO(rsc): Fix file format so that SBSS/SNOPTRBSS with data is listed as SDATA/SNOPTRDATA.
// TODO(rsc): Parallelize scan to overlap file i/o where possible.
package main
import (
"debug/goobj"
"os"
"sort"
"strings"
)
// scan scans all packages making up the program, starting with package main defined in mainfile.
func (p *Prog) scan(mainfile string) {
p.initScan()
p.scanFile("main", mainfile)
if len(p.Missing) > 0 && !p.omitRuntime {
p.scanImport("runtime")
}
var missing []string
for sym := range p.Missing {
if !p.isAuto(sym) {
missing = append(missing, sym.String())
}
}
if missing != nil {
sort.Strings(missing)
for _, sym := range missing {
p.errorf("undefined: %s", sym)
}
}
// TODO(rsc): Walk import graph to diagnose cycles.
}
// initScan initializes the Prog fields needed by scan.
func (p *Prog) initScan() {
p.Packages = make(map[string]*Package)
p.Syms = make(map[goobj.SymID]*Sym)
p.Missing = make(map[goobj.SymID]bool)
p.Missing[p.startSym] = true
}
// scanFile reads file to learn about the package with the given import path.
func (p *Prog) scanFile(pkgpath string, file string) {
pkg := &Package{
File: file,
}
p.Packages[pkgpath] = pkg
f, err := os.Open(file)
if err != nil {
p.errorf("%v", err)
return
}
gp, err := goobj.Parse(f, pkgpath)
f.Close()
if err != nil {
p.errorf("reading %s: %v", file, err)
return
}
// TODO(rsc): Change debug/goobj to record package name as gp.Name.
// TODO(rsc): If pkgpath == "main", check that gp.Name == "main".
pkg.Package = gp
for _, gs := range gp.Syms {
// TODO(rsc): Fix file format instead of this workaround.
if gs.Data.Size > 0 {
switch gs.Kind {
case goobj.SBSS:
gs.Kind = goobj.SDATA
case goobj.SNOPTRBSS:
gs.Kind = goobj.SNOPTRDATA
}
}
if gs.Version != 0 {
gs.Version += p.MaxVersion
}
for i := range gs.Reloc {
r := &gs.Reloc[i]
if r.Sym.Version != 0 {
r.Sym.Version += p.MaxVersion
}
if p.Syms[r.Sym] == nil {
p.Missing[r.Sym] = true
}
}
if gs.Func != nil {
for i := range gs.Func.FuncData {
fdata := &gs.Func.FuncData[i]
if fdata.Sym.Name != "" {
if fdata.Sym.Version != 0 {
fdata.Sym.Version += p.MaxVersion
}
if p.Syms[fdata.Sym] == nil {
p.Missing[fdata.Sym] = true
}
}
}
}
if old := p.Syms[gs.SymID]; old != nil {
// Duplicate definition of symbol. Is it okay?
// TODO(rsc): Write test for this code.
switch {
// If both symbols are BSS (no data), take max of sizes
// but otherwise ignore second symbol.
case old.Data.Size == 0 && gs.Data.Size == 0:
if old.Size < gs.Size {
old.Size = gs.Size
}
continue
// If one is in BSS and one is not, use the one that is not.
case old.Data.Size > 0 && gs.Data.Size == 0:
continue
case gs.Data.Size > 0 && old.Data.Size == 0:
break // install gs as new symbol below
// If either is marked as DupOK, we can keep either one.
// Keep the one that we saw first.
case old.DupOK || gs.DupOK:
continue
// Otherwise, there's an actual conflict:
default:
p.errorf("symbol %s defined in both %s and %s %v %v", gs.SymID, old.Package.File, file, old.Data, gs.Data)
continue
}
}
s := &Sym{
Sym: gs,
Package: pkg,
}
p.addSym(s)
delete(p.Missing, gs.SymID)
if s.Data.Size > int64(s.Size) {
p.errorf("%s: initialized data larger than symbol (%d > %d)", s, s.Data.Size, s.Size)
}
}
p.MaxVersion += pkg.MaxVersion
for i, pkgpath := range pkg.Imports {
// TODO(rsc): Fix file format to drop .a from recorded import path.
pkgpath = strings.TrimSuffix(pkgpath, ".a")
pkg.Imports[i] = pkgpath
p.scanImport(pkgpath)
}
}
func (p *Prog) addSym(s *Sym) {
pkg := s.Package
if pkg == nil {
pkg = p.Packages[""]
if pkg == nil {
pkg = &Package{}
p.Packages[""] = pkg
}
s.Package = pkg
}
pkg.Syms = append(pkg.Syms, s)
p.Syms[s.SymID] = s
p.SymOrder = append(p.SymOrder, s)
}
// scanImport finds the object file for the given import path and then scans it.
func (p *Prog) scanImport(pkgpath string) {
if p.Packages[pkgpath] != nil {
return // already loaded
}
// TODO(rsc): Implement correct search to find file.
p.scanFile(pkgpath, p.pkgdir+"/"+pkgpath+".a")
}

View File

@@ -1,15 +0,0 @@
ALL=\
autosection.6\
autoweak.6\
dead.6\
hello.6\
layout.6\
pclntab.6\
all: $(ALL)
%.6: %.s
GOARCH=amd64 GOOS=darwin go tool 6a -trimpath=$(shell pwd) $*.s
pclntab.s: genpcln.go
go run genpcln.go >pclntab.s

Binary file not shown.

View File

@@ -1,60 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test of section-named symbols.
#include "textflag.h"
TEXT start(SB),7,$0
MOVQ $autotab(SB),AX
MOVQ $autoptr(SB),AX
RET
GLOBL zero(SB), $8
GLOBL zeronoptr(SB), NOPTR, $16
// text
DATA autotab+0x00(SB)/8, $runtime·text(SB)
DATA autotab+0x08(SB)/8, $start(SB)
DATA autotab+0x10(SB)/8, $runtime·etext(SB)
DATA autotab+0x18(SB)/8, $start+16(SB)
// data
DATA autotab+0x20(SB)/8, $runtime·data(SB)
DATA autotab+0x28(SB)/8, $autotab(SB)
DATA autotab+0x30(SB)/8, $runtime·edata(SB)
DATA autotab+0x38(SB)/8, $nonzero+4(SB)
// bss
DATA autotab+0x40(SB)/8, $runtime·bss(SB)
DATA autotab+0x48(SB)/8, $zero(SB)
DATA autotab+0x50(SB)/8, $runtime·ebss(SB)
DATA autotab+0x58(SB)/8, $zero+8(SB)
// noptrdata
DATA autotab+0x60(SB)/8, $runtime·noptrdata(SB)
DATA autotab+0x68(SB)/8, $nonzeronoptr(SB)
DATA autotab+0x70(SB)/8, $runtime·enoptrdata(SB)
DATA autotab+0x78(SB)/8, $nonzeronoptr+8(SB)
// noptrbss
DATA autotab+0x80(SB)/8, $runtime·noptrbss(SB)
DATA autotab+0x88(SB)/8, $zeronoptr(SB)
DATA autotab+0x90(SB)/8, $runtime·enoptrbss(SB)
DATA autotab+0x98(SB)/8, $zeronoptr+16(SB)
// end
DATA autotab+0xa0(SB)/8, $runtime·end(SB)
DATA autotab+0xa8(SB)/8, $zeronoptr+16(SB)
GLOBL autotab(SB), $0xb0
DATA nonzero(SB)/4, $1
GLOBL nonzero(SB), $4
DATA nonzeronoptr(SB)/8, $2
GLOBL nonzeronoptr(SB), NOPTR, $8
GLOBL autoptr(SB), $0

Binary file not shown.

View File

@@ -1,30 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test of go.weak symbols.
TEXT start(SB),7,$0
MOVQ $autotab(SB),AX
MOVQ $autoptr(SB),AX
RET
// go.weak.sym should resolve to sym, because sym is in the binary.
DATA autotab+0(SB)/8, $go·weak·sym(SB)
DATA autotab+8(SB)/8, $sym(SB)
// go.weak.missingsym should resolve to 0, because missingsym is not in the binary.
DATA autotab+16(SB)/8, $go·weak·missingsym(SB)
DATA autotab+24(SB)/8, $0
// go.weak.deadsym should resolve to 0, because deadsym is discarded during dead code removal
DATA autotab+32(SB)/8, $go·weak·deadsym(SB)
DATA autotab+40(SB)/8, $0
GLOBL autotab(SB), $48
GLOBL sym(SB), $1
GLOBL deadsym(SB), $1
GLOBL autoptr(SB), $0

Binary file not shown.

View File

@@ -1,48 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test of dead code removal.
// Symbols with names beginning with dead_ should be discarded.
// Others should be kept.
TEXT start(SB),7,$0 // start symbol
MOVQ $data1<>(SB), AX
CALL text1(SB)
MOVQ $text2(SB), BX
RET
TEXT text1(SB),7,$0
FUNCDATA $1, funcdata+4(SB)
RET
TEXT text2(SB),7,$0
MOVQ $runtime·edata(SB),BX
RET
DATA data1<>+0(SB)/8, $data2(SB)
DATA data1<>+8(SB)/8, $data3(SB)
GLOBL data1<>(SB), $16
GLOBL data2(SB), $1
GLOBL data3(SB), $1
GLOBL funcdata(SB), $8
TEXT dead_start(SB),7,$0
MOVQ $dead_data1(SB), AX
CALL dead_text1(SB)
MOVQ $dead_text2(SB), BX
RET
TEXT dead_text1(SB),7,$0
FUNCDATA $1, dead_funcdata+4(SB)
RET
TEXT dead_text2(SB),7,$0
RET
DATA dead_data1+0(SB)/8, $dead_data2(SB)
DATA dead_data1+8(SB)/8, $dead_data3(SB)
GLOBL dead_data1(SB), $16
GLOBL dead_data2(SB), $1
GLOBL dead_data3(SB), $1
GLOBL dead_funcdata(SB), $8

View File

@@ -1,112 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This program generates a .s file using a pseudorandom
// value stream for the runtime function data.
// The pclntab test checks that the linked copy
// still has the same pseudorandom value stream.
package main
import (
"fmt"
"math/rand"
)
func main() {
fmt.Printf("// generated by genpcln.go; do not edit\n\n")
for f := 0; f < 3; f++ {
r := rand.New(rand.NewSource(int64(f)))
file := "input"
line := 1
args := r.Intn(100) * 8
frame := 32 + r.Intn(32)/8*8
fmt.Printf("#line %d %q\n", line, file)
fmt.Printf("TEXT func%d(SB),7,$%d-%d\n", f, frame, args)
fmt.Printf("\tFUNCDATA $1, funcdata%d(SB)\n", f)
fmt.Printf("#line %d %q\n", line, file)
size := 200 + r.Intn(100)*8
spadj := 0
flushed := 0
firstpc := 4
flush := func(i int) {
for i-flushed >= 10 {
fmt.Printf("#line %d %q\n", line, file)
fmt.Printf("/*%#04x*/\tMOVQ $0x123456789, AX\n", firstpc+flushed)
flushed += 10
}
for i-flushed >= 5 {
fmt.Printf("#line %d %q\n", line, file)
fmt.Printf("/*%#04x*/\tMOVL $0x1234567, AX\n", firstpc+flushed)
flushed += 5
}
for i-flushed > 0 {
fmt.Printf("#line %d %q\n", line, file)
fmt.Printf("/*%#04x*/\tBYTE $0\n", firstpc+flushed)
flushed++
}
}
for i := 0; i < size; i++ {
// Possible SP adjustment.
if r.Intn(100) == 0 {
flush(i)
fmt.Printf("#line %d %q\n", line, file)
if spadj <= -32 || spadj < 32 && r.Intn(2) == 0 {
spadj += 8
fmt.Printf("/*%#04x*/\tPUSHQ AX\n", firstpc+i)
} else {
spadj -= 8
fmt.Printf("/*%#04x*/\tPOPQ AX\n", firstpc+i)
}
i += 1
flushed = i
}
// Possible PCFile change.
if r.Intn(100) == 0 {
flush(i)
file = fmt.Sprintf("file%d.s", r.Intn(10))
line = r.Intn(100) + 1
}
// Possible PCLine change.
if r.Intn(10) == 0 {
flush(i)
line = r.Intn(1000) + 1
}
// Possible PCData $1 change.
if r.Intn(100) == 0 {
flush(i)
fmt.Printf("/*%6s*/\tPCDATA $1, $%d\n", "", r.Intn(1000))
}
// Possible PCData $2 change.
if r.Intn(100) == 0 {
flush(i)
fmt.Printf("/*%6s*/\tPCDATA $2, $%d\n", "", r.Intn(1000))
}
}
flush(size)
for spadj < 0 {
fmt.Printf("\tPUSHQ AX\n")
spadj += 8
}
for spadj > 0 {
fmt.Printf("\tPOPQ AX\n")
spadj -= 8
}
fmt.Printf("\tRET\n")
fmt.Printf("\n")
fmt.Printf("GLOBL funcdata%d(SB), $16\n", f)
}
fmt.Printf("\nTEXT start(SB),7,$0\n")
for f := 0; f < 3; f++ {
fmt.Printf("\tCALL func%d(SB)\n", f)
}
fmt.Printf("\tMOVQ $runtime·pclntab(SB), AX\n")
fmt.Printf("\n\tRET\n")
}

Binary file not shown.

View File

@@ -1,15 +0,0 @@
TEXT _rt0_go(SB),7,$0
MOVL $1, DI
MOVL $hello<>(SB), SI
MOVL $12, DX
MOVL $0x2000004, AX
SYSCALL
MOVL $0, DI
MOVL $0x2000001, AX
SYSCALL
RET
DATA hello<>+0(SB)/4, $"hell"
DATA hello<>+4(SB)/4, $"o wo"
DATA hello<>+8(SB)/4, $"rld\n"
GLOBL hello<>(SB), $12

Binary file not shown.

View File

@@ -1,29 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test of section assignment in layout.go.
// Each symbol should end up in the section named by the symbol name prefix (up to the underscore).
#include "textflag.h"
TEXT text_start(SB),7,$0
MOVQ $rodata_sym(SB), AX
MOVQ $noptrdata_sym(SB), AX
MOVQ $data_sym(SB), AX
MOVQ $bss_sym(SB), AX
MOVQ $noptrbss_sym(SB), AX
RET
DATA rodata_sym(SB)/4, $1
GLOBL rodata_sym(SB), RODATA, $4
DATA noptrdata_sym(SB)/4, $1
GLOBL noptrdata_sym(SB), NOPTR, $4
DATA data_sym(SB)/4, $1
GLOBL data_sym(SB), $4
GLOBL bss_sym(SB), $4
GLOBL noptrbss_sym(SB), NOPTR, $4

View File

@@ -1,54 +0,0 @@
00000000 cf fa ed fe 07 00 00 01 03 00 00 00 02 00 00 00 |................|
00000010 04 00 00 00 d0 02 00 00 01 00 00 00 00 00 00 00 |................|
00000020 19 00 00 00 48 00 00 00 5f 5f 50 41 47 45 5a 45 |....H...__PAGEZE|
00000030 52 4f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |RO..............|
00000040 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000060 00 00 00 00 00 00 00 00 19 00 00 00 38 01 00 00 |............8...|
00000070 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
00000080 00 10 00 00 00 00 00 00 b0 10 00 00 00 00 00 00 |................|
00000090 00 00 00 00 00 00 00 00 b0 10 00 00 00 00 00 00 |................|
000000a0 07 00 00 00 05 00 00 00 03 00 00 00 00 00 00 00 |................|
000000b0 5f 5f 74 65 78 74 00 00 00 00 00 00 00 00 00 00 |__text..........|
000000c0 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
000000d0 00 20 00 00 00 00 00 00 20 00 00 00 00 00 00 00 |. ...... .......|
000000e0 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000f0 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000100 5f 5f 72 6f 64 61 74 61 00 00 00 00 00 00 00 00 |__rodata........|
00000110 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
00000120 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ..............|
00000130 20 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ...............|
*
00000150 5f 5f 66 75 6e 63 74 61 62 00 00 00 00 00 00 00 |__functab.......|
00000160 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
00000170 20 20 00 00 00 00 00 00 90 00 00 00 00 00 00 00 | ..............|
00000180 20 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ...............|
*
000001a0 19 00 00 00 98 00 00 00 5f 5f 44 41 54 41 00 00 |........__DATA..|
000001b0 00 00 00 00 00 00 00 00 00 30 00 00 00 00 00 00 |.........0......|
000001c0 0c 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......|
000001d0 0c 00 00 00 00 00 00 00 03 00 00 00 03 00 00 00 |................|
000001e0 01 00 00 00 00 00 00 00 5f 5f 64 61 74 61 00 00 |........__data..|
000001f0 00 00 00 00 00 00 00 00 5f 5f 44 41 54 41 00 00 |........__DATA..|
00000200 00 00 00 00 00 00 00 00 00 30 00 00 00 00 00 00 |.........0......|
00000210 0c 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......|
*
00000230 00 00 00 00 00 00 00 00 05 00 00 00 b8 00 00 00 |................|
00000240 04 00 00 00 2a 00 00 00 00 00 00 00 00 00 00 00 |....*...........|
*
000002c0 00 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......|
*
00001000 bf 01 00 00 00 be 00 30 00 00 ba 0c 00 00 00 b8 |.......0........|
00001010 04 00 00 02 0f 05 31 ff b8 01 00 00 02 0f 05 c3 |......1.........|
00001020 fb ff ff ff 00 00 01 08 01 00 00 00 00 00 00 00 |................|
00001030 00 20 00 00 00 00 00 00 30 00 00 00 00 00 00 00 |. ......0.......|
00001040 20 20 00 00 00 00 00 00 80 00 00 00 00 00 00 00 | ..............|
00001050 00 20 00 00 00 00 00 00 58 00 00 00 00 00 00 80 |. ......X.......|
00001060 08 00 00 00 60 00 00 00 63 00 00 00 66 00 00 00 |....`...c...f...|
00001070 00 00 00 00 00 00 00 00 5f 72 74 30 5f 67 6f 00 |........_rt0_go.|
00001080 02 20 00 04 20 00 06 05 02 05 02 05 02 05 02 02 |. .. ...........|
00001090 02 02 02 05 02 02 02 01 00 00 00 00 00 00 00 00 |................|
000010a0 02 00 00 00 88 00 00 00 68 65 6c 6c 6f 2e 73 00 |........hello.s.|
*
00002000 68 65 6c 6c 6f 20 77 6f 72 6c 64 0a |hello world.|
0000200c

View File

@@ -1,24 +0,0 @@
00000000 cf fa ed fe 07 00 00 01 03 00 00 00 02 00 00 00 |................|
00000010 03 00 00 00 98 01 00 00 01 00 00 00 00 00 00 00 |................|
00000020 19 00 00 00 48 00 00 00 5f 5f 50 41 47 45 5a 45 |....H...__PAGEZE|
00000030 52 4f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |RO..............|
00000040 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000060 00 00 00 00 00 00 00 00 19 00 00 00 98 00 00 00 |................|
00000070 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
00000080 00 10 00 00 00 00 00 00 0d 10 00 00 00 00 00 00 |................|
00000090 00 00 00 00 00 00 00 00 0d 10 00 00 00 00 00 00 |................|
000000a0 07 00 00 00 05 00 00 00 01 00 00 00 00 00 00 00 |................|
000000b0 5f 5f 74 65 78 74 00 00 00 00 00 00 00 00 00 00 |__text..........|
000000c0 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
000000d0 00 20 00 00 00 00 00 00 0d 00 00 00 00 00 00 00 |. ..............|
000000e0 00 10 00 00 06 00 00 00 00 00 00 00 00 00 00 00 |................|
000000f0 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000100 05 00 00 00 b8 00 00 00 04 00 00 00 2a 00 00 00 |............*...|
00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000190 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |. ..............|
000001a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00001000 b8 01 00 00 02 bf 09 00 00 00 0f 05 f4 |.............|
0000100d

View File

@@ -1,39 +0,0 @@
00000000 cf fa ed fe 07 00 00 01 03 00 00 00 02 00 00 00 |................|
00000010 04 00 00 00 30 02 00 00 01 00 00 00 00 00 00 00 |....0...........|
00000020 19 00 00 00 48 00 00 00 5f 5f 50 41 47 45 5a 45 |....H...__PAGEZE|
00000030 52 4f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |RO..............|
00000040 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000060 00 00 00 00 00 00 00 00 19 00 00 00 98 00 00 00 |................|
00000070 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
00000080 00 10 00 00 00 00 00 00 23 10 00 00 00 00 00 00 |........#.......|
00000090 00 00 00 00 00 00 00 00 23 10 00 00 00 00 00 00 |........#.......|
000000a0 07 00 00 00 05 00 00 00 01 00 00 00 00 00 00 00 |................|
000000b0 5f 5f 74 65 78 74 00 00 00 00 00 00 00 00 00 00 |__text..........|
000000c0 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
000000d0 00 20 00 00 00 00 00 00 23 00 00 00 00 00 00 00 |. ......#.......|
000000e0 00 10 00 00 06 00 00 00 00 00 00 00 00 00 00 00 |................|
000000f0 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000100 19 00 00 00 98 00 00 00 5f 5f 44 41 54 41 00 00 |........__DATA..|
00000110 00 00 00 00 00 00 00 00 00 30 00 00 00 00 00 00 |.........0......|
00000120 0c 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......|
00000130 0c 00 00 00 00 00 00 00 03 00 00 00 03 00 00 00 |................|
00000140 01 00 00 00 00 00 00 00 5f 5f 64 61 74 61 00 00 |........__data..|
00000150 00 00 00 00 00 00 00 00 5f 5f 44 41 54 41 00 00 |........__DATA..|
00000160 00 00 00 00 00 00 00 00 00 30 00 00 00 00 00 00 |.........0......|
00000170 0c 00 00 00 00 00 00 00 00 20 00 00 06 00 00 00 |......... ......|
00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000190 00 00 00 00 00 00 00 00 05 00 00 00 b8 00 00 00 |................|
000001a0 04 00 00 00 2a 00 00 00 00 00 00 00 00 00 00 00 |....*...........|
000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000220 00 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 |......... ......|
00000230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00001000 b8 04 00 00 02 bf 01 00 00 00 be 00 30 00 00 ba |............0...|
00001010 0c 00 00 00 0f 05 b8 01 00 00 02 bf 09 00 00 00 |................|
00001020 0f 05 f4 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00001030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00002000 68 65 6c 6c 6f 20 77 6f 72 6c 64 0a |hello world.|
0000200c

View File

@@ -1,34 +0,0 @@
00000000 cf fa ed fe 07 00 00 01 03 00 00 00 02 00 00 00 |................|
00000010 03 00 00 00 e8 01 00 00 01 00 00 00 00 00 00 00 |................|
00000020 19 00 00 00 48 00 00 00 5f 5f 50 41 47 45 5a 45 |....H...__PAGEZE|
00000030 52 4f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |RO..............|
00000040 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000060 00 00 00 00 00 00 00 00 19 00 00 00 e8 00 00 00 |................|
00000070 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
00000080 00 10 00 00 00 00 00 00 0c 20 00 00 00 00 00 00 |......... ......|
00000090 00 00 00 00 00 00 00 00 0c 20 00 00 00 00 00 00 |......... ......|
000000a0 07 00 00 00 05 00 00 00 02 00 00 00 00 00 00 00 |................|
000000b0 5f 5f 74 65 78 74 00 00 00 00 00 00 00 00 00 00 |__text..........|
000000c0 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
000000d0 00 20 00 00 00 00 00 00 23 00 00 00 00 00 00 00 |. ......#.......|
000000e0 00 10 00 00 06 00 00 00 00 00 00 00 00 00 00 00 |................|
000000f0 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000100 5f 5f 72 6f 64 61 74 61 00 00 00 00 00 00 00 00 |__rodata........|
00000110 5f 5f 54 45 58 54 00 00 00 00 00 00 00 00 00 00 |__TEXT..........|
00000120 00 30 00 00 00 00 00 00 0c 00 00 00 00 00 00 00 |.0..............|
00000130 00 20 00 00 06 00 00 00 00 00 00 00 00 00 00 00 |. ..............|
00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000150 05 00 00 00 b8 00 00 00 04 00 00 00 2a 00 00 00 |............*...|
00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000001e0 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |. ..............|
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00001000 b8 04 00 00 02 bf 01 00 00 00 be 00 30 00 00 ba |............0...|
00001010 0c 00 00 00 0f 05 b8 01 00 00 02 bf 00 00 00 00 |................|
00001020 0f 05 f4 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00001030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00002000 68 65 6c 6c 6f 20 77 6f 72 6c 64 0a |hello world.|
0000200c

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
// round returns size rounded up to the next multiple of align;
// align must be a power of two.
func round(size, align Addr) Addr {
return (size + align - 1) &^ (align - 1)
}

View File

@@ -1,14 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Writing of executable and (for hostlink mode) object files.
package main
import "io"
func (p *Prog) write(w io.Writer) {
p.Entry = p.Syms[p.startSym].Addr
p.formatter.write(w, p)
}

View File

@@ -11,6 +11,7 @@ import (
"io"
"os"
"os/exec"
"runtime"
"strings"
"cmd/pprof/internal/plugin"
@@ -71,15 +72,27 @@ func PProf(c Completer, interactive **bool, svgpan **string) Commands {
"eog": {c, report.Dot, invokeVisualizer(interactive, invokeDot("svg"), "svg", []string{"eog"}), false, "Visualize graph through eog"},
"evince": {c, report.Dot, invokeVisualizer(interactive, invokeDot("pdf"), "pdf", []string{"evince"}), false, "Visualize graph through evince"},
"gv": {c, report.Dot, invokeVisualizer(interactive, invokeDot("ps"), "ps", []string{"gv --noantialias"}), false, "Visualize graph through gv"},
"web": {c, report.Dot, invokeVisualizer(interactive, saveSVGToFile(svgpan), "svg", browsers), false, "Visualize graph through web browser"},
"web": {c, report.Dot, invokeVisualizer(interactive, saveSVGToFile(svgpan), "svg", browsers()), false, "Visualize graph through web browser"},
// Visualize HTML directly generated by report.
"weblist": {c, report.WebList, invokeVisualizer(interactive, awayFromTTY("html"), "html", browsers), true, "Output annotated source in HTML for functions matching regexp or address"},
"weblist": {c, report.WebList, invokeVisualizer(interactive, awayFromTTY("html"), "html", browsers()), true, "Output annotated source in HTML for functions matching regexp or address"},
}
}
// List of web browsers to attempt for web visualization
var browsers = []string{"chrome", "google-chrome", "firefox", "/usr/bin/open"}
// browsers returns a list of commands to attempt for web visualization
// on the current platform
func browsers() []string {
cmds := []string{"chrome", "google-chrome", "firefox"}
switch runtime.GOOS {
case "darwin":
cmds = append(cmds, "/usr/bin/open")
case "windows":
cmds = append(cmds, "cmd /c start")
default:
cmds = append(cmds, "xdg-open")
}
return cmds
}
// NewCompleter creates an autocompletion function for a set of commands.
func NewCompleter(cs Commands) Completer {
@@ -142,6 +155,10 @@ func awayFromTTY(format string) PostProcessor {
func invokeDot(format string) PostProcessor {
divert := awayFromTTY(format)
return func(input *bytes.Buffer, output io.Writer, ui plugin.UI) error {
if _, err := exec.LookPath("dot"); err != nil {
ui.PrintErr("Cannot find dot, have you installed Graphviz?")
return err
}
cmd := exec.Command("dot", "-T"+format)
var buf bytes.Buffer
cmd.Stdin, cmd.Stdout, cmd.Stderr = input, &buf, os.Stderr
@@ -174,6 +191,7 @@ func invokeVisualizer(interactive **bool, format PostProcessor, suffix string, v
if err = format(input, tempFile, ui); err != nil {
return err
}
tempFile.Close() // on windows, if the file is Open, start cannot access it.
// Try visualizers until one is successful
for _, v := range visualizers {
// Separate command and arguments for exec.Command.

View File

@@ -32,6 +32,10 @@ func Symbolize(mode string, prof *profile.Profile, obj plugin.ObjTool, ui plugin
}
}
if len(prof.Mapping) == 0 {
return fmt.Errorf("no known mappings")
}
mt, err := newMapping(prof, obj, ui, force)
if err != nil {
return err

View File

@@ -29,7 +29,6 @@ import (
type SyntaxError struct {
Msg string
Line int
Byte int64 // byte offset from start of stream
}
func (e *SyntaxError) Error() string {

View File

@@ -1310,11 +1310,13 @@ func (ctxt *Context) goodOSArchFile(name string, allTags map[string]bool) bool {
// auto-tagging to apply only to files with a non-empty prefix, so
// "foo_linux.go" is tagged but "linux.go" is not. This allows new operating
// sytems, such as android, to arrive without breaking existing code with
// innocuous source code in "android.go". The easiest fix: files without
// underscores are always included.
if !strings.ContainsRune(name, '_') {
// innocuous source code in "android.go". The easiest fix: cut everything
// in the name before the initial _.
i := strings.Index(name, "_")
if i < 0 {
return true
}
name = name[i:] // ignore everything before first _
l := strings.Split(name, "_")
if n := len(l); n > 0 && l[n-1] == "test" {

View File

@@ -189,6 +189,7 @@ var matchFileTests = []struct {
{ctxtAndroid, "foo_plan9.go", "", false},
{ctxtAndroid, "android.go", "", true},
{ctxtAndroid, "plan9.go", "", true},
{ctxtAndroid, "plan9_test.go", "", true},
{ctxtAndroid, "arm.s", "", true},
{ctxtAndroid, "amd64.s", "", true},
}

View File

@@ -143,6 +143,9 @@ func (d *decoder) fill() error {
// Fill in the rest of the buffer.
n, err := d.r.Read(d.bytes.buf[d.bytes.j:])
d.bytes.j += n
if n > 0 {
err = nil
}
return err
}

View File

@@ -9,6 +9,7 @@ import (
"fmt"
"image"
"image/color"
"io"
"io/ioutil"
"math/rand"
"os"
@@ -88,6 +89,51 @@ func decodeFile(filename string) (image.Image, error) {
return Decode(f)
}
type eofReader struct {
data []byte // deliver from Read without EOF
dataEOF []byte // then deliver from Read with EOF on last chunk
lenAtEOF int
}
func (r *eofReader) Read(b []byte) (n int, err error) {
if len(r.data) > 0 {
n = copy(b, r.data)
r.data = r.data[n:]
} else {
n = copy(b, r.dataEOF)
r.dataEOF = r.dataEOF[n:]
if len(r.dataEOF) == 0 {
err = io.EOF
if r.lenAtEOF == -1 {
r.lenAtEOF = n
}
}
}
return
}
func TestDecodeEOF(t *testing.T) {
// Check that if reader returns final data and EOF at same time, jpeg handles it.
data, err := ioutil.ReadFile("../testdata/video-001.jpeg")
if err != nil {
t.Fatal(err)
}
n := len(data)
for i := 0; i < n; {
r := &eofReader{data[:n-i], data[n-i:], -1}
_, err := Decode(r)
if err != nil {
t.Errorf("Decode with Read() = %d, EOF: %v", r.lenAtEOF, err)
}
if i == 0 {
i = 1
} else {
i *= 2
}
}
}
// check checks that the two pix data are equal, within the given bounds.
func check(bounds image.Rectangle, pix0, pix1 []byte, stride0, stride1 int) error {
if stride0 <= 0 || stride0%8 != 0 {

View File

@@ -887,7 +887,7 @@ func (z *Int) AndNot(x, y *Int) *Int {
}
// x &^ (-y) == x &^ ^(y-1) == x & (y-1)
y1 := nat(nil).add(y.abs, natOne)
y1 := nat(nil).sub(y.abs, natOne)
z.abs = z.abs.and(x.abs, y1)
z.neg = false
return z

View File

@@ -1201,6 +1201,7 @@ var bitwiseTests = []struct {
{"-0x01", "-0x01", "-0x01", "-0x01", "0x00", "0x00"},
{"0x07", "0x08", "0x00", "0x0f", "0x0f", "0x07"},
{"0x05", "0x0f", "0x05", "0x0f", "0x0a", "0x00"},
{"0xff", "-0x0a", "0xf6", "-0x01", "-0xf7", "0x09"},
{"0x013ff6", "0x9a4e", "0x1a46", "0x01bffe", "0x01a5b8", "0x0125b0"},
{"-0x013ff6", "0x9a4e", "0x800a", "-0x0125b2", "-0x01a5bc", "-0x01c000"},
{"-0x013ff6", "-0x9a4e", "-0x01bffe", "-0x1a46", "0x01a5b8", "0x8008"},

View File

@@ -4055,3 +4055,104 @@ func TestLargeGCProg(t *testing.T) {
fv := ValueOf(func([256]*byte) {})
fv.Call([]Value{ValueOf([256]*byte{})})
}
// Issue 9179.
func TestCallGC(t *testing.T) {
f := func(a, b, c, d, e string) {
}
g := func(in []Value) []Value {
runtime.GC()
return nil
}
typ := ValueOf(f).Type()
f2 := MakeFunc(typ, g).Interface().(func(string, string, string, string, string))
f2("four", "five5", "six666", "seven77", "eight888")
}
type funcLayoutTest struct {
rcvr, t Type
argsize, retOffset uintptr
stack []byte
}
var funcLayoutTests []funcLayoutTest
func init() {
var argAlign = PtrSize
if runtime.GOARCH == "amd64p32" {
argAlign = 2 * PtrSize
}
roundup := func(x uintptr, a uintptr) uintptr {
return (x + a - 1) / a * a
}
funcLayoutTests = append(funcLayoutTests,
funcLayoutTest{
nil,
ValueOf(func(a, b string) string { return "" }).Type(),
4 * PtrSize,
4 * PtrSize,
[]byte{BitsPointer, BitsScalar, BitsPointer},
})
var r []byte
if PtrSize == 4 {
r = []byte{BitsScalar, BitsScalar, BitsScalar, BitsPointer}
} else {
r = []byte{BitsScalar, BitsScalar, BitsPointer}
}
funcLayoutTests = append(funcLayoutTests,
funcLayoutTest{
nil,
ValueOf(func(a, b, c uint32, p *byte, d uint16) {}).Type(),
roundup(3*4, PtrSize) + PtrSize + 2,
roundup(roundup(3*4, PtrSize)+PtrSize+2, argAlign),
r,
})
funcLayoutTests = append(funcLayoutTests,
funcLayoutTest{
nil,
ValueOf(func(a map[int]int, b uintptr, c interface{}) {}).Type(),
4 * PtrSize,
4 * PtrSize,
[]byte{BitsPointer, BitsScalar, BitsPointer, BitsPointer},
})
type S struct {
a, b uintptr
c, d *byte
}
funcLayoutTests = append(funcLayoutTests,
funcLayoutTest{
nil,
ValueOf(func(a S) {}).Type(),
4 * PtrSize,
4 * PtrSize,
[]byte{BitsScalar, BitsScalar, BitsPointer, BitsPointer},
})
funcLayoutTests = append(funcLayoutTests,
funcLayoutTest{
ValueOf((*byte)(nil)).Type(),
ValueOf(func(a uintptr, b *int) {}).Type(),
3 * PtrSize,
roundup(3*PtrSize, argAlign),
[]byte{BitsPointer, BitsScalar, BitsPointer},
})
}
func TestFuncLayout(t *testing.T) {
for _, lt := range funcLayoutTests {
_, argsize, retOffset, stack := FuncLayout(lt.t, lt.rcvr)
if argsize != lt.argsize {
t.Errorf("funcLayout(%v, %v).argsize=%d, want %d", lt.t, lt.rcvr, argsize, lt.argsize)
}
if retOffset != lt.retOffset {
t.Errorf("funcLayout(%v, %v).retOffset=%d, want %d", lt.t, lt.rcvr, retOffset, lt.retOffset)
}
if !bytes.Equal(stack, lt.stack) {
t.Errorf("funcLayout(%v, %v).stack=%v, want %v", lt.t, lt.rcvr, stack, lt.stack)
}
}
}

View File

@@ -17,3 +17,22 @@ func IsRO(v Value) bool {
var ArrayOf = arrayOf
var CallGC = &callGC
const PtrSize = ptrSize
const BitsPointer = bitsPointer
const BitsScalar = bitsScalar
func FuncLayout(t Type, rcvr Type) (frametype Type, argSize, retOffset uintptr, stack []byte) {
var ft *rtype
var s *bitVector
if rcvr != nil {
ft, argSize, retOffset, s = funcLayout(t.(*rtype), rcvr.(*rtype))
} else {
ft, argSize, retOffset, s = funcLayout(t.(*rtype), nil)
}
frametype = ft
for i := uint32(0); i < s.n; i += 2 {
stack = append(stack, s.data[i/8]>>(i%8)&3)
}
return
}

View File

@@ -1498,8 +1498,9 @@ func MapOf(key, elem Type) Type {
// gcProg is a helper type for generatation of GC pointer info.
type gcProg struct {
gc []byte
size uintptr // size of type in bytes
gc []byte
size uintptr // size of type in bytes
hasPtr bool
}
func (gc *gcProg) append(v byte) {
@@ -1560,11 +1561,14 @@ func (gc *gcProg) appendWord(v byte) {
gc.gc[nptr/2] &= ^(3 << ((nptr%2)*4 + 2))
gc.gc[nptr/2] |= v << ((nptr%2)*4 + 2)
gc.size += ptrsize
if v == bitsPointer {
gc.hasPtr = true
}
}
func (gc *gcProg) finalize() unsafe.Pointer {
func (gc *gcProg) finalize() (unsafe.Pointer, bool) {
if gc.size == 0 {
return nil
return nil, false
}
ptrsize := unsafe.Sizeof(uintptr(0))
gc.align(ptrsize)
@@ -1579,7 +1583,7 @@ func (gc *gcProg) finalize() unsafe.Pointer {
gc.appendWord(extractGCWord(gc.gc, i))
}
}
return unsafe.Pointer(&gc.gc[0])
return unsafe.Pointer(&gc.gc[0]), gc.hasPtr
}
func extractGCWord(gc []byte, i uintptr) byte {
@@ -1624,10 +1628,6 @@ func bucketOf(ktyp, etyp *rtype) *rtype {
for i := 0; i < int(bucketSize*unsafe.Sizeof(uint8(0))/ptrsize); i++ {
gc.append(bitsScalar)
}
gc.append(bitsPointer) // overflow
if runtime.GOARCH == "amd64p32" {
gc.append(bitsScalar)
}
// keys
for i := 0; i < bucketSize; i++ {
gc.appendProg(ktyp)
@@ -1636,10 +1636,15 @@ func bucketOf(ktyp, etyp *rtype) *rtype {
for i := 0; i < bucketSize; i++ {
gc.appendProg(etyp)
}
// overflow
gc.append(bitsPointer)
if runtime.GOARCH == "amd64p32" {
gc.append(bitsScalar)
}
b := new(rtype)
b.size = gc.size
b.gc[0] = gc.finalize()
b.gc[0], _ = gc.finalize()
s := "bucket(" + *ktyp.string + "," + *etyp.string + ")"
b.string = &s
return b
@@ -1840,7 +1845,11 @@ func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uin
// build dummy rtype holding gc program
x := new(rtype)
x.size = gc.size
x.gc[0] = gc.finalize()
var hasPtr bool
x.gc[0], hasPtr = gc.finalize()
if !hasPtr {
x.kind |= kindNoPointers
}
var s string
if rcvr != nil {
s = "methodargs(" + *rcvr.string + ")(" + *t.string + ")"
@@ -1894,14 +1903,14 @@ func addTypeBits(bv *bitVector, offset *uintptr, t *rtype) {
switch Kind(t.kind & kindMask) {
case Chan, Func, Map, Ptr, Slice, String, UnsafePointer:
// 1 pointer at start of representation
for bv.n < uint32(*offset/uintptr(ptrSize)) {
for bv.n < 2*uint32(*offset/uintptr(ptrSize)) {
bv.append2(bitsScalar)
}
bv.append2(bitsPointer)
case Interface:
// 2 pointers
for bv.n < uint32(*offset/uintptr(ptrSize)) {
for bv.n < 2*uint32(*offset/uintptr(ptrSize)) {
bv.append2(bitsScalar)
}
bv.append2(bitsPointer)

View File

@@ -64,17 +64,6 @@ echo
echo '# sync -cpu=10'
go test sync -short -timeout=$(expr 120 \* $timeout_scale)s -cpu=10
# Race detector only supported on Linux, FreeBSD and OS X,
# and only on amd64, and only when cgo is enabled.
case "$GOHOSTOS-$GOOS-$GOARCH-$CGO_ENABLED" in
linux-linux-amd64-1 | freebsd-freebsd-amd64-1 | darwin-darwin-amd64-1)
echo
echo '# Testing race detector.'
go test -race -i runtime/race flag
go test -race -run=Output runtime/race
go test -race -short flag
esac
xcd() {
echo
echo '#' $1
@@ -120,6 +109,7 @@ go run $GOROOT/test/run.go - . || exit 1
[ "$CGO_ENABLED" != 1 ] ||
(xcd ../misc/cgo/test
# cgo tests inspect the traceback for runtime functions
extlink=0
export GOTRACEBACK=2
go test -ldflags '-linkmode=auto' || exit 1
# linkmode=internal fails on dragonfly since errno is a TLS relocation.
@@ -128,19 +118,24 @@ case "$GOHOSTOS-$GOARCH" in
openbsd-386 | openbsd-amd64)
# test linkmode=external, but __thread not supported, so skip testtls.
go test -ldflags '-linkmode=external' || exit 1
extlink=1
;;
darwin-386 | darwin-amd64)
# linkmode=external fails on OS X 10.6 and earlier == Darwin
# 10.8 and earlier.
case $(uname -r) in
[0-9].* | 10.*) ;;
*) go test -ldflags '-linkmode=external' || exit 1;;
*)
go test -ldflags '-linkmode=external' || exit 1
extlink=1
;;
esac
;;
android-arm | dragonfly-386 | dragonfly-amd64 | freebsd-386 | freebsd-amd64 | freebsd-arm | linux-386 | linux-amd64 | linux-arm | netbsd-386 | netbsd-amd64)
go test -ldflags '-linkmode=external' || exit 1
go test -ldflags '-linkmode=auto' ../testtls || exit 1
go test -ldflags '-linkmode=external' ../testtls || exit 1
extlink=1
case "$GOHOSTOS-$GOARCH" in
netbsd-386 | netbsd-amd64) ;; # no static linking
@@ -164,6 +159,23 @@ android-arm | dragonfly-386 | dragonfly-amd64 | freebsd-386 | freebsd-amd64 | fr
esac
) || exit $?
# Race detector only supported on Linux, FreeBSD and OS X,
# and only on amd64, and only when cgo is enabled.
# Delayed until here so we know whether to try external linking.
case "$GOHOSTOS-$GOOS-$GOARCH-$CGO_ENABLED" in
linux-linux-amd64-1 | freebsd-freebsd-amd64-1 | darwin-darwin-amd64-1)
echo
echo '# Testing race detector.'
go test -race -i runtime/race flag os/exec
go test -race -run=Output runtime/race
go test -race -short flag os/exec
# Test with external linking; see issue 9133.
if [ "$extlink" = 1 ]; then
go test -race -short -ldflags=-linkmode=external flag os/exec
fi
esac
# This tests cgo -cdefs. That mode is not supported,
# so it's okay if it doesn't work on some systems.
# In particular, it works badly with clang on OS X.

View File

@@ -65,12 +65,39 @@ thread_start_wrapper(void *arg)
return args.func(args.arg);
}
static void init_pthread_wrapper(void) {
void *handle;
// Locate symbol for the system pthread_create function.
handle = dlopen("libpthread.so", RTLD_LAZY);
if(handle == NULL) {
fprintf(stderr, "runtime/cgo: dlopen failed to load libpthread: %s\n", dlerror());
abort();
}
sys_pthread_create = dlsym(handle, "pthread_create");
if(sys_pthread_create == NULL) {
fprintf(stderr, "runtime/cgo: dlsym failed to find pthread_create: %s\n", dlerror());
abort();
}
dlclose(handle);
}
static pthread_once_t init_pthread_wrapper_once = PTHREAD_ONCE_INIT;
int
pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg)
{
struct thread_args *p;
// we must initialize our wrapper in pthread_create, because it is valid to call
// pthread_create in a static constructor, and in fact, our test for issue 9456
// does just that.
if(pthread_once(&init_pthread_wrapper_once, init_pthread_wrapper) != 0) {
fprintf(stderr, "runtime/cgo: failed to initialize pthread_create wrapper\n");
abort();
}
p = malloc(sizeof(*p));
if(p == NULL) {
errno = ENOMEM;
@@ -87,7 +114,6 @@ x_cgo_init(G *g, void (*setg)(void*))
{
pthread_attr_t attr;
size_t size;
void *handle;
setg_gcc = setg;
pthread_attr_init(&attr);
@@ -95,18 +121,10 @@ x_cgo_init(G *g, void (*setg)(void*))
g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
// Locate symbol for the system pthread_create function.
handle = dlopen("libpthread.so", RTLD_LAZY);
if(handle == NULL) {
fprintf(stderr, "dlopen: failed to load libpthread: %s\n", dlerror());
if(pthread_once(&init_pthread_wrapper_once, init_pthread_wrapper) != 0) {
fprintf(stderr, "runtime/cgo: failed to initialize pthread_create wrapper\n");
abort();
}
sys_pthread_create = dlsym(handle, "pthread_create");
if(sys_pthread_create == NULL) {
fprintf(stderr, "dlsym: failed to find pthread_create: %s\n", dlerror());
abort();
}
dlclose(handle);
tcb_fixup(1);
}

View File

@@ -65,12 +65,39 @@ thread_start_wrapper(void *arg)
return args.func(args.arg);
}
static void init_pthread_wrapper(void) {
void *handle;
// Locate symbol for the system pthread_create function.
handle = dlopen("libpthread.so", RTLD_LAZY);
if(handle == NULL) {
fprintf(stderr, "runtime/cgo: dlopen failed to load libpthread: %s\n", dlerror());
abort();
}
sys_pthread_create = dlsym(handle, "pthread_create");
if(sys_pthread_create == NULL) {
fprintf(stderr, "runtime/cgo: dlsym failed to find pthread_create: %s\n", dlerror());
abort();
}
dlclose(handle);
}
static pthread_once_t init_pthread_wrapper_once = PTHREAD_ONCE_INIT;
int
pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg)
{
struct thread_args *p;
// we must initialize our wrapper in pthread_create, because it is valid to call
// pthread_create in a static constructor, and in fact, our test for issue 9456
// does just that.
if(pthread_once(&init_pthread_wrapper_once, init_pthread_wrapper) != 0) {
fprintf(stderr, "runtime/cgo: failed to initialize pthread_create wrapper\n");
abort();
}
p = malloc(sizeof(*p));
if(p == NULL) {
errno = ENOMEM;
@@ -87,7 +114,6 @@ x_cgo_init(G *g, void (*setg)(void*))
{
pthread_attr_t attr;
size_t size;
void *handle;
setg_gcc = setg;
pthread_attr_init(&attr);
@@ -95,18 +121,10 @@ x_cgo_init(G *g, void (*setg)(void*))
g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
// Locate symbol for the system pthread_create function.
handle = dlopen("libpthread.so", RTLD_LAZY);
if(handle == NULL) {
fprintf(stderr, "dlopen: failed to load libpthread: %s\n", dlerror());
if(pthread_once(&init_pthread_wrapper_once, init_pthread_wrapper) != 0) {
fprintf(stderr, "runtime/cgo: failed to initialize pthread_create wrapper\n");
abort();
}
sys_pthread_create = dlsym(handle, "pthread_create");
if(sys_pthread_create == NULL) {
fprintf(stderr, "dlsym: failed to find pthread_create: %s\n", dlerror());
abort();
}
dlclose(handle);
tcb_fixup(1);
}

View File

@@ -7,6 +7,7 @@
package runtime_test
import (
"os/exec"
"runtime"
"strings"
"testing"
@@ -50,6 +51,30 @@ func TestCgoExternalThreadPanic(t *testing.T) {
}
}
func TestCgoExternalThreadSIGPROF(t *testing.T) {
// issue 9456.
switch runtime.GOOS {
case "plan9", "windows":
t.Skipf("no pthreads on %s", runtime.GOOS)
case "darwin":
// static constructor needs external linking, but we don't support
// external linking on OS X 10.6.
out, err := exec.Command("uname", "-r").Output()
if err != nil {
t.Fatalf("uname -r failed: %v", err)
}
// OS X 10.6 == Darwin 10.x
if strings.HasPrefix(string(out), "10.") {
t.Skipf("no external linking on OS X 10.6")
}
}
got := executeTest(t, cgoExternalThreadSIGPROFSource, nil)
want := "OK\n"
if got != want {
t.Fatalf("expected %q, but got %q", want, got)
}
}
const cgoSignalDeadlockSource = `
package main
@@ -194,3 +219,46 @@ start(void)
printf("_beginthreadex failed\n");
}
`
const cgoExternalThreadSIGPROFSource = `
package main
/*
#include <stdint.h>
#include <signal.h>
#include <pthread.h>
volatile int32_t spinlock;
static void *thread1(void *p) {
(void)p;
while (spinlock == 0)
;
pthread_kill(pthread_self(), SIGPROF);
spinlock = 0;
return NULL;
}
__attribute__((constructor)) void issue9456() {
pthread_t tid;
pthread_create(&tid, 0, thread1, NULL);
}
*/
import "C"
import (
"runtime"
"sync/atomic"
"unsafe"
)
func main() {
// This test intends to test that sending SIGPROF to foreign threads
// before we make any cgo call will not abort the whole process, so
// we cannot make any cgo call here. See http://golang.org/issue/9456.
atomic.StoreInt32((*int32)(unsafe.Pointer(&C.spinlock)), 1)
for atomic.LoadInt32((*int32)(unsafe.Pointer(&C.spinlock))) == 1 {
runtime.Gosched()
}
println("OK")
}
`

View File

@@ -41,6 +41,7 @@ const (
DUPLICATE_SAME_ACCESS = C.DUPLICATE_SAME_ACCESS
THREAD_PRIORITY_HIGHEST = C.THREAD_PRIORITY_HIGHEST
SIGPROF = 0 // dummy value for badsignal
SIGINT = C.SIGINT
CTRL_C_EVENT = C.CTRL_C_EVENT
CTRL_BREAK_EVENT = C.CTRL_BREAK_EVENT

View File

@@ -117,12 +117,12 @@ type hmap struct {
// A bucket for a Go map.
type bmap struct {
tophash [bucketCnt]uint8
overflow *bmap
tophash [bucketCnt]uint8
// Followed by bucketCnt keys and then bucketCnt values.
// NOTE: packing all the keys together and then all the values together makes the
// code a bit more complicated than alternating key/value/key/value/... but it allows
// us to eliminate padding which would be needed for, e.g., map[int64]int8.
// Followed by an overflow pointer.
}
// A hash iteration structure.
@@ -149,6 +149,13 @@ func evacuated(b *bmap) bool {
return h > empty && h < minTopHash
}
func (b *bmap) overflow(t *maptype) *bmap {
return *(**bmap)(add(unsafe.Pointer(b), uintptr(t.bucketsize)-regSize))
}
func (b *bmap) setoverflow(t *maptype, ovf *bmap) {
*(**bmap)(add(unsafe.Pointer(b), uintptr(t.bucketsize)-regSize)) = ovf
}
func makemap(t *maptype, hint int64) *hmap {
if sz := unsafe.Sizeof(hmap{}); sz > 48 || sz != uintptr(t.hmap.size) {
gothrow("bad hmap size")
@@ -275,7 +282,7 @@ func mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
return v
}
}
b = b.overflow
b = b.overflow(t)
if b == nil {
return unsafe.Pointer(t.elem.zero)
}
@@ -323,7 +330,7 @@ func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool)
return v, true
}
}
b = b.overflow
b = b.overflow(t)
if b == nil {
return unsafe.Pointer(t.elem.zero), false
}
@@ -366,7 +373,7 @@ func mapaccessK(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, unsafe
return k, v
}
}
b = b.overflow
b = b.overflow(t)
if b == nil {
return nil, nil
}
@@ -437,10 +444,11 @@ again:
memmove(v2, val, uintptr(t.elem.size))
return
}
if b.overflow == nil {
ovf := b.overflow(t)
if ovf == nil {
break
}
b = b.overflow
b = ovf
}
// did not find mapping for key. Allocate new cell & add entry.
@@ -455,7 +463,7 @@ again:
memstats.next_gc = memstats.heap_alloc
}
newb := (*bmap)(newobject(t.bucket))
b.overflow = newb
b.setoverflow(t, newb)
inserti = &newb.tophash[0]
insertk = add(unsafe.Pointer(newb), dataOffset)
insertv = add(insertk, bucketCnt*uintptr(t.keysize))
@@ -525,7 +533,7 @@ func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
h.count--
return
}
b = b.overflow
b = b.overflow(t)
if b == nil {
return
}
@@ -720,7 +728,7 @@ next:
return
}
}
b = b.overflow
b = b.overflow(t)
i = 0
goto next
}
@@ -778,7 +786,7 @@ func evacuate(t *maptype, h *hmap, oldbucket uintptr) {
yk := add(unsafe.Pointer(y), dataOffset)
xv := add(xk, bucketCnt*uintptr(t.keysize))
yv := add(yk, bucketCnt*uintptr(t.keysize))
for ; b != nil; b = b.overflow {
for ; b != nil; b = b.overflow(t) {
k := add(unsafe.Pointer(b), dataOffset)
v := add(k, bucketCnt*uintptr(t.keysize))
for i := 0; i < bucketCnt; i, k, v = i+1, add(k, uintptr(t.keysize)), add(v, uintptr(t.valuesize)) {
@@ -828,7 +836,7 @@ func evacuate(t *maptype, h *hmap, oldbucket uintptr) {
memstats.next_gc = memstats.heap_alloc
}
newx := (*bmap)(newobject(t.bucket))
x.overflow = newx
x.setoverflow(t, newx)
x = newx
xi = 0
xk = add(unsafe.Pointer(x), dataOffset)
@@ -855,7 +863,7 @@ func evacuate(t *maptype, h *hmap, oldbucket uintptr) {
memstats.next_gc = memstats.heap_alloc
}
newy := (*bmap)(newobject(t.bucket))
y.overflow = newy
y.setoverflow(t, newy)
y = newy
yi = 0
yk = add(unsafe.Pointer(y), dataOffset)
@@ -881,7 +889,6 @@ func evacuate(t *maptype, h *hmap, oldbucket uintptr) {
// Unlink the overflow buckets & clear key/value to help GC.
if h.flags&oldIterator == 0 {
b = (*bmap)(add(h.oldbuckets, oldbucket*uintptr(t.bucketsize)))
b.overflow = nil
memclr(add(unsafe.Pointer(b), dataOffset), uintptr(t.bucketsize)-dataOffset)
}
}

View File

@@ -43,7 +43,7 @@ func mapaccess1_fast32(t *maptype, h *hmap, key uint32) unsafe.Pointer {
}
return add(unsafe.Pointer(b), dataOffset+bucketCnt*4+i*uintptr(t.valuesize))
}
b = b.overflow
b = b.overflow(t)
if b == nil {
return unsafe.Pointer(t.elem.zero)
}
@@ -85,7 +85,7 @@ func mapaccess2_fast32(t *maptype, h *hmap, key uint32) (unsafe.Pointer, bool) {
}
return add(unsafe.Pointer(b), dataOffset+bucketCnt*4+i*uintptr(t.valuesize)), true
}
b = b.overflow
b = b.overflow(t)
if b == nil {
return unsafe.Pointer(t.elem.zero), false
}
@@ -127,7 +127,7 @@ func mapaccess1_fast64(t *maptype, h *hmap, key uint64) unsafe.Pointer {
}
return add(unsafe.Pointer(b), dataOffset+bucketCnt*8+i*uintptr(t.valuesize))
}
b = b.overflow
b = b.overflow(t)
if b == nil {
return unsafe.Pointer(t.elem.zero)
}
@@ -169,7 +169,7 @@ func mapaccess2_fast64(t *maptype, h *hmap, key uint64) (unsafe.Pointer, bool) {
}
return add(unsafe.Pointer(b), dataOffset+bucketCnt*8+i*uintptr(t.valuesize)), true
}
b = b.overflow
b = b.overflow(t)
if b == nil {
return unsafe.Pointer(t.elem.zero), false
}
@@ -271,7 +271,7 @@ dohash:
return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+i*uintptr(t.valuesize))
}
}
b = b.overflow
b = b.overflow(t)
if b == nil {
return unsafe.Pointer(t.elem.zero)
}
@@ -371,7 +371,7 @@ dohash:
return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+i*uintptr(t.valuesize)), true
}
}
b = b.overflow
b = b.overflow(t)
if b == nil {
return unsafe.Pointer(t.elem.zero), false
}

Some files were not shown because too many files have changed in this diff Show More