mirror of
https://github.com/golang/go
synced 2024-10-01 16:08:33 -06: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
|
||||
Etextp *LSym
|
||||
Errors int
|
||||
RefsWritten int // Number of symbol references already written to object file.
|
||||
|
||||
// state for writing objects
|
||||
Text []*LSym
|
||||
|
@ -108,6 +108,7 @@
|
||||
package obj
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"path/filepath"
|
||||
@ -120,7 +121,7 @@ import (
|
||||
// does not write out object files.
|
||||
func Writeobjdirect(ctxt *Link, b *Biobuf) {
|
||||
Flushplist(ctxt)
|
||||
Writeobjfile(ctxt, b)
|
||||
WriteObjFile(ctxt, b)
|
||||
}
|
||||
|
||||
func Flushplist(ctxt *Link) {
|
||||
@ -309,18 +310,32 @@ func flushplist(ctxt *Link, freeProgs bool) {
|
||||
}
|
||||
}
|
||||
|
||||
type sectionLengths struct {
|
||||
data int
|
||||
reloc int
|
||||
pcdata int
|
||||
autom int
|
||||
funcdata int
|
||||
file int
|
||||
// objWriter writes Go object files.
|
||||
type objWriter struct {
|
||||
wr *bufio.Writer
|
||||
ctxt *Link
|
||||
// Temporary buffer for zigzag int writing.
|
||||
varintbuf [10]uint8
|
||||
|
||||
// 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) {
|
||||
l.data += len(s.P)
|
||||
l.reloc += len(s.R)
|
||||
func (w *objWriter) addLengths(s *LSym) {
|
||||
w.nData += len(s.P)
|
||||
w.nReloc += len(s.R)
|
||||
|
||||
if s.Type != STEXT {
|
||||
return
|
||||
@ -336,102 +351,106 @@ func (l *sectionLengths) add(s *LSym) {
|
||||
data += len(pc.Pcdata[i].P)
|
||||
}
|
||||
|
||||
l.data += data
|
||||
l.pcdata += len(pc.Pcdata)
|
||||
w.nData += data
|
||||
w.nPcdata += len(pc.Pcdata)
|
||||
|
||||
autom := 0
|
||||
for a := s.Autom; a != nil; a = a.Link {
|
||||
autom++
|
||||
}
|
||||
l.autom += autom
|
||||
l.funcdata += len(pc.Funcdataoff)
|
||||
l.file += len(pc.File)
|
||||
w.nAutom += autom
|
||||
w.nFuncdata += len(pc.Funcdataoff)
|
||||
w.nFile += len(pc.File)
|
||||
}
|
||||
|
||||
func wrlengths(b *Biobuf, sl sectionLengths) {
|
||||
wrint(b, int64(sl.data))
|
||||
wrint(b, int64(sl.reloc))
|
||||
wrint(b, int64(sl.pcdata))
|
||||
wrint(b, int64(sl.autom))
|
||||
wrint(b, int64(sl.funcdata))
|
||||
wrint(b, int64(sl.file))
|
||||
func (w *objWriter) writeLengths() {
|
||||
w.writeInt(int64(w.nData))
|
||||
w.writeInt(int64(w.nReloc))
|
||||
w.writeInt(int64(w.nPcdata))
|
||||
w.writeInt(int64(w.nAutom))
|
||||
w.writeInt(int64(w.nFuncdata))
|
||||
w.writeInt(int64(w.nFile))
|
||||
}
|
||||
|
||||
func Writeobjfile(ctxt *Link, b *Biobuf) {
|
||||
// Emit header.
|
||||
Bputc(b, 0)
|
||||
|
||||
Bputc(b, 0)
|
||||
fmt.Fprintf(b, "go13ld")
|
||||
Bputc(b, 1) // version
|
||||
|
||||
// Emit autolib.
|
||||
for _, pkg := range ctxt.Imports {
|
||||
wrstring(b, pkg)
|
||||
func newObjWriter(ctxt *Link, b *Biobuf) *objWriter {
|
||||
return &objWriter{
|
||||
ctxt: ctxt,
|
||||
wr: b.w,
|
||||
vrefIdx: make(map[string]int),
|
||||
refIdx: make(map[string]int),
|
||||
}
|
||||
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 {
|
||||
writerefs(ctxt, b, s)
|
||||
lengths.add(s)
|
||||
w.writeRefs(s)
|
||||
w.addLengths(s)
|
||||
}
|
||||
for _, s := range ctxt.Data {
|
||||
writerefs(ctxt, b, s)
|
||||
lengths.add(s)
|
||||
w.writeRefs(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 {
|
||||
b.w.Write(s.P)
|
||||
w.wr.Write(s.P)
|
||||
pc := s.Pcln
|
||||
b.w.Write(pc.Pcsp.P)
|
||||
b.w.Write(pc.Pcfile.P)
|
||||
b.w.Write(pc.Pcline.P)
|
||||
w.wr.Write(pc.Pcsp.P)
|
||||
w.wr.Write(pc.Pcfile.P)
|
||||
w.wr.Write(pc.Pcline.P)
|
||||
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 {
|
||||
b.w.Write(s.P)
|
||||
w.wr.Write(s.P)
|
||||
}
|
||||
|
||||
// Emit symbols.
|
||||
// Symbols
|
||||
for _, s := range ctxt.Text {
|
||||
writesym(ctxt, b, s)
|
||||
w.writeSym(s)
|
||||
}
|
||||
for _, s := range ctxt.Data {
|
||||
writesym(ctxt, b, s)
|
||||
w.writeSym(s)
|
||||
}
|
||||
|
||||
// Emit footer.
|
||||
Bputc(b, 0xff)
|
||||
|
||||
Bputc(b, 0xff)
|
||||
fmt.Fprintf(b, "go13ld")
|
||||
// Magic footer
|
||||
w.wr.WriteString("\xff\xffgo13ld")
|
||||
}
|
||||
|
||||
// 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.
|
||||
var refIdx = make(map[string]int)
|
||||
var vrefIdx = make(map[string]int)
|
||||
// Symbols are prefixed so their content doesn't get confused with the magic footer.
|
||||
const symPrefix = 0xfe
|
||||
|
||||
func wrref(ctxt *Link, b *Biobuf, s *LSym, isPath bool) {
|
||||
func (w *objWriter) writeRef(s *LSym, isPath bool) {
|
||||
if s == nil || s.RefIdx != 0 {
|
||||
return
|
||||
}
|
||||
var m map[string]int
|
||||
switch s.Version {
|
||||
case 0:
|
||||
m = refIdx
|
||||
m = w.refIdx
|
||||
case 1:
|
||||
m = vrefIdx
|
||||
m = w.vrefIdx
|
||||
default:
|
||||
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
|
||||
return
|
||||
}
|
||||
Bputc(b, 0xfe)
|
||||
w.wr.WriteByte(symPrefix)
|
||||
if isPath {
|
||||
wrstring(b, filepath.ToSlash(s.Name))
|
||||
w.writeString(filepath.ToSlash(s.Name))
|
||||
} else {
|
||||
wrstring(b, s.Name)
|
||||
w.writeString(s.Name)
|
||||
}
|
||||
wrint(b, int64(s.Version))
|
||||
ctxt.RefsWritten++
|
||||
s.RefIdx = ctxt.RefsWritten
|
||||
m[s.Name] = ctxt.RefsWritten
|
||||
w.writeInt(int64(s.Version))
|
||||
w.nRefs++
|
||||
s.RefIdx = w.nRefs
|
||||
m[s.Name] = w.nRefs
|
||||
}
|
||||
|
||||
func writerefs(ctxt *Link, b *Biobuf, s *LSym) {
|
||||
wrref(ctxt, b, s, false)
|
||||
wrref(ctxt, b, s.Gotype, false)
|
||||
func (w *objWriter) writeRefs(s *LSym) {
|
||||
w.writeRef(s, false)
|
||||
w.writeRef(s.Gotype, false)
|
||||
for i := range s.R {
|
||||
wrref(ctxt, b, s.R[i].Sym, false)
|
||||
w.writeRef(s.R[i].Sym, false)
|
||||
}
|
||||
|
||||
if s.Type == STEXT {
|
||||
for a := s.Autom; a != nil; a = a.Link {
|
||||
wrref(ctxt, b, a.Asym, false)
|
||||
wrref(ctxt, b, a.Gotype, false)
|
||||
w.writeRef(a.Asym, false)
|
||||
w.writeRef(a.Gotype, false)
|
||||
}
|
||||
pc := s.Pcln
|
||||
for _, d := range pc.Funcdata {
|
||||
wrref(ctxt, b, d, false)
|
||||
w.writeRef(d, false)
|
||||
}
|
||||
for _, f := range pc.File {
|
||||
wrref(ctxt, b, f, true)
|
||||
w.writeRef(f, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func writesym(ctxt *Link, b *Biobuf, s *LSym) {
|
||||
if ctxt.Debugasm != 0 {
|
||||
fmt.Fprintf(ctxt.Bso, "%s ", s.Name)
|
||||
if s.Version != 0 {
|
||||
fmt.Fprintf(ctxt.Bso, "v=%d ", s.Version)
|
||||
func (w *objWriter) writeSymDebug(s *LSym) {
|
||||
ctxt := w.ctxt
|
||||
fmt.Fprintf(ctxt.Bso, "%s ", s.Name)
|
||||
if s.Version != 0 {
|
||||
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 {
|
||||
fmt.Fprintf(ctxt.Bso, "dupok ")
|
||||
for ; j < i+16; j++ {
|
||||
fmt.Fprintf(ctxt.Bso, " ")
|
||||
}
|
||||
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")
|
||||
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")
|
||||
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])
|
||||
}
|
||||
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))
|
||||
}
|
||||
}
|
||||
i += 16
|
||||
}
|
||||
|
||||
Bputc(b, 0xfe)
|
||||
wrint(b, int64(s.Type))
|
||||
wrsym(b, s)
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
if s.Dupok {
|
||||
flags |= 1
|
||||
@ -553,112 +578,110 @@ func writesym(ctxt *Link, b *Biobuf, s *LSym) {
|
||||
if s.Local {
|
||||
flags |= 1 << 1
|
||||
}
|
||||
wrint(b, flags)
|
||||
wrint(b, s.Size)
|
||||
wrsym(b, s.Gotype)
|
||||
wrint(b, int64(len(s.P)))
|
||||
w.writeInt(flags)
|
||||
w.writeInt(s.Size)
|
||||
w.writeRefIndex(s.Gotype)
|
||||
w.writeInt(int64(len(s.P)))
|
||||
|
||||
wrint(b, int64(len(s.R)))
|
||||
w.writeInt(int64(len(s.R)))
|
||||
var r *Reloc
|
||||
for i := 0; i < len(s.R); i++ {
|
||||
r = &s.R[i]
|
||||
wrint(b, int64(r.Off))
|
||||
wrint(b, int64(r.Siz))
|
||||
wrint(b, int64(r.Type))
|
||||
wrint(b, r.Add)
|
||||
wrsym(b, r.Sym)
|
||||
w.writeInt(int64(r.Off))
|
||||
w.writeInt(int64(r.Siz))
|
||||
w.writeInt(int64(r.Type))
|
||||
w.writeInt(r.Add)
|
||||
w.writeRefIndex(r.Sym)
|
||||
}
|
||||
|
||||
if s.Type == STEXT {
|
||||
wrint(b, int64(s.Args))
|
||||
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)
|
||||
}
|
||||
if s.Type != STEXT {
|
||||
return
|
||||
}
|
||||
|
||||
pc := s.Pcln
|
||||
wrint(b, int64(len(pc.Pcsp.P)))
|
||||
wrint(b, int64(len(pc.Pcfile.P)))
|
||||
wrint(b, int64(len(pc.Pcline.P)))
|
||||
wrint(b, int64(len(pc.Pcdata)))
|
||||
for i := 0; i < len(pc.Pcdata); i++ {
|
||||
wrint(b, int64(len(pc.Pcdata[i].P)))
|
||||
}
|
||||
wrint(b, int64(len(pc.Funcdataoff)))
|
||||
for i := 0; i < len(pc.Funcdataoff); i++ {
|
||||
wrsym(b, pc.Funcdata[i])
|
||||
}
|
||||
for i := 0; i < len(pc.Funcdataoff); i++ {
|
||||
wrint(b, pc.Funcdataoff[i])
|
||||
}
|
||||
wrint(b, int64(len(pc.File)))
|
||||
for _, f := range pc.File {
|
||||
wrsym(b, f)
|
||||
w.writeInt(int64(s.Args))
|
||||
w.writeInt(int64(s.Locals))
|
||||
if s.Nosplit {
|
||||
w.writeInt(1)
|
||||
} else {
|
||||
w.writeInt(0)
|
||||
}
|
||||
flags = int64(0)
|
||||
if s.Leaf {
|
||||
flags |= 1
|
||||
}
|
||||
if s.Cfunc {
|
||||
flags |= 1 << 1
|
||||
}
|
||||
if s.ReflectMethod {
|
||||
flags |= 1 << 2
|
||||
}
|
||||
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.
|
||||
// This buffer was responsible for 15% of gc's allocations.
|
||||
var varintbuf [10]uint8
|
||||
|
||||
func wrint(b *Biobuf, sval int64) {
|
||||
func (w *objWriter) writeInt(sval int64) {
|
||||
var v uint64
|
||||
uv := (uint64(sval) << 1) ^ uint64(int64(sval>>63))
|
||||
p := varintbuf[:]
|
||||
p := w.varintbuf[:]
|
||||
for v = uv; v >= 0x80; v >>= 7 {
|
||||
p[0] = uint8(v | 0x80)
|
||||
p = p[1:]
|
||||
}
|
||||
p[0] = uint8(v)
|
||||
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) {
|
||||
wrint(b, int64(len(s)))
|
||||
b.w.WriteString(s)
|
||||
func (w *objWriter) writeString(s string) {
|
||||
w.writeInt(int64(len(s)))
|
||||
w.wr.WriteString(s)
|
||||
}
|
||||
|
||||
func wrsym(b *Biobuf, s *LSym) {
|
||||
func (w *objWriter) writeRefIndex(s *LSym) {
|
||||
if s == nil {
|
||||
wrint(b, 0)
|
||||
w.writeInt(0)
|
||||
return
|
||||
}
|
||||
if s.RefIdx == 0 {
|
||||
log.Fatalln("writing an unreferenced symbol", s.Name)
|
||||
}
|
||||
wrint(b, int64(s.RefIdx))
|
||||
w.writeInt(int64(s.RefIdx))
|
||||
}
|
||||
|
||||
// relocByOff sorts relocations by their offsets.
|
||||
|
Loading…
Reference in New Issue
Block a user