[dev.regabi] all: merge master into dev.regabi

The list of conflicted files for this merge is:

   src/cmd/compile/internal/gc/inl.go
   src/cmd/compile/internal/gc/order.go
   src/cmd/compile/internal/gc/ssa.go
   test/fixedbugs/issue20415.go
   test/fixedbugs/issue22822.go
   test/fixedbugs/issue28079b.go

inl.go was updated for changes on dev.regabi: namely that OSELRECV has
been removed, and that OSELRECV2 now only uses List, rather than both
Left and List.

order.go was updated IsAutoTmp is now a standalone function, rather
than a method on Node.

ssa.go was similarly updated for new APIs involving package ir.

The tests are all merging upstream additions for gccgo error messages
with changes to cmd/compile's error messages on the dev.regabi branch.

Change-Id: Icaaf186d69da791b5994dbb6688ec989caabec42
This commit is contained in:
Matthew Dempsky 2020-12-20 10:36:21 -08:00
commit ca8e17164e
263 changed files with 2759 additions and 1847 deletions

481
api/go1.16.txt Normal file
View file

@ -0,0 +1,481 @@
pkg archive/zip, method (*ReadCloser) Open(string) (fs.File, error)
pkg archive/zip, method (*Reader) Open(string) (fs.File, error)
pkg crypto/x509, method (SystemRootsError) Unwrap() error
pkg crypto/x509, type CertificateRequest struct, BasicConstraintsValid bool
pkg crypto/x509, type CertificateRequest struct, ExtKeyUsage []ExtKeyUsage
pkg crypto/x509, type CertificateRequest struct, IsCA bool
pkg crypto/x509, type CertificateRequest struct, KeyUsage KeyUsage
pkg crypto/x509, type CertificateRequest struct, MaxPathLen int
pkg crypto/x509, type CertificateRequest struct, MaxPathLenZero bool
pkg crypto/x509, type CertificateRequest struct, PolicyIdentifiers []asn1.ObjectIdentifier
pkg crypto/x509, type CertificateRequest struct, SubjectKeyId []uint8
pkg crypto/x509, type CertificateRequest struct, UnknownExtKeyUsage []asn1.ObjectIdentifier
pkg debug/elf, const DT_ADDRRNGHI = 1879047935
pkg debug/elf, const DT_ADDRRNGHI DynTag
pkg debug/elf, const DT_ADDRRNGLO = 1879047680
pkg debug/elf, const DT_ADDRRNGLO DynTag
pkg debug/elf, const DT_AUDIT = 1879047932
pkg debug/elf, const DT_AUDIT DynTag
pkg debug/elf, const DT_AUXILIARY = 2147483645
pkg debug/elf, const DT_AUXILIARY DynTag
pkg debug/elf, const DT_CHECKSUM = 1879047672
pkg debug/elf, const DT_CHECKSUM DynTag
pkg debug/elf, const DT_CONFIG = 1879047930
pkg debug/elf, const DT_CONFIG DynTag
pkg debug/elf, const DT_DEPAUDIT = 1879047931
pkg debug/elf, const DT_DEPAUDIT DynTag
pkg debug/elf, const DT_FEATURE = 1879047676
pkg debug/elf, const DT_FEATURE DynTag
pkg debug/elf, const DT_FILTER = 2147483647
pkg debug/elf, const DT_FILTER DynTag
pkg debug/elf, const DT_FLAGS_1 = 1879048187
pkg debug/elf, const DT_FLAGS_1 DynTag
pkg debug/elf, const DT_GNU_CONFLICT = 1879047928
pkg debug/elf, const DT_GNU_CONFLICT DynTag
pkg debug/elf, const DT_GNU_CONFLICTSZ = 1879047670
pkg debug/elf, const DT_GNU_CONFLICTSZ DynTag
pkg debug/elf, const DT_GNU_HASH = 1879047925
pkg debug/elf, const DT_GNU_HASH DynTag
pkg debug/elf, const DT_GNU_LIBLIST = 1879047929
pkg debug/elf, const DT_GNU_LIBLIST DynTag
pkg debug/elf, const DT_GNU_LIBLISTSZ = 1879047671
pkg debug/elf, const DT_GNU_LIBLISTSZ DynTag
pkg debug/elf, const DT_GNU_PRELINKED = 1879047669
pkg debug/elf, const DT_GNU_PRELINKED DynTag
pkg debug/elf, const DT_MIPS_AUX_DYNAMIC = 1879048241
pkg debug/elf, const DT_MIPS_AUX_DYNAMIC DynTag
pkg debug/elf, const DT_MIPS_BASE_ADDRESS = 1879048198
pkg debug/elf, const DT_MIPS_BASE_ADDRESS DynTag
pkg debug/elf, const DT_MIPS_COMPACT_SIZE = 1879048239
pkg debug/elf, const DT_MIPS_COMPACT_SIZE DynTag
pkg debug/elf, const DT_MIPS_CONFLICT = 1879048200
pkg debug/elf, const DT_MIPS_CONFLICT DynTag
pkg debug/elf, const DT_MIPS_CONFLICTNO = 1879048203
pkg debug/elf, const DT_MIPS_CONFLICTNO DynTag
pkg debug/elf, const DT_MIPS_CXX_FLAGS = 1879048226
pkg debug/elf, const DT_MIPS_CXX_FLAGS DynTag
pkg debug/elf, const DT_MIPS_DELTA_CLASS = 1879048215
pkg debug/elf, const DT_MIPS_DELTA_CLASS DynTag
pkg debug/elf, const DT_MIPS_DELTA_CLASSSYM = 1879048224
pkg debug/elf, const DT_MIPS_DELTA_CLASSSYM DynTag
pkg debug/elf, const DT_MIPS_DELTA_CLASSSYM_NO = 1879048225
pkg debug/elf, const DT_MIPS_DELTA_CLASSSYM_NO DynTag
pkg debug/elf, const DT_MIPS_DELTA_CLASS_NO = 1879048216
pkg debug/elf, const DT_MIPS_DELTA_CLASS_NO DynTag
pkg debug/elf, const DT_MIPS_DELTA_INSTANCE = 1879048217
pkg debug/elf, const DT_MIPS_DELTA_INSTANCE DynTag
pkg debug/elf, const DT_MIPS_DELTA_INSTANCE_NO = 1879048218
pkg debug/elf, const DT_MIPS_DELTA_INSTANCE_NO DynTag
pkg debug/elf, const DT_MIPS_DELTA_RELOC = 1879048219
pkg debug/elf, const DT_MIPS_DELTA_RELOC DynTag
pkg debug/elf, const DT_MIPS_DELTA_RELOC_NO = 1879048220
pkg debug/elf, const DT_MIPS_DELTA_RELOC_NO DynTag
pkg debug/elf, const DT_MIPS_DELTA_SYM = 1879048221
pkg debug/elf, const DT_MIPS_DELTA_SYM DynTag
pkg debug/elf, const DT_MIPS_DELTA_SYM_NO = 1879048222
pkg debug/elf, const DT_MIPS_DELTA_SYM_NO DynTag
pkg debug/elf, const DT_MIPS_DYNSTR_ALIGN = 1879048235
pkg debug/elf, const DT_MIPS_DYNSTR_ALIGN DynTag
pkg debug/elf, const DT_MIPS_FLAGS = 1879048197
pkg debug/elf, const DT_MIPS_FLAGS DynTag
pkg debug/elf, const DT_MIPS_GOTSYM = 1879048211
pkg debug/elf, const DT_MIPS_GOTSYM DynTag
pkg debug/elf, const DT_MIPS_GP_VALUE = 1879048240
pkg debug/elf, const DT_MIPS_GP_VALUE DynTag
pkg debug/elf, const DT_MIPS_HIDDEN_GOTIDX = 1879048231
pkg debug/elf, const DT_MIPS_HIDDEN_GOTIDX DynTag
pkg debug/elf, const DT_MIPS_HIPAGENO = 1879048212
pkg debug/elf, const DT_MIPS_HIPAGENO DynTag
pkg debug/elf, const DT_MIPS_ICHECKSUM = 1879048195
pkg debug/elf, const DT_MIPS_ICHECKSUM DynTag
pkg debug/elf, const DT_MIPS_INTERFACE = 1879048234
pkg debug/elf, const DT_MIPS_INTERFACE DynTag
pkg debug/elf, const DT_MIPS_INTERFACE_SIZE = 1879048236
pkg debug/elf, const DT_MIPS_INTERFACE_SIZE DynTag
pkg debug/elf, const DT_MIPS_IVERSION = 1879048196
pkg debug/elf, const DT_MIPS_IVERSION DynTag
pkg debug/elf, const DT_MIPS_LIBLIST = 1879048201
pkg debug/elf, const DT_MIPS_LIBLIST DynTag
pkg debug/elf, const DT_MIPS_LIBLISTNO = 1879048208
pkg debug/elf, const DT_MIPS_LIBLISTNO DynTag
pkg debug/elf, const DT_MIPS_LOCALPAGE_GOTIDX = 1879048229
pkg debug/elf, const DT_MIPS_LOCALPAGE_GOTIDX DynTag
pkg debug/elf, const DT_MIPS_LOCAL_GOTIDX = 1879048230
pkg debug/elf, const DT_MIPS_LOCAL_GOTIDX DynTag
pkg debug/elf, const DT_MIPS_LOCAL_GOTNO = 1879048202
pkg debug/elf, const DT_MIPS_LOCAL_GOTNO DynTag
pkg debug/elf, const DT_MIPS_MSYM = 1879048199
pkg debug/elf, const DT_MIPS_MSYM DynTag
pkg debug/elf, const DT_MIPS_OPTIONS = 1879048233
pkg debug/elf, const DT_MIPS_OPTIONS DynTag
pkg debug/elf, const DT_MIPS_PERF_SUFFIX = 1879048238
pkg debug/elf, const DT_MIPS_PERF_SUFFIX DynTag
pkg debug/elf, const DT_MIPS_PIXIE_INIT = 1879048227
pkg debug/elf, const DT_MIPS_PIXIE_INIT DynTag
pkg debug/elf, const DT_MIPS_PLTGOT = 1879048242
pkg debug/elf, const DT_MIPS_PLTGOT DynTag
pkg debug/elf, const DT_MIPS_PROTECTED_GOTIDX = 1879048232
pkg debug/elf, const DT_MIPS_PROTECTED_GOTIDX DynTag
pkg debug/elf, const DT_MIPS_RLD_MAP = 1879048214
pkg debug/elf, const DT_MIPS_RLD_MAP DynTag
pkg debug/elf, const DT_MIPS_RLD_MAP_REL = 1879048245
pkg debug/elf, const DT_MIPS_RLD_MAP_REL DynTag
pkg debug/elf, const DT_MIPS_RLD_TEXT_RESOLVE_ADDR = 1879048237
pkg debug/elf, const DT_MIPS_RLD_TEXT_RESOLVE_ADDR DynTag
pkg debug/elf, const DT_MIPS_RLD_VERSION = 1879048193
pkg debug/elf, const DT_MIPS_RLD_VERSION DynTag
pkg debug/elf, const DT_MIPS_RWPLT = 1879048244
pkg debug/elf, const DT_MIPS_RWPLT DynTag
pkg debug/elf, const DT_MIPS_SYMBOL_LIB = 1879048228
pkg debug/elf, const DT_MIPS_SYMBOL_LIB DynTag
pkg debug/elf, const DT_MIPS_SYMTABNO = 1879048209
pkg debug/elf, const DT_MIPS_SYMTABNO DynTag
pkg debug/elf, const DT_MIPS_TIME_STAMP = 1879048194
pkg debug/elf, const DT_MIPS_TIME_STAMP DynTag
pkg debug/elf, const DT_MIPS_UNREFEXTNO = 1879048210
pkg debug/elf, const DT_MIPS_UNREFEXTNO DynTag
pkg debug/elf, const DT_MOVEENT = 1879047674
pkg debug/elf, const DT_MOVEENT DynTag
pkg debug/elf, const DT_MOVESZ = 1879047675
pkg debug/elf, const DT_MOVESZ DynTag
pkg debug/elf, const DT_MOVETAB = 1879047934
pkg debug/elf, const DT_MOVETAB DynTag
pkg debug/elf, const DT_PLTPAD = 1879047933
pkg debug/elf, const DT_PLTPAD DynTag
pkg debug/elf, const DT_PLTPADSZ = 1879047673
pkg debug/elf, const DT_PLTPADSZ DynTag
pkg debug/elf, const DT_POSFLAG_1 = 1879047677
pkg debug/elf, const DT_POSFLAG_1 DynTag
pkg debug/elf, const DT_PPC64_GLINK = 1879048192
pkg debug/elf, const DT_PPC64_GLINK DynTag
pkg debug/elf, const DT_PPC64_OPD = 1879048193
pkg debug/elf, const DT_PPC64_OPD DynTag
pkg debug/elf, const DT_PPC64_OPDSZ = 1879048194
pkg debug/elf, const DT_PPC64_OPDSZ DynTag
pkg debug/elf, const DT_PPC64_OPT = 1879048195
pkg debug/elf, const DT_PPC64_OPT DynTag
pkg debug/elf, const DT_PPC_GOT = 1879048192
pkg debug/elf, const DT_PPC_GOT DynTag
pkg debug/elf, const DT_PPC_OPT = 1879048193
pkg debug/elf, const DT_PPC_OPT DynTag
pkg debug/elf, const DT_RELACOUNT = 1879048185
pkg debug/elf, const DT_RELACOUNT DynTag
pkg debug/elf, const DT_RELCOUNT = 1879048186
pkg debug/elf, const DT_RELCOUNT DynTag
pkg debug/elf, const DT_SPARC_REGISTER = 1879048193
pkg debug/elf, const DT_SPARC_REGISTER DynTag
pkg debug/elf, const DT_SYMINENT = 1879047679
pkg debug/elf, const DT_SYMINENT DynTag
pkg debug/elf, const DT_SYMINFO = 1879047935
pkg debug/elf, const DT_SYMINFO DynTag
pkg debug/elf, const DT_SYMINSZ = 1879047678
pkg debug/elf, const DT_SYMINSZ DynTag
pkg debug/elf, const DT_SYMTAB_SHNDX = 34
pkg debug/elf, const DT_SYMTAB_SHNDX DynTag
pkg debug/elf, const DT_TLSDESC_GOT = 1879047927
pkg debug/elf, const DT_TLSDESC_GOT DynTag
pkg debug/elf, const DT_TLSDESC_PLT = 1879047926
pkg debug/elf, const DT_TLSDESC_PLT DynTag
pkg debug/elf, const DT_USED = 2147483646
pkg debug/elf, const DT_USED DynTag
pkg debug/elf, const DT_VALRNGHI = 1879047679
pkg debug/elf, const DT_VALRNGHI DynTag
pkg debug/elf, const DT_VALRNGLO = 1879047424
pkg debug/elf, const DT_VALRNGLO DynTag
pkg debug/elf, const DT_VERDEF = 1879048188
pkg debug/elf, const DT_VERDEF DynTag
pkg debug/elf, const DT_VERDEFNUM = 1879048189
pkg debug/elf, const DT_VERDEFNUM DynTag
pkg debug/elf, const PT_AARCH64_ARCHEXT = 1879048192
pkg debug/elf, const PT_AARCH64_ARCHEXT ProgType
pkg debug/elf, const PT_AARCH64_UNWIND = 1879048193
pkg debug/elf, const PT_AARCH64_UNWIND ProgType
pkg debug/elf, const PT_ARM_ARCHEXT = 1879048192
pkg debug/elf, const PT_ARM_ARCHEXT ProgType
pkg debug/elf, const PT_ARM_EXIDX = 1879048193
pkg debug/elf, const PT_ARM_EXIDX ProgType
pkg debug/elf, const PT_GNU_EH_FRAME = 1685382480
pkg debug/elf, const PT_GNU_EH_FRAME ProgType
pkg debug/elf, const PT_GNU_MBIND_HI = 1685386580
pkg debug/elf, const PT_GNU_MBIND_HI ProgType
pkg debug/elf, const PT_GNU_MBIND_LO = 1685382485
pkg debug/elf, const PT_GNU_MBIND_LO ProgType
pkg debug/elf, const PT_GNU_PROPERTY = 1685382483
pkg debug/elf, const PT_GNU_PROPERTY ProgType
pkg debug/elf, const PT_GNU_RELRO = 1685382482
pkg debug/elf, const PT_GNU_RELRO ProgType
pkg debug/elf, const PT_GNU_STACK = 1685382481
pkg debug/elf, const PT_GNU_STACK ProgType
pkg debug/elf, const PT_MIPS_ABIFLAGS = 1879048195
pkg debug/elf, const PT_MIPS_ABIFLAGS ProgType
pkg debug/elf, const PT_MIPS_OPTIONS = 1879048194
pkg debug/elf, const PT_MIPS_OPTIONS ProgType
pkg debug/elf, const PT_MIPS_REGINFO = 1879048192
pkg debug/elf, const PT_MIPS_REGINFO ProgType
pkg debug/elf, const PT_MIPS_RTPROC = 1879048193
pkg debug/elf, const PT_MIPS_RTPROC ProgType
pkg debug/elf, const PT_OPENBSD_BOOTDATA = 1705253862
pkg debug/elf, const PT_OPENBSD_BOOTDATA ProgType
pkg debug/elf, const PT_OPENBSD_RANDOMIZE = 1705237478
pkg debug/elf, const PT_OPENBSD_RANDOMIZE ProgType
pkg debug/elf, const PT_OPENBSD_WXNEEDED = 1705237479
pkg debug/elf, const PT_OPENBSD_WXNEEDED ProgType
pkg debug/elf, const PT_PAX_FLAGS = 1694766464
pkg debug/elf, const PT_PAX_FLAGS ProgType
pkg debug/elf, const PT_S390_PGSTE = 1879048192
pkg debug/elf, const PT_S390_PGSTE ProgType
pkg debug/elf, const PT_SUNWSTACK = 1879048187
pkg debug/elf, const PT_SUNWSTACK ProgType
pkg debug/elf, const PT_SUNW_EH_FRAME = 1685382480
pkg debug/elf, const PT_SUNW_EH_FRAME ProgType
pkg embed, method (FS) Open(string) (fs.File, error)
pkg embed, method (FS) ReadDir(string) ([]fs.DirEntry, error)
pkg embed, method (FS) ReadFile(string) ([]uint8, error)
pkg embed, type FS struct
pkg flag, func Func(string, string, func(string) error)
pkg flag, method (*FlagSet) Func(string, string, func(string) error)
pkg go/build, type Package struct, EmbedPatterns []string
pkg go/build, type Package struct, IgnoredOtherFiles []string
pkg go/build, type Package struct, TestEmbedPatterns []string
pkg go/build, type Package struct, XTestEmbedPatterns []string
pkg html/template, func ParseFS(fs.FS, ...string) (*Template, error)
pkg html/template, method (*Template) ParseFS(fs.FS, ...string) (*Template, error)
pkg io, func NopCloser(Reader) ReadCloser
pkg io, func ReadAll(Reader) ([]uint8, error)
pkg io, type ReadSeekCloser interface { Close, Read, Seek }
pkg io, type ReadSeekCloser interface, Close() error
pkg io, type ReadSeekCloser interface, Read([]uint8) (int, error)
pkg io, type ReadSeekCloser interface, Seek(int64, int) (int64, error)
pkg io, var Discard Writer
pkg io/fs, const ModeAppend = 1073741824
pkg io/fs, const ModeAppend FileMode
pkg io/fs, const ModeCharDevice = 2097152
pkg io/fs, const ModeCharDevice FileMode
pkg io/fs, const ModeDevice = 67108864
pkg io/fs, const ModeDevice FileMode
pkg io/fs, const ModeDir = 2147483648
pkg io/fs, const ModeDir FileMode
pkg io/fs, const ModeExclusive = 536870912
pkg io/fs, const ModeExclusive FileMode
pkg io/fs, const ModeIrregular = 524288
pkg io/fs, const ModeIrregular FileMode
pkg io/fs, const ModeNamedPipe = 33554432
pkg io/fs, const ModeNamedPipe FileMode
pkg io/fs, const ModePerm = 511
pkg io/fs, const ModePerm FileMode
pkg io/fs, const ModeSetgid = 4194304
pkg io/fs, const ModeSetgid FileMode
pkg io/fs, const ModeSetuid = 8388608
pkg io/fs, const ModeSetuid FileMode
pkg io/fs, const ModeSocket = 16777216
pkg io/fs, const ModeSocket FileMode
pkg io/fs, const ModeSticky = 1048576
pkg io/fs, const ModeSticky FileMode
pkg io/fs, const ModeSymlink = 134217728
pkg io/fs, const ModeSymlink FileMode
pkg io/fs, const ModeTemporary = 268435456
pkg io/fs, const ModeTemporary FileMode
pkg io/fs, const ModeType = 2401763328
pkg io/fs, const ModeType FileMode
pkg io/fs, func Glob(FS, string) ([]string, error)
pkg io/fs, func ReadDir(FS, string) ([]DirEntry, error)
pkg io/fs, func ReadFile(FS, string) ([]uint8, error)
pkg io/fs, func Stat(FS, string) (FileInfo, error)
pkg io/fs, func Sub(FS, string) (FS, error)
pkg io/fs, func ValidPath(string) bool
pkg io/fs, func WalkDir(FS, string, WalkDirFunc) error
pkg io/fs, method (*PathError) Error() string
pkg io/fs, method (*PathError) Timeout() bool
pkg io/fs, method (*PathError) Unwrap() error
pkg io/fs, method (FileMode) IsDir() bool
pkg io/fs, method (FileMode) IsRegular() bool
pkg io/fs, method (FileMode) Perm() FileMode
pkg io/fs, method (FileMode) String() string
pkg io/fs, method (FileMode) Type() FileMode
pkg io/fs, type DirEntry interface { Info, IsDir, Name, Type }
pkg io/fs, type DirEntry interface, Info() (FileInfo, error)
pkg io/fs, type DirEntry interface, IsDir() bool
pkg io/fs, type DirEntry interface, Name() string
pkg io/fs, type DirEntry interface, Type() FileMode
pkg io/fs, type FS interface { Open }
pkg io/fs, type FS interface, Open(string) (File, error)
pkg io/fs, type File interface { Close, Read, Stat }
pkg io/fs, type File interface, Close() error
pkg io/fs, type File interface, Read([]uint8) (int, error)
pkg io/fs, type File interface, Stat() (FileInfo, error)
pkg io/fs, type FileInfo interface { IsDir, ModTime, Mode, Name, Size, Sys }
pkg io/fs, type FileInfo interface, IsDir() bool
pkg io/fs, type FileInfo interface, ModTime() time.Time
pkg io/fs, type FileInfo interface, Mode() FileMode
pkg io/fs, type FileInfo interface, Name() string
pkg io/fs, type FileInfo interface, Size() int64
pkg io/fs, type FileInfo interface, Sys() interface{}
pkg io/fs, type FileMode uint32
pkg io/fs, type GlobFS interface { Glob, Open }
pkg io/fs, type GlobFS interface, Glob(string) ([]string, error)
pkg io/fs, type GlobFS interface, Open(string) (File, error)
pkg io/fs, type PathError struct
pkg io/fs, type PathError struct, Err error
pkg io/fs, type PathError struct, Op string
pkg io/fs, type PathError struct, Path string
pkg io/fs, type ReadDirFS interface { Open, ReadDir }
pkg io/fs, type ReadDirFS interface, Open(string) (File, error)
pkg io/fs, type ReadDirFS interface, ReadDir(string) ([]DirEntry, error)
pkg io/fs, type ReadDirFile interface { Close, Read, ReadDir, Stat }
pkg io/fs, type ReadDirFile interface, Close() error
pkg io/fs, type ReadDirFile interface, Read([]uint8) (int, error)
pkg io/fs, type ReadDirFile interface, ReadDir(int) ([]DirEntry, error)
pkg io/fs, type ReadDirFile interface, Stat() (FileInfo, error)
pkg io/fs, type ReadFileFS interface { Open, ReadFile }
pkg io/fs, type ReadFileFS interface, Open(string) (File, error)
pkg io/fs, type ReadFileFS interface, ReadFile(string) ([]uint8, error)
pkg io/fs, type StatFS interface { Open, Stat }
pkg io/fs, type StatFS interface, Open(string) (File, error)
pkg io/fs, type StatFS interface, Stat(string) (FileInfo, error)
pkg io/fs, type SubFS interface { Open, Sub }
pkg io/fs, type SubFS interface, Open(string) (File, error)
pkg io/fs, type SubFS interface, Sub(string) (FS, error)
pkg io/fs, type WalkDirFunc func(string, DirEntry, error) error
pkg io/fs, var ErrClosed error
pkg io/fs, var ErrExist error
pkg io/fs, var ErrInvalid error
pkg io/fs, var ErrNotExist error
pkg io/fs, var ErrPermission error
pkg io/fs, var SkipDir error
pkg log, func Default() *Logger
pkg net, var ErrClosed error
pkg net/http, func FS(fs.FS) FileSystem
pkg net/http, type Transport struct, GetProxyConnectHeader func(context.Context, *url.URL, string) (Header, error)
pkg os, const ModeAppend fs.FileMode
pkg os, const ModeCharDevice fs.FileMode
pkg os, const ModeDevice fs.FileMode
pkg os, const ModeDir fs.FileMode
pkg os, const ModeExclusive fs.FileMode
pkg os, const ModeIrregular fs.FileMode
pkg os, const ModeNamedPipe fs.FileMode
pkg os, const ModePerm fs.FileMode
pkg os, const ModeSetgid fs.FileMode
pkg os, const ModeSetuid fs.FileMode
pkg os, const ModeSocket fs.FileMode
pkg os, const ModeSticky fs.FileMode
pkg os, const ModeSymlink fs.FileMode
pkg os, const ModeTemporary fs.FileMode
pkg os, const ModeType fs.FileMode
pkg os, func Chmod(string, fs.FileMode) error
pkg os, func CreateTemp(string, string) (*File, error)
pkg os, func DirFS(string) fs.FS
pkg os, func Lstat(string) (fs.FileInfo, error)
pkg os, func Mkdir(string, fs.FileMode) error
pkg os, func MkdirAll(string, fs.FileMode) error
pkg os, func MkdirTemp(string, string) (string, error)
pkg os, func OpenFile(string, int, fs.FileMode) (*File, error)
pkg os, func ReadDir(string) ([]fs.DirEntry, error)
pkg os, func ReadFile(string) ([]uint8, error)
pkg os, func SameFile(fs.FileInfo, fs.FileInfo) bool
pkg os, func Stat(string) (fs.FileInfo, error)
pkg os, func WriteFile(string, []uint8, fs.FileMode) error
pkg os, method (*File) Chmod(fs.FileMode) error
pkg os, method (*File) ReadDir(int) ([]fs.DirEntry, error)
pkg os, method (*File) Readdir(int) ([]fs.FileInfo, error)
pkg os, method (*File) Stat() (fs.FileInfo, error)
pkg os, type DirEntry = fs.DirEntry
pkg os, type FileInfo = fs.FileInfo
pkg os, type FileMode = fs.FileMode
pkg os, type PathError = fs.PathError
pkg os, var ErrProcessDone error
pkg os/signal, func NotifyContext(context.Context, ...os.Signal) (context.Context, context.CancelFunc)
pkg path/filepath, func WalkDir(string, fs.WalkDirFunc) error
pkg runtime/metrics, const KindBad = 0
pkg runtime/metrics, const KindBad ValueKind
pkg runtime/metrics, const KindFloat64 = 2
pkg runtime/metrics, const KindFloat64 ValueKind
pkg runtime/metrics, const KindFloat64Histogram = 3
pkg runtime/metrics, const KindFloat64Histogram ValueKind
pkg runtime/metrics, const KindUint64 = 1
pkg runtime/metrics, const KindUint64 ValueKind
pkg runtime/metrics, func All() []Description
pkg runtime/metrics, func Read([]Sample)
pkg runtime/metrics, method (Value) Float64() float64
pkg runtime/metrics, method (Value) Float64Histogram() *Float64Histogram
pkg runtime/metrics, method (Value) Kind() ValueKind
pkg runtime/metrics, method (Value) Uint64() uint64
pkg runtime/metrics, type Description struct
pkg runtime/metrics, type Description struct, Cumulative bool
pkg runtime/metrics, type Description struct, Description string
pkg runtime/metrics, type Description struct, Kind ValueKind
pkg runtime/metrics, type Description struct, Name string
pkg runtime/metrics, type Description struct, StopTheWorld bool
pkg runtime/metrics, type Float64Histogram struct
pkg runtime/metrics, type Float64Histogram struct, Buckets []float64
pkg runtime/metrics, type Float64Histogram struct, Counts []uint64
pkg runtime/metrics, type Sample struct
pkg runtime/metrics, type Sample struct, Name string
pkg runtime/metrics, type Sample struct, Value Value
pkg runtime/metrics, type Value struct
pkg runtime/metrics, type ValueKind int
pkg syscall (linux-386), func AllThreadsSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-386), func AllThreadsSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-386), func Setegid(int) error
pkg syscall (linux-386), func Seteuid(int) error
pkg syscall (linux-386-cgo), func AllThreadsSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-386-cgo), func AllThreadsSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-386-cgo), func Setegid(int) error
pkg syscall (linux-386-cgo), func Seteuid(int) error
pkg syscall (linux-amd64), func AllThreadsSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-amd64), func AllThreadsSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-amd64), func Setegid(int) error
pkg syscall (linux-amd64), func Seteuid(int) error
pkg syscall (linux-amd64-cgo), func AllThreadsSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-amd64-cgo), func AllThreadsSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-amd64-cgo), func Setegid(int) error
pkg syscall (linux-amd64-cgo), func Seteuid(int) error
pkg syscall (linux-arm), func AllThreadsSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-arm), func AllThreadsSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-arm), func Setegid(int) error
pkg syscall (linux-arm), func Seteuid(int) error
pkg syscall (linux-arm-cgo), func AllThreadsSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-arm-cgo), func AllThreadsSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-arm-cgo), func Setegid(int) error
pkg syscall (linux-arm-cgo), func Seteuid(int) error
pkg syscall (windows-386), func RtlGenRandom(*uint8, uint32) error
pkg syscall (windows-386), method (*DLLError) Unwrap() error
pkg syscall (windows-386), type SysProcAttr struct, NoInheritHandles bool
pkg syscall (windows-amd64), func RtlGenRandom(*uint8, uint32) error
pkg syscall (windows-amd64), method (*DLLError) Unwrap() error
pkg syscall (windows-amd64), type SysProcAttr struct, NoInheritHandles bool
pkg testing/fstest, func TestFS(fs.FS, ...string) error
pkg testing/fstest, method (MapFS) Glob(string) ([]string, error)
pkg testing/fstest, method (MapFS) Open(string) (fs.File, error)
pkg testing/fstest, method (MapFS) ReadDir(string) ([]fs.DirEntry, error)
pkg testing/fstest, method (MapFS) ReadFile(string) ([]uint8, error)
pkg testing/fstest, method (MapFS) Stat(string) (fs.FileInfo, error)
pkg testing/fstest, method (MapFS) Sub(string) (fs.FS, error)
pkg testing/fstest, type MapFS map[string]*MapFile
pkg testing/fstest, type MapFile struct
pkg testing/fstest, type MapFile struct, Data []uint8
pkg testing/fstest, type MapFile struct, ModTime time.Time
pkg testing/fstest, type MapFile struct, Mode fs.FileMode
pkg testing/fstest, type MapFile struct, Sys interface{}
pkg testing/iotest, func ErrReader(error) io.Reader
pkg testing/iotest, func TestReader(io.Reader, []uint8) error
pkg text/template, func ParseFS(fs.FS, ...string) (*Template, error)
pkg text/template, method (*Template) ParseFS(fs.FS, ...string) (*Template, error)
pkg text/template/parse, const NodeComment = 20
pkg text/template/parse, const NodeComment NodeType
pkg text/template/parse, const ParseComments = 1
pkg text/template/parse, const ParseComments Mode
pkg text/template/parse, method (*CommentNode) Copy() Node
pkg text/template/parse, method (*CommentNode) String() string
pkg text/template/parse, method (CommentNode) Position() Pos
pkg text/template/parse, method (CommentNode) Type() NodeType
pkg text/template/parse, type CommentNode struct
pkg text/template/parse, type CommentNode struct, Text string
pkg text/template/parse, type CommentNode struct, embedded NodeType
pkg text/template/parse, type CommentNode struct, embedded Pos
pkg text/template/parse, type Mode uint
pkg text/template/parse, type Tree struct, Mode Mode
pkg unicode, const Version = "13.0.0"
pkg unicode, var Chorasmian *RangeTable
pkg unicode, var Dives_Akuru *RangeTable
pkg unicode, var Khitan_Small_Script *RangeTable
pkg unicode, var Yezidi *RangeTable

