1
0
mirror of https://github.com/golang/go synced 2024-11-19 01:14:39 -07:00
go/cmd/godex/gccgo.go
Robert Griesemer 4a27ee3a1b go.tools/cmd/godex: a tool to dump export information
Initial implementation. Lots of missing pieces.

Example use:
        godex math
        godex math.Sin
        godex math.Sin math.Cos

LGTM=adonovan
R=adonovan
CC=golang-codereviews
https://golang.org/cl/76890044
2014-03-25 15:26:38 -07:00

89 lines
1.9 KiB
Go

// 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.
// This file implements access to gccgo-generated export data.
package main
import (
"debug/elf"
"fmt"
"io"
"os"
"code.google.com/p/go.tools/go/gccgoimporter"
"code.google.com/p/go.tools/go/importer"
"code.google.com/p/go.tools/go/types"
)
func init() {
// importer for default gccgo
var inst gccgoimporter.GccgoInstallation
inst.InitFromDriver("gccgo")
register("gccgo", protect(inst.GetImporter(nil)))
// importer for gccgo using condensed export format (experimental)
register("gccgo-new", protect(gccgoNewImporter))
}
func gccgoNewImporter(packages map[string]*types.Package, path string) (*types.Package, error) {
reader, closer, err := openGccgoExportFile(path)
if err != nil {
return nil, err
}
defer closer.Close()
// TODO(gri) importer.ImportData takes a []byte instead of an io.Reader;
// hence the need to read some amount of data. At the same time we don't
// want to read the entire, potentially very large object file. For now,
// read 10K. Fix this!
var data = make([]byte, 10<<10)
n, err := reader.Read(data)
if err != nil && err != io.EOF {
return nil, err
}
return importer.ImportData(packages, data[:n])
}
// openGccgoExportFile was copied from gccgoimporter.
func openGccgoExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err error) {
f, err := os.Open(fpath)
if err != nil {
return
}
defer func() {
if err != nil {
f.Close()
}
}()
closer = f
var magic [4]byte
_, err = f.ReadAt(magic[:], 0)
if err != nil {
return
}
if string(magic[:]) == "v1;\n" {
// Raw export data.
reader = f
return
}
ef, err := elf.NewFile(f)
if err != nil {
return
}
sec := ef.Section(".go_export")
if sec == nil {
err = fmt.Errorf("%s: .go_export section not found", fpath)
return
}
reader = sec.Open()
return
}