"cmd/internal/obj"
"fmt"
"os"
- "strconv"
"strings"
)
return strings.Replace(t0, `"".`, pkg+".", -1)
}
-// accumulate all type information from .6 files.
-// check for inconsistencies.
-
// TODO:
// generate debugging section in binary.
// once the dust settles, try to move some code to
// libmach, so that other linkers and ar can share.
-/*
- * package import data
- */
-type Import struct {
- prefix string // "type", "var", "func", "const"
- name string
- def string
- file string
-}
-
-// importmap records type information about imported symbols to detect inconsistencies.
-// Entries are keyed by qualified symbol name (e.g., "runtime.Callers" or "net/url.Error").
-var importmap = map[string]*Import{}
-
-func lookupImport(name string) *Import {
- if x, ok := importmap[name]; ok {
- return x
- }
- x := &Import{name: name}
- importmap[name] = x
- return x
-}
-
func ldpkg(f *obj.Biobuf, pkg string, length int64, filename string, whence int) {
var p0, p1 int
return
}
+ // In a __.PKGDEF, we only care about the package name.
+ // Don't read all the export data.
+ if length > 1000 && whence == Pkgdef {
+ length = 1000
+ }
+
bdata := make([]byte, length)
if int64(obj.Bread(f, bdata)) != length {
fmt.Fprintf(os.Stderr, "%s: short pkg read %s\n", os.Args[0], filename)
// second marks end of exports / beginning of local data
p1 = strings.Index(data[p0:], "\n$$\n")
+ if p1 < 0 && whence == Pkgdef {
+ p1 = len(data) - p0
+ }
if p1 < 0 {
fmt.Fprintf(os.Stderr, "%s: cannot find end of exports in %s\n", os.Args[0], filename)
if Debug['u'] != 0 {
if pkg == "main" && name != "main" {
Exitf("%s: not package main (package %s)", filename, name)
}
-
- loadpkgdata(filename, pkg, data[p0:p1])
}
// __.PKGDEF has no cgo section - those are in the C compiler-generated object files.
}
}
-func loadpkgdata(file string, pkg string, data string) {
- var prefix string
- var name string
- var def string
-
- p := data
- for parsepkgdata(file, pkg, &p, &prefix, &name, &def) > 0 {
- x := lookupImport(name)
- if x.prefix == "" {
- x.prefix = prefix
- x.def = def
- x.file = file
- } else if x.prefix != prefix {
- fmt.Fprintf(os.Stderr, "%s: conflicting definitions for %s\n", os.Args[0], name)
- fmt.Fprintf(os.Stderr, "%s:\t%s %s ...\n", x.file, x.prefix, name)
- fmt.Fprintf(os.Stderr, "%s:\t%s %s ...\n", file, prefix, name)
- nerrors++
- } else if x.def != def {
- fmt.Fprintf(os.Stderr, "%s: conflicting definitions for %s\n", os.Args[0], name)
- fmt.Fprintf(os.Stderr, "%s:\t%s %s %s\n", x.file, x.prefix, name, x.def)
- fmt.Fprintf(os.Stderr, "%s:\t%s %s %s\n", file, prefix, name, def)
- nerrors++
- }
- }
-}
-
-func parsepkgdata(file string, pkg string, pp *string, prefixp *string, namep *string, defp *string) int {
- // skip white space
- p := *pp
-
-loop:
- for len(p) > 0 && (p[0] == ' ' || p[0] == '\t' || p[0] == '\n') {
- p = p[1:]
- }
- if len(p) == 0 || strings.HasPrefix(p, "$$\n") {
- return 0
- }
-
- // prefix: (var|type|func|const)
- prefix := p
-
- if len(p) < 7 {
- return -1
- }
- if strings.HasPrefix(p, "var ") {
- p = p[4:]
- } else if strings.HasPrefix(p, "type ") {
- p = p[5:]
- } else if strings.HasPrefix(p, "func ") {
- p = p[5:]
- } else if strings.HasPrefix(p, "const ") {
- p = p[6:]
- } else if strings.HasPrefix(p, "import ") {
- p = p[7:]
- for len(p) > 0 && p[0] != ' ' {
- p = p[1:]
- }
- p = p[1:]
- line := p
- for len(p) > 0 && p[0] != '\n' {
- p = p[1:]
- }
- if len(p) == 0 {
- fmt.Fprintf(os.Stderr, "%s: %s: confused in import line\n", os.Args[0], file)
- nerrors++
- return -1
- }
- line = line[:len(line)-len(p)]
- line = strings.TrimSuffix(line, " // indirect")
- path, err := strconv.Unquote(line)
- if err != nil {
- fmt.Fprintf(os.Stderr, "%s: %s: confused in import path: %q\n", os.Args[0], file, line)
- nerrors++
- return -1
- }
- p = p[1:]
- imported(pkg, path)
- goto loop
- } else {
- fmt.Fprintf(os.Stderr, "%s: %s: confused in pkg data near <<%.40s>>\n", os.Args[0], file, prefix)
- nerrors++
- return -1
- }
-
- prefix = prefix[:len(prefix)-len(p)-1]
-
- // name: a.b followed by space
- name := p
-
- inquote := false
- for len(p) > 0 {
- if p[0] == ' ' && !inquote {
- break
- }
-
- if p[0] == '\\' {
- p = p[1:]
- } else if p[0] == '"' {
- inquote = !inquote
- }
-
- p = p[1:]
- }
-
- if len(p) == 0 {
- return -1
- }
- name = name[:len(name)-len(p)]
- p = p[1:]
-
- // def: free form to new line
- def := p
-
- for len(p) > 0 && p[0] != '\n' {
- p = p[1:]
- }
- if len(p) == 0 {
- return -1
- }
- def = def[:len(def)-len(p)]
- var defbuf *bytes.Buffer
- p = p[1:]
-
- // include methods on successive lines in def of named type
- var meth string
- for parsemethod(&p, &meth) > 0 {
- if defbuf == nil {
- defbuf = new(bytes.Buffer)
- defbuf.WriteString(def)
- }
- defbuf.WriteString("\n\t")
- defbuf.WriteString(meth)
- }
- if defbuf != nil {
- def = defbuf.String()
- }
-
- name = expandpkg(name, pkg)
- def = expandpkg(def, pkg)
-
- // done
- *pp = p
-
- *prefixp = prefix
- *namep = name
- *defp = def
- return 1
-}
-
-func parsemethod(pp *string, methp *string) int {
- // skip white space
- p := *pp
-
- for len(p) > 0 && (p[0] == ' ' || p[0] == '\t') {
- p = p[1:]
- }
- if len(p) == 0 {
- return 0
- }
-
- // might be a comment about the method
- if strings.HasPrefix(p, "//") {
- goto useline
- }
-
- // if it says "func (", it's a method
- if strings.HasPrefix(p, "func (") {
- goto useline
- }
- return 0
-
- // definition to end of line
-useline:
- *methp = p
-
- for len(p) > 0 && p[0] != '\n' {
- p = p[1:]
- }
- if len(p) == 0 {
- fmt.Fprintf(os.Stderr, "%s: lost end of line in method definition\n", os.Args[0])
- *pp = ""
- return -1
- }
-
- *methp = (*methp)[:len(*methp)-len(p)]
- *pp = p[1:]
- return 1
-}
-
func loadcgo(file string, pkg string, p string) {
var next string
var q string
--- /dev/null
+// +build !nacl
+// run
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Run the sinit test.
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "strings"
+)
+
+func cleanup() {
+ os.Remove("linkmain.o")
+ os.Remove("linkmain.a")
+ os.Remove("linkmain1.o")
+ os.Remove("linkmain1.a")
+ os.Remove("linkmain.exe")
+}
+
+func run(cmdline string) {
+ args := strings.Fields(cmdline)
+ cmd := exec.Command(args[0], args[1:]...)
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ fmt.Printf("$ %s\n", strings.Join(args, " "))
+ fmt.Println(string(out))
+ fmt.Println(err)
+ cleanup()
+ os.Exit(1)
+ }
+}
+
+func runFail(args ...string) {
+ cmd := exec.Command(args[0], args[1:]...)
+ out, err := cmd.CombinedOutput()
+ if err == nil {
+ fmt.Printf("$ %s\n", strings.Join(args, " "))
+ fmt.Println(string(out))
+ fmt.Println("SHOULD HAVE FAILED!")
+ cleanup()
+ os.Exit(1)
+ }
+}
+
+func main() {
+ // helloworld.go is package main
+ run("go tool compile -o linkmain.o helloworld.go")
+ run("go tool compile -pack -o linkmain.a helloworld.go")
+ run("go tool link -o linkmain.exe linkmain.o")
+ run("go tool link -o linkmain.exe linkmain.a")
+
+ // linkmain.go is not
+ run("go tool compile -o linkmain.o linkmain.go")
+ run("go tool compile -pack -o linkmain.a linkmain.go")
+ runFail("go tool link -o linkmain.exe linkmain1.o")
+ runFail("go tool link -o linkmain.exe linkmain1.a")
+ cleanup()
+}