예제 #1
0
파일: goobj.go 프로젝트: oshimaya/go
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
}
예제 #2
0
파일: scan.go 프로젝트: sreis/go
// 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)
	}
}