2016-04-11 17:35:55 +03:00
|
|
|
// Copyright 2013 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.
|
|
|
|
|
|
|
|
|
|
package obj
|
|
|
|
|
|
|
|
|
|
import (
|
2017-04-18 12:53:25 -07:00
|
|
|
"cmd/internal/objabi"
|
2016-04-11 17:35:55 +03:00
|
|
|
"fmt"
|
|
|
|
|
"strings"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Plist struct {
|
|
|
|
|
Firstpc *Prog
|
2017-03-23 16:39:04 -07:00
|
|
|
Curfn interface{} // holds a *gc.Node, if non-nil
|
2016-04-11 17:35:55 +03:00
|
|
|
}
|
|
|
|
|
|
2017-04-04 14:31:55 -07:00
|
|
|
// ProgAlloc is a function that allocates Progs.
|
|
|
|
|
// It is used to provide access to cached/bulk-allocated Progs to the assemblers.
|
|
|
|
|
type ProgAlloc func() *Prog
|
|
|
|
|
|
2017-04-05 07:05:35 -07:00
|
|
|
func Flushplist(ctxt *Link, plist *Plist, newprog ProgAlloc) {
|
2016-04-11 17:35:55 +03:00
|
|
|
// Build list of symbols, and assign instructions to lists.
|
|
|
|
|
var curtext *LSym
|
|
|
|
|
var etext *Prog
|
|
|
|
|
var text []*LSym
|
|
|
|
|
|
2017-02-17 16:52:16 -05:00
|
|
|
var plink *Prog
|
|
|
|
|
for p := plist.Firstpc; p != nil; p = plink {
|
2017-03-20 15:01:20 -07:00
|
|
|
if ctxt.Debugasm && ctxt.Debugvlog {
|
2017-02-17 16:52:16 -05:00
|
|
|
fmt.Printf("obj: %v\n", p)
|
|
|
|
|
}
|
|
|
|
|
plink = p.Link
|
|
|
|
|
p.Link = nil
|
2016-04-11 17:35:55 +03:00
|
|
|
|
2017-02-17 16:52:16 -05:00
|
|
|
switch p.As {
|
|
|
|
|
case AEND:
|
|
|
|
|
continue
|
2016-04-11 17:35:55 +03:00
|
|
|
|
2017-02-17 16:52:16 -05:00
|
|
|
case ATEXT:
|
|
|
|
|
s := p.From.Sym
|
|
|
|
|
if s == nil {
|
|
|
|
|
// func _() { }
|
|
|
|
|
curtext = nil
|
2016-04-11 17:35:55 +03:00
|
|
|
continue
|
2017-02-17 16:52:16 -05:00
|
|
|
}
|
|
|
|
|
text = append(text, s)
|
|
|
|
|
etext = p
|
|
|
|
|
curtext = s
|
|
|
|
|
continue
|
2016-04-11 17:35:55 +03:00
|
|
|
|
2017-02-17 16:52:16 -05:00
|
|
|
case AFUNCDATA:
|
|
|
|
|
// Rewrite reference to go_args_stackmap(SB) to the Go-provided declaration information.
|
|
|
|
|
if curtext == nil { // func _() {}
|
2016-04-11 17:35:55 +03:00
|
|
|
continue
|
|
|
|
|
}
|
2017-02-17 16:52:16 -05:00
|
|
|
if p.To.Sym.Name == "go_args_stackmap" {
|
2017-04-18 12:53:25 -07:00
|
|
|
if p.From.Type != TYPE_CONST || p.From.Offset != objabi.FUNCDATA_ArgsPointerMaps {
|
2017-02-17 16:52:16 -05:00
|
|
|
ctxt.Diag("FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps")
|
|
|
|
|
}
|
2017-04-20 07:13:02 -07:00
|
|
|
p.To.Sym = ctxt.LookupDerived(curtext, curtext.Name+".args_stackmap")
|
2017-02-17 16:52:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if curtext == nil {
|
|
|
|
|
etext = nil
|
|
|
|
|
continue
|
2016-04-11 17:35:55 +03:00
|
|
|
}
|
2017-02-17 16:52:16 -05:00
|
|
|
etext.Link = p
|
|
|
|
|
etext = p
|
2016-04-11 17:35:55 +03:00
|
|
|
}
|
|
|
|
|
|
2017-04-05 07:05:35 -07:00
|
|
|
if newprog == nil {
|
|
|
|
|
newprog = ctxt.NewProg
|
|
|
|
|
}
|
2017-04-04 14:31:55 -07:00
|
|
|
|
2016-04-11 17:35:55 +03:00
|
|
|
// Add reference to Go arguments for C or assembly functions without them.
|
|
|
|
|
for _, s := range text {
|
|
|
|
|
if !strings.HasPrefix(s.Name, "\"\".") {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
found := false
|
2017-04-18 10:18:34 -07:00
|
|
|
for p := s.Func.Text; p != nil; p = p.Link {
|
2017-04-18 12:53:25 -07:00
|
|
|
if p.As == AFUNCDATA && p.From.Type == TYPE_CONST && p.From.Offset == objabi.FUNCDATA_ArgsPointerMaps {
|
2016-04-11 17:35:55 +03:00
|
|
|
found = true
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !found {
|
2017-04-18 10:18:34 -07:00
|
|
|
p := Appendp(s.Func.Text, newprog)
|
2016-04-11 17:35:55 +03:00
|
|
|
p.As = AFUNCDATA
|
|
|
|
|
p.From.Type = TYPE_CONST
|
2017-04-18 12:53:25 -07:00
|
|
|
p.From.Offset = objabi.FUNCDATA_ArgsPointerMaps
|
2016-04-11 17:35:55 +03:00
|
|
|
p.To.Type = TYPE_MEM
|
|
|
|
|
p.To.Name = NAME_EXTERN
|
2017-04-20 07:13:02 -07:00
|
|
|
p.To.Sym = ctxt.LookupDerived(s, s.Name+".args_stackmap")
|
2016-04-11 17:35:55 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Turn functions into machine code images.
|
|
|
|
|
for _, s := range text {
|
|
|
|
|
mkfwd(s)
|
2017-04-04 14:31:55 -07:00
|
|
|
linkpatch(ctxt, s, newprog)
|
|
|
|
|
ctxt.Arch.Preprocess(ctxt, s, newprog)
|
|
|
|
|
ctxt.Arch.Assemble(ctxt, s, newprog)
|
2016-04-11 17:35:55 +03:00
|
|
|
linkpcln(ctxt, s)
|
2017-04-13 05:57:59 -07:00
|
|
|
ctxt.populateDWARF(plist.Curfn, s)
|
2016-04-11 17:35:55 +03:00
|
|
|
}
|
|
|
|
|
}
|
2016-09-16 15:31:04 -07:00
|
|
|
|
2017-04-12 13:23:07 -07:00
|
|
|
func (ctxt *Link) InitTextSym(s *LSym, flag int) {
|
2017-04-10 16:57:06 -07:00
|
|
|
if s == nil {
|
|
|
|
|
// func _() { }
|
|
|
|
|
return
|
|
|
|
|
}
|
2017-04-18 10:18:34 -07:00
|
|
|
if s.Func != nil {
|
2017-04-10 16:57:06 -07:00
|
|
|
ctxt.Diag("InitTextSym double init for %s", s.Name)
|
|
|
|
|
}
|
2017-04-18 10:18:34 -07:00
|
|
|
s.Func = new(FuncInfo)
|
|
|
|
|
if s.Func.Text != nil {
|
2017-04-10 16:57:06 -07:00
|
|
|
ctxt.Diag("duplicate TEXT for %s", s.Name)
|
|
|
|
|
}
|
|
|
|
|
if s.OnList() {
|
|
|
|
|
ctxt.Diag("symbol %s listed multiple times", s.Name)
|
|
|
|
|
}
|
|
|
|
|
s.Set(AttrOnList, true)
|
cmd/internal/obj: stop storing Text flags in From3
Prior to this CL, flags such as NOSPLIT
on ATEXT Progs were stored in From3.Offset.
Some but not all of those flags were also
duplicated into From.Sym.Attribute.
This CL migrates all of those flags into
From.Sym.Attribute and stops creating a From3.
A side-effect of this is that printing an
ATEXT Prog can no longer simply dump From3.Offset.
That's kind of good, since the raw flag value
wasn't very informative anyway, but it did
necessitate a bunch of updates to the cmd/asm tests.
The reason I'm doing this work now is that
avoiding storing flags in both From.Sym and From3.Offset
simplifies some other changes to fix the data
race first described in CL 40254.
This CL almost passes toolstash-check -all.
The only changes are in cases where the assembler
has decided that a function's flags may be altered,
e.g. to make a function with no calls in it NOSPLIT.
Prior to this CL, that information was not printed.
Sample before:
"".Ctz64 t=1 size=63 args=0x10 locals=0x0
0x0000 00000 (/Users/josh/go/tip/src/runtime/internal/sys/intrinsics.go:35) TEXT "".Ctz64(SB), $0-16
0x0000 00000 (/Users/josh/go/tip/src/runtime/internal/sys/intrinsics.go:35) FUNCDATA $0, gclocals·f207267fbf96a0178e8758c6e3e0ce28(SB)
Sample after:
"".Ctz64 t=1 nosplit size=63 args=0x10 locals=0x0
0x0000 00000 (/Users/josh/go/tip/src/runtime/internal/sys/intrinsics.go:35) TEXT "".Ctz64(SB), NOSPLIT, $0-16
0x0000 00000 (/Users/josh/go/tip/src/runtime/internal/sys/intrinsics.go:35) FUNCDATA $0, gclocals·f207267fbf96a0178e8758c6e3e0ce28(SB)
Observe the additional "nosplit" in the first line
and the additional "NOSPLIT" in the second line.
Updates #15756
Change-Id: I5c59bd8f3bdc7c780361f801d94a261f0aef3d13
Reviewed-on: https://go-review.googlesource.com/40495
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2017-04-11 15:15:04 -07:00
|
|
|
s.Set(AttrDuplicateOK, flag&DUPOK != 0)
|
|
|
|
|
s.Set(AttrNoSplit, flag&NOSPLIT != 0)
|
|
|
|
|
s.Set(AttrReflectMethod, flag&REFLECTMETHOD != 0)
|
|
|
|
|
s.Set(AttrWrapper, flag&WRAPPER != 0)
|
|
|
|
|
s.Set(AttrNeedCtxt, flag&NEEDCTXT != 0)
|
|
|
|
|
s.Set(AttrNoFrame, flag&NOFRAME != 0)
|
2017-04-18 12:53:25 -07:00
|
|
|
s.Type = objabi.STEXT
|
2017-04-12 17:43:30 -07:00
|
|
|
ctxt.Text = append(ctxt.Text, s)
|
2017-04-13 05:57:59 -07:00
|
|
|
|
2017-05-02 16:46:01 +02:00
|
|
|
// Set up DWARF entries for s.
|
[dev.debug] cmd/compile: better DWARF with optimizations on
Debuggers use DWARF information to find local variables on the
stack and in registers. Prior to this CL, the DWARF information for
functions claimed that all variables were on the stack at all times.
That's incorrect when optimizations are enabled, and results in
debuggers showing data that is out of date or complete gibberish.
After this CL, the compiler is capable of representing variable
locations more accurately, and attempts to do so. Due to limitations of
the SSA backend, it's not possible to be completely correct.
There are a number of problems in the current design. One of the easier
to understand is that variable names currently must be attached to an
SSA value, but not all assignments in the source code actually result
in machine code. For example:
type myint int
var a int
b := myint(int)
and
b := (*uint64)(unsafe.Pointer(a))
don't generate machine code because the underlying representation is the
same, so the correct value of b will not be set when the user would
expect.
Generating the more precise debug information is behind a flag,
dwarflocationlists. Because of the issues described above, setting the
flag may not make the debugging experience much better, and may actually
make it worse in cases where the variable actually is on the stack and
the more complicated analysis doesn't realize it.
A number of changes are included:
- Add a new pseudo-instruction, RegKill, which indicates that the value
in the register has been clobbered.
- Adjust regalloc to emit RegKills in the right places. Significantly,
this means that phis are mixed with StoreReg and RegKills after
regalloc.
- Track variable decomposition in ssa.LocalSlots.
- After the SSA backend is done, analyze the result and build location
lists for each LocalSlot.
- After assembly is done, update the location lists with the assembled
PC offsets, recompose variables, and build DWARF location lists. Emit the
list as a new linker symbol, one per function.
- In the linker, aggregate the location lists into a .debug_loc section.
TODO:
- currently disabled for non-X86/AMD64 because there are no data tables.
go build -toolexec 'toolstash -cmp' -a std succeeds.
With -dwarflocationlists false:
before: f02812195637909ff675782c0b46836a8ff01976
after: 06f61e8112a42ac34fb80e0c818b3cdb84a5e7ec
benchstat -geomean /tmp/220352263 /tmp/621364410
completed 15 of 15, estimated time remaining 0s (eta 3:52PM)
name old time/op new time/op delta
Template 199ms ± 3% 198ms ± 2% ~ (p=0.400 n=15+14)
Unicode 96.6ms ± 5% 96.4ms ± 5% ~ (p=0.838 n=15+15)
GoTypes 653ms ± 2% 647ms ± 2% ~ (p=0.102 n=15+14)
Flate 133ms ± 6% 129ms ± 3% -2.62% (p=0.041 n=15+15)
GoParser 164ms ± 5% 159ms ± 3% -3.05% (p=0.000 n=15+15)
Reflect 428ms ± 4% 422ms ± 3% ~ (p=0.156 n=15+13)
Tar 123ms ±10% 124ms ± 8% ~ (p=0.461 n=15+15)
XML 228ms ± 3% 224ms ± 3% -1.57% (p=0.045 n=15+15)
[Geo mean] 206ms 377ms +82.86%
name old user-time/op new user-time/op delta
Template 292ms ±10% 301ms ±12% ~ (p=0.189 n=15+15)
Unicode 166ms ±37% 158ms ±14% ~ (p=0.418 n=15+14)
GoTypes 962ms ± 6% 963ms ± 7% ~ (p=0.976 n=15+15)
Flate 207ms ±19% 200ms ±14% ~ (p=0.345 n=14+15)
GoParser 246ms ±22% 240ms ±15% ~ (p=0.587 n=15+15)
Reflect 611ms ±13% 587ms ±14% ~ (p=0.085 n=15+13)
Tar 211ms ±12% 217ms ±14% ~ (p=0.355 n=14+15)
XML 335ms ±15% 320ms ±18% ~ (p=0.169 n=15+15)
[Geo mean] 317ms 583ms +83.72%
name old alloc/op new alloc/op delta
Template 40.2MB ± 0% 40.2MB ± 0% -0.15% (p=0.000 n=14+15)
Unicode 29.2MB ± 0% 29.3MB ± 0% ~ (p=0.624 n=15+15)
GoTypes 114MB ± 0% 114MB ± 0% -0.15% (p=0.000 n=15+14)
Flate 25.7MB ± 0% 25.6MB ± 0% -0.18% (p=0.000 n=13+15)
GoParser 32.2MB ± 0% 32.2MB ± 0% -0.14% (p=0.003 n=15+15)
Reflect 77.8MB ± 0% 77.9MB ± 0% ~ (p=0.061 n=15+15)
Tar 27.1MB ± 0% 27.0MB ± 0% -0.11% (p=0.029 n=15+15)
XML 42.7MB ± 0% 42.5MB ± 0% -0.29% (p=0.000 n=15+15)
[Geo mean] 42.1MB 75.0MB +78.05%
name old allocs/op new allocs/op delta
Template 402k ± 1% 398k ± 0% -0.91% (p=0.000 n=15+15)
Unicode 344k ± 1% 344k ± 0% ~ (p=0.715 n=15+14)
GoTypes 1.18M ± 0% 1.17M ± 0% -0.91% (p=0.000 n=15+14)
Flate 243k ± 0% 240k ± 1% -1.05% (p=0.000 n=13+15)
GoParser 327k ± 1% 324k ± 1% -0.96% (p=0.000 n=15+15)
Reflect 984k ± 1% 982k ± 0% ~ (p=0.050 n=15+15)
Tar 261k ± 1% 259k ± 1% -0.77% (p=0.000 n=15+15)
XML 411k ± 0% 404k ± 1% -1.55% (p=0.000 n=15+15)
[Geo mean] 439k 755k +72.01%
name old text-bytes new text-bytes delta
HelloSize 694kB ± 0% 694kB ± 0% -0.00% (p=0.000 n=15+15)
name old data-bytes new data-bytes delta
HelloSize 5.55kB ± 0% 5.55kB ± 0% ~ (all equal)
name old bss-bytes new bss-bytes delta
HelloSize 133kB ± 0% 133kB ± 0% ~ (all equal)
name old exe-bytes new exe-bytes delta
HelloSize 1.04MB ± 0% 1.04MB ± 0% ~ (all equal)
Change-Id: I991fc553ef175db46bb23b2128317bbd48de70d8
Reviewed-on: https://go-review.googlesource.com/41770
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
2017-07-21 18:30:19 -04:00
|
|
|
info, loc, ranges := ctxt.dwarfSym(s)
|
|
|
|
|
info.Type = objabi.SDWARFINFO
|
|
|
|
|
info.Set(AttrDuplicateOK, s.DuplicateOK())
|
|
|
|
|
if loc != nil {
|
|
|
|
|
loc.Type = objabi.SDWARFLOC
|
|
|
|
|
loc.Set(AttrDuplicateOK, s.DuplicateOK())
|
|
|
|
|
ctxt.Data = append(ctxt.Data, loc)
|
|
|
|
|
}
|
|
|
|
|
ranges.Type = objabi.SDWARFRANGE
|
|
|
|
|
ranges.Set(AttrDuplicateOK, s.DuplicateOK())
|
|
|
|
|
ctxt.Data = append(ctxt.Data, info, ranges)
|
2017-04-14 06:35:53 -07:00
|
|
|
|
|
|
|
|
// Set up the function's gcargs and gclocals.
|
|
|
|
|
// They will be filled in later if needed.
|
2017-04-18 10:18:34 -07:00
|
|
|
gcargs := &s.Func.GCArgs
|
2017-04-14 06:35:53 -07:00
|
|
|
gcargs.Set(AttrDuplicateOK, true)
|
2017-04-18 12:53:25 -07:00
|
|
|
gcargs.Type = objabi.SRODATA
|
2017-04-18 10:18:34 -07:00
|
|
|
gclocals := &s.Func.GCLocals
|
2017-04-14 06:35:53 -07:00
|
|
|
gclocals.Set(AttrDuplicateOK, true)
|
2017-04-18 12:53:25 -07:00
|
|
|
gclocals.Type = objabi.SRODATA
|
2017-04-10 16:57:06 -07:00
|
|
|
}
|
|
|
|
|
|
2016-09-16 15:31:04 -07:00
|
|
|
func (ctxt *Link) Globl(s *LSym, size int64, flag int) {
|
2016-10-24 23:15:41 +03:00
|
|
|
if s.SeenGlobl() {
|
2016-09-16 15:31:04 -07:00
|
|
|
fmt.Printf("duplicate %v\n", s)
|
|
|
|
|
}
|
2016-10-24 23:15:41 +03:00
|
|
|
s.Set(AttrSeenGlobl, true)
|
|
|
|
|
if s.OnList() {
|
2017-04-10 16:57:06 -07:00
|
|
|
ctxt.Diag("symbol %s listed multiple times", s.Name)
|
2016-09-16 15:31:04 -07:00
|
|
|
}
|
2016-10-24 23:15:41 +03:00
|
|
|
s.Set(AttrOnList, true)
|
2016-09-16 15:31:04 -07:00
|
|
|
ctxt.Data = append(ctxt.Data, s)
|
|
|
|
|
s.Size = size
|
2017-04-19 15:30:08 +12:00
|
|
|
if s.Type == 0 {
|
2017-04-18 12:53:25 -07:00
|
|
|
s.Type = objabi.SBSS
|
2016-09-16 15:31:04 -07:00
|
|
|
}
|
|
|
|
|
if flag&DUPOK != 0 {
|
2016-10-24 23:15:41 +03:00
|
|
|
s.Set(AttrDuplicateOK, true)
|
2016-09-16 15:31:04 -07:00
|
|
|
}
|
|
|
|
|
if flag&RODATA != 0 {
|
2017-04-18 12:53:25 -07:00
|
|
|
s.Type = objabi.SRODATA
|
2016-09-16 15:31:04 -07:00
|
|
|
} else if flag&NOPTR != 0 {
|
cmd/internal/obj: fix LSym.Type during compilation, not linking
Prior to this CL, the compiler and assembler
were sloppy about the LSym.Type for LSyms
containing static data.
The linker then fixed this up, converting
Sxxx and SBSS to SDATA, and SNOPTRBSS to SNOPTRDATA
if it noticed that the symbol had associated data.
It is preferable to just get this right in cmd/compile
and cmd/asm, because it removes an unnecessary traversal
of the symbol table from the linker (see #14624).
Do this by touching up the LSym.Type fixes in
LSym.prepwrite and Link.Globl.
I have confirmed by instrumenting the linker
that the now-eliminated code paths were unreached.
And an additional check in the object file writing code
will help preserve that invariant.
There was a case in the Windows linker,
with internal linking and cgo,
where we were generating SNOPTRBSS symbols with data.
For now, convert those at the site at which they occur
into SNOPTRDATA, just like they were.
Does not pass toolstash-check,
but does generate identical linked binaries.
No compiler performance changes.
Change-Id: I77b071ab103685ff8e042cee9abb864385488872
Reviewed-on: https://go-review.googlesource.com/40864
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Reviewed-by: Michael Hudson-Doyle <michael.hudson@canonical.com>
2017-04-16 08:22:44 -07:00
|
|
|
if s.Type == objabi.SDATA {
|
|
|
|
|
s.Type = objabi.SNOPTRDATA
|
|
|
|
|
} else {
|
|
|
|
|
s.Type = objabi.SNOPTRBSS
|
|
|
|
|
}
|
2016-09-16 15:31:04 -07:00
|
|
|
} else if flag&TLSBSS != 0 {
|
2017-04-18 12:53:25 -07:00
|
|
|
s.Type = objabi.STLSBSS
|
2016-09-16 15:31:04 -07:00
|
|
|
}
|
|
|
|
|
}
|