func dumpasmhdr() { var b *obj.Biobuf b, err := obj.Bopenw(asmhdr) if err != nil { Fatalf("%v", err) } fmt.Fprintf(b, "// generated by %cg -asmhdr from package %s\n\n", Thearch.Thechar, localpkg.Name) var n *Node var t *Type for l := asmlist; l != nil; l = l.Next { n = l.N if isblanksym(n.Sym) { continue } switch n.Op { case OLITERAL: fmt.Fprintf(b, "#define const_%s %v\n", n.Sym.Name, Vconv(n.Val(), obj.FmtSharp)) case OTYPE: t = n.Type if t.Etype != TSTRUCT || t.Map != nil || t.Funarg { break } fmt.Fprintf(b, "#define %s__size %d\n", t.Sym.Name, int(t.Width)) for t = t.Type; t != nil; t = t.Down { if !isblanksym(t.Sym) { fmt.Fprintf(b, "#define %s_%s %d\n", n.Sym.Name, t.Sym.Name, int(t.Width)) } } } } obj.Bterm(b) }
// hostArchive reads an archive file holding host objects and links in // required objects. The general format is the same as a Go archive // file, but it has an armap listing symbols and the objects that // define them. This is used for the compiler support library // libgcc.a. func hostArchive(name string) { f, err := obj.Bopenr(name) if err != nil { if os.IsNotExist(err) { // It's OK if we don't have a libgcc file at all. if Debug['v'] != 0 { fmt.Fprintf(&Bso, "skipping libgcc file: %v\n", err) } return } Exitf("cannot open file %s: %v", name, err) } defer obj.Bterm(f) magbuf := make([]byte, len(ARMAG)) if obj.Bread(f, magbuf) != len(magbuf) { Exitf("file %s too short", name) } var arhdr ArHdr l := nextar(f, obj.Boffset(f), &arhdr) if l <= 0 { Exitf("%s missing armap", name) } var armap archiveMap if arhdr.name == "/" || arhdr.name == "/SYM64/" { armap = readArmap(name, f, arhdr) } else { Exitf("%s missing armap", name) } loaded := make(map[uint64]bool) any := true for any { var load []uint64 for s := Ctxt.Allsym; s != nil; s = s.Allsym { for _, r := range s.R { if r.Sym != nil && r.Sym.Type&obj.SMASK == obj.SXREF { if off := armap[r.Sym.Name]; off != 0 && !loaded[off] { load = append(load, off) loaded[off] = true } } } } for _, off := range load { l := nextar(f, int64(off), &arhdr) if l <= 0 { Exitf("%s missing archive entry at offset %d", name, off) } pname := fmt.Sprintf("%s(%s)", name, arhdr.name) l = atolwhex(arhdr.size) h := ldobj(f, "libgcc", l, pname, name, ArchiveObj) obj.Bseek(f, h.off, 0) h.ld(f, h.pkg, h.length, h.pn) } any = len(load) > 0 } }
func dumpobj() { var err error bout, err = obj.Bopenw(outfile) if err != nil { Flusherrors() fmt.Printf("can't create %s: %v\n", outfile, err) errorexit() } startobj := int64(0) var arhdr [ArhdrSize]byte if writearchive != 0 { obj.Bwritestring(bout, "!<arch>\n") arhdr = [ArhdrSize]byte{} bout.Write(arhdr[:]) startobj = obj.Boffset(bout) } fmt.Fprintf(bout, "go object %s %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring()) dumpexport() if writearchive != 0 { bout.Flush() size := obj.Boffset(bout) - startobj if size&1 != 0 { obj.Bputc(bout, 0) } obj.Bseek(bout, startobj-ArhdrSize, 0) formathdr(arhdr[:], "__.PKGDEF", size) bout.Write(arhdr[:]) bout.Flush() obj.Bseek(bout, startobj+size+(size&1), 0) arhdr = [ArhdrSize]byte{} bout.Write(arhdr[:]) startobj = obj.Boffset(bout) fmt.Fprintf(bout, "go object %s %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring()) } if pragcgobuf != "" { if writearchive != 0 { // write empty export section; must be before cgo section fmt.Fprintf(bout, "\n$$\n\n$$\n\n") } fmt.Fprintf(bout, "\n$$ // cgo\n") fmt.Fprintf(bout, "%s\n$$\n\n", pragcgobuf) } fmt.Fprintf(bout, "\n!\n") externs := len(externdcl) dumpglobls() dumptypestructs() // Dump extra globals. tmp := externdcl if externdcl != nil { externdcl = externdcl[externs:] } dumpglobls() externdcl = tmp dumpdata() obj.Writeobjdirect(Ctxt, bout) if writearchive != 0 { bout.Flush() size := obj.Boffset(bout) - startobj if size&1 != 0 { obj.Bputc(bout, 0) } obj.Bseek(bout, startobj-ArhdrSize, 0) formathdr(arhdr[:], "_go_.o", size) bout.Write(arhdr[:]) } obj.Bterm(bout) }