aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
Diffstat (limited to 'libgo')
-rw-r--r--libgo/MERGE2
-rw-r--r--libgo/go/crypto/tls/handshake_server.go10
-rw-r--r--libgo/go/crypto/tls/key_agreement.go4
-rw-r--r--libgo/go/exp/gotype/gotype.go2
-rw-r--r--libgo/go/exp/types/check_test.go2
-rw-r--r--libgo/go/exp/types/exportdata.go52
-rw-r--r--libgo/go/exp/types/gcimporter.go157
-rw-r--r--libgo/go/exp/types/gcimporter_test.go18
-rw-r--r--libgo/go/go/build/build.go3
-rw-r--r--libgo/go/image/image.go2
-rw-r--r--libgo/go/net/fd.go4
-rw-r--r--libgo/go/os/types.go2
-rw-r--r--libgo/go/path/filepath/path_test.go24
-rw-r--r--libgo/go/path/filepath/path_windows.go4
-rw-r--r--libgo/go/path/filepath/symlink_windows.go40
-rw-r--r--libgo/go/text/template/doc.go2
-rw-r--r--libgo/runtime/proc.c19
17 files changed, 225 insertions, 122 deletions
diff --git a/libgo/MERGE b/libgo/MERGE
index e7e992c..46a3588 100644
--- a/libgo/MERGE
+++ b/libgo/MERGE
@@ -1,4 +1,4 @@
-bce220d03774
+dc5e410f0b4c
The first line of this file holds the Mercurial revision number of the
last merge done from the master library sources.
diff --git a/libgo/go/crypto/tls/handshake_server.go b/libgo/go/crypto/tls/handshake_server.go
index 23ec558..77e56a7 100644
--- a/libgo/go/crypto/tls/handshake_server.go
+++ b/libgo/go/crypto/tls/handshake_server.go
@@ -60,21 +60,23 @@ FindCipherSuite:
for _, id := range clientHello.cipherSuites {
for _, supported := range config.cipherSuites() {
if id == supported {
- suite = nil
+ var candidate *cipherSuite
+
for _, s := range cipherSuites {
if s.id == id {
- suite = s
+ candidate = s
break
}
}
- if suite == nil {
+ if candidate == nil {
continue
}
// Don't select a ciphersuite which we can't
// support for this client.
- if suite.elliptic && !ellipticOk {
+ if candidate.elliptic && !ellipticOk {
continue
}
+ suite = candidate
break FindCipherSuite
}
}
diff --git a/libgo/go/crypto/tls/key_agreement.go b/libgo/go/crypto/tls/key_agreement.go
index 75f5c73..a931d8f 100644
--- a/libgo/go/crypto/tls/key_agreement.go
+++ b/libgo/go/crypto/tls/key_agreement.go
@@ -130,6 +130,10 @@ Curve:
}
}
+ if curveid == 0 {
+ return nil, errors.New("tls: no supported elliptic curves offered")
+ }
+
var x, y *big.Int
var err error
ka.privateKey, x, y, err = elliptic.GenerateKey(ka.curve, config.rand())
diff --git a/libgo/go/exp/gotype/gotype.go b/libgo/go/exp/gotype/gotype.go
index 30eaf22..3aca40e 100644
--- a/libgo/go/exp/gotype/gotype.go
+++ b/libgo/go/exp/gotype/gotype.go
@@ -171,7 +171,7 @@ func processFiles(filenames []string, allFiles bool) {
func processPackage(fset *token.FileSet, files map[string]*ast.File) {
// make a package (resolve all identifiers)
- pkg, err := ast.NewPackage(fset, files, types.GcImporter, types.Universe)
+ pkg, err := ast.NewPackage(fset, files, types.GcImport, types.Universe)
if err != nil {
report(err)
return
diff --git a/libgo/go/exp/types/check_test.go b/libgo/go/exp/types/check_test.go
index 0e20646..34c26c9 100644
--- a/libgo/go/exp/types/check_test.go
+++ b/libgo/go/exp/types/check_test.go
@@ -184,7 +184,7 @@ func check(t *testing.T, testname string, testfiles []string) {
eliminate(t, errors, err)
// verify errors returned after resolving identifiers
- pkg, err := ast.NewPackage(fset, files, GcImporter, Universe)
+ pkg, err := ast.NewPackage(fset, files, GcImport, Universe)
eliminate(t, errors, err)
// verify errors returned by the typechecker
diff --git a/libgo/go/exp/types/exportdata.go b/libgo/go/exp/types/exportdata.go
index fa5b6a3..bca2038 100644
--- a/libgo/go/exp/types/exportdata.go
+++ b/libgo/go/exp/types/exportdata.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.
-// This file implements ExportData.
+// This file implements FindGcExportData.
package types
@@ -11,15 +11,14 @@ import (
"errors"
"fmt"
"io"
- "os"
"strconv"
"strings"
)
-func readGopackHeader(buf *bufio.Reader) (name string, size int, err error) {
+func readGopackHeader(r *bufio.Reader) (name string, size int, err error) {
// See $GOROOT/include/ar.h.
hdr := make([]byte, 16+12+6+6+8+10+2)
- _, err = io.ReadFull(buf, hdr)
+ _, err = io.ReadFull(r, hdr)
if err != nil {
return
}
@@ -36,33 +35,14 @@ func readGopackHeader(buf *bufio.Reader) (name string, size int, err error) {
return
}
-type dataReader struct {
- *bufio.Reader
- io.Closer
-}
-
-// ExportData returns a readCloser positioned at the beginning of the
-// export data section of the given object/archive file, or an error.
-// It is the caller's responsibility to close the readCloser.
+// FindGcExportData positions the reader r at the beginning of the
+// export data section of an underlying GC-created object/archive
+// file by reading from it. The reader must be positioned at the
+// start of the file before calling this function.
//
-func ExportData(filename string) (rc io.ReadCloser, err error) {
- file, err := os.Open(filename)
- if err != nil {
- return
- }
-
- defer func() {
- if err != nil {
- file.Close()
- // Add file name to error.
- err = fmt.Errorf("reading export data: %s: %v", filename, err)
- }
- }()
-
- buf := bufio.NewReader(file)
-
+func FindGcExportData(r *bufio.Reader) (err error) {
// Read first line to make sure this is an object file.
- line, err := buf.ReadSlice('\n')
+ line, err := r.ReadSlice('\n')
if err != nil {
return
}
@@ -74,7 +54,7 @@ func ExportData(filename string) (rc io.ReadCloser, err error) {
// First entry should be __.SYMDEF.
// Read and discard.
- if name, size, err = readGopackHeader(buf); err != nil {
+ if name, size, err = readGopackHeader(r); err != nil {
return
}
if name != "__.SYMDEF" {
@@ -88,15 +68,14 @@ func ExportData(filename string) (rc io.ReadCloser, err error) {
if n > block {
n = block
}
- _, err = io.ReadFull(buf, tmp[:n])
- if err != nil {
+ if _, err = io.ReadFull(r, tmp[:n]); err != nil {
return
}
size -= n
}
// Second entry should be __.PKGDEF.
- if name, size, err = readGopackHeader(buf); err != nil {
+ if name, size, err = readGopackHeader(r); err != nil {
return
}
if name != "__.PKGDEF" {
@@ -106,8 +85,7 @@ func ExportData(filename string) (rc io.ReadCloser, err error) {
// Read first line of __.PKGDEF data, so that line
// is once again the first line of the input.
- line, err = buf.ReadSlice('\n')
- if err != nil {
+ if line, err = r.ReadSlice('\n'); err != nil {
return
}
}
@@ -122,12 +100,10 @@ func ExportData(filename string) (rc io.ReadCloser, err error) {
// Skip over object header to export data.
// Begins after first line with $$.
for line[0] != '$' {
- line, err = buf.ReadSlice('\n')
- if err != nil {
+ if line, err = r.ReadSlice('\n'); err != nil {
return
}
}
- rc = &dataReader{buf, file}
return
}
diff --git a/libgo/go/exp/types/gcimporter.go b/libgo/go/exp/types/gcimporter.go
index cb996f2..07ab087 100644
--- a/libgo/go/exp/types/gcimporter.go
+++ b/libgo/go/exp/types/gcimporter.go
@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This file implements an ast.Importer for gc generated object files.
+// This file implements an ast.Importer for gc-generated object files.
// TODO(gri) Eventually move this into a separate package outside types.
package types
import (
+ "bufio"
"errors"
"fmt"
"go/ast"
@@ -24,41 +25,40 @@ import (
const trace = false // set to true for debugging
-var (
- pkgExts = [...]string{".a", ".5", ".6", ".8"}
-)
+var pkgExts = [...]string{".a", ".5", ".6", ".8"}
-// findPkg returns the filename and package id for an import path.
+// FindPkg returns the filename and unique package id for an import
+// path based on package information provided by build.Import (using
+// the build.Default build.Context).
// If no file was found, an empty filename is returned.
-func findPkg(path string) (filename, id string) {
+//
+func FindPkg(path, srcDir string) (filename, id string) {
if len(path) == 0 {
return
}
id = path
var noext string
- switch path[0] {
+ switch {
default:
// "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x"
- bp, _ := build.Import(path, "", build.FindOnly)
+ bp, _ := build.Import(path, srcDir, build.FindOnly)
if bp.PkgObj == "" {
return
}
noext = bp.PkgObj
if strings.HasSuffix(noext, ".a") {
- noext = noext[:len(noext)-2]
+ noext = noext[:len(noext)-len(".a")]
}
- case '.':
+ case build.IsLocalImport(path):
// "./x" -> "/this/directory/x.ext", "/this/directory/x"
- cwd, err := os.Getwd()
- if err != nil {
- return
- }
- noext = filepath.Join(cwd, path)
+ noext = filepath.Join(srcDir, path)
id = noext
- case '/':
+ case filepath.IsAbs(path):
+ // for completeness only - go/build.Import
+ // does not support absolute imports
// "/x" -> "/x.ext", "/x"
noext = path
}
@@ -75,6 +75,89 @@ func findPkg(path string) (filename, id string) {
return
}
+// GcImportData imports a package by reading the gc-generated export data,
+// adds the corresponding package object to the imports map indexed by id,
+// and returns the object.
+//
+// The imports map must contains all packages already imported, and no map
+// entry with id as the key must be present. The data reader position must
+// be the beginning of the export data section. The filename is only used
+// in error messages.
+//
+func GcImportData(imports map[string]*ast.Object, filename, id string, data *bufio.Reader) (pkg *ast.Object, err error) {
+ if trace {
+ fmt.Printf("importing %s (%s)\n", id, filename)
+ }
+
+ if imports[id] != nil {
+ panic(fmt.Sprintf("package %s already imported", id))
+ }
+
+ // support for gcParser error handling
+ defer func() {
+ if r := recover(); r != nil {
+ err = r.(importError) // will re-panic if r is not an importError
+ }
+ }()
+
+ var p gcParser
+ p.init(filename, id, data, imports)
+ pkg = p.parseExport()
+
+ return
+}
+
+// GcImport imports a gc-generated package given its import path, adds the
+// corresponding package object to the imports map, and returns the object.
+// Local import paths are interpreted relative to the current working directory.
+// The imports map must contains all packages already imported.
+// GcImport satisfies the ast.Importer signature.
+//
+func GcImport(imports map[string]*ast.Object, path string) (pkg *ast.Object, err error) {
+ if path == "unsafe" {
+ return Unsafe, nil
+ }
+
+ srcDir, err := os.Getwd()
+ if err != nil {
+ return
+ }
+ filename, id := FindPkg(path, srcDir)
+ if filename == "" {
+ err = errors.New("can't find import: " + id)
+ return
+ }
+
+ if pkg = imports[id]; pkg != nil {
+ return // package was imported before
+ }
+
+ // open file
+ f, err := os.Open(filename)
+ if err != nil {
+ return
+ }
+ defer func() {
+ f.Close()
+ if err != nil {
+ // Add file name to error.
+ err = fmt.Errorf("reading export data: %s: %v", filename, err)
+ }
+ }()
+
+ buf := bufio.NewReader(f)
+ if err = FindGcExportData(buf); err != nil {
+ return
+ }
+
+ pkg, err = GcImportData(imports, filename, id, buf)
+
+ return
+}
+
+// ----------------------------------------------------------------------------
+// gcParser
+
// gcParser parses the exports inside a gc compiler-produced
// object/archive file and populates its scope with the results.
type gcParser struct {
@@ -109,47 +192,6 @@ func (p *gcParser) next() {
}
}
-// GcImporter implements the ast.Importer signature.
-func GcImporter(imports map[string]*ast.Object, path string) (pkg *ast.Object, err error) {
- if path == "unsafe" {
- return Unsafe, nil
- }
-
- defer func() {
- if r := recover(); r != nil {
- err = r.(importError) // will re-panic if r is not an importError
- if trace {
- panic(err) // force a stack trace
- }
- }
- }()
-
- filename, id := findPkg(path)
- if filename == "" {
- err = errors.New("can't find import: " + id)
- return
- }
-
- if pkg = imports[id]; pkg != nil {
- return // package was imported before
- }
-
- buf, err := ExportData(filename)
- if err != nil {
- return
- }
- defer buf.Close()
-
- if trace {
- fmt.Printf("importing %s (%s)\n", id, filename)
- }
-
- var p gcParser
- p.init(filename, id, buf, imports)
- pkg = p.parseExport()
- return
-}
-
// Declare inserts a named object of the given kind in scope.
func (p *gcParser) declare(scope *ast.Scope, kind ast.ObjKind, name string) *ast.Object {
// the object may have been imported before - if it exists
@@ -707,7 +749,6 @@ func (p *gcParser) parseConstDecl() {
p.next()
typ = String.Underlying
default:
- println(p.tok)
p.errorf("expected literal got %s", scanner.TokenString(p.tok))
}
if obj.Type == nil {
diff --git a/libgo/go/exp/types/gcimporter_test.go b/libgo/go/exp/types/gcimporter_test.go
index c229b50..20247b0 100644
--- a/libgo/go/exp/types/gcimporter_test.go
+++ b/libgo/go/exp/types/gcimporter_test.go
@@ -17,23 +17,23 @@ import (
"time"
)
-var gcName, gcPath string // compiler name and path
+var gcPath string // Go compiler path
func init() {
// determine compiler
+ var gc string
switch runtime.GOARCH {
case "386":
- gcName = "8g"
+ gc = "8g"
case "amd64":
- gcName = "6g"
+ gc = "6g"
case "arm":
- gcName = "5g"
+ gc = "5g"
default:
- gcName = "unknown-GOARCH-compiler"
- gcPath = gcName
+ gcPath = "unknown-GOARCH-compiler"
return
}
- gcPath = filepath.Join(build.ToolDir, gcName)
+ gcPath = filepath.Join(build.ToolDir, gc)
}
func compile(t *testing.T, dirname, filename string) {
@@ -41,7 +41,7 @@ func compile(t *testing.T, dirname, filename string) {
cmd.Dir = dirname
out, err := cmd.CombinedOutput()
if err != nil {
- t.Errorf("%s %s failed: %s", gcName, filename, err)
+ t.Errorf("%s %s failed: %s", gcPath, filename, err)
return
}
t.Logf("%s", string(out))
@@ -52,7 +52,7 @@ func compile(t *testing.T, dirname, filename string) {
var imports = make(map[string]*ast.Object)
func testPath(t *testing.T, path string) bool {
- _, err := GcImporter(imports, path)
+ _, err := GcImport(imports, path)
if err != nil {
t.Errorf("testPath(%s): %s", path, err)
return false
diff --git a/libgo/go/go/build/build.go b/libgo/go/go/build/build.go
index d113dc1..d749aef 100644
--- a/libgo/go/go/build/build.go
+++ b/libgo/go/go/build/build.go
@@ -210,7 +210,6 @@ func (ctxt *Context) SrcDirs() []string {
// if set, or else the compiled code's GOARCH, GOOS, and GOROOT.
var Default Context = defaultContext()
-// This list is also known to ../../../cmd/dist/build.c.
var cgoEnabled = map[string]bool{
"darwin/386": true,
"darwin/amd64": true,
@@ -388,7 +387,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
// but check that using it wouldn't find something
// else first.
if ctxt.GOROOT != "" {
- if dir := ctxt.joinPath(ctxt.GOROOT, "src", sub); ctxt.isDir(dir) {
+ if dir := ctxt.joinPath(ctxt.GOROOT, "src", "pkg", sub); ctxt.isDir(dir) {
goto Found
}
}
diff --git a/libgo/go/image/image.go b/libgo/go/image/image.go
index 63bfb7d..03ac606 100644
--- a/libgo/go/image/image.go
+++ b/libgo/go/image/image.go
@@ -18,7 +18,7 @@
// initialization side effects.
//
// See "The Go image package" for more details:
-// http://blog.golang.org/2011/09/go-image-package.html
+// http://golang.org/doc/articles/image_package.html
package image
import (
diff --git a/libgo/go/net/fd.go b/libgo/go/net/fd.go
index ae1bf26..76c953b 100644
--- a/libgo/go/net/fd.go
+++ b/libgo/go/net/fd.go
@@ -623,6 +623,10 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err e
continue
}
}
+ } else if err == syscall.ECONNABORTED {
+ // This means that a socket on the listen queue was closed
+ // before we Accept()ed it; it's a silly error, so try again.
+ continue
}
return nil, &OpError{"accept", fd.net, fd.laddr, err}
}
diff --git a/libgo/go/os/types.go b/libgo/go/os/types.go
index 01dddf5..0c95c9c 100644
--- a/libgo/go/os/types.go
+++ b/libgo/go/os/types.go
@@ -58,7 +58,7 @@ const (
func (m FileMode) String() string {
const str = "dalTLDpSugct"
- var buf [20]byte
+ var buf [32]byte // Mode is uint32.
w := 0
for i, c := range str {
if m&(1<<uint(32-1-i)) != 0 {
diff --git a/libgo/go/path/filepath/path_test.go b/libgo/go/path/filepath/path_test.go
index 87cb5e5..b876658 100644
--- a/libgo/go/path/filepath/path_test.go
+++ b/libgo/go/path/filepath/path_test.go
@@ -814,6 +814,7 @@ type VolumeNameTest struct {
var volumenametests = []VolumeNameTest{
{`c:/foo/bar`, `c:`},
{`c:`, `c:`},
+ {`2:`, ``},
{``, ``},
{`\\\host`, ``},
{`\\\host\`, ``},
@@ -845,3 +846,26 @@ func TestVolumeName(t *testing.T) {
}
}
}
+
+func TestDriveLetterInEvalSymlinks(t *testing.T) {
+ if runtime.GOOS != "windows" {
+ return
+ }
+ wd, _ := os.Getwd()
+ if len(wd) < 3 {
+ t.Errorf("Current directory path %q is too short", wd)
+ }
+ lp := strings.ToLower(wd)
+ up := strings.ToUpper(wd)
+ flp, err := filepath.EvalSymlinks(lp)
+ if err != nil {
+ t.Fatalf("EvalSymlinks(%q) failed: %q", lp, err)
+ }
+ fup, err := filepath.EvalSymlinks(up)
+ if err != nil {
+ t.Fatalf("EvalSymlinks(%q) failed: %q", up, err)
+ }
+ if flp != fup {
+ t.Errorf("Results of EvalSymlinks do not match: %q and %q", flp, fup)
+ }
+}
diff --git a/libgo/go/path/filepath/path_windows.go b/libgo/go/path/filepath/path_windows.go
index 1d1d23b..3dcd030 100644
--- a/libgo/go/path/filepath/path_windows.go
+++ b/libgo/go/path/filepath/path_windows.go
@@ -35,9 +35,7 @@ func VolumeName(path string) (v string) {
}
// with drive letter
c := path[0]
- if path[1] == ':' &&
- ('0' <= c && c <= '9' || 'a' <= c && c <= 'z' ||
- 'A' <= c && c <= 'Z') {
+ if path[1] == ':' && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') {
return path[:2]
}
// is it UNC
diff --git a/libgo/go/path/filepath/symlink_windows.go b/libgo/go/path/filepath/symlink_windows.go
index afa88bf..1ee9399 100644
--- a/libgo/go/path/filepath/symlink_windows.go
+++ b/libgo/go/path/filepath/symlink_windows.go
@@ -8,7 +8,24 @@ import (
"syscall"
)
-func evalSymlinks(path string) (string, error) {
+func toShort(path string) (string, error) {
+ p := syscall.StringToUTF16(path)
+ b := p // GetShortPathName says we can reuse buffer
+ n, err := syscall.GetShortPathName(&p[0], &b[0], uint32(len(b)))
+ if err != nil {
+ return "", err
+ }
+ if n > uint32(len(b)) {
+ b = make([]uint16, n)
+ n, err = syscall.GetShortPathName(&p[0], &b[0], uint32(len(b)))
+ if err != nil {
+ return "", err
+ }
+ }
+ return syscall.UTF16ToString(b), nil
+}
+
+func toLong(path string) (string, error) {
p := syscall.StringToUTF16(path)
b := p // GetLongPathName says we can reuse buffer
n, err := syscall.GetLongPathName(&p[0], &b[0], uint32(len(b)))
@@ -23,5 +40,24 @@ func evalSymlinks(path string) (string, error) {
}
}
b = b[:n]
- return Clean(syscall.UTF16ToString(b)), nil
+ return syscall.UTF16ToString(b), nil
+}
+
+func evalSymlinks(path string) (string, error) {
+ p, err := toShort(path)
+ if err != nil {
+ return "", err
+ }
+ p, err = toLong(p)
+ if err != nil {
+ return "", err
+ }
+ // syscall.GetLongPathName does not change the case of the drive letter,
+ // but the result of EvalSymlinks must be unique, so we have
+ // EvalSymlinks(`c:\a`) == EvalSymlinks(`C:\a`).
+ // Make drive letter upper case.
+ if len(p) >= 2 && p[1] == ':' && 'a' <= p[0] && p[0] <= 'z' {
+ p = string(p[0]+'A'-'a') + p[1:]
+ }
+ return Clean(p), nil
}
diff --git a/libgo/go/text/template/doc.go b/libgo/go/text/template/doc.go
index 10e0f7f..aa50ab9 100644
--- a/libgo/go/text/template/doc.go
+++ b/libgo/go/text/template/doc.go
@@ -244,7 +244,7 @@ Functions
During execution functions are found in two function maps: first in the
template, then in the global function map. By default, no functions are defined
-in the template but the Funcs methods can be used to add them.
+in the template but the Funcs method can be used to add them.
Predefined global functions are named as follows.
diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c
index dbcfa0f..9ad9f96 100644
--- a/libgo/runtime/proc.c
+++ b/libgo/runtime/proc.c
@@ -448,6 +448,11 @@ runtime_main(void)
// roots.
mstats.enablegc = 1;
+ // The deadlock detection has false negatives.
+ // Let scvg start up, to eliminate the false negative
+ // for the trivial program func main() { select{} }.
+ runtime_gosched();
+
main_main();
runtime_exit(0);
for(;;)
@@ -795,6 +800,20 @@ top:
}
// Look for deadlock situation.
+ // There is a race with the scavenger that causes false negatives:
+ // if the scavenger is just starting, then we have
+ // scvg != nil && grunning == 0 && gwait == 0
+ // and we do not detect a deadlock. It is possible that we should
+ // add that case to the if statement here, but it is too close to Go 1
+ // to make such a subtle change. Instead, we work around the
+ // false negative in trivial programs by calling runtime.gosched
+ // from the main goroutine just before main.main.
+ // See runtime_main above.
+ //
+ // On a related note, it is also possible that the scvg == nil case is
+ // wrong and should include gwait, but that does not happen in
+ // standard Go programs, which all start the scavenger.
+ //
if((scvg == nil && runtime_sched.grunning == 0) ||
(scvg != nil && runtime_sched.grunning == 1 && runtime_sched.gwait == 0 &&
(scvg->status == Grunning || scvg->status == Gsyscall))) {