From 52b222055908a3ae23c2a9185e53919fe56b54db Mon Sep 17 00:00:00 2001
From: Austin Clements
Date: Fri, 19 Oct 2018 14:24:02 -0400
Subject: [PATCH 001/594] cmd/asm: factor out line parsing from assembling
Currently cmd/asm's Parser.line both consumes a line of assembly from
the lexer and assembles it. This CL separates these two steps so that
the line parser can be reused for purposes other than generating a
Prog stream.
For #27539.
Updates #17544.
Change-Id: I452c9a2112fbcc1c94bf909efc0d1fcc71014812
Reviewed-on: https://go-review.googlesource.com/c/147097
Run-TryBot: Austin Clements
TryBot-Result: Gobot Gobot
Reviewed-by: Cherry Zhang
---
src/cmd/asm/internal/asm/line_test.go | 3 +-
src/cmd/asm/internal/asm/parse.go | 65 ++++++++++++++++++---------
2 files changed, 44 insertions(+), 24 deletions(-)
diff --git a/src/cmd/asm/internal/asm/line_test.go b/src/cmd/asm/internal/asm/line_test.go
index b77337bcf2314..7462f24a1c6d8 100644
--- a/src/cmd/asm/internal/asm/line_test.go
+++ b/src/cmd/asm/internal/asm/line_test.go
@@ -38,8 +38,7 @@ func testBadInstParser(t *testing.T, goarch string, tests []badInstTest) {
parser := NewParser(ctxt, arch, tokenizer)
err := tryParse(t, func() {
- parser.start(lex.Tokenize(test.input))
- parser.line()
+ parser.Parse()
})
switch {
diff --git a/src/cmd/asm/internal/asm/parse.go b/src/cmd/asm/internal/asm/parse.go
index e77db9fba1419..3620e31320903 100644
--- a/src/cmd/asm/internal/asm/parse.go
+++ b/src/cmd/asm/internal/asm/parse.go
@@ -91,7 +91,23 @@ func (p *Parser) pos() src.XPos {
}
func (p *Parser) Parse() (*obj.Prog, bool) {
- for p.line() {
+ scratch := make([][]lex.Token, 0, 3)
+ for {
+ word, cond, operands, ok := p.line(scratch)
+ if !ok {
+ break
+ }
+ scratch = operands
+
+ if p.pseudo(word, operands) {
+ continue
+ }
+ i, present := p.arch.Instructions[word]
+ if present {
+ p.instruction(i, word, cond, operands)
+ continue
+ }
+ p.errorf("unrecognized instruction %q", word)
}
if p.errorCount > 0 {
return nil, false
@@ -100,8 +116,17 @@ func (p *Parser) Parse() (*obj.Prog, bool) {
return p.firstProg, true
}
-// WORD [ arg {, arg} ] (';' | '\n')
-func (p *Parser) line() bool {
+// line consumes a single assembly line from p.lex of the form
+//
+// {label:} WORD[.cond] [ arg {, arg} ] (';' | '\n')
+//
+// It adds any labels to p.pendingLabels and returns the word, cond,
+// operand list, and true. If there is an error or EOF, it returns
+// ok=false.
+//
+// line may reuse the memory from scratch.
+func (p *Parser) line(scratch [][]lex.Token) (word, cond string, operands [][]lex.Token, ok bool) {
+next:
// Skip newlines.
var tok lex.ScanToken
for {
@@ -114,24 +139,29 @@ func (p *Parser) line() bool {
case '\n', ';':
continue
case scanner.EOF:
- return false
+ return "", "", nil, false
}
break
}
// First item must be an identifier.
if tok != scanner.Ident {
p.errorf("expected identifier, found %q", p.lex.Text())
- return false // Might as well stop now.
+ return "", "", nil, false // Might as well stop now.
}
- word := p.lex.Text()
- var cond string
- operands := make([][]lex.Token, 0, 3)
+ word, cond = p.lex.Text(), ""
+ operands = scratch[:0]
// Zero or more comma-separated operands, one per loop.
nesting := 0
colon := -1
for tok != '\n' && tok != ';' {
// Process one operand.
- items := make([]lex.Token, 0, 3)
+ var items []lex.Token
+ if cap(operands) > len(operands) {
+ // Reuse scratch items slice.
+ items = operands[:cap(operands)][len(operands)][:0]
+ } else {
+ items = make([]lex.Token, 0, 3)
+ }
for {
tok = p.lex.Next()
if len(operands) == 0 && len(items) == 0 {
@@ -148,12 +178,12 @@ func (p *Parser) line() bool {
if tok == ':' {
// Labels.
p.pendingLabels = append(p.pendingLabels, word)
- return true
+ goto next
}
}
if tok == scanner.EOF {
p.errorf("unexpected EOF")
- return false
+ return "", "", nil, false
}
// Split operands on comma. Also, the old syntax on x86 for a "register pair"
// was AX:DX, for which the new syntax is DX, AX. Note the reordering.
@@ -162,7 +192,7 @@ func (p *Parser) line() bool {
// Remember this location so we can swap the operands below.
if colon >= 0 {
p.errorf("invalid ':' in operand")
- return true
+ return word, cond, operands, true
}
colon = len(operands)
}
@@ -188,16 +218,7 @@ func (p *Parser) line() bool {
p.errorf("missing operand")
}
}
- if p.pseudo(word, operands) {
- return true
- }
- i, present := p.arch.Instructions[word]
- if present {
- p.instruction(i, word, cond, operands)
- return true
- }
- p.errorf("unrecognized instruction %q", word)
- return true
+ return word, cond, operands, true
}
func (p *Parser) instruction(op obj.As, word, cond string, operands [][]lex.Token) {
From ba2e8a629b36e43cc27b23470b631a1dfee0900f Mon Sep 17 00:00:00 2001
From: Austin Clements
Date: Fri, 19 Oct 2018 16:24:59 -0400
Subject: [PATCH 002/594] cmd/asm: add mode to collect symbol ABIs
This adds a -symabis flag that runs the assembler in a special mode
that outputs symbol definition and reference ABIs rather than
assembling the code. This uses a fast and somewhat lax parser because
the go_asm.h definitions may not be available.
For #27539.
Change-Id: I248ba0ebab7cc75dcb2a90e82a82eb445da7e88e
Reviewed-on: https://go-review.googlesource.com/c/147098
Run-TryBot: Austin Clements
TryBot-Result: Gobot Gobot
Reviewed-by: David Chase
Reviewed-by: Cherry Zhang
---
src/cmd/asm/internal/asm/operand_test.go | 43 +++++++++++++
src/cmd/asm/internal/asm/parse.go | 81 ++++++++++++++++++++++++
src/cmd/asm/internal/flags/flags.go | 1 +
src/cmd/asm/main.go | 22 +++++--
4 files changed, 140 insertions(+), 7 deletions(-)
diff --git a/src/cmd/asm/internal/asm/operand_test.go b/src/cmd/asm/internal/asm/operand_test.go
index 69393b6b2052a..2ba3fd73df83c 100644
--- a/src/cmd/asm/internal/asm/operand_test.go
+++ b/src/cmd/asm/internal/asm/operand_test.go
@@ -122,6 +122,49 @@ func TestS390XOperandParser(t *testing.T) {
testOperandParser(t, parser, s390xOperandTests)
}
+func TestFuncAddress(t *testing.T) {
+ type subtest struct {
+ arch string
+ tests []operandTest
+ }
+ for _, sub := range []subtest{
+ {"amd64", amd64OperandTests},
+ {"386", x86OperandTests},
+ {"arm", armOperandTests},
+ {"arm64", arm64OperandTests},
+ {"ppc64", ppc64OperandTests},
+ {"mips", mipsOperandTests},
+ {"mips64", mips64OperandTests},
+ {"s390x", s390xOperandTests},
+ } {
+ t.Run(sub.arch, func(t *testing.T) {
+ parser := newParser(sub.arch)
+ for _, test := range sub.tests {
+ parser.start(lex.Tokenize(test.input))
+ name, ok := parser.funcAddress()
+
+ isFuncSym := strings.HasSuffix(test.input, "(SB)") &&
+ // Ignore static symbols.
+ !strings.Contains(test.input, "<>") &&
+ // Ignore symbols with offsets.
+ !strings.Contains(test.input, "+")
+
+ wantName := ""
+ if isFuncSym {
+ // Strip $|* and (SB).
+ wantName = test.output[:len(test.output)-4]
+ if strings.HasPrefix(wantName, "$") || strings.HasPrefix(wantName, "*") {
+ wantName = wantName[1:]
+ }
+ }
+ if ok != isFuncSym || name != wantName {
+ t.Errorf("fail at %s as function address: got %s, %v; expected %s, %v", test.input, name, ok, wantName, isFuncSym)
+ }
+ }
+ })
+ }
+}
+
type operandTest struct {
input, output string
}
diff --git a/src/cmd/asm/internal/asm/parse.go b/src/cmd/asm/internal/asm/parse.go
index 3620e31320903..346976ef48b67 100644
--- a/src/cmd/asm/internal/asm/parse.go
+++ b/src/cmd/asm/internal/asm/parse.go
@@ -116,6 +116,22 @@ func (p *Parser) Parse() (*obj.Prog, bool) {
return p.firstProg, true
}
+// ParseSymABIs parses p's assembly code to find text symbol
+// definitions and references and writes a symabis file to w.
+func (p *Parser) ParseSymABIs(w io.Writer) bool {
+ operands := make([][]lex.Token, 0, 3)
+ for {
+ word, _, operands1, ok := p.line(operands)
+ if !ok {
+ break
+ }
+ operands = operands1
+
+ p.symDefRef(w, word, operands)
+ }
+ return p.errorCount == 0
+}
+
// line consumes a single assembly line from p.lex of the form
//
// {label:} WORD[.cond] [ arg {, arg} ] (';' | '\n')
@@ -258,6 +274,42 @@ func (p *Parser) pseudo(word string, operands [][]lex.Token) bool {
return true
}
+// symDefRef scans a line for potential text symbol definitions and
+// references and writes symabis information to w.
+//
+// The symabis format is documented at
+// cmd/compile/internal/gc.readSymABIs.
+func (p *Parser) symDefRef(w io.Writer, word string, operands [][]lex.Token) {
+ switch word {
+ case "TEXT":
+ // Defines text symbol in operands[0].
+ if len(operands) > 0 {
+ p.start(operands[0])
+ if name, ok := p.funcAddress(); ok {
+ fmt.Fprintf(w, "def %s ABI0\n", name)
+ }
+ }
+ return
+ case "GLOBL", "PCDATA":
+ // No text definitions or symbol references.
+ case "DATA", "FUNCDATA":
+ // For DATA, operands[0] is defined symbol.
+ // For FUNCDATA, operands[0] is an immediate constant.
+ // Remaining operands may have references.
+ if len(operands) < 2 {
+ return
+ }
+ operands = operands[1:]
+ }
+ // Search for symbol references.
+ for _, op := range operands {
+ p.start(op)
+ if name, ok := p.funcAddress(); ok {
+ fmt.Fprintf(w, "ref %s ABI0\n", name)
+ }
+ }
+}
+
func (p *Parser) start(operand []lex.Token) {
p.input = operand
p.inputPos = 0
@@ -746,6 +798,35 @@ func (p *Parser) setPseudoRegister(addr *obj.Addr, reg string, isStatic bool, pr
}
}
+// funcAddress parses an external function address. This is a
+// constrained form of the operand syntax that's always SB-based,
+// non-static, and has no additional offsets:
+//
+// [$|*]sym(SB)
+func (p *Parser) funcAddress() (string, bool) {
+ switch p.peek() {
+ case '$', '*':
+ // Skip prefix.
+ p.next()
+ }
+
+ tok := p.next()
+ name := tok.String()
+ if tok.ScanToken != scanner.Ident || p.atStartOfRegister(name) {
+ return "", false
+ }
+ if p.next().ScanToken != '(' {
+ return "", false
+ }
+ if reg := p.next(); reg.ScanToken != scanner.Ident || reg.String() != "SB" {
+ return "", false
+ }
+ if p.next().ScanToken != ')' || p.peek() != scanner.EOF {
+ return "", false
+ }
+ return name, true
+}
+
// registerIndirect parses the general form of a register indirection.
// It is can be (R1), (R2*scale), (R1)(R2*scale), (R1)(R2.SXTX<<3) or (R1)(R2<<3)
// where R1 may be a simple register or register pair R:R or (R, R) or (R+R).
diff --git a/src/cmd/asm/internal/flags/flags.go b/src/cmd/asm/internal/flags/flags.go
index 6acde29432675..752a1d45265d3 100644
--- a/src/cmd/asm/internal/flags/flags.go
+++ b/src/cmd/asm/internal/flags/flags.go
@@ -22,6 +22,7 @@ var (
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")
AllErrors = flag.Bool("e", false, "no limit on number of errors reported")
+ SymABIs = flag.Bool("symabis", false, "write symbol ABI information to output file, don't assemble")
)
var (
diff --git a/src/cmd/asm/main.go b/src/cmd/asm/main.go
index 04f56f96467f8..55ae94a6de5a6 100644
--- a/src/cmd/asm/main.go
+++ b/src/cmd/asm/main.go
@@ -53,8 +53,10 @@ func main() {
defer bio.MustClose(out)
buf := bufio.NewWriter(bio.MustWriter(out))
- fmt.Fprintf(buf, "go object %s %s %s\n", objabi.GOOS, objabi.GOARCH, objabi.Version)
- fmt.Fprintf(buf, "!\n")
+ if !*flags.SymABIs {
+ fmt.Fprintf(buf, "go object %s %s %s\n", objabi.GOOS, objabi.GOARCH, objabi.Version)
+ fmt.Fprintf(buf, "!\n")
+ }
var ok, diag bool
var failedFile string
@@ -65,16 +67,22 @@ func main() {
diag = true
log.Printf(format, args...)
}
- pList := new(obj.Plist)
- pList.Firstpc, ok = parser.Parse()
+ if *flags.SymABIs {
+ ok = parser.ParseSymABIs(buf)
+ } else {
+ pList := new(obj.Plist)
+ pList.Firstpc, ok = parser.Parse()
+ // reports errors to parser.Errorf
+ if ok {
+ obj.Flushplist(ctxt, pList, nil, "")
+ }
+ }
if !ok {
failedFile = f
break
}
- // reports errors to parser.Errorf
- obj.Flushplist(ctxt, pList, nil, "")
}
- if ok {
+ if ok && !*flags.SymABIs {
obj.WriteObjFile(ctxt, buf)
}
if !ok || diag {
From 97e4010fd4b8094aa0b4498ad751e4c07ea8a1aa Mon Sep 17 00:00:00 2001
From: Austin Clements
Date: Mon, 22 Oct 2018 10:10:23 -0400
Subject: [PATCH 003/594] cmd/compile: accept and parse symabis
This doesn't yet do anything with this information.
For #27539.
Change-Id: Ia12c905812aa1ed425eedd6ab2f55ec75d81c0ce
Reviewed-on: https://go-review.googlesource.com/c/147099
Run-TryBot: Austin Clements
TryBot-Result: Gobot Gobot
Reviewed-by: David Chase
Reviewed-by: Cherry Zhang
---
src/cmd/compile/internal/gc/main.go | 82 +++++++++++++++++++++++++++++
src/cmd/internal/obj/abi_string.go | 16 ++++++
src/cmd/internal/obj/link.go | 22 ++++++++
3 files changed, 120 insertions(+)
create mode 100644 src/cmd/internal/obj/abi_string.go
diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go
index 78142d3bf82bc..55d6d55e6dfc8 100644
--- a/src/cmd/compile/internal/gc/main.go
+++ b/src/cmd/compile/internal/gc/main.go
@@ -247,6 +247,9 @@ func Main(archInit func(*Arch)) {
flag.Int64Var(&memprofilerate, "memprofilerate", 0, "set runtime.MemProfileRate to `rate`")
var goversion string
flag.StringVar(&goversion, "goversion", "", "required version of the runtime")
+ var symabisPath string
+ flag.StringVar(&symabisPath, "symabis", "", "read symbol ABIs from `file`")
+ flag.BoolVar(&allABIs, "allabis", false, "generate ABI wrappers for all symbols (for bootstrap)")
flag.StringVar(&traceprofile, "traceprofile", "", "write an execution trace to `file`")
flag.StringVar(&blockprofile, "blockprofile", "", "write block profile to `file`")
flag.StringVar(&mutexprofile, "mutexprofile", "", "write mutex profile to `file`")
@@ -285,6 +288,10 @@ func Main(archInit func(*Arch)) {
checkLang()
+ if symabisPath != "" {
+ readSymABIs(symabisPath, myimportpath)
+ }
+
thearch.LinkArch.Init(Ctxt)
if outfile == "" {
@@ -810,6 +817,81 @@ func readImportCfg(file string) {
}
}
+// symabiDefs and symabiRefs record the defined and referenced ABIs of
+// symbols required by non-Go code. These are keyed by link symbol
+// name, where the local package prefix is always `"".`
+var symabiDefs, symabiRefs map[string]obj.ABI
+
+// allABIs indicates that all symbol definitions should have ABI
+// wrappers. This is used during toolchain bootstrapping to avoid
+// having to find cross-package references.
+var allABIs bool
+
+// readSymABIs reads a symabis file that specifies definitions and
+// references of text symbols by ABI.
+//
+// The symabis format is a set of lines, where each line is a sequence
+// of whitespace-separated fields. The first field is a verb and is
+// either "def" for defining a symbol ABI or "ref" for referencing a
+// symbol using an ABI. For both "def" and "ref", the second field is
+// the symbol name and the third field is the ABI name, as one of the
+// named cmd/internal/obj.ABI constants.
+func readSymABIs(file, myimportpath string) {
+ data, err := ioutil.ReadFile(file)
+ if err != nil {
+ log.Fatalf("-symabis: %v", err)
+ }
+
+ symabiDefs = make(map[string]obj.ABI)
+ symabiRefs = make(map[string]obj.ABI)
+
+ localPrefix := ""
+ if myimportpath != "" {
+ // Symbols in this package may be written either as
+ // "".X or with the package's import path already in
+ // the symbol.
+ localPrefix = objabi.PathToPrefix(myimportpath) + "."
+ }
+
+ for lineNum, line := range strings.Split(string(data), "\n") {
+ lineNum++ // 1-based
+ line = strings.TrimSpace(line)
+ if line == "" || strings.HasPrefix(line, "#") {
+ continue
+ }
+
+ parts := strings.Fields(line)
+ switch parts[0] {
+ case "def", "ref":
+ // Parse line.
+ if len(parts) != 3 {
+ log.Fatalf(`%s:%d: invalid symabi: syntax is "%s sym abi"`, file, lineNum, parts[0])
+ }
+ sym, abi := parts[1], parts[2]
+ if abi != "ABI0" { // Only supported external ABI right now
+ log.Fatalf(`%s:%d: invalid symabi: unknown abi "%s"`, file, lineNum, abi)
+ }
+
+ // If the symbol is already prefixed with
+ // myimportpath, rewrite it to start with ""
+ // so it matches the compiler's internal
+ // symbol names.
+ if localPrefix != "" && strings.HasPrefix(sym, localPrefix) {
+ sym = `"".` + sym[len(localPrefix):]
+ }
+
+ // Record for later.
+ if parts[0] == "def" {
+ symabiDefs[sym] = obj.ABI0
+ } else {
+ symabiRefs[sym] = obj.ABI0
+ }
+ default:
+ log.Fatalf(`%s:%d: invalid symabi type "%s"`, file, lineNum, parts[0])
+ }
+ }
+}
+
func saveerrors() {
nsavederrors += nerrors
nerrors = 0
diff --git a/src/cmd/internal/obj/abi_string.go b/src/cmd/internal/obj/abi_string.go
new file mode 100644
index 0000000000000..a439da36a34ee
--- /dev/null
+++ b/src/cmd/internal/obj/abi_string.go
@@ -0,0 +1,16 @@
+// Code generated by "stringer -type ABI"; DO NOT EDIT.
+
+package obj
+
+import "strconv"
+
+const _ABI_name = "ABI0ABIInternalABICount"
+
+var _ABI_index = [...]uint8{0, 4, 15, 23}
+
+func (i ABI) String() string {
+ if i >= ABI(len(_ABI_index)-1) {
+ return "ABI(" + strconv.FormatInt(int64(i), 10) + ")"
+ }
+ return _ABI_name[_ABI_index[i]:_ABI_index[i+1]]
+}
diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go
index d924cbc21424b..d3721dd023466 100644
--- a/src/cmd/internal/obj/link.go
+++ b/src/cmd/internal/obj/link.go
@@ -409,6 +409,28 @@ type FuncInfo struct {
StackObjects *LSym
}
+//go:generate stringer -type ABI
+
+// ABI is the calling convention of a text symbol.
+type ABI uint8
+
+const (
+ // ABI0 is the stable stack-based ABI. It's important that the
+ // value of this is "0": we can't distinguish between
+ // references to data and ABI0 text symbols in assembly code,
+ // and hence this doesn't distinguish between symbols without
+ // an ABI and text symbols with ABI0.
+ ABI0 ABI = iota
+
+ // ABIInternal is the internal ABI that may change between Go
+ // versions. All Go functions use the internal ABI and the
+ // compiler generates wrappers for calls to and from other
+ // ABIs.
+ ABIInternal
+
+ ABICount
+)
+
// Attribute is a set of symbol attributes.
type Attribute int16
From 7f1dd3ae4df08a8619311c95f3e4c91b96132efd Mon Sep 17 00:00:00 2001
From: Austin Clements
Date: Thu, 1 Nov 2018 22:04:02 -0400
Subject: [PATCH 004/594] test: minor simplification to run.go
This is a little clearer, and we're about to need the .s file list in
one more place, so this will cut down on duplication.
Change-Id: I4da8bf03a0469fb97565b0841c40d505657b574e
Reviewed-on: https://go-review.googlesource.com/c/146998
Run-TryBot: Austin Clements
TryBot-Result: Gobot Gobot
Reviewed-by: Brad Fitzpatrick
---
test/run.go | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/test/run.go b/test/run.go
index b6421d5e419c4..6a050b0049d7c 100644
--- a/test/run.go
+++ b/test/run.go
@@ -796,14 +796,14 @@ func (t *test) run() {
t.err = dirErr
break
}
- var gos []os.FileInfo
- var asms []os.FileInfo
+ var gos []string
+ var asms []string
for _, file := range files {
switch filepath.Ext(file.Name()) {
case ".go":
- gos = append(gos, file)
+ gos = append(gos, filepath.Join(longdir, file.Name()))
case ".s":
- asms = append(asms, file)
+ asms = append(asms, filepath.Join(longdir, file.Name()))
}
}
@@ -812,9 +812,7 @@ func (t *test) run() {
if len(asms) > 0 {
cmd = append(cmd, "-asmhdr", "go_asm.h")
}
- for _, file := range gos {
- cmd = append(cmd, filepath.Join(longdir, file.Name()))
- }
+ cmd = append(cmd, gos...)
_, err := runcmd(cmd...)
if err != nil {
t.err = err
@@ -823,9 +821,7 @@ func (t *test) run() {
objs = append(objs, "go.o")
if len(asms) > 0 {
cmd = []string{goTool(), "tool", "asm", "-e", "-I", ".", "-o", "asm.o"}
- for _, file := range asms {
- cmd = append(cmd, filepath.Join(longdir, file.Name()))
- }
+ cmd = append(cmd, asms...)
_, err = runcmd(cmd...)
if err != nil {
t.err = err
From 0f5dfbcfd789c2217f40dc59d1882149a8502960 Mon Sep 17 00:00:00 2001
From: Austin Clements
Date: Mon, 22 Oct 2018 11:21:56 -0400
Subject: [PATCH 005/594] cmd/go, cmd/dist: plumb symabis from assembler to
compiler
For #27539.
Change-Id: I0e27f142224e820205fb0e65ad03be7eba93da14
Reviewed-on: https://go-review.googlesource.com/c/146999
Run-TryBot: Austin Clements
TryBot-Result: Gobot Gobot
Reviewed-by: Ian Lance Taylor
---
src/cmd/dist/build.go | 79 +++++++++++++++++++------------
src/cmd/go/internal/work/exec.go | 23 +++++++--
src/cmd/go/internal/work/gc.go | 41 ++++++++++++++--
src/cmd/go/internal/work/gccgo.go | 6 ++-
test/run.go | 15 +++++-
5 files changed, 124 insertions(+), 40 deletions(-)
diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go
index 49f4a5e6a7d6a..08cdbf2694472 100644
--- a/src/cmd/dist/build.go
+++ b/src/cmd/dist/build.go
@@ -9,6 +9,7 @@ import (
"encoding/json"
"flag"
"fmt"
+ "io/ioutil"
"log"
"os"
"os/exec"
@@ -682,7 +683,7 @@ func runInstall(dir string, ch chan struct{}) {
}
// Is the target up-to-date?
- var gofiles, missing []string
+ var gofiles, sfiles, missing []string
stale := rebuildall
files = filter(files, func(p string) bool {
for _, suf := range depsuffix {
@@ -698,6 +699,8 @@ func runInstall(dir string, ch chan struct{}) {
}
if strings.HasSuffix(p, ".go") {
gofiles = append(gofiles, p)
+ } else if strings.HasSuffix(p, ".s") {
+ sfiles = append(sfiles, p)
}
if t.After(ttarg) {
stale = true
@@ -778,10 +781,42 @@ func runInstall(dir string, ch chan struct{}) {
return
}
+ asmArgs := []string{
+ pathf("%s/asm", tooldir),
+ "-I", workdir,
+ "-I", pathf("%s/pkg/include", goroot),
+ "-D", "GOOS_" + goos,
+ "-D", "GOARCH_" + goarch,
+ "-D", "GOOS_GOARCH_" + goos + "_" + goarch,
+ }
+ if goarch == "mips" || goarch == "mipsle" {
+ // Define GOMIPS_value from gomips.
+ asmArgs = append(asmArgs, "-D", "GOMIPS_"+gomips)
+ }
+ if goarch == "mips64" || goarch == "mipsle64" {
+ // Define GOMIPS64_value from gomips64.
+ asmArgs = append(asmArgs, "-D", "GOMIPS64_"+gomips64)
+ }
+ goasmh := pathf("%s/go_asm.h", workdir)
+
+ // Collect symabis from assembly code.
+ var symabis string
+ if len(sfiles) > 0 {
+ symabis = pathf("%s/symabis", workdir)
+ var wg sync.WaitGroup
+ asmabis := append(asmArgs[:len(asmArgs):len(asmArgs)], "-symabis", "-o", symabis)
+ asmabis = append(asmabis, sfiles...)
+ if err := ioutil.WriteFile(goasmh, nil, 0666); err != nil {
+ fatalf("cannot write empty go_asm.h: %s", err)
+ }
+ bgrun(&wg, path, asmabis...)
+ bgwait(&wg)
+ }
+
var archive string
// The next loop will compile individual non-Go files.
// Hand the Go files to the compiler en masse.
- // For package runtime, this writes go_asm.h, which
+ // For packages containing assembly, this writes go_asm.h, which
// the assembly files will need.
pkg := dir
if strings.HasPrefix(dir, "cmd/") && strings.Count(dir, "/") == 1 {
@@ -794,18 +829,22 @@ func runInstall(dir string, ch chan struct{}) {
} else {
archive = b
}
+
+ // Compile Go code.
compile := []string{pathf("%s/compile", tooldir), "-std", "-pack", "-o", b, "-p", pkg}
if gogcflags != "" {
compile = append(compile, strings.Fields(gogcflags)...)
}
if dir == "runtime" {
- compile = append(compile, "-+", "-asmhdr", pathf("%s/go_asm.h", workdir))
+ compile = append(compile, "-+")
+ }
+ if len(sfiles) > 0 {
+ compile = append(compile, "-asmhdr", goasmh)
}
- if dir == "internal/bytealg" {
- // TODO: why don't we generate go_asm.h for all packages
- // that have any assembly?
- compile = append(compile, "-asmhdr", pathf("%s/go_asm.h", workdir))
+ if symabis != "" {
+ compile = append(compile, "-symabis", symabis)
}
+
compile = append(compile, gofiles...)
var wg sync.WaitGroup
// We use bgrun and immediately wait for it instead of calling run() synchronously.
@@ -815,31 +854,9 @@ func runInstall(dir string, ch chan struct{}) {
bgwait(&wg)
// Compile the files.
- for _, p := range files {
- if !strings.HasSuffix(p, ".s") {
- continue
- }
-
- var compile []string
+ for _, p := range sfiles {
// Assembly file for a Go package.
- compile = []string{
- pathf("%s/asm", tooldir),
- "-I", workdir,
- "-I", pathf("%s/pkg/include", goroot),
- "-D", "GOOS_" + goos,
- "-D", "GOARCH_" + goarch,
- "-D", "GOOS_GOARCH_" + goos + "_" + goarch,
- }
-
- if goarch == "mips" || goarch == "mipsle" {
- // Define GOMIPS_value from gomips.
- compile = append(compile, "-D", "GOMIPS_"+gomips)
- }
-
- if goarch == "mips64" || goarch == "mipsle64" {
- // Define GOMIPS64_value from gomips64.
- compile = append(compile, "-D", "GOMIPS64_"+gomips64)
- }
+ compile := asmArgs[:len(asmArgs):len(asmArgs)]
doclean := true
b := pathf("%s/%s", workdir, filepath.Base(p))
diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
index 92e814ee6f265..a7f9058b58e87 100644
--- a/src/cmd/go/internal/work/exec.go
+++ b/src/cmd/go/internal/work/exec.go
@@ -601,6 +601,12 @@ func (b *Builder) build(a *Action) (err error) {
return nil
}
+ // Collect symbol ABI requirements from assembly.
+ symabis, err := BuildToolchain.symabis(b, a, sfiles)
+ if err != nil {
+ return err
+ }
+
// Prepare Go import config.
// We start it off with a comment so it can't be empty, so icfg.Bytes() below is never nil.
// It should never be empty anyway, but there have been bugs in the past that resulted
@@ -632,7 +638,7 @@ func (b *Builder) build(a *Action) (err error) {
// Compile Go.
objpkg := objdir + "_pkg_.a"
- ofile, out, err := BuildToolchain.gc(b, a, objpkg, icfg.Bytes(), len(sfiles) > 0, gofiles)
+ ofile, out, err := BuildToolchain.gc(b, a, objpkg, icfg.Bytes(), symabis, len(sfiles) > 0, gofiles)
if len(out) > 0 {
output := b.processOutput(out)
if p.Module != nil && !allowedVersion(p.Module.GoVersion) {
@@ -1967,13 +1973,18 @@ func mkAbs(dir, f string) string {
type toolchain interface {
// gc runs the compiler in a specific directory on a set of files
// and returns the name of the generated output file.
- gc(b *Builder, a *Action, archive string, importcfg []byte, asmhdr bool, gofiles []string) (ofile string, out []byte, err error)
+ //
+ // TODO: This argument list is long. Consider putting it in a struct.
+ gc(b *Builder, a *Action, archive string, importcfg []byte, symabis string, asmhdr bool, gofiles []string) (ofile string, out []byte, err error)
// cc runs the toolchain's C compiler in a directory on a C file
// to produce an output file.
cc(b *Builder, a *Action, ofile, cfile string) error
// asm runs the assembler in a specific directory on specific files
// and returns a list of named output files.
asm(b *Builder, a *Action, sfiles []string) ([]string, error)
+ // symabis scans the symbol ABIs from sfiles and returns the
+ // path to the output symbol ABIs file, or "" if none.
+ symabis(b *Builder, a *Action, sfiles []string) (string, error)
// pack runs the archive packer in a specific directory to create
// an archive from a set of object files.
// typically it is run in the object directory.
@@ -2004,7 +2015,7 @@ func (noToolchain) linker() string {
return ""
}
-func (noToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, asmhdr bool, gofiles []string) (ofile string, out []byte, err error) {
+func (noToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, symabis string, asmhdr bool, gofiles []string) (ofile string, out []byte, err error) {
return "", nil, noCompiler()
}
@@ -2012,6 +2023,10 @@ func (noToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error)
return nil, noCompiler()
}
+func (noToolchain) symabis(b *Builder, a *Action, sfiles []string) (string, error) {
+ return "", noCompiler()
+}
+
func (noToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) error {
return noCompiler()
}
@@ -2695,7 +2710,7 @@ func (b *Builder) swigDoIntSize(objdir string) (intsize string, err error) {
p := load.GoFilesPackage(srcs)
- if _, _, e := BuildToolchain.gc(b, &Action{Mode: "swigDoIntSize", Package: p, Objdir: objdir}, "", nil, false, srcs); e != nil {
+ if _, _, e := BuildToolchain.gc(b, &Action{Mode: "swigDoIntSize", Package: p, Objdir: objdir}, "", nil, "", false, srcs); e != nil {
return "32", nil
}
return "64", nil
diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go
index 5a0bd1c2cf108..fed4a0b8cf266 100644
--- a/src/cmd/go/internal/work/gc.go
+++ b/src/cmd/go/internal/work/gc.go
@@ -36,7 +36,7 @@ func (gcToolchain) linker() string {
return base.Tool("link")
}
-func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) {
+func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, symabis string, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) {
p := a.Package
objdir := a.Objdir
if archive != "" {
@@ -98,6 +98,9 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, a
if strings.HasPrefix(runtimeVersion, "go1") && !strings.Contains(os.Args[0], "go_bootstrap") {
gcargs = append(gcargs, "-goversion", runtimeVersion)
}
+ if symabis != "" {
+ gcargs = append(gcargs, "-symabis", symabis)
+ }
gcflags := str.StringList(forcedGcflags, p.Internal.Gcflags)
if compilingRuntime {
@@ -218,8 +221,7 @@ func trimDir(dir string) string {
return dir
}
-func (gcToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error) {
- p := a.Package
+func asmArgs(a *Action, p *load.Package) []interface{} {
// Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files.
inc := filepath.Join(cfg.GOROOT, "pkg", "include")
args := []interface{}{cfg.BuildToolexec, base.Tool("asm"), "-trimpath", trimDir(a.Objdir), "-I", a.Objdir, "-I", inc, "-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch, forcedAsmflags, p.Internal.Asmflags}
@@ -241,6 +243,13 @@ func (gcToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error)
args = append(args, "-D", "GOMIPS64_"+cfg.GOMIPS64)
}
+ return args
+}
+
+func (gcToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error) {
+ p := a.Package
+ args := asmArgs(a, p)
+
var ofiles []string
for _, sfile := range sfiles {
ofile := a.Objdir + sfile[:len(sfile)-len(".s")] + ".o"
@@ -253,6 +262,32 @@ func (gcToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error)
return ofiles, nil
}
+func (gcToolchain) symabis(b *Builder, a *Action, sfiles []string) (string, error) {
+ if len(sfiles) == 0 {
+ return "", nil
+ }
+
+ p := a.Package
+ symabis := a.Objdir + "symabis"
+ args := asmArgs(a, p)
+ args = append(args, "-symabis", "-o", symabis)
+ for _, sfile := range sfiles {
+ args = append(args, mkAbs(p.Dir, sfile))
+ }
+
+ // Supply an empty go_asm.h as if the compiler had been run.
+ // -symabis parsing is lax enough that we don't need the
+ // actual definitions that would appear in go_asm.h.
+ if err := b.writeFile(a.Objdir+"go_asm.h", nil); err != nil {
+ return "", err
+ }
+
+ if err := b.run(a, p.Dir, p.ImportPath, nil, args...); err != nil {
+ return "", err
+ }
+ return symabis, nil
+}
+
// toolVerify checks that the command line args writes the same output file
// if run using newTool instead.
// Unused now but kept around for future use.
diff --git a/src/cmd/go/internal/work/gccgo.go b/src/cmd/go/internal/work/gccgo.go
index b89d07ead0a38..784a4ae1b3fa5 100644
--- a/src/cmd/go/internal/work/gccgo.go
+++ b/src/cmd/go/internal/work/gccgo.go
@@ -51,7 +51,7 @@ func checkGccgoBin() {
os.Exit(2)
}
-func (tools gccgoToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) {
+func (tools gccgoToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, symabis string, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) {
p := a.Package
objdir := a.Objdir
out := "_go_.o"
@@ -172,6 +172,10 @@ func (tools gccgoToolchain) asm(b *Builder, a *Action, sfiles []string) ([]strin
return ofiles, nil
}
+func (gccgoToolchain) symabis(b *Builder, a *Action, sfiles []string) (string, error) {
+ return "", nil
+}
+
func gccgoArchive(basedir, imp string) string {
end := filepath.FromSlash(imp + ".a")
afile := filepath.Join(basedir, end)
diff --git a/test/run.go b/test/run.go
index 6a050b0049d7c..a01fd6a9574ce 100644
--- a/test/run.go
+++ b/test/run.go
@@ -807,10 +807,23 @@ func (t *test) run() {
}
}
+ if len(asms) > 0 {
+ if err := ioutil.WriteFile(filepath.Join(longdir, "go_asm.h"), nil, 0666); err != nil {
+ t.err = fmt.Errorf("write empty go_asm.h: %s", err)
+ return
+ }
+ cmd := []string{goTool(), "tool", "asm", "-symabis", "-o", "symabis"}
+ cmd = append(cmd, asms...)
+ _, err = runcmd(cmd...)
+ if err != nil {
+ t.err = err
+ break
+ }
+ }
var objs []string
cmd := []string{goTool(), "tool", "compile", "-e", "-D", ".", "-I", ".", "-o", "go.o"}
if len(asms) > 0 {
- cmd = append(cmd, "-asmhdr", "go_asm.h")
+ cmd = append(cmd, "-asmhdr", "go_asm.h", "-symabis", "symabis")
}
cmd = append(cmd, gos...)
_, err := runcmd(cmd...)
From 07544c7e80a7559973930befca8c8744f43df3ce Mon Sep 17 00:00:00 2001
From: Austin Clements
Date: Fri, 2 Nov 2018 16:38:52 -0400
Subject: [PATCH 006/594] cmd/go, cmd/dist: collect known cross-package uses of
runtime symbols
This extends cmd/go's symabis support to collect known cross-package
uses of runtime symbols from other "basically runtime" packages in
std. This avoids having to declare a large number of ABI0 symbols in
the runtime for a small number of known cross-package references.
For cmd/dist, we use a simpler but less efficient approach and tell
the compiler to generate ABI wrappers for everything.
Change-Id: Ifaed94efdcff42e7345ab11b4d2fb880fb1a24e8
Reviewed-on: https://go-review.googlesource.com/c/147257
Run-TryBot: Austin Clements
TryBot-Result: Gobot Gobot
Reviewed-by: Ian Lance Taylor
---
src/cmd/dist/build.go | 7 +++
src/cmd/go/internal/work/exec.go | 19 ++++++++
src/cmd/go/internal/work/gc.go | 80 ++++++++++++++++++++++++++------
3 files changed, 91 insertions(+), 15 deletions(-)
diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go
index 08cdbf2694472..a94a43fd66459 100644
--- a/src/cmd/dist/build.go
+++ b/src/cmd/dist/build.go
@@ -844,6 +844,13 @@ func runInstall(dir string, ch chan struct{}) {
if symabis != "" {
compile = append(compile, "-symabis", symabis)
}
+ if dir == "runtime" || dir == "runtime/internal/atomic" {
+ // These packages define symbols referenced by
+ // assembly in other packages. In cmd/go, we work out
+ // the exact details. For bootstrapping, just tell the
+ // compiler to generate ABI wrappers for everything.
+ compile = append(compile, "-allabis")
+ }
compile = append(compile, gofiles...)
var wg sync.WaitGroup
diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
index a7f9058b58e87..d31f96591b727 100644
--- a/src/cmd/go/internal/work/exec.go
+++ b/src/cmd/go/internal/work/exec.go
@@ -1618,6 +1618,25 @@ func (b *Builder) writeFile(file string, text []byte) error {
return ioutil.WriteFile(file, text, 0666)
}
+// appendFile appends the text to file.
+func (b *Builder) appendFile(file string, text []byte) error {
+ if cfg.BuildN || cfg.BuildX {
+ b.Showcmd("", "cat >>%s << 'EOF' # internal\n%sEOF", file, text)
+ }
+ if cfg.BuildN {
+ return nil
+ }
+ f, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ if _, err = f.Write(text); err != nil {
+ return err
+ }
+ return f.Close()
+}
+
// Install the cgo export header file, if there is one.
func (b *Builder) installHeader(a *Action) error {
src := a.Objdir + "_cgo_install.h"
diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go
index fed4a0b8cf266..89ef2da8cb59f 100644
--- a/src/cmd/go/internal/work/gc.go
+++ b/src/cmd/go/internal/work/gc.go
@@ -263,28 +263,78 @@ func (gcToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error)
}
func (gcToolchain) symabis(b *Builder, a *Action, sfiles []string) (string, error) {
- if len(sfiles) == 0 {
- return "", nil
+ mkSymabis := func(p *load.Package, sfiles []string, path string) error {
+ args := asmArgs(a, p)
+ args = append(args, "-symabis", "-o", path)
+ for _, sfile := range sfiles {
+ if p.ImportPath == "runtime/cgo" && strings.HasPrefix(sfile, "gcc_") {
+ continue
+ }
+ args = append(args, mkAbs(p.Dir, sfile))
+ }
+
+ // Supply an empty go_asm.h as if the compiler had been run.
+ // -symabis parsing is lax enough that we don't need the
+ // actual definitions that would appear in go_asm.h.
+ if err := b.writeFile(a.Objdir+"go_asm.h", nil); err != nil {
+ return err
+ }
+
+ return b.run(a, p.Dir, p.ImportPath, nil, args...)
}
+ var symabis string // Only set if we actually create the file
p := a.Package
- symabis := a.Objdir + "symabis"
- args := asmArgs(a, p)
- args = append(args, "-symabis", "-o", symabis)
- for _, sfile := range sfiles {
- args = append(args, mkAbs(p.Dir, sfile))
+ if len(sfiles) != 0 {
+ symabis = a.Objdir + "symabis"
+ if err := mkSymabis(p, sfiles, symabis); err != nil {
+ return "", err
+ }
}
- // Supply an empty go_asm.h as if the compiler had been run.
- // -symabis parsing is lax enough that we don't need the
- // actual definitions that would appear in go_asm.h.
- if err := b.writeFile(a.Objdir+"go_asm.h", nil); err != nil {
- return "", err
- }
+ // Gather known cross-package references from assembly code.
+ var otherPkgs []string
+ if p.ImportPath == "runtime" {
+ // Assembly in syscall and runtime/cgo references
+ // symbols in runtime.
+ otherPkgs = []string{"syscall", "runtime/cgo"}
+ } else if p.ImportPath == "runtime/internal/atomic" {
+ // sync/atomic is an assembly wrapper around
+ // runtime/internal/atomic.
+ otherPkgs = []string{"sync/atomic"}
+ }
+ for _, p2name := range otherPkgs {
+ p2 := load.LoadPackage(p2name, &load.ImportStack{})
+ if len(p2.SFiles) == 0 {
+ continue
+ }
+
+ symabis2 := a.Objdir + "symabis2"
+ if err := mkSymabis(p2, p2.SFiles, symabis2); err != nil {
+ return "", err
+ }
- if err := b.run(a, p.Dir, p.ImportPath, nil, args...); err != nil {
- return "", err
+ // Filter out just the symbol refs and append them to
+ // the symabis file.
+ abis2, err := ioutil.ReadFile(symabis2)
+ if err != nil {
+ return "", err
+ }
+ var refs bytes.Buffer
+ for _, line := range strings.Split(string(abis2), "\n") {
+ fs := strings.Fields(line)
+ if len(fs) >= 2 && fs[0] == "ref" && !strings.HasPrefix(fs[1], `"".`) {
+ fmt.Fprintf(&refs, "%s\n", line)
+ }
+ }
+ if refs.Len() != 0 {
+ symabis = a.Objdir + "symabis"
+ if err := b.appendFile(symabis, refs.Bytes()); err != nil {
+ return "", err
+ }
+ }
}
+
return symabis, nil
}
From c5718b6b261a66aa47312037f17281d3d810c98c Mon Sep 17 00:00:00 2001
From: Austin Clements
Date: Fri, 26 Oct 2018 13:53:02 -0400
Subject: [PATCH 007/594] cmd/internal/obj, cmd/link: record ABIs and aliases
in Go obj files
This repurposes the "version" field of a symbol reference in the Go
object file format to be an ABI field. Currently, this is just 0 or 1
depending on whether the symbol is static (the linker turns it into a
different internal version number), so it's already only tenuously a
symbol version. We change this to be -1 for static symbols and
otherwise by the ABI number.
This also adds a separate list of ABI alias symbols to be recorded in
the object file. The ABI aliases must be a separate list and not just
part of the symbol definitions because it's possible to have a symbol
defined in one package and the alias "defined" in a different package.
For example, this can happen if a symbol is defined in assembly in one
package and stubbed in a different package. The stub triggers the
generation of the ABI alias, but in a different package from the
definition.
For #27539.
Change-Id: I015c9fe54690c027de6ef77e22b5585976a01587
Reviewed-on: https://go-review.googlesource.com/c/147157
Run-TryBot: Austin Clements
TryBot-Result: Gobot Gobot
Reviewed-by: David Chase
---
src/cmd/internal/goobj/read.go | 29 ++++++++++++++++------
src/cmd/internal/obj/link.go | 31 +++++++++++++++++++++++-
src/cmd/internal/obj/objfile.go | 19 ++++++++++++---
src/cmd/internal/objabi/doc.go | 8 +++---
src/cmd/link/internal/objfile/objfile.go | 20 +++++++++------
src/cmd/link/internal/sym/symbol.go | 15 +++++++++++-
6 files changed, 96 insertions(+), 26 deletions(-)
diff --git a/src/cmd/internal/goobj/read.go b/src/cmd/internal/goobj/read.go
index 2d618eefa557a..2081098ca8f80 100644
--- a/src/cmd/internal/goobj/read.go
+++ b/src/cmd/internal/goobj/read.go
@@ -288,18 +288,31 @@ func (r *objReader) readSymID() SymID {
}
func (r *objReader) readRef() {
- name, vers := r.readString(), r.readInt()
+ name, abiOrStatic := r.readString(), r.readInt()
// In a symbol name in an object file, "". denotes the
// prefix for the package in which the object file has been found.
// Expand it.
name = strings.ReplaceAll(name, `"".`, r.pkgprefix)
- // An individual object file only records version 0 (extern) or 1 (static).
- // To make static symbols unique across all files being read, we
- // replace version 1 with the version corresponding to the current
- // file number. The number is incremented on each call to parseObject.
- if vers != 0 {
+ // The ABI field records either the ABI or -1 for static symbols.
+ //
+ // To distinguish different static symbols with the same name,
+ // we use the symbol "version". Version 0 corresponds to
+ // global symbols, and each file has a unique version > 0 for
+ // all of its static symbols. The version is incremented on
+ // each call to parseObject.
+ //
+ // For global symbols, we currently ignore the ABI.
+ //
+ // TODO(austin): Record the ABI in SymID. Since this is a
+ // public API, we'll have to keep Version as 0 and record the
+ // ABI in a new field (which differs from how the linker does
+ // this, but that's okay). Show the ABI in things like
+ // objdump.
+ var vers int64
+ if abiOrStatic == -1 {
+ // Static symbol
vers = r.p.MaxVersion
}
r.p.SymRefs = append(r.p.SymRefs, SymID{name, vers})
@@ -487,7 +500,7 @@ func (r *objReader) parseObject(prefix []byte) error {
// TODO: extract OS + build ID if/when we need it
r.readFull(r.tmp[:8])
- if !bytes.Equal(r.tmp[:8], []byte("\x00\x00go19ld")) {
+ if !bytes.Equal(r.tmp[:8], []byte("\x00go112ld")) {
return r.error(errCorruptObject)
}
@@ -602,7 +615,7 @@ func (r *objReader) parseObject(prefix []byte) error {
}
r.readFull(r.tmp[:7])
- if !bytes.Equal(r.tmp[:7], []byte("\xffgo19ld")) {
+ if !bytes.Equal(r.tmp[:7], []byte("go112ld")) {
return r.error(errCorruptObject)
}
diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go
index d3721dd023466..2989831a0a63b 100644
--- a/src/cmd/internal/obj/link.go
+++ b/src/cmd/internal/obj/link.go
@@ -432,7 +432,7 @@ const (
)
// Attribute is a set of symbol attributes.
-type Attribute int16
+type Attribute uint16
const (
AttrDuplicateOK Attribute = 1 << iota
@@ -468,6 +468,13 @@ const (
// For function symbols; indicates that the specified function was the
// target of an inline during compilation
AttrWasInlined
+
+ // attrABIBase is the value at which the ABI is encoded in
+ // Attribute. This must be last; all bits after this are
+ // assumed to be an ABI value.
+ //
+ // MUST BE LAST since all bits above this comprise the ABI.
+ attrABIBase
)
func (a Attribute) DuplicateOK() bool { return a&AttrDuplicateOK != 0 }
@@ -493,6 +500,12 @@ func (a *Attribute) Set(flag Attribute, value bool) {
}
}
+func (a Attribute) ABI() ABI { return ABI(a / attrABIBase) }
+func (a *Attribute) SetABI(abi ABI) {
+ const mask = 1 // Only one ABI bit for now.
+ *a = (*a &^ (mask * attrABIBase)) | Attribute(abi)*attrABIBase
+}
+
var textAttrStrings = [...]struct {
bit Attribute
s string
@@ -524,6 +537,12 @@ func (a Attribute) TextAttrString() string {
a &^= x.bit
}
}
+ switch a.ABI() {
+ case ABI0:
+ case ABIInternal:
+ s += "ABIInternal|"
+ a.SetABI(0) // Clear ABI so we don't print below.
+ }
if a != 0 {
s += fmt.Sprintf("UnknownAttribute(%d)|", a)
}
@@ -606,6 +625,16 @@ type Link struct {
// state for writing objects
Text []*LSym
Data []*LSym
+
+ // ABIAliases are text symbols that should be aliased to all
+ // ABIs. These symbols may only be referenced and not defined
+ // by this object, since the need for an alias may appear in a
+ // different object than the definition. Hence, this
+ // information can't be carried in the symbol definition.
+ //
+ // TODO(austin): Replace this with ABI wrappers once the ABIs
+ // actually diverge.
+ ABIAliases []*LSym
}
func (ctxt *Link) Diag(format string, args ...interface{}) {
diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go
index 3c72f543ccb37..94334d8361b5e 100644
--- a/src/cmd/internal/obj/objfile.go
+++ b/src/cmd/internal/obj/objfile.go
@@ -82,7 +82,7 @@ func WriteObjFile(ctxt *Link, b *bufio.Writer) {
w := newObjWriter(ctxt, b)
// Magic header
- w.wr.WriteString("\x00\x00go19ld")
+ w.wr.WriteString("\x00go112ld")
// Version
w.wr.WriteByte(1)
@@ -102,6 +102,10 @@ func WriteObjFile(ctxt *Link, b *bufio.Writer) {
w.writeRefs(s)
w.addLengths(s)
}
+ for _, s := range ctxt.ABIAliases {
+ w.writeRefs(s)
+ w.addLengths(s)
+ }
// End symbol references
w.wr.WriteByte(0xff)
@@ -137,9 +141,12 @@ func WriteObjFile(ctxt *Link, b *bufio.Writer) {
for _, s := range ctxt.Data {
w.writeSym(s)
}
+ for _, s := range ctxt.ABIAliases {
+ w.writeSym(s)
+ }
// Magic footer
- w.wr.WriteString("\xff\xffgo19ld")
+ w.wr.WriteString("\xffgo112ld")
}
// Symbols are prefixed so their content doesn't get confused with the magic footer.
@@ -155,8 +162,12 @@ func (w *objWriter) writeRef(s *LSym, isPath bool) {
} else {
w.writeString(s.Name)
}
- // Write "version".
- w.writeBool(s.Static())
+ // Write ABI/static information.
+ abi := int64(s.ABI())
+ if s.Static() {
+ abi = -1
+ }
+ w.writeInt(abi)
w.nRefs++
s.RefIdx = w.nRefs
}
diff --git a/src/cmd/internal/objabi/doc.go b/src/cmd/internal/objabi/doc.go
index 7bd5ff63e562c..03dc9fb88bc76 100644
--- a/src/cmd/internal/objabi/doc.go
+++ b/src/cmd/internal/objabi/doc.go
@@ -22,7 +22,7 @@
//
// The file format is:
//
-// - magic header: "\x00\x00go19ld"
+// - magic header: "\x00go112ld"
// - byte 1 - version number
// - sequence of strings giving dependencies (imported packages)
// - empty string (marks end of sequence)
@@ -38,7 +38,7 @@
// - data, the content of the defined symbols
// - sequence of defined symbols
// - byte 0xff (marks end of sequence)
-// - magic footer: "\xff\xffgo19ld"
+// - magic footer: "\xffgo112ld"
//
// All integers are stored in a zigzag varint format.
// See golang.org/s/go12symtab for a definition.
@@ -46,7 +46,7 @@
// Data blocks and strings are both stored as an integer
// followed by that many bytes.
//
-// A symbol reference is a string name followed by a version.
+// A symbol reference is a string name followed by an ABI or -1 for static.
//
// A symbol points to other symbols using an index into the symbol
// reference sequence. Index 0 corresponds to a nil symbol pointer.
@@ -57,7 +57,7 @@
//
// - byte 0xfe (sanity check for synchronization)
// - type [byte]
-// - name & version [symref index]
+// - name & ABI [symref index]
// - flags [int]
// 1<<0 dupok
// 1<<1 local
diff --git a/src/cmd/link/internal/objfile/objfile.go b/src/cmd/link/internal/objfile/objfile.go
index 3a8923b07333f..77c3a7f9148c4 100644
--- a/src/cmd/link/internal/objfile/objfile.go
+++ b/src/cmd/link/internal/objfile/objfile.go
@@ -13,6 +13,7 @@ import (
"bytes"
"cmd/internal/bio"
"cmd/internal/dwarf"
+ "cmd/internal/obj"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/link/internal/sym"
@@ -23,8 +24,8 @@ import (
)
const (
- startmagic = "\x00\x00go19ld"
- endmagic = "\xff\xffgo19ld"
+ startmagic = "\x00go112ld"
+ endmagic = "\xffgo112ld"
)
var emptyPkg = []byte(`"".`)
@@ -382,17 +383,20 @@ func (r *objReader) readRef() {
log.Fatalf("readSym out of sync")
}
name := r.readSymName()
- v := r.readInt()
- if v != 0 && v != 1 {
- log.Fatalf("invalid symbol version for %q: %d", name, v)
- }
- if v == 1 {
+ var v int
+ if abi := r.readInt(); abi == -1 {
+ // Static
v = r.localSymVersion
+ } else if abiver := sym.ABIToVersion(obj.ABI(abi)); abiver != -1 {
+ // Note that data symbols are "ABI0", which maps to version 0.
+ v = abiver
+ } else {
+ log.Fatalf("invalid symbol ABI for %q: %d", name, abi)
}
s := r.syms.Lookup(name, v)
r.refs = append(r.refs, s)
- if s == nil || v != 0 {
+ if s == nil || v == r.localSymVersion {
return
}
if s.Name[0] == '$' && len(s.Name) > 5 && s.Type == 0 && len(s.P) == 0 {
diff --git a/src/cmd/link/internal/sym/symbol.go b/src/cmd/link/internal/sym/symbol.go
index 4faa991463b08..5e5fca467da2e 100644
--- a/src/cmd/link/internal/sym/symbol.go
+++ b/src/cmd/link/internal/sym/symbol.go
@@ -5,6 +5,7 @@
package sym
import (
+ "cmd/internal/obj"
"cmd/internal/objabi"
"cmd/internal/sys"
"debug/elf"
@@ -52,9 +53,21 @@ type AuxSymbol struct {
}
const (
- SymVerStatic = 10 // Minimum version used by static (file-local) syms
+ SymVerABI0 = 0
+ SymVerABIInternal = 1
+ SymVerStatic = 10 // Minimum version used by static (file-local) syms
)
+func ABIToVersion(abi obj.ABI) int {
+ switch abi {
+ case obj.ABI0:
+ return SymVerABI0
+ case obj.ABIInternal:
+ return SymVerABIInternal
+ }
+ return -1
+}
+
func (s *Symbol) String() string {
if s.Version == 0 {
return s.Name
From 16e6cd9a4dc499db164624a048f25e2f382ac016 Mon Sep 17 00:00:00 2001
From: Austin Clements
Date: Thu, 1 Nov 2018 12:20:28 -0400
Subject: [PATCH 008/594] cmd/compile: mark function Syms
In order to mark the obj.LSyms produced by the compiler with the
correct ABI, we need to know which types.Syms refer to function
symbols. This CL adds a flag to types.Syms to mark symbols for
functions, and sets this flag everywhere we create a PFUNC-class node,
and in the one place where we directly create function symbols without
always wrapping them in a PFUNC node (methodSym).
We'll use this information to construct obj.LSyms with correct ABI
information.
For #27539.
Change-Id: Ie3ac8bf3da013e449e78f6ca85546a055f275463
Reviewed-on: https://go-review.googlesource.com/c/147158
Run-TryBot: Austin Clements
TryBot-Result: Gobot Gobot
Reviewed-by: David Chase
Reviewed-by: Keith Randall
---
src/cmd/compile/internal/gc/alg.go | 1 +
src/cmd/compile/internal/gc/dcl.go | 9 ++++++++-
src/cmd/compile/internal/gc/export.go | 3 +++
src/cmd/compile/internal/gc/iimport.go | 1 +
src/cmd/compile/internal/gc/main.go | 5 +++++
src/cmd/compile/internal/gc/ssa.go | 1 +
src/cmd/compile/internal/gc/subr.go | 1 +
src/cmd/compile/internal/gc/typecheck.go | 1 +
src/cmd/compile/internal/gc/walk.go | 1 +
src/cmd/compile/internal/types/sym.go | 3 +++
10 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/src/cmd/compile/internal/gc/alg.go b/src/cmd/compile/internal/gc/alg.go
index b112ff679723c..f52c15b1f5c3c 100644
--- a/src/cmd/compile/internal/gc/alg.go
+++ b/src/cmd/compile/internal/gc/alg.go
@@ -330,6 +330,7 @@ func hashfor(t *types.Type) *Node {
n := newname(sym)
n.SetClass(PFUNC)
+ n.Sym.SetFunc(true)
n.Type = functype(nil, []*Node{
anonfield(types.NewPtr(t)),
anonfield(types.Types[TUINTPTR]),
diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go
index 645ba7558c1cd..d4d0708b1c876 100644
--- a/src/cmd/compile/internal/gc/dcl.go
+++ b/src/cmd/compile/internal/gc/dcl.go
@@ -125,6 +125,9 @@ func declare(n *Node, ctxt Class) {
s.Def = asTypesNode(n)
n.Name.Vargen = int32(gen)
n.SetClass(ctxt)
+ if ctxt == PFUNC {
+ n.Sym.SetFunc(true)
+ }
autoexport(n, ctxt)
}
@@ -801,8 +804,12 @@ func origSym(s *types.Sym) *types.Sym {
// Method symbols can be used to distinguish the same method appearing
// in different method sets. For example, T.M and (*T).M have distinct
// method symbols.
+//
+// The returned symbol will be marked as a function.
func methodSym(recv *types.Type, msym *types.Sym) *types.Sym {
- return methodSymSuffix(recv, msym, "")
+ sym := methodSymSuffix(recv, msym, "")
+ sym.SetFunc(true)
+ return sym
}
// methodSymSuffix is like methodsym, but allows attaching a
diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go
index 85916509cb9f2..4fe1f8b95f12d 100644
--- a/src/cmd/compile/internal/gc/export.go
+++ b/src/cmd/compile/internal/gc/export.go
@@ -140,6 +140,9 @@ func importobj(ipkg *types.Pkg, pos src.XPos, s *types.Sym, op Op, ctxt Class, t
n.Op = op
n.Pos = pos
n.SetClass(ctxt)
+ if ctxt == PFUNC {
+ n.Sym.SetFunc(true)
+ }
n.Type = t
return n
}
diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go
index 8614c7a14f383..c9198499dd643 100644
--- a/src/cmd/compile/internal/gc/iimport.go
+++ b/src/cmd/compile/internal/gc/iimport.go
@@ -334,6 +334,7 @@ func (r *importReader) doDecl(n *Node) {
m := newfuncnamel(mpos, methodSym(recv.Type, msym))
m.Type = mtyp
m.SetClass(PFUNC)
+ // methodSym already marked m.Sym as a function.
// (comment from parser.go)
// inl.C's inlnode in on a dotmeth node expects to find the inlineable body as
diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go
index 55d6d55e6dfc8..087371c6f6c9c 100644
--- a/src/cmd/compile/internal/gc/main.go
+++ b/src/cmd/compile/internal/gc/main.go
@@ -649,6 +649,11 @@ func Main(archInit func(*Arch)) {
Curfn = nil
peekitabs()
+ // The "init" function is the only user-spellable symbol that
+ // we construct later. Mark it as a function now before
+ // anything can ask for its Linksym.
+ lookup("init").SetFunc(true)
+
// Phase 8: Compile top level functions.
// Don't use range--walk can add functions to xtop.
timings.Start("be", "compilefuncs")
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index b0ccd01752470..d43dc8e617596 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -3670,6 +3670,7 @@ func (s *state) call(n *Node, k callKind) *ssa.Value {
n2 := newnamel(fn.Pos, fn.Sym)
n2.Name.Curfn = s.curfn
n2.SetClass(PFUNC)
+ n2.Sym.SetFunc(true)
n2.Pos = fn.Pos
n2.Type = types.Types[TUINT8] // dummy type for a static closure. Could use runtime.funcval if we had it.
closure = s.expr(n2)
diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go
index 97f7e4880d9c7..53bfcba3ffc7b 100644
--- a/src/cmd/compile/internal/gc/subr.go
+++ b/src/cmd/compile/internal/gc/subr.go
@@ -1619,6 +1619,7 @@ func hashmem(t *types.Type) *Node {
n := newname(sym)
n.SetClass(PFUNC)
+ n.Sym.SetFunc(true)
n.Type = functype(nil, []*Node{
anonfield(types.NewPtr(t)),
anonfield(types.Types[TUINTPTR]),
diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
index e6a8ed4bda149..371e0924e7155 100644
--- a/src/cmd/compile/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -2513,6 +2513,7 @@ func typecheckMethodExpr(n *Node) (res *Node) {
n.Type = methodfunc(m.Type, n.Left.Type)
n.Xoffset = 0
n.SetClass(PFUNC)
+ // methodSym already marked n.Sym as a function.
return n
}
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index 37d995b1bdf8c..5056212984ca8 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -3063,6 +3063,7 @@ func eqfor(t *types.Type) (n *Node, needsize bool) {
sym := typesymprefix(".eq", t)
n := newname(sym)
n.SetClass(PFUNC)
+ n.Sym.SetFunc(true)
n.Type = functype(nil, []*Node{
anonfield(types.NewPtr(t)),
anonfield(types.NewPtr(t)),
diff --git a/src/cmd/compile/internal/types/sym.go b/src/cmd/compile/internal/types/sym.go
index b7fd7ae9fbbbe..28583378d9dbe 100644
--- a/src/cmd/compile/internal/types/sym.go
+++ b/src/cmd/compile/internal/types/sym.go
@@ -42,6 +42,7 @@ const (
symSiggen // type symbol has been generated
symAsm // on asmlist, for writing to -asmhdr
symAlgGen // algorithm table has been generated
+ symFunc // function symbol; uses internal ABI
)
func (sym *Sym) OnExportList() bool { return sym.flags&symOnExportList != 0 }
@@ -49,12 +50,14 @@ func (sym *Sym) Uniq() bool { return sym.flags&symUniq != 0 }
func (sym *Sym) Siggen() bool { return sym.flags&symSiggen != 0 }
func (sym *Sym) Asm() bool { return sym.flags&symAsm != 0 }
func (sym *Sym) AlgGen() bool { return sym.flags&symAlgGen != 0 }
+func (sym *Sym) Func() bool { return sym.flags&symFunc != 0 }
func (sym *Sym) SetOnExportList(b bool) { sym.flags.set(symOnExportList, b) }
func (sym *Sym) SetUniq(b bool) { sym.flags.set(symUniq, b) }
func (sym *Sym) SetSiggen(b bool) { sym.flags.set(symSiggen, b) }
func (sym *Sym) SetAsm(b bool) { sym.flags.set(symAsm, b) }
func (sym *Sym) SetAlgGen(b bool) { sym.flags.set(symAlgGen, b) }
+func (sym *Sym) SetFunc(b bool) { sym.flags.set(symFunc, b) }
func (sym *Sym) IsBlank() bool {
return sym != nil && sym.Name == "_"
From 1794ee682994ed2efbb9371060856cd7b146f405 Mon Sep 17 00:00:00 2001
From: Austin Clements
Date: Wed, 31 Oct 2018 20:42:38 -0400
Subject: [PATCH 009/594] cmd/link: nice error message on ABI mismatch
Currently, if a symbol is only defined under one ABI and referenced
under another ABI, you simply get a "relocation target X not defined".
This is confusing because it seems like the symbol is defined.
This CL enhances the error message in this case to be "relocation
target X not defined for (but is defined for )".
For #27539.
Change-Id: If857a1882c3fe9af5346797d5295ca1fe50ae565
Reviewed-on: https://go-review.googlesource.com/c/147159
Run-TryBot: Austin Clements
TryBot-Result: Gobot Gobot
Reviewed-by: Keith Randall
---
src/cmd/link/internal/ld/link.go | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/src/cmd/link/internal/ld/link.go b/src/cmd/link/internal/ld/link.go
index 48b92724b6fe0..f3f1bba773a25 100644
--- a/src/cmd/link/internal/ld/link.go
+++ b/src/cmd/link/internal/ld/link.go
@@ -32,6 +32,7 @@ package ld
import (
"bufio"
+ "cmd/internal/obj"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/link/internal/sym"
@@ -108,9 +109,27 @@ func (ctxt *Link) ErrorUnresolved(s *sym.Symbol, r *sym.Reloc) {
k := unresolvedSymKey{from: s, to: r.Sym}
if !ctxt.unresolvedSymSet[k] {
ctxt.unresolvedSymSet[k] = true
+
+ // Try to find symbol under another ABI.
+ var reqABI, haveABI obj.ABI
+ haveABI = ^obj.ABI(0)
+ for abi := obj.ABI(0); abi < obj.ABICount; abi++ {
+ v := sym.ABIToVersion(abi)
+ if v == -1 {
+ continue
+ }
+ if v == int(r.Sym.Version) {
+ reqABI = abi
+ } else if ctxt.Syms.ROLookup(r.Sym.Name, v) != nil {
+ haveABI = abi
+ }
+ }
+
// Give a special error message for main symbol (see #24809).
if r.Sym.Name == "main.main" {
Errorf(s, "function main is undeclared in the main package")
+ } else if haveABI != ^obj.ABI(0) {
+ Errorf(s, "relocation target %s not defined for %s (but is defined for %s)", r.Sym.Name, reqABI, haveABI)
} else {
Errorf(s, "relocation target %s not defined", r.Sym.Name)
}
From 685aca45dc8435df7b7e8059a42a8a98efdaf22c Mon Sep 17 00:00:00 2001
From: Austin Clements
Date: Thu, 1 Nov 2018 12:30:23 -0400
Subject: [PATCH 010/594] cmd/compile, cmd/link: separate stable and internal
ABIs
This implements compiler and linker support for separating the
function calling ABI into two ABIs: a stable and an internal ABI. At
the moment, the two ABIs are identical, but we'll be able to evolve
the internal ABI without breaking existing assembly code that depends
on the stable ABI for calling to and from Go.
The Go compiler generates internal ABI symbols for all Go functions.
It uses the symabis information produced by the assembler to create
ABI wrappers whenever it encounters a body-less Go function that's
defined in assembly or a Go function that's referenced from assembly.
Since the two ABIs are currently identical, for the moment this is
implemented using "ABI alias" symbols, which are just forwarding
references to the native ABI symbol for a function. This way there's
no actual code involved in the ABI wrapper, which is good because
we're not deriving any benefit from it right now. Once the ABIs
diverge, we can eliminate ABI aliases.
The linker represents these different ABIs internally as different
versions of the same symbol. This way, the linker keeps us honest,
since every symbol definition and reference also specifies its
version. The linker is responsible for resolving ABI aliases.
Fixes #27539.
Change-Id: I197c52ec9f8fc435db8f7a4259029b20f6d65e95
Reviewed-on: https://go-review.googlesource.com/c/147160
Run-TryBot: Austin Clements
TryBot-Result: Gobot Gobot
Reviewed-by: David Chase
---
src/cmd/compile/internal/gc/gen.go | 11 ++++
src/cmd/compile/internal/gc/gsubr.go | 63 ++++++++++++++++++++-
src/cmd/compile/internal/gc/noder.go | 13 +++++
src/cmd/compile/internal/gc/pgen.go | 4 +-
src/cmd/compile/internal/gc/reflect.go | 4 +-
src/cmd/compile/internal/gc/ssa.go | 40 ++++++-------
src/cmd/compile/internal/types/sym.go | 6 ++
src/cmd/internal/obj/arm/asm5.go | 1 +
src/cmd/internal/obj/wasm/wasmobj.go | 2 +
src/cmd/internal/obj/x86/asm6.go | 1 +
src/cmd/internal/objabi/symkind.go | 7 +++
src/cmd/internal/objabi/symkind_string.go | 4 +-
src/cmd/link/internal/ld/deadcode.go | 12 +++-
src/cmd/link/internal/ld/go.go | 16 ++++++
src/cmd/link/internal/ld/lib.go | 32 ++++++++++-
src/cmd/link/internal/ld/symtab.go | 2 +-
src/cmd/link/internal/ppc64/asm.go | 2 +-
src/cmd/link/internal/sym/symbols.go | 2 +
src/cmd/link/internal/sym/symkind.go | 4 ++
src/cmd/link/internal/sym/symkind_string.go | 4 +-
20 files changed, 196 insertions(+), 34 deletions(-)
diff --git a/src/cmd/compile/internal/gc/gen.go b/src/cmd/compile/internal/gc/gen.go
index f9b4584cf6bcd..43d12925eb3b9 100644
--- a/src/cmd/compile/internal/gc/gen.go
+++ b/src/cmd/compile/internal/gc/gen.go
@@ -11,7 +11,18 @@ import (
"strconv"
)
+// sysfunc looks up Go function name in package runtime. This function
+// must follow the internal calling convention.
func sysfunc(name string) *obj.LSym {
+ s := Runtimepkg.Lookup(name)
+ s.SetFunc(true)
+ return s.Linksym()
+}
+
+// sysvar looks up a variable (or assembly function) name in package
+// runtime. If this is a function, it may have a special calling
+// convention.
+func sysvar(name string) *obj.LSym {
return Runtimepkg.Lookup(name).Linksym()
}
diff --git a/src/cmd/compile/internal/gc/gsubr.go b/src/cmd/compile/internal/gc/gsubr.go
index 16602b9988233..01ac4cb929be7 100644
--- a/src/cmd/compile/internal/gc/gsubr.go
+++ b/src/cmd/compile/internal/gc/gsubr.go
@@ -187,7 +187,13 @@ func (pp *Progs) settext(fn *Node) {
ptxt.From.Sym = fn.Func.lsym
}
-func (f *Func) initLSym() {
+// initLSym defines f's obj.LSym and initializes it based on the
+// properties of f. This includes setting the symbol flags and ABI and
+// creating and initializing related DWARF symbols.
+//
+// initLSym must be called exactly once per function and must be
+// called for both functions with bodies and functions without bodies.
+func (f *Func) initLSym(hasBody bool) {
if f.lsym != nil {
Fatalf("Func.initLSym called twice")
}
@@ -197,6 +203,61 @@ func (f *Func) initLSym() {
if f.Pragma&Systemstack != 0 {
f.lsym.Set(obj.AttrCFunc, true)
}
+
+ var aliasABI obj.ABI
+ needABIAlias := false
+ if abi, ok := symabiDefs[f.lsym.Name]; ok && abi == obj.ABI0 {
+ // Symbol is defined as ABI0. Create an
+ // Internal -> ABI0 wrapper.
+ f.lsym.SetABI(obj.ABI0)
+ needABIAlias, aliasABI = true, obj.ABIInternal
+ } else {
+ // No ABI override. Check that the symbol is
+ // using the expected ABI.
+ want := obj.ABIInternal
+ if f.lsym.ABI() != want {
+ Fatalf("function symbol %s has the wrong ABI %v, expected %v", f.lsym, f.lsym.ABI(), want)
+ }
+ }
+
+ if abi, ok := symabiRefs[f.lsym.Name]; ok && abi == obj.ABI0 {
+ // Symbol is referenced as ABI0. Create an
+ // ABI0 -> Internal wrapper if necessary.
+ if f.lsym.ABI() != obj.ABI0 {
+ needABIAlias, aliasABI = true, obj.ABI0
+ }
+ }
+
+ if !needABIAlias && allABIs {
+ // The compiler was asked to produce ABI
+ // wrappers for everything.
+ switch f.lsym.ABI() {
+ case obj.ABI0:
+ needABIAlias, aliasABI = true, obj.ABIInternal
+ case obj.ABIInternal:
+ needABIAlias, aliasABI = true, obj.ABI0
+ }
+ }
+
+ if needABIAlias {
+ // These LSyms have the same name as the
+ // native function, so we create them directly
+ // rather than looking them up. The uniqueness
+ // of f.lsym ensures uniqueness of asym.
+ asym := &obj.LSym{
+ Name: f.lsym.Name,
+ Type: objabi.SABIALIAS,
+ R: []obj.Reloc{{Sym: f.lsym}}, // 0 size, so "informational"
+ }
+ asym.SetABI(aliasABI)
+ asym.Set(obj.AttrDuplicateOK, true)
+ Ctxt.ABIAliases = append(Ctxt.ABIAliases, asym)
+ }
+ }
+
+ if !hasBody {
+ // For body-less functions, we only create the LSym.
+ return
}
var flag int
diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go
index f13d2cdbb5594..a2ed103c80c7a 100644
--- a/src/cmd/compile/internal/gc/noder.go
+++ b/src/cmd/compile/internal/gc/noder.go
@@ -15,6 +15,7 @@ import (
"cmd/compile/internal/syntax"
"cmd/compile/internal/types"
+ "cmd/internal/obj"
"cmd/internal/objabi"
"cmd/internal/src"
)
@@ -250,6 +251,18 @@ func (p *noder) node() {
}
}
+ // The linker expects an ABI0 wrapper for all cgo-exported
+ // functions.
+ for _, prag := range p.pragcgobuf {
+ switch prag[0] {
+ case "cgo_export_static", "cgo_export_dynamic":
+ if symabiRefs == nil {
+ symabiRefs = make(map[string]obj.ABI)
+ }
+ symabiRefs[prag[1]] = obj.ABI0
+ }
+ }
+
pragcgobuf = append(pragcgobuf, p.pragcgobuf...)
lineno = src.NoXPos
clearImports()
diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go
index 01dacb783bf86..d567cfe14989b 100644
--- a/src/cmd/compile/internal/gc/pgen.go
+++ b/src/cmd/compile/internal/gc/pgen.go
@@ -198,6 +198,8 @@ func funccompile(fn *Node) {
dowidth(fn.Type)
if fn.Nbody.Len() == 0 {
+ // Initialize ABI wrappers if necessary.
+ fn.Func.initLSym(false)
emitptrargsmap(fn)
return
}
@@ -231,7 +233,7 @@ func compile(fn *Node) {
Curfn = nil
// Set up the function's LSym early to avoid data races with the assemblers.
- fn.Func.initLSym()
+ fn.Func.initLSym(true)
// Make sure type syms are declared for all types that might
// be types of stack objects. We need to do this here
diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go
index 50b741358f41e..130c83036c970 100644
--- a/src/cmd/compile/internal/gc/reflect.go
+++ b/src/cmd/compile/internal/gc/reflect.go
@@ -801,7 +801,7 @@ var (
func dcommontype(lsym *obj.LSym, t *types.Type) int {
sizeofAlg := 2 * Widthptr
if algarray == nil {
- algarray = sysfunc("algarray")
+ algarray = sysvar("algarray")
}
dowidth(t)
alg := algtype(t)
@@ -1618,7 +1618,7 @@ func dalgsym(t *types.Type) *obj.LSym {
if memhashvarlen == nil {
memhashvarlen = sysfunc("memhash_varlen")
- memequalvarlen = sysfunc("memequal_varlen")
+ memequalvarlen = sysvar("memequal_varlen") // asm func
}
// make hash closure
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index d43dc8e617596..883cf7936d3b0 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -68,9 +68,9 @@ func initssaconfig() {
assertI2I2 = sysfunc("assertI2I2")
deferproc = sysfunc("deferproc")
Deferreturn = sysfunc("deferreturn")
- Duffcopy = sysfunc("duffcopy")
- Duffzero = sysfunc("duffzero")
- gcWriteBarrier = sysfunc("gcWriteBarrier")
+ Duffcopy = sysvar("duffcopy") // asm func with special ABI
+ Duffzero = sysvar("duffzero") // asm func with special ABI
+ gcWriteBarrier = sysvar("gcWriteBarrier") // asm func with special ABI
goschedguarded = sysfunc("goschedguarded")
growslice = sysfunc("growslice")
msanread = sysfunc("msanread")
@@ -86,25 +86,25 @@ func initssaconfig() {
racereadrange = sysfunc("racereadrange")
racewrite = sysfunc("racewrite")
racewriterange = sysfunc("racewriterange")
- supportPopcnt = sysfunc("support_popcnt")
- supportSSE41 = sysfunc("support_sse41")
- arm64SupportAtomics = sysfunc("arm64_support_atomics")
+ supportPopcnt = sysvar("support_popcnt") // bool
+ supportSSE41 = sysvar("support_sse41") // bool
+ arm64SupportAtomics = sysvar("arm64_support_atomics") // bool
typedmemclr = sysfunc("typedmemclr")
typedmemmove = sysfunc("typedmemmove")
- Udiv = sysfunc("udiv")
- writeBarrier = sysfunc("writeBarrier")
-
- // GO386=387 runtime functions
- ControlWord64trunc = sysfunc("controlWord64trunc")
- ControlWord32 = sysfunc("controlWord32")
-
- // Wasm
- WasmMove = sysfunc("wasmMove")
- WasmZero = sysfunc("wasmZero")
- WasmDiv = sysfunc("wasmDiv")
- WasmTruncS = sysfunc("wasmTruncS")
- WasmTruncU = sysfunc("wasmTruncU")
- SigPanic = sysfunc("sigpanic")
+ Udiv = sysvar("udiv") // asm func with special ABI
+ writeBarrier = sysvar("writeBarrier") // struct { bool; ... }
+
+ // GO386=387 runtime definitions
+ ControlWord64trunc = sysvar("controlWord64trunc") // uint16
+ ControlWord32 = sysvar("controlWord32") // uint16
+
+ // Wasm (all asm funcs with special ABIs)
+ WasmMove = sysvar("wasmMove")
+ WasmZero = sysvar("wasmZero")
+ WasmDiv = sysvar("wasmDiv")
+ WasmTruncS = sysvar("wasmTruncS")
+ WasmTruncU = sysvar("wasmTruncU")
+ SigPanic = sysvar("sigpanic")
}
// buildssa builds an SSA function for fn.
diff --git a/src/cmd/compile/internal/types/sym.go b/src/cmd/compile/internal/types/sym.go
index 28583378d9dbe..86f5022b5c84f 100644
--- a/src/cmd/compile/internal/types/sym.go
+++ b/src/cmd/compile/internal/types/sym.go
@@ -77,6 +77,12 @@ func (sym *Sym) Linksym() *obj.LSym {
if sym == nil {
return nil
}
+ if sym.Func() {
+ // This is a function symbol. Mark it as "internal ABI".
+ return Ctxt.LookupInit(sym.LinksymName(), func(s *obj.LSym) {
+ s.SetABI(obj.ABIInternal)
+ })
+ }
return Ctxt.Lookup(sym.LinksymName())
}
diff --git a/src/cmd/internal/obj/arm/asm5.go b/src/cmd/internal/obj/arm/asm5.go
index dd6d9265c4bf0..316937bde0892 100644
--- a/src/cmd/internal/obj/arm/asm5.go
+++ b/src/cmd/internal/obj/arm/asm5.go
@@ -1530,6 +1530,7 @@ func buildop(ctxt *obj.Link) {
}
deferreturn = ctxt.Lookup("runtime.deferreturn")
+ deferreturn.SetABI(obj.ABIInternal)
symdiv = ctxt.Lookup("runtime._div")
symdivu = ctxt.Lookup("runtime._divu")
diff --git a/src/cmd/internal/obj/wasm/wasmobj.go b/src/cmd/internal/obj/wasm/wasmobj.go
index f271101f4bbe9..a1b758836a5d1 100644
--- a/src/cmd/internal/obj/wasm/wasmobj.go
+++ b/src/cmd/internal/obj/wasm/wasmobj.go
@@ -126,7 +126,9 @@ func instinit(ctxt *obj.Link) {
morestackNoCtxt = ctxt.Lookup("runtime.morestack_noctxt")
gcWriteBarrier = ctxt.Lookup("runtime.gcWriteBarrier")
sigpanic = ctxt.Lookup("runtime.sigpanic")
+ sigpanic.SetABI(obj.ABIInternal)
deferreturn = ctxt.Lookup("runtime.deferreturn")
+ deferreturn.SetABI(obj.ABIInternal)
jmpdefer = ctxt.Lookup(`"".jmpdefer`)
}
diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go
index a4507352f77e4..520f4be8f5653 100644
--- a/src/cmd/internal/obj/x86/asm6.go
+++ b/src/cmd/internal/obj/x86/asm6.go
@@ -2065,6 +2065,7 @@ func instinit(ctxt *obj.Link) {
plan9privates = ctxt.Lookup("_privates")
case objabi.Hnacl:
deferreturn = ctxt.Lookup("runtime.deferreturn")
+ deferreturn.SetABI(obj.ABIInternal)
}
for i := range avxOptab {
diff --git a/src/cmd/internal/objabi/symkind.go b/src/cmd/internal/objabi/symkind.go
index b95a0d3c701fd..16b4c535ed85b 100644
--- a/src/cmd/internal/objabi/symkind.go
+++ b/src/cmd/internal/objabi/symkind.go
@@ -60,6 +60,13 @@ const (
SDWARFRANGE
SDWARFLOC
SDWARFMISC
+ // ABI alias. An ABI alias symbol is an empty symbol with a
+ // single relocation with 0 size that references the native
+ // function implementation symbol.
+ //
+ // TODO(austin): Remove this and all uses once the compiler
+ // generates real ABI wrappers rather than symbol aliases.
+ SABIALIAS
// Update cmd/link/internal/sym/AbiSymKindToSymKind for new SymKind values.
)
diff --git a/src/cmd/internal/objabi/symkind_string.go b/src/cmd/internal/objabi/symkind_string.go
index 7152d6c006901..2b9a9080e8c0f 100644
--- a/src/cmd/internal/objabi/symkind_string.go
+++ b/src/cmd/internal/objabi/symkind_string.go
@@ -4,9 +4,9 @@ package objabi
import "strconv"
-const _SymKind_name = "SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFINFOSDWARFRANGESDWARFLOCSDWARFMISC"
+const _SymKind_name = "SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFINFOSDWARFRANGESDWARFLOCSDWARFMISCSABIALIAS"
-var _SymKind_index = [...]uint8{0, 4, 9, 16, 26, 31, 35, 44, 51, 61, 72, 81, 91}
+var _SymKind_index = [...]uint8{0, 4, 9, 16, 26, 31, 35, 44, 51, 61, 72, 81, 91, 100}
func (i SymKind) String() string {
if i >= SymKind(len(_SymKind_index)-1) {
diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go
index df989cc94486a..8f582174c549c 100644
--- a/src/cmd/link/internal/ld/deadcode.go
+++ b/src/cmd/link/internal/ld/deadcode.go
@@ -60,8 +60,8 @@ func deadcode(ctxt *Link) {
d.init()
d.flood()
- callSym := ctxt.Syms.ROLookup("reflect.Value.Call", 0)
- methSym := ctxt.Syms.ROLookup("reflect.Value.Method", 0)
+ callSym := ctxt.Syms.ROLookup("reflect.Value.Call", sym.SymVerABIInternal)
+ methSym := ctxt.Syms.ROLookup("reflect.Value.Method", sym.SymVerABIInternal)
reflectSeen := false
if ctxt.DynlinkingGo() {
@@ -257,7 +257,10 @@ func (d *deadcodepass) init() {
}
for _, name := range names {
+ // Mark symbol as an data/ABI0 symbol.
d.mark(d.ctxt.Syms.ROLookup(name, 0), nil)
+ // Also mark any Go functions (internal ABI).
+ d.mark(d.ctxt.Syms.ROLookup(name, sym.SymVerABIInternal), nil)
}
}
@@ -308,6 +311,11 @@ func (d *deadcodepass) flood() {
// reachable.
continue
}
+ if r.Sym.Type == sym.SABIALIAS {
+ // Patch this relocation through the
+ // ABI alias before marking.
+ r.Sym = resolveABIAlias(r.Sym)
+ }
if r.Type != objabi.R_METHODOFF {
d.mark(r.Sym, s)
continue
diff --git a/src/cmd/link/internal/ld/go.go b/src/cmd/link/internal/ld/go.go
index d6c6b53a44c52..c942956cc47e3 100644
--- a/src/cmd/link/internal/ld/go.go
+++ b/src/cmd/link/internal/ld/go.go
@@ -25,6 +25,17 @@ func expandpkg(t0 string, pkg string) string {
return strings.Replace(t0, `"".`, pkg+".", -1)
}
+func resolveABIAlias(s *sym.Symbol) *sym.Symbol {
+ if s.Type != sym.SABIALIAS {
+ return s
+ }
+ target := s.R[0].Sym
+ if target.Type == sym.SABIALIAS {
+ panic(fmt.Sprintf("ABI alias %s references another ABI alias %s", s, target))
+ }
+ return target
+}
+
// TODO:
// generate debugging section in binary.
// once the dust settles, try to move some code to
@@ -191,6 +202,11 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
}
local = expandpkg(local, pkg)
+ // The compiler arranges for an ABI0 wrapper
+ // to be available for all cgo-exported
+ // functions. Link.loadlib will resolve any
+ // ABI aliases we find here (since we may not
+ // yet know it's an alias).
s := ctxt.Syms.Lookup(local, 0)
switch ctxt.BuildMode {
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index aa472ee07f752..3038b7957444b 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -169,7 +169,7 @@ func (ctxt *Link) DynlinkingGo() bool {
// CanUsePlugins returns whether a plugins can be used
func (ctxt *Link) CanUsePlugins() bool {
- return ctxt.Syms.ROLookup("plugin.Open", 0) != nil
+ return ctxt.Syms.ROLookup("plugin.Open", sym.SymVerABIInternal) != nil
}
// UseRelro returns whether to make use of "read only relocations" aka
@@ -635,6 +635,19 @@ func (ctxt *Link) loadlib() {
}
ctxt.Textp = textp
}
+
+ // Resolve ABI aliases in the list of cgo-exported functions.
+ // This is necessary because we load the ABI0 symbol for all
+ // cgo exports.
+ for i, s := range dynexp {
+ if s.Type != sym.SABIALIAS {
+ continue
+ }
+ t := resolveABIAlias(s)
+ t.Attr |= s.Attr
+ t.SetExtname(s.Extname())
+ dynexp[i] = t
+ }
}
// mangleTypeSym shortens the names of symbols that represent Go types
@@ -651,7 +664,7 @@ func (ctxt *Link) loadlib() {
// those programs loaded dynamically in multiple parts need these
// symbols to have entries in the symbol table.
func (ctxt *Link) mangleTypeSym() {
- if ctxt.BuildMode != BuildModeShared && !ctxt.linkShared && ctxt.BuildMode != BuildModePlugin && ctxt.Syms.ROLookup("plugin.Open", 0) == nil {
+ if ctxt.BuildMode != BuildModeShared && !ctxt.linkShared && ctxt.BuildMode != BuildModePlugin && !ctxt.CanUsePlugins() {
return
}
@@ -1801,6 +1814,21 @@ func ldshlibsyms(ctxt *Link, shlib string) {
gcdataLocations[elfsym.Value+2*uint64(ctxt.Arch.PtrSize)+8+1*uint64(ctxt.Arch.PtrSize)] = lsym
}
}
+ // For function symbols, we don't know what ABI is
+ // available, so alias it under both ABIs.
+ //
+ // TODO(austin): This is almost certainly wrong once
+ // the ABIs are actually different. We might have to
+ // mangle Go function names in the .so to include the
+ // ABI.
+ if elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC {
+ alias := ctxt.Syms.Lookup(elfsym.Name, sym.SymVerABIInternal)
+ if alias.Type != 0 {
+ continue
+ }
+ alias.Type = sym.SABIALIAS
+ alias.R = []sym.Reloc{{Sym: lsym}}
+ }
}
gcdataAddresses := make(map[*sym.Symbol]uint64)
if ctxt.Arch.Family == sys.ARM64 {
diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go
index 276a3a1cbbb87..7c296d766c44f 100644
--- a/src/cmd/link/internal/ld/symtab.go
+++ b/src/cmd/link/internal/ld/symtab.go
@@ -506,7 +506,7 @@ func (ctxt *Link) symtab() {
abihashgostr.AddAddr(ctxt.Arch, hashsym)
abihashgostr.AddUint(ctxt.Arch, uint64(hashsym.Size))
}
- if ctxt.BuildMode == BuildModePlugin || ctxt.Syms.ROLookup("plugin.Open", 0) != nil {
+ if ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() {
for _, l := range ctxt.Library {
s := ctxt.Syms.Lookup("go.link.pkghashbytes."+l.Pkg, 0)
s.Attr |= sym.AttrReachable
diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go
index c4a49c6a1e595..11a7aa2164311 100644
--- a/src/cmd/link/internal/ppc64/asm.go
+++ b/src/cmd/link/internal/ppc64/asm.go
@@ -133,7 +133,7 @@ func genplt(ctxt *ld.Link) {
}
func genaddmoduledata(ctxt *ld.Link) {
- addmoduledata := ctxt.Syms.ROLookup("runtime.addmoduledata", 0)
+ addmoduledata := ctxt.Syms.ROLookup("runtime.addmoduledata", sym.SymVerABI0)
if addmoduledata.Type == sym.STEXT && ctxt.BuildMode != ld.BuildModePlugin {
return
}
diff --git a/src/cmd/link/internal/sym/symbols.go b/src/cmd/link/internal/sym/symbols.go
index d7266c840b74c..f0fcf2361b178 100644
--- a/src/cmd/link/internal/sym/symbols.go
+++ b/src/cmd/link/internal/sym/symbols.go
@@ -43,6 +43,8 @@ func NewSymbols() *Symbols {
hash := make([]map[string]*Symbol, SymVerStatic)
// Preallocate about 2mb for hash of non static symbols
hash[0] = make(map[string]*Symbol, 100000)
+ // And another 1mb for internal ABI text symbols.
+ hash[SymVerABIInternal] = make(map[string]*Symbol, 50000)
return &Symbols{
hash: hash,
Allsym: make([]*Symbol, 0, 100000),
diff --git a/src/cmd/link/internal/sym/symkind.go b/src/cmd/link/internal/sym/symkind.go
index b1756d6145e9e..6e1e1b58a1f71 100644
--- a/src/cmd/link/internal/sym/symkind.go
+++ b/src/cmd/link/internal/sym/symkind.go
@@ -109,6 +109,9 @@ const (
SDWARFRANGE
SDWARFLOC
SDWARFMISC // Not really a section; informs/affects other DWARF section generation
+
+ // ABI aliases (these never appear in the output)
+ SABIALIAS
)
// AbiSymKindToSymKind maps values read from object files (which are
@@ -126,6 +129,7 @@ var AbiSymKindToSymKind = [...]SymKind{
SDWARFRANGE,
SDWARFLOC,
SDWARFMISC,
+ SABIALIAS,
}
// ReadOnly are the symbol kinds that form read-only sections. In some
diff --git a/src/cmd/link/internal/sym/symkind_string.go b/src/cmd/link/internal/sym/symkind_string.go
index 7428503b1c8a3..4da6c656f7bab 100644
--- a/src/cmd/link/internal/sym/symkind_string.go
+++ b/src/cmd/link/internal/sym/symkind_string.go
@@ -4,9 +4,9 @@ package sym
import "strconv"
-const _SymKind_name = "SxxxSTEXTSELFRXSECTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASFUNCTABSELFROSECTSMACHOPLTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSTYPELINKSITABLINKSSYMTABSPCLNTABSELFSECTSMACHOSMACHOGOTSWINDOWSSELFGOTSNOPTRDATASINITARRSDATASBSSSNOPTRBSSSTLSBSSSXCOFFTOCSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSFILEPATHSCONSTSDYNIMPORTSHOSTOBJSDWARFSECTSDWARFINFOSDWARFRANGESDWARFLOCSDWARFMISC"
+const _SymKind_name = "SxxxSTEXTSELFRXSECTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASFUNCTABSELFROSECTSMACHOPLTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSTYPELINKSITABLINKSSYMTABSPCLNTABSELFSECTSMACHOSMACHOGOTSWINDOWSSELFGOTSNOPTRDATASINITARRSDATASBSSSNOPTRBSSSTLSBSSSXCOFFTOCSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSFILEPATHSCONSTSDYNIMPORTSHOSTOBJSDWARFSECTSDWARFINFOSDWARFRANGESDWARFLOCSDWARFMISCSABIALIAS"
-var _SymKind_index = [...]uint16{0, 4, 9, 19, 24, 31, 40, 47, 54, 61, 69, 79, 88, 98, 110, 124, 136, 148, 160, 173, 182, 191, 198, 206, 214, 220, 229, 237, 244, 254, 262, 267, 271, 280, 287, 296, 301, 313, 325, 342, 359, 368, 374, 384, 392, 402, 412, 423, 432, 442}
+var _SymKind_index = [...]uint16{0, 4, 9, 19, 24, 31, 40, 47, 54, 61, 69, 79, 88, 98, 110, 124, 136, 148, 160, 173, 182, 191, 198, 206, 214, 220, 229, 237, 244, 254, 262, 267, 271, 280, 287, 296, 301, 313, 325, 342, 359, 368, 374, 384, 392, 402, 412, 423, 432, 442, 451}
func (i SymKind) String() string {
if i >= SymKind(len(_SymKind_index)-1) {
From 891f99eb43ad86814662549e4121e4e8c30e8b40 Mon Sep 17 00:00:00 2001
From: Austin Clements
Date: Mon, 12 Nov 2018 16:37:12 -0500
Subject: [PATCH 011/594] cmd/compile: fix TestFormats
This fixes the linux-amd64-longtest builder, which was broken by CL
147160.
Updates #27539.
Change-Id: If6e69581ef503bba2449ec9bacaa31f34f59beb1
Reviewed-on: https://go-review.googlesource.com/c/149157
Reviewed-by: Brad Fitzpatrick
---
src/cmd/compile/fmt_test.go | 1 +
src/cmd/compile/internal/gc/gsubr.go | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/cmd/compile/fmt_test.go b/src/cmd/compile/fmt_test.go
index 05d13b58a565c..c5c050fa17c47 100644
--- a/src/cmd/compile/fmt_test.go
+++ b/src/cmd/compile/fmt_test.go
@@ -672,6 +672,7 @@ var knownFormats = map[string]string{
"cmd/compile/internal/types.EType %d": "",
"cmd/compile/internal/types.EType %s": "",
"cmd/compile/internal/types.EType %v": "",
+ "cmd/internal/obj.ABI %v": "",
"error %v": "",
"float64 %.2f": "",
"float64 %.3f": "",
diff --git a/src/cmd/compile/internal/gc/gsubr.go b/src/cmd/compile/internal/gc/gsubr.go
index 01ac4cb929be7..5ad7b9a1b6fc5 100644
--- a/src/cmd/compile/internal/gc/gsubr.go
+++ b/src/cmd/compile/internal/gc/gsubr.go
@@ -216,7 +216,7 @@ func (f *Func) initLSym(hasBody bool) {
// using the expected ABI.
want := obj.ABIInternal
if f.lsym.ABI() != want {
- Fatalf("function symbol %s has the wrong ABI %v, expected %v", f.lsym, f.lsym.ABI(), want)
+ Fatalf("function symbol %s has the wrong ABI %v, expected %v", f.lsym.Name, f.lsym.ABI(), want)
}
}
From b52db19b983d9b92c013184f7699bba2d0166c10 Mon Sep 17 00:00:00 2001
From: Austin Clements
Date: Mon, 12 Nov 2018 16:31:47 -0500
Subject: [PATCH 012/594] cmd/compile: create "init" symbol earlier
We create the "init" symbol and mark it as a function before compiling
to SSA because SSA can initialize this symbol, but it turns out we do
it slightly too late. peekitabs, at least, can also create the "init"
LSym. Move this initialization to just after type-checking.
Fixes the linux-amd64-ssacheck and the android-arm64-wiko-fever
builders.
Updates #27539.
Change-Id: If145952c79d39f75c93b24e35e67fe026dd08329
Reviewed-on: https://go-review.googlesource.com/c/149137
Run-TryBot: Austin Clements
TryBot-Result: Gobot Gobot
Reviewed-by: Robert Griesemer
---
src/cmd/compile/internal/gc/main.go | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go
index 087371c6f6c9c..e5d42bfd7da15 100644
--- a/src/cmd/compile/internal/gc/main.go
+++ b/src/cmd/compile/internal/gc/main.go
@@ -557,6 +557,11 @@ func Main(archInit func(*Arch)) {
errorexit()
}
+ // The "init" function is the only user-spellable symbol that
+ // we construct later. Mark it as a function now before
+ // anything can ask for its Linksym.
+ lookup("init").SetFunc(true)
+
// Phase 4: Decide how to capture closed variables.
// This needs to run before escape analysis,
// because variables captured by value do not escape.
@@ -649,11 +654,6 @@ func Main(archInit func(*Arch)) {
Curfn = nil
peekitabs()
- // The "init" function is the only user-spellable symbol that
- // we construct later. Mark it as a function now before
- // anything can ask for its Linksym.
- lookup("init").SetFunc(true)
-
// Phase 8: Compile top level functions.
// Don't use range--walk can add functions to xtop.
timings.Start("be", "compilefuncs")
From 5cf2b4c2d39e0490b235822f5ea7fa105280b9f2 Mon Sep 17 00:00:00 2001
From: Austin Clements
Date: Mon, 12 Nov 2018 16:49:52 -0500
Subject: [PATCH 013/594] cmd/compile: fix race on initializing Sym symFunc
flag
SSA lowering can create PFUNC ONAME nodes when compiling method calls.
Since we generally initialize the node's Sym to a func when we set its
class to PFUNC, we did this here, too. Unfortunately, since SSA
compilation is concurrent, this can cause a race if two function
compilations try to initialize the same symbol.
Luckily, we don't need to do this at all, since we're actually just
wrapping an ONAME node around an existing Sym that's already marked as
a function symbol.
Fixes the linux-amd64-racecompile builder, which was broken by CL
147158.
Updates #27539.
Change-Id: I8ddfce6e66a08ce53998c5bfa6f5a423c1ffc1eb
Reviewed-on: https://go-review.googlesource.com/c/149158
Run-TryBot: Austin Clements
TryBot-Result: Gobot Gobot
Reviewed-by: David Chase
---
src/cmd/compile/internal/gc/ssa.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index 883cf7936d3b0..9da45258f5268 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -3670,7 +3670,7 @@ func (s *state) call(n *Node, k callKind) *ssa.Value {
n2 := newnamel(fn.Pos, fn.Sym)
n2.Name.Curfn = s.curfn
n2.SetClass(PFUNC)
- n2.Sym.SetFunc(true)
+ // n2.Sym already existed, so it's already marked as a function.
n2.Pos = fn.Pos
n2.Type = types.Types[TUINT8] // dummy type for a static closure. Could use runtime.funcval if we had it.
closure = s.expr(n2)
From 595bc63e8fb9636bb89c0cff3f879467d3c06988 Mon Sep 17 00:00:00 2001
From: Ali Rizvi-Santiago
Date: Mon, 12 Nov 2018 21:54:16 +0000
Subject: [PATCH 014/594] runtime/cgo: added missing includes for errno.h to
the windows gcc stubs.
This adds the includes for errno.h to the windows stubs
for runtime/cgo so that "errno" is properly declared.
Due to "errno" not being properly declared, the compiler is
forced to assume it's an external which leaves it up to the
linker. This is an issue in some implementations as errno
might be a macro which results in an unresolved symbol error
during linking.
runtime/cgo/gcc_libinit_windows.c: added include
runtime/cgo/gcc_windows_386.c: added include
runtime/cgo/gcc_windows_amd64.c: added include
Change-Id: I77167d02f7409462979135efc55cf50bbc6bd363
GitHub-Last-Rev: 90da06ee3cbec3f51c6d31185868bb70341ce9d3
GitHub-Pull-Request: golang/go#28747
Reviewed-on: https://go-review.googlesource.com/c/149118
Run-TryBot: Ian Lance Taylor
TryBot-Result: Gobot Gobot
Reviewed-by: Ian Lance Taylor
---
src/runtime/cgo/gcc_libinit_windows.c | 1 +
src/runtime/cgo/gcc_windows_386.c | 1 +
src/runtime/cgo/gcc_windows_amd64.c | 1 +
3 files changed, 3 insertions(+)
diff --git a/src/runtime/cgo/gcc_libinit_windows.c b/src/runtime/cgo/gcc_libinit_windows.c
index b6f51b3e4dd66..248d59fd69574 100644
--- a/src/runtime/cgo/gcc_libinit_windows.c
+++ b/src/runtime/cgo/gcc_libinit_windows.c
@@ -9,6 +9,7 @@
#include
#include
+#include
#include "libcgo.h"
diff --git a/src/runtime/cgo/gcc_windows_386.c b/src/runtime/cgo/gcc_windows_386.c
index f2ff710f60cdf..9184b91393ff5 100644
--- a/src/runtime/cgo/gcc_windows_386.c
+++ b/src/runtime/cgo/gcc_windows_386.c
@@ -7,6 +7,7 @@
#include
#include
#include
+#include
#include "libcgo.h"
static void threadentry(void*);
diff --git a/src/runtime/cgo/gcc_windows_amd64.c b/src/runtime/cgo/gcc_windows_amd64.c
index 511ab44fa9822..7192a24631543 100644
--- a/src/runtime/cgo/gcc_windows_amd64.c
+++ b/src/runtime/cgo/gcc_windows_amd64.c
@@ -7,6 +7,7 @@
#include
#include
#include
+#include
#include "libcgo.h"
static void threadentry(void*);
From 70e3b1df4a5d5b91f6c0e7bd4f7879d6ae95fc12 Mon Sep 17 00:00:00 2001
From: Filippo Valsorda
Date: Mon, 12 Nov 2018 16:04:07 -0500
Subject: [PATCH 015/594] crypto/tls: don't modify Config.Certificates in
BuildNameToCertificate
The Config does not own the memory pointed to by the Certificate slice.
Instead, opportunistically use Certificate.Leaf and let the application
set it if it desires the performance gain.
This is a partial rollback of CL 107627. See the linked issue for the
full explanation.
Fixes #28744
Change-Id: I33ce9e6712e3f87939d9d0932a06d24e48ba4567
Reviewed-on: https://go-review.googlesource.com/c/149098
Reviewed-by: Emmanuel Odeke
Run-TryBot: Emmanuel Odeke
TryBot-Result: Gobot Gobot
---
src/crypto/tls/common.go | 8 ++++----
src/crypto/tls/tls_test.go | 22 ++++++++++++++++++++++
2 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go
index 25e4a7d8860d8..3ba3aac86bb09 100644
--- a/src/crypto/tls/common.go
+++ b/src/crypto/tls/common.go
@@ -871,14 +871,14 @@ func (c *Config) BuildNameToCertificate() {
c.NameToCertificate = make(map[string]*Certificate)
for i := range c.Certificates {
cert := &c.Certificates[i]
- if cert.Leaf == nil {
- x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
+ x509Cert := cert.Leaf
+ if x509Cert == nil {
+ var err error
+ x509Cert, err = x509.ParseCertificate(cert.Certificate[0])
if err != nil {
continue
}
- cert.Leaf = x509Cert
}
- x509Cert := cert.Leaf
if len(x509Cert.Subject.CommonName) > 0 {
c.NameToCertificate[x509Cert.Subject.CommonName] = cert
}
diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go
index e23068ce43573..00bb6e4ef3754 100644
--- a/src/crypto/tls/tls_test.go
+++ b/src/crypto/tls/tls_test.go
@@ -1087,3 +1087,25 @@ func TestEscapeRoute(t *testing.T) {
t.Errorf("Client negotiated version %x, expected %x", cs.Version, VersionTLS12)
}
}
+
+// Issue 28744: Ensure that we don't modify memory
+// that Config doesn't own such as Certificates.
+func TestBuildNameToCertificate_doesntModifyCertificates(t *testing.T) {
+ c0 := Certificate{
+ Certificate: [][]byte{testRSACertificate},
+ PrivateKey: testRSAPrivateKey,
+ }
+ c1 := Certificate{
+ Certificate: [][]byte{testSNICertificate},
+ PrivateKey: testRSAPrivateKey,
+ }
+ config := testConfig.Clone()
+ config.Certificates = []Certificate{c0, c1}
+
+ config.BuildNameToCertificate()
+ got := config.Certificates
+ want := []Certificate{c0, c1}
+ if !reflect.DeepEqual(got, want) {
+ t.Fatalf("Certificates were mutated by BuildNameToCertificate\nGot: %#v\nWant: %#v\n", got, want)
+ }
+}
From 5d39260079b5170e6b4263adb4022cc4b54153c4 Mon Sep 17 00:00:00 2001
From: Emmanuel T Odeke
Date: Thu, 8 Nov 2018 22:08:35 -0800
Subject: [PATCH 016/594] net: preserve unexpired context values for
LookupIPAddr
To avoid any cancelation of the parent context from affecting
lookupGroup operations, Resolver.LookupIPAddr previously used
an entirely new context created from context.Background().
However, this meant that all the values in the parent context
with which LookupIPAddr was invoked were dropped.
This change provides a custom context implementation
that only preserves values of the parent context by composing
context.Background() and the parent context. It only falls back
to the parent context to perform value lookups if the parent
context has not yet expired.
This context is never canceled, and has no deadlines.
Fixes #28600
Change-Id: If2f570caa26c65bad638b7102c35c79d5e429fea
Reviewed-on: https://go-review.googlesource.com/c/148698
Run-TryBot: Emmanuel Odeke
Reviewed-by: Brad Fitzpatrick
---
src/net/lookup.go | 32 ++++++++++++++++--
src/net/lookup_test.go | 75 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 105 insertions(+), 2 deletions(-)
diff --git a/src/net/lookup.go b/src/net/lookup.go
index cb810dea267bd..e10889331e4f5 100644
--- a/src/net/lookup.go
+++ b/src/net/lookup.go
@@ -205,6 +205,33 @@ func (r *Resolver) LookupIPAddr(ctx context.Context, host string) ([]IPAddr, err
return r.lookupIPAddr(ctx, "ip", host)
}
+// onlyValuesCtx is a context that uses an underlying context
+// for value lookup if the underlying context hasn't yet expired.
+type onlyValuesCtx struct {
+ context.Context
+ lookupValues context.Context
+}
+
+var _ context.Context = (*onlyValuesCtx)(nil)
+
+// Value performs a lookup if the original context hasn't expired.
+func (ovc *onlyValuesCtx) Value(key interface{}) interface{} {
+ select {
+ case <-ovc.lookupValues.Done():
+ return nil
+ default:
+ return ovc.lookupValues.Value(key)
+ }
+}
+
+// withUnexpiredValuesPreserved returns a context.Context that only uses lookupCtx
+// for its values, otherwise it is never canceled and has no deadline.
+// If the lookup context expires, any looked up values will return nil.
+// See Issue 28600.
+func withUnexpiredValuesPreserved(lookupCtx context.Context) context.Context {
+ return &onlyValuesCtx{Context: context.Background(), lookupValues: lookupCtx}
+}
+
// lookupIPAddr looks up host using the local resolver and particular network.
// It returns a slice of that host's IPv4 and IPv6 addresses.
func (r *Resolver) lookupIPAddr(ctx context.Context, network, host string) ([]IPAddr, error) {
@@ -231,8 +258,9 @@ func (r *Resolver) lookupIPAddr(ctx context.Context, network, host string) ([]IP
// We don't want a cancelation of ctx to affect the
// lookupGroup operation. Otherwise if our context gets
// canceled it might cause an error to be returned to a lookup
- // using a completely different context.
- lookupGroupCtx, lookupGroupCancel := context.WithCancel(context.Background())
+ // using a completely different context. However we need to preserve
+ // only the values in context. See Issue 28600.
+ lookupGroupCtx, lookupGroupCancel := context.WithCancel(withUnexpiredValuesPreserved(ctx))
dnsWaitGroup.Add(1)
ch, called := r.getLookupGroup().DoChan(host, func() (interface{}, error) {
diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go
index aeeda8f7d0eb7..65daa76467dd9 100644
--- a/src/net/lookup_test.go
+++ b/src/net/lookup_test.go
@@ -1034,3 +1034,78 @@ func TestIPVersion(t *testing.T) {
}
}
}
+
+// Issue 28600: The context that is used to lookup ips should always
+// preserve the values from the context that was passed into LookupIPAddr.
+func TestLookupIPAddrPreservesContextValues(t *testing.T) {
+ origTestHookLookupIP := testHookLookupIP
+ defer func() { testHookLookupIP = origTestHookLookupIP }()
+
+ keyValues := []struct {
+ key, value interface{}
+ }{
+ {"key-1", 12},
+ {384, "value2"},
+ {new(float64), 137},
+ }
+ ctx := context.Background()
+ for _, kv := range keyValues {
+ ctx = context.WithValue(ctx, kv.key, kv.value)
+ }
+
+ wantIPs := []IPAddr{
+ {IP: IPv4(127, 0, 0, 1)},
+ {IP: IPv6loopback},
+ }
+
+ checkCtxValues := func(ctx_ context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
+ for _, kv := range keyValues {
+ g, w := ctx_.Value(kv.key), kv.value
+ if !reflect.DeepEqual(g, w) {
+ t.Errorf("Value lookup:\n\tGot: %v\n\tWant: %v", g, w)
+ }
+ }
+ return wantIPs, nil
+ }
+ testHookLookupIP = checkCtxValues
+
+ resolvers := []*Resolver{
+ nil,
+ new(Resolver),
+ }
+
+ for i, resolver := range resolvers {
+ gotIPs, err := resolver.LookupIPAddr(ctx, "golang.org")
+ if err != nil {
+ t.Errorf("Resolver #%d: unexpected error: %v", i, err)
+ }
+ if !reflect.DeepEqual(gotIPs, wantIPs) {
+ t.Errorf("#%d: mismatched IPAddr results\n\tGot: %v\n\tWant: %v", i, gotIPs, wantIPs)
+ }
+ }
+}
+
+func TestWithUnexpiredValuesPreserved(t *testing.T) {
+ ctx, cancel := context.WithCancel(context.Background())
+
+ // Insert a value into it.
+ key, value := "key-1", 2
+ ctx = context.WithValue(ctx, key, value)
+
+ // Now use the "values preserving context" like
+ // we would for LookupIPAddr. See Issue 28600.
+ ctx = withUnexpiredValuesPreserved(ctx)
+
+ // Lookup before expiry.
+ if g, w := ctx.Value(key), value; g != w {
+ t.Errorf("Lookup before expiry: Got %v Want %v", g, w)
+ }
+
+ // Cancel the context.
+ cancel()
+
+ // Lookup after expiry should return nil
+ if g := ctx.Value(key); g != nil {
+ t.Errorf("Lookup after expiry: Got %v want nil", g)
+ }
+}
From 7ebe35093dbac03f86f7471590a18bf4ddd4b29c Mon Sep 17 00:00:00 2001
From: Ian Lance Taylor
Date: Mon, 12 Nov 2018 10:38:02 -0800
Subject: [PATCH 017/594] cmd/compile: correct check for valid -lang version
Change-Id: Iad10d0a2dbc8e12e9f776c6cfb34070f584fd439
Reviewed-on: https://go-review.googlesource.com/c/149057
Run-TryBot: Ian Lance Taylor
TryBot-Result: Gobot Gobot
Reviewed-by: Emmanuel Odeke
---
src/cmd/compile/internal/gc/lang_test.go | 5 +++++
src/cmd/compile/internal/gc/main.go | 2 +-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/cmd/compile/internal/gc/lang_test.go b/src/cmd/compile/internal/gc/lang_test.go
index b225f03a1de1f..72e7f07a21c00 100644
--- a/src/cmd/compile/internal/gc/lang_test.go
+++ b/src/cmd/compile/internal/gc/lang_test.go
@@ -41,6 +41,11 @@ func TestInvalidLang(t *testing.T) {
t.Error("compilation with -lang=go9.99 succeeded unexpectedly")
}
+ // This test will have to be adjusted if we ever reach 1.99 or 2.0.
+ if testLang(t, "go1.99", src, outfile) == nil {
+ t.Error("compilation with -lang=go1.99 succeeded unexpectedly")
+ }
+
if testLang(t, "go1.8", src, outfile) == nil {
t.Error("compilation with -lang=go1.8 succeeded unexpectedly")
}
diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go
index e5d42bfd7da15..44c540492b092 100644
--- a/src/cmd/compile/internal/gc/main.go
+++ b/src/cmd/compile/internal/gc/main.go
@@ -1444,7 +1444,7 @@ func checkLang() {
if err != nil {
log.Fatalf("internal error parsing default lang %q: %v", def, err)
}
- if langWant.major > defVers.major || (langWant.major == defVers.major && langWant.major > defVers.minor) {
+ if langWant.major > defVers.major || (langWant.major == defVers.major && langWant.minor > defVers.minor) {
log.Fatalf("invalid value %q for -lang: max known version is %q", flag_lang, def)
}
}
From de578dcdd682182c69efc8f9328c9bba500192b0 Mon Sep 17 00:00:00 2001
From: Robert Griesemer
Date: Mon, 12 Nov 2018 11:25:58 -0800
Subject: [PATCH 018/594] spec: be clearer about definition of string length
Adjusted spec to explicitly define the string length as the
number of bytes of the string; the prose now matches the prose
for arrays. Made analogous change for slices.
Fixes #28736.
Change-Id: I47cab321c87de0a4c482f5466b819b2cc8993fd1
Reviewed-on: https://go-review.googlesource.com/c/149077
Reviewed-by: Rob Pike
Reviewed-by: Matthew Dempsky
---
doc/go_spec.html | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/doc/go_spec.html b/doc/go_spec.html
index cc2bada913901..098a92551a914 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
@@ -823,6 +823,7 @@ String types
A string type represents the set of string values.
A string value is a (possibly empty) sequence of bytes.
+The number of bytes is called the length of the string and is never negative.
Strings are immutable: once created,
it is impossible to change the contents of a string.
The predeclared string type is string
;
@@ -830,7 +831,7 @@
String types
-The length of a string s
(its size in bytes) can be discovered using
+The length of a string s
can be discovered using
the built-in function len
.
The length is a compile-time constant if the string is a constant.
A string's bytes can be accessed by integer indices
@@ -846,8 +847,7 @@
Array types
An array is a numbered sequence of elements of a single
type, called the element type.
-The number of elements is called the length and is never
-negative.
+The number of elements is called the length of the array and is never negative.
@@ -883,6 +883,7 @@ Slice types
A slice is a descriptor for a contiguous segment of an underlying array and
provides access to a numbered sequence of elements from that array.
A slice type denotes the set of all slices of arrays of its element type.
+The number of elements is called the length of the slice and is never negative.
The value of an uninitialized slice is nil
.
@@ -891,8 +892,7 @@ Slice types
-Like arrays, slices are indexable and have a length. The length of a
-slice s
can be discovered by the built-in function
+The length of a slice s
can be discovered by the built-in function
len
; unlike with arrays it may change during
execution. The elements can be addressed by integer indices
0 through len(s)-1
. The slice index of a
From ee55f0856a3f1fed5d8c15af54c40e4799c2d32f Mon Sep 17 00:00:00 2001
From: Brad Fitzpatrick
Date: Mon, 29 Oct 2018 23:21:40 +0000
Subject: [PATCH 019/594] net/http/httputil: make ReverseProxy automatically
proxy WebSocket requests
Fixes #26937
Change-Id: I6cdc1bad4cf476cd2ea1462b53444eccd8841e14
Reviewed-on: https://go-review.googlesource.com/c/146437
Run-TryBot: Brad Fitzpatrick
TryBot-Result: Gobot Gobot
Reviewed-by: Dmitri Shuralyov
---
src/go/build/deps_test.go | 2 +-
src/net/http/httputil/reverseproxy.go | 81 ++++++++++++++++++++
src/net/http/httputil/reverseproxy_test.go | 88 +++++++++++++++++++---
src/net/http/transport.go | 2 +-
4 files changed, 161 insertions(+), 12 deletions(-)
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index d632954d0c4b3..0ecf38c567df1 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -436,7 +436,7 @@ var pkgDeps = map[string][]string{
"L4", "NET", "OS", "crypto/tls", "flag", "net/http", "net/http/internal", "crypto/x509",
"golang_org/x/net/http/httpguts",
},
- "net/http/httputil": {"L4", "NET", "OS", "context", "net/http", "net/http/internal"},
+ "net/http/httputil": {"L4", "NET", "OS", "context", "net/http", "net/http/internal", "golang_org/x/net/http/httpguts"},
"net/http/pprof": {"L4", "OS", "html/template", "net/http", "runtime/pprof", "runtime/trace"},
"net/rpc": {"L4", "NET", "encoding/gob", "html/template", "net/http"},
"net/rpc/jsonrpc": {"L4", "NET", "encoding/json", "net/rpc"},
diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go
index f82d820a43007..e9552a2256414 100644
--- a/src/net/http/httputil/reverseproxy.go
+++ b/src/net/http/httputil/reverseproxy.go
@@ -8,6 +8,7 @@ package httputil
import (
"context"
+ "fmt"
"io"
"log"
"net"
@@ -16,6 +17,8 @@ import (
"strings"
"sync"
"time"
+
+ "golang_org/x/net/http/httpguts"
)
// ReverseProxy is an HTTP Handler that takes an incoming request and
@@ -199,6 +202,7 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
p.Director(outreq)
outreq.Close = false
+ reqUpType := upgradeType(outreq.Header)
removeConnectionHeaders(outreq.Header)
// Remove hop-by-hop headers to the backend. Especially
@@ -221,6 +225,13 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
outreq.Header.Del(h)
}
+ // After stripping all the hop-by-hop connection headers above, add back any
+ // necessary for protocol upgrades, such as for websockets.
+ if reqUpType != "" {
+ outreq.Header.Set("Connection", "Upgrade")
+ outreq.Header.Set("Upgrade", reqUpType)
+ }
+
if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
// If we aren't the first proxy retain prior
// X-Forwarded-For information as a comma+space
@@ -237,6 +248,12 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
return
}
+ // Deal with 101 Switching Protocols responses: (WebSocket, h2c, etc)
+ if res.StatusCode == http.StatusSwitchingProtocols {
+ p.handleUpgradeResponse(rw, outreq, res)
+ return
+ }
+
removeConnectionHeaders(res.Header)
for _, h := range hopHeaders {
@@ -463,3 +480,67 @@ func (m *maxLatencyWriter) stop() {
m.t.Stop()
}
}
+
+func upgradeType(h http.Header) string {
+ if !httpguts.HeaderValuesContainsToken(h["Connection"], "Upgrade") {
+ return ""
+ }
+ return strings.ToLower(h.Get("Upgrade"))
+}
+
+func (p *ReverseProxy) handleUpgradeResponse(rw http.ResponseWriter, req *http.Request, res *http.Response) {
+ reqUpType := upgradeType(req.Header)
+ resUpType := upgradeType(res.Header)
+ if reqUpType != resUpType {
+ p.getErrorHandler()(rw, req, fmt.Errorf("backend tried to switch protocol %q when %q was requested", resUpType, reqUpType))
+ return
+ }
+ hj, ok := rw.(http.Hijacker)
+ if !ok {
+ p.getErrorHandler()(rw, req, fmt.Errorf("can't switch protocols using non-Hijacker ResponseWriter type %T", rw))
+ return
+ }
+ backConn, ok := res.Body.(io.ReadWriteCloser)
+ if !ok {
+ p.getErrorHandler()(rw, req, fmt.Errorf("internal error: 101 switching protocols response with non-writable body"))
+ return
+ }
+ defer backConn.Close()
+ conn, brw, err := hj.Hijack()
+ if err != nil {
+ p.getErrorHandler()(rw, req, fmt.Errorf("Hijack failed on protocol switch: %v", err))
+ return
+ }
+ defer conn.Close()
+ res.Body = nil // so res.Write only writes the headers; we have res.Body in backConn above
+ if err := res.Write(brw); err != nil {
+ p.getErrorHandler()(rw, req, fmt.Errorf("response write: %v", err))
+ return
+ }
+ if err := brw.Flush(); err != nil {
+ p.getErrorHandler()(rw, req, fmt.Errorf("response flush: %v", err))
+ return
+ }
+ errc := make(chan error, 1)
+ spc := switchProtocolCopier{user: conn, backend: backConn}
+ go spc.copyToBackend(errc)
+ go spc.copyFromBackend(errc)
+ <-errc
+ return
+}
+
+// switchProtocolCopier exists so goroutines proxying data back and
+// forth have nice names in stacks.
+type switchProtocolCopier struct {
+ user, backend io.ReadWriter
+}
+
+func (c switchProtocolCopier) copyFromBackend(errc chan<- error) {
+ _, err := io.Copy(c.user, c.backend)
+ errc <- err
+}
+
+func (c switchProtocolCopier) copyToBackend(errc chan<- error) {
+ _, err := io.Copy(c.backend, c.user)
+ errc <- err
+}
diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go
index ddae11b168ce7..039273e7c581e 100644
--- a/src/net/http/httputil/reverseproxy_test.go
+++ b/src/net/http/httputil/reverseproxy_test.go
@@ -153,15 +153,20 @@ func TestReverseProxy(t *testing.T) {
func TestReverseProxyStripHeadersPresentInConnection(t *testing.T) {
const fakeConnectionToken = "X-Fake-Connection-Token"
const backendResponse = "I am the backend"
+
+ // someConnHeader is some arbitrary header to be declared as a hop-by-hop header
+ // in the Request's Connection header.
+ const someConnHeader = "X-Some-Conn-Header"
+
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if c := r.Header.Get(fakeConnectionToken); c != "" {
t.Errorf("handler got header %q = %q; want empty", fakeConnectionToken, c)
}
- if c := r.Header.Get("Upgrade"); c != "" {
- t.Errorf("handler got header %q = %q; want empty", "Upgrade", c)
+ if c := r.Header.Get(someConnHeader); c != "" {
+ t.Errorf("handler got header %q = %q; want empty", someConnHeader, c)
}
- w.Header().Set("Connection", "Upgrade, "+fakeConnectionToken)
- w.Header().Set("Upgrade", "should be deleted")
+ w.Header().Set("Connection", someConnHeader+", "+fakeConnectionToken)
+ w.Header().Set(someConnHeader, "should be deleted")
w.Header().Set(fakeConnectionToken, "should be deleted")
io.WriteString(w, backendResponse)
}))
@@ -173,15 +178,15 @@ func TestReverseProxyStripHeadersPresentInConnection(t *testing.T) {
proxyHandler := NewSingleHostReverseProxy(backendURL)
frontend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
proxyHandler.ServeHTTP(w, r)
- if c := r.Header.Get("Upgrade"); c != "original value" {
- t.Errorf("handler modified header %q = %q; want %q", "Upgrade", c, "original value")
+ if c := r.Header.Get(someConnHeader); c != "original value" {
+ t.Errorf("handler modified header %q = %q; want %q", someConnHeader, c, "original value")
}
}))
defer frontend.Close()
getReq, _ := http.NewRequest("GET", frontend.URL, nil)
- getReq.Header.Set("Connection", "Upgrade, "+fakeConnectionToken)
- getReq.Header.Set("Upgrade", "original value")
+ getReq.Header.Set("Connection", someConnHeader+", "+fakeConnectionToken)
+ getReq.Header.Set(someConnHeader, "original value")
getReq.Header.Set(fakeConnectionToken, "should be deleted")
res, err := frontend.Client().Do(getReq)
if err != nil {
@@ -195,8 +200,8 @@ func TestReverseProxyStripHeadersPresentInConnection(t *testing.T) {
if got, want := string(bodyBytes), backendResponse; got != want {
t.Errorf("got body %q; want %q", got, want)
}
- if c := res.Header.Get("Upgrade"); c != "" {
- t.Errorf("handler got header %q = %q; want empty", "Upgrade", c)
+ if c := res.Header.Get(someConnHeader); c != "" {
+ t.Errorf("handler got header %q = %q; want empty", someConnHeader, c)
}
if c := res.Header.Get(fakeConnectionToken); c != "" {
t.Errorf("handler got header %q = %q; want empty", fakeConnectionToken, c)
@@ -980,3 +985,66 @@ func TestSelectFlushInterval(t *testing.T) {
})
}
}
+
+func TestReverseProxyWebSocket(t *testing.T) {
+ backendServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if upgradeType(r.Header) != "websocket" {
+ t.Error("unexpected backend request")
+ http.Error(w, "unexpected request", 400)
+ return
+ }
+ c, _, err := w.(http.Hijacker).Hijack()
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ defer c.Close()
+ io.WriteString(c, "HTTP/1.1 101 Switching Protocols\r\nConnection: upgrade\r\nUpgrade: WebSocket\r\n\r\n")
+ bs := bufio.NewScanner(c)
+ if !bs.Scan() {
+ t.Errorf("backend failed to read line from client: %v", bs.Err())
+ return
+ }
+ fmt.Fprintf(c, "backend got %q\n", bs.Text())
+ }))
+ defer backendServer.Close()
+
+ backURL, _ := url.Parse(backendServer.URL)
+ rproxy := NewSingleHostReverseProxy(backURL)
+ rproxy.ErrorLog = log.New(ioutil.Discard, "", 0) // quiet for tests
+
+ frontendProxy := httptest.NewServer(rproxy)
+ defer frontendProxy.Close()
+
+ req, _ := http.NewRequest("GET", frontendProxy.URL, nil)
+ req.Header.Set("Connection", "Upgrade")
+ req.Header.Set("Upgrade", "websocket")
+
+ c := frontendProxy.Client()
+ res, err := c.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if res.StatusCode != 101 {
+ t.Fatalf("status = %v; want 101", res.Status)
+ }
+ if upgradeType(res.Header) != "websocket" {
+ t.Fatalf("not websocket upgrade; got %#v", res.Header)
+ }
+ rwc, ok := res.Body.(io.ReadWriteCloser)
+ if !ok {
+ t.Fatalf("response body is of type %T; does not implement ReadWriteCloser", res.Body)
+ }
+ defer rwc.Close()
+
+ io.WriteString(rwc, "Hello\n")
+ bs := bufio.NewScanner(rwc)
+ if !bs.Scan() {
+ t.Fatalf("Scan: %v", bs.Err())
+ }
+ got := bs.Text()
+ want := `backend got "Hello"`
+ if got != want {
+ t.Errorf("got %#q, want %#q", got, want)
+ }
+}
diff --git a/src/net/http/transport.go b/src/net/http/transport.go
index c459092cb8987..7ef414ba53a2f 100644
--- a/src/net/http/transport.go
+++ b/src/net/http/transport.go
@@ -1714,7 +1714,7 @@ func (pc *persistConn) readLoop() {
alive = false
}
- if !hasBody {
+ if !hasBody || bodyWritable {
pc.t.setReqCanceler(rc.req, nil)
// Put the idle conn back into the pool before we send the response
From de50ea3cd848f187766825402f8d6c8109536443 Mon Sep 17 00:00:00 2001
From: Russ Cox
Date: Mon, 12 Nov 2018 11:36:12 -0500
Subject: [PATCH 020/594] bufio: put notes about len(p) together
CL 145577 added the part about io.ReadFull to read len(p)
but it should be next to the existing sentence about not
reading len(p) bytes.
Change-Id: Idfa037c59a3085d44d5da6129188473db0e96d23
Reviewed-on: https://go-review.googlesource.com/c/148903
Run-TryBot: Russ Cox
TryBot-Result: Gobot Gobot
Reviewed-by: Brad Fitzpatrick
Reviewed-by: Alan Donovan
---
src/bufio/bufio.go | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/bufio/bufio.go b/src/bufio/bufio.go
index e498dfea1ed16..46df6192280b8 100644
--- a/src/bufio/bufio.go
+++ b/src/bufio/bufio.go
@@ -186,9 +186,8 @@ func (b *Reader) Discard(n int) (discarded int, err error) {
// It returns the number of bytes read into p.
// The bytes are taken from at most one Read on the underlying Reader,
// hence n may be less than len(p).
-// At EOF, the count will be zero and err will be io.EOF.
-//
// To read exactly len(p) bytes, use io.ReadFull(b, p).
+// At EOF, the count will be zero and err will be io.EOF.
func (b *Reader) Read(p []byte) (n int, err error) {
n = len(p)
if n == 0 {
From a48a666bc89d355205550d43a9fdf1a9c507a123 Mon Sep 17 00:00:00 2001
From: Russ Cox
Date: Mon, 12 Nov 2018 22:20:17 -0500
Subject: [PATCH 021/594] go/build: do not suggest runtime.Version in comment
The form of runtime.Version is not guaranteed to be helpful.
Do not suggest it. (The suggestion was added in CL 136215.)
Change-Id: I3227d2e66b6ce860b7e62d7ba531c18fb173823c
Reviewed-on: https://go-review.googlesource.com/c/149258
Run-TryBot: Russ Cox
TryBot-Result: Gobot Gobot
Reviewed-by: Ian Lance Taylor
---
src/go/build/doc.go | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/go/build/doc.go b/src/go/build/doc.go
index 682315cbd6a43..8e3858feea926 100644
--- a/src/go/build/doc.go
+++ b/src/go/build/doc.go
@@ -111,8 +111,7 @@
// - "go1.12", from Go version 1.12 onward
// - any additional words listed in ctxt.BuildTags
//
-// There are no build tags for beta or minor releases. Programs that need the
-// minor release number can call runtime.Version.
+// There are no build tags for beta or minor releases.
//
// If a file's name, after stripping the extension and a possible _test suffix,
// matches any of the following patterns:
From 9d025bdafe8390011428b27fe944ee6acc8fa011 Mon Sep 17 00:00:00 2001
From: Russ Cox
Date: Mon, 12 Nov 2018 12:42:47 -0500
Subject: [PATCH 022/594] container/heap: adjust wording in comments
Followup to CL 129779 but also some other minor tweaks.
Change-Id: Id71455d8a14f5e33f82c942c9e892da56c49d17c
Reviewed-on: https://go-review.googlesource.com/c/149257
Run-TryBot: Russ Cox
TryBot-Result: Gobot Gobot
Reviewed-by: Brad Fitzpatrick
---
src/container/heap/heap.go | 21 +++++++++------------
1 file changed, 9 insertions(+), 12 deletions(-)
diff --git a/src/container/heap/heap.go b/src/container/heap/heap.go
index 1ed0da8e6a653..2e09da8613aa3 100644
--- a/src/container/heap/heap.go
+++ b/src/container/heap/heap.go
@@ -38,7 +38,7 @@ type Interface interface {
// Init establishes the heap invariants required by the other routines in this package.
// Init is idempotent with respect to the heap invariants
// and may be called whenever the heap invariants may have been invalidated.
-// Its complexity is O(n) where n = h.Len().
+// The complexity is O(n) where n = h.Len().
func Init(h Interface) {
// heapify
n := h.Len()
@@ -47,18 +47,16 @@ func Init(h Interface) {
}
}
-// Push pushes the element x onto the heap. The complexity is
-// O(log(n)) where n = h.Len().
-//
+// Push pushes the element x onto the heap.
+// The complexity is O(log n) where n = h.Len().
func Push(h Interface, x interface{}) {
h.Push(x)
up(h, h.Len()-1)
}
-// Pop removes the minimum element (according to Less) from the heap
-// and returns it. The complexity is O(log(n)) where n = h.Len().
-// It is equivalent to Remove(h, 0).
-//
+// Pop removes and returns the minimum element (according to Less) from the heap.
+// The complexity is O(log n) where n = h.Len().
+// Pop is equivalent to Remove(h, 0).
func Pop(h Interface) interface{} {
n := h.Len() - 1
h.Swap(0, n)
@@ -66,9 +64,8 @@ func Pop(h Interface) interface{} {
return h.Pop()
}
-// Remove removes the element at index i from the heap and returns
-// the element. The complexity is O(log(n)) where n = h.Len().
-//
+// Remove removes and returns the element at index i from the heap.
+// The complexity is O(log n) where n = h.Len().
func Remove(h Interface, i int) interface{} {
n := h.Len() - 1
if n != i {
@@ -83,7 +80,7 @@ func Remove(h Interface, i int) interface{} {
// Fix re-establishes the heap ordering after the element at index i has changed its value.
// Changing the value of the element at index i and then calling Fix is equivalent to,
// but less expensive than, calling Remove(h, i) followed by a Push of the new value.
-// The complexity is O(log(n)) where n = h.Len().
+// The complexity is O(log n) where n = h.Len().
func Fix(h Interface, i int) {
if !down(h, i, h.Len()) {
up(h, i)
From e51b19a993efa61b7d8f8d2828d9ee95ea82c98c Mon Sep 17 00:00:00 2001
From: Martin Garton
Date: Tue, 13 Nov 2018 13:34:42 +0000
Subject: [PATCH 023/594] bufio: make Reader.Peek invalidate Unreads
Since Reader.Peek potentially reads from the underlying io.Reader,
discarding previous buffers, UnreadRune and UnreadByte cannot
necessarily work. Change Peek to invalidate the unread buffers in all
cases (as allowed according to the documentation) and thus prevent
hiding bugs in the caller.
(This change was previoiusly merged and then reverted due concern about
being too close to a release)
Fixes #18556
Change-Id: I9027d75aa834d4b27703f37711ba25de04d89f3c
GitHub-Last-Rev: 917ef1e51131d734f92efc946a0ab5ca4ff69be6
GitHub-Pull-Request: golang/go#28768
Reviewed-on: https://go-review.googlesource.com/c/149297
Run-TryBot: Ian Lance Taylor
TryBot-Result: Gobot Gobot
Reviewed-by: Ian Lance Taylor
---
src/bufio/bufio.go | 3 +++
src/bufio/bufio_test.go | 18 ++++++++++++++++++
2 files changed, 21 insertions(+)
diff --git a/src/bufio/bufio.go b/src/bufio/bufio.go
index 46df6192280b8..ffb278ad9e2d0 100644
--- a/src/bufio/bufio.go
+++ b/src/bufio/bufio.go
@@ -128,6 +128,9 @@ func (b *Reader) Peek(n int) ([]byte, error) {
return nil, ErrNegativeCount
}
+ b.lastByte = -1
+ b.lastRuneSize = -1
+
for b.w-b.r < n && b.w-b.r < len(b.buf) && b.err == nil {
b.fill() // b.w-b.r < len(b.buf) => buffer is not full
}
diff --git a/src/bufio/bufio_test.go b/src/bufio/bufio_test.go
index 34d70312f7bc0..f7a0682e7033d 100644
--- a/src/bufio/bufio_test.go
+++ b/src/bufio/bufio_test.go
@@ -285,6 +285,24 @@ func TestUnreadRune(t *testing.T) {
}
}
+func TestNoUnreadRuneAfterPeek(t *testing.T) {
+ br := NewReader(strings.NewReader("example"))
+ br.ReadRune()
+ br.Peek(1)
+ if err := br.UnreadRune(); err == nil {
+ t.Error("UnreadRune didn't fail after Peek")
+ }
+}
+
+func TestNoUnreadByteAfterPeek(t *testing.T) {
+ br := NewReader(strings.NewReader("example"))
+ br.ReadByte()
+ br.Peek(1)
+ if err := br.UnreadByte(); err == nil {
+ t.Error("UnreadByte didn't fail after Peek")
+ }
+}
+
func TestUnreadByte(t *testing.T) {
segments := []string{"Hello, ", "world"}
r := NewReader(&StringReader{data: segments})
From 8f7173dcdeb1a1c8af885bb2a267674b4f5fbfc4 Mon Sep 17 00:00:00 2001
From: Russ Cox
Date: Tue, 13 Nov 2018 15:15:02 +0000
Subject: [PATCH 024/594] cmd/go: revert "remove unnecessary else conditions"
This reverts CL 144137.
Reason for revert: The justification for the original commit
was that golint said so, but golint is wrong. The code reads
more clearly the original way.
Change-Id: I960f286ed66fec67aabd953e7b69993f60b00bca
Reviewed-on: https://go-review.googlesource.com/c/149339
Reviewed-by: Russ Cox
---
src/cmd/go/internal/semver/semver.go | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/src/cmd/go/internal/semver/semver.go b/src/cmd/go/internal/semver/semver.go
index d61c6b476a678..4af7118e55d2e 100644
--- a/src/cmd/go/internal/semver/semver.go
+++ b/src/cmd/go/internal/semver/semver.go
@@ -312,8 +312,9 @@ func compareInt(x, y string) int {
}
if x < y {
return -1
+ } else {
+ return +1
}
- return +1
}
func comparePrerelease(x, y string) int {
@@ -352,8 +353,9 @@ func comparePrerelease(x, y string) int {
if ix != iy {
if ix {
return -1
+ } else {
+ return +1
}
- return +1
}
if ix {
if len(dx) < len(dy) {
@@ -365,14 +367,16 @@ func comparePrerelease(x, y string) int {
}
if dx < dy {
return -1
+ } else {
+ return +1
}
- return +1
}
}
if x == "" {
return -1
+ } else {
+ return +1
}
- return +1
}
func nextIdent(x string) (dx, rest string) {
From 43edf21eff83e95b32cc43453c3a8df816d85e88 Mon Sep 17 00:00:00 2001
From: Than McIntosh
Date: Tue, 6 Nov 2018 15:07:46 -0500
Subject: [PATCH 025/594] cmd/cgo: fix typo in gccgo name mangling recipe
The code to implement new-style gccgo name mangling had a recipe that
didn't quite match that of the compiler (incorrect handling for '.').
This showed up as a failure in the gotools cgo test if the directory
containing the test run included a "." character.
[This is a copy of https://golang.org/cl/147917].
Change-Id: Ia94728ecead879c8d223eb6cee6c102a8af1c86e
Reviewed-on: https://go-review.googlesource.com/c/147937
Reviewed-by: Cherry Zhang
---
src/cmd/cgo/out.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index c203873b13084..bc0b0b63877a3 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -1271,7 +1271,7 @@ func gccgoPkgpathToSymbolNew(ppath string) string {
for _, c := range []byte(ppath) {
switch {
case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z',
- '0' <= c && c <= '9', '_' == c:
+ '0' <= c && c <= '9', c == '_', c == '.':
bsl = append(bsl, c)
default:
changed = true
From b075dfba8066033e35cd62aaacf3c8a2593cfa57 Mon Sep 17 00:00:00 2001
From: Russ Cox
Date: Tue, 13 Nov 2018 09:46:32 -0500
Subject: [PATCH 026/594] cmd/go/internal/modload: skip go.mod directories on
all systems, not just Plan 9
I see no reason Plan 9 should be special cased.
A directory named go.mod is not useful on any system.
Followup to CL 129804.
Change-Id: I9cc91b5934b17650bfdb07370aa73aeae445968c
Reviewed-on: https://go-review.googlesource.com/c/149337
Run-TryBot: Russ Cox
TryBot-Result: Gobot Gobot
Reviewed-by: Brad Fitzpatrick
Reviewed-by: Bryan C. Mills
---
src/cmd/go/internal/modload/init.go | 5 ++---
.../go/internal/modload/{init_plan9_test.go => init_test.go} | 0
2 files changed, 2 insertions(+), 3 deletions(-)
rename src/cmd/go/internal/modload/{init_plan9_test.go => init_test.go} (100%)
diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go
index da778b4fad413..7e8c223189395 100644
--- a/src/cmd/go/internal/modload/init.go
+++ b/src/cmd/go/internal/modload/init.go
@@ -25,7 +25,6 @@ import (
"path"
"path/filepath"
"regexp"
- "runtime"
"strconv"
"strings"
)
@@ -402,7 +401,7 @@ func FindModuleRoot(dir, limit string, legacyConfigOK bool) (root, file string)
// Look for enclosing go.mod.
for {
- if fi, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil && !(runtime.GOOS == "plan9" && fi.IsDir()) {
+ if fi, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil && !fi.IsDir() {
return dir, "go.mod"
}
if dir == limit {
@@ -420,7 +419,7 @@ func FindModuleRoot(dir, limit string, legacyConfigOK bool) (root, file string)
dir = dir1
for {
for _, name := range altConfigs {
- if fi, err := os.Stat(filepath.Join(dir, name)); err == nil && !(runtime.GOOS == "plan9" && fi.IsDir()) {
+ if fi, err := os.Stat(filepath.Join(dir, name)); err == nil && !fi.IsDir() {
return dir, name
}
}
diff --git a/src/cmd/go/internal/modload/init_plan9_test.go b/src/cmd/go/internal/modload/init_test.go
similarity index 100%
rename from src/cmd/go/internal/modload/init_plan9_test.go
rename to src/cmd/go/internal/modload/init_test.go
From e787b133284263e53154b8b2f8f6078e8f0c9850 Mon Sep 17 00:00:00 2001
From: Alan Donovan
Date: Mon, 12 Nov 2018 13:42:46 -0500
Subject: [PATCH 027/594] cmd/go: vet: pass non-.go files to vet tool
The "gofiles" cache entry has been renamed "srcfiles", and it includes
non-Go files (.s, .c, .cxx) that belong to the package. It does not
include raw cgo files.
Added regression test.
Fixes #27665
Change-Id: I4884fe9b4f823f50705f8c2d357a04a8e567734f
Reviewed-on: https://go-review.googlesource.com/c/148904
Reviewed-by: Bryan C. Mills
---
src/cmd/go/internal/work/exec.go | 51 ++++++++++++++++++--------
src/cmd/go/testdata/script/vet_asm.txt | 15 ++++++++
src/cmd/vet/main.go | 8 +++-
3 files changed, 58 insertions(+), 16 deletions(-)
create mode 100644 src/cmd/go/testdata/script/vet_asm.txt
diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
index d31f96591b727..d6f9021c35c09 100644
--- a/src/cmd/go/internal/work/exec.go
+++ b/src/cmd/go/internal/work/exec.go
@@ -377,7 +377,7 @@ func (b *Builder) build(a *Action) (err error) {
if b.NeedExport {
p.Export = a.built
}
- if need&needCompiledGoFiles != 0 && b.loadCachedGoFiles(a) {
+ if need&needCompiledGoFiles != 0 && b.loadCachedSrcFiles(a) {
need &^= needCompiledGoFiles
}
// Otherwise, we need to write files to a.Objdir (needVet, needCgoHdr).
@@ -575,7 +575,13 @@ func (b *Builder) build(a *Action) (err error) {
b.cacheCgoHdr(a)
}
}
- b.cacheGofiles(a, gofiles)
+
+ var srcfiles []string // .go and non-.go
+ srcfiles = append(srcfiles, gofiles...)
+ srcfiles = append(srcfiles, sfiles...)
+ srcfiles = append(srcfiles, cfiles...)
+ srcfiles = append(srcfiles, cxxfiles...)
+ b.cacheSrcFiles(a, srcfiles)
// Running cgo generated the cgo header.
need &^= needCgoHdr
@@ -587,11 +593,11 @@ func (b *Builder) build(a *Action) (err error) {
// Prepare Go vet config if needed.
if need&needVet != 0 {
- buildVetConfig(a, gofiles)
+ buildVetConfig(a, srcfiles)
need &^= needVet
}
if need&needCompiledGoFiles != 0 {
- if !b.loadCachedGoFiles(a) {
+ if !b.loadCachedSrcFiles(a) {
return fmt.Errorf("failed to cache compiled Go files")
}
need &^= needCompiledGoFiles
@@ -794,13 +800,13 @@ func (b *Builder) loadCachedCgoHdr(a *Action) bool {
return err == nil
}
-func (b *Builder) cacheGofiles(a *Action, gofiles []string) {
+func (b *Builder) cacheSrcFiles(a *Action, srcfiles []string) {
c := cache.Default()
if c == nil {
return
}
var buf bytes.Buffer
- for _, file := range gofiles {
+ for _, file := range srcfiles {
if !strings.HasPrefix(file, a.Objdir) {
// not generated
buf.WriteString("./")
@@ -815,7 +821,7 @@ func (b *Builder) cacheGofiles(a *Action, gofiles []string) {
return
}
}
- c.PutBytes(cache.Subkey(a.actionID, "gofiles"), buf.Bytes())
+ c.PutBytes(cache.Subkey(a.actionID, "srcfiles"), buf.Bytes())
}
func (b *Builder) loadCachedVet(a *Action) bool {
@@ -823,34 +829,34 @@ func (b *Builder) loadCachedVet(a *Action) bool {
if c == nil {
return false
}
- list, _, err := c.GetBytes(cache.Subkey(a.actionID, "gofiles"))
+ list, _, err := c.GetBytes(cache.Subkey(a.actionID, "srcfiles"))
if err != nil {
return false
}
- var gofiles []string
+ var srcfiles []string
for _, name := range strings.Split(string(list), "\n") {
if name == "" { // end of list
continue
}
if strings.HasPrefix(name, "./") {
- gofiles = append(gofiles, name[2:])
+ srcfiles = append(srcfiles, name[2:])
continue
}
if err := b.loadCachedObjdirFile(a, c, name); err != nil {
return false
}
- gofiles = append(gofiles, a.Objdir+name)
+ srcfiles = append(srcfiles, a.Objdir+name)
}
- buildVetConfig(a, gofiles)
+ buildVetConfig(a, srcfiles)
return true
}
-func (b *Builder) loadCachedGoFiles(a *Action) bool {
+func (b *Builder) loadCachedSrcFiles(a *Action) bool {
c := cache.Default()
if c == nil {
return false
}
- list, _, err := c.GetBytes(cache.Subkey(a.actionID, "gofiles"))
+ list, _, err := c.GetBytes(cache.Subkey(a.actionID, "srcfiles"))
if err != nil {
return false
}
@@ -879,6 +885,7 @@ type vetConfig struct {
Dir string // directory containing package
ImportPath string // canonical import path ("package path")
GoFiles []string // absolute paths to package source files
+ NonGoFiles []string // absolute paths to package non-Go files
ImportMap map[string]string // map import path in source code to package path
PackageFile map[string]string // map package path to .a file with export data
@@ -890,7 +897,18 @@ type vetConfig struct {
SucceedOnTypecheckFailure bool // awful hack; see #18395 and below
}
-func buildVetConfig(a *Action, gofiles []string) {
+func buildVetConfig(a *Action, srcfiles []string) {
+ // Classify files based on .go extension.
+ // srcfiles does not include raw cgo files.
+ var gofiles, nongofiles []string
+ for _, name := range srcfiles {
+ if strings.HasSuffix(name, ".go") {
+ gofiles = append(gofiles, name)
+ } else {
+ nongofiles = append(nongofiles, name)
+ }
+ }
+
// Pass list of absolute paths to vet,
// so that vet's error messages will use absolute paths,
// so that we can reformat them relative to the directory
@@ -899,6 +917,7 @@ func buildVetConfig(a *Action, gofiles []string) {
Compiler: cfg.BuildToolchainName,
Dir: a.Package.Dir,
GoFiles: mkAbsFiles(a.Package.Dir, gofiles),
+ NonGoFiles: mkAbsFiles(a.Package.Dir, nongofiles),
ImportPath: a.Package.ImportPath,
ImportMap: make(map[string]string),
PackageFile: make(map[string]string),
@@ -995,6 +1014,8 @@ func (b *Builder) vet(a *Action) error {
}
}
+ // TODO(adonovan): delete this when we use the new vet printf checker.
+ // https://github.com/golang/go/issues/28756
if vcfg.ImportMap["fmt"] == "" {
a1 := a.Deps[1]
vcfg.ImportMap["fmt"] = "fmt"
diff --git a/src/cmd/go/testdata/script/vet_asm.txt b/src/cmd/go/testdata/script/vet_asm.txt
new file mode 100644
index 0000000000000..a066058c705b5
--- /dev/null
+++ b/src/cmd/go/testdata/script/vet_asm.txt
@@ -0,0 +1,15 @@
+# Issue 27665. Verify that "go vet" analyzes non-Go files.
+
+env GOARCH=amd64
+! go vet -asmdecl a
+stderr 'f: invalid MOVW of x'
+
+-- a/a.go --
+package a
+
+func f(x int8)
+
+-- a/asm.s --
+TEXT ·f(SB),0,$0-1
+ MOVW x+0(FP), AX
+ RET
diff --git a/src/cmd/vet/main.go b/src/cmd/vet/main.go
index cf91e4d59679f..799f0bfb64329 100644
--- a/src/cmd/vet/main.go
+++ b/src/cmd/vet/main.go
@@ -365,6 +365,7 @@ type vetConfig struct {
Dir string
ImportPath string
GoFiles []string
+ NonGoFiles []string
ImportMap map[string]string
PackageFile map[string]string
Standard map[string]bool
@@ -430,7 +431,12 @@ func doPackageCfg(cfgFile string) {
stdImporter = &vcfg
inittypes()
mustTypecheck = true
- doPackage(vcfg.GoFiles, nil)
+
+ var allFiles []string
+ allFiles = append(allFiles, vcfg.GoFiles...)
+ allFiles = append(allFiles, vcfg.NonGoFiles...)
+
+ doPackage(allFiles, nil)
if vcfg.VetxOutput != "" {
out := make([]vetxExport, 0, len(exporters))
for name, fn := range exporters {
From 978cfa8e46d71992395d67382e96036596520cb6 Mon Sep 17 00:00:00 2001
From: "Fangming.Fang"
Date: Wed, 20 Jun 2018 09:09:03 +0000
Subject: [PATCH 028/594] cmd,runtime: enable race detector on arm64
Changes include:
1. enable compiler option -race for arm64
2. add runtime/race_arm64.s to manage the calls from Go to the compiler-rt runtime
3. change racewalk.go to call racefuncenterfp instead of racefuncenter on arm64 to
allow the caller pc to be obtained in the asm code before calling the tsan version
4. race_linux_arm64.syso comes from compiler-rt which just supports 48bit VA, compiler-rt
is fetched from master branch which latest commit is 3aa2b775d08f903f804246af10b
Fixes #25682
Change-Id: I04364c580b8157fd117deecae74a4656ba16e005
Reviewed-on: https://go-review.googlesource.com/c/138675
Run-TryBot: Cherry Zhang
TryBot-Result: Gobot Gobot
Reviewed-by: Cherry Zhang
---
src/cmd/compile/internal/gc/racewalk.go | 4 +-
src/cmd/go/internal/work/init.go | 2 +-
src/cmd/internal/sys/supported.go | 2 +-
src/cmd/link/internal/ld/config.go | 4 +-
src/race.bash | 4 +-
src/runtime/asm_arm64.s | 3 +-
src/runtime/race/README | 1 +
src/runtime/race/race.go | 2 +-
src/runtime/race/race_linux_arm64.syso | Bin 0 -> 418080 bytes
src/runtime/race_arm64.s | 445 ++++++++++++++++++++++++
10 files changed, 457 insertions(+), 10 deletions(-)
create mode 100644 src/runtime/race/race_linux_arm64.syso
create mode 100644 src/runtime/race_arm64.s
diff --git a/src/cmd/compile/internal/gc/racewalk.go b/src/cmd/compile/internal/gc/racewalk.go
index 8a8b436a23ab2..6f251377c94ea 100644
--- a/src/cmd/compile/internal/gc/racewalk.go
+++ b/src/cmd/compile/internal/gc/racewalk.go
@@ -71,14 +71,14 @@ func instrument(fn *Node) {
lno := lineno
lineno = src.NoXPos
- if thearch.LinkArch.Arch == sys.ArchPPC64LE {
+ if thearch.LinkArch.Arch.Family != sys.AMD64 {
fn.Func.Enter.Prepend(mkcall("racefuncenterfp", nil, nil))
fn.Func.Exit.Append(mkcall("racefuncexit", nil, nil))
} else {
// nodpc is the PC of the caller as extracted by
// getcallerpc. We use -widthptr(FP) for x86.
- // BUG: This only works for amd64. This will not
+ // This only works for amd64. This will not
// work on arm or others that might support
// race in the future.
nodpc := nodfp.copy()
diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go
index 3f6252ed84b7f..8d2fd10524b06 100644
--- a/src/cmd/go/internal/work/init.go
+++ b/src/cmd/go/internal/work/init.go
@@ -49,7 +49,7 @@ func instrumentInit() {
}
if cfg.BuildRace {
if !sys.RaceDetectorSupported(cfg.Goos, cfg.Goarch) {
- fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, linux/ppc64le, freebsd/amd64, netbsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
+ fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, linux/ppc64le, linux/arm64, freebsd/amd64, netbsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
os.Exit(2)
}
}
diff --git a/src/cmd/internal/sys/supported.go b/src/cmd/internal/sys/supported.go
index 22dec702a576d..a53da6ed2cbeb 100644
--- a/src/cmd/internal/sys/supported.go
+++ b/src/cmd/internal/sys/supported.go
@@ -9,7 +9,7 @@ package sys
func RaceDetectorSupported(goos, goarch string) bool {
switch goos {
case "linux":
- return goarch == "amd64" || goarch == "ppc64le"
+ return goarch == "amd64" || goarch == "ppc64le" || goarch == "arm64"
case "darwin", "freebsd", "netbsd", "windows":
return goarch == "amd64"
default:
diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go
index 77b03b67f9b82..2f6dd7a7e22d8 100644
--- a/src/cmd/link/internal/ld/config.go
+++ b/src/cmd/link/internal/ld/config.go
@@ -199,8 +199,8 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) {
// When the race flag is set, the LLVM tsan relocatable file is linked
// into the final binary, which means external linking is required because
// internal linking does not support it.
- if *flagRace && ctxt.Arch.InFamily(sys.PPC64) {
- return true, "race on ppc64le"
+ if *flagRace && ctxt.Arch.InFamily(sys.PPC64, sys.ARM64) {
+ return true, "race on " + objabi.GOARCH
}
// Some build modes require work the internal linker cannot do (yet).
diff --git a/src/race.bash b/src/race.bash
index d673f503a9a73..e83c175df3b4c 100755
--- a/src/race.bash
+++ b/src/race.bash
@@ -9,7 +9,7 @@
set -e
function usage {
- echo 'race detector is only supported on linux/amd64, linux/ppc64le, freebsd/amd64, netbsd/amd64 and darwin/amd64' 1>&2
+ echo 'race detector is only supported on linux/amd64, linux/ppc64le, linux/arm64, freebsd/amd64, netbsd/amd64 and darwin/amd64' 1>&2
exit 1
}
@@ -21,7 +21,7 @@ case $(uname) in
fi
;;
"Linux")
- if [ $(uname -m) != "x86_64" ] && [ $(uname -m) != "ppc64le" ]; then
+ if [ $(uname -m) != "x86_64" ] && [ $(uname -m) != "ppc64le" ] && [ $(uname -m) != "aarch64" ]; then
usage
fi
;;
diff --git a/src/runtime/asm_arm64.s b/src/runtime/asm_arm64.s
index 2248cec132520..28d3077b9dea0 100644
--- a/src/runtime/asm_arm64.s
+++ b/src/runtime/asm_arm64.s
@@ -18,7 +18,8 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0
// create istack out of the given (operating system) stack.
// _cgo_init may update stackguard.
MOVD $runtime·g0(SB), g
- MOVD RSP, R7
+ BL runtime·save_g(SB)
+ MOVD RSP, R7
MOVD $(-64*1024)(R7), R0
MOVD R0, g_stackguard0(g)
MOVD R0, g_stackguard1(g)
diff --git a/src/runtime/race/README b/src/runtime/race/README
index 1c66c636956a8..be53b4c37c9a2 100644
--- a/src/runtime/race/README
+++ b/src/runtime/race/README
@@ -10,3 +10,4 @@ race_linux_amd64.syso built with LLVM fe2c72c59aa7f4afa45e3f65a5d16a374b6cce26 a
race_linux_ppc64le.syso built with LLVM fe2c72c59aa7f4afa45e3f65a5d16a374b6cce26 and Go 323c85862a7afbde66a3bba0776bf4ba6cd7c030.
race_netbsd_amd64.syso built with LLVM fe2c72c59aa7f4afa45e3f65a5d16a374b6cce26 and Go 323c85862a7afbde66a3bba0776bf4ba6cd7c030.
race_windows_amd64.syso built with LLVM ae08a22cc215448aa3ad5a6fb099f6df77e9fa01 and Go 323c85862a7afbde66a3bba0776bf4ba6cd7c030.
+race_linux_arm64.syso built with LLVM 3aa2b775d08f903f804246af10b80a439c16b436 and Go ef2c48659880c7e8a989e6721a21f018790f7793.
diff --git a/src/runtime/race/race.go b/src/runtime/race/race.go
index 95e965411b76d..d298e805cfaec 100644
--- a/src/runtime/race/race.go
+++ b/src/runtime/race/race.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build race,linux,amd64 race,freebsd,amd64 race,netbsd,amd64 race,darwin,amd64 race,windows,amd64 race,linux,ppc64le
+// +build race,linux,amd64 race,freebsd,amd64 race,netbsd,amd64 race,darwin,amd64 race,windows,amd64 race,linux,ppc64le race,linux,arm64
package race
diff --git a/src/runtime/race/race_linux_arm64.syso b/src/runtime/race/race_linux_arm64.syso
new file mode 100644
index 0000000000000000000000000000000000000000..65bc1ececa5a7cef882b63a37ab3a53b46952aae
GIT binary patch
literal 418080
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%0AA4>)PE{UyWno}D*KfRU%S*&&
z96MiURI|HZ#m9xNcKmhjx{RB=?oMd1iQf~xAAeljo@CnL_4g2pO$9Mip`QDYe*Rx;UouKa{@FD$Oq`3a`h|AO20n(#h?tu@O+ykxl
zcbBvI-DPlvZ>%+W-6tF9Pdp=)o?qMVv?*Yp-uVd6ZAdr?I}_*p(|D&;3aKK0fs$t&dOr
z@=c`mq|W2fkC?}!U%sETmGs-BJ4mB*ItuCa2B!&0i_MGL4fcv?E$u!MGM%+KO~P0AIxylj5vZd6-A6Pz~{LDg1n6
zdDkkBvwIPKFFh>B;rJS_ki4nmd6Seki@d_|yj#$lJm@~cZ>NWKp9e=?lstYvJX=w!@Ach?-KI(J@qh;V3ZnfA$gaK=gCj*Eh2B>
zc-}40iuu3Ed-wRLuJhh|?U?~&AO?dF*G4lE_(IaOwedxXPuL?7e616MV*5BbWk$jd
zj?yMJvCS>kNZ?C6J;xScr@>B$$IIUE@|%8q)?Zu)3XW8rm~kj}C78BWR`e
ze+Hbu);2`56`x8SD>uqE)Nr{+v!(y)EQikfO~zIlk2XVVe!O>iDE16AVPg_sz4UzP
z!=e!(cnjYnWYE~l!+xaWi~qMDx8ddd?wK%wd~6e2rRPM(lbZ0str2+lj7m+)kgx6Fu5i<#wUH)#
zo0s)K;}1fs4?PnhSD-s^J+!_D-NKk~dLjAYl+Urjgm3CyYv2VT^23EKJr^xcTxjj4
z&|%`AE{x+745u}g+6%G01AFT<-Ui{e7_^W|O`)dxP_?AkKj?7qb?__a)}!Gm)N$
zJ;KIzOlRGrVJ|jPb5Pue&S{vxSUAuz-fYvHe#3n1T*1xA-(eT-Wc~R%%soz>2rI?X-e`fTUpHY
zV!}+3nKz4A2F_~O{9`jHdlhBwp}Eee<+ft0we}2eKh716(0)vS-^if@J(qZKW*N>-X#Az%__|3;ehVH7x7s_#
zm@89T;uR_GxY!S_Uk2{)2iLJfR}<%Jab4$*_k-)M-ht~WeS_;+z8%JJ7316ouE+Sc
zJ~bcLGZ8cIFM$7c#)zEXB_;1T|
z_9csqc>(*V!Q$a`+gA{WsP%3U9|sR5>-JnSEF;GwIW{ayPhPb+39UJWe}t*uS>oa2
z5DdDIp;*7+|4x(a21EZ@f91s;`p^2ml>49c|7-pWE`kU8-3S~&4j7P}+bDi2Uvx44
z-W>mSKEHHUcyt_H+1hV45B#B)4{A?64}NGK&R5ngdLEckZlHrTRR6-a5P1SBiH*WW
zc<*8Q3{ie9G#C0e5dM;4pu}fNPwQV-+bs`yV^DkI;bHD7UF(=DBecC4SvbbpucJ+T
zH3MolLc2BWHJwul{H*!#pG~{A?Nnj@Rm=NM|DF0RLq;IBa$e|D%r_Nkf=_N+Dj6J^
zalXqrT|UVoY}1^94}D5`qn*AN;H81zCHPiZ^_^Tt{$FGlm5=!4Td@(y-yuIoaW!_)
zO7JRTWP{kY_CDZt&!|Y4lRWZhp_!Ioi
zjJM`))|>Het~3MHj3e|
zyB>eoT*)iq6X7+t6NhM?Tu0r5pLAbb*X+Dr`{OTn-yI>g(v0dOzOA}}Tmjta`c@15
zUg*mYF>oabOth}0*k_O#IkQxGSu`Qtk2n}`C%MLbDZVE0lEzx=>jp{mPVmP13`2aY
zjOc*M<(`WQ=A}8Y7n(G`q#u8t|E}|*6tbtcUnF;k7PEnebI?GSkukW>h#a=aIu2u(
zO-keZ3G%D@*KhIuUi9@IzR8X7BlcaMUwoK9W{@8@ych4*Ju9We)ArxQ`8Dcw!C&!x
z>>c3!SYY)4GL`PDJ^~(X2$iH2d!lm7ZQV#;4e-rEkIh8y?2Txn;*~hN!~NGK*7u`2
zo3T;v!nUcpt?bu*zh2Yr=q{pV54?gurcS=aGWM+I;j#u*tVIC-AAxuBRR(a=S-=3U
zE&jRg;ddoN?}9Vm2H0v}p(h^mVu?5h7-^gV4&94h)vkSNeYmc2h;iP4*h1C0pZLt>
z*lV9!bw&T?v5^tJ)ZzZZbAz!&qO8N;c{nS1SNl|aHg`Sy+4GWn-zFwX>!o~G?}SI$
zwIv>V8)q)($_8)`I@-nH*UtCmALD%2z}@(Cu_si|4^Qjs0p8NXwpJ3e77q7yu?F+U
zxo!LMTh%R4*EoZbDogS2)
z-|&gwrif>jA6~YVO5Teu)IPaxQy5szL1*5qI7H$PM=^Gna>NnreFVD(b9sF~@7}1dccnH7WQ6kXVwORp3U1wFIp
z)a9pUA9DY>@#HJ~dmZ2#XAvYz=>CEKBiu$$s3y)~TQRh1Bef9|%vGo2A|;`l+J*GCm#Pis+ZxRh!!Xwh!nCcZ+VyKkKV^De46A8>gFd
z{L>Fxni{-U9AqxtXvlk?53?5kJ^e{;v+|7kKEC?zY<|b6Z0@yQKK2^s-NU&$!B1r(
z`27|r&U}KN!)JIe`>Eh2pLCpe$5(sj_JZ*R{oD1r*BiU-k8?bN?_{4JNM9DLb*D~(
zZ>^E#2gvAxU5aPT$P38k=?FNzld}drtQ~O-b`DzC1ai!B$|<%XS9W!Xr5}zb@Z{Fa
zb;vzA@du)l+2g)^#~L}%nw{{F-!QLCl^1WJIvTrj2p$55B|quE)-88jwdjGt{FP@h
zfPwQ>Z~m%xV19~oOQ}VhvELbJPEbB5yNg(#*yF?S3gU_y*;jFVKd}yTYdJc9J$}l2
za^wz;BgQ&aviGAAlWsKLnIoNtc4oteSfem@QsJso
zgW9#@(EVN1|G^sPu};5!3j2oW#p%WqpZbX12ikYEwMa5p8EurWi9Ggwzl|;6!xG{(
z6FKnFIAV;Utk4+F(4WTJGTrM_^ATMsPI$RFC9CSpuyQL)_k0IFBR(kHco1HjK*r60
zBM<2Jjfx{R1LDDnO355%K=m!pvH6vU^YkAlr;hfA@V~c8G+X;n=T^PEa|b4PJ`Fvy
zXY1za8$QMU)ZWC_|Dz0X^hu+A*=6-Lz4yjX+l*g$FMFUDA59+ph1x$}tdPc)8(ZYn
z^Xy&IsH?f^9GCoJnzQDw`?1u=7Uo<=E)QZ&7oj^9>py<}i@39?t_FV6e2Z*XC2hrb
zEbmu8^9BdEWkU1!S(^iLmfGCl$2l<`?%jemC|1;-tMhU)Xgn%MACv67&rpu{z|j!%
zqdhJ-jeyxuTvHJ9IfePjHl=w5{9+w*h=A8xhld$|n0d(udJnQiGkN7I*>l)5wrPJU
z<~=4q0lFMHJ?3ey-WaEh$n(H6yFa`*YsJ))lSuZ9)ASFmw>pAkn-pU(=m1e-bt2Lk
z@u_qI+cWi*zn>a5uCx0n|9P|1Y{u
zdLufQ(V6*0N%9@kT=>xn?Gw*eFmk^LhHt|I^{sPQxp8-bb>Lsf(HBOnw{!>P^OoKq
zn_NIQ1b?l&)}OUU*JbU2e}UwA1YG
zlg!$+*G_?kXV$K}R&&@<Zh&xgYZK0k9LpVOQ?{$|=V2aoPczjNj$G$)I^2OcsU|4;eiTs%r#41e|gQ~`ZdA0Cf|*XGb>(E@B|
zmfwgjDrb5K-Xfl(^9eQJdDN<$!*=G;
z?9aKFId5c*0y?AT;xWpL;_(?DF3ewLf_MPUQ#{?y7db*aGT^0}pI{yEQ_5Ig+J#@9
zbr``%d&GC_T+hTuN6Hq#`U~%JVIMpf9TyD;23pJF7;%vH{Km-%_WTBSt#p?anMpCm
z99dR-4f!W#G?>^}XIc3*reR6%U$!*vI}94sE%E07K=_1
zud*IH8>)zt-i+T3dm^$pcOYWdO~SuJMZ#|68zI
zOVaT1$CcMCW~LKcGJl`u67=EZ+9;H_%$^1J^cvv{x+?Y;uYGh2(e#b#M}6p>`s=WE
z{*gLhA-WLonU>ppnt-io_QWN>ZD8%1L#g!v-dr}`eM>YX4xNsUpWhn8CZK&MTd>aD
zV5e!*U90SmpOn%@3-z<%&KII){=OINowDX9xq5p*pAHa@TZ1&!M+!#i8!dA51=I66@h!whh
zSl1Pg^kic1Uhw>J2wp9*M=k9W+=*Ej_Df)kQr`Dm{LZ(3#J}v-m2Rayx(j?B1AcAB
zueuD_O1G8kHjkMe(k>
zH(If-vKf$%XYQAY$#jWPvE}_T2EU+7jEbJ!L7YnITKqh;5zO7fXDn;$&%J`V&!>!o
z4?QTOI0uLK#BzYQz~=DC_i7`kU+%-Mnf>-Cc%-_6!XMF0PJJr!Q-PoIS*IzaG%Z9)B%WrgYiW*C>WTICMYl
z6vCrk_W40#Tn>cCw7tf9w)plH(T?x)|F8W2yZHS#{Eo7Y<*e!Re4gX?J$xVL^9H}~
z=F>sBM<^#bV5Gfq+7La7kQXGj%d=?&`&fScfTldh-R3QwBi{$_R5$CtI}_b>x=vG{
zFSlA^JD(+HShm;%HdzXN;A+3
zF0b?dFI{MK#=pAe2LBy%8)5rZJ6a#{Ny)jHM?*G_sfP6te_RSbI8f@_ny`aQ
z&kv*D%YJ(RUMjn7iqDW901RbQ&wnP}0lj8!?%iUY2AyTK@>+T}9pzp>3cd*b-nexB
zT=(92GP1Sd|8g@qF`*;inaYU=g?Q#rM*q7*#>)SaxyyMLV(xmLWlW+y!Y#@Dz