Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
bababde7
Commit
bababde7
authored
Nov 08, 2019
by
Gerrit Code Review
Browse files
Options
Browse Files
Download
Plain Diff
Merge "cmd: merge branch 'dev.link' into master"
parents
7a5e0fec
bbae923d
Changes
50
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
50 changed files
with
4471 additions
and
336 deletions
+4471
-336
src/cmd/asm/internal/flags/flags.go
src/cmd/asm/internal/flags/flags.go
+1
-0
src/cmd/asm/main.go
src/cmd/asm/main.go
+5
-5
src/cmd/compile/internal/gc/iexport.go
src/cmd/compile/internal/gc/iexport.go
+19
-0
src/cmd/compile/internal/gc/iimport.go
src/cmd/compile/internal/gc/iimport.go
+17
-0
src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/gc/main.go
+6
-1
src/cmd/compile/internal/gc/obj.go
src/cmd/compile/internal/gc/obj.go
+18
-16
src/cmd/compile/internal/types/sym.go
src/cmd/compile/internal/types/sym.go
+9
-2
src/cmd/dist/buildtool.go
src/cmd/dist/buildtool.go
+2
-0
src/cmd/dist/test.go
src/cmd/dist/test.go
+1
-1
src/cmd/go/alldocs.go
src/cmd/go/alldocs.go
+2
-2
src/cmd/go/internal/work/build.go
src/cmd/go/internal/work/build.go
+2
-2
src/cmd/go/internal/work/init.go
src/cmd/go/internal/work/init.go
+1
-0
src/cmd/internal/dwarf/dwarf.go
src/cmd/internal/dwarf/dwarf.go
+7
-1
src/cmd/internal/goobj/read.go
src/cmd/internal/goobj/read.go
+8
-0
src/cmd/internal/goobj/readnew.go
src/cmd/internal/goobj/readnew.go
+187
-0
src/cmd/internal/goobj2/builtin.go
src/cmd/internal/goobj2/builtin.go
+45
-0
src/cmd/internal/goobj2/builtinlist.go
src/cmd/internal/goobj2/builtinlist.go
+194
-0
src/cmd/internal/goobj2/funcinfo.go
src/cmd/internal/goobj2/funcinfo.go
+147
-0
src/cmd/internal/goobj2/mkbuiltin.go
src/cmd/internal/goobj2/mkbuiltin.go
+124
-0
src/cmd/internal/goobj2/objfile.go
src/cmd/internal/goobj2/objfile.go
+587
-0
src/cmd/internal/obj/link.go
src/cmd/internal/obj/link.go
+23
-1
src/cmd/internal/obj/objfile.go
src/cmd/internal/obj/objfile.go
+10
-4
src/cmd/internal/obj/objfile2.go
src/cmd/internal/obj/objfile2.go
+429
-0
src/cmd/internal/obj/sizeof_test.go
src/cmd/internal/obj/sizeof_test.go
+1
-1
src/cmd/internal/obj/sym.go
src/cmd/internal/obj/sym.go
+176
-0
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/data.go
+3
-3
src/cmd/link/internal/ld/deadcode.go
src/cmd/link/internal/ld/deadcode.go
+66
-9
src/cmd/link/internal/ld/deadcode2.go
src/cmd/link/internal/ld/deadcode2.go
+441
-0
src/cmd/link/internal/ld/decodesym.go
src/cmd/link/internal/ld/decodesym.go
+28
-28
src/cmd/link/internal/ld/dwarf.go
src/cmd/link/internal/ld/dwarf.go
+7
-7
src/cmd/link/internal/ld/go.go
src/cmd/link/internal/ld/go.go
+38
-7
src/cmd/link/internal/ld/lib.go
src/cmd/link/internal/ld/lib.go
+358
-205
src/cmd/link/internal/ld/link.go
src/cmd/link/internal/ld/link.go
+13
-0
src/cmd/link/internal/ld/main.go
src/cmd/link/internal/ld/main.go
+7
-1
src/cmd/link/internal/ld/pcln.go
src/cmd/link/internal/ld/pcln.go
+2
-2
src/cmd/link/internal/ld/symtab.go
src/cmd/link/internal/ld/symtab.go
+1
-1
src/cmd/link/internal/ld/util.go
src/cmd/link/internal/ld/util.go
+7
-0
src/cmd/link/internal/loadelf/ldelf.go
src/cmd/link/internal/loadelf/ldelf.go
+24
-11
src/cmd/link/internal/loader/loader.go
src/cmd/link/internal/loader/loader.go
+1308
-0
src/cmd/link/internal/loadmacho/ldmacho.go
src/cmd/link/internal/loadmacho/ldmacho.go
+16
-5
src/cmd/link/internal/loadpe/ldpe.go
src/cmd/link/internal/loadpe/ldpe.go
+20
-10
src/cmd/link/internal/loadxcoff/ldxcoff.go
src/cmd/link/internal/loadxcoff/ldxcoff.go
+19
-6
src/cmd/link/internal/objfile/objfile.go
src/cmd/link/internal/objfile/objfile.go
+1
-1
src/cmd/link/internal/ppc64/asm.go
src/cmd/link/internal/ppc64/asm.go
+1
-1
src/cmd/link/internal/sym/symbol.go
src/cmd/link/internal/sym/symbol.go
+1
-1
src/cmd/link/internal/sym/symbols.go
src/cmd/link/internal/sym/symbols.go
+11
-0
src/cmd/link/internal/sym/symkind.go
src/cmd/link/internal/sym/symkind.go
+5
-0
src/cmd/link/link_test.go
src/cmd/link/link_test.go
+65
-0
src/runtime/internal/atomic/sys_linux_arm.s
src/runtime/internal/atomic/sys_linux_arm.s
+2
-2
test/linkx.go
test/linkx.go
+6
-0
No files found.
src/cmd/asm/internal/flags/flags.go
View file @
bababde7
...
...
@@ -23,6 +23,7 @@ var (
Dynlink
=
flag
.
Bool
(
"dynlink"
,
false
,
"support references to Go symbols defined in other shared libraries"
)
AllErrors
=
flag
.
Bool
(
"e"
,
false
,
"no limit on number of errors reported"
)
SymABIs
=
flag
.
Bool
(
"gensymabis"
,
false
,
"write symbol ABI information to output file, don't assemble"
)
Newobj
=
flag
.
Bool
(
"newobj"
,
false
,
"use new object file format"
)
)
var
(
...
...
src/cmd/asm/main.go
View file @
bababde7
...
...
@@ -40,18 +40,18 @@ func main() {
}
ctxt
.
Flag_dynlink
=
*
flags
.
Dynlink
ctxt
.
Flag_shared
=
*
flags
.
Shared
||
*
flags
.
Dynlink
ctxt
.
Flag_newobj
=
*
flags
.
Newobj
ctxt
.
Bso
=
bufio
.
NewWriter
(
os
.
Stdout
)
defer
ctxt
.
Bso
.
Flush
()
architecture
.
Init
(
ctxt
)
// Create object file, write header.
out
,
err
:=
os
.
Create
(
*
flags
.
OutputFile
)
buf
,
err
:=
bio
.
Create
(
*
flags
.
OutputFile
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
defer
bio
.
MustClose
(
out
)
buf
:=
bufio
.
NewWriter
(
bio
.
MustWriter
(
out
))
defer
buf
.
Close
()
if
!*
flags
.
SymABIs
{
fmt
.
Fprintf
(
buf
,
"go object %s %s %s
\n
"
,
objabi
.
GOOS
,
objabi
.
GOARCH
,
objabi
.
Version
)
...
...
@@ -83,6 +83,7 @@ func main() {
}
}
if
ok
&&
!*
flags
.
SymABIs
{
ctxt
.
NumberSyms
(
true
)
obj
.
WriteObjFile
(
ctxt
,
buf
,
""
)
}
if
!
ok
||
diag
{
...
...
@@ -91,9 +92,8 @@ func main() {
}
else
{
log
.
Print
(
"assembly failed"
)
}
out
.
Close
()
buf
.
Close
()
os
.
Remove
(
*
flags
.
OutputFile
)
os
.
Exit
(
1
)
}
buf
.
Flush
()
}
src/cmd/compile/internal/gc/iexport.go
View file @
bababde7
...
...
@@ -203,6 +203,7 @@ import (
"bufio"
"bytes"
"cmd/compile/internal/types"
"cmd/internal/goobj2"
"cmd/internal/src"
"encoding/binary"
"fmt"
...
...
@@ -945,10 +946,12 @@ func (w *exportWriter) string(s string) { w.uint64(w.p.stringOff(s)) }
func
(
w
*
exportWriter
)
varExt
(
n
*
Node
)
{
w
.
linkname
(
n
.
Sym
)
w
.
symIdx
(
n
.
Sym
)
}
func
(
w
*
exportWriter
)
funcExt
(
n
*
Node
)
{
w
.
linkname
(
n
.
Sym
)
w
.
symIdx
(
n
.
Sym
)
// Escape analysis.
for
_
,
fs
:=
range
types
.
RecvsParams
{
...
...
@@ -987,6 +990,22 @@ func (w *exportWriter) linkname(s *types.Sym) {
w
.
string
(
s
.
Linkname
)
}
func
(
w
*
exportWriter
)
symIdx
(
s
*
types
.
Sym
)
{
if
Ctxt
.
Flag_newobj
{
lsym
:=
s
.
Linksym
()
if
lsym
.
PkgIdx
>
goobj2
.
PkgIdxSelf
||
(
lsym
.
PkgIdx
==
goobj2
.
PkgIdxInvalid
&&
!
lsym
.
Indexed
())
||
s
.
Linkname
!=
""
{
// Don't export index for non-package symbols, linkname'd symbols,
// and symbols without an index. They can only be referenced by
// name.
w
.
int64
(
-
1
)
}
else
{
// For a defined symbol, export its index.
// For re-exporting an imported symbol, pass its index through.
w
.
int64
(
int64
(
lsym
.
SymIdx
))
}
}
}
// Inline bodies.
func
(
w
*
exportWriter
)
stmtList
(
list
Nodes
)
{
...
...
src/cmd/compile/internal/gc/iimport.go
View file @
bababde7
...
...
@@ -10,6 +10,7 @@ package gc
import
(
"cmd/compile/internal/types"
"cmd/internal/bio"
"cmd/internal/obj"
"cmd/internal/src"
"encoding/binary"
"fmt"
...
...
@@ -651,10 +652,12 @@ func (r *importReader) byte() byte {
func
(
r
*
importReader
)
varExt
(
n
*
Node
)
{
r
.
linkname
(
n
.
Sym
)
r
.
symIdx
(
n
.
Sym
)
}
func
(
r
*
importReader
)
funcExt
(
n
*
Node
)
{
r
.
linkname
(
n
.
Sym
)
r
.
symIdx
(
n
.
Sym
)
// Escape analysis.
for
_
,
fs
:=
range
types
.
RecvsParams
{
...
...
@@ -683,6 +686,20 @@ func (r *importReader) linkname(s *types.Sym) {
s
.
Linkname
=
r
.
string
()
}
func
(
r
*
importReader
)
symIdx
(
s
*
types
.
Sym
)
{
if
Ctxt
.
Flag_newobj
{
lsym
:=
s
.
Linksym
()
idx
:=
int32
(
r
.
int64
())
if
idx
!=
-
1
{
if
s
.
Linkname
!=
""
{
Fatalf
(
"bad index for linknamed symbol: %v %d
\n
"
,
lsym
,
idx
)
}
lsym
.
SymIdx
=
idx
lsym
.
Set
(
obj
.
AttrIndexed
,
true
)
}
}
}
func
(
r
*
importReader
)
doInline
(
n
*
Node
)
{
if
len
(
n
.
Func
.
Inl
.
Body
)
!=
0
{
Fatalf
(
"%v already has inline body"
,
n
)
...
...
src/cmd/compile/internal/gc/main.go
View file @
bababde7
...
...
@@ -260,6 +260,7 @@ func Main(archInit func(*Arch)) {
if
supportsDynlink
(
thearch
.
LinkArch
.
Arch
)
{
flag
.
BoolVar
(
&
flag_shared
,
"shared"
,
false
,
"generate code that can be linked into a shared library"
)
flag
.
BoolVar
(
&
flag_dynlink
,
"dynlink"
,
false
,
"support references to Go symbols defined in other shared libraries"
)
flag
.
BoolVar
(
&
Ctxt
.
Flag_linkshared
,
"linkshared"
,
false
,
"generate code that will be linked against Go shared libraries"
)
}
flag
.
StringVar
(
&
cpuprofile
,
"cpuprofile"
,
""
,
"write cpu profile to `file`"
)
flag
.
StringVar
(
&
memprofile
,
"memprofile"
,
""
,
"write memory profile to `file`"
)
...
...
@@ -274,12 +275,14 @@ func Main(archInit func(*Arch)) {
flag
.
StringVar
(
&
benchfile
,
"bench"
,
""
,
"append benchmark times to `file`"
)
flag
.
BoolVar
(
&
smallFrames
,
"smallframes"
,
false
,
"reduce the size limit for stack allocated objects"
)
flag
.
BoolVar
(
&
Ctxt
.
UseBASEntries
,
"dwarfbasentries"
,
Ctxt
.
UseBASEntries
,
"use base address selection entries in DWARF"
)
flag
.
BoolVar
(
&
Ctxt
.
Flag_newobj
,
"newobj"
,
false
,
"use new object file format"
)
objabi
.
Flagparse
(
usage
)
// Record flags that affect the build result. (And don't
// record flags that don't, since that would cause spurious
// changes in the binary.)
recordFlags
(
"B"
,
"N"
,
"l"
,
"msan"
,
"race"
,
"shared"
,
"dynlink"
,
"dwarflocationlists"
,
"dwarfbasentries"
,
"smallframes"
)
recordFlags
(
"B"
,
"N"
,
"l"
,
"msan"
,
"race"
,
"shared"
,
"dynlink"
,
"dwarflocationlists"
,
"dwarfbasentries"
,
"smallframes"
,
"newobj"
)
if
smallFrames
{
maxStackVarSize
=
128
*
1024
...
...
@@ -746,6 +749,8 @@ func Main(archInit func(*Arch)) {
// Write object data to disk.
timings
.
Start
(
"be"
,
"dumpobj"
)
dumpdata
()
Ctxt
.
NumberSyms
(
false
)
dumpobj
()
if
asmhdr
!=
""
{
dumpasmhdr
()
...
...
src/cmd/compile/internal/gc/obj.go
View file @
bababde7
...
...
@@ -111,21 +111,7 @@ func dumpCompilerObj(bout *bio.Writer) {
dumpexport
(
bout
)
}
func
dumpLinkerObj
(
bout
*
bio
.
Writer
)
{
printObjHeader
(
bout
)
if
len
(
pragcgobuf
)
!=
0
{
// write empty export section; must be before cgo section
fmt
.
Fprintf
(
bout
,
"
\n
$$
\n\n
$$
\n\n
"
)
fmt
.
Fprintf
(
bout
,
"
\n
$$ // cgo
\n
"
)
if
err
:=
json
.
NewEncoder
(
bout
)
.
Encode
(
pragcgobuf
);
err
!=
nil
{
Fatalf
(
"serializing pragcgobuf: %v"
,
err
)
}
fmt
.
Fprintf
(
bout
,
"
\n
$$
\n\n
"
)
}
fmt
.
Fprintf
(
bout
,
"
\n
!
\n
"
)
func
dumpdata
()
{
externs
:=
len
(
externdcl
)
dumpglobls
()
...
...
@@ -163,8 +149,24 @@ func dumpLinkerObj(bout *bio.Writer) {
}
addGCLocals
()
}
func
dumpLinkerObj
(
bout
*
bio
.
Writer
)
{
printObjHeader
(
bout
)
if
len
(
pragcgobuf
)
!=
0
{
// write empty export section; must be before cgo section
fmt
.
Fprintf
(
bout
,
"
\n
$$
\n\n
$$
\n\n
"
)
fmt
.
Fprintf
(
bout
,
"
\n
$$ // cgo
\n
"
)
if
err
:=
json
.
NewEncoder
(
bout
)
.
Encode
(
pragcgobuf
);
err
!=
nil
{
Fatalf
(
"serializing pragcgobuf: %v"
,
err
)
}
fmt
.
Fprintf
(
bout
,
"
\n
$$
\n\n
"
)
}
fmt
.
Fprintf
(
bout
,
"
\n
!
\n
"
)
obj
.
WriteObjFile
(
Ctxt
,
bout
.
Writer
,
myimportpath
)
obj
.
WriteObjFile
(
Ctxt
,
bout
,
myimportpath
)
}
func
addptabs
()
{
...
...
src/cmd/compile/internal/types/sym.go
View file @
bababde7
...
...
@@ -80,11 +80,18 @@ func (sym *Sym) Linksym() *obj.LSym {
if
sym
==
nil
{
return
nil
}
initPkg
:=
func
(
r
*
obj
.
LSym
)
{
if
sym
.
Linkname
!=
""
{
r
.
Pkg
=
"_"
}
else
{
r
.
Pkg
=
sym
.
Pkg
.
Prefix
}
}
if
sym
.
Func
()
{
// This is a function symbol. Mark it as "internal ABI".
return
Ctxt
.
LookupABI
(
sym
.
LinksymName
(),
obj
.
ABIInternal
)
return
Ctxt
.
LookupABI
Init
(
sym
.
LinksymName
(),
obj
.
ABIInternal
,
initPkg
)
}
return
Ctxt
.
Lookup
(
sym
.
LinksymName
()
)
return
Ctxt
.
Lookup
Init
(
sym
.
LinksymName
(),
initPkg
)
}
// Less reports whether symbol a is ordered before symbol b.
...
...
src/cmd/dist/buildtool.go
View file @
bababde7
...
...
@@ -54,6 +54,7 @@ var bootstrapDirs = []string{
"cmd/internal/gcprog"
,
"cmd/internal/dwarf"
,
"cmd/internal/edit"
,
"cmd/internal/goobj2"
,
"cmd/internal/objabi"
,
"cmd/internal/obj"
,
"cmd/internal/obj/arm"
,
...
...
@@ -72,6 +73,7 @@ var bootstrapDirs = []string{
"cmd/link/internal/arm64"
,
"cmd/link/internal/ld"
,
"cmd/link/internal/loadelf"
,
"cmd/link/internal/loader"
,
"cmd/link/internal/loadmacho"
,
"cmd/link/internal/loadpe"
,
"cmd/link/internal/loadxcoff"
,
...
...
src/cmd/dist/test.go
View file @
bababde7
...
...
@@ -585,7 +585,7 @@ func (t *tester) registerTests() {
},
})
// Also test a cgo package.
if
t
.
cgoEnabled
{
if
t
.
cgoEnabled
&&
t
.
internalLink
()
{
t
.
tests
=
append
(
t
.
tests
,
distTest
{
name
:
"pie_internal_cgo"
,
heading
:
"internal linking of -buildmode=pie"
,
...
...
src/cmd/go/alldocs.go
View file @
bababde7
...
...
@@ -145,8 +145,8 @@
// -ldflags '[pattern=]arg list'
// arguments to pass on each go tool link invocation.
// -linkshared
//
link against shared libraries previously created with
// -buildmode=shared.
//
build code that will be linked against shared libraries previously
//
created with
-buildmode=shared.
// -mod mode
// module download mode to use: readonly or vendor.
// See 'go help modules' for more.
...
...
src/cmd/go/internal/work/build.go
View file @
bababde7
...
...
@@ -97,8 +97,8 @@ and test commands:
-ldflags '[pattern=]arg list'
arguments to pass on each go tool link invocation.
-linkshared
link against shared libraries previously created with
-buildmode=shared.
build code that will be linked against shared libraries previously
created with
-buildmode=shared.
-mod mode
module download mode to use: readonly or vendor.
See 'go help modules' for more.
...
...
src/cmd/go/internal/work/init.go
View file @
bababde7
...
...
@@ -224,6 +224,7 @@ func buildModeInit() {
base
.
Fatalf
(
"-linkshared not supported on %s
\n
"
,
platform
)
}
codegenArg
=
"-dynlink"
forcedGcflags
=
append
(
forcedGcflags
,
"-linkshared"
)
// TODO(mwhudson): remove -w when that gets fixed in linker.
forcedLdflags
=
append
(
forcedLdflags
,
"-linkshared"
,
"-w"
)
}
...
...
src/cmd/internal/dwarf/dwarf.go
View file @
bababde7
...
...
@@ -1372,7 +1372,13 @@ func PutDefaultFunc(ctxt Context, s *FnState) error {
abbrev
:=
DW_ABRV_FUNCTION
Uleb128put
(
ctxt
,
s
.
Info
,
int64
(
abbrev
))
putattr
(
ctxt
,
s
.
Info
,
DW_ABRV_FUNCTION
,
DW_FORM_string
,
DW_CLS_STRING
,
int64
(
len
(
s
.
Name
)),
s
.
Name
)
// Expand '"".' to import path.
name
:=
s
.
Name
if
s
.
Importpath
!=
""
{
name
=
strings
.
Replace
(
name
,
"
\"\"
."
,
objabi
.
PathToPrefix
(
s
.
Importpath
)
+
"."
,
-
1
)
}
putattr
(
ctxt
,
s
.
Info
,
DW_ABRV_FUNCTION
,
DW_FORM_string
,
DW_CLS_STRING
,
int64
(
len
(
name
)),
name
)
putattr
(
ctxt
,
s
.
Info
,
abbrev
,
DW_FORM_addr
,
DW_CLS_ADDRESS
,
0
,
s
.
StartPC
)
putattr
(
ctxt
,
s
.
Info
,
abbrev
,
DW_FORM_addr
,
DW_CLS_ADDRESS
,
s
.
Size
,
s
.
StartPC
)
putattr
(
ctxt
,
s
.
Info
,
abbrev
,
DW_FORM_block1
,
DW_CLS_BLOCK
,
1
,
[]
byte
{
DW_OP_call_frame_cfa
})
...
...
src/cmd/internal/goobj/read.go
View file @
bababde7
...
...
@@ -502,6 +502,14 @@ func (r *objReader) parseObject(prefix []byte) error {
}
// TODO: extract OS + build ID if/when we need it
p
,
err
:=
r
.
peek
(
8
)
if
err
!=
nil
{
return
err
}
if
bytes
.
Equal
(
p
,
[]
byte
(
"
\x00
go114LD"
))
{
r
.
readNew
()
return
nil
}
r
.
readFull
(
r
.
tmp
[
:
8
])
if
!
bytes
.
Equal
(
r
.
tmp
[
:
8
],
[]
byte
(
"
\x00
go114ld"
))
{
return
r
.
error
(
errCorruptObject
)
...
...
src/cmd/internal/goobj/readnew.go
0 → 100644
View file @
bababde7
// 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.
package
goobj
import
(
"cmd/internal/goobj2"
"cmd/internal/objabi"
"fmt"
"strings"
)
// Read object file in new format. For now we still fill
// the data to the current goobj API.
func
(
r
*
objReader
)
readNew
()
{
start
:=
uint32
(
r
.
offset
)
length
:=
r
.
limit
-
r
.
offset
objbytes
:=
make
([]
byte
,
length
)
r
.
readFull
(
objbytes
)
rr
:=
goobj2
.
NewReaderFromBytes
(
objbytes
,
false
)
if
rr
==
nil
{
panic
(
"cannot read object file"
)
}
// Imports
r
.
p
.
Imports
=
rr
.
Autolib
()
pkglist
:=
rr
.
Pkglist
()
abiToVer
:=
func
(
abi
uint16
)
int64
{
var
vers
int64
if
abi
==
goobj2
.
SymABIstatic
{
// Static symbol
vers
=
r
.
p
.
MaxVersion
}
return
vers
}
resolveSymRef
:=
func
(
s
goobj2
.
SymRef
)
SymID
{
var
i
int
switch
p
:=
s
.
PkgIdx
;
p
{
case
goobj2
.
PkgIdxInvalid
:
if
s
.
SymIdx
!=
0
{
panic
(
"bad sym ref"
)
}
return
SymID
{}
case
goobj2
.
PkgIdxNone
:
i
=
int
(
s
.
SymIdx
)
+
rr
.
NSym
()
case
goobj2
.
PkgIdxBuiltin
:
name
,
abi
:=
goobj2
.
BuiltinName
(
int
(
s
.
SymIdx
))
return
SymID
{
name
,
int64
(
abi
)}
case
goobj2
.
PkgIdxSelf
:
i
=
int
(
s
.
SymIdx
)
default
:
pkg
:=
pkglist
[
p
]
return
SymID
{
fmt
.
Sprintf
(
"%s.<#%d>"
,
pkg
,
s
.
SymIdx
),
0
}
}
sym
:=
goobj2
.
Sym
{}
sym
.
Read
(
rr
,
rr
.
SymOff
(
i
))
return
SymID
{
sym
.
Name
,
abiToVer
(
sym
.
ABI
)}
}
// Read things for the current goobj API for now.
// Symbols
pcdataBase
:=
start
+
rr
.
PcdataBase
()
n
:=
rr
.
NSym
()
+
rr
.
NNonpkgdef
()
+
rr
.
NNonpkgref
()
ndef
:=
rr
.
NSym
()
+
rr
.
NNonpkgdef
()
for
i
:=
0
;
i
<
n
;
i
++
{
osym
:=
goobj2
.
Sym
{}
osym
.
Read
(
rr
,
rr
.
SymOff
(
i
))
if
osym
.
Name
==
""
{
continue
// not a real symbol
}
// In a symbol name in an object file, "". denotes the
// prefix for the package in which the object file has been found.
// Expand it.
name
:=
strings
.
ReplaceAll
(
osym
.
Name
,
`"".`
,
r
.
pkgprefix
)
symID
:=
SymID
{
Name
:
name
,
Version
:
abiToVer
(
osym
.
ABI
)}
r
.
p
.
SymRefs
=
append
(
r
.
p
.
SymRefs
,
symID
)
if
i
>=
ndef
{
continue
// not a defined symbol from here
}
// Symbol data
dataOff
:=
rr
.
DataOff
(
i
)
siz
:=
int64
(
rr
.
DataSize
(
i
))
sym
:=
Sym
{
SymID
:
symID
,
Kind
:
objabi
.
SymKind
(
osym
.
Type
),
DupOK
:
osym
.
Dupok
(),
Size
:
int64
(
osym
.
Siz
),
Data
:
Data
{
int64
(
start
+
dataOff
),
siz
},
}
r
.
p
.
Syms
=
append
(
r
.
p
.
Syms
,
&
sym
)
// Reloc
nreloc
:=
rr
.
NReloc
(
i
)
sym
.
Reloc
=
make
([]
Reloc
,
nreloc
)
for
j
:=
0
;
j
<
nreloc
;
j
++
{
rel
:=
goobj2
.
Reloc
{}
rel
.
Read
(
rr
,
rr
.
RelocOff
(
i
,
j
))
sym
.
Reloc
[
j
]
=
Reloc
{
Offset
:
int64
(
rel
.
Off
),
Size
:
int64
(
rel
.
Siz
),
Type
:
objabi
.
RelocType
(
rel
.
Type
),
Add
:
rel
.
Add
,
Sym
:
resolveSymRef
(
rel
.
Sym
),
}
}
// Aux symbol info
isym
:=
-
1
funcdata
:=
make
([]
goobj2
.
SymRef
,
0
,
4
)
naux
:=
rr
.
NAux
(
i
)
for
j
:=
0
;
j
<
naux
;
j
++
{
a
:=
goobj2
.
Aux
{}
a
.
Read
(
rr
,
rr
.
AuxOff
(
i
,
j
))
switch
a
.
Type
{
case
goobj2
.
AuxGotype
:
sym
.
Type
=
resolveSymRef
(
a
.
Sym
)
case
goobj2
.
AuxFuncInfo
:
if
a
.
Sym
.
PkgIdx
!=
goobj2
.
PkgIdxSelf
{
panic
(
"funcinfo symbol not defined in current package"
)
}
isym
=
int
(
a
.
Sym
.
SymIdx
)
case
goobj2
.
AuxFuncdata
:
funcdata
=
append
(
funcdata
,
a
.
Sym
)
case
goobj2
.
AuxDwarfInfo
,
goobj2
.
AuxDwarfLoc
,
goobj2
.
AuxDwarfRanges
,
goobj2
.
AuxDwarfLines
:
// nothing to do
default
:
panic
(
"unknown aux type"
)
}
}
// Symbol Info
if
isym
==
-
1
{
continue
}
b
:=
rr
.
BytesAt
(
rr
.
DataOff
(
isym
),
rr
.
DataSize
(
isym
))
info
:=
goobj2
.
FuncInfo
{}
info
.
Read
(
b
)
info
.
Pcdata
=
append
(
info
.
Pcdata
,
info
.
PcdataEnd
)
// for the ease of knowing where it ends
f
:=
&
Func
{
Args
:
int64
(
info
.
Args
),
Frame
:
int64
(
info
.
Locals
),
NoSplit
:
info
.
NoSplit
!=
0
,
Leaf
:
osym
.
Leaf
(),
TopFrame
:
osym
.
TopFrame
(),
PCSP
:
Data
{
int64
(
pcdataBase
+
info
.
Pcsp
),
int64
(
info
.
Pcfile
-
info
.
Pcsp
)},
PCFile
:
Data
{
int64
(
pcdataBase
+
info
.
Pcfile
),
int64
(
info
.
Pcline
-
info
.
Pcfile
)},
PCLine
:
Data
{
int64
(
pcdataBase
+
info
.
Pcline
),
int64
(
info
.
Pcinline
-
info
.
Pcline
)},
PCInline
:
Data
{
int64
(
pcdataBase
+
info
.
Pcinline
),
int64
(
info
.
Pcdata
[
0
]
-
info
.
Pcinline
)},
PCData
:
make
([]
Data
,
len
(
info
.
Pcdata
)
-
1
),
// -1 as we appended one above
FuncData
:
make
([]
FuncData
,
len
(
info
.
Funcdataoff
)),
File
:
make
([]
string
,
len
(
info
.
File
)),
InlTree
:
make
([]
InlinedCall
,
len
(
info
.
InlTree
)),
}
sym
.
Func
=
f
for
k
:=
range
f
.
PCData
{
f
.
PCData
[
k
]
=
Data
{
int64
(
pcdataBase
+
info
.
Pcdata
[
k
]),
int64
(
info
.
Pcdata
[
k
+
1
]
-
info
.
Pcdata
[
k
])}
}
for
k
:=
range
f
.
FuncData
{
symID
:=
resolveSymRef
(
funcdata
[
k
])
f
.
FuncData
[
k
]
=
FuncData
{
symID
,
int64
(
info
.
Funcdataoff
[
k
])}
}
for
k
:=
range
f
.
File
{
symID
:=
resolveSymRef
(
info
.
File
[
k
])
f
.
File
[
k
]
=
symID
.
Name
}
for
k
:=
range
f
.
InlTree
{
inl
:=
&
info
.
InlTree
[
k
]
f
.
InlTree
[
k
]
=
InlinedCall
{
Parent
:
int64
(
inl
.
Parent
),
File
:
resolveSymRef
(
inl
.
File
)
.
Name
,
Line
:
int64
(
inl
.
Line
),
Func
:
resolveSymRef
(
inl
.
Func
),
ParentPC
:
int64
(
inl
.
ParentPC
),
}
}
}
}
src/cmd/internal/goobj2/builtin.go
0 → 100644
View file @
bababde7
// 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.
package
goobj2
// Builtin (compiler-generated) function references appear
// frequently. We assign special indices for them, so they
// don't need to be referenced by name.
// NBuiltin returns the number of listed builtin
// symbols.
func
NBuiltin
()
int
{
return
len
(
builtins
)
}
// BuiltinName returns the name and ABI of the i-th
// builtin symbol.
func
BuiltinName
(
i
int
)
(
string
,
int
)
{
return
builtins
[
i
]
.
name
,
builtins
[
i
]
.
abi
}
// BuiltinIdx returns the index of the builtin with the
// given name and abi, or -1 if it is not a builtin.
func
BuiltinIdx
(
name
string
,
abi
int
)
int
{
i
,
ok
:=
builtinMap
[
name
]
if
!
ok
{
return
-
1
}
if
builtins
[
i
]
.
abi
!=
abi
{
return
-
1
}
return
i
}
//go:generate go run mkbuiltin.go
var
builtinMap
map
[
string
]
int
func
init
()
{
builtinMap
=
make
(
map
[
string
]
int
,
len
(
builtins
))
for
i
,
b
:=
range
builtins
{
builtinMap
[
b
.
name
]
=
i
}
}
src/cmd/internal/goobj2/builtinlist.go
0 → 100644
View file @
bababde7
// Code generated by mkbuiltin.go. DO NOT EDIT.
package
goobj2
var
builtins
=
[
...
]
struct
{
name
string
abi
int
}{
{
"runtime.newobject"
,
1
},
{
"runtime.panicdivide"
,
1
},
{
"runtime.panicshift"
,
1
},
{
"runtime.panicmakeslicelen"
,
1
},
{
"runtime.throwinit"
,
1
},
{
"runtime.panicwrap"
,
1
},
{
"runtime.gopanic"
,
1
},
{
"runtime.gorecover"
,
1
},
{
"runtime.goschedguarded"
,
1
},
{
"runtime.goPanicIndex"
,
1
},
{
"runtime.goPanicIndexU"
,
1
},
{
"runtime.goPanicSliceAlen"
,
1
},
{
"runtime.goPanicSliceAlenU"
,
1
},
{
"runtime.goPanicSliceAcap"
,
1
},
{
"runtime.goPanicSliceAcapU"
,
1
},
{
"runtime.goPanicSliceB"
,
1
},
{
"runtime.goPanicSliceBU"
,
1
},
{
"runtime.goPanicSlice3Alen"
,
1
},
{
"runtime.goPanicSlice3AlenU"
,
1
},
{
"runtime.goPanicSlice3Acap"
,
1
},
{
"runtime.goPanicSlice3AcapU"
,
1
},
{
"runtime.goPanicSlice3B"
,
1
},
{
"runtime.goPanicSlice3BU"
,
1
},
{
"runtime.goPanicSlice3C"
,
1
},
{
"runtime.goPanicSlice3CU"
,
1
},
{
"runtime.printbool"
,
1
},
{
"runtime.printfloat"
,
1
},
{
"runtime.printint"
,
1
},
{
"runtime.printhex"
,
1
},
{
"runtime.printuint"
,
1
},
{
"runtime.printcomplex"
,
1
},
{
"runtime.printstring"
,
1
},
{
"runtime.printpointer"
,
1
},
{
"runtime.printiface"
,
1
},
{
"runtime.printeface"
,
1
},
{
"runtime.printslice"
,
1
},
{
"runtime.printnl"
,
1
},
{
"runtime.printsp"
,
1
},
{
"runtime.printlock"
,
1
},
{
"runtime.printunlock"
,
1
},
{
"runtime.concatstring2"
,
1
},
{
"runtime.concatstring3"
,
1
},
{
"runtime.concatstring4"
,
1
},
{
"runtime.concatstring5"
,
1
},
{
"runtime.concatstrings"
,
1
},
{
"runtime.cmpstring"
,
1
},
{
"runtime.intstring"
,
1
},
{
"runtime.slicebytetostring"
,
1
},
{
"runtime.slicebytetostringtmp"
,
1
},
{
"runtime.slicerunetostring"
,
1
},
{
"runtime.stringtoslicebyte"
,
1
},
{
"runtime.stringtoslicerune"
,
1
},
{
"runtime.slicecopy"
,
1
},
{
"runtime.slicestringcopy"
,
1
},
{
"runtime.decoderune"
,
1
},
{
"runtime.countrunes"
,
1
},
{
"runtime.convI2I"
,
1
},
{
"runtime.convT16"
,
1
},
{
"runtime.convT32"
,
1
},
{
"runtime.convT64"
,
1
},
{
"runtime.convTstring"
,
1
},
{
"runtime.convTslice"
,
1
},
{
"runtime.convT2E"
,
1
},
{
"runtime.convT2Enoptr"
,
1
},
{
"runtime.convT2I"
,
1
},
{
"runtime.convT2Inoptr"
,
1
},
{
"runtime.assertE2I"
,
1
},
{
"runtime.assertE2I2"
,
1
},
{
"runtime.assertI2I"
,
1
},
{
"runtime.assertI2I2"
,
1
},
{
"runtime.panicdottypeE"
,
1
},
{
"runtime.panicdottypeI"
,
1
},
{
"runtime.panicnildottype"
,
1
},
{
"runtime.ifaceeq"
,
1
},
{
"runtime.efaceeq"
,
1
},
{
"runtime.fastrand"
,
1
},
{
"runtime.makemap64"
,
1
},
{
"runtime.makemap"
,
1
},
{
"runtime.makemap_small"
,
1
},
{
"runtime.mapaccess1"
,
1
},
{
"runtime.mapaccess1_fast32"
,
1
},
{
"runtime.mapaccess1_fast64"
,
1
},
{
"runtime.mapaccess1_faststr"
,
1
},
{
"runtime.mapaccess1_fat"
,
1
},
{
"runtime.mapaccess2"
,
1
},
{
"runtime.mapaccess2_fast32"
,
1
},
{
"runtime.mapaccess2_fast64"
,
1
},
{
"runtime.mapaccess2_faststr"
,
1
},
{
"runtime.mapaccess2_fat"
,
1
},
{
"runtime.mapassign"
,
1
},
{
"runtime.mapassign_fast32"
,
1
},
{
"runtime.mapassign_fast32ptr"
,
1
},
{
"runtime.mapassign_fast64"
,
1
},
{
"runtime.mapassign_fast64ptr"
,
1
},
{
"runtime.mapassign_faststr"
,
1
},
{
"runtime.mapiterinit"
,
1
},
{
"runtime.mapdelete"
,
1
},
{
"runtime.mapdelete_fast32"
,
1
},
{
"runtime.mapdelete_fast64"
,
1
},
{
"runtime.mapdelete_faststr"
,
1
},
{
"runtime.mapiternext"
,
1
},
{
"runtime.mapclear"
,
1
},
{
"runtime.makechan64"
,
1
},
{
"runtime.makechan"
,
1
},
{
"runtime.chanrecv1"
,
1
},
{
"runtime.chanrecv2"
,
1
},
{
"runtime.chansend1"
,
1
},
{
"runtime.closechan"
,
1
},
{
"runtime.writeBarrier"
,
0
},
{
"runtime.typedmemmove"
,
1
},
{
"runtime.typedmemclr"
,
1
},
{
"runtime.typedslicecopy"
,
1
},
{
"runtime.selectnbsend"
,
1
},
{
"runtime.selectnbrecv"
,
1
},
{
"runtime.selectnbrecv2"
,
1
},
{
"runtime.selectsetpc"
,
1
},
{
"runtime.selectgo"
,
1
},
{
"runtime.block"
,
1
},
{
"runtime.makeslice"
,
1
},
{
"runtime.makeslice64"
,
1
},
{
"runtime.growslice"
,
1
},
{
"runtime.memmove"
,
1
},
{
"runtime.memclrNoHeapPointers"
,
1
},
{
"runtime.memclrHasPointers"
,
1
},
{
"runtime.memequal"
,
1
},
{
"runtime.memequal0"
,
1
},
{
"runtime.memequal8"
,
1
},
{
"runtime.memequal16"
,
1
},
{
"runtime.memequal32"
,
1
},
{
"runtime.memequal64"
,
1
},
{
"runtime.memequal128"
,
1
},
{
"runtime.f32equal"
,
1
},
{
"runtime.f64equal"
,
1
},
{
"runtime.c64equal"
,
1
},
{
"runtime.c128equal"
,
1
},
{
"runtime.strequal"
,
1
},
{
"runtime.interequal"
,
1
},
{
"runtime.nilinterequal"
,
1
},
{
"runtime.memhash"
,
1
},
{
"runtime.memhash0"
,
1
},
{
"runtime.memhash8"
,
1
},
{
"runtime.memhash16"
,
1
},
{
"runtime.memhash32"
,
1
},
{
"runtime.memhash64"
,
1
},
{
"runtime.memhash128"
,
1
},
{
"runtime.f32hash"
,
1
},
{
"runtime.f64hash"
,
1
},
{
"runtime.c64hash"
,
1
},
{
"runtime.c128hash"
,
1
},
{
"runtime.strhash"
,
1
},
{
"runtime.interhash"
,
1
},
{
"runtime.nilinterhash"
,
1
},
{
"runtime.int64div"
,
1
},
{
"runtime.uint64div"
,
1
},
{
"runtime.int64mod"
,
1
},
{
"runtime.uint64mod"
,
1
},
{
"runtime.float64toint64"
,
1
},
{
"runtime.float64touint64"
,
1
},
{
"runtime.float64touint32"
,
1
},
{
"runtime.int64tofloat64"
,
1
},
{
"runtime.uint64tofloat64"
,
1
},
{
"runtime.uint32tofloat64"
,
1
},
{
"runtime.complex128div"
,
1
},
{
"runtime.racefuncenter"
,
1
},
{
"runtime.racefuncenterfp"
,
1
},
{
"runtime.racefuncexit"
,
1
},
{
"runtime.raceread"
,
1
},
{
"runtime.racewrite"
,
1
},
{
"runtime.racereadrange"
,
1
},
{
"runtime.racewriterange"
,
1
},
{
"runtime.msanread"
,
1
},
{
"runtime.msanwrite"
,
1
},
{
"runtime.checkptrAlignment"
,
1
},
{
"runtime.checkptrArithmetic"
,
1
},
{
"runtime.x86HasPOPCNT"
,
0
},
{
"runtime.x86HasSSE41"
,
0
},
{
"runtime.arm64HasATOMICS"
,
0
},
{
"runtime.gcWriteBarrier"
,
0
},
{
"runtime.deferproc"
,
1
},
{
"runtime.deferprocStack"
,
1
},
{
"runtime.deferreturn"
,
1
},
{
"runtime.newproc"
,
1
},
{
"runtime.morestack"
,
0
},
{
"runtime.morestackc"
,
0
},
{
"runtime.morestack_noctxt"
,
0
},
}
src/cmd/internal/goobj2/funcinfo.go
0 → 100644
View file @
bababde7
// 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.
package
goobj2
import
(
"bytes"
"encoding/binary"
)
// FuncInfo is serialized as a symbol (aux symbol). The symbol data is
// the binary encoding of the struct below.
//
// TODO: make each pcdata a separate symbol?
type
FuncInfo
struct
{
NoSplit
uint8
Args
uint32
Locals
uint32
Pcsp
uint32
Pcfile
uint32
Pcline
uint32
Pcinline
uint32
Pcdata
[]
uint32
PcdataEnd
uint32
Funcdataoff
[]
uint32
File
[]
SymRef
// TODO: just use string?
InlTree
[]
InlTreeNode
}
func
(
a
*
FuncInfo
)
Write
(
w
*
bytes
.
Buffer
)
{
w
.
WriteByte
(
a
.
NoSplit
)
var
b
[
4
]
byte
writeUint32
:=
func
(
x
uint32
)
{
binary
.
LittleEndian
.
PutUint32
(
b
[
:
],
x
)
w
.
Write
(
b
[
:
])
}
writeUint32
(
a
.
Args
)
writeUint32
(
a
.
Locals
)
writeUint32
(
a
.
Pcsp
)
writeUint32
(
a
.
Pcfile
)
writeUint32
(
a
.
Pcline
)
writeUint32
(
a
.
Pcinline
)
writeUint32
(
uint32
(
len
(
a
.
Pcdata
)))
for
_
,
x
:=
range
a
.
Pcdata
{
writeUint32
(
x
)
}
writeUint32
(
a
.
PcdataEnd
)
writeUint32
(
uint32
(
len
(
a
.
Funcdataoff
)))
for
_
,
x
:=
range
a
.
Funcdataoff
{
writeUint32
(
x
)
}
writeUint32
(
uint32
(
len
(
a
.
File
)))
for
_
,
f
:=
range
a
.
File
{
writeUint32
(
f
.
PkgIdx
)
writeUint32
(
f
.
SymIdx
)
}
writeUint32
(
uint32
(
len
(
a
.
InlTree
)))
for
i
:=
range
a
.
InlTree
{
a
.
InlTree
[
i
]
.
Write
(
w
)
}
}
func
(
a
*
FuncInfo
)
Read
(
b
[]
byte
)
{
a
.
NoSplit
=
b
[
0
]
b
=
b
[
1
:
]
readUint32
:=
func
()
uint32
{
x
:=
binary
.
LittleEndian
.
Uint32
(
b
)
b
=
b
[
4
:
]
return
x
}
a
.
Args
=
readUint32
()
a
.
Locals
=
readUint32
()
a
.
Pcsp
=
readUint32
()
a
.
Pcfile
=
readUint32
()
a
.
Pcline
=
readUint32
()
a
.
Pcinline
=
readUint32
()
pcdatalen
:=
readUint32
()
a
.
Pcdata
=
make
([]
uint32
,
pcdatalen
)
for
i
:=
range
a
.
Pcdata
{
a
.
Pcdata
[
i
]
=
readUint32
()
}
a
.
PcdataEnd
=
readUint32
()
funcdataofflen
:=
readUint32
()
a
.
Funcdataoff
=
make
([]
uint32
,
funcdataofflen
)
for
i
:=
range
a
.
Funcdataoff
{
a
.
Funcdataoff
[
i
]
=
readUint32
()
}
filelen
:=
readUint32
()
a
.
File
=
make
([]
SymRef
,
filelen
)
for
i
:=
range
a
.
File
{
a
.
File
[
i
]
=
SymRef
{
readUint32
(),
readUint32
()}
}
inltreelen
:=
readUint32
()
a
.
InlTree
=
make
([]
InlTreeNode
,
inltreelen
)
for
i
:=
range
a
.
InlTree
{
b
=
a
.
InlTree
[
i
]
.
Read
(
b
)
}
}
// InlTreeNode is the serialized form of FileInfo.InlTree.
type
InlTreeNode
struct
{
Parent
int32
File
SymRef
Line
int32
Func
SymRef
ParentPC
int32
}
func
(
inl
*
InlTreeNode
)
Write
(
w
*
bytes
.
Buffer
)
{
var
b
[
4
]
byte
writeUint32
:=
func
(
x
uint32
)
{
binary
.
LittleEndian
.
PutUint32
(
b
[
:
],
x
)
w
.
Write
(
b
[
:
])
}
writeUint32
(
uint32
(
inl
.
Parent
))
writeUint32
(
inl
.
File
.
PkgIdx
)
writeUint32
(
inl
.
File
.
SymIdx
)
writeUint32
(
uint32
(
inl
.
Line
))
writeUint32
(
inl
.
Func
.
PkgIdx
)
writeUint32
(
inl
.
Func
.
SymIdx
)
writeUint32
(
uint32
(
inl
.
ParentPC
))
}
// Read an InlTreeNode from b, return the remaining bytes.
func
(
inl
*
InlTreeNode
)
Read
(
b
[]
byte
)
[]
byte
{
readUint32
:=
func
()
uint32
{
x
:=
binary
.
LittleEndian
.
Uint32
(
b
)
b
=
b
[
4
:
]
return
x
}
inl
.
Parent
=
int32
(
readUint32
())
inl
.
File
=
SymRef
{
readUint32
(),
readUint32
()}
inl
.
Line
=
int32
(
readUint32
())
inl
.
Func
=
SymRef
{
readUint32
(),
readUint32
()}
inl
.
ParentPC
=
int32
(
readUint32
())
return
b
}
src/cmd/internal/goobj2/mkbuiltin.go
0 → 100644
View file @
bababde7
// 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.
// +build ignore
// Generate builtinlist.go from cmd/compile/internal/gc/builtin/runtime.go.
package
main
import
(
"bytes"
"flag"
"fmt"
"go/ast"
"go/format"
"go/parser"
"go/token"
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
)
var
stdout
=
flag
.
Bool
(
"stdout"
,
false
,
"write to stdout instead of builtinlist.go"
)
func
main
()
{
flag
.
Parse
()
var
b
bytes
.
Buffer
fmt
.
Fprintln
(
&
b
,
"// Code generated by mkbuiltin.go. DO NOT EDIT."
)
fmt
.
Fprintln
(
&
b
)
fmt
.
Fprintln
(
&
b
,
"package goobj2"
)
mkbuiltin
(
&
b
)
out
,
err
:=
format
.
Source
(
b
.
Bytes
())
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
if
*
stdout
{
_
,
err
=
os
.
Stdout
.
Write
(
out
)
}
else
{
err
=
ioutil
.
WriteFile
(
"builtinlist.go"
,
out
,
0666
)
}
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
}
func
mkbuiltin
(
w
io
.
Writer
)
{
pkg
:=
"runtime"
fset
:=
token
.
NewFileSet
()
path
:=
filepath
.
Join
(
".."
,
".."
,
"compile"
,
"internal"
,
"gc"
,
"builtin"
,
"runtime.go"
)
f
,
err
:=
parser
.
ParseFile
(
fset
,
path
,
nil
,
0
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
decls
:=
make
(
map
[
string
]
bool
)
fmt
.
Fprintf
(
w
,
"var builtins = [...]struct{ name string; abi int }{
\n
"
)
for
_
,
decl
:=
range
f
.
Decls
{
switch
decl
:=
decl
.
(
type
)
{
case
*
ast
.
FuncDecl
:
if
decl
.
Recv
!=
nil
{
log
.
Fatal
(
"methods unsupported"
)
}
if
decl
.
Body
!=
nil
{
log
.
Fatal
(
"unexpected function body"
)
}
declName
:=
pkg
+
"."
+
decl
.
Name
.
Name
decls
[
declName
]
=
true
fmt
.
Fprintf
(
w
,
"{%q, 1},
\n
"
,
declName
)
// functions are ABIInternal (1)
case
*
ast
.
GenDecl
:
if
decl
.
Tok
==
token
.
IMPORT
{
continue
}
if
decl
.
Tok
!=
token
.
VAR
{
log
.
Fatal
(
"unhandled declaration kind"
,
decl
.
Tok
)
}
for
_
,
spec
:=
range
decl
.
Specs
{
spec
:=
spec
.
(
*
ast
.
ValueSpec
)
if
len
(
spec
.
Values
)
!=
0
{
log
.
Fatal
(
"unexpected values"
)
}
for
_
,
name
:=
range
spec
.
Names
{
declName
:=
pkg
+
"."
+
name
.
Name
decls
[
declName
]
=
true
fmt
.
Fprintf
(
w
,
"{%q, 0},
\n
"
,
declName
)
// variables are ABI0
}
}
default
:
log
.
Fatal
(
"unhandled decl type"
,
decl
)
}
}
// The list above only contains ones that are used by the frontend.
// The backend may create more references of builtin functions.
// Add them.
for
_
,
b
:=
range
extra
{
name
:=
pkg
+
"."
+
b
.
name
if
decls
[
name
]
{
log
.
Fatalf
(
"%q already added -- mkbuiltin.go out of sync?"
,
name
)
}
fmt
.
Fprintf
(
w
,
"{%q, %d},
\n
"
,
name
,
b
.
abi
)
}
fmt
.
Fprintln
(
w
,
"}"
)
}
var
extra
=
[
...
]
struct
{
name
string
abi
int
}{
{
"gcWriteBarrier"
,
0
},
// asm function, ABI0
{
"deferproc"
,
1
},
{
"deferprocStack"
,
1
},
{
"deferreturn"
,
1
},
{
"newproc"
,
1
},
{
"morestack"
,
0
},
// asm function, ABI0
{
"morestackc"
,
0
},
// asm function, ABI0
{
"morestack_noctxt"
,
0
},
// asm function, ABI0
}
src/cmd/internal/goobj2/objfile.go
0 → 100644
View file @
bababde7
This diff is collapsed.
Click to expand it.
src/cmd/internal/obj/link.go
View file @
bababde7
...
...
@@ -388,6 +388,10 @@ type LSym struct {
R
[]
Reloc
Func
*
FuncInfo
Pkg
string
PkgIdx
int32
SymIdx
int32
// TODO: replace RefIdx
}
// A FuncInfo contains extra fields for STEXT symbols.
...
...
@@ -410,6 +414,8 @@ type FuncInfo struct {
GCRegs
*
LSym
StackObjects
*
LSym
OpenCodedDeferInfo
*
LSym
FuncInfoSym
*
LSym
}
type
InlMark
struct
{
...
...
@@ -461,7 +467,7 @@ const (
)
// Attribute is a set of symbol attributes.
type
Attribute
uint
16
type
Attribute
uint
32
const
(
AttrDuplicateOK
Attribute
=
1
<<
iota
...
...
@@ -502,6 +508,10 @@ const (
// keep unwinding beyond this frame.
AttrTopFrame
// Indexed indicates this symbol has been assigned with an index (when using the
// new object file format).
AttrIndexed
// attrABIBase is the value at which the ABI is encoded in
// Attribute. This must be last; all bits after this are
// assumed to be an ABI value.
...
...
@@ -525,6 +535,7 @@ func (a Attribute) NoFrame() bool { return a&AttrNoFrame != 0 }
func
(
a
Attribute
)
Static
()
bool
{
return
a
&
AttrStatic
!=
0
}
func
(
a
Attribute
)
WasInlined
()
bool
{
return
a
&
AttrWasInlined
!=
0
}
func
(
a
Attribute
)
TopFrame
()
bool
{
return
a
&
AttrTopFrame
!=
0
}
func
(
a
Attribute
)
Indexed
()
bool
{
return
a
&
AttrIndexed
!=
0
}
func
(
a
*
Attribute
)
Set
(
flag
Attribute
,
value
bool
)
{
if
value
{
...
...
@@ -559,6 +570,7 @@ var textAttrStrings = [...]struct {
{
bit
:
AttrStatic
,
s
:
"STATIC"
},
{
bit
:
AttrWasInlined
,
s
:
""
},
{
bit
:
AttrTopFrame
,
s
:
"TOPFRAME"
},
{
bit
:
AttrIndexed
,
s
:
""
},
}
// TextAttrString formats a for printing in as part of a TEXT prog.
...
...
@@ -637,8 +649,10 @@ type Link struct {
Debugpcln
string
Flag_shared
bool
Flag_dynlink
bool
Flag_linkshared
bool
Flag_optimize
bool
Flag_locationlists
bool
Flag_newobj
bool
// use new object file format
Bso
*
bufio
.
Writer
Pathname
string
hashmu
sync
.
Mutex
// protects hash, funchash
...
...
@@ -672,6 +686,14 @@ type Link struct {
// TODO(austin): Replace this with ABI wrappers once the ABIs
// actually diverge.
ABIAliases
[]
*
LSym
// pkgIdx maps package path to index. The index is used for
// symbol reference in the object file.
pkgIdx
map
[
string
]
int32
defs
[]
*
LSym
// list of defined symbols in the current package
nonpkgdefs
[]
*
LSym
// list of defined non-package symbols
nonpkgrefs
[]
*
LSym
// list of referenced non-package symbols
}
func
(
ctxt
*
Link
)
Diag
(
format
string
,
args
...
interface
{})
{
...
...
src/cmd/internal/obj/objfile.go
View file @
bababde7
...
...
@@ -8,6 +8,7 @@ package obj
import
(
"bufio"
"cmd/internal/bio"
"cmd/internal/dwarf"
"cmd/internal/objabi"
"cmd/internal/sys"
...
...
@@ -80,7 +81,13 @@ func newObjWriter(ctxt *Link, b *bufio.Writer, pkgpath string) *objWriter {
}
}
func
WriteObjFile
(
ctxt
*
Link
,
b
*
bufio
.
Writer
,
pkgpath
string
)
{
func
WriteObjFile
(
ctxt
*
Link
,
bout
*
bio
.
Writer
,
pkgpath
string
)
{
if
ctxt
.
Flag_newobj
{
WriteObjFile2
(
ctxt
,
bout
,
pkgpath
)
return
}
b
:=
bout
.
Writer
w
:=
newObjWriter
(
ctxt
,
b
,
pkgpath
)
// Magic header
...
...
@@ -221,8 +228,7 @@ func (w *objWriter) writeRefs(s *LSym) {
}
}
func
(
w
*
objWriter
)
writeSymDebug
(
s
*
LSym
)
{
ctxt
:=
w
.
ctxt
func
(
ctxt
*
Link
)
writeSymDebug
(
s
*
LSym
)
{
fmt
.
Fprintf
(
ctxt
.
Bso
,
"%s "
,
s
.
Name
)
if
s
.
Type
!=
0
{
fmt
.
Fprintf
(
ctxt
.
Bso
,
"%v "
,
s
.
Type
)
...
...
@@ -302,7 +308,7 @@ func (w *objWriter) writeSymDebug(s *LSym) {
func
(
w
*
objWriter
)
writeSym
(
s
*
LSym
)
{
ctxt
:=
w
.
ctxt
if
ctxt
.
Debugasm
>
0
{
w
.
writeSymDebug
(
s
)
w
.
ctxt
.
writeSymDebug
(
s
)
}
w
.
wr
.
WriteByte
(
symPrefix
)
...
...
src/cmd/internal/obj/objfile2.go
0 → 100644
View file @
bababde7
// 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"
"path/filepath"
"strings"
)
// Entry point of writing new object file.
func
WriteObjFile2
(
ctxt
*
Link
,
b
*
bio
.
Writer
,
pkgpath
string
)
{
if
ctxt
.
Debugasm
>
0
{
ctxt
.
traverseSyms
(
traverseDefs
,
ctxt
.
writeSymDebug
)
}
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.
flags
:=
uint32
(
0
)
if
ctxt
.
Flag_shared
{
flags
|=
goobj2
.
ObjFlagShared
}
h
:=
goobj2
.
Header
{
Magic
:
goobj2
.
Magic
,
Flags
:
flags
}
h
.
Write
(
w
.
Writer
)
// String table
w
.
StringTable
()
// Autolib
h
.
Offsets
[
goobj2
.
BlkAutolib
]
=
w
.
Offset
()
for
_
,
pkg
:=
range
ctxt
.
Imports
{
w
.
StringRef
(
pkg
)
}
// Package references
h
.
Offsets
[
goobj2
.
BlkPkgIdx
]
=
w
.
Offset
()
for
_
,
pkg
:=
range
w
.
pkglist
{
w
.
StringRef
(
pkg
)
}
// DWARF file table
h
.
Offsets
[
goobj2
.
BlkDwarfFile
]
=
w
.
Offset
()
for
_
,
f
:=
range
ctxt
.
PosTable
.
DebugLinesFileTable
()
{
w
.
StringRef
(
f
)
}
// 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
)
naux
+=
uint32
(
nAuxSym
(
s
))
}
}
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
{
w
.
AddString
(
filepath
.
ToSlash
(
f
))
}
for
_
,
call
:=
range
pc
.
InlTree
.
nodes
{
f
,
_
:=
linkgetlineFromPos
(
w
.
ctxt
,
call
.
Pos
)
w
.
AddString
(
filepath
.
ToSlash
(
f
))
}
})
for
_
,
f
:=
range
w
.
ctxt
.
PosTable
.
DebugLinesFileTable
()
{
w
.
AddString
(
f
)
}
}
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
}
if
s
.
Leaf
()
{
flag
|=
goobj2
.
SymFlagLeaf
}
if
s
.
CFunc
()
{
flag
|=
goobj2
.
SymFlagCFunc
}
if
s
.
ReflectMethod
()
{
flag
|=
goobj2
.
SymFlagReflectMethod
}
if
s
.
TopFrame
()
{
flag
|=
goobj2
.
SymFlagTopFrame
}
if
strings
.
HasPrefix
(
s
.
Name
,
"type."
)
&&
s
.
Name
[
5
]
!=
'.'
&&
s
.
Type
==
objabi
.
SRODATA
{
flag
|=
goobj2
.
SymFlagGoType
}
name
:=
s
.
Name
if
strings
.
HasPrefix
(
name
,
"gofile.."
)
{
name
=
filepath
.
ToSlash
(
name
)
}
o
:=
goobj2
.
Sym
{
Name
:
name
,
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
)
}
if
s
.
Func
.
dwarfInfoSym
!=
nil
{
o
:=
goobj2
.
Aux
{
Type
:
goobj2
.
AuxDwarfInfo
,
Sym
:
makeSymRef
(
s
.
Func
.
dwarfInfoSym
),
}
o
.
Write
(
w
.
Writer
)
}
if
s
.
Func
.
dwarfLocSym
!=
nil
{
o
:=
goobj2
.
Aux
{
Type
:
goobj2
.
AuxDwarfLoc
,
Sym
:
makeSymRef
(
s
.
Func
.
dwarfLocSym
),
}
o
.
Write
(
w
.
Writer
)
}
if
s
.
Func
.
dwarfRangesSym
!=
nil
{
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
++
}
if
s
.
Func
.
dwarfLocSym
!=
nil
{
n
++
}
if
s
.
Func
.
dwarfRangesSym
!=
nil
{
n
++
}
if
s
.
Func
.
dwarfDebugLinesSym
!=
nil
{
n
++
}
}
return
n
}
// 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
}
nosplit
:=
uint8
(
0
)
if
s
.
NoSplit
()
{
nosplit
=
1
}
o
:=
goobj2
.
FuncInfo
{
NoSplit
:
nosplit
,
Args
:
uint32
(
s
.
Func
.
Args
),
Locals
:
uint32
(
s
.
Func
.
Locals
),
}
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
)
}
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
,
}
}
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
()
}
ctxt
.
defs
=
append
(
ctxt
.
defs
,
infosyms
...
)
}
src/cmd/internal/obj/sizeof_test.go
View file @
bababde7
...
...
@@ -21,7 +21,7 @@ func TestSizeof(t *testing.T) {
_64bit
uintptr
// size on 64bit platforms
}{
{
Addr
{},
32
,
48
},
{
LSym
{},
56
,
104
},
{
LSym
{},
76
,
128
},
{
Prog
{},
132
,
200
},
}
...
...
src/cmd/internal/obj/sym.go
View file @
bababde7
...
...
@@ -32,10 +32,12 @@
package
obj
import
(
"cmd/internal/goobj2"
"cmd/internal/objabi"
"fmt"
"log"
"math"
"sort"
)
func
Linknew
(
arch
*
LinkArch
)
*
Link
{
...
...
@@ -78,6 +80,13 @@ func (ctxt *Link) LookupStatic(name string) *LSym {
// LookupABI looks up a symbol with the given ABI.
// If it does not exist, it creates it.
func
(
ctxt
*
Link
)
LookupABI
(
name
string
,
abi
ABI
)
*
LSym
{
return
ctxt
.
LookupABIInit
(
name
,
abi
,
nil
)
}
// LookupABI looks up a symbol with the given ABI.
// If it does not exist, it creates it and
// passes it to init for one-time initialization.
func
(
ctxt
*
Link
)
LookupABIInit
(
name
string
,
abi
ABI
,
init
func
(
s
*
LSym
))
*
LSym
{
var
hash
map
[
string
]
*
LSym
switch
abi
{
case
ABI0
:
...
...
@@ -94,6 +103,9 @@ func (ctxt *Link) LookupABI(name string, abi ABI) *LSym {
s
=
&
LSym
{
Name
:
name
}
s
.
SetABI
(
abi
)
hash
[
name
]
=
s
if
init
!=
nil
{
init
(
s
)
}
}
ctxt
.
hashmu
.
Unlock
()
return
s
...
...
@@ -147,3 +159,167 @@ func (ctxt *Link) Int64Sym(i int64) *LSym {
s
.
Set
(
AttrLocal
,
true
)
})
}
// Assign index to symbols.
// asm is set to true if this is called by the assembler (i.e. not the compiler),
// in which case all the symbols are non-package (for now).
func
(
ctxt
*
Link
)
NumberSyms
(
asm
bool
)
{
if
!
ctxt
.
Flag_newobj
{
return
}
if
ctxt
.
Headtype
==
objabi
.
Haix
{
// Data must be sorted to keep a constant order in TOC symbols.
// As they are created during Progedit, two symbols can be switched between
// two different compilations. Therefore, BuildID will be different.
// TODO: find a better place and optimize to only sort TOC symbols
sort
.
Slice
(
ctxt
.
Data
,
func
(
i
,
j
int
)
bool
{
return
ctxt
.
Data
[
i
]
.
Name
<
ctxt
.
Data
[
j
]
.
Name
})
}
ctxt
.
pkgIdx
=
make
(
map
[
string
]
int32
)
ctxt
.
defs
=
[]
*
LSym
{}
ctxt
.
nonpkgdefs
=
[]
*
LSym
{}
var
idx
,
nonpkgidx
int32
=
0
,
0
ctxt
.
traverseSyms
(
traverseDefs
,
func
(
s
*
LSym
)
{
if
isNonPkgSym
(
ctxt
,
asm
,
s
)
{
s
.
PkgIdx
=
goobj2
.
PkgIdxNone
s
.
SymIdx
=
nonpkgidx
if
nonpkgidx
!=
int32
(
len
(
ctxt
.
nonpkgdefs
))
{
panic
(
"bad index"
)
}
ctxt
.
nonpkgdefs
=
append
(
ctxt
.
nonpkgdefs
,
s
)
nonpkgidx
++
}
else
{
s
.
PkgIdx
=
goobj2
.
PkgIdxSelf
s
.
SymIdx
=
idx
if
idx
!=
int32
(
len
(
ctxt
.
defs
))
{
panic
(
"bad index"
)
}
ctxt
.
defs
=
append
(
ctxt
.
defs
,
s
)
idx
++
}
s
.
Set
(
AttrIndexed
,
true
)
})
ipkg
:=
int32
(
1
)
// 0 is invalid index
nonpkgdef
:=
nonpkgidx
ctxt
.
traverseSyms
(
traverseRefs
|
traverseAux
,
func
(
rs
*
LSym
)
{
if
rs
.
PkgIdx
!=
goobj2
.
PkgIdxInvalid
{
return
}
if
!
ctxt
.
Flag_linkshared
{
// Assign special index for builtin symbols.
// Don't do it when linking against shared libraries, as the runtime
// may be in a different library.
if
i
:=
goobj2
.
BuiltinIdx
(
rs
.
Name
,
int
(
rs
.
ABI
()));
i
!=
-
1
{
rs
.
PkgIdx
=
goobj2
.
PkgIdxBuiltin
rs
.
SymIdx
=
int32
(
i
)
rs
.
Set
(
AttrIndexed
,
true
)
return
}
}
pkg
:=
rs
.
Pkg
if
pkg
==
""
||
pkg
==
"
\"\"
"
||
pkg
==
"_"
||
!
rs
.
Indexed
()
{
rs
.
PkgIdx
=
goobj2
.
PkgIdxNone
rs
.
SymIdx
=
nonpkgidx
rs
.
Set
(
AttrIndexed
,
true
)
if
nonpkgidx
!=
nonpkgdef
+
int32
(
len
(
ctxt
.
nonpkgrefs
))
{
panic
(
"bad index"
)
}
ctxt
.
nonpkgrefs
=
append
(
ctxt
.
nonpkgrefs
,
rs
)
nonpkgidx
++
return
}
if
k
,
ok
:=
ctxt
.
pkgIdx
[
pkg
];
ok
{
rs
.
PkgIdx
=
k
return
}
rs
.
PkgIdx
=
ipkg
ctxt
.
pkgIdx
[
pkg
]
=
ipkg
ipkg
++
})
}
// Returns whether s is a non-package symbol, which needs to be referenced
// by name instead of by index.
func
isNonPkgSym
(
ctxt
*
Link
,
asm
bool
,
s
*
LSym
)
bool
{
if
asm
&&
!
s
.
Static
()
{
// asm symbols are referenced by name only, except static symbols
// which are file-local and can be referenced by index.
return
true
}
if
ctxt
.
Flag_linkshared
{
// The referenced symbol may be in a different shared library so
// the linker cannot see its index.
return
true
}
if
s
.
Pkg
==
"_"
{
// The frontend uses package "_" to mark symbols that should not
// be referenced by index, e.g. linkname'd symbols.
return
true
}
if
s
.
DuplicateOK
()
{
// Dupok symbol needs to be dedup'd by name.
return
true
}
return
false
}
type
traverseFlag
uint32
const
(
traverseDefs
traverseFlag
=
1
<<
iota
traverseRefs
traverseAux
traverseAll
=
traverseDefs
|
traverseRefs
|
traverseAux
)
// Traverse symbols based on flag, call fn for each symbol.
func
(
ctxt
*
Link
)
traverseSyms
(
flag
traverseFlag
,
fn
func
(
*
LSym
))
{
lists
:=
[][]
*
LSym
{
ctxt
.
Text
,
ctxt
.
Data
,
ctxt
.
ABIAliases
}
for
_
,
list
:=
range
lists
{
for
_
,
s
:=
range
list
{
if
flag
&
traverseDefs
!=
0
{
fn
(
s
)
}
if
flag
&
traverseRefs
!=
0
{
for
_
,
r
:=
range
s
.
R
{
if
r
.
Sym
!=
nil
{
fn
(
r
.
Sym
)
}
}
}
if
flag
&
traverseAux
!=
0
{
if
s
.
Gotype
!=
nil
{
fn
(
s
.
Gotype
)
}
if
s
.
Type
==
objabi
.
STEXT
{
pc
:=
&
s
.
Func
.
Pcln
for
_
,
d
:=
range
pc
.
Funcdata
{
if
d
!=
nil
{
fn
(
d
)
}
}
for
_
,
f
:=
range
pc
.
File
{
if
fsym
:=
ctxt
.
Lookup
(
f
);
fsym
!=
nil
{
fn
(
fsym
)
}
}
for
_
,
call
:=
range
pc
.
InlTree
.
nodes
{
if
call
.
Func
!=
nil
{
fn
(
call
.
Func
)
}
f
,
_
:=
linkgetlineFromPos
(
ctxt
,
call
.
Pos
)
if
fsym
:=
ctxt
.
Lookup
(
f
);
fsym
!=
nil
{
fn
(
fsym
)
}
}
}
}
}
}
}
src/cmd/link/internal/ld/data.go
View file @
bababde7
...
...
@@ -402,7 +402,7 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
case
objabi
.
R_ADDRCUOFF
:
// debug_range and debug_loc elements use this relocation type to get an
// offset from the start of the compile unit.
o
=
Symaddr
(
r
.
Sym
)
+
r
.
Add
-
Symaddr
(
r
.
Sym
.
Unit
.
Lib
.
Textp
[
0
])
o
=
Symaddr
(
r
.
Sym
)
+
r
.
Add
-
Symaddr
(
r
.
Sym
.
Unit
.
Textp
[
0
])
// r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
case
objabi
.
R_GOTPCREL
:
...
...
@@ -1086,13 +1086,13 @@ func (p *GCProg) AddSym(s *sym.Symbol) {
}
ptrsize
:=
int64
(
p
.
ctxt
.
Arch
.
PtrSize
)
nptr
:=
decodetypePtrdata
(
p
.
ctxt
.
Arch
,
typ
)
/
ptrsize
nptr
:=
decodetypePtrdata
(
p
.
ctxt
.
Arch
,
typ
.
P
)
/
ptrsize
if
debugGCProg
{
fmt
.
Fprintf
(
os
.
Stderr
,
"gcprog sym: %s at %d (ptr=%d+%d)
\n
"
,
s
.
Name
,
s
.
Value
,
s
.
Value
/
ptrsize
,
nptr
)
}
if
decodetypeUsegcprog
(
p
.
ctxt
.
Arch
,
typ
)
==
0
{
if
decodetypeUsegcprog
(
p
.
ctxt
.
Arch
,
typ
.
P
)
==
0
{
// Copy pointers from mask into program.
mask
:=
decodetypeGcmask
(
p
.
ctxt
,
typ
)
for
i
:=
int64
(
0
);
i
<
nptr
;
i
++
{
...
...
src/cmd/link/internal/ld/deadcode.go
View file @
bababde7
...
...
@@ -46,6 +46,15 @@ import (
//
// Any unreached text symbols are removed from ctxt.Textp.
func
deadcode
(
ctxt
*
Link
)
{
if
ctxt
.
Debugvlog
!=
0
{
ctxt
.
Logf
(
"deadcode
\n
"
)
}
if
*
flagNewobj
{
deadcode2
(
ctxt
)
return
}
d
:=
&
deadcodepass
{
ctxt
:
ctxt
,
ifaceMethod
:
make
(
map
[
methodsig
]
bool
),
...
...
@@ -114,22 +123,70 @@ func deadcode(ctxt *Link) {
}
}
for
_
,
lib
:=
range
ctxt
.
Library
{
lib
.
Textp
=
lib
.
Textp
[
:
0
]
}
addToTextp
(
ctxt
)
}
func
addToTextp
(
ctxt
*
Link
)
{
// Remove dead text but keep file information (z symbols).
textp
:=
make
([]
*
sym
.
Symbol
,
0
,
len
(
ctxt
.
Textp
))
textp
:=
[]
*
sym
.
Symbol
{}
for
_
,
s
:=
range
ctxt
.
Textp
{
if
s
.
Attr
.
Reachable
()
{
if
s
.
Unit
!=
nil
{
s
.
Unit
.
Lib
.
Textp
=
append
(
s
.
Unit
.
Lib
.
Textp
,
s
)
s
.
Unit
.
Textp
=
append
(
s
.
Unit
.
Textp
,
s
)
}
textp
=
append
(
textp
,
s
)
}
}
// Put reachable text symbols into Textp.
// do it in postorder so that packages are laid down in dependency order
// internal first, then everything else
ctxt
.
Library
=
postorder
(
ctxt
.
Library
)
for
_
,
doInternal
:=
range
[
2
]
bool
{
true
,
false
}
{
for
_
,
lib
:=
range
ctxt
.
Library
{
if
isRuntimeDepPkg
(
lib
.
Pkg
)
!=
doInternal
{
continue
}
libtextp
:=
lib
.
Textp
[
:
0
]
for
_
,
s
:=
range
lib
.
Textp
{
if
s
.
Attr
.
Reachable
()
{
textp
=
append
(
textp
,
s
)
libtextp
=
append
(
libtextp
,
s
)
if
s
.
Unit
!=
nil
{
s
.
Unit
.
Textp
=
append
(
s
.
Unit
.
Textp
,
s
)
}
}
}
for
_
,
s
:=
range
lib
.
DupTextSyms
{
if
s
.
Attr
.
Reachable
()
&&
!
s
.
Attr
.
OnList
()
{
textp
=
append
(
textp
,
s
)
libtextp
=
append
(
libtextp
,
s
)
if
s
.
Unit
!=
nil
{
s
.
Unit
.
Textp
=
append
(
s
.
Unit
.
Textp
,
s
)
}
s
.
Attr
|=
sym
.
AttrOnList
// dupok symbols may be defined in multiple packages. its
// associated package is chosen sort of arbitrarily (the
// first containing package that the linker loads). canonicalize
// it here to the package with which it will be laid down
// in text.
s
.
File
=
objabi
.
PathToPrefix
(
lib
.
Pkg
)
}
}
lib
.
Textp
=
libtextp
}
}
ctxt
.
Textp
=
textp
if
len
(
ctxt
.
Shlibs
)
>
0
{
// We might have overwritten some functions above (this tends to happen for the
// autogenerated type equality/hashing functions) and we don't want to generated
// pcln table entries for these any more so remove them from Textp.
textp
:=
make
([]
*
sym
.
Symbol
,
0
,
len
(
ctxt
.
Textp
))
for
_
,
s
:=
range
ctxt
.
Textp
{
if
s
.
Type
!=
sym
.
SDYNIMPORT
{
textp
=
append
(
textp
,
s
)
}
}
ctxt
.
Textp
=
textp
}
}
// methodref holds the relocations from a receiver type symbol to its
...
...
@@ -274,7 +331,7 @@ func (d *deadcodepass) flood() {
// later will give a better error than deadcode.
continue
}
if
decodetypeKind
(
d
.
ctxt
.
Arch
,
s
)
&
kindMask
==
kindInterface
{
if
decodetypeKind
(
d
.
ctxt
.
Arch
,
s
.
P
)
&
kindMask
==
kindInterface
{
for
_
,
sig
:=
range
decodeIfaceMethods
(
d
.
ctxt
.
Arch
,
s
)
{
if
d
.
ctxt
.
Debugvlog
>
1
{
d
.
ctxt
.
Logf
(
"reached iface method: %s
\n
"
,
sig
)
...
...
src/cmd/link/internal/ld/deadcode2.go
0 → 100644
View file @
bababde7
This diff is collapsed.
Click to expand it.
src/cmd/link/internal/ld/decodesym.go
View file @
bababde7
...
...
@@ -65,28 +65,28 @@ func structfieldSize(arch *sys.Arch) int { return 3 * arch.PtrSize } // ru
func
uncommonSize
()
int
{
return
4
+
2
+
2
+
4
+
4
}
// runtime.uncommontype
// Type.commonType.kind
func
decodetypeKind
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
uint8
{
return
s
.
P
[
2
*
arch
.
PtrSize
+
7
]
&
objabi
.
KindMask
// 0x13 / 0x1f
func
decodetypeKind
(
arch
*
sys
.
Arch
,
p
[]
byte
)
uint8
{
return
p
[
2
*
arch
.
PtrSize
+
7
]
&
objabi
.
KindMask
// 0x13 / 0x1f
}
// Type.commonType.kind
func
decodetypeUsegcprog
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
uint8
{
return
s
.
P
[
2
*
arch
.
PtrSize
+
7
]
&
objabi
.
KindGCProg
// 0x13 / 0x1f
func
decodetypeUsegcprog
(
arch
*
sys
.
Arch
,
p
[]
byte
)
uint8
{
return
p
[
2
*
arch
.
PtrSize
+
7
]
&
objabi
.
KindGCProg
// 0x13 / 0x1f
}
// Type.commonType.size
func
decodetypeSize
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
int64
{
return
int64
(
decodeInuxi
(
arch
,
s
.
P
,
arch
.
PtrSize
))
// 0x8 / 0x10
func
decodetypeSize
(
arch
*
sys
.
Arch
,
p
[]
byte
)
int64
{
return
int64
(
decodeInuxi
(
arch
,
p
,
arch
.
PtrSize
))
// 0x8 / 0x10
}
// Type.commonType.ptrdata
func
decodetypePtrdata
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
int64
{
return
int64
(
decodeInuxi
(
arch
,
s
.
P
[
arch
.
PtrSize
:
],
arch
.
PtrSize
))
// 0x8 / 0x10
func
decodetypePtrdata
(
arch
*
sys
.
Arch
,
p
[]
byte
)
int64
{
return
int64
(
decodeInuxi
(
arch
,
p
[
arch
.
PtrSize
:
],
arch
.
PtrSize
))
// 0x8 / 0x10
}
// Type.commonType.tflag
func
decodetypeHasUncommon
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
bool
{
return
s
.
P
[
2
*
arch
.
PtrSize
+
4
]
&
tflagUncommon
!=
0
func
decodetypeHasUncommon
(
arch
*
sys
.
Arch
,
p
[]
byte
)
bool
{
return
p
[
2
*
arch
.
PtrSize
+
4
]
&
tflagUncommon
!=
0
}
// Find the elf.Section of a given shared library that contains a given address.
...
...
@@ -138,7 +138,7 @@ func decodetypeGcprogShlib(ctxt *Link, s *sym.Symbol) uint64 {
func
decodetypeGcmask
(
ctxt
*
Link
,
s
*
sym
.
Symbol
)
[]
byte
{
if
s
.
Type
==
sym
.
SDYNIMPORT
{
addr
:=
decodetypeGcprogShlib
(
ctxt
,
s
)
ptrdata
:=
decodetypePtrdata
(
ctxt
.
Arch
,
s
)
ptrdata
:=
decodetypePtrdata
(
ctxt
.
Arch
,
s
.
P
)
sect
:=
findShlibSection
(
ctxt
,
s
.
File
,
addr
)
if
sect
!=
nil
{
r
:=
make
([]
byte
,
ptrdata
/
int64
(
ctxt
.
Arch
.
PtrSize
))
...
...
@@ -181,17 +181,17 @@ func decodetypeChanElem(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
}
// Type.FuncType.dotdotdot
func
decodetypeFuncDotdotdot
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
bool
{
return
uint16
(
decodeInuxi
(
arch
,
s
.
P
[
commonsize
(
arch
)
+
2
:
],
2
))
&
(
1
<<
15
)
!=
0
func
decodetypeFuncDotdotdot
(
arch
*
sys
.
Arch
,
p
[]
byte
)
bool
{
return
uint16
(
decodeInuxi
(
arch
,
p
[
commonsize
(
arch
)
+
2
:
],
2
))
&
(
1
<<
15
)
!=
0
}
// Type.FuncType.inCount
func
decodetypeFuncInCount
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
int
{
return
int
(
decodeInuxi
(
arch
,
s
.
P
[
commonsize
(
arch
)
:
],
2
))
func
decodetypeFuncInCount
(
arch
*
sys
.
Arch
,
p
[]
byte
)
int
{
return
int
(
decodeInuxi
(
arch
,
p
[
commonsize
(
arch
)
:
],
2
))
}
func
decodetypeFuncOutCount
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
int
{
return
int
(
uint16
(
decodeInuxi
(
arch
,
s
.
P
[
commonsize
(
arch
)
+
2
:
],
2
))
&
(
1
<<
15
-
1
))
func
decodetypeFuncOutCount
(
arch
*
sys
.
Arch
,
p
[]
byte
)
int
{
return
int
(
uint16
(
decodeInuxi
(
arch
,
p
[
commonsize
(
arch
)
+
2
:
],
2
))
&
(
1
<<
15
-
1
))
}
func
decodetypeFuncInType
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
,
i
int
)
*
sym
.
Symbol
{
...
...
@@ -199,14 +199,14 @@ func decodetypeFuncInType(arch *sys.Arch, s *sym.Symbol, i int) *sym.Symbol {
if
arch
.
PtrSize
==
8
{
uadd
+=
4
}
if
decodetypeHasUncommon
(
arch
,
s
)
{
if
decodetypeHasUncommon
(
arch
,
s
.
P
)
{
uadd
+=
uncommonSize
()
}
return
decodeRelocSym
(
s
,
int32
(
uadd
+
i
*
arch
.
PtrSize
))
}
func
decodetypeFuncOutType
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
,
i
int
)
*
sym
.
Symbol
{
return
decodetypeFuncInType
(
arch
,
s
,
i
+
decodetypeFuncInCount
(
arch
,
s
))
return
decodetypeFuncInType
(
arch
,
s
,
i
+
decodetypeFuncInCount
(
arch
,
s
.
P
))
}
// Type.StructType.fields.Slice::length
...
...
@@ -216,7 +216,7 @@ func decodetypeStructFieldCount(arch *sys.Arch, s *sym.Symbol) int {
func
decodetypeStructFieldArrayOff
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
,
i
int
)
int
{
off
:=
commonsize
(
arch
)
+
4
*
arch
.
PtrSize
if
decodetypeHasUncommon
(
arch
,
s
)
{
if
decodetypeHasUncommon
(
arch
,
s
.
P
)
{
off
+=
uncommonSize
()
}
off
+=
i
*
structfieldSize
(
arch
)
...
...
@@ -264,8 +264,8 @@ func decodetypeStructFieldOffsAnon(arch *sys.Arch, s *sym.Symbol, i int) int64 {
}
// InterfaceType.methods.length
func
decodetypeIfaceMethodCount
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
int64
{
return
int64
(
decodeInuxi
(
arch
,
s
.
P
[
commonsize
(
arch
)
+
2
*
arch
.
PtrSize
:
],
arch
.
PtrSize
))
func
decodetypeIfaceMethodCount
(
arch
*
sys
.
Arch
,
p
[]
byte
)
int64
{
return
int64
(
decodeInuxi
(
arch
,
p
[
commonsize
(
arch
)
+
2
*
arch
.
PtrSize
:
],
arch
.
PtrSize
))
}
// methodsig is a fully qualified typed method signature, like
...
...
@@ -299,7 +299,7 @@ func decodeMethodSig(arch *sys.Arch, s *sym.Symbol, off, size, count int) []meth
mtypSym
:=
decodeRelocSym
(
s
,
int32
(
off
+
4
))
buf
.
WriteRune
(
'('
)
inCount
:=
decodetypeFuncInCount
(
arch
,
mtypSym
)
inCount
:=
decodetypeFuncInCount
(
arch
,
mtypSym
.
P
)
for
i
:=
0
;
i
<
inCount
;
i
++
{
if
i
>
0
{
buf
.
WriteString
(
", "
)
...
...
@@ -307,7 +307,7 @@ func decodeMethodSig(arch *sys.Arch, s *sym.Symbol, off, size, count int) []meth
buf
.
WriteString
(
decodetypeFuncInType
(
arch
,
mtypSym
,
i
)
.
Name
)
}
buf
.
WriteString
(
") ("
)
outCount
:=
decodetypeFuncOutCount
(
arch
,
mtypSym
)
outCount
:=
decodetypeFuncOutCount
(
arch
,
mtypSym
.
P
)
for
i
:=
0
;
i
<
outCount
;
i
++
{
if
i
>
0
{
buf
.
WriteString
(
", "
)
...
...
@@ -324,7 +324,7 @@ func decodeMethodSig(arch *sys.Arch, s *sym.Symbol, off, size, count int) []meth
}
func
decodeIfaceMethods
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
[]
methodsig
{
if
decodetypeKind
(
arch
,
s
)
&
kindMask
!=
kindInterface
{
if
decodetypeKind
(
arch
,
s
.
P
)
&
kindMask
!=
kindInterface
{
panic
(
fmt
.
Sprintf
(
"symbol %q is not an interface"
,
s
.
Name
))
}
r
:=
decodeReloc
(
s
,
int32
(
commonsize
(
arch
)
+
arch
.
PtrSize
))
...
...
@@ -335,17 +335,17 @@ func decodeIfaceMethods(arch *sys.Arch, s *sym.Symbol) []methodsig {
panic
(
fmt
.
Sprintf
(
"imethod slice pointer in %q leads to a different symbol"
,
s
.
Name
))
}
off
:=
int
(
r
.
Add
)
// array of reflect.imethod values
numMethods
:=
int
(
decodetypeIfaceMethodCount
(
arch
,
s
))
numMethods
:=
int
(
decodetypeIfaceMethodCount
(
arch
,
s
.
P
))
sizeofIMethod
:=
4
+
4
return
decodeMethodSig
(
arch
,
s
,
off
,
sizeofIMethod
,
numMethods
)
}
func
decodetypeMethods
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
[]
methodsig
{
if
!
decodetypeHasUncommon
(
arch
,
s
)
{
if
!
decodetypeHasUncommon
(
arch
,
s
.
P
)
{
panic
(
fmt
.
Sprintf
(
"no methods on %q"
,
s
.
Name
))
}
off
:=
commonsize
(
arch
)
// reflect.rtype
switch
decodetypeKind
(
arch
,
s
)
&
kindMask
{
switch
decodetypeKind
(
arch
,
s
.
P
)
&
kindMask
{
case
kindStruct
:
// reflect.structType
off
+=
4
*
arch
.
PtrSize
case
kindPtr
:
// reflect.ptrType
...
...
src/cmd/link/internal/ld/dwarf.go
View file @
bababde7
...
...
@@ -422,8 +422,8 @@ func defgotype(ctxt *Link, gotype *sym.Symbol) *sym.Symbol {
func
newtype
(
ctxt
*
Link
,
gotype
*
sym
.
Symbol
)
*
dwarf
.
DWDie
{
name
:=
gotype
.
Name
[
5
:
]
// could also decode from Type.string
kind
:=
decodetypeKind
(
ctxt
.
Arch
,
gotype
)
bytesize
:=
decodetypeSize
(
ctxt
.
Arch
,
gotype
)
kind
:=
decodetypeKind
(
ctxt
.
Arch
,
gotype
.
P
)
bytesize
:=
decodetypeSize
(
ctxt
.
Arch
,
gotype
.
P
)
var
die
,
typedefdie
*
dwarf
.
DWDie
switch
kind
{
...
...
@@ -488,17 +488,17 @@ func newtype(ctxt *Link, gotype *sym.Symbol) *dwarf.DWDie {
die
=
newdie
(
ctxt
,
&
dwtypes
,
dwarf
.
DW_ABRV_FUNCTYPE
,
name
,
0
)
newattr
(
die
,
dwarf
.
DW_AT_byte_size
,
dwarf
.
DW_CLS_CONSTANT
,
bytesize
,
0
)
typedefdie
=
dotypedef
(
ctxt
,
&
dwtypes
,
name
,
die
)
nfields
:=
decodetypeFuncInCount
(
ctxt
.
Arch
,
gotype
)
nfields
:=
decodetypeFuncInCount
(
ctxt
.
Arch
,
gotype
.
P
)
for
i
:=
0
;
i
<
nfields
;
i
++
{
s
:=
decodetypeFuncInType
(
ctxt
.
Arch
,
gotype
,
i
)
fld
:=
newdie
(
ctxt
,
die
,
dwarf
.
DW_ABRV_FUNCTYPEPARAM
,
s
.
Name
[
5
:
],
0
)
newrefattr
(
fld
,
dwarf
.
DW_AT_type
,
defgotype
(
ctxt
,
s
))
}
if
decodetypeFuncDotdotdot
(
ctxt
.
Arch
,
gotype
)
{
if
decodetypeFuncDotdotdot
(
ctxt
.
Arch
,
gotype
.
P
)
{
newdie
(
ctxt
,
die
,
dwarf
.
DW_ABRV_DOTDOTDOT
,
"..."
,
0
)
}
nfields
=
decodetypeFuncOutCount
(
ctxt
.
Arch
,
gotype
)
nfields
=
decodetypeFuncOutCount
(
ctxt
.
Arch
,
gotype
.
P
)
for
i
:=
0
;
i
<
nfields
;
i
++
{
s
:=
decodetypeFuncOutType
(
ctxt
.
Arch
,
gotype
,
i
)
fld
:=
newdie
(
ctxt
,
die
,
dwarf
.
DW_ABRV_FUNCTYPEPARAM
,
s
.
Name
[
5
:
],
0
)
...
...
@@ -508,7 +508,7 @@ func newtype(ctxt *Link, gotype *sym.Symbol) *dwarf.DWDie {
case
objabi
.
KindInterface
:
die
=
newdie
(
ctxt
,
&
dwtypes
,
dwarf
.
DW_ABRV_IFACETYPE
,
name
,
0
)
typedefdie
=
dotypedef
(
ctxt
,
&
dwtypes
,
name
,
die
)
nfields
:=
int
(
decodetypeIfaceMethodCount
(
ctxt
.
Arch
,
gotype
))
nfields
:=
int
(
decodetypeIfaceMethodCount
(
ctxt
.
Arch
,
gotype
.
P
))
var
s
*
sym
.
Symbol
if
nfields
==
0
{
s
=
lookupOrDiag
(
ctxt
,
"type.runtime.eface"
)
...
...
@@ -733,7 +733,7 @@ func synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) {
gotype
:=
getattr
(
die
,
dwarf
.
DW_AT_type
)
.
Data
.
(
*
sym
.
Symbol
)
keytype
:=
decodetypeMapKey
(
ctxt
.
Arch
,
gotype
)
valtype
:=
decodetypeMapValue
(
ctxt
.
Arch
,
gotype
)
keysize
,
valsize
:=
decodetypeSize
(
ctxt
.
Arch
,
keytype
),
decodetypeSize
(
ctxt
.
Arch
,
valtype
)
keysize
,
valsize
:=
decodetypeSize
(
ctxt
.
Arch
,
keytype
.
P
),
decodetypeSize
(
ctxt
.
Arch
,
valtype
.
P
)
keytype
,
valtype
=
walksymtypedef
(
ctxt
,
defgotype
(
ctxt
,
keytype
)),
walksymtypedef
(
ctxt
,
defgotype
(
ctxt
,
valtype
))
// compute size info like hashmap.c does.
...
...
src/cmd/link/internal/ld/go.go
View file @
bababde7
...
...
@@ -110,7 +110,6 @@ func ldpkg(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, filename s
return
}
p1
+=
p0
loadcgo
(
ctxt
,
filename
,
objabi
.
PathToPrefix
(
lib
.
Pkg
),
data
[
p0
:
p1
])
}
}
...
...
@@ -123,6 +122,39 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
return
}
// Find cgo_export symbols. They are roots in the deadcode pass.
for
_
,
f
:=
range
directives
{
switch
f
[
0
]
{
case
"cgo_export_static"
,
"cgo_export_dynamic"
:
if
len
(
f
)
<
2
||
len
(
f
)
>
3
{
continue
}
local
:=
f
[
1
]
switch
ctxt
.
BuildMode
{
case
BuildModeCShared
,
BuildModeCArchive
,
BuildModePlugin
:
if
local
==
"main"
{
continue
}
}
local
=
expandpkg
(
local
,
pkg
)
if
f
[
0
]
==
"cgo_export_static"
{
ctxt
.
cgo_export_static
[
local
]
=
true
}
else
{
ctxt
.
cgo_export_dynamic
[
local
]
=
true
}
}
}
if
*
flagNewobj
{
// Record the directives. We'll process them later after Symbols are created.
ctxt
.
cgodata
=
append
(
ctxt
.
cgodata
,
cgodata
{
file
,
pkg
,
directives
})
}
else
{
setCgoAttr
(
ctxt
,
ctxt
.
Syms
.
Lookup
,
file
,
pkg
,
directives
)
}
}
// Set symbol attributes or flags based on cgo directives.
func
setCgoAttr
(
ctxt
*
Link
,
lookup
func
(
string
,
int
)
*
sym
.
Symbol
,
file
string
,
pkg
string
,
directives
[][]
string
)
{
for
_
,
f
:=
range
directives
{
switch
f
[
0
]
{
case
"cgo_import_dynamic"
:
...
...
@@ -164,8 +196,8 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
if
i
:=
strings
.
Index
(
remote
,
"#"
);
i
>=
0
{
remote
,
q
=
remote
[
:
i
],
remote
[
i
+
1
:
]
}
s
:=
ctxt
.
Syms
.
L
ookup
(
local
,
0
)
if
s
.
Type
==
0
||
s
.
Type
==
sym
.
SXREF
||
s
.
Type
==
sym
.
SHOSTOBJ
{
s
:=
l
ookup
(
local
,
0
)
if
s
.
Type
==
0
||
s
.
Type
==
sym
.
SXREF
||
s
.
Type
==
sym
.
S
BSS
||
s
.
Type
==
sym
.
SNOPTRBSS
||
s
.
Type
==
sym
.
S
HOSTOBJ
{
s
.
SetDynimplib
(
lib
)
s
.
SetExtname
(
remote
)
s
.
SetDynimpvers
(
q
)
...
...
@@ -183,7 +215,7 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
}
local
:=
f
[
1
]
s
:=
ctxt
.
Syms
.
L
ookup
(
local
,
0
)
s
:=
l
ookup
(
local
,
0
)
s
.
Type
=
sym
.
SHOSTOBJ
s
.
Size
=
0
continue
...
...
@@ -204,11 +236,11 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
// functions. Link.loadlib will resolve any
// ABI aliases we find here (since we may not
// yet know it's an alias).
s
:=
ctxt
.
Syms
.
L
ookup
(
local
,
0
)
s
:=
l
ookup
(
local
,
0
)
switch
ctxt
.
BuildMode
{
case
BuildModeCShared
,
BuildModeCArchive
,
BuildModePlugin
:
if
s
==
ctxt
.
Syms
.
L
ookup
(
"main"
,
0
)
{
if
s
==
l
ookup
(
"main"
,
0
)
{
continue
}
}
...
...
@@ -223,7 +255,6 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
if
!
s
.
Attr
.
CgoExport
()
{
s
.
SetExtname
(
remote
)
dynexp
=
append
(
dynexp
,
s
)
}
else
if
s
.
Extname
()
!=
remote
{
fmt
.
Fprintf
(
os
.
Stderr
,
"%s: conflicting cgo_export directives: %s as %s and %s
\n
"
,
os
.
Args
[
0
],
s
.
Name
,
s
.
Extname
(),
remote
)
nerrors
++
...
...
src/cmd/link/internal/ld/lib.go
View file @
bababde7
This diff is collapsed.
Click to expand it.
src/cmd/link/internal/ld/link.go
View file @
bababde7
...
...
@@ -35,6 +35,7 @@ import (
"cmd/internal/obj"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/link/internal/loader"
"cmd/link/internal/sym"
"debug/elf"
"fmt"
...
...
@@ -96,6 +97,18 @@ type Link struct {
runtimeCU
*
sym
.
CompilationUnit
// One of the runtime CUs, the last one seen.
relocbuf
[]
byte
// temporary buffer for applying relocations
loader
*
loader
.
Loader
cgodata
[]
cgodata
// cgo directives to load, three strings are args for loadcgo
cgo_export_static
map
[
string
]
bool
cgo_export_dynamic
map
[
string
]
bool
}
type
cgodata
struct
{
file
string
pkg
string
directives
[][]
string
}
type
unresolvedSymKey
struct
{
...
...
src/cmd/link/internal/ld/main.go
View file @
bababde7
...
...
@@ -87,6 +87,7 @@ var (
flagInterpreter
=
flag
.
String
(
"I"
,
""
,
"use `linker` as ELF dynamic linker"
)
FlagDebugTramp
=
flag
.
Int
(
"debugtramp"
,
0
,
"debug trampolines"
)
FlagStrictDups
=
flag
.
Int
(
"strictdups"
,
0
,
"sanity check duplicate symbol contents during object file reading (1=warn 2=err)."
)
flagNewobj
=
flag
.
Bool
(
"newobj"
,
false
,
"use new object file format"
)
FlagRound
=
flag
.
Int
(
"R"
,
-
1
,
"set address rounding `quantum`"
)
FlagTextAddr
=
flag
.
Int64
(
"T"
,
-
1
,
"set text segment `address`"
)
...
...
@@ -208,8 +209,13 @@ func Main(arch *sys.Arch, theArch Arch) {
}
ctxt
.
loadlib
()
ctxt
.
dostrdata
()
deadcode
(
ctxt
)
if
*
flagNewobj
{
ctxt
.
loadlibfull
()
// XXX do it here for now
}
ctxt
.
linksetup
()
ctxt
.
dostrdata
()
dwarfGenerateDebugInfo
(
ctxt
)
if
objabi
.
Fieldtrack_enabled
!=
0
{
fieldtrack
(
ctxt
)
...
...
src/cmd/link/internal/ld/pcln.go
View file @
bababde7
...
...
@@ -305,10 +305,10 @@ func (ctxt *Link) pclntab() {
// appears in the Pcfile table. In that case, this assigns
// the outer file a number.
numberfile
(
ctxt
,
call
.
File
)
nameoff
:=
nameToOffset
(
call
.
Func
.
Name
)
nameoff
:=
nameToOffset
(
call
.
Func
)
inlTreeSym
.
SetUint16
(
ctxt
.
Arch
,
int64
(
i
*
20
+
0
),
uint16
(
call
.
Parent
))
inlTreeSym
.
SetUint8
(
ctxt
.
Arch
,
int64
(
i
*
20
+
2
),
uint8
(
objabi
.
GetFuncID
(
call
.
Func
.
Name
,
call
.
Func
.
File
)))
inlTreeSym
.
SetUint8
(
ctxt
.
Arch
,
int64
(
i
*
20
+
2
),
uint8
(
objabi
.
GetFuncID
(
call
.
Func
,
""
)))
// byte 3 is unused
inlTreeSym
.
SetUint32
(
ctxt
.
Arch
,
int64
(
i
*
20
+
4
),
uint32
(
call
.
File
.
Value
))
inlTreeSym
.
SetUint32
(
ctxt
.
Arch
,
int64
(
i
*
20
+
8
),
uint32
(
call
.
Line
))
...
...
src/cmd/link/internal/ld/symtab.go
View file @
bababde7
...
...
@@ -694,7 +694,7 @@ func (ctxt *Link) symtab() {
// creating the moduledata from scratch and it does not have a
// compiler-provided size, so read it from the type data.
moduledatatype
:=
ctxt
.
Syms
.
ROLookup
(
"type.runtime.moduledata"
,
0
)
moduledata
.
Size
=
decodetypeSize
(
ctxt
.
Arch
,
moduledatatype
)
moduledata
.
Size
=
decodetypeSize
(
ctxt
.
Arch
,
moduledatatype
.
P
)
moduledata
.
Grow
(
moduledata
.
Size
)
lastmoduledatap
:=
ctxt
.
Syms
.
Lookup
(
"runtime.lastmoduledatap"
,
0
)
...
...
src/cmd/link/internal/ld/util.go
View file @
bababde7
...
...
@@ -88,3 +88,10 @@ func contains(s []string, v string) bool {
}
return
false
}
// implements sort.Interface, for sorting symbols by name.
type
byName
[]
*
sym
.
Symbol
func
(
s
byName
)
Len
()
int
{
return
len
(
s
)
}
func
(
s
byName
)
Swap
(
i
,
j
int
)
{
s
[
i
],
s
[
j
]
=
s
[
j
],
s
[
i
]
}
func
(
s
byName
)
Less
(
i
,
j
int
)
bool
{
return
s
[
i
]
.
Name
<
s
[
j
]
.
Name
}
src/cmd/link/internal/loadelf/ldelf.go
View file @
bababde7
...
...
@@ -10,6 +10,7 @@ import (
"cmd/internal/bio"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/link/internal/loader"
"cmd/link/internal/sym"
"debug/elf"
"encoding/binary"
...
...
@@ -451,7 +452,20 @@ func parseArmAttributes(e binary.ByteOrder, data []byte) (found bool, ehdrFlags
return
found
,
ehdrFlags
,
nil
}
// Load loads the ELF file pn from f.
func
Load
(
l
*
loader
.
Loader
,
arch
*
sys
.
Arch
,
syms
*
sym
.
Symbols
,
f
*
bio
.
Reader
,
pkg
string
,
length
int64
,
pn
string
,
flags
uint32
)
([]
*
sym
.
Symbol
,
uint32
,
error
)
{
newSym
:=
func
(
name
string
,
version
int
)
*
sym
.
Symbol
{
return
l
.
LookupOrCreate
(
name
,
version
,
syms
)
}
return
load
(
arch
,
syms
.
IncVersion
(),
newSym
,
newSym
,
f
,
pkg
,
length
,
pn
,
flags
)
}
func
LoadOld
(
arch
*
sys
.
Arch
,
syms
*
sym
.
Symbols
,
f
*
bio
.
Reader
,
pkg
string
,
length
int64
,
pn
string
,
flags
uint32
)
([]
*
sym
.
Symbol
,
uint32
,
error
)
{
return
load
(
arch
,
syms
.
IncVersion
(),
syms
.
Newsym
,
syms
.
Lookup
,
f
,
pkg
,
length
,
pn
,
flags
)
}
type
lookupFunc
func
(
string
,
int
)
*
sym
.
Symbol
// load loads the ELF file pn from f.
// Symbols are written into syms, and a slice of the text symbols is returned.
//
// On ARM systems, Load will attempt to determine what ELF header flags to
...
...
@@ -459,12 +473,11 @@ func parseArmAttributes(e binary.ByteOrder, data []byte) (found bool, ehdrFlags
// parameter initEhdrFlags contains the current header flags for the output
// object, and the returned ehdrFlags contains what this Load function computes.
// TODO: find a better place for this logic.
func
Load
(
arch
*
sys
.
Arch
,
syms
*
sym
.
Symbols
,
f
*
bio
.
Reader
,
pkg
string
,
length
int64
,
pn
string
,
initEhdrFlags
uint32
)
(
textp
[]
*
sym
.
Symbol
,
ehdrFlags
uint32
,
err
error
)
{
func
load
(
arch
*
sys
.
Arch
,
localSymVersion
int
,
newSym
,
lookup
lookupFunc
,
f
*
bio
.
Reader
,
pkg
string
,
length
int64
,
pn
string
,
initEhdrFlags
uint32
)
(
textp
[]
*
sym
.
Symbol
,
ehdrFlags
uint32
,
err
error
)
{
errorf
:=
func
(
str
string
,
args
...
interface
{})
([]
*
sym
.
Symbol
,
uint32
,
error
)
{
return
nil
,
0
,
fmt
.
Errorf
(
"loadelf: %s: %v"
,
pn
,
fmt
.
Sprintf
(
str
,
args
...
))
}
localSymVersion
:=
syms
.
IncVersion
()
base
:=
f
.
Offset
()
var
hdrbuf
[
64
]
uint8
...
...
@@ -715,7 +728,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length i
}
sectsymNames
[
name
]
=
true
s
:=
syms
.
L
ookup
(
name
,
localSymVersion
)
s
:=
l
ookup
(
name
,
localSymVersion
)
switch
int
(
sect
.
flags
)
&
(
ElfSectFlagAlloc
|
ElfSectFlagWrite
|
ElfSectFlagExec
)
{
default
:
...
...
@@ -754,7 +767,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length i
for
i
:=
1
;
i
<
elfobj
.
nsymtab
;
i
++
{
var
elfsym
ElfSym
if
err
:=
readelfsym
(
arch
,
syms
,
elfobj
,
i
,
&
elfsym
,
1
,
localSymVersion
);
err
!=
nil
{
if
err
:=
readelfsym
(
newSym
,
lookup
,
arch
,
elfobj
,
i
,
&
elfsym
,
1
,
localSymVersion
);
err
!=
nil
{
return
errorf
(
"%s: malformed elf file: %v"
,
pn
,
err
)
}
symbols
[
i
]
=
elfsym
.
sym
...
...
@@ -925,7 +938,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length i
rp
.
Sym
=
nil
}
else
{
var
elfsym
ElfSym
if
err
:=
readelfsym
(
arch
,
syms
,
elfobj
,
int
(
info
>>
32
),
&
elfsym
,
0
,
0
);
err
!=
nil
{
if
err
:=
readelfsym
(
newSym
,
lookup
,
arch
,
elfobj
,
int
(
info
>>
32
),
&
elfsym
,
0
,
0
);
err
!=
nil
{
return
errorf
(
"malformed elf file: %v"
,
err
)
}
elfsym
.
sym
=
symbols
[
info
>>
32
]
...
...
@@ -1002,7 +1015,7 @@ func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
return
nil
}
func
readelfsym
(
arch
*
sys
.
Arch
,
syms
*
sym
.
Symbols
,
elfobj
*
ElfObj
,
i
int
,
elfsym
*
ElfSym
,
needSym
int
,
localSymVersion
int
)
(
err
error
)
{
func
readelfsym
(
newSym
,
lookup
lookupFunc
,
arch
*
sys
.
Arch
,
elfobj
*
ElfObj
,
i
int
,
elfsym
*
ElfSym
,
needSym
int
,
localSymVersion
int
)
(
err
error
)
{
if
i
>=
elfobj
.
nsymtab
||
i
<
0
{
err
=
fmt
.
Errorf
(
"invalid elf symbol index"
)
return
err
...
...
@@ -1052,7 +1065,7 @@ func readelfsym(arch *sys.Arch, syms *sym.Symbols, elfobj *ElfObj, i int, elfsym
switch
elfsym
.
bind
{
case
ElfSymBindGlobal
:
if
needSym
!=
0
{
s
=
syms
.
L
ookup
(
elfsym
.
name
,
0
)
s
=
l
ookup
(
elfsym
.
name
,
0
)
// for global scoped hidden symbols we should insert it into
// symbol hash table, but mark them as hidden.
...
...
@@ -1077,7 +1090,7 @@ func readelfsym(arch *sys.Arch, syms *sym.Symbols, elfobj *ElfObj, i int, elfsym
// We need to be able to look this up,
// so put it in the hash table.
if
needSym
!=
0
{
s
=
syms
.
L
ookup
(
elfsym
.
name
,
localSymVersion
)
s
=
l
ookup
(
elfsym
.
name
,
localSymVersion
)
s
.
Attr
|=
sym
.
AttrVisibilityHidden
}
...
...
@@ -1088,14 +1101,14 @@ func readelfsym(arch *sys.Arch, syms *sym.Symbols, elfobj *ElfObj, i int, elfsym
// local names and hidden global names are unique
// and should only be referenced by their index, not name, so we
// don't bother to add them into the hash table
s
=
syms
.
News
ym
(
elfsym
.
name
,
localSymVersion
)
s
=
newS
ym
(
elfsym
.
name
,
localSymVersion
)
s
.
Attr
|=
sym
.
AttrVisibilityHidden
}
case
ElfSymBindWeak
:
if
needSym
!=
0
{
s
=
syms
.
L
ookup
(
elfsym
.
name
,
0
)
s
=
l
ookup
(
elfsym
.
name
,
0
)
if
elfsym
.
other
==
2
{
s
.
Attr
|=
sym
.
AttrVisibilityHidden
}
...
...
src/cmd/link/internal/loader/loader.go
0 → 100644
View file @
bababde7
This diff is collapsed.
Click to expand it.
src/cmd/link/internal/loadmacho/ldmacho.go
View file @
bababde7
...
...
@@ -10,6 +10,7 @@ import (
"cmd/internal/bio"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/link/internal/loader"
"cmd/link/internal/sym"
"encoding/binary"
"fmt"
...
...
@@ -423,14 +424,24 @@ func macholoadsym(m *ldMachoObj, symtab *ldMachoSymtab) int {
return
0
}
// Load loads the Mach-O file pn from f.
func
Load
(
l
*
loader
.
Loader
,
arch
*
sys
.
Arch
,
syms
*
sym
.
Symbols
,
f
*
bio
.
Reader
,
pkg
string
,
length
int64
,
pn
string
)
([]
*
sym
.
Symbol
,
error
)
{
newSym
:=
func
(
name
string
,
version
int
)
*
sym
.
Symbol
{
return
l
.
LookupOrCreate
(
name
,
version
,
syms
)
}
return
load
(
arch
,
syms
.
IncVersion
(),
newSym
,
f
,
pkg
,
length
,
pn
)
}
func
LoadOld
(
arch
*
sys
.
Arch
,
syms
*
sym
.
Symbols
,
f
*
bio
.
Reader
,
pkg
string
,
length
int64
,
pn
string
)
(
textp
[]
*
sym
.
Symbol
,
err
error
)
{
return
load
(
arch
,
syms
.
IncVersion
(),
syms
.
Lookup
,
f
,
pkg
,
length
,
pn
)
}
// load the Mach-O file pn from f.
// Symbols are written into syms, and a slice of the text symbols is returned.
func
Load
(
arch
*
sys
.
Arch
,
syms
*
sym
.
Symbols
,
f
*
bio
.
Reader
,
pkg
string
,
length
int64
,
pn
string
)
(
textp
[]
*
sym
.
Symbol
,
err
error
)
{
func
load
(
arch
*
sys
.
Arch
,
localSymVersion
int
,
lookup
func
(
string
,
int
)
*
sym
.
Symbol
,
f
*
bio
.
Reader
,
pkg
string
,
length
int64
,
pn
string
)
(
textp
[]
*
sym
.
Symbol
,
err
error
)
{
errorf
:=
func
(
str
string
,
args
...
interface
{})
([]
*
sym
.
Symbol
,
error
)
{
return
nil
,
fmt
.
Errorf
(
"loadmacho: %v: %v"
,
pn
,
fmt
.
Sprintf
(
str
,
args
...
))
}
localSymVersion
:=
syms
.
IncVersion
()
base
:=
f
.
Offset
()
var
hdr
[
7
*
4
]
uint8
...
...
@@ -562,7 +573,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length i
continue
}
name
:=
fmt
.
Sprintf
(
"%s(%s/%s)"
,
pkg
,
sect
.
segname
,
sect
.
name
)
s
:=
syms
.
L
ookup
(
name
,
localSymVersion
)
s
:=
l
ookup
(
name
,
localSymVersion
)
if
s
.
Type
!=
0
{
return
errorf
(
"duplicate %s/%s"
,
sect
.
segname
,
sect
.
name
)
}
...
...
@@ -610,7 +621,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length i
if
machsym
.
type_
&
N_EXT
==
0
{
v
=
localSymVersion
}
s
:=
syms
.
L
ookup
(
name
,
v
)
s
:=
l
ookup
(
name
,
v
)
if
machsym
.
type_
&
N_EXT
==
0
{
s
.
Attr
|=
sym
.
AttrDuplicateOK
}
...
...
src/cmd/link/internal/loadpe/ldpe.go
View file @
bababde7
...
...
@@ -9,6 +9,7 @@ import (
"cmd/internal/bio"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/link/internal/loader"
"cmd/link/internal/sym"
"debug/pe"
"encoding/binary"
...
...
@@ -144,12 +145,21 @@ func (f *peBiobuf) ReadAt(p []byte, off int64) (int, error) {
return
n
,
nil
}
// Load loads the PE file pn from input.
func
Load
(
l
*
loader
.
Loader
,
arch
*
sys
.
Arch
,
syms
*
sym
.
Symbols
,
input
*
bio
.
Reader
,
pkg
string
,
length
int64
,
pn
string
)
(
textp
[]
*
sym
.
Symbol
,
rsrc
*
sym
.
Symbol
,
err
error
)
{
lookup
:=
func
(
name
string
,
version
int
)
*
sym
.
Symbol
{
return
l
.
LookupOrCreate
(
name
,
version
,
syms
)
}
return
load
(
arch
,
lookup
,
syms
.
IncVersion
(),
input
,
pkg
,
length
,
pn
)
}
func
LoadOld
(
arch
*
sys
.
Arch
,
syms
*
sym
.
Symbols
,
input
*
bio
.
Reader
,
pkg
string
,
length
int64
,
pn
string
)
(
textp
[]
*
sym
.
Symbol
,
rsrc
*
sym
.
Symbol
,
err
error
)
{
return
load
(
arch
,
syms
.
Lookup
,
syms
.
IncVersion
(),
input
,
pkg
,
length
,
pn
)
}
// load loads the PE file pn from input.
// Symbols are written into syms, and a slice of the text symbols is returned.
// If an .rsrc section is found, its symbol is returned as rsrc.
func
Load
(
arch
*
sys
.
Arch
,
syms
*
sym
.
Symbols
,
input
*
bio
.
Reader
,
pkg
string
,
length
int64
,
pn
string
)
(
textp
[]
*
sym
.
Symbol
,
rsrc
*
sym
.
Symbol
,
err
error
)
{
localSymVersion
:=
syms
.
IncVersion
()
func
load
(
arch
*
sys
.
Arch
,
lookup
func
(
string
,
int
)
*
sym
.
Symbol
,
localSymVersion
int
,
input
*
bio
.
Reader
,
pkg
string
,
length
int64
,
pn
string
)
(
textp
[]
*
sym
.
Symbol
,
rsrc
*
sym
.
Symbol
,
err
error
)
{
sectsyms
:=
make
(
map
[
*
pe
.
Section
]
*
sym
.
Symbol
)
sectdata
:=
make
(
map
[
*
pe
.
Section
][]
byte
)
...
...
@@ -181,7 +191,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, leng
}
name
:=
fmt
.
Sprintf
(
"%s(%s)"
,
pkg
,
sect
.
Name
)
s
:=
syms
.
L
ookup
(
name
,
localSymVersion
)
s
:=
l
ookup
(
name
,
localSymVersion
)
switch
sect
.
Characteristics
&
(
IMAGE_SCN_CNT_UNINITIALIZED_DATA
|
IMAGE_SCN_CNT_INITIALIZED_DATA
|
IMAGE_SCN_MEM_READ
|
IMAGE_SCN_MEM_WRITE
|
IMAGE_SCN_CNT_CODE
|
IMAGE_SCN_MEM_EXECUTE
)
{
case
IMAGE_SCN_CNT_INITIALIZED_DATA
|
IMAGE_SCN_MEM_READ
:
//.rdata
...
...
@@ -239,7 +249,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, leng
return
nil
,
nil
,
fmt
.
Errorf
(
"relocation number %d symbol index idx=%d cannot be large then number of symbols %d"
,
j
,
r
.
SymbolTableIndex
,
len
(
f
.
COFFSymbols
))
}
pesym
:=
&
f
.
COFFSymbols
[
r
.
SymbolTableIndex
]
gosym
,
err
:=
readpesym
(
arch
,
syms
,
f
,
pesym
,
sectsyms
,
localSymVersion
)
gosym
,
err
:=
readpesym
(
arch
,
lookup
,
f
,
pesym
,
sectsyms
,
localSymVersion
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
...
...
@@ -351,7 +361,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, leng
}
}
s
,
err
:=
readpesym
(
arch
,
syms
,
f
,
pesym
,
sectsyms
,
localSymVersion
)
s
,
err
:=
readpesym
(
arch
,
lookup
,
f
,
pesym
,
sectsyms
,
localSymVersion
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
...
...
@@ -435,7 +445,7 @@ func issect(s *pe.COFFSymbol) bool {
return
s
.
StorageClass
==
IMAGE_SYM_CLASS_STATIC
&&
s
.
Type
==
0
&&
s
.
Name
[
0
]
==
'.'
}
func
readpesym
(
arch
*
sys
.
Arch
,
syms
*
sym
.
Symbols
,
f
*
pe
.
File
,
pesym
*
pe
.
COFFSymbol
,
sectsyms
map
[
*
pe
.
Section
]
*
sym
.
Symbol
,
localSymVersion
int
)
(
*
sym
.
Symbol
,
error
)
{
func
readpesym
(
arch
*
sys
.
Arch
,
lookup
func
(
string
,
int
)
*
sym
.
Symbol
,
f
*
pe
.
File
,
pesym
*
pe
.
COFFSymbol
,
sectsyms
map
[
*
pe
.
Section
]
*
sym
.
Symbol
,
localSymVersion
int
)
(
*
sym
.
Symbol
,
error
)
{
symname
,
err
:=
pesym
.
FullName
(
f
.
StringTable
)
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -481,10 +491,10 @@ func readpesym(arch *sys.Arch, syms *sym.Symbols, f *pe.File, pesym *pe.COFFSymb
case
IMAGE_SYM_DTYPE_FUNCTION
,
IMAGE_SYM_DTYPE_NULL
:
switch
pesym
.
StorageClass
{
case
IMAGE_SYM_CLASS_EXTERNAL
:
//global
s
=
syms
.
L
ookup
(
name
,
0
)
s
=
l
ookup
(
name
,
0
)
case
IMAGE_SYM_CLASS_NULL
,
IMAGE_SYM_CLASS_STATIC
,
IMAGE_SYM_CLASS_LABEL
:
s
=
syms
.
L
ookup
(
name
,
localSymVersion
)
s
=
l
ookup
(
name
,
localSymVersion
)
s
.
Attr
|=
sym
.
AttrDuplicateOK
default
:
...
...
src/cmd/link/internal/loadxcoff/ldxcoff.go
View file @
bababde7
...
...
@@ -9,6 +9,7 @@ import (
"cmd/internal/bio"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/link/internal/loader"
"cmd/link/internal/sym"
"errors"
"fmt"
...
...
@@ -38,13 +39,25 @@ func (f *xcoffBiobuf) ReadAt(p []byte, off int64) (int, error) {
return
n
,
nil
}
// Load loads the Xcoff file pn from f.
// Load loads xcoff files with the indexed object files.
func
Load
(
l
*
loader
.
Loader
,
arch
*
sys
.
Arch
,
syms
*
sym
.
Symbols
,
input
*
bio
.
Reader
,
pkg
string
,
length
int64
,
pn
string
)
(
textp
[]
*
sym
.
Symbol
,
err
error
)
{
lookup
:=
func
(
name
string
,
version
int
)
*
sym
.
Symbol
{
return
l
.
LookupOrCreate
(
name
,
version
,
syms
)
}
return
load
(
arch
,
lookup
,
syms
.
IncVersion
(),
input
,
pkg
,
length
,
pn
)
}
// LoadOld uses the old version of object loading.
func
LoadOld
(
arch
*
sys
.
Arch
,
syms
*
sym
.
Symbols
,
input
*
bio
.
Reader
,
pkg
string
,
length
int64
,
pn
string
)
(
textp
[]
*
sym
.
Symbol
,
err
error
)
{
return
load
(
arch
,
syms
.
Lookup
,
syms
.
IncVersion
(),
input
,
pkg
,
length
,
pn
)
}
// loads the Xcoff file pn from f.
// Symbols are written into syms, and a slice of the text symbols is returned.
func
Load
(
arch
*
sys
.
Arch
,
syms
*
sym
.
Symbols
,
input
*
bio
.
Reader
,
pkg
string
,
length
int64
,
pn
string
)
(
textp
[]
*
sym
.
Symbol
,
err
error
)
{
func
load
(
arch
*
sys
.
Arch
,
lookup
func
(
string
,
int
)
*
sym
.
Symbol
,
localSymVersion
int
,
input
*
bio
.
Reader
,
pkg
string
,
length
int64
,
pn
string
)
(
textp
[]
*
sym
.
Symbol
,
err
error
)
{
errorf
:=
func
(
str
string
,
args
...
interface
{})
([]
*
sym
.
Symbol
,
error
)
{
return
nil
,
fmt
.
Errorf
(
"loadxcoff: %v: %v"
,
pn
,
fmt
.
Sprintf
(
str
,
args
...
))
}
localSymVersion
:=
syms
.
IncVersion
()
var
ldSections
[]
*
ldSection
...
...
@@ -62,7 +75,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, leng
lds
:=
new
(
ldSection
)
lds
.
Section
=
*
sect
name
:=
fmt
.
Sprintf
(
"%s(%s)"
,
pkg
,
lds
.
Name
)
s
:=
syms
.
L
ookup
(
name
,
localSymVersion
)
s
:=
l
ookup
(
name
,
localSymVersion
)
switch
lds
.
Type
{
default
:
...
...
@@ -100,7 +113,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, leng
continue
}
s
:=
syms
.
L
ookup
(
sx
.
Name
,
0
)
s
:=
l
ookup
(
sx
.
Name
,
0
)
// Text symbol
if
s
.
Type
==
sym
.
STEXT
{
...
...
@@ -122,7 +135,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, leng
for
i
,
rx
:=
range
sect
.
Relocs
{
r
:=
&
rs
[
i
]
r
.
Sym
=
syms
.
L
ookup
(
rx
.
Symbol
.
Name
,
0
)
r
.
Sym
=
l
ookup
(
rx
.
Symbol
.
Name
,
0
)
if
uint64
(
int32
(
rx
.
VirtualAddress
))
!=
rx
.
VirtualAddress
{
return
errorf
(
"virtual address of a relocation is too big: 0x%x"
,
rx
.
VirtualAddress
)
}
...
...
src/cmd/link/internal/objfile/objfile.go
View file @
bababde7
...
...
@@ -369,7 +369,7 @@ overwrite:
pc
.
InlTree
[
i
]
.
Parent
=
r
.
readInt32
()
pc
.
InlTree
[
i
]
.
File
=
r
.
readSymIndex
()
pc
.
InlTree
[
i
]
.
Line
=
r
.
readInt32
()
pc
.
InlTree
[
i
]
.
Func
=
r
.
readSymIndex
()
pc
.
InlTree
[
i
]
.
Func
=
r
.
readSymIndex
()
.
Name
pc
.
InlTree
[
i
]
.
ParentPC
=
r
.
readInt32
()
}
...
...
src/cmd/link/internal/ppc64/asm.go
View file @
bababde7
...
...
@@ -550,7 +550,7 @@ func archreloctoc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
const
prefix
=
"TOC."
var
tarSym
*
sym
.
Symbol
if
strings
.
HasPrefix
(
r
.
Sym
.
Name
,
prefix
)
{
tarSym
=
ctxt
.
Syms
.
ROLookup
(
strings
.
TrimPrefix
(
r
.
Sym
.
Name
,
prefix
),
0
)
tarSym
=
r
.
Sym
.
R
[
0
]
.
Sym
}
else
{
ld
.
Errorf
(
s
,
"archreloctoc called for a symbol without TOC anchor"
)
}
...
...
src/cmd/link/internal/sym/symbol.go
View file @
bababde7
...
...
@@ -534,7 +534,7 @@ type InlinedCall struct {
Parent
int32
// index of parent in InlTree
File
*
Symbol
// file of the inlined call
Line
int32
// line number of the inlined call
Func
*
Symbol
//
function that was inlined
Func
string
// name of the
function that was inlined
ParentPC
int32
// PC of the instruction just before the inlined body (offset from function start)
}
...
...
src/cmd/link/internal/sym/symbols.go
View file @
bababde7
...
...
@@ -86,6 +86,17 @@ func (syms *Symbols) ROLookup(name string, v int) *Symbol {
return
syms
.
hash
[
v
][
name
]
}
// Add an existing symbol to the symbol table.
func
(
syms
*
Symbols
)
Add
(
s
*
Symbol
)
{
name
:=
s
.
Name
v
:=
int
(
s
.
Version
)
m
:=
syms
.
hash
[
v
]
if
_
,
ok
:=
m
[
name
];
ok
{
panic
(
name
+
" already added"
)
}
m
[
name
]
=
s
}
// Allocate a new version (i.e. symbol namespace).
func
(
syms
*
Symbols
)
IncVersion
()
int
{
syms
.
hash
=
append
(
syms
.
hash
,
make
(
map
[
string
]
*
Symbol
))
...
...
src/cmd/link/internal/sym/symkind.go
View file @
bababde7
...
...
@@ -161,3 +161,8 @@ var RelROMap = map[SymKind]SymKind{
SRODATA
:
SRODATARELRO
,
SFUNCTAB
:
SFUNCTABRELRO
,
}
// IsData returns true if the type is a data type.
func
(
t
SymKind
)
IsData
()
bool
{
return
t
==
SDATA
||
t
==
SNOPTRDATA
||
t
==
SBSS
||
t
==
SNOPTRBSS
}
src/cmd/link/link_test.go
View file @
bababde7
...
...
@@ -376,3 +376,68 @@ func TestIssue34788Android386TLSSequence(t *testing.T) {
}
}
}
const
testStrictDupGoSrc
=
`
package main
func f()
func main() { f() }
`
const
testStrictDupAsmSrc1
=
`
#include "textflag.h"
TEXT ·f(SB), NOSPLIT|DUPOK, $0-0
RET
`
const
testStrictDupAsmSrc2
=
`
#include "textflag.h"
TEXT ·f(SB), NOSPLIT|DUPOK, $0-0
JMP 0(PC)
`
func
TestStrictDup
(
t
*
testing
.
T
)
{
// Check that -strictdups flag works.
testenv
.
MustHaveGoBuild
(
t
)
tmpdir
,
err
:=
ioutil
.
TempDir
(
""
,
"TestStrictDup"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
defer
os
.
RemoveAll
(
tmpdir
)
src
:=
filepath
.
Join
(
tmpdir
,
"x.go"
)
err
=
ioutil
.
WriteFile
(
src
,
[]
byte
(
testStrictDupGoSrc
),
0666
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
src
=
filepath
.
Join
(
tmpdir
,
"a.s"
)
err
=
ioutil
.
WriteFile
(
src
,
[]
byte
(
testStrictDupAsmSrc1
),
0666
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
src
=
filepath
.
Join
(
tmpdir
,
"b.s"
)
err
=
ioutil
.
WriteFile
(
src
,
[]
byte
(
testStrictDupAsmSrc2
),
0666
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
cmd
:=
exec
.
Command
(
testenv
.
GoToolPath
(
t
),
"build"
,
"-ldflags=-strictdups=1"
)
cmd
.
Dir
=
tmpdir
out
,
err
:=
cmd
.
CombinedOutput
()
if
err
!=
nil
{
t
.
Errorf
(
"linking with -strictdups=1 failed: %v"
,
err
)
}
if
!
bytes
.
Contains
(
out
,
[]
byte
(
"mismatched payload"
))
{
t
.
Errorf
(
"unexpected output:
\n
%s"
,
out
)
}
cmd
=
exec
.
Command
(
testenv
.
GoToolPath
(
t
),
"build"
,
"-ldflags=-strictdups=2"
)
cmd
.
Dir
=
tmpdir
out
,
err
=
cmd
.
CombinedOutput
()
if
err
==
nil
{
t
.
Errorf
(
"linking with -strictdups=2 did not fail"
)
}
if
!
bytes
.
Contains
(
out
,
[]
byte
(
"mismatched payload"
))
{
t
.
Errorf
(
"unexpected output:
\n
%s"
,
out
)
}
}
src/runtime/internal/atomic/sys_linux_arm.s
View file @
bababde7
...
...
@@ -29,9 +29,9 @@ TEXT runtime∕internal∕atomic·Cas(SB),NOSPLIT|NOFRAME,$0
CMP
$
7
,
R11
BLT
2
(
PC
)
JMP
·
armcas
(
SB
)
JMP
·
kernelcas
<>(
SB
)
JMP
kernelcas
<>(
SB
)
TEXT
runtime
∕
internal
∕
atomic
·
kernelcas
<>(
SB
),
NOSPLIT
,$0
TEXT
kernelcas
<>(
SB
),
NOSPLIT
,$0
MOVW
ptr
+
0
(
FP
),
R2
//
trigger
potential
paging
fault
here
,
//
because
we
don
't know how to traceback through __kuser_cmpxchg
...
...
test/linkx.go
View file @
bababde7
...
...
@@ -29,4 +29,10 @@ func main() {
fmt
.
Println
(
overwrite
)
fmt
.
Println
(
overwritecopy
)
fmt
.
Println
(
arraycopy
[
1
])
// Check non-string symbols are not overwritten.
// This also make them used.
if
b
||
x
!=
0
{
panic
(
"b or x overwritten"
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment