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 (
...
@@ -23,6 +23,7 @@ var (
Dynlink
=
flag
.
Bool
(
"dynlink"
,
false
,
"support references to Go symbols defined in other shared libraries"
)
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"
)
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"
)
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
(
var
(
...
...
src/cmd/asm/main.go
View file @
bababde7
...
@@ -40,18 +40,18 @@ func main() {
...
@@ -40,18 +40,18 @@ func main() {
}
}
ctxt
.
Flag_dynlink
=
*
flags
.
Dynlink
ctxt
.
Flag_dynlink
=
*
flags
.
Dynlink
ctxt
.
Flag_shared
=
*
flags
.
Shared
||
*
flags
.
Dynlink
ctxt
.
Flag_shared
=
*
flags
.
Shared
||
*
flags
.
Dynlink
ctxt
.
Flag_newobj
=
*
flags
.
Newobj
ctxt
.
Bso
=
bufio
.
NewWriter
(
os
.
Stdout
)
ctxt
.
Bso
=
bufio
.
NewWriter
(
os
.
Stdout
)
defer
ctxt
.
Bso
.
Flush
()
defer
ctxt
.
Bso
.
Flush
()
architecture
.
Init
(
ctxt
)
architecture
.
Init
(
ctxt
)
// Create object file, write header.
// Create object file, write header.
out
,
err
:=
os
.
Create
(
*
flags
.
OutputFile
)
buf
,
err
:=
bio
.
Create
(
*
flags
.
OutputFile
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Fatal
(
err
)
log
.
Fatal
(
err
)
}
}
defer
bio
.
MustClose
(
out
)
defer
buf
.
Close
()
buf
:=
bufio
.
NewWriter
(
bio
.
MustWriter
(
out
))
if
!*
flags
.
SymABIs
{
if
!*
flags
.
SymABIs
{
fmt
.
Fprintf
(
buf
,
"go object %s %s %s
\n
"
,
objabi
.
GOOS
,
objabi
.
GOARCH
,
objabi
.
Version
)
fmt
.
Fprintf
(
buf
,
"go object %s %s %s
\n
"
,
objabi
.
GOOS
,
objabi
.
GOARCH
,
objabi
.
Version
)
...
@@ -83,6 +83,7 @@ func main() {
...
@@ -83,6 +83,7 @@ func main() {
}
}
}
}
if
ok
&&
!*
flags
.
SymABIs
{
if
ok
&&
!*
flags
.
SymABIs
{
ctxt
.
NumberSyms
(
true
)
obj
.
WriteObjFile
(
ctxt
,
buf
,
""
)
obj
.
WriteObjFile
(
ctxt
,
buf
,
""
)
}
}
if
!
ok
||
diag
{
if
!
ok
||
diag
{
...
@@ -91,9 +92,8 @@ func main() {
...
@@ -91,9 +92,8 @@ func main() {
}
else
{
}
else
{
log
.
Print
(
"assembly failed"
)
log
.
Print
(
"assembly failed"
)
}
}
out
.
Close
()
buf
.
Close
()
os
.
Remove
(
*
flags
.
OutputFile
)
os
.
Remove
(
*
flags
.
OutputFile
)
os
.
Exit
(
1
)
os
.
Exit
(
1
)
}
}
buf
.
Flush
()
}
}
src/cmd/compile/internal/gc/iexport.go
View file @
bababde7
...
@@ -203,6 +203,7 @@ import (
...
@@ -203,6 +203,7 @@ import (
"bufio"
"bufio"
"bytes"
"bytes"
"cmd/compile/internal/types"
"cmd/compile/internal/types"
"cmd/internal/goobj2"
"cmd/internal/src"
"cmd/internal/src"
"encoding/binary"
"encoding/binary"
"fmt"
"fmt"
...
@@ -945,10 +946,12 @@ func (w *exportWriter) string(s string) { w.uint64(w.p.stringOff(s)) }
...
@@ -945,10 +946,12 @@ func (w *exportWriter) string(s string) { w.uint64(w.p.stringOff(s)) }
func
(
w
*
exportWriter
)
varExt
(
n
*
Node
)
{
func
(
w
*
exportWriter
)
varExt
(
n
*
Node
)
{
w
.
linkname
(
n
.
Sym
)
w
.
linkname
(
n
.
Sym
)
w
.
symIdx
(
n
.
Sym
)
}
}
func
(
w
*
exportWriter
)
funcExt
(
n
*
Node
)
{
func
(
w
*
exportWriter
)
funcExt
(
n
*
Node
)
{
w
.
linkname
(
n
.
Sym
)
w
.
linkname
(
n
.
Sym
)
w
.
symIdx
(
n
.
Sym
)
// Escape analysis.
// Escape analysis.
for
_
,
fs
:=
range
types
.
RecvsParams
{
for
_
,
fs
:=
range
types
.
RecvsParams
{
...
@@ -987,6 +990,22 @@ func (w *exportWriter) linkname(s *types.Sym) {
...
@@ -987,6 +990,22 @@ func (w *exportWriter) linkname(s *types.Sym) {
w
.
string
(
s
.
Linkname
)
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.
// Inline bodies.
func
(
w
*
exportWriter
)
stmtList
(
list
Nodes
)
{
func
(
w
*
exportWriter
)
stmtList
(
list
Nodes
)
{
...
...
src/cmd/compile/internal/gc/iimport.go
View file @
bababde7
...
@@ -10,6 +10,7 @@ package gc
...
@@ -10,6 +10,7 @@ package gc
import
(
import
(
"cmd/compile/internal/types"
"cmd/compile/internal/types"
"cmd/internal/bio"
"cmd/internal/bio"
"cmd/internal/obj"
"cmd/internal/src"
"cmd/internal/src"
"encoding/binary"
"encoding/binary"
"fmt"
"fmt"
...
@@ -651,10 +652,12 @@ func (r *importReader) byte() byte {
...
@@ -651,10 +652,12 @@ func (r *importReader) byte() byte {
func
(
r
*
importReader
)
varExt
(
n
*
Node
)
{
func
(
r
*
importReader
)
varExt
(
n
*
Node
)
{
r
.
linkname
(
n
.
Sym
)
r
.
linkname
(
n
.
Sym
)
r
.
symIdx
(
n
.
Sym
)
}
}
func
(
r
*
importReader
)
funcExt
(
n
*
Node
)
{
func
(
r
*
importReader
)
funcExt
(
n
*
Node
)
{
r
.
linkname
(
n
.
Sym
)
r
.
linkname
(
n
.
Sym
)
r
.
symIdx
(
n
.
Sym
)
// Escape analysis.
// Escape analysis.
for
_
,
fs
:=
range
types
.
RecvsParams
{
for
_
,
fs
:=
range
types
.
RecvsParams
{
...
@@ -683,6 +686,20 @@ func (r *importReader) linkname(s *types.Sym) {
...
@@ -683,6 +686,20 @@ func (r *importReader) linkname(s *types.Sym) {
s
.
Linkname
=
r
.
string
()
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
)
{
func
(
r
*
importReader
)
doInline
(
n
*
Node
)
{
if
len
(
n
.
Func
.
Inl
.
Body
)
!=
0
{
if
len
(
n
.
Func
.
Inl
.
Body
)
!=
0
{
Fatalf
(
"%v already has inline body"
,
n
)
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)) {
...
@@ -260,6 +260,7 @@ func Main(archInit func(*Arch)) {
if
supportsDynlink
(
thearch
.
LinkArch
.
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_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
(
&
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
(
&
cpuprofile
,
"cpuprofile"
,
""
,
"write cpu profile to `file`"
)
flag
.
StringVar
(
&
memprofile
,
"memprofile"
,
""
,
"write memory profile to `file`"
)
flag
.
StringVar
(
&
memprofile
,
"memprofile"
,
""
,
"write memory profile to `file`"
)
...
@@ -274,12 +275,14 @@ func Main(archInit func(*Arch)) {
...
@@ -274,12 +275,14 @@ func Main(archInit func(*Arch)) {
flag
.
StringVar
(
&
benchfile
,
"bench"
,
""
,
"append benchmark times to `file`"
)
flag
.
StringVar
(
&
benchfile
,
"bench"
,
""
,
"append benchmark times to `file`"
)
flag
.
BoolVar
(
&
smallFrames
,
"smallframes"
,
false
,
"reduce the size limit for stack allocated objects"
)
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
.
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
)
objabi
.
Flagparse
(
usage
)
// Record flags that affect the build result. (And don't
// Record flags that affect the build result. (And don't
// record flags that don't, since that would cause spurious
// record flags that don't, since that would cause spurious
// changes in the binary.)
// 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
{
if
smallFrames
{
maxStackVarSize
=
128
*
1024
maxStackVarSize
=
128
*
1024
...
@@ -746,6 +749,8 @@ func Main(archInit func(*Arch)) {
...
@@ -746,6 +749,8 @@ func Main(archInit func(*Arch)) {
// Write object data to disk.
// Write object data to disk.
timings
.
Start
(
"be"
,
"dumpobj"
)
timings
.
Start
(
"be"
,
"dumpobj"
)
dumpdata
()
Ctxt
.
NumberSyms
(
false
)
dumpobj
()
dumpobj
()
if
asmhdr
!=
""
{
if
asmhdr
!=
""
{
dumpasmhdr
()
dumpasmhdr
()
...
...
src/cmd/compile/internal/gc/obj.go
View file @
bababde7
...
@@ -111,21 +111,7 @@ func dumpCompilerObj(bout *bio.Writer) {
...
@@ -111,21 +111,7 @@ func dumpCompilerObj(bout *bio.Writer) {
dumpexport
(
bout
)
dumpexport
(
bout
)
}
}
func
dumpLinkerObj
(
bout
*
bio
.
Writer
)
{
func
dumpdata
()
{
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
"
)
externs
:=
len
(
externdcl
)
externs
:=
len
(
externdcl
)
dumpglobls
()
dumpglobls
()
...
@@ -163,8 +149,24 @@ func dumpLinkerObj(bout *bio.Writer) {
...
@@ -163,8 +149,24 @@ func dumpLinkerObj(bout *bio.Writer) {
}
}
addGCLocals
()
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
()
{
func
addptabs
()
{
...
...
src/cmd/compile/internal/types/sym.go
View file @
bababde7
...
@@ -80,11 +80,18 @@ func (sym *Sym) Linksym() *obj.LSym {
...
@@ -80,11 +80,18 @@ func (sym *Sym) Linksym() *obj.LSym {
if
sym
==
nil
{
if
sym
==
nil
{
return
nil
return
nil
}
}
initPkg
:=
func
(
r
*
obj
.
LSym
)
{
if
sym
.
Linkname
!=
""
{
r
.
Pkg
=
"_"
}
else
{
r
.
Pkg
=
sym
.
Pkg
.
Prefix
}
}
if
sym
.
Func
()
{
if
sym
.
Func
()
{
// This is a function symbol. Mark it as "internal ABI".
// 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.
// 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{
...
@@ -54,6 +54,7 @@ var bootstrapDirs = []string{
"cmd/internal/gcprog"
,
"cmd/internal/gcprog"
,
"cmd/internal/dwarf"
,
"cmd/internal/dwarf"
,
"cmd/internal/edit"
,
"cmd/internal/edit"
,
"cmd/internal/goobj2"
,
"cmd/internal/objabi"
,
"cmd/internal/objabi"
,
"cmd/internal/obj"
,
"cmd/internal/obj"
,
"cmd/internal/obj/arm"
,
"cmd/internal/obj/arm"
,
...
@@ -72,6 +73,7 @@ var bootstrapDirs = []string{
...
@@ -72,6 +73,7 @@ var bootstrapDirs = []string{
"cmd/link/internal/arm64"
,
"cmd/link/internal/arm64"
,
"cmd/link/internal/ld"
,
"cmd/link/internal/ld"
,
"cmd/link/internal/loadelf"
,
"cmd/link/internal/loadelf"
,
"cmd/link/internal/loader"
,
"cmd/link/internal/loadmacho"
,
"cmd/link/internal/loadmacho"
,
"cmd/link/internal/loadpe"
,
"cmd/link/internal/loadpe"
,
"cmd/link/internal/loadxcoff"
,
"cmd/link/internal/loadxcoff"
,
...
...
src/cmd/dist/test.go
View file @
bababde7
...
@@ -585,7 +585,7 @@ func (t *tester) registerTests() {
...
@@ -585,7 +585,7 @@ func (t *tester) registerTests() {
},
},
})
})
// Also test a cgo package.
// Also test a cgo package.
if
t
.
cgoEnabled
{
if
t
.
cgoEnabled
&&
t
.
internalLink
()
{
t
.
tests
=
append
(
t
.
tests
,
distTest
{
t
.
tests
=
append
(
t
.
tests
,
distTest
{
name
:
"pie_internal_cgo"
,
name
:
"pie_internal_cgo"
,
heading
:
"internal linking of -buildmode=pie"
,
heading
:
"internal linking of -buildmode=pie"
,
...
...
src/cmd/go/alldocs.go
View file @
bababde7
...
@@ -145,8 +145,8 @@
...
@@ -145,8 +145,8 @@
// -ldflags '[pattern=]arg list'
// -ldflags '[pattern=]arg list'
// arguments to pass on each go tool link invocation.
// arguments to pass on each go tool link invocation.
// -linkshared
// -linkshared
//
link against shared libraries previously created with
//
build code that will be linked against shared libraries previously
// -buildmode=shared.
//
created with
-buildmode=shared.
// -mod mode
// -mod mode
// module download mode to use: readonly or vendor.
// module download mode to use: readonly or vendor.
// See 'go help modules' for more.
// See 'go help modules' for more.
...
...
src/cmd/go/internal/work/build.go
View file @
bababde7
...
@@ -97,8 +97,8 @@ and test commands:
...
@@ -97,8 +97,8 @@ and test commands:
-ldflags '[pattern=]arg list'
-ldflags '[pattern=]arg list'
arguments to pass on each go tool link invocation.
arguments to pass on each go tool link invocation.
-linkshared
-linkshared
link against shared libraries previously created with
build code that will be linked against shared libraries previously
-buildmode=shared.
created with
-buildmode=shared.
-mod mode
-mod mode
module download mode to use: readonly or vendor.
module download mode to use: readonly or vendor.
See 'go help modules' for more.
See 'go help modules' for more.
...
...
src/cmd/go/internal/work/init.go
View file @
bababde7
...
@@ -224,6 +224,7 @@ func buildModeInit() {
...
@@ -224,6 +224,7 @@ func buildModeInit() {
base
.
Fatalf
(
"-linkshared not supported on %s
\n
"
,
platform
)
base
.
Fatalf
(
"-linkshared not supported on %s
\n
"
,
platform
)
}
}
codegenArg
=
"-dynlink"
codegenArg
=
"-dynlink"
forcedGcflags
=
append
(
forcedGcflags
,
"-linkshared"
)
// TODO(mwhudson): remove -w when that gets fixed in linker.
// TODO(mwhudson): remove -w when that gets fixed in linker.
forcedLdflags
=
append
(
forcedLdflags
,
"-linkshared"
,
"-w"
)
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 {
...
@@ -1372,7 +1372,13 @@ func PutDefaultFunc(ctxt Context, s *FnState) error {
abbrev
:=
DW_ABRV_FUNCTION
abbrev
:=
DW_ABRV_FUNCTION
Uleb128put
(
ctxt
,
s
.
Info
,
int64
(
abbrev
))
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
,
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_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
})
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 {
...
@@ -502,6 +502,14 @@ func (r *objReader) parseObject(prefix []byte) error {
}
}
// TODO: extract OS + build ID if/when we need it
// 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
])
r
.
readFull
(
r
.
tmp
[
:
8
])
if
!
bytes
.
Equal
(
r
.
tmp
[
:
8
],
[]
byte
(
"
\x00
go114ld"
))
{
if
!
bytes
.
Equal
(
r
.
tmp
[
:
8
],
[]
byte
(
"
\x00
go114ld"
))
{
return
r
.
error
(
errCorruptObject
)
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 {
...
@@ -388,6 +388,10 @@ type LSym struct {
R
[]
Reloc
R
[]
Reloc
Func
*
FuncInfo
Func
*
FuncInfo
Pkg
string
PkgIdx
int32
SymIdx
int32
// TODO: replace RefIdx
}
}
// A FuncInfo contains extra fields for STEXT symbols.
// A FuncInfo contains extra fields for STEXT symbols.
...
@@ -410,6 +414,8 @@ type FuncInfo struct {
...
@@ -410,6 +414,8 @@ type FuncInfo struct {
GCRegs
*
LSym
GCRegs
*
LSym
StackObjects
*
LSym
StackObjects
*
LSym
OpenCodedDeferInfo
*
LSym
OpenCodedDeferInfo
*
LSym
FuncInfoSym
*
LSym
}
}
type
InlMark
struct
{
type
InlMark
struct
{
...
@@ -461,7 +467,7 @@ const (
...
@@ -461,7 +467,7 @@ const (
)
)
// Attribute is a set of symbol attributes.
// Attribute is a set of symbol attributes.
type
Attribute
uint
16
type
Attribute
uint
32
const
(
const
(
AttrDuplicateOK
Attribute
=
1
<<
iota
AttrDuplicateOK
Attribute
=
1
<<
iota
...
@@ -502,6 +508,10 @@ const (
...
@@ -502,6 +508,10 @@ const (
// keep unwinding beyond this frame.
// keep unwinding beyond this frame.
AttrTopFrame
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
// attrABIBase is the value at which the ABI is encoded in
// Attribute. This must be last; all bits after this are
// Attribute. This must be last; all bits after this are
// assumed to be an ABI value.
// assumed to be an ABI value.
...
@@ -525,6 +535,7 @@ func (a Attribute) NoFrame() bool { return a&AttrNoFrame != 0 }
...
@@ -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
)
Static
()
bool
{
return
a
&
AttrStatic
!=
0
}
func
(
a
Attribute
)
WasInlined
()
bool
{
return
a
&
AttrWasInlined
!=
0
}
func
(
a
Attribute
)
WasInlined
()
bool
{
return
a
&
AttrWasInlined
!=
0
}
func
(
a
Attribute
)
TopFrame
()
bool
{
return
a
&
AttrTopFrame
!=
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
)
{
func
(
a
*
Attribute
)
Set
(
flag
Attribute
,
value
bool
)
{
if
value
{
if
value
{
...
@@ -559,6 +570,7 @@ var textAttrStrings = [...]struct {
...
@@ -559,6 +570,7 @@ var textAttrStrings = [...]struct {
{
bit
:
AttrStatic
,
s
:
"STATIC"
},
{
bit
:
AttrStatic
,
s
:
"STATIC"
},
{
bit
:
AttrWasInlined
,
s
:
""
},
{
bit
:
AttrWasInlined
,
s
:
""
},
{
bit
:
AttrTopFrame
,
s
:
"TOPFRAME"
},
{
bit
:
AttrTopFrame
,
s
:
"TOPFRAME"
},
{
bit
:
AttrIndexed
,
s
:
""
},
}
}
// TextAttrString formats a for printing in as part of a TEXT prog.
// TextAttrString formats a for printing in as part of a TEXT prog.
...
@@ -637,8 +649,10 @@ type Link struct {
...
@@ -637,8 +649,10 @@ type Link struct {
Debugpcln
string
Debugpcln
string
Flag_shared
bool
Flag_shared
bool
Flag_dynlink
bool
Flag_dynlink
bool
Flag_linkshared
bool
Flag_optimize
bool
Flag_optimize
bool
Flag_locationlists
bool
Flag_locationlists
bool
Flag_newobj
bool
// use new object file format
Bso
*
bufio
.
Writer
Bso
*
bufio
.
Writer
Pathname
string
Pathname
string
hashmu
sync
.
Mutex
// protects hash, funchash
hashmu
sync
.
Mutex
// protects hash, funchash
...
@@ -672,6 +686,14 @@ type Link struct {
...
@@ -672,6 +686,14 @@ type Link struct {
// TODO(austin): Replace this with ABI wrappers once the ABIs
// TODO(austin): Replace this with ABI wrappers once the ABIs
// actually diverge.
// actually diverge.
ABIAliases
[]
*
LSym
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
{})
{
func
(
ctxt
*
Link
)
Diag
(
format
string
,
args
...
interface
{})
{
...
...
src/cmd/internal/obj/objfile.go
View file @
bababde7
...
@@ -8,6 +8,7 @@ package obj
...
@@ -8,6 +8,7 @@ package obj
import
(
import
(
"bufio"
"bufio"
"cmd/internal/bio"
"cmd/internal/dwarf"
"cmd/internal/dwarf"
"cmd/internal/objabi"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/internal/sys"
...
@@ -80,7 +81,13 @@ func newObjWriter(ctxt *Link, b *bufio.Writer, pkgpath string) *objWriter {
...
@@ -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
)
w
:=
newObjWriter
(
ctxt
,
b
,
pkgpath
)
// Magic header
// Magic header
...
@@ -221,8 +228,7 @@ func (w *objWriter) writeRefs(s *LSym) {
...
@@ -221,8 +228,7 @@ func (w *objWriter) writeRefs(s *LSym) {
}
}
}
}
func
(
w
*
objWriter
)
writeSymDebug
(
s
*
LSym
)
{
func
(
ctxt
*
Link
)
writeSymDebug
(
s
*
LSym
)
{
ctxt
:=
w
.
ctxt
fmt
.
Fprintf
(
ctxt
.
Bso
,
"%s "
,
s
.
Name
)
fmt
.
Fprintf
(
ctxt
.
Bso
,
"%s "
,
s
.
Name
)
if
s
.
Type
!=
0
{
if
s
.
Type
!=
0
{
fmt
.
Fprintf
(
ctxt
.
Bso
,
"%v "
,
s
.
Type
)
fmt
.
Fprintf
(
ctxt
.
Bso
,
"%v "
,
s
.
Type
)
...
@@ -302,7 +308,7 @@ func (w *objWriter) writeSymDebug(s *LSym) {
...
@@ -302,7 +308,7 @@ func (w *objWriter) writeSymDebug(s *LSym) {
func
(
w
*
objWriter
)
writeSym
(
s
*
LSym
)
{
func
(
w
*
objWriter
)
writeSym
(
s
*
LSym
)
{
ctxt
:=
w
.
ctxt
ctxt
:=
w
.
ctxt
if
ctxt
.
Debugasm
>
0
{
if
ctxt
.
Debugasm
>
0
{
w
.
writeSymDebug
(
s
)
w
.
ctxt
.
writeSymDebug
(
s
)
}
}
w
.
wr
.
WriteByte
(
symPrefix
)
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) {
...
@@ -21,7 +21,7 @@ func TestSizeof(t *testing.T) {
_64bit
uintptr
// size on 64bit platforms
_64bit
uintptr
// size on 64bit platforms
}{
}{
{
Addr
{},
32
,
48
},
{
Addr
{},
32
,
48
},
{
LSym
{},
56
,
104
},
{
LSym
{},
76
,
128
},
{
Prog
{},
132
,
200
},
{
Prog
{},
132
,
200
},
}
}
...
...
src/cmd/internal/obj/sym.go
View file @
bababde7
...
@@ -32,10 +32,12 @@
...
@@ -32,10 +32,12 @@
package
obj
package
obj
import
(
import
(
"cmd/internal/goobj2"
"cmd/internal/objabi"
"cmd/internal/objabi"
"fmt"
"fmt"
"log"
"log"
"math"
"math"
"sort"
)
)
func
Linknew
(
arch
*
LinkArch
)
*
Link
{
func
Linknew
(
arch
*
LinkArch
)
*
Link
{
...
@@ -78,6 +80,13 @@ func (ctxt *Link) LookupStatic(name string) *LSym {
...
@@ -78,6 +80,13 @@ func (ctxt *Link) LookupStatic(name string) *LSym {
// LookupABI looks up a symbol with the given ABI.
// LookupABI looks up a symbol with the given ABI.
// If it does not exist, it creates it.
// If it does not exist, it creates it.
func
(
ctxt
*
Link
)
LookupABI
(
name
string
,
abi
ABI
)
*
LSym
{
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
var
hash
map
[
string
]
*
LSym
switch
abi
{
switch
abi
{
case
ABI0
:
case
ABI0
:
...
@@ -94,6 +103,9 @@ func (ctxt *Link) LookupABI(name string, abi ABI) *LSym {
...
@@ -94,6 +103,9 @@ func (ctxt *Link) LookupABI(name string, abi ABI) *LSym {
s
=
&
LSym
{
Name
:
name
}
s
=
&
LSym
{
Name
:
name
}
s
.
SetABI
(
abi
)
s
.
SetABI
(
abi
)
hash
[
name
]
=
s
hash
[
name
]
=
s
if
init
!=
nil
{
init
(
s
)
}
}
}
ctxt
.
hashmu
.
Unlock
()
ctxt
.
hashmu
.
Unlock
()
return
s
return
s
...
@@ -147,3 +159,167 @@ func (ctxt *Link) Int64Sym(i int64) *LSym {
...
@@ -147,3 +159,167 @@ func (ctxt *Link) Int64Sym(i int64) *LSym {
s
.
Set
(
AttrLocal
,
true
)
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) {
...
@@ -402,7 +402,7 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
case
objabi
.
R_ADDRCUOFF
:
case
objabi
.
R_ADDRCUOFF
:
// debug_range and debug_loc elements use this relocation type to get an
// debug_range and debug_loc elements use this relocation type to get an
// offset from the start of the compile unit.
// 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.
// r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
case
objabi
.
R_GOTPCREL
:
case
objabi
.
R_GOTPCREL
:
...
@@ -1086,13 +1086,13 @@ func (p *GCProg) AddSym(s *sym.Symbol) {
...
@@ -1086,13 +1086,13 @@ func (p *GCProg) AddSym(s *sym.Symbol) {
}
}
ptrsize
:=
int64
(
p
.
ctxt
.
Arch
.
PtrSize
)
ptrsize
:=
int64
(
p
.
ctxt
.
Arch
.
PtrSize
)
nptr
:=
decodetypePtrdata
(
p
.
ctxt
.
Arch
,
typ
)
/
ptrsize
nptr
:=
decodetypePtrdata
(
p
.
ctxt
.
Arch
,
typ
.
P
)
/
ptrsize
if
debugGCProg
{
if
debugGCProg
{
fmt
.
Fprintf
(
os
.
Stderr
,
"gcprog sym: %s at %d (ptr=%d+%d)
\n
"
,
s
.
Name
,
s
.
Value
,
s
.
Value
/
ptrsize
,
nptr
)
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.
// Copy pointers from mask into program.
mask
:=
decodetypeGcmask
(
p
.
ctxt
,
typ
)
mask
:=
decodetypeGcmask
(
p
.
ctxt
,
typ
)
for
i
:=
int64
(
0
);
i
<
nptr
;
i
++
{
for
i
:=
int64
(
0
);
i
<
nptr
;
i
++
{
...
...
src/cmd/link/internal/ld/deadcode.go
View file @
bababde7
...
@@ -46,6 +46,15 @@ import (
...
@@ -46,6 +46,15 @@ import (
//
//
// Any unreached text symbols are removed from ctxt.Textp.
// Any unreached text symbols are removed from ctxt.Textp.
func
deadcode
(
ctxt
*
Link
)
{
func
deadcode
(
ctxt
*
Link
)
{
if
ctxt
.
Debugvlog
!=
0
{
ctxt
.
Logf
(
"deadcode
\n
"
)
}
if
*
flagNewobj
{
deadcode2
(
ctxt
)
return
}
d
:=
&
deadcodepass
{
d
:=
&
deadcodepass
{
ctxt
:
ctxt
,
ctxt
:
ctxt
,
ifaceMethod
:
make
(
map
[
methodsig
]
bool
),
ifaceMethod
:
make
(
map
[
methodsig
]
bool
),
...
@@ -114,22 +123,70 @@ func deadcode(ctxt *Link) {
...
@@ -114,22 +123,70 @@ func deadcode(ctxt *Link) {
}
}
}
}
for
_
,
lib
:=
range
ctxt
.
Library
{
addToTextp
(
ctxt
)
lib
.
Textp
=
lib
.
Textp
[
:
0
]
}
}
func
addToTextp
(
ctxt
*
Link
)
{
// Remove dead text but keep file information (z symbols).
// 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
{
for
_
,
s
:=
range
ctxt
.
Textp
{
if
s
.
Attr
.
Reachable
()
{
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
)
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
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
// methodref holds the relocations from a receiver type symbol to its
...
@@ -274,7 +331,7 @@ func (d *deadcodepass) flood() {
...
@@ -274,7 +331,7 @@ func (d *deadcodepass) flood() {
// later will give a better error than deadcode.
// later will give a better error than deadcode.
continue
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
)
{
for
_
,
sig
:=
range
decodeIfaceMethods
(
d
.
ctxt
.
Arch
,
s
)
{
if
d
.
ctxt
.
Debugvlog
>
1
{
if
d
.
ctxt
.
Debugvlog
>
1
{
d
.
ctxt
.
Logf
(
"reached iface method: %s
\n
"
,
sig
)
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
...
@@ -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
func
uncommonSize
()
int
{
return
4
+
2
+
2
+
4
+
4
}
// runtime.uncommontype
// Type.commonType.kind
// Type.commonType.kind
func
decodetypeKind
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
uint8
{
func
decodetypeKind
(
arch
*
sys
.
Arch
,
p
[]
byte
)
uint8
{
return
s
.
P
[
2
*
arch
.
PtrSize
+
7
]
&
objabi
.
KindMask
// 0x13 / 0x1f
return
p
[
2
*
arch
.
PtrSize
+
7
]
&
objabi
.
KindMask
// 0x13 / 0x1f
}
}
// Type.commonType.kind
// Type.commonType.kind
func
decodetypeUsegcprog
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
uint8
{
func
decodetypeUsegcprog
(
arch
*
sys
.
Arch
,
p
[]
byte
)
uint8
{
return
s
.
P
[
2
*
arch
.
PtrSize
+
7
]
&
objabi
.
KindGCProg
// 0x13 / 0x1f
return
p
[
2
*
arch
.
PtrSize
+
7
]
&
objabi
.
KindGCProg
// 0x13 / 0x1f
}
}
// Type.commonType.size
// Type.commonType.size
func
decodetypeSize
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
int64
{
func
decodetypeSize
(
arch
*
sys
.
Arch
,
p
[]
byte
)
int64
{
return
int64
(
decodeInuxi
(
arch
,
s
.
P
,
arch
.
PtrSize
))
// 0x8 / 0x10
return
int64
(
decodeInuxi
(
arch
,
p
,
arch
.
PtrSize
))
// 0x8 / 0x10
}
}
// Type.commonType.ptrdata
// Type.commonType.ptrdata
func
decodetypePtrdata
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
int64
{
func
decodetypePtrdata
(
arch
*
sys
.
Arch
,
p
[]
byte
)
int64
{
return
int64
(
decodeInuxi
(
arch
,
s
.
P
[
arch
.
PtrSize
:
],
arch
.
PtrSize
))
// 0x8 / 0x10
return
int64
(
decodeInuxi
(
arch
,
p
[
arch
.
PtrSize
:
],
arch
.
PtrSize
))
// 0x8 / 0x10
}
}
// Type.commonType.tflag
// Type.commonType.tflag
func
decodetypeHasUncommon
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
bool
{
func
decodetypeHasUncommon
(
arch
*
sys
.
Arch
,
p
[]
byte
)
bool
{
return
s
.
P
[
2
*
arch
.
PtrSize
+
4
]
&
tflagUncommon
!=
0
return
p
[
2
*
arch
.
PtrSize
+
4
]
&
tflagUncommon
!=
0
}
}
// Find the elf.Section of a given shared library that contains a given address.
// 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 {
...
@@ -138,7 +138,7 @@ func decodetypeGcprogShlib(ctxt *Link, s *sym.Symbol) uint64 {
func
decodetypeGcmask
(
ctxt
*
Link
,
s
*
sym
.
Symbol
)
[]
byte
{
func
decodetypeGcmask
(
ctxt
*
Link
,
s
*
sym
.
Symbol
)
[]
byte
{
if
s
.
Type
==
sym
.
SDYNIMPORT
{
if
s
.
Type
==
sym
.
SDYNIMPORT
{
addr
:=
decodetypeGcprogShlib
(
ctxt
,
s
)
addr
:=
decodetypeGcprogShlib
(
ctxt
,
s
)
ptrdata
:=
decodetypePtrdata
(
ctxt
.
Arch
,
s
)
ptrdata
:=
decodetypePtrdata
(
ctxt
.
Arch
,
s
.
P
)
sect
:=
findShlibSection
(
ctxt
,
s
.
File
,
addr
)
sect
:=
findShlibSection
(
ctxt
,
s
.
File
,
addr
)
if
sect
!=
nil
{
if
sect
!=
nil
{
r
:=
make
([]
byte
,
ptrdata
/
int64
(
ctxt
.
Arch
.
PtrSize
))
r
:=
make
([]
byte
,
ptrdata
/
int64
(
ctxt
.
Arch
.
PtrSize
))
...
@@ -181,17 +181,17 @@ func decodetypeChanElem(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
...
@@ -181,17 +181,17 @@ func decodetypeChanElem(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
}
}
// Type.FuncType.dotdotdot
// Type.FuncType.dotdotdot
func
decodetypeFuncDotdotdot
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
bool
{
func
decodetypeFuncDotdotdot
(
arch
*
sys
.
Arch
,
p
[]
byte
)
bool
{
return
uint16
(
decodeInuxi
(
arch
,
s
.
P
[
commonsize
(
arch
)
+
2
:
],
2
))
&
(
1
<<
15
)
!=
0
return
uint16
(
decodeInuxi
(
arch
,
p
[
commonsize
(
arch
)
+
2
:
],
2
))
&
(
1
<<
15
)
!=
0
}
}
// Type.FuncType.inCount
// Type.FuncType.inCount
func
decodetypeFuncInCount
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
int
{
func
decodetypeFuncInCount
(
arch
*
sys
.
Arch
,
p
[]
byte
)
int
{
return
int
(
decodeInuxi
(
arch
,
s
.
P
[
commonsize
(
arch
)
:
],
2
))
return
int
(
decodeInuxi
(
arch
,
p
[
commonsize
(
arch
)
:
],
2
))
}
}
func
decodetypeFuncOutCount
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
int
{
func
decodetypeFuncOutCount
(
arch
*
sys
.
Arch
,
p
[]
byte
)
int
{
return
int
(
uint16
(
decodeInuxi
(
arch
,
s
.
P
[
commonsize
(
arch
)
+
2
:
],
2
))
&
(
1
<<
15
-
1
))
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
{
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 {
...
@@ -199,14 +199,14 @@ func decodetypeFuncInType(arch *sys.Arch, s *sym.Symbol, i int) *sym.Symbol {
if
arch
.
PtrSize
==
8
{
if
arch
.
PtrSize
==
8
{
uadd
+=
4
uadd
+=
4
}
}
if
decodetypeHasUncommon
(
arch
,
s
)
{
if
decodetypeHasUncommon
(
arch
,
s
.
P
)
{
uadd
+=
uncommonSize
()
uadd
+=
uncommonSize
()
}
}
return
decodeRelocSym
(
s
,
int32
(
uadd
+
i
*
arch
.
PtrSize
))
return
decodeRelocSym
(
s
,
int32
(
uadd
+
i
*
arch
.
PtrSize
))
}
}
func
decodetypeFuncOutType
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
,
i
int
)
*
sym
.
Symbol
{
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
// Type.StructType.fields.Slice::length
...
@@ -216,7 +216,7 @@ func decodetypeStructFieldCount(arch *sys.Arch, s *sym.Symbol) int {
...
@@ -216,7 +216,7 @@ func decodetypeStructFieldCount(arch *sys.Arch, s *sym.Symbol) int {
func
decodetypeStructFieldArrayOff
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
,
i
int
)
int
{
func
decodetypeStructFieldArrayOff
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
,
i
int
)
int
{
off
:=
commonsize
(
arch
)
+
4
*
arch
.
PtrSize
off
:=
commonsize
(
arch
)
+
4
*
arch
.
PtrSize
if
decodetypeHasUncommon
(
arch
,
s
)
{
if
decodetypeHasUncommon
(
arch
,
s
.
P
)
{
off
+=
uncommonSize
()
off
+=
uncommonSize
()
}
}
off
+=
i
*
structfieldSize
(
arch
)
off
+=
i
*
structfieldSize
(
arch
)
...
@@ -264,8 +264,8 @@ func decodetypeStructFieldOffsAnon(arch *sys.Arch, s *sym.Symbol, i int) int64 {
...
@@ -264,8 +264,8 @@ func decodetypeStructFieldOffsAnon(arch *sys.Arch, s *sym.Symbol, i int) int64 {
}
}
// InterfaceType.methods.length
// InterfaceType.methods.length
func
decodetypeIfaceMethodCount
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
int64
{
func
decodetypeIfaceMethodCount
(
arch
*
sys
.
Arch
,
p
[]
byte
)
int64
{
return
int64
(
decodeInuxi
(
arch
,
s
.
P
[
commonsize
(
arch
)
+
2
*
arch
.
PtrSize
:
],
arch
.
PtrSize
))
return
int64
(
decodeInuxi
(
arch
,
p
[
commonsize
(
arch
)
+
2
*
arch
.
PtrSize
:
],
arch
.
PtrSize
))
}
}
// methodsig is a fully qualified typed method signature, like
// 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
...
@@ -299,7 +299,7 @@ func decodeMethodSig(arch *sys.Arch, s *sym.Symbol, off, size, count int) []meth
mtypSym
:=
decodeRelocSym
(
s
,
int32
(
off
+
4
))
mtypSym
:=
decodeRelocSym
(
s
,
int32
(
off
+
4
))
buf
.
WriteRune
(
'('
)
buf
.
WriteRune
(
'('
)
inCount
:=
decodetypeFuncInCount
(
arch
,
mtypSym
)
inCount
:=
decodetypeFuncInCount
(
arch
,
mtypSym
.
P
)
for
i
:=
0
;
i
<
inCount
;
i
++
{
for
i
:=
0
;
i
<
inCount
;
i
++
{
if
i
>
0
{
if
i
>
0
{
buf
.
WriteString
(
", "
)
buf
.
WriteString
(
", "
)
...
@@ -307,7 +307,7 @@ func decodeMethodSig(arch *sys.Arch, s *sym.Symbol, off, size, count int) []meth
...
@@ -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
(
decodetypeFuncInType
(
arch
,
mtypSym
,
i
)
.
Name
)
}
}
buf
.
WriteString
(
") ("
)
buf
.
WriteString
(
") ("
)
outCount
:=
decodetypeFuncOutCount
(
arch
,
mtypSym
)
outCount
:=
decodetypeFuncOutCount
(
arch
,
mtypSym
.
P
)
for
i
:=
0
;
i
<
outCount
;
i
++
{
for
i
:=
0
;
i
<
outCount
;
i
++
{
if
i
>
0
{
if
i
>
0
{
buf
.
WriteString
(
", "
)
buf
.
WriteString
(
", "
)
...
@@ -324,7 +324,7 @@ func decodeMethodSig(arch *sys.Arch, s *sym.Symbol, off, size, count int) []meth
...
@@ -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
{
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
))
panic
(
fmt
.
Sprintf
(
"symbol %q is not an interface"
,
s
.
Name
))
}
}
r
:=
decodeReloc
(
s
,
int32
(
commonsize
(
arch
)
+
arch
.
PtrSize
))
r
:=
decodeReloc
(
s
,
int32
(
commonsize
(
arch
)
+
arch
.
PtrSize
))
...
@@ -335,17 +335,17 @@ func decodeIfaceMethods(arch *sys.Arch, s *sym.Symbol) []methodsig {
...
@@ -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
))
panic
(
fmt
.
Sprintf
(
"imethod slice pointer in %q leads to a different symbol"
,
s
.
Name
))
}
}
off
:=
int
(
r
.
Add
)
// array of reflect.imethod values
off
:=
int
(
r
.
Add
)
// array of reflect.imethod values
numMethods
:=
int
(
decodetypeIfaceMethodCount
(
arch
,
s
))
numMethods
:=
int
(
decodetypeIfaceMethodCount
(
arch
,
s
.
P
))
sizeofIMethod
:=
4
+
4
sizeofIMethod
:=
4
+
4
return
decodeMethodSig
(
arch
,
s
,
off
,
sizeofIMethod
,
numMethods
)
return
decodeMethodSig
(
arch
,
s
,
off
,
sizeofIMethod
,
numMethods
)
}
}
func
decodetypeMethods
(
arch
*
sys
.
Arch
,
s
*
sym
.
Symbol
)
[]
methodsig
{
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
))
panic
(
fmt
.
Sprintf
(
"no methods on %q"
,
s
.
Name
))
}
}
off
:=
commonsize
(
arch
)
// reflect.rtype
off
:=
commonsize
(
arch
)
// reflect.rtype
switch
decodetypeKind
(
arch
,
s
)
&
kindMask
{
switch
decodetypeKind
(
arch
,
s
.
P
)
&
kindMask
{
case
kindStruct
:
// reflect.structType
case
kindStruct
:
// reflect.structType
off
+=
4
*
arch
.
PtrSize
off
+=
4
*
arch
.
PtrSize
case
kindPtr
:
// reflect.ptrType
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 {
...
@@ -422,8 +422,8 @@ func defgotype(ctxt *Link, gotype *sym.Symbol) *sym.Symbol {
func
newtype
(
ctxt
*
Link
,
gotype
*
sym
.
Symbol
)
*
dwarf
.
DWDie
{
func
newtype
(
ctxt
*
Link
,
gotype
*
sym
.
Symbol
)
*
dwarf
.
DWDie
{
name
:=
gotype
.
Name
[
5
:
]
// could also decode from Type.string
name
:=
gotype
.
Name
[
5
:
]
// could also decode from Type.string
kind
:=
decodetypeKind
(
ctxt
.
Arch
,
gotype
)
kind
:=
decodetypeKind
(
ctxt
.
Arch
,
gotype
.
P
)
bytesize
:=
decodetypeSize
(
ctxt
.
Arch
,
gotype
)
bytesize
:=
decodetypeSize
(
ctxt
.
Arch
,
gotype
.
P
)
var
die
,
typedefdie
*
dwarf
.
DWDie
var
die
,
typedefdie
*
dwarf
.
DWDie
switch
kind
{
switch
kind
{
...
@@ -488,17 +488,17 @@ func newtype(ctxt *Link, gotype *sym.Symbol) *dwarf.DWDie {
...
@@ -488,17 +488,17 @@ func newtype(ctxt *Link, gotype *sym.Symbol) *dwarf.DWDie {
die
=
newdie
(
ctxt
,
&
dwtypes
,
dwarf
.
DW_ABRV_FUNCTYPE
,
name
,
0
)
die
=
newdie
(
ctxt
,
&
dwtypes
,
dwarf
.
DW_ABRV_FUNCTYPE
,
name
,
0
)
newattr
(
die
,
dwarf
.
DW_AT_byte_size
,
dwarf
.
DW_CLS_CONSTANT
,
bytesize
,
0
)
newattr
(
die
,
dwarf
.
DW_AT_byte_size
,
dwarf
.
DW_CLS_CONSTANT
,
bytesize
,
0
)
typedefdie
=
dotypedef
(
ctxt
,
&
dwtypes
,
name
,
die
)
typedefdie
=
dotypedef
(
ctxt
,
&
dwtypes
,
name
,
die
)
nfields
:=
decodetypeFuncInCount
(
ctxt
.
Arch
,
gotype
)
nfields
:=
decodetypeFuncInCount
(
ctxt
.
Arch
,
gotype
.
P
)
for
i
:=
0
;
i
<
nfields
;
i
++
{
for
i
:=
0
;
i
<
nfields
;
i
++
{
s
:=
decodetypeFuncInType
(
ctxt
.
Arch
,
gotype
,
i
)
s
:=
decodetypeFuncInType
(
ctxt
.
Arch
,
gotype
,
i
)
fld
:=
newdie
(
ctxt
,
die
,
dwarf
.
DW_ABRV_FUNCTYPEPARAM
,
s
.
Name
[
5
:
],
0
)
fld
:=
newdie
(
ctxt
,
die
,
dwarf
.
DW_ABRV_FUNCTYPEPARAM
,
s
.
Name
[
5
:
],
0
)
newrefattr
(
fld
,
dwarf
.
DW_AT_type
,
defgotype
(
ctxt
,
s
))
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
)
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
++
{
for
i
:=
0
;
i
<
nfields
;
i
++
{
s
:=
decodetypeFuncOutType
(
ctxt
.
Arch
,
gotype
,
i
)
s
:=
decodetypeFuncOutType
(
ctxt
.
Arch
,
gotype
,
i
)
fld
:=
newdie
(
ctxt
,
die
,
dwarf
.
DW_ABRV_FUNCTYPEPARAM
,
s
.
Name
[
5
:
],
0
)
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 {
...
@@ -508,7 +508,7 @@ func newtype(ctxt *Link, gotype *sym.Symbol) *dwarf.DWDie {
case
objabi
.
KindInterface
:
case
objabi
.
KindInterface
:
die
=
newdie
(
ctxt
,
&
dwtypes
,
dwarf
.
DW_ABRV_IFACETYPE
,
name
,
0
)
die
=
newdie
(
ctxt
,
&
dwtypes
,
dwarf
.
DW_ABRV_IFACETYPE
,
name
,
0
)
typedefdie
=
dotypedef
(
ctxt
,
&
dwtypes
,
name
,
die
)
typedefdie
=
dotypedef
(
ctxt
,
&
dwtypes
,
name
,
die
)
nfields
:=
int
(
decodetypeIfaceMethodCount
(
ctxt
.
Arch
,
gotype
))
nfields
:=
int
(
decodetypeIfaceMethodCount
(
ctxt
.
Arch
,
gotype
.
P
))
var
s
*
sym
.
Symbol
var
s
*
sym
.
Symbol
if
nfields
==
0
{
if
nfields
==
0
{
s
=
lookupOrDiag
(
ctxt
,
"type.runtime.eface"
)
s
=
lookupOrDiag
(
ctxt
,
"type.runtime.eface"
)
...
@@ -733,7 +733,7 @@ func synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) {
...
@@ -733,7 +733,7 @@ func synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) {
gotype
:=
getattr
(
die
,
dwarf
.
DW_AT_type
)
.
Data
.
(
*
sym
.
Symbol
)
gotype
:=
getattr
(
die
,
dwarf
.
DW_AT_type
)
.
Data
.
(
*
sym
.
Symbol
)
keytype
:=
decodetypeMapKey
(
ctxt
.
Arch
,
gotype
)
keytype
:=
decodetypeMapKey
(
ctxt
.
Arch
,
gotype
)
valtype
:=
decodetypeMapValue
(
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
))
keytype
,
valtype
=
walksymtypedef
(
ctxt
,
defgotype
(
ctxt
,
keytype
)),
walksymtypedef
(
ctxt
,
defgotype
(
ctxt
,
valtype
))
// compute size info like hashmap.c does.
// 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
...
@@ -110,7 +110,6 @@ func ldpkg(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, filename s
return
return
}
}
p1
+=
p0
p1
+=
p0
loadcgo
(
ctxt
,
filename
,
objabi
.
PathToPrefix
(
lib
.
Pkg
),
data
[
p0
:
p1
])
loadcgo
(
ctxt
,
filename
,
objabi
.
PathToPrefix
(
lib
.
Pkg
),
data
[
p0
:
p1
])
}
}
}
}
...
@@ -123,6 +122,39 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
...
@@ -123,6 +122,39 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
return
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
{
for
_
,
f
:=
range
directives
{
switch
f
[
0
]
{
switch
f
[
0
]
{
case
"cgo_import_dynamic"
:
case
"cgo_import_dynamic"
:
...
@@ -164,8 +196,8 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
...
@@ -164,8 +196,8 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
if
i
:=
strings
.
Index
(
remote
,
"#"
);
i
>=
0
{
if
i
:=
strings
.
Index
(
remote
,
"#"
);
i
>=
0
{
remote
,
q
=
remote
[
:
i
],
remote
[
i
+
1
:
]
remote
,
q
=
remote
[
:
i
],
remote
[
i
+
1
:
]
}
}
s
:=
ctxt
.
Syms
.
L
ookup
(
local
,
0
)
s
:=
l
ookup
(
local
,
0
)
if
s
.
Type
==
0
||
s
.
Type
==
sym
.
SXREF
||
s
.
Type
==
sym
.
SHOSTOBJ
{
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
.
SetDynimplib
(
lib
)
s
.
SetExtname
(
remote
)
s
.
SetExtname
(
remote
)
s
.
SetDynimpvers
(
q
)
s
.
SetDynimpvers
(
q
)
...
@@ -183,7 +215,7 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
...
@@ -183,7 +215,7 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
}
}
local
:=
f
[
1
]
local
:=
f
[
1
]
s
:=
ctxt
.
Syms
.
L
ookup
(
local
,
0
)
s
:=
l
ookup
(
local
,
0
)
s
.
Type
=
sym
.
SHOSTOBJ
s
.
Type
=
sym
.
SHOSTOBJ
s
.
Size
=
0
s
.
Size
=
0
continue
continue
...
@@ -204,11 +236,11 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
...
@@ -204,11 +236,11 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
// functions. Link.loadlib will resolve any
// functions. Link.loadlib will resolve any
// ABI aliases we find here (since we may not
// ABI aliases we find here (since we may not
// yet know it's an alias).
// yet know it's an alias).
s
:=
ctxt
.
Syms
.
L
ookup
(
local
,
0
)
s
:=
l
ookup
(
local
,
0
)
switch
ctxt
.
BuildMode
{
switch
ctxt
.
BuildMode
{
case
BuildModeCShared
,
BuildModeCArchive
,
BuildModePlugin
:
case
BuildModeCShared
,
BuildModeCArchive
,
BuildModePlugin
:
if
s
==
ctxt
.
Syms
.
L
ookup
(
"main"
,
0
)
{
if
s
==
l
ookup
(
"main"
,
0
)
{
continue
continue
}
}
}
}
...
@@ -223,7 +255,6 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
...
@@ -223,7 +255,6 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
if
!
s
.
Attr
.
CgoExport
()
{
if
!
s
.
Attr
.
CgoExport
()
{
s
.
SetExtname
(
remote
)
s
.
SetExtname
(
remote
)
dynexp
=
append
(
dynexp
,
s
)
}
else
if
s
.
Extname
()
!=
remote
{
}
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
)
fmt
.
Fprintf
(
os
.
Stderr
,
"%s: conflicting cgo_export directives: %s as %s and %s
\n
"
,
os
.
Args
[
0
],
s
.
Name
,
s
.
Extname
(),
remote
)
nerrors
++
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 (
...
@@ -35,6 +35,7 @@ import (
"cmd/internal/obj"
"cmd/internal/obj"
"cmd/internal/objabi"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/internal/sys"
"cmd/link/internal/loader"
"cmd/link/internal/sym"
"cmd/link/internal/sym"
"debug/elf"
"debug/elf"
"fmt"
"fmt"
...
@@ -96,6 +97,18 @@ type Link struct {
...
@@ -96,6 +97,18 @@ type Link struct {
runtimeCU
*
sym
.
CompilationUnit
// One of the runtime CUs, the last one seen.
runtimeCU
*
sym
.
CompilationUnit
// One of the runtime CUs, the last one seen.
relocbuf
[]
byte
// temporary buffer for applying relocations
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
{
type
unresolvedSymKey
struct
{
...
...
src/cmd/link/internal/ld/main.go
View file @
bababde7
...
@@ -87,6 +87,7 @@ var (
...
@@ -87,6 +87,7 @@ var (
flagInterpreter
=
flag
.
String
(
"I"
,
""
,
"use `linker` as ELF dynamic linker"
)
flagInterpreter
=
flag
.
String
(
"I"
,
""
,
"use `linker` as ELF dynamic linker"
)
FlagDebugTramp
=
flag
.
Int
(
"debugtramp"
,
0
,
"debug trampolines"
)
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)."
)
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`"
)
FlagRound
=
flag
.
Int
(
"R"
,
-
1
,
"set address rounding `quantum`"
)
FlagTextAddr
=
flag
.
Int64
(
"T"
,
-
1
,
"set text segment `address`"
)
FlagTextAddr
=
flag
.
Int64
(
"T"
,
-
1
,
"set text segment `address`"
)
...
@@ -208,8 +209,13 @@ func Main(arch *sys.Arch, theArch Arch) {
...
@@ -208,8 +209,13 @@ func Main(arch *sys.Arch, theArch Arch) {
}
}
ctxt
.
loadlib
()
ctxt
.
loadlib
()
ctxt
.
dostrdata
()
deadcode
(
ctxt
)
deadcode
(
ctxt
)
if
*
flagNewobj
{
ctxt
.
loadlibfull
()
// XXX do it here for now
}
ctxt
.
linksetup
()
ctxt
.
dostrdata
()
dwarfGenerateDebugInfo
(
ctxt
)
dwarfGenerateDebugInfo
(
ctxt
)
if
objabi
.
Fieldtrack_enabled
!=
0
{
if
objabi
.
Fieldtrack_enabled
!=
0
{
fieldtrack
(
ctxt
)
fieldtrack
(
ctxt
)
...
...
src/cmd/link/internal/ld/pcln.go
View file @
bababde7
...
@@ -305,10 +305,10 @@ func (ctxt *Link) pclntab() {
...
@@ -305,10 +305,10 @@ func (ctxt *Link) pclntab() {
// appears in the Pcfile table. In that case, this assigns
// appears in the Pcfile table. In that case, this assigns
// the outer file a number.
// the outer file a number.
numberfile
(
ctxt
,
call
.
File
)
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
.
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
// byte 3 is unused
inlTreeSym
.
SetUint32
(
ctxt
.
Arch
,
int64
(
i
*
20
+
4
),
uint32
(
call
.
File
.
Value
))
inlTreeSym
.
SetUint32
(
ctxt
.
Arch
,
int64
(
i
*
20
+
4
),
uint32
(
call
.
File
.
Value
))
inlTreeSym
.
SetUint32
(
ctxt
.
Arch
,
int64
(
i
*
20
+
8
),
uint32
(
call
.
Line
))
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() {
...
@@ -694,7 +694,7 @@ func (ctxt *Link) symtab() {
// creating the moduledata from scratch and it does not have a
// creating the moduledata from scratch and it does not have a
// compiler-provided size, so read it from the type data.
// compiler-provided size, so read it from the type data.
moduledatatype
:=
ctxt
.
Syms
.
ROLookup
(
"type.runtime.moduledata"
,
0
)
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
)
moduledata
.
Grow
(
moduledata
.
Size
)
lastmoduledatap
:=
ctxt
.
Syms
.
Lookup
(
"runtime.lastmoduledatap"
,
0
)
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 {
...
@@ -88,3 +88,10 @@ func contains(s []string, v string) bool {
}
}
return
false
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 (
...
@@ -10,6 +10,7 @@ import (
"cmd/internal/bio"
"cmd/internal/bio"
"cmd/internal/objabi"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/internal/sys"
"cmd/link/internal/loader"
"cmd/link/internal/sym"
"cmd/link/internal/sym"
"debug/elf"
"debug/elf"
"encoding/binary"
"encoding/binary"
...
@@ -451,7 +452,20 @@ func parseArmAttributes(e binary.ByteOrder, data []byte) (found bool, ehdrFlags
...
@@ -451,7 +452,20 @@ func parseArmAttributes(e binary.ByteOrder, data []byte) (found bool, ehdrFlags
return
found
,
ehdrFlags
,
nil
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.
// 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
// 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
...
@@ -459,12 +473,11 @@ func parseArmAttributes(e binary.ByteOrder, data []byte) (found bool, ehdrFlags
// parameter initEhdrFlags contains the current header flags for the output
// parameter initEhdrFlags contains the current header flags for the output
// object, and the returned ehdrFlags contains what this Load function computes.
// object, and the returned ehdrFlags contains what this Load function computes.
// TODO: find a better place for this logic.
// 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
)
{
errorf
:=
func
(
str
string
,
args
...
interface
{})
([]
*
sym
.
Symbol
,
uint32
,
error
)
{
return
nil
,
0
,
fmt
.
Errorf
(
"loadelf: %s: %v"
,
pn
,
fmt
.
Sprintf
(
str
,
args
...
))
return
nil
,
0
,
fmt
.
Errorf
(
"loadelf: %s: %v"
,
pn
,
fmt
.
Sprintf
(
str
,
args
...
))
}
}
localSymVersion
:=
syms
.
IncVersion
()
base
:=
f
.
Offset
()
base
:=
f
.
Offset
()
var
hdrbuf
[
64
]
uint8
var
hdrbuf
[
64
]
uint8
...
@@ -715,7 +728,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length i
...
@@ -715,7 +728,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length i
}
}
sectsymNames
[
name
]
=
true
sectsymNames
[
name
]
=
true
s
:=
syms
.
L
ookup
(
name
,
localSymVersion
)
s
:=
l
ookup
(
name
,
localSymVersion
)
switch
int
(
sect
.
flags
)
&
(
ElfSectFlagAlloc
|
ElfSectFlagWrite
|
ElfSectFlagExec
)
{
switch
int
(
sect
.
flags
)
&
(
ElfSectFlagAlloc
|
ElfSectFlagWrite
|
ElfSectFlagExec
)
{
default
:
default
:
...
@@ -754,7 +767,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length i
...
@@ -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
++
{
for
i
:=
1
;
i
<
elfobj
.
nsymtab
;
i
++
{
var
elfsym
ElfSym
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
)
return
errorf
(
"%s: malformed elf file: %v"
,
pn
,
err
)
}
}
symbols
[
i
]
=
elfsym
.
sym
symbols
[
i
]
=
elfsym
.
sym
...
@@ -925,7 +938,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length i
...
@@ -925,7 +938,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length i
rp
.
Sym
=
nil
rp
.
Sym
=
nil
}
else
{
}
else
{
var
elfsym
ElfSym
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
)
return
errorf
(
"malformed elf file: %v"
,
err
)
}
}
elfsym
.
sym
=
symbols
[
info
>>
32
]
elfsym
.
sym
=
symbols
[
info
>>
32
]
...
@@ -1002,7 +1015,7 @@ func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
...
@@ -1002,7 +1015,7 @@ func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
return
nil
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
{
if
i
>=
elfobj
.
nsymtab
||
i
<
0
{
err
=
fmt
.
Errorf
(
"invalid elf symbol index"
)
err
=
fmt
.
Errorf
(
"invalid elf symbol index"
)
return
err
return
err
...
@@ -1052,7 +1065,7 @@ func readelfsym(arch *sys.Arch, syms *sym.Symbols, elfobj *ElfObj, i int, elfsym
...
@@ -1052,7 +1065,7 @@ func readelfsym(arch *sys.Arch, syms *sym.Symbols, elfobj *ElfObj, i int, elfsym
switch
elfsym
.
bind
{
switch
elfsym
.
bind
{
case
ElfSymBindGlobal
:
case
ElfSymBindGlobal
:
if
needSym
!=
0
{
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
// for global scoped hidden symbols we should insert it into
// symbol hash table, but mark them as hidden.
// 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
...
@@ -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,
// We need to be able to look this up,
// so put it in the hash table.
// so put it in the hash table.
if
needSym
!=
0
{
if
needSym
!=
0
{
s
=
syms
.
L
ookup
(
elfsym
.
name
,
localSymVersion
)
s
=
l
ookup
(
elfsym
.
name
,
localSymVersion
)
s
.
Attr
|=
sym
.
AttrVisibilityHidden
s
.
Attr
|=
sym
.
AttrVisibilityHidden
}
}
...
@@ -1088,14 +1101,14 @@ func readelfsym(arch *sys.Arch, syms *sym.Symbols, elfobj *ElfObj, i int, elfsym
...
@@ -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
// local names and hidden global names are unique
// and should only be referenced by their index, not name, so we
// and should only be referenced by their index, not name, so we
// don't bother to add them into the hash table
// 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
s
.
Attr
|=
sym
.
AttrVisibilityHidden
}
}
case
ElfSymBindWeak
:
case
ElfSymBindWeak
:
if
needSym
!=
0
{
if
needSym
!=
0
{
s
=
syms
.
L
ookup
(
elfsym
.
name
,
0
)
s
=
l
ookup
(
elfsym
.
name
,
0
)
if
elfsym
.
other
==
2
{
if
elfsym
.
other
==
2
{
s
.
Attr
|=
sym
.
AttrVisibilityHidden
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 (
...
@@ -10,6 +10,7 @@ import (
"cmd/internal/bio"
"cmd/internal/bio"
"cmd/internal/objabi"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/internal/sys"
"cmd/link/internal/loader"
"cmd/link/internal/sym"
"cmd/link/internal/sym"
"encoding/binary"
"encoding/binary"
"fmt"
"fmt"
...
@@ -423,14 +424,24 @@ func macholoadsym(m *ldMachoObj, symtab *ldMachoSymtab) int {
...
@@ -423,14 +424,24 @@ func macholoadsym(m *ldMachoObj, symtab *ldMachoSymtab) int {
return
0
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.
// 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
)
{
errorf
:=
func
(
str
string
,
args
...
interface
{})
([]
*
sym
.
Symbol
,
error
)
{
return
nil
,
fmt
.
Errorf
(
"loadmacho: %v: %v"
,
pn
,
fmt
.
Sprintf
(
str
,
args
...
))
return
nil
,
fmt
.
Errorf
(
"loadmacho: %v: %v"
,
pn
,
fmt
.
Sprintf
(
str
,
args
...
))
}
}
localSymVersion
:=
syms
.
IncVersion
()
base
:=
f
.
Offset
()
base
:=
f
.
Offset
()
var
hdr
[
7
*
4
]
uint8
var
hdr
[
7
*
4
]
uint8
...
@@ -562,7 +573,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length i
...
@@ -562,7 +573,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length i
continue
continue
}
}
name
:=
fmt
.
Sprintf
(
"%s(%s/%s)"
,
pkg
,
sect
.
segname
,
sect
.
name
)
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
{
if
s
.
Type
!=
0
{
return
errorf
(
"duplicate %s/%s"
,
sect
.
segname
,
sect
.
name
)
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
...
@@ -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
{
if
machsym
.
type_
&
N_EXT
==
0
{
v
=
localSymVersion
v
=
localSymVersion
}
}
s
:=
syms
.
L
ookup
(
name
,
v
)
s
:=
l
ookup
(
name
,
v
)
if
machsym
.
type_
&
N_EXT
==
0
{
if
machsym
.
type_
&
N_EXT
==
0
{
s
.
Attr
|=
sym
.
AttrDuplicateOK
s
.
Attr
|=
sym
.
AttrDuplicateOK
}
}
...
...
src/cmd/link/internal/loadpe/ldpe.go
View file @
bababde7
...
@@ -9,6 +9,7 @@ import (
...
@@ -9,6 +9,7 @@ import (
"cmd/internal/bio"
"cmd/internal/bio"
"cmd/internal/objabi"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/internal/sys"
"cmd/link/internal/loader"
"cmd/link/internal/sym"
"cmd/link/internal/sym"
"debug/pe"
"debug/pe"
"encoding/binary"
"encoding/binary"
...
@@ -144,12 +145,21 @@ func (f *peBiobuf) ReadAt(p []byte, off int64) (int, error) {
...
@@ -144,12 +145,21 @@ func (f *peBiobuf) ReadAt(p []byte, off int64) (int, error) {
return
n
,
nil
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.
// 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.
// 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
)
{
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
)
{
localSymVersion
:=
syms
.
IncVersion
()
sectsyms
:=
make
(
map
[
*
pe
.
Section
]
*
sym
.
Symbol
)
sectsyms
:=
make
(
map
[
*
pe
.
Section
]
*
sym
.
Symbol
)
sectdata
:=
make
(
map
[
*
pe
.
Section
][]
byte
)
sectdata
:=
make
(
map
[
*
pe
.
Section
][]
byte
)
...
@@ -181,7 +191,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, leng
...
@@ -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
)
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
)
{
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
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
...
@@ -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
))
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
]
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
{
if
err
!=
nil
{
return
nil
,
nil
,
err
return
nil
,
nil
,
err
}
}
...
@@ -351,7 +361,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, leng
...
@@ -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
{
if
err
!=
nil
{
return
nil
,
nil
,
err
return
nil
,
nil
,
err
}
}
...
@@ -435,7 +445,7 @@ func issect(s *pe.COFFSymbol) bool {
...
@@ -435,7 +445,7 @@ func issect(s *pe.COFFSymbol) bool {
return
s
.
StorageClass
==
IMAGE_SYM_CLASS_STATIC
&&
s
.
Type
==
0
&&
s
.
Name
[
0
]
==
'.'
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
)
symname
,
err
:=
pesym
.
FullName
(
f
.
StringTable
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -481,10 +491,10 @@ func readpesym(arch *sys.Arch, syms *sym.Symbols, f *pe.File, pesym *pe.COFFSymb
...
@@ -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
:
case
IMAGE_SYM_DTYPE_FUNCTION
,
IMAGE_SYM_DTYPE_NULL
:
switch
pesym
.
StorageClass
{
switch
pesym
.
StorageClass
{
case
IMAGE_SYM_CLASS_EXTERNAL
:
//global
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
:
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
s
.
Attr
|=
sym
.
AttrDuplicateOK
default
:
default
:
...
...
src/cmd/link/internal/loadxcoff/ldxcoff.go
View file @
bababde7
...
@@ -9,6 +9,7 @@ import (
...
@@ -9,6 +9,7 @@ import (
"cmd/internal/bio"
"cmd/internal/bio"
"cmd/internal/objabi"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/internal/sys"
"cmd/link/internal/loader"
"cmd/link/internal/sym"
"cmd/link/internal/sym"
"errors"
"errors"
"fmt"
"fmt"
...
@@ -38,13 +39,25 @@ func (f *xcoffBiobuf) ReadAt(p []byte, off int64) (int, error) {
...
@@ -38,13 +39,25 @@ func (f *xcoffBiobuf) ReadAt(p []byte, off int64) (int, error) {
return
n
,
nil
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.
// 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
)
{
errorf
:=
func
(
str
string
,
args
...
interface
{})
([]
*
sym
.
Symbol
,
error
)
{
return
nil
,
fmt
.
Errorf
(
"loadxcoff: %v: %v"
,
pn
,
fmt
.
Sprintf
(
str
,
args
...
))
return
nil
,
fmt
.
Errorf
(
"loadxcoff: %v: %v"
,
pn
,
fmt
.
Sprintf
(
str
,
args
...
))
}
}
localSymVersion
:=
syms
.
IncVersion
()
var
ldSections
[]
*
ldSection
var
ldSections
[]
*
ldSection
...
@@ -62,7 +75,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, leng
...
@@ -62,7 +75,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, leng
lds
:=
new
(
ldSection
)
lds
:=
new
(
ldSection
)
lds
.
Section
=
*
sect
lds
.
Section
=
*
sect
name
:=
fmt
.
Sprintf
(
"%s(%s)"
,
pkg
,
lds
.
Name
)
name
:=
fmt
.
Sprintf
(
"%s(%s)"
,
pkg
,
lds
.
Name
)
s
:=
syms
.
L
ookup
(
name
,
localSymVersion
)
s
:=
l
ookup
(
name
,
localSymVersion
)
switch
lds
.
Type
{
switch
lds
.
Type
{
default
:
default
:
...
@@ -100,7 +113,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, leng
...
@@ -100,7 +113,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, leng
continue
continue
}
}
s
:=
syms
.
L
ookup
(
sx
.
Name
,
0
)
s
:=
l
ookup
(
sx
.
Name
,
0
)
// Text symbol
// Text symbol
if
s
.
Type
==
sym
.
STEXT
{
if
s
.
Type
==
sym
.
STEXT
{
...
@@ -122,7 +135,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, leng
...
@@ -122,7 +135,7 @@ func Load(arch *sys.Arch, syms *sym.Symbols, input *bio.Reader, pkg string, leng
for
i
,
rx
:=
range
sect
.
Relocs
{
for
i
,
rx
:=
range
sect
.
Relocs
{
r
:=
&
rs
[
i
]
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
{
if
uint64
(
int32
(
rx
.
VirtualAddress
))
!=
rx
.
VirtualAddress
{
return
errorf
(
"virtual address of a relocation is too big: 0x%x"
,
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:
...
@@ -369,7 +369,7 @@ overwrite:
pc
.
InlTree
[
i
]
.
Parent
=
r
.
readInt32
()
pc
.
InlTree
[
i
]
.
Parent
=
r
.
readInt32
()
pc
.
InlTree
[
i
]
.
File
=
r
.
readSymIndex
()
pc
.
InlTree
[
i
]
.
File
=
r
.
readSymIndex
()
pc
.
InlTree
[
i
]
.
Line
=
r
.
readInt32
()
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
()
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 {
...
@@ -550,7 +550,7 @@ func archreloctoc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
const
prefix
=
"TOC."
const
prefix
=
"TOC."
var
tarSym
*
sym
.
Symbol
var
tarSym
*
sym
.
Symbol
if
strings
.
HasPrefix
(
r
.
Sym
.
Name
,
prefix
)
{
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
{
}
else
{
ld
.
Errorf
(
s
,
"archreloctoc called for a symbol without TOC anchor"
)
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 {
...
@@ -534,7 +534,7 @@ type InlinedCall struct {
Parent
int32
// index of parent in InlTree
Parent
int32
// index of parent in InlTree
File
*
Symbol
// file of the inlined call
File
*
Symbol
// file of the inlined call
Line
int32
// line number 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)
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 {
...
@@ -86,6 +86,17 @@ func (syms *Symbols) ROLookup(name string, v int) *Symbol {
return
syms
.
hash
[
v
][
name
]
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).
// Allocate a new version (i.e. symbol namespace).
func
(
syms
*
Symbols
)
IncVersion
()
int
{
func
(
syms
*
Symbols
)
IncVersion
()
int
{
syms
.
hash
=
append
(
syms
.
hash
,
make
(
map
[
string
]
*
Symbol
))
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{
...
@@ -161,3 +161,8 @@ var RelROMap = map[SymKind]SymKind{
SRODATA
:
SRODATARELRO
,
SRODATA
:
SRODATARELRO
,
SFUNCTAB
:
SFUNCTABRELRO
,
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) {
...
@@ -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
...
@@ -29,9 +29,9 @@ TEXT runtime∕internal∕atomic·Cas(SB),NOSPLIT|NOFRAME,$0
CMP
$
7
,
R11
CMP
$
7
,
R11
BLT
2
(
PC
)
BLT
2
(
PC
)
JMP
·
armcas
(
SB
)
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
MOVW
ptr
+
0
(
FP
),
R2
//
trigger
potential
paging
fault
here
,
//
trigger
potential
paging
fault
here
,
//
because
we
don
't know how to traceback through __kuser_cmpxchg
//
because
we
don
't know how to traceback through __kuser_cmpxchg
...
...
test/linkx.go
View file @
bababde7
...
@@ -29,4 +29,10 @@ func main() {
...
@@ -29,4 +29,10 @@ func main() {
fmt
.
Println
(
overwrite
)
fmt
.
Println
(
overwrite
)
fmt
.
Println
(
overwritecopy
)
fmt
.
Println
(
overwritecopy
)
fmt
.
Println
(
arraycopy
[
1
])
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