func (b *Builder) link(out io.Writer, p *pkg, main string) error { var funcs []*link8.PkgSym addInit := func(p *pkg) { name := p.pkg.Init if name != "" && p.pkg.Lib.HasFunc(name) { funcs = append(funcs, &link8.PkgSym{p.path, name}) } } for _, dep := range p.deps { addInit(b.pkgs[dep]) } addInit(p) funcs = append(funcs, &link8.PkgSym{p.path, main}) debugTable := debug8.NewTable() job := link8.NewJob(b.linkPkgs, funcs) job.InitPC = b.InitPC job.FuncDebug = func(pkg, name string, addr, size uint32) { debugTable.LinkFunc(b.debugFuncs, pkg, name, addr, size) } secs, err := job.Link() if err != nil { return err } debugSec, err := debugSection(debugTable) if err != nil { return err } secs = append(secs, debugSec) return e8.Write(out, secs) }
// LinkBareFunc produces a image of a single function that has no links. func LinkBareFunc(f *Func) ([]byte, error) { if f.TooLarge() { return nil, fmt.Errorf("code section too large") } buf := new(bytes.Buffer) w := newWriter(make(map[string]*Pkg), buf) w.writeBareFunc(f) if err := w.Err(); err != nil { return nil, err } image := new(bytes.Buffer) sec := &e8.Section{ Header: &e8.Header{ Type: e8.Code, Addr: arch8.InitPC, }, Bytes: buf.Bytes(), } if err := e8.Write(image, []*e8.Section{sec}); err != nil { return nil, err } return image.Bytes(), nil }
// BuildSingleFile builds a package named "main" from a single file. func BuildSingleFile(f string, rc io.ReadCloser) ([]byte, []*lex8.Error) { path := "_" pinfo := build8.SimplePkg(path, f, rc) pkg, errs := Lang().Compile(pinfo, new(build8.Options)) if errs != nil { return nil, errs } secs, err := link8.LinkSinglePkg(pkg.Lib, pkg.Main) if err != nil { return nil, lex8.SingleErr(err) } buf := new(bytes.Buffer) if err := e8.Write(buf, secs); err != nil { return nil, lex8.SingleErr(err) } return buf.Bytes(), nil }