mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.boringcrypto] all: merge master (nearly Go 1.10 beta 1) into dev.boringcrypto
This is a git merge of master into dev.boringcrypto. The branch was previously based on release-branch.go1.9, so there are a handful of spurious conflicts that would also arise if trying to merge master into release-branch.go1.9 (which we never do). Those have all been resolved by taking the original file from master, discarding any Go 1.9-specific edits. all.bash passes on darwin/amd64, which is to say without actually using BoringCrypto. Go 1.10-related fixes to BoringCrypto itself will be in a followup CL. This CL is just the merge. Change-Id: I4c97711fec0fb86761913dcde28d25c001246c35
This commit is contained in:
commit
185e6094fd
1928 changed files with 201870 additions and 56156 deletions
3
.github/CODE_OF_CONDUCT.md
vendored
Normal file
3
.github/CODE_OF_CONDUCT.md
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Code of Conduct
|
||||||
|
|
||||||
|
Please read the [Go Community Code of Conduct](https://golang.org/conduct).
|
||||||
5
.github/ISSUE_TEMPLATE
vendored
5
.github/ISSUE_TEMPLATE
vendored
|
|
@ -1,8 +1,12 @@
|
||||||
Please answer these questions before submitting your issue. Thanks!
|
Please answer these questions before submitting your issue. Thanks!
|
||||||
|
|
||||||
|
|
||||||
### What version of Go are you using (`go version`)?
|
### What version of Go are you using (`go version`)?
|
||||||
|
|
||||||
|
|
||||||
|
### Does this issue reproduce with the latest release?
|
||||||
|
|
||||||
|
|
||||||
### What operating system and processor architecture are you using (`go env`)?
|
### What operating system and processor architecture are you using (`go env`)?
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -18,4 +22,3 @@ A link on play.golang.org is best.
|
||||||
|
|
||||||
### What did you see instead?
|
### What did you see instead?
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -31,6 +31,7 @@ _testmain.go
|
||||||
/pkg/
|
/pkg/
|
||||||
/src/*.*/
|
/src/*.*/
|
||||||
/src/cmd/cgo/zdefaultcc.go
|
/src/cmd/cgo/zdefaultcc.go
|
||||||
|
/src/cmd/dist/dist
|
||||||
/src/cmd/go/internal/cfg/zdefaultcc.go
|
/src/cmd/go/internal/cfg/zdefaultcc.go
|
||||||
/src/cmd/go/internal/cfg/zosarch.go
|
/src/cmd/go/internal/cfg/zosarch.go
|
||||||
/src/cmd/internal/objabi/zbootstrap.go
|
/src/cmd/internal/objabi/zbootstrap.go
|
||||||
|
|
@ -43,3 +44,8 @@ _testmain.go
|
||||||
/test/pass.out
|
/test/pass.out
|
||||||
/test/run.out
|
/test/run.out
|
||||||
/test/times.out
|
/test/times.out
|
||||||
|
|
||||||
|
# This file includes artifacts of Go build that should not be checked in.
|
||||||
|
# For files created by specific development environment (e.g. editor),
|
||||||
|
# use alternative ways to exclude files from git.
|
||||||
|
# For example, set up .git/info/exclude or use a global .gitignore.
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
pkg encoding/json, method (*RawMessage) MarshalJSON() ([]uint8, error)
|
pkg encoding/json, method (*RawMessage) MarshalJSON() ([]uint8, error)
|
||||||
|
pkg math/big, const MaxBase = 36
|
||||||
pkg math/big, type Word uintptr
|
pkg math/big, type Word uintptr
|
||||||
pkg net, func ListenUnixgram(string, *UnixAddr) (*UDPConn, error)
|
pkg net, func ListenUnixgram(string, *UnixAddr) (*UDPConn, error)
|
||||||
pkg os (linux-arm), const O_SYNC = 4096
|
pkg os (linux-arm), const O_SYNC = 4096
|
||||||
|
|
@ -343,3 +344,4 @@ pkg syscall (openbsd-386), const SYS_KILL = 37
|
||||||
pkg syscall (openbsd-386-cgo), const SYS_KILL = 37
|
pkg syscall (openbsd-386-cgo), const SYS_KILL = 37
|
||||||
pkg syscall (openbsd-amd64), const SYS_KILL = 37
|
pkg syscall (openbsd-amd64), const SYS_KILL = 37
|
||||||
pkg syscall (openbsd-amd64-cgo), const SYS_KILL = 37
|
pkg syscall (openbsd-amd64-cgo), const SYS_KILL = 37
|
||||||
|
pkg unicode, const Version = "9.0.0"
|
||||||
|
|
|
||||||
641
api/next.txt
641
api/next.txt
|
|
@ -0,0 +1,641 @@
|
||||||
|
pkg archive/tar, const FormatGNU = 8
|
||||||
|
pkg archive/tar, const FormatGNU Format
|
||||||
|
pkg archive/tar, const FormatPAX = 4
|
||||||
|
pkg archive/tar, const FormatPAX Format
|
||||||
|
pkg archive/tar, const FormatUSTAR = 2
|
||||||
|
pkg archive/tar, const FormatUSTAR Format
|
||||||
|
pkg archive/tar, const FormatUnknown = 0
|
||||||
|
pkg archive/tar, const FormatUnknown Format
|
||||||
|
pkg archive/tar, method (*Header) DetectSparseHoles(*os.File) error
|
||||||
|
pkg archive/tar, method (*Header) PunchSparseHoles(*os.File) error
|
||||||
|
pkg archive/tar, method (*Reader) WriteTo(io.Writer) (int64, error)
|
||||||
|
pkg archive/tar, method (*Writer) ReadFrom(io.Reader) (int64, error)
|
||||||
|
pkg archive/tar, method (Format) String() string
|
||||||
|
pkg archive/tar, type Format int
|
||||||
|
pkg archive/tar, type Header struct, Format Format
|
||||||
|
pkg archive/tar, type Header struct, PAXRecords map[string]string
|
||||||
|
pkg archive/tar, type Header struct, SparseHoles []SparseEntry
|
||||||
|
pkg archive/tar, type SparseEntry struct
|
||||||
|
pkg archive/tar, type SparseEntry struct, Length int64
|
||||||
|
pkg archive/tar, type SparseEntry struct, Offset int64
|
||||||
|
pkg archive/zip, type FileHeader struct, Modified time.Time
|
||||||
|
pkg archive/zip, type FileHeader struct, NonUTF8 bool
|
||||||
|
pkg archive/zip, type Writer struct, Comment string
|
||||||
|
pkg bufio, method (*Reader) Size() int
|
||||||
|
pkg bufio, method (*Writer) Size() int
|
||||||
|
pkg crypto/tls, const ECDSAWithSHA1 = 515
|
||||||
|
pkg crypto/tls, const ECDSAWithSHA1 SignatureScheme
|
||||||
|
pkg crypto/x509, const CANotAuthorizedForExtKeyUsage = 9
|
||||||
|
pkg crypto/x509, const CANotAuthorizedForExtKeyUsage InvalidReason
|
||||||
|
pkg crypto/x509, const NameConstraintsWithoutSANs = 6
|
||||||
|
pkg crypto/x509, const NameConstraintsWithoutSANs InvalidReason
|
||||||
|
pkg crypto/x509, const TooManyConstraints = 8
|
||||||
|
pkg crypto/x509, const TooManyConstraints InvalidReason
|
||||||
|
pkg crypto/x509, const UnconstrainedName = 7
|
||||||
|
pkg crypto/x509, const UnconstrainedName InvalidReason
|
||||||
|
pkg crypto/x509, func MarshalPKCS8PrivateKey(interface{}) ([]uint8, error)
|
||||||
|
pkg crypto/x509, method (PublicKeyAlgorithm) String() string
|
||||||
|
pkg crypto/x509, type Certificate struct, ExcludedEmailAddresses []string
|
||||||
|
pkg crypto/x509, type Certificate struct, ExcludedIPRanges []*net.IPNet
|
||||||
|
pkg crypto/x509, type Certificate struct, ExcludedURIDomains []string
|
||||||
|
pkg crypto/x509, type Certificate struct, PermittedEmailAddresses []string
|
||||||
|
pkg crypto/x509, type Certificate struct, PermittedIPRanges []*net.IPNet
|
||||||
|
pkg crypto/x509, type Certificate struct, PermittedURIDomains []string
|
||||||
|
pkg crypto/x509, type Certificate struct, URIs []*url.URL
|
||||||
|
pkg crypto/x509, type CertificateInvalidError struct, Detail string
|
||||||
|
pkg crypto/x509, type CertificateRequest struct, URIs []*url.URL
|
||||||
|
pkg crypto/x509, type VerifyOptions struct, MaxConstraintComparisions int
|
||||||
|
pkg crypto/x509/pkix, method (Name) String() string
|
||||||
|
pkg crypto/x509/pkix, method (RDNSequence) String() string
|
||||||
|
pkg database/sql, func OpenDB(driver.Connector) *DB
|
||||||
|
pkg database/sql/driver, type Connector interface { Connect, Driver }
|
||||||
|
pkg database/sql/driver, type Connector interface, Connect(context.Context) (Conn, error)
|
||||||
|
pkg database/sql/driver, type Connector interface, Driver() Driver
|
||||||
|
pkg database/sql/driver, type SessionResetter interface { ResetSession }
|
||||||
|
pkg database/sql/driver, type SessionResetter interface, ResetSession(context.Context) error
|
||||||
|
pkg debug/elf, const R_386_16 = 20
|
||||||
|
pkg debug/elf, const R_386_16 R_386
|
||||||
|
pkg debug/elf, const R_386_32PLT = 11
|
||||||
|
pkg debug/elf, const R_386_32PLT R_386
|
||||||
|
pkg debug/elf, const R_386_8 = 22
|
||||||
|
pkg debug/elf, const R_386_8 R_386
|
||||||
|
pkg debug/elf, const R_386_GOT32X = 43
|
||||||
|
pkg debug/elf, const R_386_GOT32X R_386
|
||||||
|
pkg debug/elf, const R_386_IRELATIVE = 42
|
||||||
|
pkg debug/elf, const R_386_IRELATIVE R_386
|
||||||
|
pkg debug/elf, const R_386_PC16 = 21
|
||||||
|
pkg debug/elf, const R_386_PC16 R_386
|
||||||
|
pkg debug/elf, const R_386_PC8 = 23
|
||||||
|
pkg debug/elf, const R_386_PC8 R_386
|
||||||
|
pkg debug/elf, const R_386_SIZE32 = 38
|
||||||
|
pkg debug/elf, const R_386_SIZE32 R_386
|
||||||
|
pkg debug/elf, const R_386_TLS_DESC = 41
|
||||||
|
pkg debug/elf, const R_386_TLS_DESC R_386
|
||||||
|
pkg debug/elf, const R_386_TLS_DESC_CALL = 40
|
||||||
|
pkg debug/elf, const R_386_TLS_DESC_CALL R_386
|
||||||
|
pkg debug/elf, const R_386_TLS_GOTDESC = 39
|
||||||
|
pkg debug/elf, const R_386_TLS_GOTDESC R_386
|
||||||
|
pkg debug/elf, const R_AARCH64_LD64_GOTOFF_LO15 = 310
|
||||||
|
pkg debug/elf, const R_AARCH64_LD64_GOTOFF_LO15 R_AARCH64
|
||||||
|
pkg debug/elf, const R_AARCH64_LD64_GOTPAGE_LO15 = 313
|
||||||
|
pkg debug/elf, const R_AARCH64_LD64_GOTPAGE_LO15 R_AARCH64
|
||||||
|
pkg debug/elf, const R_AARCH64_TLSGD_ADR_PREL21 = 512
|
||||||
|
pkg debug/elf, const R_AARCH64_TLSGD_ADR_PREL21 R_AARCH64
|
||||||
|
pkg debug/elf, const R_AARCH64_TLSGD_MOVW_G0_NC = 516
|
||||||
|
pkg debug/elf, const R_AARCH64_TLSGD_MOVW_G0_NC R_AARCH64
|
||||||
|
pkg debug/elf, const R_AARCH64_TLSGD_MOVW_G1 = 515
|
||||||
|
pkg debug/elf, const R_AARCH64_TLSGD_MOVW_G1 R_AARCH64
|
||||||
|
pkg debug/elf, const R_AARCH64_TLSLD_ADR_PAGE21 = 518
|
||||||
|
pkg debug/elf, const R_AARCH64_TLSLD_ADR_PAGE21 R_AARCH64
|
||||||
|
pkg debug/elf, const R_AARCH64_TLSLD_ADR_PREL21 = 517
|
||||||
|
pkg debug/elf, const R_AARCH64_TLSLD_ADR_PREL21 R_AARCH64
|
||||||
|
pkg debug/elf, const R_AARCH64_TLSLD_LDST128_DTPREL_LO12 = 572
|
||||||
|
pkg debug/elf, const R_AARCH64_TLSLD_LDST128_DTPREL_LO12 R_AARCH64
|
||||||
|
pkg debug/elf, const R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC = 573
|
||||||
|
pkg debug/elf, const R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC R_AARCH64
|
||||||
|
pkg debug/elf, const R_AARCH64_TLSLE_LDST128_TPREL_LO12 = 570
|
||||||
|
pkg debug/elf, const R_AARCH64_TLSLE_LDST128_TPREL_LO12 R_AARCH64
|
||||||
|
pkg debug/elf, const R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC = 571
|
||||||
|
pkg debug/elf, const R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC R_AARCH64
|
||||||
|
pkg debug/elf, const R_ARM_ABS32_NOI = 55
|
||||||
|
pkg debug/elf, const R_ARM_ABS32_NOI R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_ALU_PCREL_15_8 = 33
|
||||||
|
pkg debug/elf, const R_ARM_ALU_PCREL_15_8 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_ALU_PCREL_23_15 = 34
|
||||||
|
pkg debug/elf, const R_ARM_ALU_PCREL_23_15 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_ALU_PCREL_7_0 = 32
|
||||||
|
pkg debug/elf, const R_ARM_ALU_PCREL_7_0 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_ALU_PC_G0 = 58
|
||||||
|
pkg debug/elf, const R_ARM_ALU_PC_G0 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_ALU_PC_G0_NC = 57
|
||||||
|
pkg debug/elf, const R_ARM_ALU_PC_G0_NC R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_ALU_PC_G1 = 60
|
||||||
|
pkg debug/elf, const R_ARM_ALU_PC_G1 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_ALU_PC_G1_NC = 59
|
||||||
|
pkg debug/elf, const R_ARM_ALU_PC_G1_NC R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_ALU_PC_G2 = 61
|
||||||
|
pkg debug/elf, const R_ARM_ALU_PC_G2 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_ALU_SBREL_19_12_NC = 36
|
||||||
|
pkg debug/elf, const R_ARM_ALU_SBREL_19_12_NC R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_ALU_SBREL_27_20_CK = 37
|
||||||
|
pkg debug/elf, const R_ARM_ALU_SBREL_27_20_CK R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_ALU_SB_G0 = 71
|
||||||
|
pkg debug/elf, const R_ARM_ALU_SB_G0 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_ALU_SB_G0_NC = 70
|
||||||
|
pkg debug/elf, const R_ARM_ALU_SB_G0_NC R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_ALU_SB_G1 = 73
|
||||||
|
pkg debug/elf, const R_ARM_ALU_SB_G1 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_ALU_SB_G1_NC = 72
|
||||||
|
pkg debug/elf, const R_ARM_ALU_SB_G1_NC R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_ALU_SB_G2 = 74
|
||||||
|
pkg debug/elf, const R_ARM_ALU_SB_G2 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_BASE_ABS = 31
|
||||||
|
pkg debug/elf, const R_ARM_BASE_ABS R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_CALL = 28
|
||||||
|
pkg debug/elf, const R_ARM_CALL R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_GOTOFF12 = 98
|
||||||
|
pkg debug/elf, const R_ARM_GOTOFF12 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_GOTRELAX = 99
|
||||||
|
pkg debug/elf, const R_ARM_GOTRELAX R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_GOT_ABS = 95
|
||||||
|
pkg debug/elf, const R_ARM_GOT_ABS R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_GOT_BREL12 = 97
|
||||||
|
pkg debug/elf, const R_ARM_GOT_BREL12 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_GOT_PREL = 96
|
||||||
|
pkg debug/elf, const R_ARM_GOT_PREL R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_IRELATIVE = 160
|
||||||
|
pkg debug/elf, const R_ARM_IRELATIVE R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_JUMP24 = 29
|
||||||
|
pkg debug/elf, const R_ARM_JUMP24 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_LDC_PC_G0 = 67
|
||||||
|
pkg debug/elf, const R_ARM_LDC_PC_G0 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_LDC_PC_G1 = 68
|
||||||
|
pkg debug/elf, const R_ARM_LDC_PC_G1 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_LDC_PC_G2 = 69
|
||||||
|
pkg debug/elf, const R_ARM_LDC_PC_G2 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_LDC_SB_G0 = 81
|
||||||
|
pkg debug/elf, const R_ARM_LDC_SB_G0 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_LDC_SB_G1 = 82
|
||||||
|
pkg debug/elf, const R_ARM_LDC_SB_G1 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_LDC_SB_G2 = 83
|
||||||
|
pkg debug/elf, const R_ARM_LDC_SB_G2 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_LDRS_PC_G0 = 64
|
||||||
|
pkg debug/elf, const R_ARM_LDRS_PC_G0 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_LDRS_PC_G1 = 65
|
||||||
|
pkg debug/elf, const R_ARM_LDRS_PC_G1 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_LDRS_PC_G2 = 66
|
||||||
|
pkg debug/elf, const R_ARM_LDRS_PC_G2 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_LDRS_SB_G0 = 78
|
||||||
|
pkg debug/elf, const R_ARM_LDRS_SB_G0 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_LDRS_SB_G1 = 79
|
||||||
|
pkg debug/elf, const R_ARM_LDRS_SB_G1 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_LDRS_SB_G2 = 80
|
||||||
|
pkg debug/elf, const R_ARM_LDRS_SB_G2 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_LDR_PC_G1 = 62
|
||||||
|
pkg debug/elf, const R_ARM_LDR_PC_G1 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_LDR_PC_G2 = 63
|
||||||
|
pkg debug/elf, const R_ARM_LDR_PC_G2 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_LDR_SBREL_11_10_NC = 35
|
||||||
|
pkg debug/elf, const R_ARM_LDR_SBREL_11_10_NC R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_LDR_SB_G0 = 75
|
||||||
|
pkg debug/elf, const R_ARM_LDR_SB_G0 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_LDR_SB_G1 = 76
|
||||||
|
pkg debug/elf, const R_ARM_LDR_SB_G1 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_LDR_SB_G2 = 77
|
||||||
|
pkg debug/elf, const R_ARM_LDR_SB_G2 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_ME_TOO = 128
|
||||||
|
pkg debug/elf, const R_ARM_ME_TOO R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_MOVT_ABS = 44
|
||||||
|
pkg debug/elf, const R_ARM_MOVT_ABS R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_MOVT_BREL = 85
|
||||||
|
pkg debug/elf, const R_ARM_MOVT_BREL R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_MOVT_PREL = 46
|
||||||
|
pkg debug/elf, const R_ARM_MOVT_PREL R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_MOVW_ABS_NC = 43
|
||||||
|
pkg debug/elf, const R_ARM_MOVW_ABS_NC R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_MOVW_BREL = 86
|
||||||
|
pkg debug/elf, const R_ARM_MOVW_BREL R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_MOVW_BREL_NC = 84
|
||||||
|
pkg debug/elf, const R_ARM_MOVW_BREL_NC R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_MOVW_PREL_NC = 45
|
||||||
|
pkg debug/elf, const R_ARM_MOVW_PREL_NC R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_PLT32_ABS = 94
|
||||||
|
pkg debug/elf, const R_ARM_PLT32_ABS R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_PREL31 = 42
|
||||||
|
pkg debug/elf, const R_ARM_PREL31 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_0 = 112
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_0 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_1 = 113
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_1 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_10 = 122
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_10 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_11 = 123
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_11 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_12 = 124
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_12 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_13 = 125
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_13 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_14 = 126
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_14 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_15 = 127
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_15 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_2 = 114
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_2 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_3 = 115
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_3 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_4 = 116
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_4 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_5 = 117
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_5 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_6 = 118
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_6 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_7 = 119
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_7 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_8 = 120
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_8 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_9 = 121
|
||||||
|
pkg debug/elf, const R_ARM_PRIVATE_9 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_REL32_NOI = 56
|
||||||
|
pkg debug/elf, const R_ARM_REL32_NOI R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_RXPC25 = 249
|
||||||
|
pkg debug/elf, const R_ARM_RXPC25 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_SBREL31 = 39
|
||||||
|
pkg debug/elf, const R_ARM_SBREL31 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_TARGET1 = 38
|
||||||
|
pkg debug/elf, const R_ARM_TARGET1 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_TARGET2 = 41
|
||||||
|
pkg debug/elf, const R_ARM_TARGET2 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_ALU_ABS_G0_NC = 132
|
||||||
|
pkg debug/elf, const R_ARM_THM_ALU_ABS_G0_NC R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_ALU_ABS_G1_NC = 133
|
||||||
|
pkg debug/elf, const R_ARM_THM_ALU_ABS_G1_NC R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_ALU_ABS_G2_NC = 134
|
||||||
|
pkg debug/elf, const R_ARM_THM_ALU_ABS_G2_NC R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_ALU_ABS_G3 = 135
|
||||||
|
pkg debug/elf, const R_ARM_THM_ALU_ABS_G3 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_ALU_PREL_11_0 = 53
|
||||||
|
pkg debug/elf, const R_ARM_THM_ALU_PREL_11_0 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_GOT_BREL12 = 131
|
||||||
|
pkg debug/elf, const R_ARM_THM_GOT_BREL12 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_JUMP11 = 102
|
||||||
|
pkg debug/elf, const R_ARM_THM_JUMP11 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_JUMP19 = 51
|
||||||
|
pkg debug/elf, const R_ARM_THM_JUMP19 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_JUMP24 = 30
|
||||||
|
pkg debug/elf, const R_ARM_THM_JUMP24 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_JUMP6 = 52
|
||||||
|
pkg debug/elf, const R_ARM_THM_JUMP6 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_JUMP8 = 103
|
||||||
|
pkg debug/elf, const R_ARM_THM_JUMP8 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_MOVT_ABS = 48
|
||||||
|
pkg debug/elf, const R_ARM_THM_MOVT_ABS R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_MOVT_BREL = 88
|
||||||
|
pkg debug/elf, const R_ARM_THM_MOVT_BREL R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_MOVT_PREL = 50
|
||||||
|
pkg debug/elf, const R_ARM_THM_MOVT_PREL R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_MOVW_ABS_NC = 47
|
||||||
|
pkg debug/elf, const R_ARM_THM_MOVW_ABS_NC R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_MOVW_BREL = 89
|
||||||
|
pkg debug/elf, const R_ARM_THM_MOVW_BREL R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_MOVW_BREL_NC = 87
|
||||||
|
pkg debug/elf, const R_ARM_THM_MOVW_BREL_NC R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_MOVW_PREL_NC = 49
|
||||||
|
pkg debug/elf, const R_ARM_THM_MOVW_PREL_NC R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_PC12 = 54
|
||||||
|
pkg debug/elf, const R_ARM_THM_PC12 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_TLS_CALL = 93
|
||||||
|
pkg debug/elf, const R_ARM_THM_TLS_CALL R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_TLS_DESCSEQ16 = 129
|
||||||
|
pkg debug/elf, const R_ARM_THM_TLS_DESCSEQ16 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_THM_TLS_DESCSEQ32 = 130
|
||||||
|
pkg debug/elf, const R_ARM_THM_TLS_DESCSEQ32 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_TLS_CALL = 91
|
||||||
|
pkg debug/elf, const R_ARM_TLS_CALL R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_TLS_DESCSEQ = 92
|
||||||
|
pkg debug/elf, const R_ARM_TLS_DESCSEQ R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_TLS_DTPMOD32 = 17
|
||||||
|
pkg debug/elf, const R_ARM_TLS_DTPMOD32 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_TLS_DTPOFF32 = 18
|
||||||
|
pkg debug/elf, const R_ARM_TLS_DTPOFF32 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_TLS_GD32 = 104
|
||||||
|
pkg debug/elf, const R_ARM_TLS_GD32 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_TLS_GOTDESC = 90
|
||||||
|
pkg debug/elf, const R_ARM_TLS_GOTDESC R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_TLS_IE12GP = 111
|
||||||
|
pkg debug/elf, const R_ARM_TLS_IE12GP R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_TLS_IE32 = 107
|
||||||
|
pkg debug/elf, const R_ARM_TLS_IE32 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_TLS_LDM32 = 105
|
||||||
|
pkg debug/elf, const R_ARM_TLS_LDM32 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_TLS_LDO12 = 109
|
||||||
|
pkg debug/elf, const R_ARM_TLS_LDO12 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_TLS_LDO32 = 106
|
||||||
|
pkg debug/elf, const R_ARM_TLS_LDO32 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_TLS_LE12 = 110
|
||||||
|
pkg debug/elf, const R_ARM_TLS_LE12 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_TLS_LE32 = 108
|
||||||
|
pkg debug/elf, const R_ARM_TLS_LE32 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_TLS_TPOFF32 = 19
|
||||||
|
pkg debug/elf, const R_ARM_TLS_TPOFF32 R_ARM
|
||||||
|
pkg debug/elf, const R_ARM_V4BX = 40
|
||||||
|
pkg debug/elf, const R_ARM_V4BX R_ARM
|
||||||
|
pkg debug/elf, const R_PPC64_ADDR16_HIGH = 110
|
||||||
|
pkg debug/elf, const R_PPC64_ADDR16_HIGH R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_ADDR16_HIGHA = 111
|
||||||
|
pkg debug/elf, const R_PPC64_ADDR16_HIGHA R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_ADDR64_LOCAL = 117
|
||||||
|
pkg debug/elf, const R_PPC64_ADDR64_LOCAL R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_DTPREL16_HIGH = 114
|
||||||
|
pkg debug/elf, const R_PPC64_DTPREL16_HIGH R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_DTPREL16_HIGHA = 115
|
||||||
|
pkg debug/elf, const R_PPC64_DTPREL16_HIGHA R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_ENTRY = 118
|
||||||
|
pkg debug/elf, const R_PPC64_ENTRY R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_IRELATIVE = 248
|
||||||
|
pkg debug/elf, const R_PPC64_IRELATIVE R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_JMP_IREL = 247
|
||||||
|
pkg debug/elf, const R_PPC64_JMP_IREL R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_PLT16_LO_DS = 60
|
||||||
|
pkg debug/elf, const R_PPC64_PLT16_LO_DS R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_PLTGOT16 = 52
|
||||||
|
pkg debug/elf, const R_PPC64_PLTGOT16 R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_PLTGOT16_DS = 65
|
||||||
|
pkg debug/elf, const R_PPC64_PLTGOT16_DS R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_PLTGOT16_HA = 55
|
||||||
|
pkg debug/elf, const R_PPC64_PLTGOT16_HA R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_PLTGOT16_HI = 54
|
||||||
|
pkg debug/elf, const R_PPC64_PLTGOT16_HI R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_PLTGOT16_LO = 53
|
||||||
|
pkg debug/elf, const R_PPC64_PLTGOT16_LO R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_PLTGOT_LO_DS = 66
|
||||||
|
pkg debug/elf, const R_PPC64_PLTGOT_LO_DS R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_REL16DX_HA = 246
|
||||||
|
pkg debug/elf, const R_PPC64_REL16DX_HA R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_REL24_NOTOC = 116
|
||||||
|
pkg debug/elf, const R_PPC64_REL24_NOTOC R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_SECTOFF_DS = 61
|
||||||
|
pkg debug/elf, const R_PPC64_SECTOFF_DS R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_SECTOFF_LO_DS = 61
|
||||||
|
pkg debug/elf, const R_PPC64_SECTOFF_LO_DS R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_TOCSAVE = 109
|
||||||
|
pkg debug/elf, const R_PPC64_TOCSAVE R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_TPREL16_HIGH = 112
|
||||||
|
pkg debug/elf, const R_PPC64_TPREL16_HIGH R_PPC64
|
||||||
|
pkg debug/elf, const R_PPC64_TPREL16_HIGHA = 113
|
||||||
|
pkg debug/elf, const R_PPC64_TPREL16_HIGHA R_PPC64
|
||||||
|
pkg debug/elf, const R_X86_64_GOT64 = 27
|
||||||
|
pkg debug/elf, const R_X86_64_GOT64 R_X86_64
|
||||||
|
pkg debug/elf, const R_X86_64_GOTOFF64 = 25
|
||||||
|
pkg debug/elf, const R_X86_64_GOTOFF64 R_X86_64
|
||||||
|
pkg debug/elf, const R_X86_64_GOTPC32 = 26
|
||||||
|
pkg debug/elf, const R_X86_64_GOTPC32 R_X86_64
|
||||||
|
pkg debug/elf, const R_X86_64_GOTPC32_TLSDESC = 34
|
||||||
|
pkg debug/elf, const R_X86_64_GOTPC32_TLSDESC R_X86_64
|
||||||
|
pkg debug/elf, const R_X86_64_GOTPC64 = 29
|
||||||
|
pkg debug/elf, const R_X86_64_GOTPC64 R_X86_64
|
||||||
|
pkg debug/elf, const R_X86_64_GOTPCREL64 = 28
|
||||||
|
pkg debug/elf, const R_X86_64_GOTPCREL64 R_X86_64
|
||||||
|
pkg debug/elf, const R_X86_64_GOTPCRELX = 41
|
||||||
|
pkg debug/elf, const R_X86_64_GOTPCRELX R_X86_64
|
||||||
|
pkg debug/elf, const R_X86_64_GOTPLT64 = 30
|
||||||
|
pkg debug/elf, const R_X86_64_GOTPLT64 R_X86_64
|
||||||
|
pkg debug/elf, const R_X86_64_IRELATIVE = 37
|
||||||
|
pkg debug/elf, const R_X86_64_IRELATIVE R_X86_64
|
||||||
|
pkg debug/elf, const R_X86_64_PC32_BND = 39
|
||||||
|
pkg debug/elf, const R_X86_64_PC32_BND R_X86_64
|
||||||
|
pkg debug/elf, const R_X86_64_PC64 = 24
|
||||||
|
pkg debug/elf, const R_X86_64_PC64 R_X86_64
|
||||||
|
pkg debug/elf, const R_X86_64_PLT32_BND = 40
|
||||||
|
pkg debug/elf, const R_X86_64_PLT32_BND R_X86_64
|
||||||
|
pkg debug/elf, const R_X86_64_PLTOFF64 = 31
|
||||||
|
pkg debug/elf, const R_X86_64_PLTOFF64 R_X86_64
|
||||||
|
pkg debug/elf, const R_X86_64_RELATIVE64 = 38
|
||||||
|
pkg debug/elf, const R_X86_64_RELATIVE64 R_X86_64
|
||||||
|
pkg debug/elf, const R_X86_64_REX_GOTPCRELX = 42
|
||||||
|
pkg debug/elf, const R_X86_64_REX_GOTPCRELX R_X86_64
|
||||||
|
pkg debug/elf, const R_X86_64_SIZE32 = 32
|
||||||
|
pkg debug/elf, const R_X86_64_SIZE32 R_X86_64
|
||||||
|
pkg debug/elf, const R_X86_64_SIZE64 = 33
|
||||||
|
pkg debug/elf, const R_X86_64_SIZE64 R_X86_64
|
||||||
|
pkg debug/elf, const R_X86_64_TLSDESC = 36
|
||||||
|
pkg debug/elf, const R_X86_64_TLSDESC R_X86_64
|
||||||
|
pkg debug/elf, const R_X86_64_TLSDESC_CALL = 35
|
||||||
|
pkg debug/elf, const R_X86_64_TLSDESC_CALL R_X86_64
|
||||||
|
pkg debug/macho, const ARM64_RELOC_ADDEND = 10
|
||||||
|
pkg debug/macho, const ARM64_RELOC_ADDEND RelocTypeARM64
|
||||||
|
pkg debug/macho, const ARM64_RELOC_BRANCH26 = 2
|
||||||
|
pkg debug/macho, const ARM64_RELOC_BRANCH26 RelocTypeARM64
|
||||||
|
pkg debug/macho, const ARM64_RELOC_GOT_LOAD_PAGE21 = 5
|
||||||
|
pkg debug/macho, const ARM64_RELOC_GOT_LOAD_PAGE21 RelocTypeARM64
|
||||||
|
pkg debug/macho, const ARM64_RELOC_GOT_LOAD_PAGEOFF12 = 6
|
||||||
|
pkg debug/macho, const ARM64_RELOC_GOT_LOAD_PAGEOFF12 RelocTypeARM64
|
||||||
|
pkg debug/macho, const ARM64_RELOC_PAGE21 = 3
|
||||||
|
pkg debug/macho, const ARM64_RELOC_PAGE21 RelocTypeARM64
|
||||||
|
pkg debug/macho, const ARM64_RELOC_PAGEOFF12 = 4
|
||||||
|
pkg debug/macho, const ARM64_RELOC_PAGEOFF12 RelocTypeARM64
|
||||||
|
pkg debug/macho, const ARM64_RELOC_POINTER_TO_GOT = 7
|
||||||
|
pkg debug/macho, const ARM64_RELOC_POINTER_TO_GOT RelocTypeARM64
|
||||||
|
pkg debug/macho, const ARM64_RELOC_SUBTRACTOR = 1
|
||||||
|
pkg debug/macho, const ARM64_RELOC_SUBTRACTOR RelocTypeARM64
|
||||||
|
pkg debug/macho, const ARM64_RELOC_TLVP_LOAD_PAGE21 = 8
|
||||||
|
pkg debug/macho, const ARM64_RELOC_TLVP_LOAD_PAGE21 RelocTypeARM64
|
||||||
|
pkg debug/macho, const ARM64_RELOC_TLVP_LOAD_PAGEOFF12 = 9
|
||||||
|
pkg debug/macho, const ARM64_RELOC_TLVP_LOAD_PAGEOFF12 RelocTypeARM64
|
||||||
|
pkg debug/macho, const ARM64_RELOC_UNSIGNED = 0
|
||||||
|
pkg debug/macho, const ARM64_RELOC_UNSIGNED RelocTypeARM64
|
||||||
|
pkg debug/macho, const ARM_RELOC_BR24 = 5
|
||||||
|
pkg debug/macho, const ARM_RELOC_BR24 RelocTypeARM
|
||||||
|
pkg debug/macho, const ARM_RELOC_HALF = 8
|
||||||
|
pkg debug/macho, const ARM_RELOC_HALF RelocTypeARM
|
||||||
|
pkg debug/macho, const ARM_RELOC_HALF_SECTDIFF = 9
|
||||||
|
pkg debug/macho, const ARM_RELOC_HALF_SECTDIFF RelocTypeARM
|
||||||
|
pkg debug/macho, const ARM_RELOC_LOCAL_SECTDIFF = 3
|
||||||
|
pkg debug/macho, const ARM_RELOC_LOCAL_SECTDIFF RelocTypeARM
|
||||||
|
pkg debug/macho, const ARM_RELOC_PAIR = 1
|
||||||
|
pkg debug/macho, const ARM_RELOC_PAIR RelocTypeARM
|
||||||
|
pkg debug/macho, const ARM_RELOC_PB_LA_PTR = 4
|
||||||
|
pkg debug/macho, const ARM_RELOC_PB_LA_PTR RelocTypeARM
|
||||||
|
pkg debug/macho, const ARM_RELOC_SECTDIFF = 2
|
||||||
|
pkg debug/macho, const ARM_RELOC_SECTDIFF RelocTypeARM
|
||||||
|
pkg debug/macho, const ARM_RELOC_VANILLA = 0
|
||||||
|
pkg debug/macho, const ARM_RELOC_VANILLA RelocTypeARM
|
||||||
|
pkg debug/macho, const ARM_THUMB_32BIT_BRANCH = 7
|
||||||
|
pkg debug/macho, const ARM_THUMB_32BIT_BRANCH RelocTypeARM
|
||||||
|
pkg debug/macho, const ARM_THUMB_RELOC_BR22 = 6
|
||||||
|
pkg debug/macho, const ARM_THUMB_RELOC_BR22 RelocTypeARM
|
||||||
|
pkg debug/macho, const FlagAllModsBound = 4096
|
||||||
|
pkg debug/macho, const FlagAllModsBound uint32
|
||||||
|
pkg debug/macho, const FlagAllowStackExecution = 131072
|
||||||
|
pkg debug/macho, const FlagAllowStackExecution uint32
|
||||||
|
pkg debug/macho, const FlagAppExtensionSafe = 33554432
|
||||||
|
pkg debug/macho, const FlagAppExtensionSafe uint32
|
||||||
|
pkg debug/macho, const FlagBindAtLoad = 8
|
||||||
|
pkg debug/macho, const FlagBindAtLoad uint32
|
||||||
|
pkg debug/macho, const FlagBindsToWeak = 65536
|
||||||
|
pkg debug/macho, const FlagBindsToWeak uint32
|
||||||
|
pkg debug/macho, const FlagCanonical = 16384
|
||||||
|
pkg debug/macho, const FlagCanonical uint32
|
||||||
|
pkg debug/macho, const FlagDeadStrippableDylib = 4194304
|
||||||
|
pkg debug/macho, const FlagDeadStrippableDylib uint32
|
||||||
|
pkg debug/macho, const FlagDyldLink = 4
|
||||||
|
pkg debug/macho, const FlagDyldLink uint32
|
||||||
|
pkg debug/macho, const FlagForceFlat = 256
|
||||||
|
pkg debug/macho, const FlagForceFlat uint32
|
||||||
|
pkg debug/macho, const FlagHasTLVDescriptors = 8388608
|
||||||
|
pkg debug/macho, const FlagHasTLVDescriptors uint32
|
||||||
|
pkg debug/macho, const FlagIncrLink = 2
|
||||||
|
pkg debug/macho, const FlagIncrLink uint32
|
||||||
|
pkg debug/macho, const FlagLazyInit = 64
|
||||||
|
pkg debug/macho, const FlagLazyInit uint32
|
||||||
|
pkg debug/macho, const FlagNoFixPrebinding = 1024
|
||||||
|
pkg debug/macho, const FlagNoFixPrebinding uint32
|
||||||
|
pkg debug/macho, const FlagNoHeapExecution = 16777216
|
||||||
|
pkg debug/macho, const FlagNoHeapExecution uint32
|
||||||
|
pkg debug/macho, const FlagNoMultiDefs = 512
|
||||||
|
pkg debug/macho, const FlagNoMultiDefs uint32
|
||||||
|
pkg debug/macho, const FlagNoReexportedDylibs = 1048576
|
||||||
|
pkg debug/macho, const FlagNoReexportedDylibs uint32
|
||||||
|
pkg debug/macho, const FlagNoUndefs = 1
|
||||||
|
pkg debug/macho, const FlagNoUndefs uint32
|
||||||
|
pkg debug/macho, const FlagPIE = 2097152
|
||||||
|
pkg debug/macho, const FlagPIE uint32
|
||||||
|
pkg debug/macho, const FlagPrebindable = 2048
|
||||||
|
pkg debug/macho, const FlagPrebindable uint32
|
||||||
|
pkg debug/macho, const FlagPrebound = 16
|
||||||
|
pkg debug/macho, const FlagPrebound uint32
|
||||||
|
pkg debug/macho, const FlagRootSafe = 262144
|
||||||
|
pkg debug/macho, const FlagRootSafe uint32
|
||||||
|
pkg debug/macho, const FlagSetuidSafe = 524288
|
||||||
|
pkg debug/macho, const FlagSetuidSafe uint32
|
||||||
|
pkg debug/macho, const FlagSplitSegs = 32
|
||||||
|
pkg debug/macho, const FlagSplitSegs uint32
|
||||||
|
pkg debug/macho, const FlagSubsectionsViaSymbols = 8192
|
||||||
|
pkg debug/macho, const FlagSubsectionsViaSymbols uint32
|
||||||
|
pkg debug/macho, const FlagTwoLevel = 128
|
||||||
|
pkg debug/macho, const FlagTwoLevel uint32
|
||||||
|
pkg debug/macho, const FlagWeakDefines = 32768
|
||||||
|
pkg debug/macho, const FlagWeakDefines uint32
|
||||||
|
pkg debug/macho, const GENERIC_RELOC_LOCAL_SECTDIFF = 4
|
||||||
|
pkg debug/macho, const GENERIC_RELOC_LOCAL_SECTDIFF RelocTypeGeneric
|
||||||
|
pkg debug/macho, const GENERIC_RELOC_PAIR = 1
|
||||||
|
pkg debug/macho, const GENERIC_RELOC_PAIR RelocTypeGeneric
|
||||||
|
pkg debug/macho, const GENERIC_RELOC_PB_LA_PTR = 3
|
||||||
|
pkg debug/macho, const GENERIC_RELOC_PB_LA_PTR RelocTypeGeneric
|
||||||
|
pkg debug/macho, const GENERIC_RELOC_SECTDIFF = 2
|
||||||
|
pkg debug/macho, const GENERIC_RELOC_SECTDIFF RelocTypeGeneric
|
||||||
|
pkg debug/macho, const GENERIC_RELOC_TLV = 5
|
||||||
|
pkg debug/macho, const GENERIC_RELOC_TLV RelocTypeGeneric
|
||||||
|
pkg debug/macho, const GENERIC_RELOC_VANILLA = 0
|
||||||
|
pkg debug/macho, const GENERIC_RELOC_VANILLA RelocTypeGeneric
|
||||||
|
pkg debug/macho, const LoadCmdRpath = 2147483676
|
||||||
|
pkg debug/macho, const LoadCmdRpath LoadCmd
|
||||||
|
pkg debug/macho, const X86_64_RELOC_BRANCH = 2
|
||||||
|
pkg debug/macho, const X86_64_RELOC_BRANCH RelocTypeX86_64
|
||||||
|
pkg debug/macho, const X86_64_RELOC_GOT = 4
|
||||||
|
pkg debug/macho, const X86_64_RELOC_GOT RelocTypeX86_64
|
||||||
|
pkg debug/macho, const X86_64_RELOC_GOT_LOAD = 3
|
||||||
|
pkg debug/macho, const X86_64_RELOC_GOT_LOAD RelocTypeX86_64
|
||||||
|
pkg debug/macho, const X86_64_RELOC_SIGNED = 1
|
||||||
|
pkg debug/macho, const X86_64_RELOC_SIGNED RelocTypeX86_64
|
||||||
|
pkg debug/macho, const X86_64_RELOC_SIGNED_1 = 6
|
||||||
|
pkg debug/macho, const X86_64_RELOC_SIGNED_1 RelocTypeX86_64
|
||||||
|
pkg debug/macho, const X86_64_RELOC_SIGNED_2 = 7
|
||||||
|
pkg debug/macho, const X86_64_RELOC_SIGNED_2 RelocTypeX86_64
|
||||||
|
pkg debug/macho, const X86_64_RELOC_SIGNED_4 = 8
|
||||||
|
pkg debug/macho, const X86_64_RELOC_SIGNED_4 RelocTypeX86_64
|
||||||
|
pkg debug/macho, const X86_64_RELOC_SUBTRACTOR = 5
|
||||||
|
pkg debug/macho, const X86_64_RELOC_SUBTRACTOR RelocTypeX86_64
|
||||||
|
pkg debug/macho, const X86_64_RELOC_TLV = 9
|
||||||
|
pkg debug/macho, const X86_64_RELOC_TLV RelocTypeX86_64
|
||||||
|
pkg debug/macho, const X86_64_RELOC_UNSIGNED = 0
|
||||||
|
pkg debug/macho, const X86_64_RELOC_UNSIGNED RelocTypeX86_64
|
||||||
|
pkg debug/macho, method (RelocTypeARM) GoString() string
|
||||||
|
pkg debug/macho, method (RelocTypeARM) String() string
|
||||||
|
pkg debug/macho, method (RelocTypeARM64) GoString() string
|
||||||
|
pkg debug/macho, method (RelocTypeARM64) String() string
|
||||||
|
pkg debug/macho, method (RelocTypeGeneric) GoString() string
|
||||||
|
pkg debug/macho, method (RelocTypeGeneric) String() string
|
||||||
|
pkg debug/macho, method (RelocTypeX86_64) GoString() string
|
||||||
|
pkg debug/macho, method (RelocTypeX86_64) String() string
|
||||||
|
pkg debug/macho, method (Rpath) Raw() []uint8
|
||||||
|
pkg debug/macho, method (Type) GoString() string
|
||||||
|
pkg debug/macho, method (Type) String() string
|
||||||
|
pkg debug/macho, type Reloc struct
|
||||||
|
pkg debug/macho, type Reloc struct, Addr uint32
|
||||||
|
pkg debug/macho, type Reloc struct, Extern bool
|
||||||
|
pkg debug/macho, type Reloc struct, Len uint8
|
||||||
|
pkg debug/macho, type Reloc struct, Pcrel bool
|
||||||
|
pkg debug/macho, type Reloc struct, Scattered bool
|
||||||
|
pkg debug/macho, type Reloc struct, Type uint8
|
||||||
|
pkg debug/macho, type Reloc struct, Value uint32
|
||||||
|
pkg debug/macho, type RelocTypeARM int
|
||||||
|
pkg debug/macho, type RelocTypeARM64 int
|
||||||
|
pkg debug/macho, type RelocTypeGeneric int
|
||||||
|
pkg debug/macho, type RelocTypeX86_64 int
|
||||||
|
pkg debug/macho, type Rpath struct
|
||||||
|
pkg debug/macho, type Rpath struct, Path string
|
||||||
|
pkg debug/macho, type Rpath struct, embedded LoadBytes
|
||||||
|
pkg debug/macho, type RpathCmd struct
|
||||||
|
pkg debug/macho, type RpathCmd struct, Cmd LoadCmd
|
||||||
|
pkg debug/macho, type RpathCmd struct, Len uint32
|
||||||
|
pkg debug/macho, type RpathCmd struct, Path uint32
|
||||||
|
pkg debug/macho, type Section struct, Relocs []Reloc
|
||||||
|
pkg encoding/csv, type ParseError struct, StartLine int
|
||||||
|
pkg encoding/hex, func NewDecoder(io.Reader) io.Reader
|
||||||
|
pkg encoding/hex, func NewEncoder(io.Writer) io.Writer
|
||||||
|
pkg encoding/json, method (*Decoder) DisallowUnknownFields()
|
||||||
|
pkg encoding/xml, func NewTokenDecoder(TokenReader) *Decoder
|
||||||
|
pkg encoding/xml, type TokenReader interface { Token }
|
||||||
|
pkg encoding/xml, type TokenReader interface, Token() (Token, error)
|
||||||
|
pkg flag, method (*FlagSet) ErrorHandling() ErrorHandling
|
||||||
|
pkg flag, method (*FlagSet) Name() string
|
||||||
|
pkg flag, method (*FlagSet) Output() io.Writer
|
||||||
|
pkg math, func Erfcinv(float64) float64
|
||||||
|
pkg math, func Erfinv(float64) float64
|
||||||
|
pkg math, func Round(float64) float64
|
||||||
|
pkg math, func RoundToEven(float64) float64
|
||||||
|
pkg math/big, const MaxBase = 62
|
||||||
|
pkg math/big, method (*Float) Sqrt(*Float) *Float
|
||||||
|
pkg math/big, method (*Int) CmpAbs(*Int) int
|
||||||
|
pkg math/rand, func Shuffle(int, func(int, int))
|
||||||
|
pkg math/rand, method (*Rand) Shuffle(int, func(int, int))
|
||||||
|
pkg net, method (*TCPListener) SyscallConn() (syscall.RawConn, error)
|
||||||
|
pkg net, method (*UnixListener) SyscallConn() (syscall.RawConn, error)
|
||||||
|
pkg net/smtp, method (*Client) Noop() error
|
||||||
|
pkg os, func IsTimeout(error) bool
|
||||||
|
pkg os, method (*File) SetDeadline(time.Time) error
|
||||||
|
pkg os, method (*File) SetReadDeadline(time.Time) error
|
||||||
|
pkg os, method (*File) SetWriteDeadline(time.Time) error
|
||||||
|
pkg os, method (*PathError) Timeout() bool
|
||||||
|
pkg os, method (*SyscallError) Timeout() bool
|
||||||
|
pkg os, var ErrNoDeadline error
|
||||||
|
pkg strings, method (*Builder) Grow(int)
|
||||||
|
pkg strings, method (*Builder) Len() int
|
||||||
|
pkg strings, method (*Builder) ReadFrom(io.Reader) (int64, error)
|
||||||
|
pkg strings, method (*Builder) Reset()
|
||||||
|
pkg strings, method (*Builder) String() string
|
||||||
|
pkg strings, method (*Builder) Write([]uint8) (int, error)
|
||||||
|
pkg strings, method (*Builder) WriteByte(uint8) error
|
||||||
|
pkg strings, method (*Builder) WriteRune(int32) (int, error)
|
||||||
|
pkg strings, method (*Builder) WriteString(string) (int, error)
|
||||||
|
pkg strings, type Builder struct
|
||||||
|
pkg syscall (freebsd-386), const SYS_UTIMENSAT = 547
|
||||||
|
pkg syscall (freebsd-386), const SYS_UTIMENSAT ideal-int
|
||||||
|
pkg syscall (freebsd-386-cgo), const SYS_UTIMENSAT = 547
|
||||||
|
pkg syscall (freebsd-386-cgo), const SYS_UTIMENSAT ideal-int
|
||||||
|
pkg syscall (freebsd-amd64), const SYS_UTIMENSAT = 547
|
||||||
|
pkg syscall (freebsd-amd64), const SYS_UTIMENSAT ideal-int
|
||||||
|
pkg syscall (freebsd-amd64-cgo), const SYS_UTIMENSAT = 547
|
||||||
|
pkg syscall (freebsd-amd64-cgo), const SYS_UTIMENSAT ideal-int
|
||||||
|
pkg syscall (freebsd-arm), const SYS_UTIMENSAT = 547
|
||||||
|
pkg syscall (freebsd-arm), const SYS_UTIMENSAT ideal-int
|
||||||
|
pkg syscall (freebsd-arm-cgo), const SYS_UTIMENSAT = 547
|
||||||
|
pkg syscall (freebsd-arm-cgo), const SYS_UTIMENSAT ideal-int
|
||||||
|
pkg syscall (windows-386), func CreateProcessAsUser(Token, *uint16, *uint16, *SecurityAttributes, *SecurityAttributes, bool, uint32, *uint16, *uint16, *StartupInfo, *ProcessInformation) error
|
||||||
|
pkg syscall (windows-386), type SysProcAttr struct, Token Token
|
||||||
|
pkg syscall (windows-amd64), func CreateProcessAsUser(Token, *uint16, *uint16, *SecurityAttributes, *SecurityAttributes, bool, uint32, *uint16, *uint16, *StartupInfo, *ProcessInformation) error
|
||||||
|
pkg syscall (windows-amd64), type SysProcAttr struct, Token Token
|
||||||
|
pkg text/template/parse, const NodeBreak = 20
|
||||||
|
pkg text/template/parse, const NodeBreak NodeType
|
||||||
|
pkg text/template/parse, const NodeContinue = 21
|
||||||
|
pkg text/template/parse, const NodeContinue NodeType
|
||||||
|
pkg text/template/parse, method (*BreakNode) Copy() Node
|
||||||
|
pkg text/template/parse, method (*BreakNode) Position() Pos
|
||||||
|
pkg text/template/parse, method (*BreakNode) String() string
|
||||||
|
pkg text/template/parse, method (*BreakNode) Type() NodeType
|
||||||
|
pkg text/template/parse, method (*ContinueNode) Copy() Node
|
||||||
|
pkg text/template/parse, method (*ContinueNode) Position() Pos
|
||||||
|
pkg text/template/parse, method (*ContinueNode) String() string
|
||||||
|
pkg text/template/parse, method (*ContinueNode) Type() NodeType
|
||||||
|
pkg text/template/parse, type BreakNode struct
|
||||||
|
pkg text/template/parse, type BreakNode struct, embedded NodeType
|
||||||
|
pkg text/template/parse, type BreakNode struct, embedded Pos
|
||||||
|
pkg text/template/parse, type ContinueNode struct
|
||||||
|
pkg text/template/parse, type ContinueNode struct, embedded NodeType
|
||||||
|
pkg text/template/parse, type ContinueNode struct, embedded Pos
|
||||||
|
pkg unicode, const Version = "10.0.0"
|
||||||
|
pkg unicode, var Masaram_Gondi *RangeTable
|
||||||
|
pkg unicode, var Nushu *RangeTable
|
||||||
|
pkg unicode, var Regional_Indicator *RangeTable
|
||||||
|
pkg unicode, var Soyombo *RangeTable
|
||||||
|
pkg unicode, var Zanabazar_Square *RangeTable
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
@ -98,5 +99,5 @@ func main() {
|
||||||
http.HandleFunc("/view/", viewHandler)
|
http.HandleFunc("/view/", viewHandler)
|
||||||
http.HandleFunc("/edit/", editHandler)
|
http.HandleFunc("/edit/", editHandler)
|
||||||
http.HandleFunc("/save/", saveHandler)
|
http.HandleFunc("/save/", saveHandler)
|
||||||
http.ListenAndServe(":8080", nil)
|
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -49,5 +50,5 @@ func viewHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
func main() {
|
func main() {
|
||||||
http.HandleFunc("/view/", viewHandler)
|
http.HandleFunc("/view/", viewHandler)
|
||||||
http.HandleFunc("/edit/", editHandler)
|
http.HandleFunc("/edit/", editHandler)
|
||||||
http.ListenAndServe(":8080", nil)
|
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
@ -87,5 +88,5 @@ func main() {
|
||||||
http.HandleFunc("/view/", makeHandler(viewHandler))
|
http.HandleFunc("/view/", makeHandler(viewHandler))
|
||||||
http.HandleFunc("/edit/", makeHandler(editHandler))
|
http.HandleFunc("/edit/", makeHandler(editHandler))
|
||||||
http.HandleFunc("/save/", makeHandler(saveHandler))
|
http.HandleFunc("/save/", makeHandler(saveHandler))
|
||||||
http.ListenAndServe(":8080", nil)
|
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -61,5 +62,5 @@ func main() {
|
||||||
http.HandleFunc("/view/", viewHandler)
|
http.HandleFunc("/view/", viewHandler)
|
||||||
http.HandleFunc("/edit/", editHandler)
|
http.HandleFunc("/edit/", editHandler)
|
||||||
http.HandleFunc("/save/", saveHandler)
|
http.HandleFunc("/save/", saveHandler)
|
||||||
http.ListenAndServe(":8080", nil)
|
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,27 @@
|
||||||
*** final.go 2015-06-14 23:59:22.000000000 +0200
|
--- final.go 2017-08-31 13:19:00.422925489 -0700
|
||||||
--- final-test.go 2015-06-15 00:15:41.000000000 +0200
|
+++ final-test.go 2017-08-31 13:23:43.381391659 -0700
|
||||||
***************
|
@@ -8,6 +8,7 @@
|
||||||
*** 7,12 ****
|
"html/template"
|
||||||
--- 7,14 ----
|
"io/ioutil"
|
||||||
import (
|
"log"
|
||||||
"html/template"
|
+ "net"
|
||||||
"io/ioutil"
|
"net/http"
|
||||||
+ "log"
|
"regexp"
|
||||||
+ "net"
|
)
|
||||||
"net/http"
|
@@ -86,5 +87,15 @@
|
||||||
"regexp"
|
http.HandleFunc("/edit/", makeHandler(editHandler))
|
||||||
)
|
http.HandleFunc("/save/", makeHandler(saveHandler))
|
||||||
***************
|
|
||||||
*** 85,89 ****
|
|
||||||
http.HandleFunc("/edit/", makeHandler(editHandler))
|
|
||||||
http.HandleFunc("/save/", makeHandler(saveHandler))
|
|
||||||
|
|
||||||
! http.ListenAndServe(":8080", nil)
|
- log.Fatal(http.ListenAndServe(":8080", nil))
|
||||||
}
|
+ l, err := net.Listen("tcp", "127.0.0.1:0")
|
||||||
--- 87,101 ----
|
+ if err != nil {
|
||||||
http.HandleFunc("/edit/", makeHandler(editHandler))
|
+ log.Fatal(err)
|
||||||
http.HandleFunc("/save/", makeHandler(saveHandler))
|
+ }
|
||||||
|
+ err = ioutil.WriteFile("final-test-port.txt", []byte(l.Addr().String()), 0644)
|
||||||
! l, err := net.Listen("tcp", "127.0.0.1:0")
|
+ if err != nil {
|
||||||
! if err != nil {
|
+ log.Fatal(err)
|
||||||
! log.Fatal(err)
|
+ }
|
||||||
! }
|
+ s := &http.Server{}
|
||||||
! err = ioutil.WriteFile("final-test-port.txt", []byte(l.Addr().String()), 0644)
|
+ s.Serve(l)
|
||||||
! if err != nil {
|
+ return
|
||||||
! log.Fatal(err)
|
}
|
||||||
! }
|
|
||||||
! s := &http.Server{}
|
|
||||||
! s.Serve(l)
|
|
||||||
! return
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
@ -85,5 +86,5 @@ func main() {
|
||||||
http.HandleFunc("/edit/", makeHandler(editHandler))
|
http.HandleFunc("/edit/", makeHandler(editHandler))
|
||||||
http.HandleFunc("/save/", makeHandler(saveHandler))
|
http.HandleFunc("/save/", makeHandler(saveHandler))
|
||||||
|
|
||||||
http.ListenAndServe(":8080", nil)
|
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -11,5 +12,5 @@ func handler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
http.HandleFunc("/", handler)
|
http.HandleFunc("/", handler)
|
||||||
http.ListenAndServe(":8080", nil)
|
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -179,7 +179,7 @@ You can compile and run the program like this:
|
||||||
<pre>
|
<pre>
|
||||||
$ go build wiki.go
|
$ go build wiki.go
|
||||||
$ ./wiki
|
$ ./wiki
|
||||||
This is a sample page.
|
This is a sample Page.
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -213,6 +213,12 @@ worry about its second parameter, <code>nil</code>, for now.)
|
||||||
This function will block until the program is terminated.
|
This function will block until the program is terminated.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<code>ListenAndServe</code> always returns an error, since it only returns when an
|
||||||
|
unexpected error occurs.
|
||||||
|
In order to log that error we wrap the function call with <code>log.Fatal</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The function <code>handler</code> is of the type <code>http.HandlerFunc</code>.
|
The function <code>handler</code> is of the type <code>http.HandlerFunc</code>.
|
||||||
It takes an <code>http.ResponseWriter</code> and an <code>http.Request</code> as
|
It takes an <code>http.ResponseWriter</code> and an <code>http.Request</code> as
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -52,5 +53,5 @@ func editHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
func main() {
|
func main() {
|
||||||
http.HandleFunc("/view/", viewHandler)
|
http.HandleFunc("/view/", viewHandler)
|
||||||
http.HandleFunc("/edit/", editHandler)
|
http.HandleFunc("/edit/", editHandler)
|
||||||
http.ListenAndServe(":8080", nil)
|
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -37,5 +38,5 @@ func viewHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
http.HandleFunc("/view/", viewHandler)
|
http.HandleFunc("/view/", viewHandler)
|
||||||
http.ListenAndServe(":8080", nil)
|
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -69,5 +70,5 @@ func main() {
|
||||||
http.HandleFunc("/view/", viewHandler)
|
http.HandleFunc("/view/", viewHandler)
|
||||||
http.HandleFunc("/edit/", editHandler)
|
http.HandleFunc("/edit/", editHandler)
|
||||||
http.HandleFunc("/save/", saveHandler)
|
http.HandleFunc("/save/", saveHandler)
|
||||||
http.ListenAndServe(":8080", nil)
|
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -53,5 +54,5 @@ func main() {
|
||||||
http.HandleFunc("/view/", viewHandler)
|
http.HandleFunc("/view/", viewHandler)
|
||||||
http.HandleFunc("/edit/", editHandler)
|
http.HandleFunc("/edit/", editHandler)
|
||||||
//http.HandleFunc("/save/", saveHandler)
|
//http.HandleFunc("/save/", saveHandler)
|
||||||
http.ListenAndServe(":8080", nil)
|
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -876,6 +876,12 @@ Addressing modes:
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The value of <code>GOMIPS</code> environment variable (<code>hardfloat</code> or
|
||||||
|
<code>softfloat</code>) is made available to assembly code by predefining either
|
||||||
|
<code>GOMIPS_hardfloat</code> or <code>GOMIPS_softfloat</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3 id="unsupported_opcodes">Unsupported opcodes</h3>
|
<h3 id="unsupported_opcodes">Unsupported opcodes</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ We encourage all Go users to subscribe to
|
||||||
<p>A <a href="/doc/devel/release.html">summary</a> of the changes between Go releases. Notes for the major releases:</p>
|
<p>A <a href="/doc/devel/release.html">summary</a> of the changes between Go releases. Notes for the major releases:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
<li><a href="/doc/go1.10">Go 1.10</a> <small>(February 2018)</small></li>
|
||||||
<li><a href="/doc/go1.9">Go 1.9</a> <small>(August 2017)</small></li>
|
<li><a href="/doc/go1.9">Go 1.9</a> <small>(August 2017)</small></li>
|
||||||
<li><a href="/doc/go1.8">Go 1.8</a> <small>(February 2017)</small></li>
|
<li><a href="/doc/go1.8">Go 1.8</a> <small>(February 2017)</small></li>
|
||||||
<li><a href="/doc/go1.7">Go 1.7</a> <small>(August 2016)</small></li>
|
<li><a href="/doc/go1.7">Go 1.7</a> <small>(August 2016)</small></li>
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ script as *nix.)
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Your secret authentication token is now in a <code>.gitcookie</code> file
|
Your secret authentication token is now in a <code>.gitcookies</code> file
|
||||||
and Git is configured to use this file.
|
and Git is configured to use this file.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
@ -158,7 +158,7 @@ completed and update the <code>AUTHORS</code> file.
|
||||||
Changes to Go must be reviewed before they are accepted, no matter who makes the change.
|
Changes to Go must be reviewed before they are accepted, no matter who makes the change.
|
||||||
A custom git command called <code>git-codereview</code>, discussed below,
|
A custom git command called <code>git-codereview</code>, discussed below,
|
||||||
helps manage the code review process through a Google-hosted
|
helps manage the code review process through a Google-hosted
|
||||||
<a href="https://go-review.googlesource.com/">instance</a> Gerrit.
|
<a href="https://go-review.googlesource.com/">instance</a> of Gerrit.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="git-codereview_install">Install the git-codereview command</h3>
|
<h3 id="git-codereview_install">Install the git-codereview command</h3>
|
||||||
|
|
@ -208,12 +208,6 @@ daily work, install the hooks in a new Git checkout by running
|
||||||
<code>git-codereview</code> <code>hooks</code>.
|
<code>git-codereview</code> <code>hooks</code>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
|
||||||
The workflow described below assumes a single change per branch.
|
|
||||||
It is also possible to prepare a sequence of (usually related) changes in a single branch.
|
|
||||||
See the <a href="https://golang.org/x/review/git-codereview">git-codereview documentation</a> for details.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h3 id="git-config">Set up git aliases</h3>
|
<h3 id="git-config">Set up git aliases</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -305,6 +299,15 @@ which only bug fixes and doc updates are accepted. New contributions can be
|
||||||
sent during a feature freeze but will not be accepted until the freeze thaws.
|
sent during a feature freeze but will not be accepted until the freeze thaws.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h3 id="scratch">Not sure what change to make?</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
If you want to become familiar with Gerrit and the contribution process,
|
||||||
|
but aren't sure what you'd like to contribute just yet, you can use the <a
|
||||||
|
href="https://go.googlesource.com/scratch">scratch repository</a> to practice
|
||||||
|
making a change.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h2 id="making_a_change">Making a change</h2>
|
<h2 id="making_a_change">Making a change</h2>
|
||||||
|
|
||||||
<h3 id="checkout_go">Getting Go Source</h3>
|
<h3 id="checkout_go">Getting Go Source</h3>
|
||||||
|
|
@ -420,6 +423,12 @@ In the Go contribution workflow this is done with a <code>git</code>
|
||||||
directly to that local branch.
|
directly to that local branch.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The workflow described here assumes a single change per branch.
|
||||||
|
It is also possible to prepare a sequence of (usually related) changes in a single branch.
|
||||||
|
See the <a href="https://golang.org/x/review/git-codereview">git-codereview documentation</a> for details.
|
||||||
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
$ git change <i><branch></i>
|
$ git change <i><branch></i>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
@ -681,8 +690,8 @@ reviewers asking them to visit the issue's URL and make comments on the change.
|
||||||
When done, the reviewer adds comments through the Gerrit user interface
|
When done, the reviewer adds comments through the Gerrit user interface
|
||||||
and clicks "Reply" to send comments back.
|
and clicks "Reply" to send comments back.
|
||||||
You will receive a mail notification when this happens.
|
You will receive a mail notification when this happens.
|
||||||
You must reply through the web interface.
|
You may reply through the web interface or
|
||||||
(Unlike with the old Rietveld review system, replying by mail has no effect.)
|
<a href="https://gerrit-review.googlesource.com/Documentation/intro-user.html#reply-by-email">via email</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="revise">Revise and resend</h3>
|
<h3 id="revise">Revise and resend</h3>
|
||||||
|
|
@ -696,8 +705,8 @@ all the changes and comments made in the single URL.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
You must respond to review comments through the web interface.
|
You may respond to review comments through the web interface or
|
||||||
(Unlike with the old Rietveld review system, responding by mail has no effect.)
|
<a href="https://gerrit-review.googlesource.com/Documentation/intro-user.html#reply-by-email">via email</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,8 @@ In time, a more Go-centric debugging architecture may be required.
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
When you compile and link your Go programs with the <code>gc</code> toolchain
|
When you compile and link your Go programs with the <code>gc</code> toolchain
|
||||||
on Linux, Mac OS X, FreeBSD or NetBSD, the resulting binaries contain DWARFv3
|
on Linux, Mac OS X, FreeBSD or NetBSD, the resulting binaries contain DWARFv4
|
||||||
debugging information that recent versions (>7.1) of the GDB debugger can
|
debugging information that recent versions (≥7.5) of the GDB debugger can
|
||||||
use to inspect a live process or a core dump.
|
use to inspect a live process or a core dump.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,16 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.4">Go
|
||||||
1.8.4 milestone</a> on our issue tracker for details.
|
1.8.4 milestone</a> on our issue tracker for details.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
go1.8.5 (released 2017/10/25) includes fixes to the compiler, linker, runtime,
|
||||||
|
documentation, <code>go</code> command,
|
||||||
|
and the <code>crypto/x509</code> and <code>net/smtp</code> packages.
|
||||||
|
It includes a fix to a bug introduced in Go 1.8.4 that broke <code>go</code> <code>get</code>
|
||||||
|
of non-Git repositories under certain conditions.
|
||||||
|
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.5">Go
|
||||||
|
1.8.5 milestone</a> on our issue tracker for details.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h2 id="go1.7">go1.7 (released 2016/08/15)</h2>
|
<h2 id="go1.7">go1.7 (released 2016/08/15)</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
||||||
439
doc/diagnostics.html
Normal file
439
doc/diagnostics.html
Normal file
|
|
@ -0,0 +1,439 @@
|
||||||
|
<!--{
|
||||||
|
"Title": "Diagnostics",
|
||||||
|
"Template": true
|
||||||
|
}-->
|
||||||
|
|
||||||
|
<h2 id="introduction">Introduction</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The Go ecosystem provides a large suite of APIs and tools to
|
||||||
|
diagnose logic and performance problems in Go programs. This page
|
||||||
|
summarizes the available tools and helps Go users pick the right one
|
||||||
|
for their specific problem.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Diagnostics solutions can be categorized into the following groups:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><strong>Profiling</strong>: Profiling tools analyze the complexity and costs of a
|
||||||
|
Go program such as its memory usage and frequently called
|
||||||
|
functions to identify the expensive sections of a Go program.</li>
|
||||||
|
<li><strong>Tracing</strong>: Tracing is a way to instrument code to analyze latency
|
||||||
|
throughout the lifecycle of a call or user request. Traces provide an
|
||||||
|
overview of how much latency each component contributes to the overall
|
||||||
|
latency in a system. Traces can span multiple Go processes.</li>
|
||||||
|
<li><strong>Debugging</strong>: Debugging allows us to pause a Go program and examine
|
||||||
|
its execution. Program state and flow can be verified with debugging.</li>
|
||||||
|
<li><strong>Runtime statistics and events</strong>: Collection and analysis of runtime stats and events
|
||||||
|
provides a high-level overview of the health of Go programs. Spikes/dips of metrics
|
||||||
|
helps us to identify changes in throughput, utilization, and performance.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Note: Some diagnostics tools may interfere with each other. For example, precise
|
||||||
|
memory profiling skews CPU profiles and goroutine blocking profiling affects scheduler
|
||||||
|
trace. Use tools in isolation to get more precise info.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="profiling">Profiling</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Profiling is useful for identifying expensive or frequently called sections
|
||||||
|
of code. The Go runtime provides <a href="https://golang.org/pkg/runtime/pprof/">
|
||||||
|
profiling data</a> in the format expected by the
|
||||||
|
<a href="https://github.com/google/pprof/blob/master/doc/pprof.md">pprof visualization tool</a>.
|
||||||
|
The profiling data can be collected during testing
|
||||||
|
via <code>go test</code> or endpoints made available from the <a href="/pkg/net/http/pprof/">
|
||||||
|
net/http/pprof</a> package. Users need to collect the profiling data and use pprof tools to filter
|
||||||
|
and visualize the top code paths.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Predefined profiles provided by the <a href="/pkg/runtime/pprof">runtime/pprof</a> package:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<strong>cpu</strong>: CPU profile determines where a program spends
|
||||||
|
its time while actively consuming CPU cycles (as opposed to while sleeping or waiting for I/O).
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>heap</strong>: Heap profile reports memory allocation samples;
|
||||||
|
used to monitor current and historical memory usage, and to check for memory leaks.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>threadcreate</strong>: Thread creation profile reports the sections
|
||||||
|
of the program that lead the creation of new OS threads.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>goroutine</strong>: Goroutine profile reports the stack traces of all current goroutines.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>block</strong>: Block profile shows where goroutines block waiting on synchronization
|
||||||
|
primitives (including timer channels). Block profile is not enabled by default;
|
||||||
|
use <code>runtime.SetBlockProfileRate</code> to enable it.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>mutex</strong>: Mutex profile reports the lock contentions. When you think your
|
||||||
|
CPU is not fully utilized due to a mutex contention, use this profile. Mutex profile
|
||||||
|
is not enabled by default, see <code>runtime.SetMutexProfileFraction</code> to enable it.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<p><strong>What other profilers can I use to profile Go programs?</strong></p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
On Linux, <a href="https://perf.wiki.kernel.org/index.php/Tutorial">perf tools</a>
|
||||||
|
can be used for profiling Go programs. Perf can profile
|
||||||
|
and unwind cgo/SWIG code and kernel, so it can be useful to get insights into
|
||||||
|
native/kernel performance bottlenecks. On macOS,
|
||||||
|
<a href="https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/">Instruments</a>
|
||||||
|
suite can be used profile Go programs.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><strong>Can I profile my production services?</strong></p>
|
||||||
|
|
||||||
|
<p>Yes. It is safe to profile programs in production, but enabling
|
||||||
|
some profiles (e.g. the CPU profile) adds cost. You should expect to
|
||||||
|
see performance downgrade. The performance penalty can be estimated
|
||||||
|
by measuring the overhead of the profiler before turning it on in
|
||||||
|
production.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
You may want to periodically profile your production services.
|
||||||
|
Especially in a system with many replicas of a single process, selecting
|
||||||
|
a random replica periodically is a safe option.
|
||||||
|
Select a production process, profile it for
|
||||||
|
X seconds for every Y seconds and save the results for visualization and
|
||||||
|
analysis; then repeat periodically. Results may be manually and/or automatically
|
||||||
|
reviewed to find problems.
|
||||||
|
Collection of profiles can interfere with each other,
|
||||||
|
so it is recommended to collect only a single profile at a time.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<strong>What are the best ways to visualize the profiling data?</strong>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The Go tools provide text, graph, and <a href="http://valgrind.org/docs/manual/cl-manual.html">callgrind</a>
|
||||||
|
visualization of the profile data via
|
||||||
|
<code><a href="https://github.com/google/pprof/blob/master/doc/pprof.md">go tool pprof</a></code>.
|
||||||
|
Read <a href="https://blog.golang.org/profiling-go-programs">Profiling Go programs</a>
|
||||||
|
to see them in action.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<img width="800" src="https://storage.googleapis.com/golangorg-assets/pprof-text.png">
|
||||||
|
<br>
|
||||||
|
<small>Listing of the most expensive calls as text.</small>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<img width="800" src="https://storage.googleapis.com/golangorg-assets/pprof-dot.png">
|
||||||
|
<br>
|
||||||
|
<small>Visualization of the most expensive calls as a graph.</small>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Weblist view displays the expensive parts of the source line by line in
|
||||||
|
an HTML page. In the following example, 530ms is spent in the
|
||||||
|
<code>runtime.concatstrings</code> and cost of each line is presented
|
||||||
|
in the listing.</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<img width="800" src="https://storage.googleapis.com/golangorg-assets/pprof-weblist.png">
|
||||||
|
<br>
|
||||||
|
<small>Visualization of the most expensive calls as weblist.</small>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Another way to visualize profile data is a <a href="https://github.com/uber/go-torch">flame graph</a>.
|
||||||
|
Flame graphs allow you to move in a specific ancestry path, so you can zoom
|
||||||
|
in/out specific sections of code more easily.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<img width="800" src="https://storage.googleapis.com/golangorg-assets/flame.png">
|
||||||
|
<br>
|
||||||
|
<small>Flame graphs offers visualization to spot the most expensive code-paths.</small>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><strong>Am I restricted to the built-in profiles?</strong></p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Additionally to what is provided by the runtime, Go users can create
|
||||||
|
their custom profiles via <a href="/pkg/runtime/pprof/#Profile">pprof.Profile</a>
|
||||||
|
and use the existing tools to examine them.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><strong>Can I serve the profiler handlers (/debug/pprof/...) on a different path and port?</strong></p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Yes. The <code>net/http/pprof</code> package registers its handlers to the default
|
||||||
|
mux by default, but you can also register them yourself by using the handlers
|
||||||
|
exported from the package.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
For example, the following example will serve the pprof.Profile
|
||||||
|
handler on :7777 at /custom_debug_path/profile:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<pre>
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/custom_debug_path/profile", pprof.Profile)
|
||||||
|
http.ListenAndServe(":7777", mux)
|
||||||
|
</pre>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="tracing">Tracing</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Tracing is a way to instrument code to analyze latency throughout the
|
||||||
|
lifecycle of a chain of calls. Go provides
|
||||||
|
<a href="https://godoc.org/golang.org/x/net/trace">golang.org/x/net/trace</a>
|
||||||
|
package as a minimal tracing backend per Go node and provides a minimal
|
||||||
|
instrumentation library with a simple dashboard. Go also provides
|
||||||
|
an execution tracer to trace the runtime events within an interval.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Tracing enables us to:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Instrument and profile application latency in a Go process.</li>
|
||||||
|
<li>Measure the cost of specific calls in a long chain of calls.</li>
|
||||||
|
<li>Figure out the utilization and performance improvements.
|
||||||
|
Bottlenecks are not always obvious without tracing data.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In monolithic systems, it's relatively easy to collect diagnostic data
|
||||||
|
from the building blocks of a program. All modules live within one
|
||||||
|
process and share common resources to report logs, errors, and other
|
||||||
|
diagnostic information. Once your system grows beyond a single process and
|
||||||
|
starts to become distributed, it becomes harder to follow a call starting
|
||||||
|
from the front-end web server to all of its back-ends until a response is
|
||||||
|
returned back to the user. This is where distributed tracing plays a big
|
||||||
|
role to instrument and analyze your production systems.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Distributed tracing is a way to instrument code to analyze latency throughout
|
||||||
|
the lifecycle of a user request. When a system is distributed and when
|
||||||
|
conventional profiling and debugging tools don’t scale, you might want
|
||||||
|
to use distributed tracing tools to analyze the performance of your user
|
||||||
|
requests and RPCs.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Distributed tracing enables us to:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Instrument and profile application latency in a large system.</li>
|
||||||
|
<li>Track all RPCs within the lifecycle of a user request and see integration issues
|
||||||
|
that are only visible in production.</li>
|
||||||
|
<li>Figure out performance improvements that can be applied to our systems.
|
||||||
|
Many bottlenecks are not obvious before the collection of tracing data.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>The Go ecosystem provides various distributed tracing libraries per tracing system
|
||||||
|
and backend-agnostic ones.</p>
|
||||||
|
|
||||||
|
|
||||||
|
<p><strong>Is there a way to automatically intercept each function call and create traces?</strong></p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Go doesn’t provide a way to automatically intercept every function call and create
|
||||||
|
trace spans. You need to manually instrument your code to create, end, and annotate spans.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><strong>How should I propagate trace headers in Go libraries?</strong></p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
You can propagate trace identifiers and tags in the <code>context.Context</code>.
|
||||||
|
There is no canonical trace key or common representation of trace headers
|
||||||
|
in the industry yet. Each tracing provider is responsible for providing propagation
|
||||||
|
utilities in their Go libraries.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<strong>What other low-level events from the standard library or
|
||||||
|
runtime can be included in a trace?</strong>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The standard library and runtime are trying to expose several additional APIs
|
||||||
|
to notify on low level internal events. For example, httptrace.ClientTrace
|
||||||
|
provides APIs to follow low-level events in the life cycle of an outgoing request.
|
||||||
|
There is an ongoing effort to retrieve low-level runtime events from
|
||||||
|
the runtime execution tracer and allow users to define and record their user events.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="debugging">Debugging</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Debugging is the process of identifying why a program misbehaves.
|
||||||
|
Debuggers allow us to understand a program’s execution flow and current state.
|
||||||
|
There are several styles of debugging; this section will only focus on attaching
|
||||||
|
a debugger to a program and core dump debugging.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Go users mostly use the following debuggers:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="https://github.com/derekparker/delve">Delve</a>:
|
||||||
|
Delve is a debugger for the Go programming language. It has
|
||||||
|
support for Go’s runtime concepts and built-in types. Delve is
|
||||||
|
trying to be a fully featured reliable debugger for Go programs.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://golang.org/doc/gdb">GDB</a>:
|
||||||
|
Go provides GDB support via the standard Go compiler and Gccgo.
|
||||||
|
The stack management, threading, and runtime contain aspects that differ
|
||||||
|
enough from the execution model GDB expects that they can confuse the
|
||||||
|
debugger, even when the program is compiled with gccgo. Even though
|
||||||
|
GDB can be used to debug Go programs, it is not ideal and may
|
||||||
|
create confusion.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p><strong>How well do debuggers work with Go programs?</strong></p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
As of Go 1.9, the DWARF info generated by the gc compiler is not complete
|
||||||
|
and sometimes makes debugging harder. There is an ongoing effort to improve the
|
||||||
|
DWARF information to help the debuggers display more accurate information.
|
||||||
|
Until those improvements are in you may prefer to disable compiler
|
||||||
|
optimizations during development for more accuracy. To disable optimizations,
|
||||||
|
use the "-N -l" compiler flags. For example, the following command builds
|
||||||
|
a package with no compiler optimizations:
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<pre>
|
||||||
|
$ go build -gcflags="-N -l"
|
||||||
|
</pre>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
As of Go 1.10, the Go binaries will have the required DWARF information
|
||||||
|
for accurate debugging. To enable the DWARF improvements, use the following
|
||||||
|
compiler flags and use GDB until Delve supports location lists:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<pre>
|
||||||
|
$ go build -gcflags="-dwarflocationlists=true"
|
||||||
|
</pre>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><strong>What’s the recommended debugger user interface?</strong></p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Even though both delve and gdb provides CLIs, most editor integrations
|
||||||
|
and IDEs provides debugging-specific user interfaces. Please refer to
|
||||||
|
the <a href="/doc/editors.html">editors guide</a> to see the options
|
||||||
|
with debugger UI support.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><strong>Is it possible to do postmortem debugging with Go programs?</strong></p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
A core dump file is a file that contains the memory dump of a running
|
||||||
|
process and its process status. It is primarily used for post-mortem
|
||||||
|
debugging of a program and to understand its state
|
||||||
|
while it is still running. These two cases make debugging of core
|
||||||
|
dumps a good diagnostic aid to postmortem and analyze production
|
||||||
|
services. It is possible to obtain core files from Go programs and
|
||||||
|
use delve or gdb to debug, see the
|
||||||
|
<a href="https://golang.org/wiki/CoreDumpDebugging">core dump debugging</a>
|
||||||
|
page for a step-by-step guide.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="runtime">Runtime statistics and events</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The runtime provides stats and reporting of internal events for
|
||||||
|
users to diagnose performance and utilization problems at the
|
||||||
|
runtime level.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Users can monitor these stats to better understand the overall
|
||||||
|
health and performance of Go programs.
|
||||||
|
Some frequently monitored stats and states:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><code><a href="/pkg/runtime/#ReadMemStats">runtime.ReadMemStats</a></code>
|
||||||
|
reports the metrics related to heap
|
||||||
|
allocation and garbage collection. Memory stats are useful for
|
||||||
|
monitoring how much memory resources a process is consuming,
|
||||||
|
whether the process can utilize memory well, and to catch
|
||||||
|
memory leaks.</li>
|
||||||
|
<li><code><a href="/pkg/runtime/debug/#ReadGCStats">debug.ReadGCStats</a></code>
|
||||||
|
reads statistics about garbage collection.
|
||||||
|
It is useful to see how much of the resources are spent on GC pauses.
|
||||||
|
It also reports a timeline of garbage collector pauses and pause time percentiles.</li>
|
||||||
|
<li><code><a href="/pkg/runtime/debug/#Stack">debug.Stack</a></code>
|
||||||
|
returns the current stack trace. Stack trace
|
||||||
|
is useful to see how many goroutines are currently running,
|
||||||
|
what they are doing, and whether they are blocked or not.</li>
|
||||||
|
<li><code><a href="/pkg/runtime/debug/#WriteHeapDump">debug.WriteHeapDump</a></code>
|
||||||
|
suspends the execution of all goroutines
|
||||||
|
and allows you to dump the heap to a file. A heap dump is a
|
||||||
|
snapshot of a Go process' memory at a given time. It contains all
|
||||||
|
allocated objects as well as goroutines, finalizers, and more.</li>
|
||||||
|
<li><code><a href="/pkg/runtime#NumGoroutine">runtime.NumGoroutine</a></code>
|
||||||
|
returns the number of current goroutines.
|
||||||
|
The value can be monitored to see whether enough goroutines are
|
||||||
|
utilized, or to detect goroutine leaks.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 id="execution-tracer">Execution tracer</h3>
|
||||||
|
|
||||||
|
<p>Go comes with a runtime execution tracer to capture a wide range
|
||||||
|
of runtime events. Scheduling, syscall, garbage collections,
|
||||||
|
heap size, and other events are collected by runtime and available
|
||||||
|
for visualization by the go tool trace. Execution tracer is a tool
|
||||||
|
to detect latency and utilization problems. You can examine how well
|
||||||
|
the CPU is utilized, and when networking or syscalls are a cause of
|
||||||
|
preemption for the goroutines.</p>
|
||||||
|
|
||||||
|
<p>Tracer is useful to:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Understand how your goroutines execute.</li>
|
||||||
|
<li>Understand some of the core runtime events such as GC runs.</li>
|
||||||
|
<li>Identify poorly parallelized execution.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>However, it is not great for identifying hot spots such as
|
||||||
|
analyzing the cause of excessive memory or CPU usage.
|
||||||
|
Use profiling tools instead first to address them.</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<img width="800" src="https://storage.googleapis.com/golangorg-assets/tracer-lock.png">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Above, the go tool trace visualization shows the execution started
|
||||||
|
fine, and then it became serialized. It suggests that there might
|
||||||
|
be lock contention for a shared resource that creates a bottleneck.</p>
|
||||||
|
|
||||||
|
<p>See <a href="https://golang.org/cmd/trace/"><code>go tool trace</code></a>
|
||||||
|
to collect and analyze runtime traces.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="godebug">GODEBUG</h3>
|
||||||
|
|
||||||
|
<p>Runtime also emits events and information if
|
||||||
|
<a href="https://golang.org/pkg/runtime/#hdr-Environment_Variables">GODEBUG</a>
|
||||||
|
environmental variable is set accordingly.</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>GODEBUG=gctrace=1 prints garbage collector events at
|
||||||
|
each collection, summarizing the amount of memory collected
|
||||||
|
and the length of the pause.</li>
|
||||||
|
<li>GODEBUG=schedtrace=X prints scheduling events every X milliseconds.</li>
|
||||||
|
</ul>
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<!--{
|
<!--{
|
||||||
"Title": "Documentation",
|
"Title": "Documentation",
|
||||||
"Path": "/doc/"
|
"Path": "/doc/",
|
||||||
|
"Template": true
|
||||||
}-->
|
}-->
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -33,28 +34,37 @@ libraries.
|
||||||
|
|
||||||
<img class="gopher" src="/doc/gopher/doc.png"/>
|
<img class="gopher" src="/doc/gopher/doc.png"/>
|
||||||
|
|
||||||
<h3 id="go_tour"><a href="//tour.golang.org/">A Tour of Go</a></h3>
|
<h3 id="go_tour">
|
||||||
|
{{if $.GoogleCN}}
|
||||||
|
A Tour of Go
|
||||||
|
{{else}}
|
||||||
|
<a href="//tour.golang.org/">A Tour of Go</a>
|
||||||
|
{{end}}
|
||||||
|
</h3>
|
||||||
<p>
|
<p>
|
||||||
An interactive introduction to Go in three sections.
|
An interactive introduction to Go in three sections.
|
||||||
The first section covers basic syntax and data structures; the second discusses
|
The first section covers basic syntax and data structures; the second discusses
|
||||||
methods and interfaces; and the third introduces Go's concurrency primitives.
|
methods and interfaces; and the third introduces Go's concurrency primitives.
|
||||||
Each section concludes with a few exercises so you can practice what you've
|
Each section concludes with a few exercises so you can practice what you've
|
||||||
learned. You can <a href="//tour.golang.org/">take the tour online</a> or
|
learned. You can {{if not $.GoogleCN}}<a href="//tour.golang.org/">take the tour
|
||||||
install it locally with:
|
online</a> or{{end}} install it locally with:
|
||||||
</p>
|
</p>
|
||||||
<p>
|
|
||||||
<pre>
|
<pre>
|
||||||
$ go get golang.org/x/tour/gotour
|
$ go get golang.org/x/tour/gotour
|
||||||
</pre>
|
</pre>
|
||||||
|
<p>
|
||||||
This will place the <code>gotour</code> binary in your workspace's <code>bin</code> directory.
|
This will place the <code>gotour</code> binary in your workspace's <code>bin</code> directory.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="code"><a href="code.html">How to write Go code</a></h3>
|
<h3 id="code"><a href="code.html">How to write Go code</a></h3>
|
||||||
<p>
|
<p>
|
||||||
Also available as a
|
{{if not $.GoogleCN}}
|
||||||
<a href="//www.youtube.com/watch?v=XCsL89YtqCs">screencast</a>, this doc
|
Also available as a <a href="//www.youtube.com/watch?v=XCsL89YtqCs">screencast</a>, this
|
||||||
explains how to use the <a href="/cmd/go/">go command</a> to fetch, build, and
|
{{else}}
|
||||||
install packages, commands, and run tests.
|
This
|
||||||
|
{{end}}
|
||||||
|
doc explains how to use the <a href="/cmd/go/">go command</a>
|
||||||
|
to fetch, build, and install packages, commands, and run tests.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="editors"><a href="editors.html">Editor plugins and IDEs</a></h3>
|
<h3 id="editors"><a href="editors.html">Editor plugins and IDEs</a></h3>
|
||||||
|
|
@ -70,6 +80,11 @@ A must read for any new Go programmer. It augments the tour and
|
||||||
the language specification, both of which should be read first.
|
the language specification, both of which should be read first.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h3 id="diagnostics"><a href="/doc/diagnostics.html">Diagnostics</a></h3>
|
||||||
|
<p>
|
||||||
|
Summarizes tools and methodologies to diagnose problems in Go programs.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3 id="faq"><a href="/doc/faq">Frequently Asked Questions (FAQ)</a></h3>
|
<h3 id="faq"><a href="/doc/faq">Frequently Asked Questions (FAQ)</a></h3>
|
||||||
<p>
|
<p>
|
||||||
Answers to common questions about Go.
|
Answers to common questions about Go.
|
||||||
|
|
@ -115,9 +130,11 @@ same variable in a different goroutine.
|
||||||
|
|
||||||
<h2 id="articles">Articles</h2>
|
<h2 id="articles">Articles</h2>
|
||||||
|
|
||||||
|
{{if not $.GoogleCN}}
|
||||||
<h3 id="blog"><a href="//blog.golang.org/">The Go Blog</a></h3>
|
<h3 id="blog"><a href="//blog.golang.org/">The Go Blog</a></h3>
|
||||||
<p>The official blog of the Go project, featuring news and in-depth articles by
|
<p>The official blog of the Go project, featuring news and in-depth articles by
|
||||||
the Go team and guests.</p>
|
the Go team and guests.</p>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
<h4>Codewalks</h4>
|
<h4>Codewalks</h4>
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -130,6 +147,7 @@ Guided tours of Go programs.
|
||||||
<li><a href="/doc/articles/wiki/">Writing Web Applications</a> - building a simple web application.</li>
|
<li><a href="/doc/articles/wiki/">Writing Web Applications</a> - building a simple web application.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
{{if not $.GoogleCN}}
|
||||||
<h4>Language</h4>
|
<h4>Language</h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="/blog/json-rpc-tale-of-interfaces">JSON-RPC: a tale of interfaces</a></li>
|
<li><a href="/blog/json-rpc-tale-of-interfaces">JSON-RPC: a tale of interfaces</a></li>
|
||||||
|
|
@ -150,17 +168,20 @@ Guided tours of Go programs.
|
||||||
<li><a href="/blog/go-image-package">The Go image package</a> - the fundamentals of the <a href="/pkg/image/">image</a> package.</li>
|
<li><a href="/blog/go-image-package">The Go image package</a> - the fundamentals of the <a href="/pkg/image/">image</a> package.</li>
|
||||||
<li><a href="/blog/go-imagedraw-package">The Go image/draw package</a> - the fundamentals of the <a href="/pkg/image/draw/">image/draw</a> package.</li>
|
<li><a href="/blog/go-imagedraw-package">The Go image/draw package</a> - the fundamentals of the <a href="/pkg/image/draw/">image/draw</a> package.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
<h4>Tools</h4>
|
<h4>Tools</h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="/doc/articles/go_command.html">About the Go command</a> - why we wrote it, what it is, what it's not, and how to use it.</li>
|
<li><a href="/doc/articles/go_command.html">About the Go command</a> - why we wrote it, what it is, what it's not, and how to use it.</li>
|
||||||
<li><a href="/blog/c-go-cgo">C? Go? Cgo!</a> - linking against C code with <a href="/cmd/cgo/">cgo</a>.</li>
|
|
||||||
<li><a href="/doc/gdb">Debugging Go Code with GDB</a></li>
|
<li><a href="/doc/gdb">Debugging Go Code with GDB</a></li>
|
||||||
|
<li><a href="/doc/articles/race_detector.html">Data Race Detector</a> - a manual for the data race detector.</li>
|
||||||
|
<li><a href="/doc/asm">A Quick Guide to Go's Assembler</a> - an introduction to the assembler used by Go.</li>
|
||||||
|
{{if not $.GoogleCN}}
|
||||||
|
<li><a href="/blog/c-go-cgo">C? Go? Cgo!</a> - linking against C code with <a href="/cmd/cgo/">cgo</a>.</li>
|
||||||
<li><a href="/blog/godoc-documenting-go-code">Godoc: documenting Go code</a> - writing good documentation for <a href="/cmd/godoc/">godoc</a>.</li>
|
<li><a href="/blog/godoc-documenting-go-code">Godoc: documenting Go code</a> - writing good documentation for <a href="/cmd/godoc/">godoc</a>.</li>
|
||||||
<li><a href="/blog/profiling-go-programs">Profiling Go Programs</a></li>
|
<li><a href="/blog/profiling-go-programs">Profiling Go Programs</a></li>
|
||||||
<li><a href="/doc/articles/race_detector.html">Data Race Detector</a> - a manual for the data race detector.</li>
|
|
||||||
<li><a href="/blog/race-detector">Introducing the Go Race Detector</a> - an introduction to the race detector.</li>
|
<li><a href="/blog/race-detector">Introducing the Go Race Detector</a> - an introduction to the race detector.</li>
|
||||||
<li><a href="/doc/asm">A Quick Guide to Go's Assembler</a> - an introduction to the assembler used by Go.</li>
|
{{end}}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h4 id="articles_more">More</h4>
|
<h4 id="articles_more">More</h4>
|
||||||
|
|
@ -169,7 +190,7 @@ See the <a href="/wiki/Articles">Articles page</a> at the
|
||||||
<a href="/wiki">Wiki</a> for more Go articles.
|
<a href="/wiki">Wiki</a> for more Go articles.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
{{if not $.GoogleCN}}
|
||||||
<h2 id="talks">Talks</h2>
|
<h2 id="talks">Talks</h2>
|
||||||
|
|
||||||
<img class="gopher" src="/doc/gopher/talks.png"/>
|
<img class="gopher" src="/doc/gopher/talks.png"/>
|
||||||
|
|
@ -200,7 +221,7 @@ This talk expands on the <i>Go Concurrency Patterns</i> talk to dive deeper into
|
||||||
<p>
|
<p>
|
||||||
See the <a href="/talks">Go Talks site</a> and <a href="/wiki/GoTalks">wiki page</a> for more Go talks.
|
See the <a href="/talks">Go Talks site</a> and <a href="/wiki/GoTalks">wiki page</a> for more Go talks.
|
||||||
</p>
|
</p>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
<h2 id="nonenglish">Non-English Documentation</h2>
|
<h2 id="nonenglish">Non-English Documentation</h2>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@ editing, navigation, testing, and debugging experience.
|
||||||
<li><a href="https://github.com/fatih/vim-go">vim</a>: vim-go plugin provides Go programming language support</li>
|
<li><a href="https://github.com/fatih/vim-go">vim</a>: vim-go plugin provides Go programming language support</li>
|
||||||
<li><a href="https://marketplace.visualstudio.com/items?itemName=lukehoban.Go">Visual Studio Code</a>:
|
<li><a href="https://marketplace.visualstudio.com/items?itemName=lukehoban.Go">Visual Studio Code</a>:
|
||||||
Go extension provides support for the Go programming language</li>
|
Go extension provides support for the Go programming language</li>
|
||||||
<li><a href="https://www.jetbrains.com/go">Gogland</a>: Gogland is distributed either as a standalone IDE
|
<li><a href="https://www.jetbrains.com/go">GoLand</a>: GoLand is distributed either as a standalone IDE
|
||||||
or as a plugin for the commercial IntelliJ Platform IDEs</li>
|
or as a plugin for IntelliJ IDEA Ultimate</li>
|
||||||
<li><a href="https://atom.io/packages/go-plus">Atom</a>: Go-Plus is an Atom package that provides enhanced Go support</li>
|
<li><a href="https://atom.io/packages/go-plus">Atom</a>: Go-Plus is an Atom package that provides enhanced Go support</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
@ -44,7 +44,7 @@ The following feature matrix lists and compares the most significant features.
|
||||||
<th></th>
|
<th></th>
|
||||||
<th><img title="Vim Go" src="/doc/editors/vimgo.png"><br>vim</th>
|
<th><img title="Vim Go" src="/doc/editors/vimgo.png"><br>vim</th>
|
||||||
<th><img title="Visual Studio Code" src="/doc/editors/vscodego.png"><br>Visual Studio Code</th>
|
<th><img title="Visual Studio Code" src="/doc/editors/vscodego.png"><br>Visual Studio Code</th>
|
||||||
<th><img title="Gogland" src="/doc/editors/gogland.png"><br>Gogland</th>
|
<th><img title="GoLand" src="/doc/editors/goland.png"><br>GoLand</th>
|
||||||
<th><img title="Go-Plus" src="/doc/editors/go-plus.png"><br>Atom</th>
|
<th><img title="Go-Plus" src="/doc/editors/go-plus.png"><br>Atom</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -159,7 +159,7 @@ The following feature matrix lists and compares the most significant features.
|
||||||
<td>Auto generate tests for packages, files and identifiers</td>
|
<td>Auto generate tests for packages, files and identifiers</td>
|
||||||
<td class="no">No</td>
|
<td class="no">No</td>
|
||||||
<td class="yes">Yes</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="no">No</td>
|
<td class="yes">Yes</td>
|
||||||
<td class="no">No</td>
|
<td class="no">No</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 9.2 KiB |
|
|
@ -1431,9 +1431,7 @@ func Append(slice, data []byte) []byte {
|
||||||
slice = newSlice
|
slice = newSlice
|
||||||
}
|
}
|
||||||
slice = slice[0:l+len(data)]
|
slice = slice[0:l+len(data)]
|
||||||
for i, c := range data {
|
copy(slice[l:], data)
|
||||||
slice[l+i] = c
|
|
||||||
}
|
|
||||||
return slice
|
return slice
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
@ -1521,7 +1519,7 @@ for i := range picture {
|
||||||
<p>
|
<p>
|
||||||
Maps are a convenient and powerful built-in data structure that associate
|
Maps are a convenient and powerful built-in data structure that associate
|
||||||
values of one type (the <em>key</em>) with values of another type
|
values of one type (the <em>key</em>) with values of another type
|
||||||
(the <em>element</em> or <em>value</em>)
|
(the <em>element</em> or <em>value</em>).
|
||||||
The key can be of any type for which the equality operator is defined,
|
The key can be of any type for which the equality operator is defined,
|
||||||
such as integers,
|
such as integers,
|
||||||
floating point and complex numbers,
|
floating point and complex numbers,
|
||||||
|
|
@ -2792,7 +2790,7 @@ job := &Job{command, log.New(os.Stderr, "Job: ", log.Ldate)}
|
||||||
<p>
|
<p>
|
||||||
If we need to refer to an embedded field directly, the type name of the field,
|
If we need to refer to an embedded field directly, the type name of the field,
|
||||||
ignoring the package qualifier, serves as a field name, as it did
|
ignoring the package qualifier, serves as a field name, as it did
|
||||||
in the <code>Read</code> method of our <code>ReaderWriter</code> struct.
|
in the <code>Read</code> method of our <code>ReadWriter</code> struct.
|
||||||
Here, if we needed to access the
|
Here, if we needed to access the
|
||||||
<code>*log.Logger</code> of a <code>Job</code> variable <code>job</code>,
|
<code>*log.Logger</code> of a <code>Job</code> variable <code>job</code>,
|
||||||
we would write <code>job.Logger</code>,
|
we would write <code>job.Logger</code>,
|
||||||
|
|
|
||||||
|
|
@ -59,10 +59,17 @@ should not be visible to Go programs.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The GCC 7 releases are expected to include a complete implementation
|
The GCC 7 releases include a complete implementation of the Go 1.8.1
|
||||||
of the Go 1.8 user libraries. As with earlier releases, the Go 1.8
|
user libraries. As with earlier releases, the Go 1.8 runtime is not
|
||||||
runtime is not fully merged, but that should not be visible to Go
|
fully merged, but that should not be visible to Go programs.
|
||||||
programs.
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The GCC 8 releases are expected to include a complete implementation
|
||||||
|
of the Go 1.10 release, depending on release timing. The Go 1.10
|
||||||
|
runtime has now been fully merged into the GCC development sources,
|
||||||
|
and concurrent garbage collection is expected to be fully supported in
|
||||||
|
GCC 8.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 id="Source_code">Source code</h2>
|
<h2 id="Source_code">Source code</h2>
|
||||||
|
|
|
||||||
1240
doc/go1.10.html
Normal file
1240
doc/go1.10.html
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -719,6 +719,11 @@ version of gccgo.
|
||||||
header when matching handlers. The host is matched unmodified for <code>CONNECT</code> requests.
|
header when matching handlers. The host is matched unmodified for <code>CONNECT</code> requests.
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li><!-- CL 44074 -->
|
||||||
|
The new <a href="/pkg/net/http/#Server.ServeTLS"><code>Server.ServeTLS</code></a> method wraps
|
||||||
|
<a href="/pkg/net/http/#Server.Serve"><code>Server.Serve</code></a> with added TLS support.
|
||||||
|
</li>
|
||||||
|
|
||||||
<li><!-- CL 34727 -->
|
<li><!-- CL 34727 -->
|
||||||
<a href="/pkg/net/http/#Server.WriteTimeout"><code>Server.WriteTimeout</code></a>
|
<a href="/pkg/net/http/#Server.WriteTimeout"><code>Server.WriteTimeout</code></a>
|
||||||
now applies to HTTP/2 connections and is enforced per-stream.
|
now applies to HTTP/2 connections and is enforced per-stream.
|
||||||
|
|
|
||||||
|
|
@ -1476,6 +1476,53 @@ For more detail on this topic see the talk entitled,
|
||||||
<a href="//blog.golang.org/2013/01/concurrency-is-not-parallelism.html">Concurrency
|
<a href="//blog.golang.org/2013/01/concurrency-is-not-parallelism.html">Concurrency
|
||||||
is not Parallelism</a>.
|
is not Parallelism</a>.
|
||||||
|
|
||||||
|
<h3 id="no_goroutine_id">
|
||||||
|
Why is there no goroutine ID?</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Goroutines do not have names; they are just anonymous workers.
|
||||||
|
They expose no unique identifier, name, or data structure to the programmer.
|
||||||
|
Some people are surprised by this, expecting the <code>go</code>
|
||||||
|
statement to return some item that can be used to access and control
|
||||||
|
the goroutine later.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The fundamental reason goroutines are anonymous is so that
|
||||||
|
the full Go language is available when programming concurrent code.
|
||||||
|
By contrast, the usage patterns that develop when threads and goroutines are
|
||||||
|
named can restrict what a library using them can do.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Here is an illustration of the difficulties.
|
||||||
|
Once one names a goroutine and constructs a model around
|
||||||
|
it, it becomes special, and one is tempted to associate all computation
|
||||||
|
with that goroutine, ignoring the possibility
|
||||||
|
of using multiple, possibly shared goroutines for the processing.
|
||||||
|
If the <code>net/http</code> package associated per-request
|
||||||
|
state with a goroutine,
|
||||||
|
clients would be unable to use more goroutines
|
||||||
|
when serving a request.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Moreover, experience with libraries such as those for graphics systems
|
||||||
|
that require all processing to occur on the "main thread"
|
||||||
|
has shown how awkward and limiting the approach can be when
|
||||||
|
deployed in a concurrent language.
|
||||||
|
The very existence of a special thread or goroutine forces
|
||||||
|
the programmer to distort the program to avoid crashes
|
||||||
|
and other problems caused by inadvertently operating
|
||||||
|
on the wrong thread.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
For those cases where a particular goroutine is truly special,
|
||||||
|
the language provides features such as channels that can be
|
||||||
|
used in flexible ways to interact with it.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h2 id="Functions_methods">Functions and Methods</h2>
|
<h2 id="Functions_methods">Functions and Methods</h2>
|
||||||
|
|
||||||
<h3 id="different_method_sets">
|
<h3 id="different_method_sets">
|
||||||
|
|
|
||||||
241
doc/go_spec.html
241
doc/go_spec.html
|
|
@ -1,6 +1,6 @@
|
||||||
<!--{
|
<!--{
|
||||||
"Title": "The Go Programming Language Specification",
|
"Title": "The Go Programming Language Specification",
|
||||||
"Subtitle": "Version of June 28, 2017",
|
"Subtitle": "Version of October 25, 2017",
|
||||||
"Path": "/ref/spec"
|
"Path": "/ref/spec"
|
||||||
}-->
|
}-->
|
||||||
|
|
||||||
|
|
@ -16,8 +16,7 @@ Go is a general-purpose language designed with systems programming
|
||||||
in mind. It is strongly typed and garbage-collected and has explicit
|
in mind. It is strongly typed and garbage-collected and has explicit
|
||||||
support for concurrent programming. Programs are constructed from
|
support for concurrent programming. Programs are constructed from
|
||||||
<i>packages</i>, whose properties allow efficient management of
|
<i>packages</i>, whose properties allow efficient management of
|
||||||
dependencies. The existing implementations use a traditional
|
dependencies.
|
||||||
compile/link model to generate executable binaries.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -577,11 +576,7 @@ or <a href="#Conversions">conversion</a>, or implicitly when used in a
|
||||||
<a href="#Assignments">assignment</a> or as an
|
<a href="#Assignments">assignment</a> or as an
|
||||||
operand in an <a href="#Expressions">expression</a>.
|
operand in an <a href="#Expressions">expression</a>.
|
||||||
It is an error if the constant value
|
It is an error if the constant value
|
||||||
cannot be represented as a value of the respective type.
|
cannot be <a href="#Representability">represented</a> as a value of the respective type.
|
||||||
For instance, <code>3.0</code> can be given any integer or any
|
|
||||||
floating-point type, while <code>2147483648.0</code> (equal to <code>1<<31</code>)
|
|
||||||
can be given the types <code>float32</code>, <code>float64</code>, or <code>uint32</code> but
|
|
||||||
not <code>int32</code> or <code>string</code>.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -765,7 +760,8 @@ using a receiver of that type.
|
||||||
<p>
|
<p>
|
||||||
A <i>boolean type</i> represents the set of Boolean truth values
|
A <i>boolean type</i> represents the set of Boolean truth values
|
||||||
denoted by the predeclared constants <code>true</code>
|
denoted by the predeclared constants <code>true</code>
|
||||||
and <code>false</code>. The predeclared boolean type is <code>bool</code>.
|
and <code>false</code>. The predeclared boolean type is <code>bool</code>;
|
||||||
|
it is a <a href="#Type_definitions">defined type</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="Numeric_types">Numeric types</h3>
|
<h3 id="Numeric_types">Numeric types</h3>
|
||||||
|
|
@ -812,8 +808,9 @@ uintptr an unsigned integer large enough to store the uninterpreted bits of a p
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
To avoid portability issues all numeric types are distinct except
|
To avoid portability issues all numeric types are <a href="#Type_definitions">defined
|
||||||
<code>byte</code>, which is an alias for <code>uint8</code>, and
|
types</a> and thus distinct except
|
||||||
|
<code>byte</code>, which is an <a href="#Alias_declarations">alias</a> for <code>uint8</code>, and
|
||||||
<code>rune</code>, which is an alias for <code>int32</code>.
|
<code>rune</code>, which is an alias for <code>int32</code>.
|
||||||
Conversions
|
Conversions
|
||||||
are required when different numeric types are mixed in an expression
|
are required when different numeric types are mixed in an expression
|
||||||
|
|
@ -829,7 +826,8 @@ A <i>string type</i> represents the set of string values.
|
||||||
A string value is a (possibly empty) sequence of bytes.
|
A string value is a (possibly empty) sequence of bytes.
|
||||||
Strings are immutable: once created,
|
Strings are immutable: once created,
|
||||||
it is impossible to change the contents of a string.
|
it is impossible to change the contents of a string.
|
||||||
The predeclared string type is <code>string</code>.
|
The predeclared string type is <code>string</code>;
|
||||||
|
it is a <a href="#Type_definitions">defined type</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -861,7 +859,8 @@ ElementType = Type .
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The length is part of the array's type; it must evaluate to a
|
The length is part of the array's type; it must evaluate to a
|
||||||
non-negative <a href="#Constants">constant</a> representable by a value
|
non-negative <a href="#Constants">constant</a>
|
||||||
|
<a href="#Representability">representable</a> by a value
|
||||||
of type <code>int</code>.
|
of type <code>int</code>.
|
||||||
The length of array <code>a</code> can be discovered
|
The length of array <code>a</code> can be discovered
|
||||||
using the built-in function <a href="#Length_and_capacity"><code>len</code></a>.
|
using the built-in function <a href="#Length_and_capacity"><code>len</code></a>.
|
||||||
|
|
@ -1514,7 +1513,7 @@ are different because <code>B0</code> is different from <code>[]string</code>.
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
A value <code>x</code> is <i>assignable</i> to a <a href="#Variables">variable</a> of type <code>T</code>
|
A value <code>x</code> is <i>assignable</i> to a <a href="#Variables">variable</a> of type <code>T</code>
|
||||||
("<code>x</code> is assignable to <code>T</code>") in any of these cases:
|
("<code>x</code> is assignable to <code>T</code>") if one of the following conditions applies:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
@ -1540,12 +1539,68 @@ and at least one of <code>V</code> or <code>T</code> is not a defined type.
|
||||||
is a pointer, function, slice, map, channel, or interface type.
|
is a pointer, function, slice, map, channel, or interface type.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<code>x</code> is an untyped <a href="#Constants">constant</a> representable
|
<code>x</code> is an untyped <a href="#Constants">constant</a>
|
||||||
|
<a href="#Representability">representable</a>
|
||||||
by a value of type <code>T</code>.
|
by a value of type <code>T</code>.
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="Representability">Representability</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
A <a href="#Constants">constant</a> <code>x</code> is <i>representable</i>
|
||||||
|
by a value of type <code>T</code> if one of the following conditions applies:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<code>x</code> is in the set of values <a href="#Types">determined</a> by <code>T</code>.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<code>T</code> is a floating-point type and <code>x</code> can be rounded to <code>T</code>'s
|
||||||
|
precision without overflow. Rounding uses IEEE 754 round-to-even rules but with an IEEE
|
||||||
|
negative zero further simplified to an unsigned zero. Note that constant values never result
|
||||||
|
in an IEEE negative zero, NaN, or infinity.
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<code>T</code> is a complex type, and <code>x</code>'s
|
||||||
|
<a href="#Complex_numbers">components</a> <code>real(x)</code> and <code>imag(x)</code>
|
||||||
|
are representable by values of <code>T</code>'s component type (<code>float32</code> or
|
||||||
|
<code>float64</code>).
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
x T x is representable by a value of T because
|
||||||
|
|
||||||
|
'a' byte 97 is in the set of byte values
|
||||||
|
97 rune rune is an alias for int32, and 97 is in the set of 32-bit integers
|
||||||
|
"foo" string "foo" is in the set of string values
|
||||||
|
1024 int16 1024 is in the set of 16-bit integers
|
||||||
|
42.0 byte 42 is in the set of unsigned 8-bit integers
|
||||||
|
1e10 uint64 10000000000 is in the set of unsigned 64-bit integers
|
||||||
|
2.718281828459045 float32 2.718281828459045 rounds to 2.7182817 which is in the set of float32 values
|
||||||
|
-1e-1000 float64 -1e-1000 rounds to IEEE -0.0 which is further simplified to 0.0
|
||||||
|
0i int 0 is an integer value
|
||||||
|
(42 + 0i) float32 42.0 (with zero imaginary part) is in the set of float32 values
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
x T x is not representable by a value of T because
|
||||||
|
|
||||||
|
0 bool 0 is not in the set of boolean values
|
||||||
|
'a' string 'a' is a rune, it is not in the set of string values
|
||||||
|
1024 byte 1024 is not in the set of unsigned 8-bit integers
|
||||||
|
-1 uint16 -1 is not in the set of unsigned 16-bit integers
|
||||||
|
1.1 int 1.1 is not an integer value
|
||||||
|
42i float32 (0 + 42i) is not in the set of float32 values
|
||||||
|
1e1000 float64 1e1000 overflows to IEEE +Inf after rounding
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
<h2 id="Blocks">Blocks</h2>
|
<h2 id="Blocks">Blocks</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -1781,7 +1836,7 @@ const u, v float32 = 0, 3 // u = 0.0, v = 3.0
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Within a parenthesized <code>const</code> declaration list the
|
Within a parenthesized <code>const</code> declaration list the
|
||||||
expression list may be omitted from any but the first declaration.
|
expression list may be omitted from any but the first ConstSpec.
|
||||||
Such an empty list is equivalent to the textual substitution of the
|
Such an empty list is equivalent to the textual substitution of the
|
||||||
first preceding non-empty expression list and its type if any.
|
first preceding non-empty expression list and its type if any.
|
||||||
Omitting the list of expressions is therefore equivalent to
|
Omitting the list of expressions is therefore equivalent to
|
||||||
|
|
@ -1810,52 +1865,51 @@ const (
|
||||||
<p>
|
<p>
|
||||||
Within a <a href="#Constant_declarations">constant declaration</a>, the predeclared identifier
|
Within a <a href="#Constant_declarations">constant declaration</a>, the predeclared identifier
|
||||||
<code>iota</code> represents successive untyped integer <a href="#Constants">
|
<code>iota</code> represents successive untyped integer <a href="#Constants">
|
||||||
constants</a>. It is reset to 0 whenever the reserved word <code>const</code>
|
constants</a>. Its value is the index of the respective <a href="#ConstSpec">ConstSpec</a>
|
||||||
appears in the source and increments after each <a href="#ConstSpec">ConstSpec</a>.
|
in that constant declaration, starting at zero.
|
||||||
It can be used to construct a set of related constants:
|
It can be used to construct a set of related constants:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
const ( // iota is reset to 0
|
const (
|
||||||
c0 = iota // c0 == 0
|
c0 = iota // c0 == 0
|
||||||
c1 = iota // c1 == 1
|
c1 = iota // c1 == 1
|
||||||
c2 = iota // c2 == 2
|
c2 = iota // c2 == 2
|
||||||
)
|
)
|
||||||
|
|
||||||
const ( // iota is reset to 0
|
const (
|
||||||
a = 1 << iota // a == 1
|
a = 1 << iota // a == 1 (iota == 0)
|
||||||
b = 1 << iota // b == 2
|
b = 1 << iota // b == 2 (iota == 1)
|
||||||
c = 3 // c == 3 (iota is not used but still incremented)
|
c = 3 // c == 3 (iota == 2, unused)
|
||||||
d = 1 << iota // d == 8
|
d = 1 << iota // d == 8 (iota == 3)
|
||||||
)
|
)
|
||||||
|
|
||||||
const ( // iota is reset to 0
|
const (
|
||||||
u = iota * 42 // u == 0 (untyped integer constant)
|
u = iota * 42 // u == 0 (untyped integer constant)
|
||||||
v float64 = iota * 42 // v == 42.0 (float64 constant)
|
v float64 = iota * 42 // v == 42.0 (float64 constant)
|
||||||
w = iota * 42 // w == 84 (untyped integer constant)
|
w = iota * 42 // w == 84 (untyped integer constant)
|
||||||
)
|
)
|
||||||
|
|
||||||
const x = iota // x == 0 (iota has been reset)
|
const x = iota // x == 0
|
||||||
const y = iota // y == 0 (iota has been reset)
|
const y = iota // y == 0
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Within an ExpressionList, the value of each <code>iota</code> is the same because
|
By definition, multiple uses of <code>iota</code> in the same ConstSpec all have the same value:
|
||||||
it is only incremented after each ConstSpec:
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
const (
|
const (
|
||||||
bit0, mask0 = 1 << iota, 1<<iota - 1 // bit0 == 1, mask0 == 0
|
bit0, mask0 = 1 << iota, 1<<iota - 1 // bit0 == 1, mask0 == 0 (iota == 0)
|
||||||
bit1, mask1 // bit1 == 2, mask1 == 1
|
bit1, mask1 // bit1 == 2, mask1 == 1 (iota == 1)
|
||||||
_, _ // skips iota == 2
|
_, _ // (iota == 2, unused)
|
||||||
bit3, mask3 // bit3 == 8, mask3 == 7
|
bit3, mask3 // bit3 == 8, mask3 == 7 (iota == 3)
|
||||||
)
|
)
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
This last example exploits the implicit repetition of the
|
This last example exploits the <a href="#Constant_declarations">implicit repetition</a>
|
||||||
last non-empty expression list.
|
of the last non-empty expression list.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1946,7 +2000,7 @@ func (m *Mutex) Unlock() { /* Unlock implementation */ }
|
||||||
// NewMutex has the same composition as Mutex but its method set is empty.
|
// NewMutex has the same composition as Mutex but its method set is empty.
|
||||||
type NewMutex Mutex
|
type NewMutex Mutex
|
||||||
|
|
||||||
// The method set of the <a href="#Pointer_types">base type</a> of PtrMutex remains unchanged,
|
// The method set of PtrMutex's underlying type *Mutex remains unchanged,
|
||||||
// but the method set of PtrMutex is empty.
|
// but the method set of PtrMutex is empty.
|
||||||
type PtrMutex *Mutex
|
type PtrMutex *Mutex
|
||||||
|
|
||||||
|
|
@ -2224,7 +2278,6 @@ non-<a href="#Blank_identifier">blank</a> identifier denoting a
|
||||||
<a href="#Constant_declarations">constant</a>,
|
<a href="#Constant_declarations">constant</a>,
|
||||||
<a href="#Variable_declarations">variable</a>, or
|
<a href="#Variable_declarations">variable</a>, or
|
||||||
<a href="#Function_declarations">function</a>,
|
<a href="#Function_declarations">function</a>,
|
||||||
a <a href="#Method_expressions">method expression</a> yielding a function,
|
|
||||||
or a parenthesized expression.
|
or a parenthesized expression.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
@ -2234,7 +2287,7 @@ operand only on the left-hand side of an <a href="#Assignments">assignment</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre class="ebnf">
|
<pre class="ebnf">
|
||||||
Operand = Literal | OperandName | MethodExpr | "(" Expression ")" .
|
Operand = Literal | OperandName | "(" Expression ")" .
|
||||||
Literal = BasicLit | CompositeLit | FunctionLit .
|
Literal = BasicLit | CompositeLit | FunctionLit .
|
||||||
BasicLit = int_lit | float_lit | imaginary_lit | rune_lit | string_lit .
|
BasicLit = int_lit | float_lit | imaginary_lit | rune_lit | string_lit .
|
||||||
OperandName = identifier | QualifiedIdent.
|
OperandName = identifier | QualifiedIdent.
|
||||||
|
|
@ -2348,7 +2401,8 @@ For array and slice literals the following rules apply:
|
||||||
its position in the array.
|
its position in the array.
|
||||||
</li>
|
</li>
|
||||||
<li>An element with a key uses the key as its index. The
|
<li>An element with a key uses the key as its index. The
|
||||||
key must be a non-negative constant representable by
|
key must be a non-negative constant
|
||||||
|
<a href="#Representability">representable</a> by
|
||||||
a value of type <code>int</code>; and if it is typed
|
a value of type <code>int</code>; and if it is typed
|
||||||
it must be of integer type.
|
it must be of integer type.
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -2499,6 +2553,7 @@ Primary expressions are the operands for unary and binary expressions.
|
||||||
PrimaryExpr =
|
PrimaryExpr =
|
||||||
Operand |
|
Operand |
|
||||||
Conversion |
|
Conversion |
|
||||||
|
MethodExpr |
|
||||||
PrimaryExpr Selector |
|
PrimaryExpr Selector |
|
||||||
PrimaryExpr Index |
|
PrimaryExpr Index |
|
||||||
PrimaryExpr Slice |
|
PrimaryExpr Slice |
|
||||||
|
|
@ -2685,7 +2740,7 @@ argument that is the receiver of the method.
|
||||||
|
|
||||||
<pre class="ebnf">
|
<pre class="ebnf">
|
||||||
MethodExpr = ReceiverType "." MethodName .
|
MethodExpr = ReceiverType "." MethodName .
|
||||||
ReceiverType = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" .
|
ReceiverType = Type .
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -2921,11 +2976,12 @@ The following rules apply:
|
||||||
If <code>a</code> is not a map:
|
If <code>a</code> is not a map:
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>the index <code>x</code> must be of integer type or untyped;
|
<li>the index <code>x</code> must be of integer type or an untyped constant</li>
|
||||||
it is <i>in range</i> if <code>0 <= x < len(a)</code>,
|
<li>a constant index must be non-negative and
|
||||||
|
<a href="#Representability">representable</a> by a value of type <code>int</code></li>
|
||||||
|
<li>a constant index that is untyped is given type <code>int</code></li>
|
||||||
|
<li>the index <code>x</code> is <i>in range</i> if <code>0 <= x < len(a)</code>,
|
||||||
otherwise it is <i>out of range</i></li>
|
otherwise it is <i>out of range</i></li>
|
||||||
<li>a <a href="#Constants">constant</a> index must be non-negative
|
|
||||||
and representable by a value of type <code>int</code>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -3075,7 +3131,8 @@ For arrays or strings, the indices are <i>in range</i> if
|
||||||
<code>0</code> <= <code>low</code> <= <code>high</code> <= <code>len(a)</code>,
|
<code>0</code> <= <code>low</code> <= <code>high</code> <= <code>len(a)</code>,
|
||||||
otherwise they are <i>out of range</i>.
|
otherwise they are <i>out of range</i>.
|
||||||
For slices, the upper index bound is the slice capacity <code>cap(a)</code> rather than the length.
|
For slices, the upper index bound is the slice capacity <code>cap(a)</code> rather than the length.
|
||||||
A <a href="#Constants">constant</a> index must be non-negative and representable by a value of type
|
A <a href="#Constants">constant</a> index must be non-negative and
|
||||||
|
<a href="#Representability">representable</a> by a value of type
|
||||||
<code>int</code>; for arrays or constant strings, constant indices must also be in range.
|
<code>int</code>; for arrays or constant strings, constant indices must also be in range.
|
||||||
If both indices are constant, they must satisfy <code>low <= high</code>.
|
If both indices are constant, they must satisfy <code>low <= high</code>.
|
||||||
If the indices are out of range at run time, a <a href="#Run_time_panics">run-time panic</a> occurs.
|
If the indices are out of range at run time, a <a href="#Run_time_panics">run-time panic</a> occurs.
|
||||||
|
|
@ -3091,8 +3148,8 @@ and the result of the slice operation is a slice with the same element type as t
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
If the sliced operand of a valid slice expression is a <code>nil</code> slice, the result
|
If the sliced operand of a valid slice expression is a <code>nil</code> slice, the result
|
||||||
is a <code>nil</code> slice. Otherwise, the result shares its underlying array with the
|
is a <code>nil</code> slice. Otherwise, if the result is a slice, it shares its underlying
|
||||||
operand.
|
array with the operand.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h4>Full slice expressions</h4>
|
<h4>Full slice expressions</h4>
|
||||||
|
|
@ -3135,7 +3192,8 @@ If the sliced operand is an array, it must be <a href="#Address_operators">addre
|
||||||
<p>
|
<p>
|
||||||
The indices are <i>in range</i> if <code>0 <= low <= high <= max <= cap(a)</code>,
|
The indices are <i>in range</i> if <code>0 <= low <= high <= max <= cap(a)</code>,
|
||||||
otherwise they are <i>out of range</i>.
|
otherwise they are <i>out of range</i>.
|
||||||
A <a href="#Constants">constant</a> index must be non-negative and representable by a value of type
|
A <a href="#Constants">constant</a> index must be non-negative and
|
||||||
|
<a href="#Representability">representable</a> by a value of type
|
||||||
<code>int</code>; for arrays, constant indices must also be in range.
|
<code>int</code>; for arrays, constant indices must also be in range.
|
||||||
If multiple indices are constant, the constants that are present must be in range relative to each
|
If multiple indices are constant, the constants that are present must be in range relative to each
|
||||||
other.
|
other.
|
||||||
|
|
@ -3384,7 +3442,8 @@ to the type of the other operand.
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The right operand in a shift expression must have unsigned integer type
|
The right operand in a shift expression must have unsigned integer type
|
||||||
or be an untyped constant representable by a value of type <code>uint</code>.
|
or be an untyped constant <a href="#Representability">representable</a> by a
|
||||||
|
value of type <code>uint</code>.
|
||||||
If the left operand of a non-constant shift expression is an untyped constant,
|
If the left operand of a non-constant shift expression is an untyped constant,
|
||||||
it is first converted to the type it would assume if the shift expression were
|
it is first converted to the type it would assume if the shift expression were
|
||||||
replaced by its left operand alone.
|
replaced by its left operand alone.
|
||||||
|
|
@ -3392,18 +3451,20 @@ replaced by its left operand alone.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
var s uint = 33
|
var s uint = 33
|
||||||
var i = 1<<s // 1 has type int
|
var i = 1<<s // 1 has type int
|
||||||
var j int32 = 1<<s // 1 has type int32; j == 0
|
var j int32 = 1<<s // 1 has type int32; j == 0
|
||||||
var k = uint64(1<<s) // 1 has type uint64; k == 1<<33
|
var k = uint64(1<<s) // 1 has type uint64; k == 1<<33
|
||||||
var m int = 1.0<<s // 1.0 has type int; m == 0 if ints are 32bits in size
|
var m int = 1.0<<s // 1.0 has type int; m == 0 if ints are 32bits in size
|
||||||
var n = 1.0<<s == j // 1.0 has type int32; n == true
|
var n = 1.0<<s == j // 1.0 has type int32; n == true
|
||||||
var o = 1<<s == 2<<s // 1 and 2 have type int; o == true if ints are 32bits in size
|
var o = 1<<s == 2<<s // 1 and 2 have type int; o == true if ints are 32bits in size
|
||||||
var p = 1<<s == 1<<33 // illegal if ints are 32bits in size: 1 has type int, but 1<<33 overflows int
|
var p = 1<<s == 1<<33 // illegal if ints are 32bits in size: 1 has type int, but 1<<33 overflows int
|
||||||
var u = 1.0<<s // illegal: 1.0 has type float64, cannot shift
|
var u = 1.0<<s // illegal: 1.0 has type float64, cannot shift
|
||||||
var u1 = 1.0<<s != 0 // illegal: 1.0 has type float64, cannot shift
|
var u1 = 1.0<<s != 0 // illegal: 1.0 has type float64, cannot shift
|
||||||
var u2 = 1<<s != 1.0 // illegal: 1 has type float64, cannot shift
|
var u2 = 1<<s != 1.0 // illegal: 1 has type float64, cannot shift
|
||||||
var v float32 = 1<<s // illegal: 1 has type float32, cannot shift
|
var v float32 = 1<<s // illegal: 1 has type float32, cannot shift
|
||||||
var w int64 = 1.0<<33 // 1.0<<33 is a constant shift expression
|
var w int64 = 1.0<<33 // 1.0<<33 is a constant shift expression
|
||||||
|
var x = a[1.0<<s] // 1.0 has type int; x == a[0] if ints are 32bits in size
|
||||||
|
var a = make([]byte, 1.0<<s) // 1.0 has type int; len(a) == 0 if ints are 32bits in size
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -3877,30 +3938,14 @@ func() int(x) // x is converted to func() int (unambiguous)
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
A <a href="#Constants">constant</a> value <code>x</code> can be converted to
|
A <a href="#Constants">constant</a> value <code>x</code> can be converted to
|
||||||
type <code>T</code> in any of these cases:
|
type <code>T</code> if <code>x</code> is <a href="#Representability">representable</a>
|
||||||
|
by a value of <code>T</code>.
|
||||||
|
As a special case, an integer constant <code>x</code> can be converted to a
|
||||||
|
<a href="#String_types">string type</a> using the
|
||||||
|
<a href="#Conversions_to_and_from_a_string_type">same rule</a>
|
||||||
|
as for non-constant <code>x</code>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<code>x</code> is representable by a value of type <code>T</code>.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<code>x</code> is a floating-point constant,
|
|
||||||
<code>T</code> is a floating-point type,
|
|
||||||
and <code>x</code> is representable by a value
|
|
||||||
of type <code>T</code> after rounding using
|
|
||||||
IEEE 754 round-to-even rules, but with an IEEE <code>-0.0</code>
|
|
||||||
further rounded to an unsigned <code>0.0</code>.
|
|
||||||
The constant <code>T(x)</code> is the rounded value.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<code>x</code> is an integer constant and <code>T</code> is a
|
|
||||||
<a href="#String_types">string type</a>.
|
|
||||||
The <a href="#Conversions_to_and_from_a_string_type">same rule</a>
|
|
||||||
as for non-constant <code>x</code> applies in this case.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Converting a constant yields a typed constant as result.
|
Converting a constant yields a typed constant as result.
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -4187,7 +4232,8 @@ The divisor of a constant division or remainder operation must not be zero:
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The values of <i>typed</i> constants must always be accurately representable as values
|
The values of <i>typed</i> constants must always be accurately
|
||||||
|
<a href="#Representability">representable</a> by values
|
||||||
of the constant type. The following constant expressions are illegal:
|
of the constant type. The following constant expressions are illegal:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
@ -4820,8 +4866,9 @@ in the TypeSwitchGuard.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The type in a case may be <a href="#Predeclared_identifiers"><code>nil</code></a>;
|
Instead of a type, a case may use the predeclared identifier
|
||||||
that case is used when the expression in the TypeSwitchGuard
|
<a href="#Predeclared_identifiers"><code>nil</code></a>;
|
||||||
|
that case is selected when the expression in the TypeSwitchGuard
|
||||||
is a <code>nil</code> interface value.
|
is a <code>nil</code> interface value.
|
||||||
There may be at most one <code>nil</code> case.
|
There may be at most one <code>nil</code> case.
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -4979,12 +5026,10 @@ the range clause is equivalent to the same clause without that identifier.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The range expression is evaluated once before beginning the loop,
|
The range expression <code>x</code> is evaluated once before beginning the loop,
|
||||||
with one exception: if the range expression is an array or a pointer to an array
|
with one exception: if at most one iteration variable is present and
|
||||||
and at most one iteration variable is present, only the range expression's
|
<code>len(x)</code> is <a href="#Length_and_capacity">constant</a>,
|
||||||
length is evaluated; if that length is constant,
|
the range expression is not evaluated.
|
||||||
<a href="#Length_and_capacity">by definition</a>
|
|
||||||
the range expression itself will not be evaluated.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -5680,9 +5725,10 @@ make(T, n) channel buffered channel of type T, buffer size n
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The size arguments <code>n</code> and <code>m</code> must be of integer type or untyped.
|
Each of the size arguments <code>n</code> and <code>m</code> must be of integer type
|
||||||
A <a href="#Constants">constant</a> size argument must be non-negative and
|
or an untyped <a href="#Constants">constant</a>.
|
||||||
representable by a value of type <code>int</code>.
|
A constant size argument must be non-negative and <a href="#Representability">representable</a>
|
||||||
|
by a value of type <code>int</code>; if it is an untyped constant it is given type <code>int</code>.
|
||||||
If both <code>n</code> and <code>m</code> are provided and are constant, then
|
If both <code>n</code> and <code>m</code> are provided and are constant, then
|
||||||
<code>n</code> must be no larger than <code>m</code>.
|
<code>n</code> must be no larger than <code>m</code>.
|
||||||
If <code>n</code> is negative or larger than <code>m</code> at run time,
|
If <code>n</code> is negative or larger than <code>m</code> at run time,
|
||||||
|
|
@ -6157,7 +6203,7 @@ of <code>make</code>,
|
||||||
and no explicit initialization is provided, the variable or value is
|
and no explicit initialization is provided, the variable or value is
|
||||||
given a default value. Each element of such a variable or value is
|
given a default value. Each element of such a variable or value is
|
||||||
set to the <i>zero value</i> for its type: <code>false</code> for booleans,
|
set to the <i>zero value</i> for its type: <code>false</code> for booleans,
|
||||||
<code>0</code> for integers, <code>0.0</code> for floats, <code>""</code>
|
<code>0</code> for numeric types, <code>""</code>
|
||||||
for strings, and <code>nil</code> for pointers, functions, interfaces, slices, channels, and maps.
|
for strings, and <code>nil</code> for pointers, functions, interfaces, slices, channels, and maps.
|
||||||
This initialization is done recursively, so for instance each element of an
|
This initialization is done recursively, so for instance each element of an
|
||||||
array of structs will have its fields zeroed if no value is specified.
|
array of structs will have its fields zeroed if no value is specified.
|
||||||
|
|
@ -6409,7 +6455,8 @@ type Error interface {
|
||||||
<h3 id="Package_unsafe">Package <code>unsafe</code></h3>
|
<h3 id="Package_unsafe">Package <code>unsafe</code></h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The built-in package <code>unsafe</code>, known to the compiler,
|
The built-in package <code>unsafe</code>, known to the compiler
|
||||||
|
and accessible through the <a href="#Import_declarations">import path</a> <code>"unsafe"</code>,
|
||||||
provides facilities for low-level programming including operations
|
provides facilities for low-level programming including operations
|
||||||
that violate the type system. A package using <code>unsafe</code>
|
that violate the type system. A package using <code>unsafe</code>
|
||||||
must be vetted manually for type safety and may not be portable.
|
must be vetted manually for type safety and may not be portable.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<!--{
|
<!--{
|
||||||
"Title": "Help",
|
"Title": "Help",
|
||||||
"Path": "/help/"
|
"Path": "/help/",
|
||||||
|
"Template": true
|
||||||
}-->
|
}-->
|
||||||
|
|
||||||
<div id="manual-nav"></div>
|
<div id="manual-nav"></div>
|
||||||
|
|
@ -9,6 +10,7 @@
|
||||||
|
|
||||||
<img class="gopher" src="/doc/gopher/help.png"/>
|
<img class="gopher" src="/doc/gopher/help.png"/>
|
||||||
|
|
||||||
|
{{if not $.GoogleCN}}
|
||||||
<h3 id="mailinglist"><a href="https://groups.google.com/group/golang-nuts">Go Nuts Mailing List</a></h3>
|
<h3 id="mailinglist"><a href="https://groups.google.com/group/golang-nuts">Go Nuts Mailing List</a></h3>
|
||||||
<p>
|
<p>
|
||||||
Get help from Go users, and share your work on the official mailing list.
|
Get help from Go users, and share your work on the official mailing list.
|
||||||
|
|
@ -31,10 +33,12 @@ forum for Go programmers.
|
||||||
<h3 id="irc"><a href="irc:irc.freenode.net/go-nuts">Go IRC Channel</a></h3>
|
<h3 id="irc"><a href="irc:irc.freenode.net/go-nuts">Go IRC Channel</a></h3>
|
||||||
<p>Get live support at <b>#go-nuts</b> on <b>irc.freenode.net</b>, the official
|
<p>Get live support at <b>#go-nuts</b> on <b>irc.freenode.net</b>, the official
|
||||||
Go IRC channel.</p>
|
Go IRC channel.</p>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
<h3 id="faq"><a href="/doc/faq">Frequently Asked Questions (FAQ)</a></h3>
|
<h3 id="faq"><a href="/doc/faq">Frequently Asked Questions (FAQ)</a></h3>
|
||||||
<p>Answers to common questions about Go.</p>
|
<p>Answers to common questions about Go.</p>
|
||||||
|
|
||||||
|
{{if not $.GoogleCN}}
|
||||||
<h2 id="inform">Stay informed</h2>
|
<h2 id="inform">Stay informed</h2>
|
||||||
|
|
||||||
<h3 id="announce"><a href="https://groups.google.com/group/golang-announce">Go Announcements Mailing List</a></h3>
|
<h3 id="announce"><a href="https://groups.google.com/group/golang-announce">Go Announcements Mailing List</a></h3>
|
||||||
|
|
@ -64,6 +68,7 @@ for Go news and discussion.
|
||||||
The <a href="https://changelog.com/gotime">Go Time podcast</a> is a panel of Go experts and special guests
|
The <a href="https://changelog.com/gotime">Go Time podcast</a> is a panel of Go experts and special guests
|
||||||
discussing the Go programming language, the community, and everything in between.
|
discussing the Go programming language, the community, and everything in between.
|
||||||
</p>
|
</p>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
<h2 id="community">Community resources</h2>
|
<h2 id="community">Community resources</h2>
|
||||||
|
|
||||||
|
|
@ -73,11 +78,13 @@ Each month in places around the world, groups of Go programmers ("gophers")
|
||||||
meet to talk about Go. Find a chapter near you.
|
meet to talk about Go. Find a chapter near you.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
{{if not $.GoogleCN}}
|
||||||
<h3 id="playground"><a href="/play">Go Playground</a></h3>
|
<h3 id="playground"><a href="/play">Go Playground</a></h3>
|
||||||
<p>A place to write, run, and share Go code.</p>
|
<p>A place to write, run, and share Go code.</p>
|
||||||
|
|
||||||
<h3 id="wiki"><a href="/wiki">Go Wiki</a></h3>
|
<h3 id="wiki"><a href="/wiki">Go Wiki</a></h3>
|
||||||
<p>A wiki maintained by the Go community.</p>
|
<p>A wiki maintained by the Go community.</p>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
<h3 id="conduct"><a href="/conduct">Code of Conduct</a></h3>
|
<h3 id="conduct"><a href="/conduct">Code of Conduct</a></h3>
|
||||||
<p>
|
<p>
|
||||||
|
|
|
||||||
|
|
@ -143,12 +143,13 @@ packaged Go distribution.
|
||||||
<p>
|
<p>
|
||||||
To build a bootstrap tool chain from source, use
|
To build a bootstrap tool chain from source, use
|
||||||
either the git branch <code>release-branch.go1.4</code> or
|
either the git branch <code>release-branch.go1.4</code> or
|
||||||
<a href="https://storage.googleapis.com/golang/go1.4-bootstrap-20170531.tar.gz">go1.4-bootstrap-20170531.tar.gz</a>,
|
<a href="https://dl.google.com/go/go1.4-bootstrap-20171003.tar.gz">go1.4-bootstrap-20171003.tar.gz</a>,
|
||||||
which contains the Go 1.4 source code plus accumulated fixes
|
which contains the Go 1.4 source code plus accumulated fixes
|
||||||
to keep the tools running on newer operating systems.
|
to keep the tools running on newer operating systems.
|
||||||
(Go 1.4 was the last distribution in which the tool chain was written in C.)
|
(Go 1.4 was the last distribution in which the tool chain was written in C.)
|
||||||
After unpacking the Go 1.4 source, <code>cd</code> to
|
After unpacking the Go 1.4 source, <code>cd</code> to
|
||||||
the <code>src</code> subdirectory and run <code>make.bash</code> (or,
|
the <code>src</code> subdirectory, set <code>CGO_ENABLED=0</code> in
|
||||||
|
the environment, and run <code>make.bash</code> (or,
|
||||||
on Windows, <code>make.bat</code>).
|
on Windows, <code>make.bat</code>).
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
@ -471,8 +472,9 @@ Choices for <code>$GOARCH</code> are
|
||||||
<code>amd64</code> (64-bit x86, the most mature port),
|
<code>amd64</code> (64-bit x86, the most mature port),
|
||||||
<code>386</code> (32-bit x86), <code>arm</code> (32-bit ARM), <code>arm64</code> (64-bit ARM),
|
<code>386</code> (32-bit x86), <code>arm</code> (32-bit ARM), <code>arm64</code> (64-bit ARM),
|
||||||
<code>ppc64le</code> (PowerPC 64-bit, little-endian), <code>ppc64</code> (PowerPC 64-bit, big-endian),
|
<code>ppc64le</code> (PowerPC 64-bit, little-endian), <code>ppc64</code> (PowerPC 64-bit, big-endian),
|
||||||
<code>mips64le</code> (MIPS 64-bit, little-endian), and <code>mips64</code> (MIPS 64-bit, big-endian).
|
<code>mips64le</code> (MIPS 64-bit, little-endian), <code>mips64</code> (MIPS 64-bit, big-endian),
|
||||||
<code>mipsle</code> (MIPS 32-bit, little-endian), and <code>mips</code> (MIPS 32-bit, big-endian).
|
<code>mipsle</code> (MIPS 32-bit, little-endian), <code>mips</code> (MIPS 32-bit, big-endian), and
|
||||||
|
<code>s390x</code> (IBM System z 64-bit, big-endian).
|
||||||
The valid combinations of <code>$GOOS</code> and <code>$GOARCH</code> are:
|
The valid combinations of <code>$GOOS</code> and <code>$GOARCH</code> are:
|
||||||
<table cellpadding="0">
|
<table cellpadding="0">
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -536,6 +538,9 @@ The valid combinations of <code>$GOOS</code> and <code>$GOARCH</code> are:
|
||||||
<td></td><td><code>linux</code></td> <td><code>mips64le</code></td>
|
<td></td><td><code>linux</code></td> <td><code>mips64le</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
<td></td><td><code>linux</code></td> <td><code>s390x</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
<td></td><td><code>netbsd</code></td> <td><code>386</code></td>
|
<td></td><td><code>netbsd</code></td> <td><code>386</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<a href="https://golang.org/dl/" target="_blank">Official binary
|
<a href="https://golang.org/dl/" target="_blank">Official binary
|
||||||
distributions</a> are available for the FreeBSD (release 8-STABLE and above),
|
distributions</a> are available for the FreeBSD (release 10-STABLE and above),
|
||||||
Linux, Mac OS X (10.8 and above), and Windows operating systems and
|
Linux, Mac OS X (10.8 and above), and Windows operating systems and
|
||||||
the 32-bit (<code>386</code>) and 64-bit (<code>amd64</code>) x86 processor
|
the 32-bit (<code>386</code>) and 64-bit (<code>amd64</code>) x86 processor
|
||||||
architectures.
|
architectures.
|
||||||
|
|
@ -47,7 +47,7 @@ If your OS or architecture is not on the list, you may be able to
|
||||||
<th align="center">Notes</th>
|
<th align="center">Notes</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr><td colspan="3"><hr></td></tr>
|
<tr><td colspan="3"><hr></td></tr>
|
||||||
<tr><td>FreeBSD 9.3 or later</td> <td>amd64, 386</td> <td>Debian GNU/kFreeBSD not supported</td></tr>
|
<tr><td>FreeBSD 10.3 or later</td> <td>amd64, 386</td> <td>Debian GNU/kFreeBSD not supported</td></tr>
|
||||||
<tr valign='top'><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm, arm64,<br>s390x, ppc64le</td> <td>CentOS/RHEL 5.x not supported.<br>Install from source for other libc.</td></tr>
|
<tr valign='top'><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm, arm64,<br>s390x, ppc64le</td> <td>CentOS/RHEL 5.x not supported.<br>Install from source for other libc.</td></tr>
|
||||||
<tr><td>macOS 10.8 or later</td> <td>amd64</td> <td>use the clang or gcc<sup>†</sup> that comes with Xcode<sup>‡</sup> for <code>cgo</code> support</td></tr>
|
<tr><td>macOS 10.8 or later</td> <td>amd64</td> <td>use the clang or gcc<sup>†</sup> that comes with Xcode<sup>‡</sup> for <code>cgo</code> support</td></tr>
|
||||||
<tr><td>Windows XP SP2 or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>†</sup>. No need for cygwin or msys.</td></tr>
|
<tr><td>Windows XP SP2 or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>†</sup>. No need for cygwin or msys.</td></tr>
|
||||||
|
|
|
||||||
|
|
@ -219,12 +219,5 @@ func fixcgo() {
|
||||||
// cgo1 and cgo2 don't run on netbsd, srandom has a different signature
|
// cgo1 and cgo2 don't run on netbsd, srandom has a different signature
|
||||||
skipTest("cgo1")
|
skipTest("cgo1")
|
||||||
skipTest("cgo2")
|
skipTest("cgo2")
|
||||||
// cgo3 and cgo4 don't run on netbsd, since cgo cannot handle stdout correctly, see issue #10715.
|
|
||||||
skipTest("cgo3")
|
|
||||||
skipTest("cgo4")
|
|
||||||
case "openbsd", "solaris":
|
|
||||||
// cgo3 and cgo4 don't run on openbsd and solaris, since cgo cannot handle stdout correctly, see issue #10715.
|
|
||||||
skipTest("cgo3")
|
|
||||||
skipTest("cgo4")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
161
misc/cgo/errors/errors_test.go
Normal file
161
misc/cgo/errors/errors_test.go
Normal file
|
|
@ -0,0 +1,161 @@
|
||||||
|
// Copyright 2017 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 errorstest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func path(file string) string {
|
||||||
|
return filepath.Join("src", file)
|
||||||
|
}
|
||||||
|
|
||||||
|
func check(t *testing.T, file string) {
|
||||||
|
t.Run(file, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
contents, err := ioutil.ReadFile(path(file))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
var errors []*regexp.Regexp
|
||||||
|
for i, line := range bytes.Split(contents, []byte("\n")) {
|
||||||
|
if bytes.HasSuffix(line, []byte("ERROR HERE")) {
|
||||||
|
re := regexp.MustCompile(regexp.QuoteMeta(fmt.Sprintf("%s:%d:", file, i+1)))
|
||||||
|
errors = append(errors, re)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
frags := bytes.SplitAfterN(line, []byte("ERROR HERE: "), 2)
|
||||||
|
if len(frags) == 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
re, err := regexp.Compile(string(frags[1]))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Invalid regexp after `ERROR HERE: `: %#q", frags[1])
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
errors = append(errors, re)
|
||||||
|
}
|
||||||
|
if len(errors) == 0 {
|
||||||
|
t.Fatalf("cannot find ERROR HERE")
|
||||||
|
}
|
||||||
|
expect(t, file, errors)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func expect(t *testing.T, file string, errors []*regexp.Regexp) {
|
||||||
|
dir, err := ioutil.TempDir("", filepath.Base(t.Name()))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
dst := filepath.Join(dir, strings.TrimSuffix(file, ".go"))
|
||||||
|
cmd := exec.Command("go", "build", "-gcflags=-L", "-o="+dst, path(file)) // TODO(gri) no need for -gcflags=-L if go tool is adjusted
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("expected cgo to fail but it succeeded")
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := bytes.Split(out, []byte("\n"))
|
||||||
|
for _, re := range errors {
|
||||||
|
found := false
|
||||||
|
for _, line := range lines {
|
||||||
|
if re.Match(line) {
|
||||||
|
t.Logf("found match for %#q: %q", re, line)
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
t.Errorf("expected error output to contain %#q", re)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.Failed() {
|
||||||
|
t.Logf("actual output:\n%s", out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sizeofLongDouble(t *testing.T) int {
|
||||||
|
cmd := exec.Command("go", "run", path("long_double_size.go"))
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%#q: %v:\n%s", strings.Join(cmd.Args, " "), err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
i, err := strconv.Atoi(strings.TrimSpace(string(out)))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("long_double_size.go printed invalid size: %s", out)
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReportsTypeErrors(t *testing.T) {
|
||||||
|
for _, file := range []string{
|
||||||
|
"err1.go",
|
||||||
|
"err2.go",
|
||||||
|
"err3.go",
|
||||||
|
"issue7757.go",
|
||||||
|
"issue8442.go",
|
||||||
|
"issue11097a.go",
|
||||||
|
"issue11097b.go",
|
||||||
|
"issue13129.go",
|
||||||
|
"issue13423.go",
|
||||||
|
"issue13467.go",
|
||||||
|
"issue13635.go",
|
||||||
|
"issue13830.go",
|
||||||
|
"issue16116.go",
|
||||||
|
"issue16591.go",
|
||||||
|
"issue18452.go",
|
||||||
|
"issue18889.go",
|
||||||
|
} {
|
||||||
|
check(t, file)
|
||||||
|
}
|
||||||
|
|
||||||
|
if sizeofLongDouble(t) > 8 {
|
||||||
|
check(t, "err4.go")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToleratesOptimizationFlag(t *testing.T) {
|
||||||
|
for _, cflags := range []string{
|
||||||
|
"",
|
||||||
|
"-O",
|
||||||
|
} {
|
||||||
|
cflags := cflags
|
||||||
|
t.Run(cflags, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
cmd := exec.Command("go", "build", path("issue14669.go"))
|
||||||
|
cmd.Env = append(os.Environ(), "CGO_CFLAGS="+cflags)
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%#q: %v:\n%s", strings.Join(cmd.Args, " "), err, out)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMallocCrashesOnNil(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
cmd := exec.Command("go", "run", path("malloc.go"))
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err == nil {
|
||||||
|
t.Logf("%#q:\n%s", strings.Join(cmd.Args, " "), out)
|
||||||
|
t.Fatalf("succeeded unexpectedly")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// issue 13635: used to output error about C.unsignedchar.
|
|
||||||
// This test tests all such types.
|
|
||||||
|
|
||||||
package pkg
|
|
||||||
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var (
|
|
||||||
_ C.uchar = "uc" // ERROR HERE
|
|
||||||
_ C.schar = "sc" // ERROR HERE
|
|
||||||
_ C.ushort = "us" // ERROR HERE
|
|
||||||
_ C.uint = "ui" // ERROR HERE
|
|
||||||
_ C.ulong = "ul" // ERROR HERE
|
|
||||||
_ C.longlong = "ll" // ERROR HERE
|
|
||||||
_ C.ulonglong = "ull" // ERROR HERE
|
|
||||||
_ C.complexfloat = "cf" // ERROR HERE
|
|
||||||
_ C.complexdouble = "cd" // ERROR HERE
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -4,20 +4,18 @@
|
||||||
|
|
||||||
// Tests that cgo detects invalid pointer passing at runtime.
|
// Tests that cgo detects invalid pointer passing at runtime.
|
||||||
|
|
||||||
package main
|
package errorstest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ptrTest is the tests without the boilerplate.
|
// ptrTest is the tests without the boilerplate.
|
||||||
|
|
@ -344,7 +342,7 @@ var ptrTests = []ptrTest{
|
||||||
fail: false,
|
fail: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Issue #21306.
|
// Test preemption while entering a cgo call. Issue #21306.
|
||||||
name: "preempt-during-call",
|
name: "preempt-during-call",
|
||||||
c: `void f() {}`,
|
c: `void f() {}`,
|
||||||
imports: []string{"runtime", "sync"},
|
imports: []string{"runtime", "sync"},
|
||||||
|
|
@ -353,219 +351,145 @@ var ptrTests = []ptrTest{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func TestPointerChecks(t *testing.T) {
|
||||||
os.Exit(doTests())
|
for _, pt := range ptrTests {
|
||||||
|
pt := pt
|
||||||
|
t.Run(pt.name, func(t *testing.T) {
|
||||||
|
testOne(t, pt)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func doTests() int {
|
func testOne(t *testing.T, pt ptrTest) {
|
||||||
gopath, err := ioutil.TempDir("", "cgoerrors")
|
t.Parallel()
|
||||||
|
|
||||||
|
gopath, err := ioutil.TempDir("", filepath.Base(t.Name()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
t.Fatal(err)
|
||||||
return 2
|
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(gopath)
|
defer os.RemoveAll(gopath)
|
||||||
|
|
||||||
if err := os.MkdirAll(filepath.Join(gopath, "src"), 0777); err != nil {
|
src := filepath.Join(gopath, "src")
|
||||||
fmt.Fprintln(os.Stderr, err)
|
if err := os.Mkdir(src, 0777); err != nil {
|
||||||
return 2
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
workers := runtime.NumCPU() + 1
|
name := filepath.Join(src, fmt.Sprintf("%s.go", filepath.Base(t.Name())))
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
c := make(chan int)
|
|
||||||
errs := make(chan int)
|
|
||||||
for i := 0; i < workers; i++ {
|
|
||||||
wg.Add(1)
|
|
||||||
go func() {
|
|
||||||
worker(gopath, c, errs)
|
|
||||||
wg.Done()
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range ptrTests {
|
|
||||||
c <- i
|
|
||||||
}
|
|
||||||
close(c)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
wg.Wait()
|
|
||||||
close(errs)
|
|
||||||
}()
|
|
||||||
|
|
||||||
tot := 0
|
|
||||||
for e := range errs {
|
|
||||||
tot += e
|
|
||||||
}
|
|
||||||
return tot
|
|
||||||
}
|
|
||||||
|
|
||||||
func worker(gopath string, c, errs chan int) {
|
|
||||||
e := 0
|
|
||||||
for i := range c {
|
|
||||||
if !doOne(gopath, i) {
|
|
||||||
e++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if e > 0 {
|
|
||||||
errs <- e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func doOne(gopath string, i int) bool {
|
|
||||||
t := &ptrTests[i]
|
|
||||||
|
|
||||||
dir := filepath.Join(gopath, "src", fmt.Sprintf("dir%d", i))
|
|
||||||
if err := os.Mkdir(dir, 0777); err != nil {
|
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
name := filepath.Join(dir, fmt.Sprintf("t%d.go", i))
|
|
||||||
f, err := os.Create(name)
|
f, err := os.Create(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
t.Fatal(err)
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
b := bufio.NewWriter(f)
|
b := bufio.NewWriter(f)
|
||||||
fmt.Fprintln(b, `package main`)
|
fmt.Fprintln(b, `package main`)
|
||||||
fmt.Fprintln(b)
|
fmt.Fprintln(b)
|
||||||
fmt.Fprintln(b, `/*`)
|
fmt.Fprintln(b, `/*`)
|
||||||
fmt.Fprintln(b, t.c)
|
fmt.Fprintln(b, pt.c)
|
||||||
fmt.Fprintln(b, `*/`)
|
fmt.Fprintln(b, `*/`)
|
||||||
fmt.Fprintln(b, `import "C"`)
|
fmt.Fprintln(b, `import "C"`)
|
||||||
fmt.Fprintln(b)
|
fmt.Fprintln(b)
|
||||||
for _, imp := range t.imports {
|
for _, imp := range pt.imports {
|
||||||
fmt.Fprintln(b, `import "`+imp+`"`)
|
fmt.Fprintln(b, `import "`+imp+`"`)
|
||||||
}
|
}
|
||||||
if len(t.imports) > 0 {
|
if len(pt.imports) > 0 {
|
||||||
fmt.Fprintln(b)
|
fmt.Fprintln(b)
|
||||||
}
|
}
|
||||||
if len(t.support) > 0 {
|
if len(pt.support) > 0 {
|
||||||
fmt.Fprintln(b, t.support)
|
fmt.Fprintln(b, pt.support)
|
||||||
fmt.Fprintln(b)
|
fmt.Fprintln(b)
|
||||||
}
|
}
|
||||||
fmt.Fprintln(b, `func main() {`)
|
fmt.Fprintln(b, `func main() {`)
|
||||||
fmt.Fprintln(b, t.body)
|
fmt.Fprintln(b, pt.body)
|
||||||
fmt.Fprintln(b, `}`)
|
fmt.Fprintln(b, `}`)
|
||||||
|
|
||||||
if err := b.Flush(); err != nil {
|
if err := b.Flush(); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "flushing %s: %v\n", name, err)
|
t.Fatalf("flushing %s: %v", name, err)
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
if err := f.Close(); err != nil {
|
if err := f.Close(); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "closing %s: %v\n", name, err)
|
t.Fatalf("closing %s: %v", name, err)
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, e := range t.extra {
|
for _, e := range pt.extra {
|
||||||
if err := ioutil.WriteFile(filepath.Join(dir, e.name), []byte(e.contents), 0644); err != nil {
|
if err := ioutil.WriteFile(filepath.Join(src, e.name), []byte(e.contents), 0644); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "writing %s: %v\n", e.name, err)
|
t.Fatalf("writing %s: %v", e.name, err)
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ok := true
|
args := func(cmd *exec.Cmd) string {
|
||||||
|
return strings.Join(cmd.Args, " ")
|
||||||
|
}
|
||||||
|
|
||||||
cmd := exec.Command("go", "build")
|
cmd := exec.Command("go", "build")
|
||||||
cmd.Dir = dir
|
cmd.Dir = src
|
||||||
cmd.Env = addEnv("GOPATH", gopath)
|
cmd.Env = addEnv("GOPATH", gopath)
|
||||||
buf, err := cmd.CombinedOutput()
|
buf, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "test %s failed to build: %v\n%s", t.name, err, buf)
|
t.Logf("%#q:\n%s", args(cmd), buf)
|
||||||
return false
|
t.Fatalf("failed to build: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
exe := filepath.Join(dir, filepath.Base(dir))
|
exe := filepath.Join(src, filepath.Base(src))
|
||||||
cmd = exec.Command(exe)
|
cmd = exec.Command(exe)
|
||||||
cmd.Dir = dir
|
cmd.Dir = src
|
||||||
|
|
||||||
if t.expensive {
|
if pt.expensive {
|
||||||
cmd.Env = cgocheckEnv("1")
|
cmd.Env = cgocheckEnv("1")
|
||||||
buf, err := cmd.CombinedOutput()
|
buf, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var errbuf bytes.Buffer
|
t.Logf("%#q:\n%s", args(cmd), buf)
|
||||||
if t.fail {
|
if pt.fail {
|
||||||
fmt.Fprintf(&errbuf, "test %s marked expensive but failed when not expensive: %v\n", t.name, err)
|
t.Fatalf("test marked expensive, but failed when not expensive: %v", err)
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(&errbuf, "test %s failed unexpectedly with GODEBUG=cgocheck=1: %v\n", t.name, err)
|
t.Errorf("failed unexpectedly with GODEBUG=cgocheck=1: %v", err)
|
||||||
}
|
}
|
||||||
reportTestOutput(&errbuf, t.name, buf)
|
|
||||||
os.Stderr.Write(errbuf.Bytes())
|
|
||||||
ok = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = exec.Command(exe)
|
cmd = exec.Command(exe)
|
||||||
cmd.Dir = dir
|
cmd.Dir = src
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.expensive {
|
if pt.expensive {
|
||||||
cmd.Env = cgocheckEnv("2")
|
cmd.Env = cgocheckEnv("2")
|
||||||
}
|
}
|
||||||
|
|
||||||
buf, err = cmd.CombinedOutput()
|
buf, err = cmd.CombinedOutput()
|
||||||
|
if pt.fail {
|
||||||
if t.fail {
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
var errbuf bytes.Buffer
|
t.Logf("%#q:\n%s", args(cmd), buf)
|
||||||
fmt.Fprintf(&errbuf, "test %s did not fail as expected\n", t.name)
|
t.Fatalf("did not fail as expected")
|
||||||
reportTestOutput(&errbuf, t.name, buf)
|
|
||||||
os.Stderr.Write(errbuf.Bytes())
|
|
||||||
ok = false
|
|
||||||
} else if !bytes.Contains(buf, []byte("Go pointer")) {
|
} else if !bytes.Contains(buf, []byte("Go pointer")) {
|
||||||
var errbuf bytes.Buffer
|
t.Logf("%#q:\n%s", args(cmd), buf)
|
||||||
fmt.Fprintf(&errbuf, "test %s output does not contain expected error (failed with %v)\n", t.name, err)
|
t.Fatalf("did not print expected error (failed with %v)", err)
|
||||||
reportTestOutput(&errbuf, t.name, buf)
|
|
||||||
os.Stderr.Write(errbuf.Bytes())
|
|
||||||
ok = false
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var errbuf bytes.Buffer
|
t.Logf("%#q:\n%s", args(cmd), buf)
|
||||||
fmt.Fprintf(&errbuf, "test %s failed unexpectedly: %v\n", t.name, err)
|
t.Fatalf("failed unexpectedly: %v", err)
|
||||||
reportTestOutput(&errbuf, t.name, buf)
|
|
||||||
os.Stderr.Write(errbuf.Bytes())
|
|
||||||
ok = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !t.expensive && ok {
|
if !pt.expensive {
|
||||||
// Make sure it passes with the expensive checks.
|
// Make sure it passes with the expensive checks.
|
||||||
cmd := exec.Command(exe)
|
cmd := exec.Command(exe)
|
||||||
cmd.Dir = dir
|
cmd.Dir = src
|
||||||
cmd.Env = cgocheckEnv("2")
|
cmd.Env = cgocheckEnv("2")
|
||||||
buf, err := cmd.CombinedOutput()
|
buf, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var errbuf bytes.Buffer
|
t.Logf("%#q:\n%s", args(cmd), buf)
|
||||||
fmt.Fprintf(&errbuf, "test %s failed unexpectedly with expensive checks: %v\n", t.name, err)
|
t.Fatalf("failed unexpectedly with expensive checks: %v", err)
|
||||||
reportTestOutput(&errbuf, t.name, buf)
|
|
||||||
os.Stderr.Write(errbuf.Bytes())
|
|
||||||
ok = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.fail && ok {
|
if pt.fail {
|
||||||
cmd = exec.Command(exe)
|
cmd = exec.Command(exe)
|
||||||
cmd.Dir = dir
|
cmd.Dir = src
|
||||||
cmd.Env = cgocheckEnv("0")
|
cmd.Env = cgocheckEnv("0")
|
||||||
buf, err := cmd.CombinedOutput()
|
buf, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var errbuf bytes.Buffer
|
t.Logf("%#q:\n%s", args(cmd), buf)
|
||||||
fmt.Fprintf(&errbuf, "test %s failed unexpectedly with GODEBUG=cgocheck=0: %v\n", t.name, err)
|
t.Fatalf("failed unexpectedly with GODEBUG=cgocheck=0: %v", err)
|
||||||
reportTestOutput(&errbuf, t.name, buf)
|
|
||||||
os.Stderr.Write(errbuf.Bytes())
|
|
||||||
ok = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func reportTestOutput(w io.Writer, name string, buf []byte) {
|
|
||||||
fmt.Fprintf(w, "=== test %s output ===\n", name)
|
|
||||||
fmt.Fprintf(w, "%s", buf)
|
|
||||||
fmt.Fprintf(w, "=== end of test %s output ===\n", name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func cgocheckEnv(val string) []string {
|
func cgocheckEnv(val string) []string {
|
||||||
15
misc/cgo/errors/src/err4.go
Normal file
15
misc/cgo/errors/src/err4.go
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright 2017 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
|
||||||
|
|
||||||
|
/*
|
||||||
|
long double x = 0;
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
_ = C.x // ERROR HERE
|
||||||
|
_ = C.x
|
||||||
|
}
|
||||||
|
|
@ -10,5 +10,5 @@ import "C"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var x C.ushort
|
var x C.ushort
|
||||||
x = int(0) // ERROR HERE
|
x = int(0) // ERROR HERE: C\.ushort
|
||||||
}
|
}
|
||||||
15
misc/cgo/errors/src/issue13467.go
Normal file
15
misc/cgo/errors/src/issue13467.go
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright 2017 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 p
|
||||||
|
|
||||||
|
/*
|
||||||
|
static int transform(int x) { return x; }
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func F() {
|
||||||
|
var x rune = '✈'
|
||||||
|
var _ rune = C.transform(x) // ERROR HERE: C\.int
|
||||||
|
}
|
||||||
24
misc/cgo/errors/src/issue13635.go
Normal file
24
misc/cgo/errors/src/issue13635.go
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// issue 13635: used to output error about C.unsignedchar.
|
||||||
|
// This test tests all such types.
|
||||||
|
|
||||||
|
package pkg
|
||||||
|
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var (
|
||||||
|
_ C.uchar = "uc" // ERROR HERE: C\.uchar
|
||||||
|
_ C.schar = "sc" // ERROR HERE: C\.schar
|
||||||
|
_ C.ushort = "us" // ERROR HERE: C\.ushort
|
||||||
|
_ C.uint = "ui" // ERROR HERE: C\.uint
|
||||||
|
_ C.ulong = "ul" // ERROR HERE: C\.ulong
|
||||||
|
_ C.longlong = "ll" // ERROR HERE: C\.longlong
|
||||||
|
_ C.ulonglong = "ull" // ERROR HERE: C\.ulonglong
|
||||||
|
_ C.complexfloat = "cf" // ERROR HERE: C\.complexfloat
|
||||||
|
_ C.complexdouble = "cd" // ERROR HERE: C\.complexdouble
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -13,6 +13,6 @@ import (
|
||||||
|
|
||||||
func a() {
|
func a() {
|
||||||
fmt.Println("Hello, world!")
|
fmt.Println("Hello, world!")
|
||||||
C.function_that_does_not_exist() // line 16
|
C.function_that_does_not_exist() // ERROR HERE
|
||||||
C.pi // line 17
|
C.pi // ERROR HERE
|
||||||
}
|
}
|
||||||
16
misc/cgo/errors/src/long_double_size.go
Normal file
16
misc/cgo/errors/src/long_double_size.go
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright 2017 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
|
||||||
|
|
||||||
|
/*
|
||||||
|
const int sizeofLongDouble = sizeof(long double);
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(C.sizeofLongDouble)
|
||||||
|
}
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
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
|
|
||||||
expect $file $file:$line:
|
|
||||||
}
|
|
||||||
|
|
||||||
expect() {
|
|
||||||
file=$1
|
|
||||||
shift
|
|
||||||
if go build -gcflags=-C $file >errs 2>&1; then
|
|
||||||
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected cgo to fail on $file but it succeeded
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if ! test -s errs; then
|
|
||||||
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error output for $file but saw none
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
for error; do
|
|
||||||
if ! fgrep $error errs >/dev/null 2>&1; then
|
|
||||||
echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error output for $file to contain \"$error\" but saw:
|
|
||||||
cat 1>&2 errs
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
check err1.go
|
|
||||||
check err2.go
|
|
||||||
check err3.go
|
|
||||||
check issue7757.go
|
|
||||||
check issue8442.go
|
|
||||||
check issue11097a.go
|
|
||||||
check issue11097b.go
|
|
||||||
expect issue13129.go C.ushort
|
|
||||||
check issue13423.go
|
|
||||||
expect issue13635.go C.uchar C.schar C.ushort C.uint C.ulong C.longlong C.ulonglong C.complexfloat C.complexdouble
|
|
||||||
check issue13830.go
|
|
||||||
check issue16116.go
|
|
||||||
check issue16591.go
|
|
||||||
check issue18889.go
|
|
||||||
expect issue18452.go issue18452.go:16 issue18452.go:17
|
|
||||||
|
|
||||||
if ! go build issue14669.go; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if ! CGO_CFLAGS="-O" go build issue14669.go; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! go run ptr.go; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# The malloc.go test should crash.
|
|
||||||
rm -f malloc.out
|
|
||||||
if go run malloc.go >malloc.out 2>&1; then
|
|
||||||
echo '`go run malloc.go` succeeded unexpectedly'
|
|
||||||
cat malloc.out
|
|
||||||
rm -f malloc.out
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
rm -f malloc.out
|
|
||||||
|
|
||||||
rm -rf errs _obj
|
|
||||||
exit 0
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// cmpout
|
// cmpout -tags=use_go_run
|
||||||
|
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
// Copyright 2010 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
|
|
@ -11,9 +11,10 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"."
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"."
|
||||||
)
|
)
|
||||||
|
|
||||||
const MAXDIM = 100
|
const MAXDIM = 100
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// cmpout
|
// cmpout -tags=use_go_run
|
||||||
|
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// cmpout
|
// cmpout -tags=use_go_run
|
||||||
|
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// cmpout
|
// cmpout -tags=use_go_run
|
||||||
|
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,11 @@ func Test20369(t *testing.T) { test20369(t) }
|
||||||
func Test18720(t *testing.T) { test18720(t) }
|
func Test18720(t *testing.T) { test18720(t) }
|
||||||
func Test20266(t *testing.T) { test20266(t) }
|
func Test20266(t *testing.T) { test20266(t) }
|
||||||
func Test20129(t *testing.T) { test20129(t) }
|
func Test20129(t *testing.T) { test20129(t) }
|
||||||
|
func Test20910(t *testing.T) { test20910(t) }
|
||||||
func Test21708(t *testing.T) { test21708(t) }
|
func Test21708(t *testing.T) { test21708(t) }
|
||||||
|
func Test21809(t *testing.T) { test21809(t) }
|
||||||
|
func Test6907(t *testing.T) { test6907(t) }
|
||||||
|
func Test6907Go(t *testing.T) { test6907Go(t) }
|
||||||
|
func Test21897(t *testing.T) { test21897(t) }
|
||||||
|
|
||||||
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
|
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,39 @@ package cgotest
|
||||||
struct foo { char c; };
|
struct foo { char c; };
|
||||||
#define SIZE_OF(x) sizeof(x)
|
#define SIZE_OF(x) sizeof(x)
|
||||||
#define SIZE_OF_FOO SIZE_OF(struct foo)
|
#define SIZE_OF_FOO SIZE_OF(struct foo)
|
||||||
|
#define VAR1 VAR
|
||||||
|
#define VAR var
|
||||||
|
int var = 5;
|
||||||
|
|
||||||
|
#define ADDR &var
|
||||||
|
|
||||||
|
#define CALL fn()
|
||||||
|
int fn(void) {
|
||||||
|
return ++var;
|
||||||
|
}
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
func test18720(t *testing.T) {
|
func test18720(t *testing.T) {
|
||||||
if C.HELLO_WORLD != "hello\000world" {
|
if got, want := C.HELLO_WORLD, "hello\000world"; got != want {
|
||||||
t.Fatalf(`expected "hello\000world", but got %q`, C.HELLO_WORLD)
|
t.Errorf("C.HELLO_WORLD == %q, expected %q", got, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
if got, want := C.VAR1, C.int(5); got != want {
|
||||||
|
t.Errorf("C.VAR1 == %v, expected %v", got, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
if got, want := *C.ADDR, C.int(5); got != want {
|
||||||
|
t.Errorf("*C.ADDR == %v, expected %v", got, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
if got, want := C.CALL, C.int(6); got != want {
|
||||||
|
t.Errorf("C.CALL == %v, expected %v", got, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
if got, want := C.CALL, C.int(7); got != want {
|
||||||
|
t.Errorf("C.CALL == %v, expected %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue 20125.
|
// Issue 20125.
|
||||||
|
|
|
||||||
16
misc/cgo/test/issue19832.go
Normal file
16
misc/cgo/test/issue19832.go
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Issue 19832. Functions taking a pointer typedef were being expanded and triggering a compiler error.
|
||||||
|
|
||||||
|
package cgotest
|
||||||
|
|
||||||
|
// typedef struct { int i; } *PS;
|
||||||
|
// void T19832(PS p) {}
|
||||||
|
import "C"
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func test19832(t *testing.T) {
|
||||||
|
C.T19832(nil)
|
||||||
|
}
|
||||||
19
misc/cgo/test/issue20910.c
Normal file
19
misc/cgo/test/issue20910.c
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright 2017 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 <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "_cgo_export.h"
|
||||||
|
|
||||||
|
/* Test calling a Go function with multiple return values. */
|
||||||
|
|
||||||
|
void
|
||||||
|
callMulti(void)
|
||||||
|
{
|
||||||
|
struct multi_return result = multi();
|
||||||
|
assert(strcmp(result.r0, "multi") == 0);
|
||||||
|
assert(result.r1 == 0);
|
||||||
|
free(result.r0);
|
||||||
|
}
|
||||||
19
misc/cgo/test/issue20910.go
Normal file
19
misc/cgo/test/issue20910.go
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright 2017 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 cgotest
|
||||||
|
|
||||||
|
//void callMulti(void);
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
//export multi
|
||||||
|
func multi() (*C.char, C.int) {
|
||||||
|
return C.CString("multi"), 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func test20910(t *testing.T) {
|
||||||
|
C.callMulti()
|
||||||
|
}
|
||||||
45
misc/cgo/test/issue21809.go
Normal file
45
misc/cgo/test/issue21809.go
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Copyright 2017 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 cgotest
|
||||||
|
|
||||||
|
// Issue 21809. Compile C `typedef` to go type aliases.
|
||||||
|
|
||||||
|
// typedef long MySigned_t;
|
||||||
|
// /* tests alias-to-alias */
|
||||||
|
// typedef MySigned_t MySigned2_t;
|
||||||
|
//
|
||||||
|
// long takes_long(long x) { return x * x; }
|
||||||
|
// MySigned_t takes_typedef(MySigned_t x) { return x * x; }
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func test21809(t *testing.T) {
|
||||||
|
longVar := C.long(3)
|
||||||
|
typedefVar := C.MySigned_t(4)
|
||||||
|
typedefTypedefVar := C.MySigned2_t(5)
|
||||||
|
|
||||||
|
// all three should be considered identical to `long`
|
||||||
|
if ret := C.takes_long(longVar); ret != 9 {
|
||||||
|
t.Errorf("got %v but expected %v", ret, 9)
|
||||||
|
}
|
||||||
|
if ret := C.takes_long(typedefVar); ret != 16 {
|
||||||
|
t.Errorf("got %v but expected %v", ret, 16)
|
||||||
|
}
|
||||||
|
if ret := C.takes_long(typedefTypedefVar); ret != 25 {
|
||||||
|
t.Errorf("got %v but expected %v", ret, 25)
|
||||||
|
}
|
||||||
|
|
||||||
|
// They should also be identical to the typedef'd type
|
||||||
|
if ret := C.takes_typedef(longVar); ret != 9 {
|
||||||
|
t.Errorf("got %v but expected %v", ret, 9)
|
||||||
|
}
|
||||||
|
if ret := C.takes_typedef(typedefVar); ret != 16 {
|
||||||
|
t.Errorf("got %v but expected %v", ret, 16)
|
||||||
|
}
|
||||||
|
if ret := C.takes_typedef(typedefTypedefVar); ret != 25 {
|
||||||
|
t.Errorf("got %v but expected %v", ret, 25)
|
||||||
|
}
|
||||||
|
}
|
||||||
56
misc/cgo/test/issue21897.go
Normal file
56
misc/cgo/test/issue21897.go
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
// Copyright 2017 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 darwin,cgo,!internal
|
||||||
|
|
||||||
|
package cgotest
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo LDFLAGS: -framework CoreFoundation
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"runtime/debug"
|
||||||
|
"testing"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func test21897(t *testing.T) {
|
||||||
|
// Please write barrier, kick in soon.
|
||||||
|
defer debug.SetGCPercent(debug.SetGCPercent(1))
|
||||||
|
|
||||||
|
for i := 0; i < 10000; i++ {
|
||||||
|
testCFNumberRef()
|
||||||
|
testCFDateRef()
|
||||||
|
testCFBooleanRef()
|
||||||
|
// Allocate some memory, so eventually the write barrier is enabled
|
||||||
|
// and it will see writes of bad pointers in the test* functions below.
|
||||||
|
byteSliceSink = make([]byte, 1024)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var byteSliceSink []byte
|
||||||
|
|
||||||
|
func testCFNumberRef() {
|
||||||
|
var v int64 = 0
|
||||||
|
xCFNumberRef = C.CFNumberCreate(C.kCFAllocatorSystemDefault, C.kCFNumberSInt64Type, unsafe.Pointer(&v))
|
||||||
|
//fmt.Printf("CFNumberRef: %x\n", uintptr(unsafe.Pointer(xCFNumberRef)))
|
||||||
|
}
|
||||||
|
|
||||||
|
var xCFNumberRef C.CFNumberRef
|
||||||
|
|
||||||
|
func testCFDateRef() {
|
||||||
|
xCFDateRef = C.CFDateCreate(C.kCFAllocatorSystemDefault, 0) // 0 value is 1 Jan 2001 00:00:00 GMT
|
||||||
|
//fmt.Printf("CFDateRef: %x\n", uintptr(unsafe.Pointer(xCFDateRef)))
|
||||||
|
}
|
||||||
|
|
||||||
|
var xCFDateRef C.CFDateRef
|
||||||
|
|
||||||
|
func testCFBooleanRef() {
|
||||||
|
xCFBooleanRef = C.kCFBooleanFalse
|
||||||
|
//fmt.Printf("CFBooleanRef: %x\n", uintptr(unsafe.Pointer(xCFBooleanRef)))
|
||||||
|
}
|
||||||
|
|
||||||
|
var xCFBooleanRef C.CFBooleanRef
|
||||||
13
misc/cgo/test/issue21897b.go
Normal file
13
misc/cgo/test/issue21897b.go
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright 2017 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 !darwin !cgo internal
|
||||||
|
|
||||||
|
package cgotest
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func test21897(t *testing.T) {
|
||||||
|
t.Skip("test runs only on darwin+cgo")
|
||||||
|
}
|
||||||
24
misc/cgo/test/issue22958.go
Normal file
24
misc/cgo/test/issue22958.go
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright 2017 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 cgotest
|
||||||
|
|
||||||
|
// Test handling of bitfields.
|
||||||
|
|
||||||
|
/*
|
||||||
|
typedef struct {
|
||||||
|
unsigned long long f8 : 8;
|
||||||
|
unsigned long long f16 : 16;
|
||||||
|
unsigned long long f24 : 24;
|
||||||
|
unsigned long long f32 : 32;
|
||||||
|
unsigned long long f40 : 40;
|
||||||
|
unsigned long long f48 : 48;
|
||||||
|
unsigned long long f56 : 56;
|
||||||
|
unsigned long long f64 : 64;
|
||||||
|
} issue22958Type;
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
// Nothing to run, just make sure this compiles.
|
||||||
|
var Vissue22958 C.issue22958Type
|
||||||
33
misc/cgo/test/issue6907.go
Normal file
33
misc/cgo/test/issue6907.go
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Copyright 2017 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 cgotest
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
char* Issue6907CopyString(_GoString_ s) {
|
||||||
|
size_t n;
|
||||||
|
const char *p;
|
||||||
|
char *r;
|
||||||
|
|
||||||
|
n = _GoStringLen(s);
|
||||||
|
p = _GoStringPtr(s);
|
||||||
|
r = malloc(n + 1);
|
||||||
|
memmove(r, p, n);
|
||||||
|
r[n] = '\0';
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func test6907(t *testing.T) {
|
||||||
|
want := "yarn"
|
||||||
|
if got := C.GoString(C.Issue6907CopyString(want)); got != want {
|
||||||
|
t.Errorf("C.GoString(C.Issue6907CopyString(%q)) == %q, want %q", want, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
30
misc/cgo/test/issue6907export.go
Normal file
30
misc/cgo/test/issue6907export.go
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2017 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 cgotest
|
||||||
|
|
||||||
|
/*
|
||||||
|
extern int CheckIssue6907C(_GoString_);
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const CString = "C string"
|
||||||
|
|
||||||
|
//export CheckIssue6907Go
|
||||||
|
func CheckIssue6907Go(s string) C.int {
|
||||||
|
if s == CString {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func test6907Go(t *testing.T) {
|
||||||
|
if got := C.CheckIssue6907C(CString); got != 1 {
|
||||||
|
t.Errorf("C.CheckIssue6907C() == %d, want %d", got, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
11
misc/cgo/test/issue6907export_c.c
Normal file
11
misc/cgo/test/issue6907export_c.c
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright 2017 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 <string.h>
|
||||||
|
|
||||||
|
#include "_cgo_export.h"
|
||||||
|
|
||||||
|
int CheckIssue6907C(_GoString_ s) {
|
||||||
|
return CheckIssue6907Go(s);
|
||||||
|
}
|
||||||
|
|
@ -44,8 +44,8 @@ static void issue7978c(uint32_t *sync) {
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"runtime/debug"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -114,12 +114,7 @@ func test7978(t *testing.T) {
|
||||||
if C.HAS_SYNC_FETCH_AND_ADD == 0 {
|
if C.HAS_SYNC_FETCH_AND_ADD == 0 {
|
||||||
t.Skip("clang required for __sync_fetch_and_add support on darwin/arm")
|
t.Skip("clang required for __sync_fetch_and_add support on darwin/arm")
|
||||||
}
|
}
|
||||||
if runtime.GOOS == "android" || runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
|
debug.SetTraceback("2")
|
||||||
t.Skip("GOTRACEBACK is not passed on to the exec wrapper")
|
|
||||||
}
|
|
||||||
if os.Getenv("GOTRACEBACK") != "2" {
|
|
||||||
t.Fatalf("GOTRACEBACK must be 2")
|
|
||||||
}
|
|
||||||
issue7978sync = 0
|
issue7978sync = 0
|
||||||
go issue7978go()
|
go issue7978go()
|
||||||
// test in c code, before callback
|
// test in c code, before callback
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ package carchive_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"bytes"
|
||||||
"debug/elf"
|
"debug/elf"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
@ -134,8 +135,10 @@ func cmdToRun(name string) []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testInstall(t *testing.T, exe, libgoa, libgoh string, buildcmd ...string) {
|
func testInstall(t *testing.T, exe, libgoa, libgoh string, buildcmd ...string) {
|
||||||
|
t.Helper()
|
||||||
cmd := exec.Command(buildcmd[0], buildcmd[1:]...)
|
cmd := exec.Command(buildcmd[0], buildcmd[1:]...)
|
||||||
cmd.Env = gopathEnv
|
cmd.Env = gopathEnv
|
||||||
|
t.Log(buildcmd)
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
if out, err := cmd.CombinedOutput(); err != nil {
|
||||||
t.Logf("%s", out)
|
t.Logf("%s", out)
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
@ -171,7 +174,7 @@ func TestInstall(t *testing.T) {
|
||||||
testInstall(t, "./testp1"+exeSuffix,
|
testInstall(t, "./testp1"+exeSuffix,
|
||||||
filepath.Join("pkg", libgodir, "libgo.a"),
|
filepath.Join("pkg", libgodir, "libgo.a"),
|
||||||
filepath.Join("pkg", libgodir, "libgo.h"),
|
filepath.Join("pkg", libgodir, "libgo.h"),
|
||||||
"go", "install", "-buildmode=c-archive", "libgo")
|
"go", "install", "-i", "-buildmode=c-archive", "libgo")
|
||||||
|
|
||||||
// Test building libgo other than installing it.
|
// Test building libgo other than installing it.
|
||||||
// Header files are now present.
|
// Header files are now present.
|
||||||
|
|
@ -488,7 +491,7 @@ func TestPIE(t *testing.T) {
|
||||||
os.RemoveAll("pkg")
|
os.RemoveAll("pkg")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
cmd := exec.Command("go", "install", "-buildmode=c-archive", "libgo")
|
cmd := exec.Command("go", "install", "-i", "-buildmode=c-archive", "libgo")
|
||||||
cmd.Env = gopathEnv
|
cmd.Env = gopathEnv
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
if out, err := cmd.CombinedOutput(); err != nil {
|
||||||
t.Logf("%s", out)
|
t.Logf("%s", out)
|
||||||
|
|
@ -549,6 +552,8 @@ func TestSIGPROF(t *testing.T) {
|
||||||
switch GOOS {
|
switch GOOS {
|
||||||
case "windows", "plan9":
|
case "windows", "plan9":
|
||||||
t.Skipf("skipping SIGPROF test on %s", GOOS)
|
t.Skipf("skipping SIGPROF test on %s", GOOS)
|
||||||
|
case "darwin":
|
||||||
|
t.Skipf("skipping SIGPROF test on %s; see https://golang.org/issue/19320", GOOS)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
@ -605,9 +610,26 @@ func TestCompileWithoutShared(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
exe := "./testnoshared" + exeSuffix
|
exe := "./testnoshared" + exeSuffix
|
||||||
ccArgs := append(cc, "-o", exe, "main5.c", "libgo2.a")
|
|
||||||
|
// In some cases, -no-pie is needed here, but not accepted everywhere. First try
|
||||||
|
// if -no-pie is accepted. See #22126.
|
||||||
|
ccArgs := append(cc, "-o", exe, "-no-pie", "main5.c", "libgo2.a")
|
||||||
t.Log(ccArgs)
|
t.Log(ccArgs)
|
||||||
out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
|
out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
|
||||||
|
|
||||||
|
// If -no-pie unrecognized, try -nopie if this is possibly clang
|
||||||
|
if err != nil && bytes.Contains(out, []byte("unknown")) && !strings.Contains(cc[0], "gcc") {
|
||||||
|
ccArgs = append(cc, "-o", exe, "-nopie", "main5.c", "libgo2.a")
|
||||||
|
t.Log(ccArgs)
|
||||||
|
out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't use either -no-pie or -nopie
|
||||||
|
if err != nil && bytes.Contains(out, []byte("unrecognized")) {
|
||||||
|
ccArgs := append(cc, "-o", exe, "main5.c", "libgo2.a")
|
||||||
|
t.Log(ccArgs)
|
||||||
|
out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
|
||||||
|
}
|
||||||
t.Logf("%s", out)
|
t.Logf("%s", out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
|
||||||
479
misc/cgo/testcshared/cshared_test.go
Normal file
479
misc/cgo/testcshared/cshared_test.go
Normal file
|
|
@ -0,0 +1,479 @@
|
||||||
|
// Copyright 2017 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 cshared_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"debug/elf"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
// C compiler with args (from $(go env CC) $(go env GOGCCFLAGS)).
|
||||||
|
var cc []string
|
||||||
|
|
||||||
|
// An environment with GOPATH=$(pwd).
|
||||||
|
var gopathEnv []string
|
||||||
|
|
||||||
|
// ".exe" on Windows.
|
||||||
|
var exeSuffix string
|
||||||
|
|
||||||
|
var GOOS, GOARCH, GOROOT string
|
||||||
|
var installdir, androiddir string
|
||||||
|
var libSuffix, libgoname string
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
GOOS = goEnv("GOOS")
|
||||||
|
GOARCH = goEnv("GOARCH")
|
||||||
|
GOROOT = goEnv("GOROOT")
|
||||||
|
|
||||||
|
if _, err := os.Stat(GOROOT); os.IsNotExist(err) {
|
||||||
|
log.Fatalf("Unable able to find GOROOT at '%s'", GOROOT)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Directory where cgo headers and outputs will be installed.
|
||||||
|
// The installation directory format varies depending on the platform.
|
||||||
|
installdir = path.Join("pkg", fmt.Sprintf("%s_%s_testcshared", GOOS, GOARCH))
|
||||||
|
switch GOOS {
|
||||||
|
case "darwin":
|
||||||
|
libSuffix = "dylib"
|
||||||
|
case "windows":
|
||||||
|
libSuffix = "dll"
|
||||||
|
default:
|
||||||
|
libSuffix = "so"
|
||||||
|
installdir = path.Join("pkg", fmt.Sprintf("%s_%s_testcshared_shared", GOOS, GOARCH))
|
||||||
|
}
|
||||||
|
|
||||||
|
androiddir = fmt.Sprintf("/data/local/tmp/testcshared-%d", os.Getpid())
|
||||||
|
if GOOS == "android" {
|
||||||
|
cmd := exec.Command("adb", "shell", "mkdir", "-p", androiddir)
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("setupAndroid failed: %v\n%s\n", err, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
libgoname = "libgo." + libSuffix
|
||||||
|
|
||||||
|
cc = []string{goEnv("CC")}
|
||||||
|
|
||||||
|
out := goEnv("GOGCCFLAGS")
|
||||||
|
quote := '\000'
|
||||||
|
start := 0
|
||||||
|
lastSpace := true
|
||||||
|
backslash := false
|
||||||
|
s := string(out)
|
||||||
|
for i, c := range s {
|
||||||
|
if quote == '\000' && unicode.IsSpace(c) {
|
||||||
|
if !lastSpace {
|
||||||
|
cc = append(cc, s[start:i])
|
||||||
|
lastSpace = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if lastSpace {
|
||||||
|
start = i
|
||||||
|
lastSpace = false
|
||||||
|
}
|
||||||
|
if quote == '\000' && !backslash && (c == '"' || c == '\'') {
|
||||||
|
quote = c
|
||||||
|
backslash = false
|
||||||
|
} else if !backslash && quote == c {
|
||||||
|
quote = '\000'
|
||||||
|
} else if (quote == '\000' || quote == '"') && !backslash && c == '\\' {
|
||||||
|
backslash = true
|
||||||
|
} else {
|
||||||
|
backslash = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !lastSpace {
|
||||||
|
cc = append(cc, s[start:])
|
||||||
|
}
|
||||||
|
|
||||||
|
switch GOOS {
|
||||||
|
case "darwin":
|
||||||
|
// For Darwin/ARM.
|
||||||
|
// TODO(crawshaw): can we do better?
|
||||||
|
cc = append(cc, []string{"-framework", "CoreFoundation", "-framework", "Foundation"}...)
|
||||||
|
case "android":
|
||||||
|
cc = append(cc, "-pie", "-fuse-ld=gold")
|
||||||
|
}
|
||||||
|
libgodir := GOOS + "_" + GOARCH
|
||||||
|
switch GOOS {
|
||||||
|
case "darwin":
|
||||||
|
if GOARCH == "arm" || GOARCH == "arm64" {
|
||||||
|
libgodir += "_shared"
|
||||||
|
}
|
||||||
|
case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
|
||||||
|
libgodir += "_shared"
|
||||||
|
}
|
||||||
|
cc = append(cc, "-I", filepath.Join("pkg", libgodir))
|
||||||
|
|
||||||
|
// Build an environment with GOPATH=$(pwd)
|
||||||
|
dir, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
gopathEnv = append(os.Environ(), "GOPATH="+dir)
|
||||||
|
|
||||||
|
if GOOS == "windows" {
|
||||||
|
exeSuffix = ".exe"
|
||||||
|
}
|
||||||
|
|
||||||
|
st := m.Run()
|
||||||
|
|
||||||
|
os.Remove(libgoname)
|
||||||
|
os.RemoveAll("pkg")
|
||||||
|
cleanupHeaders()
|
||||||
|
cleanupAndroid()
|
||||||
|
|
||||||
|
os.Exit(st)
|
||||||
|
}
|
||||||
|
|
||||||
|
func goEnv(key string) string {
|
||||||
|
out, err := exec.Command("go", "env", key).Output()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "go env %s failed:\n%s", key, err)
|
||||||
|
fmt.Fprintf(os.Stderr, "%s", err.(*exec.ExitError).Stderr)
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(string(out))
|
||||||
|
}
|
||||||
|
|
||||||
|
func cmdToRun(name string) string {
|
||||||
|
return "./" + name + exeSuffix
|
||||||
|
}
|
||||||
|
|
||||||
|
func adbPush(t *testing.T, filename string) {
|
||||||
|
if GOOS != "android" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
args := []string{"adb", "push", filename, fmt.Sprintf("%s/%s", androiddir, filename)}
|
||||||
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
|
if out, err := cmd.CombinedOutput(); err != nil {
|
||||||
|
t.Fatalf("adb command failed: %v\n%s\n", err, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func adbRun(t *testing.T, env []string, adbargs ...string) string {
|
||||||
|
if GOOS != "android" {
|
||||||
|
t.Fatalf("trying to run adb command when operating system is not android.")
|
||||||
|
}
|
||||||
|
args := []string{"adb", "shell"}
|
||||||
|
// Propagate LD_LIBRARY_PATH to the adb shell invocation.
|
||||||
|
for _, e := range env {
|
||||||
|
if strings.Index(e, "LD_LIBRARY_PATH=") != -1 {
|
||||||
|
adbargs = append([]string{e}, adbargs...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shellcmd := fmt.Sprintf("cd %s; %s", androiddir, strings.Join(adbargs, " "))
|
||||||
|
args = append(args, shellcmd)
|
||||||
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("adb command failed: %v\n%s\n", err, out)
|
||||||
|
}
|
||||||
|
return strings.Replace(string(out), "\r", "", -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(t *testing.T, env []string, args ...string) string {
|
||||||
|
t.Helper()
|
||||||
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
|
cmd.Env = env
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("command failed: %v\n%v\n%s\n", args, err, out)
|
||||||
|
} else {
|
||||||
|
t.Logf("run: %v", args)
|
||||||
|
}
|
||||||
|
return string(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runExe(t *testing.T, env []string, args ...string) string {
|
||||||
|
t.Helper()
|
||||||
|
if GOOS == "android" {
|
||||||
|
return adbRun(t, env, args...)
|
||||||
|
}
|
||||||
|
return run(t, env, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runCC(t *testing.T, args ...string) string {
|
||||||
|
t.Helper()
|
||||||
|
// This function is run in parallel, so append to a copy of cc
|
||||||
|
// rather than cc itself.
|
||||||
|
return run(t, nil, append(append([]string(nil), cc...), args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createHeaders() error {
|
||||||
|
args := []string{"go", "install", "-i", "-buildmode=c-shared",
|
||||||
|
"-installsuffix", "testcshared", "libgo"}
|
||||||
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
|
cmd.Env = gopathEnv
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("command failed: %v\n%v\n%s\n", args, err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
args = []string{"go", "build", "-buildmode=c-shared",
|
||||||
|
"-installsuffix", "testcshared",
|
||||||
|
"-o", libgoname,
|
||||||
|
filepath.Join("src", "libgo", "libgo.go")}
|
||||||
|
cmd = exec.Command(args[0], args[1:]...)
|
||||||
|
cmd.Env = gopathEnv
|
||||||
|
out, err = cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("command failed: %v\n%v\n%s\n", args, err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
if GOOS == "android" {
|
||||||
|
args = []string{"adb", "push", libgoname, fmt.Sprintf("%s/%s", androiddir, libgoname)}
|
||||||
|
cmd = exec.Command(args[0], args[1:]...)
|
||||||
|
out, err = cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("adb command failed: %v\n%s\n", err, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
headersOnce sync.Once
|
||||||
|
headersErr error
|
||||||
|
)
|
||||||
|
|
||||||
|
func createHeadersOnce(t *testing.T) {
|
||||||
|
headersOnce.Do(func() {
|
||||||
|
headersErr = createHeaders()
|
||||||
|
})
|
||||||
|
if headersErr != nil {
|
||||||
|
t.Fatal(headersErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanupHeaders() {
|
||||||
|
os.Remove("libgo.h")
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanupAndroid() {
|
||||||
|
if GOOS != "android" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cmd := exec.Command("adb", "shell", "rm", "-rf", androiddir)
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("cleanupAndroid failed: %v\n%s\n", err, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test0: exported symbols in shared lib are accessible.
|
||||||
|
func TestExportedSymbols(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
cmd := "testp0"
|
||||||
|
bin := cmdToRun(cmd)
|
||||||
|
|
||||||
|
createHeadersOnce(t)
|
||||||
|
|
||||||
|
runCC(t, "-I", installdir, "-o", cmd, "main0.c", libgoname)
|
||||||
|
adbPush(t, cmd)
|
||||||
|
|
||||||
|
defer os.Remove(bin)
|
||||||
|
|
||||||
|
out := runExe(t, append(gopathEnv, "LD_LIBRARY_PATH=."), bin)
|
||||||
|
if strings.TrimSpace(out) != "PASS" {
|
||||||
|
t.Error(out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test1: shared library can be dynamically loaded and exported symbols are accessible.
|
||||||
|
func TestExportedSymbolsWithDynamicLoad(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
if GOOS == "windows" {
|
||||||
|
t.Logf("Skipping on %s", GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := "testp1"
|
||||||
|
bin := cmdToRun(cmd)
|
||||||
|
|
||||||
|
createHeadersOnce(t)
|
||||||
|
|
||||||
|
runCC(t, "-o", cmd, "main1.c", "-ldl")
|
||||||
|
adbPush(t, cmd)
|
||||||
|
|
||||||
|
defer os.Remove(bin)
|
||||||
|
|
||||||
|
out := runExe(t, nil, bin, "./"+libgoname)
|
||||||
|
if strings.TrimSpace(out) != "PASS" {
|
||||||
|
t.Error(out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test2: tests libgo2 which does not export any functions.
|
||||||
|
func TestUnexportedSymbols(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
if GOOS == "windows" {
|
||||||
|
t.Logf("Skipping on %s", GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := "testp2"
|
||||||
|
bin := cmdToRun(cmd)
|
||||||
|
libname := "libgo2." + libSuffix
|
||||||
|
|
||||||
|
run(t,
|
||||||
|
gopathEnv,
|
||||||
|
"go", "build",
|
||||||
|
"-buildmode=c-shared",
|
||||||
|
"-installsuffix", "testcshared",
|
||||||
|
"-o", libname, "libgo2",
|
||||||
|
)
|
||||||
|
adbPush(t, libname)
|
||||||
|
|
||||||
|
linkFlags := "-Wl,--no-as-needed"
|
||||||
|
if GOOS == "darwin" {
|
||||||
|
linkFlags = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
runCC(t, "-o", cmd, "main2.c", linkFlags, libname)
|
||||||
|
adbPush(t, cmd)
|
||||||
|
|
||||||
|
defer os.Remove(libname)
|
||||||
|
defer os.Remove(bin)
|
||||||
|
|
||||||
|
out := runExe(t, append(gopathEnv, "LD_LIBRARY_PATH=."), bin)
|
||||||
|
|
||||||
|
if strings.TrimSpace(out) != "PASS" {
|
||||||
|
t.Error(out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test3: tests main.main is exported on android.
|
||||||
|
func TestMainExportedOnAndroid(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
switch GOOS {
|
||||||
|
case "android":
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
t.Logf("Skipping on %s", GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := "testp3"
|
||||||
|
bin := cmdToRun(cmd)
|
||||||
|
|
||||||
|
createHeadersOnce(t)
|
||||||
|
|
||||||
|
runCC(t, "-o", cmd, "main3.c", "-ldl")
|
||||||
|
adbPush(t, cmd)
|
||||||
|
|
||||||
|
defer os.Remove(bin)
|
||||||
|
|
||||||
|
out := runExe(t, nil, bin, "./"+libgoname)
|
||||||
|
if strings.TrimSpace(out) != "PASS" {
|
||||||
|
t.Error(out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSignalHandlers(t *testing.T, pkgname, cfile, cmd string) {
|
||||||
|
libname := pkgname + "." + libSuffix
|
||||||
|
run(t,
|
||||||
|
gopathEnv,
|
||||||
|
"go", "build",
|
||||||
|
"-buildmode=c-shared",
|
||||||
|
"-installsuffix", "testcshared",
|
||||||
|
"-o", libname, pkgname,
|
||||||
|
)
|
||||||
|
adbPush(t, libname)
|
||||||
|
runCC(t, "-pthread", "-o", cmd, cfile, "-ldl")
|
||||||
|
adbPush(t, cmd)
|
||||||
|
|
||||||
|
bin := cmdToRun(cmd)
|
||||||
|
|
||||||
|
defer os.Remove(libname)
|
||||||
|
defer os.Remove(bin)
|
||||||
|
defer os.Remove(pkgname + ".h")
|
||||||
|
|
||||||
|
out := runExe(t, nil, bin, "./"+libname)
|
||||||
|
if strings.TrimSpace(out) != "PASS" {
|
||||||
|
t.Error(run(t, nil, bin, libname, "verbose"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test4: test signal handlers
|
||||||
|
func TestSignalHandlers(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
if GOOS == "windows" {
|
||||||
|
t.Logf("Skipping on %s", GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
testSignalHandlers(t, "libgo4", "main4.c", "testp4")
|
||||||
|
}
|
||||||
|
|
||||||
|
// test5: test signal handlers with os/signal.Notify
|
||||||
|
func TestSignalHandlersWithNotify(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
if GOOS == "windows" {
|
||||||
|
t.Logf("Skipping on %s", GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
testSignalHandlers(t, "libgo5", "main5.c", "testp5")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPIE(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
switch GOOS {
|
||||||
|
case "linux", "android":
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
t.Logf("Skipping on %s", GOOS)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
createHeadersOnce(t)
|
||||||
|
|
||||||
|
f, err := elf.Open(libgoname)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("elf.Open failed: %v", err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
ds := f.SectionByType(elf.SHT_DYNAMIC)
|
||||||
|
if ds == nil {
|
||||||
|
t.Fatalf("no SHT_DYNAMIC section")
|
||||||
|
}
|
||||||
|
d, err := ds.Data()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't read SHT_DYNAMIC contents: %v", err)
|
||||||
|
}
|
||||||
|
for len(d) > 0 {
|
||||||
|
var tag elf.DynTag
|
||||||
|
switch f.Class {
|
||||||
|
case elf.ELFCLASS32:
|
||||||
|
tag = elf.DynTag(f.ByteOrder.Uint32(d[:4]))
|
||||||
|
d = d[8:]
|
||||||
|
case elf.ELFCLASS64:
|
||||||
|
tag = elf.DynTag(f.ByteOrder.Uint64(d[:8]))
|
||||||
|
d = d[16:]
|
||||||
|
}
|
||||||
|
if tag == elf.DT_TEXTREL {
|
||||||
|
t.Fatalf("%s has DT_TEXTREL flag", libgoname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,5 +8,6 @@ import "C"
|
||||||
|
|
||||||
//export FromPkg
|
//export FromPkg
|
||||||
func FromPkg() int32 { return 1024 }
|
func FromPkg() int32 { return 1024 }
|
||||||
|
|
||||||
//export Divu
|
//export Divu
|
||||||
func Divu(a, b uint32) uint32 { return a / b }
|
func Divu(a, b uint32) uint32 { return a / b }
|
||||||
|
|
|
||||||
|
|
@ -1,193 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# Copyright 2015 The Go Authors. All rights reserved.
|
|
||||||
# Use of this source code is governed by a BSD-style
|
|
||||||
# license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
# For testing Android, this script requires adb to push and run compiled
|
|
||||||
# binaries on a target device.
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if [ ! -f src/libgo/libgo.go ]; then
|
|
||||||
cwd=$(pwd)
|
|
||||||
echo "misc/cgo/testcshared/test.bash is running in $cwd" 1>&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
goos=$(go env GOOS)
|
|
||||||
goarch=$(go env GOARCH)
|
|
||||||
goroot=$(go env GOROOT)
|
|
||||||
if [ ! -d "$goroot" ]; then
|
|
||||||
echo 'misc/cgo/testcshared/test.bash cannot find GOROOT' 1>&2
|
|
||||||
echo '$GOROOT:' "$GOROOT" 1>&2
|
|
||||||
echo 'go env GOROOT:' "$goroot" 1>&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Directory where cgo headers and outputs will be installed.
|
|
||||||
# The installation directory format varies depending on the platform.
|
|
||||||
installdir=pkg/${goos}_${goarch}_testcshared_shared
|
|
||||||
if [ "${goos}" = "darwin" ]; then
|
|
||||||
installdir=pkg/${goos}_${goarch}_testcshared
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Temporary directory on the android device.
|
|
||||||
androidpath=/data/local/tmp/testcshared-$$
|
|
||||||
|
|
||||||
function cleanup() {
|
|
||||||
rm -f libgo.$libext libgo2.$libext libgo4.$libext libgo5.$libext
|
|
||||||
rm -f libgo.h libgo4.h libgo5.h
|
|
||||||
rm -f testp testp2 testp3 testp4 testp5
|
|
||||||
rm -rf pkg "${goroot}/${installdir}"
|
|
||||||
|
|
||||||
if [ "$goos" = "android" ]; then
|
|
||||||
adb shell rm -rf "$androidpath"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
trap cleanup EXIT
|
|
||||||
|
|
||||||
if [ "$goos" = "android" ]; then
|
|
||||||
adb shell mkdir -p "$androidpath"
|
|
||||||
fi
|
|
||||||
|
|
||||||
function run() {
|
|
||||||
case "$goos" in
|
|
||||||
"android")
|
|
||||||
local args=$@
|
|
||||||
output=$(adb shell "cd ${androidpath}; $@")
|
|
||||||
output=$(echo $output|tr -d '\r')
|
|
||||||
case $output in
|
|
||||||
*PASS) echo "PASS";;
|
|
||||||
*) echo "$output";;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo $(env $@)
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
function binpush() {
|
|
||||||
bin=${1}
|
|
||||||
if [ "$goos" = "android" ]; then
|
|
||||||
adb push "$bin" "${androidpath}/${bin}" 2>/dev/null
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
rm -rf pkg
|
|
||||||
|
|
||||||
suffix="-installsuffix testcshared"
|
|
||||||
|
|
||||||
libext="so"
|
|
||||||
if [ "$goos" = "darwin" ]; then
|
|
||||||
libext="dylib"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create the header files.
|
|
||||||
GOPATH=$(pwd) go install -buildmode=c-shared $suffix libgo
|
|
||||||
|
|
||||||
GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo.$libext src/libgo/libgo.go
|
|
||||||
binpush libgo.$libext
|
|
||||||
|
|
||||||
if [ "$goos" = "linux" ] || [ "$goos" = "android" ] ; then
|
|
||||||
if readelf -d libgo.$libext | grep TEXTREL >/dev/null; then
|
|
||||||
echo "libgo.$libext has TEXTREL set"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
GOGCCFLAGS=$(go env GOGCCFLAGS)
|
|
||||||
if [ "$goos" = "android" ]; then
|
|
||||||
GOGCCFLAGS="${GOGCCFLAGS} -pie -fuse-ld=gold"
|
|
||||||
fi
|
|
||||||
|
|
||||||
status=0
|
|
||||||
|
|
||||||
# test0: exported symbols in shared lib are accessible.
|
|
||||||
# TODO(iant): using _shared here shouldn't really be necessary.
|
|
||||||
$(go env CC) ${GOGCCFLAGS} -I ${installdir} -o testp main0.c ./libgo.$libext
|
|
||||||
binpush testp
|
|
||||||
|
|
||||||
output=$(run LD_LIBRARY_PATH=. ./testp)
|
|
||||||
if [ "$output" != "PASS" ]; then
|
|
||||||
echo "FAIL test0 got ${output}"
|
|
||||||
status=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# test1: shared library can be dynamically loaded and exported symbols are accessible.
|
|
||||||
$(go env CC) ${GOGCCFLAGS} -o testp main1.c -ldl
|
|
||||||
binpush testp
|
|
||||||
output=$(run ./testp ./libgo.$libext)
|
|
||||||
if [ "$output" != "PASS" ]; then
|
|
||||||
echo "FAIL test1 got ${output}"
|
|
||||||
status=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# test2: tests libgo2 which does not export any functions.
|
|
||||||
GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo2.$libext libgo2
|
|
||||||
binpush libgo2.$libext
|
|
||||||
linkflags="-Wl,--no-as-needed"
|
|
||||||
if [ "$goos" = "darwin" ]; then
|
|
||||||
linkflags=""
|
|
||||||
fi
|
|
||||||
$(go env CC) ${GOGCCFLAGS} -o testp2 main2.c $linkflags libgo2.$libext
|
|
||||||
binpush testp2
|
|
||||||
output=$(run LD_LIBRARY_PATH=. ./testp2)
|
|
||||||
if [ "$output" != "PASS" ]; then
|
|
||||||
echo "FAIL test2 got ${output}"
|
|
||||||
status=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# test3: tests main.main is exported on android.
|
|
||||||
if [ "$goos" = "android" ]; then
|
|
||||||
$(go env CC) ${GOGCCFLAGS} -o testp3 main3.c -ldl
|
|
||||||
binpush testp3
|
|
||||||
output=$(run ./testp ./libgo.so)
|
|
||||||
if [ "$output" != "PASS" ]; then
|
|
||||||
echo "FAIL test3 got ${output}"
|
|
||||||
status=1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# test4: tests signal handlers
|
|
||||||
GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo4.$libext libgo4
|
|
||||||
binpush libgo4.$libext
|
|
||||||
$(go env CC) ${GOGCCFLAGS} -pthread -o testp4 main4.c -ldl
|
|
||||||
binpush testp4
|
|
||||||
output=$(run ./testp4 ./libgo4.$libext 2>&1)
|
|
||||||
if test "$output" != "PASS"; then
|
|
||||||
echo "FAIL test4 got ${output}"
|
|
||||||
if test "$goos" != "android"; then
|
|
||||||
echo "re-running test4 in verbose mode"
|
|
||||||
./testp4 ./libgo4.$libext verbose
|
|
||||||
fi
|
|
||||||
status=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# test5: tests signal handlers with os/signal.Notify
|
|
||||||
GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo5.$libext libgo5
|
|
||||||
binpush libgo5.$libext
|
|
||||||
$(go env CC) ${GOGCCFLAGS} -pthread -o testp5 main5.c -ldl
|
|
||||||
binpush testp5
|
|
||||||
output=$(run ./testp5 ./libgo5.$libext 2>&1)
|
|
||||||
if test "$output" != "PASS"; then
|
|
||||||
echo "FAIL test5 got ${output}"
|
|
||||||
if test "$goos" != "android"; then
|
|
||||||
echo "re-running test5 in verbose mode"
|
|
||||||
./testp5 ./libgo5.$libext verbose
|
|
||||||
fi
|
|
||||||
status=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$libext" = "dylib"; then
|
|
||||||
# make sure dylibs are well-formed
|
|
||||||
if ! otool -l libgo*.dylib >/dev/null; then
|
|
||||||
status=1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test $status = 0; then
|
|
||||||
echo "ok"
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit $status
|
|
||||||
|
|
@ -126,14 +126,24 @@ func main() {
|
||||||
log.Fatalf(`plugin1.F()=%d, want 17`, gotf)
|
log.Fatalf(`plugin1.F()=%d, want 17`, gotf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// plugin2 has no exported symbols, only an init function.
|
p2, err := plugin.Open("plugin2.so")
|
||||||
if _, err := plugin.Open("plugin2.so"); err != nil {
|
if err != nil {
|
||||||
log.Fatalf("plugin.Open failed: %v", err)
|
log.Fatalf("plugin.Open failed: %v", err)
|
||||||
}
|
}
|
||||||
|
// Check that plugin2's init function was called, and
|
||||||
|
// that it modifies the same global variable as the host.
|
||||||
if got, want := common.X, 2; got != want {
|
if got, want := common.X, 2; got != want {
|
||||||
log.Fatalf("after loading plugin2, common.X=%d, want %d", got, want)
|
log.Fatalf("after loading plugin2, common.X=%d, want %d", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err = plugin.Open("plugin2-dup.so")
|
||||||
|
if err == nil {
|
||||||
|
log.Fatal(`plugin.Open("plugin2-dup.so"): duplicate open should have failed`)
|
||||||
|
}
|
||||||
|
if s := err.Error(); !strings.Contains(s, "already loaded") {
|
||||||
|
log.Fatal(`plugin.Open("plugin2.so"): error does not mention "already loaded"`)
|
||||||
|
}
|
||||||
|
|
||||||
_, err = plugin.Open("plugin-mismatch.so")
|
_, err = plugin.Open("plugin-mismatch.so")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Fatal(`plugin.Open("plugin-mismatch.so"): should have failed`)
|
log.Fatal(`plugin.Open("plugin-mismatch.so"): should have failed`)
|
||||||
|
|
@ -142,6 +152,24 @@ func main() {
|
||||||
log.Fatalf(`plugin.Open("plugin-mismatch.so"): error does not mention "different version": %v`, s)
|
log.Fatalf(`plugin.Open("plugin-mismatch.so"): error does not mention "different version": %v`, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err = plugin.Open("plugin2-dup.so")
|
||||||
|
if err == nil {
|
||||||
|
log.Fatal(`plugin.Open("plugin2-dup.so"): duplicate open after bad plugin should have failed`)
|
||||||
|
}
|
||||||
|
_, err = plugin.Open("plugin2.so")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf(`plugin.Open("plugin2.so"): second open with same name failed: %v`, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that unexported types with the same names in
|
||||||
|
// different plugins do not interfere with each other.
|
||||||
|
//
|
||||||
|
// See Issue #21386.
|
||||||
|
UnexportedNameReuse, _ := p.Lookup("UnexportedNameReuse")
|
||||||
|
UnexportedNameReuse.(func())()
|
||||||
|
UnexportedNameReuse, _ = p2.Lookup("UnexportedNameReuse")
|
||||||
|
UnexportedNameReuse.(func())()
|
||||||
|
|
||||||
testUnnamed()
|
testUnnamed()
|
||||||
|
|
||||||
fmt.Println("PASS")
|
fmt.Println("PASS")
|
||||||
|
|
|
||||||
23
misc/cgo/testplugin/src/issue18584/main.go
Normal file
23
misc/cgo/testplugin/src/issue18584/main.go
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright 2017 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 "plugin"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
p, err := plugin.Open("plugin.so")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sym, err := p.Lookup("G")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
g := sym.(func() bool)
|
||||||
|
if !g() {
|
||||||
|
panic("expected types to match, Issue #18584")
|
||||||
|
}
|
||||||
|
}
|
||||||
19
misc/cgo/testplugin/src/issue18584/plugin.go
Normal file
19
misc/cgo/testplugin/src/issue18584/plugin.go
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright 2017 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 "reflect"
|
||||||
|
|
||||||
|
type C struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func F(c *C) *C {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func G() bool {
|
||||||
|
var c *C
|
||||||
|
return reflect.TypeOf(F).Out(0) == reflect.TypeOf(c)
|
||||||
|
}
|
||||||
29
misc/cgo/testplugin/src/issue19418/main.go
Normal file
29
misc/cgo/testplugin/src/issue19418/main.go
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2017 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 (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
p, err := plugin.Open("plugin.so")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
val, err := p.Lookup("Val")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
got := *val.(*string)
|
||||||
|
const want = "linkstr"
|
||||||
|
if got != want {
|
||||||
|
fmt.Fprintf(os.Stderr, "issue19418 value is %q, want %q\n", got, want)
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,6 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package cpu
|
package main
|
||||||
|
|
||||||
const CacheLineSize = 128
|
var Val = "val-unset"
|
||||||
15
misc/cgo/testplugin/src/issue19529/plugin.go
Normal file
15
misc/cgo/testplugin/src/issue19529/plugin.go
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Foo struct {
|
||||||
|
Bar string `json:"Bar@baz,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func F() {
|
||||||
|
println(reflect.TypeOf(Foo{}).Field(0).Tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {}
|
||||||
28
misc/cgo/testplugin/src/issue22175/main.go
Normal file
28
misc/cgo/testplugin/src/issue22175/main.go
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
// Copyright 2017 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 (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
p2, err := plugin.Open("issue22175_plugin1.so")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
f, err := p2.Lookup("F")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
got := f.(func() int)()
|
||||||
|
const want = 971
|
||||||
|
if got != want {
|
||||||
|
fmt.Fprintf(os.Stderr, "issue22175: F()=%d, want %d", got, want)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
21
misc/cgo/testplugin/src/issue22175/plugin1.go
Normal file
21
misc/cgo/testplugin/src/issue22175/plugin1.go
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright 2017 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 "plugin"
|
||||||
|
|
||||||
|
func F() int {
|
||||||
|
p2, err := plugin.Open("issue22175_plugin2.so")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
g, err := p2.Lookup("G")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return g.(func() int)()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {}
|
||||||
9
misc/cgo/testplugin/src/issue22175/plugin2.go
Normal file
9
misc/cgo/testplugin/src/issue22175/plugin2.go
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
// Copyright 2017 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
|
||||||
|
|
||||||
|
func G() int { return 971 }
|
||||||
|
|
||||||
|
func main() {}
|
||||||
28
misc/cgo/testplugin/src/issue22295.pkg/main.go
Normal file
28
misc/cgo/testplugin/src/issue22295.pkg/main.go
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
// Copyright 2017 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
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
p, err := plugin.Open("issue.22295.so")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
f, err := p.Lookup("F")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
const want = 2503
|
||||||
|
got := f.(func() int)()
|
||||||
|
if got != want {
|
||||||
|
log.Fatalf("got %d, want %d", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
16
misc/cgo/testplugin/src/issue22295.pkg/plugin.go
Normal file
16
misc/cgo/testplugin/src/issue22295.pkg/plugin.go
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright 2017 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
|
||||||
|
|
||||||
|
var f *int
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
f = new(int)
|
||||||
|
*f = 2503
|
||||||
|
}
|
||||||
|
|
||||||
|
func F() int { return *f }
|
||||||
|
|
||||||
|
func main() {}
|
||||||
|
|
@ -7,7 +7,10 @@ package main
|
||||||
// // No C code required.
|
// // No C code required.
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import "common"
|
import (
|
||||||
|
"common"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
func F() int {
|
func F() int {
|
||||||
_ = make([]byte, 1<<21) // trigger stack unwind, Issue #18190.
|
_ = make([]byte, 1<<21) // trigger stack unwind, Issue #18190.
|
||||||
|
|
@ -33,6 +36,21 @@ func init() {
|
||||||
call(g)
|
call(g)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sameNameReusedInPlugins struct {
|
||||||
|
X string
|
||||||
|
}
|
||||||
|
|
||||||
|
type sameNameHolder struct {
|
||||||
|
F *sameNameReusedInPlugins
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnexportedNameReuse() {
|
||||||
|
h := sameNameHolder{}
|
||||||
|
v := reflect.ValueOf(&h).Elem().Field(0)
|
||||||
|
newval := reflect.New(v.Type().Elem())
|
||||||
|
v.Set(newval)
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
panic("plugin1.main called")
|
panic("plugin1.main called")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"common"
|
"common"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -22,6 +23,21 @@ func init() {
|
||||||
common.X = 2
|
common.X = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sameNameReusedInPlugins struct {
|
||||||
|
X string
|
||||||
|
}
|
||||||
|
|
||||||
|
type sameNameHolder struct {
|
||||||
|
F *sameNameReusedInPlugins
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnexportedNameReuse() {
|
||||||
|
h := sameNameHolder{}
|
||||||
|
v := reflect.ValueOf(&h).Elem().Field(0)
|
||||||
|
newval := reflect.New(v.Type().Elem())
|
||||||
|
v.Set(newval)
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
panic("plugin1.main called")
|
panic("plugin1.main called")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,39 +14,77 @@ fi
|
||||||
goos=$(go env GOOS)
|
goos=$(go env GOOS)
|
||||||
goarch=$(go env GOARCH)
|
goarch=$(go env GOARCH)
|
||||||
|
|
||||||
|
echo SKIP: golang.org/issue/22571.
|
||||||
|
exit 0
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
rm -f plugin*.so unnamed*.so iface*.so
|
rm -f plugin*.so unnamed*.so iface*.so issue*
|
||||||
rm -rf host pkg sub iface issue18676 issue19534
|
rm -rf host pkg sub iface
|
||||||
}
|
}
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
|
|
||||||
rm -rf pkg sub
|
rm -rf pkg sub
|
||||||
mkdir sub
|
mkdir sub
|
||||||
|
|
||||||
GOPATH=$(pwd) go build -buildmode=plugin plugin1
|
GOPATH=$(pwd) go build -i -gcflags "$GO_GCFLAGS" -buildmode=plugin plugin1
|
||||||
GOPATH=$(pwd) go build -buildmode=plugin plugin2
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin plugin2
|
||||||
GOPATH=$(pwd)/altpath go build -buildmode=plugin plugin-mismatch
|
cp plugin2.so plugin2-dup.so
|
||||||
GOPATH=$(pwd) go build -buildmode=plugin -o=sub/plugin1.so sub/plugin1
|
GOPATH=$(pwd)/altpath go build -gcflags "$GO_GCFLAGS" -buildmode=plugin plugin-mismatch
|
||||||
GOPATH=$(pwd) go build -buildmode=plugin unnamed1.go
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o=sub/plugin1.so sub/plugin1
|
||||||
GOPATH=$(pwd) go build -buildmode=plugin unnamed2.go
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o=unnamed1.so unnamed1/main.go
|
||||||
GOPATH=$(pwd) go build host
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o=unnamed2.so unnamed2/main.go
|
||||||
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" host
|
||||||
|
|
||||||
LD_LIBRARY_PATH=$(pwd) ./host
|
LD_LIBRARY_PATH=$(pwd) ./host
|
||||||
|
|
||||||
# Test that types and itabs get properly uniqified.
|
# Test that types and itabs get properly uniqified.
|
||||||
GOPATH=$(pwd) go build -buildmode=plugin iface_a
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin iface_a
|
||||||
GOPATH=$(pwd) go build -buildmode=plugin iface_b
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin iface_b
|
||||||
GOPATH=$(pwd) go build iface
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" iface
|
||||||
LD_LIBRARY_PATH=$(pwd) ./iface
|
LD_LIBRARY_PATH=$(pwd) ./iface
|
||||||
|
|
||||||
|
function _timeout() (
|
||||||
|
set -e
|
||||||
|
$2 &
|
||||||
|
p=$!
|
||||||
|
(sleep $1; kill $p 2>/dev/null) &
|
||||||
|
p2=$!
|
||||||
|
wait $p 2>/dev/null
|
||||||
|
kill -0 $p2 2>/dev/null
|
||||||
|
)
|
||||||
|
|
||||||
# Test for issue 18676 - make sure we don't add the same itab twice.
|
# Test for issue 18676 - make sure we don't add the same itab twice.
|
||||||
# The buggy code hangs forever, so use a timeout to check for that.
|
# The buggy code hangs forever, so use a timeout to check for that.
|
||||||
GOPATH=$(pwd) go build -buildmode=plugin -o plugin.so src/issue18676/plugin.go
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o plugin.so src/issue18676/plugin.go
|
||||||
GOPATH=$(pwd) go build -o issue18676 src/issue18676/main.go
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -o issue18676 src/issue18676/main.go
|
||||||
timeout 10s ./issue18676
|
_timeout 10s ./issue18676
|
||||||
|
|
||||||
# Test for issue 19534 - that we can load a plugin built in a path with non-alpha
|
# Test for issue 19534 - that we can load a plugin built in a path with non-alpha
|
||||||
# characters
|
# characters
|
||||||
GOPATH=$(pwd) go build -buildmode=plugin -ldflags='-pluginpath=issue.19534' -o plugin.so src/issue19534/plugin.go
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -ldflags='-pluginpath=issue.19534' -o plugin.so src/issue19534/plugin.go
|
||||||
GOPATH=$(pwd) go build -o issue19534 src/issue19534/main.go
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -o issue19534 src/issue19534/main.go
|
||||||
./issue19534
|
./issue19534
|
||||||
|
|
||||||
|
# Test for issue 18584
|
||||||
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o plugin.so src/issue18584/plugin.go
|
||||||
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -o issue18584 src/issue18584/main.go
|
||||||
|
./issue18584
|
||||||
|
|
||||||
|
# Test for issue 19418
|
||||||
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin "-ldflags=-X main.Val=linkstr" -o plugin.so src/issue19418/plugin.go
|
||||||
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -o issue19418 src/issue19418/main.go
|
||||||
|
./issue19418
|
||||||
|
|
||||||
|
# Test for issue 19529
|
||||||
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o plugin.so src/issue19529/plugin.go
|
||||||
|
|
||||||
|
# Test for issue 22175
|
||||||
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o issue22175_plugin1.so src/issue22175/plugin1.go
|
||||||
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o issue22175_plugin2.so src/issue22175/plugin2.go
|
||||||
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -o issue22175 src/issue22175/main.go
|
||||||
|
./issue22175
|
||||||
|
|
||||||
|
# Test for issue 22295
|
||||||
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o issue.22295.so issue22295.pkg
|
||||||
|
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -o issue22295 src/issue22295.pkg/main.go
|
||||||
|
./issue22295
|
||||||
|
|
|
||||||
441
misc/cgo/testsanitizers/cc_test.go
Normal file
441
misc/cgo/testsanitizers/cc_test.go
Normal file
|
|
@ -0,0 +1,441 @@
|
||||||
|
// Copyright 2017 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.
|
||||||
|
|
||||||
|
// sanitizers_test checks the use of Go with sanitizers like msan, asan, etc.
|
||||||
|
// See https://github.com/google/sanitizers.
|
||||||
|
package sanitizers_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
"testing"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
var overcommit struct {
|
||||||
|
sync.Once
|
||||||
|
value int
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// requireOvercommit skips t if the kernel does not allow overcommit.
|
||||||
|
func requireOvercommit(t *testing.T) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
overcommit.Once.Do(func() {
|
||||||
|
var out []byte
|
||||||
|
out, overcommit.err = ioutil.ReadFile("/proc/sys/vm/overcommit_memory")
|
||||||
|
if overcommit.err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
overcommit.value, overcommit.err = strconv.Atoi(string(bytes.TrimSpace(out)))
|
||||||
|
})
|
||||||
|
|
||||||
|
if overcommit.err != nil {
|
||||||
|
t.Skipf("couldn't determine vm.overcommit_memory (%v); assuming no overcommit", overcommit.err)
|
||||||
|
}
|
||||||
|
if overcommit.value == 2 {
|
||||||
|
t.Skip("vm.overcommit_memory=2")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var env struct {
|
||||||
|
sync.Once
|
||||||
|
m map[string]string
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// goEnv returns the output of $(go env) as a map.
|
||||||
|
func goEnv(key string) (string, error) {
|
||||||
|
env.Once.Do(func() {
|
||||||
|
var out []byte
|
||||||
|
out, env.err = exec.Command("go", "env", "-json").Output()
|
||||||
|
if env.err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
env.m = make(map[string]string)
|
||||||
|
env.err = json.Unmarshal(out, &env.m)
|
||||||
|
})
|
||||||
|
if env.err != nil {
|
||||||
|
return "", env.err
|
||||||
|
}
|
||||||
|
|
||||||
|
v, ok := env.m[key]
|
||||||
|
if !ok {
|
||||||
|
return "", fmt.Errorf("`go env`: no entry for %v", key)
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// replaceEnv sets the key environment variable to value in cmd.
|
||||||
|
func replaceEnv(cmd *exec.Cmd, key, value string) {
|
||||||
|
if cmd.Env == nil {
|
||||||
|
cmd.Env = os.Environ()
|
||||||
|
}
|
||||||
|
cmd.Env = append(cmd.Env, key+"="+value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mustRun executes t and fails cmd with a well-formatted message if it fails.
|
||||||
|
func mustRun(t *testing.T, cmd *exec.Cmd) {
|
||||||
|
t.Helper()
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%#q exited with %v\n%s", strings.Join(cmd.Args, " "), err, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cc returns a cmd that executes `$(go env CC) $(go env GOGCCFLAGS) $args`.
|
||||||
|
func cc(args ...string) (*exec.Cmd, error) {
|
||||||
|
CC, err := goEnv("CC")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
GOGCCFLAGS, err := goEnv("GOGCCFLAGS")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split GOGCCFLAGS, respecting quoting.
|
||||||
|
//
|
||||||
|
// TODO(bcmills): This code also appears in
|
||||||
|
// misc/cgo/testcarchive/carchive_test.go, and perhaps ought to go in
|
||||||
|
// src/cmd/dist/test.go as well. Figure out where to put it so that it can be
|
||||||
|
// shared.
|
||||||
|
var flags []string
|
||||||
|
quote := '\000'
|
||||||
|
start := 0
|
||||||
|
lastSpace := true
|
||||||
|
backslash := false
|
||||||
|
for i, c := range GOGCCFLAGS {
|
||||||
|
if quote == '\000' && unicode.IsSpace(c) {
|
||||||
|
if !lastSpace {
|
||||||
|
flags = append(flags, GOGCCFLAGS[start:i])
|
||||||
|
lastSpace = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if lastSpace {
|
||||||
|
start = i
|
||||||
|
lastSpace = false
|
||||||
|
}
|
||||||
|
if quote == '\000' && !backslash && (c == '"' || c == '\'') {
|
||||||
|
quote = c
|
||||||
|
backslash = false
|
||||||
|
} else if !backslash && quote == c {
|
||||||
|
quote = '\000'
|
||||||
|
} else if (quote == '\000' || quote == '"') && !backslash && c == '\\' {
|
||||||
|
backslash = true
|
||||||
|
} else {
|
||||||
|
backslash = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !lastSpace {
|
||||||
|
flags = append(flags, GOGCCFLAGS[start:])
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command(CC, flags...)
|
||||||
|
cmd.Args = append(cmd.Args, args...)
|
||||||
|
return cmd, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type version struct {
|
||||||
|
name string
|
||||||
|
major, minor int
|
||||||
|
}
|
||||||
|
|
||||||
|
var compiler struct {
|
||||||
|
sync.Once
|
||||||
|
version
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// compilerVersion detects the version of $(go env CC).
|
||||||
|
//
|
||||||
|
// It returns a non-nil error if the compiler matches a known version schema but
|
||||||
|
// the version could not be parsed, or if $(go env CC) could not be determined.
|
||||||
|
func compilerVersion() (version, error) {
|
||||||
|
compiler.Once.Do(func() {
|
||||||
|
compiler.err = func() error {
|
||||||
|
compiler.name = "unknown"
|
||||||
|
|
||||||
|
cmd, err := cc("--version")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
out, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
// Compiler does not support "--version" flag: not Clang or GCC.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var match [][]byte
|
||||||
|
if bytes.HasPrefix(out, []byte("gcc")) {
|
||||||
|
compiler.name = "gcc"
|
||||||
|
|
||||||
|
cmd, err := cc("-dumpversion")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
out, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
// gcc, but does not support gcc's "-dumpversion" flag?!
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
gccRE := regexp.MustCompile(`(\d+)\.(\d+)`)
|
||||||
|
match = gccRE.FindSubmatch(out)
|
||||||
|
} else {
|
||||||
|
clangRE := regexp.MustCompile(`clang version (\d+)\.(\d+)`)
|
||||||
|
if match = clangRE.FindSubmatch(out); len(match) > 0 {
|
||||||
|
compiler.name = "clang"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(match) < 3 {
|
||||||
|
return nil // "unknown"
|
||||||
|
}
|
||||||
|
if compiler.major, err = strconv.Atoi(string(match[1])); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if compiler.minor, err = strconv.Atoi(string(match[2])); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}()
|
||||||
|
})
|
||||||
|
return compiler.version, compiler.err
|
||||||
|
}
|
||||||
|
|
||||||
|
type compilerCheck struct {
|
||||||
|
once sync.Once
|
||||||
|
err error
|
||||||
|
skip bool // If true, skip with err instead of failing with it.
|
||||||
|
}
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
sanitizer string
|
||||||
|
|
||||||
|
cFlags, ldFlags, goFlags []string
|
||||||
|
|
||||||
|
sanitizerCheck, runtimeCheck compilerCheck
|
||||||
|
}
|
||||||
|
|
||||||
|
var configs struct {
|
||||||
|
sync.Mutex
|
||||||
|
m map[string]*config
|
||||||
|
}
|
||||||
|
|
||||||
|
// configure returns the configuration for the given sanitizer.
|
||||||
|
func configure(sanitizer string) *config {
|
||||||
|
configs.Lock()
|
||||||
|
defer configs.Unlock()
|
||||||
|
if c, ok := configs.m[sanitizer]; ok {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
c := &config{
|
||||||
|
sanitizer: sanitizer,
|
||||||
|
cFlags: []string{"-fsanitize=" + sanitizer},
|
||||||
|
ldFlags: []string{"-fsanitize=" + sanitizer},
|
||||||
|
}
|
||||||
|
|
||||||
|
if testing.Verbose() {
|
||||||
|
c.goFlags = append(c.goFlags, "-x")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch sanitizer {
|
||||||
|
case "memory":
|
||||||
|
c.goFlags = append(c.goFlags, "-msan")
|
||||||
|
|
||||||
|
case "thread":
|
||||||
|
c.goFlags = append(c.goFlags, "--installsuffix=tsan")
|
||||||
|
compiler, _ := compilerVersion()
|
||||||
|
if compiler.name == "gcc" {
|
||||||
|
c.cFlags = append(c.cFlags, "-fPIC")
|
||||||
|
c.ldFlags = append(c.ldFlags, "-fPIC", "-static-libtsan")
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unrecognized sanitizer: %q", sanitizer))
|
||||||
|
}
|
||||||
|
|
||||||
|
if configs.m == nil {
|
||||||
|
configs.m = make(map[string]*config)
|
||||||
|
}
|
||||||
|
configs.m[sanitizer] = c
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// goCmd returns a Cmd that executes "go $subcommand $args" with appropriate
|
||||||
|
// additional flags and environment.
|
||||||
|
func (c *config) goCmd(subcommand string, args ...string) *exec.Cmd {
|
||||||
|
cmd := exec.Command("go", subcommand)
|
||||||
|
cmd.Args = append(cmd.Args, c.goFlags...)
|
||||||
|
cmd.Args = append(cmd.Args, args...)
|
||||||
|
replaceEnv(cmd, "CGO_CFLAGS", strings.Join(c.cFlags, " "))
|
||||||
|
replaceEnv(cmd, "CGO_LDFLAGS", strings.Join(c.ldFlags, " "))
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// skipIfCSanitizerBroken skips t if the C compiler does not produce working
|
||||||
|
// binaries as configured.
|
||||||
|
func (c *config) skipIfCSanitizerBroken(t *testing.T) {
|
||||||
|
check := &c.sanitizerCheck
|
||||||
|
check.once.Do(func() {
|
||||||
|
check.skip, check.err = c.checkCSanitizer()
|
||||||
|
})
|
||||||
|
if check.err != nil {
|
||||||
|
t.Helper()
|
||||||
|
if check.skip {
|
||||||
|
t.Skip(check.err)
|
||||||
|
}
|
||||||
|
t.Fatal(check.err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var cMain = []byte(`
|
||||||
|
int main() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
func (c *config) checkCSanitizer() (skip bool, err error) {
|
||||||
|
dir, err := ioutil.TempDir("", c.sanitizer)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("failed to create temp directory: %v", err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
src := filepath.Join(dir, "return0.c")
|
||||||
|
if err := ioutil.WriteFile(src, cMain, 0600); err != nil {
|
||||||
|
return false, fmt.Errorf("failed to write C source file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dst := filepath.Join(dir, "return0")
|
||||||
|
cmd, err := cc(c.cFlags...)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
cmd.Args = append(cmd.Args, c.ldFlags...)
|
||||||
|
cmd.Args = append(cmd.Args, "-o", dst, src)
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
if bytes.Contains(out, []byte("-fsanitize")) &&
|
||||||
|
(bytes.Contains(out, []byte("unrecognized")) ||
|
||||||
|
bytes.Contains(out, []byte("unsupported"))) {
|
||||||
|
return true, errors.New(string(out))
|
||||||
|
}
|
||||||
|
return true, fmt.Errorf("%#q failed: %v\n%s", strings.Join(cmd.Args, " "), err, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
if out, err := exec.Command(dst).CombinedOutput(); err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return true, fmt.Errorf("%#q failed to produce executable: %v", strings.Join(cmd.Args, " "), err)
|
||||||
|
}
|
||||||
|
snippet := bytes.SplitN(out, []byte{'\n'}, 2)[0]
|
||||||
|
return true, fmt.Errorf("%#q generated broken executable: %v\n%s", strings.Join(cmd.Args, " "), err, snippet)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// skipIfRuntimeIncompatible skips t if the Go runtime is suspected not to work
|
||||||
|
// with cgo as configured.
|
||||||
|
func (c *config) skipIfRuntimeIncompatible(t *testing.T) {
|
||||||
|
check := &c.runtimeCheck
|
||||||
|
check.once.Do(func() {
|
||||||
|
check.skip, check.err = c.checkRuntime()
|
||||||
|
})
|
||||||
|
if check.err != nil {
|
||||||
|
t.Helper()
|
||||||
|
if check.skip {
|
||||||
|
t.Skip(check.err)
|
||||||
|
}
|
||||||
|
t.Fatal(check.err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *config) checkRuntime() (skip bool, err error) {
|
||||||
|
if c.sanitizer != "thread" {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// libcgo.h sets CGO_TSAN if it detects TSAN support in the C compiler.
|
||||||
|
// Dump the preprocessor defines to check that that works.
|
||||||
|
// (Sometimes it doesn't: see https://golang.org/issue/15983.)
|
||||||
|
cmd, err := cc(c.cFlags...)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
cmd.Args = append(cmd.Args, "-dM", "-E", "../../../src/runtime/cgo/libcgo.h")
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("%#q exited with %v\n%s", strings.Join(cmd.Args, " "), err, out)
|
||||||
|
}
|
||||||
|
if !bytes.Contains(out, []byte("#define CGO_TSAN")) {
|
||||||
|
return true, fmt.Errorf("%#q did not define CGO_TSAN")
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// srcPath returns the path to the given file relative to this test's source tree.
|
||||||
|
func srcPath(path string) string {
|
||||||
|
return filepath.Join("src", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A tempDir manages a temporary directory within a test.
|
||||||
|
type tempDir struct {
|
||||||
|
base string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *tempDir) RemoveAll(t *testing.T) {
|
||||||
|
t.Helper()
|
||||||
|
if d.base == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := os.RemoveAll(d.base); err != nil {
|
||||||
|
t.Fatal("Failed to remove temp dir: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *tempDir) Join(name string) string {
|
||||||
|
return filepath.Join(d.base, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTempDir(t *testing.T) *tempDir {
|
||||||
|
t.Helper()
|
||||||
|
dir, err := ioutil.TempDir("", filepath.Dir(t.Name()))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create temp dir: %v", err)
|
||||||
|
}
|
||||||
|
return &tempDir{base: dir}
|
||||||
|
}
|
||||||
|
|
||||||
|
// hangProneCmd returns an exec.Cmd for a command that is likely to hang.
|
||||||
|
//
|
||||||
|
// If one of these tests hangs, the caller is likely to kill the test process
|
||||||
|
// using SIGINT, which will be sent to all of the processes in the test's group.
|
||||||
|
// Unfortunately, TSAN in particular is prone to dropping signals, so the SIGINT
|
||||||
|
// may terminate the test binary but leave the subprocess running. hangProneCmd
|
||||||
|
// configures subprocess to receive SIGKILL instead to ensure that it won't
|
||||||
|
// leak.
|
||||||
|
func hangProneCmd(name string, arg ...string) *exec.Cmd {
|
||||||
|
cmd := exec.Command(name, arg...)
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||||
|
Pdeathsig: syscall.SIGKILL,
|
||||||
|
}
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
74
misc/cgo/testsanitizers/cshared_test.go
Normal file
74
misc/cgo/testsanitizers/cshared_test.go
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
// Copyright 2017 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 sanitizers_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestShared(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
requireOvercommit(t)
|
||||||
|
|
||||||
|
GOOS, err := goEnv("GOOS")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
libExt := "so"
|
||||||
|
if GOOS == "darwin" {
|
||||||
|
libExt = "dylib"
|
||||||
|
}
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
src string
|
||||||
|
sanitizer string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
src: "msan_shared.go",
|
||||||
|
sanitizer: "memory",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "tsan_shared.go",
|
||||||
|
sanitizer: "thread",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
tc := tc
|
||||||
|
name := strings.TrimSuffix(tc.src, ".go")
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
config := configure(tc.sanitizer)
|
||||||
|
config.skipIfCSanitizerBroken(t)
|
||||||
|
|
||||||
|
dir := newTempDir(t)
|
||||||
|
defer dir.RemoveAll(t)
|
||||||
|
|
||||||
|
lib := dir.Join(fmt.Sprintf("lib%s.%s", name, libExt))
|
||||||
|
mustRun(t, config.goCmd("build", "-buildmode=c-shared", "-o", lib, srcPath(tc.src)))
|
||||||
|
|
||||||
|
cSrc := dir.Join("main.c")
|
||||||
|
if err := ioutil.WriteFile(cSrc, cMain, 0600); err != nil {
|
||||||
|
t.Fatalf("failed to write C source file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dstBin := dir.Join(name)
|
||||||
|
cmd, err := cc(config.cFlags...)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
cmd.Args = append(cmd.Args, config.ldFlags...)
|
||||||
|
cmd.Args = append(cmd.Args, "-o", dstBin, cSrc, lib)
|
||||||
|
mustRun(t, cmd)
|
||||||
|
|
||||||
|
cmd = hangProneCmd(dstBin)
|
||||||
|
replaceEnv(cmd, "LD_LIBRARY_PATH", ".")
|
||||||
|
mustRun(t, cmd)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
55
misc/cgo/testsanitizers/msan_test.go
Normal file
55
misc/cgo/testsanitizers/msan_test.go
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
// Copyright 2017 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 sanitizers_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMSAN(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
requireOvercommit(t)
|
||||||
|
config := configure("memory")
|
||||||
|
config.skipIfCSanitizerBroken(t)
|
||||||
|
|
||||||
|
mustRun(t, config.goCmd("build", "std"))
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
src string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{src: "msan.go"},
|
||||||
|
{src: "msan2.go"},
|
||||||
|
{src: "msan2_cmsan.go"},
|
||||||
|
{src: "msan3.go"},
|
||||||
|
{src: "msan4.go"},
|
||||||
|
{src: "msan5.go"},
|
||||||
|
{src: "msan_fail.go", wantErr: true},
|
||||||
|
}
|
||||||
|
for _, tc := range cases {
|
||||||
|
tc := tc
|
||||||
|
name := strings.TrimSuffix(tc.src, ".go")
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
dir := newTempDir(t)
|
||||||
|
defer dir.RemoveAll(t)
|
||||||
|
|
||||||
|
outPath := dir.Join(name)
|
||||||
|
mustRun(t, config.goCmd("build", "-o", outPath, srcPath(tc.src)))
|
||||||
|
|
||||||
|
cmd := hangProneCmd(outPath)
|
||||||
|
if tc.wantErr {
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Fatalf("%#q exited without error; want MSAN failure\n%s", strings.Join(cmd.Args, " "), out)
|
||||||
|
}
|
||||||
|
mustRun(t, cmd)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue