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
|
|
|
|
|
|
|
|
// Set up DWARF entry for s.
|
|
|
|
|
dsym := ctxt.dwarfSym(s)
|
2017-04-18 12:53:25 -07:00
|
|
|
dsym.Type = objabi.SDWARFINFO
|
2017-04-13 05:57:59 -07:00
|
|
|
dsym.Set(AttrDuplicateOK, s.DuplicateOK())
|
|
|
|
|
ctxt.Data = append(ctxt.Data, dsym)
|
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
|
|
|
}
|
|
|
|
|
}
|