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.
|
2020-05-01 19:13:30 -04:00
|
|
|
func WriteObjFile(ctxt *Link, b *bio.Writer, pkgpath string) {
|
2020-03-11 11:18:00 -04:00
|
|
|
|
|
|
|
|
debugAsmEmit(ctxt)
|
2019-10-08 21:43:20 -04:00
|
|
|
|
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
|
|
|
|
|
}
|
2020-05-18 18:20:18 -04:00
|
|
|
if pkgpath == "" {
|
|
|
|
|
flags |= goobj2.ObjFlagNeedNameExpansion
|
|
|
|
|
}
|
[dev.link] cmd/internal/goobj2: add index fingerprint to object file
The new object files use indices for symbol references, instead
of names. Fundamental to the design, it requires that the
importing and imported packages have consistent view of symbol
indices. The Go command should already ensure this, when using
"go build". But in case it goes wrong, it could lead to obscure
errors like run-time crashes. It would be better to check the
index consistency at build time.
To do that, we add a fingerprint to each object file, which is
a hash of symbol indices. In the object file it records the
fingerprints of all imported packages, as well as its own
fingerprint. At link time, the linker checks that a package's
fingerprint matches the fingerprint recorded in the importing
packages, and issue an error if they don't match.
This CL does the first part: introducing the fingerprint in the
object file, and propagating fingerprints through
importing/exporting by the compiler. It is not yet used by the
linker. Next CL will do.
Change-Id: I0aa372da652e4afb11f2867cb71689a3e3f9966e
Reviewed-on: https://go-review.googlesource.com/c/go/+/229617
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
2020-04-22 19:21:30 -04:00
|
|
|
h := goobj2.Header{
|
|
|
|
|
Magic: goobj2.Magic,
|
|
|
|
|
Fingerprint: ctxt.Fingerprint,
|
|
|
|
|
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()
|
[dev.link] cmd/internal/goobj2: add index fingerprint to object file
The new object files use indices for symbol references, instead
of names. Fundamental to the design, it requires that the
importing and imported packages have consistent view of symbol
indices. The Go command should already ensure this, when using
"go build". But in case it goes wrong, it could lead to obscure
errors like run-time crashes. It would be better to check the
index consistency at build time.
To do that, we add a fingerprint to each object file, which is
a hash of symbol indices. In the object file it records the
fingerprints of all imported packages, as well as its own
fingerprint. At link time, the linker checks that a package's
fingerprint matches the fingerprint recorded in the importing
packages, and issue an error if they don't match.
This CL does the first part: introducing the fingerprint in the
object file, and propagating fingerprints through
importing/exporting by the compiler. It is not yet used by the
linker. Next CL will do.
Change-Id: I0aa372da652e4afb11f2867cb71689a3e3f9966e
Reviewed-on: https://go-review.googlesource.com/c/go/+/229617
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
2020-04-22 19:21:30 -04:00
|
|
|
for i := range ctxt.Imports {
|
|
|
|
|
ctxt.Imports[i].Write(w.Writer)
|
2019-10-09 10:22:02 -04:00
|
|
|
}
|
|
|
|
|
|
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("")
|
[dev.link] cmd/internal/goobj2: add index fingerprint to object file
The new object files use indices for symbol references, instead
of names. Fundamental to the design, it requires that the
importing and imported packages have consistent view of symbol
indices. The Go command should already ensure this, when using
"go build". But in case it goes wrong, it could lead to obscure
errors like run-time crashes. It would be better to check the
index consistency at build time.
To do that, we add a fingerprint to each object file, which is
a hash of symbol indices. In the object file it records the
fingerprints of all imported packages, as well as its own
fingerprint. At link time, the linker checks that a package's
fingerprint matches the fingerprint recorded in the importing
packages, and issue an error if they don't match.
This CL does the first part: introducing the fingerprint in the
object file, and propagating fingerprints through
importing/exporting by the compiler. It is not yet used by the
linker. Next CL will do.
Change-Id: I0aa372da652e4afb11f2867cb71689a3e3f9966e
Reviewed-on: https://go-review.googlesource.com/c/go/+/229617
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
2020-04-22 19:21:30 -04:00
|
|
|
for _, p := range w.ctxt.Imports {
|
|
|
|
|
w.AddString(p.Pkg)
|
2019-08-22 17:26:41 -04:00
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
|
}
|
2020-04-02 12:48:13 -04:00
|
|
|
var align uint32
|
|
|
|
|
if s.Func != nil {
|
|
|
|
|
align = uint32(s.Func.Align)
|
|
|
|
|
}
|
2020-04-09 20:45:14 -04:00
|
|
|
var o goobj2.Sym
|
2020-04-08 13:24:27 -04:00
|
|
|
o.SetName(name, w.Writer)
|
|
|
|
|
o.SetABI(abi)
|
|
|
|
|
o.SetType(uint8(s.Type))
|
|
|
|
|
o.SetFlag(flag)
|
|
|
|
|
o.SetSiz(uint32(s.Size))
|
|
|
|
|
o.SetAlign(align)
|
2019-08-22 17:26:41 -04:00
|
|
|
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) {
|
2020-04-09 20:45:14 -04:00
|
|
|
var o goobj2.Reloc
|
2020-04-08 13:24:27 -04:00
|
|
|
o.SetOff(r.Off)
|
|
|
|
|
o.SetSiz(r.Siz)
|
|
|
|
|
o.SetType(uint8(r.Type))
|
|
|
|
|
o.SetAdd(r.Add)
|
|
|
|
|
o.SetSym(makeSymRef(r.Sym))
|
|
|
|
|
o.Write(w.Writer)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (w *writer) aux1(typ uint8, rs *LSym) {
|
2020-04-09 20:45:14 -04:00
|
|
|
var o goobj2.Aux
|
2020-04-08 13:24:27 -04:00
|
|
|
o.SetType(typ)
|
|
|
|
|
o.SetSym(makeSymRef(rs))
|
2019-08-22 17:26:41 -04:00
|
|
|
o.Write(w.Writer)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (w *writer) Aux(s *LSym) {
|
|
|
|
|
if s.Gotype != nil {
|
2020-04-08 13:24:27 -04:00
|
|
|
w.aux1(goobj2.AuxGotype, s.Gotype)
|
2019-08-22 17:26:41 -04:00
|
|
|
}
|
|
|
|
|
if s.Func != nil {
|
2020-04-08 13:24:27 -04:00
|
|
|
w.aux1(goobj2.AuxFuncInfo, s.Func.FuncInfoSym)
|
2019-08-22 17:26:41 -04:00
|
|
|
|
|
|
|
|
for _, d := range s.Func.Pcln.Funcdata {
|
2020-04-08 13:24:27 -04:00
|
|
|
w.aux1(goobj2.AuxFuncdata, d)
|
2019-08-22 17:26:41 -04:00
|
|
|
}
|
2019-10-07 21:10:41 -04:00
|
|
|
|
2020-03-16 08:13:16 -04:00
|
|
|
if s.Func.dwarfInfoSym != nil && s.Func.dwarfInfoSym.Size != 0 {
|
2020-04-08 13:24:27 -04:00
|
|
|
w.aux1(goobj2.AuxDwarfInfo, s.Func.dwarfInfoSym)
|
2019-10-07 21:10:41 -04:00
|
|
|
}
|
[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 {
|
2020-04-08 13:24:27 -04:00
|
|
|
w.aux1(goobj2.AuxDwarfLoc, s.Func.dwarfLocSym)
|
2019-10-07 21:10:41 -04:00
|
|
|
}
|
[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 {
|
2020-04-08 13:24:27 -04:00
|
|
|
w.aux1(goobj2.AuxDwarfRanges, s.Func.dwarfRangesSym)
|
2019-10-07 21:10:41 -04:00
|
|
|
}
|
2020-03-11 11:16:19 -04:00
|
|
|
if s.Func.dwarfDebugLinesSym != nil && s.Func.dwarfDebugLinesSym.Size != 0 {
|
2020-04-08 13:24:27 -04:00
|
|
|
w.aux1(goobj2.AuxDwarfLines, s.Func.dwarfDebugLinesSym)
|
2019-10-07 21:10:41 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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)
|
2020-03-16 08:13:16 -04:00
|
|
|
if s.Func.dwarfInfoSym != nil && s.Func.dwarfInfoSym.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.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++
|
|
|
|
|
}
|
2020-03-11 11:16:19 -04:00
|
|
|
if s.Func.dwarfDebugLinesSym != nil && s.Func.dwarfDebugLinesSym.Size != 0 {
|
2019-10-07 21:10:41 -04:00
|
|
|
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
|
|
|
|
2020-03-16 08:13:16 -04:00
|
|
|
dwsyms := []*LSym{s.Func.dwarfRangesSym, s.Func.dwarfLocSym, s.Func.dwarfDebugLinesSym, s.Func.dwarfInfoSym}
|
[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
|
|
|
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...)
|
|
|
|
|
}
|
2020-03-11 11:18:00 -04:00
|
|
|
|
|
|
|
|
// debugDumpAux is a dumper for selected aux symbols.
|
|
|
|
|
func writeAuxSymDebug(ctxt *Link, par *LSym, aux *LSym) {
|
|
|
|
|
// Most aux symbols (ex: funcdata) are not interesting--
|
|
|
|
|
// pick out just the DWARF ones for now.
|
|
|
|
|
if aux.Type != objabi.SDWARFLOC &&
|
2020-05-20 13:51:59 -04:00
|
|
|
aux.Type != objabi.SDWARFFCN &&
|
|
|
|
|
aux.Type != objabi.SDWARFABSFCN &&
|
2020-03-11 11:18:00 -04:00
|
|
|
aux.Type != objabi.SDWARFLINES &&
|
|
|
|
|
aux.Type != objabi.SDWARFRANGE {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
ctxt.writeSymDebugNamed(aux, "aux for "+par.Name)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func debugAsmEmit(ctxt *Link) {
|
|
|
|
|
if ctxt.Debugasm > 0 {
|
|
|
|
|
ctxt.traverseSyms(traverseDefs, ctxt.writeSymDebug)
|
|
|
|
|
if ctxt.Debugasm > 1 {
|
|
|
|
|
fn := func(par *LSym, aux *LSym) {
|
|
|
|
|
writeAuxSymDebug(ctxt, par, aux)
|
|
|
|
|
}
|
2020-03-16 15:24:48 -04:00
|
|
|
ctxt.traverseAuxSyms(traverseAux, fn)
|
2020-03-11 11:18:00 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|