GoPLS Viewer

Home|gopls/go/gccgoexportdata/gccgoexportdata.go
1// Copyright 2016 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package gccgoexportdata provides functions for reading export data
6// files containing type information produced by the gccgo compiler.
7//
8// This package is a stop-gap until such time as gccgo uses the same
9// export data format as gc; see Go issue 17573. Once that occurs, this
10// package will be deprecated and eventually deleted.
11package gccgoexportdata
12
13// TODO(adonovan): add Find, Write, Importer to the API,
14// for symmetry with gcexportdata.
15
16import (
17    "bytes"
18    "debug/elf"
19    "fmt"
20    "go/token"
21    "go/types"
22    "io"
23    "io/ioutil"
24    "strconv"
25    "strings"
26
27    "golang.org/x/tools/go/internal/gccgoimporter"
28)
29
30// CompilerInfo executes the specified gccgo compiler and returns
31// information about it: its version (e.g. "4.8.0"), its target triple
32// (e.g. "x86_64-unknown-linux-gnu"), and the list of directories it
33// searches to find standard packages. The given arguments are passed
34// directly to calls to the specified gccgo compiler.
35func CompilerInfo(gccgo stringargs ...string) (versiontriple stringdirs []stringerr error) {
36    var inst gccgoimporter.GccgoInstallation
37    err = inst.InitFromDriver(gccgoargs...)
38    if err == nil {
39        version = inst.GccVersion
40        triple = inst.TargetTriple
41        dirs = inst.SearchPaths()
42    }
43    return
44}
45
46// NewReader returns a reader for the export data section of an object
47// (.o) or archive (.a) file read from r.
48func NewReader(r io.Reader) (io.Readererror) {
49    dataerr := ioutil.ReadAll(r)
50    if err != nil {
51        return nilerr
52    }
53
54    // If the file is an archive, extract the first section.
55    const archiveMagic = "!<arch>\n"
56    if bytes.HasPrefix(data, []byte(archiveMagic)) {
57        sectionerr := firstSection(data[len(archiveMagic):])
58        if err != nil {
59            return nilerr
60        }
61        data = section
62    }
63
64    // Data contains an ELF file with a .go_export section.
65    // ELF magic number is "\x7fELF".
66    eferr := elf.NewFile(bytes.NewReader(data))
67    if err != nil {
68        return nilerr
69    }
70    sec := ef.Section(".go_export")
71    if sec == nil {
72        return nilfmt.Errorf("no .go_export section")
73    }
74    return sec.Open(), nil
75}
76
77// firstSection returns the contents of the first regular file in an ELF
78// archive (http://www.sco.com/developers/devspecs/gabi41.pdf, ยง7.2).
79func firstSection(a []byte) ([]byteerror) {
80    for len(a) >= 60 {
81        var hdr []byte
82        hdra = a[:60], a[60:]
83
84        name := strings.TrimSpace(string(hdr[:16]))
85
86        sizeStr := string(hdr[48:58])
87        sizeerr := strconv.Atoi(strings.TrimSpace(sizeStr))
88        if err != nil {
89            return nilfmt.Errorf("invalid size: %q"sizeStr)
90        }
91
92        if len(a) < size {
93            return nilfmt.Errorf("invalid section size: %d"size)
94        }
95
96        // The payload is padded to an even number of bytes.
97        var payload []byte
98        payloada = a[:size], a[size+size&1:]
99
100        // Skip special files:
101        //   "/"           archive symbol table
102        //   "/SYM64/"     archive symbol table on e.g. s390x
103        //   "//"          archive string table (if any filename is >15 bytes)
104        if name == "/" || name == "/SYM64/" || name == "//" {
105            continue
106        }
107
108        return payloadnil
109    }
110    return nilfmt.Errorf("archive has no regular sections")
111}
112
113// Read reads export data from in, decodes it, and returns type
114// information for the package.
115// The package name is specified by path.
116//
117// The FileSet parameter is currently unused but exists for symmetry
118// with gcexportdata.
119//
120// Read may inspect and add to the imports map to ensure that references
121// within the export data to other packages are consistent.  The caller
122// must ensure that imports[path] does not exist, or exists but is
123// incomplete (see types.Package.Complete), and Read inserts the
124// resulting package into this map entry.
125//
126// On return, the state of the reader is undefined.
127func Read(in io.Reader_ *token.FileSetimports map[string]*types.Packagepath string) (*types.Packageerror) {
128    return gccgoimporter.Parse(inimportspath)
129}
130
MembersX
NewReader
NewReader.r
NewReader.ef
firstSection.BlockStmt.hdr
Read.in
fmt
ioutil
CompilerInfo.version
Read
types
CompilerInfo.gccgo
CompilerInfo.triple
NewReader.archiveMagic
NewReader.BlockStmt.section
token
CompilerInfo.dirs
firstSection
Read.imports
io
strconv
CompilerInfo.args
firstSection.BlockStmt.sizeStr
firstSection.BlockStmt.size
bytes
NewReader.data
strings
CompilerInfo.err
CompilerInfo.inst
NewReader.BlockStmt.err
NewReader.sec
firstSection.BlockStmt.err
firstSection.BlockStmt.payload
elf
CompilerInfo
NewReader.err
firstSection.a
firstSection.BlockStmt.name
Read.path
gccgoimporter
Members
X