// An objReader is an object file reader.
type objReader struct {
- p *Package
- b *bufio.Reader
- f io.ReadSeeker
- err error
- offset int64
- limit int64
- tmp [256]byte
- pkg string
- pkgprefix string
+ p *Package
+ b *bufio.Reader
+ f io.ReadSeeker
+ err error
+ offset int64
+ dataOffset int64
+ limit int64
+ tmp [256]byte
+ pkg string
+ pkgprefix string
}
// importPathToPrefix returns the prefix that will be used in the
// readData reads a data reference from the input file.
func (r *objReader) readData() Data {
n := r.readInt()
- d := Data{Offset: r.offset, Size: int64(n)}
- r.skip(int64(n))
+ d := Data{Offset: r.dataOffset, Size: int64(n)}
+ r.dataOffset += int64(n)
return d
}
r.readRef()
}
+ dataLength := r.readInt()
+ r.dataOffset = r.offset
+ r.skip(int64(dataLength))
+
// Symbols.
for {
if b := r.readByte(); b != 0xfe {
// - byte 1 - version number
// - sequence of strings giving dependencies (imported packages)
// - empty string (marks end of sequence)
-// - sequence of sybol references used by the defined symbols
+// - sequence of symbol references used by the defined symbols
// - byte 0xff (marks end of sequence)
+// - integer (length of following data)
+// - data, the content of the defined symbols
// - sequence of defined symbols
// - byte 0xff (marks end of sequence)
// - magic footer: "\xff\xffgo13ld"
//
// TODO(rsc): The file format is good for a first pass but needs work.
// - There are SymID in the object file that should really just be strings.
-// - The actual symbol memory images are interlaced with the symbol
-// metadata. They should be separated, to reduce the I/O required to
-// load just the metadata.
package obj
}
wrstring(b, "")
+ var dataLength int64
// Emit symbol references.
for _, s := range ctxt.Text {
writerefs(ctxt, b, s)
+ dataLength += int64(len(s.P))
+
+ pc := s.Pcln
+ dataLength += int64(len(pc.Pcsp.P))
+ dataLength += int64(len(pc.Pcfile.P))
+ dataLength += int64(len(pc.Pcline.P))
+ for i := 0; i < len(pc.Pcdata); i++ {
+ dataLength += int64(len(pc.Pcdata[i].P))
+ }
}
for _, s := range ctxt.Data {
writerefs(ctxt, b, s)
+ dataLength += int64(len(s.P))
}
Bputc(b, 0xff)
+ // Write data block
+ wrint(b, dataLength)
+ for _, s := range ctxt.Text {
+ b.w.Write(s.P)
+ pc := s.Pcln
+ b.w.Write(pc.Pcsp.P)
+ b.w.Write(pc.Pcfile.P)
+ b.w.Write(pc.Pcline.P)
+ for i := 0; i < len(pc.Pcdata); i++ {
+ b.w.Write(pc.Pcdata[i].P)
+ }
+ }
+ for _, s := range ctxt.Data {
+ b.w.Write(s.P)
+ }
+
// Emit symbols.
for _, s := range ctxt.Text {
writesym(ctxt, b, s)
wrint(b, flags)
wrint(b, s.Size)
wrsym(b, s.Gotype)
- wrdata(b, s.P)
+ wrint(b, int64(len(s.P)))
wrint(b, int64(len(s.R)))
var r *Reloc
}
pc := s.Pcln
- wrdata(b, pc.Pcsp.P)
- wrdata(b, pc.Pcfile.P)
- wrdata(b, pc.Pcline.P)
+ 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++ {
- wrdata(b, pc.Pcdata[i].P)
+ wrint(b, int64(len(pc.Pcdata[i].P)))
}
wrint(b, int64(len(pc.Funcdataoff)))
for i := 0; i < len(pc.Funcdataoff); i++ {
b.w.WriteString(s)
}
-func wrdata(b *Biobuf, v []byte) {
- wrint(b, int64(len(v)))
- b.Write(v)
-}
-
func wrsym(b *Biobuf, s *LSym) {
if s == nil {
wrint(b, 0)
// - empty string (marks end of sequence)
// - sequence of sybol references used by the defined symbols
// - byte 0xff (marks end of sequence)
+// - integer (length of following data)
+// - data, the content of the defined symbols
// - sequence of defined symbols
// - byte 0xff (marks end of sequence)
// - magic footer: "\xff\xffgo13ld"
//
// TODO(rsc): The file format is good for a first pass but needs work.
// - There are SymID in the object file that should really just be strings.
-// - The actual symbol memory images are interlaced with the symbol
-// metadata. They should be separated, to reduce the I/O required to
-// load just the metadata.
import (
"bytes"
readref(ctxt, f, pkg, pn)
}
+ dataLength := rdint64(f)
+ data := make([]byte, dataLength)
+ obj.Bread(f, data)
+
for {
c, err := f.Peek(1)
if err != nil {
if c[0] == 0xff {
break
}
- readsym(ctxt, f, pkg, pn)
+ readsym(ctxt, f, &data, pkg, pn)
}
buf = [8]uint8{}
}
}
-func readsym(ctxt *Link, f *obj.Biobuf, pkg string, pn string) {
+func readsym(ctxt *Link, f *obj.Biobuf, buf *[]byte, pkg string, pn string) {
if obj.Bgetc(f) != 0xfe {
log.Fatalf("readsym out of sync")
}
local := flags&2 != 0
size := rdint(f)
typ := rdsym(ctxt, f, pkg)
- data := rddata(f)
+ data := rddata(f, buf)
nreloc := rdint(f)
var dup *LSym
s.Pcln = new(Pcln)
pc := s.Pcln
- pc.Pcsp.P = rddata(f)
- pc.Pcfile.P = rddata(f)
- pc.Pcline.P = rddata(f)
+ pc.Pcsp.P = rddata(f, buf)
+ pc.Pcfile.P = rddata(f, buf)
+ pc.Pcline.P = rddata(f, buf)
n = rdint(f)
pc.Pcdata = make([]Pcdata, n)
pc.Npcdata = n
for i := 0; i < n; i++ {
- pc.Pcdata[i].P = rddata(f)
+ pc.Pcdata[i].P = rddata(f, buf)
}
n = rdint(f)
pc.Funcdata = make([]*LSym, n)
return string(rdBuf[:n])
}
-const rddataBufMax = 1 << 14
-
-var rddataBuf = make([]byte, rddataBufMax)
-
-func rddata(f *obj.Biobuf) []byte {
- var p []byte
+func rddata(f *obj.Biobuf, buf *[]byte) []byte {
n := rdint(f)
- if n > rddataBufMax {
- p = make([]byte, n)
- } else {
- if len(rddataBuf) < n {
- rddataBuf = make([]byte, rddataBufMax)
- }
- p = rddataBuf[:n:n]
- rddataBuf = rddataBuf[n:]
- }
- obj.Bread(f, p)
+ p := (*buf)[:n:n]
+ *buf = (*buf)[n:]
return p
}