Compare commits

...

68 Commits

Author SHA1 Message Date
Andrew Gerrand
4abdb873be go1.2rc5
R=dsymonds
CC=golang-dev
https://golang.org/cl/28140043
2013-11-18 12:44:03 +11:00
Andrew Gerrand
1ca6226dda [release-branch.go1.2] C: add Marko Mikulicic (Google CLA)
««« CL 27000043 / c8d3de543c1b
C: add Marko Mikulicic (Google CLA)

R=golang-dev, crawshaw
CC=golang-dev
https://golang.org/cl/27000043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/28130043
2013-11-18 12:41:48 +11:00
Andrew Gerrand
6d8aa1bcbb [release-branch.go1.2] doc/asm: more about SP, ARM R11
««« CL 26170043 / b1edf8faa5d6
doc/asm: more about SP, ARM R11

Also rename URL to /doc/asm.

R=golang-dev, minux.ma, r
CC=golang-dev
https://golang.org/cl/26170043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/28120043
2013-11-18 12:40:54 +11:00
Andrew Gerrand
0bb20c6189 [release-branch.go1.2] encoding/gob: do not use MarshalText, UnmarshalText
««« CL 22770044 / 23fc3139589c
encoding/gob: do not use MarshalText, UnmarshalText

This seems to be the best of a long list of bad ways to fix this issue.

Fixes #6760.

R=r
CC=golang-dev
https://golang.org/cl/22770044
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/28110043
2013-11-18 12:40:00 +11:00
Andrew Gerrand
3409e2a2e6 [release-branch.go1.2] encoding/gob: expose encode/decode example
««« CL 26220045 / d76ade89413f
encoding/gob: expose encode/decode example

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/26220045
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25380044
2013-11-18 12:38:31 +11:00
Andrew Gerrand
a5940dddba go1.2rc4
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/25420045
2013-11-13 15:29:48 +11:00
Andrew Gerrand
8a28f58bc9 [release-branch.go1.2] src/cmd/?a: link to new assembler document
««« CL 18430044 / 1a86e8314ff5
src/cmd/?a: link to new assembler document
Blocked on 20930043, the CL the new text references.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/18430044
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25480046
2013-11-13 15:17:48 +11:00
Andrew Gerrand
af4b9ae6e1 [release-branch.go1.2] doc/asm.html: new document, a brief guide to the assembler
««« CL 20930043 / 5a585f237d28
doc/asm.html: new document, a brief guide to the assembler

Fixes #6060

R=golang-dev, iant, bradfitz, josharian, minux.ma, aram, rsc
CC=golang-dev
https://golang.org/cl/20930043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25820043
2013-11-13 15:13:59 +11:00
Andrew Gerrand
61af4f905b [release-branch.go1.2] spec: clarify rules for blank identifiers
««« CL 14415043 / 4daa80747394
spec: clarify rules for blank identifiers

This documents the status quo more precisely.
Not a language change.

Fixes #6006.

R=r, rsc, iant, ken
CC=golang-dev
https://golang.org/cl/14415043

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25790043
2013-11-13 14:40:41 +11:00
Andrew Gerrand
cd618b24a6 [release-branch.go1.2] doc: use the same wording for OS X as the other OSes
««« CL 25670043 / b7308814101a
doc: use the same wording for OS X as the other OSes

I used "and above" when I should have said "or later".

Sorry for the churn.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/25670043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25780043
2013-11-13 14:39:53 +11:00
Andrew Gerrand
268d4631ae [release-branch.go1.2] doc: we support all recent versions of OS X
««« CL 25370045 / d809ded6f335
doc: we support all recent versions of OS X

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/25370045
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25580044
2013-11-13 14:39:07 +11:00
Andrew Gerrand
2b6571cdfa [release-branch.go1.2] CONTRIBUTORS: add additional e-mail address for Richard Musiol
««« CL 25360043 / 37afbf6361e2
CONTRIBUTORS: add additional e-mail address for Richard Musiol

R=adonovan
CC=golang-dev
https://golang.org/cl/25360043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25770043
2013-11-13 14:38:19 +11:00
Andrew Gerrand
02c5ab4f87 [release-branch.go1.2] A+C: Richard Musiol (individual CLA)
««« CL 25350043 / d3cc963320cd
A+C: Richard Musiol (individual CLA)

Generated by addca.

R=gobot
CC=golang-dev
https://golang.org/cl/25350043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25670044
2013-11-13 14:37:32 +11:00
Andrew Gerrand
9af8f45258 [release-branch.go1.2] misc/vim: add a gofmt_command flag for :Fmt
««« CL 22940044 / 39c724dd7f25
misc/vim: add a gofmt_command flag for :Fmt

R=dsymonds, dominik.honnef, n13m3y3r, rsc, kamil.kisiel
CC=golang-dev
https://golang.org/cl/22940044

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25760043
2013-11-13 14:36:45 +11:00
Andrew Gerrand
021476db3b [release-branch.go1.2] cmd/godoc: document package-level examples
««« CL 23940043 / 6ad0ec54cf2d
cmd/godoc: document package-level examples

Fixes  issue  5807 .

R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/23940043

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25500045
2013-11-13 14:35:59 +11:00
Andrew Gerrand
1c961995ae [release-branch.go1.2] misc/emacs: various cleanups
««« CL 20100043 / 9fe43a708b89
misc/emacs: various cleanups

- Use #' for function symbols
- Remove unused variables
- Use declare-function to shut up byte compiler

This is identical to CL 19010044 with one exception: Making sure
it doesn't break on Emacs 22.1

R=adonovan, bradfitz, shendaras
CC=golang-dev
https://golang.org/cl/20100043

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25750043
2013-11-13 14:35:13 +11:00
Andrew Gerrand
1bca9371e7 [release-branch.go1.2] emacs: allow users to customize the gofmt command, in particular, to use goimports instead.
««« CL 23680043 / 341a490e4736
emacs: allow users to customize the gofmt command, in particular, to use goimports instead.

R=adonovan
CC=golang-dev
https://golang.org/cl/23680043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25740043
2013-11-13 14:34:24 +11:00
Andrew Gerrand
6ec8f31510 [release-branch.go1.2] cmd/cgo: fix handling of array of pointers when using clang
««« CL 22840043 / e6794866ebeb
cmd/cgo: fix handling of array of pointers when using clang

Clang does not record the "size" field for pointer types,
so we must insert the size ourselves. We were already
doing this, but only for the case of pointer types.
For an array of pointer types, the setting of the size for
the nested pointer type was happening after the computation
of the size of the array type, meaning that the array type
was always computed as 0 bytes. Delay the size computation.

This bug happens on all Clang systems, not just FreeBSD.
Our test checked that cgo wrote something, not that it was correct.
FreeBSD's default clang rejects array[0] as a C struct field,
so it noticed the incorrect sizes. But the sizes were incorrect
everywhere.

Update testcdefs to check the output has the right semantics.

Fixes #6292.

R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/22840043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25460046
2013-11-13 14:33:38 +11:00
Andrew Gerrand
f0189653ca [release-branch.go1.2] doc: update note about GCC 4.8.2 in gccgo instructions
««« CL 22510043 / 77e77f508509
doc: update note about GCC 4.8.2 in gccgo instructions

R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/22510043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25730043
2013-11-13 14:32:47 +11:00
Andrew Gerrand
f7edec22f7 [release-branch.go1.2] go/doc: add full stop of Japanese, Chinese and Korean.
««« CL 21130043 / 0685a9549d5a
go/doc: add full stop of Japanese, Chinese and Korean.

This fix will show a good synopsis on package listings in that languages.

R=adg, r
CC=golang-dev
https://golang.org/cl/21130043

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25720043
2013-11-13 14:31:58 +11:00
Andrew Gerrand
9cb593dc89 [release-branch.go1.2] A+C: Ato Araki (individual CLA)
««« CL 21790043 / cbbdbdf908b9
A+C: Ato Araki (individual CLA)

Generated by addca.

R=gobot
CC=golang-dev
https://golang.org/cl/21790043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25640046
2013-11-13 14:31:09 +11:00
Andrew Gerrand
db1c08e7a1 [release-branch.go1.2] doc/go1.2: link to cgo documentation
««« CL 21770043 / ae58065f7dff
doc/go1.2: link to cgo documentation

I know it's linked in the previous sentence, but this new link is where I want it to be while reading this sentence.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/21770043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25640045
2013-11-13 14:30:20 +11:00
Andrew Gerrand
4f8794d3e7 [release-branch.go1.2] net/textproto: fix CanonicalMIMEHeaderKey panic
««« CL 21450043 / e081962da65c
net/textproto: fix CanonicalMIMEHeaderKey panic

Fixes #6712

R=golang-dev, adg, rsc
CC=golang-dev
https://golang.org/cl/21450043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25640044
2013-11-13 14:29:35 +11:00
Andrew Gerrand
065f8fd5a7 [release-branch.go1.2] C: add Robert Snedegar (Google CLA)
««« CL 21390044 / dc2762a9130d
C: add Robert Snedegar (Google CLA)

R=golang-dev
CC=golang-dev
https://golang.org/cl/21390044
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25420044
2013-11-13 14:28:46 +11:00
Andrew Gerrand
e491f0c376 [release-branch.go1.2] C: add Brad Garcia (Google CLA)
««« CL 19990045 / 78cebfb89b21
C: add Brad Garcia (Google CLA)

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/19990045
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/25700044
2013-11-13 14:27:59 +11:00
Andrew Gerrand
2eb51b1ba8 go1.2rc3
R=golang-dev, nigeltao
CC=golang-dev
https://golang.org/cl/19560047
2013-11-01 12:44:30 +11:00
Andrew Gerrand
4708b76f84 [release-branch.go1.2] cmd/5l, runtime: fix divide for profiling tracebacks on ARM
««« CL 19910044 / 9eb64f5ef3a6
cmd/5l, runtime: fix divide for profiling tracebacks on ARM

Two bugs:
1. The first iteration of the traceback always uses LR when provided,
which it is (only) during a profiling signal, but in fact LR is correct
only if the stack frame has not been allocated yet. Otherwise an
intervening call may have changed LR, and the saved copy in the stack
frame should be used. Fix in traceback_arm.c.

2. The division runtime call adds 8 bytes to the stack. In order to
keep the traceback routines happy, it must copy the saved LR into
the new 0(SP). Change

        SUB $8, SP

into

        MOVW    0(SP), R11 // r11 is temporary, for use by linker
        MOVW.W  R11, -8(SP)

to update SP and 0(SP) atomically, so that the traceback always
sees a saved LR at 0(SP).

Fixes #6681.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/19910044
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20170048
2013-11-01 11:34:40 +11:00
Andrew Gerrand
1d78c86897 [release-branch.go1.2] doc/go1.2.html: delete repeated word
««« CL 19840043 / 938b64b0f608
doc/go1.2.html: delete repeated word
TBR=rsc

R=golang-dev
CC=golang-dev
https://golang.org/cl/19840043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20240044
2013-11-01 11:33:51 +11:00
Andrew Gerrand
28c1081208 [release-branch.go1.2] doc/go1.2.html: stack sizes, thread limits
««« CL 19600043 / 746466b52725
doc/go1.2.html: stack sizes, thread limits

R=golang-dev, minux.ma, adg, rsc
CC=golang-dev
https://golang.org/cl/19600043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20110046
2013-11-01 11:33:03 +11:00
Andrew Gerrand
8648d26c5f [release-branch.go1.2] cmd/cgo: accept extra leading _ on __cgodebug_data for all object formats
««« CL 19780043 / 8b49cdda6ff4
cmd/cgo: accept extra leading _ on __cgodebug_data for all object formats

The current Windows build breakage appears to be because
the Windows code should be looking for __cgodebug_data
not ___cgodebug_data. Dodge the question everywhere by
accepting both.

R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/19780043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20660043
2013-11-01 11:32:10 +11:00
Andrew Gerrand
63ff715a55 [release-branch.go1.2] database/sql: document Result methods
««« CL 19280046 / 2ad8ac71220d
database/sql: document Result methods

Fixes #5110

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/19280046
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20650043
2013-11-01 11:31:18 +11:00
Andrew Gerrand
6d10afd9e5 [release-branch.go1.2] database/sql: Fix typos in doc
««« CL 17590043 / fb5224487f1b
database/sql: Fix typos in doc

R=golang-dev
CC=bradfitz, golang-dev
https://golang.org/cl/17590043

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20150046
2013-11-01 11:30:30 +11:00
Andrew Gerrand
89f0148955 [release-branch.go1.2] A+C: Jakob Borg (individual CLA).
««« CL 19510043 / ae106f792e5d
A+C: Jakob Borg (individual CLA).

R=golang-dev
CC=golang-dev
https://golang.org/cl/19510043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20570045
2013-11-01 11:29:41 +11:00
Andrew Gerrand
842a18c28f [release-branch.go1.2] time: correct path to time zone zip file on Unix
««« CL 19280043 / 9d199c7582d6
time: correct path to time zone zip file on Unix

Most Unix systems have their own time zone data,
so we almost never get far enough in the list to
discover that we cannot fall back to the zip file.
Adjust testing to exercise the final fallback.

Plan 9 and Windows were already correct
(and are the main users of the zip file).

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/19280043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20640043
2013-11-01 11:28:57 +11:00
Andrew Gerrand
6ab0f588a8 [release-branch.go1.2] encoding/xml: fix doc comment
««« CL 19300046 / 5ac568b9d67b
encoding/xml: fix doc comment

The tag is ",chardata" not "chardata".

Fixes #6631.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/19300046
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20060045
2013-11-01 11:28:07 +11:00
Andrew Gerrand
71b3aca9fa [release-branch.go1.2] net/http/httputil: fix DumpRequestOut with ContentLength & false body param
««« CL 14920050 / 5ed8c82778ae
net/http/httputil: fix DumpRequestOut with ContentLength & false body param

Fixes #6471

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/14920050
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20590044
2013-11-01 11:27:19 +11:00
Andrew Gerrand
a4085fdf10 [release-branch.go1.2] os: do not return Lstat errors from Readdir
««« CL 18870043 / eca0ca43a863
os: do not return Lstat errors from Readdir

This CL restores the Go 1.1.2 semantics for os.File's Readdir method.

The code in Go 1.1.2 was rewritten mainly because it looked buggy.
This new version attempts to be clearer but still provide the 1.1.2 results.

The important diff is not this CL's version against tip but this CL's version
against Go 1.1.2.

Go 1.1.2:

        names, err := f.Readdirnames(n)
        fi = make([]FileInfo, len(names))
        for i, filename := range names {
                fip, err := Lstat(dirname + filename)
                if err == nil {
                        fi[i] = fip
                } else {
                        fi[i] = &fileStat{name: filename}
                }
        }
        return fi, err

This CL:

        names, err := f.Readdirnames(n)
        fi = make([]FileInfo, len(names))
        for i, filename := range names {
                fip, lerr := lstat(dirname + filename)
                if lerr != nil {
                        fi[i] = &fileStat{name: filename}
                        continue
                }
                fi[i] = fip
        }
        return fi, err

The changes from Go 1.1.2 are stylistic, not semantic:
1. Use lstat instead of Lstat, for testing (done before this CL).
2. Make error handling in loop body look more like an error case.
3. Use separate error variable name in loop body, to be clear
   we are not trying to influence the final return result.

Fixes #6656.
Fixes #6680.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/18870043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20110045
2013-11-01 11:26:31 +11:00
Andrew Gerrand
d4bc355c56 [release-branch.go1.2] cmd/gc: silence clang warning
««« CL 19160043 / 104d56b5d664
cmd/gc: silence clang warning

This code is only built when you run 'make' in cmd/gc,
not in all.bash.

R=golang-dev, jsing, iant
CC=golang-dev
https://golang.org/cl/19160043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20290046
2013-11-01 11:25:45 +11:00
Andrew Gerrand
2737f274f5 [release-branch.go1.2] misc/emacs: support godef-jump on import statements
««« CL 18230043 / f2b59b5163b0
misc/emacs: support godef-jump on import statements

The newest version of godef supports jumping to a package's source
directory if point is on an import statement.

R=adonovan
CC=golang-dev
https://golang.org/cl/18230043

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20620043
2013-11-01 11:24:57 +11:00
Andrew Gerrand
744d53cdeb [release-branch.go1.2] debug/dwarf: add DWARF 4 form constants
««« CL 18460043 / 08e6655618f5
debug/dwarf: add DWARF 4 form constants

Some versions of clang generate DWARF 4-format attributes
even when using -gdwarf-2. We don't care much about the
values, but we do need to be able to parse past them.

This fixes a bug in Go 1.2 rc2 reported via private mail using
a near-tip version of clang.

R=golang-dev, iant, dvyukov
CC=golang-dev
https://golang.org/cl/18460043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20470045
2013-11-01 11:24:11 +11:00
Andrew Gerrand
2cce16c4a0 [release-branch.go1.2] doc: update front page summary text
««« CL 18080045 / 5ffdb9cc0bfe
doc: update front page summary text

R=rsc
CC=golang-dev
https://golang.org/cl/18080045
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20540044
2013-11-01 11:23:23 +11:00
Andrew Gerrand
153283b74b [release-branch.go1.2] cmd/cgo: stop using -fno-eliminate-unused-debug-types
««« CL 18850043 / 5ef4bf9eb256
cmd/cgo: stop using -fno-eliminate-unused-debug-types

This flag was added in January 2010, in CL 181102, to fix issue 497.
(Numbers were just shorter back then.) The fix was for OS X machines
and the llvm-gcc frontend.

In July 2011 we had to change the way we get enum values, because
there were no flags available to force Xcode's llvm-gcc to include the
enum names and values in DWARF debug output.

We now use clang, not llvm-gcc, on OS X machines.
Earlier versions of clang printed a warning about not knowing the flag.
Newer versions of clang now make that an error.

That is:
 - The flag was added for OS X machines.
 - The flag is no longer necessary on OS X machines.
 - The flag now breaks some OS X machines.

Remove it.

I have run the original program from issue 497 successfully
without the flag on both OS X and Linux machines.

Fixes #6678.

R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/18850043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/19850048
2013-11-01 11:22:39 +11:00
Andrew Gerrand
038ff9dca1 [release-branch.go1.2] runtime: relax preemption assertion during stack split
««« CL 18740044 / 1a8903f0a577
runtime: relax preemption assertion during stack split

The case can happen when starttheworld is calling acquirep
to get things moving again and acquirep gets preempted.
The stack trace is in golang.org/issue/6644.

It is difficult to build a short test case for this, but
the person who reported issue 6644 confirms that this
solves the problem.

Fixes #6644.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/18740044
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20460044
2013-11-01 11:21:54 +11:00
Andrew Gerrand
724d28a03d [release-branch.go1.2] net: handle single-line non-\n-terminated files correctly in readLine
««« CL 15960047 / a0d4544cdb2a
net: handle single-line non-\n-terminated files correctly in readLine

Fixes #6646.

R=rsc, bradfitz
CC=golang-dev
https://golang.org/cl/15960047

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20560044
2013-11-01 11:21:05 +11:00
Andrew Gerrand
7097ed7337 [release-branch.go1.2] net/url: fix Encode doc comment
««« CL 16430043 / f9af8b83c78c
net/url: fix Encode doc comment

Encoded query strings are always sorted by key; the example wasn't.

R=golang-dev, dsymonds, minux.ma, bradfitz
CC=golang-dev
https://golang.org/cl/16430043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20480044
2013-11-01 11:20:21 +11:00
Andrew Gerrand
5962673984 [release-branch.go1.2] misc/linkcheck: better redirect handling, use meaningful exit code
««« CL 14425049 / 093d299d669e
misc/linkcheck: better redirect handling, use meaningful exit code

Prevent linkcheck from following redirects that lead beyond the outside
the root URL.

Return a non-zero exit code when there are problems.

Some minor refactoring for clarity.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/14425049
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20360044
2013-11-01 11:19:34 +11:00
Andrew Gerrand
efb3af3d5c [release-branch.go1.2] strings: fix Replacer bug with prefix matches
««« CL 16880043 / 0eb6508d3e88
strings: fix Replacer bug with prefix matches

singleStringReplacer had a bug where if a string was replaced
at the beginning and no output had yet been produced into the
temp buffer before matching ended, an invalid nil check (used
as a proxy for having matched anything) meant it always
returned its input.

Fixes #6659

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/16880043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20570044
2013-11-01 11:18:49 +11:00
Andrew Gerrand
7191e08599 [release-branch.go1.2] database/sql: link to wiki in package docs
««« CL 14087043 / 7ebbddd21330
database/sql: link to wiki in package docs

Update #5886

R=golang-dev, kamil.kisiel, adg, r, rsc, dave, arnehormann, bradfitz
CC=golang-dev
https://golang.org/cl/14087043

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20610043
2013-11-01 11:18:03 +11:00
Andrew Gerrand
0911539937 [release-branch.go1.2] C+A: add Matthew Cottingham (Individual CLA)
««« CL 16650043 / afb8e00de04a
C+A: add Matthew Cottingham (Individual CLA)

Done by addca, but codereview failed with a Python stacktrace,
so submitting by hand.

R=golang-dev
CC=golang-dev
https://golang.org/cl/16650043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/19560046
2013-11-01 11:17:17 +11:00
Andrew Gerrand
ce1a9fcbf5 [release-branch.go1.2] plan9: correct create permissions with union directory
««« CL 15360045 / f257b02e7ffe
plan9: correct create permissions with union directory

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/15360045

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/19960046
2013-11-01 11:16:32 +11:00
Andrew Gerrand
cc10ac750d [release-branch.go1.2] misc/dist: use go.tools release branch
««« CL 15450047 / 1f81a19c2ee2
misc/dist: use go.tools release branch

R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/15450047
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/19850047
2013-11-01 11:15:47 +11:00
Andrew Gerrand
df3e05d37c [release-branch.go1.2] test/mapnan: use time.Now instead of syscall.Getrusage
««« CL 15570046 / 9169cb38c3e8
test/mapnan: use time.Now instead of syscall.Getrusage

Avoids a dependency on a somewhat nonstandard part of package syscall.

R=golang-dev, dave, r
CC=golang-dev
https://golang.org/cl/15570046
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/19960045
2013-11-01 11:15:02 +11:00
Andrew Gerrand
407b1130cd [release-branch.go1.2] cmd/cgo: use __typeof__, -w instead of typeof, -Wno-all
««« CL 14920052 / 98840b3349f4
cmd/cgo: use __typeof__, -w instead of typeof, -Wno-all

Suggested by iant in earlier CL.

R=golang-dev, bradfitz, iant
CC=golang-dev
https://golang.org/cl/14920052
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20600043
2013-11-01 11:14:19 +11:00
Andrew Gerrand
194b6a4bf2 [release-branch.go1.2] time: fix ParseDuration overflow when given more than 9 digits on 32-bit arch
««« CL 15080043 / fbf3b853e00b
time: fix ParseDuration overflow when given more than 9 digits on 32-bit arch
Fixes #6617.

R=golang-dev, rsc, r
CC=golang-dev
https://golang.org/cl/15080043

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20050045
2013-11-01 11:13:30 +11:00
Andrew Gerrand
f17adc0765 [release-branch.go1.2] misc/emacs: handle empty "import ()" in go-goto-imports
««« CL 14454058 / 6b8f33ab7ca4
misc/emacs: handle empty "import ()" in go-goto-imports

R=adonovan
CC=golang-dev
https://golang.org/cl/14454058

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20590043
2013-11-01 11:12:28 +11:00
Andrew Gerrand
645a023474 [release-branch.go1.2] math: remove unnecessary source file
««« CL 15750046 / 2d1e1adf8ece
math: remove unnecessary source file

The routines in this file are dregs from a very early copy of the math API.
There are no Go prototypes and no non-amd64 implementations.

R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/15750046
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/19560045
2013-11-01 11:11:36 +11:00
Andrew Gerrand
77ac7fdcc8 [release-branch.go1.2] go/build: document the go1.2 build tag
««« CL 14930046 / d4f6533fad0b
go/build: document the go1.2 build tag

R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/14930046

»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/19960044
2013-11-01 11:10:46 +11:00
Andrew Gerrand
bf5d7c6713 [release-branch.go1.2] crypto/x509: name constraints should be a disjunction.
««« CL 15570044 / b4c37131e846
crypto/x509: name constraints should be a disjunction.

The code was requiring that all constraints be met, but it should be
satisfied by meeting *any* of them.

R=golang-dev, bradfitz, r
CC=golang-dev
https://golang.org/cl/15570044
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20580043
2013-11-01 11:09:56 +11:00
Andrew Gerrand
6cbfe8df5c [release-branch.go1.2] crypto/tls: advertise support for RSA+SHA1 in TLS 1.2 handshake.
««« CL 15650043 / 29d3ab5ced5a
crypto/tls: advertise support for RSA+SHA1 in TLS 1.2 handshake.

Despite SHA256 support being required for TLS 1.2 handshakes, some
servers are aborting handshakes that don't offer SHA1 support.

This change adds support for signing TLS 1.2 ServerKeyExchange messages
with SHA1. It does not add support for signing TLS 1.2 client
certificates with SHA1 as that would require the handshake to be
buffered.

Fixes #6618.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/15650043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20570043
2013-11-01 11:09:06 +11:00
Andrew Gerrand
34250ab212 [release-branch.go1.2] net/mail: fix minor doc typo.
««« CL 15510043 / 6752a7aad603
net/mail: fix minor doc typo.

R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/15510043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20560043
2013-11-01 11:08:05 +11:00
Andrew Gerrand
11f1f82b30 [release-branch.go1.2] cmd/yacc: fix stderr on Windows.
««« CL 15330043 / 69bf31787310
cmd/yacc: fix stderr on Windows.
Fixes #6620.

R=golang-dev, dave, r
CC=golang-dev
https://golang.org/cl/15330043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20550043
2013-11-01 11:07:06 +11:00
Andrew Gerrand
e3597e3920 [release-branch.go1.2] cmd/cgo: fix line number in an error message
««« CL 14870046 / b508daf6dae6
cmd/cgo: fix line number in an error message

Fixes #6563.

R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/14870046
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20150045
2013-11-01 11:06:07 +11:00
Andrew Gerrand
265ff83af6 [release-branch.go1.2] cmd/cgo: stop using compiler error message text to analyze C names
««« CL 15070043 / 90a628ac54ed
cmd/cgo: stop using compiler error message text to analyze C names

The old approach to determining whether "name" was a type, constant,
or expression was to compile the C program

        name;

and scan the errors and warnings generated by the compiler.
This requires looking for specific substrings in the errors and warnings,
which ties the implementation to specific compiler versions.
As compilers change their errors or drop warnings, cgo breaks.
This happens slowly but it does happen.
Clang in particular (now required on OS X) has a significant churn rate.

The new approach compiles a slightly more complex program
that is either valid C or not valid C depending on what kind of
thing "name" is. It uses only the presence or absence of an error
message on a particular line, not the error text itself. The program is:

        // error if and only if name is undeclared
        void f1(void) { typeof(name) *x; }

        // error if and only if name is not a type
        void f2(void) { name *x; }

        // error if and only if name is not an integer constant
        void f3(void) { enum { x = (name)*1 }; }

