From 1adae7fe76d27cb9623cb269bb3ede2372f5eea6 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Sat, 25 Apr 2020 17:50:48 -0400 Subject: [PATCH] [dev.link] cmd/link: convert asmb pass to new style Change-Id: I8675f56a7f7f18653754eb87b95f5a7aec31ad74 Reviewed-on: https://go-review.googlesource.com/c/go/+/229860 Run-TryBot: Cherry Zhang TryBot-Result: Gobot Gobot Reviewed-by: Than McIntosh Reviewed-by: Jeremy Faller --- src/cmd/link/internal/ld/data.go | 75 +++++++++++++------------- src/cmd/link/internal/ld/main.go | 5 +- src/cmd/link/internal/ld/outbuf.go | 11 ++-- src/cmd/link/internal/loader/loader.go | 31 ++++++++++- 4 files changed, 77 insertions(+), 45 deletions(-) diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 1fd048e10d..d44d590623 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -716,7 +716,7 @@ func Codeblk(ctxt *Link, out *OutBuf, addr int64, size int64) { } func CodeblkPad(ctxt *Link, out *OutBuf, addr int64, size int64, pad []byte) { - writeBlocks(out, ctxt.outSem, ctxt.Textp, addr, size, pad) + writeBlocks(out, ctxt.outSem, ctxt.loader, ctxt.Textp2, addr, size, pad) } const blockSize = 1 << 20 // 1MB chunks written at a time. @@ -726,9 +726,9 @@ const blockSize = 1 << 20 // 1MB chunks written at a time. // as many goroutines as necessary to accomplish this task. This call then // blocks, waiting on the writes to complete. Note that we use the sem parameter // to limit the number of concurrent writes taking place. -func writeBlocks(out *OutBuf, sem chan int, syms []*sym.Symbol, addr, size int64, pad []byte) { +func writeBlocks(out *OutBuf, sem chan int, ldr *loader.Loader, syms []loader.Sym, addr, size int64, pad []byte) { for i, s := range syms { - if s.Value >= addr && !s.Attr.SubSymbol() { + if ldr.SymValue(s) >= addr && !ldr.AttrSubSymbol(s) { syms = syms[i:] break } @@ -740,13 +740,14 @@ func writeBlocks(out *OutBuf, sem chan int, syms []*sym.Symbol, addr, size int64 // Find the last symbol we'd write. idx := -1 for i, s := range syms { - if s.Attr.SubSymbol() { + if ldr.AttrSubSymbol(s) { continue } // If the next symbol's size would put us out of bounds on the total length, // stop looking. - if s.Value+s.Size > lastAddr { + end := ldr.SymValue(s) + ldr.SymSize(s) + if end > lastAddr { break } @@ -754,7 +755,7 @@ func writeBlocks(out *OutBuf, sem chan int, syms []*sym.Symbol, addr, size int64 idx = i // If we cross over the max size, we've got enough symbols. - if s.Value+s.Size > addr+max { + if end > addr+max { break } } @@ -775,11 +776,11 @@ func writeBlocks(out *OutBuf, sem chan int, syms []*sym.Symbol, addr, size int64 // Skip over sub symbols so we won't split a containter symbol // into two blocks. next := syms[idx+1] - for next.Attr.SubSymbol() { + for ldr.AttrSubSymbol(next) { idx++ next = syms[idx+1] } - length = next.Value - addr + length = ldr.SymValue(next) - addr } if length == 0 || length > lastAddr-addr { length = lastAddr - addr @@ -789,13 +790,13 @@ func writeBlocks(out *OutBuf, sem chan int, syms []*sym.Symbol, addr, size int64 if o, err := out.View(uint64(out.Offset() + written)); err == nil { sem <- 1 wg.Add(1) - go func(o *OutBuf, syms []*sym.Symbol, addr, size int64, pad []byte) { - writeBlock(o, syms, addr, size, pad) + go func(o *OutBuf, ldr *loader.Loader, syms []loader.Sym, addr, size int64, pad []byte) { + writeBlock(o, ldr, syms, addr, size, pad) wg.Done() <-sem - }(o, syms, addr, length, pad) + }(o, ldr, syms, addr, length, pad) } else { // output not mmaped, don't parallelize. - writeBlock(out, syms, addr, length, pad) + writeBlock(out, ldr, syms, addr, length, pad) } // Prepare for the next loop. @@ -808,9 +809,9 @@ func writeBlocks(out *OutBuf, sem chan int, syms []*sym.Symbol, addr, size int64 wg.Wait() } -func writeBlock(out *OutBuf, syms []*sym.Symbol, addr, size int64, pad []byte) { +func writeBlock(out *OutBuf, ldr *loader.Loader, syms []loader.Sym, addr, size int64, pad []byte) { for i, s := range syms { - if s.Value >= addr && !s.Attr.SubSymbol() { + if ldr.SymValue(s) >= addr && !ldr.AttrSubSymbol(s) { syms = syms[i:] break } @@ -822,31 +823,33 @@ func writeBlock(out *OutBuf, syms []*sym.Symbol, addr, size int64, pad []byte) { // so dwarfcompress will fix this up later if necessary. eaddr := addr + size for _, s := range syms { - if s.Attr.SubSymbol() { + if ldr.AttrSubSymbol(s) { continue } - if s.Value >= eaddr { + val := ldr.SymValue(s) + if val >= eaddr { break } - if s.Value < addr { - Errorf(s, "phase error: addr=%#x but sym=%#x type=%d", addr, s.Value, s.Type) + if val < addr { + ldr.Errorf(s, "phase error: addr=%#x but sym=%#x type=%d", addr, val, ldr.SymType(s)) errorexit() } - if addr < s.Value { - out.WriteStringPad("", int(s.Value-addr), pad) - addr = s.Value + if addr < val { + out.WriteStringPad("", int(val-addr), pad) + addr = val } - out.WriteSym(s) - addr += int64(len(s.P)) - if addr < s.Value+s.Size { - out.WriteStringPad("", int(s.Value+s.Size-addr), pad) - addr = s.Value + s.Size + out.WriteSym(ldr, s) + addr += int64(len(ldr.Data(s))) + siz := ldr.SymSize(s) + if addr < val+siz { + out.WriteStringPad("", int(val+siz-addr), pad) + addr = val + siz } - if addr != s.Value+s.Size { - Errorf(s, "phase error: addr=%#x value+size=%#x", addr, s.Value+s.Size) + if addr != val+siz { + ldr.Errorf(s, "phase error: addr=%#x value+size=%#x", addr, val+siz) errorexit() } - if s.Value+s.Size >= eaddr { + if val+siz >= eaddr { break } } @@ -885,7 +888,7 @@ func DatblkBytes(ctxt *Link, addr int64, size int64) []byte { } func writeDatblkToOutBuf(ctxt *Link, out *OutBuf, addr int64, size int64) { - writeBlocks(out, ctxt.outSem, ctxt.datap, addr, size, zeros[:]) + writeBlocks(out, ctxt.outSem, ctxt.loader, ctxt.datap2, addr, size, zeros[:]) } func Dwarfblk(ctxt *Link, out *OutBuf, addr int64, size int64) { @@ -896,14 +899,14 @@ func Dwarfblk(ctxt *Link, out *OutBuf, addr int64, size int64) { // section, but this would run the risk of undoing any file offset // adjustments made during layout. n := 0 - for i := range dwarfp { - n += len(dwarfp[i].syms) + for i := range dwarfp2 { + n += len(dwarfp2[i].syms) } - syms := make([]*sym.Symbol, 0, n) - for i := range dwarfp { - syms = append(syms, dwarfp[i].syms...) + syms := make([]loader.Sym, 0, n) + for i := range dwarfp2 { + syms = append(syms, dwarfp2[i].syms...) } - writeBlocks(out, ctxt.outSem, syms, addr, size, zeros[:]) + writeBlocks(out, ctxt.outSem, ctxt.loader, syms, addr, size, zeros[:]) } var zeros [512]byte diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index 48fea57cc9..a4526230c9 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -306,8 +306,6 @@ func Main(arch *sys.Arch, theArch Arch) { dwarfcompress(ctxt) bench.Start("layout") filesize := ctxt.layout(order) - bench.Start("loadlibfull") - ctxt.loadlibfull(symGroupType) // XXX do it here for now // Write out the output file. // It is split into two parts (Asmb and Asmb2). The first @@ -325,7 +323,10 @@ func Main(arch *sys.Arch, theArch Arch) { // Asmb will redirect symbols to the output file mmap, and relocations // will be applied directly there. bench.Start("Asmb") + ctxt.loader.InitOutData() thearch.Asmb(ctxt, ctxt.loader) + bench.Start("loadlibfull") + ctxt.loadlibfull(symGroupType) // XXX do it here for now bench.Start("reloc") ctxt.reloc() bench.Start("Asmb2") diff --git a/src/cmd/link/internal/ld/outbuf.go b/src/cmd/link/internal/ld/outbuf.go index 40e02cb7cf..4ce211172c 100644 --- a/src/cmd/link/internal/ld/outbuf.go +++ b/src/cmd/link/internal/ld/outbuf.go @@ -6,7 +6,7 @@ package ld import ( "cmd/internal/sys" - "cmd/link/internal/sym" + "cmd/link/internal/loader" "encoding/binary" "errors" "log" @@ -285,10 +285,11 @@ func (out *OutBuf) WriteStringPad(s string, n int, pad []byte) { // to point to the output buffer that we just wrote, so we can apply further // edit to the symbol content. // If the output file is not Mmap'd, just writes the content. -func (out *OutBuf) WriteSym(s *sym.Symbol) { - n := int64(len(s.P)) +func (out *OutBuf) WriteSym(ldr *loader.Loader, s loader.Sym) { + P := ldr.Data(s) + n := int64(len(P)) pos, buf := out.writeLoc(n) - copy(buf[pos:], s.P) + copy(buf[pos:], P) out.off += n - s.P = buf[pos : pos+n] + ldr.SetOutData(s, buf[pos:pos+n]) } diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index fb792ac059..775a2cb522 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -216,6 +216,8 @@ type Loader struct { sects []*sym.Section // sections symSects []uint16 // symbol's section, index to sects array + outdata [][]byte // symbol's data in the output buffer + itablink map[Sym]struct{} // itablink[j] defined if j is go.itablink.* objByPkg map[string]*oReader // map package path to its Go object reader @@ -1080,6 +1082,32 @@ func (l *Loader) Data(i Sym) []byte { return r.Data(li) } +// Returns the data of the i-th symbol in the output buffer. +func (l *Loader) OutData(i Sym) []byte { + if int(i) < len(l.outdata) && l.outdata[i] != nil { + return l.outdata[i] + } + return l.Data(i) +} + +// SetOutData sets the position of the data of the i-th symbol in the output buffer. +// i is global index. +func (l *Loader) SetOutData(i Sym, data []byte) { + if l.IsExternal(i) { + pp := l.getPayload(i) + if pp != nil { + pp.data = data + return + } + } + l.outdata[i] = data +} + +// InitOutData initializes the slice used to store symbol output data. +func (l *Loader) InitOutData() { + l.outdata = make([][]byte, l.extStart) +} + // SymAlign returns the alignment for a symbol. func (l *Loader) SymAlign(i Sym) int32 { // If an alignment has been recorded, return that. @@ -2592,8 +2620,7 @@ func loadObjFull(l *Loader, r *oReader) { size := osym.Siz() // Symbol data - s.P = r.Data(i) - s.Attr.Set(sym.AttrReadOnly, r.ReadOnly()) + s.P = l.OutData(gi) // Relocs relocs := l.relocs(r, i) -- 2.48.1