예제 #1
0
파일: main.go 프로젝트: 0x7cc/rsc
func main() {
	f, err := os.Open(os.Args[1])
	if err != nil {
		log.Fatal(err)
	}
	pkg, err := goobj.Parse(f, "main")
	if err != nil {
		log.Fatal(err)
	}
	js, err := json.MarshalIndent(pkg, "", "\t")
	if err != nil {
		log.Fatal(err)
	}
	os.Stdout.WriteString(string(js) + "\n")
}
예제 #2
0
func goobjSymbols(f *os.File) []Sym {
	pkg, err := goobj.Parse(f, `""`)
	if err != nil {
		errorf("parsing %s: %v", f.Name(), err)
		return nil
	}

	seen := make(map[goobj.SymID]bool)

	var syms []Sym
	for _, s := range pkg.Syms {
		seen[s.SymID] = true
		sym := Sym{Addr: uint64(s.Data.Offset), Name: goobjName(s.SymID), Size: int64(s.Size), Type: s.Type.Name, Code: '?'}
		switch s.Kind {
		case goobj.STEXT, goobj.SELFRXSECT:
			sym.Code = 'T'
		case goobj.STYPE, goobj.SSTRING, goobj.SGOSTRING, goobj.SGOFUNC, goobj.SRODATA, goobj.SFUNCTAB, goobj.STYPELINK, goobj.SSYMTAB, goobj.SPCLNTAB, goobj.SELFROSECT:
			sym.Code = 'R'
		case goobj.SMACHOPLT, goobj.SELFSECT, goobj.SMACHO, goobj.SMACHOGOT, goobj.SNOPTRDATA, goobj.SINITARR, goobj.SDATA, goobj.SWINDOWS:
			sym.Code = 'D'
		case goobj.SBSS, goobj.SNOPTRBSS, goobj.STLSBSS:
			sym.Code = 'B'
		case goobj.SXREF, goobj.SMACHOSYMSTR, goobj.SMACHOSYMTAB, goobj.SMACHOINDIRECTPLT, goobj.SMACHOINDIRECTGOT, goobj.SFILE, goobj.SFILEPATH, goobj.SCONST, goobj.SDYNIMPORT, goobj.SHOSTOBJ:
			sym.Code = 'X' // should not see
		}
		if s.Version != 0 {
			sym.Code += 'a' - 'A'
		}
		syms = append(syms, sym)
	}

	for _, s := range pkg.Syms {
		for _, r := range s.Reloc {
			if !seen[r.Sym] {
				seen[r.Sym] = true
				sym := Sym{Name: goobjName(r.Sym), Code: 'U'}
				if s.Version != 0 {
					// should not happen but handle anyway
					sym.Code = 'u'
				}
				syms = append(syms, sym)
			}
		}
	}

	return syms
}
예제 #3
0
// 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 debug/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)
	}
}