View file

@ -1,452 +0,0 @@
pkg archive/zip, method (*ReadCloser) Open(string) (fs.File, error)
pkg archive/zip, method (*Reader) Open(string) (fs.File, error)
pkg debug/elf, const DT_ADDRRNGHI = 1879047935
pkg debug/elf, const DT_ADDRRNGHI DynTag
pkg debug/elf, const DT_ADDRRNGLO = 1879047680
pkg debug/elf, const DT_ADDRRNGLO DynTag
pkg debug/elf, const DT_AUDIT = 1879047932
pkg debug/elf, const DT_AUDIT DynTag
pkg debug/elf, const DT_AUXILIARY = 2147483645
pkg debug/elf, const DT_AUXILIARY DynTag
pkg debug/elf, const DT_CHECKSUM = 1879047672
pkg debug/elf, const DT_CHECKSUM DynTag
pkg debug/elf, const DT_CONFIG = 1879047930
pkg debug/elf, const DT_CONFIG DynTag
pkg debug/elf, const DT_DEPAUDIT = 1879047931
pkg debug/elf, const DT_DEPAUDIT DynTag
pkg debug/elf, const DT_FEATURE = 1879047676
pkg debug/elf, const DT_FEATURE DynTag
pkg debug/elf, const DT_FILTER = 2147483647
pkg debug/elf, const DT_FILTER DynTag
pkg debug/elf, const DT_FLAGS_1 = 1879048187
pkg debug/elf, const DT_FLAGS_1 DynTag
pkg debug/elf, const DT_GNU_CONFLICT = 1879047928
pkg debug/elf, const DT_GNU_CONFLICT DynTag
pkg debug/elf, const DT_GNU_CONFLICTSZ = 1879047670
pkg debug/elf, const DT_GNU_CONFLICTSZ DynTag
pkg debug/elf, const DT_GNU_HASH = 1879047925
pkg debug/elf, const DT_GNU_HASH DynTag
pkg debug/elf, const DT_GNU_LIBLIST = 1879047929
pkg debug/elf, const DT_GNU_LIBLIST DynTag
pkg debug/elf, const DT_GNU_LIBLISTSZ = 1879047671
pkg debug/elf, const DT_GNU_LIBLISTSZ DynTag
pkg debug/elf, const DT_GNU_PRELINKED = 1879047669
pkg debug/elf, const DT_GNU_PRELINKED DynTag
pkg debug/elf, const DT_MIPS_AUX_DYNAMIC = 1879048241
pkg debug/elf, const DT_MIPS_AUX_DYNAMIC DynTag
pkg debug/elf, const DT_MIPS_BASE_ADDRESS = 1879048198
pkg debug/elf, const DT_MIPS_BASE_ADDRESS DynTag
pkg debug/elf, const DT_MIPS_COMPACT_SIZE = 1879048239
pkg debug/elf, const DT_MIPS_COMPACT_SIZE DynTag
pkg debug/elf, const DT_MIPS_CONFLICT = 1879048200
pkg debug/elf, const DT_MIPS_CONFLICT DynTag
pkg debug/elf, const DT_MIPS_CONFLICTNO = 1879048203
pkg debug/elf, const DT_MIPS_CONFLICTNO DynTag
pkg debug/elf, const DT_MIPS_CXX_FLAGS = 1879048226
pkg debug/elf, const DT_MIPS_CXX_FLAGS DynTag
pkg debug/elf, const DT_MIPS_DELTA_CLASS = 1879048215
pkg debug/elf, const DT_MIPS_DELTA_CLASS DynTag
pkg debug/elf, const DT_MIPS_DELTA_CLASSSYM = 1879048224
pkg debug/elf, const DT_MIPS_DELTA_CLASSSYM DynTag
pkg debug/elf, const DT_MIPS_DELTA_CLASSSYM_NO = 1879048225
pkg debug/elf, const DT_MIPS_DELTA_CLASSSYM_NO DynTag
pkg debug/elf, const DT_MIPS_DELTA_CLASS_NO = 1879048216
pkg debug/elf, const DT_MIPS_DELTA_CLASS_NO DynTag
pkg debug/elf, const DT_MIPS_DELTA_INSTANCE = 1879048217
pkg debug/elf, const DT_MIPS_DELTA_INSTANCE DynTag
pkg debug/elf, const DT_MIPS_DELTA_INSTANCE_NO = 1879048218
pkg debug/elf, const DT_MIPS_DELTA_INSTANCE_NO DynTag
pkg debug/elf, const DT_MIPS_DELTA_RELOC = 1879048219
pkg debug/elf, const DT_MIPS_DELTA_RELOC DynTag
pkg debug/elf, const DT_MIPS_DELTA_RELOC_NO = 1879048220
pkg debug/elf, const DT_MIPS_DELTA_RELOC_NO DynTag
pkg debug/elf, const DT_MIPS_DELTA_SYM = 1879048221
pkg debug/elf, const DT_MIPS_DELTA_SYM DynTag
pkg debug/elf, const DT_MIPS_DELTA_SYM_NO = 1879048222
pkg debug/elf, const DT_MIPS_DELTA_SYM_NO DynTag
pkg debug/elf, const DT_MIPS_DYNSTR_ALIGN = 1879048235
pkg debug/elf, const DT_MIPS_DYNSTR_ALIGN DynTag
pkg debug/elf, const DT_MIPS_FLAGS = 1879048197
pkg debug/elf, const DT_MIPS_FLAGS DynTag
pkg debug/elf, const DT_MIPS_GOTSYM = 1879048211
pkg debug/elf, const DT_MIPS_GOTSYM DynTag
pkg debug/elf, const DT_MIPS_GP_VALUE = 1879048240
pkg debug/elf, const DT_MIPS_GP_VALUE DynTag
pkg debug/elf, const DT_MIPS_HIDDEN_GOTIDX = 1879048231
pkg debug/elf, const DT_MIPS_HIDDEN_GOTIDX DynTag
pkg debug/elf, const DT_MIPS_HIPAGENO = 1879048212
pkg debug/elf, const DT_MIPS_HIPAGENO DynTag
pkg debug/elf, const DT_MIPS_ICHECKSUM = 1879048195
pkg debug/elf, const DT_MIPS_ICHECKSUM DynTag
pkg debug/elf, const DT_MIPS_INTERFACE = 1879048234
pkg debug/elf, const DT_MIPS_INTERFACE DynTag
pkg debug/elf, const DT_MIPS_INTERFACE_SIZE = 1879048236
pkg debug/elf, const DT_MIPS_INTERFACE_SIZE DynTag
pkg debug/elf, const DT_MIPS_IVERSION = 1879048196
pkg debug/elf, const DT_MIPS_IVERSION DynTag
pkg debug/elf, const DT_MIPS_LIBLIST = 1879048201
pkg debug/elf, const DT_MIPS_LIBLIST DynTag
pkg debug/elf, const DT_MIPS_LIBLISTNO = 1879048208
pkg debug/elf, const DT_MIPS_LIBLISTNO DynTag
pkg debug/elf, const DT_MIPS_LOCALPAGE_GOTIDX = 1879048229
pkg debug/elf, const DT_MIPS_LOCALPAGE_GOTIDX DynTag
pkg debug/elf, const DT_MIPS_LOCAL_GOTIDX = 1879048230
pkg debug/elf, const DT_MIPS_LOCAL_GOTIDX DynTag
pkg debug/elf, const DT_MIPS_LOCAL_GOTNO = 1879048202
pkg debug/elf, const DT_MIPS_LOCAL_GOTNO DynTag
pkg debug/elf, const DT_MIPS_MSYM = 1879048199
pkg debug/elf, const DT_MIPS_MSYM DynTag
pkg debug/elf, const DT_MIPS_OPTIONS = 1879048233
pkg debug/elf, const DT_MIPS_OPTIONS DynTag
pkg debug/elf, const DT_MIPS_PERF_SUFFIX = 1879048238
pkg debug/elf, const DT_MIPS_PERF_SUFFIX DynTag
pkg debug/elf, const DT_MIPS_PIXIE_INIT = 1879048227
pkg debug/elf, const DT_MIPS_PIXIE_INIT DynTag
pkg debug/elf, const DT_MIPS_PLTGOT = 1879048242
pkg debug/elf, const DT_MIPS_PLTGOT DynTag
pkg debug/elf, const DT_MIPS_PROTECTED_GOTIDX = 1879048232
pkg debug/elf, const DT_MIPS_PROTECTED_GOTIDX DynTag
pkg debug/elf, const DT_MIPS_RLD_MAP = 1879048214
pkg debug/elf, const DT_MIPS_RLD_MAP DynTag
pkg debug/elf, const DT_MIPS_RLD_MAP_REL = 1879048245
pkg debug/elf, const DT_MIPS_RLD_MAP_REL DynTag
pkg debug/elf, const DT_MIPS_RLD_TEXT_RESOLVE_ADDR = 1879048237
pkg debug/elf, const DT_MIPS_RLD_TEXT_RESOLVE_ADDR DynTag
pkg debug/elf, const DT_MIPS_RLD_VERSION = 1879048193
pkg debug/elf, const DT_MIPS_RLD_VERSION DynTag
pkg debug/elf, const DT_MIPS_RWPLT = 1879048244
pkg debug/elf, const DT_MIPS_RWPLT DynTag
pkg debug/elf, const DT_MIPS_SYMBOL_LIB = 1879048228
pkg debug/elf, const DT_MIPS_SYMBOL_LIB DynTag
pkg debug/elf, const DT_MIPS_SYMTABNO = 1879048209
pkg debug/elf, const DT_MIPS_SYMTABNO DynTag
pkg debug/elf, const DT_MIPS_TIME_STAMP = 1879048194
pkg debug/elf, const DT_MIPS_TIME_STAMP DynTag
pkg debug/elf, const DT_MIPS_UNREFEXTNO = 1879048210
pkg debug/elf, const DT_MIPS_UNREFEXTNO DynTag
pkg debug/elf, const DT_MOVEENT = 1879047674
pkg debug/elf, const DT_MOVEENT DynTag
pkg debug/elf, const DT_MOVESZ = 1879047675
pkg debug/elf, const DT_MOVESZ DynTag
pkg debug/elf, const DT_MOVETAB = 1879047934
pkg debug/elf, const DT_MOVETAB DynTag
pkg debug/elf, const DT_PLTPAD = 1879047933
pkg debug/elf, const DT_PLTPAD DynTag
pkg debug/elf, const DT_PLTPADSZ = 1879047673
pkg debug/elf, const DT_PLTPADSZ DynTag
pkg debug/elf, const DT_POSFLAG_1 = 1879047677
pkg debug/elf, const DT_POSFLAG_1 DynTag
pkg debug/elf, const DT_PPC64_GLINK = 1879048192
pkg debug/elf, const DT_PPC64_GLINK DynTag
pkg debug/elf, const DT_PPC64_OPD = 1879048193
pkg debug/elf, const DT_PPC64_OPD DynTag
pkg debug/elf, const DT_PPC64_OPDSZ = 1879048194
pkg debug/elf, const DT_PPC64_OPDSZ DynTag
pkg debug/elf, const DT_PPC64_OPT = 1879048195
pkg debug/elf, const DT_PPC64_OPT DynTag
pkg debug/elf, const DT_PPC_GOT = 1879048192
pkg debug/elf, const DT_PPC_GOT DynTag
pkg debug/elf, const DT_PPC_OPT = 1879048193
pkg debug/elf, const DT_PPC_OPT DynTag
pkg debug/elf, const DT_RELACOUNT = 1879048185
pkg debug/elf, const DT_RELACOUNT DynTag
pkg debug/elf, const DT_RELCOUNT = 1879048186
pkg debug/elf, const DT_RELCOUNT DynTag
pkg debug/elf, const DT_SPARC_REGISTER = 1879048193
pkg debug/elf, const DT_SPARC_REGISTER DynTag
pkg debug/elf, const DT_SYMINENT = 1879047679
pkg debug/elf, const DT_SYMINENT DynTag
pkg debug/elf, const DT_SYMINFO = 1879047935
pkg debug/elf, const DT_SYMINFO DynTag
pkg debug/elf, const DT_SYMINSZ = 1879047678
pkg debug/elf, const DT_SYMINSZ DynTag
pkg debug/elf, const DT_SYMTAB_SHNDX = 34
pkg debug/elf, const DT_SYMTAB_SHNDX DynTag
pkg debug/elf, const DT_TLSDESC_GOT = 1879047927
pkg debug/elf, const DT_TLSDESC_GOT DynTag
pkg debug/elf, const DT_TLSDESC_PLT = 1879047926
pkg debug/elf, const DT_TLSDESC_PLT DynTag
pkg debug/elf, const DT_USED = 2147483646
pkg debug/elf, const DT_USED DynTag
pkg debug/elf, const DT_VALRNGHI = 1879047679
pkg debug/elf, const DT_VALRNGHI DynTag
pkg debug/elf, const DT_VALRNGLO = 1879047424
pkg debug/elf, const DT_VALRNGLO DynTag
pkg debug/elf, const DT_VERDEF = 1879048188
pkg debug/elf, const DT_VERDEF DynTag
pkg debug/elf, const DT_VERDEFNUM = 1879048189
pkg debug/elf, const DT_VERDEFNUM DynTag
pkg debug/elf, const PT_AARCH64_ARCHEXT = 1879048192
pkg debug/elf, const PT_AARCH64_ARCHEXT ProgType
pkg debug/elf, const PT_AARCH64_UNWIND = 1879048193
pkg debug/elf, const PT_AARCH64_UNWIND ProgType
pkg debug/elf, const PT_ARM_ARCHEXT = 1879048192
pkg debug/elf, const PT_ARM_ARCHEXT ProgType
pkg debug/elf, const PT_ARM_EXIDX = 1879048193
pkg debug/elf, const PT_ARM_EXIDX ProgType
pkg debug/elf, const PT_GNU_EH_FRAME = 1685382480
pkg debug/elf, const PT_GNU_EH_FRAME ProgType
pkg debug/elf, const PT_GNU_MBIND_HI = 1685386580
pkg debug/elf, const PT_GNU_MBIND_HI ProgType
pkg debug/elf, const PT_GNU_MBIND_LO = 1685382485
pkg debug/elf, const PT_GNU_MBIND_LO ProgType
pkg debug/elf, const PT_GNU_PROPERTY = 1685382483
pkg debug/elf, const PT_GNU_PROPERTY ProgType
pkg debug/elf, const PT_GNU_RELRO = 1685382482
pkg debug/elf, const PT_GNU_RELRO ProgType
pkg debug/elf, const PT_GNU_STACK = 1685382481
pkg debug/elf, const PT_GNU_STACK ProgType
pkg debug/elf, const PT_MIPS_ABIFLAGS = 1879048195
pkg debug/elf, const PT_MIPS_ABIFLAGS ProgType
pkg debug/elf, const PT_MIPS_OPTIONS = 1879048194
pkg debug/elf, const PT_MIPS_OPTIONS ProgType
pkg debug/elf, const PT_MIPS_REGINFO = 1879048192
pkg debug/elf, const PT_MIPS_REGINFO ProgType
pkg debug/elf, const PT_MIPS_RTPROC = 1879048193
pkg debug/elf, const PT_MIPS_RTPROC ProgType
pkg debug/elf, const PT_OPENBSD_BOOTDATA = 1705253862
pkg debug/elf, const PT_OPENBSD_BOOTDATA ProgType
pkg debug/elf, const PT_OPENBSD_RANDOMIZE = 1705237478
pkg debug/elf, const PT_OPENBSD_RANDOMIZE ProgType
pkg debug/elf, const PT_OPENBSD_WXNEEDED = 1705237479
pkg debug/elf, const PT_OPENBSD_WXNEEDED ProgType
pkg debug/elf, const PT_PAX_FLAGS = 1694766464
pkg debug/elf, const PT_PAX_FLAGS ProgType
pkg debug/elf, const PT_S390_PGSTE = 1879048192
pkg debug/elf, const PT_S390_PGSTE ProgType
pkg debug/elf, const PT_SUNWSTACK = 1879048187
pkg debug/elf, const PT_SUNWSTACK ProgType
pkg debug/elf, const PT_SUNW_EH_FRAME = 1685382480
pkg debug/elf, const PT_SUNW_EH_FRAME ProgType
pkg embed, method (FS) Open(string) (fs.File, error)
pkg embed, method (FS) ReadDir(string) ([]fs.DirEntry, error)
pkg embed, method (FS) ReadFile(string) ([]uint8, error)
pkg embed, type FS struct
pkg flag, func Func(string, string, func(string) error)
pkg flag, method (*FlagSet) Func(string, string, func(string) error)
pkg go/build, type Package struct, EmbedPatterns []string
pkg go/build, type Package struct, IgnoredOtherFiles []string
pkg go/build, type Package struct, TestEmbedPatterns []string
pkg go/build, type Package struct, XTestEmbedPatterns []string
pkg html/template, func ParseFS(fs.FS, ...string) (*Template, error)
pkg html/template, method (*Template) ParseFS(fs.FS, ...string) (*Template, error)
pkg io, func NopCloser(Reader) ReadCloser
pkg io, func ReadAll(Reader) ([]uint8, error)
pkg io, type ReadSeekCloser interface { Close, Read, Seek }
pkg io, type ReadSeekCloser interface, Close() error
pkg io, type ReadSeekCloser interface, Read([]uint8) (int, error)
pkg io, type ReadSeekCloser interface, Seek(int64, int) (int64, error)
pkg io, var Discard Writer
pkg io/fs, const ModeAppend = 1073741824
pkg io/fs, const ModeAppend FileMode
pkg io/fs, const ModeCharDevice = 2097152
pkg io/fs, const ModeCharDevice FileMode
pkg io/fs, const ModeDevice = 67108864
pkg io/fs, const ModeDevice FileMode
pkg io/fs, const ModeDir = 2147483648
pkg io/fs, const ModeDir FileMode
pkg io/fs, const ModeExclusive = 536870912
pkg io/fs, const ModeExclusive FileMode
pkg io/fs, const ModeIrregular = 524288
pkg io/fs, const ModeIrregular FileMode
pkg io/fs, const ModeNamedPipe = 33554432
pkg io/fs, const ModeNamedPipe FileMode
pkg io/fs, const ModePerm = 511
pkg io/fs, const ModePerm FileMode
pkg io/fs, const ModeSetgid = 4194304
pkg io/fs, const ModeSetgid FileMode
pkg io/fs, const ModeSetuid = 8388608
pkg io/fs, const ModeSetuid FileMode
pkg io/fs, const ModeSocket = 16777216
pkg io/fs, const ModeSocket FileMode
pkg io/fs, const ModeSticky = 1048576
pkg io/fs, const ModeSticky FileMode
pkg io/fs, const ModeSymlink = 134217728
pkg io/fs, const ModeSymlink FileMode
pkg io/fs, const ModeTemporary = 268435456
pkg io/fs, const ModeTemporary FileMode
pkg io/fs, const ModeType = 2401763328
pkg io/fs, const ModeType FileMode
pkg io/fs, func Glob(FS, string) ([]string, error)
pkg io/fs, func ReadDir(FS, string) ([]DirEntry, error)
pkg io/fs, func ReadFile(FS, string) ([]uint8, error)
pkg io/fs, func Stat(FS, string) (FileInfo, error)
pkg io/fs, func ValidPath(string) bool
pkg io/fs, method (*PathError) Error() string
pkg io/fs, method (*PathError) Timeout() bool
pkg io/fs, method (*PathError) Unwrap() error
pkg io/fs, method (FileMode) IsDir() bool
pkg io/fs, method (FileMode) IsRegular() bool
pkg io/fs, method (FileMode) Perm() FileMode
pkg io/fs, method (FileMode) String() string
pkg io/fs, method (FileMode) Type() FileMode
pkg io/fs, type DirEntry interface { Info, IsDir, Name, Type }
pkg io/fs, type DirEntry interface, Info() (FileInfo, error)
pkg io/fs, type DirEntry interface, IsDir() bool
pkg io/fs, type DirEntry interface, Name() string
pkg io/fs, type DirEntry interface, Type() FileMode
pkg io/fs, type FS interface { Open }
pkg io/fs, type FS interface, Open(string) (File, error)
pkg io/fs, type File interface { Close, Read, Stat }
pkg io/fs, type File interface, Close() error
pkg io/fs, type File interface, Read([]uint8) (int, error)
pkg io/fs, type File interface, Stat() (FileInfo, error)
pkg io/fs, type FileInfo interface { IsDir, ModTime, Mode, Name, Size, Sys }
pkg io/fs, type FileInfo interface, IsDir() bool
pkg io/fs, type FileInfo interface, ModTime() time.Time
pkg io/fs, type FileInfo interface, Mode() FileMode
pkg io/fs, type FileInfo interface, Name() string
pkg io/fs, type FileInfo interface, Size() int64
pkg io/fs, type FileInfo interface, Sys() interface{}
pkg io/fs, type FileMode uint32
pkg io/fs, type GlobFS interface { Glob, Open }
pkg io/fs, type GlobFS interface, Glob(string) ([]string, error)
pkg io/fs, type GlobFS interface, Open(string) (File, error)
pkg io/fs, type PathError struct
pkg io/fs, type PathError struct, Err error
pkg io/fs, type PathError struct, Op string
pkg io/fs, type PathError struct, Path string
pkg io/fs, type ReadDirFS interface { Open, ReadDir }
pkg io/fs, type ReadDirFS interface, Open(string) (File, error)
pkg io/fs, type ReadDirFS interface, ReadDir(string) ([]DirEntry, error)
pkg io/fs, type ReadDirFile interface { Close, Read, ReadDir, Stat }
pkg io/fs, type ReadDirFile interface, Close() error
pkg io/fs, type ReadDirFile interface, Read([]uint8) (int, error)
pkg io/fs, type ReadDirFile interface, ReadDir(int) ([]DirEntry, error)
pkg io/fs, type ReadDirFile interface, Stat() (FileInfo, error)
pkg io/fs, type ReadFileFS interface { Open, ReadFile }
pkg io/fs, type ReadFileFS interface, Open(string) (File, error)
pkg io/fs, type ReadFileFS interface, ReadFile(string) ([]uint8, error)
pkg io/fs, type StatFS interface { Open, Stat }
pkg io/fs, type StatFS interface, Open(string) (File, error)
pkg io/fs, type StatFS interface, Stat(string) (FileInfo, error)
pkg io/fs, var ErrClosed error
pkg io/fs, var ErrExist error
pkg io/fs, var ErrInvalid error
pkg io/fs, var ErrNotExist error
pkg io/fs, var ErrPermission error
pkg log, func Default() *Logger
pkg net, var ErrClosed error
pkg net/http, func FS(fs.FS) FileSystem
pkg net/http, type Transport struct, GetProxyConnectHeader func(context.Context, *url.URL, string) (Header, error)
pkg os, const ModeAppend fs.FileMode
pkg os, const ModeCharDevice fs.FileMode
pkg os, const ModeDevice fs.FileMode
pkg os, const ModeDir fs.FileMode
pkg os, const ModeExclusive fs.FileMode
pkg os, const ModeIrregular fs.FileMode
pkg os, const ModeNamedPipe fs.FileMode
pkg os, const ModePerm fs.FileMode
pkg os, const ModeSetgid fs.FileMode
pkg os, const ModeSetuid fs.FileMode
pkg os, const ModeSocket fs.FileMode
pkg os, const ModeSticky fs.FileMode
pkg os, const ModeSymlink fs.FileMode
pkg os, const ModeTemporary fs.FileMode
pkg os, const ModeType fs.FileMode
pkg os, func Chmod(string, fs.FileMode) error
pkg os, func DirFS(string) fs.FS
pkg os, func Lstat(string) (fs.FileInfo, error)
pkg os, func Mkdir(string, fs.FileMode) error
pkg os, func MkdirAll(string, fs.FileMode) error
pkg os, func OpenFile(string, int, fs.FileMode) (*File, error)
pkg os, func SameFile(fs.FileInfo, fs.FileInfo) bool
pkg os, func Stat(string) (fs.FileInfo, error)
pkg os, method (*File) Chmod(fs.FileMode) error
pkg os, method (*File) ReadDir(int) ([]fs.DirEntry, error)
pkg os, method (*File) Readdir(int) ([]fs.FileInfo, error)
pkg os, method (*File) Stat() (fs.FileInfo, error)
pkg os, type DirEntry = fs.DirEntry
pkg os, type FileInfo = fs.FileInfo
pkg os, type FileMode = fs.FileMode
pkg os, type PathError = fs.PathError
pkg os/signal, func NotifyContext(context.Context, ...os.Signal) (context.Context, context.CancelFunc)
pkg runtime/metrics, const KindBad = 0
pkg runtime/metrics, const KindBad ValueKind
pkg runtime/metrics, const KindFloat64 = 2
pkg runtime/metrics, const KindFloat64 ValueKind
pkg runtime/metrics, const KindFloat64Histogram = 3
pkg runtime/metrics, const KindFloat64Histogram ValueKind
pkg runtime/metrics, const KindUint64 = 1
pkg runtime/metrics, const KindUint64 ValueKind
pkg runtime/metrics, func All() []Description
pkg runtime/metrics, func Read([]Sample)
pkg runtime/metrics, method (Value) Float64() float64
pkg runtime/metrics, method (Value) Float64Histogram() *Float64Histogram
pkg runtime/metrics, method (Value) Kind() ValueKind
pkg runtime/metrics, method (Value) Uint64() uint64
pkg runtime/metrics, type Description struct
pkg runtime/metrics, type Description struct, Cumulative bool
pkg runtime/metrics, type Description struct, Description string
pkg runtime/metrics, type Description struct, Kind ValueKind
pkg runtime/metrics, type Description struct, Name string
pkg runtime/metrics, type Description struct, StopTheWorld bool
pkg runtime/metrics, type Float64Histogram struct
pkg runtime/metrics, type Float64Histogram struct, Buckets []float64
pkg runtime/metrics, type Float64Histogram struct, Counts []uint64
pkg runtime/metrics, type Sample struct
pkg runtime/metrics, type Sample struct, Name string
pkg runtime/metrics, type Sample struct, Value Value
pkg runtime/metrics, type Value struct
pkg runtime/metrics, type ValueKind int
pkg syscall (linux-386), func AllThreadsSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-386), func AllThreadsSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-386), func Setegid(int) error
pkg syscall (linux-386), func Seteuid(int) error
pkg syscall (linux-386-cgo), func AllThreadsSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-386-cgo), func AllThreadsSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-386-cgo), func Setegid(int) error
pkg syscall (linux-386-cgo), func Seteuid(int) error
pkg syscall (linux-amd64), func AllThreadsSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-amd64), func AllThreadsSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-amd64), func Setegid(int) error
pkg syscall (linux-amd64), func Seteuid(int) error
pkg syscall (linux-amd64-cgo), func AllThreadsSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-amd64-cgo), func AllThreadsSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-amd64-cgo), func Setegid(int) error
pkg syscall (linux-amd64-cgo), func Seteuid(int) error
pkg syscall (linux-arm), func AllThreadsSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-arm), func AllThreadsSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-arm), func Setegid(int) error
pkg syscall (linux-arm), func Seteuid(int) error
pkg syscall (linux-arm-cgo), func AllThreadsSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-arm-cgo), func AllThreadsSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
pkg syscall (linux-arm-cgo), func Setegid(int) error
pkg syscall (linux-arm-cgo), func Seteuid(int) error
pkg syscall (windows-386), func RtlGenRandom(*uint8, uint32) error
pkg syscall (windows-amd64), func RtlGenRandom(*uint8, uint32) error
pkg testing/fstest, func TestFS(fs.FS, ...string) error
pkg testing/fstest, method (MapFS) Glob(string) ([]string, error)
pkg testing/fstest, method (MapFS) Open(string) (fs.File, error)
pkg testing/fstest, method (MapFS) ReadDir(string) ([]fs.DirEntry, error)
pkg testing/fstest, method (MapFS) ReadFile(string) ([]uint8, error)
pkg testing/fstest, method (MapFS) Stat(string) (fs.FileInfo, error)
pkg testing/fstest, type MapFS map[string]*MapFile
pkg testing/fstest, type MapFile struct
pkg testing/fstest, type MapFile struct, Data []uint8
pkg testing/fstest, type MapFile struct, ModTime time.Time
pkg testing/fstest, type MapFile struct, Mode fs.FileMode
pkg testing/fstest, type MapFile struct, Sys interface{}
pkg testing/iotest, func ErrReader(error) io.Reader
pkg testing/iotest, func TestReader(io.Reader, []uint8) error
pkg text/template, func ParseFS(fs.FS, ...string) (*Template, error)
pkg text/template, method (*Template) ParseFS(fs.FS, ...string) (*Template, error)
pkg text/template/parse, const NodeComment = 20
pkg text/template/parse, const NodeComment NodeType
pkg text/template/parse, const ParseComments = 1
pkg text/template/parse, const ParseComments Mode
pkg text/template/parse, method (*CommentNode) Copy() Node
pkg text/template/parse, method (*CommentNode) String() string
pkg text/template/parse, method (CommentNode) Position() Pos
pkg text/template/parse, method (CommentNode) Type() NodeType
pkg text/template/parse, type CommentNode struct
pkg text/template/parse, type CommentNode struct, Text string
pkg text/template/parse, type CommentNode struct, embedded NodeType
pkg text/template/parse, type CommentNode struct, embedded Pos
pkg text/template/parse, type Mode uint
pkg text/template/parse, type Tree struct, Mode Mode
pkg unicode, const Version = "13.0.0"
pkg unicode, var Chorasmian *RangeTable
pkg unicode, var Dives_Akuru *RangeTable
pkg unicode, var Khitan_Small_Script *RangeTable
pkg unicode, var Yezidi *RangeTable