I had not been planning to do this until Go 1.3, because it is a
non-trivial change, but it fixes a real Xcode 5 problem in Go 1.2,
and the new code is easier to understand than the old code.
It should be significantly more robust.

Fixes #6596.
Fixes #6612.

R=golang-dev, r, james, iant
CC=golang-dev
https://golang.org/cl/15070043
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20060044
2013-11-01 11:05:17 +11:00
Andrew Gerrand
c57029d43d [release-branch.go1.2] cmd/gc: shorten name used for map bucket type
««« CL 15110044 / 95336afd420c
cmd/gc: shorten name used for map bucket type

Before:
type.struct { buckets *struct { overflow *struct { overflow *struct { overflow *struct { overflow *struct { overflow *<...>; keys [8]string; values [8]*"".RangeTable }; keys [8]string; values [8]*"".RangeTable }; keys [8]string; values [8]*"".RangeTable }; keys [8]string; values [8]*"".RangeTable }; keys [8]string; values [8]*"".RangeTable }; oldbuckets *struct { overflow *struct { overflow *struct { overflow *struct { overflow *struct { overflow *<...>; keys [8]string; values [8]*"".RangeTable }; keys [8]string; values [8]*"".RangeTable }; keys [8]string; values [8]*"".RangeTable }; keys [8]string; values [8]*"".RangeTable }; keys [8]string; values [8]*"".RangeTable } }

After:
type.map.bucket[string]*"".RangeTable

This makes debugging maps a little nicer, and it takes up less space in the binary.

R=golang-dev, r
CC=golang-dev, khr
https://golang.org/cl/15110044
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20050044
2013-11-01 11:00:12 +11:00
Andrew Gerrand
287fa600ed [release-branch.go1.2] net: make sure failed Dial returns nil Conn
««« CL 14950045 / 1e60ffd5933d
net: make sure failed Dial returns nil Conn

Fixes #6614.

R=golang-dev, bradfitz, mikioh.mikioh
CC=golang-dev
https://golang.org/cl/14950045
»»»

R=golang-dev
CC=golang-dev
https://golang.org/cl/20170047
2013-11-01 10:58:25 +11:00
Andrew Gerrand
000c1c5127 [release-branch.go1.2] runtime: remove nomemprof
««« CL 14695044 / 35d5bae6aac8
runtime: remove nomemprof
Nomemprof seems to be unneeded now, there is no recursion.
If the recursion will be re-introduced, it will break loudly by deadlocking.
Fixes #6566.

R=golang-dev, minux.ma, rsc
CC=golang-dev
https://golang.org/cl/14695044
»»»

R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/20540043
2013-11-01 10:51:42 +11:00
Andrew Gerrand
c1792398d4 [release-branch.go1.2] misc/dist: build race packages when os suffix present
««« CL 14930043 / 5746e3a5443b
misc/dist: build race packages when os suffix present

The "darwin-amd64-osx10.8" target was not matching "darwin-amd64".

R=golang-dev
CC=golang-dev
https://golang.org/cl/14930043
»»»

R=golang-dev, dsymonds
CC=golang-dev
https://golang.org/cl/20290045
2013-11-01 10:50:00 +11:00
Andrew Gerrand
309e16554a go1.2rc2 2013-10-18 13:53:33 +09:00
85 changed files with 1828 additions and 1577 deletions

View File

@@ -47,6 +47,7 @@ Anthony Starks <ajstarks@gmail.com>
Arnaud Ysmal <arnaud.ysmal@gmail.com>
Aron Nopanen <aron.nopanen@gmail.com>
Arvindh Rajesh Tamilmani <art@a-30.net>
Ato Araki <ato.araki@gmail.com>
Aulus Egnatius Varialus <varialus@gmail.com>
Ben Olive <sionide21@gmail.com>
Benjamin Black <b@b3k.us>
@@ -149,6 +150,7 @@ Hong Ruiqi <hongruiqi@gmail.com>
Icarus Sparry <golang@icarus.freeuk.com>
Ingo Oeser <nightlyone@googlemail.com>
Isaac Wagner <ibw@isaacwagner.me>
Jakob Borg <jakob@nym.se>
James David Chalfant <james.chalfant@gmail.com>
James Fysh <james.fysh@gmail.com>
James Gray <james@james4k.com>
@@ -218,6 +220,7 @@ Mats Lidell <mats.lidell@cag.se>
Matt Jibson <matt.jibson@gmail.com>
Matt Joiner <anacrolix@gmail.com>
Matt Reiferson <mreiferson@gmail.com>
Matthew Cottingham <mattcottingham@gmail.com>
Matthew Horsnell <matthew.horsnell@gmail.com>
Micah Stetson <micah.stetson@gmail.com>
Michael Chaten <mchaten@gmail.com>
@@ -277,6 +280,7 @@ Quan Yong Zhai <qyzhai@gmail.com>
Raif S. Naffah <go@naffah-raif.name>
Rémy Oudompheng <oudomphe@phare.normalesup.org>
Richard Eric Gavaletz <gavaletz@gmail.com>
Richard Musiol <mail@richard-musiol.de>
Rick Arnold <rickarnoldjr@gmail.com>
Risto Jaakko Saarelma <rsaarelm@gmail.com>
Robert Daniel Kortschak <dan.kortschak@adelaide.edu.au>

View File

@@ -80,6 +80,7 @@ Arnaud Ysmal <arnaud.ysmal@gmail.com>
Aron Nopanen <aron.nopanen@gmail.com>
Arvindh Rajesh Tamilmani <art@a-30.net>
Asim Shankar <asimshankar@gmail.com>
Ato Araki <ato.araki@gmail.com>
Aulus Egnatius Varialus <varialus@gmail.com>
Austin Clements <aclements@csail.mit.edu>
Balazs Lecz <leczb@google.com>
@@ -97,6 +98,7 @@ Bjorn Tipling <bjorn.tipling@gmail.com>
Blake Mizerany <blake.mizerany@gmail.com>
Bobby Powers <bobbypowers@gmail.com>
Brad Fitzpatrick <bradfitz@golang.org> <bradfitz@gmail.com>
Brad Garcia <bgarcia@golang.org>
Brendan O'Dea <bod@golang.org>
Brian Dellisanti <briandellisanti@gmail.com>
Brian G. Merrell <bgmerrell@gmail.com>
@@ -220,6 +222,7 @@ Ingo Oeser <nightlyone@googlemail.com> <nightlyone@gmail.com>
Isaac Wagner <ibw@isaacwagner.me>
Ivan Krasin <krasin@golang.org>
Jacob Baskin <jbaskin@google.com>
Jakob Borg <jakob@nym.se>
James Aguilar <jaguilar@google.com>
James David Chalfant <james.chalfant@gmail.com>
James Fysh <james.fysh@gmail.com>
@@ -311,6 +314,7 @@ Marcel van Lohuizen <mpvl@golang.org>
Marco Hennings <marco.hennings@freiheit.com>
Mark Zavislak <zavislak@google.com>
Marko Juhani Silokunnas <marko.silokunnas@gmail.com>
Marko Mikulicic <mkm@google.com>
Markus Duft <markus.duft@salomon.at>
Markus Sonderegger <marraison@gmail.com>
Martin Neubauer <m.ne@gmx.net>
@@ -322,6 +326,7 @@ Matt Jibson <matt.jibson@gmail.com>
Matt Joiner <anacrolix@gmail.com>
Matt Jones <mrjones@google.com>
Matt Reiferson <mreiferson@gmail.com>
Matthew Cottingham <mattcottingham@gmail.com>
Matthew Dempsky <mdempsky@google.com>
Matthew Horsnell <matthew.horsnell@gmail.com>
Maxim Pimenov <mpimenov@google.com>
@@ -398,6 +403,7 @@ Raif S. Naffah <go@naffah-raif.name>
Raph Levien <raph@google.com>
Rémy Oudompheng <oudomphe@phare.normalesup.org> <remyoudompheng@gmail.com>
Richard Eric Gavaletz <gavaletz@gmail.com>
Richard Musiol <mail@richard-musiol.de> <neelance@gmail.com>
Rick Arnold <rickarnoldjr@gmail.com>
Risto Jaakko Saarelma <rsaarelm@gmail.com>
Rob Pike <r@golang.org>
@@ -407,6 +413,7 @@ Robert Figueiredo <robfig@gmail.com>
Robert Griesemer <gri@golang.org>
Robert Hencke <robert.hencke@gmail.com>
Robert Obryk <robryk@gmail.com>
Robert Snedegar <roberts@google.com>
Robin Eklind <r.eklind.87@gmail.com>
Rodrigo Moraes de Oliveira <rodrigo.moraes@gmail.com>
Rodrigo Rafael Monti Kochenburger <divoxx@gmail.com>

1
VERSION Normal file
View File

@@ -0,0 +1 @@
go1.2rc5

439
doc/asm.html Normal file
View File

@@ -0,0 +1,439 @@
<!--{
"Title": "A Quick Guide to Go's Assembler",
"Path": "/doc/asm"
}-->
<h2 id="introduction">A Quick Guide to Go's Assembler</h2>
<p>
This document is a quick outline of the unusual form of assembly language used by the <code>gc</code>
suite of Go compilers (<code>6g</code>, <code>8g</code>, etc.).
It is based on the input to the Plan 9 assemblers, which is documented in detail
<a href="http://plan9.bell-labs.com/sys/doc/asm.html">on the Plan 9 site</a>.
If you plan to write assembly language, you should read that document although much of it is Plan 9-specific.
This document provides a summary of the syntax and
describes the peculiarities that apply when writing assembly code to interact with Go.
</p>
<p>
The most important thing to know about Go's assembler is that it is not a direct representation of the underlying machine.
Some of the details map precisely to the machine, but some do not.
This is because the compiler suite (see
<a href="http://plan9.bell-labs.com/sys/doc/compiler.html">this description</a>)
needs no assembler pass in the usual pipeline.
Instead, the compiler emits a kind of incompletely defined instruction set, in binary form, which the linker
then completes.
In particular, the linker does instruction selection, so when you see an instruction like <code>MOV</code>
what the linker actually generates for that operation might not be a move instruction at all, perhaps a clear or load.
Or it might correspond exactly to the machine instruction with that name.
In general, machine-specific operations tend to appear as themselves, while more general concepts like
memory move and subroutine call and return are more abstract.
The details vary with architecture, and we apologize for the imprecision; the situation is not well-defined.
</p>
<p>
The assembler program is a way to generate that intermediate, incompletely defined instruction sequence
as input for the linker.
If you want to see what the instructions look like in assembly for a given architecture, say amd64, there
are many examples in the sources of the standard library, in packages such as
<a href="/pkg/runtime/"><code>runtime</code></a> and
<a href="/pkg/math/big/"><code>math/big</code></a>.
You can also examine what the compiler emits as assembly code:
</p>
<pre>
$ cat x.go
package main
func main() {
println(3)
}
$ go tool 6g -S x.go # or: go build -gcflags -S x.go
--- prog list "main" ---
0000 (x.go:3) TEXT main+0(SB),$8-0
0001 (x.go:3) FUNCDATA $0,gcargs·0+0(SB)
0002 (x.go:3) FUNCDATA $1,gclocals·0+0(SB)
0003 (x.go:4) MOVQ $3,(SP)
0004 (x.go:4) PCDATA $0,$8
0005 (x.go:4) CALL ,runtime.printint+0(SB)
0006 (x.go:4) PCDATA $0,$-1
0007 (x.go:4) PCDATA $0,$0
0008 (x.go:4) CALL ,runtime.printnl+0(SB)
0009 (x.go:4) PCDATA $0,$-1
0010 (x.go:5) RET ,
...
</pre>
<p>
The <code>FUNCDATA</code> and <code>PCDATA</code> directives contain information
for use by the garbage collector; they are introduced by the compiler.
</p>
<p>
To see what gets put in the binary after linking, add the <code>-a</code> flag to the linker:
</p>
<pre>
$ go tool 6l -a x.6 # or: go build -ldflags -a x.go
codeblk [0x2000,0x1d059) at offset 0x1000
002000 main.main | (3) TEXT main.main+0(SB),$8
002000 65488b0c25a0080000 | (3) MOVQ 2208(GS),CX
002009 483b21 | (3) CMPQ SP,(CX)
00200c 7707 | (3) JHI ,2015
00200e e83da20100 | (3) CALL ,1c250+runtime.morestack00
002013 ebeb | (3) JMP ,2000
002015 4883ec08 | (3) SUBQ $8,SP
002019 | (3) FUNCDATA $0,main.gcargs·0+0(SB)
002019 | (3) FUNCDATA $1,main.gclocals·0+0(SB)
002019 48c7042403000000 | (4) MOVQ $3,(SP)
002021 | (4) PCDATA $0,$8
002021 e8aad20000 | (4) CALL ,f2d0+runtime.printint
002026 | (4) PCDATA $0,$-1
002026 | (4) PCDATA $0,$0
002026 e865d40000 | (4) CALL ,f490+runtime.printnl
00202b | (4) PCDATA $0,$-1
00202b 4883c408 | (5) ADDQ $8,SP
00202f c3 | (5) RET ,
...
</pre>
<h3 id="symbols">Symbols</h3>
<p>
Some symbols, such as <code>PC</code>, <code>R0</code> and <code>SP</code>, are predeclared and refer to registers.
There are two other predeclared symbols, <code>SB</code> (static base) and <code>FP</code> (frame pointer).
All user-defined symbols other than jump labels are written as offsets to these pseudo-registers.
</p>
<p>
The <code>SB</code> pseudo-register can be thought of as the origin of memory, so the symbol <code>foo(SB)</code>
is the name <code>foo</code> as an address in memory.
</p>
<p>
The <code>FP</code> pseudo-register is a virtual frame pointer
used to refer to function arguments.
The compilers maintain a virtual frame pointer and refer to the arguments on the stack as offsets from that pseudo-register.
Thus <code>0(FP)</code> is the first argument to the function,
<code>8(FP)</code> is the second (on a 64-bit machine), and so on.
When referring to a function argument this way, it is conventional to place the name
at the beginning, as in <code>first_arg+0(FP)</code> and <code>second_arg+8(FP)</code>.
Some of the assemblers enforce this convention, rejecting plain <code>0(FP)</code> and <code>8(FP)</code>.
For assembly functions with Go prototypes, <code>go vet</code> will check that the argument names
and offsets match.
</p>
<p>
The <code>SP</code> pseudo-register is a virtual stack pointer
used to refer to frame-local variables and the arguments being
prepared for function calls.
It points to the top of the local stack frame, so references should use negative offsets
in the range [framesize, 0):
<code>x-8(SP)</code>, <code>y-4(SP)</code>, and so on.
On architectures with a real register named <code>SP</code>, the name prefix distinguishes
references to the virtual stack pointer from references to the architectural <code>SP</code> register.
That is, <code>x-8(SP)</code> and <code>-8(SP)</code> are different memory locations:
the first refers to the virtual stack pointer pseudo-register, while the second refers to the
hardware's <code>SP</code> register.
</p>
<p>
Instructions, registers, and assembler directives are always in UPPER CASE to remind you
that assembly programming is a fraught endeavor.
(Exceptions: the <code>m</code> and <code>g</code> register renamings on ARM.)
</p>
<p>
In Go object files and binaries, the full name of a symbol is the
package path followed by a period and the symbol name:
<code>fmt.Printf</code> or <code>math/rand.Int</code>.
Because the assembler's parser treats period and slash as punctuation,
those strings cannot be used directly as identifier names.
Instead, the assembler allows the middle dot character U+00B7
and the division slash U+2215 in identifiers and rewrites them to
plain period and slash.
Within an assembler source file, the symbols above are written as
<code>fmt·Printf</code> and <code>mathrand·Int</code>.
The assembly listings generated by the compilers when using the <code>-S</code> flag
show the period and slash directly instead of the Unicode replacements
required by the assemblers.
</p>
<p>
Most hand-written assembly files do not include the full package path
in symbol names, because the linker inserts the package path of the current
object file at the beginning of any name starting with a period:
in an assembly source file within the math/rand package implementation,
the package's Int function can be referred to as <code>·Int</code>.
This convention avoids the need to hard-code a package's import path in its
own source code, making it easier to move the code from one location to another.
</p>
<h3 id="directives">Directives</h3>
<p>
The assembler uses various directives to bind text and data to symbol names.
For example, here is a simple complete function definition. The <code>TEXT</code>
directive declares the symbol <code>runtime·profileloop</code> and the instructions
that follow form the body of the function.
The last instruction in a <code>TEXT</code> block must be some sort of jump, usually a <code>RET</code> (pseudo-)instruction.
(If it's not, the linker will append a jump-to-itself instruction; there is no fallthrough in <code>TEXTs</code>.)
After the symbol, the arguments are flags (see below)
and the frame size, a constant (but see below):
</p>
<pre>
TEXT runtime·profileloop(SB),NOSPLIT,$8
MOVQ $runtime·profileloop1(SB), CX
MOVQ CX, 0(SP)
CALL runtime·externalthreadhandler(SB)
RET
</pre>
<p>
In the general case, the frame size is followed by an argument size, separated by a minus sign.
(It's not an subtraction, just idiosyncratic syntax.)
The frame size <code>$24-8</code> states that the function has a 24-byte frame
and is called with 8 bytes of argument, which live on the caller's frame.
If <code>NOSPLIT</code> is not specified for the <code>TEXT</code>,
the argument size must be provided.
</p>
<p>
Note that the symbol name uses a middle dot to separate the components and is specified as an offset from the
static base pseudo-register <code>SB</code>.
This function would be called from Go source for package <code>runtime</code> using the
simple name <code>profileloop</code>.
</p>
<p>
For <code>DATA</code> directives, the symbol is followed by a slash and the number
of bytes the memory associated with the symbol occupies.
The arguments are optional flags and the data itself.
For instance,
</p>
<pre>
DATA runtime·isplan9(SB)/4, $1
</pre>
<p>
declares the local symbol <code>runtime·isplan9</code> of size 4 and value 1.
Again the symbol has the middle dot and is offset from <code>SB</code>.
</p>
<p>
The <code>GLOBL</code> directive declares a symbol to be global.
The arguments are optional flags and the size of the data being declared as a global,
which will have initial value all zeros unless a <code>DATA</code> directive
has initialized it.
The <code>GLOBL</code> directive must follow any corresponding <code>DATA</code> directives.
This example
</p>
<pre>
GLOBL runtime·tlsoffset(SB),$4
</pre>
<p>
declares <code>runtime·tlsoffset</code> to have size 4.
</p>
<p>
There may be one or two arguments to the directives.
If there are two, the first is a bit mask of flags,
which can be written as numeric expressions, added or or-ed together,
or can be set symbolically for easier absorption by a human.
Their values, defined in the file <code>src/cmd/ld/textflag.h</code>, are:
</p>
<ul>
<li>
<code>NOPROF</code> = 1
<br>
(For <code>TEXT</code> items.)
Don't profile the marked function. This flag is deprecated.
</li>
<li>
<code>DUPOK</code> = 2
<br>
It is legal to have multiple instances of this symbol in a single binary.
The linker will choose one of the duplicates to use.
</li>
<li>
<code>NOSPLIT</code> = 4
<br>
(For <code>TEXT</code> items.)
Don't insert the preamble to check if the stack must be split.
The frame for the routine, plus anything it calls, must fit in the
spare space at the top of the stack segment.
Used to protect routines such as the stack splitting code itself.
</li>
<li>
<code>RODATA</code> = 8
<br>
(For <code>DATA</code> and <code>GLOBL</code> items.)
Put this data in a read-only section.
</li>
<li>
<code>NOPTR</code> = 16
<br>
(For <code>DATA</code> and <code>GLOBL</code> items.)
This data contains no pointers and therefore does not need to be
scanned by the garbage collector.
</li>
<li>
<code>WRAPPER</code> = 32
<br>
(For <code>TEXT</code> items.)
This is a wrapper function and should not count as disabling <code>recover</code>.
</li>
</ul>
<h2 id="architectures">Architecture-specific details</h2>
<p>
It is impractical to list all the instructions and other details for each machine.
To see what instructions are defined for a given machine, say 32-bit Intel x86,
look in the top-level header file for the corresponding linker, in this case <code>8l</code>.
That is, the file <code>$GOROOT/src/cmd/8l/8.out.h</code> contains a C enumeration, called <code>as</code>,
of the instructions and their spellings as known to the assembler and linker for that architecture.
In that file you'll find a declaration that begins
</p>
<pre>
enum as
{
AXXX,
AAAA,
AAAD,
AAAM,
AAAS,
AADCB,
...
</pre>
<p>
Each instruction begins with a initial capital <code>A</code> in this list, so <code>AADCB</code>
represents the <code>ADCB</code> (add carry byte) instruction.
The enumeration is in alphabetical order, plus some late additions (<code>AXXX</code> occupies
the zero slot as an invalid instruction).
The sequence has nothing to do with the actual encoding of the machine instructions.
Again, the linker takes care of that detail.
</p>
<p>
One detail evident in the examples from the previous sections is that data in the instructions flows from left to right:
<code>MOVQ</code> <code>$0,</code> <code>CX</code> clears <code>CX</code>.
This convention applies even on architectures where the usual mode is the opposite direction.
</p>
<p>
Here follows some descriptions of key Go-specific details for the supported architectures.
</p>
<h3 id="x86">32-bit Intel 386</h3>
<p>
The runtime pointers to the <code>m</code> and <code>g</code> structures are maintained
through the value of an otherwise unused (as far as Go is concerned) register in the MMU.
A OS-dependent macro <code>get_tls</code> is defined for the assembler if the source includes
an architecture-dependent header file, like this:
</p>
<pre>
#include "zasm_GOOS_GOARCH.h"
</pre>
<p>
Within the runtime, the <code>get_tls</code> macro loads its argument register
with a pointer to a pair of words representing the <code>g</code> and <code>m</code> pointers.
The sequence to load <code>g</code> and <code>m</code> using <code>CX</code> looks like this:
</p>
<pre>
get_tls(CX)
MOVL g(CX), AX // Move g into AX.
MOVL m(CX), BX // Move m into BX.
</pre>
<h3 id="amd64">64-bit Intel 386 (a.k.a. amd64)</h3>
<p>
The assembly code to access the <code>m</code> and <code>g</code>
pointers is the same as on the 386, except it uses <code>MOVQ</code> rather than
<code>MOVL</code>:
</p>
<pre>
get_tls(CX)
MOVQ g(CX), AX // Move g into AX.
MOVQ m(CX), BX // Move m into BX.
</pre>
<h3 id="arm">ARM</h3>
<p>
The registers <code>R9</code>, <code>R10</code>, and <code>R11</code>
are reserved by the compiler and linker.
</p>
<p>
<code>R9</code> and <code>R10</code> point to the <code>m</code> (machine) and <code>g</code>
(goroutine) structures, respectively.
Within assembler source code, these pointers must be referred to as <code>m</code> and <code>g</code>;
the names <code>R9</code> and <code>R10</code> are not recognized.
</p>
<p>
To make it easier for people and compilers to write assembly, the ARM linker
allows general addressing forms and pseudo-operations like <code>DIV</code> or <code>MOD</code>
that may not be expressible using a single hardware instruction.
It implements these forms as multiple instructions, often using the <code>R11</code> register
to hold temporary values.
Hand-written assembly can use <code>R11</code>, but doing so requires
being sure that the linker is not also using it to implement any of the other
instructions in the function.
</p>
<p>
When defining a <code>TEXT</code>, specifying frame size <code>$-4</code>
tells the linker that this is a leaf function that does not need to save <code>LR</code> on entry.
</p>
<p>
The name <code>SP</code> always refers to the virtual stack pointer described earlier.
For the hardware register, use <code>R13</code>.
</p>
<h3 id="unsupported_opcodes">Unsupported opcodes</h3>
<p>
The assemblers are designed to support the compiler so not all hardware instructions
are defined for all architectures: if the compiler doesn't generate it, it might not be there.
If you need to use a missing instruction, there are two ways to proceed.
One is to update the assembler to support that instruction, which is straightforward
but only worthwhile if it's likely the instruction will be used again.
Instead, for simple one-off cases, it's possible to use the <code>BYTE</code>
and <code>WORD</code> directives
to lay down explicit data into the instruction stream within a <code>TEXT</code>.
Here's how the 386 runtime defines the 64-bit atomic load function.
</p>
<pre>
// uint64 atomicload64(uint64 volatile* addr);
// so actually
// void atomicload64(uint64 *res, uint64 volatile *addr);
TEXT runtime·atomicload64(SB), NOSPLIT, $0-8
MOVL 4(SP), BX
MOVL 8(SP), AX
// MOVQ (%EAX), %MM0
BYTE $0x0f; BYTE $0x6f; BYTE $0x00
// MOVQ %MM0, 0(%EBX)
BYTE $0x0f; BYTE $0x7f; BYTE $0x03
// EMMS
BYTE $0x0F; BYTE $0x77
RET
</pre>

View File

@@ -38,8 +38,8 @@ The GCC 4.7.1 release and all later 4.7 releases include a complete
<p>
Due to timing, the GCC 4.8.0 and 4.8.1 releases are close to but not
identical to Go 1.1. The GCC 4.8.2 release is expected to include a
complete Go 1.1.1 implementation.
identical to Go 1.1. The GCC 4.8.2 release includes a complete Go
1.1.2 implementation.
</p>
<h2 id="Source_code">Source code</h2>

View File

@@ -137,12 +137,61 @@ This means that any loop that includes a (non-inlined) function call can
be pre-empted, allowing other goroutines to run on the same thread.
</p>
<h3 id="thread_limit">Limit on the number of threads</h3>
<p>
Go 1.2 introduces a configurable limit (default 10,000) to the total number of threads
a single program may have in its address space, to avoid resource starvation
issues in some environments.
Note that goroutines are multiplexed onto threads so this limit does not directly
limit the number of goroutines, only the number that may be simultaneously blocked
in a system call.
In practice, the limit is hard to reach.
</p>
<p>
The new <a href="/pkg/runtime/debug/#SetMaxThreads"><code>SetMaxThreads</code></a> function in the
<a href="/pkg/runtime/debug/"><code>runtime/debug</code></a> package controls the thread count limit.
</p>
<p>
<em>Updating</em>:
Few functions will be affected by the limit, but if a program dies because it hits the
limit, it could be modified to call <code>SetMaxThreads</code> to set a higher count.
Even better would be to refactor the program to need fewer threads, reducing consumption
of kernel resources.
</p>
<h3 id="stack_size">Stack size</h3>
<p>
In Go 1.2, the minimum size of the stack when a goroutine is created has been lifted from 4KB to 8KB.
Many programs were suffering performance problems with the old size, which had a tendency
to introduce expensive stack-segment switching in performance-critical sections.
The new number was determined by empirical testing.
</p>
<p>
At the other end, the new function <a href="/pkg/runtime/debug/#SetMaxStack"><code>SetMaxStack</code></a>
in the <a href="/pkg/runtime/debug"><code>runtime/debug</code></a> package controls
the <em>maximum</em> size of a single goroutine's stack.
The default is 1GB on 64-bit systems and 250MB on 32-bit systems.
Before Go 1.2, it was too easy for a runaway recursion to consume all the memory on a machine.
</p>
<p>
<em>Updating</em>:
The increased minimum stack size may cause programs with many goroutines to use
more memory. There is no workaround, but plans for future releases
include new stack management technology that should address the problem better.
</p>
<h3 id="cgo_and_cpp">Cgo and C++</h3>
<p>
The <a href="/cmd/cgo/"><code>cgo</code></a> command will now invoke the C++
compiler to build any pieces of the linked-to library that are written in C++; the
documentation has more detail.
compiler to build any pieces of the linked-to library that are written in C++;
<a href="/cmd/cgo/">the documentation</a> has more detail.
</p>
<h3 id="go_tools_godoc">Godoc and vet moved to the go.tools subrepository</h3>
@@ -687,7 +736,8 @@ now treats channel and function fields of structures as if they were unexported,
even if they are not. That is, it ignores them completely. Previously they would
trigger an error, which could cause unexpected compatibility problems if an
embedded structure added such a field.
The package also now supports the generic encoding interfaces of the
The package also now supports the generic <code>BinaryMarshaler</code> and
<code>BinaryUnmarshaler</code> interfaces of the
<a href="/pkg/encoding/"><code>encoding</code></a> package
described above.
</li>

View File

@@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
"Subtitle": "Version of Oct 16, 2013",
"Subtitle": "Version of Nov 13, 2013",
"Path": "/ref/spec"
}-->
@@ -1456,10 +1456,6 @@ by a value of type <code>T</code>.
</li>
</ul>
<p>
Any value may be assigned to the <a href="#Blank_identifier">blank identifier</a>.
</p>
<h2 id="Blocks">Blocks</h2>
@@ -1516,6 +1512,11 @@ No identifier may be declared twice in the same block, and
no identifier may be declared in both the file and package block.
</p>
<p>
The <a href="#Blank_identifier">blank identifier</a> may be used like any other identifier
in a declaration, but it does not introduce a binding and thus is not declared.
</p>
<pre class="ebnf">
Declaration = ConstDecl | TypeDecl | VarDecl .
TopLevelDecl = Declaration | FunctionDecl | MethodDecl .
@@ -1585,8 +1586,10 @@ the body of any nested function.
<h3 id="Blank_identifier">Blank identifier</h3>
<p>
The <i>blank identifier</i>, represented by the underscore character <code>_</code>, may be used in a declaration like
any other identifier but the declaration does not introduce a new <a href="#Declarations_and_scope">binding</a>.
The <i>blank identifier</i> is represented by the underscore character <code>_</code>.
It serves as an anonymous placeholder instead of a regular (non-blank)
identifier and has special meaning in <a href="#Declarations_and_scope">declarations</a>,
as an <a href="#Operands">operand</a>, and in <a href="#Assignments">assignments</a>.
</p>
@@ -2077,8 +2080,8 @@ operators and functions to operands.
<p>
Operands denote the elementary values in an expression. An operand may be a
literal, a (possibly <a href="#Qualified_identifiers">qualified</a>) identifier
denoting a
literal, a (possibly <a href="#Qualified_identifiers">qualified</a>)
non-<a href="#Blank_identifier">blank</a> identifier denoting a
<a href="#Constant_declarations">constant</a>,
<a href="#Variable_declarations">variable</a>, or
<a href="#Function_declarations">function</a>,
@@ -2086,6 +2089,11 @@ a <a href="#Method_expressions">method expression</a> yielding a function,
or a parenthesized expression.
</p>
<p>
The <a href="#Blank_identifier">blank identifier</a> may appear as an
operand only on the left-hand side of an <a href="#Assignments">assignment</a>.
</p>
<pre class="ebnf">
Operand = Literal | OperandName | MethodExpr | "(" Expression ")" .
Literal = BasicLit | CompositeLit | FunctionLit .
@@ -4255,7 +4263,8 @@ assign_op = [ add_op | mul_op ] "=" .
<p>
Each left-hand side operand must be <a href="#Address_operators">addressable</a>,
a map index expression, or the <a href="#Blank_identifier">blank identifier</a>.
a map index expression, or (for <code>=</code> assignments only) the
<a href="#Blank_identifier">blank identifier</a>.
Operands may be parenthesized.
</p>
@@ -4268,12 +4277,13 @@ a[i] = 23
<p>
An <i>assignment operation</i> <code>x</code> <i>op</i><code>=</code>
<code>y</code> where <i>op</i> is a binary arithmetic operation is equivalent
<code>y</code> where <i>op</i> is a binary arithmetic operation equivalent
to <code>x</code> <code>=</code> <code>x</code> <i>op</i>
<code>y</code> but evaluates <code>x</code>
only once. The <i>op</i><code>=</code> construct is a single token.
In assignment operations, both the left- and right-hand expression lists
must contain exactly one single-valued expression.
must contain exactly one single-valued expression, and the left-hand
expression must not be the blank identifier.
</p>
<pre>
@@ -4298,21 +4308,26 @@ x, y = f()
<p>
assigns the first value to <code>x</code> and the second to <code>y</code>.
The <a href="#Blank_identifier">blank identifier</a> provides a
way to ignore values returned by a multi-valued expression:
</p>
<pre>
x, _ = f() // ignore second value returned by f()
</pre>
<p>
In the second form, the number of operands on the left must equal the number
of expressions on the right, each of which must be single-valued, and the
<i>n</i>th expression on the right is assigned to the <i>n</i>th
operand on the left.
operand on the left:
</p>
<pre>
one, two, three = '一', '二', '三'
</pre>
<p>
The <a href="#Blank_identifier">blank identifier</a> provides a way to
ignore right-hand side values in an assignment:
</p>
<pre>
_ = x // evaluate x but ignore it
x, _ = f() // evaluate f() but ignore second result value
</pre>
<p>
The assignment proceeds in two phases.
First, the operands of <a href="#Index_expressions">index expressions</a>
@@ -4350,16 +4365,29 @@ for i, x[i] = range x { // set i, x[2] = 0, x[0]
</pre>
<p>
In assignments, each value must be
<a href="#Assignability">assignable</a> to the type of the
operand to which it is assigned. If an untyped <a href="#Constants">constant</a>
is assigned to a variable of interface type, the constant is <a href="#Conversions">converted</a>
to type <code>bool</code>, <code>rune</code>, <code>int</code>, <code>float64</code>,
<code>complex128</code> or <code>string</code>
respectively, depending on whether the value is a
boolean, rune, integer, floating-point, complex, or string constant.
In assignments, each value must be <a href="#Assignability">assignable</a>
to the type of the operand to which it is assigned, with the following special cases:
</p>
<ol>
<li><p>
If an untyped <a href="#Constants">constant</a>
is assigned to a variable of interface type or the blank identifier,
the constant is first <a href="#Conversions">converted</a> to type
<code>bool</code>, <code>rune</code>, <code>int</code>, <code>float64</code>,
<code>complex128</code> or <code>string</code> respectively, depending on
whether the value is a boolean, rune, integer, floating-point, complex, or
string constant.
</p></li>
<li><p>
<!-- Note that the result of a comparison is an untyped bool that may not be constant. -->
If a left-hand side is the blank identifier, any typed or non-constant
value except for the predeclared identifier
<a href="#Predeclared_identifiers"><code>nil</code></a>
may be assigned to it.
</p></li>
</ol>
<h3 id="If_statements">If statements</h3>

View File

@@ -51,7 +51,7 @@ proceeding. If your OS or architecture is not on the list, it's possible that
<tr><td colspan="3"><hr></td></tr>
<tr><td>FreeBSD 7 or later</td> <td>amd64, 386, arm</td> <td>Debian GNU/kFreeBSD not supported; FreeBSD/ARM needs FreeBSD 10 or later</td></tr>
<tr><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm</td> <td>CentOS/RHEL 5.x not supported; no binary distribution for ARM yet</td></tr>
<tr><td>Mac OS X 10.6/10.7</td> <td>amd64, 386</td> <td>use the gcc<sup>&#8224;</sup> that comes with Xcode<sup>&#8225;</sup></td></tr>
<tr><td>Mac OS X 10.6 or later</td> <td>amd64, 386</td> <td>use the gcc<sup>&#8224;</sup> that comes with Xcode<sup>&#8225;</sup></td></tr>
<tr><td>Windows 2000 or later</td> <td>amd64, 386</td> <td>use mingw gcc<sup>&#8224;</sup>; cygwin or msys is not needed</td></tr>
<tr><td>NetBSD 6 or later</td> <td>amd64, 386</td> <td></td></tr>
</table>

View File

@@ -47,7 +47,7 @@ Hello, 世界
<div class="right">
<div id="about">
Go is an open source programming environment that makes it easy to build
Go is an open source programming language that makes it easy to build
simple, reliable, and efficient software.
</div>

View File

@@ -65,7 +65,7 @@ from mercurial import util as hg_util
if os.sys.platform == 'plan9':
try:
import plan9
n = plan9.bind(os.path.expanduser("~/lib"), os.path.expanduser("~"), plan9.MBEFORE)
n = plan9.bind(os.path.expanduser("~/lib"), os.path.expanduser("~"), plan9.MBEFORE|plan9.MCREATE)
except ImportError:
pass

View File

@@ -1,10 +1,14 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
/*
#cgo LDFLAGS: -c
void test() {
xxx; // This is line 7.
xxx; // ERROR HERE
}
*/
import "C"

13
misc/cgo/errors/err2.go Normal file
View File

@@ -0,0 +1,13 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "C"
func main() {
s := ""
_ = s
C.malloc(s) // ERROR HERE
}

View File

@@ -2,18 +2,30 @@
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
if go tool cgo err1.go >errs 2>&1; then
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected cgo to fail but it succeeded
exit 1
fi
if ! test -s errs; then
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error output but saw none
exit 1
fi
if ! fgrep err1.go:7 errs >/dev/null 2>&1; then
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error on line 7 but saw:
cat 1>&2 errs
exit 1
fi
check() {
file=$1
line=$(grep -n 'ERROR HERE' $file | sed 's/:.*//')
if [ "$line" = "" ]; then
echo 1>&2 misc/cgo/errors/test.bash: BUG: cannot find ERROR HERE in $file
exit 1
fi
if go build $file >errs 2>&1; then
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected cgo to fail but it succeeded
exit 1
fi
if ! test -s errs; then
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error output but saw none
exit 1
fi
if ! fgrep $file:$line: errs >/dev/null 2>&1; then
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error on line $line but saw:
cat 1>&2 errs
exit 1
fi
}
check err1.go
check err2.go
rm -rf errs _obj
exit 0

View File

@@ -49,5 +49,6 @@ func TestFpVar(t *testing.T) { testFpVar(t) }
func Test4339(t *testing.T) { test4339(t) }
func Test6390(t *testing.T) { test6390(t) }
func Test5986(t *testing.T) { test5986(t) }
func TestNaming(t *testing.T) { testNaming(t) }
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }

View File

@@ -0,0 +1,93 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// golang.org/issue/6612
// Test new scheme for deciding whether C.name is an expression, type, constant.
// Clang silences some warnings when the name is a #defined macro, so test those too
// (even though we now use errors exclusively, not warnings).
package cgotest
/*
void myfunc(void) {}
int myvar = 5;
const char *mytext = "abcdef";
typedef int mytype;
enum {
myenum = 1234,
};
#define myfunc_def myfunc
#define myvar_def myvar
#define mytext_def mytext
#define mytype_def mytype
#define myenum_def myenum
#define myint_def 12345
#define myfloat_def 1.5
#define mystring_def "hello"
*/
import "C"
import "testing"
func testNaming(t *testing.T) {
C.myfunc()
C.myfunc_def()
if v := C.myvar; v != 5 {
t.Errorf("C.myvar = %d, want 5", v)
}
if v := C.myvar_def; v != 5 {
t.Errorf("C.myvar_def = %d, want 5", v)
}
if s := C.GoString(C.mytext); s != "abcdef" {
t.Errorf("C.mytext = %q, want %q", s, "abcdef")
}
if s := C.GoString(C.mytext_def); s != "abcdef" {
t.Errorf("C.mytext_def = %q, want %q", s, "abcdef")
}
if c := C.myenum; c != 1234 {
t.Errorf("C.myenum = %v, want 1234", c)
}
if c := C.myenum_def; c != 1234 {
t.Errorf("C.myenum_def = %v, want 1234", c)
}
{
const c = C.myenum
if c != 1234 {
t.Errorf("C.myenum as const = %v, want 1234", c)
}
}
{
const c = C.myenum_def
if c != 1234 {
t.Errorf("C.myenum as const = %v, want 1234", c)
}
}
if c := C.myint_def; c != 12345 {
t.Errorf("C.myint_def = %v, want 12345", c)
}
{
const c = C.myint_def
if c != 12345 {
t.Errorf("C.myint as const = %v, want 12345", c)
}
}
// This would be nice, but it has never worked.
/*
if c := C.myfloat_def; c != 1.5 {
t.Errorf("C.myint_def = %v, want 1.5", c)
}
{
const c = C.myfloat_def
if c != 1.5 {
t.Errorf("C.myint as const = %v, want 1.5", c)
}
}
*/
if s := C.mystring_def; s != "hello" {
t.Errorf("C.mystring_def = %q, want %q", s, "hello")
}
}

48
misc/cgo/testcdefs/main.c Normal file
View File

@@ -0,0 +1,48 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "runtime.h"
#include "cdefstest.h"
void runtime·printf(int8*, ...);
// From cdefstest.go.
typedef struct CdefsOrig CdefsOrig;
struct CdefsOrig {
int8 array1[20];
int8 array2[20][20];
int8 *array3[20];
int8 *array4[20][20];
int8 **array5[20][20];
};
void
main·test(int32 ret)
{
CdefsOrig o;
CdefsTest t;
ret = 0;
if(sizeof(t.array1) != sizeof(o.array1) || offsetof(CdefsTest, array1[0]) != offsetof(CdefsOrig, array1[0])) {
runtime·printf("array1: size, offset = %d, %d, want %d, %d\n", sizeof(t.array1), offsetof(CdefsTest, array1[0]), sizeof(o.array1), offsetof(CdefsOrig, array1[0]));
ret = 1;
}
if(sizeof(t.array2) != sizeof(o.array2) || offsetof(CdefsTest, array2[0][0]) != offsetof(CdefsOrig, array2[0][0])) {
runtime·printf("array2: size, offset = %d, %d, want %d, %d\n", sizeof(t.array2), offsetof(CdefsTest, array2[0][0]), sizeof(o.array2), offsetof(CdefsOrig, array2[0][0]));
ret = 1;
}
if(sizeof(t.array3) != sizeof(o.array3) || offsetof(CdefsTest, array3[0]) != offsetof(CdefsOrig, array3[0])) {
runtime·printf("array3: size, offset = %d, %d, want %d, %d\n", sizeof(t.array3), offsetof(CdefsTest, array3[0]), sizeof(o.array3), offsetof(CdefsOrig, array3[0]));
ret = 1;
}
if(sizeof(t.array4) != sizeof(o.array4) || offsetof(CdefsTest, array4[0][0]) != offsetof(CdefsOrig, array4[0][0])) {
runtime·printf("array4: size, offset = %d, %d, want %d, %d\n", sizeof(t.array4), offsetof(CdefsTest, array4[0][0]), sizeof(o.array4), offsetof(CdefsOrig, array4[0][0]));
ret = 1;
}
if(sizeof(t.array5) != sizeof(o.array5) || offsetof(CdefsTest, array5[0][0]) != offsetof(CdefsOrig, array5[0][0])) {
runtime·printf("array5: size, offset = %d, %d, want %d, %d\n", sizeof(t.array5), offsetof(CdefsTest, array5[0][0]), sizeof(o.array5), offsetof(CdefsOrig, array5[0][0]));
ret = 1;
}
FLUSH(&ret); // flush return value
}

View File

@@ -2,7 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package cgotest
package main
// This file only exists so we can run 'go build' and build our .c files
func test() {}
import "os"
func test() int32 // in main.c
func main() {
os.Exit(int(test()))
}

View File

@@ -10,7 +10,7 @@ do
go tool cgo -cdefs ${FP}.go > ${FP}.h
done
go build .
go build . && ./testcdefs
EXIT=$?
rm -rf _obj main *.h
exit $EXIT

View File

@@ -49,7 +49,7 @@ const (
blogPath = "code.google.com/p/go.blog"
toolPath = "code.google.com/p/go.tools"
tourPath = "code.google.com/p/go-tour"
defaultToolTag = "9e246fa49449" // go.tools as of 2013-10-18, for go1.2
defaultToolTag = "release-branch.go1.2"
)
// Import paths for tool commands.
@@ -175,7 +175,7 @@ func main() {
}
if *includeRace {
for _, t := range raceAvailable {
if t == targ {
if t == targ || strings.HasPrefix(targ, t+"-") {
b.Race = true
}
}

View File

@@ -41,8 +41,8 @@
(defalias 'go--kill-whole-line
(if (fboundp 'kill-whole-line)
'kill-whole-line
'kill-entire-line))
#'kill-whole-line
#'kill-entire-line))
;; Delete the current line without putting it in the kill-ring.
(defun go--delete-whole-line (&optional arg)
@@ -56,12 +56,16 @@
(kill-new (s) ()))
(go--kill-whole-line arg)))
;; declare-function is an empty macro that only byte-compile cares
;; about. Wrap in always false if to satisfy Emacsen without that
;; macro.
(if nil
(declare-function go--position-bytes "go-mode" (point)))
;; XEmacs unfortunately does not offer position-bytes. We can fall
;; back to just using (point), but it will be incorrect as soon as
;; multibyte characters are being used.
(if (fboundp 'position-bytes)
(defalias 'go--position-bytes 'position-bytes)
(defalias 'go--position-bytes #'position-bytes)
(defun go--position-bytes (point) point))
(defun go--old-completion-list-style (list)
@@ -157,6 +161,12 @@ customize this variable to point to the wrapper script."
:type 'string
:group 'go)
(defcustom gofmt-command "gofmt"
"The 'gofmt' command. Some users may replace this with 'goimports'
from https://github.com/bradfitz/goimports."
:type 'string
:group 'go)
(defface go-coverage-untracked
'((t (:foreground "#505050")))
"Coverage color of untracked code."
@@ -273,15 +283,15 @@ For mode=set, all covered lines will have this weight."
(defvar go-mode-map
(let ((m (make-sparse-keymap)))
(define-key m "}" 'go-mode-insert-and-indent)
(define-key m ")" 'go-mode-insert-and-indent)
(define-key m "," 'go-mode-insert-and-indent)
(define-key m ":" 'go-mode-insert-and-indent)
(define-key m "=" 'go-mode-insert-and-indent)
(define-key m (kbd "C-c C-a") 'go-import-add)
(define-key m (kbd "C-c C-j") 'godef-jump)
(define-key m (kbd "C-x 4 C-c C-j") 'godef-jump-other-window)
(define-key m (kbd "C-c C-d") 'godef-describe)
(define-key m "}" #'go-mode-insert-and-indent)
(define-key m ")" #'go-mode-insert-and-indent)
(define-key m "," #'go-mode-insert-and-indent)
(define-key m ":" #'go-mode-insert-and-indent)
(define-key m "=" #'go-mode-insert-and-indent)
(define-key m (kbd "C-c C-a") #'go-import-add)
(define-key m (kbd "C-c C-j") #'godef-jump)
(define-key m (kbd "C-x 4 C-c C-j") #'godef-jump-other-window)
(define-key m (kbd "C-c C-d") #'godef-describe)
m)
"Keymap used by Go mode to implement electric keys.")
@@ -390,7 +400,7 @@ current line will be returned."
(defun go-indentation-at-point ()
(save-excursion
(let (start-nesting (outindent 0))
(let (start-nesting)
(back-to-indentation)
(setq start-nesting (go-paren-level))
@@ -420,7 +430,6 @@ current line will be returned."
(interactive)
(let (indent
shift-amt
end
(pos (- (point-max) (point)))
(point (point))
(beg (line-beginning-position)))
@@ -511,7 +520,7 @@ consider binding godef-jump to `M-.', which is the default key
for `find-tag':
\(add-hook 'go-mode-hook (lambda ()
(local-set-key (kbd \"M-.\") 'godef-jump)))
(local-set-key (kbd \"M-.\") #'godef-jump)))
Please note that godef is an external dependency. You can install
it with
@@ -531,7 +540,7 @@ recommended that you look at goflymake
'(go--build-font-lock-keywords))
;; Indentation
(set (make-local-variable 'indent-line-function) 'go-mode-indent-line)
(set (make-local-variable 'indent-line-function) #'go-mode-indent-line)
;; Comments
(set (make-local-variable 'comment-start) "// ")
@@ -539,12 +548,12 @@ recommended that you look at goflymake
(set (make-local-variable 'comment-use-syntax) t)
(set (make-local-variable 'comment-start-skip) "\\(//+\\|/\\*+\\)\\s *")
(set (make-local-variable 'beginning-of-defun-function) 'go-beginning-of-defun)
(set (make-local-variable 'end-of-defun-function) 'go-end-of-defun)
(set (make-local-variable 'beginning-of-defun-function) #'go-beginning-of-defun)
(set (make-local-variable 'end-of-defun-function) #'go-end-of-defun)
(set (make-local-variable 'parse-sexp-lookup-properties) t)
(if (boundp 'syntax-propertize-function)
(set (make-local-variable 'syntax-propertize-function) 'go-propertize-syntax))
(set (make-local-variable 'syntax-propertize-function) #'go-propertize-syntax))
(set (make-local-variable 'go-dangling-cache) (make-hash-table :test 'eql))
(add-hook 'before-change-functions (lambda (x y) (setq go-dangling-cache (make-hash-table :test 'eql))) t t)
@@ -638,7 +647,7 @@ buffer."
;; We're using errbuf for the mixed stdout and stderr output. This
;; is not an issue because gofmt -w does not produce any stdout
;; output in case of success.
(if (zerop (call-process "gofmt" nil errbuf nil "-w" tmpfile))
(if (zerop (call-process gofmt-command nil errbuf nil "-w" tmpfile))
(if (zerop (call-process-region (point-min) (point-max) "diff" nil patchbuf nil "-n" "-" tmpfile))
(progn
(kill-buffer errbuf)
@@ -749,6 +758,9 @@ declaration."
(let ((old-point (point)))
(goto-char (point-min))
(cond
((re-search-forward "^import ()" nil t)
(backward-char 1)
'block-empty)
((re-search-forward "^import ([^)]+)" nil t)
(backward-char 2)
'block)
@@ -843,6 +855,8 @@ uncommented, otherwise a new import will be added."
(uncomment-region (line-beginning-position) (line-end-position))
(case (go-goto-imports)
('fail (message "Could not find a place to add import."))
('block-empty
(insert "\n\t" line "\n"))
('block
(save-excursion
(re-search-backward "^import (")
@@ -893,13 +907,13 @@ If IGNORE-CASE is non-nil, the comparison is case-insensitive."
(mapcar (lambda (file)
(let ((sub (substring file (length pkgdir) -2)))
(unless (or (go--string-prefix-p "obj/" sub) (go--string-prefix-p "tool/" sub))
(mapconcat 'identity (cdr (split-string sub "/")) "/"))))
(mapconcat #'identity (cdr (split-string sub "/")) "/"))))
(if (file-directory-p dir)
(directory-files dir t "\\.a$"))))
(if (file-directory-p pkgdir)
(go--directory-dirs pkgdir)))))
(go-root-and-paths)))
'string<))
#'string<))
(defun go-unused-imports-lines ()
;; FIXME Technically, -o /dev/null fails in quite some cases (on
@@ -945,11 +959,12 @@ will be commented, otherwise they will be removed completely."
"Given a file name in the format of `filename:line:column',
visit FILENAME and go to line LINE and column COLUMN."
(if (not (string-match "\\(.+\\):\\([0-9]+\\):\\([0-9]+\\)" specifier))
(error "Unexpected godef output: %s" specifier)
;; We've only been given a directory name
(funcall (if other-window #'find-file-other-window #'find-file) specifier)
(let ((filename (match-string 1 specifier))
(line (string-to-number (match-string 2 specifier)))
(column (string-to-number (match-string 3 specifier))))
(with-current-buffer (funcall (if other-window 'find-file-other-window 'find-file) filename)
(with-current-buffer (funcall (if other-window #'find-file-other-window #'find-file) filename)
(go--goto-line line)
(beginning-of-line)
(forward-char (1- column))
@@ -988,7 +1003,7 @@ description at POINT."
(let ((description (cdr (butlast (godef--call point) 1))))
(if (not description)
(message "No description found for expression at point")
(message "%s" (mapconcat 'identity description "\n"))))
(message "%s" (mapconcat #'identity description "\n"))))
(file-error (message "Could not run godef binary"))))
(defun godef-jump (point &optional other-window)
@@ -1003,6 +1018,8 @@ description at POINT."
(message "%s" file))
((go--string-prefix-p "godef: no declaration found for " file)
(message "%s" file))
((go--string-prefix-p "error finding import path for " file)
(message "%s" file))
(t
(push-mark)
(ring-insert find-tag-marker-ring (point-marker))
@@ -1137,6 +1154,6 @@ for."
(go--coverage-make-overlay range (cadr ranges-and-divisor))))
(if (not (eq cur-buffer (current-buffer)))
(display-buffer (current-buffer) 'display-buffer-reuse-window)))))
(display-buffer (current-buffer) #'display-buffer-reuse-window)))))
(provide 'go-mode)

View File

@@ -8,11 +8,13 @@
package main
import (
"errors"
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"regexp"
"strings"
"sync"
@@ -101,57 +103,78 @@ func crawl(url string, sourceURL string) {
func addProblem(url, errmsg string) {
msg := fmt.Sprintf("Error on %s: %s (from %s)", url, errmsg, linkSources[url])
log.Print(msg)
if *verbose {
log.Print(msg)
}
problems = append(problems, msg)
}
func crawlLoop() {
for url := range urlq {
res, err := http.Get(url)
if err != nil {
addProblem(url, fmt.Sprintf("Error fetching: %v", err))
wg.Done()
continue
if err := doCrawl(url); err != nil {
addProblem(url, err.Error())
}
if res.StatusCode != 200 {
addProblem(url, fmt.Sprintf("Status code = %d", res.StatusCode))
wg.Done()
continue
}
slurp, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
log.Fatalf("Error reading %s body: %v", url, err)
}
if *verbose {
log.Printf("Len of %s: %d", url, len(slurp))
}
body := string(slurp)
for _, ref := range localLinks(body) {
if *verbose {
log.Printf(" links to %s", ref)
}
dest := *root + ref
linkSources[dest] = append(linkSources[dest], url)
crawl(dest, url)
}
for _, id := range pageIDs(body) {
if *verbose {
log.Printf(" url %s has #%s", url, id)
}
fragExists[urlFrag{url, id}] = true
}
wg.Done()
}
}
func doCrawl(url string) error {
defer wg.Done()
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return err
}
res, err := http.DefaultTransport.RoundTrip(req)
if err != nil {
return err
}
// Handle redirects.
if res.StatusCode/100 == 3 {
newURL, err := res.Location()
if err != nil {
return fmt.Errorf("resolving redirect: %v", err)
}
if !strings.HasPrefix(newURL.String(), *root) {
// Skip off-site redirects.
return nil
}
crawl(newURL.String(), url)
return nil
}
if res.StatusCode != 200 {
return errors.New(res.Status)
}
slurp, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
log.Fatalf("Error reading %s body: %v", url, err)
}
if *verbose {
log.Printf("Len of %s: %d", url, len(slurp))
}
body := string(slurp)
for _, ref := range localLinks(body) {
if *verbose {
log.Printf(" links to %s", ref)
}
dest := *root + ref
linkSources[dest] = append(linkSources[dest], url)
crawl(dest, url)
}
for _, id := range pageIDs(body) {
if *verbose {
log.Printf(" url %s has #%s", url, id)
}
fragExists[urlFrag{url, id}] = true
}
return nil
}
func main() {
flag.Parse()
go crawlLoop()
crawl(*root, "")
crawl(*root+"/doc/go1.1.html", "")
wg.Wait()
close(urlq)
@@ -164,4 +187,7 @@ func main() {
for _, s := range problems {
fmt.Println(s)
}
if len(problems) > 0 {
os.Exit(1)
}
}

View File

@@ -18,15 +18,21 @@
"
" Flag to indicate whether to enable the commands listed above.
"
" g:gofmt_command [default="gofmt"]
"
" Flag naming the gofmt executable to use.
"
if exists("b:did_ftplugin_go_fmt")
finish
endif
if !exists("g:go_fmt_commands")
let g:go_fmt_commands = 1
endif
if !exists("g:gofmt_command")
let g:gofmt_command = "gofmt"
endif
if g:go_fmt_commands
command! -buffer Fmt call s:GoFormat()
@@ -34,7 +40,7 @@ endif
function! s:GoFormat()
let view = winsaveview()
silent %!gofmt
silent execute "%!" . g:gofmt_command
if v:shell_error
let errors = []
for line in getline(1, line('$'))

View File

@@ -10,6 +10,10 @@
http://plan9.bell-labs.com/magic/man2html/1/8a
Go-specific considerations are documented at
http://golang.org/doc/asm
Its target architecture is the ARM, referred to by these tools as arm.
*/

View File

@@ -472,14 +472,27 @@ noops(void)
p->to.reg = REGSP;
p->spadj = -8;
/* SUB $8,SP */
q1->as = ASUB;
q1->from.type = D_CONST;
q1->from.offset = 8;
q1->from.reg = NREG;
/* Keep saved LR at 0(SP) after SP change. */
/* MOVW 0(SP), REGTMP; MOVW REGTMP, -8!(SP) */
/* TODO: Remove SP adjustments; see issue 6699. */
q1->as = AMOVW;
q1->from.type = D_OREG;
q1->from.reg = REGSP;
q1->from.offset = 0;
q1->reg = NREG;
q1->to.type = D_REG;
q1->to.reg = REGTMP;
/* SUB $8,SP */
q1 = appendp(q1);
q1->as = AMOVW;
q1->from.type = D_REG;
q1->from.reg = REGTMP;
q1->reg = NREG;
q1->to.type = D_OREG;
q1->to.reg = REGSP;
q1->to.offset = -8;
q1->scond |= C_WBIT;
q1->spadj = 8;
break;

View File

@@ -10,6 +10,10 @@
http://plan9.bell-labs.com/magic/man2html/1/8a
Go-specific considerations are documented at
http://golang.org/doc/asm
Its target architecture is the x86-64, referred to by these tools as amd64.
*/

View File

@@ -10,6 +10,11 @@
http://plan9.bell-labs.com/magic/man2html/1/8a
Go-specific considerations are documented at
http://golang.org/doc/asm
I
Its target architecture is the x86, referred to by these tools for historical reasons as 386.
*/

View File

@@ -269,29 +269,30 @@ Next, cgo needs to identify the kinds for each identifier. For the
identifiers C.foo and C.bar, cgo generates this C program:
<preamble>
void __cgo__f__(void) {
#line 1 "cgo-test"
foo;
enum { _cgo_enum_0 = foo };
bar;
enum { _cgo_enum_1 = bar };
}
#line 1 "not-declared"
void __cgo_f_xxx_1(void) { __typeof__(foo) *__cgo_undefined__; }
#line 1 "not-type"
void __cgo_f_xxx_2(void) { foo *__cgo_undefined__; }
#line 1 "not-const"
void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (foo)*1 }; }
#line 2 "not-declared"
void __cgo_f_xxx_1(void) { __typeof__(bar) *__cgo_undefined__; }
#line 2 "not-type"
void __cgo_f_xxx_2(void) { bar *__cgo_undefined__; }
#line 2 "not-const"
void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (bar)*1 }; }
This program will not compile, but cgo can look at the error messages
to infer the kind of each identifier. The line number given in the
error tells cgo which identifier is involved.
This program will not compile, but cgo can use the presence or absence
of an error message on a given line to deduce the information it
needs. The program is syntactically valid regardless of whether each
name is a type or an ordinary identifier, so there will be no syntax
errors that might stop parsing early.
An error like "unexpected type name" or "useless type name in empty
declaration" or "declaration does not declare anything" tells cgo that
the identifier is a type.
An error on not-declared:1 indicates that foo is undeclared.
An error on not-type:1 indicates that foo is not a type (if declared at all, it is an identifier).
An error on not-const:1 indicates that foo is not an integer constant.
An error like "statement with no effect" or "expression result unused"
tells cgo that the identifier is not a type, but not whether it is a
constant, function, or global variable.
An error like "not an integer constant" tells cgo that the identifier
is not a constant. If it is also not a type, it must be a function or
global variable. For now, those can be treated the same.
The line number specifies the name involved. In the example, 1 is foo and 2 is bar.
Next, cgo must learn the details of each type, variable, function, or
constant. It can do this by reading object files. If cgo has decided
@@ -299,14 +300,14 @@ that t1 is a type, v2 and v3 are variables or functions, and c4, c5,
and c6 are constants, it generates:
<preamble>
typeof(t1) *__cgo__1;
typeof(v2) *__cgo__2;
typeof(v3) *__cgo__3;
typeof(c4) *__cgo__4;
__typeof__(t1) *__cgo__1;
__typeof__(v2) *__cgo__2;
__typeof__(v3) *__cgo__3;
__typeof__(c4) *__cgo__4;
enum { __cgo_enum__4 = c4 };
typeof(c5) *__cgo__5;
__typeof__(c5) *__cgo__5;
enum { __cgo_enum__5 = c5 };
typeof(c6) *__cgo__6;
__typeof__(c6) *__cgo__6;
enum { __cgo_enum__6 = c6 };
long long __cgo_debug_data[] = {

View File

@@ -226,42 +226,22 @@ func (p *Package) loadDefines(f *File) {
// name xxx for the references C.xxx in the Go input.
// The kind is either a constant, type, or variable.
func (p *Package) guessKinds(f *File) []*Name {
// Coerce gcc into telling us whether each name is
// a type, a value, or undeclared. We compile a function
// containing the line:
// name;
// If name is a type, gcc will print:
// cgo-test:2: warning: useless type name in empty declaration
// If name is a value, gcc will print
// cgo-test:2: warning: statement with no effect
// If name is undeclared, gcc will print
// cgo-test:2: error: 'name' undeclared (first use in this function)
// A line number directive causes the line number to
// correspond to the index in the names array.
//
// The line also has an enum declaration:
// name; enum { _cgo_enum_1 = name };
// If name is not a constant, gcc will print:
// cgo-test:4: error: enumerator value for '_cgo_enum_4' is not an integer constant
// we assume lines without that error are constants.
// Make list of names that need sniffing, type lookup.
toSniff := make([]*Name, 0, len(f.Name))
needType := make([]*Name, 0, len(f.Name))
// Determine kinds for names we already know about,
// like #defines or 'struct foo', before bothering with gcc.
var names, needType []*Name
for _, n := range f.Name {
// If we've already found this name as a #define
// and we can translate it as a constant value, do so.
if n.Define != "" {
ok := false
isConst := false
if _, err := strconv.Atoi(n.Define); err == nil {
ok = true
isConst = true
} else if n.Define[0] == '"' || n.Define[0] == '\'' {
if _, err := parser.ParseExpr(n.Define); err == nil {
ok = true
isConst = true
}
}
if ok {
if isConst {
n.Kind = "const"
// Turn decimal into hex, just for consistency
// with enum-derived constants. Otherwise
@@ -281,126 +261,139 @@ func (p *Package) guessKinds(f *File) []*Name {
}
}
// If this is a struct, union, or enum type name,
// record the kind but also that we need type information.
needType = append(needType, n)
// If this is a struct, union, or enum type name, no need to guess the kind.
if strings.HasPrefix(n.C, "struct ") || strings.HasPrefix(n.C, "union ") || strings.HasPrefix(n.C, "enum ") {
n.Kind = "type"
i := len(needType)
needType = needType[0 : i+1]
needType[i] = n
continue
}
i := len(toSniff)
toSniff = toSniff[0 : i+1]
toSniff[i] = n
// Otherwise, we'll need to find out from gcc.
names = append(names, n)
}
if len(toSniff) == 0 {
// Bypass gcc if there's nothing left to find out.
if len(names) == 0 {
return needType
}
// Coerce gcc into telling us whether each name is a type, a value, or undeclared.
// For names, find out whether they are integer constants.
// We used to look at specific warning or error messages here, but that tied the
// behavior too closely to specific versions of the compilers.
// Instead, arrange that we can infer what we need from only the presence or absence
// of an error on a specific line.
//
// For each name, we generate these lines, where xxx is the index in toSniff plus one.
//
// #line xxx "not-declared"
// void __cgo_f_xxx_1(void) { __typeof__(name) *__cgo_undefined__; }
// #line xxx "not-type"
// void __cgo_f_xxx_2(void) { name *__cgo_undefined__; }
// #line xxx "not-const"
// void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (name)*1 }; }
//
// If we see an error at not-declared:xxx, the corresponding name is not declared.
// If we see an error at not-type:xxx, the corresponding name is a type.
// If we see an error at not-const:xxx, the corresponding name is not an integer constant.
// If we see no errors, we assume the name is an expression but not a constant
// (so a variable or a function).
//
// The specific input forms are chosen so that they are valid C syntax regardless of
// whether name denotes a type or an expression.
var b bytes.Buffer
b.WriteString(f.Preamble)
b.WriteString(builtinProlog)
b.WriteString("void __cgo__f__(void) {\n")
// For a #defined expression, clang silences the warning about "unused expression".
// http://llvm.org/viewvc/llvm-project?view=revision&revision=172696
// Silencing the warning is not a big deal, because our default assumption is that
// (in the absence of other evidence) names are expressions.
// However, if all the C names we are investigating are #defined expressions,
// clang will print no warnings at all and then exit successfully.
// We want clang to print warnings, so seed the code with a function
// that is guaranteed to provoke a warning (that we will ignore).
// This way, if clang becomes even more broken, we'll find out.
// See golang.org/issue/6128.
fmt.Fprintf(&b, "1;\n")
b.WriteString("#line 1 \"cgo-test\"\n")
for i, n := range toSniff {
fmt.Fprintf(&b, "%s; /* #%d */\nenum { _cgo_enum_%d = %s }; /* #%d */\n", n.C, i, i, n.C, i)
for i, n := range names {
fmt.Fprintf(&b, "#line %d \"not-declared\"\n"+
"void __cgo_f_%d_1(void) { __typeof__(%s) *__cgo_undefined__; }\n"+
"#line %d \"not-type\"\n"+
"void __cgo_f_%d_2(void) { %s *__cgo_undefined__; }\n"+
"#line %d \"not-const\"\n"+
"void __cgo_f_%d_3(void) { enum { __cgo__undefined__ = (%s)*1 }; }\n",
i+1, i+1, n.C,
i+1, i+1, n.C,
i+1, i+1, n.C)
}
b.WriteString("}\n")
fmt.Fprintf(&b, "#line 1 \"completed\"\n"+
"int __cgo__1 = __cgo__2;\n")
stderr := p.gccErrors(b.Bytes())
if stderr == "" {
fatalf("%s produced no output\non input:\n%s", p.gccBaseCmd()[0], b.Bytes())
}
names := make([]*Name, len(toSniff))
copy(names, toSniff)
isConst := make([]bool, len(toSniff))
for i := range isConst {
isConst[i] = true // until proven otherwise
}
completed := false
sniff := make([]int, len(names))
const (
notType = 1 << iota
notConst
)
for _, line := range strings.Split(stderr, "\n") {
if len(line) < 9 || line[0:9] != "cgo-test:" {
// the user will see any compiler errors when the code is compiled later.
if !strings.Contains(line, ": error:") {
// we only care about errors.
// we tried to turn off warnings on the command line, but one never knows.
continue
}
line = line[9:]
colon := strings.Index(line, ":")
if colon < 0 {
continue
}
i, err := strconv.Atoi(line[0:colon])
if err != nil {
continue
}
i = (i - 1) / 2
what := ""
switch {
default:
continue
case strings.Contains(line, ": useless type name in empty declaration"),
strings.Contains(line, ": declaration does not declare anything"),
strings.Contains(line, ": unexpected type name"):
what = "type"
isConst[i] = false
case strings.Contains(line, ": statement with no effect"),
strings.Contains(line, ": expression result unused"):
what = "not-type" // const or func or var
case strings.Contains(line, "undeclared"):
error_(token.NoPos, "%s", strings.TrimSpace(line[colon+1:]))
case strings.Contains(line, "is not an integer constant"):
isConst[i] = false
continue
}
n := toSniff[i]
if n == nil {
continue
}
toSniff[i] = nil
n.Kind = what
j := len(needType)
needType = needType[0 : j+1]
needType[j] = n
}
for i, b := range isConst {
if b {
names[i].Kind = "const"
if toSniff[i] != nil && names[i].Const == "" {
j := len(needType)
needType = needType[0 : j+1]
needType[j] = names[i]
}
}
}
for _, n := range toSniff {
if n == nil {
c1 := strings.Index(line, ":")
if c1 < 0 {
continue
}
if n.Kind != "" {
c2 := strings.Index(line[c1+1:], ":")
if c2 < 0 {
continue
}
error_(token.NoPos, "could not determine kind of name for C.%s", fixGo(n.Go))
c2 += c1 + 1
filename := line[:c1]
i, _ := strconv.Atoi(line[c1+1 : c2])
i--
if i < 0 || i >= len(names) {
continue
}
switch filename {
case "completed":
// Strictly speaking, there is no guarantee that seeing the error at completed:1
// (at the end of the file) means we've seen all the errors from earlier in the file,
// but usually it does. Certainly if we don't see the completed:1 error, we did
// not get all the errors we expected.
completed = true
case "not-declared":
error_(token.NoPos, "%s", strings.TrimSpace(line[c2+1:]))
case "not-type":
sniff[i] |= notType
case "not-const":
sniff[i] |= notConst
}
}
if !completed {
fatalf("%s did not produce error at completed:1\non input:\n%s", p.gccBaseCmd()[0], b.Bytes())
}
for i, n := range names {
switch sniff[i] {
case 0:
error_(token.NoPos, "could not determine kind of name for C.%s", fixGo(n.Go))
case notType:
n.Kind = "const"
case notConst:
n.Kind = "type"
case notConst | notType:
n.Kind = "not-type"
}
}
if nerrors > 0 {
fatalf("unresolved names")
}
needType = append(needType, names...)
return needType
}
@@ -413,14 +406,14 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
// for symbols in the object file, so it is not enough to print the
// preamble and hope the symbols we care about will be there.
// Instead, emit
// typeof(names[i]) *__cgo__i;
// __typeof__(names[i]) *__cgo__i;
// for each entry in names and then dereference the type we
// learn for __cgo__i.
var b bytes.Buffer
b.WriteString(f.Preamble)
b.WriteString(builtinProlog)
for i, n := range names {
fmt.Fprintf(&b, "typeof(%s) *__cgo__%d;\n", n.C, i)
fmt.Fprintf(&b, "__typeof__(%s) *__cgo__%d;\n", n.C, i)
if n.Kind == "const" {
fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C)
}
@@ -661,7 +654,7 @@ func (p *Package) rewriteRef(f *File) {
// Okay - might be new(T)
expr = r.Name.Type.Go
} else if r.Name.Kind == "var" {
expr = &ast.StarExpr{X: expr}
expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
}
case "type":
@@ -690,6 +683,16 @@ func (p *Package) rewriteRef(f *File) {
}
}
}
// Copy position information from old expr into new expr,
// in case expression being replaced is first on line.
// See golang.org/issue/6563.
pos := (*r.Expr).Pos()
switch x := expr.(type) {
case *ast.Ident:
expr = &ast.Ident{NamePos: pos, Name: x.Name}
}
*r.Expr = expr
}
@@ -739,13 +742,12 @@ func gccTmp() string {
// the input.
func (p *Package) gccCmd() []string {
c := append(p.gccBaseCmd(),
"-Wall", // many warnings
"-Werror", // warnings are errors
"-o"+gccTmp(), // write object to tmp
"-gdwarf-2", // generate DWARF v2 debugging symbols
"-fno-eliminate-unused-debug-types", // gets rid of e.g. untyped enum otherwise
"-c", // do not link
"-xc", // input language is C
"-w", // no warnings
"-Wno-error", // warnings are not errors
"-o"+gccTmp(), // write object to tmp
"-gdwarf-2", // generate DWARF v2 debugging symbols
"-c", // do not link
"-xc", // input language is C
)
if strings.Contains(c[0], "clang") {
c = append(c,
@@ -778,6 +780,11 @@ func (p *Package) gccCmd() []string {
func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte) {
runGcc(stdin, p.gccCmd())
isDebugData := func(s string) bool {
// Some systems use leading _ to denote non-assembly symbols.
return s == "__cgodebug_data" || s == "___cgodebug_data"
}
if f, err := macho.Open(gccTmp()); err == nil {
defer f.Close()
d, err := f.DWARF()
@@ -788,8 +795,7 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte)
if f.Symtab != nil {
for i := range f.Symtab.Syms {
s := &f.Symtab.Syms[i]
// Mach-O still uses a leading _ to denote non-assembly symbols.
if s.Name == "_"+"__cgodebug_data" {
if isDebugData(s.Name) {
// Found it. Now find data section.
if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
sect := f.Sections[i]
@@ -816,7 +822,7 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte)
if err == nil {
for i := range symtab {
s := &symtab[i]
if s.Name == "__cgodebug_data" {
if isDebugData(s.Name) {
// Found it. Now find data section.
if i := int(s.Section); 0 <= i && i < len(f.Sections) {
sect := f.Sections[i]
@@ -840,7 +846,7 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte)
}
var data []byte
for _, s := range f.Symbols {
if s.Name == "_"+"__cgodebug_data" {
if isDebugData(s.Name) {
if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
sect := f.Sections[i]
if s.Value < sect.Size {
@@ -876,14 +882,6 @@ func (p *Package) gccErrors(stdin []byte) string {
// TODO(rsc): require failure
args := p.gccCmd()
// GCC 4.8.0 has a bug: it sometimes does not apply
// -Wunused-value to values that are macros defined in system
// headers. See issue 5118. Adding -Wsystem-headers avoids
// that problem. This will produce additional errors, but it
// doesn't matter because we will ignore all errors that are
// not marked for the cgo-test file.
args = append(args, "-Wsystem-headers")
if *debugGcc {
fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " "))
os.Stderr.Write(stdin)
@@ -1048,21 +1046,11 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
}
t := new(Type)
t.Size = dtype.Size()
t.Size = dtype.Size() // note: wrong for array of pointers, corrected below
t.Align = -1
t.C = &TypeRepr{Repr: dtype.Common().Name}
c.m[dtype] = t
if t.Size < 0 {
// Unsized types are [0]byte
t.Size = 0
t.Go = c.Opaque(0)
if t.C.Empty() {
t.C.Set("void")
}
return t
}
switch dt := dtype.(type) {
default:
fatalf("%s: unexpected type: %s", lineno(pos), dtype)
@@ -1087,7 +1075,7 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
sub := c.Type(dt.Type, pos)
t.Align = sub.Align
gt.Elt = sub.Go
t.C.Set("typeof(%s[%d])", sub.C, dt.Count)
t.C.Set("__typeof__(%s[%d])", sub.C, dt.Count)
case *dwarf.BoolType:
t.Go = c.bool
@@ -1209,6 +1197,9 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
return t
case *dwarf.StructType:
if dt.ByteSize < 0 { // opaque struct
break
}
// Convert to Go struct, being careful about alignment.
// Have to give it a name to simulate C "struct foo" references.
tag := dt.StructName
@@ -1225,7 +1216,7 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
case "class", "union":
t.Go = c.Opaque(t.Size)
if t.C.Empty() {
t.C.Set("typeof(unsigned char[%d])", t.Size)
t.C.Set("__typeof__(unsigned char[%d])", t.Size)
}
t.Align = 1 // TODO: should probably base this on field alignment.
typedef[name.Name] = t
@@ -1327,6 +1318,25 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
}
}
if t.Size <= 0 {
// Clang does not record the size of a pointer in its DWARF entry,
// so if dtype is an array, the call to dtype.Size at the top of the function
// computed the size as the array length * 0 = 0.
// The type switch called Type (this function) recursively on the pointer
// entry, and the code near the top of the function updated the size to
// be correct, so calling dtype.Size again will produce the correct value.
t.Size = dtype.Size()
if t.Size < 0 {
// Unsized types are [0]byte
t.Size = 0
t.Go = c.Opaque(0)
if t.C.Empty() {
t.C.Set("void")
}
return t
}
}
if t.C.Empty() {
fatalf("%s: internal error: did not create C name for %s", lineno(pos), dtype)
}

View File

@@ -700,6 +700,13 @@ typefmt(Fmt *fp, Type *t)
return 0;
case TSTRUCT:
// Format the bucket struct for map[x]y as map.bucket[x]y.
// This avoids a recursive print that generates very long names.
if(t->hmap != T) {
t = t->hmap;
return fmtprint(fp, "map.bucket[%T]%T", t->down, t->type);
}
if(t->funarg) {
fmtstrcpy(fp, "(");
if(fmtmode == FTypeId || fmtmode == FErr) { // no argument names on function signature, and no "noescape" tags

View File

@@ -62,7 +62,7 @@ begin:
// sys.go claims to be in package PACKAGE to avoid
// conflicts during "6g sys.go". rename PACKAGE to $2.
printf("\t\"");
while(q = strstr(p, "PACKAGE")) {
while((q = strstr(p, "PACKAGE")) != NULL) {
*q = 0;
esc(p); // up to the substitution
printf("%s", name); // the sub name

View File

@@ -229,6 +229,7 @@ hmap(Type *t)
h->width = offset;
h->local = t->local;
t->hmap = h;
h->hmap = t;
return h;
}

View File

@@ -1,5 +0,0 @@
# Copyright 2012 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
include ../../Make.dist

View File

@@ -1,49 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
Prof is a rudimentary real-time profiler.
Given a command to run or the process id (pid) of a command already
running, it samples the program's state at regular intervals and reports
on its behavior. With no options, it prints a histogram of the locations
in the code that were sampled during execution.
Since it is a real-time profiler, unlike a traditional profiler it samples
the program's state even when it is not running, such as when it is
asleep or waiting for I/O. Each thread contributes equally to the
statistics.
Usage:
go tool prof -p pid [-t total_secs] [-d delta_msec] [6.out args ...]
The output modes (default -h) are:
-P file.prof:
Write the profile information to file.prof, in the format used by pprof.
At the moment, this only works on Linux amd64 binaries and requires that the
binary be written using 6l -e to produce ELF debug info.
See http://code.google.com/p/google-perftools for details.
-h: histograms
How many times a sample occurred at each location.
-f: dynamic functions
At each sample period, print the name of the executing function.
-l: dynamic file and line numbers
At each sample period, print the file and line number of the executing instruction.
-r: dynamic registers
At each sample period, print the register contents.
-s: dynamic function stack traces
At each sample period, print the symbolic stack trace.
Flag -t sets the maximum real time to sample, in seconds, and -d
sets the sampling interval in milliseconds. The default is to sample
every 100ms until the program completes.
It is installed as go tool prof and is architecture-independent.
*/
package main

View File

@@ -1,910 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !plan9
#include <u.h>
#include <time.h>
#include <libc.h>
#include <bio.h>
#include <ctype.h>
#define Ureg Ureg_amd64
#include <ureg_amd64.h>
#undef Ureg
#define Ureg Ureg_x86
#include <ureg_x86.h>
#undef Ureg
#include <mach.h>
char* file = "6.out";
static Fhdr fhdr;
int have_syms;
int fd;
struct Ureg_amd64 ureg_amd64;
struct Ureg_x86 ureg_x86;
int total_sec = 0;
int delta_msec = 100;
int nsample;
int nsamplethread;
// pprof data, stored as sequences of N followed by N PC values.
// See http://code.google.com/p/google-perftools .
uvlong *ppdata; // traces
Biobuf* pproffd; // file descriptor to write trace info
long ppstart; // start position of current trace
long nppdata; // length of data
long ppalloc; // size of allocated data
char ppmapdata[10*1024]; // the map information for the output file
// output formats
int pprof; // print pprof output to named file
int functions; // print functions
int histograms; // print histograms
int linenums; // print file and line numbers rather than function names
int registers; // print registers
int stacks; // print stack traces
int pid; // main process pid
int nthread; // number of threads
int thread[32]; // thread pids
Map *map[32]; // thread maps
void
Usage(void)
{
fprint(2, "Usage: prof -p pid [-t total_secs] [-d delta_msec]\n");
fprint(2, " prof [-t total_secs] [-d delta_msec] 6.out args ...\n");
fprint(2, "\tformats (default -h):\n");
fprint(2, "\t\t-P file.prof: write [c]pprof output to file.prof\n");
fprint(2, "\t\t-h: histograms\n");
fprint(2, "\t\t-f: dynamic functions\n");
fprint(2, "\t\t-l: dynamic file and line numbers\n");
fprint(2, "\t\t-r: dynamic registers\n");
fprint(2, "\t\t-s: dynamic function stack traces\n");
fprint(2, "\t\t-hs: include stack info in histograms\n");
exit(2);
}
typedef struct PC PC;
struct PC {
uvlong pc;
uvlong callerpc;
unsigned int count;
PC* next;
};
enum {
Ncounters = 256
};
PC *counters[Ncounters];
// Set up by setarch() to make most of the code architecture-independent.
typedef struct Arch Arch;
struct Arch {
char* name;
void (*regprint)(void);
int (*getregs)(Map*);
int (*getPC)(Map*);
int (*getSP)(Map*);
uvlong (*uregPC)(void);
uvlong (*uregSP)(void);
void (*ppword)(uvlong w);
};
void
amd64_regprint(void)
{
fprint(2, "ax\t0x%llux\n", ureg_amd64.ax);
fprint(2, "bx\t0x%llux\n", ureg_amd64.bx);
fprint(2, "cx\t0x%llux\n", ureg_amd64.cx);
fprint(2, "dx\t0x%llux\n", ureg_amd64.dx);
fprint(2, "si\t0x%llux\n", ureg_amd64.si);
fprint(2, "di\t0x%llux\n", ureg_amd64.di);
fprint(2, "bp\t0x%llux\n", ureg_amd64.bp);
fprint(2, "r8\t0x%llux\n", ureg_amd64.r8);
fprint(2, "r9\t0x%llux\n", ureg_amd64.r9);
fprint(2, "r10\t0x%llux\n", ureg_amd64.r10);
fprint(2, "r11\t0x%llux\n", ureg_amd64.r11);
fprint(2, "r12\t0x%llux\n", ureg_amd64.r12);
fprint(2, "r13\t0x%llux\n", ureg_amd64.r13);
fprint(2, "r14\t0x%llux\n", ureg_amd64.r14);
fprint(2, "r15\t0x%llux\n", ureg_amd64.r15);
fprint(2, "ds\t0x%llux\n", ureg_amd64.ds);
fprint(2, "es\t0x%llux\n", ureg_amd64.es);
fprint(2, "fs\t0x%llux\n", ureg_amd64.fs);
fprint(2, "gs\t0x%llux\n", ureg_amd64.gs);
fprint(2, "type\t0x%llux\n", ureg_amd64.type);
fprint(2, "error\t0x%llux\n", ureg_amd64.error);
fprint(2, "pc\t0x%llux\n", ureg_amd64.ip);
fprint(2, "cs\t0x%llux\n", ureg_amd64.cs);
fprint(2, "flags\t0x%llux\n", ureg_amd64.flags);
fprint(2, "sp\t0x%llux\n", ureg_amd64.sp);
fprint(2, "ss\t0x%llux\n", ureg_amd64.ss);
}
int
amd64_getregs(Map *map)
{
int i;
union {
uvlong regs[1];
struct Ureg_amd64 ureg;
} u;
for(i = 0; i < sizeof ureg_amd64; i+=8) {
if(get8(map, (uvlong)i, &u.regs[i/8]) < 0)
return -1;
}
ureg_amd64 = u.ureg;
return 0;
}
int
amd64_getPC(Map *map)
{
uvlong x;
int r;
r = get8(map, offsetof(struct Ureg_amd64, ip), &x);
ureg_amd64.ip = x;
return r;
}
int
amd64_getSP(Map *map)
{
uvlong x;
int r;
r = get8(map, offsetof(struct Ureg_amd64, sp), &x);
ureg_amd64.sp = x;
return r;
}
uvlong
amd64_uregPC(void)
{
return ureg_amd64.ip;
}
uvlong
amd64_uregSP(void)
{
return ureg_amd64.sp;
}
void
amd64_ppword(uvlong w)
{
uchar buf[8];
buf[0] = w;
buf[1] = w >> 8;
buf[2] = w >> 16;
buf[3] = w >> 24;
buf[4] = w >> 32;
buf[5] = w >> 40;
buf[6] = w >> 48;
buf[7] = w >> 56;
Bwrite(pproffd, buf, 8);
}
void
x86_regprint(void)
{
fprint(2, "ax\t0x%ux\n", ureg_x86.ax);
fprint(2, "bx\t0x%ux\n", ureg_x86.bx);
fprint(2, "cx\t0x%ux\n", ureg_x86.cx);
fprint(2, "dx\t0x%ux\n", ureg_x86.dx);
fprint(2, "si\t0x%ux\n", ureg_x86.si);
fprint(2, "di\t0x%ux\n", ureg_x86.di);
fprint(2, "bp\t0x%ux\n", ureg_x86.bp);
fprint(2, "ds\t0x%ux\n", ureg_x86.ds);
fprint(2, "es\t0x%ux\n", ureg_x86.es);
fprint(2, "fs\t0x%ux\n", ureg_x86.fs);
fprint(2, "gs\t0x%ux\n", ureg_x86.gs);
fprint(2, "cs\t0x%ux\n", ureg_x86.cs);
fprint(2, "flags\t0x%ux\n", ureg_x86.flags);
fprint(2, "pc\t0x%ux\n", ureg_x86.pc);
fprint(2, "sp\t0x%ux\n", ureg_x86.sp);
fprint(2, "ss\t0x%ux\n", ureg_x86.ss);
}
int
x86_getregs(Map *map)
{
int i;
for(i = 0; i < sizeof ureg_x86; i+=4) {
if(get4(map, (uvlong)i, &((uint32*)&ureg_x86)[i/4]) < 0)
return -1;
}
return 0;
}
int
x86_getPC(Map* map)
{
return get4(map, offsetof(struct Ureg_x86, pc), &ureg_x86.pc);
}
int
x86_getSP(Map* map)
{
return get4(map, offsetof(struct Ureg_x86, sp), &ureg_x86.sp);
}
uvlong
x86_uregPC(void)
{
return (uvlong)ureg_x86.pc;
}
uvlong
x86_uregSP(void)
{
return (uvlong)ureg_x86.sp;
}
void
x86_ppword(uvlong w)
{
uchar buf[4];
buf[0] = w;
buf[1] = w >> 8;
buf[2] = w >> 16;
buf[3] = w >> 24;
Bwrite(pproffd, buf, 4);
}
Arch archtab[] = {
{
"amd64",
amd64_regprint,
amd64_getregs,
amd64_getPC,
amd64_getSP,
amd64_uregPC,
amd64_uregSP,
amd64_ppword,
},
{
"386",
x86_regprint,
x86_getregs,
x86_getPC,
x86_getSP,
x86_uregPC,
x86_uregSP,
x86_ppword,
},
{
nil
}
};
Arch *arch;
int
setarch(void)
{
int i;
if(mach != nil) {
for(i = 0; archtab[i].name != nil; i++) {
if (strcmp(mach->name, archtab[i].name) == 0) {
arch = &archtab[i];
return 0;
}
}
}
return -1;
}
int
getthreads(void)
{
int i, j, curn, found;
Map *curmap[nelem(map)];
int curthread[nelem(map)];
static int complained = 0;
curn = procthreadpids(pid, curthread, nelem(curthread));
if(curn <= 0)
return curn;
if(curn > nelem(map)) {
if(complained == 0) {
fprint(2, "prof: too many threads; limiting to %d\n", nthread, nelem(map));
complained = 1;
}
curn = nelem(map);
}
if(curn == nthread && memcmp(thread, curthread, curn*sizeof(*thread)) == 0)
return curn; // no changes
// Number of threads has changed (might be the init case).
// A bit expensive but rare enough not to bother being clever.
for(i = 0; i < curn; i++) {
found = 0;
for(j = 0; j < nthread; j++) {
if(curthread[i] == thread[j]) {
found = 1;
curmap[i] = map[j];
map[j] = nil;
break;
}
}
if(found)
continue;
// map new thread
curmap[i] = attachproc(curthread[i], &fhdr);
if(curmap[i] == nil) {
fprint(2, "prof: can't attach to %d: %r\n", curthread[i]);
return -1;
}
}
for(j = 0; j < nthread; j++)
if(map[j] != nil)
detachproc(map[j]);
nthread = curn;
memmove(thread, curthread, nthread*sizeof thread[0]);
memmove(map, curmap, sizeof map);
return nthread;
}
int
sample(Map *map)
{
static int n;
n++;
if(registers) {
if(arch->getregs(map) < 0)
goto bad;
} else {
// we need only two registers
if(arch->getPC(map) < 0)
goto bad;
if(arch->getSP(map) < 0)
goto bad;
}
return 1;
bad:
if(n == 1)
fprint(2, "prof: can't read registers: %r\n");
return 0;
}
void
addtohistogram(uvlong pc, uvlong callerpc, uvlong sp)
{
int h;
PC *x;
USED(sp);
h = (pc + callerpc*101) % Ncounters;
for(x = counters[h]; x != NULL; x = x->next) {
if(x->pc == pc && x->callerpc == callerpc) {
x->count++;
return;
}
}
x = malloc(sizeof(PC));
if(x == nil)
sysfatal("out of memory");
x->pc = pc;
x->callerpc = callerpc;
x->count = 1;
x->next = counters[h];
counters[h] = x;
}
void
addppword(uvlong pc)
{
if(pc == 0) {
return;
}
if(nppdata == ppalloc) {
ppalloc = (1000+nppdata)*2;
ppdata = realloc(ppdata, ppalloc * sizeof ppdata[0]);
if(ppdata == nil) {
fprint(2, "prof: realloc failed: %r\n");
exit(2);
}
}
ppdata[nppdata++] = pc;
}
void
startpptrace(void)
{
ppstart = nppdata;
addppword(~0);
}
void
endpptrace(void)
{
ppdata[ppstart] = nppdata-ppstart-1;
}
uvlong nextpc;
void
xptrace(Map *map, uvlong pc, uvlong sp, Symbol *sym)
{
USED(map);
char buf[1024];
if(sym == nil){
fprint(2, "syms\n");
return;
}
if(histograms)
addtohistogram(nextpc, pc, sp);
if(!histograms || stacks > 1 || pprof) {
if(nextpc == 0)
nextpc = sym->value;
if(stacks){
fprint(2, "%s(", sym->name);
fprint(2, ")");
if(nextpc != sym->value)
fprint(2, "+%#llux ", nextpc - sym->value);
if(have_syms && linenums && fileline(buf, sizeof buf, pc)) {
fprint(2, " %s", buf);
}
fprint(2, "\n");
}
if (pprof) {
addppword(nextpc);
}
}
nextpc = pc;
}
void
stacktracepcsp(Map *map, uvlong pc, uvlong sp)
{
nextpc = pc;
if(pprof){
startpptrace();
}
if(machdata->ctrace==nil)
fprint(2, "no machdata->ctrace\n");
else if(machdata->ctrace(map, pc, sp, 0, xptrace) <= 0)
fprint(2, "no stack frame: pc=%#p sp=%#p\n", pc, sp);
else {
addtohistogram(nextpc, 0, sp);
if(stacks)
fprint(2, "\n");
}
if(pprof){
endpptrace();
}
}
void
printpc(Map *map, uvlong pc, uvlong sp)
{
char buf[1024];
if(registers)
arch->regprint();
if(have_syms > 0 && linenums && fileline(buf, sizeof buf, pc))
fprint(2, "%s\n", buf);
if(have_syms > 0 && functions) {
symoff(buf, sizeof(buf), pc, CANY);
fprint(2, "%s\n", buf);
}
if(stacks || pprof){
stacktracepcsp(map, pc, sp);
}
else if(histograms){
addtohistogram(pc, 0, sp);
}
}
void
ppmaps(void)
{
int fd, n;
char tmp[100];
Seg *seg;
// If it's Linux, the info is in /proc/$pid/maps
snprint(tmp, sizeof tmp, "/proc/%d/maps", pid);
fd = open(tmp, 0);
if(fd >= 0) {
n = read(fd, ppmapdata, sizeof ppmapdata - 1);
close(fd);
if(n < 0) {
fprint(2, "prof: can't read %s: %r\n", tmp);
exit(2);
}
ppmapdata[n] = 0;
return;
}
// It's probably a mac. Synthesize an entry for the text file.
// The register segment may come first but it has a zero offset, so grab the first non-zero offset segment.
for(n = 0; n < 3; n++){
seg = &map[0]->seg[n];
if(seg->b == 0) {
continue;
}
snprint(ppmapdata, sizeof ppmapdata,
"%.16x-%.16x r-xp %d 00:00 34968549 %s\n",
seg->b, seg->e, seg->f, "/home/r/6.out"
);
return;
}
fprint(2, "prof: no text segment in maps for %s\n", file);
exit(2);
}
void
samples(void)
{
int i, pid, msec;
struct timespec req;
int getmaps;
req.tv_sec = delta_msec/1000;
req.tv_nsec = 1000000*(delta_msec % 1000);
getmaps = 0;
if(pprof)
getmaps= 1;
for(msec = 0; total_sec <= 0 || msec < 1000*total_sec; msec += delta_msec) {
nsample++;
nsamplethread += nthread;
for(i = 0; i < nthread; i++) {
pid = thread[i];
if(ctlproc(pid, "stop") < 0)
return;
if(!sample(map[i])) {
ctlproc(pid, "start");
return;
}
printpc(map[i], arch->uregPC(), arch->uregSP());
ctlproc(pid, "start");
}
nanosleep(&req, NULL);
getthreads();
if(nthread == 0)
break;
if(getmaps) {
getmaps = 0;
ppmaps();
}
}
}
typedef struct Func Func;
struct Func
{
Func *next;
Symbol s;
uint onstack;
uint leaf;
};
Func *func[257];
int nfunc;
Func*
findfunc(uvlong pc)
{
Func *f;
uint h;
Symbol s;
if(pc == 0)
return nil;
if(!findsym(pc, CTEXT, &s))
return nil;
h = s.value % nelem(func);
for(f = func[h]; f != NULL; f = f->next)
if(f->s.value == s.value)
return f;
f = malloc(sizeof *f);
if(f == nil)
sysfatal("out of memory");
memset(f, 0, sizeof *f);
f->s = s;
f->next = func[h];
func[h] = f;
nfunc++;
return f;
}
int
compareleaf(const void *va, const void *vb)
{
Func *a, *b;
a = *(Func**)va;
b = *(Func**)vb;
if(a->leaf != b->leaf)
return b->leaf - a->leaf;
if(a->onstack != b->onstack)
return b->onstack - a->onstack;
return strcmp(a->s.name, b->s.name);
}
void
dumphistogram(void)
{
int i, h, n;
PC *x;
Func *f, **ff;
if(!histograms)
return;
// assign counts to functions.
for(h = 0; h < Ncounters; h++) {
for(x = counters[h]; x != NULL; x = x->next) {
f = findfunc(x->pc);
if(f) {
f->onstack += x->count;
f->leaf += x->count;
}
f = findfunc(x->callerpc);
if(f)
f->leaf -= x->count;
}
}
// build array
ff = malloc(nfunc*sizeof ff[0]);
if(ff == nil)
sysfatal("out of memory");
n = 0;
for(h = 0; h < nelem(func); h++)
for(f = func[h]; f != NULL; f = f->next)
ff[n++] = f;
// sort by leaf counts
qsort(ff, nfunc, sizeof ff[0], compareleaf);
// print.
fprint(2, "%d samples (avg %.1g threads)\n", nsample, (double)nsamplethread/nsample);
for(i = 0; i < nfunc; i++) {
f = ff[i];
fprint(2, "%6.2f%%\t", 100.0*(double)f->leaf/nsample);
if(stacks)
fprint(2, "%6.2f%%\t", 100.0*(double)f->onstack/nsample);
fprint(2, "%s\n", f->s.name);
}
}
typedef struct Trace Trace;
struct Trace {
int count;
int npc;
uvlong *pc;
Trace *next;
};
void
dumppprof(void)
{
uvlong i, n, *p, *e;
int ntrace;
Trace *trace, *tp, *up, *prev;
if(!pprof)
return;
e = ppdata + nppdata;
// Create list of traces. First, count the traces
ntrace = 0;
for(p = ppdata; p < e;) {
n = *p++;
p += n;
if(n == 0)
continue;
ntrace++;
}
if(ntrace <= 0)
return;
// Allocate and link the traces together.
trace = malloc(ntrace * sizeof(Trace));
if(trace == nil)
sysfatal("out of memory");
tp = trace;
for(p = ppdata; p < e;) {
n = *p++;
if(n == 0)
continue;
tp->count = 1;
tp->npc = n;
tp->pc = p;
tp->next = tp+1;
tp++;
p += n;
}
trace[ntrace-1].next = nil;
// Eliminate duplicates. Lousy algorithm, although not as bad as it looks because
// the list collapses fast.
for(tp = trace; tp != nil; tp = tp->next) {
prev = tp;
for(up = tp->next; up != nil; up = up->next) {
if(up->npc == tp->npc && memcmp(up->pc, tp->pc, up->npc*sizeof up->pc[0]) == 0) {
tp->count++;
prev->next = up->next;
} else {
prev = up;
}
}
}
// Write file.
// See http://code.google.com/p/google-perftools/source/browse/trunk/doc/cpuprofile-fileformat.html
// 1) Header
arch->ppword(0); // must be zero
arch->ppword(3); // 3 words follow in header
arch->ppword(0); // must be zero
arch->ppword(delta_msec * 1000); // sampling period in microseconds
arch->ppword(0); // must be zero (padding)
// 2) One record for each trace.
for(tp = trace; tp != nil; tp = tp->next) {
arch->ppword(tp->count);
arch->ppword(tp->npc);
for(i = 0; i < tp->npc; i++) {
arch->ppword(tp->pc[i]);
}
}
// 3) Binary trailer
arch->ppword(0); // must be zero
arch->ppword(1); // must be one
arch->ppword(0); // must be zero
// 4) Mapped objects.
Bwrite(pproffd, ppmapdata, strlen(ppmapdata));
// 5) That's it.
Bterm(pproffd);
}
int
startprocess(char **argv)
{
int pid;
if((pid = fork()) == 0) {
pid = getpid();
if(ctlproc(pid, "hang") < 0){
fprint(2, "prof: child process could not hang\n");
exits(0);
}
execv(argv[0], argv);
fprint(2, "prof: could not exec %s: %r\n", argv[0]);
exits(0);
}
if(pid == -1) {
fprint(2, "prof: could not fork\n");
exit(1);
}
if(ctlproc(pid, "attached") < 0 || ctlproc(pid, "waitstop") < 0) {
fprint(2, "prof: could not attach to child process: %r\n");
exit(1);
}
return pid;
}
void
detach(void)
{
int i;
for(i = 0; i < nthread; i++)
detachproc(map[i]);
}
int
main(int argc, char *argv[])
{
int i;
char *ppfile;
ARGBEGIN{
case 'P':
pprof =1;
ppfile = EARGF(Usage());
pproffd = Bopen(ppfile, OWRITE);
if(pproffd == nil) {
fprint(2, "prof: cannot open %s: %r\n", ppfile);
exit(2);
}
break;
case 'd':
delta_msec = atoi(EARGF(Usage()));
break;
case 't':
total_sec = atoi(EARGF(Usage()));
break;
case 'p':
pid = atoi(EARGF(Usage()));
break;
case 'f':
functions = 1;
break;
case 'h':
histograms = 1;
break;
case 'l':
linenums = 1;
break;
case 'r':
registers = 1;
break;
case 's':
stacks++;
break;
default:
Usage();
}ARGEND
if(pid <= 0 && argc == 0)
Usage();
if(functions+linenums+registers+stacks+pprof == 0)
histograms = 1;
if(!machbyname("amd64")) {
fprint(2, "prof: no amd64 support\n", pid);
exit(1);
}
if(argc > 0)
file = argv[0];
else if(pid) {
file = proctextfile(pid);
if (file == NULL) {
fprint(2, "prof: can't find file for pid %d: %r\n", pid);
fprint(2, "prof: on Darwin, need to provide file name explicitly\n");
exit(1);
}
}
fd = open(file, 0);
if(fd < 0) {
fprint(2, "prof: can't open %s: %r\n", file);
exit(1);
}
if(crackhdr(fd, &fhdr)) {
have_syms = syminit(fd, &fhdr);
if(!have_syms) {
fprint(2, "prof: no symbols for %s: %r\n", file);
}
} else {
fprint(2, "prof: crack header for %s: %r\n", file);
exit(1);
}
if(pid <= 0)
pid = startprocess(argv);
attachproc(pid, &fhdr); // initializes thread list
if(setarch() < 0) {
detach();
fprint(2, "prof: can't identify binary architecture for pid %d\n", pid);
exit(1);
}
if(getthreads() <= 0) {
detach();
fprint(2, "prof: can't find threads for pid %d\n", pid);
exit(1);
}
for(i = 0; i < nthread; i++)
ctlproc(thread[i], "start");
samples();
detach();
dumphistogram();
dumppprof();
exit(0);
}

View File

@@ -357,7 +357,7 @@ func main() {
func setup() {
var j, ty int
stderr = bufio.NewWriter(os.NewFile(2, "stderr"))
stderr = bufio.NewWriter(os.Stderr)
foutput = nil
flag.Parse()

View File

@@ -126,10 +126,19 @@ type signatureAndHash struct {
hash, signature uint8
}
// supportedSignatureAlgorithms contains the signature and hash algorithms that
// the code can advertise as supported both in a TLS 1.2 ClientHello and
// supportedSKXSignatureAlgorithms contains the signature and hash algorithms
// that the code advertises as supported in a TLS 1.2 ClientHello.
var supportedSKXSignatureAlgorithms = []signatureAndHash{
{hashSHA256, signatureRSA},
{hashSHA256, signatureECDSA},
{hashSHA1, signatureRSA},
{hashSHA1, signatureECDSA},
}
// supportedClientCertSignatureAlgorithms contains the signature and hash
// algorithms that the code advertises as supported in a TLS 1.2
// CertificateRequest.
var supportedSignatureAlgorithms = []signatureAndHash{
var supportedClientCertSignatureAlgorithms = []signatureAndHash{
{hashSHA256, signatureRSA},
{hashSHA256, signatureECDSA},
}

View File

@@ -63,7 +63,7 @@ NextCipherSuite:
}
if hello.vers >= VersionTLS12 {
hello.signatureAndHashes = supportedSignatureAlgorithms
hello.signatureAndHashes = supportedSKXSignatureAlgorithms
}
c.writeRecord(recordTypeHandshake, hello.marshal())

View File

@@ -1834,30 +1834,30 @@ var clientChainCertificateScript = [][]byte{
// -minversion=0x0303 -maxversion=0x0303
var clientTLS12Script = [][]byte{
{
0x16, 0x03, 0x01, 0x00, 0x54, 0x01, 0x00, 0x00,
0x50, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x16, 0x03, 0x01, 0x00, 0x58, 0x01, 0x00, 0x00,
0x54, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x13,
0x01, 0x00, 0x00, 0x25, 0x00, 0x05, 0x00, 0x05,
0x01, 0x00, 0x00, 0x29, 0x00, 0x05, 0x00, 0x05,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
0x0d, 0x00, 0x06, 0x00, 0x04, 0x04, 0x01, 0x04,
0x03,
0x0d, 0x00, 0x0a, 0x00, 0x08, 0x04, 0x01, 0x04,
0x03, 0x02, 0x01, 0x02, 0x03,
},
{
0x16, 0x03, 0x03, 0x00, 0x54, 0x02, 0x00, 0x00,
0x50, 0x03, 0x03, 0x51, 0xe5, 0x78, 0x4c, 0x64,
0x66, 0xd0, 0xee, 0x0b, 0x8b, 0xfd, 0x9b, 0xe0,
0x54, 0x3c, 0x6e, 0x05, 0x04, 0x2f, 0x77, 0x07,
0x8c, 0x04, 0xb9, 0xf6, 0xdd, 0xea, 0x1a, 0x7c,
0xdf, 0x65, 0x39, 0x20, 0xea, 0xa2, 0xef, 0x53,
0x96, 0xf5, 0x0b, 0x8a, 0x47, 0xa0, 0x7c, 0x20,
0x53, 0x75, 0xee, 0x87, 0xb9, 0xd3, 0xe2, 0xa6,
0x97, 0x64, 0xb9, 0xa6, 0xcc, 0xc0, 0xe5, 0xbf,
0x92, 0x1d, 0xee, 0x4d, 0xc0, 0x13, 0x00, 0x00,
0x50, 0x03, 0x03, 0x52, 0x65, 0x67, 0xbd, 0xe8,
0x72, 0x03, 0x6a, 0x52, 0x8d, 0x28, 0x2c, 0x9a,
0x53, 0xff, 0xc2, 0xa1, 0x62, 0x5f, 0x54, 0xfb,
0x73, 0x00, 0xcf, 0x4d, 0x28, 0x36, 0xc2, 0xee,
0xfd, 0x78, 0xf0, 0x20, 0x6f, 0xbe, 0x49, 0xec,
0x5b, 0x6f, 0xf9, 0x53, 0x42, 0x69, 0x0d, 0x6d,
0x8b, 0x68, 0x2e, 0xca, 0x3c, 0x3c, 0x88, 0x9e,
0x8b, 0xf9, 0x32, 0x65, 0x09, 0xd6, 0xa0, 0x7d,
0xea, 0xc6, 0xd5, 0xc4, 0xc0, 0x13, 0x00, 0x00,
0x08, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01,
0x02, 0x16, 0x03, 0x03, 0x02, 0x39, 0x0b, 0x00,
0x02, 0x35, 0x00, 0x02, 0x32, 0x00, 0x02, 0x2f,
@@ -1932,24 +1932,24 @@ var clientTLS12Script = [][]byte{
0xbb, 0x77, 0xba, 0xe4, 0x12, 0xbb, 0xf4, 0xc8,
0x5e, 0x9c, 0x81, 0xa8, 0x97, 0x60, 0x4c, 0x16,
0x03, 0x03, 0x00, 0x8d, 0x0c, 0x00, 0x00, 0x89,
0x03, 0x00, 0x17, 0x41, 0x04, 0x39, 0xe9, 0x59,
0x24, 0x76, 0xf0, 0x1a, 0xd6, 0x21, 0xa5, 0xbc,
0x28, 0xb9, 0xd5, 0x3d, 0xf7, 0xf3, 0xbe, 0x09,
0xff, 0xc1, 0x79, 0x33, 0x82, 0xf8, 0xe1, 0x5f,
0x1c, 0x34, 0x96, 0x3a, 0x10, 0xf2, 0x2c, 0x69,
0xab, 0x57, 0xf6, 0x20, 0xb6, 0x59, 0x1f, 0x8c,
0x3e, 0xa2, 0xac, 0x4d, 0xf2, 0x10, 0x58, 0x0b,
0x61, 0x27, 0x6c, 0x47, 0xa0, 0x52, 0xc7, 0xe6,
0x36, 0xfd, 0xb1, 0xa2, 0x49, 0x04, 0x01, 0x00,
0x40, 0x99, 0x7e, 0xf9, 0xed, 0x8b, 0x62, 0x82,
0x00, 0xde, 0x5f, 0x2f, 0xb9, 0xf9, 0x9d, 0xa1,
0xb0, 0x14, 0x05, 0xc1, 0xdd, 0xa3, 0xb9, 0x08,
0xa5, 0x36, 0xb6, 0xfe, 0x8a, 0x5b, 0x2d, 0x6e,
0xd8, 0x5a, 0x5c, 0x89, 0x84, 0x85, 0x56, 0x01,
0xaf, 0x43, 0xd3, 0x0f, 0x85, 0xd0, 0xb2, 0x35,
0x3d, 0x1d, 0xd6, 0x67, 0x52, 0x48, 0xe8, 0x82,
0x47, 0xbb, 0x2a, 0x54, 0x4a, 0x55, 0xcd, 0x10,
0x54, 0x16, 0x03, 0x03, 0x00, 0x04, 0x0e, 0x00,
0x03, 0x00, 0x17, 0x41, 0x04, 0x48, 0x93, 0x62,
0x6a, 0xf8, 0x7c, 0x94, 0xcc, 0xcc, 0x0a, 0x9b,
0x5e, 0x11, 0xad, 0x0b, 0x30, 0xc4, 0x5d, 0xf7,
0x63, 0x24, 0xc1, 0xb0, 0x40, 0x5f, 0xff, 0x9f,
0x0d, 0x7e, 0xd5, 0xa5, 0xd0, 0x4f, 0x80, 0x16,
0xa8, 0x66, 0x18, 0x31, 0x1f, 0x81, 0xb2, 0x9a,
0x41, 0x62, 0x5b, 0xcf, 0x73, 0xac, 0x4a, 0x64,
0xb5, 0xc1, 0x46, 0x4d, 0x8a, 0xac, 0x25, 0xba,
0x81, 0x7f, 0xbe, 0x64, 0x68, 0x04, 0x01, 0x00,
0x40, 0x4e, 0x3f, 0x1e, 0x04, 0x4c, 0xef, 0xd2,
0xa6, 0x82, 0xe6, 0x7c, 0x76, 0x23, 0x17, 0xb9,
0xe7, 0x52, 0x15, 0x6b, 0x3d, 0xb2, 0xb1, 0x17,
0x7d, 0xe6, 0xde, 0x06, 0x87, 0x30, 0xb0, 0xb5,
0x57, 0xae, 0xdf, 0xb2, 0xdc, 0x8d, 0xab, 0x76,
0x9c, 0xaa, 0x45, 0x6d, 0x23, 0x5d, 0xc1, 0xa8,
0x7b, 0x79, 0x79, 0xb1, 0x3c, 0xdc, 0xf5, 0x33,
0x2c, 0xa1, 0x62, 0x3e, 0xbd, 0xf5, 0x5d, 0x6c,
0x87, 0x16, 0x03, 0x03, 0x00, 0x04, 0x0e, 0x00,
0x00, 0x00,
},
{
@@ -1965,74 +1965,74 @@ var clientTLS12Script = [][]byte{
0xdc, 0x5a, 0x89, 0x14, 0x03, 0x03, 0x00, 0x01,
0x01, 0x16, 0x03, 0x03, 0x00, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xcb,
0x97, 0x41, 0x63, 0x39, 0xeb, 0xda, 0x04, 0x39,
0xfb, 0x67, 0x1d, 0x6d, 0xf8, 0x58, 0xd1, 0x22,
0x35, 0xe3, 0xc3, 0x9d, 0xfc, 0x4e, 0xcc, 0x71,
0x93, 0x78, 0x64, 0x39, 0x04, 0xa0, 0xa9, 0x41,
0xcf, 0x4c, 0xd6, 0x34, 0xad, 0x5c, 0xc9, 0x7a,
0x44, 0xb1, 0x1d, 0x77, 0x52, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x17,
0x54, 0x51, 0xb6, 0x1d, 0x8e, 0xe4, 0x6b, 0xed,
0x5b, 0xa1, 0x27, 0x7f, 0xdc, 0xa9, 0xa5, 0xcf,
0x38, 0xe6, 0x5d, 0x17, 0x34, 0xf9, 0xc0, 0x07,
0xb8, 0xbe, 0x56, 0xe6, 0xd6, 0x6a, 0xb6, 0x26,
0x4e, 0x45, 0x8d, 0x48, 0xe9, 0xc6, 0xb1, 0xa1,
0xea, 0xdc, 0xb1, 0x37, 0xd9, 0xf6,
},
{
0x14, 0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03,
0x03, 0x00, 0x40, 0x55, 0x75, 0x8a, 0x57, 0xb4,
0x53, 0xa2, 0x8f, 0xbf, 0xd3, 0x79, 0x72, 0x1e,
0x94, 0x53, 0xb3, 0x03, 0x9d, 0x4d, 0x8a, 0x1f,
0xbd, 0x25, 0x79, 0x69, 0x61, 0x65, 0xd7, 0x26,
0xad, 0xa6, 0x0e, 0x89, 0x83, 0xc0, 0xbe, 0x46,
0x51, 0xe4, 0x38, 0x7b, 0x65, 0x74, 0x6d, 0x24,
0xff, 0xd4, 0x9f, 0xcb, 0xfc, 0xd7, 0x03, 0xaa,
0x7b, 0x8e, 0x30, 0x09, 0xdb, 0xaa, 0x9d, 0xad,
0xcd, 0x56, 0xcf,
0x03, 0x00, 0x40, 0x00, 0x68, 0xc5, 0x27, 0xd5,
0x3d, 0xba, 0x04, 0xde, 0x63, 0xf1, 0x5b, 0xc3,
0x86, 0xb9, 0x82, 0xc7, 0xb3, 0x90, 0x31, 0xea,
0x15, 0xe1, 0x42, 0x76, 0x7d, 0x90, 0xcb, 0xc9,
0xd1, 0x05, 0xe6, 0x8c, 0x76, 0xc7, 0x9a, 0x35,
0x67, 0xa2, 0x70, 0x9a, 0x8a, 0x6c, 0xb5, 0x6b,
0xc7, 0x87, 0xf3, 0x65, 0x0a, 0xa0, 0x98, 0xba,
0x57, 0xbb, 0x31, 0x7b, 0x1f, 0x1a, 0xf7, 0x2a,
0xf3, 0x12, 0xf6,
},
{
0x17, 0x03, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x01, 0x46,
0xa8, 0xdd, 0x62, 0x73, 0x67, 0x99, 0x01, 0x42,
0xb2, 0x9e, 0x22, 0x18, 0xf5, 0x8f, 0x10, 0x97,
0xde, 0x58, 0x24, 0x34, 0x36, 0xa2, 0x5d, 0xf4,
0x96, 0x2a, 0xed, 0x6c, 0x06, 0x15, 0x03, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x80,
0x54, 0x1e, 0x72, 0xd3, 0x1a, 0x86, 0x1c, 0xc4,
0x4a, 0x9b, 0xd4, 0x80, 0xd2, 0x03, 0x35, 0x0d,
0xe4, 0x12, 0xc2, 0x3d, 0x79, 0x4a, 0x2c, 0xba,
0xc2, 0xad, 0xf3, 0xd2, 0x16, 0x15, 0x03, 0x03,
0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x9f, 0x7a, 0x9f, 0xab, 0xf5, 0x4e,
0x1c, 0x4e, 0xf4, 0xcb, 0x1a, 0x39, 0xae, 0x21,
0x85, 0x39, 0xc4, 0x51, 0xac, 0x14, 0xde, 0xa0,
0xe7, 0x70, 0x7c, 0x6a, 0x53, 0x54, 0x19, 0xbc,
0x2f, 0x32,
0x00, 0x00, 0x04, 0x9b, 0x68, 0x78, 0x92, 0x28,
0x62, 0x02, 0x65, 0x87, 0x90, 0xe4, 0x32, 0xd7,
0x72, 0x08, 0x70, 0xb8, 0x52, 0x32, 0x1f, 0x97,
0xd4, 0x6a, 0xc6, 0x28, 0x83, 0xb0, 0x1d, 0x6e,
0x16, 0xd5,
},
}
// $ openssl s_server -tls1_2 -cert server.crt -key server.key \
// -port 10443
// -port 10443 -verify 0
// $ go test -test.run "TestRunClient" -connect -ciphersuites=0xc02f \
// -maxversion=0x0303
var clientTLS12ClientCertScript = [][]byte{
{
0x16, 0x03, 0x01, 0x00, 0x54, 0x01, 0x00, 0x00,
0x50, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x16, 0x03, 0x01, 0x00, 0x58, 0x01, 0x00, 0x00,
0x54, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x2f,
0x01, 0x00, 0x00, 0x25, 0x00, 0x05, 0x00, 0x05,
0x01, 0x00, 0x00, 0x29, 0x00, 0x05, 0x00, 0x05,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
0x0d, 0x00, 0x06, 0x00, 0x04, 0x04, 0x01, 0x04,
0x03,
0x0d, 0x00, 0x0a, 0x00, 0x08, 0x04, 0x01, 0x04,
0x03, 0x02, 0x01, 0x02, 0x03,
},
{
0x16, 0x03, 0x03, 0x00, 0x54, 0x02, 0x00, 0x00,
0x50, 0x03, 0x03, 0x52, 0x37, 0x21, 0x96, 0x1c,
0x0a, 0x59, 0xc7, 0x16, 0x6d, 0x44, 0x76, 0xda,
0x3f, 0x36, 0x12, 0x0c, 0x9d, 0xe1, 0xf7, 0xeb,
0x45, 0x53, 0x89, 0xd6, 0x88, 0xc0, 0xe9, 0xce,
0x8b, 0x40, 0xf5, 0x20, 0x13, 0x61, 0xd9, 0x3b,
0x29, 0x74, 0x3c, 0x4b, 0x9c, 0x7b, 0x3d, 0xfa,
0x7a, 0x8e, 0x5b, 0xf2, 0x27, 0x62, 0xc5, 0xdf,
0xe4, 0x61, 0x7d, 0xe3, 0x8f, 0x03, 0x0c, 0x2b,
0x38, 0x6c, 0xfe, 0x31, 0xc0, 0x2f, 0x00, 0x00,
0x50, 0x03, 0x03, 0x52, 0x65, 0x67, 0xe0, 0xe8,
0xf1, 0x13, 0x2a, 0x83, 0x28, 0xa8, 0x2e, 0x76,
0x69, 0xe6, 0x89, 0x55, 0x6c, 0x48, 0x49, 0x2e,
0x00, 0xf6, 0x87, 0x6c, 0x13, 0xa1, 0xd4, 0xaa,
0xd0, 0x76, 0x3b, 0x20, 0xe4, 0xd6, 0x5b, 0x1d,
0x11, 0xf2, 0x42, 0xf2, 0x82, 0x0c, 0x0d, 0x66,
0x6d, 0xec, 0x52, 0xf8, 0x4a, 0xd9, 0x45, 0xcf,
0xe4, 0x4a, 0xba, 0x8b, 0xf1, 0xab, 0x55, 0xe4,
0x57, 0x18, 0xa9, 0x36, 0xc0, 0x2f, 0x00, 0x00,
0x08, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01,
0x02, 0x16, 0x03, 0x03, 0x02, 0x39, 0x0b, 0x00,
0x02, 0x35, 0x00, 0x02, 0x32, 0x00, 0x02, 0x2f,
@@ -2107,24 +2107,24 @@ var clientTLS12ClientCertScript = [][]byte{
0xbb, 0x77, 0xba, 0xe4, 0x12, 0xbb, 0xf4, 0xc8,
0x5e, 0x9c, 0x81, 0xa8, 0x97, 0x60, 0x4c, 0x16,
0x03, 0x03, 0x00, 0x8d, 0x0c, 0x00, 0x00, 0x89,
0x03, 0x00, 0x17, 0x41, 0x04, 0xdf, 0xc4, 0x75,
0x20, 0x7f, 0xc1, 0x8f, 0x92, 0x2d, 0xab, 0x2d,
0x65, 0x19, 0x40, 0xf6, 0x26, 0x19, 0x90, 0x84,
0x40, 0x55, 0xd3, 0x50, 0xe5, 0x63, 0x9e, 0x4b,
0x7a, 0x95, 0xdc, 0xb7, 0x2b, 0xa7, 0xa3, 0x5a,
0x5e, 0x01, 0xa0, 0x3e, 0xc2, 0x3c, 0x5d, 0xf6,
0x9a, 0xc8, 0xbe, 0x22, 0x23, 0x38, 0x31, 0x7c,
0x51, 0x83, 0x5d, 0x4f, 0xfb, 0x08, 0x66, 0x5f,
0xfe, 0xf5, 0x97, 0x9a, 0x93, 0x04, 0x01, 0x00,
0x40, 0x81, 0x52, 0x86, 0xe6, 0x20, 0x49, 0x65,
0x1b, 0x27, 0x46, 0x88, 0xd8, 0x0c, 0x44, 0x47,
0xae, 0xbd, 0xc6, 0xe4, 0x4a, 0x2c, 0x10, 0xf4,
0x3a, 0xd5, 0xbe, 0x5c, 0xfb, 0x5a, 0xe9, 0x85,
0x57, 0xda, 0xf9, 0xb1, 0x8e, 0xce, 0x01, 0x43,
0x84, 0x91, 0x68, 0x58, 0xa0, 0xbf, 0xd0, 0x24,
0xaa, 0x86, 0xfa, 0x19, 0x59, 0x06, 0x16, 0xe8,
0x82, 0x99, 0x90, 0x60, 0x02, 0x82, 0xaf, 0x7e,
0x0e, 0x16, 0x03, 0x03, 0x00, 0x30, 0x0d, 0x00,
0x03, 0x00, 0x17, 0x41, 0x04, 0xaa, 0xf0, 0x0c,
0xa3, 0x60, 0xcf, 0x69, 0x1e, 0xad, 0x16, 0x9a,
0x01, 0x40, 0xc6, 0x22, 0xc4, 0xbb, 0x06, 0x3b,
0x84, 0x65, 0xea, 0xc7, 0xa2, 0x96, 0x79, 0x17,
0x2f, 0xc7, 0xbe, 0x56, 0x39, 0xe4, 0x79, 0xf3,
0xad, 0x17, 0xf3, 0x7e, 0xe2, 0x7b, 0xa2, 0x6f,
0x3f, 0x96, 0xea, 0xe5, 0x0e, 0xea, 0x39, 0x79,
0x77, 0xeb, 0x14, 0x18, 0xbb, 0x7c, 0x95, 0xda,
0xa7, 0x51, 0x09, 0xba, 0xd7, 0x04, 0x01, 0x00,
0x40, 0x82, 0x3e, 0xce, 0xee, 0x7e, 0xba, 0x3b,
0x51, 0xb1, 0xba, 0x71, 0x2e, 0x54, 0xa9, 0xb9,
0xe2, 0xb1, 0x59, 0x17, 0xa1, 0xac, 0x76, 0xb4,
0x4e, 0xf1, 0xae, 0x65, 0x17, 0x2b, 0x43, 0x06,
0x31, 0x29, 0x0b, 0xa0, 0x1e, 0xb6, 0xfa, 0x35,
0xe8, 0x63, 0x06, 0xde, 0x13, 0x89, 0x83, 0x69,
0x3b, 0xc2, 0x15, 0x73, 0x1c, 0xc5, 0x07, 0xe9,
0x38, 0x9b, 0x06, 0x81, 0x1b, 0x97, 0x7c, 0xa6,
0x89, 0x16, 0x03, 0x03, 0x00, 0x30, 0x0d, 0x00,
0x00, 0x28, 0x03, 0x01, 0x02, 0x40, 0x00, 0x20,
0x06, 0x01, 0x06, 0x02, 0x06, 0x03, 0x05, 0x01,
0x05, 0x02, 0x05, 0x03, 0x04, 0x01, 0x04, 0x02,
@@ -2496,65 +2496,65 @@ var clientTLS12ClientCertScript = [][]byte{
0xa6, 0xb5, 0x68, 0x1a, 0x41, 0x03, 0x56, 0x6b,
0xdc, 0x5a, 0x89, 0x16, 0x03, 0x03, 0x01, 0x08,
0x0f, 0x00, 0x01, 0x04, 0x04, 0x01, 0x01, 0x00,
0x78, 0x13, 0xba, 0x6a, 0xc6, 0xec, 0xd8, 0x03,
0x7f, 0x66, 0x83, 0xbd, 0xa6, 0xd0, 0x60, 0x05,
0x20, 0xf7, 0x2b, 0xa3, 0xe3, 0x8c, 0xbf, 0xab,
0x40, 0x95, 0x47, 0x31, 0xd0, 0xb6, 0x9e, 0x3c,
0x82, 0xf1, 0xd9, 0x25, 0x89, 0x6b, 0x12, 0xf4,
0xb4, 0xf4, 0x50, 0x44, 0xad, 0xa1, 0x96, 0x5a,
0x2e, 0x2a, 0x75, 0xb5, 0x61, 0x71, 0x08, 0xa0,
0x73, 0xc0, 0xdf, 0xa6, 0xd6, 0x34, 0x0f, 0xc8,
0x3d, 0x8e, 0x67, 0x73, 0x15, 0x7d, 0x6e, 0xe7,
0xe8, 0xf9, 0x79, 0xd2, 0x26, 0x28, 0xef, 0x94,
0x06, 0x68, 0xf4, 0x41, 0xc9, 0x06, 0x3c, 0x38,
0x27, 0xb9, 0xbe, 0xf3, 0x03, 0x9f, 0x3f, 0x17,
0xa9, 0xf8, 0x3f, 0x2b, 0x98, 0x09, 0x69, 0xd2,
0x98, 0x71, 0xa8, 0xec, 0xe6, 0xdc, 0xf3, 0x38,
0xbc, 0x2f, 0x4a, 0x91, 0xe5, 0x4e, 0x1d, 0x83,
0x49, 0xb4, 0xdb, 0x1c, 0x88, 0x6f, 0x0c, 0x5d,
0xbd, 0xf4, 0x9a, 0xd3, 0xd1, 0x32, 0xd0, 0xa6,
0xf1, 0xe9, 0xb8, 0xf6, 0xfe, 0x3c, 0x09, 0x67,
0x40, 0xb5, 0x13, 0xe6, 0xd4, 0x82, 0xda, 0x67,
0x27, 0x31, 0xc6, 0xac, 0xc8, 0xf4, 0x17, 0x99,
0x2c, 0x1d, 0xf1, 0x6f, 0x1d, 0x25, 0x5f, 0x83,
0x60, 0xa9, 0xaf, 0xf1, 0x24, 0x85, 0xd8, 0x01,
0x2f, 0x61, 0x21, 0x64, 0xeb, 0xa3, 0x43, 0xb7,
0x8f, 0x55, 0x1e, 0xb6, 0xda, 0x47, 0x30, 0xb2,
0x30, 0x40, 0xd9, 0x35, 0xb7, 0x6f, 0x5e, 0x7b,
0x6f, 0x00, 0x5a, 0x08, 0xa9, 0x67, 0xa4, 0xe5,
0xe7, 0xe9, 0xe1, 0xa7, 0x5b, 0x9e, 0xbd, 0xdb,
0xd1, 0x2a, 0x48, 0xb2, 0x4f, 0xf6, 0xd5, 0xe4,
0x44, 0x4a, 0xb8, 0xd3, 0x68, 0x25, 0xf9, 0xe9,
0xb2, 0xf5, 0xcc, 0xcd, 0x81, 0xe0, 0x01, 0x0e,
0xb6, 0x1a, 0xe4, 0x23, 0xe9, 0xee, 0xb1, 0x7b,
0xca, 0xa8, 0xaa, 0x45, 0xf4, 0x14, 0xeb, 0x2d,
0x7e, 0xe4, 0x65, 0x02, 0x8e, 0xb3, 0x34, 0x6a,
0x47, 0x71, 0xd1, 0xb0, 0x8d, 0x3c, 0x0c, 0xe1,
0xde, 0x7e, 0x5f, 0xb4, 0x15, 0x2d, 0x32, 0x0a,
0x2a, 0xdb, 0x9b, 0x40, 0xba, 0xce, 0x8b, 0xf5,
0x74, 0xc1, 0x68, 0x20, 0x7c, 0x87, 0x23, 0x13,
0xc3, 0x13, 0xa7, 0xdb, 0xec, 0x59, 0xa0, 0x40,
0x9e, 0x64, 0x03, 0x60, 0xac, 0x76, 0xff, 0x01,
0x34, 0x7b, 0x32, 0x26, 0xd9, 0x41, 0x31, 0x93,
0xaa, 0x30, 0x51, 0x83, 0x85, 0x40, 0xeb, 0x4e,
0x66, 0x39, 0x83, 0xb1, 0x30, 0x0d, 0x96, 0x01,
0xee, 0x81, 0x53, 0x5e, 0xec, 0xa9, 0xc9, 0xdf,
0x7e, 0xc1, 0x09, 0x47, 0x8b, 0x35, 0xdb, 0x10,
0x15, 0xd4, 0xc7, 0x5a, 0x39, 0xe3, 0xc0, 0xf3,
0x93, 0x38, 0x11, 0xdc, 0x71, 0xbb, 0xc7, 0x62,
0x2b, 0x85, 0xad, 0x6b, 0x4f, 0x09, 0xb3, 0x31,
0xa8, 0xe5, 0xd1, 0xb3, 0xa9, 0x21, 0x37, 0x50,
0xc8, 0x7d, 0xc3, 0xd2, 0xf7, 0x00, 0xd3, 0xdb,
0x0f, 0x82, 0xf2, 0x43, 0xcf, 0x36, 0x6c, 0x98,
0x63, 0xd8, 0x1d, 0xb3, 0xf3, 0xde, 0x63, 0x79,
0x64, 0xf0, 0xdb, 0x46, 0x04, 0xe1, 0x1c, 0x57,
0x0f, 0x9e, 0x96, 0xb9, 0x93, 0x45, 0x71, 0x1c,
0x8b, 0x65, 0x7d, 0x1e, 0xad, 0xbd, 0x03, 0x51,
0xae, 0x44, 0xef, 0x97, 0x45, 0x0d, 0x8d, 0x41,
0x5c, 0x80, 0x7b, 0xe6, 0xe0, 0xbc, 0xa6, 0x72,
0x95, 0xa0, 0x97, 0xe1, 0xbb, 0xc0, 0xcc, 0xe5,
0x1e, 0xc3, 0xbe, 0xd7, 0x42, 0x2a, 0xf3, 0x75,
0x8a, 0x44, 0x67, 0x3c, 0xe5, 0x68, 0x78, 0xe5,
0x40, 0x1f, 0xf0, 0x89, 0x57, 0xda, 0xee, 0x45,
0xf4, 0x44, 0x81, 0x01, 0x77, 0xf0, 0x4a, 0x14,
0xb1, 0x3f, 0x60, 0x2b, 0xeb, 0x42, 0x38, 0xa6,
0xfb, 0xe5, 0x4d, 0x71, 0xdc, 0x7d, 0x0a, 0x72,
0x56, 0x28, 0x9d, 0xa6, 0x8e, 0x74, 0x2d, 0xbd,
0x14, 0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03,
0x03, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x56, 0x37, 0x62, 0x42, 0xb3,
0xdc, 0xa4, 0x01, 0x64, 0x7f, 0xa7, 0xcf, 0xb1,
0xa4, 0x03, 0x4c, 0xf2, 0x4c, 0xe1, 0xee, 0xd6,
0x29, 0x45, 0x71, 0x67, 0xeb, 0x3f, 0x82, 0x77,
0x65, 0x0c, 0x13,
0x00, 0x00, 0x00, 0x31, 0x4d, 0x58, 0x94, 0x0b,
0x0b, 0x06, 0x5f, 0xae, 0x57, 0x17, 0x98, 0x86,
0xaa, 0x49, 0x17, 0x7f, 0xbd, 0x41, 0x05, 0xa5,
0x74, 0x1c, 0x58, 0xc8, 0x38, 0x2d, 0x99, 0x5d,
0xe5, 0x12, 0x43,
},
{
0x14, 0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03,
0x03, 0x00, 0x28, 0xd3, 0x6b, 0x15, 0x0f, 0x23,
0xd3, 0x5b, 0x93, 0x1d, 0x39, 0x6a, 0x74, 0xd9,
0x78, 0x39, 0xf6, 0x76, 0x6d, 0x5d, 0x21, 0x98,
0x7e, 0x10, 0xa4, 0x12, 0x11, 0x55, 0x25, 0xf7,
0x6f, 0x12, 0xf1, 0x9b, 0x9f, 0xe1, 0xc0, 0xe6,
0xbd, 0x93, 0xde,
0x03, 0x00, 0x28, 0xf2, 0x60, 0xc2, 0x75, 0x27,
0x64, 0xf4, 0x05, 0x98, 0xc9, 0xd3, 0xa8, 0x00,
0x4c, 0xa0, 0x49, 0x82, 0x68, 0xf1, 0x21, 0x05,
0x7b, 0x4b, 0x25, 0x3e, 0xe1, 0x5f, 0x0f, 0x84,
0x26, 0x2d, 0x16, 0x2e, 0xc0, 0xfd, 0xdf, 0x0a,
0xf4, 0xba, 0x19,
},
{
0x17, 0x03, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0xc8, 0x95, 0x86,
0xc0, 0xd0, 0xc2, 0x24, 0x1d, 0xf4, 0x20, 0xca,
0x2b, 0x30, 0x08, 0xf1, 0xb7, 0xe3, 0x5d, 0xcf,
0x86, 0xc3, 0xc5, 0x15, 0x03, 0x03, 0x00, 0x1a,
0x00, 0x00, 0x00, 0x00, 0x01, 0x35, 0xef, 0x9d,
0x6a, 0x86, 0x98, 0xc5, 0xca, 0x55, 0xca, 0x89,
0x29, 0xb4, 0x55, 0xd4, 0x41, 0x08, 0x96, 0xe0,
0xf3, 0x39, 0xfc, 0x15, 0x03, 0x03, 0x00, 0x1a,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x20, 0x13, 0xac, 0xc4, 0x6a, 0x48, 0x36, 0x04,
0xdb, 0xae, 0x52, 0xc5, 0xc1, 0x6f, 0x4c, 0xc4,
0x0a, 0x77,
0x02, 0x63, 0x1b, 0xaa, 0xc6, 0xc9, 0x6d, 0x72,
0x24, 0x10, 0x55, 0xa9, 0x8c, 0x3b, 0x23, 0xce,
0xd8, 0x4a,
},
}

View File

@@ -136,7 +136,7 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
}
}
if rand.Intn(10) > 5 {
m.signatureAndHashes = supportedSignatureAlgorithms
m.signatureAndHashes = supportedSKXSignatureAlgorithms
}
return reflect.ValueOf(m)

View File

@@ -318,7 +318,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
}
if c.vers >= VersionTLS12 {
certReq.hasSignatureAndHash = true
certReq.signatureAndHashes = supportedSignatureAlgorithms
certReq.signatureAndHashes = supportedClientCertSignatureAlgorithms
}
// An empty list of certificateAuthorities signals to

View File

@@ -117,15 +117,47 @@ func sha256Hash(slices [][]byte) []byte {
}
// hashForServerKeyExchange hashes the given slices and returns their digest
// and the identifier of the hash function used.
func hashForServerKeyExchange(sigType uint8, version uint16, slices ...[]byte) ([]byte, crypto.Hash) {
// and the identifier of the hash function used. The hashFunc argument is only
// used for >= TLS 1.2 and precisely identifies the hash function to use.
func hashForServerKeyExchange(sigType, hashFunc uint8, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) {
if version >= VersionTLS12 {
return sha256Hash(slices), crypto.SHA256
switch hashFunc {
case hashSHA256:
return sha256Hash(slices), crypto.SHA256, nil
case hashSHA1:
return sha1Hash(slices), crypto.SHA1, nil
default:
return nil, crypto.Hash(0), errors.New("tls: unknown hash function used by peer")
}
}
if sigType == signatureECDSA {
return sha1Hash(slices), crypto.SHA1
return sha1Hash(slices), crypto.SHA1, nil
}
return md5SHA1Hash(slices), crypto.MD5SHA1
return md5SHA1Hash(slices), crypto.MD5SHA1, nil
}
// pickTLS12HashForSignature returns a TLS 1.2 hash identifier for signing a
// ServerKeyExchange given the signature type being used and the client's
// advertized list of supported signature and hash combinations.
func pickTLS12HashForSignature(sigType uint8, clientSignatureAndHashes []signatureAndHash) (uint8, error) {
if len(clientSignatureAndHashes) == 0 {
// If the client didn't specify any signature_algorithms
// extension then we can assume that it supports SHA1. See
// http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
return hashSHA1, nil
}
for _, sigAndHash := range clientSignatureAndHashes {
if sigAndHash.signature != sigType {
continue
}
switch sigAndHash.hash {
case hashSHA1, hashSHA256:
return sigAndHash.hash, nil
}
}
return 0, errors.New("tls: client doesn't support any common hash functions")
}
// ecdheRSAKeyAgreement implements a TLS key agreement where the server
@@ -181,7 +213,17 @@ Curve:
serverECDHParams[3] = byte(len(ecdhePublic))
copy(serverECDHParams[4:], ecdhePublic)
digest, hashFunc := hashForServerKeyExchange(ka.sigType, ka.version, clientHello.random, hello.random, serverECDHParams)
var tls12HashId uint8
if ka.version >= VersionTLS12 {
if tls12HashId, err = pickTLS12HashForSignature(ka.sigType, clientHello.signatureAndHashes); err != nil {
return nil, err
}
}
digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, tls12HashId, ka.version, clientHello.random, hello.random, serverECDHParams)
if err != nil {
return nil, err
}
var sig []byte
switch ka.sigType {
case signatureECDSA:
@@ -216,7 +258,7 @@ Curve:
copy(skx.key, serverECDHParams)
k := skx.key[len(serverECDHParams):]
if ka.version >= VersionTLS12 {
k[0] = hashSHA256
k[0] = tls12HashId
k[1] = ka.sigType
k = k[2:]
}
@@ -279,9 +321,16 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
if len(sig) < 2 {
return errServerKeyExchange
}
var tls12HashId uint8
if ka.version >= VersionTLS12 {
// ignore SignatureAndHashAlgorithm
sig = sig[2:]
// handle SignatureAndHashAlgorithm
var sigAndHash []uint8
sigAndHash, sig = sig[:2], sig[2:]
if sigAndHash[1] != ka.sigType {
return errServerKeyExchange
}
tls12HashId = sigAndHash[0]
if len(sig) < 2 {
return errServerKeyExchange
}
@@ -292,7 +341,10 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
}
sig = sig[2:]
digest, hashFunc := hashForServerKeyExchange(ka.sigType, ka.version, clientHello.random, serverHello.random, serverECDHParams)
digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, tls12HashId, ka.version, clientHello.random, serverHello.random, serverECDHParams)
if err != nil {
return err
}
switch ka.sigType {
case signatureECDSA:
pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey)

View File

@@ -154,14 +154,18 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
}
if len(c.PermittedDNSDomains) > 0 {
ok := false
for _, domain := range c.PermittedDNSDomains {
if opts.DNSName == domain ||
(strings.HasSuffix(opts.DNSName, domain) &&
len(opts.DNSName) >= 1+len(domain) &&
opts.DNSName[len(opts.DNSName)-len(domain)-1] == '.') {
continue
ok = true
break
}
}
if !ok {
return CertificateInvalidError{c, CANotAuthorizedForThisName}
}
}

View File

@@ -183,6 +183,24 @@ var verifyTests = []verifyTest{
{"mega.co.nz", "EssentialSSL CA", "COMODO Certification Authority"},
},
},
{
// Check that a name constrained intermediate works even when
// it lists multiple constraints.
leaf: nameConstraintsLeaf,
intermediates: []string{nameConstraintsIntermediate1, nameConstraintsIntermediate2},
roots: []string{globalSignRoot},
currentTime: 1382387896,
dnsName: "secure.iddl.vt.edu",
expectedChains: [][]string{
{
"Technology-enhanced Learning and Online Strategies",
"Virginia Tech Global Qualified Server CA",
"Trusted Root CA G2",
"GlobalSign Root CA",
},
},
},
}
func expectHostnameError(t *testing.T, i int, err error) (ok bool) {
@@ -753,3 +771,168 @@ zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
ZQ==
-----END CERTIFICATE-----`
var nameConstraintsLeaf = `-----BEGIN CERTIFICATE-----
MIIHMTCCBRmgAwIBAgIIIZaV/3ezOJkwDQYJKoZIhvcNAQEFBQAwgcsxCzAJBgNV
BAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEj
MCEGA1UECxMaR2xvYmFsIFF1YWxpZmllZCBTZXJ2ZXIgQ0ExPDA6BgNVBAoTM1Zp
cmdpbmlhIFBvbHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUgVW5pdmVyc2l0
eTExMC8GA1UEAxMoVmlyZ2luaWEgVGVjaCBHbG9iYWwgUXVhbGlmaWVkIFNlcnZl
ciBDQTAeFw0xMzA5MTkxNDM2NTVaFw0xNTA5MTkxNDM2NTVaMIHNMQswCQYDVQQG
EwJVUzERMA8GA1UECAwIVmlyZ2luaWExEzARBgNVBAcMCkJsYWNrc2J1cmcxPDA6
BgNVBAoMM1ZpcmdpbmlhIFBvbHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUg
VW5pdmVyc2l0eTE7MDkGA1UECwwyVGVjaG5vbG9neS1lbmhhbmNlZCBMZWFybmlu
ZyBhbmQgT25saW5lIFN0cmF0ZWdpZXMxGzAZBgNVBAMMEnNlY3VyZS5pZGRsLnZ0
LmVkdTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkOyPpsOK/6IuPG
WnIBlVwlHzeYf+cUlggqkLq0b0+vZbiTXgio9/VCuNQ8opSoss7J7o3ygV9to+9Y
YwJKVC5WDT/y5JWpQey0CWILymViJnpNSwnxBc8A+Q8w5NUGDd/UhtPx/U8/hqbd
WPDYj2hbOqyq8UlRhfS5pwtnv6BbCTaY11I6FhCLK7zttISyTuWCf9p9o/ggiipP
ii/5oh4dkl+r5SfuSp5GPNHlYO8lWqys5NAPoDD4fc/kuflcK7Exx7XJ+Oqu0W0/
psjEY/tES1ZgDWU/ParcxxFpFmKHbD5DXsfPOObzkVWXIY6tGMutSlE1Froy/Nn0
OZsAOrcCAwEAAaOCAhMwggIPMIG4BggrBgEFBQcBAQSBqzCBqDBYBggrBgEFBQcw
AoZMaHR0cDovL3d3dy5wa2kudnQuZWR1L2dsb2JhbHF1YWxpZmllZHNlcnZlci9j
YWNlcnQvZ2xvYmFscXVhbGlmaWVkc2VydmVyLmNydDBMBggrBgEFBQcwAYZAaHR0
cDovL3Z0Y2EtcC5lcHJvdi5zZXRpLnZ0LmVkdTo4MDgwL2VqYmNhL3B1YmxpY3dl
Yi9zdGF0dXMvb2NzcDAdBgNVHQ4EFgQUp7xbO6iHkvtZbPE4jmndmnAbSEcwDAYD
VR0TAQH/BAIwADAfBgNVHSMEGDAWgBS8YmAn1eM1SBfpS6tFatDIqHdxjDBqBgNV
HSAEYzBhMA4GDCsGAQQBtGgFAgICATAOBgwrBgEEAbRoBQICAQEwPwYMKwYBBAG0
aAUCAgMBMC8wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucGtpLnZ0LmVkdS9nbG9i
YWwvY3BzLzBKBgNVHR8EQzBBMD+gPaA7hjlodHRwOi8vd3d3LnBraS52dC5lZHUv
Z2xvYmFscXVhbGlmaWVkc2VydmVyL2NybC9jYWNybC5jcmwwDgYDVR0PAQH/BAQD
AgTwMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHREEFjAUghJz
ZWN1cmUuaWRkbC52dC5lZHUwDQYJKoZIhvcNAQEFBQADggIBAEgoYo4aUtatY3gI
OyyKp7QlIOaLbTJZywESHqy+L5EGDdJW2DJV+mcE0LDGvqa2/1Lo+AR1ntsZwfOi
Y718JwgVVaX/RCd5+QKP25c5/x72xI8hb/L1bgS0ED9b0YAhd7Qm1K1ot82+6mqX
DW6WiGeDr8Z07MQ3143qQe2rBlq+QI69DYzm2GOqAIAnUIWv7tCyLUm31b4DwmrJ
TeudVreTKUbBNB1TWRFHEPkWhjjXKZnNGRO11wHXcyBu6YekIvVZ+vmx8ePee4jJ
3GFOi7lMuWOeq57jTVL7KOKaKLVXBb6gqo5aq+Wwt8RUD5MakrCAEeQZj7DKaFmZ
oQCO0Pxrsl3InCGvxnGzT+bFVO9nJ/BAMj7hknFdm9Jr6Bg5q33Z+gnf909AD9QF
ESqUSykaHu2LVdJx2MaCH1CyKnRgMw5tEwE15EXpUjCm24m8FMOYC+rNtf18pgrz
5D8Jhh+oxK9PjcBYqXNtnioIxiMCYcV0q5d4w4BYFEh71tk7/bYB0R55CsBUVPmp
timWNOdRd57Tfpk3USaVsumWZAf9MP3wPiC7gb4d5tYEEAG5BuDT8ruFw838wU8G
1VvAVutSiYBg7k3NYO7AUqZ+Ax4klQX3aM9lgonmJ78Qt94UPtbptrfZ4/lSqEf8
GBUwDrQNTb+gsXsDkjd5lcYxNx6l
-----END CERTIFICATE-----`
var nameConstraintsIntermediate1 = `-----BEGIN CERTIFICATE-----
MIINLjCCDBagAwIBAgIRIqpyf/YoGgvHc8HiDAxAI8owDQYJKoZIhvcNAQEFBQAw
XDELMAkGA1UEBhMCQkUxFTATBgNVBAsTDFRydXN0ZWQgUm9vdDEZMBcGA1UEChMQ
R2xvYmFsU2lnbiBudi1zYTEbMBkGA1UEAxMSVHJ1c3RlZCBSb290IENBIEcyMB4X
DTEyMTIxMzAwMDAwMFoXDTE3MTIxMzAwMDAwMFowgcsxCzAJBgNVBAYTAlVTMREw
DwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEjMCEGA1UECxMa
R2xvYmFsIFF1YWxpZmllZCBTZXJ2ZXIgQ0ExPDA6BgNVBAoTM1ZpcmdpbmlhIFBv
bHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUgVW5pdmVyc2l0eTExMC8GA1UE
AxMoVmlyZ2luaWEgVGVjaCBHbG9iYWwgUXVhbGlmaWVkIFNlcnZlciBDQTCCAiIw
DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALgIZhEaptBWADBqdJ45ueFGzMXa
GHnzNxoxR1fQIaaRQNdCg4cw3A4dWKMeEgYLtsp65ai3Xfw62Qaus0+KJ3RhgV+r
ihqK81NUzkls78fJlADVDI4fCTlothsrE1CTOMiy97jKHai5mVTiWxmcxpmjv7fm
5Nhc+uHgh2hIz6npryq495mD51ZrUTIaqAQN6Pw/VHfAmR524vgriTOjtp1t4lA9
pXGWjF/vkhAKFFheOQSQ00rngo2wHgCqMla64UTN0oz70AsCYNZ3jDLx0kOP0YmM
R3Ih91VA63kLqPXA0R6yxmmhhxLZ5bcyAy1SLjr1N302MIxLM/pSy6aquEnbELhz
qyp9yGgRyGJay96QH7c4RJY6gtcoPDbldDcHI9nXngdAL4DrZkJ9OkDkJLyqG66W
ZTF5q4EIs6yMdrywz0x7QP+OXPJrjYpbeFs6tGZCFnWPFfmHCRJF8/unofYrheq+
9J7Jx3U55S/k57NXbAM1RAJOuMTlfn9Etf9Dpoac9poI4Liav6rBoUQk3N3JWqnV
HNx/NdCyJ1/6UbKMJUZsStAVglsi6lVPo289HHOE4f7iwl3SyekizVOp01wUin3y
cnbZB/rXmZbwapSxTTSBf0EIOr9i4EGfnnhCAVA9U5uLrI5OEB69IY8PNX0071s3
Z2a2fio5c8m3JkdrAgMBAAGjggh5MIIIdTAOBgNVHQ8BAf8EBAMCAQYwTAYDVR0g
BEUwQzBBBgkrBgEEAaAyATwwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xv
YmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wEgYDVR0TAQH/BAgwBgEB/wIBADCCBtAG
A1UdHgSCBscwggbDoIIGvzASghAzZGJsYWNrc2J1cmcub3JnMBiCFmFjY2VsZXJh
dGV2aXJnaW5pYS5jb20wGIIWYWNjZWxlcmF0ZXZpcmdpbmlhLm9yZzALgglhY3Zj
cC5vcmcwCYIHYmV2Lm5ldDAJggdiZXYub3JnMAuCCWNsaWdzLm9yZzAMggpjbWl3
ZWIub3JnMBeCFWVhc3Rlcm5icm9va3Ryb3V0Lm5ldDAXghVlYXN0ZXJuYnJvb2t0
cm91dC5vcmcwEYIPZWNvcnJpZG9ycy5pbmZvMBOCEWVkZ2FycmVzZWFyY2gub3Jn
MBKCEGdldC1lZHVjYXRlZC5jb20wE4IRZ2V0LWVkdWNhdGVkLmluZm8wEYIPZ2V0
ZWR1Y2F0ZWQubmV0MBKCEGdldC1lZHVjYXRlZC5uZXQwEYIPZ2V0ZWR1Y2F0ZWQu
b3JnMBKCEGdldC1lZHVjYXRlZC5vcmcwD4INaG9raWVjbHViLmNvbTAQgg5ob2tp
ZXBob3RvLmNvbTAPgg1ob2tpZXNob3AuY29tMBGCD2hva2llc3BvcnRzLmNvbTAS
ghBob2tpZXRpY2tldHMuY29tMBKCEGhvdGVscm9hbm9rZS5jb20wE4IRaHVtYW53
aWxkbGlmZS5vcmcwF4IVaW5uYXR2aXJnaW5pYXRlY2guY29tMA+CDWlzY2hwMjAx
MS5vcmcwD4INbGFuZHJlaGFiLm9yZzAggh5uYXRpb25hbHRpcmVyZXNlYXJjaGNl
bnRlci5jb20wFYITbmV0d29ya3ZpcmdpbmlhLm5ldDAMggpwZHJjdnQuY29tMBiC
FnBldGVkeWVyaXZlcmNvdXJzZS5jb20wDYILcmFkaW9pcS5vcmcwFYITcml2ZXJj
b3Vyc2Vnb2xmLmNvbTALgglzZGltaS5vcmcwEIIOc292YW1vdGlvbi5jb20wHoIc
c3VzdGFpbmFibGUtYmlvbWF0ZXJpYWxzLmNvbTAeghxzdXN0YWluYWJsZS1iaW9t
YXRlcmlhbHMub3JnMBWCE3RoaXNpc3RoZWZ1dHVyZS5jb20wGIIWdGhpcy1pcy10
aGUtZnV0dXJlLmNvbTAVghN0aGlzaXN0aGVmdXR1cmUubmV0MBiCFnRoaXMtaXMt
dGhlLWZ1dHVyZS5uZXQwCoIIdmFkcy5vcmcwDIIKdmFsZWFmLm9yZzANggt2YXRl
Y2guaW5mbzANggt2YXRlY2gubW9iaTAcghp2YXRlY2hsaWZlbG9uZ2xlYXJuaW5n
LmNvbTAcghp2YXRlY2hsaWZlbG9uZ2xlYXJuaW5nLm5ldDAcghp2YXRlY2hsaWZl
bG9uZ2xlYXJuaW5nLm9yZzAKggh2Y29tLmVkdTASghB2aXJnaW5pYXZpZXcubmV0
MDSCMnZpcmdpbmlhcG9seXRlY2huaWNpbnN0aXR1dGVhbmRzdGF0ZXVuaXZlcnNp
dHkuY29tMDWCM3ZpcmdpbmlhcG9seXRlY2huaWNpbnN0aXR1dGVhbmRzdGF0ZXVu
aXZlcnNpdHkuaW5mbzA0gjJ2aXJnaW5pYXBvbHl0ZWNobmljaW5zdGl0dXRlYW5k
c3RhdGV1bml2ZXJzaXR5Lm5ldDA0gjJ2aXJnaW5pYXBvbHl0ZWNobmljaW5zdGl0
dXRlYW5kc3RhdGV1bml2ZXJzaXR5Lm9yZzAZghd2aXJnaW5pYXB1YmxpY3JhZGlv
Lm9yZzASghB2aXJnaW5pYXRlY2guZWR1MBOCEXZpcmdpbmlhdGVjaC5tb2JpMByC
GnZpcmdpbmlhdGVjaGZvdW5kYXRpb24ub3JnMAiCBnZ0LmVkdTALggl2dGFyYy5v
cmcwDIIKdnQtYXJjLm9yZzALggl2dGNyYy5jb20wCoIIdnRpcC5vcmcwDIIKdnRs
ZWFuLm9yZzAWghR2dGtub3dsZWRnZXdvcmtzLmNvbTAYghZ2dGxpZmVsb25nbGVh
cm5pbmcuY29tMBiCFnZ0bGlmZWxvbmdsZWFybmluZy5uZXQwGIIWdnRsaWZlbG9u
Z2xlYXJuaW5nLm9yZzATghF2dHNwb3J0c21lZGlhLmNvbTALggl2dHdlaS5jb20w
D4INd2l3YXR3ZXJjLmNvbTAKggh3dnRmLm9yZzAIgQZ2dC5lZHUwd6R1MHMxCzAJ
BgNVBAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVy
ZzE8MDoGA1UEChMzVmlyZ2luaWEgUG9seXRlY2huaWMgSW5zdGl0dXRlIGFuZCBT
dGF0ZSBVbml2ZXJzaXR5MCcGA1UdJQQgMB4GCCsGAQUFBwMCBggrBgEFBQcDAQYI
KwYBBQUHAwkwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2NybC5nbG9iYWxzaWdu
LmNvbS9ncy90cnVzdHJvb3RnMi5jcmwwgYQGCCsGAQUFBwEBBHgwdjAzBggrBgEF
BQcwAYYnaHR0cDovL29jc3AyLmdsb2JhbHNpZ24uY29tL3RydXN0cm9vdGcyMD8G
CCsGAQUFBzAChjNodHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29tL2NhY2VydC90
cnVzdHJvb3RnMi5jcnQwHQYDVR0OBBYEFLxiYCfV4zVIF+lLq0Vq0Miod3GMMB8G
A1UdIwQYMBaAFBT25YsxtkWASkxt/MKHico2w5BiMA0GCSqGSIb3DQEBBQUAA4IB
AQAyJm/lOB2Er4tHXhc/+fSufSzgjohJgYfMkvG4LknkvnZ1BjliefR8tTXX49d2
SCDFWfGjqyJZwavavkl/4p3oXPG/nAMDMvxh4YAT+CfEK9HH+6ICV087kD4BLegi
+aFJMj8MMdReWCzn5sLnSR1rdse2mo2arX3Uod14SW+PGrbUmTuWNyvRbz3fVmxp
UdbGmj3laknO9YPsBGgHfv73pVVsTJkW4ZfY/7KdD/yaVv6ophpOB3coXfjl2+kd
Z4ypn2zK+cx9IL/LSewqd/7W9cD55PCUy4X9OTbEmAccwiz3LB66mQoUGfdHdkoB
jUY+v9vLQXmaVwI0AYL7g9LN
-----END CERTIFICATE-----`
var nameConstraintsIntermediate2 = `-----BEGIN CERTIFICATE-----
MIIEXTCCA0WgAwIBAgILBAAAAAABNuk6OrMwDQYJKoZIhvcNAQEFBQAwVzELMAkG
A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xMjA0MjUxMTAw
MDBaFw0yNzA0MjUxMTAwMDBaMFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVz
dGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRy
dXN0ZWQgUm9vdCBDQSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AKyuvqrtcMr7g7EuNbu4sKwxM127UsCmx1RxbxxgcArGS7rjiefpBH/w4LYrymjf
vcw1ueyMNoqLo9nJMz/ORXupb35NNfE667prQYHa+tTjl1IiKpB7QUwt3wXPuTMF
Ja1tXtjKzkqJyuJlNuPKT76HcjgNqgV1s9qG44MD5I2JvI12du8zI1bgdQ+l/KsX
kTfbGjUvhOLOlVNWVQDpL+YMIrGqgBYxy5TUNgrAcRtwpNdS2KkF5otSmMweVb5k
hoUVv3u8UxQH/WWbNhHq1RrIlg/0rBUfi/ziShYFSB7U+aLx5DxPphTFBiDquQGp
tB+FC4JvnukDStFihZCZ1R8CAwEAAaOCASMwggEfMA4GA1UdDwEB/wQEAwIBBjAP
BgNVHRMBAf8EBTADAQH/MEcGA1UdIARAMD4wPAYEVR0gADA0MDIGCCsGAQUFBwIB
FiZodHRwczovL3d3dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5LzAdBgNVHQ4E
FgQUFPblizG2RYBKTG38woeJyjbDkGIwMwYDVR0fBCwwKjAooCagJIYiaHR0cDov
L2NybC5nbG9iYWxzaWduLm5ldC9yb290LmNybDA+BggrBgEFBQcBAQQyMDAwLgYI
KwYBBQUHMAGGImh0dHA6Ly9vY3NwMi5nbG9iYWxzaWduLmNvbS9yb290cjEwHwYD
VR0jBBgwFoAUYHtmGkUNl8qJUC99BM00qP/8/UswDQYJKoZIhvcNAQEFBQADggEB
AL7IG0l+k4LkcpI+a/kvZsSRwSM4uA6zGX34e78A2oytr8RG8bJwVb8+AHMUD+Xe
2kYdh/Uj/waQXfqR0OgxQXL9Ct4ZM+JlR1avsNKXWL5AwYXAXCOB3J5PW2XOck7H
Zw0vRbGQhjWjQx+B4KOUFg1b3ov/z6Xkr3yaCfRQhXh7KC0Bc0RXPPG5Nv5lCW+z
tbbg0zMm3kyfQITRusMSg6IBsDJqOnjaiaKQRcXiD0Sk43ZXb2bUKMxC7+Td3QL4
RyHcWJbQ7YylLTS/x+jxWIcOQ0oO5/54t5PTQ14neYhOz9x4gUk2AYAW6d1vePwb
hcC8roQwkHT7HvfYBoc74FM=
-----END CERTIFICATE-----`
var globalSignRoot = `-----BEGIN CERTIFICATE-----
MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
-----END CERTIFICATE-----`

View File

@@ -140,8 +140,8 @@ type Stmt interface {
}
// ColumnConverter may be optionally implemented by Stmt if the
// the statement is aware of its own columns' types and can
// convert from any type to a driver Value.
// statement is aware of its own columns' types and can convert from
// any type to a driver Value.
type ColumnConverter interface {
// ColumnConverter returns a ValueConverter for the provided
// column index. If the type of a specific column isn't known

View File

@@ -7,6 +7,9 @@
//
// The sql package must be used in conjunction with a database driver.
// See http://golang.org/s/sqldrivers for a list of drivers.
//
// For more usage examples, see the wiki page at
// http://golang.org/s/sqlwiki.
package sql
import (
@@ -198,7 +201,7 @@ type DB struct {
connRequests *list.List // of connRequest
numOpen int
pendingOpens int
// Used to sygnal the need for new connections
// Used to signal the need for new connections
// a goroutine running connectionOpener() reads on this chan and
// maybeOpenNewConnections sends on the chan (one send per needed connection)
// It is closed during db.Close(). The close tells the connectionOpener
@@ -1634,7 +1637,16 @@ func (r *Row) Scan(dest ...interface{}) error {
// A Result summarizes an executed SQL command.
type Result interface {
// LastInsertId returns the integer generated by the database
// in response to a command. Typically this will be from an
// "auto increment" column when inserting a new row. Not all
// databases support this feature, and the syntax of such
// statements varies.
LastInsertId() (int64, error)
// RowsAffected returns the number of rows affected by an
// update, insert, or delete. Not every database or database
// driver may support this.
RowsAffected() (int64, error)
}

View File

@@ -207,7 +207,10 @@ const (
formRef8 format = 0x14
formRefUdata format = 0x15
formIndirect format = 0x16
formSecOffset format = 0x17
formExprloc format = 0x18
formFlagPresent format = 0x19
formRefSig8 format = 0x20
)
// A Tag is the classification (the type) of an Entry.

View File

@@ -188,6 +188,7 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
// flag
case formFlag:
val = b.uint8() == 1
// New in DWARF 4.
case formFlagPresent:
// The attribute is implicitly indicated as present, and no value is
// encoded in the debugging information entry itself.
@@ -236,6 +237,30 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
b.err = b1.err
return nil
}
// lineptr, loclistptr, macptr, rangelistptr
// New in DWARF 4, but clang can generate them with -gdwarf-2.
// Section reference, replacing use of formData4 and formData8.
case formSecOffset:
is64, known := b.format.dwarf64()
if !known {
b.error("unknown size for DW_FORM_sec_offset")
} else if is64 {
val = int64(b.uint64())
} else {
val = int64(b.uint32())
}
// exprloc
// New in DWARF 4.
case formExprloc:
val = b.bytes(int(b.uint()))
// reference
// New in DWARF 4.
case formRefSig8:
// 64-bit type signature.
val = b.uint64()
}
e.Field[i].Val = val
}

View File

@@ -86,13 +86,13 @@ Functions and channels will not be sent in a gob. Attempting to encode such a va
at top the level will fail. A struct field of chan or func type is treated exactly
like an unexported field and is ignored.
Gob can encode a value of any type implementing the GobEncoder,
encoding.BinaryMarshaler, or encoding.TextMarshaler interfaces by calling the
corresponding method, in that order of preference.
Gob can encode a value of any type implementing the GobEncoder or
encoding.BinaryMarshaler interfaces by calling the corresponding method,
in that order of preference.
Gob can decode a value of any type implementing the GobDecoder,
encoding.BinaryUnmarshaler, or encoding.TextUnmarshaler interfaces by calling
the corresponding method, again in that order of preference.
Gob can decode a value of any type implementing the GobDecoder or
encoding.BinaryUnmarshaler interfaces by calling the corresponding method,
again in that order of preference.
Encoding Details

View File

@@ -37,7 +37,7 @@ func (v *Vector) UnmarshalBinary(data []byte) error {
}
// This example transmits a value that implements the custom encoding and decoding methods.
func Example_gob_encode_decode() {
func Example_encodeDecode() {
var network bytes.Buffer // Stand-in for the network.
// Create an encoder and send a value.

View File

@@ -11,6 +11,7 @@ import (
"errors"
"fmt"
"io"
"net"
"strings"
"testing"
"time"
@@ -767,3 +768,17 @@ func TestGobEncodePtrError(t *testing.T) {
t.Fatalf("expected nil, got %v", err2)
}
}
func TestNetIP(t *testing.T) {
// Encoding of net.IP{1,2,3,4} in Go 1.1.
enc := []byte{0x07, 0x0a, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04}
var ip net.IP
err := NewDecoder(bytes.NewReader(enc)).Decode(&ip)
if err != nil {
t.Fatalf("decode: %v", err)
}
if ip.String() != "1.2.3.4" {
t.Errorf("decoded to %v, want 1.2.3.4", ip.String())
}
}

View File

@@ -88,18 +88,25 @@ func validUserType(rt reflect.Type) (ut *userTypeInfo, err error) {
ut.externalEnc, ut.encIndir = xGob, indir
} else if ok, indir := implementsInterface(ut.user, binaryMarshalerInterfaceType); ok {
ut.externalEnc, ut.encIndir = xBinary, indir
} else if ok, indir := implementsInterface(ut.user, textMarshalerInterfaceType); ok {
ut.externalEnc, ut.encIndir = xText, indir
}
// NOTE(rsc): Would like to allow MarshalText here, but results in incompatibility
// with older encodings for net.IP. See golang.org/issue/6760.
// } else if ok, indir := implementsInterface(ut.user, textMarshalerInterfaceType); ok {
// ut.externalEnc, ut.encIndir = xText, indir
// }
if ok, indir := implementsInterface(ut.user, gobDecoderInterfaceType); ok {
ut.externalDec, ut.decIndir = xGob, indir
} else if ok, indir := implementsInterface(ut.user, binaryUnmarshalerInterfaceType); ok {
ut.externalDec, ut.decIndir = xBinary, indir
} else if ok, indir := implementsInterface(ut.user, textUnmarshalerInterfaceType); ok {
ut.externalDec, ut.decIndir = xText, indir
}
// See note above.
// } else if ok, indir := implementsInterface(ut.user, textUnmarshalerInterfaceType); ok {
// ut.externalDec, ut.decIndir = xText, indir
// }
userTypeCache[rt] = ut
return
}

View File

@@ -53,7 +53,7 @@ import (
// Unmarshal records the attribute value in that field.
//
// * If the XML element contains character data, that data is
// accumulated in the first struct field that has tag "chardata".
// accumulated in the first struct field that has tag ",chardata".
// The struct field may have type []byte or string.
// If there is no such field, the character data is discarded.
//

View File

@@ -94,6 +94,7 @@
// - the compiler being used, either "gc" or "gccgo"
// - "cgo", if ctxt.CgoEnabled is true
// - "go1.1", from Go version 1.1 onward
// - "go1.2", from Go version 1.2 onward
// - any additional words listed in ctxt.BuildTags
//
// If a file's name, after stripping the extension and a possible _test suffix,

View File

@@ -22,6 +22,9 @@ func firstSentenceLen(s string) int {
if q == ' ' && p == '.' && (!unicode.IsUpper(pp) || unicode.IsUpper(ppp)) {
return i
}
if p == '。' || p == '' {
return i
}
ppp, pp, p = pp, p, q
}
return len(s)

View File

@@ -28,6 +28,8 @@ var tests = []struct {
{"P. Q. ", 8, "P. Q."},
{"Package Καλημέρα κόσμε.", 36, "Package Καλημέρα κόσμε."},
{"Package こんにちは 世界\n", 31, "Package こんにちは 世界"},
{"Package こんにちは。世界", 26, "Package こんにちは。"},
{"Package 안녕.世界", 17, "Package 안녕."},
{"Package foo does bar.", 21, "Package foo does bar."},
{"Copyright 2012 Google, Inc. Package foo does bar.", 27, ""},
{"All Rights reserved. Package foo does bar.", 20, ""},

View File

@@ -1,69 +0,0 @@
// Derived from Inferno's libkern/getfcr-amd64.s
// http://code.google.com/p/inferno-os/source/browse/libkern/getfcr-amd64.s
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com). All rights reserved.
// Portions Copyright 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "../../cmd/ld/textflag.h"
TEXT ·SetFPControl(SB), NOSPLIT, $8
// Set new
MOVL p+0(FP), DI
XORL $(0x3F<<7), DI
ANDL $0xFFC0, DI
WAIT
STMXCSR 0(SP)
MOVL 0(SP), AX
ANDL $~0x3F, AX
ORL DI, AX
MOVL AX, 0(SP)
LDMXCSR 0(SP)
RET
TEXT ·GetFPControl(SB), NOSPLIT, $0
WAIT
STMXCSR 0(SP)
MOVWLZX 0(SP), AX
ANDL $0xFFC0, AX
XORL $(0x3F<<7), AX
MOVL AX, ret+0(FP)
RET
TEXT ·SetFPStatus(SB), $0
MOVL p+0(FP), DI
ANDL $0x3F, DI
WAIT
STMXCSR 0(SP)
MOVL 0(SP), AX
ANDL $~0x3F, AX
ORL DI, AX
MOVL AX, 0(SP)
LDMXCSR 0(SP)
RET
TEXT ·GetFPStatus(SB), $0
WAIT
STMXCSR 0(SP)
MOVL 0(SP), AX
ANDL $0x3F, AX
MOVL AX, ret+0(FP)
RET

View File

@@ -215,26 +215,30 @@ func dialMulti(net, addr string, la Addr, ras addrList, deadline time.Time) (Con
// dialSingle attempts to establish and returns a single connection to
// the destination address.
func dialSingle(net, addr string, la, ra Addr, deadline time.Time) (Conn, error) {
func dialSingle(net, addr string, la, ra Addr, deadline time.Time) (c Conn, err error) {
if la != nil && la.Network() != ra.Network() {
return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: errors.New("mismatched local address type " + la.Network())}
}
switch ra := ra.(type) {
case *TCPAddr:
la, _ := la.(*TCPAddr)
return dialTCP(net, la, ra, deadline)
c, err = dialTCP(net, la, ra, deadline)
case *UDPAddr:
la, _ := la.(*UDPAddr)
return dialUDP(net, la, ra, deadline)
c, err = dialUDP(net, la, ra, deadline)
case *IPAddr:
la, _ := la.(*IPAddr)
return dialIP(net, la, ra, deadline)
c, err = dialIP(net, la, ra, deadline)
case *UnixAddr:
la, _ := la.(*UnixAddr)
return dialUnix(net, la, ra, deadline)
c, err = dialUnix(net, la, ra, deadline)
default:
return nil, &OpError{Op: "dial", Net: net, Addr: ra, Err: &AddrError{Err: "unexpected address type", Addr: addr}}
}
if err != nil {
return nil, err // c is non-nil interface containing nil pointer
}
return c, nil
}
// Listen announces on the local network address laddr.
@@ -246,14 +250,19 @@ func Listen(net, laddr string) (Listener, error) {
if err != nil {
return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
}
var l Listener
switch la := la.toAddr().(type) {
case *TCPAddr:
return ListenTCP(net, la)
l, err = ListenTCP(net, la)
case *UnixAddr:
return ListenUnix(net, la)
l, err = ListenUnix(net, la)
default:
return nil, &OpError{Op: "listen", Net: net, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
}
if err != nil {
return nil, err // l is non-nil interface containing nil pointer
}
return l, nil
}
// ListenPacket announces on the local network address laddr.
@@ -265,14 +274,19 @@ func ListenPacket(net, laddr string) (PacketConn, error) {
if err != nil {
return nil, &OpError{Op: "listen", Net: net, Addr: nil, Err: err}
}
var l PacketConn
switch la := la.toAddr().(type) {
case *UDPAddr:
return ListenUDP(net, la)
l, err = ListenUDP(net, la)
case *IPAddr:
return ListenIP(net, la)
l, err = ListenIP(net, la)
case *UnixAddr:
return ListenUnixgram(net, la)
l, err = ListenUnixgram(net, la)
default:
return nil, &OpError{Op: "listen", Net: net, Addr: la, Err: &AddrError{Err: "unexpected address type", Addr: laddr}}
}
if err != nil {
return nil, err // l is non-nil interface containing nil pointer
}
return l, nil
}

View File

@@ -53,6 +53,19 @@ func TestLookupStaticHost(t *testing.T) {
hostsPath = p
}
// https://code.google.com/p/go/issues/detail?id=6646
func TestSingleLineHostsFile(t *testing.T) {
p := hostsPath
hostsPath = "testdata/hosts_singleline"
ips := lookupStaticHost("odin")
if len(ips) != 1 || ips[0] != "127.0.0.2" {
t.Errorf("lookupStaticHost = %v, want %v", ips, []string{"127.0.0.2"})
}
hostsPath = p
}
func TestLookupHost(t *testing.T) {
// Can't depend on this to return anything in particular,
// but if it does return something, make sure it doesn't

View File

@@ -45,13 +45,27 @@ func (c *dumpConn) SetDeadline(t time.Time) error { return nil }
func (c *dumpConn) SetReadDeadline(t time.Time) error { return nil }
func (c *dumpConn) SetWriteDeadline(t time.Time) error { return nil }
type neverEnding byte
func (b neverEnding) Read(p []byte) (n int, err error) {
for i := range p {
p[i] = byte(b)
}
return len(p), nil
}
// DumpRequestOut is like DumpRequest but includes
// headers that the standard http.Transport adds,
// such as User-Agent.
func DumpRequestOut(req *http.Request, body bool) ([]byte, error) {
save := req.Body
dummyBody := false
if !body || req.Body == nil {
req.Body = nil
if req.ContentLength != 0 {
req.Body = ioutil.NopCloser(io.LimitReader(neverEnding('x'), req.ContentLength))
dummyBody = true
}
} else {
var err error
save, req.Body, err = drainBody(req.Body)
@@ -99,7 +113,19 @@ func DumpRequestOut(req *http.Request, body bool) ([]byte, error) {
if err != nil {
return nil, err
}
return buf.Bytes(), nil
dump := buf.Bytes()
// If we used a dummy body above, remove it now.
// TODO: if the req.ContentLength is large, we allocate memory
// unnecessarily just to slice it off here. But this is just
// a debug function, so this is acceptable for now. We could
// discard the body earlier if this matters.
if dummyBody {
if i := bytes.Index(dump, []byte("\r\n\r\n")); i >= 0 {
dump = dump[:i+4]
}
}
return dump, nil
}
// delegateReader is a reader that delegates to another reader,

View File

@@ -20,6 +20,7 @@ type dumpTest struct {
WantDump string
WantDumpOut string
NoBody bool // if true, set DumpRequest{,Out} body to false
}
var dumpTests = []dumpTest{
@@ -83,6 +84,31 @@ var dumpTests = []dumpTest{
"User-Agent: Go 1.1 package http\r\n" +
"Accept-Encoding: gzip\r\n\r\n",
},
// Request with Body, but Dump requested without it.
{
Req: http.Request{
Method: "POST",
URL: &url.URL{
Scheme: "http",
Host: "post.tld",
Path: "/",
},
ContentLength: 6,
ProtoMajor: 1,
ProtoMinor: 1,
},
Body: []byte("abcdef"),
WantDumpOut: "POST / HTTP/1.1\r\n" +
"Host: post.tld\r\n" +
"User-Agent: Go 1.1 package http\r\n" +
"Content-Length: 6\r\n" +
"Accept-Encoding: gzip\r\n\r\n",
NoBody: true,
},
}
func TestDumpRequest(t *testing.T) {
@@ -105,7 +131,7 @@ func TestDumpRequest(t *testing.T) {
if tt.WantDump != "" {
setBody()
dump, err := DumpRequest(&tt.Req, true)
dump, err := DumpRequest(&tt.Req, !tt.NoBody)
if err != nil {
t.Errorf("DumpRequest #%d: %s", i, err)
continue
@@ -118,7 +144,7 @@ func TestDumpRequest(t *testing.T) {
if tt.WantDumpOut != "" {
setBody()
dump, err := DumpRequestOut(&tt.Req, true)
dump, err := DumpRequestOut(&tt.Req, !tt.NoBody)
if err != nil {
t.Errorf("DumpRequestOut #%d: %s", i, err)
continue

View File

@@ -521,7 +521,7 @@ func isAtext(c byte, dot bool) bool {
return bytes.IndexByte(atextChars, c) >= 0
}
// isQtext returns true if c is an RFC 5322 qtest character.
// isQtext returns true if c is an RFC 5322 qtext character.
func isQtext(c byte) bool {
// Printable US-ASCII, excluding backslash or quote.
if c == '\\' || c == '"' {

View File

@@ -218,3 +218,41 @@ func TestTCPClose(t *testing.T) {
t.Fatal(err)
}
}
func TestErrorNil(t *testing.T) {
c, err := Dial("tcp", "127.0.0.1:65535")
if err == nil {
t.Fatal("Dial 127.0.0.1:65535 succeeded")
}
if c != nil {
t.Fatalf("Dial returned non-nil interface %T(%v) with err != nil", c, c)
}
// Make Listen fail by relistening on the same address.
l, err := Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal("Listen 127.0.0.1:0: %v", err)
}
defer l.Close()
l1, err := Listen("tcp", l.Addr().String())
if err == nil {
t.Fatal("second Listen %v: %v", l.Addr(), err)
}
if l1 != nil {
t.Fatalf("Listen returned non-nil interface %T(%v) with err != nil", l1, l1)
}
// Make ListenPacket fail by relistening on the same address.
lp, err := ListenPacket("udp", "127.0.0.1:0")
if err != nil {
t.Fatal("Listen 127.0.0.1:0: %v", err)
}
defer lp.Close()
lp1, err := ListenPacket("udp", lp.LocalAddr().String())
if err == nil {
t.Fatal("second Listen %v: %v", lp.LocalAddr(), err)
}
if lp1 != nil {
t.Fatalf("ListenPacket returned non-nil interface %T(%v) with err != nil", lp1, lp1)
}
}

View File

@@ -54,7 +54,7 @@ func (f *file) readLine() (s string, ok bool) {
if n >= 0 {
f.data = f.data[0 : ln+n]
}
if err == io.EOF {
if err == io.EOF || err == io.ErrUnexpectedEOF {
f.atEOF = true
}
}

1
src/pkg/net/testdata/hosts_singleline vendored Normal file
View File

@@ -0,0 +1 @@
127.0.0.2 odin

View File

@@ -574,13 +574,10 @@ func canonicalMIMEHeaderKey(a []byte) string {
// and upper case after each dash.
// (Host, User-Agent, If-Modified-Since).
// MIME headers are ASCII only, so no Unicode issues.
if a[i] == ' ' {
a[i] = '-'
upper = true
continue
}
c := a[i]
if upper && 'a' <= c && c <= 'z' {
if c == ' ' {
c = '-'
} else if upper && 'a' <= c && c <= 'z' {
c -= toLower
} else if !upper && 'A' <= c && c <= 'Z' {
c += toLower

View File

@@ -25,6 +25,10 @@ var canonicalHeaderKeyTests = []canonicalHeaderKeyTest{
{"user-agent", "User-Agent"},
{"USER-AGENT", "User-Agent"},
{"üser-agenT", "üser-Agent"}, // non-ASCII unchanged
// This caused a panic due to mishandling of a space:
{"C Ontent-Transfer-Encoding", "C-Ontent-Transfer-Encoding"},
{"foo bar", "Foo-Bar"},
}
func TestCanonicalMIMEHeaderKey(t *testing.T) {

View File

@@ -558,8 +558,8 @@ func parseQuery(m Values, query string) (err error) {
return err
}
// Encode encodes the values into ``URL encoded'' form.
// e.g. "foo=bar&bar=baz"
// Encode encodes the values into ``URL encoded'' form
// ("bar=baz&foo=quux") sorted by key.
func (v Values) Encode() string {
if v == nil {
return ""

View File

@@ -165,14 +165,11 @@ func (f *File) readdir(n int) (fi []FileInfo, err error) {
fi = make([]FileInfo, len(names))
for i, filename := range names {
fip, lerr := lstat(dirname + filename)
if lerr == nil {
fi[i] = fip
} else {
if lerr != nil {
fi[i] = &fileStat{name: filename}
if err == nil {
err = lerr
}
continue
}
fi[i] = fip
}
return fi, err
}

View File

@@ -92,8 +92,8 @@ func TestReaddirWithBadLstat(t *testing.T) {
defer func() { *LstatP = Lstat }()
dirs, err := handle.Readdir(-1)
if err != ErrInvalid {
t.Fatalf("Expected Readdir to return ErrInvalid, got %v", err)
if err != nil {
t.Fatalf("Expected Readdir to return no error, got %v", err)
}
foundfail := false
for _, dir := range dirs {

View File

@@ -255,10 +255,6 @@ runtime·MProf_Malloc(void *p, uintptr size)
uintptr stk[32];
Bucket *b;
if(m->nomemprof > 0)
return;
m->nomemprof++;
nstk = runtime·callers(1, stk, 32);
runtime·lock(&proflock);
b = stkbucket(MProf, stk, nstk, true);
@@ -266,7 +262,6 @@ runtime·MProf_Malloc(void *p, uintptr size)
b->recent_alloc_bytes += size;
setaddrbucket((uintptr)p, b);
runtime·unlock(&proflock);
m->nomemprof--;
}
// Called when freeing a profiled block.
@@ -275,10 +270,6 @@ runtime·MProf_Free(void *p, uintptr size)
{
Bucket *b;
if(m->nomemprof > 0)
return;
m->nomemprof++;
runtime·lock(&proflock);
b = getaddrbucket((uintptr)p);
if(b != nil) {
@@ -286,7 +277,6 @@ runtime·MProf_Free(void *p, uintptr size)
b->recent_free_bytes += size;
}
runtime·unlock(&proflock);
m->nomemprof--;
}
int64 runtime·blockprofilerate; // in CPU ticks

View File

@@ -8,6 +8,7 @@ import (
"bytes"
"fmt"
"hash/crc32"
"math/big"
"os/exec"
"regexp"
"runtime"
@@ -123,6 +124,10 @@ func testCPUProfile(t *testing.T, need []string, f func()) {
}
})
if len(need) == 0 {
return
}
var total uintptr
for i, name := range need {
total += have[i]
@@ -237,6 +242,26 @@ func TestGoroutineSwitch(t *testing.T) {
}
}
// Test that profiling of division operations is okay, especially on ARM. See issue 6681.
func TestMathBigDivide(t *testing.T) {
testCPUProfile(t, nil, func() {
t := time.After(5 * time.Second)
pi := new(big.Int)
for {
for i := 0; i < 100; i++ {
n := big.NewInt(2646693125139304345)
d := big.NewInt(842468587426513207)
pi.Div(n, d)
}
select {
case <-t:
return
default:
}
}
})
}
// Operating systems that are expected to fail the tests. See issue 6047.
var badOS = map[string]bool{
"darwin": true,

View File

@@ -133,7 +133,6 @@ runtime·schedinit(void)
runtime·sched.maxmcount = 10000;
runtime·precisestack = haveexperiment("precisestack");
m->nomemprof++;
runtime·mprofinit();
runtime·mallocinit();
mcommoninit(m);
@@ -163,7 +162,6 @@ runtime·schedinit(void)
procresize(procs);
mstats.enablegc = 1;
m->nomemprof--;
if(raceenabled)
g->racectx = runtime·raceinit();

View File

@@ -310,7 +310,6 @@ struct M
int32 throwing;
int32 gcing;
int32 locks;
int32 nomemprof;
int32 dying;
int32 profilehz;
int32 helpgc;

View File

@@ -255,7 +255,7 @@ runtime·newstack(void)
if(gp->stackguard0 == (uintptr)StackPreempt) {
if(gp == m->g0)
runtime·throw("runtime: preempt g0");
if(oldstatus == Grunning && m->p == nil)
if(oldstatus == Grunning && m->p == nil && m->locks == 0)
runtime·throw("runtime: g is running but p is not");
if(oldstatus == Gsyscall && m->locks == 0)
runtime·throw("runtime: stack split during syscall");

View File

@@ -84,7 +84,7 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
frame.lr = 0;
flr = nil;
} else {
if(frame.lr == 0)
if((n == 0 && frame.sp < frame.fp) || frame.lr == 0)
frame.lr = *(uintptr*)frame.sp;
flr = runtime·findfunc(frame.lr);
if(flr == nil) {

View File

@@ -364,17 +364,18 @@ func makeSingleStringReplacer(pattern string, value string) *singleStringReplace
func (r *singleStringReplacer) Replace(s string) string {
var buf []byte
i := 0
i, matched := 0, false
for {
match := r.finder.next(s[i:])
if match == -1 {
break
}
matched = true
buf = append(buf, s[i:i+match]...)
buf = append(buf, r.value...)
i += match + len(r.finder.pattern)
}
if buf == nil {
if !matched {
return s
}
buf = append(buf, s[i:]...)

View File

@@ -261,10 +261,21 @@ func TestReplacer(t *testing.T) {
testCases = append(testCases,
testCase{abcMatcher, "", ""},
testCase{abcMatcher, "ab", "ab"},
testCase{abcMatcher, "abc", "[match]"},
testCase{abcMatcher, "abcd", "[match]d"},
testCase{abcMatcher, "cabcabcdabca", "c[match][match]d[match]a"},
)
// Issue 6659 cases (more single string replacer)
noHello := NewReplacer("Hello", "")
testCases = append(testCases,
testCase{noHello, "Hello", ""},
testCase{noHello, "Hellox", "x"},
testCase{noHello, "xHello", "x"},
testCase{noHello, "xHellox", "xx"},
)
// No-arg test cases.
nop := NewReplacer()

View File

@@ -73,17 +73,19 @@
//
// Example functions without output comments are compiled but not executed.
//
// The naming convention to declare examples for a function F, a type T and
// The naming convention to declare examples for the package, a function F, a type T and
// method M on type T are:
//
// func Example() { ... }
// func ExampleF() { ... }
// func ExampleT() { ... }
// func ExampleT_M() { ... }
//
// Multiple example functions for a type/function/method may be provided by
// Multiple example functions for a package/type/function/method may be provided by
// appending a distinct suffix to the name. The suffix must start with a
// lower-case letter.
//
// func Example_suffix() { ... }
// func ExampleF_suffix() { ... }
// func ExampleT_suffix() { ... }
// func ExampleT_M_suffix() { ... }

View File

@@ -18,4 +18,7 @@ func ForceUSPacificForTesting() {
localOnce.Do(initTestingZone)
}
var ParseTimeZone = parseTimeZone
var (
ForceZipFileForTesting = forceZipFileForTesting
ParseTimeZone = parseTimeZone
)

View File

@@ -1204,11 +1204,11 @@ func ParseDuration(s string) (Duration, error) {
if err != nil {
return 0, errors.New("time: invalid duration " + orig)
}
scale := 1
scale := 1.0
for n := pl - len(s); n > 0; n-- {
scale *= 10
}
g += float64(x) / float64(scale)
g += float64(x) / scale
post = pl != len(s)
}
if !pre && !post {

View File

@@ -578,6 +578,16 @@ func TestParseInSydney(t *testing.T) {
}
}
func TestLoadLocationZipFile(t *testing.T) {
ForceZipFileForTesting(true)
defer ForceZipFileForTesting(false)
_, err := LoadLocation("Australia/Sydney")
if err != nil {
t.Fatal(err)
}
}
var rubyTests = []ParseTest{
{"RubyDate", RubyDate, "Thu Feb 04 21:00:57 -0800 2010", true, true, 1, 0},
// Ignore the time zone in the test. If it parses, it'll be OK.
@@ -1318,6 +1328,8 @@ var parseDurationTests = []struct {
{"39h9m14.425s", true, 39*Hour + 9*Minute + 14*Second + 425*Millisecond},
// large value
{"52763797000ns", true, 52763797000 * Nanosecond},
// more than 9 digits after decimal point, see http://golang.org/issue/6617
{"0.3333333333333333333h", true, 20 * Minute},
// errors
{"", false, 0},

View File

@@ -154,3 +154,7 @@ func loadLocation(name string) (*Location, error) {
}
return nil, errors.New("unknown time zone " + name)
}
func forceZipFileForTesting(zipOnly bool) {
// We only use the zip file anyway.
}

View File

@@ -32,7 +32,19 @@ var zoneDirs = []string{
"/usr/share/zoneinfo/",
"/usr/share/lib/zoneinfo/",
"/usr/lib/locale/TZ/",
runtime.GOROOT() + "/lib/time/zoneinfo/",
runtime.GOROOT() + "/lib/time/zoneinfo.zip",
}
var origZoneDirs = zoneDirs
func forceZipFileForTesting(zipOnly bool) {
zoneDirs = make([]string, len(origZoneDirs))
copy(zoneDirs, origZoneDirs)
if zipOnly {
for i := 0; i < len(zoneDirs)-1; i++ {
zoneDirs[i] = "/XXXNOEXIST"
}
}
}
func initLocal() {

View File

@@ -264,3 +264,7 @@ func loadLocation(name string) (*Location, error) {
}
return nil, errors.New("unknown time zone " + name)
}
func forceZipFileForTesting(zipOnly bool) {
// We only use the zip file anyway.
}

View File

@@ -13,17 +13,13 @@ import (
"fmt"
"math"
"time"
"syscall"
)
func main() {
// Test that NaNs in maps don't go quadratic.
t := func(n int) time.Duration {
var u0 syscall.Rusage
if err := syscall.Getrusage(0, &u0); err != nil {
panic(err)
}
t1 := time.Now()
m := map[float64]int{}
nan := math.NaN()
for i := 0; i < n; i++ {
@@ -32,11 +28,7 @@ func main() {
if len(m) != n {
panic("wrong size map after nan insertion")
}
var u1 syscall.Rusage
if err := syscall.Getrusage(0, &u1); err != nil {
panic(err)
}
return time.Duration(u1.Utime.Nano() - u0.Utime.Nano())
return time.Since(t1)
}
// Depending on the machine and OS, this test might be too fast