// Copyright 2013 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.
// Package gccgoimporter implements Import for gccgo-generated object files.
package gccgoimporter // import "go/internal/gccgoimporter"import ()// A PackageInit describes an imported package that needs initialization.typePackageInitstruct { Name string// short package name InitFunc string// name of init function Priority int// priority of init function, see InitData.Priority}// The gccgo-specific init data for a package.typeInitDatastruct {// Initialization priority of this package relative to other packages. // This is based on the maximum depth of the package's dependency graph; // it is guaranteed to be greater than that of its dependencies. Priority int// The list of packages which this package depends on to be initialized, // including itself if needed. This is the subset of the transitive closure of // the package's dependencies that need initialization. Inits []PackageInit}// Locate the file from which to read export data.// This is intended to replicate the logic in gofrontend.func findExportFile( []string, string) (string, error) {for , := range { := filepath.Join(, ) , := filepath.Split()for , := range [...]string{ , + ".gox", + "lib" + + ".so", + "lib" + + ".a", + ".o", } { , := os.Stat()if == nil && !.IsDir() {return , nil } } }return"", fmt.Errorf("%s: could not find export data (tried %s)", , strings.Join(, ":"))}const ( gccgov1Magic = "v1;\n" gccgov2Magic = "v2;\n" gccgov3Magic = "v3;\n" goimporterMagic = "\n$$ " archiveMagic = "!<ar" aixbigafMagic = "<big")// Opens the export data file at the given path. If this is an ELF file,// searches for and opens the .go_export section. If this is an archive,// reads the export data from the first member, which is assumed to be an ELF file.// This is intended to replicate the logic in gofrontend.func openExportFile( string) ( io.ReadSeeker, io.Closer, error) { , := os.Open()if != nil {return } = deferfunc() {if != nil && != nil { .Close() } }()var [4]byte _, = .ReadAt([:], 0)if != nil {return }vario.ReaderAtswitchstring([:]) {casegccgov1Magic, gccgov2Magic, gccgov3Magic, goimporterMagic:// Raw export data. = returncasearchiveMagic, aixbigafMagic: , = arExportData()returndefault: = } , := elf.NewFile()if == nil { := .Section(".go_export")if == nil { = fmt.Errorf("%s: .go_export section not found", )return } = .Open()return } , := xcoff.NewFile()if == nil { := .CSect(".go_export")if == nil { = fmt.Errorf("%s: .go_export section not found", )return } = bytes.NewReader()return } = fmt.Errorf("%s: unrecognized file format", )return}// An Importer resolves import paths to Packages. The imports map records// packages already known, indexed by package path.// An importer must determine the canonical package path and check imports// to see if it is already present in the map. If so, the Importer can return// the map entry. Otherwise, the importer must load the package data for the// given path into a new *Package, record it in imports map, and return the// package.typeImporterfunc(imports map[string]*types.Package, path, srcDir string, lookup func(string) (io.ReadCloser, error)) (*types.Package, error)func ( []string, map[*types.Package]InitData) Importer {returnfunc( map[string]*types.Package, , string, func(string) (io.ReadCloser, error)) ( *types.Package, error) {// TODO(gri): Use srcDir. // Or not. It's possible that srcDir will fade in importance as // the go command and other tools provide a translation table // for relative imports (like ./foo or vendored imports).if == "unsafe" {returntypes.Unsafe, nil }vario.ReadSeekervarstringvario.ReadCloserif != nil {if := []; != nil && .Complete() {return , nil } , = ()if != nil {returnnil, } }if != nil {defer .Close() , := .(io.ReadSeeker)if ! {returnnil, fmt.Errorf("gccgo importer requires lookup to return an io.ReadSeeker, have %T", ) } = = "<lookup " + + ">"// Take name from Name method (like on os.File) if present.if , := .(interface{ () string }); { = .() } } else { , = findExportFile(, )if != nil {returnnil, } , , := openExportFile()if != nil {returnnil, }if != nil {defer .Close() } = }varstring , = readMagic()if != nil {return }if == archiveMagic || == aixbigafMagic { , = arExportData()if != nil {return } , = readMagic()if != nil {return } }switch {casegccgov1Magic, gccgov2Magic, gccgov3Magic:varparser .init(, , ) = .parsePackage()if != nil { [] = .initdata }// Excluded for now: Standard gccgo doesn't support this import format currently. // case goimporterMagic: // var data []byte // data, err = io.ReadAll(reader) // if err != nil { // return // } // var n int // n, pkg, err = importer.ImportData(imports, data) // if err != nil { // return // }// if initmap != nil { // suffixreader := bytes.NewReader(data[n:]) // var p parser // p.init(fpath, suffixreader, nil) // p.parseInitData() // initmap[pkg] = p.initdata // }default: = fmt.Errorf("unrecognized magic string: %q", ) }return }}// readMagic reads the four bytes at the start of a ReadSeeker and// returns them as a string.func readMagic( io.ReadSeeker) (string, error) {var [4]byteif , := .Read([:]); != nil {return"", }if , := .Seek(0, io.SeekStart); != nil {return"", }returnstring([:]), nil}
The pages are generated with Goldsv0.7.0-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.