aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/link/internal
diff options
context:
space:
mode:
authorRick Hudson <rlh@golang.org>2016-04-27 18:19:16 -0400
committerRick Hudson <rlh@golang.org>2016-04-27 18:46:52 -0400
commit23aeb34df172b17b7bfaa85fb59ca64bef9073bb (patch)
treea8ab866f1e50f0059856ce628f036d93ab620155 /src/cmd/link/internal
parent1354b32cd70f2702381764fd595dd2faa996840c (diff)
parentd3c79d324acd7300b6f705e66af8ca711af00d9f (diff)
downloadgo-23aeb34df172b17b7bfaa85fb59ca64bef9073bb.tar.xz
[dev.garbage] Merge remote-tracking branch 'origin/master' into HEAD
Change-Id: I282fd9ce9db435dfd35e882a9502ab1abc185297
Diffstat (limited to 'src/cmd/link/internal')
-rw-r--r--src/cmd/link/internal/amd64/asm.go55
-rw-r--r--src/cmd/link/internal/amd64/l.go5
-rw-r--r--src/cmd/link/internal/amd64/obj.go11
-rw-r--r--src/cmd/link/internal/amd64/z.go1
-rw-r--r--src/cmd/link/internal/arm/asm.go77
-rw-r--r--src/cmd/link/internal/arm/l.go2
-rw-r--r--src/cmd/link/internal/arm/obj.go9
-rw-r--r--src/cmd/link/internal/arm64/asm.go48
-rw-r--r--src/cmd/link/internal/arm64/l.go2
-rw-r--r--src/cmd/link/internal/arm64/obj.go9
-rw-r--r--src/cmd/link/internal/ld/ar.go23
-rw-r--r--src/cmd/link/internal/ld/arch.go97
-rw-r--r--src/cmd/link/internal/ld/data.go1032
-rw-r--r--src/cmd/link/internal/ld/deadcode.go63
-rw-r--r--src/cmd/link/internal/ld/decodesym.go126
-rw-r--r--src/cmd/link/internal/ld/dwarf.go1590
-rw-r--r--src/cmd/link/internal/ld/elf.go146
-rw-r--r--src/cmd/link/internal/ld/go.go36
-rw-r--r--src/cmd/link/internal/ld/ldelf.go214
-rw-r--r--src/cmd/link/internal/ld/ldmacho.go85
-rw-r--r--src/cmd/link/internal/ld/ldpe.go46
-rw-r--r--src/cmd/link/internal/ld/lib.go302
-rw-r--r--src/cmd/link/internal/ld/link.go45
-rw-r--r--src/cmd/link/internal/ld/macho.go126
-rw-r--r--src/cmd/link/internal/ld/macho_combine_dwarf.go4
-rw-r--r--src/cmd/link/internal/ld/objfile.go74
-rw-r--r--src/cmd/link/internal/ld/pcln.go146
-rw-r--r--src/cmd/link/internal/ld/pe.go51
-rw-r--r--src/cmd/link/internal/ld/pobj.go26
-rw-r--r--src/cmd/link/internal/ld/sym.go33
-rw-r--r--src/cmd/link/internal/ld/symtab.go121
-rw-r--r--src/cmd/link/internal/mips64/asm.go39
-rw-r--r--src/cmd/link/internal/mips64/l.go2
-rw-r--r--src/cmd/link/internal/mips64/obj.go15
-rw-r--r--src/cmd/link/internal/ppc64/asm.go69
-rw-r--r--src/cmd/link/internal/ppc64/l.go2
-rw-r--r--src/cmd/link/internal/ppc64/obj.go17
-rw-r--r--src/cmd/link/internal/s390x/asm.go27
-rw-r--r--src/cmd/link/internal/s390x/l.go5
-rw-r--r--src/cmd/link/internal/s390x/obj.go9
-rw-r--r--src/cmd/link/internal/x86/asm.go58
-rw-r--r--src/cmd/link/internal/x86/l.go3
-rw-r--r--src/cmd/link/internal/x86/obj.go9
43 files changed, 2207 insertions, 2653 deletions
diff --git a/src/cmd/link/internal/amd64/asm.go b/src/cmd/link/internal/amd64/asm.go
index d809f6e8ed..cdb0354579 100644
--- a/src/cmd/link/internal/amd64/asm.go
+++ b/src/cmd/link/internal/amd64/asm.go
@@ -86,12 +86,7 @@ func gentext() {
Addcall(ld.Ctxt, initfunc, addmoduledata)
// c: c3 retq
o(0xc3)
- if ld.Ctxt.Etextp != nil {
- ld.Ctxt.Etextp.Next = initfunc
- } else {
- ld.Ctxt.Textp = initfunc
- }
- ld.Ctxt.Etextp = initfunc
+ ld.Ctxt.Textp = append(ld.Ctxt.Textp, initfunc)
initarray_entry := ld.Linklookup(ld.Ctxt, "go.link.addmoduledatainit", 0)
initarray_entry.Attr |= ld.AttrReachable
initarray_entry.Attr |= ld.AttrLocal
@@ -99,12 +94,6 @@ func gentext() {
ld.Addaddr(ld.Ctxt, initarray_entry, initfunc)
}
-func adddynrela(rela *ld.LSym, s *ld.LSym, r *ld.Reloc) {
- ld.Addaddrplus(ld.Ctxt, rela, s, int64(r.Off))
- ld.Adduint64(ld.Ctxt, rela, ld.R_X86_64_RELATIVE)
- ld.Addaddrplus(ld.Ctxt, rela, r.Sym, r.Add) // Addend
-}
-
func adddynrel(s *ld.LSym, r *ld.Reloc) {
targ := r.Sym
ld.Ctxt.Cursym = s
@@ -285,7 +274,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
return
}
- if ld.HEADTYPE == obj.Hdarwin && s.Size == int64(ld.Thearch.Ptrsize) && r.Off == 0 {
+ if ld.HEADTYPE == obj.Hdarwin && s.Size == int64(ld.SysArch.PtrSize) && r.Off == 0 {
// Mach-O relocations are a royal pain to lay out.
// They use a compact stateful bytecode representation
// that is too much bother to deal with.
@@ -611,12 +600,12 @@ func addgotsym(s *ld.LSym) {
func asmb() {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f asmb\n", obj.Cputime())
}
ld.Bso.Flush()
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f codeblk\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f codeblk\n", obj.Cputime())
}
ld.Bso.Flush()
@@ -634,7 +623,7 @@ func asmb() {
if ld.Segrodata.Filelen > 0 {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
}
ld.Bso.Flush()
@@ -643,26 +632,18 @@ func asmb() {
}
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f datblk\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f datblk\n", obj.Cputime())
}
ld.Bso.Flush()
ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
+ ld.Cseek(int64(ld.Segdwarf.Fileoff))
+ ld.Dwarfblk(int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
+
machlink := int64(0)
if ld.HEADTYPE == obj.Hdarwin {
- if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
- }
-
- dwarfoff := ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Length), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND))
- ld.Cseek(dwarfoff)
-
- ld.Segdwarf.Fileoff = uint64(ld.Cpos())
- ld.Dwarfemitdebugsections()
- ld.Segdwarf.Filelen = uint64(ld.Cpos()) - ld.Segdwarf.Fileoff
-
machlink = ld.Domacholink()
}
@@ -696,7 +677,7 @@ func asmb() {
symo := int64(0)
if ld.Debug['s'] == 0 {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f sym\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f sym\n", obj.Cputime())
}
ld.Bso.Flush()
switch ld.HEADTYPE {
@@ -715,11 +696,11 @@ func asmb() {
obj.Hdragonfly,
obj.Hsolaris,
obj.Hnacl:
- symo = int64(ld.Segdata.Fileoff + ld.Segdata.Filelen)
+ symo = int64(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
symo = ld.Rnd(symo, int64(ld.INITRND))
case obj.Hwindows:
- symo = int64(ld.Segdata.Fileoff + ld.Segdata.Filelen)
+ symo = int64(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
symo = ld.Rnd(symo, ld.PEFILEALIGN)
}
@@ -733,11 +714,9 @@ func asmb() {
ld.Cwrite(ld.Elfstrdat)
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f dwarf\n", obj.Cputime())
}
- ld.Dwarfemitdebugsections()
-
if ld.Linkmode == ld.LinkExternal {
ld.Elfemitreloc()
}
@@ -751,7 +730,7 @@ func asmb() {
if sym != nil {
ld.Lcsize = int32(len(sym.P))
for i := 0; int32(i) < ld.Lcsize; i++ {
- ld.Cput(uint8(sym.P[i]))
+ ld.Cput(sym.P[i])
}
ld.Cflush()
@@ -759,11 +738,9 @@ func asmb() {
case obj.Hwindows:
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f dwarf\n", obj.Cputime())
}
- ld.Dwarfemitdebugsections()
-
case obj.Hdarwin:
if ld.Linkmode == ld.LinkExternal {
ld.Machoemitreloc()
@@ -772,7 +749,7 @@ func asmb() {
}
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f headr\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f headr\n", obj.Cputime())
}
ld.Bso.Flush()
ld.Cseek(0)
diff --git a/src/cmd/link/internal/amd64/l.go b/src/cmd/link/internal/amd64/l.go
index 4ec8610afb..2fbc8adc51 100644
--- a/src/cmd/link/internal/amd64/l.go
+++ b/src/cmd/link/internal/amd64/l.go
@@ -31,16 +31,11 @@
package amd64
const (
- thechar = '6'
MaxAlign = 32 // max data alignment
MinAlign = 1 // min data alignment
FuncAlign = 16
)
-const (
- MINLC = 1
-)
-
/* Used by ../internal/ld/dwarf.go */
const (
DWARFREGSP = 7
diff --git a/src/cmd/link/internal/amd64/obj.go b/src/cmd/link/internal/amd64/obj.go
index f9e13f2e18..860f588224 100644
--- a/src/cmd/link/internal/amd64/obj.go
+++ b/src/cmd/link/internal/amd64/obj.go
@@ -32,6 +32,7 @@ package amd64
import (
"cmd/internal/obj"
+ "cmd/internal/sys"
"cmd/link/internal/ld"
"fmt"
"log"
@@ -45,20 +46,14 @@ func Main() {
}
func linkarchinit() {
- ld.Thestring = "amd64"
- ld.Thelinkarch = &ld.Linkamd64
+ ld.SysArch = sys.ArchAMD64
if obj.Getgoarch() == "amd64p32" {
- ld.Thelinkarch = &ld.Linkamd64p32
+ ld.SysArch = sys.ArchAMD64P32
}
- ld.Thearch.Thechar = thechar
- ld.Thearch.Ptrsize = ld.Thelinkarch.Ptrsize
- ld.Thearch.Intsize = ld.Thelinkarch.Ptrsize
- ld.Thearch.Regsize = ld.Thelinkarch.Regsize
ld.Thearch.Funcalign = FuncAlign
ld.Thearch.Maxalign = MaxAlign
ld.Thearch.Minalign = MinAlign
- ld.Thearch.Minlc = MINLC
ld.Thearch.Dwarfregsp = DWARFREGSP
ld.Thearch.Dwarfreglr = DWARFREGLR
diff --git a/src/cmd/link/internal/amd64/z.go b/src/cmd/link/internal/amd64/z.go
deleted file mode 100644
index f70035b9e3..0000000000
--- a/src/cmd/link/internal/amd64/z.go
+++ /dev/null
@@ -1 +0,0 @@
-package amd64
diff --git a/src/cmd/link/internal/arm/asm.go b/src/cmd/link/internal/arm/asm.go
index bb90cf77b6..aafdd9bc3d 100644
--- a/src/cmd/link/internal/arm/asm.go
+++ b/src/cmd/link/internal/arm/asm.go
@@ -95,12 +95,7 @@ func gentext() {
rel.Type = obj.R_PCREL
rel.Add = 4
- if ld.Ctxt.Etextp != nil {
- ld.Ctxt.Etextp.Next = initfunc
- } else {
- ld.Ctxt.Textp = initfunc
- }
- ld.Ctxt.Etextp = initfunc
+ ld.Ctxt.Textp = append(ld.Ctxt.Textp, initfunc)
initarray_entry := ld.Linklookup(ld.Ctxt, "go.link.addmoduledatainit", 0)
initarray_entry.Attr |= ld.AttrReachable
initarray_entry.Attr |= ld.AttrLocal
@@ -114,11 +109,6 @@ func braddoff(a int32, b int32) int32 {
return int32((uint32(a))&0xff000000 | 0x00ffffff&uint32(a+b))
}
-func adddynrela(rel *ld.LSym, s *ld.LSym, r *ld.Reloc) {
- ld.Addaddrplus(ld.Ctxt, rel, s, int64(r.Off))
- ld.Adduint32(ld.Ctxt, rel, ld.R_ARM_RELATIVE)
-}
-
func adddynrel(s *ld.LSym, r *ld.Reloc) {
targ := r.Sym
ld.Ctxt.Cursym = s
@@ -340,6 +330,36 @@ func machoreloc1(r *ld.Reloc, sectoff int64) int {
rs := r.Xsym
+ if r.Type == obj.R_PCREL {
+ if rs.Type == obj.SHOSTOBJ {
+ ld.Diag("pc-relative relocation of external symbol is not supported")
+ return -1
+ }
+ if r.Siz != 4 {
+ return -1
+ }
+
+ // emit a pair of "scattered" relocations that
+ // resolve to the difference of section addresses of
+ // the symbol and the instruction
+ // this value is added to the field being relocated
+ o1 := uint32(sectoff)
+ o1 |= 1 << 31 // scattered bit
+ o1 |= ld.MACHO_ARM_RELOC_SECTDIFF << 24
+ o1 |= 2 << 28 // size = 4
+
+ o2 := uint32(0)
+ o2 |= 1 << 31 // scattered bit
+ o2 |= ld.MACHO_ARM_RELOC_PAIR << 24
+ o2 |= 2 << 28 // size = 4
+
+ ld.Thearch.Lput(o1)
+ ld.Thearch.Lput(uint32(ld.Symaddr(rs)))
+ ld.Thearch.Lput(o2)
+ ld.Thearch.Lput(uint32(ld.Ctxt.Cursym.Value + int64(r.Off)))
+ return 0
+ }
+
if rs.Type == obj.SHOSTOBJ || r.Type == obj.R_CALLARM {
if rs.Dynid < 0 {
ld.Diag("reloc %d to non-macho symbol %s type=%d", r.Type, rs.Name, rs.Type)
@@ -563,7 +583,7 @@ func addgotsym(ctxt *ld.Link, s *ld.LSym) {
func asmb() {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f asmb\n", obj.Cputime())
}
ld.Bso.Flush()
@@ -581,7 +601,7 @@ func asmb() {
if ld.Segrodata.Filelen > 0 {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
}
ld.Bso.Flush()
@@ -590,26 +610,18 @@ func asmb() {
}
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f datblk\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f datblk\n", obj.Cputime())
}
ld.Bso.Flush()
ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
+ ld.Cseek(int64(ld.Segdwarf.Fileoff))
+ ld.Dwarfblk(int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
+
machlink := uint32(0)
if ld.HEADTYPE == obj.Hdarwin {
- if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
- }
-
- dwarfoff := uint32(ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Length), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND)))
- ld.Cseek(int64(dwarfoff))
-
- ld.Segdwarf.Fileoff = uint64(ld.Cpos())
- ld.Dwarfemitdebugsections()
- ld.Segdwarf.Filelen = uint64(ld.Cpos()) - ld.Segdwarf.Fileoff
-
machlink = uint32(ld.Domacholink())
}
@@ -621,13 +633,13 @@ func asmb() {
if ld.Debug['s'] == 0 {
// TODO: rationalize
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f sym\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f sym\n", obj.Cputime())
}
ld.Bso.Flush()
switch ld.HEADTYPE {
default:
if ld.Iself {
- symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
+ symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND)))
}
@@ -643,17 +655,12 @@ func asmb() {
default:
if ld.Iself {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f elfsym\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f elfsym\n", obj.Cputime())
}
ld.Asmelfsym()
ld.Cflush()
ld.Cwrite(ld.Elfstrdat)
- if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
- }
- ld.Dwarfemitdebugsections()
-
if ld.Linkmode == ld.LinkExternal {
ld.Elfemitreloc()
}
@@ -667,7 +674,7 @@ func asmb() {
if sym != nil {
ld.Lcsize = int32(len(sym.P))
for i := 0; int32(i) < ld.Lcsize; i++ {
- ld.Cput(uint8(sym.P[i]))
+ ld.Cput(sym.P[i])
}
ld.Cflush()
@@ -682,7 +689,7 @@ func asmb() {
ld.Ctxt.Cursym = nil
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f header\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f header\n", obj.Cputime())
}
ld.Bso.Flush()
ld.Cseek(0)
diff --git a/src/cmd/link/internal/arm/l.go b/src/cmd/link/internal/arm/l.go
index 58aecc4b64..2b73a7b172 100644
--- a/src/cmd/link/internal/arm/l.go
+++ b/src/cmd/link/internal/arm/l.go
@@ -63,11 +63,9 @@ package arm
// THE SOFTWARE.
const (
- thechar = '5'
MaxAlign = 8 // max data alignment
MinAlign = 1 // min data alignment
FuncAlign = 4 // single-instruction alignment
- MINLC = 4
)
/* Used by ../internal/ld/dwarf.go */
diff --git a/src/cmd/link/internal/arm/obj.go b/src/cmd/link/internal/arm/obj.go
index bcd61fda9b..9125a1fa32 100644
--- a/src/cmd/link/internal/arm/obj.go
+++ b/src/cmd/link/internal/arm/obj.go
@@ -32,6 +32,7 @@ package arm
import (
"cmd/internal/obj"
+ "cmd/internal/sys"
"cmd/link/internal/ld"
"fmt"
"log"
@@ -45,17 +46,11 @@ func Main() {
}
func linkarchinit() {
- ld.Thestring = "arm"
- ld.Thelinkarch = &ld.Linkarm
+ ld.SysArch = sys.ArchARM
- ld.Thearch.Thechar = thechar
- ld.Thearch.Ptrsize = ld.Thelinkarch.Ptrsize
- ld.Thearch.Intsize = ld.Thelinkarch.Ptrsize
- ld.Thearch.Regsize = ld.Thelinkarch.Regsize
ld.Thearch.Funcalign = FuncAlign
ld.Thearch.Maxalign = MaxAlign
ld.Thearch.Minalign = MinAlign
- ld.Thearch.Minlc = MINLC
ld.Thearch.Dwarfregsp = DWARFREGSP
ld.Thearch.Dwarfreglr = DWARFREGLR
diff --git a/src/cmd/link/internal/arm64/asm.go b/src/cmd/link/internal/arm64/asm.go
index 250f0afb16..97803c9d03 100644
--- a/src/cmd/link/internal/arm64/asm.go
+++ b/src/cmd/link/internal/arm64/asm.go
@@ -78,12 +78,7 @@ func gentext() {
rel.Sym = ld.Linklookup(ld.Ctxt, "runtime.addmoduledata", 0)
rel.Type = obj.R_CALLARM64 // Really should be R_AARCH64_JUMP26 but doesn't seem to make any difference
- if ld.Ctxt.Etextp != nil {
- ld.Ctxt.Etextp.Next = initfunc
- } else {
- ld.Ctxt.Textp = initfunc
- }
- ld.Ctxt.Etextp = initfunc
+ ld.Ctxt.Textp = append(ld.Ctxt.Textp, initfunc)
initarray_entry := ld.Linklookup(ld.Ctxt, "go.link.addmoduledatainit", 0)
initarray_entry.Attr |= ld.AttrReachable
initarray_entry.Attr |= ld.AttrLocal
@@ -91,10 +86,6 @@ func gentext() {
ld.Addaddr(ld.Ctxt, initarray_entry, initfunc)
}
-func adddynrela(rel *ld.LSym, s *ld.LSym, r *ld.Reloc) {
- log.Fatalf("adddynrela not implemented")
-}
-
func adddynrel(s *ld.LSym, r *ld.Reloc) {
log.Fatalf("adddynrel not implemented")
}
@@ -375,7 +366,7 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
}
// The TCB is two pointers. This is not documented anywhere, but is
// de facto part of the ABI.
- v := r.Sym.Value + int64(2*ld.Thearch.Ptrsize)
+ v := r.Sym.Value + int64(2*ld.SysArch.PtrSize)
if v < 0 || v >= 32678 {
ld.Diag("TLS offset out of range %d", v)
}
@@ -401,7 +392,7 @@ func archrelocvariant(r *ld.Reloc, s *ld.LSym, t int64) int64 {
func asmb() {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f asmb\n", obj.Cputime())
}
ld.Bso.Flush()
@@ -419,7 +410,7 @@ func asmb() {
if ld.Segrodata.Filelen > 0 {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
}
ld.Bso.Flush()
@@ -428,26 +419,18 @@ func asmb() {
}
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f datblk\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f datblk\n", obj.Cputime())
}
ld.Bso.Flush()
ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
+ ld.Cseek(int64(ld.Segdwarf.Fileoff))
+ ld.Dwarfblk(int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
+
machlink := uint32(0)
if ld.HEADTYPE == obj.Hdarwin {
- if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
- }
-
- dwarfoff := uint32(ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Length), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND)))
- ld.Cseek(int64(dwarfoff))
-
- ld.Segdwarf.Fileoff = uint64(ld.Cpos())
- ld.Dwarfemitdebugsections()
- ld.Segdwarf.Filelen = uint64(ld.Cpos()) - ld.Segdwarf.Fileoff
-
machlink = uint32(ld.Domacholink())
}
@@ -459,13 +442,13 @@ func asmb() {
if ld.Debug['s'] == 0 {
// TODO: rationalize
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f sym\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f sym\n", obj.Cputime())
}
ld.Bso.Flush()
switch ld.HEADTYPE {
default:
if ld.Iself {
- symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
+ symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND)))
}
@@ -481,17 +464,12 @@ func asmb() {
default:
if ld.Iself {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f elfsym\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f elfsym\n", obj.Cputime())
}
ld.Asmelfsym()
ld.Cflush()
ld.Cwrite(ld.Elfstrdat)
- if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
- }
- ld.Dwarfemitdebugsections()
-
if ld.Linkmode == ld.LinkExternal {
ld.Elfemitreloc()
}
@@ -505,7 +483,7 @@ func asmb() {
if sym != nil {
ld.Lcsize = int32(len(sym.P))
for i := 0; int32(i) < ld.Lcsize; i++ {
- ld.Cput(uint8(sym.P[i]))
+ ld.Cput(sym.P[i])
}
ld.Cflush()
@@ -520,7 +498,7 @@ func asmb() {
ld.Ctxt.Cursym = nil
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f header\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f header\n", obj.Cputime())
}
ld.Bso.Flush()
ld.Cseek(0)
diff --git a/src/cmd/link/internal/arm64/l.go b/src/cmd/link/internal/arm64/l.go
index b9b7ea50e3..67ad5c977f 100644
--- a/src/cmd/link/internal/arm64/l.go
+++ b/src/cmd/link/internal/arm64/l.go
@@ -62,11 +62,9 @@ package arm64
// THE SOFTWARE.
const (
- thechar = '7'
MaxAlign = 32 // max data alignment
MinAlign = 1 // min data alignment
FuncAlign = 8
- MINLC = 4
)
/* Used by ../internal/ld/dwarf.go */
diff --git a/src/cmd/link/internal/arm64/obj.go b/src/cmd/link/internal/arm64/obj.go
index 693e106ff1..1169e79a58 100644
--- a/src/cmd/link/internal/arm64/obj.go
+++ b/src/cmd/link/internal/arm64/obj.go
@@ -32,6 +32,7 @@ package arm64
import (
"cmd/internal/obj"
+ "cmd/internal/sys"
"cmd/link/internal/ld"
"fmt"
"log"
@@ -45,17 +46,11 @@ func Main() {
}
func linkarchinit() {
- ld.Thestring = obj.Getgoarch()
- ld.Thelinkarch = &ld.Linkarm64
+ ld.SysArch = sys.ArchARM64
- ld.Thearch.Thechar = thechar
- ld.Thearch.Ptrsize = ld.Thelinkarch.Ptrsize
- ld.Thearch.Intsize = ld.Thelinkarch.Ptrsize
- ld.Thearch.Regsize = ld.Thelinkarch.Regsize
ld.Thearch.Funcalign = FuncAlign
ld.Thearch.Maxalign = MaxAlign
ld.Thearch.Minalign = MinAlign
- ld.Thearch.Minlc = MINLC
ld.Thearch.Dwarfregsp = DWARFREGSP
ld.Thearch.Dwarfreglr = DWARFREGLR
diff --git a/src/cmd/link/internal/ld/ar.go b/src/cmd/link/internal/ld/ar.go
index d07756071d..323dfbefc5 100644
--- a/src/cmd/link/internal/ld/ar.go
+++ b/src/cmd/link/internal/ld/ar.go
@@ -31,9 +31,11 @@
package ld
import (
+ "cmd/internal/bio"
"cmd/internal/obj"
"encoding/binary"
"fmt"
+ "io"
"os"
)
@@ -62,26 +64,26 @@ type ArHdr struct {
// define them. This is used for the compiler support library
// libgcc.a.
func hostArchive(name string) {
- f, err := obj.Bopenr(name)
+ f, err := bio.Open(name)
if err != nil {
if os.IsNotExist(err) {
// It's OK if we don't have a libgcc file at all.
if Debug['v'] != 0 {
- fmt.Fprintf(&Bso, "skipping libgcc file: %v\n", err)
+ fmt.Fprintf(Bso, "skipping libgcc file: %v\n", err)
}
return
}
Exitf("cannot open file %s: %v", name, err)
}
- defer obj.Bterm(f)
+ defer f.Close()
- magbuf := make([]byte, len(ARMAG))
- if obj.Bread(f, magbuf) != len(magbuf) {
+ var magbuf [len(ARMAG)]byte
+ if _, err := io.ReadFull(f, magbuf[:]); err != nil {
Exitf("file %s too short", name)
}
var arhdr ArHdr
- l := nextar(f, obj.Boffset(f), &arhdr)
+ l := nextar(f, f.Offset(), &arhdr)
if l <= 0 {
Exitf("%s missing armap", name)
}
@@ -117,7 +119,7 @@ func hostArchive(name string) {
l = atolwhex(arhdr.size)
h := ldobj(f, "libgcc", l, pname, name, ArchiveObj)
- obj.Bseek(f, h.off, 0)
+ f.Seek(h.off, 0)
h.ld(f, h.pkg, h.length, h.pn)
}
@@ -130,16 +132,15 @@ func hostArchive(name string) {
type archiveMap map[string]uint64
// readArmap reads the archive symbol map.
-func readArmap(filename string, f *obj.Biobuf, arhdr ArHdr) archiveMap {
+func readArmap(filename string, f *bio.Reader, arhdr ArHdr) archiveMap {
is64 := arhdr.name == "/SYM64/"
wordSize := 4
if is64 {
wordSize = 8
}
- l := atolwhex(arhdr.size)
- contents := make([]byte, l)
- if obj.Bread(f, contents) != int(l) {
+ contents := make([]byte, atolwhex(arhdr.size))
+ if _, err := io.ReadFull(f, contents); err != nil {
Exitf("short read from %s", filename)
}
diff --git a/src/cmd/link/internal/ld/arch.go b/src/cmd/link/internal/ld/arch.go
deleted file mode 100644
index d28f37fa02..0000000000
--- a/src/cmd/link/internal/ld/arch.go
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2015 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 ld
-
-import "encoding/binary"
-
-var Linkarm = LinkArch{
- ByteOrder: binary.LittleEndian,
- Name: "arm",
- Thechar: '5',
- Minlc: 4,
- Ptrsize: 4,
- Regsize: 4,
-}
-
-var Linkarm64 = LinkArch{
- ByteOrder: binary.LittleEndian,
- Name: "arm64",
- Thechar: '7',
- Minlc: 4,
- Ptrsize: 8,
- Regsize: 8,
-}
-
-var Linkamd64 = LinkArch{
- ByteOrder: binary.LittleEndian,
- Name: "amd64",
- Thechar: '6',
- Minlc: 1,
- Ptrsize: 8,
- Regsize: 8,
-}
-
-var Linkamd64p32 = LinkArch{
- ByteOrder: binary.LittleEndian,
- Name: "amd64p32",
- Thechar: '6',
- Minlc: 1,
- Ptrsize: 4,
- Regsize: 8,
-}
-
-var Link386 = LinkArch{
- ByteOrder: binary.LittleEndian,
- Name: "386",
- Thechar: '8',
- Minlc: 1,
- Ptrsize: 4,
- Regsize: 4,
-}
-
-var Linkppc64 = LinkArch{
- ByteOrder: binary.BigEndian,
- Name: "ppc64",
- Thechar: '9',
- Minlc: 4,
- Ptrsize: 8,
- Regsize: 8,
-}
-
-var Linkppc64le = LinkArch{
- ByteOrder: binary.LittleEndian,
- Name: "ppc64le",
- Thechar: '9',
- Minlc: 4,
- Ptrsize: 8,
- Regsize: 8,
-}
-
-var Linkmips64 = LinkArch{
- ByteOrder: binary.BigEndian,
- Name: "mips64",
- Thechar: '0',
- Minlc: 4,
- Ptrsize: 8,
- Regsize: 8,
-}
-
-var Linkmips64le = LinkArch{
- ByteOrder: binary.LittleEndian,
- Name: "mips64le",
- Thechar: '0',
- Minlc: 4,
- Ptrsize: 8,
- Regsize: 8,
-}
-
-var Links390x = LinkArch{
- ByteOrder: binary.BigEndian,
- Name: "s390x",
- Thechar: 'z',
- Minlc: 2,
- Ptrsize: 8,
- Regsize: 8,
-}
diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go
index fe74cc9208..8964757846 100644
--- a/src/cmd/link/internal/ld/data.go
+++ b/src/cmd/link/internal/ld/data.go
@@ -34,12 +34,14 @@ package ld
import (
"cmd/internal/gcprog"
"cmd/internal/obj"
+ "cmd/internal/sys"
"fmt"
"log"
"os"
"sort"
"strconv"
"strings"
+ "sync"
)
func Symgrow(ctxt *Link, s *LSym, siz int64) {
@@ -49,8 +51,9 @@ func Symgrow(ctxt *Link, s *LSym, siz int64) {
if int64(len(s.P)) >= siz {
return
}
- for cap(s.P) < int(siz) {
- s.P = append(s.P[:len(s.P)], 0)
+ if cap(s.P) < int(siz) {
+ p := make([]byte, 2*(siz+1))
+ s.P = append(p[:0], s.P...)
}
s.P = s.P[:siz]
}
@@ -78,12 +81,23 @@ func setuintxx(ctxt *Link, s *LSym, off int64, v uint64, wid int64) int64 {
case 4:
ctxt.Arch.ByteOrder.PutUint32(s.P[off:], uint32(v))
case 8:
- ctxt.Arch.ByteOrder.PutUint64(s.P[off:], uint64(v))
+ ctxt.Arch.ByteOrder.PutUint64(s.P[off:], v)
}
return off + wid
}
+func Addbytes(ctxt *Link, s *LSym, bytes []byte) int64 {
+ if s.Type == 0 {
+ s.Type = obj.SDATA
+ }
+ s.Attr |= AttrReachable
+ s.P = append(s.P, bytes...)
+ s.Size = int64(len(s.P))
+
+ return s.Size
+}
+
func adduintxx(ctxt *Link, s *LSym, v uint64, wid int) int64 {
off := s.Size
setuintxx(ctxt, s, off, v, int64(wid))
@@ -91,7 +105,15 @@ func adduintxx(ctxt *Link, s *LSym, v uint64, wid int) int64 {
}
func Adduint8(ctxt *Link, s *LSym, v uint8) int64 {
- return adduintxx(ctxt, s, uint64(v), 1)
+ off := s.Size
+ if s.Type == 0 {
+ s.Type = obj.SDATA
+ }
+ s.Attr |= AttrReachable
+ s.Size++
+ s.P = append(s.P, v)
+
+ return off
}
func Adduint16(ctxt *Link, s *LSym, v uint16) int64 {
@@ -107,7 +129,7 @@ func Adduint64(ctxt *Link, s *LSym, v uint64) int64 {
}
func adduint(ctxt *Link, s *LSym, v uint64) int64 {
- return adduintxx(ctxt, s, v, Thearch.Intsize)
+ return adduintxx(ctxt, s, v, SysArch.IntSize)
}
func setuint8(ctxt *Link, s *LSym, r int64, v uint8) int64 {
@@ -124,12 +146,12 @@ func Addaddrplus(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
}
s.Attr |= AttrReachable
i := s.Size
- s.Size += int64(ctxt.Arch.Ptrsize)
+ s.Size += int64(ctxt.Arch.PtrSize)
Symgrow(ctxt, s, s.Size)
r := Addrel(s)
r.Sym = t
r.Off = int32(i)
- r.Siz = uint8(ctxt.Arch.Ptrsize)
+ r.Siz = uint8(ctxt.Arch.PtrSize)
r.Type = obj.R_ADDR
r.Add = add
return i + int64(r.Siz)
@@ -149,7 +171,7 @@ func Addpcrelplus(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
r.Add = add
r.Type = obj.R_PCREL
r.Siz = 4
- if Thearch.Thechar == 'z' {
+ if SysArch.Family == sys.S390X {
r.Variant = RV_390_DBL
}
return i + int64(r.Siz)
@@ -164,15 +186,15 @@ func setaddrplus(ctxt *Link, s *LSym, off int64, t *LSym, add int64) int64 {
s.Type = obj.SDATA
}
s.Attr |= AttrReachable
- if off+int64(ctxt.Arch.Ptrsize) > s.Size {
- s.Size = off + int64(ctxt.Arch.Ptrsize)
+ if off+int64(ctxt.Arch.PtrSize) > s.Size {
+ s.Size = off + int64(ctxt.Arch.PtrSize)
Symgrow(ctxt, s, s.Size)
}
r := Addrel(s)
r.Sym = t
r.Off = int32(off)
- r.Siz = uint8(ctxt.Arch.Ptrsize)
+ r.Siz = uint8(ctxt.Arch.PtrSize)
r.Type = obj.R_ADDR
r.Add = add
return off + int64(r.Siz)
@@ -188,12 +210,12 @@ func addsize(ctxt *Link, s *LSym, t *LSym) int64 {
}
s.Attr |= AttrReachable
i := s.Size
- s.Size += int64(ctxt.Arch.Ptrsize)
+ s.Size += int64(ctxt.Arch.PtrSize)
Symgrow(ctxt, s, s.Size)
r := Addrel(s)
r.Sym = t
r.Off = int32(i)
- r.Siz = uint8(ctxt.Arch.Ptrsize)
+ r.Siz = uint8(ctxt.Arch.PtrSize)
r.Type = obj.R_SIZE
return i + int64(r.Siz)
}
@@ -221,10 +243,6 @@ func addaddrplus4(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
* Used for the data block.
*/
-func listnextp(s *LSym) **LSym {
- return &s.Next
-}
-
func listsubp(s *LSym) **LSym {
return &s.Sub
}
@@ -342,7 +360,7 @@ func relocsym(s *LSym) {
// We need to be able to reference dynimport symbols when linking against
// shared libraries, and Solaris needs it always
if HEADTYPE != obj.Hsolaris && r.Sym != nil && r.Sym.Type == obj.SDYNIMPORT && !DynlinkingGo() {
- if !(Thearch.Thechar == '9' && Linkmode == LinkExternal && r.Sym.Name == ".TOC.") {
+ if !(SysArch.Family == sys.PPC64 && Linkmode == LinkExternal && r.Sym.Name == ".TOC.") {
Diag("unhandled relocation for %s (type %d rtype %d)", r.Sym.Name, r.Sym.Type, r.Type)
}
}
@@ -351,7 +369,7 @@ func relocsym(s *LSym) {
}
// TODO(mundaym): remove this special case - see issue 14218.
- if Thearch.Thechar == 'z' {
+ if SysArch.Family == sys.S390X {
switch r.Type {
case obj.R_PCRELDBL:
r.Type = obj.R_PCREL
@@ -380,7 +398,7 @@ func relocsym(s *LSym) {
}
case obj.R_TLS_LE:
- isAndroidX86 := goos == "android" && (Thearch.Thechar == '6' || Thearch.Thechar == '8')
+ isAndroidX86 := goos == "android" && (SysArch.InFamily(sys.AMD64, sys.I386))
if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd && !isAndroidX86 {
r.Done = 0
@@ -390,13 +408,13 @@ func relocsym(s *LSym) {
r.Xsym = r.Sym
r.Xadd = r.Add
o = 0
- if Thearch.Thechar != '6' {
+ if SysArch.Family != sys.AMD64 {
o = r.Add
}
break
}
- if Iself && Thearch.Thechar == '5' {
+ if Iself && SysArch.Family == sys.ARM {
// On ELF ARM, the thread pointer is 8 bytes before
// the start of the thread-local data block, so add 8
// to the actual TLS offset (r->sym->value).
@@ -414,7 +432,7 @@ func relocsym(s *LSym) {
}
case obj.R_TLS_IE:
- isAndroidX86 := goos == "android" && (Thearch.Thechar == '6' || Thearch.Thechar == '8')
+ isAndroidX86 := goos == "android" && (SysArch.InFamily(sys.AMD64, sys.I386))
if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd && !isAndroidX86 {
r.Done = 0
@@ -424,7 +442,7 @@ func relocsym(s *LSym) {
r.Xsym = r.Sym
r.Xadd = r.Add
o = 0
- if Thearch.Thechar != '6' {
+ if SysArch.Family != sys.AMD64 {
o = r.Add
}
break
@@ -451,7 +469,7 @@ func relocsym(s *LSym) {
o = r.Xadd
if Iself {
- if Thearch.Thechar == '6' {
+ if SysArch.Family == sys.AMD64 {
o = 0
}
} else if HEADTYPE == obj.Hdarwin {
@@ -461,10 +479,10 @@ func relocsym(s *LSym) {
// The workaround is that on arm64 don't ever add symaddr to o and always use
// extern relocation by requiring rs->dynid >= 0.
if rs.Type != obj.SHOSTOBJ {
- if Thearch.Thechar == '7' && rs.Dynid < 0 {
+ if SysArch.Family == sys.ARM64 && rs.Dynid < 0 {
Diag("R_ADDR reloc to %s+%d is not supported on darwin/arm64", rs.Name, o)
}
- if Thearch.Thechar != '7' {
+ if SysArch.Family != sys.ARM64 {
o += Symaddr(rs)
}
}
@@ -484,11 +502,33 @@ func relocsym(s *LSym) {
// fail at runtime. See https://golang.org/issue/7980.
// Instead of special casing only amd64, we treat this as an error on all
// 64-bit architectures so as to be future-proof.
- if int32(o) < 0 && Thearch.Ptrsize > 4 && siz == 4 {
+ if int32(o) < 0 && SysArch.PtrSize > 4 && siz == 4 {
Diag("non-pc-relative relocation address is too big: %#x (%#x + %#x)", uint64(o), Symaddr(r.Sym), r.Add)
errorexit()
}
+ case obj.R_DWARFREF:
+ if r.Sym.Sect == nil {
+ Diag("missing DWARF section: %s from %s", r.Sym.Name, s.Name)
+ }
+ if Linkmode == LinkExternal {
+ r.Done = 0
+ r.Type = obj.R_ADDR
+
+ r.Xsym = Linkrlookup(Ctxt, r.Sym.Sect.Name, 0)
+ r.Xadd = r.Add + Symaddr(r.Sym) - int64(r.Sym.Sect.Vaddr)
+ o = r.Xadd
+ rs = r.Xsym
+ if Iself && SysArch.Family == sys.AMD64 {
+ o = 0
+ }
+ break
+ }
+ o = Symaddr(r.Sym) + r.Add - int64(r.Sym.Sect.Vaddr)
+
+ case obj.R_ADDROFF:
+ o = Symaddr(r.Sym) - int64(r.Sym.Sect.Vaddr) + r.Add
+
// r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
case obj.R_CALL, obj.R_GOTPCREL, obj.R_PCREL:
if Linkmode == LinkExternal && r.Sym != nil && r.Sym.Type != obj.SCONST && (r.Sym.Sect != Ctxt.Cursym.Sect || r.Type == obj.R_GOTPCREL) {
@@ -511,7 +551,7 @@ func relocsym(s *LSym) {
o = r.Xadd
if Iself {
- if Thearch.Thechar == '6' {
+ if SysArch.Family == sys.AMD64 {
o = 0
}
} else if HEADTYPE == obj.Hdarwin {
@@ -520,10 +560,13 @@ func relocsym(s *LSym) {
o += int64(uint64(Symaddr(rs)) - rs.Sect.Vaddr)
}
o -= int64(r.Off) // relative to section offset, not symbol
+ } else if SysArch.Family == sys.ARM {
+ // see ../arm/asm.go:/machoreloc1
+ o += Symaddr(rs) - int64(Ctxt.Cursym.Value) - int64(r.Off)
} else {
o += int64(r.Siz)
}
- } else if HEADTYPE == obj.Hwindows && Thearch.Thechar == '6' { // only amd64 needs PCREL
+ } else if HEADTYPE == obj.Hwindows && SysArch.Family == sys.AMD64 { // only amd64 needs PCREL
// PE/COFF's PC32 relocation uses the address after the relocated
// bytes as the base. Compensate by skewing the addend.
o += int64(r.Siz)
@@ -604,14 +647,17 @@ func relocsym(s *LSym) {
func reloc() {
if Debug['v'] != 0 {
- fmt.Fprintf(&Bso, "%5.2f reloc\n", obj.Cputime())
+ fmt.Fprintf(Bso, "%5.2f reloc\n", obj.Cputime())
}
Bso.Flush()
- for s := Ctxt.Textp; s != nil; s = s.Next {
+ for _, s := range Ctxt.Textp {
relocsym(s)
}
- for s := datap; s != nil; s = s.Next {
+ for _, sym := range datap {
+ relocsym(sym)
+ }
+ for s := dwarfp; s != nil; s = s.Next {
relocsym(s)
}
}
@@ -622,11 +668,9 @@ func dynrelocsym(s *LSym) {
if s == rel {
return
}
- var r *Reloc
- var targ *LSym
for ri := 0; ri < len(s.R); ri++ {
- r = &s.R[ri]
- targ = r.Sym
+ r := &s.R[ri]
+ targ := r.Sym
if targ == nil {
continue
}
@@ -639,7 +683,7 @@ func dynrelocsym(s *LSym) {
r.Add = int64(targ.Plt)
// jmp *addr
- if Thearch.Thechar == '8' {
+ if SysArch.Family == sys.I386 {
Adduint8(Ctxt, rel, 0xff)
Adduint8(Ctxt, rel, 0x25)
Addaddr(Ctxt, rel, targ)
@@ -661,9 +705,8 @@ func dynrelocsym(s *LSym) {
return
}
- var r *Reloc
for ri := 0; ri < len(s.R); ri++ {
- r = &s.R[ri]
+ r := &s.R[ri]
if r.Sym != nil && r.Sym.Type == obj.SDYNIMPORT || r.Type >= 256 {
if r.Sym != nil && !r.Sym.Attr.Reachable() {
Diag("internal inconsistency: dynamic symbol %s is not reachable.", r.Sym.Name)
@@ -673,22 +716,24 @@ func dynrelocsym(s *LSym) {
}
}
-func dynreloc() {
+func dynreloc(data *[obj.SXREF][]*LSym) {
// -d suppresses dynamic loader format, so we may as well not
// compute these sections or mark their symbols as reachable.
if Debug['d'] != 0 && HEADTYPE != obj.Hwindows {
return
}
if Debug['v'] != 0 {
- fmt.Fprintf(&Bso, "%5.2f reloc\n", obj.Cputime())
+ fmt.Fprintf(Bso, "%5.2f reloc\n", obj.Cputime())
}
Bso.Flush()
- for s := Ctxt.Textp; s != nil; s = s.Next {
+ for _, s := range Ctxt.Textp {
dynrelocsym(s)
}
- for s := datap; s != nil; s = s.Next {
- dynrelocsym(s)
+ for _, syms := range data {
+ for _, sym := range syms {
+ dynrelocsym(sym)
+ }
}
if Iself {
elfdynhash()
@@ -705,7 +750,6 @@ func blk(start *LSym, addr int64, size int64) {
}
eaddr := addr + size
- var p []byte
for ; sym != nil; sym = sym.Next {
if sym.Type&obj.SSUB != 0 {
continue
@@ -715,7 +759,7 @@ func blk(start *LSym, addr int64, size int64) {
}
Ctxt.Cursym = sym
if sym.Value < addr {
- Diag("phase error: addr=%#x but sym=%#x type=%d", int64(addr), int64(sym.Value), sym.Type)
+ Diag("phase error: addr=%#x but sym=%#x type=%d", addr, sym.Value, sym.Type)
errorexit()
}
@@ -723,15 +767,14 @@ func blk(start *LSym, addr int64, size int64) {
strnput("", int(sym.Value-addr))
addr = sym.Value
}
- p = sym.P
- Cwrite(p)
+ Cwrite(sym.P)
addr += int64(len(sym.P))
if addr < sym.Value+sym.Size {
strnput("", int(sym.Value+sym.Size-addr))
addr = sym.Value + sym.Size
}
if addr != sym.Value+sym.Size {
- Diag("phase error: addr=%#x value+size=%#x", int64(addr), int64(sym.Value)+sym.Size)
+ Diag("phase error: addr=%#x value+size=%#x", addr, sym.Value+sym.Size)
errorexit()
}
@@ -748,29 +791,30 @@ func blk(start *LSym, addr int64, size int64) {
func Codeblk(addr int64, size int64) {
if Debug['a'] != 0 {
- fmt.Fprintf(&Bso, "codeblk [%#x,%#x) at offset %#x\n", addr, addr+size, Cpos())
+ fmt.Fprintf(Bso, "codeblk [%#x,%#x) at offset %#x\n", addr, addr+size, Cpos())
}
- blk(Ctxt.Textp, addr, size)
+ blkSlice(Ctxt.Textp, addr, size)
/* again for printing */
if Debug['a'] == 0 {
return
}
- var sym *LSym
- for sym = Ctxt.Textp; sym != nil; sym = sym.Next {
+ syms := Ctxt.Textp
+ for i, sym := range syms {
if !sym.Attr.Reachable() {
continue
}
if sym.Value >= addr {
+ syms = syms[i:]
break
}
}
eaddr := addr + size
var q []byte
- for ; sym != nil; sym = sym.Next {
+ for _, sym := range syms {
if !sym.Attr.Reachable() {
continue
}
@@ -779,118 +823,164 @@ func Codeblk(addr int64, size int64) {
}
if addr < sym.Value {
- fmt.Fprintf(&Bso, "%-20s %.8x|", "_", uint64(int64(addr)))
+ fmt.Fprintf(Bso, "%-20s %.8x|", "_", uint64(addr))
for ; addr < sym.Value; addr++ {
- fmt.Fprintf(&Bso, " %.2x", 0)
+ fmt.Fprintf(Bso, " %.2x", 0)
}
- fmt.Fprintf(&Bso, "\n")
+ fmt.Fprintf(Bso, "\n")
}
- fmt.Fprintf(&Bso, "%.6x\t%-20s\n", uint64(int64(addr)), sym.Name)
+ fmt.Fprintf(Bso, "%.6x\t%-20s\n", uint64(addr), sym.Name)
q = sym.P
for len(q) >= 16 {
- fmt.Fprintf(&Bso, "%.6x\t% x\n", uint64(addr), q[:16])
+ fmt.Fprintf(Bso, "%.6x\t% x\n", uint64(addr), q[:16])
addr += 16
q = q[16:]
}
if len(q) > 0 {
- fmt.Fprintf(&Bso, "%.6x\t% x\n", uint64(addr), q)
+ fmt.Fprintf(Bso, "%.6x\t% x\n", uint64(addr), q)
addr += int64(len(q))
}
}
if addr < eaddr {
- fmt.Fprintf(&Bso, "%-20s %.8x|", "_", uint64(int64(addr)))
+ fmt.Fprintf(Bso, "%-20s %.8x|", "_", uint64(addr))
for ; addr < eaddr; addr++ {
- fmt.Fprintf(&Bso, " %.2x", 0)
+ fmt.Fprintf(Bso, " %.2x", 0)
}
}
Bso.Flush()
}
+// blkSlice is a variant of blk that processes slices.
+// After text symbols are converted from a linked list to a slice,
+// delete blk and give this function its name.
+func blkSlice(syms []*LSym, addr, size int64) {
+ for i, s := range syms {
+ if s.Type&obj.SSUB == 0 && s.Value >= addr {
+ syms = syms[i:]
+ break
+ }
+ }
+
+ eaddr := addr + size
+ for _, s := range syms {
+ if s.Type&obj.SSUB != 0 {
+ continue
+ }
+ if s.Value >= eaddr {
+ break
+ }
+ Ctxt.Cursym = s
+ if s.Value < addr {
+ Diag("phase error: addr=%#x but sym=%#x type=%d", addr, s.Value, s.Type)
+ errorexit()
+ }
+ if addr < s.Value {
+ strnput("", int(s.Value-addr))
+ addr = s.Value
+ }
+ Cwrite(s.P)
+ addr += int64(len(s.P))
+ if addr < s.Value+s.Size {
+ strnput("", int(s.Value+s.Size-addr))
+ addr = s.Value + s.Size
+ }
+ if addr != s.Value+s.Size {
+ Diag("phase error: addr=%#x value+size=%#x", addr, s.Value+s.Size)
+ errorexit()
+ }
+ if s.Value+s.Size >= eaddr {
+ break
+ }
+ }
+
+ if addr < eaddr {
+ strnput("", int(eaddr-addr))
+ }
+ Cflush()
+}
+
func Datblk(addr int64, size int64) {
if Debug['a'] != 0 {
- fmt.Fprintf(&Bso, "datblk [%#x,%#x) at offset %#x\n", addr, addr+size, Cpos())
+ fmt.Fprintf(Bso, "datblk [%#x,%#x) at offset %#x\n", addr, addr+size, Cpos())
}
- blk(datap, addr, size)
+ blkSlice(datap, addr, size)
/* again for printing */
if Debug['a'] == 0 {
return
}
- var sym *LSym
- for sym = datap; sym != nil; sym = sym.Next {
+ syms := datap
+ for i, sym := range syms {
if sym.Value >= addr {
+ syms = syms[i:]
break
}
}
eaddr := addr + size
- var ep []byte
- var i int64
- var p []byte
- var r *Reloc
- var rsname string
- var typ string
- for ; sym != nil; sym = sym.Next {
+ for _, sym := range syms {
if sym.Value >= eaddr {
break
}
if addr < sym.Value {
- fmt.Fprintf(&Bso, "\t%.8x| 00 ...\n", uint64(addr))
+ fmt.Fprintf(Bso, "\t%.8x| 00 ...\n", uint64(addr))
addr = sym.Value
}
- fmt.Fprintf(&Bso, "%s\n\t%.8x|", sym.Name, uint(addr))
- p = sym.P
- ep = p[len(sym.P):]
- for -cap(p) < -cap(ep) {
- if -cap(p) > -cap(sym.P) && int(-cap(p)+cap(sym.P))%16 == 0 {
- fmt.Fprintf(&Bso, "\n\t%.8x|", uint(addr+int64(-cap(p)+cap(sym.P))))
+ fmt.Fprintf(Bso, "%s\n\t%.8x|", sym.Name, uint64(addr))
+ for i, b := range sym.P {
+ if i > 0 && i%16 == 0 {
+ fmt.Fprintf(Bso, "\n\t%.8x|", uint64(addr)+uint64(i))
}
- fmt.Fprintf(&Bso, " %.2x", p[0])
- p = p[1:]
+ fmt.Fprintf(Bso, " %.2x", b)
}
addr += int64(len(sym.P))
for ; addr < sym.Value+sym.Size; addr++ {
- fmt.Fprintf(&Bso, " %.2x", 0)
+ fmt.Fprintf(Bso, " %.2x", 0)
}
- fmt.Fprintf(&Bso, "\n")
-
- if Linkmode == LinkExternal {
- for i = 0; i < int64(len(sym.R)); i++ {
- r = &sym.R[i]
- rsname = ""
- if r.Sym != nil {
- rsname = r.Sym.Name
- }
- typ = "?"
- switch r.Type {
- case obj.R_ADDR:
- typ = "addr"
-
- case obj.R_PCREL:
- typ = "pcrel"
+ fmt.Fprintf(Bso, "\n")
- case obj.R_CALL:
- typ = "call"
- }
-
- fmt.Fprintf(&Bso, "\treloc %.8x/%d %s %s+%#x [%#x]\n", uint(sym.Value+int64(r.Off)), r.Siz, typ, rsname, int64(r.Add), int64(r.Sym.Value+r.Add))
+ if Linkmode != LinkExternal {
+ continue
+ }
+ for _, r := range sym.R {
+ rsname := ""
+ if r.Sym != nil {
+ rsname = r.Sym.Name
+ }
+ typ := "?"
+ switch r.Type {
+ case obj.R_ADDR:
+ typ = "addr"
+ case obj.R_PCREL:
+ typ = "pcrel"
+ case obj.R_CALL:
+ typ = "call"
}
+ fmt.Fprintf(Bso, "\treloc %.8x/%d %s %s+%#x [%#x]\n", uint(sym.Value+int64(r.Off)), r.Siz, typ, rsname, r.Add, r.Sym.Value+r.Add)
}
}
if addr < eaddr {
- fmt.Fprintf(&Bso, "\t%.8x| 00 ...\n", uint(addr))
+ fmt.Fprintf(Bso, "\t%.8x| 00 ...\n", uint(addr))
}
- fmt.Fprintf(&Bso, "\t%.8x|\n", uint(eaddr))
+ fmt.Fprintf(Bso, "\t%.8x|\n", uint(eaddr))
+}
+
+func Dwarfblk(addr int64, size int64) {
+ if Debug['a'] != 0 {
+ fmt.Fprintf(Bso, "dwarfblk [%#x,%#x) at offset %#x\n", addr, addr+size, Cpos())
+ }
+
+ blk(dwarfp, addr, size)
}
var zeros [512]byte
@@ -938,7 +1028,7 @@ func addstrdata(name string, value string) {
s.Attr |= AttrDuplicateOK
reachable := s.Attr.Reachable()
Addaddr(Ctxt, s, sp)
- adduintxx(Ctxt, s, uint64(len(value)), Thearch.Ptrsize)
+ adduintxx(Ctxt, s, uint64(len(value)), SysArch.PtrSize)
// addstring, addaddr, etc., mark the symbols as reachable.
// In this case that is not necessarily true, so stick to what
@@ -965,16 +1055,14 @@ func Addstring(s *LSym, str string) int64 {
s.Type = obj.SNOPTRDATA
}
s.Attr |= AttrReachable
- r := int32(s.Size)
- n := len(str) + 1
+ r := s.Size
if s.Name == ".shstrtab" {
elfsetstring(str, int(r))
}
- Symgrow(Ctxt, s, int64(r)+int64(n))
- copy(s.P[r:], str)
- s.P[int(r)+len(str)] = 0
- s.Size += int64(n)
- return int64(r)
+ s.P = append(s.P, str...)
+ s.P = append(s.P, 0)
+ s.Size = int64(len(s.P))
+ return r
}
// addgostring adds str, as a Go string value, to s. symname is the name of the
@@ -1031,7 +1119,7 @@ func symalign(s *LSym) int32 {
} else if s.Align != 0 {
return min
}
- if strings.HasPrefix(s.Name, "go.string.") && !strings.HasPrefix(s.Name, "go.string.hdr.") {
+ if (strings.HasPrefix(s.Name, "go.string.") && !strings.HasPrefix(s.Name, "go.string.hdr.")) || strings.HasPrefix(s.Name, "type..namedata.") {
// String data is just bytes.
// If we align it, we waste a lot of space to padding.
return min
@@ -1047,22 +1135,6 @@ func aligndatsize(datsize int64, s *LSym) int64 {
return Rnd(datsize, int64(symalign(s)))
}
-// maxalign returns the maximum required alignment for
-// the list of symbols s; the list stops when s->type exceeds type.
-func maxalign(s *LSym, type_ int) int32 {
- var align int32
-
- max := int32(0)
- for ; s != nil && int(s.Type) <= type_; s = s.Next {
- align = symalign(s)
- if max < align {
- max = align
- }
- }
-
- return max
-}
-
const debugGCProg = false
type GCProg struct {
@@ -1084,7 +1156,7 @@ func (p *GCProg) writeByte(x byte) {
}
func (p *GCProg) End(size int64) {
- p.w.ZeroUntil(size / int64(Thearch.Ptrsize))
+ p.w.ZeroUntil(size / int64(SysArch.PtrSize))
p.w.End()
if debugGCProg {
fmt.Fprintf(os.Stderr, "ld: end GCProg\n")
@@ -1100,7 +1172,7 @@ func (p *GCProg) AddSym(s *LSym) {
return
}
- ptrsize := int64(Thearch.Ptrsize)
+ ptrsize := int64(SysArch.PtrSize)
nptr := decodetype_ptrdata(typ) / ptrsize
if debugGCProg {
@@ -1124,236 +1196,170 @@ func (p *GCProg) AddSym(s *LSym) {
p.w.Append(prog[4:], nptr)
}
+// dataSortKey is used to sort a slice of data symbol *LSym pointers.
+// The sort keys are kept inline to improve cache behaviour while sorting.
type dataSortKey struct {
- // keep sort keys inline to improve cache behaviour while sorting
- Type int16
- Size int64
- Name string
-
- Lsym *LSym
+ size int64
+ name string
+ lsym *LSym
}
-type dataSlice []dataSortKey
-
-func (d dataSlice) Len() int { return len(d) }
-func (d dataSlice) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
-func (d dataSlice) Less(i, j int) bool {
- s1, s2 := &d[i], &d[j]
- if s1.Type != s2.Type {
- return s1.Type < s2.Type
- }
+type bySizeAndName []dataSortKey
- // For ppc64, we want to interleave the .got and .toc sections
- // from input files. Both are type SELFGOT, so in that case
- // fall through to the name comparison (conveniently, .got
- // sorts before .toc).
- if s1.Type != obj.SELFGOT && s1.Size != s2.Size {
- return s1.Size < s2.Size
+func (d bySizeAndName) Len() int { return len(d) }
+func (d bySizeAndName) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
+func (d bySizeAndName) Less(i, j int) bool {
+ s1, s2 := d[i], d[j]
+ if s1.size != s2.size {
+ return s1.size < s2.size
}
-
- return s1.Name < s2.Name
+ return s1.name < s2.name
}
-func growdatsize(datsizep *int64, s *LSym) {
- datsize := *datsizep
- const cutoff int64 = 2e9 // 2 GB (or so; looks better in errors than 2^31)
- switch {
- case s.Size < 0:
- Diag("%s: negative size (%d bytes)", s.Name, s.Size)
- case s.Size > cutoff:
- Diag("%s: symbol too large (%d bytes)", s.Name, s.Size)
- case datsize <= cutoff && datsize+s.Size > cutoff:
- Diag("%s: too much data (over %d bytes)", s.Name, cutoff)
- }
- *datsizep = datsize + s.Size
-}
+const cutoff int64 = 2e9 // 2 GB (or so; looks better in errors than 2^31)
-func list2Slice(head *LSym) dataSlice {
- n := 0
- for s := datap; s != nil; s = s.Next {
- n++
+func checkdatsize(datsize int64, symn int) {
+ if datsize > cutoff {
+ Diag("too much data in section %v (over %d bytes)", symn, cutoff)
}
- slice := make(dataSlice, n)
- i := 0
- for s := datap; s != nil; s = s.Next {
- k := &slice[i]
- k.Type = s.Type
- k.Size = s.Size
- k.Name = s.Name
- k.Lsym = s
-
- i++
- }
- return slice
}
-func slice2List(d dataSlice) *LSym {
- for i := 0; i < len(d)-1; i++ {
- d[i].Lsym.Next = d[i+1].Lsym
+func list2slice(s *LSym) []*LSym {
+ var syms []*LSym
+ for ; s != nil; s = s.Next {
+ syms = append(syms, s)
}
- d[len(d)-1].Lsym.Next = nil
- return d[0].Lsym
+ return syms
}
-func dataSort(head *LSym) *LSym {
- d := list2Slice(head)
- sort.Sort(d)
- return slice2List(d)
-}
+// datap is a collection of reachable data symbols in address order.
+// Generated by dodata.
+var datap []*LSym
func dodata() {
if Debug['v'] != 0 {
- fmt.Fprintf(&Bso, "%5.2f dodata\n", obj.Cputime())
+ fmt.Fprintf(Bso, "%5.2f dodata\n", obj.Cputime())
}
Bso.Flush()
- var last *LSym
- datap = nil
-
+ // Collect data symbols by type into data.
+ var data [obj.SXREF][]*LSym
for _, s := range Ctxt.Allsym {
if !s.Attr.Reachable() || s.Attr.Special() {
continue
}
- if obj.STEXT < s.Type && s.Type < obj.SXREF {
- if s.Attr.OnList() {
- log.Fatalf("symbol %s listed multiple times", s.Name)
- }
- s.Attr |= AttrOnList
- if last == nil {
- datap = s
- } else {
- last.Next = s
- }
- s.Next = nil
- last = s
- }
- }
-
- for s := datap; s != nil; s = s.Next {
- if int64(len(s.P)) > s.Size {
- Diag("%s: initialize bounds (%d < %d)", s.Name, int64(s.Size), len(s.P))
+ if s.Type <= obj.STEXT || s.Type >= obj.SXREF {
+ continue
}
+ data[s.Type] = append(data[s.Type], s)
}
- /*
- * now that we have the datap list, but before we start
- * to assign addresses, record all the necessary
- * dynamic relocations. these will grow the relocation
- * symbol, which is itself data.
- *
- * on darwin, we need the symbol table numbers for dynreloc.
- */
+ // Now that we have the data symbols, but before we start
+ // to assign addresses, record all the necessary
+ // dynamic relocations. These will grow the relocation
+ // symbol, which is itself data.
+ //
+ // On darwin, we need the symbol table numbers for dynreloc.
if HEADTYPE == obj.Hdarwin {
machosymorder()
}
- dynreloc()
-
- /* some symbols may no longer belong in datap (Mach-O) */
- var l **LSym
- var s *LSym
- for l = &datap; ; {
- s = *l
- if s == nil {
- break
- }
-
- if s.Type <= obj.STEXT || obj.SXREF <= s.Type {
- *l = s.Next
- } else {
- l = &s.Next
- }
- }
-
- *l = nil
+ dynreloc(&data)
if UseRelro() {
// "read only" data with relocations needs to go in its own section
// when building a shared library. We do this by boosting objects of
// type SXXX with relocations to type SXXXRELRO.
- for s := datap; s != nil; s = s.Next {
- if (s.Type >= obj.STYPE && s.Type <= obj.SFUNCTAB && len(s.R) > 0) || s.Type == obj.STYPE || s.Type == obj.SGOSTRINGHDR {
- s.Type += (obj.STYPERELRO - obj.STYPE)
- if s.Outer != nil {
- s.Outer.Type = s.Type
- }
- }
- }
- // Check that we haven't made two symbols with the same .Outer into
- // different types (because references two symbols with non-nil Outer
- // become references to the outer symbol + offset it's vital that the
- // symbol and the outer end up in the same section).
- for s := datap; s != nil; s = s.Next {
- if s.Outer != nil && s.Outer.Type != s.Type {
- Diag("inconsistent types for %s and its Outer %s (%d != %d)",
- s.Name, s.Outer.Name, s.Type, s.Outer.Type)
- }
- }
-
- }
+ for symnro := int16(obj.STYPE); symnro < obj.STYPERELRO; symnro++ {
+ symnrelro := symnro + obj.STYPERELRO - obj.STYPE
- datap = dataSort(datap)
+ ro := []*LSym{}
+ relro := data[symnrelro]
- if Iself {
- // Make .rela and .rela.plt contiguous, the ELF ABI requires this
- // and Solaris actually cares.
- var relplt *LSym
- for l = &datap; *l != nil; l = &(*l).Next {
- if (*l).Name == ".rel.plt" || (*l).Name == ".rela.plt" {
- relplt = (*l)
- *l = (*l).Next
- break
+ for _, s := range data[symnro] {
+ isRelro := len(s.R) > 0
+ switch s.Type {
+ case obj.STYPE, obj.SGOSTRINGHDR, obj.STYPERELRO, obj.SGOSTRINGHDRRELRO:
+ // Symbols are not sorted yet, so it is possible
+ // that an Outer symbol has been changed to a
+ // relro Type before it reaches here.
+ isRelro = true
+ }
+ if isRelro {
+ s.Type = symnrelro
+ if s.Outer != nil {
+ s.Outer.Type = s.Type
+ }
+ relro = append(relro, s)
+ } else {
+ ro = append(ro, s)
+ }
}
- }
- if relplt != nil {
- for s = datap; s != nil; s = s.Next {
- if s.Name == ".rel" || s.Name == ".rela" {
- relplt.Next = s.Next
- s.Next = relplt
+
+ // Check that we haven't made two symbols with the same .Outer into
+ // different types (because references two symbols with non-nil Outer
+ // become references to the outer symbol + offset it's vital that the
+ // symbol and the outer end up in the same section).
+ for _, s := range relro {
+ if s.Outer != nil && s.Outer.Type != s.Type {
+ Diag("inconsistent types for %s and its Outer %s (%d != %d)",
+ s.Name, s.Outer.Name, s.Type, s.Outer.Type)
}
}
+
+ data[symnro] = ro
+ data[symnrelro] = relro
}
}
- /*
- * allocate sections. list is sorted by type,
- * so we can just walk it for each piece we want to emit.
- * segdata is processed before segtext, because we need
- * to see all symbols in the .data and .bss sections in order
- * to generate garbage collection information.
- */
-
- /* begin segdata */
-
- /* skip symbols belonging to segtext */
- s = datap
-
- for ; s != nil && s.Type < obj.SELFSECT; s = s.Next {
+ // Sort symbols.
+ var dataMaxAlign [obj.SXREF]int32
+ var wg sync.WaitGroup
+ for symn := range data {
+ symn := symn
+ wg.Add(1)
+ go func() {
+ data[symn], dataMaxAlign[symn] = dodataSect(symn, data[symn])
+ wg.Done()
+ }()
}
+ wg.Wait()
- /* writable ELF sections */
+ // Allocate sections.
+ // Data is processed before segtext, because we need
+ // to see all symbols in the .data and .bss sections in order
+ // to generate garbage collection information.
datsize := int64(0)
- var sect *Section
- for ; s != nil && s.Type < obj.SELFGOT; s = s.Next {
- sect = addsection(&Segdata, s.Name, 06)
- sect.Align = symalign(s)
- datsize = Rnd(datsize, int64(sect.Align))
- sect.Vaddr = uint64(datsize)
- s.Sect = sect
- s.Type = obj.SDATA
- s.Value = int64(uint64(datsize) - sect.Vaddr)
- growdatsize(&datsize, s)
- sect.Length = uint64(datsize) - sect.Vaddr
+ // Writable sections.
+ writableSects := []int{
+ obj.SELFSECT,
+ obj.SMACHO,
+ obj.SMACHOGOT,
+ obj.SWINDOWS,
+ }
+ for _, symn := range writableSects {
+ for _, s := range data[symn] {
+ sect := addsection(&Segdata, s.Name, 06)
+ sect.Align = symalign(s)
+ datsize = Rnd(datsize, int64(sect.Align))
+ sect.Vaddr = uint64(datsize)
+ s.Sect = sect
+ s.Type = obj.SDATA
+ s.Value = int64(uint64(datsize) - sect.Vaddr)
+ datsize += s.Size
+ sect.Length = uint64(datsize) - sect.Vaddr
+ }
+ checkdatsize(datsize, symn)
}
- /* .got (and .toc on ppc64) */
- if s.Type == obj.SELFGOT {
+ // .got (and .toc on ppc64)
+ if len(data[obj.SELFGOT]) > 0 {
sect := addsection(&Segdata, ".got", 06)
- sect.Align = maxalign(s, obj.SELFGOT)
+ sect.Align = dataMaxAlign[obj.SELFGOT]
datsize = Rnd(datsize, int64(sect.Align))
sect.Vaddr = uint64(datsize)
var toc *LSym
- for ; s != nil && s.Type == obj.SELFGOT; s = s.Next {
+ for _, s := range data[obj.SELFGOT] {
datsize = aligndatsize(datsize, s)
s.Sect = sect
s.Type = obj.SDATA
@@ -1361,7 +1367,6 @@ func dodata() {
// Resolve .TOC. symbol for this object file (ppc64)
toc = Linkrlookup(Ctxt, ".TOC.", int(s.Version))
-
if toc != nil {
toc.Sect = sect
toc.Outer = s
@@ -1371,28 +1376,27 @@ func dodata() {
toc.Value = 0x8000
}
- growdatsize(&datsize, s)
+ datsize += s.Size
}
-
+ checkdatsize(datsize, obj.SELFGOT)
sect.Length = uint64(datsize) - sect.Vaddr
}
/* pointer-free data */
- sect = addsection(&Segdata, ".noptrdata", 06)
-
- sect.Align = maxalign(s, obj.SINITARR-1)
+ sect := addsection(&Segdata, ".noptrdata", 06)
+ sect.Align = dataMaxAlign[obj.SNOPTRDATA]
datsize = Rnd(datsize, int64(sect.Align))
sect.Vaddr = uint64(datsize)
Linklookup(Ctxt, "runtime.noptrdata", 0).Sect = sect
Linklookup(Ctxt, "runtime.enoptrdata", 0).Sect = sect
- for ; s != nil && s.Type < obj.SINITARR; s = s.Next {
+ for _, s := range data[obj.SNOPTRDATA] {
datsize = aligndatsize(datsize, s)
s.Sect = sect
s.Type = obj.SDATA
s.Value = int64(uint64(datsize) - sect.Vaddr)
- growdatsize(&datsize, s)
+ datsize += s.Size
}
-
+ checkdatsize(datsize, obj.SNOPTRDATA)
sect.Length = uint64(datsize) - sect.Vaddr
hasinitarr := Linkshared
@@ -1402,116 +1406,102 @@ func dodata() {
case BuildmodeCArchive, BuildmodeCShared, BuildmodeShared:
hasinitarr = true
}
-
if hasinitarr {
sect := addsection(&Segdata, ".init_array", 06)
- sect.Align = maxalign(s, obj.SINITARR)
+ sect.Align = dataMaxAlign[obj.SINITARR]
datsize = Rnd(datsize, int64(sect.Align))
sect.Vaddr = uint64(datsize)
- for ; s != nil && s.Type == obj.SINITARR; s = s.Next {
+ for _, s := range data[obj.SINITARR] {
datsize = aligndatsize(datsize, s)
s.Sect = sect
s.Value = int64(uint64(datsize) - sect.Vaddr)
- growdatsize(&datsize, s)
+ datsize += s.Size
}
-
sect.Length = uint64(datsize) - sect.Vaddr
+ checkdatsize(datsize, obj.SINITARR)
}
/* data */
sect = addsection(&Segdata, ".data", 06)
- sect.Align = maxalign(s, obj.SBSS-1)
+ sect.Align = dataMaxAlign[obj.SDATA]
datsize = Rnd(datsize, int64(sect.Align))
sect.Vaddr = uint64(datsize)
Linklookup(Ctxt, "runtime.data", 0).Sect = sect
Linklookup(Ctxt, "runtime.edata", 0).Sect = sect
var gc GCProg
gc.Init("runtime.gcdata")
- for ; s != nil && s.Type < obj.SBSS; s = s.Next {
- if s.Type == obj.SINITARR {
- Ctxt.Cursym = s
- Diag("unexpected symbol type %d", s.Type)
- }
-
+ for _, s := range data[obj.SDATA] {
s.Sect = sect
s.Type = obj.SDATA
datsize = aligndatsize(datsize, s)
s.Value = int64(uint64(datsize) - sect.Vaddr)
gc.AddSym(s)
- growdatsize(&datsize, s)
+ datsize += s.Size
}
+ checkdatsize(datsize, obj.SDATA)
sect.Length = uint64(datsize) - sect.Vaddr
gc.End(int64(sect.Length))
/* bss */
sect = addsection(&Segdata, ".bss", 06)
- sect.Align = maxalign(s, obj.SNOPTRBSS-1)
+ sect.Align = dataMaxAlign[obj.SBSS]
datsize = Rnd(datsize, int64(sect.Align))
sect.Vaddr = uint64(datsize)
Linklookup(Ctxt, "runtime.bss", 0).Sect = sect
Linklookup(Ctxt, "runtime.ebss", 0).Sect = sect
gc = GCProg{}
gc.Init("runtime.gcbss")
- for ; s != nil && s.Type < obj.SNOPTRBSS; s = s.Next {
+ for _, s := range data[obj.SBSS] {
s.Sect = sect
datsize = aligndatsize(datsize, s)
s.Value = int64(uint64(datsize) - sect.Vaddr)
gc.AddSym(s)
- growdatsize(&datsize, s)
+ datsize += s.Size
}
+ checkdatsize(datsize, obj.SBSS)
sect.Length = uint64(datsize) - sect.Vaddr
gc.End(int64(sect.Length))
/* pointer-free bss */
sect = addsection(&Segdata, ".noptrbss", 06)
-
- sect.Align = maxalign(s, obj.SNOPTRBSS)
+ sect.Align = dataMaxAlign[obj.SNOPTRBSS]
datsize = Rnd(datsize, int64(sect.Align))
sect.Vaddr = uint64(datsize)
Linklookup(Ctxt, "runtime.noptrbss", 0).Sect = sect
Linklookup(Ctxt, "runtime.enoptrbss", 0).Sect = sect
- for ; s != nil && s.Type == obj.SNOPTRBSS; s = s.Next {
+ for _, s := range data[obj.SNOPTRBSS] {
datsize = aligndatsize(datsize, s)
s.Sect = sect
s.Value = int64(uint64(datsize) - sect.Vaddr)
- growdatsize(&datsize, s)
+ datsize += s.Size
}
sect.Length = uint64(datsize) - sect.Vaddr
Linklookup(Ctxt, "runtime.end", 0).Sect = sect
+ checkdatsize(datsize, obj.SNOPTRBSS)
- // 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
- if datsize != int64(uint32(datsize)) {
- Diag("data or bss segment too large")
- }
-
- if s != nil && s.Type == obj.STLSBSS {
+ if len(data[obj.STLSBSS]) > 0 {
+ var sect *Section
if Iself && (Linkmode == LinkExternal || Debug['d'] == 0) && HEADTYPE != obj.Hopenbsd {
sect = addsection(&Segdata, ".tbss", 06)
- sect.Align = int32(Thearch.Ptrsize)
+ sect.Align = int32(SysArch.PtrSize)
sect.Vaddr = 0
- } else {
- sect = nil
}
datsize = 0
- for ; s != nil && s.Type == obj.STLSBSS; s = s.Next {
+ for _, s := range data[obj.STLSBSS] {
datsize = aligndatsize(datsize, s)
s.Sect = sect
s.Value = datsize
- growdatsize(&datsize, s)
+ datsize += s.Size
}
+ checkdatsize(datsize, obj.STLSBSS)
if sect != nil {
sect.Length = uint64(datsize)
}
}
- if s != nil {
- Ctxt.Cursym = nil
- Diag("unexpected symbol type %d for %s", s.Type, s.Name)
- }
-
/*
* We finished data, begin read-only data.
* Not all systems support a separate read-only non-executable data section.
@@ -1529,39 +1519,62 @@ func dodata() {
segro = &Segtext
}
- s = datap
-
datsize = 0
/* read-only executable ELF, Mach-O sections */
- for ; s != nil && s.Type < obj.STYPE; s = s.Next {
- sect = addsection(&Segtext, s.Name, 04)
+ if len(data[obj.STEXT]) != 0 {
+ Diag("dodata found an STEXT symbol: %s", data[obj.STEXT][0].Name)
+ }
+ for _, s := range data[obj.SELFRXSECT] {
+ sect := addsection(&Segtext, s.Name, 04)
sect.Align = symalign(s)
datsize = Rnd(datsize, int64(sect.Align))
sect.Vaddr = uint64(datsize)
s.Sect = sect
s.Type = obj.SRODATA
s.Value = int64(uint64(datsize) - sect.Vaddr)
- growdatsize(&datsize, s)
+ datsize += s.Size
sect.Length = uint64(datsize) - sect.Vaddr
+ checkdatsize(datsize, obj.SELFRXSECT)
}
/* read-only data */
sect = addsection(segro, ".rodata", 04)
- sect.Align = maxalign(s, obj.STYPERELRO-1)
- datsize = Rnd(datsize, int64(sect.Align))
sect.Vaddr = 0
Linklookup(Ctxt, "runtime.rodata", 0).Sect = sect
Linklookup(Ctxt, "runtime.erodata", 0).Sect = sect
- for ; s != nil && s.Type < obj.STYPERELRO; s = s.Next {
- datsize = aligndatsize(datsize, s)
- s.Sect = sect
- s.Type = obj.SRODATA
- s.Value = int64(uint64(datsize) - sect.Vaddr)
- growdatsize(&datsize, s)
+ if !UseRelro() {
+ Linklookup(Ctxt, "runtime.types", 0).Sect = sect
+ Linklookup(Ctxt, "runtime.etypes", 0).Sect = sect
+ }
+ roSects := []int{
+ obj.STYPE,
+ obj.SSTRING,
+ obj.SGOSTRING,
+ obj.SGOSTRINGHDR,
+ obj.SGOFUNC,
+ obj.SGCBITS,
+ obj.SRODATA,
+ obj.SFUNCTAB,
+ }
+ for _, symn := range roSects {
+ align := dataMaxAlign[symn]
+ if sect.Align < align {
+ sect.Align = align
+ }
+ }
+ datsize = Rnd(datsize, int64(sect.Align))
+ for _, symn := range roSects {
+ for _, s := range data[symn] {
+ datsize = aligndatsize(datsize, s)
+ s.Sect = sect
+ s.Type = obj.SRODATA
+ s.Value = int64(uint64(datsize) - sect.Vaddr)
+ datsize += s.Size
+ }
+ checkdatsize(datsize, symn)
}
-
sect.Length = uint64(datsize) - sect.Vaddr
// There is some data that are conceptually read-only but are written to by
@@ -1583,18 +1596,38 @@ func dodata() {
/* data only written by relocations */
sect = addsection(segro, ".data.rel.ro", 06)
- sect.Align = maxalign(s, obj.STYPELINK-1)
- datsize = Rnd(datsize, int64(sect.Align))
sect.Vaddr = 0
- for ; s != nil && s.Type < obj.STYPELINK; s = s.Next {
- datsize = aligndatsize(datsize, s)
- if s.Outer != nil && s.Outer.Sect != nil && s.Outer.Sect != sect {
- Diag("s.Outer (%s) in different section from s (%s)", s.Outer.Name, s.Name)
+ Linklookup(Ctxt, "runtime.types", 0).Sect = sect
+ Linklookup(Ctxt, "runtime.etypes", 0).Sect = sect
+ relroSects := []int{
+ obj.STYPERELRO,
+ obj.SSTRINGRELRO,
+ obj.SGOSTRINGRELRO,
+ obj.SGOSTRINGHDRRELRO,
+ obj.SGOFUNCRELRO,
+ obj.SGCBITSRELRO,
+ obj.SRODATARELRO,
+ obj.SFUNCTABRELRO,
+ }
+ for _, symn := range relroSects {
+ align := dataMaxAlign[symn]
+ if sect.Align < align {
+ sect.Align = align
}
- s.Sect = sect
- s.Type = obj.SRODATA
- s.Value = int64(uint64(datsize) - sect.Vaddr)
- growdatsize(&datsize, s)
+ }
+ datsize = Rnd(datsize, int64(sect.Align))
+ for _, symn := range relroSects {
+ for _, s := range data[symn] {
+ datsize = aligndatsize(datsize, s)
+ if s.Outer != nil && s.Outer.Sect != nil && s.Outer.Sect != sect {
+ Diag("s.Outer (%s) in different section from s (%s)", s.Outer.Name, s.Name)
+ }
+ s.Sect = sect
+ s.Type = obj.SRODATA
+ s.Value = int64(uint64(datsize) - sect.Vaddr)
+ datsize += s.Size
+ }
+ checkdatsize(datsize, symn)
}
sect.Length = uint64(datsize) - sect.Vaddr
@@ -1603,78 +1636,74 @@ func dodata() {
/* typelink */
sect = addsection(segro, relro_prefix+".typelink", relro_perms)
-
- sect.Align = maxalign(s, obj.STYPELINK)
+ sect.Align = dataMaxAlign[obj.STYPELINK]
datsize = Rnd(datsize, int64(sect.Align))
sect.Vaddr = uint64(datsize)
Linklookup(Ctxt, "runtime.typelink", 0).Sect = sect
Linklookup(Ctxt, "runtime.etypelink", 0).Sect = sect
- for ; s != nil && s.Type == obj.STYPELINK; s = s.Next {
+ for _, s := range data[obj.STYPELINK] {
datsize = aligndatsize(datsize, s)
s.Sect = sect
s.Type = obj.SRODATA
s.Value = int64(uint64(datsize) - sect.Vaddr)
- growdatsize(&datsize, s)
+ datsize += s.Size
}
-
+ checkdatsize(datsize, obj.STYPELINK)
sect.Length = uint64(datsize) - sect.Vaddr
/* itablink */
sect = addsection(segro, relro_prefix+".itablink", relro_perms)
-
- sect.Align = maxalign(s, obj.SITABLINK)
+ sect.Align = dataMaxAlign[obj.SITABLINK]
datsize = Rnd(datsize, int64(sect.Align))
sect.Vaddr = uint64(datsize)
Linklookup(Ctxt, "runtime.itablink", 0).Sect = sect
Linklookup(Ctxt, "runtime.eitablink", 0).Sect = sect
- for ; s != nil && s.Type == obj.SITABLINK; s = s.Next {
+ for _, s := range data[obj.SITABLINK] {
datsize = aligndatsize(datsize, s)
s.Sect = sect
s.Type = obj.SRODATA
s.Value = int64(uint64(datsize) - sect.Vaddr)
- growdatsize(&datsize, s)
+ datsize += s.Size
}
-
+ checkdatsize(datsize, obj.SITABLINK)
sect.Length = uint64(datsize) - sect.Vaddr
/* gosymtab */
sect = addsection(segro, relro_prefix+".gosymtab", relro_perms)
-
- sect.Align = maxalign(s, obj.SPCLNTAB-1)
+ sect.Align = dataMaxAlign[obj.SSYMTAB]
datsize = Rnd(datsize, int64(sect.Align))
sect.Vaddr = uint64(datsize)
Linklookup(Ctxt, "runtime.symtab", 0).Sect = sect
Linklookup(Ctxt, "runtime.esymtab", 0).Sect = sect
- for ; s != nil && s.Type < obj.SPCLNTAB; s = s.Next {
+ for _, s := range data[obj.SSYMTAB] {
datsize = aligndatsize(datsize, s)
s.Sect = sect
s.Type = obj.SRODATA
s.Value = int64(uint64(datsize) - sect.Vaddr)
- growdatsize(&datsize, s)
+ datsize += s.Size
}
-
+ checkdatsize(datsize, obj.SSYMTAB)
sect.Length = uint64(datsize) - sect.Vaddr
/* gopclntab */
sect = addsection(segro, relro_prefix+".gopclntab", relro_perms)
-
- sect.Align = maxalign(s, obj.SELFROSECT-1)
+ sect.Align = dataMaxAlign[obj.SPCLNTAB]
datsize = Rnd(datsize, int64(sect.Align))
sect.Vaddr = uint64(datsize)
Linklookup(Ctxt, "runtime.pclntab", 0).Sect = sect
Linklookup(Ctxt, "runtime.epclntab", 0).Sect = sect
- for ; s != nil && s.Type < obj.SELFROSECT; s = s.Next {
+ for _, s := range data[obj.SPCLNTAB] {
datsize = aligndatsize(datsize, s)
s.Sect = sect
s.Type = obj.SRODATA
s.Value = int64(uint64(datsize) - sect.Vaddr)
- growdatsize(&datsize, s)
+ datsize += s.Size
}
-
+ checkdatsize(datsize, obj.SRODATA)
sect.Length = uint64(datsize) - sect.Vaddr
/* read-only ELF, Mach-O sections */
- for ; s != nil && s.Type < obj.SELFSECT; s = s.Next {
+ for _, s := range data[obj.SELFROSECT] {
sect = addsection(segro, s.Name, 04)
sect.Align = symalign(s)
datsize = Rnd(datsize, int64(sect.Align))
@@ -1682,15 +1711,65 @@ func dodata() {
s.Sect = sect
s.Type = obj.SRODATA
s.Value = int64(uint64(datsize) - sect.Vaddr)
- growdatsize(&datsize, s)
+ datsize += s.Size
sect.Length = uint64(datsize) - sect.Vaddr
}
+ checkdatsize(datsize, obj.SELFROSECT)
+
+ for _, s := range data[obj.SMACHOPLT] {
+ sect = addsection(segro, s.Name, 04)
+ sect.Align = symalign(s)
+ datsize = Rnd(datsize, int64(sect.Align))
+ sect.Vaddr = uint64(datsize)
+ s.Sect = sect
+ s.Type = obj.SRODATA
+ s.Value = int64(uint64(datsize) - sect.Vaddr)
+ datsize += s.Size
+ sect.Length = uint64(datsize) - sect.Vaddr
+ }
+ checkdatsize(datsize, obj.SMACHOPLT)
// 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
if datsize != int64(uint32(datsize)) {
Diag("read-only data segment too large")
}
+ for symn := obj.SELFRXSECT; symn < obj.SXREF; symn++ {
+ datap = append(datap, data[symn]...)
+ }
+
+ dwarfgeneratedebugsyms()
+
+ var s *LSym
+ for s = dwarfp; s != nil && s.Type == obj.SDWARFSECT; s = s.Next {
+ sect = addsection(&Segdwarf, s.Name, 04)
+ sect.Align = 1
+ datsize = Rnd(datsize, int64(sect.Align))
+ sect.Vaddr = uint64(datsize)
+ s.Sect = sect
+ s.Type = obj.SRODATA
+ s.Value = int64(uint64(datsize) - sect.Vaddr)
+ datsize += s.Size
+ sect.Length = uint64(datsize) - sect.Vaddr
+ }
+ checkdatsize(datsize, obj.SDWARFSECT)
+
+ if s != nil {
+ sect = addsection(&Segdwarf, ".debug_info", 04)
+ sect.Align = 1
+ datsize = Rnd(datsize, int64(sect.Align))
+ sect.Vaddr = uint64(datsize)
+ for ; s != nil && s.Type == obj.SDWARFINFO; s = s.Next {
+ s.Sect = sect
+ s.Type = obj.SRODATA
+ s.Value = int64(uint64(datsize) - sect.Vaddr)
+ s.Attr |= AttrLocal
+ datsize += s.Size
+ }
+ sect.Length = uint64(datsize) - sect.Vaddr
+ checkdatsize(datsize, obj.SDWARFINFO)
+ }
+
/* number the sections */
n := int32(1)
@@ -1706,6 +1785,97 @@ func dodata() {
sect.Extnum = int16(n)
n++
}
+ for sect := Segdwarf.Sect; sect != nil; sect = sect.Next {
+ sect.Extnum = int16(n)
+ n++
+ }
+}
+
+func dodataSect(symn int, syms []*LSym) (result []*LSym, maxAlign int32) {
+ if HEADTYPE == obj.Hdarwin {
+ // Some symbols may no longer belong in syms
+ // due to movement in machosymorder.
+ newSyms := make([]*LSym, 0, len(syms))
+ for _, s := range syms {
+ if int(s.Type) == symn {
+ newSyms = append(newSyms, s)
+ }
+ }
+ syms = newSyms
+ }
+
+ symsSort := make([]dataSortKey, len(syms))
+ for i, s := range syms {
+ if s.Attr.OnList() {
+ log.Fatalf("symbol %s listed multiple times", s.Name)
+ }
+ s.Attr |= AttrOnList
+ switch {
+ case s.Size < int64(len(s.P)):
+ Diag("%s: initialize bounds (%d < %d)", s.Name, s.Size, len(s.P))
+ case s.Size < 0:
+ Diag("%s: negative size (%d bytes)", s.Name, s.Size)
+ case s.Size > cutoff:
+ Diag("%s: symbol too large (%d bytes)", s.Name, s.Size)
+ }
+
+ symsSort[i] = dataSortKey{
+ size: s.Size,
+ name: s.Name,
+ lsym: s,
+ }
+
+ switch s.Type {
+ case obj.SELFGOT:
+ // For ppc64, we want to interleave the .got and .toc sections
+ // from input files. Both are type SELFGOT, so in that case
+ // we skip size comparison and fall through to the name
+ // comparison (conveniently, .got sorts before .toc).
+ symsSort[i].size = 0
+ case obj.STYPELINK:
+ // Sort typelinks by the rtype.string field so the reflect
+ // package can binary search type links.
+ symsSort[i].name = string(decodetype_str(s.R[0].Sym))
+ }
+ }
+
+ sort.Sort(bySizeAndName(symsSort))
+
+ for i, symSort := range symsSort {
+ syms[i] = symSort.lsym
+ align := symalign(symSort.lsym)
+ if maxAlign < align {
+ maxAlign = align
+ }
+ }
+
+ if Iself && symn == obj.SELFROSECT {
+ // Make .rela and .rela.plt contiguous, the ELF ABI requires this
+ // and Solaris actually cares.
+ reli, plti := -1, -1
+ for i, s := range syms {
+ switch s.Name {
+ case ".rel.plt", ".rela.plt":
+ plti = i
+ case ".rel", ".rela":
+ reli = i
+ }
+ }
+ if reli >= 0 && plti >= 0 && plti != reli+1 {
+ var first, second int
+ if plti > reli {
+ first, second = reli, plti
+ } else {
+ first, second = plti, reli
+ }
+ rel, plt := syms[reli], syms[plti]
+ copy(syms[first+2:], syms[first+1:second])
+ syms[first+0] = rel
+ syms[first+1] = plt
+ }
+ }
+
+ return syms, maxAlign
}
// Add buildid to beginning of text segment, on non-ELF systems.
@@ -1727,14 +1897,13 @@ func textbuildid() {
sym.P = []byte(data)
sym.Size = int64(len(sym.P))
- sym.Next = Ctxt.Textp
- Ctxt.Textp = sym
+ Ctxt.Textp = append(Ctxt.Textp, nil)
+ copy(Ctxt.Textp[1:], Ctxt.Textp)
+ Ctxt.Textp[0] = sym
}
// assign addresses to text
func textaddress() {
- var sub *LSym
-
addsection(&Segtext, ".text", 05)
// Assign PCs in text segment.
@@ -1750,7 +1919,7 @@ func textaddress() {
}
va := uint64(INITTEXT)
sect.Vaddr = va
- for sym := Ctxt.Textp; sym != nil; sym = sym.Next {
+ for _, sym := range Ctxt.Textp {
sym.Sect = sect
if sym.Type&obj.SSUB != 0 {
continue
@@ -1761,7 +1930,7 @@ func textaddress() {
va = uint64(Rnd(int64(va), int64(Funcalign)))
}
sym.Value = 0
- for sub = sym; sub != nil; sub = sub.Sub {
+ for sub := sym; sub != nil; sub = sub.Sub {
sub.Value += int64(va)
}
if sym.Size == 0 && sym.Sub != nil {
@@ -1857,6 +2026,29 @@ func address() {
Segdata.Filelen = bss.Vaddr - Segdata.Vaddr
+ va = uint64(Rnd(int64(va), int64(INITRND)))
+ Segdwarf.Rwx = 06
+ Segdwarf.Vaddr = va
+ Segdwarf.Fileoff = Segdata.Fileoff + uint64(Rnd(int64(Segdata.Filelen), int64(INITRND)))
+ Segdwarf.Filelen = 0
+ if HEADTYPE == obj.Hwindows {
+ Segdwarf.Fileoff = Segdata.Fileoff + uint64(Rnd(int64(Segdata.Filelen), int64(PEFILEALIGN)))
+ }
+ for s := Segdwarf.Sect; s != nil; s = s.Next {
+ vlen = int64(s.Length)
+ if s.Next != nil {
+ vlen = int64(s.Next.Vaddr - s.Vaddr)
+ }
+ s.Vaddr = va
+ va += uint64(vlen)
+ if HEADTYPE == obj.Hwindows {
+ va = uint64(Rnd(int64(va), PEFILEALIGN))
+ }
+ Segdwarf.Length = va - Segdwarf.Vaddr
+ }
+
+ Segdwarf.Filelen = va - Segdwarf.Vaddr
+
text := Segtext.Sect
var rodata *Section
if Segrodata.Sect != nil {
@@ -1864,23 +2056,34 @@ func address() {
} else {
rodata = text.Next
}
+ var relrodata *Section
typelink := rodata.Next
if UseRelro() {
// There is another section (.data.rel.ro) when building a shared
// object on elf systems.
+ relrodata = typelink
typelink = typelink.Next
}
itablink := typelink.Next
symtab := itablink.Next
pclntab := symtab.Next
- var sub *LSym
- for sym := datap; sym != nil; sym = sym.Next {
+ for _, s := range datap {
+ Ctxt.Cursym = s
+ if s.Sect != nil {
+ s.Value += int64(s.Sect.Vaddr)
+ }
+ for sub := s.Sub; sub != nil; sub = sub.Sub {
+ sub.Value += s.Value
+ }
+ }
+
+ for sym := dwarfp; sym != nil; sym = sym.Next {
Ctxt.Cursym = sym
if sym.Sect != nil {
sym.Value += int64(sym.Sect.Vaddr)
}
- for sub = sym.Sub; sub != nil; sub = sub.Sub {
+ for sub := sym.Sub; sub != nil; sub = sub.Sub {
sub.Value += sym.Value
}
}
@@ -1892,6 +2095,11 @@ func address() {
s.Value = int64(sectSym.Sect.Vaddr + 16)
}
+ types := relrodata
+ if types == nil {
+ types = rodata
+ }
+
xdefine("runtime.text", obj.STEXT, int64(text.Vaddr))
xdefine("runtime.etext", obj.STEXT, int64(text.Vaddr+text.Length))
if HEADTYPE == obj.Hwindows {
@@ -1899,6 +2107,8 @@ func address() {
}
xdefine("runtime.rodata", obj.SRODATA, int64(rodata.Vaddr))
xdefine("runtime.erodata", obj.SRODATA, int64(rodata.Vaddr+rodata.Length))
+ xdefine("runtime.types", obj.SRODATA, int64(types.Vaddr))
+ xdefine("runtime.etypes", obj.SRODATA, int64(types.Vaddr+types.Length))
xdefine("runtime.typelink", obj.SRODATA, int64(typelink.Vaddr))
xdefine("runtime.etypelink", obj.SRODATA, int64(typelink.Vaddr+typelink.Length))
xdefine("runtime.itablink", obj.SRODATA, int64(itablink.Vaddr))
diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go
index 56c4370bcc..aaed6cde21 100644
--- a/src/cmd/link/internal/ld/deadcode.go
+++ b/src/cmd/link/internal/ld/deadcode.go
@@ -6,6 +6,7 @@ package ld
import (
"cmd/internal/obj"
+ "cmd/internal/sys"
"fmt"
"strings"
"unicode"
@@ -18,7 +19,7 @@ import (
//
// This flood fill is wrapped in logic for pruning unused methods.
// All methods are mentioned by relocations on their receiver's *rtype.
-// These relocations are specially defined as R_METHOD by the compiler
+// These relocations are specially defined as R_METHODOFF by the compiler
// so we can detect and manipulated them here.
//
// There are three ways a method of a reachable type can be invoked:
@@ -99,7 +100,7 @@ func deadcode(ctxt *Link) {
d.flood()
}
- // Remove all remaining unreached R_METHOD relocations.
+ // Remove all remaining unreached R_METHODOFF relocations.
for _, m := range d.markableMethods {
for _, r := range m.r {
d.cleanupReloc(r)
@@ -118,25 +119,13 @@ func deadcode(ctxt *Link) {
}
// Remove dead text but keep file information (z symbols).
- var last *LSym
- for s := ctxt.Textp; s != nil; s = s.Next {
- if !s.Attr.Reachable() {
- continue
+ textp := make([]*LSym, 0, len(ctxt.Textp))
+ for _, s := range ctxt.Textp {
+ if s.Attr.Reachable() {
+ textp = append(textp, s)
}
- if last == nil {
- ctxt.Textp = s
- } else {
- last.Next = s
- }
- last = s
- }
- if last == nil {
- ctxt.Textp = nil
- ctxt.Etextp = nil
- } else {
- last.Next = nil
- ctxt.Etextp = last
}
+ ctxt.Textp = textp
}
var markextra = []string{
@@ -166,12 +155,10 @@ var markextra = []string{
type methodref struct {
m methodsig
src *LSym // receiver type symbol
- r [3]*Reloc // R_METHOD relocations to fields of runtime.method
+ r [3]*Reloc // R_METHODOFF relocations to fields of runtime.method
}
-func (m methodref) mtyp() *LSym { return m.r[0].Sym }
-func (m methodref) ifn() *LSym { return m.r[1].Sym }
-func (m methodref) tfn() *LSym { return m.r[2].Sym }
+func (m methodref) ifn() *LSym { return m.r[1].Sym }
func (m methodref) isExported() bool {
for _, r := range m.m {
@@ -191,7 +178,7 @@ type deadcodepass struct {
func (d *deadcodepass) cleanupReloc(r *Reloc) {
if r.Sym.Attr.Reachable() {
- r.Type = obj.R_ADDR
+ r.Type = obj.R_ADDROFF
} else {
if Debug['v'] > 1 {
fmt.Fprintf(d.ctxt.Bso, "removing method %s\n", r.Sym.Name)
@@ -209,6 +196,13 @@ func (d *deadcodepass) mark(s, parent *LSym) {
if s.Attr.ReflectMethod() {
d.reflectMethod = true
}
+ if flag_dumpdep {
+ p := "_"
+ if parent != nil {
+ p = parent.Name
+ }
+ fmt.Printf("%s -> %s\n", p, s.Name)
+ }
s.Attr |= AttrReachable
s.Reachparent = parent
d.markQueue = append(d.markQueue, s)
@@ -218,7 +212,7 @@ func (d *deadcodepass) mark(s, parent *LSym) {
func (d *deadcodepass) markMethod(m methodref) {
for _, r := range m.r {
d.mark(r.Sym, m.src)
- r.Type = obj.R_ADDR
+ r.Type = obj.R_ADDROFF
}
}
@@ -227,7 +221,7 @@ func (d *deadcodepass) markMethod(m methodref) {
func (d *deadcodepass) init() {
var names []string
- if Thearch.Thechar == '5' {
+ if SysArch.Family == sys.ARM {
// mark some functions that are only referenced after linker code editing
if d.ctxt.Goarm == 5 {
names = append(names, "_sfloat")
@@ -273,9 +267,12 @@ func (d *deadcodepass) flood() {
if Debug['v'] > 1 {
fmt.Fprintf(d.ctxt.Bso, "marktext %s\n", s.Name)
}
- for _, a := range s.Autom {
- d.mark(a.Gotype, s)
+ if s.FuncInfo != nil {
+ for _, a := range s.FuncInfo.Autom {
+ d.mark(a.Gotype, s)
+ }
}
+
}
if strings.HasPrefix(s.Name, "type.") && s.Name[5] != '.' {
@@ -289,14 +286,14 @@ func (d *deadcodepass) flood() {
}
}
- mpos := 0 // 0-3, the R_METHOD relocs of runtime.uncommontype
+ mpos := 0 // 0-3, the R_METHODOFF relocs of runtime.uncommontype
var methods []methodref
for i := 0; i < len(s.R); i++ {
r := &s.R[i]
if r.Sym == nil {
continue
}
- if r.Type != obj.R_METHOD {
+ if r.Type != obj.R_METHODOFF {
d.mark(r.Sym, s)
continue
}
@@ -333,9 +330,9 @@ func (d *deadcodepass) flood() {
d.markableMethods = append(d.markableMethods, methods...)
}
- if s.Pcln != nil {
- for i := range s.Pcln.Funcdata {
- d.mark(s.Pcln.Funcdata[i], s)
+ if s.FuncInfo != nil {
+ for i := range s.FuncInfo.Funcdata {
+ d.mark(s.FuncInfo.Funcdata[i], s)
}
}
d.mark(s.Gotype, s)
diff --git a/src/cmd/link/internal/ld/decodesym.go b/src/cmd/link/internal/ld/decodesym.go
index 0a6bf094aa..551ff802d7 100644
--- a/src/cmd/link/internal/ld/decodesym.go
+++ b/src/cmd/link/internal/ld/decodesym.go
@@ -7,6 +7,7 @@ package ld
import (
"bytes"
"cmd/internal/obj"
+ "cmd/internal/sys"
"debug/elf"
"fmt"
)
@@ -15,10 +16,22 @@ import (
// ../../runtime/type.go, or more specifically, with what
// ../gc/reflect.c stuffs in these.
+// tflag is documented in reflect/type.go.
+//
+// tflag values must be kept in sync with copies in:
+// cmd/compile/internal/gc/reflect.go
+// cmd/link/internal/ld/decodesym.go
+// reflect/type.go
+// runtime/type.go
+const (
+ tflagUncommon = 1 << 0
+ tflagExtraStar = 1 << 1
+)
+
func decode_reloc(s *LSym, off int32) *Reloc {
- for i := 0; i < len(s.R); i++ {
+ for i := range s.R {
if s.R[i].Off == off {
- return &s.R[i:][0]
+ return &s.R[i]
}
}
return nil
@@ -46,39 +59,33 @@ func decode_inuxi(p []byte, sz int) uint64 {
}
}
-func commonsize() int { return 6*Thearch.Ptrsize + 8 } // runtime._type
-func structfieldSize() int { return 3 * Thearch.Ptrsize } // runtime.structfield
-func uncommonSize() int { return 2*Thearch.Ptrsize + 2*Thearch.Intsize } // runtime.uncommontype
+func commonsize() int { return 4*SysArch.PtrSize + 8 + 8 } // runtime._type
+func structfieldSize() int { return 3 * SysArch.PtrSize } // runtime.structfield
+func uncommonSize() int { return 4 + 2 + 2 } // runtime.uncommontype
// Type.commonType.kind
func decodetype_kind(s *LSym) uint8 {
- return uint8(s.P[2*Thearch.Ptrsize+7] & obj.KindMask) // 0x13 / 0x1f
-}
-
-// Type.commonType.kind
-func decodetype_noptr(s *LSym) uint8 {
- return uint8(s.P[2*Thearch.Ptrsize+7] & obj.KindNoPointers) // 0x13 / 0x1f
+ return s.P[2*SysArch.PtrSize+7] & obj.KindMask // 0x13 / 0x1f
}
// Type.commonType.kind
func decodetype_usegcprog(s *LSym) uint8 {
- return uint8(s.P[2*Thearch.Ptrsize+7] & obj.KindGCProg) // 0x13 / 0x1f
+ return s.P[2*SysArch.PtrSize+7] & obj.KindGCProg // 0x13 / 0x1f
}
// Type.commonType.size
func decodetype_size(s *LSym) int64 {
- return int64(decode_inuxi(s.P, Thearch.Ptrsize)) // 0x8 / 0x10
+ return int64(decode_inuxi(s.P, SysArch.PtrSize)) // 0x8 / 0x10
}
// Type.commonType.ptrdata
func decodetype_ptrdata(s *LSym) int64 {
- return int64(decode_inuxi(s.P[Thearch.Ptrsize:], Thearch.Ptrsize)) // 0x8 / 0x10
+ return int64(decode_inuxi(s.P[SysArch.PtrSize:], SysArch.PtrSize)) // 0x8 / 0x10
}
// Type.commonType.tflag
func decodetype_hasUncommon(s *LSym) bool {
- const tflagUncommon = 1 // see ../../../../reflect/type.go:/^type.tflag
- return s.P[2*Thearch.Ptrsize+4]&tflagUncommon != 0
+ return s.P[2*SysArch.PtrSize+4]&tflagUncommon != 0
}
// Find the elf.Section of a given shared library that contains a given address.
@@ -112,11 +119,11 @@ func decodetype_gcprog(s *LSym) []byte {
Exitf("cannot find gcprog for %s", s.Name)
return nil
}
- return decode_reloc_sym(s, 2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize)).P
+ return decode_reloc_sym(s, 2*int32(SysArch.PtrSize)+8+1*int32(SysArch.PtrSize)).P
}
func decodetype_gcprog_shlib(s *LSym) uint64 {
- if Thearch.Thechar == '7' {
+ if SysArch.Family == sys.ARM64 {
for _, shlib := range Ctxt.Shlibs {
if shlib.Path == s.File {
return shlib.gcdata_addresses[s]
@@ -124,7 +131,7 @@ func decodetype_gcprog_shlib(s *LSym) uint64 {
}
return 0
}
- return decode_inuxi(s.P[2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize):], Thearch.Ptrsize)
+ return decode_inuxi(s.P[2*int32(SysArch.PtrSize)+8+1*int32(SysArch.PtrSize):], SysArch.PtrSize)
}
func decodetype_gcmask(s *LSym) []byte {
@@ -133,14 +140,14 @@ func decodetype_gcmask(s *LSym) []byte {
ptrdata := decodetype_ptrdata(s)
sect := findShlibSection(s.File, addr)
if sect != nil {
- r := make([]byte, ptrdata/int64(Thearch.Ptrsize))
+ r := make([]byte, ptrdata/int64(SysArch.PtrSize))
sect.ReadAt(r, int64(addr-sect.Addr))
return r
}
Exitf("cannot find gcmask for %s", s.Name)
return nil
}
- mask := decode_reloc_sym(s, 2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize))
+ mask := decode_reloc_sym(s, 2*int32(SysArch.PtrSize)+8+1*int32(SysArch.PtrSize))
return mask.P
}
@@ -150,7 +157,7 @@ func decodetype_arrayelem(s *LSym) *LSym {
}
func decodetype_arraylen(s *LSym) int64 {
- return int64(decode_inuxi(s.P[commonsize()+2*Thearch.Ptrsize:], Thearch.Ptrsize))
+ return int64(decode_inuxi(s.P[commonsize()+2*SysArch.PtrSize:], SysArch.PtrSize))
}
// Type.PtrType.elem
@@ -164,7 +171,7 @@ func decodetype_mapkey(s *LSym) *LSym {
}
func decodetype_mapvalue(s *LSym) *LSym {
- return decode_reloc_sym(s, int32(commonsize())+int32(Thearch.Ptrsize)) // 0x20 / 0x38
+ return decode_reloc_sym(s, int32(commonsize())+int32(SysArch.PtrSize)) // 0x20 / 0x38
}
// Type.ChanType.elem
@@ -188,13 +195,13 @@ func decodetype_funcoutcount(s *LSym) int {
func decodetype_funcintype(s *LSym, i int) *LSym {
uadd := commonsize() + 4
- if Thearch.Ptrsize == 8 {
+ if SysArch.PtrSize == 8 {
uadd += 4
}
if decodetype_hasUncommon(s) {
uadd += uncommonSize()
}
- return decode_reloc_sym(s, int32(uadd+i*Thearch.Ptrsize))
+ return decode_reloc_sym(s, int32(uadd+i*SysArch.PtrSize))
}
func decodetype_funcouttype(s *LSym, i int) *LSym {
@@ -203,11 +210,11 @@ func decodetype_funcouttype(s *LSym, i int) *LSym {
// Type.StructType.fields.Slice::length
func decodetype_structfieldcount(s *LSym) int {
- return int(decode_inuxi(s.P[commonsize()+2*Thearch.Ptrsize:], Thearch.Intsize))
+ return int(decode_inuxi(s.P[commonsize()+2*SysArch.PtrSize:], SysArch.IntSize))
}
func decodetype_structfieldarrayoff(s *LSym, i int) int {
- off := commonsize() + 2*Thearch.Ptrsize + 2*Thearch.Intsize
+ off := commonsize() + 2*SysArch.PtrSize + 2*SysArch.IntSize
if decodetype_hasUncommon(s) {
off += uncommonSize()
}
@@ -215,17 +222,13 @@ func decodetype_structfieldarrayoff(s *LSym, i int) int {
return off
}
-func decodetype_stringptr(s *LSym, off int) string {
- s = decode_reloc_sym(s, int32(off))
- if s == nil {
- return ""
- }
- r := decode_reloc(s, 0) // s has a pointer to the string data at offset 0
- if r == nil { // shouldn't happen.
- return ""
+// decodetype_str returns the contents of an rtype's str field (a nameOff).
+func decodetype_str(s *LSym) string {
+ str := decodetype_name(s, 4*SysArch.PtrSize+8)
+ if s.P[2*SysArch.PtrSize+4]&tflagExtraStar != 0 {
+ return str[1:]
}
- strlen := int64(decode_inuxi(s.P[Thearch.Ptrsize:], Thearch.Intsize))
- return string(r.Sym.P[r.Add : r.Add+strlen])
+ return str
}
// decodetype_name decodes the name from a reflect.name.
@@ -236,9 +239,8 @@ func decodetype_name(s *LSym, off int) string {
}
data := r.Sym.P
- namelen := int(uint16(data[1]<<8) | uint16(data[2]))
+ namelen := int(uint16(data[1])<<8 | uint16(data[2]))
return string(data[3 : 3+namelen])
-
}
func decodetype_structfieldname(s *LSym, i int) string {
@@ -248,17 +250,17 @@ func decodetype_structfieldname(s *LSym, i int) string {
func decodetype_structfieldtype(s *LSym, i int) *LSym {
off := decodetype_structfieldarrayoff(s, i)
- return decode_reloc_sym(s, int32(off+Thearch.Ptrsize))
+ return decode_reloc_sym(s, int32(off+SysArch.PtrSize))
}
func decodetype_structfieldoffs(s *LSym, i int) int64 {
off := decodetype_structfieldarrayoff(s, i)
- return int64(decode_inuxi(s.P[off+2*Thearch.Ptrsize:], Thearch.Intsize))
+ return int64(decode_inuxi(s.P[off+2*SysArch.PtrSize:], SysArch.IntSize))
}
// InterfaceType.methods.length
func decodetype_ifacemethodcount(s *LSym) int64 {
- return int64(decode_inuxi(s.P[commonsize()+2*Thearch.Ptrsize:], Thearch.Intsize))
+ return int64(decode_inuxi(s.P[commonsize()+2*SysArch.PtrSize:], SysArch.IntSize))
}
// methodsig is a fully qualified typed method signature, like
@@ -279,8 +281,9 @@ const (
)
// decode_methodsig decodes an array of method signature information.
-// Each element of the array is size bytes. The first word is a
-// reflect.name for the name, the second word is a *rtype for the funcType.
+// Each element of the array is size bytes. The first 4 bytes is a
+// nameOff for the method name, and the next 4 bytes is a typeOff for
+// the function type.
//
// Conveniently this is the layout of both runtime.method and runtime.imethod.
func decode_methodsig(s *LSym, off, size, count int) []methodsig {
@@ -288,7 +291,7 @@ func decode_methodsig(s *LSym, off, size, count int) []methodsig {
var methods []methodsig
for i := 0; i < count; i++ {
buf.WriteString(decodetype_name(s, off))
- mtypSym := decode_reloc_sym(s, int32(off+Thearch.Ptrsize))
+ mtypSym := decode_reloc_sym(s, int32(off+4))
buf.WriteRune('(')
inCount := decodetype_funcincount(mtypSym)
@@ -319,7 +322,7 @@ func decodetype_ifacemethods(s *LSym) []methodsig {
if decodetype_kind(s)&kindMask != kindInterface {
panic(fmt.Sprintf("symbol %q is not an interface", s.Name))
}
- r := decode_reloc(s, int32(commonsize()+Thearch.Ptrsize))
+ r := decode_reloc(s, int32(commonsize()+SysArch.PtrSize))
if r == nil {
return nil
}
@@ -328,7 +331,7 @@ func decodetype_ifacemethods(s *LSym) []methodsig {
}
off := int(r.Add) // array of reflect.imethod values
numMethods := int(decodetype_ifacemethodcount(s))
- sizeofIMethod := 2 * Thearch.Ptrsize
+ sizeofIMethod := 4 + 4
return decode_methodsig(s, off, sizeofIMethod, numMethods)
}
@@ -339,31 +342,28 @@ func decodetype_methods(s *LSym) []methodsig {
off := commonsize() // reflect.rtype
switch decodetype_kind(s) & kindMask {
case kindStruct: // reflect.structType
- off += 2*Thearch.Ptrsize + 2*Thearch.Intsize
+ off += 2*SysArch.PtrSize + 2*SysArch.IntSize
case kindPtr: // reflect.ptrType
- off += Thearch.Ptrsize
+ off += SysArch.PtrSize
case kindFunc: // reflect.funcType
- off += Thearch.Ptrsize // 4 bytes, pointer aligned
+ off += SysArch.PtrSize // 4 bytes, pointer aligned
case kindSlice: // reflect.sliceType
- off += Thearch.Ptrsize
+ off += SysArch.PtrSize
case kindArray: // reflect.arrayType
- off += 3 * Thearch.Ptrsize
+ off += 3 * SysArch.PtrSize
case kindChan: // reflect.chanType
- off += 2 * Thearch.Ptrsize
+ off += 2 * SysArch.PtrSize
case kindMap: // reflect.mapType
- off += 4*Thearch.Ptrsize + 8
+ off += 4*SysArch.PtrSize + 8
case kindInterface: // reflect.interfaceType
- off += Thearch.Ptrsize + 2*Thearch.Intsize
+ off += SysArch.PtrSize + 2*SysArch.IntSize
default:
// just Sizeof(rtype)
}
- numMethods := int(decode_inuxi(s.P[off+2*Thearch.Ptrsize:], Thearch.Intsize))
- r := decode_reloc(s, int32(off+Thearch.Ptrsize))
- if r.Sym != s {
- panic(fmt.Sprintf("method slice pointer in %s leads to a different symbol %s", s, r.Sym))
- }
- off = int(r.Add) // array of reflect.method values
- sizeofMethod := 4 * Thearch.Ptrsize // sizeof reflect.method in program
- return decode_methodsig(s, off, sizeofMethod, numMethods)
+ mcount := int(decode_inuxi(s.P[off+4:], 2))
+ moff := int(decode_inuxi(s.P[off+4+2:], 2))
+ off += moff // offset to array of reflect.method values
+ const sizeofMethod = 4 * 4 // sizeof reflect.method in program
+ return decode_methodsig(s, off, sizeofMethod, mcount)
}
diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go
index fd177cfef0..bf1a7e74c1 100644
--- a/src/cmd/link/internal/ld/dwarf.go
+++ b/src/cmd/link/internal/ld/dwarf.go
@@ -17,97 +17,34 @@ package ld
import (
"cmd/internal/obj"
"fmt"
+ "log"
"os"
"strings"
)
+const infoprefix = "go.dwarf.info."
+
/*
* Offsets and sizes of the debug_* sections in the cout file.
*/
-var abbrevo int64
-
-var abbrevsize int64
-
var abbrevsym *LSym
-
-var abbrevsympos int64
-
-var lineo int64
-
-var linesize int64
-
-var linesym *LSym
-
-var linesympos int64
-
-var infoo int64 // also the base for DWDie->offs and reference attributes.
-
-var infosize int64
-
-var infosym *LSym
-
-var infosympos int64
-
-var frameo int64
-
-var framesize int64
-
-var framesym *LSym
-
-var framesympos int64
-
-var pubnameso int64
-
-var pubnamessize int64
-
-var pubtypeso int64
-
-var pubtypessize int64
-
-var arangeso int64
-
-var arangessize int64
-
-var gdbscripto int64
-
-var gdbscriptsize int64
-
-var infosec *LSym
-
-var inforeloco int64
-
-var inforelocsize int64
-
var arangessec *LSym
-
-var arangesreloco int64
-
-var arangesrelocsize int64
-
-var linesec *LSym
-
-var linereloco int64
-
-var linerelocsize int64
-
var framesec *LSym
-
-var framereloco int64
-
-var framerelocsize int64
+var infosec *LSym
+var linesec *LSym
var gdbscript string
/*
* Basic I/O
*/
-func addrput(addr int64) {
- switch Thearch.Ptrsize {
+func addrput(s *LSym, addr int64) {
+ switch SysArch.PtrSize {
case 4:
- Thearch.Lput(uint32(addr))
+ Adduint32(Ctxt, s, uint32(addr))
case 8:
- Thearch.Vput(uint64(addr))
+ Adduint64(Ctxt, s, uint64(addr))
}
}
@@ -144,14 +81,14 @@ func appendSleb128(b []byte, v int64) []byte {
var encbuf [10]byte
-func uleb128put(v int64) {
+func uleb128put(s *LSym, v int64) {
b := appendUleb128(encbuf[:0], uint64(v))
- Cwrite(b)
+ Addbytes(Ctxt, s, b)
}
-func sleb128put(v int64) {
+func sleb128put(s *LSym, v int64) {
b := appendSleb128(encbuf[:0], v)
- Cwrite(b)
+ Addbytes(Ctxt, s, b)
}
/*
@@ -462,24 +399,29 @@ var abbrevs = [DW_NABRV]DWAbbrev{
},
}
-func writeabbrev() {
- abbrevo = Cpos()
+var dwarfp *LSym
+
+func writeabbrev() *LSym {
+ s := Linklookup(Ctxt, ".debug_abbrev", 0)
+ s.Type = obj.SDWARFSECT
+ abbrevsym = s
+
for i := 1; i < DW_NABRV; i++ {
// See section 7.5.3
- uleb128put(int64(i))
+ uleb128put(s, int64(i))
- uleb128put(int64(abbrevs[i].tag))
- Cput(abbrevs[i].children)
+ uleb128put(s, int64(abbrevs[i].tag))
+ Adduint8(Ctxt, s, abbrevs[i].children)
for _, f := range abbrevs[i].attr {
- uleb128put(int64(f.attr))
- uleb128put(int64(f.form))
+ uleb128put(s, int64(f.attr))
+ uleb128put(s, int64(f.form))
}
- uleb128put(0)
- uleb128put(0)
+ uleb128put(s, 0)
+ uleb128put(s, 0)
}
- Cput(0)
- abbrevsize = Cpos() - abbrevo
+ Adduint8(Ctxt, s, 0)
+ return s
}
/*
@@ -504,10 +446,7 @@ type DWDie struct {
link *DWDie
child *DWDie
attr *DWAttr
- // offset into .debug_info section, i.e relative to
- // infoo. only valid after call to putdie()
- offs int64
- hash map[string]*DWDie // optional index of DWAttr by name, enabled by mkindex()
+ sym *LSym
}
/*
@@ -556,9 +495,8 @@ func getattr(die *DWDie, attr uint16) *DWAttr {
}
// Every DIE has at least a DW_AT_name attribute (but it will only be
-// written out if it is listed in the abbrev). If its parent is
-// keeping an index, the new DIE will be inserted there.
-func newdie(parent *DWDie, abbrev int, name string) *DWDie {
+// written out if it is listed in the abbrev).
+func newdie(parent *DWDie, abbrev int, name string, version int) *DWDie {
die := new(DWDie)
die.abbrev = abbrev
die.link = parent.child
@@ -566,17 +504,17 @@ func newdie(parent *DWDie, abbrev int, name string) *DWDie {
newattr(die, DW_AT_name, DW_CLS_STRING, int64(len(name)), name)
- if parent.hash != nil {
- parent.hash[name] = die
+ if name != "" && (abbrev <= DW_ABRV_VARIABLE || abbrev >= DW_ABRV_NULLTYPE) {
+ if abbrev != DW_ABRV_VARIABLE || version == 0 {
+ die.sym = Linklookup(Ctxt, infoprefix+name, version)
+ die.sym.Attr |= AttrHidden
+ die.sym.Type = obj.SDWARFINFO
+ }
}
return die
}
-func mkindex(die *DWDie) {
- die.hash = make(map[string]*DWDie)
-}
-
func walktypedef(die *DWDie) *DWDie {
// Resolve typedef if present.
if die.abbrev == DW_ABRV_TYPEDECL {
@@ -590,159 +528,157 @@ func walktypedef(die *DWDie) *DWDie {
return die
}
+func walksymtypedef(s *LSym) *LSym {
+ if t := Linkrlookup(Ctxt, s.Name+".def", int(s.Version)); t != nil {
+ return t
+ }
+ return s
+}
+
// Find child by AT_name using hashtable if available or linear scan
// if not.
-func find(die *DWDie, name string) *DWDie {
+func findchild(die *DWDie, name string) *DWDie {
var prev *DWDie
for ; die != prev; prev, die = die, walktypedef(die) {
- if die.hash == nil {
- for a := die.child; a != nil; a = a.link {
- if name == getattr(a, DW_AT_name).data {
- return a
- }
+ for a := die.child; a != nil; a = a.link {
+ if name == getattr(a, DW_AT_name).data {
+ return a
}
- continue
- }
- if a := die.hash[name]; a != nil {
- return a
}
+ continue
}
return nil
}
-func mustFind(die *DWDie, name string) *DWDie {
- r := find(die, name)
+// Used to avoid string allocation when looking up dwarf symbols
+var prefixBuf = []byte(infoprefix)
+
+func find(name string) *LSym {
+ n := append(prefixBuf, name...)
+ // The string allocation below is optimized away because it is only used in a map lookup.
+ s := Linkrlookup(Ctxt, string(n), 0)
+ prefixBuf = n[:len(infoprefix)]
+ return s
+}
+
+func mustFind(name string) *LSym {
+ r := find(name)
if r == nil {
- Exitf("dwarf find: %s %p has no %s", getattr(die, DW_AT_name).data, die, name)
+ Exitf("dwarf find: cannot find %s", name)
}
return r
}
-func adddwarfrel(sec *LSym, sym *LSym, offsetbase int64, siz int, addend int64) {
- r := Addrel(sec)
- r.Sym = sym
- r.Xsym = sym
- r.Off = int32(Cpos() - offsetbase)
- r.Siz = uint8(siz)
- r.Type = obj.R_ADDR
- r.Add = addend
- r.Xadd = addend
- if Iself && Thearch.Thechar == '6' {
- addend = 0
- }
- if HEADTYPE == obj.Hdarwin {
- addend += sym.Value
- }
- switch siz {
- case 4:
- Thearch.Lput(uint32(addend))
-
- case 8:
- Thearch.Vput(uint64(addend))
-
+func adddwarfref(ctxt *Link, s *LSym, t *LSym, size int) int64 {
+ var result int64
+ switch size {
default:
- Diag("bad size in adddwarfrel")
+ Diag("invalid size %d in adddwarfref\n", size)
+ fallthrough
+ case SysArch.PtrSize:
+ result = Addaddr(ctxt, s, t)
+ case 4:
+ result = addaddrplus4(ctxt, s, t, 0)
}
+ r := &s.R[len(s.R)-1]
+ r.Type = obj.R_DWARFREF
+ return result
}
-func newrefattr(die *DWDie, attr uint16, ref *DWDie) *DWAttr {
+func newrefattr(die *DWDie, attr uint16, ref *LSym) *DWAttr {
if ref == nil {
return nil
}
return newattr(die, attr, DW_CLS_REFERENCE, 0, ref)
}
-var fwdcount int
-
-func putattr(abbrev int, form int, cls int, value int64, data interface{}) {
+func putattr(s *LSym, abbrev int, form int, cls int, value int64, data interface{}) {
switch form {
case DW_FORM_addr: // address
if Linkmode == LinkExternal {
value -= (data.(*LSym)).Value
- adddwarfrel(infosec, data.(*LSym), infoo, Thearch.Ptrsize, value)
+ Addaddrplus(Ctxt, s, data.(*LSym), value)
break
}
- addrput(value)
+ addrput(s, value)
case DW_FORM_block1: // block
if cls == DW_CLS_ADDRESS {
- Cput(uint8(1 + Thearch.Ptrsize))
- Cput(DW_OP_addr)
- if Linkmode == LinkExternal {
- value -= (data.(*LSym)).Value
- adddwarfrel(infosec, data.(*LSym), infoo, Thearch.Ptrsize, value)
- break
- }
-
- addrput(value)
+ Adduint8(Ctxt, s, uint8(1+SysArch.PtrSize))
+ Adduint8(Ctxt, s, DW_OP_addr)
+ Addaddr(Ctxt, s, data.(*LSym))
break
}
value &= 0xff
- Cput(uint8(value))
+ Adduint8(Ctxt, s, uint8(value))
p := data.([]byte)
for i := 0; int64(i) < value; i++ {
- Cput(uint8(p[i]))
+ Adduint8(Ctxt, s, p[i])
}
case DW_FORM_block2: // block
value &= 0xffff
- Thearch.Wput(uint16(value))
+ Adduint16(Ctxt, s, uint16(value))
p := data.([]byte)
for i := 0; int64(i) < value; i++ {
- Cput(uint8(p[i]))
+ Adduint8(Ctxt, s, p[i])
}
case DW_FORM_block4: // block
value &= 0xffffffff
- Thearch.Lput(uint32(value))
+ Adduint32(Ctxt, s, uint32(value))
p := data.([]byte)
for i := 0; int64(i) < value; i++ {
- Cput(uint8(p[i]))
+ Adduint8(Ctxt, s, p[i])
}
case DW_FORM_block: // block
- uleb128put(value)
+ uleb128put(s, value)
p := data.([]byte)
for i := 0; int64(i) < value; i++ {
- Cput(uint8(p[i]))
+ Adduint8(Ctxt, s, p[i])
}
case DW_FORM_data1: // constant
- Cput(uint8(value))
+ Adduint8(Ctxt, s, uint8(value))
case DW_FORM_data2: // constant
- Thearch.Wput(uint16(value))
+ Adduint16(Ctxt, s, uint16(value))
case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr
if Linkmode == LinkExternal && cls == DW_CLS_PTR {
- adddwarfrel(infosec, linesym, infoo, 4, value)
+ adddwarfref(Ctxt, s, linesec, 4)
break
}
- Thearch.Lput(uint32(value))
+ Adduint32(Ctxt, s, uint32(value))
case DW_FORM_data8: // constant, {line,loclist,mac,rangelist}ptr
- Thearch.Vput(uint64(value))
+ Adduint64(Ctxt, s, uint64(value))
case DW_FORM_sdata: // constant
- sleb128put(value)
+ sleb128put(s, value)
case DW_FORM_udata: // constant
- uleb128put(value)
+ uleb128put(s, value)
case DW_FORM_string: // string
- strnput(data.(string), int(value+1))
+ str := data.(string)
+ Addstring(s, str)
+ for i := int64(len(str)); i < value; i++ {
+ Adduint8(Ctxt, s, 0)
+ }
case DW_FORM_flag: // flag
if value != 0 {
- Cput(1)
+ Adduint8(Ctxt, s, 1)
} else {
- Cput(0)
+ Adduint8(Ctxt, s, 0)
}
// In DWARF 2 (which is what we claim to generate),
@@ -752,22 +688,14 @@ func putattr(abbrev int, form int, cls int, value int64, data interface{}) {
case DW_FORM_ref_addr: // reference to a DIE in the .info section
if data == nil {
Diag("dwarf: null reference in %d", abbrev)
- if Thearch.Ptrsize == 8 {
- Thearch.Vput(0) // invalid dwarf, gdb will complain.
+ if SysArch.PtrSize == 8 {
+ Adduint64(Ctxt, s, 0) // invalid dwarf, gdb will complain.
} else {
- Thearch.Lput(0) // invalid dwarf, gdb will complain.
+ Adduint32(Ctxt, s, 0) // invalid dwarf, gdb will complain.
}
} else {
- off := (data.(*DWDie)).offs
- if off == 0 {
- fwdcount++
- }
- if Linkmode == LinkExternal {
- adddwarfrel(infosec, infosym, infoo, Thearch.Ptrsize, off)
- break
- }
-
- addrput(off)
+ dsym := data.(*LSym)
+ adddwarfref(Ctxt, s, dsym, SysArch.PtrSize)
}
case DW_FORM_ref1, // reference within the compilation unit
@@ -786,34 +714,45 @@ func putattr(abbrev int, form int, cls int, value int64, data interface{}) {
// Note that we can (and do) add arbitrary attributes to a DIE, but
// only the ones actually listed in the Abbrev will be written out.
-func putattrs(abbrev int, attr *DWAttr) {
+func putattrs(s *LSym, abbrev int, attr *DWAttr) {
Outer:
for _, f := range abbrevs[abbrev].attr {
for ap := attr; ap != nil; ap = ap.link {
if ap.atr == f.attr {
- putattr(abbrev, int(f.form), int(ap.cls), ap.value, ap.data)
+ putattr(s, abbrev, int(f.form), int(ap.cls), ap.value, ap.data)
continue Outer
}
}
- putattr(abbrev, int(f.form), 0, 0, nil)
+ putattr(s, abbrev, int(f.form), 0, 0, nil)
}
}
-func putdies(die *DWDie) {
+func putdies(prev *LSym, die *DWDie) *LSym {
for ; die != nil; die = die.link {
- putdie(die)
+ prev = putdie(prev, die)
}
+ Adduint8(Ctxt, prev, 0)
+ return prev
}
-func putdie(die *DWDie) {
- die.offs = Cpos() - infoo
- uleb128put(int64(die.abbrev))
- putattrs(die.abbrev, die.attr)
+func putdie(prev *LSym, die *DWDie) *LSym {
+ s := die.sym
+ if s == nil {
+ s = prev
+ } else {
+ if s.Attr.OnList() {
+ log.Fatalf("symbol %s listed multiple times", s.Name)
+ }
+ s.Attr |= AttrOnList
+ prev.Next = s
+ }
+ uleb128put(s, int64(die.abbrev))
+ putattrs(s, die.abbrev, die.attr)
if abbrevs[die.abbrev].children != 0 {
- putdies(die.child)
- Cput(0)
+ return putdies(s, die.child)
}
+ return s
}
func reverselist(list **DWDie) {
@@ -880,44 +819,50 @@ func dotypedef(parent *DWDie, name string, def *DWDie) {
Diag("dwarf: bad def in dotypedef")
}
+ def.sym = Linklookup(Ctxt, def.sym.Name+".def", 0)
+ def.sym.Attr |= AttrHidden
+ def.sym.Type = obj.SDWARFINFO
+
// The typedef entry must be created after the def,
// so that future lookups will find the typedef instead
// of the real definition. This hooks the typedef into any
// circular definition loops, so that gdb can understand them.
- die := newdie(parent, DW_ABRV_TYPEDECL, name)
+ die := newdie(parent, DW_ABRV_TYPEDECL, name, 0)
- newrefattr(die, DW_AT_type, def)
+ newrefattr(die, DW_AT_type, def.sym)
}
// Define gotype, for composite ones recurse into constituents.
-func defgotype(gotype *LSym) *DWDie {
+func defgotype(gotype *LSym) *LSym {
if gotype == nil {
- return mustFind(&dwtypes, "<unspecified>")
+ return mustFind("<unspecified>")
}
if !strings.HasPrefix(gotype.Name, "type.") {
Diag("dwarf: type name doesn't start with \"type.\": %s", gotype.Name)
- return mustFind(&dwtypes, "<unspecified>")
+ return mustFind("<unspecified>")
}
name := gotype.Name[5:] // could also decode from Type.string
- die := find(&dwtypes, name)
+ sdie := find(name)
- if die != nil {
- return die
+ if sdie != nil {
+ return sdie
}
- if false && Debug['v'] > 2 {
- fmt.Printf("new type: %v\n", gotype)
- }
+ return newtype(gotype).sym
+}
+func newtype(gotype *LSym) *DWDie {
+ name := gotype.Name[5:] // could also decode from Type.string
kind := decodetype_kind(gotype)
bytesize := decodetype_size(gotype)
+ var die *DWDie
switch kind {
case obj.KindBool:
- die = newdie(&dwtypes, DW_ABRV_BASETYPE, name)
+ die = newdie(&dwtypes, DW_ABRV_BASETYPE, name, 0)
newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_boolean, 0)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
@@ -926,7 +871,7 @@ func defgotype(gotype *LSym) *DWDie {
obj.KindInt16,
obj.KindInt32,
obj.KindInt64:
- die = newdie(&dwtypes, DW_ABRV_BASETYPE, name)
+ die = newdie(&dwtypes, DW_ABRV_BASETYPE, name, 0)
newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_signed, 0)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
@@ -936,66 +881,69 @@ func defgotype(gotype *LSym) *DWDie {
obj.KindUint32,
obj.KindUint64,
obj.KindUintptr:
- die = newdie(&dwtypes, DW_ABRV_BASETYPE, name)
+ die = newdie(&dwtypes, DW_ABRV_BASETYPE, name, 0)
newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_unsigned, 0)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
case obj.KindFloat32,
obj.KindFloat64:
- die = newdie(&dwtypes, DW_ABRV_BASETYPE, name)
+ die = newdie(&dwtypes, DW_ABRV_BASETYPE, name, 0)
newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_float, 0)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
case obj.KindComplex64,
obj.KindComplex128:
- die = newdie(&dwtypes, DW_ABRV_BASETYPE, name)
+ die = newdie(&dwtypes, DW_ABRV_BASETYPE, name, 0)
newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_complex_float, 0)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
case obj.KindArray:
- die = newdie(&dwtypes, DW_ABRV_ARRAYTYPE, name)
+ die = newdie(&dwtypes, DW_ABRV_ARRAYTYPE, name, 0)
dotypedef(&dwtypes, name, die)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
s := decodetype_arrayelem(gotype)
newrefattr(die, DW_AT_type, defgotype(s))
- fld := newdie(die, DW_ABRV_ARRAYRANGE, "range")
+ fld := newdie(die, DW_ABRV_ARRAYRANGE, "range", 0)
// use actual length not upper bound; correct for 0-length arrays.
newattr(fld, DW_AT_count, DW_CLS_CONSTANT, decodetype_arraylen(gotype), 0)
- newrefattr(fld, DW_AT_type, mustFind(&dwtypes, "uintptr"))
+ newrefattr(fld, DW_AT_type, mustFind("uintptr"))
case obj.KindChan:
- die = newdie(&dwtypes, DW_ABRV_CHANTYPE, name)
+ die = newdie(&dwtypes, DW_ABRV_CHANTYPE, name, 0)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
s := decodetype_chanelem(gotype)
newrefattr(die, DW_AT_go_elem, defgotype(s))
+ // Save elem type for synthesizechantypes. We could synthesize here
+ // but that would change the order of DIEs we output.
+ newrefattr(die, DW_AT_type, s)
case obj.KindFunc:
- die = newdie(&dwtypes, DW_ABRV_FUNCTYPE, name)
+ die = newdie(&dwtypes, DW_ABRV_FUNCTYPE, name, 0)
dotypedef(&dwtypes, name, die)
- newrefattr(die, DW_AT_type, mustFind(&dwtypes, "void"))
+ newrefattr(die, DW_AT_type, mustFind("void"))
nfields := decodetype_funcincount(gotype)
var fld *DWDie
var s *LSym
for i := 0; i < nfields; i++ {
s = decodetype_funcintype(gotype, i)
- fld = newdie(die, DW_ABRV_FUNCTYPEPARAM, s.Name[5:])
+ fld = newdie(die, DW_ABRV_FUNCTYPEPARAM, s.Name[5:], 0)
newrefattr(fld, DW_AT_type, defgotype(s))
}
if decodetype_funcdotdotdot(gotype) {
- newdie(die, DW_ABRV_DOTDOTDOT, "...")
+ newdie(die, DW_ABRV_DOTDOTDOT, "...", 0)
}
nfields = decodetype_funcoutcount(gotype)
for i := 0; i < nfields; i++ {
s = decodetype_funcouttype(gotype, i)
- fld = newdie(die, DW_ABRV_FUNCTYPEPARAM, s.Name[5:])
+ fld = newdie(die, DW_ABRV_FUNCTYPEPARAM, s.Name[5:], 0)
newrefattr(fld, DW_AT_type, defptrto(defgotype(s)))
}
case obj.KindInterface:
- die = newdie(&dwtypes, DW_ABRV_IFACETYPE, name)
+ die = newdie(&dwtypes, DW_ABRV_IFACETYPE, name, 0)
dotypedef(&dwtypes, name, die)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
nfields := int(decodetype_ifacemethodcount(gotype))
@@ -1008,31 +956,35 @@ func defgotype(gotype *LSym) *DWDie {
newrefattr(die, DW_AT_type, defgotype(s))
case obj.KindMap:
- die = newdie(&dwtypes, DW_ABRV_MAPTYPE, name)
+ die = newdie(&dwtypes, DW_ABRV_MAPTYPE, name, 0)
s := decodetype_mapkey(gotype)
newrefattr(die, DW_AT_go_key, defgotype(s))
s = decodetype_mapvalue(gotype)
newrefattr(die, DW_AT_go_elem, defgotype(s))
+ // Save gotype for use in synthesizemaptypes. We could synthesize here,
+ // but that would change the order of the DIEs.
+ newrefattr(die, DW_AT_type, gotype)
case obj.KindPtr:
- die = newdie(&dwtypes, DW_ABRV_PTRTYPE, name)
+ die = newdie(&dwtypes, DW_ABRV_PTRTYPE, name, 0)
dotypedef(&dwtypes, name, die)
s := decodetype_ptrelem(gotype)
newrefattr(die, DW_AT_type, defgotype(s))
case obj.KindSlice:
- die = newdie(&dwtypes, DW_ABRV_SLICETYPE, name)
+ die = newdie(&dwtypes, DW_ABRV_SLICETYPE, name, 0)
dotypedef(&dwtypes, name, die)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
s := decodetype_arrayelem(gotype)
- newrefattr(die, DW_AT_go_elem, defgotype(s))
+ elem := defgotype(s)
+ newrefattr(die, DW_AT_go_elem, elem)
case obj.KindString:
- die = newdie(&dwtypes, DW_ABRV_STRINGTYPE, name)
+ die = newdie(&dwtypes, DW_ABRV_STRINGTYPE, name, 0)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
case obj.KindStruct:
- die = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, name)
+ die = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, name, 0)
dotypedef(&dwtypes, name, die)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
nfields := decodetype_structfieldcount(gotype)
@@ -1045,32 +997,41 @@ func defgotype(gotype *LSym) *DWDie {
if f == "" {
f = s.Name[5:] // skip "type."
}
- fld = newdie(die, DW_ABRV_STRUCTFIELD, f)
+ fld = newdie(die, DW_ABRV_STRUCTFIELD, f, 0)
newrefattr(fld, DW_AT_type, defgotype(s))
newmemberoffsetattr(fld, int32(decodetype_structfieldoffs(gotype, i)))
}
case obj.KindUnsafePointer:
- die = newdie(&dwtypes, DW_ABRV_BARE_PTRTYPE, name)
+ die = newdie(&dwtypes, DW_ABRV_BARE_PTRTYPE, name, 0)
default:
Diag("dwarf: definition of unknown kind %d: %s", kind, gotype.Name)
- die = newdie(&dwtypes, DW_ABRV_TYPEDECL, name)
- newrefattr(die, DW_AT_type, mustFind(&dwtypes, "<unspecified>"))
+ die = newdie(&dwtypes, DW_ABRV_TYPEDECL, name, 0)
+ newrefattr(die, DW_AT_type, mustFind("<unspecified>"))
}
newattr(die, DW_AT_go_kind, DW_CLS_CONSTANT, int64(kind), 0)
+ if _, ok := prototypedies[gotype.Name]; ok {
+ prototypedies[gotype.Name] = die
+ }
+
return die
}
+func nameFromDIESym(dwtype *LSym) string {
+ return strings.TrimSuffix(dwtype.Name[len(infoprefix):], ".def")
+}
+
// Find or construct *T given T.
-func defptrto(dwtype *DWDie) *DWDie {
- ptrname := fmt.Sprintf("*%s", getattr(dwtype, DW_AT_name).data)
- die := find(&dwtypes, ptrname)
+func defptrto(dwtype *LSym) *LSym {
+ ptrname := "*" + nameFromDIESym(dwtype)
+ die := find(ptrname)
if die == nil {
- die = newdie(&dwtypes, DW_ABRV_PTRTYPE, ptrname)
- newrefattr(die, DW_AT_type, dwtype)
+ pdie := newdie(&dwtypes, DW_ABRV_PTRTYPE, ptrname, 0)
+ newrefattr(pdie, DW_AT_type, dwtype)
+ return pdie.sym
}
return die
@@ -1084,7 +1045,7 @@ func copychildrenexcept(dst *DWDie, src *DWDie, except *DWDie) {
if src == except {
continue
}
- c := newdie(dst, src.abbrev, getattr(src, DW_AT_name).data.(string))
+ c := newdie(dst, src.abbrev, getattr(src, DW_AT_name).data.(string), 0)
for a := src.attr; a != nil; a = a.link {
newattr(c, a.atr, int(a.cls), a.value, a.data)
}
@@ -1100,9 +1061,11 @@ func copychildren(dst *DWDie, src *DWDie) {
// Search children (assumed to have DW_TAG_member) for the one named
// field and set its DW_AT_type to dwtype
-func substitutetype(structdie *DWDie, field string, dwtype *DWDie) {
- child := mustFind(structdie, field)
+func substitutetype(structdie *DWDie, field string, dwtype *LSym) {
+ child := findchild(structdie, field)
if child == nil {
+ Exitf("dwarf substitutetype: %s does not have member %s",
+ getattr(structdie, DW_AT_name).data, field)
return
}
@@ -1114,8 +1077,17 @@ func substitutetype(structdie *DWDie, field string, dwtype *DWDie) {
}
}
+func findprotodie(name string) *DWDie {
+ die, ok := prototypedies[name]
+ if ok && die == nil {
+ defgotype(lookup_or_diag(name))
+ die = prototypedies[name]
+ }
+ return die
+}
+
func synthesizestringtypes(die *DWDie) {
- prototype := walktypedef(defgotype(lookup_or_diag("type.runtime.stringStructDWARF")))
+ prototype := walktypedef(findprotodie("type.runtime.stringStructDWARF"))
if prototype == nil {
return
}
@@ -1129,7 +1101,7 @@ func synthesizestringtypes(die *DWDie) {
}
func synthesizeslicetypes(die *DWDie) {
- prototype := walktypedef(defgotype(lookup_or_diag("type.runtime.slice")))
+ prototype := walktypedef(findprotodie("type.runtime.slice"))
if prototype == nil {
return
}
@@ -1139,7 +1111,7 @@ func synthesizeslicetypes(die *DWDie) {
continue
}
copychildren(die, prototype)
- elem := getattr(die, DW_AT_go_elem).data.(*DWDie)
+ elem := getattr(die, DW_AT_go_elem).data.(*LSym)
substitutetype(die, "array", defptrto(elem))
}
}
@@ -1163,9 +1135,21 @@ const (
BucketSize = 8
)
+func mkinternaltype(abbrev int, typename, keyname, valname string, f func(*DWDie)) *LSym {
+ name := mkinternaltypename(typename, keyname, valname)
+ symname := infoprefix + name
+ s := Linkrlookup(Ctxt, symname, 0)
+ if s != nil {
+ return s
+ }
+ die := newdie(&dwtypes, abbrev, name, 0)
+ f(die)
+ return die.sym
+}
+
func synthesizemaptypes(die *DWDie) {
- hash := walktypedef(defgotype(lookup_or_diag("type.runtime.hmap")))
- bucket := walktypedef(defgotype(lookup_or_diag("type.runtime.bmap")))
+ hash := walktypedef(findprotodie("type.runtime.hmap"))
+ bucket := walktypedef(findprotodie("type.runtime.bmap"))
if hash == nil {
return
@@ -1175,97 +1159,92 @@ func synthesizemaptypes(die *DWDie) {
if die.abbrev != DW_ABRV_MAPTYPE {
continue
}
-
- keytype := walktypedef(getattr(die, DW_AT_go_key).data.(*DWDie))
- valtype := walktypedef(getattr(die, DW_AT_go_elem).data.(*DWDie))
+ gotype := getattr(die, DW_AT_type).data.(*LSym)
+ keytype := decodetype_mapkey(gotype)
+ valtype := decodetype_mapvalue(gotype)
+ keysize, valsize := decodetype_size(keytype), decodetype_size(valtype)
+ keytype, valtype = walksymtypedef(defgotype(keytype)), walksymtypedef(defgotype(valtype))
// compute size info like hashmap.c does.
- keysize, valsize := Thearch.Ptrsize, Thearch.Ptrsize
- a := getattr(keytype, DW_AT_byte_size)
- if a != nil {
- keysize = int(a.value)
- }
- a = getattr(valtype, DW_AT_byte_size)
- if a != nil {
- valsize = int(a.value)
- }
indirect_key, indirect_val := false, false
if keysize > MaxKeySize {
- keysize = Thearch.Ptrsize
+ keysize = int64(SysArch.PtrSize)
indirect_key = true
}
if valsize > MaxValSize {
- valsize = Thearch.Ptrsize
+ valsize = int64(SysArch.PtrSize)
indirect_val = true
}
// Construct type to represent an array of BucketSize keys
- dwhk := newdie(&dwtypes, DW_ABRV_ARRAYTYPE, mkinternaltypename("[]key", getattr(keytype, DW_AT_name).data.(string), ""))
-
- newattr(dwhk, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize*int64(keysize), 0)
- t := keytype
- if indirect_key {
- t = defptrto(keytype)
- }
- newrefattr(dwhk, DW_AT_type, t)
- fld := newdie(dwhk, DW_ABRV_ARRAYRANGE, "size")
- newattr(fld, DW_AT_count, DW_CLS_CONSTANT, BucketSize, 0)
- newrefattr(fld, DW_AT_type, mustFind(&dwtypes, "uintptr"))
+ keyname := nameFromDIESym(keytype)
+ dwhks := mkinternaltype(DW_ABRV_ARRAYTYPE, "[]key", keyname, "", func(dwhk *DWDie) {
+ newattr(dwhk, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize*keysize, 0)
+ t := keytype
+ if indirect_key {
+ t = defptrto(keytype)
+ }
+ newrefattr(dwhk, DW_AT_type, t)
+ fld := newdie(dwhk, DW_ABRV_ARRAYRANGE, "size", 0)
+ newattr(fld, DW_AT_count, DW_CLS_CONSTANT, BucketSize, 0)
+ newrefattr(fld, DW_AT_type, mustFind("uintptr"))
+ })
// Construct type to represent an array of BucketSize values
- dwhv := newdie(&dwtypes, DW_ABRV_ARRAYTYPE, mkinternaltypename("[]val", getattr(valtype, DW_AT_name).data.(string), ""))
-
- newattr(dwhv, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize*int64(valsize), 0)
- t = valtype
- if indirect_val {
- t = defptrto(valtype)
- }
- newrefattr(dwhv, DW_AT_type, t)
- fld = newdie(dwhv, DW_ABRV_ARRAYRANGE, "size")
- newattr(fld, DW_AT_count, DW_CLS_CONSTANT, BucketSize, 0)
- newrefattr(fld, DW_AT_type, mustFind(&dwtypes, "uintptr"))
+ valname := nameFromDIESym(valtype)
+ dwhvs := mkinternaltype(DW_ABRV_ARRAYTYPE, "[]val", valname, "", func(dwhv *DWDie) {
+ newattr(dwhv, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize*valsize, 0)
+ t := valtype
+ if indirect_val {
+ t = defptrto(valtype)
+ }
+ newrefattr(dwhv, DW_AT_type, t)
+ fld := newdie(dwhv, DW_ABRV_ARRAYRANGE, "size", 0)
+ newattr(fld, DW_AT_count, DW_CLS_CONSTANT, BucketSize, 0)
+ newrefattr(fld, DW_AT_type, mustFind("uintptr"))
+ })
// Construct bucket<K,V>
- dwhb := newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("bucket", getattr(keytype, DW_AT_name).data.(string), getattr(valtype, DW_AT_name).data.(string)))
-
- // Copy over all fields except the field "data" from the generic bucket.
- // "data" will be replaced with keys/values below.
- copychildrenexcept(dwhb, bucket, find(bucket, "data"))
+ dwhbs := mkinternaltype(DW_ABRV_STRUCTTYPE, "bucket", keyname, valname, func(dwhb *DWDie) {
+ // Copy over all fields except the field "data" from the generic
+ // bucket. "data" will be replaced with keys/values below.
+ copychildrenexcept(dwhb, bucket, findchild(bucket, "data"))
- fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "keys")
- newrefattr(fld, DW_AT_type, dwhk)
- newmemberoffsetattr(fld, BucketSize)
- fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "values")
- newrefattr(fld, DW_AT_type, dwhv)
- newmemberoffsetattr(fld, BucketSize+BucketSize*int32(keysize))
- fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "overflow")
- newrefattr(fld, DW_AT_type, defptrto(dwhb))
- newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize)))
- if Thearch.Regsize > Thearch.Ptrsize {
- fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "pad")
- newrefattr(fld, DW_AT_type, mustFind(&dwtypes, "uintptr"))
- newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))+int32(Thearch.Ptrsize))
- }
+ fld := newdie(dwhb, DW_ABRV_STRUCTFIELD, "keys", 0)
+ newrefattr(fld, DW_AT_type, dwhks)
+ newmemberoffsetattr(fld, BucketSize)
+ fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "values", 0)
+ newrefattr(fld, DW_AT_type, dwhvs)
+ newmemberoffsetattr(fld, BucketSize+BucketSize*int32(keysize))
+ fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "overflow", 0)
+ newrefattr(fld, DW_AT_type, defptrto(dwhb.sym))
+ newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize)))
+ if SysArch.RegSize > SysArch.PtrSize {
+ fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "pad", 0)
+ newrefattr(fld, DW_AT_type, mustFind("uintptr"))
+ newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))+int32(SysArch.PtrSize))
+ }
- newattr(dwhb, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize+BucketSize*int64(keysize)+BucketSize*int64(valsize)+int64(Thearch.Regsize), 0)
+ newattr(dwhb, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize+BucketSize*keysize+BucketSize*valsize+int64(SysArch.RegSize), 0)
+ })
// Construct hash<K,V>
- dwh := newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("hash", getattr(keytype, DW_AT_name).data.(string), getattr(valtype, DW_AT_name).data.(string)))
-
- copychildren(dwh, hash)
- substitutetype(dwh, "buckets", defptrto(dwhb))
- substitutetype(dwh, "oldbuckets", defptrto(dwhb))
- newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT, getattr(hash, DW_AT_byte_size).value, nil)
+ dwhs := mkinternaltype(DW_ABRV_STRUCTTYPE, "hash", keyname, valname, func(dwh *DWDie) {
+ copychildren(dwh, hash)
+ substitutetype(dwh, "buckets", defptrto(dwhbs))
+ substitutetype(dwh, "oldbuckets", defptrto(dwhbs))
+ newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT, getattr(hash, DW_AT_byte_size).value, nil)
+ })
// make map type a pointer to hash<K,V>
- newrefattr(die, DW_AT_type, defptrto(dwh))
+ newrefattr(die, DW_AT_type, defptrto(dwhs))
}
}
func synthesizechantypes(die *DWDie) {
- sudog := walktypedef(defgotype(lookup_or_diag("type.runtime.sudog")))
- waitq := walktypedef(defgotype(lookup_or_diag("type.runtime.waitq")))
- hchan := walktypedef(defgotype(lookup_or_diag("type.runtime.hchan")))
+ sudog := walktypedef(findprotodie("type.runtime.sudog"))
+ waitq := walktypedef(findprotodie("type.runtime.waitq"))
+ hchan := walktypedef(findprotodie("type.runtime.hchan"))
if sudog == nil || waitq == nil || hchan == nil {
return
}
@@ -1276,42 +1255,41 @@ func synthesizechantypes(die *DWDie) {
if die.abbrev != DW_ABRV_CHANTYPE {
continue
}
- elemsize := Thearch.Ptrsize
- elemtype := getattr(die, DW_AT_go_elem).data.(*DWDie)
- a := getattr(elemtype, DW_AT_byte_size)
- if a != nil {
- elemsize = int(a.value)
- }
+ elemgotype := getattr(die, DW_AT_type).data.(*LSym)
+ elemsize := decodetype_size(elemgotype)
+ elemname := elemgotype.Name[5:]
+ elemtype := walksymtypedef(defgotype(elemgotype))
// sudog<T>
- dws := newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("sudog", getattr(elemtype, DW_AT_name).data.(string), ""))
-
- copychildren(dws, sudog)
- substitutetype(dws, "elem", elemtype)
- if elemsize > 8 {
- elemsize -= 8
- } else {
- elemsize = 0
- }
- newattr(dws, DW_AT_byte_size, DW_CLS_CONSTANT, int64(sudogsize)+int64(elemsize), nil)
+ dwss := mkinternaltype(DW_ABRV_STRUCTTYPE, "sudog", elemname, "", func(dws *DWDie) {
+ copychildren(dws, sudog)
+ substitutetype(dws, "elem", elemtype)
+ if elemsize > 8 {
+ elemsize -= 8
+ } else {
+ elemsize = 0
+ }
+ newattr(dws, DW_AT_byte_size, DW_CLS_CONSTANT, int64(sudogsize)+elemsize, nil)
+ })
// waitq<T>
- dww := newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("waitq", getattr(elemtype, DW_AT_name).data.(string), ""))
+ dwws := mkinternaltype(DW_ABRV_STRUCTTYPE, "waitq", elemname, "", func(dww *DWDie) {
- copychildren(dww, waitq)
- substitutetype(dww, "first", defptrto(dws))
- substitutetype(dww, "last", defptrto(dws))
- newattr(dww, DW_AT_byte_size, DW_CLS_CONSTANT, getattr(waitq, DW_AT_byte_size).value, nil)
+ copychildren(dww, waitq)
+ substitutetype(dww, "first", defptrto(dwss))
+ substitutetype(dww, "last", defptrto(dwss))
+ newattr(dww, DW_AT_byte_size, DW_CLS_CONSTANT, getattr(waitq, DW_AT_byte_size).value, nil)
+ })
// hchan<T>
- dwh := newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("hchan", getattr(elemtype, DW_AT_name).data.(string), ""))
+ dwhs := mkinternaltype(DW_ABRV_STRUCTTYPE, "hchan", elemname, "", func(dwh *DWDie) {
+ copychildren(dwh, hchan)
+ substitutetype(dwh, "recvq", dwws)
+ substitutetype(dwh, "sendq", dwws)
+ newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT, getattr(hchan, DW_AT_byte_size).value, nil)
+ })
- copychildren(dwh, hchan)
- substitutetype(dwh, "recvq", dww)
- substitutetype(dwh, "sendq", dww)
- newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT, getattr(hchan, DW_AT_byte_size).value, nil)
-
- newrefattr(die, DW_AT_type, defptrto(dwh))
+ newrefattr(die, DW_AT_type, defptrto(dwhs))
}
}
@@ -1331,13 +1309,13 @@ func defdwsymb(sym *LSym, s string, t int, v int64, size int64, ver int, gotype
var dv *DWDie
- var dt *DWDie
+ var dt *LSym
switch t {
default:
return
case 'd', 'b', 'D', 'B':
- dv = newdie(&dwglobals, DW_ABRV_VARIABLE, s)
+ dv = newdie(&dwglobals, DW_ABRV_VARIABLE, s, ver)
newabslocexprattr(dv, v, sym)
if ver == 0 {
newattr(dv, DW_AT_external, DW_CLS_FLAG, 1, 0)
@@ -1367,8 +1345,8 @@ func finddebugruntimepath(s *LSym) {
return
}
- for i := range s.Pcln.File {
- f := s.Pcln.File[i]
+ for i := range s.FuncInfo.File {
+ f := s.FuncInfo.File[i]
if i := strings.Index(f.Name, "runtime/runtime.go"); i >= 0 {
gdbscript = f.Name[:i] + "runtime/runtime-gdb.py"
break
@@ -1386,23 +1364,23 @@ const (
OPCODE_BASE = 10
)
-func putpclcdelta(delta_pc int64, delta_lc int64) {
+func putpclcdelta(s *LSym, delta_pc int64, delta_lc int64) {
if LINE_BASE <= delta_lc && delta_lc < LINE_BASE+LINE_RANGE {
var opcode int64 = OPCODE_BASE + (delta_lc - LINE_BASE) + (LINE_RANGE * delta_pc)
if OPCODE_BASE <= opcode && opcode < 256 {
- Cput(uint8(opcode))
+ Adduint8(Ctxt, s, uint8(opcode))
return
}
}
if delta_pc != 0 {
- Cput(DW_LNS_advance_pc)
- sleb128put(delta_pc)
+ Adduint8(Ctxt, s, DW_LNS_advance_pc)
+ sleb128put(s, delta_pc)
}
- Cput(DW_LNS_advance_line)
- sleb128put(delta_lc)
- Cput(DW_LNS_copy)
+ Adduint8(Ctxt, s, DW_LNS_advance_line)
+ sleb128put(s, delta_lc)
+ Adduint8(Ctxt, s, DW_LNS_copy)
}
func newcfaoffsetattr(die *DWDie, offs int32) {
@@ -1428,26 +1406,6 @@ func mkvarname(name string, da int) string {
* Walk prog table, emit line program and build DIE tree.
*/
-// flush previous compilation unit.
-func flushunit(dwinfo *DWDie, pc int64, pcsym *LSym, unitstart int64, header_length int32) {
- if dwinfo != nil && pc != 0 {
- newattr(dwinfo, DW_AT_high_pc, DW_CLS_ADDRESS, pc+1, pcsym)
- }
-
- if unitstart >= 0 {
- Cput(0) // start extended opcode
- uleb128put(1)
- Cput(DW_LNE_end_sequence)
-
- here := Cpos()
- Cseek(unitstart)
- Thearch.Lput(uint32(here - unitstart - 4)) // unit_length
- Thearch.Wput(2) // dwarf version
- Thearch.Lput(uint32(header_length)) // header length starting here
- Cseek(here)
- }
-}
-
func getCompilationDir() string {
if dir, err := os.Getwd(); err == nil {
return dir
@@ -1455,28 +1413,30 @@ func getCompilationDir() string {
return "/"
}
-func writelines() {
+func writelines(prev *LSym) *LSym {
if linesec == nil {
- linesec = Linklookup(Ctxt, ".dwarfline", 0)
+ linesec = Linklookup(Ctxt, ".debug_line", 0)
}
+ linesec.Type = obj.SDWARFSECT
linesec.R = linesec.R[:0]
+ ls := linesec
+ prev.Next = ls
+
unitstart := int64(-1)
+ headerstart := int64(-1)
headerend := int64(-1)
epc := int64(0)
var epcs *LSym
- lineo = Cpos()
var dwinfo *DWDie
- flushunit(dwinfo, epc, epcs, unitstart, int32(headerend-unitstart-10))
- unitstart = Cpos()
lang := DW_LANG_Go
- s := Ctxt.Textp
+ s := Ctxt.Textp[0]
- dwinfo = newdie(&dwroot, DW_ABRV_COMPUNIT, "go")
+ dwinfo = newdie(&dwroot, DW_ABRV_COMPUNIT, "go", 0)
newattr(dwinfo, DW_AT_language, DW_CLS_CONSTANT, int64(lang), 0)
- newattr(dwinfo, DW_AT_stmt_list, DW_CLS_PTR, unitstart-lineo, 0)
+ newattr(dwinfo, DW_AT_stmt_list, DW_CLS_PTR, 0, 0)
newattr(dwinfo, DW_AT_low_pc, DW_CLS_ADDRESS, s.Value, s)
// OS X linker requires compilation dir or absolute path in comp unit name to output debug info.
compDir := getCompilationDir()
@@ -1484,61 +1444,62 @@ func writelines() {
// Write .debug_line Line Number Program Header (sec 6.2.4)
// Fields marked with (*) must be changed for 64-bit dwarf
- Thearch.Lput(0) // unit_length (*), will be filled in by flushunit.
- Thearch.Wput(2) // dwarf version (appendix F)
- Thearch.Lput(0) // header_length (*), filled in by flushunit.
+ unit_length_offset := ls.Size
+ Adduint32(Ctxt, ls, 0) // unit_length (*), filled in at end.
+ unitstart = ls.Size
+ Adduint16(Ctxt, ls, 2) // dwarf version (appendix F)
+ header_length_offset := ls.Size
+ Adduint32(Ctxt, ls, 0) // header_length (*), filled in at end.
+ headerstart = ls.Size
// cpos == unitstart + 4 + 2 + 4
- Cput(1) // minimum_instruction_length
- Cput(1) // default_is_stmt
- Cput(LINE_BASE & 0xFF) // line_base
- Cput(LINE_RANGE) // line_range
- Cput(OPCODE_BASE) // opcode_base
- Cput(0) // standard_opcode_lengths[1]
- Cput(1) // standard_opcode_lengths[2]
- Cput(1) // standard_opcode_lengths[3]
- Cput(1) // standard_opcode_lengths[4]
- Cput(1) // standard_opcode_lengths[5]
- Cput(0) // standard_opcode_lengths[6]
- Cput(0) // standard_opcode_lengths[7]
- Cput(0) // standard_opcode_lengths[8]
- Cput(1) // standard_opcode_lengths[9]
- Cput(0) // include_directories (empty)
-
- files := make([]*LSym, Ctxt.Nhistfile)
+ Adduint8(Ctxt, ls, 1) // minimum_instruction_length
+ Adduint8(Ctxt, ls, 1) // default_is_stmt
+ Adduint8(Ctxt, ls, LINE_BASE&0xFF) // line_base
+ Adduint8(Ctxt, ls, LINE_RANGE) // line_range
+ Adduint8(Ctxt, ls, OPCODE_BASE) // opcode_base
+ Adduint8(Ctxt, ls, 0) // standard_opcode_lengths[1]
+ Adduint8(Ctxt, ls, 1) // standard_opcode_lengths[2]
+ Adduint8(Ctxt, ls, 1) // standard_opcode_lengths[3]
+ Adduint8(Ctxt, ls, 1) // standard_opcode_lengths[4]
+ Adduint8(Ctxt, ls, 1) // standard_opcode_lengths[5]
+ Adduint8(Ctxt, ls, 0) // standard_opcode_lengths[6]
+ Adduint8(Ctxt, ls, 0) // standard_opcode_lengths[7]
+ Adduint8(Ctxt, ls, 0) // standard_opcode_lengths[8]
+ Adduint8(Ctxt, ls, 1) // standard_opcode_lengths[9]
+ Adduint8(Ctxt, ls, 0) // include_directories (empty)
- for f := Ctxt.Filesyms; f != nil; f = f.Next {
- files[f.Value-1] = f
- }
-
- for i := 0; int32(i) < Ctxt.Nhistfile; i++ {
- strnput(files[i].Name, len(files[i].Name)+4)
+ for _, f := range Ctxt.Filesyms {
+ Addstring(ls, f.Name)
+ Adduint8(Ctxt, ls, 0)
+ Adduint8(Ctxt, ls, 0)
+ Adduint8(Ctxt, ls, 0)
}
// 4 zeros: the string termination + 3 fields.
- Cput(0)
+ Adduint8(Ctxt, ls, 0)
// terminate file_names.
- headerend = Cpos()
+ headerend = ls.Size
- Cput(0) // start extended opcode
- uleb128put(1 + int64(Thearch.Ptrsize))
- Cput(DW_LNE_set_address)
+ Adduint8(Ctxt, ls, 0) // start extended opcode
+ uleb128put(ls, 1+int64(SysArch.PtrSize))
+ Adduint8(Ctxt, ls, DW_LNE_set_address)
pc := s.Value
line := 1
file := 1
if Linkmode == LinkExternal {
- adddwarfrel(linesec, s, lineo, Thearch.Ptrsize, 0)
+ Addaddr(Ctxt, ls, s)
} else {
- addrput(pc)
+ addrput(ls, pc)
}
var pcfile Pciter
var pcline Pciter
- for Ctxt.Cursym = Ctxt.Textp; Ctxt.Cursym != nil; Ctxt.Cursym = Ctxt.Cursym.Next {
- s = Ctxt.Cursym
+ for _, Ctxt.Cursym = range Ctxt.Textp {
+ s := Ctxt.Cursym
- dwfunc := newdie(dwinfo, DW_ABRV_FUNCTION, s.Name)
+ dwfunc := newdie(dwinfo, DW_ABRV_FUNCTION, s.Name, int(s.Version))
newattr(dwfunc, DW_AT_low_pc, DW_CLS_ADDRESS, s.Value, s)
epc = s.Value + s.Size
epcs = s
@@ -1547,14 +1508,14 @@ func writelines() {
newattr(dwfunc, DW_AT_external, DW_CLS_FLAG, 1, 0)
}
- if s.Pcln == nil {
+ if s.FuncInfo == nil {
continue
}
finddebugruntimepath(s)
- pciterinit(Ctxt, &pcfile, &s.Pcln.Pcfile)
- pciterinit(Ctxt, &pcline, &s.Pcln.Pcline)
+ pciterinit(Ctxt, &pcfile, &s.FuncInfo.Pcfile)
+ pciterinit(Ctxt, &pcline, &s.FuncInfo.Pcline)
epc = pc
for pcfile.done == 0 && pcline.done == 0 {
if epc-s.Value >= int64(pcfile.nextpc) {
@@ -1568,12 +1529,12 @@ func writelines() {
}
if int32(file) != pcfile.value {
- Cput(DW_LNS_set_file)
- uleb128put(int64(pcfile.value))
+ Adduint8(Ctxt, ls, DW_LNS_set_file)
+ uleb128put(ls, int64(pcfile.value))
file = int(pcfile.value)
}
- putpclcdelta(s.Value+int64(pcline.pc)-pc, int64(pcline.value)-int64(line))
+ putpclcdelta(ls, s.Value+int64(pcline.pc)-pc, int64(pcline.value)-int64(line))
pc = s.Value + int64(pcline.pc)
line = int(pcline.value)
@@ -1589,13 +1550,13 @@ func writelines() {
dt, da int
offs int64
)
- for _, a := range s.Autom {
+ for _, a := range s.FuncInfo.Autom {
switch a.Name {
case obj.A_AUTO:
dt = DW_ABRV_AUTO
offs = int64(a.Aoffset)
if !haslinkregister() {
- offs -= int64(Thearch.Ptrsize)
+ offs -= int64(SysArch.PtrSize)
}
case obj.A_PARAM:
@@ -1610,7 +1571,7 @@ func writelines() {
continue
}
var n string
- if find(dwfunc, a.Asym.Name) != nil {
+ if findchild(dwfunc, a.Asym.Name) != nil {
n = mkvarname(a.Asym.Name, da)
} else {
n = a.Asym.Name
@@ -1621,7 +1582,7 @@ func writelines() {
n = n[i+1:]
}
- dwvar := newdie(dwfunc, dt, n)
+ dwvar := newdie(dwfunc, dt, n, 0)
newcfaoffsetattr(dwvar, int32(offs))
newrefattr(dwvar, DW_AT_type, defgotype(a.Gotype))
@@ -1642,22 +1603,29 @@ func writelines() {
}
}
- flushunit(dwinfo, epc, epcs, unitstart, int32(headerend-unitstart-10))
- linesize = Cpos() - lineo
+ Adduint8(Ctxt, ls, 0) // start extended opcode
+ uleb128put(ls, 1)
+ Adduint8(Ctxt, ls, DW_LNE_end_sequence)
+
+ newattr(dwinfo, DW_AT_high_pc, DW_CLS_ADDRESS, epc+1, epcs)
+
+ setuint32(Ctxt, ls, unit_length_offset, uint32(ls.Size-unitstart))
+ setuint32(Ctxt, ls, header_length_offset, uint32(headerend-headerstart))
+
+ return ls
}
/*
* Emit .debug_frame
*/
const (
- CIERESERVE = 16
- DATAALIGNMENTFACTOR = -4
+ dataAlignmentFactor = -4
)
// appendPCDeltaCFA appends per-PC CFA deltas to b and returns the final slice.
func appendPCDeltaCFA(b []byte, deltapc, cfa int64) []byte {
b = append(b, DW_CFA_def_cfa_offset_sf)
- b = appendSleb128(b, cfa/DATAALIGNMENTFACTOR)
+ b = appendSleb128(b, cfa/dataAlignmentFactor)
switch {
case deltapc < 0x40:
@@ -1675,60 +1643,68 @@ func appendPCDeltaCFA(b []byte, deltapc, cfa int64) []byte {
return b
}
-func writeframes() {
+func writeframes(prev *LSym) *LSym {
if framesec == nil {
- framesec = Linklookup(Ctxt, ".dwarfframe", 0)
+ framesec = Linklookup(Ctxt, ".debug_frame", 0)
}
+ framesec.Type = obj.SDWARFSECT
framesec.R = framesec.R[:0]
- frameo = Cpos()
+ fs := framesec
+ prev.Next = fs
// Emit the CIE, Section 6.4.1
- Thearch.Lput(CIERESERVE) // initial length, must be multiple of thearch.ptrsize
- Thearch.Lput(0xffffffff) // cid.
- Cput(3) // dwarf version (appendix F)
- Cput(0) // augmentation ""
- uleb128put(1) // code_alignment_factor
- sleb128put(DATAALIGNMENTFACTOR) // guess
- uleb128put(int64(Thearch.Dwarfreglr)) // return_address_register
-
- Cput(DW_CFA_def_cfa)
-
- uleb128put(int64(Thearch.Dwarfregsp)) // register SP (**ABI-dependent, defined in l.h)
+ cieReserve := uint32(16)
if haslinkregister() {
- uleb128put(int64(0)) // offset
- } else {
- uleb128put(int64(Thearch.Ptrsize)) // offset
+ cieReserve = 32
}
+ Adduint32(Ctxt, fs, cieReserve) // initial length, must be multiple of pointer size
+ Adduint32(Ctxt, fs, 0xffffffff) // cid.
+ Adduint8(Ctxt, fs, 3) // dwarf version (appendix F)
+ Adduint8(Ctxt, fs, 0) // augmentation ""
+ uleb128put(fs, 1) // code_alignment_factor
+ sleb128put(fs, dataAlignmentFactor) // all CFI offset calculations include multiplication with this factor
+ uleb128put(fs, int64(Thearch.Dwarfreglr)) // return_address_register
- Cput(DW_CFA_offset_extended)
- uleb128put(int64(Thearch.Dwarfreglr)) // return address
+ Adduint8(Ctxt, fs, DW_CFA_def_cfa) // Set the current frame address..
+ uleb128put(fs, int64(Thearch.Dwarfregsp)) // ...to use the value in the platform's SP register (defined in l.go)...
if haslinkregister() {
- uleb128put(int64(0) / DATAALIGNMENTFACTOR) // at cfa - 0
+ uleb128put(fs, int64(0)) // ...plus a 0 offset.
+
+ Adduint8(Ctxt, fs, DW_CFA_same_value) // The platform's link register is unchanged during the prologue.
+ uleb128put(fs, int64(Thearch.Dwarfreglr))
+
+ Adduint8(Ctxt, fs, DW_CFA_val_offset) // The previous value...
+ uleb128put(fs, int64(Thearch.Dwarfregsp)) // ...of the platform's SP register...
+ uleb128put(fs, int64(0)) // ...is CFA+0.
} else {
- uleb128put(int64(-Thearch.Ptrsize) / DATAALIGNMENTFACTOR) // at cfa - x*4
+ uleb128put(fs, int64(SysArch.PtrSize)) // ...plus the word size (because the call instruction implicitly adds one word to the frame).
+
+ Adduint8(Ctxt, fs, DW_CFA_offset_extended) // The previous value...
+ uleb128put(fs, int64(Thearch.Dwarfreglr)) // ...of the return address...
+ uleb128put(fs, int64(-SysArch.PtrSize)/dataAlignmentFactor) // ...is saved at [CFA - (PtrSize/4)].
}
// 4 is to exclude the length field.
- pad := CIERESERVE + frameo + 4 - Cpos()
+ pad := int64(cieReserve) + 4 - fs.Size
if pad < 0 {
- Exitf("dwarf: CIERESERVE too small by %d bytes.", -pad)
+ Exitf("dwarf: cieReserve too small by %d bytes.", -pad)
}
- strnput("", int(pad))
+ Addbytes(Ctxt, fs, zeros[:pad])
var deltaBuf []byte
var pcsp Pciter
- for Ctxt.Cursym = Ctxt.Textp; Ctxt.Cursym != nil; Ctxt.Cursym = Ctxt.Cursym.Next {
+ for _, Ctxt.Cursym = range Ctxt.Textp {
s := Ctxt.Cursym
- if s.Pcln == nil {
+ if s.FuncInfo == nil {
continue
}
// Emit a FDE, Section 6.4.1.
// First build the section contents into a byte buffer.
deltaBuf = deltaBuf[:0]
- for pciterinit(Ctxt, &pcsp, &s.Pcln.Pcsp); pcsp.done == 0; pciternext(&pcsp) {
+ for pciterinit(Ctxt, &pcsp, &s.FuncInfo.Pcsp); pcsp.done == 0; pciternext(&pcsp) {
nextpc := pcsp.nextpc
// pciterinit goes up to the end of the function,
@@ -1741,12 +1717,27 @@ func writeframes() {
}
if haslinkregister() {
+ // TODO(bryanpkc): This is imprecise. In general, the instruction
+ // that stores the return address to the stack frame is not the
+ // same one that allocates the frame.
+ if pcsp.value > 0 {
+ // The return address is preserved at (CFA-frame_size)
+ // after a stack frame has been allocated.
+ deltaBuf = append(deltaBuf, DW_CFA_offset_extended_sf)
+ deltaBuf = appendUleb128(deltaBuf, uint64(Thearch.Dwarfreglr))
+ deltaBuf = appendSleb128(deltaBuf, -int64(pcsp.value)/dataAlignmentFactor)
+ } else {
+ // The return address is restored into the link register
+ // when a stack frame has been de-allocated.
+ deltaBuf = append(deltaBuf, DW_CFA_same_value)
+ deltaBuf = appendUleb128(deltaBuf, uint64(Thearch.Dwarfreglr))
+ }
deltaBuf = appendPCDeltaCFA(deltaBuf, int64(nextpc)-int64(pcsp.pc), int64(pcsp.value))
} else {
- deltaBuf = appendPCDeltaCFA(deltaBuf, int64(nextpc)-int64(pcsp.pc), int64(Thearch.Ptrsize)+int64(pcsp.value))
+ deltaBuf = appendPCDeltaCFA(deltaBuf, int64(nextpc)-int64(pcsp.pc), int64(SysArch.PtrSize)+int64(pcsp.value))
}
}
- pad := int(Rnd(int64(len(deltaBuf)), int64(Thearch.Ptrsize))) - len(deltaBuf)
+ pad := int(Rnd(int64(len(deltaBuf)), int64(SysArch.PtrSize))) - len(deltaBuf)
deltaBuf = append(deltaBuf, zeros[:pad]...)
// Emit the FDE header, Section 6.4.1.
@@ -1754,21 +1745,17 @@ func writeframes() {
// 4 bytes: Pointer to the CIE above, at offset 0
// ptrsize: initial location
// ptrsize: address range
- Thearch.Lput(uint32(4 + 2*Thearch.Ptrsize + len(deltaBuf))) // length (excludes itself)
+ Adduint32(Ctxt, fs, uint32(4+2*SysArch.PtrSize+len(deltaBuf))) // length (excludes itself)
if Linkmode == LinkExternal {
- adddwarfrel(framesec, framesym, frameo, 4, 0) // CIE offset
- adddwarfrel(framesec, s, frameo, Thearch.Ptrsize, 0) // initial location
+ adddwarfref(Ctxt, fs, framesec, 4)
} else {
- Thearch.Lput(0) // CIE offset
- addrput(s.Value) // initial location
+ Adduint32(Ctxt, fs, 0) // CIE offset
}
- addrput(s.Size) // address range
-
- Cwrite(deltaBuf)
+ Addaddr(Ctxt, fs, s)
+ addrput(fs, s.Size) // address range
+ Addbytes(Ctxt, fs, deltaBuf)
}
-
- Cflush()
- framesize = Cpos() - frameo
+ return fs
}
/*
@@ -1778,12 +1765,14 @@ const (
COMPUNITHEADERSIZE = 4 + 2 + 4 + 1
)
-func writeinfo() {
- fwdcount = 0
+func writeinfo(prev *LSym) *LSym {
if infosec == nil {
- infosec = Linklookup(Ctxt, ".dwarfinfo", 0)
+ infosec = Linklookup(Ctxt, ".debug_info", 0)
}
infosec.R = infosec.R[:0]
+ infosec.Type = obj.SDWARFINFO
+ infosec.Attr |= AttrReachable
+ prev.Next, prev = infosec, infosec
if arangessec == nil {
arangessec = Linklookup(Ctxt, ".dwarfaranges", 0)
@@ -1791,32 +1780,30 @@ func writeinfo() {
arangessec.R = arangessec.R[:0]
for compunit := dwroot.child; compunit != nil; compunit = compunit.link {
- unitstart := Cpos()
+ s := compunit.sym
+ prev.Next, prev = s, s
// Write .debug_info Compilation Unit Header (sec 7.5.1)
// Fields marked with (*) must be changed for 64-bit dwarf
// This must match COMPUNITHEADERSIZE above.
- Thearch.Lput(0) // unit_length (*), will be filled in later.
- Thearch.Wput(2) // dwarf version (appendix F)
+ Adduint32(Ctxt, s, 0) // unit_length (*), will be filled in later.
+ Adduint16(Ctxt, s, 2) // dwarf version (appendix F)
// debug_abbrev_offset (*)
- if Linkmode == LinkExternal {
- adddwarfrel(infosec, abbrevsym, infoo, 4, 0)
- } else {
- Thearch.Lput(0)
- }
+ adddwarfref(Ctxt, s, abbrevsym, 4)
- Cput(uint8(Thearch.Ptrsize)) // address_size
+ Adduint8(Ctxt, s, uint8(SysArch.PtrSize)) // address_size
- putdie(compunit)
+ prev = putdie(prev, compunit)
+ cusize := s.Size - 4 // exclude the length field.
+ for child := s.Next; child != nil; child = child.Next {
+ cusize += child.Size
+ }
- here := Cpos()
- Cseek(unitstart)
- Thearch.Lput(uint32(here - unitstart - 4)) // exclude the length field.
- Cseek(here)
+ setuint32(Ctxt, s, 0, uint32(cusize))
+ newattr(compunit, DW_AT_byte_size, DW_CLS_CONSTANT, cusize, 0)
}
-
- Cflush()
+ return prev
}
/*
@@ -1837,51 +1824,52 @@ func ispubtype(die *DWDie) bool {
return die.abbrev >= DW_ABRV_NULLTYPE
}
-func writepub(ispub func(*DWDie) bool) int64 {
- sectionstart := Cpos()
+func writepub(sname string, ispub func(*DWDie) bool, prev *LSym) *LSym {
+ s := Linklookup(Ctxt, sname, 0)
+ s.Type = obj.SDWARFSECT
+ prev.Next = s
for compunit := dwroot.child; compunit != nil; compunit = compunit.link {
- unitend := infoo + infosize
- unitstart := compunit.offs - COMPUNITHEADERSIZE
- if compunit.link != nil {
- unitend = compunit.link.offs - COMPUNITHEADERSIZE
- }
+ sectionstart := s.Size
+ culength := uint32(getattr(compunit, DW_AT_byte_size).value) + 4
// Write .debug_pubnames/types Header (sec 6.1.1)
- Thearch.Lput(0) // unit_length (*), will be filled in later.
- Thearch.Wput(2) // dwarf version (appendix F)
- Thearch.Lput(uint32(unitstart)) // debug_info_offset (of the Comp unit Header)
- Thearch.Lput(uint32(unitend - unitstart)) // debug_info_length
+ Adduint32(Ctxt, s, 0) // unit_length (*), will be filled in later.
+ Adduint16(Ctxt, s, 2) // dwarf version (appendix F)
+ adddwarfref(Ctxt, s, compunit.sym, 4) // debug_info_offset (of the Comp unit Header)
+ Adduint32(Ctxt, s, culength) // debug_info_length
for die := compunit.child; die != nil; die = die.link {
if !ispub(die) {
continue
}
- Thearch.Lput(uint32(die.offs - unitstart))
dwa := getattr(die, DW_AT_name)
- strnput(dwa.data.(string), int(dwa.value+1))
+ name := dwa.data.(string)
+ if die.sym == nil {
+ fmt.Println("Missing sym for ", name)
+ }
+ adddwarfref(Ctxt, s, die.sym, 4)
+ Addstring(s, name)
}
- Thearch.Lput(0)
+ Adduint32(Ctxt, s, 0)
- here := Cpos()
- Cseek(sectionstart)
- Thearch.Lput(uint32(here - sectionstart - 4)) // exclude the length field.
- Cseek(here)
+ setuint32(Ctxt, s, sectionstart, uint32(s.Size-sectionstart)-4) // exclude the length field.
}
- return sectionstart
+ return s
}
/*
* emit .debug_aranges. _info must have been written before,
* because we need die->offs of dw_globals.
*/
-func writearanges() int64 {
- sectionstart := Cpos()
+func writearanges(prev *LSym) *LSym {
+ s := Linklookup(Ctxt, ".debug_aranges", 0)
+ s.Type = obj.SDWARFSECT
// The first tuple is aligned to a multiple of the size of a single tuple
// (twice the size of an address)
- headersize := int(Rnd(4+2+4+1+1, int64(Thearch.Ptrsize*2))) // don't count unit_length field itself
+ headersize := int(Rnd(4+2+4+1+1, int64(SysArch.PtrSize*2))) // don't count unit_length field itself
for compunit := dwroot.child; compunit != nil; compunit = compunit.link {
b := getattr(compunit, DW_AT_low_pc)
@@ -1894,78 +1882,46 @@ func writearanges() int64 {
}
// Write .debug_aranges Header + entry (sec 6.1.2)
- Thearch.Lput(uint32(headersize) + 4*uint32(Thearch.Ptrsize) - 4) // unit_length (*)
- Thearch.Wput(2) // dwarf version (appendix F)
+ unitlength := uint32(headersize) + 4*uint32(SysArch.PtrSize) - 4
+ Adduint32(Ctxt, s, unitlength) // unit_length (*)
+ Adduint16(Ctxt, s, 2) // dwarf version (appendix F)
- value := compunit.offs - COMPUNITHEADERSIZE // debug_info_offset
- if Linkmode == LinkExternal {
- adddwarfrel(arangessec, infosym, sectionstart, 4, value)
- } else {
- Thearch.Lput(uint32(value))
- }
+ adddwarfref(Ctxt, s, compunit.sym, 4)
- Cput(uint8(Thearch.Ptrsize)) // address_size
- Cput(0) // segment_size
- strnput("", headersize-(4+2+4+1+1)) // align to thearch.ptrsize
-
- if Linkmode == LinkExternal {
- adddwarfrel(arangessec, b.data.(*LSym), sectionstart, Thearch.Ptrsize, b.value-(b.data.(*LSym)).Value)
- } else {
- addrput(b.value)
+ Adduint8(Ctxt, s, uint8(SysArch.PtrSize)) // address_size
+ Adduint8(Ctxt, s, 0) // segment_size
+ padding := headersize - (4 + 2 + 4 + 1 + 1)
+ for i := 0; i < padding; i++ {
+ Adduint8(Ctxt, s, 0)
}
- addrput(e.value - b.value)
- addrput(0)
- addrput(0)
+ Addaddrplus(Ctxt, s, b.data.(*LSym), b.value-(b.data.(*LSym)).Value)
+ addrput(s, e.value-b.value)
+ addrput(s, 0)
+ addrput(s, 0)
}
-
- Cflush()
- return sectionstart
-}
-
-func writegdbscript() int64 {
- sectionstart := Cpos()
-
- if gdbscript != "" {
- Cput(1) // magic 1 byte?
- strnput(gdbscript, len(gdbscript)+1)
- Cflush()
+ if s.Size > 0 {
+ prev.Next = s
+ prev = s
}
-
- return sectionstart
+ return prev
}
-func align(size int64) {
- if HEADTYPE == obj.Hwindows { // Only Windows PE need section align.
- strnput("", int(Rnd(size, PEFILEALIGN)-size))
- }
-}
+func writegdbscript(prev *LSym) *LSym {
-func writedwarfreloc(s *LSym) int64 {
- start := Cpos()
- for ri := 0; ri < len(s.R); ri++ {
- r := &s.R[ri]
- i := -1
- if Iself {
- i = Thearch.Elfreloc1(r, int64(r.Off))
- } else if HEADTYPE == obj.Hdarwin {
- i = Thearch.Machoreloc1(r, int64(r.Off))
- }
- if i < 0 {
- Diag("unsupported obj reloc %d/%d to %s", r.Type, r.Siz, r.Sym.Name)
- }
+ if gdbscript != "" {
+ s := Linklookup(Ctxt, ".debug_gdb_scripts", 0)
+ s.Type = obj.SDWARFSECT
+ prev.Next = s
+ prev = s
+ Adduint8(Ctxt, s, 1) // magic 1 byte?
+ Addstring(s, gdbscript)
}
- return start
+ return prev
}
-func addmachodwarfsect(prev *Section, name string) *Section {
- sect := addsection(&Segdwarf, name, 04)
- sect.Extnum = prev.Extnum + 1
- sym := Linklookup(Ctxt, name, 0)
- sym.Sect = sect
- return sect
-}
+var prototypedies map[string]*DWDie
/*
* This is the main entry point for generating dwarf. After emitting
@@ -1976,58 +1932,52 @@ func addmachodwarfsect(prev *Section, name string) *Section {
* passes.
*
*/
-func Dwarfemitdebugsections() {
+func dwarfgeneratedebugsyms() {
if Debug['w'] != 0 { // disable dwarf
return
}
+ if Debug['s'] != 0 && HEADTYPE != obj.Hdarwin {
+ return
+ }
+ if HEADTYPE == obj.Hplan9 {
+ return
+ }
if Linkmode == LinkExternal {
if !Iself && HEADTYPE != obj.Hdarwin {
return
}
- if HEADTYPE == obj.Hdarwin {
- sect := Segdata.Sect
- // find the last section.
- for sect.Next != nil {
- sect = sect.Next
- }
- sect = addmachodwarfsect(sect, ".debug_abbrev")
- sect = addmachodwarfsect(sect, ".debug_line")
- sect = addmachodwarfsect(sect, ".debug_frame")
- sect = addmachodwarfsect(sect, ".debug_info")
-
- infosym = Linklookup(Ctxt, ".debug_info", 0)
- infosym.Attr |= AttrHidden
-
- abbrevsym = Linklookup(Ctxt, ".debug_abbrev", 0)
- abbrevsym.Attr |= AttrHidden
-
- linesym = Linklookup(Ctxt, ".debug_line", 0)
- linesym.Attr |= AttrHidden
+ }
- framesym = Linklookup(Ctxt, ".debug_frame", 0)
- framesym.Attr |= AttrHidden
- }
+ if Debug['v'] != 0 {
+ fmt.Fprintf(Bso, "%5.2f dwarf\n", obj.Cputime())
}
// For diagnostic messages.
newattr(&dwtypes, DW_AT_name, DW_CLS_STRING, int64(len("dwtypes")), "dwtypes")
- mkindex(&dwroot)
- mkindex(&dwtypes)
- mkindex(&dwglobals)
-
// Some types that must exist to define other ones.
- newdie(&dwtypes, DW_ABRV_NULLTYPE, "<unspecified>")
+ newdie(&dwtypes, DW_ABRV_NULLTYPE, "<unspecified>", 0)
- newdie(&dwtypes, DW_ABRV_NULLTYPE, "void")
- newdie(&dwtypes, DW_ABRV_BARE_PTRTYPE, "unsafe.Pointer")
+ newdie(&dwtypes, DW_ABRV_NULLTYPE, "void", 0)
+ newdie(&dwtypes, DW_ABRV_BARE_PTRTYPE, "unsafe.Pointer", 0)
- die := newdie(&dwtypes, DW_ABRV_BASETYPE, "uintptr") // needed for array size
+ die := newdie(&dwtypes, DW_ABRV_BASETYPE, "uintptr", 0) // needed for array size
newattr(die, DW_AT_encoding, DW_CLS_CONSTANT, DW_ATE_unsigned, 0)
- newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, int64(Thearch.Ptrsize), 0)
+ newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, int64(SysArch.PtrSize), 0)
newattr(die, DW_AT_go_kind, DW_CLS_CONSTANT, obj.KindUintptr, 0)
+ // Prototypes needed for type synthesis.
+ prototypedies = map[string]*DWDie{
+ "type.runtime.stringStructDWARF": nil,
+ "type.runtime.slice": nil,
+ "type.runtime.hmap": nil,
+ "type.runtime.bmap": nil,
+ "type.runtime.sudog": nil,
+ "type.runtime.waitq": nil,
+ "type.runtime.hchan": nil,
+ }
+
// Needed by the prettyprinter code for interface inspection.
defgotype(lookup_or_diag("type.runtime._type"))
@@ -2036,12 +1986,10 @@ func Dwarfemitdebugsections() {
genasmsym(defdwsymb)
- writeabbrev()
- align(abbrevsize)
- writelines()
- align(linesize)
- writeframes()
- align(framesize)
+ dwarfp = writeabbrev()
+ last := dwarfp
+ last = writelines(last)
+ last = writeframes(last)
synthesizestringtypes(dwtypes.child)
synthesizeslicetypes(dwtypes.child)
@@ -2055,412 +2003,61 @@ func Dwarfemitdebugsections() {
movetomodule(&dwtypes)
movetomodule(&dwglobals)
- infoo = Cpos()
- writeinfo()
- infoe := Cpos()
- pubnameso = infoe
- pubtypeso = infoe
- arangeso = infoe
- gdbscripto = infoe
-
- if fwdcount > 0 {
- if Debug['v'] != 0 {
- fmt.Fprintf(&Bso, "%5.2f dwarf pass 2.\n", obj.Cputime())
- }
- Cseek(infoo)
- writeinfo()
- if fwdcount > 0 {
- Exitf("dwarf: unresolved references after first dwarf info pass")
- }
-
- if infoe != Cpos() {
- Exitf("dwarf: inconsistent second dwarf info pass")
- }
- }
-
- infosize = infoe - infoo
- align(infosize)
-
- pubnameso = writepub(ispubname)
- pubnamessize = Cpos() - pubnameso
- align(pubnamessize)
-
- pubtypeso = writepub(ispubtype)
- pubtypessize = Cpos() - pubtypeso
- align(pubtypessize)
-
- arangeso = writearanges()
- arangessize = Cpos() - arangeso
- align(arangessize)
-
- gdbscripto = writegdbscript()
- gdbscriptsize = Cpos() - gdbscripto
- align(gdbscriptsize)
+ // Need to reorder symbols so SDWARFINFO is after all SDWARFSECT
+ // (but we need to generate dies before writepub)
+ writeinfo(last)
+ infosyms := last.Next
- for Cpos()&7 != 0 {
- Cput(0)
- }
- if HEADTYPE != obj.Hdarwin {
- dwarfemitreloc()
- }
-}
-
-func dwarfemitreloc() {
- if Debug['w'] != 0 { // disable dwarf
- return
- }
- inforeloco = writedwarfreloc(infosec)
- inforelocsize = Cpos() - inforeloco
- align(inforelocsize)
-
- arangesreloco = writedwarfreloc(arangessec)
- arangesrelocsize = Cpos() - arangesreloco
- align(arangesrelocsize)
-
- linereloco = writedwarfreloc(linesec)
- linerelocsize = Cpos() - linereloco
- align(linerelocsize)
-
- framereloco = writedwarfreloc(framesec)
- framerelocsize = Cpos() - framereloco
- align(framerelocsize)
+ last = writepub(".debug_pubnames", ispubname, last)
+ last = writepub(".debug_pubtypes", ispubtype, last)
+ last = writearanges(last)
+ last = writegdbscript(last)
+ last.Next = infosyms
}
/*
* Elf.
*/
-const (
- ElfStrDebugAbbrev = iota
- ElfStrDebugAranges
- ElfStrDebugFrame
- ElfStrDebugInfo
- ElfStrDebugLine
- ElfStrDebugLoc
- ElfStrDebugMacinfo
- ElfStrDebugPubNames
- ElfStrDebugPubTypes
- ElfStrDebugRanges
- ElfStrDebugStr
- ElfStrGDBScripts
- ElfStrRelDebugInfo
- ElfStrRelDebugAranges
- ElfStrRelDebugLine
- ElfStrRelDebugFrame
- NElfStrDbg
-)
-
-var elfstrdbg [NElfStrDbg]int64
-
func dwarfaddshstrings(shstrtab *LSym) {
if Debug['w'] != 0 { // disable dwarf
return
}
- elfstrdbg[ElfStrDebugAbbrev] = Addstring(shstrtab, ".debug_abbrev")
- elfstrdbg[ElfStrDebugAranges] = Addstring(shstrtab, ".debug_aranges")
- elfstrdbg[ElfStrDebugFrame] = Addstring(shstrtab, ".debug_frame")
- elfstrdbg[ElfStrDebugInfo] = Addstring(shstrtab, ".debug_info")
- elfstrdbg[ElfStrDebugLine] = Addstring(shstrtab, ".debug_line")
- elfstrdbg[ElfStrDebugLoc] = Addstring(shstrtab, ".debug_loc")
- elfstrdbg[ElfStrDebugMacinfo] = Addstring(shstrtab, ".debug_macinfo")
- elfstrdbg[ElfStrDebugPubNames] = Addstring(shstrtab, ".debug_pubnames")
- elfstrdbg[ElfStrDebugPubTypes] = Addstring(shstrtab, ".debug_pubtypes")
- elfstrdbg[ElfStrDebugRanges] = Addstring(shstrtab, ".debug_ranges")
- elfstrdbg[ElfStrDebugStr] = Addstring(shstrtab, ".debug_str")
- elfstrdbg[ElfStrGDBScripts] = Addstring(shstrtab, ".debug_gdb_scripts")
+ Addstring(shstrtab, ".debug_abbrev")
+ Addstring(shstrtab, ".debug_aranges")
+ Addstring(shstrtab, ".debug_frame")
+ Addstring(shstrtab, ".debug_info")
+ Addstring(shstrtab, ".debug_line")
+ Addstring(shstrtab, ".debug_pubnames")
+ Addstring(shstrtab, ".debug_pubtypes")
+ Addstring(shstrtab, ".debug_gdb_scripts")
if Linkmode == LinkExternal {
- switch Thearch.Thechar {
- case '0', '6', '7', '9', 'z':
- elfstrdbg[ElfStrRelDebugInfo] = Addstring(shstrtab, ".rela.debug_info")
- elfstrdbg[ElfStrRelDebugAranges] = Addstring(shstrtab, ".rela.debug_aranges")
- elfstrdbg[ElfStrRelDebugLine] = Addstring(shstrtab, ".rela.debug_line")
- elfstrdbg[ElfStrRelDebugFrame] = Addstring(shstrtab, ".rela.debug_frame")
- default:
- elfstrdbg[ElfStrRelDebugInfo] = Addstring(shstrtab, ".rel.debug_info")
- elfstrdbg[ElfStrRelDebugAranges] = Addstring(shstrtab, ".rel.debug_aranges")
- elfstrdbg[ElfStrRelDebugLine] = Addstring(shstrtab, ".rel.debug_line")
- elfstrdbg[ElfStrRelDebugFrame] = Addstring(shstrtab, ".rel.debug_frame")
- }
-
- infosym = Linklookup(Ctxt, ".debug_info", 0)
- infosym.Attr |= AttrHidden
-
- abbrevsym = Linklookup(Ctxt, ".debug_abbrev", 0)
- abbrevsym.Attr |= AttrHidden
-
- linesym = Linklookup(Ctxt, ".debug_line", 0)
- linesym.Attr |= AttrHidden
-
- framesym = Linklookup(Ctxt, ".debug_frame", 0)
- framesym.Attr |= AttrHidden
+ Addstring(shstrtab, elfRelType+".debug_info")
+ Addstring(shstrtab, elfRelType+".debug_aranges")
+ Addstring(shstrtab, elfRelType+".debug_line")
+ Addstring(shstrtab, elfRelType+".debug_frame")
+ Addstring(shstrtab, elfRelType+".debug_pubnames")
+ Addstring(shstrtab, elfRelType+".debug_pubtypes")
}
}
-// Add section symbols for DWARF debug info. This is called before
+// Add section symbols for DWARF debug info. This is called before
// dwarfaddelfheaders.
func dwarfaddelfsectionsyms() {
- if infosym != nil {
- infosympos = Cpos()
- putelfsectionsym(infosym, 0)
- }
-
- if abbrevsym != nil {
- abbrevsympos = Cpos()
- putelfsectionsym(abbrevsym, 0)
- }
-
- if linesym != nil {
- linesympos = Cpos()
- putelfsectionsym(linesym, 0)
- }
-
- if framesym != nil {
- framesympos = Cpos()
- putelfsectionsym(framesym, 0)
- }
-}
-
-func dwarfaddelfrelocheader(elfstr int, shdata *ElfShdr, off int64, size int64) {
- sh := newElfShdr(elfstrdbg[elfstr])
- switch Thearch.Thechar {
- case '0', '6', '7', '9', 'z':
- sh.type_ = SHT_RELA
- default:
- sh.type_ = SHT_REL
- }
-
- sh.entsize = uint64(Thearch.Ptrsize) * 2
- if sh.type_ == SHT_RELA {
- sh.entsize += uint64(Thearch.Ptrsize)
- }
- sh.link = uint32(elfshname(".symtab").shnum)
- sh.info = uint32(shdata.shnum)
- sh.off = uint64(off)
- sh.size = uint64(size)
- sh.addralign = uint64(Thearch.Ptrsize)
-}
-
-func dwarfaddelfheaders() {
- if Debug['w'] != 0 { // disable dwarf
- return
- }
-
- sh := newElfShdr(elfstrdbg[ElfStrDebugAbbrev])
- sh.type_ = SHT_PROGBITS
- sh.off = uint64(abbrevo)
- sh.size = uint64(abbrevsize)
- sh.addralign = 1
- if abbrevsympos > 0 {
- putelfsymshndx(abbrevsympos, sh.shnum)
- }
-
- sh = newElfShdr(elfstrdbg[ElfStrDebugLine])
- sh.type_ = SHT_PROGBITS
- sh.off = uint64(lineo)
- sh.size = uint64(linesize)
- sh.addralign = 1
- if linesympos > 0 {
- putelfsymshndx(linesympos, sh.shnum)
- }
- shline := sh
-
- sh = newElfShdr(elfstrdbg[ElfStrDebugFrame])
- sh.type_ = SHT_PROGBITS
- sh.off = uint64(frameo)
- sh.size = uint64(framesize)
- sh.addralign = 1
- if framesympos > 0 {
- putelfsymshndx(framesympos, sh.shnum)
- }
- shframe := sh
-
- sh = newElfShdr(elfstrdbg[ElfStrDebugInfo])
- sh.type_ = SHT_PROGBITS
- sh.off = uint64(infoo)
- sh.size = uint64(infosize)
- sh.addralign = 1
- if infosympos > 0 {
- putelfsymshndx(infosympos, sh.shnum)
- }
- shinfo := sh
-
- if pubnamessize > 0 {
- sh := newElfShdr(elfstrdbg[ElfStrDebugPubNames])
- sh.type_ = SHT_PROGBITS
- sh.off = uint64(pubnameso)
- sh.size = uint64(pubnamessize)
- sh.addralign = 1
- }
-
- if pubtypessize > 0 {
- sh := newElfShdr(elfstrdbg[ElfStrDebugPubTypes])
- sh.type_ = SHT_PROGBITS
- sh.off = uint64(pubtypeso)
- sh.size = uint64(pubtypessize)
- sh.addralign = 1
- }
-
- var sharanges *ElfShdr
- if arangessize != 0 {
- sh := newElfShdr(elfstrdbg[ElfStrDebugAranges])
- sh.type_ = SHT_PROGBITS
- sh.off = uint64(arangeso)
- sh.size = uint64(arangessize)
- sh.addralign = 1
- sharanges = sh
- }
-
- if gdbscriptsize != 0 {
- sh := newElfShdr(elfstrdbg[ElfStrGDBScripts])
- sh.type_ = SHT_PROGBITS
- sh.off = uint64(gdbscripto)
- sh.size = uint64(gdbscriptsize)
- sh.addralign = 1
- }
-
- if inforelocsize != 0 {
- dwarfaddelfrelocheader(ElfStrRelDebugInfo, shinfo, inforeloco, inforelocsize)
- }
-
- if arangesrelocsize != 0 {
- dwarfaddelfrelocheader(ElfStrRelDebugAranges, sharanges, arangesreloco, arangesrelocsize)
- }
-
- if linerelocsize != 0 {
- dwarfaddelfrelocheader(ElfStrRelDebugLine, shline, linereloco, linerelocsize)
- }
-
- if framerelocsize != 0 {
- dwarfaddelfrelocheader(ElfStrRelDebugFrame, shframe, framereloco, framerelocsize)
- }
-}
-
-/*
- * Macho
- */
-func dwarfaddmachoheaders(ms *MachoSeg) {
if Debug['w'] != 0 { // disable dwarf
return
}
-
- // Zero vsize segments won't be loaded in memory, even so they
- // have to be page aligned in the file.
- fakestart := Rnd(int64(Segdwarf.Fileoff), 0x1000)
- addr := Segdata.Vaddr + Segdata.Length
-
- nsect := 4
- if pubnamessize > 0 {
- nsect++
- }
- if pubtypessize > 0 {
- nsect++
- }
- if arangessize > 0 {
- nsect++
- }
- if gdbscriptsize > 0 {
- nsect++
- }
-
if Linkmode != LinkExternal {
- ms = newMachoSeg("__DWARF", nsect)
- ms.fileoffset = uint64(fakestart)
- ms.filesize = Segdwarf.Filelen
- ms.vaddr = addr
- }
-
- msect := newMachoSect(ms, "__debug_abbrev", "__DWARF")
- msect.off = uint32(abbrevo)
- msect.size = uint64(abbrevsize)
- msect.addr = addr
- addr += msect.size
- msect.flag = 0x02000000
- if abbrevsym != nil {
- abbrevsym.Value = int64(msect.addr)
- }
-
- msect = newMachoSect(ms, "__debug_line", "__DWARF")
- msect.off = uint32(lineo)
- msect.size = uint64(linesize)
- msect.addr = addr
- addr += msect.size
- msect.flag = 0x02000000
- if linesym != nil {
- linesym.Value = int64(msect.addr)
- }
- if linerelocsize > 0 {
- msect.nreloc = uint32(len(linesec.R))
- msect.reloc = uint32(linereloco)
- }
-
- msect = newMachoSect(ms, "__debug_frame", "__DWARF")
- msect.off = uint32(frameo)
- msect.size = uint64(framesize)
- msect.addr = addr
- addr += msect.size
- msect.flag = 0x02000000
- if framesym != nil {
- framesym.Value = int64(msect.addr)
- }
- if framerelocsize > 0 {
- msect.nreloc = uint32(len(framesec.R))
- msect.reloc = uint32(framereloco)
- }
-
- msect = newMachoSect(ms, "__debug_info", "__DWARF")
- msect.off = uint32(infoo)
- msect.size = uint64(infosize)
- msect.addr = addr
- addr += msect.size
- msect.flag = 0x02000000
- if infosym != nil {
- infosym.Value = int64(msect.addr)
- }
- if inforelocsize > 0 {
- msect.nreloc = uint32(len(infosec.R))
- msect.reloc = uint32(inforeloco)
- }
-
- if pubnamessize > 0 {
- msect := newMachoSect(ms, "__debug_pubnames", "__DWARF")
- msect.off = uint32(pubnameso)
- msect.size = uint64(pubnamessize)
- msect.addr = addr
- addr += msect.size
- msect.flag = 0x02000000
- }
-
- if pubtypessize > 0 {
- msect := newMachoSect(ms, "__debug_pubtypes", "__DWARF")
- msect.off = uint32(pubtypeso)
- msect.size = uint64(pubtypessize)
- msect.addr = addr
- addr += msect.size
- msect.flag = 0x02000000
- }
-
- if arangessize > 0 {
- msect := newMachoSect(ms, "__debug_aranges", "__DWARF")
- msect.off = uint32(arangeso)
- msect.size = uint64(arangessize)
- msect.addr = addr
- addr += msect.size
- msect.flag = 0x02000000
- if arangesrelocsize > 0 {
- msect.nreloc = uint32(len(arangessec.R))
- msect.reloc = uint32(arangesreloco)
- }
- }
-
- // TODO(lvd) fix gdb/python to load MachO (16 char section name limit)
- if gdbscriptsize > 0 {
- msect := newMachoSect(ms, "__debug_gdb_scripts", "__DWARF")
- msect.off = uint32(gdbscripto)
- msect.size = uint64(gdbscriptsize)
- msect.addr = addr
- addr += msect.size
- msect.flag = 0x02000000
+ return
}
+ sym := Linklookup(Ctxt, ".debug_info", 0)
+ putelfsectionsym(sym, sym.Sect.Elfsect.shnum)
+ sym = Linklookup(Ctxt, ".debug_abbrev", 0)
+ putelfsectionsym(sym, sym.Sect.Elfsect.shnum)
+ sym = Linklookup(Ctxt, ".debug_line", 0)
+ putelfsectionsym(sym, sym.Sect.Elfsect.shnum)
+ sym = Linklookup(Ctxt, ".debug_frame", 0)
+ putelfsectionsym(sym, sym.Sect.Elfsect.shnum)
}
/*
@@ -2470,13 +2067,12 @@ func dwarfaddpeheaders() {
if Debug['w'] != 0 { // disable dwarf
return
}
-
- newPEDWARFSection(".debug_abbrev", abbrevsize)
- newPEDWARFSection(".debug_line", linesize)
- newPEDWARFSection(".debug_frame", framesize)
- newPEDWARFSection(".debug_info", infosize)
- newPEDWARFSection(".debug_pubnames", pubnamessize)
- newPEDWARFSection(".debug_pubtypes", pubtypessize)
- newPEDWARFSection(".debug_aranges", arangessize)
- newPEDWARFSection(".debug_gdb_scripts", gdbscriptsize)
+ for sect := Segdwarf.Sect; sect != nil; sect = sect.Next {
+ h := newPEDWARFSection(sect.Name, int64(sect.Length))
+ fileoff := sect.Vaddr - Segdwarf.Vaddr + Segdwarf.Fileoff
+ if uint64(h.PointerToRawData) != fileoff {
+ Diag("%s.PointerToRawData = %#x, want %#x", sect.Name, h.PointerToRawData, fileoff)
+ errorexit()
+ }
+ }
}
diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go
index ffb7c4bdde..15b8d7af93 100644
--- a/src/cmd/link/internal/ld/elf.go
+++ b/src/cmd/link/internal/ld/elf.go
@@ -6,6 +6,7 @@ package ld
import (
"cmd/internal/obj"
+ "cmd/internal/sys"
"crypto/sha1"
"encoding/binary"
"encoding/hex"
@@ -866,25 +867,23 @@ var buildinfo []byte
func Elfinit() {
Iself = true
- switch Thearch.Thechar {
- case '0', '6', '7', '9', 'z':
+ if SysArch.InFamily(sys.AMD64, sys.ARM64, sys.MIPS64, sys.PPC64, sys.S390X) {
elfRelType = ".rela"
- default:
+ } else {
elfRelType = ".rel"
}
- switch Thearch.Thechar {
+ switch SysArch.Family {
// 64-bit architectures
- case '9', 'z':
+ case sys.PPC64, sys.S390X:
if Ctxt.Arch.ByteOrder == binary.BigEndian {
ehdr.flags = 1 /* Version 1 ABI */
} else {
ehdr.flags = 2 /* Version 2 ABI */
}
fallthrough
-
- case '0', '6', '7':
- if Thearch.Thechar == '0' {
+ case sys.AMD64, sys.ARM64, sys.MIPS64:
+ if SysArch.Family == sys.MIPS64 {
ehdr.flags = 0x20000000 /* MIPS 3 */
}
elf64 = true
@@ -897,7 +896,7 @@ func Elfinit() {
// we use EABI on both linux/arm and freebsd/arm.
// 32-bit architectures
- case '5':
+ case sys.ARM:
// we use EABI on both linux/arm and freebsd/arm.
if HEADTYPE == obj.Hlinux || HEADTYPE == obj.Hfreebsd {
// We set a value here that makes no indication of which
@@ -911,7 +910,6 @@ func Elfinit() {
ehdr.flags = 0x5000002 // has entry point, Version5 EABI
}
fallthrough
-
default:
ehdr.phoff = ELF32HDRSIZE
/* Must be be ELF32HDRSIZE: first PHdr must follow ELF header */
@@ -1432,7 +1430,7 @@ func elfdynhash() {
}
// s390x (ELF64) hash table entries are 8 bytes
- if Thearch.Thechar == 'z' {
+ if SysArch.Family == sys.S390X {
Adduint64(Ctxt, s, uint64(nbucket))
Adduint64(Ctxt, s, uint64(nsym))
for i := 0; i < nbucket; i++ {
@@ -1622,6 +1620,9 @@ func elfshbits(sect *Section) *ElfShdr {
sh.flags |= SHF_TLS
sh.type_ = SHT_NOBITS
}
+ if strings.HasPrefix(sect.Name, ".debug") {
+ sh.flags = 0
+ }
if Linkmode != LinkExternal {
sh.addr = sect.Vaddr
@@ -1657,19 +1658,19 @@ func elfshreloc(sect *Section) *ElfShdr {
sh := elfshname(elfRelType + sect.Name)
sh.type_ = uint32(typ)
- sh.entsize = uint64(Thearch.Regsize) * 2
+ sh.entsize = uint64(SysArch.RegSize) * 2
if typ == SHT_RELA {
- sh.entsize += uint64(Thearch.Regsize)
+ sh.entsize += uint64(SysArch.RegSize)
}
sh.link = uint32(elfshname(".symtab").shnum)
sh.info = uint32(sect.Elfsect.shnum)
sh.off = sect.Reloff
sh.size = sect.Rellen
- sh.addralign = uint64(Thearch.Regsize)
+ sh.addralign = uint64(SysArch.RegSize)
return sh
}
-func elfrelocsect(sect *Section, first *LSym) {
+func elfrelocsect(sect *Section, syms []*LSym) {
// If main section is SHT_NOBITS, nothing to relocate.
// Also nothing to relocate in .shstrtab.
if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
@@ -1680,20 +1681,18 @@ func elfrelocsect(sect *Section, first *LSym) {
}
sect.Reloff = uint64(Cpos())
- var sym *LSym
- for sym = first; sym != nil; sym = sym.Next {
- if !sym.Attr.Reachable() {
+ for i, s := range syms {
+ if !s.Attr.Reachable() {
continue
}
- if uint64(sym.Value) >= sect.Vaddr {
+ if uint64(s.Value) >= sect.Vaddr {
+ syms = syms[i:]
break
}
}
eaddr := int32(sect.Vaddr + sect.Length)
- var r *Reloc
- var ri int
- for ; sym != nil; sym = sym.Next {
+ for _, sym := range syms {
if !sym.Attr.Reachable() {
continue
}
@@ -1702,8 +1701,8 @@ func elfrelocsect(sect *Section, first *LSym) {
}
Ctxt.Cursym = sym
- for ri = 0; ri < len(sym.R); ri++ {
- r = &sym.R[ri]
+ for ri := 0; ri < len(sym.R); ri++ {
+ r := &sym.R[ri]
if r.Done != 0 {
continue
}
@@ -1711,7 +1710,6 @@ func elfrelocsect(sect *Section, first *LSym) {
Diag("missing xsym in relocation")
continue
}
-
if r.Xsym.ElfsymForReloc() == 0 {
Diag("reloc %d to non-elf symbol %s (outer=%s) %d", r.Type, r.Sym.Name, r.Xsym.Name, r.Sym.Type)
}
@@ -1739,6 +1737,9 @@ func Elfemitreloc() {
for sect := Segdata.Sect; sect != nil; sect = sect.Next {
elfrelocsect(sect, datap)
}
+ for sect := Segdwarf.Sect; sect != nil; sect = sect.Next {
+ elfrelocsect(sect, list2slice(dwarfp))
+ }
}
func addgonote(sectionName string, tag uint32, desc []byte) {
@@ -1866,7 +1867,7 @@ func doelf() {
Addstring(shstrtab, ".interp")
Addstring(shstrtab, ".hash")
Addstring(shstrtab, ".got")
- if Thearch.Thechar == '9' {
+ if SysArch.Family == sys.PPC64 {
Addstring(shstrtab, ".glink")
}
Addstring(shstrtab, ".got.plt")
@@ -1885,10 +1886,9 @@ func doelf() {
s.Type = obj.SELFROSECT
s.Attr |= AttrReachable
- switch Thearch.Thechar {
- case '0', '6', '7', '9', 'z':
+ if elf64 {
s.Size += ELF64SYMSIZE
- default:
+ } else {
s.Size += ELF32SYMSIZE
}
@@ -1914,7 +1914,7 @@ func doelf() {
s.Type = obj.SELFGOT // writable
/* ppc64 glink resolver */
- if Thearch.Thechar == '9' {
+ if SysArch.Family == sys.PPC64 {
s := Linklookup(Ctxt, ".glink", 0)
s.Attr |= AttrReachable
s.Type = obj.SELFRXSECT
@@ -1933,7 +1933,7 @@ func doelf() {
s = Linklookup(Ctxt, ".plt", 0)
s.Attr |= AttrReachable
- if Thearch.Thechar == '9' {
+ if SysArch.Family == sys.PPC64 {
// In the ppc64 ABI, .plt is a data section
// written by the dynamic linker.
s.Type = obj.SELFSECT
@@ -1967,10 +1967,9 @@ func doelf() {
elfwritedynentsym(s, DT_HASH, Linklookup(Ctxt, ".hash", 0))
elfwritedynentsym(s, DT_SYMTAB, Linklookup(Ctxt, ".dynsym", 0))
- switch Thearch.Thechar {
- case '0', '6', '7', '9', 'z':
+ if elf64 {
Elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE)
- default:
+ } else {
Elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE)
}
elfwritedynentsym(s, DT_STRTAB, Linklookup(Ctxt, ".dynstr", 0))
@@ -1989,15 +1988,15 @@ func doelf() {
Elfwritedynent(s, DT_RUNPATH, uint64(Addstring(dynstr, rpath.val)))
}
- if Thearch.Thechar == '9' {
+ if SysArch.Family == sys.PPC64 {
elfwritedynentsym(s, DT_PLTGOT, Linklookup(Ctxt, ".plt", 0))
- } else if Thearch.Thechar == 'z' {
+ } else if SysArch.Family == sys.S390X {
elfwritedynentsym(s, DT_PLTGOT, Linklookup(Ctxt, ".got", 0))
} else {
elfwritedynentsym(s, DT_PLTGOT, Linklookup(Ctxt, ".got.plt", 0))
}
- if Thearch.Thechar == '9' {
+ if SysArch.Family == sys.PPC64 {
Elfwritedynent(s, DT_PPC64_OPT, 0)
}
@@ -2024,7 +2023,7 @@ func doelf() {
h.Write(l.hash)
}
addgonote(".note.go.abihash", ELF_NOTE_GOABIHASH_TAG, h.Sum([]byte{}))
- addgonote(".note.go.pkg-list", ELF_NOTE_GOPKGLIST_TAG, []byte(pkglistfornote))
+ addgonote(".note.go.pkg-list", ELF_NOTE_GOPKGLIST_TAG, pkglistfornote)
var deplist []string
for _, shlib := range Ctxt.Shlibs {
deplist = append(deplist, filepath.Base(shlib.Path))
@@ -2069,26 +2068,29 @@ func Asmbelfsetup() {
for sect := Segdata.Sect; sect != nil; sect = sect.Next {
elfshalloc(sect)
}
+ for sect := Segdwarf.Sect; sect != nil; sect = sect.Next {
+ elfshalloc(sect)
+ }
}
func Asmbelf(symo int64) {
eh := getElfEhdr()
- switch Thearch.Thechar {
+ switch SysArch.Family {
default:
- Exitf("unknown architecture in asmbelf: %v", Thearch.Thechar)
- case '0':
+ Exitf("unknown architecture in asmbelf: %v", SysArch.Family)
+ case sys.MIPS64:
eh.machine = EM_MIPS
- case '5':
+ case sys.ARM:
eh.machine = EM_ARM
- case '6':
+ case sys.AMD64:
eh.machine = EM_X86_64
- case '7':
+ case sys.ARM64:
eh.machine = EM_AARCH64
- case '8':
+ case sys.I386:
eh.machine = EM_386
- case '9':
+ case sys.PPC64:
eh.machine = EM_PPC64
- case 'z':
+ case sys.S390X:
eh.machine = EM_S390
}
@@ -2244,7 +2246,7 @@ func Asmbelf(symo int64) {
} else {
sh.entsize = ELF32SYMSIZE
}
- sh.addralign = uint64(Thearch.Regsize)
+ sh.addralign = uint64(SysArch.RegSize)
sh.link = uint32(elfshname(".dynstr").shnum)
// sh->info = index of first non-local symbol (number of local symbols)
@@ -2268,7 +2270,7 @@ func Asmbelf(symo int64) {
sh = elfshname(".gnu.version_r")
sh.type_ = SHT_GNU_VERNEED
sh.flags = SHF_ALLOC
- sh.addralign = uint64(Thearch.Regsize)
+ sh.addralign = uint64(SysArch.RegSize)
sh.info = uint32(elfverneed)
sh.link = uint32(elfshname(".dynstr").shnum)
shsym(sh, Linklookup(Ctxt, ".gnu.version_r", 0))
@@ -2279,7 +2281,7 @@ func Asmbelf(symo int64) {
sh.type_ = SHT_RELA
sh.flags = SHF_ALLOC
sh.entsize = ELF64RELASIZE
- sh.addralign = uint64(Thearch.Regsize)
+ sh.addralign = uint64(SysArch.RegSize)
sh.link = uint32(elfshname(".dynsym").shnum)
sh.info = uint32(elfshname(".plt").shnum)
shsym(sh, Linklookup(Ctxt, ".rela.plt", 0))
@@ -2343,15 +2345,15 @@ func Asmbelf(symo int64) {
sh := elfshname(".got")
sh.type_ = SHT_PROGBITS
sh.flags = SHF_ALLOC + SHF_WRITE
- sh.entsize = uint64(Thearch.Regsize)
- sh.addralign = uint64(Thearch.Regsize)
+ sh.entsize = uint64(SysArch.RegSize)
+ sh.addralign = uint64(SysArch.RegSize)
shsym(sh, Linklookup(Ctxt, ".got", 0))
sh = elfshname(".got.plt")
sh.type_ = SHT_PROGBITS
sh.flags = SHF_ALLOC + SHF_WRITE
- sh.entsize = uint64(Thearch.Regsize)
- sh.addralign = uint64(Thearch.Regsize)
+ sh.entsize = uint64(SysArch.RegSize)
+ sh.addralign = uint64(SysArch.RegSize)
shsym(sh, Linklookup(Ctxt, ".got.plt", 0))
}
@@ -2359,7 +2361,7 @@ func Asmbelf(symo int64) {
sh.type_ = SHT_HASH
sh.flags = SHF_ALLOC
sh.entsize = 4
- sh.addralign = uint64(Thearch.Regsize)
+ sh.addralign = uint64(SysArch.RegSize)
sh.link = uint32(elfshname(".dynsym").shnum)
shsym(sh, Linklookup(Ctxt, ".hash", 0))
@@ -2368,8 +2370,8 @@ func Asmbelf(symo int64) {
sh.type_ = SHT_DYNAMIC
sh.flags = SHF_ALLOC + SHF_WRITE
- sh.entsize = 2 * uint64(Thearch.Regsize)
- sh.addralign = uint64(Thearch.Regsize)
+ sh.entsize = 2 * uint64(SysArch.RegSize)
+ sh.addralign = uint64(SysArch.RegSize)
sh.link = uint32(elfshname(".dynstr").shnum)
shsym(sh, Linklookup(Ctxt, ".dynamic", 0))
ph := newElfPhdr()
@@ -2395,7 +2397,7 @@ func Asmbelf(symo int64) {
ph.type_ = PT_TLS
ph.flags = PF_R
ph.memsz = tlssize
- ph.align = uint64(Thearch.Regsize)
+ ph.align = uint64(SysArch.RegSize)
}
}
}
@@ -2404,12 +2406,12 @@ func Asmbelf(symo int64) {
ph := newElfPhdr()
ph.type_ = PT_GNU_STACK
ph.flags = PF_W + PF_R
- ph.align = uint64(Thearch.Regsize)
+ ph.align = uint64(SysArch.RegSize)
ph = newElfPhdr()
ph.type_ = PT_PAX_FLAGS
ph.flags = 0x2a00 // mprotect, randexec, emutramp disabled
- ph.align = uint64(Thearch.Regsize)
+ ph.align = uint64(SysArch.RegSize)
}
elfobj:
@@ -2434,6 +2436,9 @@ elfobj:
for sect := Segdata.Sect; sect != nil; sect = sect.Next {
elfshbits(sect)
}
+ for sect := Segdwarf.Sect; sect != nil; sect = sect.Next {
+ elfshbits(sect)
+ }
if Linkmode == LinkExternal {
for sect := Segtext.Sect; sect != nil; sect = sect.Next {
@@ -2445,7 +2450,14 @@ elfobj:
for sect := Segdata.Sect; sect != nil; sect = sect.Next {
elfshreloc(sect)
}
-
+ for s := dwarfp; s != nil; s = s.Next {
+ if len(s.R) > 0 || s.Type == obj.SDWARFINFO {
+ elfshreloc(s.Sect)
+ }
+ if s.Type == obj.SDWARFINFO {
+ break
+ }
+ }
// add a .note.GNU-stack section to mark the stack as non-executable
sh := elfshname(".note.GNU-stack")
@@ -2459,8 +2471,8 @@ elfobj:
sh.type_ = SHT_SYMTAB
sh.off = uint64(symo)
sh.size = uint64(Symsize)
- sh.addralign = uint64(Thearch.Regsize)
- sh.entsize = 8 + 2*uint64(Thearch.Regsize)
+ sh.addralign = uint64(SysArch.RegSize)
+ sh.entsize = 8 + 2*uint64(SysArch.RegSize)
sh.link = uint32(elfshname(".strtab").shnum)
sh.info = uint32(elfglobalsymndx)
@@ -2469,8 +2481,6 @@ elfobj:
sh.off = uint64(symo) + uint64(Symsize)
sh.size = uint64(len(Elfstrdat))
sh.addralign = 1
-
- dwarfaddelfheaders()
}
/* Main header */
@@ -2585,7 +2595,7 @@ func Elfadddynsym(ctxt *Link, s *LSym) {
/* size of object */
Adduint64(ctxt, d, uint64(s.Size))
- if Thearch.Thechar == '6' && !s.Attr.CgoExportDynamic() && s.Dynimplib != "" && !seenlib[s.Dynimplib] {
+ if SysArch.Family == sys.AMD64 && !s.Attr.CgoExportDynamic() && s.Dynimplib != "" && !seenlib[s.Dynimplib] {
Elfwritedynent(Linklookup(ctxt, ".dynamic", 0), DT_NEEDED, uint64(Addstring(Linklookup(ctxt, ".dynstr", 0), s.Dynimplib)))
}
} else {
@@ -2613,9 +2623,9 @@ func Elfadddynsym(ctxt *Link, s *LSym) {
t := STB_GLOBAL << 4
// TODO(mwhudson): presumably the behaviour should actually be the same on both arm and 386.
- if Thearch.Thechar == '8' && s.Attr.CgoExport() && s.Type&obj.SMASK == obj.STEXT {
+ if SysArch.Family == sys.I386 && s.Attr.CgoExport() && s.Type&obj.SMASK == obj.STEXT {
t |= STT_FUNC
- } else if Thearch.Thechar == '5' && s.Attr.CgoExportDynamic() && s.Type&obj.SMASK == obj.STEXT {
+ } else if SysArch.Family == sys.ARM && s.Attr.CgoExportDynamic() && s.Type&obj.SMASK == obj.STEXT {
t |= STT_FUNC
} else {
t |= STT_OBJECT
diff --git a/src/cmd/link/internal/ld/go.go b/src/cmd/link/internal/ld/go.go
index 027e05d845..425c75571f 100644
--- a/src/cmd/link/internal/ld/go.go
+++ b/src/cmd/link/internal/ld/go.go
@@ -8,8 +8,10 @@ package ld
import (
"bytes"
+ "cmd/internal/bio"
"cmd/internal/obj"
"fmt"
+ "io"
"os"
"strings"
)
@@ -26,7 +28,7 @@ func expandpkg(t0 string, pkg string) string {
// once the dust settles, try to move some code to
// libmach, so that other linkers and ar can share.
-func ldpkg(f *obj.Biobuf, pkg string, length int64, filename string, whence int) {
+func ldpkg(f *bio.Reader, pkg string, length int64, filename string, whence int) {
var p0, p1 int
if Debug['g'] != 0 {
@@ -48,7 +50,7 @@ func ldpkg(f *obj.Biobuf, pkg string, length int64, filename string, whence int)
}
bdata := make([]byte, length)
- if int64(obj.Bread(f, bdata)) != length {
+ if _, err := io.ReadFull(f, bdata); err != nil {
fmt.Fprintf(os.Stderr, "%s: short pkg read %s\n", os.Args[0], filename)
if Debug['u'] != 0 {
errorexit()
@@ -418,35 +420,7 @@ type Pkg struct {
impby []*Pkg
}
-var (
- // pkgmap records the imported-by relationship between packages.
- // Entries are keyed by package path (e.g., "runtime" or "net/url").
- pkgmap = map[string]*Pkg{}
-
- pkgall []*Pkg
-)
-
-func lookupPkg(path string) *Pkg {
- if p, ok := pkgmap[path]; ok {
- return p
- }
- p := &Pkg{path: path}
- pkgmap[path] = p
- pkgall = append(pkgall, p)
- return p
-}
-
-// imported records that package pkg imports package imp.
-func imported(pkg, imp string) {
- // everyone imports runtime, even runtime.
- if imp == "runtime" {
- return
- }
-
- p := lookupPkg(pkg)
- i := lookupPkg(imp)
- i.impby = append(i.impby, p)
-}
+var pkgall []*Pkg
func (p *Pkg) cycle() *Pkg {
if p.checked {
diff --git a/src/cmd/link/internal/ld/ldelf.go b/src/cmd/link/internal/ld/ldelf.go
index 0255331ac6..af60a5c85b 100644
--- a/src/cmd/link/internal/ld/ldelf.go
+++ b/src/cmd/link/internal/ld/ldelf.go
@@ -2,7 +2,9 @@ package ld
import (
"bytes"
+ "cmd/internal/bio"
"cmd/internal/obj"
+ "cmd/internal/sys"
"encoding/binary"
"fmt"
"io"
@@ -266,7 +268,7 @@ type ElfSect struct {
}
type ElfObj struct {
- f *obj.Biobuf
+ f *bio.Reader
base int64 // offset in f where ELF begins
length int64 // length of ELF
is64 int
@@ -403,7 +405,7 @@ func parseArmAttributes(e binary.ByteOrder, data []byte) {
ehdr.flags = 0x5000202
}
if data[0] != 'A' {
- fmt.Fprintf(&Bso, ".ARM.attributes has unexpected format %c\n", data[0])
+ fmt.Fprintf(Bso, ".ARM.attributes has unexpected format %c\n", data[0])
return
}
data = data[1:]
@@ -414,7 +416,7 @@ func parseArmAttributes(e binary.ByteOrder, data []byte) {
nulIndex := bytes.IndexByte(sectiondata, 0)
if nulIndex < 0 {
- fmt.Fprintf(&Bso, "corrupt .ARM.attributes (section name not NUL-terminated)\n")
+ fmt.Fprintf(Bso, "corrupt .ARM.attributes (section name not NUL-terminated)\n")
return
}
name := string(sectiondata[:nulIndex])
@@ -438,20 +440,20 @@ func parseArmAttributes(e binary.ByteOrder, data []byte) {
}
}
if attrList.err != nil {
- fmt.Fprintf(&Bso, "could not parse .ARM.attributes\n")
+ fmt.Fprintf(Bso, "could not parse .ARM.attributes\n")
}
}
}
}
}
-func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
+func ldelf(f *bio.Reader, pkg string, length int64, pn string) {
if Debug['v'] != 0 {
- fmt.Fprintf(&Bso, "%5.2f ldelf %s\n", obj.Cputime(), pn)
+ fmt.Fprintf(Bso, "%5.2f ldelf %s\n", obj.Cputime(), pn)
}
Ctxt.IncVersion()
- base := int32(obj.Boffset(f))
+ base := f.Offset()
var add uint64
var e binary.ByteOrder
@@ -474,7 +476,7 @@ func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
var sect *ElfSect
var sym ElfSym
var symbols []*LSym
- if obj.Bread(f, hdrbuf[:]) != len(hdrbuf) {
+ if _, err := io.ReadFull(f, hdrbuf[:]); err != nil {
goto bad
}
hdr = new(ElfHdrBytes)
@@ -498,7 +500,7 @@ func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
elfobj.e = e
elfobj.f = f
- elfobj.base = int64(base)
+ elfobj.base = base
elfobj.length = length
elfobj.name = pn
@@ -546,47 +548,48 @@ func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
return
}
- switch Thearch.Thechar {
+ switch SysArch.Family {
default:
- Diag("%s: elf %s unimplemented", pn, Thestring)
+ Diag("%s: elf %s unimplemented", pn, SysArch.Name)
return
- case '0':
+ case sys.MIPS64:
if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass64 {
Diag("%s: elf object but not mips64", pn)
return
}
- case '5':
+ case sys.ARM:
if e != binary.LittleEndian || elfobj.machine != ElfMachArm || hdr.Ident[4] != ElfClass32 {
Diag("%s: elf object but not arm", pn)
return
}
- case '6':
+ case sys.AMD64:
if e != binary.LittleEndian || elfobj.machine != ElfMachAmd64 || hdr.Ident[4] != ElfClass64 {
Diag("%s: elf object but not amd64", pn)
return
}
- case '7':
+ case sys.ARM64:
if e != binary.LittleEndian || elfobj.machine != ElfMachArm64 || hdr.Ident[4] != ElfClass64 {
Diag("%s: elf object but not arm64", pn)
return
}
- case '8':
+ case sys.I386:
if e != binary.LittleEndian || elfobj.machine != ElfMach386 || hdr.Ident[4] != ElfClass32 {
Diag("%s: elf object but not 386", pn)
return
}
- case '9':
+ case sys.PPC64:
if elfobj.machine != ElfMachPower64 || hdr.Ident[4] != ElfClass64 {
Diag("%s: elf object but not ppc64", pn)
return
}
- case 'z':
+
+ case sys.S390X:
if elfobj.machine != ElfMachS390 || hdr.Ident[4] != ElfClass64 {
Diag("%s: elf object but not s390x", pn)
return
@@ -598,7 +601,7 @@ func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
elfobj.nsect = uint(elfobj.shnum)
for i := 0; uint(i) < elfobj.nsect; i++ {
- if obj.Bseek(f, int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0) < 0 {
+ if f.Seek(int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0) < 0 {
goto bad
}
sect = &elfobj.sect[i]
@@ -609,7 +612,7 @@ func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
goto bad
}
- sect.nameoff = uint32(e.Uint32(b.Name[:]))
+ sect.nameoff = e.Uint32(b.Name[:])
sect.type_ = e.Uint32(b.Type[:])
sect.flags = e.Uint64(b.Flags[:])
sect.addr = e.Uint64(b.Addr[:])
@@ -626,7 +629,7 @@ func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
goto bad
}
- sect.nameoff = uint32(e.Uint32(b.Name[:]))
+ sect.nameoff = e.Uint32(b.Name[:])
sect.type_ = e.Uint32(b.Type[:])
sect.flags = uint64(e.Uint32(b.Flags[:]))
sect.addr = uint64(e.Uint32(b.Addr[:]))
@@ -771,7 +774,7 @@ func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
if sym.sym == nil {
continue
}
- sect = &elfobj.sect[sym.shndx:][0]
+ sect = &elfobj.sect[sym.shndx]
if sect.sym == nil {
if strings.HasPrefix(sym.name, ".Linfo_string") { // clang does this
continue
@@ -839,19 +842,13 @@ func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
log.Fatalf("symbol %s listed multiple times", s.Name)
}
s.Attr |= AttrOnList
- if Ctxt.Etextp != nil {
- Ctxt.Etextp.Next = s
- } else {
- Ctxt.Textp = s
- }
- Ctxt.Etextp = s
+ Ctxt.Textp = append(Ctxt.Textp, s)
for s = s.Sub; s != nil; s = s.Sub {
if s.Attr.OnList() {
log.Fatalf("symbol %s listed multiple times", s.Name)
}
s.Attr |= AttrOnList
- Ctxt.Etextp.Next = s
- Ctxt.Etextp = s
+ Ctxt.Textp = append(Ctxt.Textp, s)
}
}
}
@@ -925,7 +922,8 @@ func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
rp.Sym = sym.sym
}
- rp.Type = int32(reltype(pn, int(uint32(info)), &rp.Siz))
+ rp.Type = 256 + int32(info)
+ rp.Siz = relSize(pn, uint32(info))
if rela != 0 {
rp.Add = int64(add)
} else {
@@ -982,9 +980,11 @@ func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
}
sect.base = make([]byte, sect.size)
- err = fmt.Errorf("short read")
- if obj.Bseek(elfobj.f, int64(uint64(elfobj.base)+sect.off), 0) < 0 || obj.Bread(elfobj.f, sect.base) != len(sect.base) {
- return err
+ if elfobj.f.Seek(int64(uint64(elfobj.base)+sect.off), 0) < 0 {
+ return fmt.Errorf("short read: seek not successful")
+ }
+ if _, err := io.ReadFull(elfobj.f, sect.base); err != nil {
+ return fmt.Errorf("short read: %v", err)
}
return nil
@@ -1056,7 +1056,7 @@ func readelfsym(elfobj *ElfObj, i int, sym *ElfSym, needSym int) (err error) {
}
case ElfSymBindLocal:
- if Thearch.Thechar == '5' && (strings.HasPrefix(sym.name, "$a") || strings.HasPrefix(sym.name, "$d")) {
+ if SysArch.Family == sys.ARM && (strings.HasPrefix(sym.name, "$a") || strings.HasPrefix(sym.name, "$d")) {
// binutils for arm generate these mapping
// symbols, ignore these
break
@@ -1126,79 +1126,89 @@ func (x rbyoff) Less(i, j int) bool {
return false
}
-func reltype(pn string, elftype int, siz *uint8) int {
- switch uint32(Thearch.Thechar) | uint32(elftype)<<24 {
+func relSize(pn string, elftype uint32) uint8 {
+ // TODO(mdempsky): Replace this with a struct-valued switch statement
+ // once golang.org/issue/15164 is fixed or found to not impair cmd/link
+ // performance.
+
+ const (
+ AMD64 = uint32(sys.AMD64)
+ ARM = uint32(sys.ARM)
+ I386 = uint32(sys.I386)
+ PPC64 = uint32(sys.PPC64)
+ S390X = uint32(sys.S390X)
+ )
+
+ switch uint32(SysArch.Family) | elftype<<24 {
default:
Diag("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype)
fallthrough
- case 'z' | R_390_8:
- *siz = 1
+ case S390X | R_390_8<<24:
+ return 1
- case '9' | R_PPC64_TOC16<<24,
- '9' | R_PPC64_TOC16_LO<<24,
- '9' | R_PPC64_TOC16_HI<<24,
- '9' | R_PPC64_TOC16_HA<<24,
- '9' | R_PPC64_TOC16_DS<<24,
- '9' | R_PPC64_TOC16_LO_DS<<24,
- '9' | R_PPC64_REL16_LO<<24,
- '9' | R_PPC64_REL16_HI<<24,
- '9' | R_PPC64_REL16_HA<<24,
- 'z' | R_390_16<<24,
- 'z' | R_390_GOT16<<24,
- 'z' | R_390_PC16<<24,
- 'z' | R_390_PC16DBL<<24,
- 'z' | R_390_PLT16DBL<<24:
- *siz = 2
+ case PPC64 | R_PPC64_TOC16<<24,
+ PPC64 | R_PPC64_TOC16_LO<<24,
+ PPC64 | R_PPC64_TOC16_HI<<24,
+ PPC64 | R_PPC64_TOC16_HA<<24,
+ PPC64 | R_PPC64_TOC16_DS<<24,
+ PPC64 | R_PPC64_TOC16_LO_DS<<24,
+ PPC64 | R_PPC64_REL16_LO<<24,
+ PPC64 | R_PPC64_REL16_HI<<24,
+ PPC64 | R_PPC64_REL16_HA<<24,
+ S390X | R_390_16<<24,
+ S390X | R_390_GOT16<<24,
+ S390X | R_390_PC16<<24,
+ S390X | R_390_PC16DBL<<24,
+ S390X | R_390_PLT16DBL<<24:
+ return 2
- case '5' | R_ARM_ABS32<<24,
- '5' | R_ARM_GOT32<<24,
- '5' | R_ARM_PLT32<<24,
- '5' | R_ARM_GOTOFF<<24,
- '5' | R_ARM_GOTPC<<24,
- '5' | R_ARM_THM_PC22<<24,
- '5' | R_ARM_REL32<<24,
- '5' | R_ARM_CALL<<24,
- '5' | R_ARM_V4BX<<24,
- '5' | R_ARM_GOT_PREL<<24,
- '5' | R_ARM_PC24<<24,
- '5' | R_ARM_JUMP24<<24,
- '6' | R_X86_64_PC32<<24,
- '6' | R_X86_64_PLT32<<24,
- '6' | R_X86_64_GOTPCREL<<24,
- '6' | R_X86_64_GOTPCRELX<<24,
- '6' | R_X86_64_REX_GOTPCRELX<<24,
- '8' | R_386_32<<24,
- '8' | R_386_PC32<<24,
- '8' | R_386_GOT32<<24,
- '8' | R_386_PLT32<<24,
- '8' | R_386_GOTOFF<<24,
- '8' | R_386_GOTPC<<24,
- '8' | R_386_GOT32X<<24,
- '9' | R_PPC64_REL24<<24,
- '9' | R_PPC_REL32<<24,
- 'z' | R_390_32<<24,
- 'z' | R_390_PC32<<24,
- 'z' | R_390_GOT32<<24,
- 'z' | R_390_PLT32<<24,
- 'z' | R_390_PC32DBL<<24,
- 'z' | R_390_PLT32DBL<<24,
- 'z' | R_390_GOTPCDBL<<24,
- 'z' | R_390_GOTENT<<24:
- *siz = 4
+ case ARM | R_ARM_ABS32<<24,
+ ARM | R_ARM_GOT32<<24,
+ ARM | R_ARM_PLT32<<24,
+ ARM | R_ARM_GOTOFF<<24,
+ ARM | R_ARM_GOTPC<<24,
+ ARM | R_ARM_THM_PC22<<24,
+ ARM | R_ARM_REL32<<24,
+ ARM | R_ARM_CALL<<24,
+ ARM | R_ARM_V4BX<<24,
+ ARM | R_ARM_GOT_PREL<<24,
+ ARM | R_ARM_PC24<<24,
+ ARM | R_ARM_JUMP24<<24,
+ AMD64 | R_X86_64_PC32<<24,
+ AMD64 | R_X86_64_PLT32<<24,
+ AMD64 | R_X86_64_GOTPCREL<<24,
+ AMD64 | R_X86_64_GOTPCRELX<<24,
+ AMD64 | R_X86_64_REX_GOTPCRELX<<24,
+ I386 | R_386_32<<24,
+ I386 | R_386_PC32<<24,
+ I386 | R_386_GOT32<<24,
+ I386 | R_386_PLT32<<24,
+ I386 | R_386_GOTOFF<<24,
+ I386 | R_386_GOTPC<<24,
+ I386 | R_386_GOT32X<<24,
+ PPC64 | R_PPC64_REL24<<24,
+ PPC64 | R_PPC_REL32<<24,
+ S390X | R_390_32<<24,
+ S390X | R_390_PC32<<24,
+ S390X | R_390_GOT32<<24,
+ S390X | R_390_PLT32<<24,
+ S390X | R_390_PC32DBL<<24,
+ S390X | R_390_PLT32DBL<<24,
+ S390X | R_390_GOTPCDBL<<24,
+ S390X | R_390_GOTENT<<24:
+ return 4
- case '6' | R_X86_64_64<<24,
- '9' | R_PPC64_ADDR64<<24,
- 'z' | R_390_GLOB_DAT<<24,
- 'z' | R_390_RELATIVE<<24,
- 'z' | R_390_GOTOFF<<24,
- 'z' | R_390_GOTPC<<24,
- 'z' | R_390_64<<24,
- 'z' | R_390_PC64<<24,
- 'z' | R_390_GOT64<<24,
- 'z' | R_390_PLT64<<24:
- *siz = 8
+ case AMD64 | R_X86_64_64<<24,
+ PPC64 | R_PPC64_ADDR64<<24,
+ S390X | R_390_GLOB_DAT<<24,
+ S390X | R_390_RELATIVE<<24,
+ S390X | R_390_GOTOFF<<24,
+ S390X | R_390_GOTPC<<24,
+ S390X | R_390_64<<24,
+ S390X | R_390_PC64<<24,
+ S390X | R_390_GOT64<<24,
+ S390X | R_390_PLT64<<24:
+ return 8
}
-
- return 256 + elftype
}
diff --git a/src/cmd/link/internal/ld/ldmacho.go b/src/cmd/link/internal/ld/ldmacho.go
index c4c13f13b9..a10124907c 100644
--- a/src/cmd/link/internal/ld/ldmacho.go
+++ b/src/cmd/link/internal/ld/ldmacho.go
@@ -1,9 +1,12 @@
package ld
import (
+ "cmd/internal/bio"
"cmd/internal/obj"
+ "cmd/internal/sys"
"encoding/binary"
"fmt"
+ "io"
"log"
"sort"
)
@@ -41,7 +44,7 @@ const (
)
type LdMachoObj struct {
- f *obj.Biobuf
+ f *bio.Reader
base int64 // off in f where Mach-O begins
length int64 // length of Mach-O
is64 bool
@@ -297,7 +300,10 @@ func macholoadrel(m *LdMachoObj, sect *LdMachoSect) int {
rel := make([]LdMachoRel, sect.nreloc)
n := int(sect.nreloc * 8)
buf := make([]byte, n)
- if obj.Bseek(m.f, m.base+int64(sect.reloff), 0) < 0 || obj.Bread(m.f, buf) != n {
+ if m.f.Seek(m.base+int64(sect.reloff), 0) < 0 {
+ return -1
+ }
+ if _, err := io.ReadFull(m.f, buf); err != nil {
return -1
}
var p []byte
@@ -343,7 +349,10 @@ func macholoaddsym(m *LdMachoObj, d *LdMachoDysymtab) int {
n := int(d.nindirectsyms)
p := make([]byte, n*4)
- if obj.Bseek(m.f, m.base+int64(d.indirectsymoff), 0) < 0 || obj.Bread(m.f, p) != len(p) {
+ if m.f.Seek(m.base+int64(d.indirectsymoff), 0) < 0 {
+ return -1
+ }
+ if _, err := io.ReadFull(m.f, p); err != nil {
return -1
}
@@ -360,7 +369,10 @@ func macholoadsym(m *LdMachoObj, symtab *LdMachoSymtab) int {
}
strbuf := make([]byte, symtab.strsize)
- if obj.Bseek(m.f, m.base+int64(symtab.stroff), 0) < 0 || obj.Bread(m.f, strbuf) != len(strbuf) {
+ if m.f.Seek(m.base+int64(symtab.stroff), 0) < 0 {
+ return -1
+ }
+ if _, err := io.ReadFull(m.f, strbuf); err != nil {
return -1
}
@@ -370,7 +382,10 @@ func macholoadsym(m *LdMachoObj, symtab *LdMachoSymtab) int {
}
n := int(symtab.nsym * uint32(symsize))
symbuf := make([]byte, n)
- if obj.Bseek(m.f, m.base+int64(symtab.symoff), 0) < 0 || obj.Bread(m.f, symbuf) != len(symbuf) {
+ if m.f.Seek(m.base+int64(symtab.symoff), 0) < 0 {
+ return -1
+ }
+ if _, err := io.ReadFull(m.f, symbuf); err != nil {
return -1
}
sym := make([]LdMachoSym, symtab.nsym)
@@ -384,8 +399,8 @@ func macholoadsym(m *LdMachoObj, symtab *LdMachoSymtab) int {
return -1
}
s.name = cstring(strbuf[v:])
- s.type_ = uint8(p[4])
- s.sectnum = uint8(p[5])
+ s.type_ = p[4]
+ s.sectnum = p[5]
s.desc = m.e.Uint16(p[6:])
if m.is64 {
s.value = m.e.Uint64(p[8:])
@@ -400,7 +415,7 @@ func macholoadsym(m *LdMachoObj, symtab *LdMachoSymtab) int {
return 0
}
-func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) {
+func ldmacho(f *bio.Reader, pkg string, length int64, pn string) {
var err error
var j int
var is64 bool
@@ -430,8 +445,8 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) {
var name string
Ctxt.IncVersion()
- base := obj.Boffset(f)
- if obj.Bread(f, hdr[:]) != len(hdr) {
+ base := f.Offset()
+ if _, err := io.ReadFull(f, hdr[:]); err != nil {
goto bad
}
@@ -445,44 +460,43 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) {
}
is64 = e.Uint32(hdr[:]) == 0xFEEDFACF
- ncmd = e.Uint32([]byte(hdr[4*4:]))
- cmdsz = e.Uint32([]byte(hdr[5*4:]))
+ ncmd = e.Uint32(hdr[4*4:])
+ cmdsz = e.Uint32(hdr[5*4:])
if ncmd > 0x10000 || cmdsz >= 0x01000000 {
err = fmt.Errorf("implausible mach-o header ncmd=%d cmdsz=%d", ncmd, cmdsz)
goto bad
}
if is64 {
- var tmp [4]uint8
- obj.Bread(f, tmp[:4]) // skip reserved word in header
+ f.Seek(4, 1) // skip reserved word in header
}
m = new(LdMachoObj)
m.f = f
m.e = e
- m.cputype = uint(e.Uint32([]byte(hdr[1*4:])))
- m.subcputype = uint(e.Uint32([]byte(hdr[2*4:])))
- m.filetype = e.Uint32([]byte(hdr[3*4:]))
+ m.cputype = uint(e.Uint32(hdr[1*4:]))
+ m.subcputype = uint(e.Uint32(hdr[2*4:]))
+ m.filetype = e.Uint32(hdr[3*4:])
m.ncmd = uint(ncmd)
- m.flags = e.Uint32([]byte(hdr[6*4:]))
+ m.flags = e.Uint32(hdr[6*4:])
m.is64 = is64
m.base = base
m.length = length
m.name = pn
- switch Thearch.Thechar {
+ switch SysArch.Family {
default:
- Diag("%s: mach-o %s unimplemented", pn, Thestring)
+ Diag("%s: mach-o %s unimplemented", pn, SysArch.Name)
return
- case '6':
+ case sys.AMD64:
if e != binary.LittleEndian || m.cputype != LdMachoCpuAmd64 {
Diag("%s: mach-o object but not amd64", pn)
return
}
- case '8':
+ case sys.I386:
if e != binary.LittleEndian || m.cputype != LdMachoCpu386 {
Diag("%s: mach-o object but not 386", pn)
return
@@ -492,7 +506,7 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) {
m.cmd = make([]LdMachoCmd, ncmd)
off = uint32(len(hdr))
cmdp = make([]byte, cmdsz)
- if obj.Bread(f, cmdp) != len(cmdp) {
+ if _, err2 := io.ReadFull(f, cmdp); err2 != nil {
err = fmt.Errorf("reading cmds: %v", err)
goto bad
}
@@ -555,7 +569,11 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) {
}
dat = make([]byte, c.seg.filesz)
- if obj.Bseek(f, m.base+int64(c.seg.fileoff), 0) < 0 || obj.Bread(f, dat) != len(dat) {
+ if f.Seek(m.base+int64(c.seg.fileoff), 0) < 0 {
+ err = fmt.Errorf("cannot load object data: %v", err)
+ goto bad
+ }
+ if _, err2 := io.ReadFull(f, dat); err2 != nil {
err = fmt.Errorf("cannot load object data: %v", err)
goto bad
}
@@ -689,19 +707,13 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) {
log.Fatalf("symbol %s listed multiple times", s.Name)
}
s.Attr |= AttrOnList
- if Ctxt.Etextp != nil {
- Ctxt.Etextp.Next = s
- } else {
- Ctxt.Textp = s
- }
- Ctxt.Etextp = s
+ Ctxt.Textp = append(Ctxt.Textp, s)
for s1 = s.Sub; s1 != nil; s1 = s1.Sub {
if s1.Attr.OnList() {
log.Fatalf("symbol %s listed multiple times", s1.Name)
}
s1.Attr |= AttrOnList
- Ctxt.Etextp.Next = s1
- Ctxt.Etextp = s1
+ Ctxt.Textp = append(Ctxt.Textp, s1)
}
}
}
@@ -724,10 +736,9 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) {
rp = &r[rpi]
rel = &sect.rel[j]
if rel.scattered != 0 {
- if Thearch.Thechar != '8' {
+ if SysArch.Family != sys.I386 {
// mach-o only uses scattered relocation on 32-bit platforms
Diag("unexpected scattered relocation")
-
continue
}
@@ -821,7 +832,7 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) {
rp.Off = int32(rel.addr)
// Handle X86_64_RELOC_SIGNED referencing a section (rel->extrn == 0).
- if Thearch.Thechar == '6' && rel.extrn == 0 && rel.type_ == 1 {
+ if SysArch.Family == sys.AMD64 && rel.extrn == 0 && rel.type_ == 1 {
// Calculate the addend as the offset into the section.
//
// The rip-relative offset stored in the object file is encoded
@@ -847,7 +858,7 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) {
// For i386 Mach-O PC-relative, the addend is written such that
// it *is* the PC being subtracted. Use that to make
// it match our version of PC-relative.
- if rel.pcrel != 0 && Thearch.Thechar == '8' {
+ if rel.pcrel != 0 && SysArch.Family == sys.I386 {
rp.Add += int64(rp.Off) + int64(rp.Siz)
}
if rel.extrn == 0 {
@@ -866,7 +877,7 @@ func ldmacho(f *obj.Biobuf, pkg string, length int64, pn string) {
// include that information in the addend.
// We only care about the delta from the
// section base.
- if Thearch.Thechar == '8' {
+ if SysArch.Family == sys.I386 {
rp.Add -= int64(c.seg.sect[rel.symnum-1].addr)
}
} else {
diff --git a/src/cmd/link/internal/ld/ldpe.go b/src/cmd/link/internal/ld/ldpe.go
index 5c3e99c44f..7eb26bcbe8 100644
--- a/src/cmd/link/internal/ld/ldpe.go
+++ b/src/cmd/link/internal/ld/ldpe.go
@@ -5,9 +5,12 @@
package ld
import (
+ "cmd/internal/bio"
"cmd/internal/obj"
+ "cmd/internal/sys"
"encoding/binary"
"fmt"
+ "io"
"log"
"sort"
"strconv"
@@ -116,7 +119,7 @@ type PeSect struct {
}
type PeObj struct {
- f *obj.Biobuf
+ f *bio.Reader
name string
base uint32
sect []PeSect
@@ -127,14 +130,14 @@ type PeObj struct {
snames []byte
}
-func ldpe(f *obj.Biobuf, pkg string, length int64, pn string) {
+func ldpe(f *bio.Reader, pkg string, length int64, pn string) {
if Debug['v'] != 0 {
- fmt.Fprintf(&Bso, "%5.2f ldpe %s\n", obj.Cputime(), pn)
+ fmt.Fprintf(Bso, "%5.2f ldpe %s\n", obj.Cputime(), pn)
}
var sect *PeSect
Ctxt.IncVersion()
- base := int32(obj.Boffset(f))
+ base := f.Offset()
peobj := new(PeObj)
peobj.f = f
@@ -172,15 +175,15 @@ func ldpe(f *obj.Biobuf, pkg string, length int64, pn string) {
// TODO return error if found .cormeta
// load string table
- obj.Bseek(f, int64(base)+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(peobj.fh.NumberOfSymbols), 0)
+ f.Seek(base+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(peobj.fh.NumberOfSymbols), 0)
- if obj.Bread(f, symbuf[:4]) != 4 {
+ if _, err := io.ReadFull(f, symbuf[:4]); err != nil {
goto bad
}
l = Le32(symbuf[:])
peobj.snames = make([]byte, l)
- obj.Bseek(f, int64(base)+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(peobj.fh.NumberOfSymbols), 0)
- if obj.Bread(f, peobj.snames) != len(peobj.snames) {
+ f.Seek(base+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(peobj.fh.NumberOfSymbols), 0)
+ if _, err := io.ReadFull(f, peobj.snames); err != nil {
goto bad
}
@@ -200,10 +203,10 @@ func ldpe(f *obj.Biobuf, pkg string, length int64, pn string) {
peobj.pesym = make([]PeSym, peobj.fh.NumberOfSymbols)
peobj.npesym = uint(peobj.fh.NumberOfSymbols)
- obj.Bseek(f, int64(base)+int64(peobj.fh.PointerToSymbolTable), 0)
+ f.Seek(base+int64(peobj.fh.PointerToSymbolTable), 0)
for i := 0; uint32(i) < peobj.fh.NumberOfSymbols; i += numaux + 1 {
- obj.Bseek(f, int64(base)+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(i), 0)
- if obj.Bread(f, symbuf[:]) != len(symbuf) {
+ f.Seek(base+int64(peobj.fh.PointerToSymbolTable)+int64(len(symbuf))*int64(i), 0)
+ if _, err := io.ReadFull(f, symbuf[:]); err != nil {
goto bad
}
@@ -288,10 +291,10 @@ func ldpe(f *obj.Biobuf, pkg string, length int64, pn string) {
}
r = make([]Reloc, rsect.sh.NumberOfRelocations)
- obj.Bseek(f, int64(peobj.base)+int64(rsect.sh.PointerToRelocations), 0)
+ f.Seek(int64(peobj.base)+int64(rsect.sh.PointerToRelocations), 0)
for j = 0; j < int(rsect.sh.NumberOfRelocations); j++ {
rp = &r[j]
- if obj.Bread(f, symbuf[:10]) != 10 {
+ if _, err := io.ReadFull(f, symbuf[:10]); err != nil {
goto bad
}
rva := Le32(symbuf[0:])
@@ -432,19 +435,13 @@ func ldpe(f *obj.Biobuf, pkg string, length int64, pn string) {
log.Fatalf("symbol %s listed multiple times", s.Name)
}
s.Attr |= AttrOnList
- if Ctxt.Etextp != nil {
- Ctxt.Etextp.Next = s
- } else {
- Ctxt.Textp = s
- }
- Ctxt.Etextp = s
+ Ctxt.Textp = append(Ctxt.Textp, s)
for s = s.Sub; s != nil; s = s.Sub {
if s.Attr.OnList() {
log.Fatalf("symbol %s listed multiple times", s.Name)
}
s.Attr |= AttrOnList
- Ctxt.Etextp.Next = s
- Ctxt.Etextp = s
+ Ctxt.Textp = append(Ctxt.Textp, s)
}
}
}
@@ -464,7 +461,10 @@ func pemap(peobj *PeObj, sect *PeSect) int {
if sect.sh.PointerToRawData == 0 { // .bss doesn't have data in object file
return 0
}
- if obj.Bseek(peobj.f, int64(peobj.base)+int64(sect.sh.PointerToRawData), 0) < 0 || obj.Bread(peobj.f, sect.base) != len(sect.base) {
+ if peobj.f.Seek(int64(peobj.base)+int64(sect.sh.PointerToRawData), 0) < 0 {
+ return -1
+ }
+ if _, err := io.ReadFull(peobj.f, sect.base); err != nil {
return -1
}
@@ -492,7 +492,7 @@ func readpesym(peobj *PeObj, i int, y **PeSym) (err error) {
if strings.HasPrefix(name, "__imp_") {
name = name[6:] // __imp_Name => Name
}
- if Thearch.Thechar == '8' && name[0] == '_' {
+ if SysArch.Family == sys.I386 && name[0] == '_' {
name = name[1:] // _Name => Name
}
}
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 5616700445..53428bb1c6 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -33,7 +33,9 @@ package ld
import (
"bufio"
"bytes"
+ "cmd/internal/bio"
"cmd/internal/obj"
+ "cmd/internal/sys"
"crypto/sha1"
"debug/elf"
"encoding/binary"
@@ -82,14 +84,9 @@ import (
// THE SOFTWARE.
type Arch struct {
- Thechar int
- Ptrsize int
- Intsize int
- Regsize int
Funcalign int
Maxalign int
Minalign int
- Minlc int
Dwarfregsp int
Dwarfreglr int
Linuxdynld string
@@ -133,7 +130,6 @@ func (r *Rpath) String() string {
var (
Thearch Arch
- datap *LSym
Debug [128]int
Lcsize int32
rpath Rpath
@@ -191,8 +187,7 @@ func UseRelro() bool {
}
var (
- Thestring string
- Thelinkarch *LinkArch
+ SysArch *sys.Arch
outfile string
dynexp []*LSym
dynlib []string
@@ -201,6 +196,7 @@ var (
Funcalign int
iscgo bool
elfglobalsymndx int
+ flag_dumpdep bool
flag_installsuffix string
flag_race int
flag_msan int
@@ -245,9 +241,10 @@ const (
var (
headstring string
// buffered output
- Bso obj.Biobuf
+ Bso *bufio.Writer
)
+// TODO(dfc) outBuf duplicates bio.Writer
type outBuf struct {
w *bufio.Writer
f *os.File
@@ -472,7 +469,7 @@ func loadinternal(name string) {
if Linkshared {
shlibname := filepath.Join(Ctxt.Libdir[i], name+".shlibname")
if Debug['v'] != 0 {
- fmt.Fprintf(&Bso, "searching for %s.a in %s\n", name, shlibname)
+ fmt.Fprintf(Bso, "searching for %s.a in %s\n", name, shlibname)
}
if _, err := os.Stat(shlibname); err == nil {
addlibpath(Ctxt, "internal", "internal", "", name, shlibname)
@@ -482,7 +479,7 @@ func loadinternal(name string) {
}
pname := filepath.Join(Ctxt.Libdir[i], name+".a")
if Debug['v'] != 0 {
- fmt.Fprintf(&Bso, "searching for %s.a in %s\n", name, pname)
+ fmt.Fprintf(Bso, "searching for %s.a in %s\n", name, pname)
}
if _, err := os.Stat(pname); err == nil {
addlibpath(Ctxt, "internal", "internal", pname, name, "")
@@ -492,7 +489,7 @@ func loadinternal(name string) {
}
if found == 0 {
- fmt.Fprintf(&Bso, "warning: unable to find %s.a\n", name)
+ fmt.Fprintf(Bso, "warning: unable to find %s.a\n", name)
}
}
@@ -509,7 +506,7 @@ func loadlib() {
}
loadinternal("runtime")
- if Thearch.Thechar == '5' {
+ if SysArch.Family == sys.ARM {
loadinternal("math")
}
if flag_race != 0 {
@@ -524,7 +521,7 @@ func loadlib() {
iscgo = iscgo || Ctxt.Library[i].Pkg == "runtime/cgo"
if Ctxt.Library[i].Shlib == "" {
if Debug['v'] > 1 {
- fmt.Fprintf(&Bso, "%5.2f autolib: %s (from %s)\n", obj.Cputime(), Ctxt.Library[i].File, Ctxt.Library[i].Objref)
+ fmt.Fprintf(Bso, "%5.2f autolib: %s (from %s)\n", obj.Cputime(), Ctxt.Library[i].File, Ctxt.Library[i].Objref)
}
objfile(Ctxt.Library[i])
}
@@ -533,7 +530,7 @@ func loadlib() {
for i = 0; i < len(Ctxt.Library); i++ {
if Ctxt.Library[i].Shlib != "" {
if Debug['v'] > 1 {
- fmt.Fprintf(&Bso, "%5.2f autolib: %s (from %s)\n", obj.Cputime(), Ctxt.Library[i].Shlib, Ctxt.Library[i].Objref)
+ fmt.Fprintf(Bso, "%5.2f autolib: %s (from %s)\n", obj.Cputime(), Ctxt.Library[i].Shlib, Ctxt.Library[i].Objref)
}
ldshlibsyms(Ctxt.Library[i].Shlib)
}
@@ -562,7 +559,7 @@ func loadlib() {
// dependency problems when compiling natively (external linking requires
// runtime/cgo, runtime/cgo requires cmd/cgo, but cmd/cgo needs to be
// compiled using external linking.)
- if (Thearch.Thechar == '5' || Thearch.Thechar == '7') && HEADTYPE == obj.Hdarwin && iscgo {
+ if SysArch.InFamily(sys.ARM, sys.ARM64) && HEADTYPE == obj.Hdarwin && iscgo {
Linkmode = LinkExternal
}
@@ -621,7 +618,7 @@ func loadlib() {
// a variable to hold g in assembly (currently only intel).
if tlsg.Type == 0 {
tlsg.Type = obj.STLSBSS
- tlsg.Size = int64(Thearch.Ptrsize)
+ tlsg.Size = int64(SysArch.PtrSize)
} else if tlsg.Type != obj.SDYNIMPORT {
Diag("internal error: runtime declared tlsg variable %d", tlsg.Type)
}
@@ -639,7 +636,7 @@ func loadlib() {
// In addition, on ARM, the runtime depends on the linker
// recording the value of GOARM.
- if Thearch.Thechar == '5' {
+ if SysArch.Family == sys.ARM {
s := Linklookup(Ctxt, "runtime.goarm", 0)
s.Type = obj.SRODATA
@@ -696,13 +693,13 @@ func loadlib() {
args := hostlinkArchArgs()
args = append(args, "--print-libgcc-file-name")
if Debug['v'] != 0 {
- fmt.Fprintf(&Bso, "%s %v\n", extld, args)
+ fmt.Fprintf(Bso, "%s %v\n", extld, args)
}
out, err := exec.Command(extld, args...).Output()
if err != nil {
if Debug['v'] != 0 {
- fmt.Fprintln(&Bso, "not using a libgcc file because compiler failed")
- fmt.Fprintf(&Bso, "%v\n%s\n", err, out)
+ fmt.Fprintln(Bso, "not using a libgcc file because compiler failed")
+ fmt.Fprintf(Bso, "%v\n%s\n", err, out)
}
libgccfile = "none"
} else {
@@ -743,17 +740,17 @@ func loadlib() {
* look for the next file in an archive.
* adapted from libmach.
*/
-func nextar(bp *obj.Biobuf, off int64, a *ArHdr) int64 {
+func nextar(bp *bio.Reader, off int64, a *ArHdr) int64 {
if off&1 != 0 {
off++
}
- obj.Bseek(bp, off, 0)
- buf := make([]byte, SAR_HDR)
- if n := obj.Bread(bp, buf); n < len(buf) {
- if n >= 0 {
- return 0
+ bp.Seek(off, 0)
+ var buf [SAR_HDR]byte
+ if n, err := io.ReadFull(bp, buf[:]); err != nil {
+ if n == 0 && err != io.EOF {
+ return -1
}
- return -1
+ return 0
}
a.name = artrim(buf[0:16])
@@ -768,35 +765,38 @@ func nextar(bp *obj.Biobuf, off int64, a *ArHdr) int64 {
if arsize&1 != 0 {
arsize++
}
- return int64(arsize) + SAR_HDR
+ return arsize + SAR_HDR
}
func objfile(lib *Library) {
pkg := pathtoprefix(lib.Pkg)
if Debug['v'] > 1 {
- fmt.Fprintf(&Bso, "%5.2f ldobj: %s (%s)\n", obj.Cputime(), lib.File, pkg)
+ fmt.Fprintf(Bso, "%5.2f ldobj: %s (%s)\n", obj.Cputime(), lib.File, pkg)
}
Bso.Flush()
- f, err := obj.Bopenr(lib.File)
+ f, err := bio.Open(lib.File)
if err != nil {
Exitf("cannot open file %s: %v", lib.File, err)
}
- magbuf := make([]byte, len(ARMAG))
- if obj.Bread(f, magbuf) != len(magbuf) || !strings.HasPrefix(string(magbuf), ARMAG) {
+ for i := 0; i < len(ARMAG); i++ {
+ if c, err := f.ReadByte(); err == nil && c == ARMAG[i] {
+ continue
+ }
+
/* load it as a regular file */
- l := obj.Bseek(f, 0, 2)
+ l := f.Seek(0, 2)
- obj.Bseek(f, 0, 0)
+ f.Seek(0, 0)
ldobj(f, pkg, l, lib.File, lib.File, FileObj)
- obj.Bterm(f)
+ f.Close()
return
}
/* process __.PKGDEF */
- off := obj.Boffset(f)
+ off := f.Offset()
var arhdr ArHdr
l := nextar(f, off, &arhdr)
@@ -812,12 +812,14 @@ func objfile(lib *Library) {
}
if Buildmode == BuildmodeShared {
- before := obj.Boffset(f)
+ before := f.Offset()
pkgdefBytes := make([]byte, atolwhex(arhdr.size))
- obj.Bread(f, pkgdefBytes)
+ if _, err := io.ReadFull(f, pkgdefBytes); err != nil {
+ Diag("%s: short read on archive file symbol header: %v", lib.File, err)
+ }
hash := sha1.Sum(pkgdefBytes)
lib.hash = hash[:]
- obj.Bseek(f, before, 0)
+ f.Seek(before, 0)
}
off += l
@@ -853,11 +855,11 @@ func objfile(lib *Library) {
}
out:
- obj.Bterm(f)
+ f.Close()
}
type Hostobj struct {
- ld func(*obj.Biobuf, string, int64, string)
+ ld func(*bio.Reader, string, int64, string)
pkg string
pn string
file string
@@ -878,7 +880,7 @@ var internalpkg = []string{
"runtime/msan",
}
-func ldhostobj(ld func(*obj.Biobuf, string, int64, string), f *obj.Biobuf, pkg string, length int64, pn string, file string) *Hostobj {
+func ldhostobj(ld func(*bio.Reader, string, int64, string), f *bio.Reader, pkg string, length int64, pn string, file string) *Hostobj {
isinternal := false
for i := 0; i < len(internalpkg); i++ {
if pkg == internalpkg[i] {
@@ -909,26 +911,24 @@ func ldhostobj(ld func(*obj.Biobuf, string, int64, string), f *obj.Biobuf, pkg s
h.pkg = pkg
h.pn = pn
h.file = file
- h.off = obj.Boffset(f)
+ h.off = f.Offset()
h.length = length
return h
}
func hostobjs() {
- var f *obj.Biobuf
var h *Hostobj
for i := 0; i < len(hostobj); i++ {
h = &hostobj[i]
- var err error
- f, err = obj.Bopenr(h.file)
- if f == nil {
+ f, err := bio.Open(h.file)
+ if err != nil {
Exitf("cannot reopen %s: %v", h.pn, err)
}
- obj.Bseek(f, h.off, 0)
+ f.Seek(h.off, 0)
h.ld(f, h.pkg, h.length, h.pn)
- obj.Bterm(f)
+ f.Close()
}
}
@@ -1040,7 +1040,7 @@ func archive() {
argv = append(argv, hostobjCopy()...)
if Debug['v'] != 0 {
- fmt.Fprintf(&Bso, "archive: %s\n", strings.Join(argv, " "))
+ fmt.Fprintf(Bso, "archive: %s\n", strings.Join(argv, " "))
Bso.Flush()
}
@@ -1117,6 +1117,23 @@ func hostlink() {
// because lazy PLT resolution can use large amounts of stack at
// times we cannot allow it to do so.
argv = append(argv, "-Wl,-znow")
+
+ // Do not let the host linker generate COPY relocations. These
+ // can move symbols out of sections that rely on stable offsets
+ // from the beginning of the section (like STYPE).
+ argv = append(argv, "-Wl,-znocopyreloc")
+
+ if SysArch.InFamily(sys.ARM, sys.ARM64) {
+ // On ARM, the GNU linker will generate COPY relocations
+ // even with -znocopyreloc set.
+ // https://sourceware.org/bugzilla/show_bug.cgi?id=19962
+ //
+ // On ARM64, the GNU linker will fail instead of
+ // generating COPY relocations.
+ //
+ // In both cases, switch to gold.
+ argv = append(argv, "-fuse-ld=gold")
+ }
}
if Iself && len(buildinfo) > 0 {
@@ -1187,6 +1204,24 @@ func hostlink() {
argv = append(argv, ldflag...)
+ if flag_race != 0 {
+ // On a system where the toolchain creates position independent
+ // executables by default, tsan initialization can fail. So we pass
+ // -no-pie here, but support for that flag is quite new and we test
+ // for its support first.
+ src := filepath.Join(tmpdir, "trivial.c")
+ if err := ioutil.WriteFile(src, []byte{}, 0666); err != nil {
+ Ctxt.Diag("WriteFile trivial.c failed: %v", err)
+ }
+ cmd := exec.Command(argv[0], "-no-pie", "trivial.c")
+ cmd.Dir = tmpdir
+ out, err := cmd.CombinedOutput()
+ supported := err == nil && !bytes.Contains(out, []byte("unrecognized"))
+ if supported {
+ argv = append(argv, "-no-pie")
+ }
+ }
+
for _, p := range strings.Fields(extldflags) {
argv = append(argv, p)
@@ -1209,24 +1244,24 @@ func hostlink() {
}
if Debug['v'] != 0 {
- fmt.Fprintf(&Bso, "host link:")
+ fmt.Fprintf(Bso, "host link:")
for _, v := range argv {
- fmt.Fprintf(&Bso, " %q", v)
+ fmt.Fprintf(Bso, " %q", v)
}
- fmt.Fprintf(&Bso, "\n")
+ fmt.Fprintf(Bso, "\n")
Bso.Flush()
}
if out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput(); err != nil {
Exitf("running %s failed: %v\n%s", argv[0], err, out)
} else if Debug['v'] != 0 && len(out) > 0 {
- fmt.Fprintf(&Bso, "%s", out)
+ fmt.Fprintf(Bso, "%s", out)
Bso.Flush()
}
if Debug['s'] == 0 && debug_s == 0 && HEADTYPE == obj.Hdarwin {
// Skip combining dwarf on arm.
- if Thearch.Thechar != '5' && Thearch.Thechar != '7' {
+ if !SysArch.InFamily(sys.ARM, sys.ARM64) {
dsym := filepath.Join(tmpdir, "go.dwarf")
if out, err := exec.Command("dsymutil", "-f", outfile, "-o", dsym).CombinedOutput(); err != nil {
Ctxt.Cursym = nil
@@ -1254,14 +1289,14 @@ func hostlink() {
// hostlinkArchArgs returns arguments to pass to the external linker
// based on the architecture.
func hostlinkArchArgs() []string {
- switch Thearch.Thechar {
- case '8':
+ switch SysArch.Family {
+ case sys.I386:
return []string{"-m32"}
- case '6', '9', 'z':
+ case sys.AMD64, sys.PPC64, sys.S390X:
return []string{"-m64"}
- case '5':
+ case sys.ARM:
return []string{"-marm"}
- case '7':
+ case sys.ARM64:
// nothing needed
}
return nil
@@ -1270,15 +1305,15 @@ func hostlinkArchArgs() []string {
// ldobj loads an input object. If it is a host object (an object
// compiled by a non-Go compiler) it returns the Hostobj pointer. If
// it is a Go object, it returns nil.
-func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, whence int) *Hostobj {
- eof := obj.Boffset(f) + length
+func ldobj(f *bio.Reader, pkg string, length int64, pn string, file string, whence int) *Hostobj {
+ eof := f.Offset() + length
- start := obj.Boffset(f)
- c1 := obj.Bgetc(f)
- c2 := obj.Bgetc(f)
- c3 := obj.Bgetc(f)
- c4 := obj.Bgetc(f)
- obj.Bseek(f, start, 0)
+ start := f.Offset()
+ c1 := bgetc(f)
+ c2 := bgetc(f)
+ c3 := bgetc(f)
+ c4 := bgetc(f)
+ f.Seek(start, 0)
magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4)
if magic == 0x7f454c46 { // \x7F E L F
@@ -1294,22 +1329,19 @@ func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, when
}
/* check the header */
- line := obj.Brdline(f, '\n')
- if line == "" {
- if obj.Blinelen(f) > 0 {
- Diag("%s: not an object file", pn)
- return nil
- }
- Diag("truncated object file: %s", pn)
+ line, err := f.ReadString('\n')
+ if err != nil {
+ Diag("truncated object file: %s: %v", pn, err)
return nil
}
if !strings.HasPrefix(line, "go object ") {
if strings.HasSuffix(pn, ".go") {
- Exitf("%cl: input %s is not .%c file (use %cg to compile .go files)", Thearch.Thechar, pn, Thearch.Thechar, Thearch.Thechar)
+ Exitf("%s: uncompiled .go source file", pn)
+ return nil
}
- if line == Thestring {
+ if line == SysArch.Name {
// old header format: just $GOOS
Diag("%s: stale object file", pn)
return nil
@@ -1341,28 +1373,28 @@ func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, when
}
/* skip over exports and other info -- ends with \n!\n */
- import0 := obj.Boffset(f)
+ import0 := f.Offset()
c1 = '\n' // the last line ended in \n
- c2 = obj.Bgetc(f)
- c3 = obj.Bgetc(f)
+ c2 = bgetc(f)
+ c3 = bgetc(f)
for c1 != '\n' || c2 != '!' || c3 != '\n' {
c1 = c2
c2 = c3
- c3 = obj.Bgetc(f)
- if c3 == obj.Beof {
+ c3 = bgetc(f)
+ if c3 == -1 {
Diag("truncated object file: %s", pn)
return nil
}
}
- import1 := obj.Boffset(f)
+ import1 := f.Offset()
- obj.Bseek(f, import0, 0)
+ f.Seek(import0, 0)
ldpkg(f, pkg, import1-import0-2, pn, whence) // -2 for !\n
- obj.Bseek(f, import1, 0)
+ f.Seek(import1, 0)
- LoadObjFile(Ctxt, f, pkg, eof-obj.Boffset(f), pn)
+ LoadObjFile(Ctxt, f, pkg, eof-f.Offset(), pn)
return nil
}
@@ -1500,12 +1532,12 @@ func ldshlibsyms(shlib string) {
// the type data.
if strings.HasPrefix(lsym.Name, "type.") && !strings.HasPrefix(lsym.Name, "type..") {
lsym.P = readelfsymboldata(f, &elfsym)
- gcdata_locations[elfsym.Value+2*uint64(Thearch.Ptrsize)+8+1*uint64(Thearch.Ptrsize)] = lsym
+ gcdata_locations[elfsym.Value+2*uint64(SysArch.PtrSize)+8+1*uint64(SysArch.PtrSize)] = lsym
}
}
}
gcdata_addresses := make(map[*LSym]uint64)
- if Thearch.Thechar == '7' {
+ if SysArch.Family == sys.ARM64 {
for _, sect := range f.Sections {
if sect.Type == elf.SHT_RELA {
var rela elf.Rela64
@@ -1532,30 +1564,14 @@ func ldshlibsyms(shlib string) {
// 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 unstitch them from the Textp linked
- // list.
- var last *LSym
-
- for s := Ctxt.Textp; s != nil; s = s.Next {
- if s.Type == obj.SDYNIMPORT {
- continue
- }
-
- if last == nil {
- Ctxt.Textp = s
- } else {
- last.Next = s
+ // pcln table entries for these any more so remove them from Textp.
+ textp := make([]*LSym, 0, len(Ctxt.Textp))
+ for _, s := range Ctxt.Textp {
+ if s.Type != obj.SDYNIMPORT {
+ textp = append(textp, s)
}
- last = s
- }
-
- if last == nil {
- Ctxt.Textp = nil
- Ctxt.Etextp = nil
- } else {
- last.Next = nil
- Ctxt.Etextp = last
}
+ Ctxt.Textp = textp
Ctxt.Shlibs = append(Ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f, gcdata_addresses: gcdata_addresses})
}
@@ -1564,10 +1580,6 @@ func mywhatsys() {
goroot = obj.Getgoroot()
goos = obj.Getgoos()
goarch = obj.Getgoarch()
-
- if !strings.HasPrefix(goarch, Thestring) {
- log.Fatalf("cannot use %cc with GOARCH=%s", Thearch.Thechar, goarch)
- }
}
// Copied from ../gc/subr.c:/^pathtoprefix; must stay in sync.
@@ -1608,7 +1620,7 @@ func addsection(seg *Segment, name string, rwx int) *Section {
sect.Rwx = uint8(rwx)
sect.Name = name
sect.Seg = seg
- sect.Align = int32(Thearch.Ptrsize) // everything is at least pointer-aligned
+ sect.Align = int32(SysArch.PtrSize) // everything is at least pointer-aligned
*l = sect
return sect
}
@@ -1652,7 +1664,7 @@ func callsize() int {
if haslinkregister() {
return 0
}
- return Thearch.Regsize
+ return SysArch.RegSize
}
func dostkcheck() {
@@ -1673,7 +1685,7 @@ func dostkcheck() {
// Check every function, but do the nosplit functions in a first pass,
// to make the printed failure chains as short as possible.
- for s := Ctxt.Textp; s != nil; s = s.Next {
+ for _, s := range Ctxt.Textp {
// runtime.racesymbolizethunk is called from gcc-compiled C
// code running on the operating system thread stack.
// It uses more than the usual amount of stack but that's okay.
@@ -1688,7 +1700,7 @@ func dostkcheck() {
}
}
- for s := Ctxt.Textp; s != nil; s = s.Next {
+ for _, s := range Ctxt.Textp {
if !s.Attr.NoSplit() {
Ctxt.Cursym = s
ch.sym = s
@@ -1717,7 +1729,7 @@ func stkcheck(up *Chain, depth int) int {
return -1
}
- if s.Attr.External() || s.Pcln == nil {
+ if s.Attr.External() || s.FuncInfo == nil {
// external function.
// should never be called directly.
// only diagnose the direct caller.
@@ -1754,7 +1766,11 @@ func stkcheck(up *Chain, depth int) int {
return 0
}
// Raise limit to allow frame.
- limit = int(obj.StackLimit+s.Locals) + int(Ctxt.FixedFrameSize())
+ locals := int32(0)
+ if s.FuncInfo != nil {
+ locals = s.FuncInfo.Locals
+ }
+ limit = int(obj.StackLimit+locals) + int(Ctxt.FixedFrameSize())
}
// Walk through sp adjustments in function, consuming relocs.
@@ -1764,7 +1780,7 @@ func stkcheck(up *Chain, depth int) int {
var ch1 Chain
var pcsp Pciter
var r *Reloc
- for pciterinit(Ctxt, &pcsp, &s.Pcln.Pcsp); pcsp.done == 0; pciternext(&pcsp) {
+ for pciterinit(Ctxt, &pcsp, &s.FuncInfo.Pcsp); pcsp.done == 0; pciternext(&pcsp) {
// pcsp.value is in effect for [pcsp.pc, pcsp.nextpc).
// Check stack size in effect for this span.
@@ -1956,7 +1972,7 @@ func genasmsym(put func(*LSym, string, int, int64, int64, int, *LSym)) {
continue
}
if len(s.P) > 0 {
- Diag("%s should not be bss (size=%d type=%d special=%v)", s.Name, int(len(s.P)), s.Type, s.Attr.Special())
+ Diag("%s should not be bss (size=%d type=%d special=%v)", s.Name, len(s.P), s.Type, s.Attr.Special())
}
put(s, s.Name, 'B', Symaddr(s), s.Size, int(s.Version), s.Gotype)
@@ -1982,13 +1998,20 @@ func genasmsym(put func(*LSym, string, int, int64, int64, int, *LSym)) {
}
var off int32
- for s := Ctxt.Textp; s != nil; s = s.Next {
+ for _, s := range Ctxt.Textp {
put(s, s.Name, 'T', s.Value, s.Size, int(s.Version), s.Gotype)
+ locals := int32(0)
+ if s.FuncInfo != nil {
+ locals = s.FuncInfo.Locals
+ }
// NOTE(ality): acid can't produce a stack trace without .frame symbols
- put(nil, ".frame", 'm', int64(s.Locals)+int64(Thearch.Ptrsize), 0, 0, nil)
+ put(nil, ".frame", 'm', int64(locals)+int64(SysArch.PtrSize), 0, 0, nil)
- for _, a := range s.Autom {
+ if s.FuncInfo == nil {
+ continue
+ }
+ for _, a := range s.FuncInfo.Autom {
// Emit a or p according to actual offset, even if label is wrong.
// This avoids negative offsets, which cannot be encoded.
if a.Name != obj.A_AUTO && a.Name != obj.A_PARAM {
@@ -1999,7 +2022,7 @@ func genasmsym(put func(*LSym, string, int, int64, int64, int, *LSym)) {
if a.Name == obj.A_PARAM {
off = a.Aoffset
} else {
- off = a.Aoffset - int32(Thearch.Ptrsize)
+ off = a.Aoffset - int32(SysArch.PtrSize)
}
// FP
@@ -2009,8 +2032,8 @@ func genasmsym(put func(*LSym, string, int, int64, int64, int, *LSym)) {
}
// SP
- if off <= int32(-Thearch.Ptrsize) {
- put(nil, a.Asym.Name, 'a', -(int64(off) + int64(Thearch.Ptrsize)), 0, 0, a.Gotype)
+ if off <= int32(-SysArch.PtrSize) {
+ put(nil, a.Asym.Name, 'a', -(int64(off) + int64(SysArch.PtrSize)), 0, 0, a.Gotype)
continue
}
}
@@ -2019,7 +2042,7 @@ func genasmsym(put func(*LSym, string, int, int64, int64, int, *LSym)) {
// Otherwise, off is addressing the saved program counter.
// Something underhanded is going on. Say nothing.
if Debug['v'] != 0 || Debug['n'] != 0 {
- fmt.Fprintf(&Bso, "%5.2f symsize = %d\n", obj.Cputime(), uint32(Symsize))
+ fmt.Fprintf(Bso, "%5.2f symsize = %d\n", obj.Cputime(), uint32(Symsize))
}
Bso.Flush()
}
@@ -2085,10 +2108,10 @@ func undefsym(s *LSym) {
}
func undef() {
- for s := Ctxt.Textp; s != nil; s = s.Next {
+ for _, s := range Ctxt.Textp {
undefsym(s)
}
- for s := datap; s != nil; s = s.Next {
+ for _, s := range datap {
undefsym(s)
}
if nerrors > 0 {
@@ -2103,14 +2126,14 @@ func callgraph() {
var i int
var r *Reloc
- for s := Ctxt.Textp; s != nil; s = s.Next {
+ for _, s := range Ctxt.Textp {
for i = 0; i < len(s.R); i++ {
r = &s.R[i]
if r.Sym == nil {
continue
}
if (r.Type == obj.R_CALL || r.Type == obj.R_CALLARM || r.Type == obj.R_CALLPOWER || r.Type == obj.R_CALLMIPS) && r.Sym.Type == obj.STEXT {
- fmt.Fprintf(&Bso, "%s calls %s\n", s.Name, r.Sym.Name)
+ fmt.Fprintf(Bso, "%s calls %s\n", s.Name, r.Sym.Name)
}
}
}
@@ -2145,3 +2168,14 @@ func Rnd(v int64, r int64) int64 {
v -= c
return v
}
+
+func bgetc(r *bio.Reader) int {
+ c, err := r.ReadByte()
+ if err != nil {
+ if err != io.EOF {
+ log.Fatalf("reading input: %v", err)
+ }
+ return -1
+ }
+ return int(c)
+}
diff --git a/src/cmd/link/internal/ld/link.go b/src/cmd/link/internal/ld/link.go
index 67a855933e..d0515d4617 100644
--- a/src/cmd/link/internal/ld/link.go
+++ b/src/cmd/link/internal/ld/link.go
@@ -31,9 +31,9 @@
package ld
import (
- "cmd/internal/obj"
+ "bufio"
+ "cmd/internal/sys"
"debug/elf"
- "encoding/binary"
"fmt"
)
@@ -50,8 +50,6 @@ type LSym struct {
Align int32
Elfsym int32
LocalElfsym int32
- Args int32
- Locals int32
Value int64
Size int64
// ElfType is set for symbols read from shared libraries by ldshlibsyms. It
@@ -67,8 +65,7 @@ type LSym struct {
Dynimplib string
Dynimpvers string
Sect *Section
- Autom []Auto
- Pcln *Pcln
+ FuncInfo *FuncInfo
P []byte
R []Reloc
}
@@ -161,13 +158,11 @@ type Shlib struct {
}
type Link struct {
- Thechar int32
- Thestring string
Goarm int32
Headtype int
- Arch *LinkArch
+ Arch *sys.Arch
Debugvlog int32
- Bso *obj.Biobuf
+ Bso *bufio.Writer
Windows int32
Goroot string
@@ -183,10 +178,8 @@ type Link struct {
Diag func(string, ...interface{})
Cursym *LSym
Version int
- Textp *LSym
- Etextp *LSym
- Nhistfile int32
- Filesyms *LSym
+ Textp []*LSym
+ Filesyms []*LSym
Moduledata *LSym
LSymBatch []LSym
}
@@ -196,15 +189,15 @@ type Link struct {
// on the stack in the function prologue and so always have a pointer between
// the hardware stack pointer and the local variable area.
func (ctxt *Link) FixedFrameSize() int64 {
- switch ctxt.Arch.Thechar {
- case '6', '8':
+ switch ctxt.Arch.Family {
+ case sys.AMD64, sys.I386:
return 0
- case '9':
+ case sys.PPC64:
// PIC code on ppc64le requires 32 bytes of stack, and it's easier to
// just use that much stack always on ppc64x.
- return int64(4 * ctxt.Arch.Ptrsize)
+ return int64(4 * ctxt.Arch.PtrSize)
default:
- return int64(ctxt.Arch.Ptrsize)
+ return int64(ctxt.Arch.PtrSize)
}
}
@@ -213,15 +206,6 @@ func (l *Link) IncVersion() {
l.Hash = append(l.Hash, make(map[string]*LSym))
}
-type LinkArch struct {
- ByteOrder binary.ByteOrder
- Name string
- Thechar int
- Minlc int
- Ptrsize int
- Regsize int
-}
-
type Library struct {
Objref string
Srcref string
@@ -231,7 +215,10 @@ type Library struct {
hash []byte
}
-type Pcln struct {
+type FuncInfo struct {
+ Args int32
+ Locals int32
+ Autom []Auto
Pcsp Pcdata
Pcfile Pcdata
Pcline Pcdata
diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go
index d60203fb91..53cc96275d 100644
--- a/src/cmd/link/internal/ld/macho.go
+++ b/src/cmd/link/internal/ld/macho.go
@@ -6,6 +6,7 @@ package ld
import (
"cmd/internal/obj"
+ "cmd/internal/sys"
"sort"
"strings"
)
@@ -78,6 +79,8 @@ const (
MACHO_X86_64_RELOC_SIGNED_2 = 7
MACHO_X86_64_RELOC_SIGNED_4 = 8
MACHO_ARM_RELOC_VANILLA = 0
+ MACHO_ARM_RELOC_PAIR = 1
+ MACHO_ARM_RELOC_SECTDIFF = 2
MACHO_ARM_RELOC_BR24 = 5
MACHO_ARM64_RELOC_UNSIGNED = 0
MACHO_ARM64_RELOC_BRANCH26 = 2
@@ -131,15 +134,7 @@ var nsortsym int
var load_budget int = INITIAL_MACHO_HEADR - 2*1024
func Machoinit() {
- switch Thearch.Thechar {
- // 64-bit architectures
- case '6', '7', '9':
- macho64 = true
-
- // 32-bit architectures
- default:
- break
- }
+ macho64 = SysArch.RegSize == 8
}
func getMachoHdr() *MachoHdr {
@@ -356,9 +351,10 @@ func machoshbits(mseg *MachoSeg, sect *Section, segname string) {
buf := "__" + strings.Replace(sect.Name[1:], ".", "_", -1)
var msect *MachoSect
- if sect.Rwx&1 == 0 && (Thearch.Thechar == '7' || // arm64
- (Thearch.Thechar == '6' && (Buildmode == BuildmodeCShared || Buildmode == BuildmodeCArchive))) { // amd64
- // Darwin external linker on arm64 and on amd64 in c-shared/c-archive buildmode
+ if sect.Rwx&1 == 0 && segname != "__DWARF" && (SysArch.Family == sys.ARM64 ||
+ (SysArch.Family == sys.AMD64 && (Buildmode == BuildmodeCShared || Buildmode == BuildmodeCArchive)) ||
+ (SysArch.Family == sys.ARM && (Buildmode == BuildmodeCShared || Buildmode == BuildmodeCArchive))) {
+ // Darwin external linker on arm64 and on amd64 and arm in c-shared/c-archive buildmode
// complains about absolute relocs in __TEXT, so if the section is not
// executable, put it in __DATA segment.
msect = newMachoSect(mseg, buf, "__DATA")
@@ -411,6 +407,10 @@ func machoshbits(mseg *MachoSeg, sect *Section, segname string) {
msect.name = "__mod_init_func"
msect.flag = 9 // S_MOD_INIT_FUNC_POINTERS
}
+
+ if segname == "__DWARF" {
+ msect.flag |= 0x02000000
+ }
}
func Asmbmacho() {
@@ -418,23 +418,23 @@ func Asmbmacho() {
va := INITTEXT - int64(HEADR)
mh := getMachoHdr()
- switch Thearch.Thechar {
+ switch SysArch.Family {
default:
- Exitf("unknown macho architecture: %v", Thearch.Thechar)
+ Exitf("unknown macho architecture: %v", SysArch.Family)
- case '5':
+ case sys.ARM:
mh.cpu = MACHO_CPU_ARM
mh.subcpu = MACHO_SUBCPU_ARMV7
- case '6':
+ case sys.AMD64:
mh.cpu = MACHO_CPU_AMD64
mh.subcpu = MACHO_SUBCPU_X86
- case '7':
+ case sys.ARM64:
mh.cpu = MACHO_CPU_ARM64
mh.subcpu = MACHO_SUBCPU_ARM64_ALL
- case '8':
+ case sys.I386:
mh.cpu = MACHO_CPU_386
mh.subcpu = MACHO_SUBCPU_X86
}
@@ -445,7 +445,7 @@ func Asmbmacho() {
ms = newMachoSeg("", 40)
ms.fileoffset = Segtext.Fileoff
- if Thearch.Thechar == '5' || Buildmode == BuildmodeCArchive {
+ if SysArch.Family == sys.ARM || Buildmode == BuildmodeCArchive {
ms.filesize = Segdata.Fileoff + Segdata.Filelen - Segtext.Fileoff
} else {
ms.filesize = Segdwarf.Fileoff + Segdwarf.Filelen - Segtext.Fileoff
@@ -492,32 +492,46 @@ func Asmbmacho() {
machoshbits(ms, sect, "__DATA")
}
+ /* dwarf */
+ if Debug['w'] == 0 {
+ if Linkmode != LinkExternal {
+ ms = newMachoSeg("__DWARF", 20)
+ ms.vaddr = Segdwarf.Vaddr
+ ms.vsize = 0
+ ms.fileoffset = Segdwarf.Fileoff
+ ms.filesize = Segdwarf.Filelen
+ }
+ for sect := Segdwarf.Sect; sect != nil; sect = sect.Next {
+ machoshbits(ms, sect, "__DWARF")
+ }
+ }
+
if Linkmode != LinkExternal {
- switch Thearch.Thechar {
+ switch SysArch.Family {
default:
- Exitf("unknown macho architecture: %v", Thearch.Thechar)
+ Exitf("unknown macho architecture: %v", SysArch.Family)
- case '5':
+ case sys.ARM:
ml := newMachoLoad(5, 17+2) /* unix thread */
ml.data[0] = 1 /* thread type */
ml.data[1] = 17 /* word count */
ml.data[2+15] = uint32(Entryvalue()) /* start pc */
- case '6':
+ case sys.AMD64:
ml := newMachoLoad(5, 42+2) /* unix thread */
ml.data[0] = 4 /* thread type */
ml.data[1] = 42 /* word count */
ml.data[2+32] = uint32(Entryvalue()) /* start pc */
ml.data[2+32+1] = uint32(Entryvalue() >> 32)
- case '7':
+ case sys.ARM64:
ml := newMachoLoad(5, 68+2) /* unix thread */
ml.data[0] = 6 /* thread type */
ml.data[1] = 68 /* word count */
ml.data[2+64] = uint32(Entryvalue()) /* start pc */
ml.data[2+64+1] = uint32(Entryvalue() >> 32)
- case '8':
+ case sys.I386:
ml := newMachoLoad(5, 16+2) /* unix thread */
ml.data[0] = 1 /* thread type */
ml.data[1] = 16 /* word count */
@@ -528,7 +542,6 @@ func Asmbmacho() {
if Debug['d'] == 0 {
// must match domacholink below
s1 := Linklookup(Ctxt, ".machosymtab", 0)
-
s2 := Linklookup(Ctxt, ".linkedit.plt", 0)
s3 := Linklookup(Ctxt, ".linkedit.got", 0)
s4 := Linklookup(Ctxt, ".machosymstr", 0)
@@ -576,21 +589,13 @@ func Asmbmacho() {
// and we can assume OS X.
//
// See golang.org/issues/12941.
- const (
- LC_VERSION_MIN_MACOSX = 0x24
- LC_VERSION_MIN_IPHONEOS = 0x25
- LC_VERSION_MIN_WATCHOS = 0x30
- )
+ const LC_VERSION_MIN_MACOSX = 0x24
+
ml := newMachoLoad(LC_VERSION_MIN_MACOSX, 2)
ml.data[0] = 10<<16 | 7<<8 | 0<<0 // OS X version 10.7.0
ml.data[1] = 10<<16 | 7<<8 | 0<<0 // SDK 10.7.0
}
- // TODO: dwarf headers go in ms too
- if Debug['s'] == 0 {
- dwarfaddmachoheaders(ms)
- }
-
a := machowrite()
if int32(a) > HEADR {
Exitf("HEADR too small: %d > %d", a, HEADR)
@@ -680,15 +685,11 @@ func machosymorder() {
}
func machosymtab() {
- var s *LSym
- var o *LSym
- var p string
-
symtab := Linklookup(Ctxt, ".machosymtab", 0)
symstr := Linklookup(Ctxt, ".machosymstr", 0)
for i := 0; i < nsortsym; i++ {
- s = sortsym[i]
+ s := sortsym[i]
Adduint32(Ctxt, symtab, uint32(symstr.Size))
// Only add _ to C symbols. Go symbols have dot in the name.
@@ -697,33 +698,20 @@ func machosymtab() {
}
// replace "·" as ".", because DTrace cannot handle it.
- if !strings.Contains(s.Extname, "·") {
- Addstring(symstr, s.Extname)
- } else {
- for p = s.Extname; p != ""; p = p[1:] {
- if uint8(p[0]) == 0xc2 && uint8((p[1:])[0]) == 0xb7 {
- Adduint8(Ctxt, symstr, '.')
- p = p[1:]
- } else {
- Adduint8(Ctxt, symstr, uint8(p[0]))
- }
- }
-
- Adduint8(Ctxt, symstr, '\x00')
- }
+ Addstring(symstr, strings.Replace(s.Extname, "·", ".", -1))
if s.Type == obj.SDYNIMPORT || s.Type == obj.SHOSTOBJ {
Adduint8(Ctxt, symtab, 0x01) // type N_EXT, external symbol
Adduint8(Ctxt, symtab, 0) // no section
Adduint16(Ctxt, symtab, 0) // desc
- adduintxx(Ctxt, symtab, 0, Thearch.Ptrsize) // no value
+ adduintxx(Ctxt, symtab, 0, SysArch.PtrSize) // no value
} else {
if s.Attr.CgoExport() {
Adduint8(Ctxt, symtab, 0x0f)
} else {
Adduint8(Ctxt, symtab, 0x0e)
}
- o = s
+ o := s
for o.Outer != nil {
o = o.Outer
}
@@ -734,7 +722,7 @@ func machosymtab() {
Adduint8(Ctxt, symtab, uint8(o.Sect.Extnum))
}
Adduint16(Ctxt, symtab, 0) // desc
- adduintxx(Ctxt, symtab, uint64(Symaddr(s)), Thearch.Ptrsize)
+ adduintxx(Ctxt, symtab, uint64(Symaddr(s)), SysArch.PtrSize)
}
}
}
@@ -821,27 +809,25 @@ func Domacholink() int64 {
return Rnd(int64(size), int64(INITRND))
}
-func machorelocsect(sect *Section, first *LSym) {
+func machorelocsect(sect *Section, syms []*LSym) {
// If main section has no bits, nothing to relocate.
if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
return
}
sect.Reloff = uint64(Cpos())
- var sym *LSym
- for sym = first; sym != nil; sym = sym.Next {
- if !sym.Attr.Reachable() {
+ for i, s := range syms {
+ if !s.Attr.Reachable() {
continue
}
- if uint64(sym.Value) >= sect.Vaddr {
+ if uint64(s.Value) >= sect.Vaddr {
+ syms = syms[i:]
break
}
}
eaddr := int32(sect.Vaddr + sect.Length)
- var r *Reloc
- var ri int
- for ; sym != nil; sym = sym.Next {
+ for _, sym := range syms {
if !sym.Attr.Reachable() {
continue
}
@@ -850,8 +836,8 @@ func machorelocsect(sect *Section, first *LSym) {
}
Ctxt.Cursym = sym
- for ri = 0; ri < len(sym.R); ri++ {
- r = &sym.R[ri]
+ for ri := 0; ri < len(sym.R); ri++ {
+ r := &sym.R[ri]
if r.Done != 0 {
continue
}
@@ -876,5 +862,7 @@ func Machoemitreloc() {
for sect := Segdata.Sect; sect != nil; sect = sect.Next {
machorelocsect(sect, datap)
}
- dwarfemitreloc()
+ for sect := Segdwarf.Sect; sect != nil; sect = sect.Next {
+ machorelocsect(sect, list2slice(dwarfp))
+ }
}
diff --git a/src/cmd/link/internal/ld/macho_combine_dwarf.go b/src/cmd/link/internal/ld/macho_combine_dwarf.go
index b5a5a8d429..dcc371ec05 100644
--- a/src/cmd/link/internal/ld/macho_combine_dwarf.go
+++ b/src/cmd/link/internal/ld/macho_combine_dwarf.go
@@ -15,11 +15,9 @@ import (
"unsafe"
)
-var fakedwarf, realdwarf, linkseg *macho.Segment
+var realdwarf, linkseg *macho.Segment
var dwarfstart, linkstart int64
var linkoffset uint32
-var machHeader *macho.FileHeader
-var mappedHeader []byte
const (
LC_ID_DYLIB = 0xd
diff --git a/src/cmd/link/internal/ld/objfile.go b/src/cmd/link/internal/ld/objfile.go
index 8a406d17a6..bcfe52585f 100644
--- a/src/cmd/link/internal/ld/objfile.go
+++ b/src/cmd/link/internal/ld/objfile.go
@@ -110,7 +110,10 @@ package ld
import (
"bufio"
"bytes"
+ "cmd/internal/bio"
"cmd/internal/obj"
+ "crypto/sha1"
+ "encoding/base64"
"io"
"log"
"strconv"
@@ -146,18 +149,18 @@ type objReader struct {
file []*LSym
}
-func LoadObjFile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) {
- start := obj.Boffset(f)
+func LoadObjFile(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
+ start := f.Offset()
r := &objReader{
- rd: f.Reader(),
+ rd: f.Reader,
pkg: pkg,
ctxt: ctxt,
pn: pn,
dupSym: &LSym{Name: ".dup"},
}
r.loadObjFile()
- if obj.Boffset(f) != start+length {
- log.Fatalf("%s: unexpected end at %d, want %d", pn, int64(obj.Boffset(f)), int64(start+length))
+ if f.Offset() != start+length {
+ log.Fatalf("%s: unexpected end at %d, want %d", pn, f.Offset(), start+length)
}
}
@@ -330,8 +333,11 @@ overwrite:
}
if s.Type == obj.STEXT {
- s.Args = r.readInt32()
- s.Locals = r.readInt32()
+ s.FuncInfo = new(FuncInfo)
+ pc := s.FuncInfo
+
+ pc.Args = r.readInt32()
+ pc.Locals = r.readInt32()
if r.readUint8() != 0 {
s.Attr |= AttrNoSplit
}
@@ -340,13 +346,13 @@ overwrite:
s.Attr |= AttrReflectMethod
}
n := r.readInt()
- s.Autom = r.autom[:n:n]
+ pc.Autom = r.autom[:n:n]
if !isdup {
r.autom = r.autom[n:]
}
for i := 0; i < n; i++ {
- s.Autom[i] = Auto{
+ pc.Autom[i] = Auto{
Asym: r.readSymIndex(),
Aoffset: r.readInt32(),
Name: r.readInt16(),
@@ -354,8 +360,6 @@ overwrite:
}
}
- s.Pcln = new(Pcln)
- pc := s.Pcln
pc.Pcsp.P = r.readData()
pc.Pcfile.P = r.readData()
pc.Pcline.P = r.readData()
@@ -394,12 +398,7 @@ overwrite:
log.Fatalf("symbol %s listed multiple times", s.Name)
}
s.Attr |= AttrOnList
- if r.ctxt.Etextp != nil {
- r.ctxt.Etextp.Next = s
- } else {
- r.ctxt.Textp = s
- }
- r.ctxt.Etextp = s
+ r.ctxt.Textp = append(r.ctxt.Textp, s)
}
}
}
@@ -470,7 +469,7 @@ func (r *objReader) readInt64() int64 {
}
}
- return int64(uv>>1) ^ (int64(uint64(uv)<<63) >> 63)
+ return int64(uv>>1) ^ (int64(uv<<63) >> 63)
}
func (r *objReader) readInt() int {
@@ -529,13 +528,18 @@ func (r *objReader) readSymName() string {
r.readInt64()
return ""
}
- origName, err := r.rd.Peek(n)
- if err != nil {
- log.Fatalf("%s: unexpectedly long symbol name", r.pn)
- }
if cap(r.rdBuf) < n {
r.rdBuf = make([]byte, 2*n)
}
+ origName, err := r.rd.Peek(n)
+ if err == bufio.ErrBufferFull {
+ // Long symbol names are rare but exist. One source is type
+ // symbols for types with long string forms. See #15104.
+ origName = make([]byte, n)
+ r.readFull(origName)
+ } else if err != nil {
+ log.Fatalf("%s: error reading symbol: %v", err)
+ }
adjName := r.rdBuf[:0]
for {
i := bytes.Index(origName, emptyPkg)
@@ -544,8 +548,32 @@ func (r *objReader) readSymName() string {
// Read past the peeked origName, now that we're done with it,
// using the rfBuf (also no longer used) as the scratch space.
// TODO: use bufio.Reader.Discard if available instead?
- r.readFull(r.rdBuf[:n])
+ if err == nil {
+ r.readFull(r.rdBuf[:n])
+ }
r.rdBuf = adjName[:0] // in case 2*n wasn't enough
+
+ if DynlinkingGo() {
+ // These types are included in the symbol
+ // table when dynamically linking. To keep
+ // binary size down, we replace the names
+ // with SHA-1 prefixes.
+ //
+ // Keep the type.. prefix, which parts of the
+ // linker (like the DWARF generator) know means
+ // the symbol is not decodable.
+ //
+ // Leave type.runtime. symbols alone, because
+ // other parts of the linker manipulates them.
+ if strings.HasPrefix(s, "type.") && !strings.HasPrefix(s, "type.runtime.") {
+ hash := sha1.Sum([]byte(s))
+ prefix := "type."
+ if s[5] == '.' {
+ prefix = "type.."
+ }
+ s = prefix + base64.StdEncoding.EncodeToString(hash[:6])
+ }
+ }
return s
}
adjName = append(adjName, origName[:i]...)
diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go
index ff29ce2d70..991b9ef2cd 100644
--- a/src/cmd/link/internal/ld/pcln.go
+++ b/src/cmd/link/internal/ld/pcln.go
@@ -93,7 +93,7 @@ func pciterinit(ctxt *Link, it *Pciter, d *Pcdata) {
it.value = -1
it.start = 1
it.done = 0
- it.pcscale = uint32(ctxt.Arch.Minlc)
+ it.pcscale = uint32(ctxt.Arch.MinLC)
pciternext(it)
}
@@ -127,8 +127,7 @@ func addpctab(ftab *LSym, off int32, d *Pcdata) int32 {
var start int32
if len(d.P) > 0 {
start = int32(len(ftab.P))
- Symgrow(Ctxt, ftab, int64(start)+int64(len(d.P)))
- copy(ftab.P[start:], d.P)
+ Addbytes(Ctxt, ftab, d.P)
}
return int32(setuint32(Ctxt, ftab, int64(off), uint32(start)))
}
@@ -148,27 +147,21 @@ func renumberfiles(ctxt *Link, files []*LSym, d *Pcdata) {
for i := 0; i < len(files); i++ {
f = files[i]
if f.Type != obj.SFILEPATH {
- ctxt.Nhistfile++
- f.Value = int64(ctxt.Nhistfile)
+ ctxt.Filesyms = append(ctxt.Filesyms, f)
+ f.Value = int64(len(ctxt.Filesyms))
f.Type = obj.SFILEPATH
- f.Next = ctxt.Filesyms
f.Name = expandGoroot(f.Name)
- ctxt.Filesyms = f
}
}
newval := int32(-1)
var out Pcdata
-
- var dv int32
var it Pciter
- var oldval int32
- var v uint32
- var val int32
for pciterinit(ctxt, &it, d); it.done == 0; pciternext(&it) {
// value delta
- oldval = it.value
+ oldval := it.value
+ var val int32
if oldval == -1 {
val = -1
} else {
@@ -178,9 +171,9 @@ func renumberfiles(ctxt *Link, files []*LSym, d *Pcdata) {
val = int32(files[oldval].Value)
}
- dv = val - newval
+ dv := val - newval
newval = val
- v = (uint32(dv) << 1) ^ uint32(int32(dv>>31))
+ v := (uint32(dv) << 1) ^ uint32(dv>>31)
addvarint(&out, v)
// pc delta
@@ -205,7 +198,7 @@ func container(s *LSym) int {
// pclntab initializes the pclntab symbol with
// runtime function and file name information.
-var pclntab_zpcln Pcln
+var pclntab_zpcln FuncInfo
// These variables are used to initialize runtime.firstmoduledata, see symtab.go:symtab.
var pclntabNfunc int32
@@ -229,40 +222,34 @@ func pclntab() {
nfunc := int32(0)
// Find container symbols, mark them with SCONTAINER
- for Ctxt.Cursym = Ctxt.Textp; Ctxt.Cursym != nil; Ctxt.Cursym = Ctxt.Cursym.Next {
- if Ctxt.Cursym.Outer != nil {
- Ctxt.Cursym.Outer.Type |= obj.SCONTAINER
+ for _, s := range Ctxt.Textp {
+ if s.Outer != nil {
+ s.Outer.Type |= obj.SCONTAINER
}
}
- for Ctxt.Cursym = Ctxt.Textp; Ctxt.Cursym != nil; Ctxt.Cursym = Ctxt.Cursym.Next {
- if container(Ctxt.Cursym) == 0 {
+ for _, s := range Ctxt.Textp {
+ if container(s) == 0 {
nfunc++
}
}
pclntabNfunc = nfunc
- Symgrow(Ctxt, ftab, 8+int64(Thearch.Ptrsize)+int64(nfunc)*2*int64(Thearch.Ptrsize)+int64(Thearch.Ptrsize)+4)
+ Symgrow(Ctxt, ftab, 8+int64(SysArch.PtrSize)+int64(nfunc)*2*int64(SysArch.PtrSize)+int64(SysArch.PtrSize)+4)
setuint32(Ctxt, ftab, 0, 0xfffffffb)
- setuint8(Ctxt, ftab, 6, uint8(Thearch.Minlc))
- setuint8(Ctxt, ftab, 7, uint8(Thearch.Ptrsize))
- setuintxx(Ctxt, ftab, 8, uint64(nfunc), int64(Thearch.Ptrsize))
- pclntabPclntabOffset = int32(8 + Thearch.Ptrsize)
+ setuint8(Ctxt, ftab, 6, uint8(SysArch.MinLC))
+ setuint8(Ctxt, ftab, 7, uint8(SysArch.PtrSize))
+ setuintxx(Ctxt, ftab, 8, uint64(nfunc), int64(SysArch.PtrSize))
+ pclntabPclntabOffset = int32(8 + SysArch.PtrSize)
nfunc = 0
var last *LSym
- var end int32
- var funcstart int32
- var i int32
- var it Pciter
- var off int32
- var pcln *Pcln
- for Ctxt.Cursym = Ctxt.Textp; Ctxt.Cursym != nil; Ctxt.Cursym = Ctxt.Cursym.Next {
+ for _, Ctxt.Cursym = range Ctxt.Textp {
last = Ctxt.Cursym
if container(Ctxt.Cursym) != 0 {
continue
}
- pcln = Ctxt.Cursym.Pcln
+ pcln := Ctxt.Cursym.FuncInfo
if pcln == nil {
pcln = &pclntab_zpcln
}
@@ -271,17 +258,17 @@ func pclntab() {
pclntabFirstFunc = Ctxt.Cursym
}
- funcstart = int32(len(ftab.P))
- funcstart += int32(-len(ftab.P)) & (int32(Thearch.Ptrsize) - 1)
+ funcstart := int32(len(ftab.P))
+ funcstart += int32(-len(ftab.P)) & (int32(SysArch.PtrSize) - 1)
- setaddr(Ctxt, ftab, 8+int64(Thearch.Ptrsize)+int64(nfunc)*2*int64(Thearch.Ptrsize), Ctxt.Cursym)
- setuintxx(Ctxt, ftab, 8+int64(Thearch.Ptrsize)+int64(nfunc)*2*int64(Thearch.Ptrsize)+int64(Thearch.Ptrsize), uint64(funcstart), int64(Thearch.Ptrsize))
+ setaddr(Ctxt, ftab, 8+int64(SysArch.PtrSize)+int64(nfunc)*2*int64(SysArch.PtrSize), Ctxt.Cursym)
+ setuintxx(Ctxt, ftab, 8+int64(SysArch.PtrSize)+int64(nfunc)*2*int64(SysArch.PtrSize)+int64(SysArch.PtrSize), uint64(funcstart), int64(SysArch.PtrSize))
// fixed size of struct, checked below
- off = funcstart
+ off := funcstart
- end = funcstart + int32(Thearch.Ptrsize) + 3*4 + 5*4 + int32(len(pcln.Pcdata))*4 + int32(len(pcln.Funcdata))*int32(Thearch.Ptrsize)
- if len(pcln.Funcdata) > 0 && (end&int32(Thearch.Ptrsize-1) != 0) {
+ end := funcstart + int32(SysArch.PtrSize) + 3*4 + 5*4 + int32(len(pcln.Pcdata))*4 + int32(len(pcln.Funcdata))*int32(SysArch.PtrSize)
+ if len(pcln.Funcdata) > 0 && (end&int32(SysArch.PtrSize-1) != 0) {
end += 4
}
Symgrow(Ctxt, ftab, int64(end))
@@ -294,7 +281,11 @@ func pclntab() {
// args int32
// TODO: Move into funcinfo.
- off = int32(setuint32(Ctxt, ftab, int64(off), uint32(Ctxt.Cursym.Args)))
+ args := uint32(0)
+ if Ctxt.Cursym.FuncInfo != nil {
+ args = uint32(Ctxt.Cursym.FuncInfo.Args)
+ }
+ off = int32(setuint32(Ctxt, ftab, int64(off), args))
// frame int32
// This has been removed (it was never set quite correctly anyway).
@@ -307,9 +298,10 @@ func pclntab() {
renumberfiles(Ctxt, pcln.File, &pcln.Pcfile)
if false {
// Sanity check the new numbering
+ var it Pciter
for pciterinit(Ctxt, &it, &pcln.Pcfile); it.done == 0; pciternext(&it) {
- if it.value < 1 || it.value > Ctxt.Nhistfile {
- Diag("bad file number in pcfile: %d not in range [1, %d]\n", it.value, Ctxt.Nhistfile)
+ if it.value < 1 || it.value > int32(len(Ctxt.Filesyms)) {
+ Diag("bad file number in pcfile: %d not in range [1, %d]\n", it.value, len(Ctxt.Filesyms))
errorexit()
}
}
@@ -323,32 +315,32 @@ func pclntab() {
off = addpctab(ftab, off, &pcln.Pcline)
off = int32(setuint32(Ctxt, ftab, int64(off), uint32(len(pcln.Pcdata))))
off = int32(setuint32(Ctxt, ftab, int64(off), uint32(len(pcln.Funcdata))))
- for i = 0; i < int32(len(pcln.Pcdata)); i++ {
+ for i := 0; i < len(pcln.Pcdata); i++ {
off = addpctab(ftab, off, &pcln.Pcdata[i])
}
// funcdata, must be pointer-aligned and we're only int32-aligned.
// Missing funcdata will be 0 (nil pointer).
if len(pcln.Funcdata) > 0 {
- if off&int32(Thearch.Ptrsize-1) != 0 {
+ if off&int32(SysArch.PtrSize-1) != 0 {
off += 4
}
- for i = 0; i < int32(len(pcln.Funcdata)); i++ {
+ for i := 0; i < len(pcln.Funcdata); i++ {
if pcln.Funcdata[i] == nil {
- setuintxx(Ctxt, ftab, int64(off)+int64(Thearch.Ptrsize)*int64(i), uint64(pcln.Funcdataoff[i]), int64(Thearch.Ptrsize))
+ setuintxx(Ctxt, ftab, int64(off)+int64(SysArch.PtrSize)*int64(i), uint64(pcln.Funcdataoff[i]), int64(SysArch.PtrSize))
} else {
// TODO: Dedup.
funcdata_bytes += pcln.Funcdata[i].Size
- setaddrplus(Ctxt, ftab, int64(off)+int64(Thearch.Ptrsize)*int64(i), pcln.Funcdata[i], pcln.Funcdataoff[i])
+ setaddrplus(Ctxt, ftab, int64(off)+int64(SysArch.PtrSize)*int64(i), pcln.Funcdata[i], pcln.Funcdataoff[i])
}
}
- off += int32(len(pcln.Funcdata)) * int32(Thearch.Ptrsize)
+ off += int32(len(pcln.Funcdata)) * int32(SysArch.PtrSize)
}
if off != end {
- Diag("bad math in functab: funcstart=%d off=%d but end=%d (npcdata=%d nfuncdata=%d ptrsize=%d)", funcstart, off, end, len(pcln.Pcdata), len(pcln.Funcdata), Thearch.Ptrsize)
+ Diag("bad math in functab: funcstart=%d off=%d but end=%d (npcdata=%d nfuncdata=%d ptrsize=%d)", funcstart, off, end, len(pcln.Pcdata), len(pcln.Funcdata), SysArch.PtrSize)
errorexit()
}
@@ -357,25 +349,26 @@ func pclntab() {
pclntabLastFunc = last
// Final entry of table is just end pc.
- setaddrplus(Ctxt, ftab, 8+int64(Thearch.Ptrsize)+int64(nfunc)*2*int64(Thearch.Ptrsize), last, last.Size)
+ setaddrplus(Ctxt, ftab, 8+int64(SysArch.PtrSize)+int64(nfunc)*2*int64(SysArch.PtrSize), last, last.Size)
// Start file table.
start := int32(len(ftab.P))
- start += int32(-len(ftab.P)) & (int32(Thearch.Ptrsize) - 1)
+ start += int32(-len(ftab.P)) & (int32(SysArch.PtrSize) - 1)
pclntabFiletabOffset = start
- setuint32(Ctxt, ftab, 8+int64(Thearch.Ptrsize)+int64(nfunc)*2*int64(Thearch.Ptrsize)+int64(Thearch.Ptrsize), uint32(start))
+ setuint32(Ctxt, ftab, 8+int64(SysArch.PtrSize)+int64(nfunc)*2*int64(SysArch.PtrSize)+int64(SysArch.PtrSize), uint32(start))
- Symgrow(Ctxt, ftab, int64(start)+(int64(Ctxt.Nhistfile)+1)*4)
- setuint32(Ctxt, ftab, int64(start), uint32(Ctxt.Nhistfile))
- for s := Ctxt.Filesyms; s != nil; s = s.Next {
+ Symgrow(Ctxt, ftab, int64(start)+(int64(len(Ctxt.Filesyms))+1)*4)
+ setuint32(Ctxt, ftab, int64(start), uint32(len(Ctxt.Filesyms)))
+ for i := len(Ctxt.Filesyms) - 1; i >= 0; i-- {
+ s := Ctxt.Filesyms[i]
setuint32(Ctxt, ftab, int64(start)+s.Value*4, uint32(ftabaddstring(ftab, s.Name)))
}
ftab.Size = int64(len(ftab.P))
if Debug['v'] != 0 {
- fmt.Fprintf(&Bso, "%5.2f pclntab=%d bytes, funcdata total %d bytes\n", obj.Cputime(), int64(ftab.Size), int64(funcdata_bytes))
+ fmt.Fprintf(Bso, "%5.2f pclntab=%d bytes, funcdata total %d bytes\n", obj.Cputime(), ftab.Size, funcdata_bytes)
}
}
@@ -407,10 +400,9 @@ func findfunctab() {
t.Attr |= AttrLocal
// find min and max address
- min := Ctxt.Textp.Value
-
+ min := Ctxt.Textp[0].Value
max := int64(0)
- for s := Ctxt.Textp; s != nil; s = s.Next {
+ for _, s := range Ctxt.Textp {
max = s.Value + s.Size
}
@@ -423,34 +415,34 @@ func findfunctab() {
indexes[i] = NOIDX
}
idx := int32(0)
- var e *LSym
- var i int32
- var p int64
- var q int64
- for s := Ctxt.Textp; s != nil; s = s.Next {
+ for i, s := range Ctxt.Textp {
if container(s) != 0 {
continue
}
- p = s.Value
- e = s.Next
- for container(e) != 0 {
- e = e.Next
+ p := s.Value
+ var e *LSym
+ i++
+ if i < len(Ctxt.Textp) {
+ e = Ctxt.Textp[i]
+ }
+ for container(e) != 0 && i < len(Ctxt.Textp) {
+ e = Ctxt.Textp[i]
+ i++
}
+ q := max
if e != nil {
q = e.Value
- } else {
- q = max
}
//print("%d: [%lld %lld] %s\n", idx, p, q, s->name);
for ; p < q; p += SUBBUCKETSIZE {
- i = int32((p - min) / SUBBUCKETSIZE)
+ i = int((p - min) / SUBBUCKETSIZE)
if indexes[i] > idx {
indexes[i] = idx
}
}
- i = int32((q - 1 - min) / SUBBUCKETSIZE)
+ i = int((q - 1 - min) / SUBBUCKETSIZE)
if indexes[i] > idx {
indexes[i] = idx
}
@@ -463,15 +455,13 @@ func findfunctab() {
Symgrow(Ctxt, t, 4*int64(nbuckets)+int64(n))
// fill in table
- var base int32
- var j int32
for i := int32(0); i < nbuckets; i++ {
- base = indexes[i*SUBBUCKETS]
+ base := indexes[i*SUBBUCKETS]
if base == NOIDX {
Diag("hole in findfunctab")
}
setuint32(Ctxt, t, int64(i)*(4+SUBBUCKETS), uint32(base))
- for j = 0; j < SUBBUCKETS && i*SUBBUCKETS+j < n; j++ {
+ for j := int32(0); j < SUBBUCKETS && i*SUBBUCKETS+j < n; j++ {
idx = indexes[i*SUBBUCKETS+j]
if idx == NOIDX {
Diag("hole in findfunctab")
diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go
index 56698361d0..839aa6cca7 100644
--- a/src/cmd/link/internal/ld/pe.go
+++ b/src/cmd/link/internal/ld/pe.go
@@ -6,6 +6,7 @@ package ld
import (
"cmd/internal/obj"
+ "cmd/internal/sys"
"encoding/binary"
"fmt"
"os"
@@ -419,9 +420,9 @@ func chksectseg(h *IMAGE_SECTION_HEADER, s *Segment) {
func Peinit() {
var l int
- switch Thearch.Thechar {
+ switch SysArch.Family {
// 64-bit architectures
- case '6':
+ case sys.AMD64:
pe64 = 1
l = binary.Size(&oh64)
@@ -506,7 +507,7 @@ func initdynimport() *Dll {
if err != nil {
Diag("failed to parse stdcall decoration: %v", err)
}
- m.argsize *= Thearch.Ptrsize
+ m.argsize *= SysArch.PtrSize
s.Extname = s.Extname[:i]
}
@@ -520,10 +521,10 @@ func initdynimport() *Dll {
for d := dr; d != nil; d = d.next {
for m = d.ms; m != nil; m = m.next {
m.s.Type = obj.SDATA
- Symgrow(Ctxt, m.s, int64(Thearch.Ptrsize))
+ Symgrow(Ctxt, m.s, int64(SysArch.PtrSize))
dynName := m.s.Extname
// only windows/386 requires stdcall decoration
- if Thearch.Thechar == '8' && m.argsize >= 0 {
+ if SysArch.Family == sys.I386 && m.argsize >= 0 {
dynName += fmt.Sprintf("@%d", m.argsize)
}
dynSym := Linklookup(Ctxt, dynName, 0)
@@ -532,7 +533,7 @@ func initdynimport() *Dll {
r := Addrel(m.s)
r.Sym = dynSym
r.Off = 0
- r.Siz = uint8(Thearch.Ptrsize)
+ r.Siz = uint8(SysArch.PtrSize)
r.Type = obj.R_ADDR
}
}
@@ -546,10 +547,10 @@ func initdynimport() *Dll {
m.s.Sub = dynamic.Sub
dynamic.Sub = m.s
m.s.Value = dynamic.Size
- dynamic.Size += int64(Thearch.Ptrsize)
+ dynamic.Size += int64(SysArch.PtrSize)
}
- dynamic.Size += int64(Thearch.Ptrsize)
+ dynamic.Size += int64(SysArch.PtrSize)
}
}
@@ -763,7 +764,7 @@ func addexports() {
// perelocsect relocates symbols from first in section sect, and returns
// the total number of relocations emitted.
-func perelocsect(sect *Section, first *LSym) int {
+func perelocsect(sect *Section, syms []*LSym) int {
// If main section has no bits, nothing to relocate.
if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
return 0
@@ -772,20 +773,18 @@ func perelocsect(sect *Section, first *LSym) int {
relocs := 0
sect.Reloff = uint64(Cpos())
- var sym *LSym
- for sym = first; sym != nil; sym = sym.Next {
- if !sym.Attr.Reachable() {
+ for i, s := range syms {
+ if !s.Attr.Reachable() {
continue
}
- if uint64(sym.Value) >= sect.Vaddr {
+ if uint64(s.Value) >= sect.Vaddr {
+ syms = syms[i:]
break
}
}
eaddr := int32(sect.Vaddr + sect.Length)
- var r *Reloc
- var ri int
- for ; sym != nil; sym = sym.Next {
+ for _, sym := range syms {
if !sym.Attr.Reachable() {
continue
}
@@ -794,8 +793,8 @@ func perelocsect(sect *Section, first *LSym) int {
}
Ctxt.Cursym = sym
- for ri = 0; ri < len(sym.R); ri++ {
- r = &sym.R[ri]
+ for ri := 0; ri < len(sym.R); ri++ {
+ r := &sym.R[ri]
if r.Done != 0 {
continue
}
@@ -876,7 +875,7 @@ func peemitreloc(text, data, ctors *IMAGE_SECTION_HEADER) {
ctors.NumberOfRelocations = 1
ctors.PointerToRelocations = uint32(Cpos())
sectoff := ctors.VirtualAddress
- Lputl(uint32(sectoff))
+ Lputl(sectoff)
Lputl(uint32(dottext.Dynid))
switch obj.Getgoarch() {
default:
@@ -946,7 +945,7 @@ func writePESymTableRecords() int {
}
// only windows/386 requires underscore prefix on external symbols
- if Thearch.Thechar == '8' &&
+ if SysArch.Family == sys.I386 &&
Linkmode == LinkExternal &&
(s.Type != obj.SDYNIMPORT || s.Attr.CgoExport()) &&
s.Name == s.Extname &&
@@ -1002,7 +1001,7 @@ func writePESymTableRecords() int {
for d := dr; d != nil; d = d.next {
for m := d.ms; m != nil; m = m.next {
s := m.s.R[0].Xsym
- put(s, s.Name, 'U', 0, int64(Thearch.Ptrsize), 0, nil)
+ put(s, s.Name, 'U', 0, int64(SysArch.PtrSize), 0, nil)
}
}
@@ -1042,7 +1041,7 @@ func addpesymtable() {
// write COFF string table
Lputl(uint32(len(strtbl)) + 4)
for i := 0; i < len(strtbl); i++ {
- Cput(uint8(strtbl[i]))
+ Cput(strtbl[i])
}
if Linkmode != LinkExternal {
strnput("", int(h.SizeOfRawData-uint32(size)))
@@ -1129,12 +1128,12 @@ func addinitarray() (c *IMAGE_SECTION_HEADER) {
}
func Asmbpe() {
- switch Thearch.Thechar {
+ switch SysArch.Family {
default:
- Exitf("unknown PE architecture: %v", Thearch.Thechar)
- case '6':
+ Exitf("unknown PE architecture: %v", SysArch.Family)
+ case sys.AMD64:
fh.Machine = IMAGE_FILE_MACHINE_AMD64
- case '8':
+ case sys.I386:
fh.Machine = IMAGE_FILE_MACHINE_I386
}
diff --git a/src/cmd/link/internal/ld/pobj.go b/src/cmd/link/internal/ld/pobj.go
index f48b54efda..b64bb5deaf 100644
--- a/src/cmd/link/internal/ld/pobj.go
+++ b/src/cmd/link/internal/ld/pobj.go
@@ -31,7 +31,9 @@
package ld
import (
+ "bufio"
"cmd/internal/obj"
+ "cmd/internal/sys"
"flag"
"fmt"
"os"
@@ -44,13 +46,12 @@ var (
)
func Ldmain() {
- Ctxt = linknew(Thelinkarch)
- Ctxt.Thechar = int32(Thearch.Thechar)
- Ctxt.Thestring = Thestring
+ Bso = bufio.NewWriter(os.Stdout)
+
+ Ctxt = linknew(SysArch)
Ctxt.Diag = Diag
- Ctxt.Bso = &Bso
+ Ctxt.Bso = Bso
- Bso = *obj.Binitw(os.Stdout)
Debug = [128]int{}
nerrors = 0
outfile = ""
@@ -70,7 +71,7 @@ func Ldmain() {
}
}
- if Thearch.Thechar == '6' && obj.Getgoos() == "plan9" {
+ if SysArch.Family == sys.AMD64 && obj.Getgoos() == "plan9" {
obj.Flagcount("8", "use 64-bit addresses in symbol table", &Debug['8'])
}
obj.Flagfn1("B", "add an ELF NT_GNU_BUILD_ID `note` when using ELF", addbuildinfo)
@@ -89,6 +90,7 @@ func Ldmain() {
flag.Var(&Buildmode, "buildmode", "set build `mode`")
obj.Flagcount("c", "dump call graph", &Debug['c'])
obj.Flagcount("d", "disable dynamic executable", &Debug['d'])
+ flag.BoolVar(&flag_dumpdep, "dumpdep", false, "dump symbol dependency graph")
obj.Flagstr("extar", "archive program for buildmode=c-archive", &extar)
obj.Flagstr("extld", "use `linker` when linking in external mode", &extld)
obj.Flagstr("extldflags", "pass `flags` to external linker", &extldflags)
@@ -107,7 +109,7 @@ func Ldmain() {
obj.Flagcount("race", "enable race detector", &flag_race)
obj.Flagcount("s", "disable symbol table", &Debug['s'])
var flagShared int
- if Thearch.Thechar == '5' || Thearch.Thechar == '6' {
+ if SysArch.InFamily(sys.ARM, sys.AMD64) {
obj.Flagcount("shared", "generate shared object (implies -linkmode external)", &flagShared)
}
obj.Flagstr("tmpdir", "use `directory` for temporary files", &tmpdir)
@@ -122,7 +124,7 @@ func Ldmain() {
obj.Flagparse(usage)
startProfile()
- Ctxt.Bso = &Bso
+ Ctxt.Bso = Bso
Ctxt.Debugvlog = int32(Debug['v'])
if flagShared != 0 {
if Buildmode == BuildmodeUnset {
@@ -163,7 +165,7 @@ func Ldmain() {
}
if Debug['v'] != 0 {
- fmt.Fprintf(&Bso, "HEADER = -H%d -T0x%x -D0x%x -R0x%x\n", HEADTYPE, uint64(INITTEXT), uint64(INITDAT), uint32(INITRND))
+ fmt.Fprintf(Bso, "HEADER = -H%d -T0x%x -D0x%x -R0x%x\n", HEADTYPE, uint64(INITTEXT), uint64(INITDAT), uint32(INITRND))
}
Bso.Flush()
@@ -214,9 +216,9 @@ func Ldmain() {
hostlink()
archive()
if Debug['v'] != 0 {
- fmt.Fprintf(&Bso, "%5.2f cpu time\n", obj.Cputime())
- fmt.Fprintf(&Bso, "%d symbols\n", len(Ctxt.Allsym))
- fmt.Fprintf(&Bso, "%d liveness data\n", liveness)
+ fmt.Fprintf(Bso, "%5.2f cpu time\n", obj.Cputime())
+ fmt.Fprintf(Bso, "%d symbols\n", len(Ctxt.Allsym))
+ fmt.Fprintf(Bso, "%d liveness data\n", liveness)
}
Bso.Flush()
diff --git a/src/cmd/link/internal/ld/sym.go b/src/cmd/link/internal/ld/sym.go
index 3deb94644e..76fe7dab79 100644
--- a/src/cmd/link/internal/ld/sym.go
+++ b/src/cmd/link/internal/ld/sym.go
@@ -33,6 +33,7 @@ package ld
import (
"cmd/internal/obj"
+ "cmd/internal/sys"
"log"
"strconv"
)
@@ -55,7 +56,7 @@ var headers = []struct {
{"windowsgui", obj.Hwindows},
}
-func linknew(arch *LinkArch) *Link {
+func linknew(arch *sys.Arch) *Link {
ctxt := &Link{
Hash: []map[string]*LSym{
// preallocate about 2mb for hash of
@@ -98,33 +99,33 @@ func linknew(arch *LinkArch) *Link {
obj.Hdragonfly,
obj.Hsolaris:
if obj.Getgoos() == "android" {
- switch ctxt.Arch.Thechar {
- case '6':
+ switch ctxt.Arch.Family {
+ case sys.AMD64:
// Android/amd64 constant - offset from 0(FS) to our TLS slot.
// Explained in src/runtime/cgo/gcc_android_*.c
ctxt.Tlsoffset = 0x1d0
- case '8':
+ case sys.I386:
// Android/386 constant - offset from 0(GS) to our TLS slot.
ctxt.Tlsoffset = 0xf8
default:
- ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize
+ ctxt.Tlsoffset = -1 * ctxt.Arch.PtrSize
}
} else {
- ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize
+ ctxt.Tlsoffset = -1 * ctxt.Arch.PtrSize
}
case obj.Hnacl:
- switch ctxt.Arch.Thechar {
+ switch ctxt.Arch.Family {
default:
log.Fatalf("unknown thread-local storage offset for nacl/%s", ctxt.Arch.Name)
- case '5':
+ case sys.ARM:
ctxt.Tlsoffset = 0
- case '6':
+ case sys.AMD64:
ctxt.Tlsoffset = 0
- case '8':
+ case sys.I386:
ctxt.Tlsoffset = -8
}
@@ -133,26 +134,26 @@ func linknew(arch *LinkArch) *Link {
* Explained in src/runtime/cgo/gcc_darwin_*.c.
*/
case obj.Hdarwin:
- switch ctxt.Arch.Thechar {
+ switch ctxt.Arch.Family {
default:
log.Fatalf("unknown thread-local storage offset for darwin/%s", ctxt.Arch.Name)
- case '5':
+ case sys.ARM:
ctxt.Tlsoffset = 0 // dummy value, not needed
- case '6':
+ case sys.AMD64:
ctxt.Tlsoffset = 0x8a0
- case '7':
+ case sys.ARM64:
ctxt.Tlsoffset = 0 // dummy value, not needed
- case '8':
+ case sys.I386:
ctxt.Tlsoffset = 0x468
}
}
// On arm, record goarm.
- if ctxt.Arch.Thechar == '5' {
+ if ctxt.Arch.Family == sys.ARM {
ctxt.Goarm = obj.Getgoarm()
}
diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go
index 3258bc1ff9..94a6d0ab29 100644
--- a/src/cmd/link/internal/ld/symtab.go
+++ b/src/cmd/link/internal/ld/symtab.go
@@ -32,6 +32,7 @@ package ld
import (
"cmd/internal/obj"
+ "cmd/internal/sys"
"fmt"
"path/filepath"
"strings"
@@ -53,21 +54,14 @@ func putelfstr(s string) int {
s = strings.Replace(s, "·", ".", -1)
}
- n := len(s) + 1
- for len(Elfstrdat)+n > cap(Elfstrdat) {
- Elfstrdat = append(Elfstrdat[:cap(Elfstrdat)], 0)[:len(Elfstrdat)]
- }
-
off := len(Elfstrdat)
- Elfstrdat = Elfstrdat[:off+n]
- copy(Elfstrdat[off:], s)
-
+ Elfstrdat = append(Elfstrdat, s...)
+ Elfstrdat = append(Elfstrdat, 0)
return off
}
func putelfsyment(off int, addr int64, size int64, info int, shndx int, other int) {
- switch Thearch.Thechar {
- case '0', '6', '7', '9', 'z':
+ if elf64 {
Thearch.Lput(uint32(off))
Cput(uint8(info))
Cput(uint8(other))
@@ -75,8 +69,7 @@ func putelfsyment(off int, addr int64, size int64, info int, shndx int, other in
Thearch.Vput(uint64(addr))
Thearch.Vput(uint64(size))
Symsize += ELF64SYMSIZE
-
- default:
+ } else {
Thearch.Lput(uint32(off))
Thearch.Lput(uint32(addr))
Thearch.Lput(uint32(size))
@@ -162,7 +155,7 @@ func putelfsym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *L
if x.Type&obj.SHIDDEN != 0 {
other = STV_HIDDEN
}
- if (Buildmode == BuildmodePIE || DynlinkingGo()) && Thearch.Thechar == '9' && type_ == STT_FUNC && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" {
+ if (Buildmode == BuildmodePIE || DynlinkingGo()) && SysArch.Family == sys.PPC64 && type_ == STT_FUNC && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" {
// On ppc64 the top three bits of the st_other field indicate how
// many instructions separate the global and local entry points. In
// our case it is two instructions, indicated by the value 3.
@@ -197,18 +190,6 @@ func putelfsectionsym(s *LSym, shndx int) {
numelfsym++
}
-func putelfsymshndx(sympos int64, shndx int) {
- here := Cpos()
- if elf64 {
- Cseek(sympos + 6)
- } else {
- Cseek(sympos + 14)
- }
-
- Thearch.Wput(uint16(shndx))
- Cseek(here)
-}
-
func Asmelfsym() {
// the first symbol entry is reserved
putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_NOTYPE, 0, 0)
@@ -217,7 +198,9 @@ func Asmelfsym() {
// Some linkers will add a FILE sym if one is not present.
// Avoid having the working directory inserted into the symbol table.
- putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_FILE, SHN_ABS, 0)
+ // It is added with a name to avoid problems with external linking
+ // encountered on some versions of Solaris. See issue #14957.
+ putelfsyment(putelfstr("go.go"), 0, 0, STB_LOCAL<<4|STT_FILE, SHN_ABS, 0)
numelfsym++
elfbind = STB_LOCAL
@@ -243,7 +226,7 @@ func putplan9sym(x *LSym, s string, t int, addr int64, size int64, ver int, go_
'Z',
'm':
l := 4
- if HEADTYPE == obj.Hplan9 && Thearch.Thechar == '6' && Debug['8'] == 0 {
+ if HEADTYPE == obj.Hplan9 && SysArch.Family == sys.AMD64 && Debug['8'] == 0 {
Lputb(uint32(addr >> 32))
l = 8
}
@@ -253,10 +236,10 @@ func putplan9sym(x *LSym, s string, t int, addr int64, size int64, ver int, go_
var i int
if t == 'z' || t == 'Z' {
- Cput(uint8(s[0]))
+ Cput(s[0])
for i = 1; s[i] != 0 || s[i+1] != 0; i += 2 {
- Cput(uint8(s[i]))
- Cput(uint8(s[i+1]))
+ Cput(s[i])
+ Cput(s[i+1])
}
Cput(0)
@@ -268,7 +251,7 @@ func putplan9sym(x *LSym, s string, t int, addr int64, size int64, ver int, go_
s = s[1:]
}
for i = 0; i < len(s); i++ {
- Cput(uint8(s[i]))
+ Cput(s[i])
}
Cput(0)
}
@@ -346,6 +329,8 @@ func symtab() {
xdefine("runtime.eitablink", obj.SRODATA, 0)
xdefine("runtime.rodata", obj.SRODATA, 0)
xdefine("runtime.erodata", obj.SRODATA, 0)
+ xdefine("runtime.types", obj.SRODATA, 0)
+ xdefine("runtime.etypes", obj.SRODATA, 0)
xdefine("runtime.noptrdata", obj.SNOPTRDATA, 0)
xdefine("runtime.enoptrdata", obj.SNOPTRDATA, 0)
xdefine("runtime.data", obj.SDATA, 0)
@@ -399,33 +384,19 @@ func symtab() {
symtyperel = s
}
- s = Linklookup(Ctxt, "go.string.*", 0)
- s.Type = obj.SGOSTRING
- s.Attr |= AttrLocal
- s.Size = 0
- s.Attr |= AttrReachable
- symgostring := s
-
- s = Linklookup(Ctxt, "go.string.hdr.*", 0)
- s.Type = obj.SGOSTRINGHDR
- s.Attr |= AttrLocal
- s.Size = 0
- s.Attr |= AttrReachable
- symgostringhdr := s
-
- s = Linklookup(Ctxt, "go.func.*", 0)
- s.Type = obj.SGOFUNC
- s.Attr |= AttrLocal
- s.Size = 0
- s.Attr |= AttrReachable
- symgofunc := s
-
- s = Linklookup(Ctxt, "runtime.gcbits.*", 0)
- s.Type = obj.SGCBITS
- s.Attr |= AttrLocal
- s.Size = 0
- s.Attr |= AttrReachable
- symgcbits := s
+ groupSym := func(name string, t int16) *LSym {
+ s := Linklookup(Ctxt, name, 0)
+ s.Type = t
+ s.Size = 0
+ s.Attr |= AttrLocal | AttrReachable
+ return s
+ }
+ var (
+ symgostring = groupSym("go.string.*", obj.SGOSTRING)
+ symgostringhdr = groupSym("go.string.hdr.*", obj.SGOSTRINGHDR)
+ symgofunc = groupSym("go.func.*", obj.SGOFUNC)
+ symgcbits = groupSym("runtime.gcbits.*", obj.SGCBITS)
+ )
symtypelink := Linklookup(Ctxt, "runtime.typelink", 0)
symtypelink.Type = obj.STYPELINK
@@ -451,34 +422,37 @@ func symtab() {
continue
}
- if strings.HasPrefix(s.Name, "type.") {
+ switch {
+ case strings.HasPrefix(s.Name, "type."):
if !DynlinkingGo() {
s.Attr |= AttrHidden
}
- if UseRelro() && len(s.R) > 0 {
+ if UseRelro() {
s.Type = obj.STYPERELRO
s.Outer = symtyperel
} else {
s.Type = obj.STYPE
s.Outer = symtype
}
- }
- if strings.HasPrefix(s.Name, "go.typelink.") {
+ case strings.HasPrefix(s.Name, "go.importpath.") && UseRelro():
+ // Keep go.importpath symbols in the same section as types and
+ // names, as they can be referred to by a section offset.
+ s.Type = obj.STYPERELRO
+
+ case strings.HasPrefix(s.Name, "go.typelink."):
ntypelinks++
s.Type = obj.STYPELINK
s.Attr |= AttrHidden
s.Outer = symtypelink
- }
- if strings.HasPrefix(s.Name, "go.itablink.") {
+ case strings.HasPrefix(s.Name, "go.itablink."):
nitablinks++
s.Type = obj.SITABLINK
s.Attr |= AttrHidden
s.Outer = symitablink
- }
- if strings.HasPrefix(s.Name, "go.string.") {
+ case strings.HasPrefix(s.Name, "go.string."):
s.Type = obj.SGOSTRING
s.Attr |= AttrHidden
s.Outer = symgostring
@@ -486,21 +460,18 @@ func symtab() {
s.Type = obj.SGOSTRINGHDR
s.Outer = symgostringhdr
}
- }
- if strings.HasPrefix(s.Name, "runtime.gcbits.") {
+ case strings.HasPrefix(s.Name, "runtime.gcbits."):
s.Type = obj.SGCBITS
s.Attr |= AttrHidden
s.Outer = symgcbits
- }
- if strings.HasPrefix(s.Name, "go.func.") {
+ case strings.HasPrefix(s.Name, "go.func."):
s.Type = obj.SGOFUNC
s.Attr |= AttrHidden
s.Outer = symgofunc
- }
- if strings.HasPrefix(s.Name, "gcargs.") || strings.HasPrefix(s.Name, "gclocals.") || strings.HasPrefix(s.Name, "gclocals·") {
+ case strings.HasPrefix(s.Name, "gcargs."), strings.HasPrefix(s.Name, "gclocals."), strings.HasPrefix(s.Name, "gclocals·"):
s.Type = obj.SGOFUNC
s.Attr |= AttrHidden
s.Outer = symgofunc
@@ -533,8 +504,8 @@ func symtab() {
adduint(Ctxt, moduledata, uint64(pclntabNfunc+1))
// The filetab slice
Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabFiletabOffset))
- adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile)+1)
- adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile)+1)
+ adduint(Ctxt, moduledata, uint64(len(Ctxt.Filesyms))+1)
+ adduint(Ctxt, moduledata, uint64(len(Ctxt.Filesyms))+1)
// findfunctab
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.findfunctab", 0))
// minpc, maxpc
@@ -554,6 +525,8 @@ func symtab() {
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.end", 0))
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcdata", 0))
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcbss", 0))
+ Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.types", 0))
+ Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.etypes", 0))
// The typelinks slice
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.typelink", 0))
adduint(Ctxt, moduledata, uint64(ntypelinks))
diff --git a/src/cmd/link/internal/mips64/asm.go b/src/cmd/link/internal/mips64/asm.go
index 8249c54e45..785002b02c 100644
--- a/src/cmd/link/internal/mips64/asm.go
+++ b/src/cmd/link/internal/mips64/asm.go
@@ -32,6 +32,7 @@ package mips64
import (
"cmd/internal/obj"
+ "cmd/internal/sys"
"cmd/link/internal/ld"
"encoding/binary"
"fmt"
@@ -40,10 +41,6 @@ import (
func gentext() {}
-func adddynrela(rel *ld.LSym, s *ld.LSym, r *ld.Reloc) {
- log.Fatalf("adddynrela not implemented")
-}
-
func adddynrel(s *ld.LSym, r *ld.Reloc) {
log.Fatalf("adddynrel not implemented")
}
@@ -82,8 +79,8 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
// the first instruction is always at the lower address, this is endian neutral;
// but note that o1 and o2 should still use the target endian.
- o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off:])
- o2 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off+4:])
+ o1 := ld.SysArch.ByteOrder.Uint32(s.P[r.Off:])
+ o2 := ld.SysArch.ByteOrder.Uint32(s.P[r.Off+4:])
o1 = o1&0xffff0000 | uint32(t>>16)&0xffff
o2 = o2&0xffff0000 | uint32(t)&0xffff
@@ -99,7 +96,7 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
obj.R_JMPMIPS:
// Low 26 bits = (S + A) >> 2
t := ld.Symaddr(r.Sym) + r.Add
- o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off:])
+ o1 := ld.SysArch.ByteOrder.Uint32(s.P[r.Off:])
*val = int64(o1&0xfc000000 | uint32(t>>2)&^0xfc000000)
return 0
}
@@ -113,7 +110,7 @@ func archrelocvariant(r *ld.Reloc, s *ld.LSym, t int64) int64 {
func asmb() {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f asmb\n", obj.Cputime())
}
ld.Bso.Flush()
@@ -131,7 +128,7 @@ func asmb() {
if ld.Segrodata.Filelen > 0 {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
}
ld.Bso.Flush()
@@ -140,13 +137,16 @@ func asmb() {
}
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f datblk\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f datblk\n", obj.Cputime())
}
ld.Bso.Flush()
ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
+ ld.Cseek(int64(ld.Segdwarf.Fileoff))
+ ld.Dwarfblk(int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
+
/* output symbol table */
ld.Symsize = 0
@@ -155,13 +155,13 @@ func asmb() {
if ld.Debug['s'] == 0 {
// TODO: rationalize
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f sym\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f sym\n", obj.Cputime())
}
ld.Bso.Flush()
switch ld.HEADTYPE {
default:
if ld.Iself {
- symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
+ symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND)))
}
@@ -174,17 +174,12 @@ func asmb() {
default:
if ld.Iself {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f elfsym\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f elfsym\n", obj.Cputime())
}
ld.Asmelfsym()
ld.Cflush()
ld.Cwrite(ld.Elfstrdat)
- if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
- }
- ld.Dwarfemitdebugsections()
-
if ld.Linkmode == ld.LinkExternal {
ld.Elfemitreloc()
}
@@ -198,7 +193,7 @@ func asmb() {
if sym != nil {
ld.Lcsize = int32(len(sym.P))
for i := 0; int32(i) < ld.Lcsize; i++ {
- ld.Cput(uint8(sym.P[i]))
+ ld.Cput(sym.P[i])
}
ld.Cflush()
@@ -208,7 +203,7 @@ func asmb() {
ld.Ctxt.Cursym = nil
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f header\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f header\n", obj.Cputime())
}
ld.Bso.Flush()
ld.Cseek(0)
@@ -216,10 +211,10 @@ func asmb() {
default:
case obj.Hplan9: /* plan 9 */
magic := uint32(4*18*18 + 7)
- if ld.Thestring == "mips64le" {
+ if ld.SysArch == sys.ArchMIPS64LE {
magic = uint32(4*26*26 + 7)
}
- ld.Thearch.Lput(uint32(magic)) /* magic */
+ ld.Thearch.Lput(magic) /* magic */
ld.Thearch.Lput(uint32(ld.Segtext.Filelen)) /* sizes */
ld.Thearch.Lput(uint32(ld.Segdata.Filelen))
ld.Thearch.Lput(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
diff --git a/src/cmd/link/internal/mips64/l.go b/src/cmd/link/internal/mips64/l.go
index 003ee5ce71..f4191e69ab 100644
--- a/src/cmd/link/internal/mips64/l.go
+++ b/src/cmd/link/internal/mips64/l.go
@@ -62,11 +62,9 @@ package mips64
// THE SOFTWARE.
const (
- thechar = '0'
MaxAlign = 32 // max data alignment
MinAlign = 1 // min data alignment
FuncAlign = 8
- MINLC = 4
)
/* Used by ../internal/ld/dwarf.go */
diff --git a/src/cmd/link/internal/mips64/obj.go b/src/cmd/link/internal/mips64/obj.go
index 57a1b2ab14..87bb3a079b 100644
--- a/src/cmd/link/internal/mips64/obj.go
+++ b/src/cmd/link/internal/mips64/obj.go
@@ -32,6 +32,7 @@ package mips64
import (
"cmd/internal/obj"
+ "cmd/internal/sys"
"cmd/link/internal/ld"
"fmt"
"log"
@@ -45,21 +46,15 @@ func Main() {
}
func linkarchinit() {
- ld.Thestring = obj.Getgoarch()
- if ld.Thestring == "mips64le" {
- ld.Thelinkarch = &ld.Linkmips64le
+ if obj.Getgoarch() == "mips64le" {
+ ld.SysArch = sys.ArchMIPS64LE
} else {
- ld.Thelinkarch = &ld.Linkmips64
+ ld.SysArch = sys.ArchMIPS64
}
- ld.Thearch.Thechar = thechar
- ld.Thearch.Ptrsize = ld.Thelinkarch.Ptrsize
- ld.Thearch.Intsize = ld.Thelinkarch.Ptrsize
- ld.Thearch.Regsize = ld.Thelinkarch.Regsize
ld.Thearch.Funcalign = FuncAlign
ld.Thearch.Maxalign = MaxAlign
ld.Thearch.Minalign = MinAlign
- ld.Thearch.Minlc = MINLC
ld.Thearch.Dwarfregsp = DWARFREGSP
ld.Thearch.Dwarfreglr = DWARFREGLR
@@ -72,7 +67,7 @@ func linkarchinit() {
ld.Thearch.Elfsetupplt = elfsetupplt
ld.Thearch.Gentext = gentext
ld.Thearch.Machoreloc1 = machoreloc1
- if ld.Thelinkarch == &ld.Linkmips64le {
+ if ld.SysArch == sys.ArchMIPS64LE {
ld.Thearch.Lput = ld.Lputl
ld.Thearch.Wput = ld.Wputl
ld.Thearch.Vput = ld.Vputl
diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go
index ae69799abf..dbf5fac0de 100644
--- a/src/cmd/link/internal/ppc64/asm.go
+++ b/src/cmd/link/internal/ppc64/asm.go
@@ -39,14 +39,6 @@ import (
)
func genplt() {
- var s *ld.LSym
- var stub *ld.LSym
- var pprevtextp **ld.LSym
- var r *ld.Reloc
- var n string
- var o1 uint32
- var i int
-
// The ppc64 ABI PLT has similar concepts to other
// architectures, but is laid out quite differently. When we
// see an R_PPC64_REL24 relocation to a dynamic symbol
@@ -95,11 +87,9 @@ func genplt() {
//
// This assumes "case 1" from the ABI, where the caller needs
// us to save and restore the TOC pointer.
- pprevtextp = &ld.Ctxt.Textp
-
- for s = *pprevtextp; s != nil; pprevtextp, s = &s.Next, s.Next {
- for i = range s.R {
- r = &s.R[i]
+ for _, s := range ld.Ctxt.Textp {
+ for i := range s.R {
+ r := &s.R[i]
if r.Type != 256+ld.R_PPC64_REL24 || r.Sym.Type != obj.SDYNIMPORT {
continue
}
@@ -109,24 +99,16 @@ func genplt() {
addpltsym(ld.Ctxt, r.Sym)
// Generate call stub
- n = fmt.Sprintf("%s.%s", s.Name, r.Sym.Name)
+ n := fmt.Sprintf("%s.%s", s.Name, r.Sym.Name)
- stub = ld.Linklookup(ld.Ctxt, n, 0)
+ stub := ld.Linklookup(ld.Ctxt, n, 0)
if s.Attr.Reachable() {
stub.Attr |= ld.AttrReachable
}
if stub.Size == 0 {
// Need outer to resolve .TOC.
stub.Outer = s
-
- // Link in to textp before s (we could
- // do it after, but would have to skip
- // the subsymbols)
- *pprevtextp = stub
-
- stub.Next = s
- pprevtextp = &stub.Next
-
+ ld.Ctxt.Textp = append(ld.Ctxt.Textp, stub)
gencallstub(1, stub, r.Sym)
}
@@ -135,11 +117,10 @@ func genplt() {
// Restore TOC after bl. The compiler put a
// nop here for us to overwrite.
- o1 = 0xe8410018 // ld r2,24(r1)
+ const o1 = 0xe8410018 // ld r2,24(r1)
ld.Ctxt.Arch.ByteOrder.PutUint32(s.P[r.Off+4:], o1)
}
}
-
}
func genaddmoduledata() {
@@ -195,13 +176,7 @@ func genaddmoduledata() {
// blr
o(0x4e800020)
- if ld.Ctxt.Etextp != nil {
- ld.Ctxt.Etextp.Next = initfunc
- } else {
- ld.Ctxt.Textp = initfunc
- }
- ld.Ctxt.Etextp = initfunc
-
+ ld.Ctxt.Textp = append(ld.Ctxt.Textp, initfunc)
initarray_entry := ld.Linklookup(ld.Ctxt, "go.link.addmoduledatainit", 0)
initarray_entry.Attr |= ld.AttrReachable
initarray_entry.Attr |= ld.AttrLocal
@@ -265,10 +240,6 @@ func gencallstub(abicase int, stub *ld.LSym, targ *ld.LSym) {
ld.Adduint32(ld.Ctxt, stub, 0x4e800420) // bctr
}
-func adddynrela(rel *ld.LSym, s *ld.LSym, r *ld.Reloc) {
- log.Fatalf("adddynrela not implemented")
-}
-
func adddynrel(s *ld.LSym, r *ld.Reloc) {
targ := r.Sym
ld.Ctxt.Cursym = s
@@ -834,7 +805,7 @@ func ensureglinkresolver() *ld.LSym {
func asmb() {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f asmb\n", obj.Cputime())
}
ld.Bso.Flush()
@@ -852,7 +823,7 @@ func asmb() {
if ld.Segrodata.Filelen > 0 {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
}
ld.Bso.Flush()
@@ -861,13 +832,16 @@ func asmb() {
}
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f datblk\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f datblk\n", obj.Cputime())
}
ld.Bso.Flush()
ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
+ ld.Cseek(int64(ld.Segdwarf.Fileoff))
+ ld.Dwarfblk(int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
+
/* output symbol table */
ld.Symsize = 0
@@ -876,13 +850,13 @@ func asmb() {
if ld.Debug['s'] == 0 {
// TODO: rationalize
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f sym\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f sym\n", obj.Cputime())
}
ld.Bso.Flush()
switch ld.HEADTYPE {
default:
if ld.Iself {
- symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
+ symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND)))
}
@@ -895,17 +869,12 @@ func asmb() {
default:
if ld.Iself {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f elfsym\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f elfsym\n", obj.Cputime())
}
ld.Asmelfsym()
ld.Cflush()
ld.Cwrite(ld.Elfstrdat)
- if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
- }
- ld.Dwarfemitdebugsections()
-
if ld.Linkmode == ld.LinkExternal {
ld.Elfemitreloc()
}
@@ -919,7 +888,7 @@ func asmb() {
if sym != nil {
ld.Lcsize = int32(len(sym.P))
for i := 0; int32(i) < ld.Lcsize; i++ {
- ld.Cput(uint8(sym.P[i]))
+ ld.Cput(sym.P[i])
}
ld.Cflush()
@@ -929,7 +898,7 @@ func asmb() {
ld.Ctxt.Cursym = nil
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f header\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f header\n", obj.Cputime())
}
ld.Bso.Flush()
ld.Cseek(0)
diff --git a/src/cmd/link/internal/ppc64/l.go b/src/cmd/link/internal/ppc64/l.go
index 622d6bb12e..a720993fbc 100644
--- a/src/cmd/link/internal/ppc64/l.go
+++ b/src/cmd/link/internal/ppc64/l.go
@@ -62,11 +62,9 @@ package ppc64
// THE SOFTWARE.
const (
- thechar = '9'
MaxAlign = 32 // max data alignment
MinAlign = 1 // min data alignment
FuncAlign = 8
- MINLC = 4
)
/* Used by ../internal/ld/dwarf.go */
diff --git a/src/cmd/link/internal/ppc64/obj.go b/src/cmd/link/internal/ppc64/obj.go
index 539ab1ac02..a540ab85b5 100644
--- a/src/cmd/link/internal/ppc64/obj.go
+++ b/src/cmd/link/internal/ppc64/obj.go
@@ -32,6 +32,7 @@ package ppc64
import (
"cmd/internal/obj"
+ "cmd/internal/sys"
"cmd/link/internal/ld"
"fmt"
"log"
@@ -45,21 +46,15 @@ func Main() {
}
func linkarchinit() {
- ld.Thestring = obj.Getgoarch()
- if ld.Thestring == "ppc64le" {
- ld.Thelinkarch = &ld.Linkppc64le
+ if obj.Getgoarch() == "ppc64le" {
+ ld.SysArch = sys.ArchPPC64LE
} else {
- ld.Thelinkarch = &ld.Linkppc64
+ ld.SysArch = sys.ArchPPC64
}
- ld.Thearch.Thechar = thechar
- ld.Thearch.Ptrsize = ld.Thelinkarch.Ptrsize
- ld.Thearch.Intsize = ld.Thelinkarch.Ptrsize
- ld.Thearch.Regsize = ld.Thelinkarch.Regsize
ld.Thearch.Funcalign = FuncAlign
ld.Thearch.Maxalign = MaxAlign
ld.Thearch.Minalign = MinAlign
- ld.Thearch.Minlc = MINLC
ld.Thearch.Dwarfregsp = DWARFREGSP
ld.Thearch.Dwarfreglr = DWARFREGLR
@@ -72,7 +67,7 @@ func linkarchinit() {
ld.Thearch.Elfsetupplt = elfsetupplt
ld.Thearch.Gentext = gentext
ld.Thearch.Machoreloc1 = machoreloc1
- if ld.Thelinkarch == &ld.Linkppc64le {
+ if ld.SysArch == sys.ArchPPC64LE {
ld.Thearch.Lput = ld.Lputl
ld.Thearch.Wput = ld.Wputl
ld.Thearch.Vput = ld.Vputl
@@ -150,7 +145,7 @@ func archinit() {
}
case obj.Hlinux: /* ppc64 elf */
- if ld.Thestring == "ppc64" {
+ if ld.SysArch == sys.ArchPPC64 {
ld.Debug['d'] = 1 // TODO(austin): ELF ABI v1 not supported yet
}
ld.Elfinit()
diff --git a/src/cmd/link/internal/s390x/asm.go b/src/cmd/link/internal/s390x/asm.go
index 75a8206174..7c2e3358ff 100644
--- a/src/cmd/link/internal/s390x/asm.go
+++ b/src/cmd/link/internal/s390x/asm.go
@@ -90,12 +90,7 @@ func gentext() {
// undef (for debugging)
ld.Adduint32(ld.Ctxt, initfunc, 0)
- if ld.Ctxt.Etextp != nil {
- ld.Ctxt.Etextp.Next = initfunc
- } else {
- ld.Ctxt.Textp = initfunc
- }
- ld.Ctxt.Etextp = initfunc
+ ld.Ctxt.Textp = append(ld.Ctxt.Textp, initfunc)
initarray_entry := ld.Linklookup(ld.Ctxt, "go.link.addmoduledatainit", 0)
initarray_entry.Attr |= ld.AttrLocal
initarray_entry.Attr |= ld.AttrReachable
@@ -505,7 +500,7 @@ func addgotsym(s *ld.LSym) {
func asmb() {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f asmb\n", obj.Cputime())
}
ld.Bso.Flush()
@@ -523,7 +518,7 @@ func asmb() {
if ld.Segrodata.Filelen > 0 {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
}
ld.Bso.Flush()
@@ -532,13 +527,16 @@ func asmb() {
}
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f datblk\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f datblk\n", obj.Cputime())
}
ld.Bso.Flush()
ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
+ ld.Cseek(int64(ld.Segdwarf.Fileoff))
+ ld.Dwarfblk(int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
+
/* output symbol table */
ld.Symsize = 0
@@ -549,24 +547,23 @@ func asmb() {
ld.Diag("unsupported executable format")
}
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f sym\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f sym\n", obj.Cputime())
}
ld.Bso.Flush()
- symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
+ symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND)))
ld.Cseek(int64(symo))
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f elfsym\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f elfsym\n", obj.Cputime())
}
ld.Asmelfsym()
ld.Cflush()
ld.Cwrite(ld.Elfstrdat)
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f dwarf\n", obj.Cputime())
}
- ld.Dwarfemitdebugsections()
if ld.Linkmode == ld.LinkExternal {
ld.Elfemitreloc()
@@ -575,7 +572,7 @@ func asmb() {
ld.Ctxt.Cursym = nil
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f header\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f header\n", obj.Cputime())
}
ld.Bso.Flush()
ld.Cseek(0)
diff --git a/src/cmd/link/internal/s390x/l.go b/src/cmd/link/internal/s390x/l.go
index 839a9849c8..42cf15ee85 100644
--- a/src/cmd/link/internal/s390x/l.go
+++ b/src/cmd/link/internal/s390x/l.go
@@ -62,14 +62,9 @@ package s390x
// THE SOFTWARE.
const (
- thechar = 'z'
- PtrSize = 8
- IntSize = 8
- RegSize = 8
MaxAlign = 32 // max data alignment
MinAlign = 2 // min data alignment
FuncAlign = 16
- MINLC = 2
)
/* Used by ../internal/ld/dwarf.go */
diff --git a/src/cmd/link/internal/s390x/obj.go b/src/cmd/link/internal/s390x/obj.go
index ef88d22bbd..fdb9898181 100644
--- a/src/cmd/link/internal/s390x/obj.go
+++ b/src/cmd/link/internal/s390x/obj.go
@@ -32,6 +32,7 @@ package s390x
import (
"cmd/internal/obj"
+ "cmd/internal/sys"
"cmd/link/internal/ld"
"fmt"
)
@@ -44,17 +45,11 @@ func Main() {
}
func linkarchinit() {
- ld.Thestring = obj.Getgoarch()
- ld.Thelinkarch = &ld.Links390x
+ ld.SysArch = sys.ArchS390X
- ld.Thearch.Thechar = thechar
- ld.Thearch.Ptrsize = ld.Thelinkarch.Ptrsize
- ld.Thearch.Intsize = ld.Thelinkarch.Ptrsize
- ld.Thearch.Regsize = ld.Thelinkarch.Regsize
ld.Thearch.Funcalign = FuncAlign
ld.Thearch.Maxalign = MaxAlign
ld.Thearch.Minalign = MinAlign
- ld.Thearch.Minlc = MINLC
ld.Thearch.Dwarfregsp = DWARFREGSP
ld.Thearch.Dwarfreglr = DWARFREGLR
diff --git a/src/cmd/link/internal/x86/asm.go b/src/cmd/link/internal/x86/asm.go
index 97fccf3ee6..4a55b535ac 100644
--- a/src/cmd/link/internal/x86/asm.go
+++ b/src/cmd/link/internal/x86/asm.go
@@ -69,12 +69,7 @@ func gentext() {
// c3 ret
o(0xc3)
- if ld.Ctxt.Etextp != nil {
- ld.Ctxt.Etextp.Next = thunkfunc
- } else {
- ld.Ctxt.Textp = thunkfunc
- }
- ld.Ctxt.Etextp = thunkfunc
+ ld.Ctxt.Textp = append(ld.Ctxt.Textp, thunkfunc)
addmoduledata := ld.Linklookup(ld.Ctxt, "runtime.addmoduledata", 0)
if addmoduledata.Type == obj.STEXT {
@@ -130,8 +125,7 @@ func gentext() {
o(0xc3)
- ld.Ctxt.Etextp.Next = initfunc
- ld.Ctxt.Etextp = initfunc
+ ld.Ctxt.Textp = append(ld.Ctxt.Textp, initfunc)
initarray_entry := ld.Linklookup(ld.Ctxt, "go.link.addmoduledatainit", 0)
initarray_entry.Attr |= ld.AttrReachable
initarray_entry.Attr |= ld.AttrLocal
@@ -139,10 +133,6 @@ func gentext() {
ld.Addaddr(ld.Ctxt, initarray_entry, initfunc)
}
-func adddynrela(rela *ld.LSym, s *ld.LSym, r *ld.Reloc) {
- log.Fatalf("adddynrela not implemented")
-}
-
func adddynrel(s *ld.LSym, r *ld.Reloc) {
targ := r.Sym
ld.Ctxt.Cursym = s
@@ -292,7 +282,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
return
}
- if ld.HEADTYPE == obj.Hdarwin && s.Size == PtrSize && r.Off == 0 {
+ if ld.HEADTYPE == obj.Hdarwin && s.Size == int64(ld.SysArch.PtrSize) && r.Off == 0 {
// Mach-O relocations are a royal pain to lay out.
// They use a compact stateful bytecode representation
// that is too much bother to deal with.
@@ -317,7 +307,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
return
}
- if ld.HEADTYPE == obj.Hwindows && s.Size == PtrSize {
+ if ld.HEADTYPE == obj.Hwindows && s.Size == int64(ld.SysArch.PtrSize) {
// nothing to do, the relocation will be laid out in pereloc1
return
}
@@ -609,7 +599,7 @@ func addgotsym(ctxt *ld.Link, s *ld.LSym) {
func asmb() {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f asmb\n", obj.Cputime())
}
ld.Bso.Flush()
@@ -627,7 +617,7 @@ func asmb() {
if ld.Segrodata.Filelen > 0 {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
}
ld.Bso.Flush()
@@ -636,26 +626,18 @@ func asmb() {
}
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f datblk\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f datblk\n", obj.Cputime())
}
ld.Bso.Flush()
ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
+ ld.Cseek(int64(ld.Segdwarf.Fileoff))
+ ld.Dwarfblk(int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
+
machlink := uint32(0)
if ld.HEADTYPE == obj.Hdarwin {
- if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
- }
-
- dwarfoff := uint32(ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Length), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND)))
- ld.Cseek(int64(dwarfoff))
-
- ld.Segdwarf.Fileoff = uint64(ld.Cpos())
- ld.Dwarfemitdebugsections()
- ld.Segdwarf.Filelen = uint64(ld.Cpos()) - ld.Segdwarf.Fileoff
-
machlink = uint32(ld.Domacholink())
}
@@ -666,13 +648,13 @@ func asmb() {
if ld.Debug['s'] == 0 {
// TODO: rationalize
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f sym\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f sym\n", obj.Cputime())
}
ld.Bso.Flush()
switch ld.HEADTYPE {
default:
if ld.Iself {
- symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
+ symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND)))
}
@@ -683,7 +665,7 @@ func asmb() {
symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(ld.INITRND))) + uint64(machlink))
case obj.Hwindows:
- symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
+ symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
symo = uint32(ld.Rnd(int64(symo), ld.PEFILEALIGN))
}
@@ -692,17 +674,12 @@ func asmb() {
default:
if ld.Iself {
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f elfsym\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f elfsym\n", obj.Cputime())
}
ld.Asmelfsym()
ld.Cflush()
ld.Cwrite(ld.Elfstrdat)
- if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
- }
- ld.Dwarfemitdebugsections()
-
if ld.Linkmode == ld.LinkExternal {
ld.Elfemitreloc()
}
@@ -716,7 +693,7 @@ func asmb() {
if sym != nil {
ld.Lcsize = int32(len(sym.P))
for i := 0; int32(i) < ld.Lcsize; i++ {
- ld.Cput(uint8(sym.P[i]))
+ ld.Cput(sym.P[i])
}
ld.Cflush()
@@ -724,9 +701,8 @@ func asmb() {
case obj.Hwindows:
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f dwarf\n", obj.Cputime())
}
- ld.Dwarfemitdebugsections()
case obj.Hdarwin:
if ld.Linkmode == ld.LinkExternal {
@@ -736,7 +712,7 @@ func asmb() {
}
if ld.Debug['v'] != 0 {
- fmt.Fprintf(&ld.Bso, "%5.2f headr\n", obj.Cputime())
+ fmt.Fprintf(ld.Bso, "%5.2f headr\n", obj.Cputime())
}
ld.Bso.Flush()
ld.Cseek(0)
diff --git a/src/cmd/link/internal/x86/l.go b/src/cmd/link/internal/x86/l.go
index 068fed9c8d..2043f9bb4e 100644
--- a/src/cmd/link/internal/x86/l.go
+++ b/src/cmd/link/internal/x86/l.go
@@ -31,12 +31,9 @@
package x86
const (
- thechar = '8'
- PtrSize = 4
MaxAlign = 32 // max data alignment
MinAlign = 1 // min data alignment
FuncAlign = 16
- MINLC = 1
)
/* Used by ../internal/ld/dwarf.go */
diff --git a/src/cmd/link/internal/x86/obj.go b/src/cmd/link/internal/x86/obj.go
index 4380c41ebb..574c0dad2d 100644
--- a/src/cmd/link/internal/x86/obj.go
+++ b/src/cmd/link/internal/x86/obj.go
@@ -32,6 +32,7 @@ package x86
import (
"cmd/internal/obj"
+ "cmd/internal/sys"
"cmd/link/internal/ld"
"fmt"
"log"
@@ -45,17 +46,11 @@ func Main() {
}
func linkarchinit() {
- ld.Thestring = "386"
- ld.Thelinkarch = &ld.Link386
+ ld.SysArch = sys.Arch386
- ld.Thearch.Thechar = thechar
- ld.Thearch.Ptrsize = ld.Thelinkarch.Ptrsize
- ld.Thearch.Intsize = ld.Thelinkarch.Ptrsize
- ld.Thearch.Regsize = ld.Thelinkarch.Regsize
ld.Thearch.Funcalign = FuncAlign
ld.Thearch.Maxalign = MaxAlign
ld.Thearch.Minalign = MinAlign
- ld.Thearch.Minlc = MINLC
ld.Thearch.Dwarfregsp = DWARFREGSP
ld.Thearch.Dwarfreglr = DWARFREGLR