View file

@ -397,6 +397,19 @@ Do not send CLs removing the interior tags from such phrases.
documentation</a> for more information. documentation</a> for more information.
</p> </p>
<p><!-- CL 250940 -->
In Go 1.15.3 and later, cgo will not permit Go code to allocate an
undefined struct type (a C struct defined as just <code>struct
S;</code> or similar) on the stack or heap.
Go code will only be permitted to use pointers to those types.
Allocating an instance of such a struct and passing a pointer, or a
full struct value, to C code was always unsafe and unlikely to work
correctly; it is now forbidden.
The fix is to either rewrite the Go code to use only pointers, or to
ensure that the Go code sees the full definition of the struct by
including the appropriate C header file.
</p>
<h3 id="commonname">X.509 CommonName deprecation</h3> <h3 id="commonname">X.509 CommonName deprecation</h3>
<p><!-- CL 231379 --> <p><!-- CL 231379 -->

View file

@ -99,10 +99,6 @@ Do not send CLs removing the interior tags from such phrases.
<h2 id="tools">Tools</h2> <h2 id="tools">Tools</h2>
<p>
TODO
</p>
<h3 id="go-command">Go command</h3> <h3 id="go-command">Go command</h3>
<h4 id="modules">Modules</h4> <h4 id="modules">Modules</h4>
@ -275,6 +271,20 @@ Do not send CLs removing the interior tags from such phrases.
but without the extra step. but without the extra step.
</p> </p>
<h4 id="overlay-flag">The <code>-overlay</code> flag</h4>
<p><!-- golang.org/issue/39958 -->
The <code>-overlay</code> flag specifies a JSON configuration file containing
a set of file path replacements. The <code>-overlay</code> flag may be used
with all build commands and <code>go</code> <code>mod</code> subcommands.
It is primarily intended to be used by editor tooling such as gopls to
understand the effects of unsaved changes to source files. The config file
maps actual file paths to replacement file paths and the <code>go</code>
command and its builds will run as if the actual file paths exist with the
contents given by the replacement file paths, or don't exist if the replacement
file paths are empty.
</p>
<h3 id="cgo">Cgo</h3> <h3 id="cgo">Cgo</h3>
<p><!-- CL 252378 --> <p><!-- CL 252378 -->
@ -287,12 +297,55 @@ Do not send CLs removing the interior tags from such phrases.
<h3 id="vet">Vet</h3> <h3 id="vet">Vet</h3>
<p> <h4 id="vet-string-int">New warning for invalid testing.T use in
TODO goroutines</h4>
<!-- CL 235677: https://golang.org/cl/235677: cmd/vet: bring in pass to catch invalid uses of testing.T in goroutines --> <p><!-- CL 235677 -->
The vet tool now warns about invalid calls to the <code>testing.T</code>
method <code>Fatal</code> from within a goroutine created during the test.
This also warns on calls to <code>Fatalf</code>, <code>FailNow</code>, and
<code>Skip{,f,Now}</code> methods on <code>testing.T</code> tests or
<code>testing.B</code> benchmarks.
</p> </p>
<p>
Calls to these methods stop the execution of the created goroutine and not
the <code>Test*</code> or <code>Benchmark*</code> function. So these are
<a href="/pkg/testing/#T.FailNow">required</a> to be called by the goroutine
running the test or benchmark function. For example:
</p>
<pre>
func TestFoo(t *testing.T) {
go func() {
if condition() {
t.Fatal("oops") // This exits the inner func instead of TestFoo.
}
...
}()
}
</pre>
<p>
Code calling <code>t.Fatal</code> (or a similar method) from a created
goroutine should be rewritten to signal the test failure using
<code>t.Error</code> and exit the goroutine early using an alternative
method, such as using a <code>return</code> statement. The previous example
could be rewritten as:
</p>
<pre>
func TestFoo(t *testing.T) {
go func() {
if condition() {
t.Error("oops")
return
}
...
}()
}
</pre>
<p><!-- CL 248686, CL 276372 --> <p><!-- CL 248686, CL 276372 -->
The vet tool now warns about amd64 assembly that clobbers the BP The vet tool now warns about amd64 assembly that clobbers the BP
register (the frame pointer) without saving and restoring it, register (the frame pointer) without saving and restoring it,
@ -326,7 +379,7 @@ Do not send CLs removing the interior tags from such phrases.
summarizing its execution time and memory allocation. This trace can summarizing its execution time and memory allocation. This trace can
be used to find bottlenecks or regressions in Go startup be used to find bottlenecks or regressions in Go startup
performance. performance.
The <a href="/pkg/runtime/#hdr-Environment_Variables"><code>GODEBUG</code>< The <a href="/pkg/runtime/#hdr-Environment_Variables"><code>GODEBUG</code>
documentation</a> describes the format. documentation</a> describes the format.
</p> </p>
@ -408,7 +461,7 @@ Do not send CLs removing the interior tags from such phrases.
<p> <p>
On the producer side of the interface, On the producer side of the interface,
the new <a href="/pkg/embed/#FS">embed.FS</code></a> type the new <a href="/pkg/embed/#FS"><code>embed.FS</code></a> type
implements <code>fs.FS</code>, as does implements <code>fs.FS</code>, as does
<a href="/pkg/archive/zip/#Reader"><code>zip.Reader</code></a>. <a href="/pkg/archive/zip/#Reader"><code>zip.Reader</code></a>.
The new <a href="/pkg/os/#DirFS"><code>os.DirFS</code></a> function The new <a href="/pkg/os/#DirFS"><code>os.DirFS</code></a> function
@ -438,10 +491,10 @@ Do not send CLs removing the interior tags from such phrases.
implementations. implementations.
</p> </p>
<p> <!-- okay-after-beta1
TODO: when the "Minor changes to the library" section is close to completion, TODO: decide if any additional changes are worth factoring out from
decide if any changes are worth factoring out and highlighting in "Core library" "Minor changes to the library" and highlighting in "Core library"
</p> -->
<h3 id="minor_library_changes">Minor changes to the library</h3> <h3 id="minor_library_changes">Minor changes to the library</h3>
@ -451,10 +504,6 @@ Do not send CLs removing the interior tags from such phrases.
in mind. in mind.
</p> </p>
<p>
TODO: complete this section, resolve TODOs below, add missing entries
</p>
<dl id="crypto/dsa"><dt><a href="/pkg/crypto/dsa/">crypto/dsa</a></dt> <dl id="crypto/dsa"><dt><a href="/pkg/crypto/dsa/">crypto/dsa</a></dt>
<dd> <dd>
<p><!-- CL 257939 --> <p><!-- CL 257939 -->
@ -490,16 +539,6 @@ Do not send CLs removing the interior tags from such phrases.
indefinitely. indefinitely.
</p> </p>
<p><!-- CL 246338 -->
The new <a href="/pkg/crypto/tls#Conn.HandshakeContext"><code>Conn.HandshakeContext</code></a>
method allows cancellation of an in-progress handshake. The provided
context is accessible through the new
<a href="/pkg/crypto/tls#ClientHelloInfo.Context"><code>ClientHelloInfo.Context</code></a>
and <a href="/pkg/crypto/tls#CertificateRequestInfo.Context">
<code>CertificateRequestInfo.Context</code></a> methods. Canceling the
context after the handshake has finished has no effect.
</p>
<p><!-- CL 239748 --> <p><!-- CL 239748 -->
Clients now return a handshake error if the server selects Clients now return a handshake error if the server selects
<a href="/pkg/crypto/tls/#ConnectionState.NegotiatedProtocol"> <a href="/pkg/crypto/tls/#ConnectionState.NegotiatedProtocol">
@ -672,8 +711,8 @@ Do not send CLs removing the interior tags from such phrases.
<p><!-- CL 250357 --> <p><!-- CL 250357 -->
The case of I/O on a closed network connection, or I/O on a network The case of I/O on a closed network connection, or I/O on a network
connection that is closed before any of the I/O completes, can now connection that is closed before any of the I/O completes, can now
be detected using the new <a href="/pkg/net/#ErrClosed">ErrClosed</a> error. be detected using the new <a href="/pkg/net/#ErrClosed"><code>ErrClosed</code></a>
A typical use would be <code>errors.Is(err, net.ErrClosed)</code>. error. A typical use would be <code>errors.Is(err, net.ErrClosed)</code>.
In earlier releases the only way to reliably detect this case was to In earlier releases the only way to reliably detect this case was to
match the string returned by the <code>Error</code> method match the string returned by the <code>Error</code> method
with <code>"use of closed network connection"</code>. with <code>"use of closed network connection"</code>.
@ -722,13 +761,6 @@ Do not send CLs removing the interior tags from such phrases.
generating a SameSite key without a value. generating a SameSite key without a value.
</p> </p>
<p><!-- CL 246338 -->
The <a href="/pkg/net/http/"><code>net/http</code></a> package now passes the
<a href="/pkg/net/http/#Request.Context"><code>Request</code> context</a> to
<a href="/pkg/crypto/tls#Conn.HandshakeContext"><code>tls.Conn.HandshakeContext</code></a>
when performing TLS handshakes.
</p>
<p><!-- CL 250039 --> <p><!-- CL 250039 -->
The <a href="/pkg/net/http/#Client">Client</a> now sends The <a href="/pkg/net/http/#Client">Client</a> now sends
an explicit <code>Content-Length:</code> <code>0</code> an explicit <code>Content-Length:</code> <code>0</code>
@ -737,9 +769,10 @@ Do not send CLs removing the interior tags from such phrases.
</p> </p>
<p><!-- CL 249440 --> <p><!-- CL 249440 -->
The <a href="/pkg/net/http/#ProxyFromEnvironment">ProxyFromEnvironment</a> function The <a href="/pkg/net/http/#ProxyFromEnvironment"><code>ProxyFromEnvironment</code></a>
no longer returns the setting of the <code>HTTP_PROXY</code> environment function no longer returns the setting of the <code>HTTP_PROXY</code>
variable for <code>https://</code> URLs when <code>HTTPS_PROXY</code> is unset. environment variable for <code>https://</code> URLs when
<code>HTTPS_PROXY</code> is unset.
</p> </p>
</dd> </dd>
</dl><!-- net/http --> </dl><!-- net/http -->
@ -747,7 +780,7 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="net/http/httputil"><dt><a href="/pkg/net/http/httputil/">net/http/httputil</a></dt> <dl id="net/http/httputil"><dt><a href="/pkg/net/http/httputil/">net/http/httputil</a></dt>
<dd> <dd>
<p><!-- CL 260637 --> <p><!-- CL 260637 -->
The <a href="/pkg/net/http/httputil/#ReverseProxy">ReverseProxy</a> <a href="/pkg/net/http/httputil/#ReverseProxy"><code>ReverseProxy</code></a>
now flushes buffered data more aggressively when proxying now flushes buffered data more aggressively when proxying
streamed responses with unknown body lengths. streamed responses with unknown body lengths.
</p> </p>
@ -790,9 +823,9 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="path"><dt><a href="/pkg/path/">path</a></dt> <dl id="path"><dt><a href="/pkg/path/">path</a></dt>
<dd> <dd>
<p><!-- CL 264397, golang.org/issues/28614 --> <p><!-- CL 264397, golang.org/issues/28614 -->
The <code>Match</code> and <code>Glob</code> functions now The <a href="/pkg/path/#Match"><code>Match</code></a> function now
return an error if the unmatched part of the pattern has a returns an error if the unmatched part of the pattern has a
syntax error. Previously, the functions returned early on a failed syntax error. Previously, the function returned early on a failed
match, and thus did not report any later syntax error in the match, and thus did not report any later syntax error in the
pattern. pattern.
</p> </p>
@ -802,7 +835,8 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="path/filepath"><dt><a href="/pkg/path/filepath/">path/filepath</a></dt> <dl id="path/filepath"><dt><a href="/pkg/path/filepath/">path/filepath</a></dt>
<dd> <dd>
<p><!-- CL 264397, golang.org/issues/28614 --> <p><!-- CL 264397, golang.org/issues/28614 -->
The <code>Match</code> and <code>Glob</code> functions now The <a href="/pkg/path/filepath#Match"><code>Match</code></a> and
<a href="/pkg/path/filepath#Glob"><code>Glob</code></a> functions now
return an error if the unmatched part of the pattern has a return an error if the unmatched part of the pattern has a
syntax error. Previously, the functions returned early on a failed syntax error. Previously, the functions returned early on a failed
match, and thus did not report any later syntax error in the match, and thus did not report any later syntax error in the
@ -814,9 +848,10 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="reflect"><dt><a href="/pkg/reflect/">reflect</a></dt> <dl id="reflect"><dt><a href="/pkg/reflect/">reflect</a></dt>
<dd> <dd>
<p><!-- CL 248341, golang.org/issues/40281 --> <p><!-- CL 248341, golang.org/issues/40281 -->
<code>StructTag</code> now allows multiple space-separated keys <a href="/pkg/reflect/#StructTag"><code>StructTag</code></a>
in key:value pairs, as in <code>`json xml:"field1"`</code> now allows multiple space-separated keys in key:value pairs,
(equivalent to <code>`json:"field1" xml:"field1"`</code>). as in <code>`json xml:"field1"`</code> (equivalent to
<code>`json:"field1" xml:"field1"`</code>).
</p> </p>
</dd> </dd>
</dl><!-- reflect --> </dl><!-- reflect -->

View file

@ -119,11 +119,26 @@ The Go toolchain is written in Go. To build it, you need a Go compiler installed
The scripts that do the initial build of the tools look for a "go" command The scripts that do the initial build of the tools look for a "go" command
in <code>$PATH</code>, so as long as you have Go installed in your in <code>$PATH</code>, so as long as you have Go installed in your
system and configured in your <code>$PATH</code>, you are ready to build Go system and configured in your <code>$PATH</code>, you are ready to build Go
from source. from source.
Or if you prefer you can set <code>$GOROOT_BOOTSTRAP</code> to the Or if you prefer you can set <code>$GOROOT_BOOTSTRAP</code> to the
root of a Go installation to use to build the new Go toolchain; root of a Go installation to use to build the new Go toolchain;
<code>$GOROOT_BOOTSTRAP/bin/go</code> should be the go command to use.</p> <code>$GOROOT_BOOTSTRAP/bin/go</code> should be the go command to use.</p>
<p>
There are four possible ways to obtain a bootstrap toolchain:
</p>
<ul>
<li>Download a recent binary release of Go.
<li>Cross-compile a toolchain using a system with a working Go installation.
<li>Use gccgo.
<li>Compile a toolchain from Go 1.4, the last Go release with a compiler written in C.
</ul>
<p>
These approaches are detailed below.
</p>
<h3 id="bootstrapFromBinaryRelease">Bootstrap toolchain from binary release</h3> <h3 id="bootstrapFromBinaryRelease">Bootstrap toolchain from binary release</h3>
<p> <p>
@ -132,30 +147,6 @@ To use a binary release as a bootstrap toolchain, see
packaged Go distribution. packaged Go distribution.
</p> </p>
<h3 id="bootstrapFromSource">Bootstrap toolchain from source</h3>
<p>
To build a bootstrap toolchain from source, use
either the git branch <code>release-branch.go1.4</code> or
<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
to keep the tools running on newer operating systems.
(Go 1.4 was the last distribution in which the toolchain was written in C.)
After unpacking the Go 1.4 source, <code>cd</code> to
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>).
</p>
<p>
Once the Go 1.4 source has been unpacked into your GOROOT_BOOTSTRAP directory,
you must keep this git clone instance checked out to branch
<code>release-branch.go1.4</code>. Specifically, do not attempt to reuse
this git clone in the later step named "Fetch the repository." The go1.4
bootstrap toolchain <b>must be able</b> to properly traverse the go1.4 sources
that it assumes are present under this repository root.
</p>
<h3 id="bootstrapFromCrosscompiledSource">Bootstrap toolchain from cross-compiled source</h3> <h3 id="bootstrapFromCrosscompiledSource">Bootstrap toolchain from cross-compiled source</h3>
<p> <p>
@ -194,6 +185,36 @@ $ sudo update-alternatives --set go /usr/bin/go-5
$ GOROOT_BOOTSTRAP=/usr ./make.bash $ GOROOT_BOOTSTRAP=/usr ./make.bash
</pre> </pre>
<h3 id="bootstrapFromSource">Bootstrap toolchain from C source code</h3>
<p>
To build a bootstrap toolchain from C source code, use
either the git branch <code>release-branch.go1.4</code> or
<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
to keep the tools running on newer operating systems.
(Go 1.4 was the last distribution in which the toolchain was written in C.)
After unpacking the Go 1.4 source, <code>cd</code> to
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>).
</p>
<p>
Once the Go 1.4 source has been unpacked into your GOROOT_BOOTSTRAP directory,
you must keep this git clone instance checked out to branch
<code>release-branch.go1.4</code>. Specifically, do not attempt to reuse
this git clone in the later step named "Fetch the repository." The go1.4
bootstrap toolchain <b>must be able</b> to properly traverse the go1.4 sources
that it assumes are present under this repository root.
</p>
<p>
Note that Go 1.4 does not run on all systems that later versions of Go do.
In particular, Go 1.4 does not support current versions of macOS.
On such systems, the bootstrap toolchain must be obtained using one of the other methods.
</p>
<h2 id="git">Install Git, if needed</h2> <h2 id="git">Install Git, if needed</h2>
<p> <p>

View file

