mirror of
https://github.com/golang/go
synced 2024-11-19 07:14:45 -07:00
cmd/internal/obj: more idiomatic object writer
Change-Id: I41722ee605ea76a6b52e8a7e1e10f2293cef1a7a Reviewed-on: https://go-review.googlesource.com/21371 Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
parent
b91cc53033
commit
014f3e1e09
@ -658,7 +658,6 @@ type Link struct {
|
|||||||
Textp *LSym
|
Textp *LSym
|
||||||
Etextp *LSym
|
Etextp *LSym
|
||||||
Errors int
|
Errors int
|
||||||
RefsWritten int // Number of symbol references already written to object file.
|
|
||||||
|
|
||||||
// state for writing objects
|
// state for writing objects
|
||||||
Text []*LSym
|
Text []*LSym
|
||||||
|
@ -108,6 +108,7 @@
|
|||||||
package obj
|
package obj
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -120,7 +121,7 @@ import (
|
|||||||
// does not write out object files.
|
// does not write out object files.
|
||||||
func Writeobjdirect(ctxt *Link, b *Biobuf) {
|
func Writeobjdirect(ctxt *Link, b *Biobuf) {
|
||||||
Flushplist(ctxt)
|
Flushplist(ctxt)
|
||||||
Writeobjfile(ctxt, b)
|
WriteObjFile(ctxt, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Flushplist(ctxt *Link) {
|
func Flushplist(ctxt *Link) {
|
||||||
@ -309,18 +310,32 @@ func flushplist(ctxt *Link, freeProgs bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type sectionLengths struct {
|
// objWriter writes Go object files.
|
||||||
data int
|
type objWriter struct {
|
||||||
reloc int
|
wr *bufio.Writer
|
||||||
pcdata int
|
ctxt *Link
|
||||||
autom int
|
// Temporary buffer for zigzag int writing.
|
||||||
funcdata int
|
varintbuf [10]uint8
|
||||||
file int
|
|
||||||
|
// Provide the the index of a symbol reference by symbol name.
|
||||||
|
// One map for versioned symbols and one for unversioned symbols.
|
||||||
|
// Used for deduplicating the symbol reference list.
|
||||||
|
refIdx map[string]int
|
||||||
|
vrefIdx map[string]int
|
||||||
|
|
||||||
|
// Number of objects written of each type.
|
||||||
|
nRefs int
|
||||||
|
nData int
|
||||||
|
nReloc int
|
||||||
|
nPcdata int
|
||||||
|
nAutom int
|
||||||
|
nFuncdata int
|
||||||
|
nFile int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *sectionLengths) add(s *LSym) {
|
func (w *objWriter) addLengths(s *LSym) {
|
||||||
l.data += len(s.P)
|
w.nData += len(s.P)
|
||||||
l.reloc += len(s.R)
|
w.nReloc += len(s.R)
|
||||||
|
|
||||||
if s.Type != STEXT {
|
if s.Type != STEXT {
|
||||||
return
|
return
|
||||||
@ -336,102 +351,106 @@ func (l *sectionLengths) add(s *LSym) {
|
|||||||
data += len(pc.Pcdata[i].P)
|
data += len(pc.Pcdata[i].P)
|
||||||
}
|
}
|
||||||
|
|
||||||
l.data += data
|
w.nData += data
|
||||||
l.pcdata += len(pc.Pcdata)
|
w.nPcdata += len(pc.Pcdata)
|
||||||
|
|
||||||
autom := 0
|
autom := 0
|
||||||
for a := s.Autom; a != nil; a = a.Link {
|
for a := s.Autom; a != nil; a = a.Link {
|
||||||
autom++
|
autom++
|
||||||
}
|
}
|
||||||
l.autom += autom
|
w.nAutom += autom
|
||||||
l.funcdata += len(pc.Funcdataoff)
|
w.nFuncdata += len(pc.Funcdataoff)
|
||||||
l.file += len(pc.File)
|
w.nFile += len(pc.File)
|
||||||
}
|
}
|
||||||
|
|
||||||
func wrlengths(b *Biobuf, sl sectionLengths) {
|
func (w *objWriter) writeLengths() {
|
||||||
wrint(b, int64(sl.data))
|
w.writeInt(int64(w.nData))
|
||||||
wrint(b, int64(sl.reloc))
|
w.writeInt(int64(w.nReloc))
|
||||||
wrint(b, int64(sl.pcdata))
|
w.writeInt(int64(w.nPcdata))
|
||||||
wrint(b, int64(sl.autom))
|
w.writeInt(int64(w.nAutom))
|
||||||
wrint(b, int64(sl.funcdata))
|
w.writeInt(int64(w.nFuncdata))
|
||||||
wrint(b, int64(sl.file))
|
w.writeInt(int64(w.nFile))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Writeobjfile(ctxt *Link, b *Biobuf) {
|
func newObjWriter(ctxt *Link, b *Biobuf) *objWriter {
|
||||||
// Emit header.
|
return &objWriter{
|
||||||
Bputc(b, 0)
|
ctxt: ctxt,
|
||||||
|
wr: b.w,
|
||||||
Bputc(b, 0)
|
vrefIdx: make(map[string]int),
|
||||||
fmt.Fprintf(b, "go13ld")
|
refIdx: make(map[string]int),
|
||||||
Bputc(b, 1) // version
|
|
||||||
|
|
||||||
// Emit autolib.
|
|
||||||
for _, pkg := range ctxt.Imports {
|
|
||||||
wrstring(b, pkg)
|
|
||||||
}
|
}
|
||||||
wrstring(b, "")
|
}
|
||||||
|
|
||||||
var lengths sectionLengths
|
func WriteObjFile(ctxt *Link, b *Biobuf) {
|
||||||
|
w := newObjWriter(ctxt, b)
|
||||||
|
|
||||||
// Emit symbol references.
|
// Magic header
|
||||||
|
w.wr.WriteString("\x00\x00go13ld")
|
||||||
|
|
||||||
|
// Version
|
||||||
|
w.wr.WriteByte(1)
|
||||||
|
|
||||||
|
// Autolib
|
||||||
|
for _, pkg := range ctxt.Imports {
|
||||||
|
w.writeString(pkg)
|
||||||
|
}
|
||||||
|
w.writeString("")
|
||||||
|
|
||||||
|
// Symbol references
|
||||||
for _, s := range ctxt.Text {
|
for _, s := range ctxt.Text {
|
||||||
writerefs(ctxt, b, s)
|
w.writeRefs(s)
|
||||||
lengths.add(s)
|
w.addLengths(s)
|
||||||
}
|
}
|
||||||
for _, s := range ctxt.Data {
|
for _, s := range ctxt.Data {
|
||||||
writerefs(ctxt, b, s)
|
w.writeRefs(s)
|
||||||
lengths.add(s)
|
w.addLengths(s)
|
||||||
}
|
}
|
||||||
Bputc(b, 0xff)
|
// End symbol references
|
||||||
|
w.wr.WriteByte(0xff)
|
||||||
|
|
||||||
wrlengths(b, lengths)
|
// Lengths
|
||||||
|
w.writeLengths()
|
||||||
|
|
||||||
// Write data block
|
// Data block
|
||||||
for _, s := range ctxt.Text {
|
for _, s := range ctxt.Text {
|
||||||
b.w.Write(s.P)
|
w.wr.Write(s.P)
|
||||||
pc := s.Pcln
|
pc := s.Pcln
|
||||||
b.w.Write(pc.Pcsp.P)
|
w.wr.Write(pc.Pcsp.P)
|
||||||
b.w.Write(pc.Pcfile.P)
|
w.wr.Write(pc.Pcfile.P)
|
||||||
b.w.Write(pc.Pcline.P)
|
w.wr.Write(pc.Pcline.P)
|
||||||
for i := 0; i < len(pc.Pcdata); i++ {
|
for i := 0; i < len(pc.Pcdata); i++ {
|
||||||
b.w.Write(pc.Pcdata[i].P)
|
w.wr.Write(pc.Pcdata[i].P)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, s := range ctxt.Data {
|
for _, s := range ctxt.Data {
|
||||||
b.w.Write(s.P)
|
w.wr.Write(s.P)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit symbols.
|
// Symbols
|
||||||
for _, s := range ctxt.Text {
|
for _, s := range ctxt.Text {
|
||||||
writesym(ctxt, b, s)
|
w.writeSym(s)
|
||||||
}
|
}
|
||||||
for _, s := range ctxt.Data {
|
for _, s := range ctxt.Data {
|
||||||
writesym(ctxt, b, s)
|
w.writeSym(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit footer.
|
// Magic footer
|
||||||
Bputc(b, 0xff)
|
w.wr.WriteString("\xff\xffgo13ld")
|
||||||
|
|
||||||
Bputc(b, 0xff)
|
|
||||||
fmt.Fprintf(b, "go13ld")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide the the index of a symbol reference by symbol name.
|
// Symbols are prefixed so their content doesn't get confused with the magic footer.
|
||||||
// One map for versioned symbols and one for unversioned symbols.
|
const symPrefix = 0xfe
|
||||||
// Used for deduplicating the symbol reference list.
|
|
||||||
var refIdx = make(map[string]int)
|
|
||||||
var vrefIdx = make(map[string]int)
|
|
||||||
|
|
||||||
func wrref(ctxt *Link, b *Biobuf, s *LSym, isPath bool) {
|
func (w *objWriter) writeRef(s *LSym, isPath bool) {
|
||||||
if s == nil || s.RefIdx != 0 {
|
if s == nil || s.RefIdx != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var m map[string]int
|
var m map[string]int
|
||||||
switch s.Version {
|
switch s.Version {
|
||||||
case 0:
|
case 0:
|
||||||
m = refIdx
|
m = w.refIdx
|
||||||
case 1:
|
case 1:
|
||||||
m = vrefIdx
|
m = w.vrefIdx
|
||||||
default:
|
default:
|
||||||
log.Fatalf("%s: invalid version number %d", s.Name, s.Version)
|
log.Fatalf("%s: invalid version number %d", s.Name, s.Version)
|
||||||
}
|
}
|
||||||
@ -441,111 +460,117 @@ func wrref(ctxt *Link, b *Biobuf, s *LSym, isPath bool) {
|
|||||||
s.RefIdx = idx
|
s.RefIdx = idx
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
Bputc(b, 0xfe)
|
w.wr.WriteByte(symPrefix)
|
||||||
if isPath {
|
if isPath {
|
||||||
wrstring(b, filepath.ToSlash(s.Name))
|
w.writeString(filepath.ToSlash(s.Name))
|
||||||
} else {
|
} else {
|
||||||
wrstring(b, s.Name)
|
w.writeString(s.Name)
|
||||||
}
|
}
|
||||||
wrint(b, int64(s.Version))
|
w.writeInt(int64(s.Version))
|
||||||
ctxt.RefsWritten++
|
w.nRefs++
|
||||||
s.RefIdx = ctxt.RefsWritten
|
s.RefIdx = w.nRefs
|
||||||
m[s.Name] = ctxt.RefsWritten
|
m[s.Name] = w.nRefs
|
||||||
}
|
}
|
||||||
|
|
||||||
func writerefs(ctxt *Link, b *Biobuf, s *LSym) {
|
func (w *objWriter) writeRefs(s *LSym) {
|
||||||
wrref(ctxt, b, s, false)
|
w.writeRef(s, false)
|
||||||
wrref(ctxt, b, s.Gotype, false)
|
w.writeRef(s.Gotype, false)
|
||||||
for i := range s.R {
|
for i := range s.R {
|
||||||
wrref(ctxt, b, s.R[i].Sym, false)
|
w.writeRef(s.R[i].Sym, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.Type == STEXT {
|
if s.Type == STEXT {
|
||||||
for a := s.Autom; a != nil; a = a.Link {
|
for a := s.Autom; a != nil; a = a.Link {
|
||||||
wrref(ctxt, b, a.Asym, false)
|
w.writeRef(a.Asym, false)
|
||||||
wrref(ctxt, b, a.Gotype, false)
|
w.writeRef(a.Gotype, false)
|
||||||
}
|
}
|
||||||
pc := s.Pcln
|
pc := s.Pcln
|
||||||
for _, d := range pc.Funcdata {
|
for _, d := range pc.Funcdata {
|
||||||
wrref(ctxt, b, d, false)
|
w.writeRef(d, false)
|
||||||
}
|
}
|
||||||
for _, f := range pc.File {
|
for _, f := range pc.File {
|
||||||
wrref(ctxt, b, f, true)
|
w.writeRef(f, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func writesym(ctxt *Link, b *Biobuf, s *LSym) {
|
func (w *objWriter) writeSymDebug(s *LSym) {
|
||||||
if ctxt.Debugasm != 0 {
|
ctxt := w.ctxt
|
||||||
fmt.Fprintf(ctxt.Bso, "%s ", s.Name)
|
fmt.Fprintf(ctxt.Bso, "%s ", s.Name)
|
||||||
if s.Version != 0 {
|
if s.Version != 0 {
|
||||||
fmt.Fprintf(ctxt.Bso, "v=%d ", s.Version)
|
fmt.Fprintf(ctxt.Bso, "v=%d ", s.Version)
|
||||||
|
}
|
||||||
|
if s.Type != 0 {
|
||||||
|
fmt.Fprintf(ctxt.Bso, "t=%d ", s.Type)
|
||||||
|
}
|
||||||
|
if s.Dupok {
|
||||||
|
fmt.Fprintf(ctxt.Bso, "dupok ")
|
||||||
|
}
|
||||||
|
if s.Cfunc {
|
||||||
|
fmt.Fprintf(ctxt.Bso, "cfunc ")
|
||||||
|
}
|
||||||
|
if s.Nosplit {
|
||||||
|
fmt.Fprintf(ctxt.Bso, "nosplit ")
|
||||||
|
}
|
||||||
|
fmt.Fprintf(ctxt.Bso, "size=%d", s.Size)
|
||||||
|
if s.Type == STEXT {
|
||||||
|
fmt.Fprintf(ctxt.Bso, " args=%#x locals=%#x", uint64(s.Args), uint64(s.Locals))
|
||||||
|
if s.Leaf {
|
||||||
|
fmt.Fprintf(ctxt.Bso, " leaf")
|
||||||
}
|
}
|
||||||
if s.Type != 0 {
|
}
|
||||||
fmt.Fprintf(ctxt.Bso, "t=%d ", s.Type)
|
|
||||||
|
fmt.Fprintf(ctxt.Bso, "\n")
|
||||||
|
for p := s.Text; p != nil; p = p.Link {
|
||||||
|
fmt.Fprintf(ctxt.Bso, "\t%#04x %v\n", uint(int(p.Pc)), p)
|
||||||
|
}
|
||||||
|
var c int
|
||||||
|
var j int
|
||||||
|
for i := 0; i < len(s.P); {
|
||||||
|
fmt.Fprintf(ctxt.Bso, "\t%#04x", uint(i))
|
||||||
|
for j = i; j < i+16 && j < len(s.P); j++ {
|
||||||
|
fmt.Fprintf(ctxt.Bso, " %02x", s.P[j])
|
||||||
}
|
}
|
||||||
if s.Dupok {
|
for ; j < i+16; j++ {
|
||||||
fmt.Fprintf(ctxt.Bso, "dupok ")
|
fmt.Fprintf(ctxt.Bso, " ")
|
||||||
}
|
}
|
||||||
if s.Cfunc {
|
fmt.Fprintf(ctxt.Bso, " ")
|
||||||
fmt.Fprintf(ctxt.Bso, "cfunc ")
|
for j = i; j < i+16 && j < len(s.P); j++ {
|
||||||
}
|
c = int(s.P[j])
|
||||||
if s.Nosplit {
|
if ' ' <= c && c <= 0x7e {
|
||||||
fmt.Fprintf(ctxt.Bso, "nosplit ")
|
fmt.Fprintf(ctxt.Bso, "%c", c)
|
||||||
}
|
} else {
|
||||||
fmt.Fprintf(ctxt.Bso, "size=%d", s.Size)
|
fmt.Fprintf(ctxt.Bso, ".")
|
||||||
if s.Type == STEXT {
|
|
||||||
fmt.Fprintf(ctxt.Bso, " args=%#x locals=%#x", uint64(s.Args), uint64(s.Locals))
|
|
||||||
if s.Leaf {
|
|
||||||
fmt.Fprintf(ctxt.Bso, " leaf")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(ctxt.Bso, "\n")
|
fmt.Fprintf(ctxt.Bso, "\n")
|
||||||
for p := s.Text; p != nil; p = p.Link {
|
i += 16
|
||||||
fmt.Fprintf(ctxt.Bso, "\t%#04x %v\n", uint(int(p.Pc)), p)
|
|
||||||
}
|
|
||||||
var c int
|
|
||||||
var j int
|
|
||||||
for i := 0; i < len(s.P); {
|
|
||||||
fmt.Fprintf(ctxt.Bso, "\t%#04x", uint(i))
|
|
||||||
for j = i; j < i+16 && j < len(s.P); j++ {
|
|
||||||
fmt.Fprintf(ctxt.Bso, " %02x", s.P[j])
|
|
||||||
}
|
|
||||||
for ; j < i+16; j++ {
|
|
||||||
fmt.Fprintf(ctxt.Bso, " ")
|
|
||||||
}
|
|
||||||
fmt.Fprintf(ctxt.Bso, " ")
|
|
||||||
for j = i; j < i+16 && j < len(s.P); j++ {
|
|
||||||
c = int(s.P[j])
|
|
||||||
if ' ' <= c && c <= 0x7e {
|
|
||||||
fmt.Fprintf(ctxt.Bso, "%c", c)
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(ctxt.Bso, ".")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(ctxt.Bso, "\n")
|
|
||||||
i += 16
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Sort(relocByOff(s.R)) // generate stable output
|
|
||||||
for _, r := range s.R {
|
|
||||||
name := ""
|
|
||||||
if r.Sym != nil {
|
|
||||||
name = r.Sym.Name
|
|
||||||
}
|
|
||||||
if ctxt.Arch.Thechar == '5' || ctxt.Arch.Thechar == '9' {
|
|
||||||
fmt.Fprintf(ctxt.Bso, "\trel %d+%d t=%d %s+%x\n", int(r.Off), r.Siz, r.Type, name, uint64(int64(r.Add)))
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(ctxt.Bso, "\trel %d+%d t=%d %s+%d\n", int(r.Off), r.Siz, r.Type, name, int64(r.Add))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Bputc(b, 0xfe)
|
sort.Sort(relocByOff(s.R)) // generate stable output
|
||||||
wrint(b, int64(s.Type))
|
for _, r := range s.R {
|
||||||
wrsym(b, s)
|
name := ""
|
||||||
|
if r.Sym != nil {
|
||||||
|
name = r.Sym.Name
|
||||||
|
}
|
||||||
|
if ctxt.Arch.Thechar == '5' || ctxt.Arch.Thechar == '9' {
|
||||||
|
fmt.Fprintf(ctxt.Bso, "\trel %d+%d t=%d %s+%x\n", int(r.Off), r.Siz, r.Type, name, uint64(int64(r.Add)))
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(ctxt.Bso, "\trel %d+%d t=%d %s+%d\n", int(r.Off), r.Siz, r.Type, name, int64(r.Add))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *objWriter) writeSym(s *LSym) {
|
||||||
|
ctxt := w.ctxt
|
||||||
|
if ctxt.Debugasm != 0 {
|
||||||
|
w.writeSymDebug(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.wr.WriteByte(symPrefix)
|
||||||
|
w.writeInt(int64(s.Type))
|
||||||
|
w.writeRefIndex(s)
|
||||||
flags := int64(0)
|
flags := int64(0)
|
||||||
if s.Dupok {
|
if s.Dupok {
|
||||||
flags |= 1
|
flags |= 1
|
||||||
@ -553,112 +578,110 @@ func writesym(ctxt *Link, b *Biobuf, s *LSym) {
|
|||||||
if s.Local {
|
if s.Local {
|
||||||
flags |= 1 << 1
|
flags |= 1 << 1
|
||||||
}
|
}
|
||||||
wrint(b, flags)
|
w.writeInt(flags)
|
||||||
wrint(b, s.Size)
|
w.writeInt(s.Size)
|
||||||
wrsym(b, s.Gotype)
|
w.writeRefIndex(s.Gotype)
|
||||||
wrint(b, int64(len(s.P)))
|
w.writeInt(int64(len(s.P)))
|
||||||
|
|
||||||
wrint(b, int64(len(s.R)))
|
w.writeInt(int64(len(s.R)))
|
||||||
var r *Reloc
|
var r *Reloc
|
||||||
for i := 0; i < len(s.R); i++ {
|
for i := 0; i < len(s.R); i++ {
|
||||||
r = &s.R[i]
|
r = &s.R[i]
|
||||||
wrint(b, int64(r.Off))
|
w.writeInt(int64(r.Off))
|
||||||
wrint(b, int64(r.Siz))
|
w.writeInt(int64(r.Siz))
|
||||||
wrint(b, int64(r.Type))
|
w.writeInt(int64(r.Type))
|
||||||
wrint(b, r.Add)
|
w.writeInt(r.Add)
|
||||||
wrsym(b, r.Sym)
|
w.writeRefIndex(r.Sym)
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.Type == STEXT {
|
if s.Type != STEXT {
|
||||||
wrint(b, int64(s.Args))
|
return
|
||||||
wrint(b, int64(s.Locals))
|
}
|
||||||
if s.Nosplit {
|
|
||||||
wrint(b, 1)
|
|
||||||
} else {
|
|
||||||
wrint(b, 0)
|
|
||||||
}
|
|
||||||
flags := int64(0)
|
|
||||||
if s.Leaf {
|
|
||||||
flags |= 1
|
|
||||||
}
|
|
||||||
if s.Cfunc {
|
|
||||||
flags |= 1 << 1
|
|
||||||
}
|
|
||||||
if s.ReflectMethod {
|
|
||||||
flags |= 1 << 2
|
|
||||||
}
|
|
||||||
wrint(b, flags)
|
|
||||||
n := 0
|
|
||||||
for a := s.Autom; a != nil; a = a.Link {
|
|
||||||
n++
|
|
||||||
}
|
|
||||||
wrint(b, int64(n))
|
|
||||||
for a := s.Autom; a != nil; a = a.Link {
|
|
||||||
wrsym(b, a.Asym)
|
|
||||||
wrint(b, int64(a.Aoffset))
|
|
||||||
if a.Name == NAME_AUTO {
|
|
||||||
wrint(b, A_AUTO)
|
|
||||||
} else if a.Name == NAME_PARAM {
|
|
||||||
wrint(b, A_PARAM)
|
|
||||||
} else {
|
|
||||||
log.Fatalf("%s: invalid local variable type %d", s.Name, a.Name)
|
|
||||||
}
|
|
||||||
wrsym(b, a.Gotype)
|
|
||||||
}
|
|
||||||
|
|
||||||
pc := s.Pcln
|
w.writeInt(int64(s.Args))
|
||||||
wrint(b, int64(len(pc.Pcsp.P)))
|
w.writeInt(int64(s.Locals))
|
||||||
wrint(b, int64(len(pc.Pcfile.P)))
|
if s.Nosplit {
|
||||||
wrint(b, int64(len(pc.Pcline.P)))
|
w.writeInt(1)
|
||||||
wrint(b, int64(len(pc.Pcdata)))
|
} else {
|
||||||
for i := 0; i < len(pc.Pcdata); i++ {
|
w.writeInt(0)
|
||||||
wrint(b, int64(len(pc.Pcdata[i].P)))
|
}
|
||||||
}
|
flags = int64(0)
|
||||||
wrint(b, int64(len(pc.Funcdataoff)))
|
if s.Leaf {
|
||||||
for i := 0; i < len(pc.Funcdataoff); i++ {
|
flags |= 1
|
||||||
wrsym(b, pc.Funcdata[i])
|
}
|
||||||
}
|
if s.Cfunc {
|
||||||
for i := 0; i < len(pc.Funcdataoff); i++ {
|
flags |= 1 << 1
|
||||||
wrint(b, pc.Funcdataoff[i])
|
}
|
||||||
}
|
if s.ReflectMethod {
|
||||||
wrint(b, int64(len(pc.File)))
|
flags |= 1 << 2
|
||||||
for _, f := range pc.File {
|
}
|
||||||
wrsym(b, f)
|
w.writeInt(flags)
|
||||||
|
n := 0
|
||||||
|
for a := s.Autom; a != nil; a = a.Link {
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
w.writeInt(int64(n))
|
||||||
|
for a := s.Autom; a != nil; a = a.Link {
|
||||||
|
w.writeRefIndex(a.Asym)
|
||||||
|
w.writeInt(int64(a.Aoffset))
|
||||||
|
if a.Name == NAME_AUTO {
|
||||||
|
w.writeInt(A_AUTO)
|
||||||
|
} else if a.Name == NAME_PARAM {
|
||||||
|
w.writeInt(A_PARAM)
|
||||||
|
} else {
|
||||||
|
log.Fatalf("%s: invalid local variable type %d", s.Name, a.Name)
|
||||||
}
|
}
|
||||||
|
w.writeRefIndex(a.Gotype)
|
||||||
|
}
|
||||||
|
|
||||||
|
pc := s.Pcln
|
||||||
|
w.writeInt(int64(len(pc.Pcsp.P)))
|
||||||
|
w.writeInt(int64(len(pc.Pcfile.P)))
|
||||||
|
w.writeInt(int64(len(pc.Pcline.P)))
|
||||||
|
w.writeInt(int64(len(pc.Pcdata)))
|
||||||
|
for i := 0; i < len(pc.Pcdata); i++ {
|
||||||
|
w.writeInt(int64(len(pc.Pcdata[i].P)))
|
||||||
|
}
|
||||||
|
w.writeInt(int64(len(pc.Funcdataoff)))
|
||||||
|
for i := 0; i < len(pc.Funcdataoff); i++ {
|
||||||
|
w.writeRefIndex(pc.Funcdata[i])
|
||||||
|
}
|
||||||
|
for i := 0; i < len(pc.Funcdataoff); i++ {
|
||||||
|
w.writeInt(pc.Funcdataoff[i])
|
||||||
|
}
|
||||||
|
w.writeInt(int64(len(pc.File)))
|
||||||
|
for _, f := range pc.File {
|
||||||
|
w.writeRefIndex(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reusable buffer to avoid allocations.
|
func (w *objWriter) writeInt(sval int64) {
|
||||||
// This buffer was responsible for 15% of gc's allocations.
|
|
||||||
var varintbuf [10]uint8
|
|
||||||
|
|
||||||
func wrint(b *Biobuf, sval int64) {
|
|
||||||
var v uint64
|
var v uint64
|
||||||
uv := (uint64(sval) << 1) ^ uint64(int64(sval>>63))
|
uv := (uint64(sval) << 1) ^ uint64(int64(sval>>63))
|
||||||
p := varintbuf[:]
|
p := w.varintbuf[:]
|
||||||
for v = uv; v >= 0x80; v >>= 7 {
|
for v = uv; v >= 0x80; v >>= 7 {
|
||||||
p[0] = uint8(v | 0x80)
|
p[0] = uint8(v | 0x80)
|
||||||
p = p[1:]
|
p = p[1:]
|
||||||
}
|
}
|
||||||
p[0] = uint8(v)
|
p[0] = uint8(v)
|
||||||
p = p[1:]
|
p = p[1:]
|
||||||
b.Write(varintbuf[:len(varintbuf)-len(p)])
|
w.wr.Write(w.varintbuf[:len(w.varintbuf)-len(p)])
|
||||||
}
|
}
|
||||||
|
|
||||||
func wrstring(b *Biobuf, s string) {
|
func (w *objWriter) writeString(s string) {
|
||||||
wrint(b, int64(len(s)))
|
w.writeInt(int64(len(s)))
|
||||||
b.w.WriteString(s)
|
w.wr.WriteString(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func wrsym(b *Biobuf, s *LSym) {
|
func (w *objWriter) writeRefIndex(s *LSym) {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
wrint(b, 0)
|
w.writeInt(0)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if s.RefIdx == 0 {
|
if s.RefIdx == 0 {
|
||||||
log.Fatalln("writing an unreferenced symbol", s.Name)
|
log.Fatalln("writing an unreferenced symbol", s.Name)
|
||||||
}
|
}
|
||||||
wrint(b, int64(s.RefIdx))
|
w.writeInt(int64(s.RefIdx))
|
||||||
}
|
}
|
||||||
|
|
||||||
// relocByOff sorts relocations by their offsets.
|
// relocByOff sorts relocations by their offsets.
|
||||||
|
Loading…
Reference in New Issue
Block a user