2019-08-22 17:26:41 -04:00
|
|
|
// Copyright 2019 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
|
|
// Writing Go object files.
|
|
|
|
|
|
|
|
|
|
package obj
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
|
|
|
|
"cmd/internal/bio"
|
|
|
|
|
"cmd/internal/goobj2"
|
|
|
|
|
"cmd/internal/objabi"
|
|
|
|
|
"fmt"
|
2019-10-12 14:01:57 -04:00
|
|
|
"path/filepath"
|
2019-08-22 17:26:41 -04:00
|
|
|
"strings"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Entry point of writing new object file.
|
|
|
|
|
func WriteObjFile2(ctxt *Link, b *bio.Writer, pkgpath string) {
|
2019-10-08 21:43:20 -04:00
|
|
|
if ctxt.Debugasm > 0 {
|
|
|
|
|
ctxt.traverseSyms(traverseDefs, ctxt.writeSymDebug)
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-22 17:26:41 -04:00
|
|
|
genFuncInfoSyms(ctxt)
|
|
|
|
|
|
|
|
|
|
w := writer{
|
|
|
|
|
Writer: goobj2.NewWriter(b),
|
|
|
|
|
ctxt: ctxt,
|
|
|
|
|
pkgpath: objabi.PathToPrefix(pkgpath),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
start := b.Offset()
|
|
|
|
|
w.init()
|
|
|
|
|
|
|
|
|
|
// Header
|
|
|
|
|
// We just reserve the space. We'll fill in the offsets later.
|
2019-10-16 08:54:58 -04:00
|
|
|
flags := uint32(0)
|
|
|
|
|
if ctxt.Flag_shared {
|
|
|
|
|
flags |= goobj2.ObjFlagShared
|
|
|
|
|
}
|
|
|
|
|
h := goobj2.Header{Magic: goobj2.Magic, Flags: flags}
|
2019-08-22 17:26:41 -04:00
|
|
|
h.Write(w.Writer)
|
|
|
|
|
|
|
|
|
|
// String table
|
|
|
|
|
w.StringTable()
|
|
|
|
|
|
2019-10-09 10:22:02 -04:00
|
|
|
// Autolib
|
|
|
|
|
h.Offsets[goobj2.BlkAutolib] = w.Offset()
|
|
|
|
|
for _, pkg := range ctxt.Imports {
|
|
|
|
|
w.StringRef(pkg)
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-22 17:26:41 -04:00
|
|
|
// Package references
|
|
|
|
|
h.Offsets[goobj2.BlkPkgIdx] = w.Offset()
|
|
|
|
|
for _, pkg := range w.pkglist {
|
|
|
|
|
w.StringRef(pkg)
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-30 11:43:41 -04:00
|
|
|
// DWARF file table
|
|
|
|
|
h.Offsets[goobj2.BlkDwarfFile] = w.Offset()
|
|
|
|
|
for _, f := range ctxt.PosTable.DebugLinesFileTable() {
|
2020-01-31 14:22:03 -05:00
|
|
|
w.StringRef(filepath.ToSlash(f))
|
2019-09-30 11:43:41 -04:00
|
|
|
}
|
|
|
|
|
|
2019-08-22 17:26:41 -04:00
|
|
|
// Symbol definitions
|
|
|
|
|
h.Offsets[goobj2.BlkSymdef] = w.Offset()
|
|
|
|
|
for _, s := range ctxt.defs {
|
|
|
|
|
w.Sym(s)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Non-pkg symbol definitions
|
|
|
|
|
h.Offsets[goobj2.BlkNonpkgdef] = w.Offset()
|
|
|
|
|
for _, s := range ctxt.nonpkgdefs {
|
|
|
|
|
w.Sym(s)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Non-pkg symbol references
|
|
|
|
|
h.Offsets[goobj2.BlkNonpkgref] = w.Offset()
|
|
|
|
|
for _, s := range ctxt.nonpkgrefs {
|
|
|
|
|
w.Sym(s)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reloc indexes
|
|
|
|
|
h.Offsets[goobj2.BlkRelocIdx] = w.Offset()
|
|
|
|
|
nreloc := uint32(0)
|
|
|
|
|
lists := [][]*LSym{ctxt.defs, ctxt.nonpkgdefs}
|
|
|
|
|
for _, list := range lists {
|
|
|
|
|
for _, s := range list {
|
|
|
|
|
w.Uint32(nreloc)
|
|
|
|
|
nreloc += uint32(len(s.R))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
w.Uint32(nreloc)
|
|
|
|
|
|
|
|
|
|
// Symbol Info indexes
|
|
|
|
|
h.Offsets[goobj2.BlkAuxIdx] = w.Offset()
|
|
|
|
|
naux := uint32(0)
|
|
|
|
|
for _, list := range lists {
|
|
|
|
|
for _, s := range list {
|
|
|
|
|
w.Uint32(naux)
|
2019-10-07 21:10:41 -04:00
|
|
|
naux += uint32(nAuxSym(s))
|
2019-08-22 17:26:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
w.Uint32(naux)
|
|
|
|
|
|
|
|
|
|
// Data indexes
|
|
|
|
|
h.Offsets[goobj2.BlkDataIdx] = w.Offset()
|
|
|
|
|
dataOff := uint32(0)
|
|
|
|
|
for _, list := range lists {
|
|
|
|
|
for _, s := range list {
|
|
|
|
|
w.Uint32(dataOff)
|
|
|
|
|
dataOff += uint32(len(s.P))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
w.Uint32(dataOff)
|
|
|
|
|
|
|
|
|
|
// Relocs
|
|
|
|
|
h.Offsets[goobj2.BlkReloc] = w.Offset()
|
|
|
|
|
for _, list := range lists {
|
|
|
|
|
for _, s := range list {
|
|
|
|
|
for i := range s.R {
|
|
|
|
|
w.Reloc(&s.R[i])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Aux symbol info
|
|
|
|
|
h.Offsets[goobj2.BlkAux] = w.Offset()
|
|
|
|
|
for _, list := range lists {
|
|
|
|
|
for _, s := range list {
|
|
|
|
|
w.Aux(s)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Data
|
|
|
|
|
h.Offsets[goobj2.BlkData] = w.Offset()
|
|
|
|
|
for _, list := range lists {
|
|
|
|
|
for _, s := range list {
|
|
|
|
|
w.Bytes(s.P)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Pcdata
|
|
|
|
|
h.Offsets[goobj2.BlkPcdata] = w.Offset()
|
|
|
|
|
for _, s := range ctxt.Text { // iteration order must match genFuncInfoSyms
|
|
|
|
|
if s.Func != nil {
|
|
|
|
|
pc := &s.Func.Pcln
|
|
|
|
|
w.Bytes(pc.Pcsp.P)
|
|
|
|
|
w.Bytes(pc.Pcfile.P)
|
|
|
|
|
w.Bytes(pc.Pcline.P)
|
|
|
|
|
w.Bytes(pc.Pcinline.P)
|
|
|
|
|
for i := range pc.Pcdata {
|
|
|
|
|
w.Bytes(pc.Pcdata[i].P)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fix up block offsets in the header
|
|
|
|
|
end := start + int64(w.Offset())
|
|
|
|
|
b.MustSeek(start, 0)
|
|
|
|
|
h.Write(w.Writer)
|
|
|
|
|
b.MustSeek(end, 0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type writer struct {
|
|
|
|
|
*goobj2.Writer
|
|
|
|
|
ctxt *Link
|
|
|
|
|
pkgpath string // the package import path (escaped), "" if unknown
|
|
|
|
|
pkglist []string // list of packages referenced, indexed by ctxt.pkgIdx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// prepare package index list
|
|
|
|
|
func (w *writer) init() {
|
|
|
|
|
w.pkglist = make([]string, len(w.ctxt.pkgIdx)+1)
|
|
|
|
|
w.pkglist[0] = "" // dummy invalid package for index 0
|
|
|
|
|
for pkg, i := range w.ctxt.pkgIdx {
|
|
|
|
|
w.pkglist[i] = pkg
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (w *writer) StringTable() {
|
|
|
|
|
w.AddString("")
|
|
|
|
|
for _, pkg := range w.ctxt.Imports {
|
|
|
|
|
w.AddString(pkg)
|
|
|
|
|
}
|
|
|
|
|
for _, pkg := range w.pkglist {
|
|
|
|
|
w.AddString(pkg)
|
|
|
|
|
}
|
|
|
|
|
w.ctxt.traverseSyms(traverseAll, func(s *LSym) {
|
|
|
|
|
if w.pkgpath != "" {
|
|
|
|
|
s.Name = strings.Replace(s.Name, "\"\".", w.pkgpath+".", -1)
|
|
|
|
|
}
|
|
|
|
|
w.AddString(s.Name)
|
|
|
|
|
})
|
|
|
|
|
w.ctxt.traverseSyms(traverseDefs, func(s *LSym) {
|
|
|
|
|
if s.Type != objabi.STEXT {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
pc := &s.Func.Pcln
|
|
|
|
|
for _, f := range pc.File {
|
2019-10-12 14:01:57 -04:00
|
|
|
w.AddString(filepath.ToSlash(f))
|
2019-08-22 17:26:41 -04:00
|
|
|
}
|
|
|
|
|
for _, call := range pc.InlTree.nodes {
|
|
|
|
|
f, _ := linkgetlineFromPos(w.ctxt, call.Pos)
|
2019-10-12 14:01:57 -04:00
|
|
|
w.AddString(filepath.ToSlash(f))
|
2019-08-22 17:26:41 -04:00
|
|
|
}
|
|
|
|
|
})
|
2019-09-30 11:43:41 -04:00
|
|
|
for _, f := range w.ctxt.PosTable.DebugLinesFileTable() {
|
2020-01-31 14:22:03 -05:00
|
|
|
w.AddString(filepath.ToSlash(f))
|
2019-09-30 11:43:41 -04:00
|
|
|
}
|
2019-08-22 17:26:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (w *writer) Sym(s *LSym) {
|
|
|
|
|
abi := uint16(s.ABI())
|
|
|
|
|
if s.Static() {
|
|
|
|
|
abi = goobj2.SymABIstatic
|
|
|
|
|
}
|
|
|
|
|
flag := uint8(0)
|
|
|
|
|
if s.DuplicateOK() {
|
|
|
|
|
flag |= goobj2.SymFlagDupok
|
|
|
|
|
}
|
|
|
|
|
if s.Local() {
|
|
|
|
|
flag |= goobj2.SymFlagLocal
|
|
|
|
|
}
|
|
|
|
|
if s.MakeTypelink() {
|
|
|
|
|
flag |= goobj2.SymFlagTypelink
|
|
|
|
|
}
|
2019-10-08 18:21:22 -04:00
|
|
|
if s.Leaf() {
|
|
|
|
|
flag |= goobj2.SymFlagLeaf
|
|
|
|
|
}
|
2020-02-17 01:27:11 -05:00
|
|
|
if s.NoSplit() {
|
|
|
|
|
flag |= goobj2.SymFlagNoSplit
|
2019-10-08 18:21:22 -04:00
|
|
|
}
|
|
|
|
|
if s.ReflectMethod() {
|
|
|
|
|
flag |= goobj2.SymFlagReflectMethod
|
|
|
|
|
}
|
|
|
|
|
if s.TopFrame() {
|
|
|
|
|
flag |= goobj2.SymFlagTopFrame
|
|
|
|
|
}
|
2019-10-16 09:13:59 -04:00
|
|
|
if strings.HasPrefix(s.Name, "type.") && s.Name[5] != '.' && s.Type == objabi.SRODATA {
|
|
|
|
|
flag |= goobj2.SymFlagGoType
|
|
|
|
|
}
|
2019-10-12 14:01:57 -04:00
|
|
|
name := s.Name
|
|
|
|
|
if strings.HasPrefix(name, "gofile..") {
|
|
|
|
|
name = filepath.ToSlash(name)
|
|
|
|
|
}
|
2019-08-22 17:26:41 -04:00
|
|
|
o := goobj2.Sym{
|
2019-10-12 14:01:57 -04:00
|
|
|
Name: name,
|
2019-08-22 17:26:41 -04:00
|
|
|
ABI: abi,
|
|
|
|
|
Type: uint8(s.Type),
|
|
|
|
|
Flag: flag,
|
|
|
|
|
Siz: uint32(s.Size),
|
|
|
|
|
}
|
|
|
|
|
o.Write(w.Writer)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func makeSymRef(s *LSym) goobj2.SymRef {
|
|
|
|
|
if s == nil {
|
|
|
|
|
return goobj2.SymRef{}
|
|
|
|
|
}
|
|
|
|
|
if s.PkgIdx == 0 || !s.Indexed() {
|
|
|
|
|
fmt.Printf("unindexed symbol reference: %v\n", s)
|
|
|
|
|
panic("unindexed symbol reference")
|
|
|
|
|
}
|
|
|
|
|
return goobj2.SymRef{PkgIdx: uint32(s.PkgIdx), SymIdx: uint32(s.SymIdx)}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (w *writer) Reloc(r *Reloc) {
|
|
|
|
|
o := goobj2.Reloc{
|
|
|
|
|
Off: r.Off,
|
|
|
|
|
Siz: r.Siz,
|
|
|
|
|
Type: uint8(r.Type),
|
|
|
|
|
Add: r.Add,
|
|
|
|
|
Sym: makeSymRef(r.Sym),
|
|
|
|
|
}
|
|
|
|
|
o.Write(w.Writer)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (w *writer) Aux(s *LSym) {
|
|
|
|
|
if s.Gotype != nil {
|
|
|
|
|
o := goobj2.Aux{
|
|
|
|
|
Type: goobj2.AuxGotype,
|
|
|
|
|
Sym: makeSymRef(s.Gotype),
|
|
|
|
|
}
|
|
|
|
|
o.Write(w.Writer)
|
|
|
|
|
}
|
|
|
|
|
if s.Func != nil {
|
|
|
|
|
o := goobj2.Aux{
|
|
|
|
|
Type: goobj2.AuxFuncInfo,
|
|
|
|
|
Sym: makeSymRef(s.Func.FuncInfoSym),
|
|
|
|
|
}
|
|
|
|
|
o.Write(w.Writer)
|
|
|
|
|
|
|
|
|
|
for _, d := range s.Func.Pcln.Funcdata {
|
|
|
|
|
o := goobj2.Aux{
|
|
|
|
|
Type: goobj2.AuxFuncdata,
|
|
|
|
|
Sym: makeSymRef(d),
|
|
|
|
|
}
|
|
|
|
|
o.Write(w.Writer)
|
|
|
|
|
}
|
2019-10-07 21:10:41 -04:00
|
|
|
|
|
|
|
|
if s.Func.dwarfInfoSym != nil {
|
|
|
|
|
o := goobj2.Aux{
|
|
|
|
|
Type: goobj2.AuxDwarfInfo,
|
|
|
|
|
Sym: makeSymRef(s.Func.dwarfInfoSym),
|
|
|
|
|
}
|
|
|
|
|
o.Write(w.Writer)
|
|
|
|
|
}
|
[dev.link] cmd/link: demote dwarf {range,loc} sub-symbols to aux
When the compiler emits DWARF for a function F, in addition to the
text symbol for F, it emits a set of sibling or child symbols that
carry the various DWARF bits for F (for example, go.info.F,
go.ranges.F, go.loc.F, and so on).
Prior to the linker modernization work, name lookup was the way you
made your way from a function symbol to one of its child DWARF
symbols. We now have a new mechanism (aux symbols), so there is really
no need for the DWARF sub-symbols to be named or to be dupok.
This patch converts DWARF "range" and "loc" sub-symbols to be pure aux
syms: unnamed, and connected to their parent text symbol only via aux
data. This should presumably have performance benefits in that we add
fewer symbols to the linker lookup tables.
Other related DWARF sub-symbols (ex: go.line.*) will be handled in a
subsequent patch.
Change-Id: Iae3ec2d42452962d4afc1df4a1bd89ccdeadc6e4
Reviewed-on: https://go-review.googlesource.com/c/go/+/222673
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2020-03-09 11:42:03 -04:00
|
|
|
if s.Func.dwarfLocSym != nil && s.Func.dwarfLocSym.Size != 0 {
|
2019-10-07 21:10:41 -04:00
|
|
|
o := goobj2.Aux{
|
|
|
|
|
Type: goobj2.AuxDwarfLoc,
|
|
|
|
|
Sym: makeSymRef(s.Func.dwarfLocSym),
|
|
|
|
|
}
|
|
|
|
|
o.Write(w.Writer)
|
|
|
|
|
}
|
[dev.link] cmd/link: demote dwarf {range,loc} sub-symbols to aux
When the compiler emits DWARF for a function F, in addition to the
text symbol for F, it emits a set of sibling or child symbols that
carry the various DWARF bits for F (for example, go.info.F,
go.ranges.F, go.loc.F, and so on).
Prior to the linker modernization work, name lookup was the way you
made your way from a function symbol to one of its child DWARF
symbols. We now have a new mechanism (aux symbols), so there is really
no need for the DWARF sub-symbols to be named or to be dupok.
This patch converts DWARF "range" and "loc" sub-symbols to be pure aux
syms: unnamed, and connected to their parent text symbol only via aux
data. This should presumably have performance benefits in that we add
fewer symbols to the linker lookup tables.
Other related DWARF sub-symbols (ex: go.line.*) will be handled in a
subsequent patch.
Change-Id: Iae3ec2d42452962d4afc1df4a1bd89ccdeadc6e4
Reviewed-on: https://go-review.googlesource.com/c/go/+/222673
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2020-03-09 11:42:03 -04:00
|
|
|
if s.Func.dwarfRangesSym != nil && s.Func.dwarfRangesSym.Size != 0 {
|
2019-10-07 21:10:41 -04:00
|
|
|
o := goobj2.Aux{
|
|
|
|
|
Type: goobj2.AuxDwarfRanges,
|
|
|
|
|
Sym: makeSymRef(s.Func.dwarfRangesSym),
|
|
|
|
|
}
|
|
|
|
|
o.Write(w.Writer)
|
|
|
|
|
}
|
|
|
|
|
if s.Func.dwarfDebugLinesSym != nil {
|
|
|
|
|
o := goobj2.Aux{
|
|
|
|
|
Type: goobj2.AuxDwarfLines,
|
|
|
|
|
Sym: makeSymRef(s.Func.dwarfDebugLinesSym),
|
|
|
|
|
}
|
|
|
|
|
o.Write(w.Writer)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// return the number of aux symbols s have.
|
|
|
|
|
func nAuxSym(s *LSym) int {
|
|
|
|
|
n := 0
|
|
|
|
|
if s.Gotype != nil {
|
|
|
|
|
n++
|
|
|
|
|
}
|
|
|
|
|
if s.Func != nil {
|
|
|
|
|
// FuncInfo is an aux symbol, each Funcdata is an aux symbol
|
|
|
|
|
n += 1 + len(s.Func.Pcln.Funcdata)
|
|
|
|
|
if s.Func.dwarfInfoSym != nil {
|
|
|
|
|
n++
|
|
|
|
|
}
|
[dev.link] cmd/link: demote dwarf {range,loc} sub-symbols to aux
When the compiler emits DWARF for a function F, in addition to the
text symbol for F, it emits a set of sibling or child symbols that
carry the various DWARF bits for F (for example, go.info.F,
go.ranges.F, go.loc.F, and so on).
Prior to the linker modernization work, name lookup was the way you
made your way from a function symbol to one of its child DWARF
symbols. We now have a new mechanism (aux symbols), so there is really
no need for the DWARF sub-symbols to be named or to be dupok.
This patch converts DWARF "range" and "loc" sub-symbols to be pure aux
syms: unnamed, and connected to their parent text symbol only via aux
data. This should presumably have performance benefits in that we add
fewer symbols to the linker lookup tables.
Other related DWARF sub-symbols (ex: go.line.*) will be handled in a
subsequent patch.
Change-Id: Iae3ec2d42452962d4afc1df4a1bd89ccdeadc6e4
Reviewed-on: https://go-review.googlesource.com/c/go/+/222673
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2020-03-09 11:42:03 -04:00
|
|
|
if s.Func.dwarfLocSym != nil && s.Func.dwarfLocSym.Size != 0 {
|
2019-10-07 21:10:41 -04:00
|
|
|
n++
|
|
|
|
|
}
|
[dev.link] cmd/link: demote dwarf {range,loc} sub-symbols to aux
When the compiler emits DWARF for a function F, in addition to the
text symbol for F, it emits a set of sibling or child symbols that
carry the various DWARF bits for F (for example, go.info.F,
go.ranges.F, go.loc.F, and so on).
Prior to the linker modernization work, name lookup was the way you
made your way from a function symbol to one of its child DWARF
symbols. We now have a new mechanism (aux symbols), so there is really
no need for the DWARF sub-symbols to be named or to be dupok.
This patch converts DWARF "range" and "loc" sub-symbols to be pure aux
syms: unnamed, and connected to their parent text symbol only via aux
data. This should presumably have performance benefits in that we add
fewer symbols to the linker lookup tables.
Other related DWARF sub-symbols (ex: go.line.*) will be handled in a
subsequent patch.
Change-Id: Iae3ec2d42452962d4afc1df4a1bd89ccdeadc6e4
Reviewed-on: https://go-review.googlesource.com/c/go/+/222673
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2020-03-09 11:42:03 -04:00
|
|
|
if s.Func.dwarfRangesSym != nil && s.Func.dwarfRangesSym.Size != 0 {
|
2019-10-07 21:10:41 -04:00
|
|
|
n++
|
|
|
|
|
}
|
|
|
|
|
if s.Func.dwarfDebugLinesSym != nil {
|
|
|
|
|
n++
|
|
|
|
|
}
|
2019-08-22 17:26:41 -04:00
|
|
|
}
|
2019-10-07 21:10:41 -04:00
|
|
|
return n
|
2019-08-22 17:26:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// generate symbols for FuncInfo.
|
|
|
|
|
func genFuncInfoSyms(ctxt *Link) {
|
|
|
|
|
infosyms := make([]*LSym, 0, len(ctxt.Text))
|
|
|
|
|
var pcdataoff uint32
|
|
|
|
|
var b bytes.Buffer
|
|
|
|
|
symidx := int32(len(ctxt.defs))
|
|
|
|
|
for _, s := range ctxt.Text {
|
|
|
|
|
if s.Func == nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
o := goobj2.FuncInfo{
|
2020-02-17 01:27:11 -05:00
|
|
|
Args: uint32(s.Func.Args),
|
|
|
|
|
Locals: uint32(s.Func.Locals),
|
2019-08-22 17:26:41 -04:00
|
|
|
}
|
|
|
|
|
pc := &s.Func.Pcln
|
|
|
|
|
o.Pcsp = pcdataoff
|
|
|
|
|
pcdataoff += uint32(len(pc.Pcsp.P))
|
|
|
|
|
o.Pcfile = pcdataoff
|
|
|
|
|
pcdataoff += uint32(len(pc.Pcfile.P))
|
|
|
|
|
o.Pcline = pcdataoff
|
|
|
|
|
pcdataoff += uint32(len(pc.Pcline.P))
|
|
|
|
|
o.Pcinline = pcdataoff
|
|
|
|
|
pcdataoff += uint32(len(pc.Pcinline.P))
|
|
|
|
|
o.Pcdata = make([]uint32, len(pc.Pcdata))
|
|
|
|
|
for i, pcd := range pc.Pcdata {
|
|
|
|
|
o.Pcdata[i] = pcdataoff
|
|
|
|
|
pcdataoff += uint32(len(pcd.P))
|
|
|
|
|
}
|
|
|
|
|
o.PcdataEnd = pcdataoff
|
|
|
|
|
o.Funcdataoff = make([]uint32, len(pc.Funcdataoff))
|
|
|
|
|
for i, x := range pc.Funcdataoff {
|
|
|
|
|
o.Funcdataoff[i] = uint32(x)
|
|
|
|
|
}
|
|
|
|
|
o.File = make([]goobj2.SymRef, len(pc.File))
|
|
|
|
|
for i, f := range pc.File {
|
|
|
|
|
fsym := ctxt.Lookup(f)
|
|
|
|
|
o.File[i] = makeSymRef(fsym)
|
|
|
|
|
}
|
2019-10-08 17:22:20 -04:00
|
|
|
o.InlTree = make([]goobj2.InlTreeNode, len(pc.InlTree.nodes))
|
|
|
|
|
for i, inl := range pc.InlTree.nodes {
|
|
|
|
|
f, l := linkgetlineFromPos(ctxt, inl.Pos)
|
|
|
|
|
fsym := ctxt.Lookup(f)
|
|
|
|
|
o.InlTree[i] = goobj2.InlTreeNode{
|
|
|
|
|
Parent: int32(inl.Parent),
|
|
|
|
|
File: makeSymRef(fsym),
|
|
|
|
|
Line: l,
|
|
|
|
|
Func: makeSymRef(inl.Func),
|
|
|
|
|
ParentPC: inl.ParentPC,
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-08-22 17:26:41 -04:00
|
|
|
|
|
|
|
|
o.Write(&b)
|
|
|
|
|
isym := &LSym{
|
|
|
|
|
Type: objabi.SDATA, // for now, I don't think it matters
|
|
|
|
|
PkgIdx: goobj2.PkgIdxSelf,
|
|
|
|
|
SymIdx: symidx,
|
|
|
|
|
P: append([]byte(nil), b.Bytes()...),
|
|
|
|
|
}
|
|
|
|
|
isym.Set(AttrIndexed, true)
|
|
|
|
|
symidx++
|
|
|
|
|
infosyms = append(infosyms, isym)
|
|
|
|
|
s.Func.FuncInfoSym = isym
|
|
|
|
|
b.Reset()
|
[dev.link] cmd/link: demote dwarf {range,loc} sub-symbols to aux
When the compiler emits DWARF for a function F, in addition to the
text symbol for F, it emits a set of sibling or child symbols that
carry the various DWARF bits for F (for example, go.info.F,
go.ranges.F, go.loc.F, and so on).
Prior to the linker modernization work, name lookup was the way you
made your way from a function symbol to one of its child DWARF
symbols. We now have a new mechanism (aux symbols), so there is really
no need for the DWARF sub-symbols to be named or to be dupok.
This patch converts DWARF "range" and "loc" sub-symbols to be pure aux
syms: unnamed, and connected to their parent text symbol only via aux
data. This should presumably have performance benefits in that we add
fewer symbols to the linker lookup tables.
Other related DWARF sub-symbols (ex: go.line.*) will be handled in a
subsequent patch.
Change-Id: Iae3ec2d42452962d4afc1df4a1bd89ccdeadc6e4
Reviewed-on: https://go-review.googlesource.com/c/go/+/222673
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2020-03-09 11:42:03 -04:00
|
|
|
|
|
|
|
|
dwsyms := []*LSym{s.Func.dwarfRangesSym, s.Func.dwarfLocSym}
|
|
|
|
|
for _, s := range dwsyms {
|
|
|
|
|
if s == nil || s.Size == 0 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
s.PkgIdx = goobj2.PkgIdxSelf
|
|
|
|
|
s.SymIdx = symidx
|
|
|
|
|
s.Set(AttrIndexed, true)
|
|
|
|
|
symidx++
|
|
|
|
|
infosyms = append(infosyms, s)
|
|
|
|
|
}
|
2019-08-22 17:26:41 -04:00
|
|
|
}
|
|
|
|
|
ctxt.defs = append(ctxt.defs, infosyms...)
|
|
|
|
|
}
|