@ -20,6 +20,7 @@ var (
TrimPath = flag.String("trimpath", "", "remove prefix from recorded source file paths") TrimPath = flag.String("trimpath", "", "remove prefix from recorded source file paths")
Shared = flag.Bool("shared", false, "generate code that can be linked into a shared library") Shared = flag.Bool("shared", false, "generate code that can be linked into a shared library")
Dynlink = flag.Bool("dynlink", false, "support references to Go symbols defined in other shared libraries") Dynlink = flag.Bool("dynlink", false, "support references to Go symbols defined in other shared libraries")
Linkshared = flag.Bool("linkshared", false, "generate code that will be linked against Go shared libraries")
AllErrors = flag.Bool("e", false, "no limit on number of errors reported") AllErrors = flag.Bool("e", false, "no limit on number of errors reported")
SymABIs = flag.Bool("gensymabis", false, "write symbol ABI information to output file, don't assemble") SymABIs = flag.Bool("gensymabis", false, "write symbol ABI information to output file, don't assemble")
Importpath = flag.String("p", "", "set expected package import to path") Importpath = flag.String("p", "", "set expected package import to path")

View file

@ -37,6 +37,7 @@ func main() {
ctxt := obj.Linknew(architecture.LinkArch) ctxt := obj.Linknew(architecture.LinkArch)
ctxt.Debugasm = flags.PrintOut ctxt.Debugasm = flags.PrintOut
ctxt.Flag_dynlink = *flags.Dynlink ctxt.Flag_dynlink = *flags.Dynlink
ctxt.Flag_linkshared = *flags.Linkshared
ctxt.Flag_shared = *flags.Shared || *flags.Dynlink ctxt.Flag_shared = *flags.Shared || *flags.Dynlink
ctxt.IsAsm = true ctxt.IsAsm = true
ctxt.Pkgpath = *flags.Importpath ctxt.Pkgpath = *flags.Importpath

View file

@ -740,7 +740,7 @@ func reassigned(name *ir.Name) bool {
if n.Left() == name && n != name.Defn { if n.Left() == name && n != name.Defn {
return true return true
} }
case ir.OAS2, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2DOTTYPE: case ir.OAS2, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2DOTTYPE, ir.OAS2RECV, ir.OSELRECV2:
for _, p := range n.List().Slice() { for _, p := range n.List().Slice() {
if p == name && n != name.Defn { if p == name && n != name.Defn {
return true return true

View file

@ -894,7 +894,7 @@ func (o *Order) stmt(n ir.Node) {
// case x, ok = <-c // case x, ok = <-c
recv := r.Rlist().First().(*ir.UnaryExpr) recv := r.Rlist().First().(*ir.UnaryExpr)
recv.SetLeft(o.expr(recv.Left(), nil)) recv.SetLeft(o.expr(recv.Left(), nil))
if recv.Left().Op() != ir.ONAME { if !ir.IsAutoTmp(recv.Left()) {
recv.SetLeft(o.copyExpr(recv.Left())) recv.SetLeft(o.copyExpr(recv.Left()))
} }
r := r.(*ir.AssignListStmt) r := r.(*ir.AssignListStmt)

View file

@ -6003,7 +6003,7 @@ func (s *state) dottype(n *ir.TypeAssertExpr, commaok bool) (res, resok *ssa.Val
// Load type out of itab, build interface with existing idata. // Load type out of itab, build interface with existing idata.
off := s.newValue1I(ssa.OpOffPtr, byteptr, int64(Widthptr), itab) off := s.newValue1I(ssa.OpOffPtr, byteptr, int64(Widthptr), itab)
typ := s.load(byteptr, off) typ := s.load(byteptr, off)
idata := s.newValue1(ssa.OpIData, n.Type(), iface) idata := s.newValue1(ssa.OpIData, byteptr, iface)
res = s.newValue2(ssa.OpIMake, n.Type(), typ, idata) res = s.newValue2(ssa.OpIMake, n.Type(), typ, idata)
return return
} }
@ -6025,7 +6025,7 @@ func (s *state) dottype(n *ir.TypeAssertExpr, commaok bool) (res, resok *ssa.Val
bOk.AddEdgeTo(bEnd) bOk.AddEdgeTo(bEnd)
bFail.AddEdgeTo(bEnd) bFail.AddEdgeTo(bEnd)
s.startBlock(bEnd) s.startBlock(bEnd)
idata := s.newValue1(ssa.OpIData, n.Type(), iface) idata := s.newValue1(ssa.OpIData, byteptr, iface)
res = s.newValue2(ssa.OpIMake, n.Type(), s.variable(typVar, byteptr), idata) res = s.newValue2(ssa.OpIMake, n.Type(), s.variable(typVar, byteptr), idata)
resok = cond resok = cond
delete(s.vars, typVar) delete(s.vars, typVar)

View file

@ -147,6 +147,11 @@ func checkFunc(f *Func) {
canHaveAuxInt = true canHaveAuxInt = true
case auxInt128: case auxInt128:
// AuxInt must be zero, so leave canHaveAuxInt set to false. // AuxInt must be zero, so leave canHaveAuxInt set to false.
case auxUInt8:
if v.AuxInt != int64(uint8(v.AuxInt)) {
f.Fatalf("bad uint8 AuxInt value for %v", v)
}
canHaveAuxInt = true
case auxFloat32: case auxFloat32:
canHaveAuxInt = true canHaveAuxInt = true
if math.IsNaN(v.AuxFloat()) { if math.IsNaN(v.AuxFloat()) {

View file

@ -196,9 +196,6 @@ func expandCalls(f *Func) {
} }
if leaf.Op == OpIData { if leaf.Op == OpIData {
leafType = removeTrivialWrapperTypes(leaf.Type) leafType = removeTrivialWrapperTypes(leaf.Type)
if leafType.IsEmptyInterface() {
leafType = typ.BytePtr
}
} }
aux := selector.Aux aux := selector.Aux
auxInt := selector.AuxInt + offset auxInt := selector.AuxInt + offset
@ -247,12 +244,9 @@ func expandCalls(f *Func) {
// i.e., the struct select is generated and remains in because it is not applied to an actual structure. // i.e., the struct select is generated and remains in because it is not applied to an actual structure.
// The OpLoad was created to load the single field of the IData // The OpLoad was created to load the single field of the IData
// This case removes that StructSelect. // This case removes that StructSelect.
if leafType != selector.Type && !selector.Type.IsEmptyInterface() { // empty interface for #42727 if leafType != selector.Type {
f.Fatalf("Unexpected Load as selector, leaf=%s, selector=%s\n", leaf.LongString(), selector.LongString()) f.Fatalf("Unexpected Load as selector, leaf=%s, selector=%s\n", leaf.LongString(), selector.LongString())
} }
if selector.Type.IsEmptyInterface() {
selector.Type = typ.BytePtr
}
leaf.copyOf(selector) leaf.copyOf(selector)
for _, s := range namedSelects[selector] { for _, s := range namedSelects[selector] {
locs = append(locs, f.Names[s.locIndex]) locs = append(locs, f.Names[s.locIndex])

View file

@ -663,8 +663,8 @@
((OR|XOR)W x (MOVDconst [c])) => ((OR|XOR)Wconst [int32(c)] x) ((OR|XOR)W x (MOVDconst [c])) => ((OR|XOR)Wconst [int32(c)] x)
// Constant shifts. // Constant shifts.
(S(LD|RD|RAD) x (MOVDconst [c])) => (S(LD|RD|RAD)const x [int8(c&63)]) (S(LD|RD|RAD) x (MOVDconst [c])) => (S(LD|RD|RAD)const x [uint8(c&63)])
(S(LW|RW|RAW) x (MOVDconst [c])) && c&32 == 0 => (S(LW|RW|RAW)const x [int8(c&31)]) (S(LW|RW|RAW) x (MOVDconst [c])) && c&32 == 0 => (S(LW|RW|RAW)const x [uint8(c&31)])
(S(LW|RW) _ (MOVDconst [c])) && c&32 != 0 => (MOVDconst [0]) (S(LW|RW) _ (MOVDconst [c])) && c&32 != 0 => (MOVDconst [0])
(SRAW x (MOVDconst [c])) && c&32 != 0 => (SRAWconst x [31]) (SRAW x (MOVDconst [c])) && c&32 != 0 => (SRAWconst x [31])
@ -685,8 +685,8 @@
(SRAW x (MOV(W|H|B|WZ|HZ|BZ)reg y)) => (SRAW x y) (SRAW x (MOV(W|H|B|WZ|HZ|BZ)reg y)) => (SRAW x y)
// Match rotate by constant. // Match rotate by constant.
(RLLG x (MOVDconst [c])) => (RISBGZ x {s390x.NewRotateParams(0, 63, int8(c&63))}) (RLLG x (MOVDconst [c])) => (RISBGZ x {s390x.NewRotateParams(0, 63, uint8(c&63))})
(RLL x (MOVDconst [c])) => (RLLconst x [int8(c&31)]) (RLL x (MOVDconst [c])) => (RLLconst x [uint8(c&31)])
// Match rotate by constant pattern. // Match rotate by constant pattern.
((ADD|OR|XOR) (SLDconst x [c]) (SRDconst x [64-c])) => (RISBGZ x {s390x.NewRotateParams(0, 63, c)}) ((ADD|OR|XOR) (SLDconst x [c]) (SRDconst x [64-c])) => (RISBGZ x {s390x.NewRotateParams(0, 63, c)})
@ -705,10 +705,10 @@
(CMP(W|WU) (MOVDconst [c]) x) => (InvertFlags (CMP(W|WU)const x [int32(c)])) (CMP(W|WU) (MOVDconst [c]) x) => (InvertFlags (CMP(W|WU)const x [int32(c)]))
// Match (x >> c) << d to 'rotate then insert selected bits [into zero]'. // Match (x >> c) << d to 'rotate then insert selected bits [into zero]'.
(SLDconst (SRDconst x [c]) [d]) => (RISBGZ x {s390x.NewRotateParams(max8(0, c-d), 63-d, (d-c)&63)}) (SLDconst (SRDconst x [c]) [d]) => (RISBGZ x {s390x.NewRotateParams(uint8(max8(0, int8(c-d))), 63-d, uint8(int8(d-c)&63))})
// Match (x << c) >> d to 'rotate then insert selected bits [into zero]'. // Match (x << c) >> d to 'rotate then insert selected bits [into zero]'.
(SRDconst (SLDconst x [c]) [d]) => (RISBGZ x {s390x.NewRotateParams(d, min8(63, 63-c+d), (c-d)&63)}) (SRDconst (SLDconst x [c]) [d]) => (RISBGZ x {s390x.NewRotateParams(d, uint8(min8(63, int8(63-c+d))), uint8(int8(c-d)&63))})
// Absorb input zero extension into 'rotate then insert selected bits [into zero]'. // Absorb input zero extension into 'rotate then insert selected bits [into zero]'.
(RISBGZ (MOVWZreg x) {r}) && r.InMerge(0xffffffff) != nil => (RISBGZ x {*r.InMerge(0xffffffff)}) (RISBGZ (MOVWZreg x) {r}) && r.InMerge(0xffffffff) != nil => (RISBGZ x {*r.InMerge(0xffffffff)})
@ -818,18 +818,18 @@
// c = 2ˣ + 2ʸ => c - 2ˣ = 2ʸ // c = 2ˣ + 2ʸ => c - 2ˣ = 2ʸ
(MULL(D|W)const <t> x [c]) && isPowerOfTwo32(c&(c-1)) (MULL(D|W)const <t> x [c]) && isPowerOfTwo32(c&(c-1))
=> ((ADD|ADDW) (SL(D|W)const <t> x [int8(log32(c&(c-1)))]) => ((ADD|ADDW) (SL(D|W)const <t> x [uint8(log32(c&(c-1)))])
(SL(D|W)const <t> x [int8(log32(c&^(c-1)))])) (SL(D|W)const <t> x [uint8(log32(c&^(c-1)))]))
// c = 2ʸ - 2ˣ => c + 2ˣ = 2ʸ // c = 2ʸ - 2ˣ => c + 2ˣ = 2ʸ
(MULL(D|W)const <t> x [c]) && isPowerOfTwo32(c+(c&^(c-1))) (MULL(D|W)const <t> x [c]) && isPowerOfTwo32(c+(c&^(c-1)))
=> ((SUB|SUBW) (SL(D|W)const <t> x [int8(log32(c+(c&^(c-1))))]) => ((SUB|SUBW) (SL(D|W)const <t> x [uint8(log32(c+(c&^(c-1))))])
(SL(D|W)const <t> x [int8(log32(c&^(c-1)))])) (SL(D|W)const <t> x [uint8(log32(c&^(c-1)))]))
// c = 2ˣ - 2ʸ => -c + 2ˣ = 2ʸ // c = 2ˣ - 2ʸ => -c + 2ˣ = 2ʸ
(MULL(D|W)const <t> x [c]) && isPowerOfTwo32(-c+(-c&^(-c-1))) (MULL(D|W)const <t> x [c]) && isPowerOfTwo32(-c+(-c&^(-c-1)))
=> ((SUB|SUBW) (SL(D|W)const <t> x [int8(log32(-c&^(-c-1)))]) => ((SUB|SUBW) (SL(D|W)const <t> x [uint8(log32(-c&^(-c-1)))])
(SL(D|W)const <t> x [int8(log32(-c+(-c&^(-c-1))))])) (SL(D|W)const <t> x [uint8(log32(-c+(-c&^(-c-1))))]))
// Fold ADD into MOVDaddr. Odd offsets from SB shouldn't be folded (LARL can't handle them). // Fold ADD into MOVDaddr. Odd offsets from SB shouldn't be folded (LARL can't handle them).
(ADDconst [c] (MOVDaddr [d] {s} x:(SB))) && ((c+d)&1 == 0) && is32Bit(int64(c)+int64(d)) => (MOVDaddr [c+d] {s} x) (ADDconst [c] (MOVDaddr [d] {s} x:(SB))) && ((c+d)&1 == 0) && is32Bit(int64(c)+int64(d)) => (MOVDaddr [c+d] {s} x)

View file

@ -330,27 +330,27 @@ func init() {
{name: "LTDBR", argLength: 1, reg: fp1flags, asm: "LTDBR", typ: "Flags"}, // arg0 compare to 0, f64 {name: "LTDBR", argLength: 1, reg: fp1flags, asm: "LTDBR", typ: "Flags"}, // arg0 compare to 0, f64
{name: "LTEBR", argLength: 1, reg: fp1flags, asm: "LTEBR", typ: "Flags"}, // arg0 compare to 0, f32 {name: "LTEBR", argLength: 1, reg: fp1flags, asm: "LTEBR", typ: "Flags"}, // arg0 compare to 0, f32
{name: "SLD", argLength: 2, reg: sh21, asm: "SLD"}, // arg0 << arg1, shift amount is mod 64 {name: "SLD", argLength: 2, reg: sh21, asm: "SLD"}, // arg0 << arg1, shift amount is mod 64
{name: "SLW", argLength: 2, reg: sh21, asm: "SLW"}, // arg0 << arg1, shift amount is mod 64 {name: "SLW", argLength: 2, reg: sh21, asm: "SLW"}, // arg0 << arg1, shift amount is mod 64
{name: "SLDconst", argLength: 1, reg: gp11, asm: "SLD", aux: "Int8"}, // arg0 << auxint, shift amount 0-63 {name: "SLDconst", argLength: 1, reg: gp11, asm: "SLD", aux: "UInt8"}, // arg0 << auxint, shift amount 0-63
{name: "SLWconst", argLength: 1, reg: gp11, asm: "SLW", aux: "Int8"}, // arg0 << auxint, shift amount 0-31 {name: "SLWconst", argLength: 1, reg: gp11, asm: "SLW", aux: "UInt8"}, // arg0 << auxint, shift amount 0-31
{name: "SRD", argLength: 2, reg: sh21, asm: "SRD"}, // unsigned arg0 >> arg1, shift amount is mod 64 {name: "SRD", argLength: 2, reg: sh21, asm: "SRD"}, // unsigned arg0 >> arg1, shift amount is mod 64
{name: "SRW", argLength: 2, reg: sh21, asm: "SRW"}, // unsigned uint32(arg0) >> arg1, shift amount is mod 64 {name: "SRW", argLength: 2, reg: sh21, asm: "SRW"}, // unsigned uint32(arg0) >> arg1, shift amount is mod 64
{name: "SRDconst", argLength: 1, reg: gp11, asm: "SRD", aux: "Int8"}, // unsigned arg0 >> auxint, shift amount 0-63 {name: "SRDconst", argLength: 1, reg: gp11, asm: "SRD", aux: "UInt8"}, // unsigned arg0 >> auxint, shift amount 0-63
{name: "SRWconst", argLength: 1, reg: gp11, asm: "SRW", aux: "Int8"}, // unsigned uint32(arg0) >> auxint, shift amount 0-31 {name: "SRWconst", argLength: 1, reg: gp11, asm: "SRW", aux: "UInt8"}, // unsigned uint32(arg0) >> auxint, shift amount 0-31
// Arithmetic shifts clobber flags. // Arithmetic shifts clobber flags.
{name: "SRAD", argLength: 2, reg: sh21, asm: "SRAD", clobberFlags: true}, // signed arg0 >> arg1, shift amount is mod 64 {name: "SRAD", argLength: 2, reg: sh21, asm: "SRAD", clobberFlags: true}, // signed arg0 >> arg1, shift amount is mod 64
{name: "SRAW", argLength: 2, reg: sh21, asm: "SRAW", clobberFlags: true}, // signed int32(arg0) >> arg1, shift amount is mod 64 {name: "SRAW", argLength: 2, reg: sh21, asm: "SRAW", clobberFlags: true}, // signed int32(arg0) >> arg1, shift amount is mod 64
{name: "SRADconst", argLength: 1, reg: gp11, asm: "SRAD", aux: "Int8", clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-63 {name: "SRADconst", argLength: 1, reg: gp11, asm: "SRAD", aux: "UInt8", clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-63
{name: "SRAWconst", argLength: 1, reg: gp11, asm: "SRAW", aux: "Int8", clobberFlags: true}, // signed int32(arg0) >> auxint, shift amount 0-31 {name: "SRAWconst", argLength: 1, reg: gp11, asm: "SRAW", aux: "UInt8", clobberFlags: true}, // signed int32(arg0) >> auxint, shift amount 0-31
// Rotate instructions. // Rotate instructions.
// Note: no RLLGconst - use RISBGZ instead. // Note: no RLLGconst - use RISBGZ instead.
{name: "RLLG", argLength: 2, reg: sh21, asm: "RLLG"}, // arg0 rotate left arg1, rotate amount 0-63 {name: "RLLG", argLength: 2, reg: sh21, asm: "RLLG"}, // arg0 rotate left arg1, rotate amount 0-63
{name: "RLL", argLength: 2, reg: sh21, asm: "RLL"}, // arg0 rotate left arg1, rotate amount 0-31 {name: "RLL", argLength: 2, reg: sh21, asm: "RLL"}, // arg0 rotate left arg1, rotate amount 0-31
{name: "RLLconst", argLength: 1, reg: gp11, asm: "RLL", aux: "Int8"}, // arg0 rotate left auxint, rotate amount 0-31 {name: "RLLconst", argLength: 1, reg: gp11, asm: "RLL", aux: "UInt8"}, // arg0 rotate left auxint, rotate amount 0-31
// Rotate then (and|or|xor|insert) selected bits instructions. // Rotate then (and|or|xor|insert) selected bits instructions.
// //

View file

@ -1395,7 +1395,7 @@ func parseValue(val string, arch arch, loc string) (op opData, oparch, typ, auxi
func opHasAuxInt(op opData) bool { func opHasAuxInt(op opData) bool {
switch op.aux { switch op.aux {
case "Bool", "Int8", "Int16", "Int32", "Int64", "Int128", "Float32", "Float64", case "Bool", "Int8", "Int16", "Int32", "Int64", "Int128", "UInt8", "Float32", "Float64",
"SymOff", "CallOff", "SymValAndOff", "TypSize", "ARM64BitField", "FlagConstant", "CCop": "SymOff", "CallOff", "SymValAndOff", "TypSize", "ARM64BitField", "FlagConstant", "CCop":
return true return true
} }
@ -1780,6 +1780,8 @@ func (op opData) auxIntType() string {
return "int64" return "int64"
case "Int128": case "Int128":
return "int128" return "int128"
case "UInt8":
return "uint8"
case "Float32": case "Float32":
return "float32" return "float32"
case "Float64": case "Float64":

View file

@ -207,6 +207,7 @@ const (
auxInt32 // auxInt is a 32-bit integer auxInt32 // auxInt is a 32-bit integer
auxInt64 // auxInt is a 64-bit integer auxInt64 // auxInt is a 64-bit integer
auxInt128 // auxInt represents a 128-bit integer. Always 0. auxInt128 // auxInt represents a 128-bit integer. Always 0.
auxUInt8 // auxInt is an 8-bit unsigned integer
auxFloat32 // auxInt is a float32 (encoded with math.Float64bits) auxFloat32 // auxInt is a float32 (encoded with math.Float64bits)
auxFloat64 // auxInt is a float64 (encoded with math.Float64bits) auxFloat64 // auxInt is a float64 (encoded with math.Float64bits)
auxFlagConstant // auxInt is a flagConstant auxFlagConstant // auxInt is a flagConstant

View file

@ -30569,7 +30569,7 @@ var opcodeTable = [...]opInfo{
}, },
{ {
name: "SLDconst", name: "SLDconst",
auxType: auxInt8, auxType: auxUInt8,
argLen: 1, argLen: 1,
asm: s390x.ASLD, asm: s390x.ASLD,
reg: regInfo{ reg: regInfo{
@ -30583,7 +30583,7 @@ var opcodeTable = [...]opInfo{
}, },
{ {
name: "SLWconst", name: "SLWconst",
auxType: auxInt8, auxType: auxUInt8,
argLen: 1, argLen: 1,
asm: s390x.ASLW, asm: s390x.ASLW,
reg: regInfo{ reg: regInfo{
@ -30625,7 +30625,7 @@ var opcodeTable = [...]opInfo{
}, },
{ {
name: "SRDconst", name: "SRDconst",
auxType: auxInt8, auxType: auxUInt8,
argLen: 1, argLen: 1,
asm: s390x.ASRD, asm: s390x.ASRD,
reg: regInfo{ reg: regInfo{
@ -30639,7 +30639,7 @@ var opcodeTable = [...]opInfo{
}, },
{ {
name: "SRWconst", name: "SRWconst",
auxType: auxInt8, auxType: auxUInt8,
argLen: 1, argLen: 1,
asm: s390x.ASRW, asm: s390x.ASRW,
reg: regInfo{ reg: regInfo{
@ -30683,7 +30683,7 @@ var opcodeTable = [...]opInfo{
}, },
{ {
name: "SRADconst", name: "SRADconst",
auxType: auxInt8, auxType: auxUInt8,
argLen: 1, argLen: 1,
clobberFlags: true, clobberFlags: true,
asm: s390x.ASRAD, asm: s390x.ASRAD,
@ -30698,7 +30698,7 @@ var opcodeTable = [...]opInfo{
}, },
{ {
name: "SRAWconst", name: "SRAWconst",
auxType: auxInt8, auxType: auxUInt8,
argLen: 1, argLen: 1,
clobberFlags: true, clobberFlags: true,
asm: s390x.ASRAW, asm: s390x.ASRAW,
@ -30741,7 +30741,7 @@ var opcodeTable = [...]opInfo{
}, },
{ {
name: "RLLconst", name: "RLLconst",
auxType: auxInt8, auxType: auxUInt8,
argLen: 1, argLen: 1,
asm: s390x.ARLL, asm: s390x.ARLL,
reg: regInfo{ reg: regInfo{

File diff suppressed because it is too large Load diff

View file

@ -8,5 +8,5 @@ require (
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
golang.org/x/mod v0.4.0 golang.org/x/mod v0.4.0
golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect
golang.org/x/tools v0.0.0-20201208211828-de58e7c01d49 golang.org/x/tools v0.0.0-20201211025543-abf6a1d87e11
) )

View file

@ -31,8 +31,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201208211828-de58e7c01d49 h1:K1QAOVIWIvmQ66F1Z3AEa9Wzp0bj+xU3YzLkvROk2Ds= golang.org/x/tools v0.0.0-20201211025543-abf6a1d87e11 h1:9j/upNXDRpADUw2RpUfJ7E7GHtfhDih62kX6JM8vs2c=
golang.org/x/tools v0.0.0-20201208211828-de58e7c01d49/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201211025543-abf6a1d87e11/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=

View file

@ -164,6 +164,17 @@
// directory, but it is not accessed. When -modfile is specified, an // directory, but it is not accessed. When -modfile is specified, an
// alternate go.sum file is also used: its path is derived from the // alternate go.sum file is also used: its path is derived from the
// -modfile flag by trimming the ".mod" extension and appending ".sum". // -modfile flag by trimming the ".mod" extension and appending ".sum".
// -overlay file
// read a JSON config file that provides an overlay for build operations.
// The file is a JSON struct with a single field, named 'Replace', that
// maps each disk file path (a string) to its backing file path, so that
// a build will run as if the disk file path exists with the contents
// given by the backing file paths, or as if the disk file path does not
// exist if its backing file path is empty. Support for the -overlay flag
// has some limitations:importantly, cgo files included from outside the
// include path must be in the same directory as the Go package they are
// included from, and overlays will not appear when binaries and tests are
// run through go run and go test respectively.
// -pkgdir dir // -pkgdir dir
// install and load all packages from dir instead of the usual locations. // install and load all packages from dir instead of the usual locations.
// For example, when building with a non-standard configuration, // For example, when building with a non-standard configuration,

View file

@ -31,6 +31,7 @@ import (
"cmd/go/internal/cache" "cmd/go/internal/cache"
"cmd/go/internal/cfg" "cmd/go/internal/cfg"
"cmd/go/internal/robustio" "cmd/go/internal/robustio"
"cmd/go/internal/work"
"cmd/internal/sys" "cmd/internal/sys"
) )
@ -1365,6 +1366,30 @@ func TestLdflagsArgumentsWithSpacesIssue3941(t *testing.T) {
tg.grepStderr("^hello world", `ldflags -X "main.extern=hello world"' failed`) tg.grepStderr("^hello world", `ldflags -X "main.extern=hello world"' failed`)
} }
func TestLdFlagsLongArgumentsIssue42295(t *testing.T) {
// Test the extremely long command line arguments that contain '\n' characters
// get encoded and passed correctly.
skipIfGccgo(t, "gccgo does not support -ldflags -X")
tooSlow(t)
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.tempFile("main.go", `package main
var extern string
func main() {
print(extern)
}`)
testStr := "test test test test test \n\\ "
var buf bytes.Buffer
for buf.Len() < work.ArgLengthForResponseFile+1 {
buf.WriteString(testStr)
}
tg.run("run", "-ldflags", fmt.Sprintf(`-X "main.extern=%s"`, buf.String()), tg.path("main.go"))
if tg.stderr.String() != buf.String() {
t.Errorf("strings differ")
}
}
func TestGoTestDashCDashOControlsBinaryLocation(t *testing.T) { func TestGoTestDashCDashOControlsBinaryLocation(t *testing.T) {
skipIfGccgo(t, "gccgo has no standard packages") skipIfGccgo(t, "gccgo has no standard packages")
tooSlow(t) tooSlow(t)

View file

@ -33,8 +33,20 @@ See also: go fmt, go vet.
} }
func runFix(ctx context.Context, cmd *base.Command, args []string) { func runFix(ctx context.Context, cmd *base.Command, args []string) {
pkgs := load.PackagesAndErrors(ctx, args)
w := 0
for _, pkg := range pkgs {
if pkg.Error != nil {
base.Errorf("%v", pkg.Error)
continue
}
pkgs[w] = pkg
w++
}
pkgs = pkgs[:w]
printed := false printed := false
for _, pkg := range load.Packages(ctx, args) { for _, pkg := range pkgs {
if modload.Enabled() && pkg.Module != nil && !pkg.Module.Main { if modload.Enabled() && pkg.Module != nil && !pkg.Module.Main {
if !printed { if !printed {
fmt.Fprintf(os.Stderr, "go: not fixing packages in dependency modules\n") fmt.Fprintf(os.Stderr, "go: not fixing packages in dependency modules\n")

View file

@ -180,13 +180,14 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
// everything. // everything.
load.ClearPackageCache() load.ClearPackageCache()
pkgs := load.PackagesForBuild(ctx, args) pkgs := load.PackagesAndErrors(ctx, args)
load.CheckPackageErrors(pkgs)
// Phase 3. Install. // Phase 3. Install.
if *getD { if *getD {
// Download only. // Download only.
// Check delayed until now so that importPaths // Check delayed until now so that downloadPaths
// and packagesForBuild have a chance to print errors. // and CheckPackageErrors have a chance to print errors.
return return
} }

View file

@ -471,11 +471,18 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
} }
load.IgnoreImports = *listFind load.IgnoreImports = *listFind
var pkgs []*load.Package pkgs := load.PackagesAndErrors(ctx, args)
if *listE { if !*listE {
pkgs = load.PackagesAndErrors(ctx, args) w := 0
} else { for _, pkg := range pkgs {
pkgs = load.Packages(ctx, args) if pkg.Error != nil {
base.Errorf("%v", pkg.Error)
continue
}
pkgs[w] = pkg
w++
}
pkgs = pkgs[:w]
base.ExitIfErrors() base.ExitIfErrors()
} }

View file

@ -2314,30 +2314,14 @@ func LoadImportWithFlags(path, srcDir string, parent *Package, stk *ImportStack,
// argument where needed. // argument where needed.
var ModResolveTests bool var ModResolveTests bool
// Packages returns the packages named by the // PackagesAndErrors returns the packages named by the command line arguments
// command line arguments 'args'. If a named package // 'patterns'. If a named package cannot be loaded, PackagesAndErrors returns
// cannot be loaded at all (for example, if the directory does not exist), // a *Package with the Error field describing the failure. If errors are found
// then packages prints an error and does not include that // loading imported packages, the DepsErrors field is set. The Incomplete field
// package in the results. However, if errors occur trying // may be set as well.
// to load dependencies of a named package, the named //
// package is still returned, with p.Incomplete = true // To obtain a flat list of packages, use PackageList.
// and details in p.DepsErrors. // To report errors loading packages, use ReportPackageErrors.
func Packages(ctx context.Context, args []string) []*Package {
var pkgs []*Package
for _, pkg := range PackagesAndErrors(ctx, args) {
if pkg.Error != nil {
base.Errorf("%v", pkg.Error)
continue
}
pkgs = append(pkgs, pkg)
}
return pkgs
}
// PackagesAndErrors is like 'packages' but returns a
// *Package for every argument, even the ones that
// cannot be loaded at all.
// The packages that fail to load will have p.Error != nil.
func PackagesAndErrors(ctx context.Context, patterns []string) []*Package { func PackagesAndErrors(ctx context.Context, patterns []string) []*Package {
ctx, span := trace.StartSpan(ctx, "load.PackagesAndErrors") ctx, span := trace.StartSpan(ctx, "load.PackagesAndErrors")
defer span.Done() defer span.Done()
@ -2427,20 +2411,9 @@ func PackagesAndErrors(ctx context.Context, patterns []string) []*Package {
return pkgs return pkgs
} }
func setToolFlags(pkgs ...*Package) { // CheckPackageErrors prints errors encountered loading pkgs and their
for _, p := range PackageList(pkgs) { // dependencies, then exits with a non-zero status if any errors were found.
p.Internal.Asmflags = BuildAsmflags.For(p) func CheckPackageErrors(pkgs []*Package) {
p.Internal.Gcflags = BuildGcflags.For(p)
p.Internal.Ldflags = BuildLdflags.For(p)
p.Internal.Gccgoflags = BuildGccgoflags.For(p)
}
}
// PackagesForBuild is like Packages but exits
// if any of the packages or their dependencies have errors
// (cannot be built).
func PackagesForBuild(ctx context.Context, args []string) []*Package {
pkgs := PackagesAndErrors(ctx, args)
printed := map[*PackageError]bool{} printed := map[*PackageError]bool{}
for _, pkg := range pkgs { for _, pkg := range pkgs {
if pkg.Error != nil { if pkg.Error != nil {
@ -2475,8 +2448,15 @@ func PackagesForBuild(ctx context.Context, args []string) []*Package {
seen[pkg.ImportPath] = true seen[pkg.ImportPath] = true
} }
base.ExitIfErrors() base.ExitIfErrors()
}
return pkgs func setToolFlags(pkgs ...*Package) {
for _, p := range PackageList(pkgs) {
p.Internal.Asmflags = BuildAsmflags.For(p)
p.Internal.Gcflags = BuildGcflags.For(p)
p.Internal.Ldflags = BuildLdflags.For(p)
p.Internal.Gccgoflags = BuildGccgoflags.For(p)
}
} }
// GoFilesPackage creates a package for building a collection of Go files // GoFilesPackage creates a package for building a collection of Go files

View file

@ -434,11 +434,13 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
// directory. // directory.
if !*getD && len(pkgPatterns) > 0 { if !*getD && len(pkgPatterns) > 0 {
work.BuildInit() work.BuildInit()
pkgs := load.PackagesForBuild(ctx, pkgPatterns) pkgs := load.PackagesAndErrors(ctx, pkgPatterns)
load.CheckPackageErrors(pkgs)
work.InstallPackages(ctx, pkgPatterns, pkgs) work.InstallPackages(ctx, pkgPatterns, pkgs)
// TODO(#40276): After Go 1.16, print a deprecation notice when building // TODO(#40276): After Go 1.16, print a deprecation notice when building
// and installing main packages. 'go install pkg' or // and installing main packages. 'go install pkg' or
// 'go install pkg@version' should be used instead. // 'go install pkg@version' should be used instead.
// Give the specific argument to use if possible.
} }
if !modload.HasModRoot() { if !modload.HasModRoot() {

View file

@ -595,7 +595,8 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
work.VetFlags = testVet.flags work.VetFlags = testVet.flags
work.VetExplicit = testVet.explicit work.VetExplicit = testVet.explicit
pkgs = load.PackagesForBuild(ctx, pkgArgs) pkgs = load.PackagesAndErrors(ctx, pkgArgs)
load.CheckPackageErrors(pkgs)
if len(pkgs) == 0 { if len(pkgs) == 0 {
base.Fatalf("no packages to test") base.Fatalf("no packages to test")
} }
@ -678,7 +679,9 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
sort.Strings(all) sort.Strings(all)
a := &work.Action{Mode: "go test -i"} a := &work.Action{Mode: "go test -i"}
for _, p := range load.PackagesForBuild(ctx, all) { pkgs := load.PackagesAndErrors(ctx, all)
load.CheckPackageErrors(pkgs)
for _, p := range pkgs {
if cfg.BuildToolchainName == "gccgo" && p.Standard { if cfg.BuildToolchainName == "gccgo" && p.Standard {
// gccgo's standard library packages // gccgo's standard library packages
// can not be reinstalled. // can not be reinstalled.

View file

@ -87,7 +87,8 @@ func runVet(ctx context.Context, cmd *base.Command, args []string) {
} }
} }
pkgs := load.PackagesForBuild(ctx, pkgArgs) pkgs := load.PackagesAndErrors(ctx, pkgArgs)
load.CheckPackageErrors(pkgs)
if len(pkgs) == 0 { if len(pkgs) == 0 {
base.Fatalf("no packages to vet") base.Fatalf("no packages to vet")
} }

View file

@ -124,6 +124,17 @@ and test commands:
directory, but it is not accessed. When -modfile is specified, an directory, but it is not accessed. When -modfile is specified, an
alternate go.sum file is also used: its path is derived from the alternate go.sum file is also used: its path is derived from the
-modfile flag by trimming the ".mod" extension and appending ".sum". -modfile flag by trimming the ".mod" extension and appending ".sum".
-overlay file
read a JSON config file that provides an overlay for build operations.
The file is a JSON struct with a single field, named 'Replace', that
maps each disk file path (a string) to its backing file path, so that
a build will run as if the disk file path exists with the contents
given by the backing file paths, or as if the disk file path does not
exist if its backing file path is empty. Support for the -overlay flag
has some limitations:importantly, cgo files included from outside the
include path must be in the same directory as the Go package they are
included from, and overlays will not appear when binaries and tests are
run through go run and go test respectively.
-pkgdir dir -pkgdir dir
install and load all packages from dir instead of the usual locations. install and load all packages from dir instead of the usual locations.
For example, when building with a non-standard configuration, For example, when building with a non-standard configuration,
@ -358,7 +369,8 @@ func runBuild(ctx context.Context, cmd *base.Command, args []string) {
var b Builder var b Builder
b.Init() b.Init()
pkgs := load.PackagesForBuild(ctx, args) pkgs := load.PackagesAndErrors(ctx, args)
load.CheckPackageErrors(pkgs)
explicitO := len(cfg.BuildO) > 0 explicitO := len(cfg.BuildO) > 0
@ -388,7 +400,7 @@ func runBuild(ctx context.Context, cmd *base.Command, args []string) {
fmt.Fprint(os.Stderr, "go build: -i flag is deprecated\n") fmt.Fprint(os.Stderr, "go build: -i flag is deprecated\n")
} }
pkgs = omitTestOnly(pkgsFilter(load.Packages(ctx, args))) pkgs = omitTestOnly(pkgsFilter(pkgs))
// Special case -o /dev/null by not writing at all. // Special case -o /dev/null by not writing at all.
if cfg.BuildO == os.DevNull { if cfg.BuildO == os.DevNull {
@ -571,8 +583,32 @@ func runInstall(ctx context.Context, cmd *base.Command, args []string) {
return return
} }
} }
BuildInit() BuildInit()
pkgs := load.PackagesForBuild(ctx, args) pkgs := load.PackagesAndErrors(ctx, args)
if cfg.ModulesEnabled && !modload.HasModRoot() {
haveErrors := false
allMissingErrors := true
for _, pkg := range pkgs {
if pkg.Error == nil {
continue
}
haveErrors = true
if missingErr := (*modload.ImportMissingError)(nil); !errors.As(pkg.Error, &missingErr) {
allMissingErrors = false
break
}
}
if haveErrors && allMissingErrors {
latestArgs := make([]string, len(args))
for i := range args {
latestArgs[i] = args[i] + "@latest"
}
hint := strings.Join(latestArgs, " ")
base.Fatalf("go install: version is required when current directory is not in a module\n\tTry 'go install %s' to install the latest version", hint)
}
}
load.CheckPackageErrors(pkgs)
if cfg.BuildI { if cfg.BuildI {
allGoroot := true allGoroot := true
for _, pkg := range pkgs { for _, pkg := range pkgs {
@ -585,6 +621,7 @@ func runInstall(ctx context.Context, cmd *base.Command, args []string) {
fmt.Fprint(os.Stderr, "go install: -i flag is deprecated\n") fmt.Fprint(os.Stderr, "go install: -i flag is deprecated\n")
} }
} }
InstallPackages(ctx, args, pkgs) InstallPackages(ctx, args, pkgs)
} }
@ -802,7 +839,7 @@ func installOutsideModule(ctx context.Context, args []string) {
// Load packages for all arguments. Ignore non-main packages. // Load packages for all arguments. Ignore non-main packages.
// Print a warning if an argument contains "..." and matches no main packages. // Print a warning if an argument contains "..." and matches no main packages.
// PackagesForBuild already prints warnings for patterns that don't match any // PackagesAndErrors already prints warnings for patterns that don't match any
// packages, so be careful not to double print. // packages, so be careful not to double print.
matchers := make([]func(string) bool, len(patterns)) matchers := make([]func(string) bool, len(patterns))
for i, p := range patterns { for i, p := range patterns {
@ -813,7 +850,8 @@ func installOutsideModule(ctx context.Context, args []string) {
// TODO(golang.org/issue/40276): don't report errors loading non-main packages // TODO(golang.org/issue/40276): don't report errors loading non-main packages
// matched by a pattern. // matched by a pattern.
pkgs := load.PackagesForBuild(ctx, patterns) pkgs := load.PackagesAndErrors(ctx, patterns)
load.CheckPackageErrors(pkgs)
mainPkgs := make([]*load.Package, 0, len(pkgs)) mainPkgs := make([]*load.Package, 0, len(pkgs))
mainCount := make([]int, len(patterns)) mainCount := make([]int, len(patterns))
nonMainCount := make([]int, len(patterns)) nonMainCount := make([]int, len(patterns))

View file

@ -3236,7 +3236,7 @@ func passLongArgsInResponseFiles(cmd *exec.Cmd) (cleanup func()) {
cleanup = func() { os.Remove(tf.Name()) } cleanup = func() { os.Remove(tf.Name()) }
var buf bytes.Buffer var buf bytes.Buffer
for _, arg := range cmd.Args[1:] { for _, arg := range cmd.Args[1:] {
fmt.Fprintf(&buf, "%s\n", arg) fmt.Fprintf(&buf, "%s\n", encodeArg(arg))
} }
if _, err := tf.Write(buf.Bytes()); err != nil { if _, err := tf.Write(buf.Bytes()); err != nil {
tf.Close() tf.Close()
@ -3251,6 +3251,12 @@ func passLongArgsInResponseFiles(cmd *exec.Cmd) (cleanup func()) {
return cleanup return cleanup
} }
// Windows has a limit of 32 KB arguments. To be conservative and not worry
// about whether that includes spaces or not, just use 30 KB. Darwin's limit is
// less clear. The OS claims 256KB, but we've seen failures with arglen as
// small as 50KB.
const ArgLengthForResponseFile = (30 << 10)
func useResponseFile(path string, argLen int) bool { func useResponseFile(path string, argLen int) bool {
// Unless the program uses objabi.Flagparse, which understands // Unless the program uses objabi.Flagparse, which understands
// response files, don't use response files. // response files, don't use response files.
@ -3262,11 +3268,7 @@ func useResponseFile(path string, argLen int) bool {
return false return false
} }
// Windows has a limit of 32 KB arguments. To be conservative and not if argLen > ArgLengthForResponseFile {
// worry about whether that includes spaces or not, just use 30 KB.
// Darwin's limit is less clear. The OS claims 256KB, but we've seen
// failures with arglen as small as 50KB.
if argLen > (30 << 10) {
return true return true
} }
@ -3279,3 +3281,25 @@ func useResponseFile(path string, argLen int) bool {
return false return false
} }
// encodeArg encodes an argument for response file writing.
func encodeArg(arg string) string {
// If there aren't any characters we need to reencode, fastpath out.
if !strings.ContainsAny(arg, "\\\n") {
return arg
}
var b strings.Builder
for _, r := range arg {
switch r {
case '\\':
b.WriteByte('\\')
b.WriteByte('\\')
case '\n':
b.WriteByte('\\')
b.WriteByte('n')
default:
b.WriteRune(r)
}
}
return b.String()
}

View file

@ -0,0 +1,86 @@
// Copyright 2011 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 work
import (
"bytes"
"cmd/internal/objabi"
"fmt"
"math/rand"
"testing"
"time"
"unicode/utf8"
)
func TestEncodeArgs(t *testing.T) {
t.Parallel()
tests := []struct {
arg, want string
}{
{"", ""},
{"hello", "hello"},
{"hello\n", "hello\\n"},
{"hello\\", "hello\\\\"},
{"hello\nthere", "hello\\nthere"},
{"\\\n", "\\\\\\n"},
}
for _, test := range tests {
if got := encodeArg(test.arg); got != test.want {
t.Errorf("encodeArg(%q) = %q, want %q", test.arg, got, test.want)
}
}
}
func TestEncodeDecode(t *testing.T) {
t.Parallel()
tests := []string{
"",
"hello",
"hello\\there",
"hello\nthere",
"hello 中国",
"hello \n中\\国",
}
for _, arg := range tests {
if got := objabi.DecodeArg(encodeArg(arg)); got != arg {
t.Errorf("objabi.DecodeArg(encodeArg(%q)) = %q", arg, got)
}
}
}
func TestEncodeDecodeFuzz(t *testing.T) {
if testing.Short() {
t.Skip("fuzz test is slow")
}
t.Parallel()
nRunes := ArgLengthForResponseFile + 100
rBuffer := make([]rune, nRunes)
buf := bytes.NewBuffer([]byte(string(rBuffer)))
seed := time.Now().UnixNano()
t.Logf("rand seed: %v", seed)
rng := rand.New(rand.NewSource(seed))
for i := 0; i < 50; i++ {
// Generate a random string of runes.
buf.Reset()
for buf.Len() < ArgLengthForResponseFile+1 {
var r rune
for {
r = rune(rng.Intn(utf8.MaxRune + 1))
if utf8.ValidRune(r) {
break
}
}
fmt.Fprintf(buf, "%c", r)
}
arg := buf.String()
if got := objabi.DecodeArg(encodeArg(arg)); got != arg {
t.Errorf("[%d] objabi.DecodeArg(encodeArg(%q)) = %q [seed: %v]", i, arg, got, seed)
}
}
}

View file

@ -241,7 +241,8 @@ func buildModeInit() {
if gccgo { if gccgo {
codegenArg = "-fPIC" codegenArg = "-fPIC"
} else { } else {
forcedAsmflags = append(forcedAsmflags, "-D=GOBUILDMODE_shared=1") forcedAsmflags = append(forcedAsmflags, "-D=GOBUILDMODE_shared=1",
"-linkshared")
codegenArg = "-dynlink" codegenArg = "-dynlink"
forcedGcflags = append(forcedGcflags, "-linkshared") forcedGcflags = append(forcedGcflags, "-linkshared")
// TODO(mwhudson): remove -w when that gets fixed in linker. // TODO(mwhudson): remove -w when that gets fixed in linker.

View file

@ -189,13 +189,16 @@ exists $GOPATH/bin/printversion$GOEXE
# 'go install' should fail if a package argument must be resolved to a module. # 'go install' should fail if a package argument must be resolved to a module.
! go install example.com/printversion ! go install example.com/printversion
stderr 'no required module provides package example.com/printversion: working directory is not part of a module' stderr '^go install: version is required when current directory is not in a module\n\tTry ''go install example.com/printversion@latest'' to install the latest version$'
# 'go install' should fail if a source file imports a package that must be # 'go install' should fail if a source file imports a package that must be
# resolved to a module. # resolved to a module.
! go install ./needmod/needmod.go ! go install ./needmod/needmod.go
stderr 'needmod[/\\]needmod.go:10:2: no required module provides package example.com/version: working directory is not part of a module' stderr 'needmod[/\\]needmod.go:10:2: no required module provides package example.com/version: working directory is not part of a module'
# 'go install' should succeed with a package in GOROOT.
go install cmd/addr2line
! stderr .
# 'go run' with a verison should fail due to syntax. # 'go run' with a verison should fail due to syntax.
! go run example.com/printversion@v1.0.0 ! go run example.com/printversion@v1.0.0

View file

@ -483,6 +483,11 @@ func (r *RefFlags) SetFlag2(x uint8) { r[9] = x }
func (r *RefFlags) Write(w *Writer) { w.Bytes(r[:]) } func (r *RefFlags) Write(w *Writer) { w.Bytes(r[:]) }
// Used to construct an artifically large array type when reading an
// item from the object file relocs section or aux sym section (needs
// to work on 32-bit as well as 64-bit). See issue 41621.
const huge = (1<<31 - 1) / RelocSize
// Referenced symbol name. // Referenced symbol name.
// //
// Serialized format: // Serialized format:
@ -792,7 +797,7 @@ func (r *Reader) Reloc(i uint32, j int) *Reloc {
func (r *Reader) Relocs(i uint32) []Reloc { func (r *Reader) Relocs(i uint32) []Reloc {
off := r.RelocOff(i, 0) off := r.RelocOff(i, 0)
n := r.NReloc(i) n := r.NReloc(i)
return (*[1 << 20]Reloc)(unsafe.Pointer(&r.b[off]))[:n:n] return (*[huge]Reloc)(unsafe.Pointer(&r.b[off]))[:n:n]
} }
// NAux returns the number of aux symbols of the i-th symbol. // NAux returns the number of aux symbols of the i-th symbol.
@ -818,7 +823,7 @@ func (r *Reader) Aux(i uint32, j int) *Aux {
func (r *Reader) Auxs(i uint32) []Aux { func (r *Reader) Auxs(i uint32) []Aux {
off := r.AuxOff(i, 0) off := r.AuxOff(i, 0)
n := r.NAux(i) n := r.NAux(i)
return (*[1 << 20]Aux)(unsafe.Pointer(&r.b[off]))[:n:n] return (*[huge]Aux)(unsafe.Pointer(&r.b[off]))[:n:n]
} }
// DataOff returns the offset of the i-th symbol's data. // DataOff returns the offset of the i-th symbol's data.

View file

@ -28,9 +28,9 @@ import (
// input left by. Note that this rotation is performed // input left by. Note that this rotation is performed
// before the masked region is used. // before the masked region is used.
type RotateParams struct { type RotateParams struct {
Start int8 // big-endian start bit index [0..63] Start uint8 // big-endian start bit index [0..63]
End int8 // big-endian end bit index [0..63] End uint8 // big-endian end bit index [0..63]
Amount int8 // amount to rotate left Amount uint8 // amount to rotate left
} }
// NewRotateParams creates a set of parameters representing a // NewRotateParams creates a set of parameters representing a
@ -39,7 +39,7 @@ type RotateParams struct {
// //
// The start and end indexes and the rotation amount must all // The start and end indexes and the rotation amount must all
// be in the range 0-63 inclusive or this function will panic. // be in the range 0-63 inclusive or this function will panic.
func NewRotateParams(start, end, amount int8) RotateParams { func NewRotateParams(start, end, amount uint8) RotateParams {
if start&^63 != 0 { if start&^63 != 0 {
panic("start out of bounds") panic("start out of bounds")
} }
@ -58,7 +58,7 @@ func NewRotateParams(start, end, amount int8) RotateParams {
// RotateLeft generates a new set of parameters with the rotation amount // RotateLeft generates a new set of parameters with the rotation amount
// increased by the given value. The selected bits are left unchanged. // increased by the given value. The selected bits are left unchanged.
func (r RotateParams) RotateLeft(amount int8) RotateParams { func (r RotateParams) RotateLeft(amount uint8) RotateParams {
r.Amount += amount r.Amount += amount
r.Amount &= 63 r.Amount &= 63
return r return r
@ -100,8 +100,8 @@ func (r RotateParams) OutMerge(mask uint64) *RotateParams {
} }
// update start and end positions (rotation amount remains the same) // update start and end positions (rotation amount remains the same)
r.Start = int8(o+z) & 63 r.Start = uint8(o+z) & 63
r.End = (r.Start + int8(l) - 1) & 63 r.End = (r.Start + uint8(l) - 1) & 63
return &r return &r
} }

View file

@ -10,7 +10,7 @@ import (
func TestRotateParamsMask(t *testing.T) { func TestRotateParamsMask(t *testing.T) {
tests := []struct { tests := []struct {
start, end, amount int8 start, end, amount uint8
inMask, outMask uint64 inMask, outMask uint64
}{ }{
// start before end, no rotation // start before end, no rotation

View file

@ -5,6 +5,7 @@
package objabi package objabi
import ( import (
"bytes"
"flag" "flag"
"fmt" "fmt"
"io" "io"
@ -59,6 +60,9 @@ func expandArgs(in []string) (out []string) {
log.Fatal(err) log.Fatal(err)
} }
args := strings.Split(strings.TrimSpace(strings.Replace(string(slurp), "\r", "", -1)), "\n") args := strings.Split(strings.TrimSpace(strings.Replace(string(slurp), "\r", "", -1)), "\n")
for i, arg := range args {
args[i] = DecodeArg(arg)
}
out = append(out, expandArgs(args)...) out = append(out, expandArgs(args)...)
} else if out != nil { } else if out != nil {
out = append(out, s) out = append(out, s)
@ -160,3 +164,38 @@ func (f fn1) Set(s string) error {
} }
func (f fn1) String() string { return "" } func (f fn1) String() string { return "" }
// DecodeArg decodes an argument.
//
// This function is public for testing with the parallel encoder.
func DecodeArg(arg string) string {
// If no encoding, fastpath out.
if !strings.ContainsAny(arg, "\\\n") {
return arg
}
// We can't use strings.Builder as this must work at bootstrap.
var b bytes.Buffer
var wasBS bool
for _, r := range arg {
if wasBS {
switch r {
case '\\':
b.WriteByte('\\')
case 'n':
b.WriteByte('\n')
default:
// This shouldn't happen. The only backslashes that reach here
// should encode '\n' and '\\' exclusively.
panic("badly formatted input")
}
} else if r == '\\' {
wasBS = true
continue
} else {
b.WriteRune(r)
}
wasBS = false
}
return b.String()
}

View file

@ -0,0 +1,26 @@
// Copyright 2020 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 objabi
import "testing"
func TestDecodeArg(t *testing.T) {
t.Parallel()
tests := []struct {
arg, want string
}{
{"", ""},
{"hello", "hello"},
{"hello\\n", "hello\n"},
{"hello\\nthere", "hello\nthere"},
{"hello\\\\there", "hello\\there"},
{"\\\\\\n", "\\\n"},
}
for _, test := range tests {
if got := DecodeArg(test.arg); got != test.want {
t.Errorf("decodoeArg(%q) = %q, want %q", test.arg, got, test.want)
}
}
}

View file

@ -37,6 +37,7 @@ import (
"cmd/link/internal/loader" "cmd/link/internal/loader"
"cmd/link/internal/sym" "cmd/link/internal/sym"
"debug/elf" "debug/elf"
"fmt"
"log" "log"
) )
@ -463,12 +464,29 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
return true return true
} }
// sign-extends from 24-bit.
func signext24(x int64) int64 { return x << 40 >> 40 }
func machoreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, sectoff int64) bool { func machoreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, sectoff int64) bool {
var v uint32 var v uint32
rs := r.Xsym rs := r.Xsym
rt := r.Type rt := r.Type
siz := r.Size siz := r.Size
xadd := r.Xadd
if xadd != signext24(xadd) {
// If the relocation target would overflow the addend, then target
// a linker-manufactured label symbol with a smaller addend instead.
label := ldr.Lookup(machoLabelName(ldr, rs, xadd), ldr.SymVersion(rs))
if label != 0 {
xadd = ldr.SymValue(rs) + xadd - ldr.SymValue(label)
rs = label
}
if xadd != signext24(xadd) {
ldr.Errorf(s, "internal error: relocation addend overflow: %s+0x%x", ldr.SymName(rs), xadd)
}
}
if ldr.SymType(rs) == sym.SHOSTOBJ || rt == objabi.R_CALLARM64 || rt == objabi.R_ADDRARM64 || rt == objabi.R_ARM64_GOTPCREL { if ldr.SymType(rs) == sym.SHOSTOBJ || rt == objabi.R_CALLARM64 || rt == objabi.R_ADDRARM64 || rt == objabi.R_ARM64_GOTPCREL {
if ldr.SymDynid(rs) < 0 { if ldr.SymDynid(rs) < 0 {
@ -492,8 +510,8 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sy
case objabi.R_ADDR: case objabi.R_ADDR:
v |= ld.MACHO_ARM64_RELOC_UNSIGNED << 28 v |= ld.MACHO_ARM64_RELOC_UNSIGNED << 28
case objabi.R_CALLARM64: case objabi.R_CALLARM64:
if r.Xadd != 0 { if xadd != 0 {
ldr.Errorf(s, "ld64 doesn't allow BR26 reloc with non-zero addend: %s+%d", ldr.SymName(rs), r.Xadd) ldr.Errorf(s, "ld64 doesn't allow BR26 reloc with non-zero addend: %s+%d", ldr.SymName(rs), xadd)
} }
v |= 1 << 24 // pc-relative bit v |= 1 << 24 // pc-relative bit
@ -504,13 +522,13 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sy
// if r.Xadd is non-zero, add two MACHO_ARM64_RELOC_ADDEND. // if r.Xadd is non-zero, add two MACHO_ARM64_RELOC_ADDEND.
if r.Xadd != 0 { if r.Xadd != 0 {
out.Write32(uint32(sectoff + 4)) out.Write32(uint32(sectoff + 4))
out.Write32((ld.MACHO_ARM64_RELOC_ADDEND << 28) | (2 << 25) | uint32(r.Xadd&0xffffff)) out.Write32((ld.MACHO_ARM64_RELOC_ADDEND << 28) | (2 << 25) | uint32(xadd&0xffffff))
} }
out.Write32(uint32(sectoff + 4)) out.Write32(uint32(sectoff + 4))
out.Write32(v | (ld.MACHO_ARM64_RELOC_PAGEOFF12 << 28) | (2 << 25)) out.Write32(v | (ld.MACHO_ARM64_RELOC_PAGEOFF12 << 28) | (2 << 25))
if r.Xadd != 0 { if r.Xadd != 0 {
out.Write32(uint32(sectoff)) out.Write32(uint32(sectoff))
out.Write32((ld.MACHO_ARM64_RELOC_ADDEND << 28) | (2 << 25) | uint32(r.Xadd&0xffffff)) out.Write32((ld.MACHO_ARM64_RELOC_ADDEND << 28) | (2 << 25) | uint32(xadd&0xffffff))
} }
v |= 1 << 24 // pc-relative bit v |= 1 << 24 // pc-relative bit
v |= ld.MACHO_ARM64_RELOC_PAGE21 << 28 v |= ld.MACHO_ARM64_RELOC_PAGE21 << 28
@ -520,13 +538,13 @@ func machoreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sy
// if r.Xadd is non-zero, add two MACHO_ARM64_RELOC_ADDEND. // if r.Xadd is non-zero, add two MACHO_ARM64_RELOC_ADDEND.
if r.Xadd != 0 { if r.Xadd != 0 {
out.Write32(uint32(sectoff + 4)) out.Write32(uint32(sectoff + 4))
out.Write32((ld.MACHO_ARM64_RELOC_ADDEND << 28) | (2 << 25) | uint32(r.Xadd&0xffffff)) out.Write32((ld.MACHO_ARM64_RELOC_ADDEND << 28) | (2 << 25) | uint32(xadd&0xffffff))
} }
out.Write32(uint32(sectoff + 4)) out.Write32(uint32(sectoff + 4))
out.Write32(v | (ld.MACHO_ARM64_RELOC_GOT_LOAD_PAGEOFF12 << 28) | (2 << 25)) out.Write32(v | (ld.MACHO_ARM64_RELOC_GOT_LOAD_PAGEOFF12 << 28) | (2 << 25))
if r.Xadd != 0 { if r.Xadd != 0 {
out.Write32(uint32(sectoff)) out.Write32(uint32(sectoff))
out.Write32((ld.MACHO_ARM64_RELOC_ADDEND << 28) | (2 << 25) | uint32(r.Xadd&0xffffff)) out.Write32((ld.MACHO_ARM64_RELOC_ADDEND << 28) | (2 << 25) | uint32(xadd&0xffffff))
} }
v |= 1 << 24 // pc-relative bit v |= 1 << 24 // pc-relative bit
v |= ld.MACHO_ARM64_RELOC_GOT_LOAD_PAGE21 << 28 v |= ld.MACHO_ARM64_RELOC_GOT_LOAD_PAGE21 << 28
@ -965,3 +983,66 @@ func addpltsym(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade
ldr.Errorf(s, "addpltsym: unsupported binary format") ldr.Errorf(s, "addpltsym: unsupported binary format")
} }
} }
const machoRelocLimit = 1 << 23
func gensymlate(ctxt *ld.Link, ldr *loader.Loader) {
// When external linking on darwin, Mach-O relocation has only signed 24-bit
// addend. For large symbols, we generate "label" symbols in the middle, so
// that relocations can target them with smaller addends.
if !ctxt.IsDarwin() || !ctxt.IsExternal() {
return
}
big := false
for _, seg := range ld.Segments {
if seg.Length >= machoRelocLimit {
big = true
break
}
}
if !big {
return // skip work if nothing big
}
// addLabelSyms adds "label" symbols at s+machoRelocLimit, s+2*machoRelocLimit, etc.
addLabelSyms := func(s loader.Sym, sz int64) {
v := ldr.SymValue(s)
for off := int64(machoRelocLimit); off < sz; off += machoRelocLimit {
p := ldr.LookupOrCreateSym(machoLabelName(ldr, s, off), ldr.SymVersion(s))
ldr.SetAttrReachable(p, true)
ldr.SetSymValue(p, v+off)
ldr.SetSymSect(p, ldr.SymSect(s))
ld.AddMachoSym(ldr, p)
//fmt.Printf("gensymlate %s %x\n", ldr.SymName(p), ldr.SymValue(p))
}
}
for s, n := loader.Sym(1), loader.Sym(ldr.NSym()); s < n; s++ {
if !ldr.AttrReachable(s) {
continue
}
if ldr.SymType(s) == sym.STEXT {
continue // we don't target the middle of a function
}
sz := ldr.SymSize(s)
if sz <= machoRelocLimit {
continue
}
addLabelSyms(s, sz)
}
// Also for carrier symbols (for which SymSize is 0)
for _, ss := range ld.CarrierSymByType {
if ss.Sym != 0 && ss.Size > machoRelocLimit {
addLabelSyms(ss.Sym, ss.Size)
}
}
}
// machoLabelName returns the name of the "label" symbol used for a
// relocation targetting s+off. The label symbols is used on darwin
// when external linking, so that the addend fits in a Mach-O relocation.
func machoLabelName(ldr *loader.Loader, s loader.Sym, off int64) string {
return fmt.Sprintf("%s.%d", ldr.SymExtname(s), off/machoRelocLimit)
}

View file

@ -55,6 +55,7 @@ func Init() (*sys.Arch, ld.Arch) {
ElfrelocSize: 24, ElfrelocSize: 24,
Elfsetupplt: elfsetupplt, Elfsetupplt: elfsetupplt,
Gentext: gentext, Gentext: gentext,
GenSymsLate: gensymlate,
Machoreloc1: machoreloc1, Machoreloc1: machoreloc1,
MachorelocSize: 8, MachorelocSize: 8,

View file

@ -1815,6 +1815,7 @@ func (state *dodataState) allocateDataSections(ctxt *Link) {
for _, symn := range sym.ReadOnly { for _, symn := range sym.ReadOnly {
symnStartValue := state.datsize symnStartValue := state.datsize
state.assignToSection(sect, symn, sym.SRODATA) state.assignToSection(sect, symn, sym.SRODATA)
setCarrierSize(symn, state.datsize-symnStartValue)
if ctxt.HeadType == objabi.Haix { if ctxt.HeadType == objabi.Haix {
// Read-only symbols might be wrapped inside their outer // Read-only symbols might be wrapped inside their outer
// symbol. // symbol.
@ -1902,6 +1903,7 @@ func (state *dodataState) allocateDataSections(ctxt *Link) {
} }
} }
state.assignToSection(sect, symn, sym.SRODATA) state.assignToSection(sect, symn, sym.SRODATA)
setCarrierSize(symn, state.datsize-symnStartValue)
if ctxt.HeadType == objabi.Haix { if ctxt.HeadType == objabi.Haix {
// Read-only symbols might be wrapped inside their outer // Read-only symbols might be wrapped inside their outer
// symbol. // symbol.
@ -1949,6 +1951,7 @@ func (state *dodataState) allocateDataSections(ctxt *Link) {
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.pctab", 0), sect) ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.pctab", 0), sect)
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.functab", 0), sect) ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.functab", 0), sect)
ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.epclntab", 0), sect) ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.epclntab", 0), sect)
setCarrierSize(sym.SPCLNTAB, int64(sect.Length))
if ctxt.HeadType == objabi.Haix { if ctxt.HeadType == objabi.Haix {
xcoffUpdateOuterSize(ctxt, int64(sect.Length), sym.SPCLNTAB) xcoffUpdateOuterSize(ctxt, int64(sect.Length), sym.SPCLNTAB)
} }

View file

@ -1458,7 +1458,7 @@ func (ctxt *Link) hostlink() {
} }
const compressDWARF = "-Wl,--compress-debug-sections=zlib-gnu" const compressDWARF = "-Wl,--compress-debug-sections=zlib-gnu"
if ctxt.compressDWARF && linkerFlagSupported(argv[0], altLinker, compressDWARF) { if ctxt.compressDWARF && linkerFlagSupported(ctxt.Arch, argv[0], altLinker, compressDWARF) {
argv = append(argv, compressDWARF) argv = append(argv, compressDWARF)
} }
@ -1548,7 +1548,7 @@ func (ctxt *Link) hostlink() {
if ctxt.BuildMode == BuildModeExe && !ctxt.linkShared && !(ctxt.IsDarwin() && ctxt.IsARM64()) { if ctxt.BuildMode == BuildModeExe && !ctxt.linkShared && !(ctxt.IsDarwin() && ctxt.IsARM64()) {
// GCC uses -no-pie, clang uses -nopie. // GCC uses -no-pie, clang uses -nopie.
for _, nopie := range []string{"-no-pie", "-nopie"} { for _, nopie := range []string{"-no-pie", "-nopie"} {
if linkerFlagSupported(argv[0], altLinker, nopie) { if linkerFlagSupported(ctxt.Arch, argv[0], altLinker, nopie) {
argv = append(argv, nopie) argv = append(argv, nopie)
break break
} }
@ -1560,10 +1560,22 @@ func (ctxt *Link) hostlink() {
checkStatic(p) checkStatic(p)
} }
if ctxt.HeadType == objabi.Hwindows { if ctxt.HeadType == objabi.Hwindows {
// Determine which linker we're using. Add in the extldflags in
// case used has specified "-fuse-ld=...".
cmd := exec.Command(*flagExtld, *flagExtldflags, "-Wl,--version")
usingLLD := false
if out, err := cmd.CombinedOutput(); err == nil {
if bytes.Contains(out, []byte("LLD ")) {
usingLLD = true
}
}
// use gcc linker script to work around gcc bug // use gcc linker script to work around gcc bug
// (see https://golang.org/issue/20183 for details). // (see https://golang.org/issue/20183 for details).
p := writeGDBLinkerScript() if !usingLLD {
argv = append(argv, "-Wl,-T,"+p) p := writeGDBLinkerScript()
argv = append(argv, "-Wl,-T,"+p)
}
// libmingw32 and libmingwex have some inter-dependencies, // libmingw32 and libmingwex have some inter-dependencies,
// so must use linker groups. // so must use linker groups.
argv = append(argv, "-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group") argv = append(argv, "-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group")
@ -1657,7 +1669,7 @@ func (ctxt *Link) hostlink() {
var createTrivialCOnce sync.Once var createTrivialCOnce sync.Once
func linkerFlagSupported(linker, altLinker, flag string) bool { func linkerFlagSupported(arch *sys.Arch, linker, altLinker, flag string) bool {
createTrivialCOnce.Do(func() { createTrivialCOnce.Do(func() {
src := filepath.Join(*flagTmpdir, "trivial.c") src := filepath.Join(*flagTmpdir, "trivial.c")
if err := ioutil.WriteFile(src, []byte("int main() { return 0; }"), 0666); err != nil { if err := ioutil.WriteFile(src, []byte("int main() { return 0; }"), 0666); err != nil {
@ -1691,7 +1703,7 @@ func linkerFlagSupported(linker, altLinker, flag string) bool {
"-target", "-target",
} }
var flags []string flags := hostlinkArchArgs(arch)
keep := false keep := false
skip := false skip := false
extldflags := strings.Fields(*flagExtldflags) extldflags := strings.Fields(*flagExtldflags)
@ -1801,7 +1813,7 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string,
return ldhostobj(ldmacho, ctxt.HeadType, f, pkg, length, pn, file) return ldhostobj(ldmacho, ctxt.HeadType, f, pkg, length, pn, file)
} }
if c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86 { if /* x86 */ c1 == 0x4c && c2 == 0x01 || /* x86_64 */ c1 == 0x64 && c2 == 0x86 || /* armv7 */ c1 == 0xc4 && c2 == 0x01 {
ldpe := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) { ldpe := func(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
textp, rsrc, err := loadpe.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn) textp, rsrc, err := loadpe.Load(ctxt.loader, ctxt.Arch, ctxt.IncVersion(), f, pkg, length, pn)
if err != nil { if err != nil {

View file

@ -969,6 +969,15 @@ func machosymorder(ctxt *Link) {
} }
} }
// AddMachoSym adds s to Mach-O symbol table, used in GenSymLate.
// Currently only used on ARM64 when external linking.
func AddMachoSym(ldr *loader.Loader, s loader.Sym) {
ldr.SetSymDynid(s, int32(nsortsym))
sortsym = append(sortsym, s)
nsortsym++
nkind[symkind(ldr, s)]++
}
// machoShouldExport reports whether a symbol needs to be exported. // machoShouldExport reports whether a symbol needs to be exported.
// //
// When dynamically linking, all non-local variables and plugin-exported // When dynamically linking, all non-local variables and plugin-exported
@ -1474,6 +1483,17 @@ func machoCodeSign(ctxt *Link, fname string) error {
// Skip. // Skip.
return nil return nil
} }
fi, err := f.Stat()
if err != nil {
return err
}
if sigOff+sigSz != fi.Size() {
// We don't expect anything after the signature (this will invalidate
// the signature anyway.)
return fmt.Errorf("unexpected content after code signature")
}
sz := codesign.Size(sigOff, "a.out") sz := codesign.Size(sigOff, "a.out")
if sz != sigSz { if sz != sigSz {
// Update the load command, // Update the load command,
@ -1500,5 +1520,9 @@ func machoCodeSign(ctxt *Link, fname string) error {
cs := make([]byte, sz) cs := make([]byte, sz)
codesign.Sign(cs, f, "a.out", sigOff, int64(textSeg.Offset), int64(textSeg.Filesz), ctxt.IsExe() || ctxt.IsPIE()) codesign.Sign(cs, f, "a.out", sigOff, int64(textSeg.Offset), int64(textSeg.Filesz), ctxt.IsExe() || ctxt.IsPIE())
_, err = f.WriteAt(cs, sigOff) _, err = f.WriteAt(cs, sigOff)
if err != nil {
return err
}
err = f.Truncate(sigOff + sz)
return err return err
} }

View file

@ -859,6 +859,7 @@ func (ctxt *Link) pclntab(container loader.Bitmap) *pclntab {
state.carrier = ldr.LookupOrCreateSym("runtime.pclntab", 0) state.carrier = ldr.LookupOrCreateSym("runtime.pclntab", 0)
ldr.MakeSymbolUpdater(state.carrier).SetType(sym.SPCLNTAB) ldr.MakeSymbolUpdater(state.carrier).SetType(sym.SPCLNTAB)
ldr.SetAttrReachable(state.carrier, true) ldr.SetAttrReachable(state.carrier, true)
setCarrierSym(sym.SPCLNTAB, state.carrier)
state.generatePCHeader(ctxt) state.generatePCHeader(ctxt)
nameOffsets := state.generateFuncnametab(ctxt, funcs) nameOffsets := state.generateFuncnametab(ctxt, funcs)

View file

@ -1524,7 +1524,7 @@ func addpersrc(ctxt *Link) {
data := ctxt.loader.Data(rsrcsym) data := ctxt.loader.Data(rsrcsym)
size := len(data) size := len(data)
h := pefile.addSection(".rsrc", size, size) h := pefile.addSection(".rsrc", size, size)
h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA
h.checkOffset(ctxt.Out.Offset()) h.checkOffset(ctxt.Out.Offset())
// relocation // relocation

View file

@ -483,6 +483,8 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
symtype = s.Sym() symtype = s.Sym()
symtyperel = s.Sym() symtyperel = s.Sym()
} }
setCarrierSym(sym.STYPE, symtype)
setCarrierSym(sym.STYPERELRO, symtyperel)
} }
groupSym := func(name string, t sym.SymKind) loader.Sym { groupSym := func(name string, t sym.SymKind) loader.Sym {
@ -490,6 +492,7 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
s.SetType(t) s.SetType(t)
s.SetSize(0) s.SetSize(0)
s.SetLocal(true) s.SetLocal(true)
setCarrierSym(t, s.Sym())
return s.Sym() return s.Sym()
} }
var ( var (
@ -800,3 +803,23 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
} }
return symGroupType return symGroupType
} }
// CarrierSymByType tracks carrier symbols and their sizes.
var CarrierSymByType [sym.SXREF]struct {
Sym loader.Sym
Size int64
}
func setCarrierSym(typ sym.SymKind, s loader.Sym) {
if CarrierSymByType[typ].Sym != 0 {
panic(fmt.Sprintf("carrier symbol for type %v already set", typ))
}
CarrierSymByType[typ].Sym = s
}
func setCarrierSize(typ sym.SymKind, sz int64) {
if CarrierSymByType[typ].Size != 0 {
panic(fmt.Sprintf("carrier symbol size for type %v already set", typ))
}
CarrierSymByType[typ].Size = sz
}

View file

@ -574,6 +574,7 @@ func xcoffUpdateOuterSize(ctxt *Link, size int64, stype sym.SymKind) {
if size == 0 { if size == 0 {
return return
} }
// TODO: use CarrierSymByType
ldr := ctxt.loader ldr := ctxt.loader
switch stype { switch stype {

View file

@ -969,6 +969,8 @@ func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, error) {
case MIPS | uint32(elf.R_MIPS_HI16)<<16, case MIPS | uint32(elf.R_MIPS_HI16)<<16,
MIPS | uint32(elf.R_MIPS_LO16)<<16, MIPS | uint32(elf.R_MIPS_LO16)<<16,
MIPS | uint32(elf.R_MIPS_GOT16)<<16, MIPS | uint32(elf.R_MIPS_GOT16)<<16,
MIPS | uint32(elf.R_MIPS_GOT_HI16)<<16,
MIPS | uint32(elf.R_MIPS_GOT_LO16)<<16,
MIPS | uint32(elf.R_MIPS_GPREL16)<<16, MIPS | uint32(elf.R_MIPS_GPREL16)<<16,
MIPS | uint32(elf.R_MIPS_GOT_PAGE)<<16, MIPS | uint32(elf.R_MIPS_GOT_PAGE)<<16,
MIPS | uint32(elf.R_MIPS_JALR)<<16, MIPS | uint32(elf.R_MIPS_JALR)<<16,
@ -976,6 +978,8 @@ func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, error) {
MIPS64 | uint32(elf.R_MIPS_HI16)<<16, MIPS64 | uint32(elf.R_MIPS_HI16)<<16,
MIPS64 | uint32(elf.R_MIPS_LO16)<<16, MIPS64 | uint32(elf.R_MIPS_LO16)<<16,
MIPS64 | uint32(elf.R_MIPS_GOT16)<<16, MIPS64 | uint32(elf.R_MIPS_GOT16)<<16,
MIPS64 | uint32(elf.R_MIPS_GOT_HI16)<<16,
MIPS64 | uint32(elf.R_MIPS_GOT_LO16)<<16,
MIPS64 | uint32(elf.R_MIPS_GPREL16)<<16, MIPS64 | uint32(elf.R_MIPS_GPREL16)<<16,
MIPS64 | uint32(elf.R_MIPS_GOT_PAGE)<<16, MIPS64 | uint32(elf.R_MIPS_GOT_PAGE)<<16,
MIPS64 | uint32(elf.R_MIPS_JALR)<<16, MIPS64 | uint32(elf.R_MIPS_JALR)<<16,

View file

@ -6,6 +6,7 @@
package loadpe package loadpe
import ( import (
"bytes"
"cmd/internal/bio" "cmd/internal/bio"
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
@ -308,7 +309,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
rAdd = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rOff:]))) rAdd = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rOff:])))
case IMAGE_REL_ARM_ADDR32: case IMAGE_REL_ARM_ADDR32, IMAGE_REL_ARM_ADDR32NB:
rType = objabi.R_ADDR rType = objabi.R_ADDR
rAdd = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rOff:]))) rAdd = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rOff:])))
@ -359,6 +360,20 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
if pesym.SectionNumber == IMAGE_SYM_DEBUG { if pesym.SectionNumber == IMAGE_SYM_DEBUG {
continue continue
} }
if pesym.SectionNumber == IMAGE_SYM_ABSOLUTE && bytes.Equal(pesym.Name[:], []byte("@feat.00")) {
// Microsoft's linker looks at whether all input objects have an empty
// section called @feat.00. If all of them do, then it enables SEH;
// otherwise it doesn't enable that feature. So, since around the Windows
// XP SP2 era, most tools that make PE objects just tack on that section,
// so that it won't gimp Microsoft's linker logic. Go doesn't support SEH,
// so in theory, none of this really matters to us. But actually, if the
// linker tries to ingest an object with @feat.00 -- which are produced by
// LLVM's resource compiler, for example -- it chokes because of the
// IMAGE_SYM_ABSOLUTE section that it doesn't know how to deal with. Since
// @feat.00 is just a marking anyway, skip IMAGE_SYM_ABSOLUTE sections that
// are called @feat.00.
continue
}
var sect *pe.Section var sect *pe.Section
if pesym.SectionNumber > 0 { if pesym.SectionNumber > 0 {
sect = f.Sections[pesym.SectionNumber-1] sect = f.Sections[pesym.SectionNumber-1]

View file

@ -925,3 +925,57 @@ func TestIssue42396(t *testing.T) {
t.Fatalf("error message incorrect: expected it to contain %q but instead got:\n%s\n", want, out) t.Fatalf("error message incorrect: expected it to contain %q but instead got:\n%s\n", want, out)
} }
} }
const testLargeRelocSrc = `
package main
var x = [1<<25]byte{1<<23: 23, 1<<24: 24}
func main() {
check(x[1<<23-1], 0)
check(x[1<<23], 23)
check(x[1<<23+1], 0)
check(x[1<<24-1], 0)
check(x[1<<24], 24)
check(x[1<<24+1], 0)
}
func check(x, y byte) {
if x != y {
panic("FAIL")
}
}
`
func TestLargeReloc(t *testing.T) {
// Test that large relocation addend is handled correctly.
// In particular, on darwin/arm64 when external linking,
// Mach-O relocation has only 24-bit addend. See issue #42738.
testenv.MustHaveGoBuild(t)
t.Parallel()
tmpdir, err := ioutil.TempDir("", "TestIssue42396")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
src := filepath.Join(tmpdir, "x.go")
err = ioutil.WriteFile(src, []byte(testLargeRelocSrc), 0666)
if err != nil {
t.Fatalf("failed to write source file: %v", err)
}
cmd := exec.Command(testenv.GoToolPath(t), "run", src)
out, err := cmd.CombinedOutput()
if err != nil {
t.Errorf("build failed: %v. output:\n%s", err, out)
}
if testenv.HasCGO() { // currently all targets that support cgo can external link
cmd = exec.Command(testenv.GoToolPath(t), "run", "-ldflags=-linkmode=external", src)
out, err = cmd.CombinedOutput()
if err != nil {
t.Fatalf("build failed: %v. output:\n%s", err, out)
}
}
}

View file

@ -207,12 +207,12 @@ var (
) )
// validateStructTag parses the struct tag and returns an error if it is not // validateStructTag parses the struct tag and returns an error if it is not
// in the canonical format, which is a space-separated list of key:"value" // in the canonical format, as defined by reflect.StructTag.
// settings. The value may contain spaces.
func validateStructTag(tag string) error { func validateStructTag(tag string) error {
// This code is based on the StructTag.Get code in package reflect. // This code is based on the StructTag.Get code in package reflect.
n := 0 n := 0
var keys []string
for ; tag != ""; n++ { for ; tag != ""; n++ {
if n > 0 && tag != "" && tag[0] != ' ' { if n > 0 && tag != "" && tag[0] != ' ' {
// More restrictive than reflect, but catches likely mistakes // More restrictive than reflect, but catches likely mistakes
@ -240,14 +240,27 @@ func validateStructTag(tag string) error {
if i == 0 { if i == 0 {
return errTagKeySyntax return errTagKeySyntax
} }
if i+1 >= len(tag) || tag[i] != ':' { if i+1 >= len(tag) || tag[i] < ' ' || tag[i] == 0x7f {
return errTagSyntax return errTagSyntax
} }
if tag[i+1] != '"' { key := tag[:i]
keys = append(keys, key)
tag = tag[i:]
// If we found a space char here - assume that we have a tag with
// multiple keys.
if tag[0] == ' ' {
continue
}
// Spaces were filtered above so we assume that here we have
// only valid tag value started with `:"`.
if tag[0] != ':' || tag[1] != '"' {
return errTagValueSyntax return errTagValueSyntax
} }
key := tag[:i]
tag = tag[i+1:] // Remove the colon leaving tag at the start of the quoted string.
tag = tag[1:]
// Scan quoted string to find value. // Scan quoted string to find value.
i = 1 i = 1
@ -263,51 +276,56 @@ func validateStructTag(tag string) error {
qvalue := tag[:i+1] qvalue := tag[:i+1]
tag = tag[i+1:] tag = tag[i+1:]
value, err := strconv.Unquote(qvalue) wholeValue, err := strconv.Unquote(qvalue)
if err != nil { if err != nil {
return errTagValueSyntax return errTagValueSyntax
} }
if !checkTagSpaces[key] { for _, key := range keys {
continue if !checkTagSpaces[key] {
}
switch key {
case "xml":
// If the first or last character in the XML tag is a space, it is
// suspicious.
if strings.Trim(value, " ") != value {
return errTagValueSpace
}
// If there are multiple spaces, they are suspicious.
if strings.Count(value, " ") > 1 {
return errTagValueSpace
}
// If there is no comma, skip the rest of the checks.
comma := strings.IndexRune(value, ',')
if comma < 0 {
continue continue
} }
// If the character before a comma is a space, this is suspicious. value := wholeValue
if comma > 0 && value[comma-1] == ' ' { switch key {
case "xml":
// If the first or last character in the XML tag is a space, it is
// suspicious.
if strings.Trim(value, " ") != value {
return errTagValueSpace
}
// If there are multiple spaces, they are suspicious.
if strings.Count(value, " ") > 1 {
return errTagValueSpace
}
// If there is no comma, skip the rest of the checks.
comma := strings.IndexRune(value, ',')
if comma < 0 {
continue
}
// If the character before a comma is a space, this is suspicious.
if comma > 0 && value[comma-1] == ' ' {
return errTagValueSpace
}
value = value[comma+1:]
case "json":
// JSON allows using spaces in the name, so skip it.
comma := strings.IndexRune(value, ',')
if comma < 0 {
continue
}
value = value[comma+1:]
}
if strings.IndexByte(value, ' ') >= 0 {
return errTagValueSpace return errTagValueSpace
} }
value = value[comma+1:]
case "json":
// JSON allows using spaces in the name, so skip it.
comma := strings.IndexRune(value, ',')
if comma < 0 {
continue
}
value = value[comma+1:]
} }
if strings.IndexByte(value, ' ') >= 0 { keys = keys[:0]
return errTagValueSpace
}
} }
return nil return nil
} }

View file

@ -44,7 +44,7 @@ golang.org/x/mod/zip
golang.org/x/sys/internal/unsafeheader golang.org/x/sys/internal/unsafeheader
golang.org/x/sys/unix golang.org/x/sys/unix
golang.org/x/sys/windows golang.org/x/sys/windows
# golang.org/x/tools v0.0.0-20201208211828-de58e7c01d49 # golang.org/x/tools v0.0.0-20201211025543-abf6a1d87e11
## explicit ## explicit
golang.org/x/tools/go/analysis golang.org/x/tools/go/analysis
golang.org/x/tools/go/analysis/internal/analysisflags golang.org/x/tools/go/analysis/internal/analysisflags

View file

@ -7,7 +7,6 @@ package tls
import ( import (
"bytes" "bytes"
"container/list" "container/list"
"context"
"crypto" "crypto"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/ed25519" "crypto/ed25519"
@ -444,16 +443,6 @@ type ClientHelloInfo struct {
// config is embedded by the GetCertificate or GetConfigForClient caller, // config is embedded by the GetCertificate or GetConfigForClient caller,
// for use with SupportsCertificate. // for use with SupportsCertificate.
config *Config config *Config
// ctx is the context of the handshake that is in progress.
ctx context.Context
}
// Context returns the context of the handshake that is in progress.
// This context is a child of the context passed to HandshakeContext,
// if any, and is canceled when the handshake concludes.
func (c *ClientHelloInfo) Context() context.Context {
return c.ctx
} }
// CertificateRequestInfo contains information from a server's // CertificateRequestInfo contains information from a server's
@ -472,16 +461,6 @@ type CertificateRequestInfo struct {
// Version is the TLS version that was negotiated for this connection. // Version is the TLS version that was negotiated for this connection.
Version uint16 Version uint16
// ctx is the context of the handshake that is in progress.
ctx context.Context
}
// Context returns the context of the handshake that is in progress.
// This context is a child of the context passed to HandshakeContext,
// if any, and is canceled when the handshake concludes.
func (c *CertificateRequestInfo) Context() context.Context {
return c.ctx
} }
// RenegotiationSupport enumerates the different levels of support for TLS // RenegotiationSupport enumerates the different levels of support for TLS

View file

@ -8,7 +8,6 @@ package tls
import ( import (
"bytes" "bytes"
"context"
"crypto/cipher" "crypto/cipher"
"crypto/subtle" "crypto/subtle"
"crypto/x509" "crypto/x509"
@ -28,7 +27,7 @@ type Conn struct {
// constant // constant
conn net.Conn conn net.Conn
isClient bool isClient bool
handshakeFn func(context.Context) error // (*Conn).clientHandshake or serverHandshake handshakeFn func() error // (*Conn).clientHandshake or serverHandshake
// handshakeStatus is 1 if the connection is currently transferring // handshakeStatus is 1 if the connection is currently transferring
// application data (i.e. is not currently processing a handshake). // application data (i.e. is not currently processing a handshake).
@ -1191,7 +1190,7 @@ func (c *Conn) handleRenegotiation() error {
defer c.handshakeMutex.Unlock() defer c.handshakeMutex.Unlock()
atomic.StoreUint32(&c.handshakeStatus, 0) atomic.StoreUint32(&c.handshakeStatus, 0)
if c.handshakeErr = c.clientHandshake(context.Background()); c.handshakeErr == nil { if c.handshakeErr = c.clientHandshake(); c.handshakeErr == nil {
c.handshakes++ c.handshakes++
} }
return c.handshakeErr return c.handshakeErr
@ -1374,61 +1373,8 @@ func (c *Conn) closeNotify() error {
// first Read or Write will call it automatically. // first Read or Write will call it automatically.
// //
// For control over canceling or setting a timeout on a handshake, use // For control over canceling or setting a timeout on a handshake, use
// HandshakeContext or the Dialer's DialContext method instead. // the Dialer's DialContext method.
func (c *Conn) Handshake() error { func (c *Conn) Handshake() error {
return c.HandshakeContext(context.Background())
}
// HandshakeContext runs the client or server handshake
// protocol if it has not yet been run.
//
// The provided Context must be non-nil. If the context is canceled before
// the handshake is complete, the handshake is interrupted and an error is returned.
// Once the handshake has completed, cancellation of the context will not affect the
// connection.
//
// Most uses of this package need not call HandshakeContext explicitly: the
// first Read or Write will call it automatically.
func (c *Conn) HandshakeContext(ctx context.Context) error {
// Delegate to unexported method for named return
// without confusing documented signature.
return c.handshakeContext(ctx)
}
func (c *Conn) handshakeContext(ctx context.Context) (ret error) {
handshakeCtx, cancel := context.WithCancel(ctx)
// Note: defer this before starting the "interrupter" goroutine
// so that we can tell the difference between the input being canceled and
// this cancellation. In the former case, we need to close the connection.
defer cancel()
// Start the "interrupter" goroutine, if this context might be canceled.
// (The background context cannot).
//
// The interrupter goroutine waits for the input context to be done and
// closes the connection if this happens before the function returns.
if ctx.Done() != nil {
done := make(chan struct{})
interruptRes := make(chan error, 1)
defer func() {
close(done)
if ctxErr := <-interruptRes; ctxErr != nil {
// Return context error to user.
ret = ctxErr
}
}()
go func() {
select {
case <-handshakeCtx.Done():
// Close the connection, discarding the error
_ = c.conn.Close()
interruptRes <- handshakeCtx.Err()
case <-done:
interruptRes <- nil
}
}()
}
c.handshakeMutex.Lock() c.handshakeMutex.Lock()
defer c.handshakeMutex.Unlock() defer c.handshakeMutex.Unlock()
@ -1442,7 +1388,7 @@ func (c *Conn) handshakeContext(ctx context.Context) (ret error) {
c.in.Lock() c.in.Lock()
defer c.in.Unlock() defer c.in.Unlock()
c.handshakeErr = c.handshakeFn(handshakeCtx) c.handshakeErr = c.handshakeFn()
if c.handshakeErr == nil { if c.handshakeErr == nil {
c.handshakes++ c.handshakes++
} else { } else {

View file

@ -6,7 +6,6 @@ package tls
import ( import (
"bytes" "bytes"
"context"
"crypto" "crypto"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/ed25519" "crypto/ed25519"
@ -25,7 +24,6 @@ import (
type clientHandshakeState struct { type clientHandshakeState struct {
c *Conn c *Conn
ctx context.Context
serverHello *serverHelloMsg serverHello *serverHelloMsg
hello *clientHelloMsg hello *clientHelloMsg
suite *cipherSuite suite *cipherSuite
@ -136,7 +134,7 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) {
return hello, params, nil return hello, params, nil
} }
func (c *Conn) clientHandshake(ctx context.Context) (err error) { func (c *Conn) clientHandshake() (err error) {
if c.config == nil { if c.config == nil {
c.config = defaultConfig() c.config = defaultConfig()
} }
@ -200,7 +198,6 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) {
if c.vers == VersionTLS13 { if c.vers == VersionTLS13 {
hs := &clientHandshakeStateTLS13{ hs := &clientHandshakeStateTLS13{
c: c, c: c,
ctx: ctx,
serverHello: serverHello, serverHello: serverHello,
hello: hello, hello: hello,
ecdheParams: ecdheParams, ecdheParams: ecdheParams,
@ -215,7 +212,6 @@ func (c *Conn) clientHandshake(ctx context.Context) (err error) {
hs := &clientHandshakeState{ hs := &clientHandshakeState{
c: c, c: c,
ctx: ctx,
serverHello: serverHello, serverHello: serverHello,
hello: hello, hello: hello,
session: session, session: session,
@ -544,7 +540,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
certRequested = true certRequested = true
hs.finishedHash.Write(certReq.marshal()) hs.finishedHash.Write(certReq.marshal())
cri := certificateRequestInfoFromMsg(hs.ctx, c.vers, certReq) cri := certificateRequestInfoFromMsg(c.vers, certReq)
if chainToSend, err = c.getClientCertificate(cri); err != nil { if chainToSend, err = c.getClientCertificate(cri); err != nil {
c.sendAlert(alertInternalError) c.sendAlert(alertInternalError)
return err return err
@ -884,11 +880,10 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
// certificateRequestInfoFromMsg generates a CertificateRequestInfo from a TLS // certificateRequestInfoFromMsg generates a CertificateRequestInfo from a TLS
// <= 1.2 CertificateRequest, making an effort to fill in missing information. // <= 1.2 CertificateRequest, making an effort to fill in missing information.
func certificateRequestInfoFromMsg(ctx context.Context, vers uint16, certReq *certificateRequestMsg) *CertificateRequestInfo { func certificateRequestInfoFromMsg(vers uint16, certReq *certificateRequestMsg) *CertificateRequestInfo {
cri := &CertificateRequestInfo{ cri := &CertificateRequestInfo{
AcceptableCAs: certReq.certificateAuthorities, AcceptableCAs: certReq.certificateAuthorities,
Version: vers, Version: vers,
ctx: ctx,
} }
var rsaAvail, ecAvail bool var rsaAvail, ecAvail bool

View file

@ -6,7 +6,6 @@ package tls
import ( import (
"bytes" "bytes"
"context"
"crypto/rsa" "crypto/rsa"
"crypto/x509" "crypto/x509"
"encoding/base64" "encoding/base64"
@ -21,7 +20,6 @@ import (
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"reflect" "reflect"
"runtime"
"strconv" "strconv"
"strings" "strings"
"testing" "testing"
@ -2513,37 +2511,3 @@ func testResumptionKeepsOCSPAndSCT(t *testing.T, ver uint16) {
serverConfig.Certificates[0].SignedCertificateTimestamps, ccs.SignedCertificateTimestamps) serverConfig.Certificates[0].SignedCertificateTimestamps, ccs.SignedCertificateTimestamps)
} }
} }
func TestClientHandshakeContextCancellation(t *testing.T) {
c, s := localPipe(t)
serverConfig := testConfig.Clone()
serverErr := make(chan error, 1)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() {
defer close(serverErr)
defer s.Close()
conn := Server(s, serverConfig)
_, err := conn.readClientHello(ctx)
cancel()
serverErr <- err
}()
cli := Client(c, testConfig)
err := cli.HandshakeContext(ctx)
if err == nil {
t.Fatal("Client handshake did not error when the context was canceled")
}
if err != context.Canceled {
t.Errorf("Unexpected client handshake error: %v", err)
}
if err := <-serverErr; err != nil {
t.Errorf("Unexpected server error: %v", err)
}
if runtime.GOARCH == "wasm" {
t.Skip("conn.Close does not error as expected when called multiple times on WASM")
}
err = cli.Close()
if err == nil {
t.Error("Client connection was not closed when the context was canceled")
}
}

View file

@ -6,7 +6,6 @@ package tls
import ( import (
"bytes" "bytes"
"context"
"crypto" "crypto"
"crypto/hmac" "crypto/hmac"
"crypto/rsa" "crypto/rsa"
@ -18,7 +17,6 @@ import (
type clientHandshakeStateTLS13 struct { type clientHandshakeStateTLS13 struct {
c *Conn c *Conn
ctx context.Context
serverHello *serverHelloMsg serverHello *serverHelloMsg
hello *clientHelloMsg hello *clientHelloMsg
ecdheParams ecdheParameters ecdheParams ecdheParameters
@ -557,7 +555,6 @@ func (hs *clientHandshakeStateTLS13) sendClientCertificate() error {
AcceptableCAs: hs.certReq.certificateAuthorities, AcceptableCAs: hs.certReq.certificateAuthorities,
SignatureSchemes: hs.certReq.supportedSignatureAlgorithms, SignatureSchemes: hs.certReq.supportedSignatureAlgorithms,
Version: c.vers, Version: c.vers,
ctx: hs.ctx,
}) })
if err != nil { if err != nil {
return err return err

View file

@ -5,7 +5,6 @@
package tls package tls
import ( import (
"context"
"crypto" "crypto"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/ed25519" "crypto/ed25519"
@ -24,7 +23,6 @@ import (
// It's discarded once the handshake has completed. // It's discarded once the handshake has completed.
type serverHandshakeState struct { type serverHandshakeState struct {
c *Conn c *Conn
ctx context.Context
clientHello *clientHelloMsg clientHello *clientHelloMsg
hello *serverHelloMsg hello *serverHelloMsg
suite *cipherSuite suite *cipherSuite
@ -39,8 +37,8 @@ type serverHandshakeState struct {
} }
// serverHandshake performs a TLS handshake as a server. // serverHandshake performs a TLS handshake as a server.
func (c *Conn) serverHandshake(ctx context.Context) error { func (c *Conn) serverHandshake() error {
clientHello, err := c.readClientHello(ctx) clientHello, err := c.readClientHello()
if err != nil { if err != nil {
return err return err
} }
@ -48,7 +46,6 @@ func (c *Conn) serverHandshake(ctx context.Context) error {
if c.vers == VersionTLS13 { if c.vers == VersionTLS13 {
hs := serverHandshakeStateTLS13{ hs := serverHandshakeStateTLS13{
c: c, c: c,
ctx: ctx,
clientHello: clientHello, clientHello: clientHello,
} }
return hs.handshake() return hs.handshake()
@ -56,7 +53,6 @@ func (c *Conn) serverHandshake(ctx context.Context) error {
hs := serverHandshakeState{ hs := serverHandshakeState{
c: c, c: c,
ctx: ctx,
clientHello: clientHello, clientHello: clientHello,
} }
return hs.handshake() return hs.handshake()
@ -128,7 +124,7 @@ func (hs *serverHandshakeState) handshake() error {
} }
// readClientHello reads a ClientHello message and selects the protocol version. // readClientHello reads a ClientHello message and selects the protocol version.
func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, error) { func (c *Conn) readClientHello() (*clientHelloMsg, error) {
msg, err := c.readHandshake() msg, err := c.readHandshake()
if err != nil { if err != nil {
return nil, err return nil, err
@ -142,7 +138,7 @@ func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, error) {
var configForClient *Config var configForClient *Config
originalConfig := c.config originalConfig := c.config
if c.config.GetConfigForClient != nil { if c.config.GetConfigForClient != nil {
chi := clientHelloInfo(ctx, c, clientHello) chi := clientHelloInfo(c, clientHello)
if configForClient, err = c.config.GetConfigForClient(chi); err != nil { if configForClient, err = c.config.GetConfigForClient(chi); err != nil {
c.sendAlert(alertInternalError) c.sendAlert(alertInternalError)
return nil, err return nil, err
@ -224,7 +220,7 @@ func (hs *serverHandshakeState) processClientHello() error {
} }
} }
hs.cert, err = c.config.getCertificate(clientHelloInfo(hs.ctx, c, hs.clientHello)) hs.cert, err = c.config.getCertificate(clientHelloInfo(c, hs.clientHello))
if err != nil { if err != nil {
if err == errNoCertificates { if err == errNoCertificates {
c.sendAlert(alertUnrecognizedName) c.sendAlert(alertUnrecognizedName)
@ -832,7 +828,7 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error {
return nil return nil
} }
func clientHelloInfo(ctx context.Context, c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo { func clientHelloInfo(c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo {
supportedVersions := clientHello.supportedVersions supportedVersions := clientHello.supportedVersions
if len(clientHello.supportedVersions) == 0 { if len(clientHello.supportedVersions) == 0 {
supportedVersions = supportedVersionsFromMax(clientHello.vers) supportedVersions = supportedVersionsFromMax(clientHello.vers)
@ -848,6 +844,5 @@ func clientHelloInfo(ctx context.Context, c *Conn, clientHello *clientHelloMsg)
SupportedVersions: supportedVersions, SupportedVersions: supportedVersions,
Conn: c.conn, Conn: c.conn,
config: c.config, config: c.config,
ctx: ctx,
} }
} }

View file

@ -6,7 +6,6 @@ package tls
import ( import (
"bytes" "bytes"
"context"
"crypto" "crypto"
"crypto/elliptic" "crypto/elliptic"
"crypto/x509" "crypto/x509"
@ -18,7 +17,6 @@ import (
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime"
"strings" "strings"
"testing" "testing"
"time" "time"
@ -40,12 +38,10 @@ func testClientHelloFailure(t *testing.T, serverConfig *Config, m handshakeMessa
cli.writeRecord(recordTypeHandshake, m.marshal()) cli.writeRecord(recordTypeHandshake, m.marshal())
c.Close() c.Close()
}() }()
ctx := context.Background()
conn := Server(s, serverConfig) conn := Server(s, serverConfig)
ch, err := conn.readClientHello(ctx) ch, err := conn.readClientHello()
hs := serverHandshakeState{ hs := serverHandshakeState{
c: conn, c: conn,
ctx: ctx,
clientHello: ch, clientHello: ch,
} }
if err == nil { if err == nil {
@ -1425,11 +1421,9 @@ func TestSNIGivenOnFailure(t *testing.T) {
c.Close() c.Close()
}() }()
conn := Server(s, serverConfig) conn := Server(s, serverConfig)
ctx := context.Background() ch, err := conn.readClientHello()
ch, err := conn.readClientHello(ctx)
hs := serverHandshakeState{ hs := serverHandshakeState{
c: conn, c: conn,
ctx: ctx,
clientHello: ch, clientHello: ch,
} }
if err == nil { if err == nil {
@ -1683,46 +1677,6 @@ func TestMultipleCertificates(t *testing.T) {
} }
} }
func TestServerHandshakeContextCancellation(t *testing.T) {
c, s := localPipe(t)
clientConfig := testConfig.Clone()
clientErr := make(chan error, 1)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() {
defer close(clientErr)
defer c.Close()
clientHello := &clientHelloMsg{
vers: VersionTLS10,
random: make([]byte, 32),
cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
compressionMethods: []uint8{compressionNone},
}
cli := Client(c, clientConfig)
_, err := cli.writeRecord(recordTypeHandshake, clientHello.marshal())
cancel()
clientErr <- err
}()
conn := Server(s, testConfig)
err := conn.HandshakeContext(ctx)
if err == nil {
t.Fatal("Server handshake did not error when the context was canceled")
}
if err != context.Canceled {
t.Errorf("Unexpected server handshake error: %v", err)
}
if err := <-clientErr; err != nil {
t.Errorf("Unexpected client error: %v", err)
}
if runtime.GOARCH == "wasm" {
t.Skip("conn.Close does not error as expected when called multiple times on WASM")
}
err = conn.Close()
if err == nil {
t.Error("Server connection was not closed when the context was canceled")
}
}
func TestAESCipherReordering(t *testing.T) { func TestAESCipherReordering(t *testing.T) {
currentAESSupport := hasAESGCMHardwareSupport currentAESSupport := hasAESGCMHardwareSupport
defer func() { hasAESGCMHardwareSupport = currentAESSupport; initDefaultCipherSuites() }() defer func() { hasAESGCMHardwareSupport = currentAESSupport; initDefaultCipherSuites() }()

View file

@ -6,7 +6,6 @@ package tls
import ( import (
"bytes" "bytes"
"context"
"crypto" "crypto"
"crypto/hmac" "crypto/hmac"
"crypto/rsa" "crypto/rsa"
@ -24,7 +23,6 @@ const maxClientPSKIdentities = 5
type serverHandshakeStateTLS13 struct { type serverHandshakeStateTLS13 struct {
c *Conn c *Conn
ctx context.Context
clientHello *clientHelloMsg clientHello *clientHelloMsg
hello *serverHelloMsg hello *serverHelloMsg
sentDummyCCS bool sentDummyCCS bool
@ -376,7 +374,7 @@ func (hs *serverHandshakeStateTLS13) pickCertificate() error {
return c.sendAlert(alertMissingExtension) return c.sendAlert(alertMissingExtension)
} }
certificate, err := c.config.getCertificate(clientHelloInfo(hs.ctx, c, hs.clientHello)) certificate, err := c.config.getCertificate(clientHelloInfo(c, hs.clientHello))
if err != nil { if err != nil {
if err == errNoCertificates { if err == errNoCertificates {
c.sendAlert(alertUnrecognizedName) c.sendAlert(alertUnrecognizedName)

View file

@ -25,6 +25,7 @@ import (
"net" "net"
"os" "os"
"strings" "strings"
"time"
) )
// Server returns a new TLS server side connection // Server returns a new TLS server side connection
@ -115,16 +116,28 @@ func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*
} }
func dial(ctx context.Context, netDialer *net.Dialer, network, addr string, config *Config) (*Conn, error) { func dial(ctx context.Context, netDialer *net.Dialer, network, addr string, config *Config) (*Conn, error) {
if netDialer.Timeout != 0 { // We want the Timeout and Deadline values from dialer to cover the
var cancel context.CancelFunc // whole process: TCP connection and TLS handshake. This means that we
ctx, cancel = context.WithTimeout(ctx, netDialer.Timeout) // also need to start our own timers now.
defer cancel() timeout := netDialer.Timeout
}
if !netDialer.Deadline.IsZero() { if !netDialer.Deadline.IsZero() {
var cancel context.CancelFunc deadlineTimeout := time.Until(netDialer.Deadline)
ctx, cancel = context.WithDeadline(ctx, netDialer.Deadline) if timeout == 0 || deadlineTimeout < timeout {
defer cancel() timeout = deadlineTimeout
}
}
// hsErrCh is non-nil if we might not wait for Handshake to complete.
var hsErrCh chan error
if timeout != 0 || ctx.Done() != nil {
hsErrCh = make(chan error, 2)
}
if timeout != 0 {
timer := time.AfterFunc(timeout, func() {
hsErrCh <- timeoutError{}
})
defer timer.Stop()
} }
rawConn, err := netDialer.DialContext(ctx, network, addr) rawConn, err := netDialer.DialContext(ctx, network, addr)
@ -151,10 +164,34 @@ func dial(ctx context.Context, netDialer *net.Dialer, network, addr string, conf
} }
conn := Client(rawConn, config) conn := Client(rawConn, config)
if err := conn.HandshakeContext(ctx); err != nil {
if hsErrCh == nil {
err = conn.Handshake()
} else {
go func() {
hsErrCh <- conn.Handshake()
}()
select {
case <-ctx.Done():
err = ctx.Err()
case err = <-hsErrCh:
if err != nil {
// If the error was due to the context
// closing, prefer the context's error, rather
// than some random network teardown error.
if e := ctx.Err(); e != nil {
err = e
}
}
}
}
if err != nil {
rawConn.Close() rawConn.Close()
return nil, err return nil, err
} }
return conn, nil return conn, nil
} }

View file

@ -1141,7 +1141,7 @@ func (db *DB) connectionOpener(ctx context.Context) {
// Open one new connection // Open one new connection
func (db *DB) openNewConnection(ctx context.Context) { func (db *DB) openNewConnection(ctx context.Context) {
// maybeOpenNewConnctions has already executed db.numOpen++ before it sent // maybeOpenNewConnections has already executed db.numOpen++ before it sent
// on db.openerCh. This function must execute db.numOpen-- if the // on db.openerCh. This function must execute db.numOpen-- if the
// connection fails or is closed before returning. // connection fails or is closed before returning.
ci, err := db.connector.Connect(ctx) ci, err := db.connector.Connect(ctx)

View file

@ -22,7 +22,12 @@ func TestDwarf5Ranges(t *testing.T) {
if err := d.AddSection(".debug_rnglists", rngLists); err != nil { if err := d.AddSection(".debug_rnglists", rngLists); err != nil {
t.Fatal(err) t.Fatal(err)
} }
ret, err := d.dwarf5Ranges(nil, 0x5fbd, 0xc, [][2]uint64{}) u := &unit{
asize: 8,
vers: 5,
is64: true,
}
ret, err := d.dwarf5Ranges(u, nil, 0x5fbd, 0xc, [][2]uint64{})
if err != nil { if err != nil {
t.Fatalf("could not read rnglist: %v", err) t.Fatalf("could not read rnglist: %v", err)
} }

View file

@ -423,6 +423,47 @@ func (b *buf) entry(cu *Entry, atab abbrevTable, ubase Offset, vers int) *Entry
Children: a.children, Children: a.children,
Field: make([]Field, len(a.field)), Field: make([]Field, len(a.field)),
} }
// If we are currently parsing the compilation unit,
// we can't evaluate Addrx or Strx until we've seen the
// relevant base entry.
type delayed struct {
idx int
off uint64
fmt format
}
var delay []delayed
resolveStrx := func(strBase, off uint64) string {
off += strBase
if uint64(int(off)) != off {
b.error("DW_FORM_strx offset out of range")
}
b1 := makeBuf(b.dwarf, b.format, "str_offsets", 0, b.dwarf.strOffsets)
b1.skip(int(off))
is64, _ := b.format.dwarf64()
if is64 {
off = b1.uint64()
} else {
off = uint64(b1.uint32())
}
if b1.err != nil {
b.err = b1.err
return ""
}
if uint64(int(off)) != off {
b.error("DW_FORM_strx indirect offset out of range")
}
b1 = makeBuf(b.dwarf, b.format, "str", 0, b.dwarf.str)
b1.skip(int(off))
val := b1.string()
if b1.err != nil {
b.err = b1.err
}
return val
}
for i := range e.Field { for i := range e.Field {
e.Field[i].Attr = a.field[i].attr e.Field[i].Attr = a.field[i].attr
e.Field[i].Class = a.field[i].class e.Field[i].Class = a.field[i].class
@ -467,10 +508,13 @@ func (b *buf) entry(cu *Entry, atab abbrevTable, ubase Offset, vers int) *Entry
var addrBase int64 var addrBase int64
if cu != nil { if cu != nil {
addrBase, _ = cu.Val(AttrAddrBase).(int64) addrBase, _ = cu.Val(AttrAddrBase).(int64)
} else if a.tag == TagCompileUnit {
delay = append(delay, delayed{i, off, formAddrx})
break
} }
var err error var err error
val, err = b.dwarf.debugAddr(uint64(addrBase), off) val, err = b.dwarf.debugAddr(b.format, uint64(addrBase), off)
if err != nil { if err != nil {
if b.err == nil { if b.err == nil {
b.err = err b.err = err
@ -611,38 +655,16 @@ func (b *buf) entry(cu *Entry, atab abbrevTable, ubase Offset, vers int) *Entry
// compilation unit. This won't work if the // compilation unit. This won't work if the
// program uses Reader.Seek to skip over the // program uses Reader.Seek to skip over the
// unit. Not much we can do about that. // unit. Not much we can do about that.
var strBase int64
if cu != nil { if cu != nil {
cuOff, ok := cu.Val(AttrStrOffsetsBase).(int64) strBase, _ = cu.Val(AttrStrOffsetsBase).(int64)
if ok { } else if a.tag == TagCompileUnit {
off += uint64(cuOff) delay = append(delay, delayed{i, off, formStrx})
} break
} }
if uint64(int(off)) != off { val = resolveStrx(uint64(strBase), off)
b.error("DW_FORM_strx offset out of range")
}
b1 := makeBuf(b.dwarf, b.format, "str_offsets", 0, b.dwarf.strOffsets)
b1.skip(int(off))
if is64 {
off = b1.uint64()
} else {
off = uint64(b1.uint32())
}
if b1.err != nil {
b.err = b1.err
return nil
}
if uint64(int(off)) != off {
b.error("DW_FORM_strx indirect offset out of range")
}
b1 = makeBuf(b.dwarf, b.format, "str", 0, b.dwarf.str)
b1.skip(int(off))
val = b1.string()
if b1.err != nil {
b.err = b1.err
return nil
}
case formStrpSup: case formStrpSup:
is64, known := b.format.dwarf64() is64, known := b.format.dwarf64()
if !known { if !known {
@ -689,11 +711,32 @@ func (b *buf) entry(cu *Entry, atab abbrevTable, ubase Offset, vers int) *Entry
case formRnglistx: case formRnglistx:
val = b.uint() val = b.uint()
} }
e.Field[i].Val = val e.Field[i].Val = val
} }
if b.err != nil { if b.err != nil {
return nil return nil
} }
for _, del := range delay {
switch del.fmt {
case formAddrx:
addrBase, _ := e.Val(AttrAddrBase).(int64)
val, err := b.dwarf.debugAddr(b.format, uint64(addrBase), del.off)
if err != nil {
b.err = err
return nil
}
e.Field[del.idx].Val = val
case formStrx:
strBase, _ := e.Val(AttrStrOffsetsBase).(int64)
e.Field[del.idx].Val = resolveStrx(uint64(strBase), del.off)
if b.err != nil {
return nil
}
}
}
return e return e
} }
@ -877,6 +920,7 @@ func (r *Reader) SeekPC(pc uint64) (*Entry, error) {
r.err = nil r.err = nil
r.lastChildren = false r.lastChildren = false
r.unit = unit r.unit = unit
r.cu = nil
u := &r.d.unit[unit] u := &r.d.unit[unit]
r.b = makeBuf(r.d, u, "info", u.off, u.data) r.b = makeBuf(r.d, u, "info", u.off, u.data)
e, err := r.Next() e, err := r.Next()
@ -946,7 +990,7 @@ func (d *Data) Ranges(e *Entry) ([][2]uint64, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return d.dwarf5Ranges(cu, base, ranges, ret) return d.dwarf5Ranges(u, cu, base, ranges, ret)
case ClassRngList: case ClassRngList:
// TODO: support DW_FORM_rnglistx // TODO: support DW_FORM_rnglistx
@ -1023,13 +1067,13 @@ func (d *Data) dwarf2Ranges(u *unit, base uint64, ranges int64, ret [][2]uint64)
// dwarf5Ranges interpets a debug_rnglists sequence, see DWARFv5 section // dwarf5Ranges interpets a debug_rnglists sequence, see DWARFv5 section
// 2.17.3 (page 53). // 2.17.3 (page 53).
func (d *Data) dwarf5Ranges(cu *Entry, base uint64, ranges int64, ret [][2]uint64) ([][2]uint64, error) { func (d *Data) dwarf5Ranges(u *unit, cu *Entry, base uint64, ranges int64, ret [][2]uint64) ([][2]uint64, error) {
var addrBase int64 var addrBase int64
if cu != nil { if cu != nil {
addrBase, _ = cu.Val(AttrAddrBase).(int64) addrBase, _ = cu.Val(AttrAddrBase).(int64)
} }
buf := makeBuf(d, d.rngLists, "rnglists", 0, d.rngLists.data) buf := makeBuf(d, u, "rnglists", 0, d.rngLists)
buf.skip(int(ranges)) buf.skip(int(ranges))
for { for {
opcode := buf.uint8() opcode := buf.uint8()
@ -1043,7 +1087,7 @@ func (d *Data) dwarf5Ranges(cu *Entry, base uint64, ranges int64, ret [][2]uint6
case rleBaseAddressx: case rleBaseAddressx:
baseIdx := buf.uint() baseIdx := buf.uint()
var err error var err error
base, err = d.debugAddr(uint64(addrBase), baseIdx) base, err = d.debugAddr(u, uint64(addrBase), baseIdx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1052,11 +1096,11 @@ func (d *Data) dwarf5Ranges(cu *Entry, base uint64, ranges int64, ret [][2]uint6
startIdx := buf.uint() startIdx := buf.uint()
endIdx := buf.uint() endIdx := buf.uint()
start, err := d.debugAddr(uint64(addrBase), startIdx) start, err := d.debugAddr(u, uint64(addrBase), startIdx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
end, err := d.debugAddr(uint64(addrBase), endIdx) end, err := d.debugAddr(u, uint64(addrBase), endIdx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1065,7 +1109,7 @@ func (d *Data) dwarf5Ranges(cu *Entry, base uint64, ranges int64, ret [][2]uint6
case rleStartxLength: case rleStartxLength:
startIdx := buf.uint() startIdx := buf.uint()
len := buf.uint() len := buf.uint()
start, err := d.debugAddr(uint64(addrBase), startIdx) start, err := d.debugAddr(u, uint64(addrBase), startIdx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1093,19 +1137,18 @@ func (d *Data) dwarf5Ranges(cu *Entry, base uint64, ranges int64, ret [][2]uint6
} }
// debugAddr returns the address at idx in debug_addr // debugAddr returns the address at idx in debug_addr
func (d *Data) debugAddr(addrBase, idx uint64) (uint64, error) { func (d *Data) debugAddr(format dataFormat, addrBase, idx uint64) (uint64, error) {
off := idx*uint64(d.addr.addrsize()) + addrBase off := idx*uint64(format.addrsize()) + addrBase
if uint64(int(off)) != off { if uint64(int(off)) != off {
return 0, errors.New("offset out of range") return 0, errors.New("offset out of range")
} }
b := makeBuf(d, d.addr, "addr", 0, d.addr.data) b := makeBuf(d, format, "addr", 0, d.addr)
b.skip(int(off)) b.skip(int(off))
val := b.addr() val := b.addr()
if b.err != nil { if b.err != nil {
return 0, b.err return 0, b.err
} }
return val, nil return val, nil
} }

View file

@ -55,6 +55,20 @@ func TestReaderSeek(t *testing.T) {
{0x400611, nil}, {0x400611, nil},
} }
testRanges(t, "testdata/line-gcc.elf", want) testRanges(t, "testdata/line-gcc.elf", want)
want = []wantRange{
{0x401122, [][2]uint64{{0x401122, 0x401166}}},
{0x401165, [][2]uint64{{0x401122, 0x401166}}},
{0x401166, [][2]uint64{{0x401166, 0x401179}}},
}
testRanges(t, "testdata/line-gcc-dwarf5.elf", want)
want = []wantRange{
{0x401130, [][2]uint64{{0x401130, 0x40117e}}},
{0x40117d, [][2]uint64{{0x401130, 0x40117e}}},
{0x40117e, nil},
}
testRanges(t, "testdata/line-clang-dwarf5.elf", want)
} }
func TestRangesSection(t *testing.T) { func TestRangesSection(t *testing.T) {
@ -97,44 +111,72 @@ func testRanges(t *testing.T, name string, want []wantRange) {
} }
func TestReaderRanges(t *testing.T) { func TestReaderRanges(t *testing.T) {
d := elfData(t, "testdata/line-gcc.elf") type subprograms []struct {
subprograms := []struct {
name string name string
ranges [][2]uint64 ranges [][2]uint64
}
tests := []struct {
filename string
subprograms subprograms
}{ }{
{"f1", [][2]uint64{{0x40059d, 0x4005e7}}}, {
{"main", [][2]uint64{{0x4005e7, 0x400601}}}, "testdata/line-gcc.elf",
{"f2", [][2]uint64{{0x400601, 0x400611}}}, subprograms{
{"f1", [][2]uint64{{0x40059d, 0x4005e7}}},
{"main", [][2]uint64{{0x4005e7, 0x400601}}},
{"f2", [][2]uint64{{0x400601, 0x400611}}},
},
},
{
"testdata/line-gcc-dwarf5.elf",
subprograms{
{"main", [][2]uint64{{0x401147, 0x401166}}},
{"f1", [][2]uint64{{0x401122, 0x401147}}},
{"f2", [][2]uint64{{0x401166, 0x401179}}},
},
},
{
"testdata/line-clang-dwarf5.elf",
subprograms{
{"main", [][2]uint64{{0x401130, 0x401144}}},
{"f1", [][2]uint64{{0x401150, 0x40117e}}},
{"f2", [][2]uint64{{0x401180, 0x401197}}},
},
},
} }
r := d.Reader() for _, test := range tests {
i := 0 d := elfData(t, test.filename)
for entry, err := r.Next(); entry != nil && err == nil; entry, err = r.Next() { subprograms := test.subprograms
if entry.Tag != TagSubprogram {
continue r := d.Reader()
i := 0
for entry, err := r.Next(); entry != nil && err == nil; entry, err = r.Next() {
if entry.Tag != TagSubprogram {
continue
}
if i > len(subprograms) {
t.Fatalf("%s: too many subprograms (expected at most %d)", test.filename, i)
}
if got := entry.Val(AttrName).(string); got != subprograms[i].name {
t.Errorf("%s: subprogram %d name is %s, expected %s", test.filename, i, got, subprograms[i].name)
}
ranges, err := d.Ranges(entry)
if err != nil {
t.Errorf("%s: subprogram %d: %v", test.filename, i, err)
continue
}
if !reflect.DeepEqual(ranges, subprograms[i].ranges) {
t.Errorf("%s: subprogram %d ranges are %x, expected %x", test.filename, i, ranges, subprograms[i].ranges)
}
i++
} }
if i > len(subprograms) { if i < len(subprograms) {
t.Fatalf("too many subprograms (expected at most %d)", i) t.Errorf("%s: saw only %d subprograms, expected %d", test.filename, i, len(subprograms))
} }
if got := entry.Val(AttrName).(string); got != subprograms[i].name {
t.Errorf("subprogram %d name is %s, expected %s", i, got, subprograms[i].name)
}
ranges, err := d.Ranges(entry)
if err != nil {
t.Errorf("subprogram %d: %v", i, err)
continue
}
if !reflect.DeepEqual(ranges, subprograms[i].ranges) {
t.Errorf("subprogram %d ranges are %x, expected %x", i, ranges, subprograms[i].ranges)
}
i++
}
if i < len(subprograms) {
t.Errorf("saw only %d subprograms, expected %d", i, len(subprograms))
} }
} }

View file

@ -26,10 +26,10 @@ type Data struct {
str []byte str []byte
// New sections added in DWARF 5. // New sections added in DWARF 5.
addr *debugAddr addr []byte
lineStr []byte lineStr []byte
strOffsets []byte strOffsets []byte
rngLists *rngLists rngLists []byte
// parsed data // parsed data
abbrevCache map[uint64]abbrevTable abbrevCache map[uint64]abbrevTable
@ -40,21 +40,6 @@ type Data struct {
unit []unit unit []unit
} }
// rngLists represents the contents of a debug_rnglists section (DWARFv5).
type rngLists struct {
is64 bool
asize uint8
data []byte
ver uint16
}
// debugAddr represents the contents of a debug_addr section (DWARFv5).
type debugAddr struct {
is64 bool
asize uint8
data []byte
}
var errSegmentSelector = errors.New("non-zero segment_selector size not supported") var errSegmentSelector = errors.New("non-zero segment_selector size not supported")
// New returns a new Data object initialized from the given parameters. // New returns a new Data object initialized from the given parameters.
@ -132,76 +117,14 @@ func (d *Data) AddSection(name string, contents []byte) error {
var err error var err error
switch name { switch name {
case ".debug_addr": case ".debug_addr":
d.addr, err = d.parseAddrHeader(contents) d.addr = contents
case ".debug_line_str": case ".debug_line_str":
d.lineStr = contents d.lineStr = contents
case ".debug_str_offsets": case ".debug_str_offsets":
d.strOffsets = contents d.strOffsets = contents
case ".debug_rnglists": case ".debug_rnglists":
d.rngLists, err = d.parseRngListsHeader(contents) d.rngLists = contents
} }
// Just ignore names that we don't yet support. // Just ignore names that we don't yet support.
return err return err
} }
// parseRngListsHeader reads the header of a debug_rnglists section, see
// DWARFv5 section 7.28 (page 242).
func (d *Data) parseRngListsHeader(bytes []byte) (*rngLists, error) {
rngLists := &rngLists{data: bytes}
buf := makeBuf(d, unknownFormat{}, "rnglists", 0, bytes)
_, rngLists.is64 = buf.unitLength()
rngLists.ver = buf.uint16() // version
rngLists.asize = buf.uint8()
segsize := buf.uint8()
if segsize != 0 {
return nil, errSegmentSelector
}
// Header fields not read: offset_entry_count, offset table
return rngLists, nil
}
func (rngLists *rngLists) version() int {
return int(rngLists.ver)
}
func (rngLists *rngLists) dwarf64() (bool, bool) {
return rngLists.is64, true
}
func (rngLists *rngLists) addrsize() int {
return int(rngLists.asize)
}
// parseAddrHeader reads the header of a debug_addr section, see DWARFv5
// section 7.27 (page 241).
func (d *Data) parseAddrHeader(bytes []byte) (*debugAddr, error) {
addr := &debugAddr{data: bytes}
buf := makeBuf(d, unknownFormat{}, "addr", 0, bytes)
_, addr.is64 = buf.unitLength()
addr.asize = buf.uint8()
segsize := buf.uint8()
if segsize != 0 {
return nil, errSegmentSelector
}
return addr, nil
}
func (addr *debugAddr) version() int {
return 5
}
func (addr *debugAddr) dwarf64() (bool, bool) {
return addr.is64, true
}
func (addr *debugAddr) addrsize() int {
return int(addr.asize)
}

Binary file not shown.

Binary file not shown.

View file

@ -4,7 +4,7 @@ go 1.16
require ( require (
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d golang.org/x/net v0.0.0-20201209123823-ac852fbbde11
golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect
golang.org/x/text v0.3.4 // indirect golang.org/x/text v0.3.4 // indirect
) )

View file

@ -1,15 +1,15 @@
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d h1:dOiJ2n2cMwGLce/74I/QHMbnpk5GfY7InR8rczoMqRM= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11 h1:lwlPPsmjDKK0J6eG6xDWd5XPehI0R024zxjDnw3esPA=
golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88 h1:KmZPnMocC93w341XZp26yTJg8Za7lhb2KhkYmixoeso= golang.org/x/sys v0.0.0-20201204225414-ed752295db88 h1:KmZPnMocC93w341XZp26yTJg8Za7lhb2KhkYmixoeso=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=

View file

@ -10,6 +10,7 @@ package build
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"go/token"
"internal/testenv" "internal/testenv"
"io/fs" "io/fs"
"os" "os"
@ -162,6 +163,9 @@ var depsRules = `
< os < os
< os/signal; < os/signal;
io/fs
< embed;
unicode, fmt !< os, os/signal; unicode, fmt !< os, os/signal;
os/signal, STR os/signal, STR
@ -602,6 +606,7 @@ func findImports(pkg string) ([]string, error) {
} }
var imports []string var imports []string
var haveImport = map[string]bool{} var haveImport = map[string]bool{}
fset := token.NewFileSet()
for _, file := range files { for _, file := range files {
name := file.Name() name := file.Name()
if name == "slice_go14.go" || name == "slice_go18.go" { if name == "slice_go14.go" || name == "slice_go18.go" {
@ -611,8 +616,10 @@ func findImports(pkg string) ([]string, error) {
if !strings.HasSuffix(name, ".go") || strings.HasSuffix(name, "_test.go") { if !strings.HasSuffix(name, ".go") || strings.HasSuffix(name, "_test.go") {
continue continue
} }
var info fileInfo info := fileInfo{
info.name = filepath.Join(dir, name) name: filepath.Join(dir, name),
fset: fset,
}
f, err := os.Open(info.name) f, err := os.Open(info.name)
if err != nil { if err != nil {
return nil, err return nil, err
@ -840,3 +847,22 @@ func TestStdlibLowercase(t *testing.T) {
} }
} }
} }
// TestFindImports tests that findImports works. See #43249.
func TestFindImports(t *testing.T) {
imports, err := findImports("go/build")
if err != nil {
t.Fatal(err)
}
t.Logf("go/build imports %q", imports)
want := []string{"bytes", "os", "path/filepath", "strings"}
wantLoop:
for _, w := range want {
for _, imp := range imports {
if imp == w {
continue wantLoop
}
}
t.Errorf("expected to find %q in import list", w)
}
}

View file

@ -33,6 +33,10 @@ func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind {
case 1: case 1:
check.expr(x, e.Args[0]) check.expr(x, e.Args[0])
if x.mode != invalid { if x.mode != invalid {
if e.Ellipsis.IsValid() {
check.errorf(e.Args[0], _BadDotDotDotSyntax, "invalid use of ... in conversion to %s", T)
break
}
check.conversion(x, T) check.conversion(x, T)
} }
default: default:

View file

@ -1207,6 +1207,16 @@ const (
// } // }
_InvalidTypeSwitch _InvalidTypeSwitch
// _InvalidExprSwitch occurs when a switch expression is not comparable.
//
// Example:
// func _() {
// var a struct{ _ func() }
// switch a /* ERROR cannot switch on a */ {
// }
// }
_InvalidExprSwitch
/* control flow > select */ /* control flow > select */
// _InvalidSelectCase occurs when a select case is not a channel send or // _InvalidSelectCase occurs when a select case is not a channel send or

View file

@ -0,0 +1,43 @@
// Copyright 2020 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
type P *struct{}
func _() {
// want an error even if the switch is empty
var a struct{ _ func() }
switch a /* ERROR cannot switch on a */ {
}
switch a /* ERROR cannot switch on a */ {
case a: // no follow-on error here
}
// this is ok because f can be compared to nil
var f func()
switch f {
}
switch f {
case nil:
}
switch (func())(nil) {
case nil:
}
switch (func())(nil) {
case f /* ERROR cannot compare */ :
}
switch nil /* ERROR use of untyped nil in switch expression */ {
}
// this is ok
switch P(nil) {
case P(nil):
}
}

View file

@ -0,0 +1,16 @@
// Copyright 2020 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
var _ = int(0 /* ERROR invalid use of \.\.\. in conversion to int */ ...)
// test case from issue
type M []string
var (
x = []string{"a", "b"}
_ = M(x /* ERROR invalid use of \.\.\. in conversion to M */ ...)
)

View file

@ -528,6 +528,10 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
// By checking assignment of x to an invisible temporary // By checking assignment of x to an invisible temporary
// (as a compiler would), we get all the relevant checks. // (as a compiler would), we get all the relevant checks.
check.assignment(&x, nil, "switch expression") check.assignment(&x, nil, "switch expression")
if x.mode != invalid && !Comparable(x.typ) && !hasNil(x.typ) {
check.errorf(&x, _InvalidExprSwitch, "cannot switch on %s (%s is not comparable)", &x, x.typ)
x.mode = invalid
}
} else { } else {
// spec: "A missing switch expression is // spec: "A missing switch expression is
// equivalent to the boolean value true." // equivalent to the boolean value true."

View file

@ -14,6 +14,7 @@ import (
"io" "io"
"reflect" "reflect"
"strings" "strings"
"sync"
"testing" "testing"
"text/template" "text/template"
) )
@ -1706,3 +1707,72 @@ func TestIssue31810(t *testing.T) {
t.Errorf("%s got %q, expected %q", textCall, b.String(), "result") t.Errorf("%s got %q, expected %q", textCall, b.String(), "result")
} }
} }
// Issue 39807. There was a race applying escapeTemplate.
const raceText = `
{{- define "jstempl" -}}
var v = "v";
{{- end -}}
<script type="application/javascript">
{{ template "jstempl" $ }}
</script>
`
func TestEscapeRace(t *testing.T) {
tmpl := New("")
_, err := tmpl.New("templ.html").Parse(raceText)
if err != nil {
t.Fatal(err)
}
const count = 20
for i := 0; i < count; i++ {
_, err := tmpl.New(fmt.Sprintf("x%d.html", i)).Parse(`{{ template "templ.html" .}}`)
if err != nil {
t.Fatal(err)
}
}
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < count; j++ {
sub := tmpl.Lookup(fmt.Sprintf("x%d.html", j))
if err := sub.Execute(io.Discard, nil); err != nil {
t.Error(err)
}
}
}()
}
wg.Wait()
}
func TestRecursiveExecute(t *testing.T) {
tmpl := New("")
recur := func() (HTML, error) {
var sb strings.Builder
if err := tmpl.ExecuteTemplate(&sb, "subroutine", nil); err != nil {
t.Fatal(err)
}
return HTML(sb.String()), nil
}
m := FuncMap{
"recur": recur,
}
top, err := tmpl.New("x.html").Funcs(m).Parse(`{{recur}}`)
if err != nil {
t.Fatal(err)
}
_, err = tmpl.New("subroutine").Parse(`<a href="/x?p={{"'a<b'"}}">`)
if err != nil {
t.Fatal(err)
}
if err := top.Execute(io.Discard, nil); err != nil {
t.Fatal(err)
}
}

View file

@ -11,6 +11,7 @@ import (
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
"reflect"
"sync" "sync"
"text/template" "text/template"
"text/template/parse" "text/template/parse"
@ -26,7 +27,9 @@ type Template struct {
// template's in sync. // template's in sync.
text *template.Template text *template.Template
// The underlying template's parse tree, updated to be HTML-safe. // The underlying template's parse tree, updated to be HTML-safe.
Tree *parse.Tree Tree *parse.Tree
// The original functions, before wrapping.
funcMap FuncMap
*nameSpace // common to all associated templates *nameSpace // common to all associated templates
} }
@ -35,7 +38,7 @@ var escapeOK = fmt.Errorf("template escaped correctly")
// nameSpace is the data structure shared by all templates in an association. // nameSpace is the data structure shared by all templates in an association.
type nameSpace struct { type nameSpace struct {
mu sync.Mutex mu sync.RWMutex
set map[string]*Template set map[string]*Template
escaped bool escaped bool
esc escaper esc escaper
@ -45,8 +48,8 @@ type nameSpace struct {
// itself. // itself.
func (t *Template) Templates() []*Template { func (t *Template) Templates() []*Template {
ns := t.nameSpace ns := t.nameSpace
ns.mu.Lock() ns.mu.RLock()
defer ns.mu.Unlock() defer ns.mu.RUnlock()
// Return a slice so we don't expose the map. // Return a slice so we don't expose the map.
m := make([]*Template, 0, len(ns.set)) m := make([]*Template, 0, len(ns.set))
for _, v := range ns.set { for _, v := range ns.set {
@ -84,8 +87,8 @@ func (t *Template) checkCanParse() error {
if t == nil { if t == nil {
return nil return nil
} }
t.nameSpace.mu.Lock() t.nameSpace.mu.RLock()
defer t.nameSpace.mu.Unlock() defer t.nameSpace.mu.RUnlock()
if t.nameSpace.escaped { if t.nameSpace.escaped {
return fmt.Errorf("html/template: cannot Parse after Execute") return fmt.Errorf("html/template: cannot Parse after Execute")
} }
@ -94,6 +97,16 @@ func (t *Template) checkCanParse() error {
// escape escapes all associated templates. // escape escapes all associated templates.
func (t *Template) escape() error { func (t *Template) escape() error {
t.nameSpace.mu.RLock()
escapeErr := t.escapeErr
t.nameSpace.mu.RUnlock()
if escapeErr != nil {
if escapeErr == escapeOK {
return nil
}
return escapeErr
}
t.nameSpace.mu.Lock() t.nameSpace.mu.Lock()
defer t.nameSpace.mu.Unlock() defer t.nameSpace.mu.Unlock()
t.nameSpace.escaped = true t.nameSpace.escaped = true
@ -121,6 +134,8 @@ func (t *Template) Execute(wr io.Writer, data interface{}) error {
if err := t.escape(); err != nil { if err := t.escape(); err != nil {
return err return err
} }
t.nameSpace.mu.RLock()
defer t.nameSpace.mu.RUnlock()
return t.text.Execute(wr, data) return t.text.Execute(wr, data)
} }
@ -136,6 +151,8 @@ func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{})
if err != nil { if err != nil {
return err return err
} }
t.nameSpace.mu.RLock()
defer t.nameSpace.mu.RUnlock()
return tmpl.text.Execute(wr, data) return tmpl.text.Execute(wr, data)
} }
@ -143,13 +160,27 @@ func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{})
// is escaped, or returns an error if it cannot be. It returns the named // is escaped, or returns an error if it cannot be. It returns the named
// template. // template.
func (t *Template) lookupAndEscapeTemplate(name string) (tmpl *Template, err error) { func (t *Template) lookupAndEscapeTemplate(name string) (tmpl *Template, err error) {
t.nameSpace.mu.Lock() t.nameSpace.mu.RLock()
defer t.nameSpace.mu.Unlock()
t.nameSpace.escaped = true
tmpl = t.set[name] tmpl = t.set[name]
var escapeErr error
if tmpl != nil {
escapeErr = tmpl.escapeErr
}
t.nameSpace.mu.RUnlock()
if tmpl == nil { if tmpl == nil {
return nil, fmt.Errorf("html/template: %q is undefined", name) return nil, fmt.Errorf("html/template: %q is undefined", name)
} }
if escapeErr != nil {
if escapeErr != escapeOK {
return nil, escapeErr
}
return tmpl, nil
}
t.nameSpace.mu.Lock()
defer t.nameSpace.mu.Unlock()
t.nameSpace.escaped = true
if tmpl.escapeErr != nil && tmpl.escapeErr != escapeOK { if tmpl.escapeErr != nil && tmpl.escapeErr != escapeOK {
return nil, tmpl.escapeErr return nil, tmpl.escapeErr
} }
@ -229,6 +260,7 @@ func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error
nil, nil,
text, text,
text.Tree, text.Tree,
nil,
t.nameSpace, t.nameSpace,
} }
t.set[name] = ret t.set[name] = ret
@ -259,8 +291,10 @@ func (t *Template) Clone() (*Template, error) {
nil, nil,
textClone, textClone,
textClone.Tree, textClone.Tree,
t.funcMap,
ns, ns,
} }
ret.wrapFuncs()
ret.set[ret.Name()] = ret ret.set[ret.Name()] = ret
for _, x := range textClone.Templates() { for _, x := range textClone.Templates() {
name := x.Name() name := x.Name()
@ -269,12 +303,15 @@ func (t *Template) Clone() (*Template, error) {
return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name()) return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
} }
x.Tree = x.Tree.Copy() x.Tree = x.Tree.Copy()
ret.set[name] = &Template{ tc := &Template{
nil, nil,
x, x,
x.Tree, x.Tree,
src.funcMap,
ret.nameSpace, ret.nameSpace,
} }
tc.wrapFuncs()
ret.set[name] = tc
} }
// Return the template associated with the name of this template. // Return the template associated with the name of this template.
return ret.set[ret.Name()], nil return ret.set[ret.Name()], nil
@ -288,6 +325,7 @@ func New(name string) *Template {
nil, nil,
template.New(name), template.New(name),
nil, nil,
nil,
ns, ns,
} }
tmpl.set[name] = tmpl tmpl.set[name] = tmpl
@ -313,6 +351,7 @@ func (t *Template) new(name string) *Template {
nil, nil,
t.text.New(name), t.text.New(name),
nil, nil,
nil,
t.nameSpace, t.nameSpace,
} }
if existing, ok := tmpl.set[name]; ok { if existing, ok := tmpl.set[name]; ok {
@ -343,10 +382,35 @@ type FuncMap map[string]interface{}
// type. However, it is legal to overwrite elements of the map. The return // type. However, it is legal to overwrite elements of the map. The return
// value is the template, so calls can be chained. // value is the template, so calls can be chained.
func (t *Template) Funcs(funcMap FuncMap) *Template { func (t *Template) Funcs(funcMap FuncMap) *Template {
t.text.Funcs(template.FuncMap(funcMap)) t.funcMap = funcMap
t.wrapFuncs()
return t return t
} }
// wrapFuncs records the functions with text/template. We wrap them to
// unlock the nameSpace. See TestRecursiveExecute for a test case.
func (t *Template) wrapFuncs() {
if len(t.funcMap) == 0 {
return
}
tfuncs := make(template.FuncMap, len(t.funcMap))
for name, fn := range t.funcMap {
fnv := reflect.ValueOf(fn)
wrapper := func(args []reflect.Value) []reflect.Value {
t.nameSpace.mu.RUnlock()
defer t.nameSpace.mu.RLock()
if fnv.Type().IsVariadic() {
return fnv.CallSlice(args)
} else {
return fnv.Call(args)
}
}
wrapped := reflect.MakeFunc(fnv.Type(), wrapper)
tfuncs[name] = wrapped.Interface()
}
t.text.Funcs(tfuncs)
}
// Delims sets the action delimiters to the specified strings, to be used in // Delims sets the action delimiters to the specified strings, to be used in
// subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template // subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template
// definitions will inherit the settings. An empty delimiter stands for the // definitions will inherit the settings. An empty delimiter stands for the
@ -360,8 +424,8 @@ func (t *Template) Delims(left, right string) *Template {
// Lookup returns the template with the given name that is associated with t, // Lookup returns the template with the given name that is associated with t,
// or nil if there is no such template. // or nil if there is no such template.
func (t *Template) Lookup(name string) *Template { func (t *Template) Lookup(name string) *Template {
t.nameSpace.mu.Lock() t.nameSpace.mu.RLock()
defer t.nameSpace.mu.Unlock() defer t.nameSpace.mu.RUnlock()
return t.set[name] return t.set[name]
} }

View file

@ -16,8 +16,7 @@ import (
// //
// The FS interface is the minimum implementation required of the file system. // The FS interface is the minimum implementation required of the file system.
// A file system may implement additional interfaces, // A file system may implement additional interfaces,
// such as fsutil.ReadFileFS, to provide additional or optimized functionality. // such as ReadFileFS, to provide additional or optimized functionality.
// See io/fsutil for details.
type FS interface { type FS interface {
// Open opens the named file. // Open opens the named file.
// //

View file

@ -804,3 +804,13 @@ func TestIssue37499(t *testing.T) {
t.Fatalf("incorrect quotient: %s", s) t.Fatalf("incorrect quotient: %s", s)
} }
} }
// TestIssue42552 triggers an edge case of recursive division
// where the first division loop is never entered, and correcting
// the remainder takes exactly two iterations in the final loop.
func TestIssue42552(t *testing.T) {
u := natFromString("0xc23b166884c3869092a520eceedeced2b00847bd256c9cf3b2c5e2227c15bd5e6ee7ef8a2f49236ad0eedf2c8a3b453cf6e0706f64285c526b372c4b1321245519d430540804a50b7ca8b6f1b34a2ec05cdbc24de7599af112d3e3c8db347e8799fe70f16e43c6566ba3aeb169463a3ecc486172deb2d9b80a3699c776e44fef20036bd946f1b4d054dd88a2c1aeb986199b0b2b7e58c42288824b74934d112fe1fc06e06b4d99fe1c5e725946b23210521e209cd507cce90b5f39a523f27e861f9e232aee50c3f585208b4573dcc0b897b6177f2ba20254fd5c50a033e849dee1b3a93bd2dc44ba8ca836cab2c2ae50e50b126284524fa0187af28628ff0face68d87709200329db1392852c8b8963fbe3d05fb1efe19f0ed5ca9fadc2f96f82187c24bb2512b2e85a66333a7e176605695211e1c8e0b9b9e82813e50654964945b1e1e66a90840396c7d10e23e47f364d2d3f660fa54598e18d1ca2ea4fe4f35a40a11f69f201c80b48eaee3e2e9b0eda63decf92bec08a70f731587d4ed0f218d5929285c8b2ccbc497e20db42de73885191fa453350335990184d8df805072f958d5354debda38f5421effaaafd6cb9b721ace74be0892d77679f62a4a126697cd35797f6858193da4ba1770c06aea2e5c59ec04b8ea26749e61b72ecdde403f3bc7e5e546cd799578cc939fa676dfd5e648576d4a06cbadb028adc2c0b461f145b2321f42e5e0f3b4fb898ecd461df07a6f5154067787bf74b5cc5c03704a1ce47494961931f0263b0aac32505102595957531a2de69dd71aac51f8a49902f81f21283dbe8e21e01e5d82517868826f86acf338d935aa6b4d5a25c8d540389b277dd9d64569d68baf0f71bd03dba45b92a7fc052601d1bd011a2fc6790a23f97c6fa5caeea040ab86841f268d39ce4f7caf01069df78bba098e04366492f0c2ac24f1bf16828752765fa523c9a4d42b71109d123e6be8c7b1ab3ccf8ea03404075fe1a9596f1bba1d267f9a7879ceece514818316c9c0583469d2367831fc42b517ea028a28df7c18d783d16ea2436cee2b15d52db68b5dfdee6b4d26f0905f9b030c911a04d078923a4136afea96eed6874462a482917353264cc9bee298f167ac65a6db4e4eda88044b39cc0b33183843eaa946564a00c3a0ab661f2c915e70bf0bb65bfbb6fa2eea20aed16bf2c1a1d00ec55fb4ff2f76b8e462ea70c19efa579c9ee78194b86708fdae66a9ce6e2cf3d366037798cfb50277ba6d2fd4866361022fd788ab7735b40b8b61d55e32243e06719e53992e9ac16c9c4b6e6933635c3c47c8f7e73e17dd54d0dd8aeba5d76de46894e7b3f9d3ec25ad78ee82297ba69905ea0fa094b8667faa2b8885e2187b3da80268aa1164761d7b0d6de206b676777348152b8ae1d4afed753bc63c739a5ca8ce7afb2b241a226bd9e502baba391b5b13f5054f070b65a9cf3a67063bfaa803ba390732cd03888f664023f888741d04d564e0b5674b0a183ace81452001b3fbb4214c77d42ca75376742c471e58f67307726d56a1032bd236610cbcbcd03d0d7a452900136897dc55bb3ce959d10d4e6a10fb635006bd8c41cd9ded2d3dfdd8f2e229590324a7370cb2124210b2330f4c56155caa09a2564932ceded8d92c79664dcdeb87faad7d3da006cc2ea267ee3df41e9677789cc5a8cc3b83add6491561b3047919e0648b1b2e97d7ad6f6c2aa80cab8e9ae10e1f75b1fdd0246151af709d259a6a0ed0b26bd711024965ecad7c41387de45443defce53f66612948694a6032279131c257119ed876a8e805dfb49576ef5c563574115ee87050d92d191bc761ef51d966918e2ef925639400069e3959d8fe19f36136e947ff430bf74e71da0aa5923b00000000")
v := natFromString("0x838332321d443a3d30373d47301d47073847473a383d3030f25b3d3d3e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002e00000000000000000041603038331c3d32f5303441e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e0e01c0a5459bfc7b9be9fcbb9d2383840464319434707303030f43a32f53034411c0a5459413820878787878787878787878787878787878787878787878787878787878787878787870630303a3a30334036605b923a6101f83638413943413960204337602043323801526040523241846038414143015238604060328452413841413638523c0240384141364036605b923a6101f83638413943413960204334602043323801526040523241846038414143015238604060328452413841413638523c02403841413638433030f25a8b83838383838383838383838383838383837d838383ffffffffffffffff838383838383838383000000000000000000030000007d26e27c7c8b83838383838383838383838383838383837d838383ffffffffffffffff83838383838383838383838383838383838383838383435960f535073030f3343200000000000000011881301938343030fa398383300000002300000000000000000000f11af4600c845252904141364138383c60406032414443095238010241414303364443434132305b595a15434160b042385341ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff47476043410536613603593a6005411c437405fcfcfcfcfcfcfc0000000000005a3b075815054359000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
q := nat(nil).make(16)
q.div(q, u, v)
}

View file

@ -32,7 +32,7 @@ func TestConnAndListener(t *testing.T) {
} }
defer ls.teardown() defer ls.teardown()
ch := make(chan error, 1) ch := make(chan error, 1)
handler := func(ls *localServer, ln Listener) { transponder(ln, ch) } handler := func(ls *localServer, ln Listener) { ls.transponder(ln, ch) }
if err := ls.buildup(handler); err != nil { if err := ls.buildup(handler); err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -7651,6 +7651,9 @@ func (cc *http2ClientConn) roundTrip(req *Request) (res *Response, gotErrAfterRe
// we can keep it. // we can keep it.
bodyWriter.cancel() bodyWriter.cancel()
cs.abortRequestBodyWrite(http2errStopReqBodyWrite) cs.abortRequestBodyWrite(http2errStopReqBodyWrite)
if hasBody && !bodyWritten {
<-bodyWriter.resc
}
} }
if re.err != nil { if re.err != nil {
cc.forgetStreamID(cs.ID) cc.forgetStreamID(cs.ID)
@ -7671,6 +7674,7 @@ func (cc *http2ClientConn) roundTrip(req *Request) (res *Response, gotErrAfterRe
} else { } else {
bodyWriter.cancel() bodyWriter.cancel()
cs.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel) cs.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel)
<-bodyWriter.resc
} }
cc.forgetStreamID(cs.ID) cc.forgetStreamID(cs.ID)
return nil, cs.getStartedWrite(), http2errTimeout return nil, cs.getStartedWrite(), http2errTimeout
@ -7680,6 +7684,7 @@ func (cc *http2ClientConn) roundTrip(req *Request) (res *Response, gotErrAfterRe
} else { } else {
bodyWriter.cancel() bodyWriter.cancel()
cs.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel) cs.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel)
<-bodyWriter.resc
} }
cc.forgetStreamID(cs.ID) cc.forgetStreamID(cs.ID)
return nil, cs.getStartedWrite(), ctx.Err() return nil, cs.getStartedWrite(), ctx.Err()
@ -7689,6 +7694,7 @@ func (cc *http2ClientConn) roundTrip(req *Request) (res *Response, gotErrAfterRe
} else { } else {
bodyWriter.cancel() bodyWriter.cancel()
cs.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel) cs.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel)
<-bodyWriter.resc
} }
cc.forgetStreamID(cs.ID) cc.forgetStreamID(cs.ID)
return nil, cs.getStartedWrite(), http2errRequestCanceled return nil, cs.getStartedWrite(), http2errRequestCanceled
@ -7698,6 +7704,7 @@ func (cc *http2ClientConn) roundTrip(req *Request) (res *Response, gotErrAfterRe
// forgetStreamID. // forgetStreamID.
return nil, cs.getStartedWrite(), cs.resetErr return nil, cs.getStartedWrite(), cs.resetErr
case err := <-bodyWriter.resc: case err := <-bodyWriter.resc:
bodyWritten = true
// Prefer the read loop's response, if available. Issue 16102. // Prefer the read loop's response, if available. Issue 16102.
select { select {
case re := <-readLoopResCh: case re := <-readLoopResCh:
@ -7708,7 +7715,6 @@ func (cc *http2ClientConn) roundTrip(req *Request) (res *Response, gotErrAfterRe
cc.forgetStreamID(cs.ID) cc.forgetStreamID(cs.ID)
return nil, cs.getStartedWrite(), err return nil, cs.getStartedWrite(), err
} }
bodyWritten = true
if d := cc.responseHeaderTimeout(); d != 0 { if d := cc.responseHeaderTimeout(); d != 0 {
timer := time.NewTimer(d) timer := time.NewTimer(d)
defer timer.Stop() defer timer.Stop()
@ -9130,7 +9136,9 @@ func (t *http2Transport) getBodyWriterState(cs *http2clientStream, body io.Reade
func (s http2bodyWriterState) cancel() { func (s http2bodyWriterState) cancel() {
if s.timer != nil { if s.timer != nil {
s.timer.Stop() if s.timer.Stop() {
s.resc <- nil
}
} }
} }

View file

@ -91,7 +91,7 @@ func init() {
func Cmdline(w http.ResponseWriter, r *http.Request) { func Cmdline(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Content-Type-Options", "nosniff") w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("Content-Type", "text/plain; charset=utf-8") w.Header().Set("Content-Type", "text/plain; charset=utf-8")
fmt.Fprintf(w, strings.Join(os.Args, "\x00")) fmt.Fprint(w, strings.Join(os.Args, "\x00"))
} }
func sleep(r *http.Request, d time.Duration) { func sleep(r *http.Request, d time.Duration) {

View file

@ -361,7 +361,12 @@ func (r *Response) isProtocolSwitch() bool {
// isProtocolSwitchResponse reports whether the response code and // isProtocolSwitchResponse reports whether the response code and
// response header indicate a successful protocol upgrade response. // response header indicate a successful protocol upgrade response.
func isProtocolSwitchResponse(code int, h Header) bool { func isProtocolSwitchResponse(code int, h Header) bool {
return code == StatusSwitchingProtocols && return code == StatusSwitchingProtocols && isProtocolSwitchHeader(h)
h.Get("Upgrade") != "" && }
// isProtocolSwitchHeader reports whether the request or response header
// is for a protocol switch.
func isProtocolSwitchHeader(h Header) bool {
return h.Get("Upgrade") != "" &&
httpguts.HeaderValuesContainsToken(h["Connection"], "Upgrade") httpguts.HeaderValuesContainsToken(h["Connection"], "Upgrade")
} }

View file

@ -6481,6 +6481,10 @@ func TestDisableKeepAliveUpgrade(t *testing.T) {
} }
defer resp.Body.Close() defer resp.Body.Close()
if resp.StatusCode != StatusSwitchingProtocols {
t.Fatalf("unexpected status code: %v", resp.StatusCode)
}
rwc, ok := resp.Body.(io.ReadWriteCloser) rwc, ok := resp.Body.(io.ReadWriteCloser)
if !ok { if !ok {
t.Fatalf("Response.Body is not a io.ReadWriteCloser: %T", resp.Body) t.Fatalf("Response.Body is not a io.ReadWriteCloser: %T", resp.Body)

View file

@ -1837,7 +1837,7 @@ func (c *conn) serve(ctx context.Context) {
if d := c.server.WriteTimeout; d != 0 { if d := c.server.WriteTimeout; d != 0 {
c.rwc.SetWriteDeadline(time.Now().Add(d)) c.rwc.SetWriteDeadline(time.Now().Add(d))
} }
if err := tlsConn.HandshakeContext(ctx); err != nil { if err := tlsConn.Handshake(); err != nil {
// If the handshake failed due to the client not speaking // If the handshake failed due to the client not speaking
// TLS, assume they're speaking plaintext HTTP and write a // TLS, assume they're speaking plaintext HTTP and write a
// 400 response on the TLS conn's underlying net.Conn. // 400 response on the TLS conn's underlying net.Conn.

View file

@ -1505,7 +1505,7 @@ func (t *Transport) decConnsPerHost(key connectMethodKey) {
// Add TLS to a persistent connection, i.e. negotiate a TLS session. If pconn is already a TLS // Add TLS to a persistent connection, i.e. negotiate a TLS session. If pconn is already a TLS
// tunnel, this function establishes a nested TLS session inside the encrypted channel. // tunnel, this function establishes a nested TLS session inside the encrypted channel.
// The remote endpoint's name may be overridden by TLSClientConfig.ServerName. // The remote endpoint's name may be overridden by TLSClientConfig.ServerName.
func (pconn *persistConn) addTLS(ctx context.Context, name string, trace *httptrace.ClientTrace) error { func (pconn *persistConn) addTLS(name string, trace *httptrace.ClientTrace) error {
// Initiate TLS and check remote host name against certificate. // Initiate TLS and check remote host name against certificate.
cfg := cloneTLSConfig(pconn.t.TLSClientConfig) cfg := cloneTLSConfig(pconn.t.TLSClientConfig)
if cfg.ServerName == "" { if cfg.ServerName == "" {
@ -1527,7 +1527,7 @@ func (pconn *persistConn) addTLS(ctx context.Context, name string, trace *httptr
if trace != nil && trace.TLSHandshakeStart != nil { if trace != nil && trace.TLSHandshakeStart != nil {
trace.TLSHandshakeStart() trace.TLSHandshakeStart()
} }
err := tlsConn.HandshakeContext(ctx) err := tlsConn.Handshake()
if timer != nil { if timer != nil {
timer.Stop() timer.Stop()
} }
@ -1583,7 +1583,7 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *pers
if trace != nil && trace.TLSHandshakeStart != nil { if trace != nil && trace.TLSHandshakeStart != nil {
trace.TLSHandshakeStart() trace.TLSHandshakeStart()
} }
if err := tc.HandshakeContext(ctx); err != nil { if err := tc.Handshake(); err != nil {
go pconn.conn.Close() go pconn.conn.Close()
if trace != nil && trace.TLSHandshakeDone != nil { if trace != nil && trace.TLSHandshakeDone != nil {
trace.TLSHandshakeDone(tls.ConnectionState{}, err) trace.TLSHandshakeDone(tls.ConnectionState{}, err)
@ -1607,7 +1607,7 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *pers
if firstTLSHost, _, err = net.SplitHostPort(cm.addr()); err != nil { if firstTLSHost, _, err = net.SplitHostPort(cm.addr()); err != nil {
return nil, wrapErr(err) return nil, wrapErr(err)
} }
if err = pconn.addTLS(ctx, firstTLSHost, trace); err != nil { if err = pconn.addTLS(firstTLSHost, trace); err != nil {
return nil, wrapErr(err) return nil, wrapErr(err)
} }
} }
@ -1721,7 +1721,7 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *pers
} }
if cm.proxyURL != nil && cm.targetScheme == "https" { if cm.proxyURL != nil && cm.targetScheme == "https" {
if err := pconn.addTLS(ctx, cm.tlsHost(), trace); err != nil { if err := pconn.addTLS(cm.tlsHost(), trace); err != nil {
return nil, err return nil, err
} }
} }
@ -2566,7 +2566,9 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err
continueCh = make(chan struct{}, 1) continueCh = make(chan struct{}, 1)
} }
if pc.t.DisableKeepAlives && !req.wantsClose() { if pc.t.DisableKeepAlives &&
!req.wantsClose() &&
!isProtocolSwitchHeader(req.Header) {
req.extraHeaders().Set("Connection", "close") req.extraHeaders().Set("Connection", "close")
} }

View file

@ -3734,7 +3734,7 @@ func TestTransportDialTLSContext(t *testing.T) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return c, c.HandshakeContext(ctx) return c, c.Handshake()
} }
req, err := NewRequest("GET", ts.URL, nil) req, err := NewRequest("GET", ts.URL, nil)

View file

@ -87,6 +87,7 @@ type localServer struct {
lnmu sync.RWMutex lnmu sync.RWMutex
Listener Listener
done chan bool // signal that indicates server stopped done chan bool // signal that indicates server stopped
cl []Conn // accepted connection list
} }
func (ls *localServer) buildup(handler func(*localServer, Listener)) error { func (ls *localServer) buildup(handler func(*localServer, Listener)) error {
@ -99,10 +100,16 @@ func (ls *localServer) buildup(handler func(*localServer, Listener)) error {
func (ls *localServer) teardown() error { func (ls *localServer) teardown() error {
ls.lnmu.Lock() ls.lnmu.Lock()
defer ls.lnmu.Unlock()
if ls.Listener != nil { if ls.Listener != nil {
network := ls.Listener.Addr().Network() network := ls.Listener.Addr().Network()
address := ls.Listener.Addr().String() address := ls.Listener.Addr().String()
ls.Listener.Close() ls.Listener.Close()
for _, c := range ls.cl {
if err := c.Close(); err != nil {
return err
}
}
<-ls.done <-ls.done
ls.Listener = nil ls.Listener = nil
switch network { switch network {
@ -110,7 +117,6 @@ func (ls *localServer) teardown() error {
os.Remove(address) os.Remove(address)
} }
} }
ls.lnmu.Unlock()
return nil return nil
} }
@ -203,7 +209,7 @@ func newDualStackServer() (*dualStackServer, error) {
}, nil }, nil
} }
func transponder(ln Listener, ch chan<- error) { func (ls *localServer) transponder(ln Listener, ch chan<- error) {
defer close(ch) defer close(ch)
switch ln := ln.(type) { switch ln := ln.(type) {
@ -220,7 +226,7 @@ func transponder(ln Listener, ch chan<- error) {
ch <- err ch <- err
return return
} }
defer c.Close() ls.cl = append(ls.cl, c)
network := ln.Addr().Network() network := ln.Addr().Network()
if c.LocalAddr().Network() != network || c.RemoteAddr().Network() != network { if c.LocalAddr().Network() != network || c.RemoteAddr().Network() != network {

View file

@ -72,7 +72,7 @@ func TestTCPConnSpecificMethods(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
ch := make(chan error, 1) ch := make(chan error, 1)
handler := func(ls *localServer, ln Listener) { transponder(ls.Listener, ch) } handler := func(ls *localServer, ln Listener) { ls.transponder(ls.Listener, ch) }
ls, err := (&streamListener{Listener: ln}).newLocalServer() ls, err := (&streamListener{Listener: ln}).newLocalServer()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View file

@ -86,7 +86,7 @@ func TestTCPServer(t *testing.T) {
} }
for i := 0; i < N; i++ { for i := 0; i < N; i++ {
ch := tpchs[i] ch := tpchs[i]
handler := func(ls *localServer, ln Listener) { transponder(ln, ch) } handler := func(ls *localServer, ln Listener) { ls.transponder(ln, ch) }
if err := lss[i].buildup(handler); err != nil { if err := lss[i].buildup(handler); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -178,7 +178,7 @@ func TestUnixAndUnixpacketServer(t *testing.T) {
} }
for i := 0; i < N; i++ { for i := 0; i < N; i++ {
ch := tpchs[i] ch := tpchs[i]
handler := func(ls *localServer, ln Listener) { transponder(ln, ch) } handler := func(ls *localServer, ln Listener) { ls.transponder(ln, ch) }
if err := lss[i].buildup(handler); err != nil { if err := lss[i].buildup(handler); err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -393,7 +393,7 @@ func TestIPv6LinkLocalUnicastTCP(t *testing.T) {
} }
defer ls.teardown() defer ls.teardown()
ch := make(chan error, 1) ch := make(chan error, 1)
handler := func(ls *localServer, ln Listener) { transponder(ln, ch) } handler := func(ls *localServer, ln Listener) { ls.transponder(ln, ch) }
if err := ls.buildup(handler); err != nil { if err := ls.buildup(handler); err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -336,16 +336,6 @@ func hasPrefix(s, prefix string) bool {
return len(s) >= len(prefix) && s[0:len(prefix)] == prefix return len(s) >= len(prefix) && s[0:len(prefix)] == prefix
} }
// LastIndexByte from the strings package.
func lastIndex(s string, sep byte) int {
for i := len(s) - 1; i >= 0; i-- {
if s[i] == sep {
return i
}
}
return -1
}
func rename(oldname, newname string) error { func rename(oldname, newname string) error {
dirname := oldname[:lastIndex(oldname, '/')+1] dirname := oldname[:lastIndex(oldname, '/')+1]
if hasPrefix(newname, dirname) { if hasPrefix(newname, dirname) {

View file

@ -675,22 +675,68 @@ func TestTime(t *testing.T) {
<-done <-done
} }
func TestNotifyContext(t *testing.T) { var (
c, stop := NotifyContext(context.Background(), syscall.SIGINT) checkNotifyContext = flag.Bool("check_notify_ctx", false, "if true, TestNotifyContext will fail if SIGINT is not received.")
defer stop() ctxNotifyTimes = flag.Int("ctx_notify_times", 1, "number of times a SIGINT signal should be received")
)
if want, got := "signal.NotifyContext(context.Background, [interrupt])", fmt.Sprint(c); want != got { func TestNotifyContextNotifications(t *testing.T) {
t.Errorf("c.String() = %q, want %q", got, want) if *checkNotifyContext {
ctx, _ := NotifyContext(context.Background(), syscall.SIGINT)
// We want to make sure not to be calling Stop() internally on NotifyContext() when processing a received signal.
// Being able to wait for a number of received system signals allows us to do so.
var wg sync.WaitGroup
n := *ctxNotifyTimes
wg.Add(n)
for i := 0; i < n; i++ {
go func() {
syscall.Kill(syscall.Getpid(), syscall.SIGINT)
wg.Done()
}()
}
wg.Wait()
<-ctx.Done()
fmt.Print("received SIGINT")
// Sleep to give time to simultaneous signals to reach the process.
// These signals must be ignored given stop() is not called on this code.
// We want to guarantee a SIGINT doesn't cause a premature termination of the program.
time.Sleep(settleTime)
return
} }
syscall.Kill(syscall.Getpid(), syscall.SIGINT) t.Parallel()
select { testCases := []struct {
case <-c.Done(): name string
if got := c.Err(); got != context.Canceled { n int // number of times a SIGINT should be notified.
t.Errorf("c.Err() = %q, want %q", got, context.Canceled) }{
} {"once", 1},
case <-time.After(time.Second): {"multiple", 10},
t.Errorf("timed out waiting for context to be done after SIGINT") }
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
var subTimeout time.Duration
if deadline, ok := t.Deadline(); ok {
subTimeout := time.Until(deadline)
subTimeout -= subTimeout / 10 // Leave 10% headroom for cleaning up subprocess.
}
args := []string{
"-test.v",
"-test.run=TestNotifyContextNotifications$",
"-check_notify_ctx",
fmt.Sprintf("-ctx_notify_times=%d", tc.n),
}
if subTimeout != 0 {
args = append(args, fmt.Sprintf("-test.timeout=%v", subTimeout))
}
out, err := exec.Command(os.Args[0], args...).CombinedOutput()
if err != nil {
t.Errorf("ran test with -check_notify_ctx_notification and it failed with %v.\nOutput:\n%s", err, out)
}
if want := []byte("received SIGINT"); !bytes.Contains(out, want) {
t.Errorf("got %q, wanted %q", out, want)
}
})
} }
} }
@ -768,34 +814,6 @@ func TestNotifyContextPrematureCancelParent(t *testing.T) {
} }
} }
func TestNotifyContextSimultaneousNotifications(t *testing.T) {
c, stop := NotifyContext(context.Background(), syscall.SIGINT)
defer stop()
if want, got := "signal.NotifyContext(context.Background, [interrupt])", fmt.Sprint(c); want != got {
t.Errorf("c.String() = %q, want %q", got, want)
}
var wg sync.WaitGroup
n := 10
wg.Add(n)
for i := 0; i < n; i++ {
go func() {
syscall.Kill(syscall.Getpid(), syscall.SIGINT)
wg.Done()
}()
}
wg.Wait()
select {
case <-c.Done():
if got := c.Err(); got != context.Canceled {
t.Errorf("c.Err() = %q, want %q", got, context.Canceled)
}
case <-time.After(time.Second):
t.Errorf("expected context to be canceled")
}
}
func TestNotifyContextSimultaneousStop(t *testing.T) { func TestNotifyContextSimultaneousStop(t *testing.T) {
c, stop := NotifyContext(context.Background(), syscall.SIGINT) c, stop := NotifyContext(context.Background(), syscall.SIGINT)
defer stop() defer stop()

View file

@ -4,10 +4,7 @@
package os package os
import ( import "errors"
"errors"
"strings"
)
// fastrand provided by runtime. // fastrand provided by runtime.
// We generate random temporary file names so that there's a good // We generate random temporary file names so that there's a good
@ -62,7 +59,7 @@ func prefixAndSuffix(pattern string) (prefix, suffix string, err error) {
return "", "", errPatternHasSeparator return "", "", errPatternHasSeparator
} }
} }
if pos := strings.LastIndex(pattern, "*"); pos != -1 { if pos := lastIndex(pattern, '*'); pos != -1 {
prefix, suffix = pattern[:pos], pattern[pos+1:] prefix, suffix = pattern[:pos], pattern[pos+1:]
} else { } else {
prefix = pattern prefix = pattern
@ -116,3 +113,13 @@ func joinPath(dir, name string) string {
} }
return dir + string(PathSeparator) + name return dir + string(PathSeparator) + name
} }
// LastIndexByte from the strings package.
func lastIndex(s string, sep byte) int {
for i := len(s) - 1; i >= 0; i-- {
if s[i] == sep {
return i
}
}
return -1
}

View file

@ -43,7 +43,7 @@ func extractMetricDocs(t *testing.T) map[string]string {
line := strings.TrimSpace(s.Text()) line := strings.TrimSpace(s.Text())
switch state { switch state {
case stateSearch: case stateSearch:
if line == "Supported metrics" { if line == "Below is the full list of supported metrics, ordered lexicographically." {
state = stateNextMetric state = stateNextMetric
} }
case stateNextMetric: case stateNextMetric:

View file

@ -42,8 +42,16 @@ did also, and a new key should be introduced.
For more details on the precise definition of the metric key's path and unit formats, see For more details on the precise definition of the metric key's path and unit formats, see
the documentation of the Name field of the Description struct. the documentation of the Name field of the Description struct.
A note about floats
This package supports metrics whose values have a floating-point representation. In
order to improve ease-of-use, this package promises to never produce the following
classes of floating-point values: NaN, infinity.
Supported metrics Supported metrics
Below is the full list of supported metrics, ordered lexicographically.
/gc/cycles/automatic:gc-cycles /gc/cycles/automatic:gc-cycles
Count of completed GC cycles generated by the Go runtime. Count of completed GC cycles generated by the Go runtime.

View file

@ -30,6 +30,16 @@ func runtime_readMetrics(unsafe.Pointer, int, int)
// The user of this API is encouraged to re-use the same slice between calls for // The user of this API is encouraged to re-use the same slice between calls for
// efficiency, but is not required to do so. // efficiency, but is not required to do so.
// //
// Note that re-use has some caveats. Notably, Values should not be read or
// manipulated while a Read with that value is outstanding; that is a data race.
// This property includes pointer-typed Values (e.g. Float64Histogram) whose
// underlying storage will be reused by Read when possible. To safely use such
// values in a concurrent setting, all data must be deep-copied.
//
// It is safe to execute multiple Read calls concurrently, but their arguments
// must share no underlying memory. When in doubt, create a new []Sample from
// scratch, which is always safe, though may be inefficient.
//
// Sample values with names not appearing in All will have their Value populated // Sample values with names not appearing in All will have their Value populated
// as KindBad to indicate that the name is unknown. // as KindBad to indicate that the name is unknown.
func Read(m []Sample) { func Read(m []Sample) {

View file

@ -284,32 +284,31 @@ static inline void startThread(cb* c) {
*/ */
import "C" import "C"
import "time" var done chan bool
var racy int var racy int
//export goCallback //export goCallback
func goCallback() { func goCallback() {
racy++ racy++
done <- true
} }
func main() { func main() {
done = make(chan bool)
var c C.cb var c C.cb
C.startThread(&c) C.startThread(&c)
time.Sleep(time.Second)
racy++ racy++
<- done
} }
`, `================== `, `==================
WARNING: DATA RACE WARNING: DATA RACE
Read at 0x[0-9,a-f]+ by main goroutine: Read at 0x[0-9,a-f]+ by .*:
main\.main\(\) main\..*
.*/main\.go:34 \+0x[0-9,a-f]+ .*/main\.go:[0-9]+ \+0x[0-9,a-f]+(?s).*
Previous write at 0x[0-9,a-f]+ by goroutine [0-9]: Previous write at 0x[0-9,a-f]+ by .*:
main\.goCallback\(\) main\..*
.*/main\.go:27 \+0x[0-9,a-f]+ .*/main\.go:[0-9]+ \+0x[0-9,a-f]+(?s).*
_cgoexp_[0-9a-z]+_goCallback\(\)
.*_cgo_gotypes\.go:[0-9]+ \+0x[0-9,a-f]+
Goroutine [0-9] \(running\) created at: Goroutine [0-9] \(running\) created at:
runtime\.newextram\(\) runtime\.newextram\(\)

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