func openGoobj(r *os.File) (rawFile, error) { f, err := goobj.Parse(r, `""`) if err != nil { return nil, err } return &goobjFile{goobj: f, f: r}, nil }
// scanFile reads file to learn about the package with the given import path. func (p *Prog) scanFile(pkgpath string, file string) { pkg := &Package{ File: file, } p.Packages[pkgpath] = pkg f, err := os.Open(file) if err != nil { p.errorf("%v", err) return } gp, err := goobj.Parse(f, pkgpath) f.Close() if err != nil { p.errorf("reading %s: %v", file, err) return } // TODO(rsc): Change cmd/internal/goobj to record package name as gp.Name. // TODO(rsc): If pkgpath == "main", check that gp.Name == "main". pkg.Package = gp for _, gs := range gp.Syms { // TODO(rsc): Fix file format instead of this workaround. if gs.Data.Size > 0 { switch gs.Kind { case goobj.SBSS: gs.Kind = goobj.SDATA case goobj.SNOPTRBSS: gs.Kind = goobj.SNOPTRDATA } } if gs.Version != 0 { gs.Version += p.MaxVersion } for i := range gs.Reloc { r := &gs.Reloc[i] if r.Sym.Version != 0 { r.Sym.Version += p.MaxVersion } if p.Syms[r.Sym] == nil { p.Missing[r.Sym] = true } } if gs.Func != nil { for i := range gs.Func.FuncData { fdata := &gs.Func.FuncData[i] if fdata.Sym.Name != "" { if fdata.Sym.Version != 0 { fdata.Sym.Version += p.MaxVersion } if p.Syms[fdata.Sym] == nil { p.Missing[fdata.Sym] = true } } } } if old := p.Syms[gs.SymID]; old != nil { // Duplicate definition of symbol. Is it okay? // TODO(rsc): Write test for this code. switch { // If both symbols are BSS (no data), take max of sizes // but otherwise ignore second symbol. case old.Data.Size == 0 && gs.Data.Size == 0: if old.Size < gs.Size { old.Size = gs.Size } continue // If one is in BSS and one is not, use the one that is not. case old.Data.Size > 0 && gs.Data.Size == 0: continue case gs.Data.Size > 0 && old.Data.Size == 0: break // install gs as new symbol below // If either is marked as DupOK, we can keep either one. // Keep the one that we saw first. case old.DupOK || gs.DupOK: continue // Otherwise, there's an actual conflict: default: p.errorf("symbol %s defined in both %s and %s %v %v", gs.SymID, old.Package.File, file, old.Data, gs.Data) continue } } s := &Sym{ Sym: gs, Package: pkg, } p.addSym(s) delete(p.Missing, gs.SymID) if s.Data.Size > int64(s.Size) { p.errorf("%s: initialized data larger than symbol (%d > %d)", s, s.Data.Size, s.Size) } } p.MaxVersion += pkg.MaxVersion for i, pkgpath := range pkg.Imports { // TODO(rsc): Fix file format to drop .a from recorded import path. pkgpath = strings.TrimSuffix(pkgpath, ".a") pkg.Imports[i] = pkgpath p.scanImport(pkgpath) } }