Commit a037c73c authored by Ryan Brown's avatar Ryan Brown Committed by David Crawshaw

cmd/link: generate DWARF info using symbols

This updates dwarf.go to generate debug information as symbols
instead of directly writing to the output file. This should make
it easier to move generation of some of the debug info into the compiler.

Change-Id: Id2358988bfb689865ab4d68f82716f0676336df4
Reviewed-on: https://go-review.googlesource.com/20679Reviewed-by: default avatarDavid Crawshaw <crawshaw@golang.org>
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 0382a30d
...@@ -423,6 +423,8 @@ const ( ...@@ -423,6 +423,8 @@ const (
SCONST SCONST
SDYNIMPORT SDYNIMPORT
SHOSTOBJ SHOSTOBJ
SDWARFSECT
SDWARFINFO
SSUB = 1 << 8 SSUB = 1 << 8
SMASK = SSUB - 1 SMASK = SSUB - 1
SHIDDEN = 1 << 9 SHIDDEN = 1 << 9
...@@ -495,6 +497,8 @@ const ( ...@@ -495,6 +497,8 @@ const (
// of a JMP instruction, by encoding the address into the instruction. // of a JMP instruction, by encoding the address into the instruction.
// The stack nosplit check ignores this since it is not a function call. // The stack nosplit check ignores this since it is not a function call.
R_JMPMIPS R_JMPMIPS
// R_DWARFREF resolves to the offset of the symbol from its section.
R_DWARFREF
// Platform dependent relocations. Architectures with fixed width instructions // Platform dependent relocations. Architectures with fixed width instructions
// have the inherent issue that a 32-bit (or 64-bit!) displacement cannot be // have the inherent issue that a 32-bit (or 64-bit!) displacement cannot be
......
...@@ -650,19 +650,11 @@ func asmb() { ...@@ -650,19 +650,11 @@ func asmb() {
ld.Cseek(int64(ld.Segdata.Fileoff)) ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen)) 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) machlink := int64(0)
if ld.HEADTYPE == obj.Hdarwin { 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() machlink = ld.Domacholink()
} }
...@@ -715,11 +707,11 @@ func asmb() { ...@@ -715,11 +707,11 @@ func asmb() {
obj.Hdragonfly, obj.Hdragonfly,
obj.Hsolaris, obj.Hsolaris,
obj.Hnacl: 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)) symo = ld.Rnd(symo, int64(ld.INITRND))
case obj.Hwindows: 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) symo = ld.Rnd(symo, ld.PEFILEALIGN)
} }
...@@ -736,8 +728,6 @@ func asmb() { ...@@ -736,8 +728,6 @@ func asmb() {
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 { if ld.Linkmode == ld.LinkExternal {
ld.Elfemitreloc() ld.Elfemitreloc()
} }
...@@ -762,8 +752,6 @@ func asmb() { ...@@ -762,8 +752,6 @@ func asmb() {
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: case obj.Hdarwin:
if ld.Linkmode == ld.LinkExternal { if ld.Linkmode == ld.LinkExternal {
ld.Machoemitreloc() ld.Machoemitreloc()
......
...@@ -597,19 +597,11 @@ func asmb() { ...@@ -597,19 +597,11 @@ func asmb() {
ld.Cseek(int64(ld.Segdata.Fileoff)) ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen)) 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) machlink := uint32(0)
if ld.HEADTYPE == obj.Hdarwin { 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()) machlink = uint32(ld.Domacholink())
} }
...@@ -627,7 +619,7 @@ func asmb() { ...@@ -627,7 +619,7 @@ func asmb() {
switch ld.HEADTYPE { switch ld.HEADTYPE {
default: default:
if ld.Iself { 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))) symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND)))
} }
...@@ -649,11 +641,6 @@ func asmb() { ...@@ -649,11 +641,6 @@ func asmb() {
ld.Cflush() ld.Cflush()
ld.Cwrite(ld.Elfstrdat) 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 { if ld.Linkmode == ld.LinkExternal {
ld.Elfemitreloc() ld.Elfemitreloc()
} }
......
...@@ -435,19 +435,11 @@ func asmb() { ...@@ -435,19 +435,11 @@ func asmb() {
ld.Cseek(int64(ld.Segdata.Fileoff)) ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen)) 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) machlink := uint32(0)
if ld.HEADTYPE == obj.Hdarwin { 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()) machlink = uint32(ld.Domacholink())
} }
...@@ -465,7 +457,7 @@ func asmb() { ...@@ -465,7 +457,7 @@ func asmb() {
switch ld.HEADTYPE { switch ld.HEADTYPE {
default: default:
if ld.Iself { 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))) symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND)))
} }
...@@ -487,11 +479,6 @@ func asmb() { ...@@ -487,11 +479,6 @@ func asmb() {
ld.Cflush() ld.Cflush()
ld.Cwrite(ld.Elfstrdat) 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 { if ld.Linkmode == ld.LinkExternal {
ld.Elfemitreloc() ld.Elfemitreloc()
} }
......
...@@ -84,6 +84,20 @@ func setuintxx(ctxt *Link, s *LSym, off int64, v uint64, wid int64) int64 { ...@@ -84,6 +84,20 @@ func setuintxx(ctxt *Link, s *LSym, off int64, v uint64, wid int64) int64 {
return off + wid return off + wid
} }
func Addbytes(ctxt *Link, s *LSym, bytes []byte) int64 {
if s.Type == 0 {
s.Type = obj.SDATA
}
s.Attr |= AttrReachable
s.Size += int64(len(bytes))
if int64(int(s.Size)) != s.Size {
log.Fatalf("Addbytes size %d too long", s.Size)
}
s.P = append(s.P, bytes...)
return s.Size
}
func adduintxx(ctxt *Link, s *LSym, v uint64, wid int) int64 { func adduintxx(ctxt *Link, s *LSym, v uint64, wid int) int64 {
off := s.Size off := s.Size
setuintxx(ctxt, s, off, v, int64(wid)) setuintxx(ctxt, s, off, v, int64(wid))
...@@ -489,6 +503,25 @@ func relocsym(s *LSym) { ...@@ -489,6 +503,25 @@ func relocsym(s *LSym) {
errorexit() 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 && Thearch.Thechar == '6' {
o = 0
}
break
}
o = Symaddr(r.Sym) + r.Add - int64(r.Sym.Sect.Vaddr)
// r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call. // r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
case obj.R_CALL, obj.R_GOTPCREL, obj.R_PCREL: 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) { if Linkmode == LinkExternal && r.Sym != nil && r.Sym.Type != obj.SCONST && (r.Sym.Sect != Ctxt.Cursym.Sect || r.Type == obj.R_GOTPCREL) {
...@@ -614,6 +647,9 @@ func reloc() { ...@@ -614,6 +647,9 @@ func reloc() {
for s := datap; s != nil; s = s.Next { for s := datap; s != nil; s = s.Next {
relocsym(s) relocsym(s)
} }
for s := dwarfp; s != nil; s = s.Next {
relocsym(s)
}
} }
func dynrelocsym(s *LSym) { func dynrelocsym(s *LSym) {
...@@ -893,6 +929,14 @@ func Datblk(addr int64, size int64) { ...@@ -893,6 +929,14 @@ func Datblk(addr int64, size int64) {
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 var zeros [512]byte
// strnput writes the first n bytes of s. // strnput writes the first n bytes of s.
...@@ -1691,6 +1735,40 @@ func dodata() { ...@@ -1691,6 +1735,40 @@ func dodata() {
Diag("read-only data segment too large") Diag("read-only data segment too large")
} }
dwarfgeneratedebugsyms()
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)
growdatsize(&datsize, s)
sect.Length = uint64(datsize) - sect.Vaddr
}
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
growdatsize(&datsize, s)
}
sect.Length = uint64(datsize) - sect.Vaddr
}
// The compiler uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
if datsize != int64(uint32(datsize)) {
Diag("dwarf segment too large")
}
/* number the sections */ /* number the sections */
n := int32(1) n := int32(1)
...@@ -1706,6 +1784,10 @@ func dodata() { ...@@ -1706,6 +1784,10 @@ func dodata() {
sect.Extnum = int16(n) sect.Extnum = int16(n)
n++ n++
} }
for sect := Segdwarf.Sect; sect != nil; sect = sect.Next {
sect.Extnum = int16(n)
n++
}
} }
// Add buildid to beginning of text segment, on non-ELF systems. // Add buildid to beginning of text segment, on non-ELF systems.
...@@ -1857,6 +1939,29 @@ func address() { ...@@ -1857,6 +1939,29 @@ func address() {
Segdata.Filelen = bss.Vaddr - Segdata.Vaddr 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 text := Segtext.Sect
var rodata *Section var rodata *Section
if Segrodata.Sect != nil { if Segrodata.Sect != nil {
...@@ -1884,6 +1989,15 @@ func address() { ...@@ -1884,6 +1989,15 @@ func address() {
sub.Value += sym.Value sub.Value += sym.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 {
sub.Value += sym.Value
}
}
if Buildmode == BuildmodeShared { if Buildmode == BuildmodeShared {
s := Linklookup(Ctxt, "go.link.abihashbytes", 0) s := Linklookup(Ctxt, "go.link.abihashbytes", 0)
......
...@@ -17,97 +17,34 @@ package ld ...@@ -17,97 +17,34 @@ package ld
import ( import (
"cmd/internal/obj" "cmd/internal/obj"
"fmt" "fmt"
"log"
"os" "os"
"strings" "strings"
) )
const infoprefix = "go.dwarf.info."
/* /*
* Offsets and sizes of the debug_* sections in the cout file. * Offsets and sizes of the debug_* sections in the cout file.
*/ */
var abbrevo int64
var abbrevsize int64
var abbrevsym *LSym 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 arangessec *LSym
var arangesreloco int64
var arangesrelocsize int64
var linesec *LSym
var linereloco int64
var linerelocsize int64
var framesec *LSym var framesec *LSym
var infosec *LSym
var framereloco int64 var linesec *LSym
var framerelocsize int64
var gdbscript string var gdbscript string
/* /*
* Basic I/O * Basic I/O
*/ */
func addrput(addr int64) { func addrput(s *LSym, addr int64) {
switch Thearch.Ptrsize { switch Thearch.Ptrsize {
case 4: case 4:
Thearch.Lput(uint32(addr)) Adduint32(Ctxt, s, uint32(addr))
case 8: case 8:
Thearch.Vput(uint64(addr)) Adduint64(Ctxt, s, uint64(addr))
} }
} }
...@@ -144,14 +81,16 @@ func appendSleb128(b []byte, v int64) []byte { ...@@ -144,14 +81,16 @@ func appendSleb128(b []byte, v int64) []byte {
var encbuf [10]byte var encbuf [10]byte
func uleb128put(v int64) { func uleb128put(s *LSym, v int64) {
b := appendUleb128(encbuf[:0], uint64(v)) 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) b := appendSleb128(encbuf[:0], v)
Cwrite(b) for _, x := range b {
Adduint8(Ctxt, s, x)
}
} }
/* /*
...@@ -462,24 +401,29 @@ var abbrevs = [DW_NABRV]DWAbbrev{ ...@@ -462,24 +401,29 @@ var abbrevs = [DW_NABRV]DWAbbrev{
}, },
} }
func writeabbrev() { var dwarfp *LSym
abbrevo = Cpos()
func writeabbrev() *LSym {
s := Linklookup(Ctxt, ".debug_abbrev", 0)
s.Type = obj.SDWARFSECT
abbrevsym = s
for i := 1; i < DW_NABRV; i++ { for i := 1; i < DW_NABRV; i++ {
// See section 7.5.3 // See section 7.5.3
uleb128put(int64(i)) uleb128put(s, int64(i))
uleb128put(int64(abbrevs[i].tag)) uleb128put(s, int64(abbrevs[i].tag))
Cput(abbrevs[i].children) Adduint8(Ctxt, s, abbrevs[i].children)
for _, f := range abbrevs[i].attr { for _, f := range abbrevs[i].attr {
uleb128put(int64(f.attr)) uleb128put(s, int64(f.attr))
uleb128put(int64(f.form)) uleb128put(s, int64(f.form))
} }
uleb128put(0) uleb128put(s, 0)
uleb128put(0) uleb128put(s, 0)
} }
Cput(0) Adduint8(Ctxt, s, 0)
abbrevsize = Cpos() - abbrevo return s
} }
/* /*
...@@ -504,10 +448,7 @@ type DWDie struct { ...@@ -504,10 +448,7 @@ type DWDie struct {
link *DWDie link *DWDie
child *DWDie child *DWDie
attr *DWAttr attr *DWAttr
// offset into .debug_info section, i.e relative to sym *LSym
// infoo. only valid after call to putdie()
offs int64
hash map[string]*DWDie // optional index of DWAttr by name, enabled by mkindex()
} }
/* /*
...@@ -556,9 +497,8 @@ func getattr(die *DWDie, attr uint16) *DWAttr { ...@@ -556,9 +497,8 @@ func getattr(die *DWDie, attr uint16) *DWAttr {
} }
// Every DIE has at least a DW_AT_name attribute (but it will only be // 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 // written out if it is listed in the abbrev).
// keeping an index, the new DIE will be inserted there. func newdie(parent *DWDie, abbrev int, name string, version int) *DWDie {
func newdie(parent *DWDie, abbrev int, name string) *DWDie {
die := new(DWDie) die := new(DWDie)
die.abbrev = abbrev die.abbrev = abbrev
die.link = parent.child die.link = parent.child
...@@ -566,17 +506,16 @@ func newdie(parent *DWDie, abbrev int, name string) *DWDie { ...@@ -566,17 +506,16 @@ func newdie(parent *DWDie, abbrev int, name string) *DWDie {
newattr(die, DW_AT_name, DW_CLS_STRING, int64(len(name)), name) newattr(die, DW_AT_name, DW_CLS_STRING, int64(len(name)), name)
if parent.hash != nil { if name != "" && (abbrev <= DW_ABRV_VARIABLE || abbrev >= DW_ABRV_NULLTYPE) {
parent.hash[name] = die if abbrev != DW_ABRV_VARIABLE || version == 0 {
die.sym = Linklookup(Ctxt, infoprefix+name, version)
die.sym.Type = obj.SDWARFINFO
}
} }
return die return die
} }
func mkindex(die *DWDie) {
die.hash = make(map[string]*DWDie)
}
func walktypedef(die *DWDie) *DWDie { func walktypedef(die *DWDie) *DWDie {
// Resolve typedef if present. // Resolve typedef if present.
if die.abbrev == DW_ABRV_TYPEDECL { if die.abbrev == DW_ABRV_TYPEDECL {
...@@ -590,12 +529,18 @@ func walktypedef(die *DWDie) *DWDie { ...@@ -590,12 +529,18 @@ func walktypedef(die *DWDie) *DWDie {
return die 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 // Find child by AT_name using hashtable if available or linear scan
// if not. // if not.
func find(die *DWDie, name string) *DWDie { func findchild(die *DWDie, name string) *DWDie {
var prev *DWDie var prev *DWDie
for ; die != prev; prev, die = die, walktypedef(die) { for ; die != prev; prev, die = die, walktypedef(die) {
if die.hash == nil {
for a := die.child; a != nil; a = a.link { for a := die.child; a != nil; a = a.link {
if name == getattr(a, DW_AT_name).data { if name == getattr(a, DW_AT_name).data {
return a return a
...@@ -603,146 +548,131 @@ func find(die *DWDie, name string) *DWDie { ...@@ -603,146 +548,131 @@ func find(die *DWDie, name string) *DWDie {
} }
continue continue
} }
if a := die.hash[name]; a != nil {
return a
}
}
return nil return nil
} }
func mustFind(die *DWDie, name string) *DWDie { func find(name string) *LSym {
r := find(die, name) return Linkrlookup(Ctxt, infoprefix+name, 0)
}
func mustFind(name string) *LSym {
r := find(name)
if r == nil { 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 return r
} }
func adddwarfrel(sec *LSym, sym *LSym, offsetbase int64, siz int, addend int64) { func adddwarfref(ctxt *Link, s *LSym, t *LSym, size int) int64 {
r := Addrel(sec) var result int64
r.Sym = sym switch size {
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))
default: default:
Diag("bad size in adddwarfrel") Diag("invalid size %d in adddwarfref\n", size)
fallthrough
case Thearch.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 { if ref == nil {
return nil return nil
} }
return newattr(die, attr, DW_CLS_REFERENCE, 0, ref) return newattr(die, attr, DW_CLS_REFERENCE, 0, ref)
} }
var fwdcount int func putattr(s *LSym, abbrev int, form int, cls int, value int64, data interface{}) {
func putattr(abbrev int, form int, cls int, value int64, data interface{}) {
switch form { switch form {
case DW_FORM_addr: // address case DW_FORM_addr: // address
if Linkmode == LinkExternal { if Linkmode == LinkExternal {
value -= (data.(*LSym)).Value value -= (data.(*LSym)).Value
adddwarfrel(infosec, data.(*LSym), infoo, Thearch.Ptrsize, value) Addaddrplus(Ctxt, s, data.(*LSym), value)
break break
} }
addrput(value) addrput(s, value)
case DW_FORM_block1: // block case DW_FORM_block1: // block
if cls == DW_CLS_ADDRESS { if cls == DW_CLS_ADDRESS {
Cput(uint8(1 + Thearch.Ptrsize)) Adduint8(Ctxt, s, uint8(1+Thearch.Ptrsize))
Cput(DW_OP_addr) Adduint8(Ctxt, s, DW_OP_addr)
if Linkmode == LinkExternal { Addaddr(Ctxt, s, data.(*LSym))
value -= (data.(*LSym)).Value
adddwarfrel(infosec, data.(*LSym), infoo, Thearch.Ptrsize, value)
break
}
addrput(value)
break break
} }
value &= 0xff value &= 0xff
Cput(uint8(value)) Adduint8(Ctxt, s, uint8(value))
p := data.([]byte) p := data.([]byte)
for i := 0; int64(i) < value; i++ { for i := 0; int64(i) < value; i++ {
Cput(uint8(p[i])) Adduint8(Ctxt, s, uint8(p[i]))
} }
case DW_FORM_block2: // block case DW_FORM_block2: // block
value &= 0xffff value &= 0xffff
Thearch.Wput(uint16(value)) Adduint16(Ctxt, s, uint16(value))
p := data.([]byte) p := data.([]byte)
for i := 0; int64(i) < value; i++ { for i := 0; int64(i) < value; i++ {
Cput(uint8(p[i])) Adduint8(Ctxt, s, uint8(p[i]))
} }
case DW_FORM_block4: // block case DW_FORM_block4: // block
value &= 0xffffffff value &= 0xffffffff
Thearch.Lput(uint32(value)) Adduint32(Ctxt, s, uint32(value))
p := data.([]byte) p := data.([]byte)
for i := 0; int64(i) < value; i++ { for i := 0; int64(i) < value; i++ {
Cput(uint8(p[i])) Adduint8(Ctxt, s, uint8(p[i]))
} }
case DW_FORM_block: // block case DW_FORM_block: // block
uleb128put(value) uleb128put(s, value)
p := data.([]byte) p := data.([]byte)
for i := 0; int64(i) < value; i++ { for i := 0; int64(i) < value; i++ {
Cput(uint8(p[i])) Adduint8(Ctxt, s, uint8(p[i]))
} }
case DW_FORM_data1: // constant case DW_FORM_data1: // constant
Cput(uint8(value)) Adduint8(Ctxt, s, uint8(value))
case DW_FORM_data2: // constant case DW_FORM_data2: // constant
Thearch.Wput(uint16(value)) Adduint16(Ctxt, s, uint16(value))
case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr
if Linkmode == LinkExternal && cls == DW_CLS_PTR { if Linkmode == LinkExternal && cls == DW_CLS_PTR {
adddwarfrel(infosec, linesym, infoo, 4, value) adddwarfref(Ctxt, s, linesec, 4)
break break
} }
Thearch.Lput(uint32(value)) Adduint32(Ctxt, s, uint32(value))
case DW_FORM_data8: // constant, {line,loclist,mac,rangelist}ptr case DW_FORM_data8: // constant, {line,loclist,mac,rangelist}ptr
Thearch.Vput(uint64(value)) Adduint64(Ctxt, s, uint64(value))
case DW_FORM_sdata: // constant case DW_FORM_sdata: // constant
sleb128put(value) sleb128put(s, value)
case DW_FORM_udata: // constant case DW_FORM_udata: // constant
uleb128put(value) uleb128put(s, value)
case DW_FORM_string: // string 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 case DW_FORM_flag: // flag
if value != 0 { if value != 0 {
Cput(1) Adduint8(Ctxt, s, 1)
} else { } else {
Cput(0) Adduint8(Ctxt, s, 0)
} }
// In DWARF 2 (which is what we claim to generate), // In DWARF 2 (which is what we claim to generate),
...@@ -753,21 +683,13 @@ func putattr(abbrev int, form int, cls int, value int64, data interface{}) { ...@@ -753,21 +683,13 @@ func putattr(abbrev int, form int, cls int, value int64, data interface{}) {
if data == nil { if data == nil {
Diag("dwarf: null reference in %d", abbrev) Diag("dwarf: null reference in %d", abbrev)
if Thearch.Ptrsize == 8 { if Thearch.Ptrsize == 8 {
Thearch.Vput(0) // invalid dwarf, gdb will complain. Adduint64(Ctxt, s, 0) // invalid dwarf, gdb will complain.
} else { } else {
Thearch.Lput(0) // invalid dwarf, gdb will complain. Adduint32(Ctxt, s, 0) // invalid dwarf, gdb will complain.
} }
} else { } else {
off := (data.(*DWDie)).offs dsym := data.(*LSym)
if off == 0 { adddwarfref(Ctxt, s, dsym, Thearch.Ptrsize)
fwdcount++
}
if Linkmode == LinkExternal {
adddwarfrel(infosec, infosym, infoo, Thearch.Ptrsize, off)
break
}
addrput(off)
} }
case DW_FORM_ref1, // reference within the compilation unit case DW_FORM_ref1, // reference within the compilation unit
...@@ -786,34 +708,45 @@ func putattr(abbrev int, form int, cls int, value int64, data interface{}) { ...@@ -786,34 +708,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 // 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. // 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: Outer:
for _, f := range abbrevs[abbrev].attr { for _, f := range abbrevs[abbrev].attr {
for ap := attr; ap != nil; ap = ap.link { for ap := attr; ap != nil; ap = ap.link {
if ap.atr == f.attr { 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 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 { for ; die != nil; die = die.link {
putdie(die) prev = putdie(prev, die)
} }
Adduint8(Ctxt, prev, 0)
return prev
} }
func putdie(die *DWDie) { func putdie(prev *LSym, die *DWDie) *LSym {
die.offs = Cpos() - infoo s := die.sym
uleb128put(int64(die.abbrev)) if s == nil {
putattrs(die.abbrev, die.attr) 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 { if abbrevs[die.abbrev].children != 0 {
putdies(die.child) return putdies(s, die.child)
Cput(0)
} }
return s
} }
func reverselist(list **DWDie) { func reverselist(list **DWDie) {
...@@ -880,44 +813,49 @@ func dotypedef(parent *DWDie, name string, def *DWDie) { ...@@ -880,44 +813,49 @@ func dotypedef(parent *DWDie, name string, def *DWDie) {
Diag("dwarf: bad def in dotypedef") Diag("dwarf: bad def in dotypedef")
} }
def.sym = Linklookup(Ctxt, def.sym.Name+".def", 0)
def.sym.Type = obj.SDWARFINFO
// The typedef entry must be created after the def, // The typedef entry must be created after the def,
// so that future lookups will find the typedef instead // so that future lookups will find the typedef instead
// of the real definition. This hooks the typedef into any // of the real definition. This hooks the typedef into any
// circular definition loops, so that gdb can understand them. // 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. // Define gotype, for composite ones recurse into constituents.
func defgotype(gotype *LSym) *DWDie { func defgotype(gotype *LSym) *LSym {
if gotype == nil { if gotype == nil {
return mustFind(&dwtypes, "<unspecified>") return mustFind("<unspecified>")
} }
if !strings.HasPrefix(gotype.Name, "type.") { if !strings.HasPrefix(gotype.Name, "type.") {
Diag("dwarf: type name doesn't start with \"type.\": %s", gotype.Name) 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 name := gotype.Name[5:] // could also decode from Type.string
die := find(&dwtypes, name) sdie := find(name)
if die != nil { if sdie != nil {
return die return sdie
} }
if false && Debug['v'] > 2 { return newtype(gotype).sym
fmt.Printf("new type: %v\n", gotype) }
}
func newtype(gotype *LSym) *DWDie {
name := gotype.Name[5:] // could also decode from Type.string
kind := decodetype_kind(gotype) kind := decodetype_kind(gotype)
bytesize := decodetype_size(gotype) bytesize := decodetype_size(gotype)
var die *DWDie
switch kind { switch kind {
case obj.KindBool: 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_encoding, DW_CLS_CONSTANT, DW_ATE_boolean, 0)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
...@@ -926,7 +864,7 @@ func defgotype(gotype *LSym) *DWDie { ...@@ -926,7 +864,7 @@ func defgotype(gotype *LSym) *DWDie {
obj.KindInt16, obj.KindInt16,
obj.KindInt32, obj.KindInt32,
obj.KindInt64: 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_encoding, DW_CLS_CONSTANT, DW_ATE_signed, 0)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
...@@ -936,66 +874,69 @@ func defgotype(gotype *LSym) *DWDie { ...@@ -936,66 +874,69 @@ func defgotype(gotype *LSym) *DWDie {
obj.KindUint32, obj.KindUint32,
obj.KindUint64, obj.KindUint64,
obj.KindUintptr: 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_encoding, DW_CLS_CONSTANT, DW_ATE_unsigned, 0)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
case obj.KindFloat32, case obj.KindFloat32,
obj.KindFloat64: 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_encoding, DW_CLS_CONSTANT, DW_ATE_float, 0)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
case obj.KindComplex64, case obj.KindComplex64,
obj.KindComplex128: 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_encoding, DW_CLS_CONSTANT, DW_ATE_complex_float, 0)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
case obj.KindArray: case obj.KindArray:
die = newdie(&dwtypes, DW_ABRV_ARRAYTYPE, name) die = newdie(&dwtypes, DW_ABRV_ARRAYTYPE, name, 0)
dotypedef(&dwtypes, name, die) dotypedef(&dwtypes, name, die)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
s := decodetype_arrayelem(gotype) s := decodetype_arrayelem(gotype)
newrefattr(die, DW_AT_type, defgotype(s)) 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. // use actual length not upper bound; correct for 0-length arrays.
newattr(fld, DW_AT_count, DW_CLS_CONSTANT, decodetype_arraylen(gotype), 0) 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: 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) newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
s := decodetype_chanelem(gotype) s := decodetype_chanelem(gotype)
newrefattr(die, DW_AT_go_elem, defgotype(s)) 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: case obj.KindFunc:
die = newdie(&dwtypes, DW_ABRV_FUNCTYPE, name) die = newdie(&dwtypes, DW_ABRV_FUNCTYPE, name, 0)
dotypedef(&dwtypes, name, die) dotypedef(&dwtypes, name, die)
newrefattr(die, DW_AT_type, mustFind(&dwtypes, "void")) newrefattr(die, DW_AT_type, mustFind("void"))
nfields := decodetype_funcincount(gotype) nfields := decodetype_funcincount(gotype)
var fld *DWDie var fld *DWDie
var s *LSym var s *LSym
for i := 0; i < nfields; i++ { for i := 0; i < nfields; i++ {
s = decodetype_funcintype(gotype, 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)) newrefattr(fld, DW_AT_type, defgotype(s))
} }
if decodetype_funcdotdotdot(gotype) { if decodetype_funcdotdotdot(gotype) {
newdie(die, DW_ABRV_DOTDOTDOT, "...") newdie(die, DW_ABRV_DOTDOTDOT, "...", 0)
} }
nfields = decodetype_funcoutcount(gotype) nfields = decodetype_funcoutcount(gotype)
for i := 0; i < nfields; i++ { for i := 0; i < nfields; i++ {
s = decodetype_funcouttype(gotype, 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))) newrefattr(fld, DW_AT_type, defptrto(defgotype(s)))
} }
case obj.KindInterface: case obj.KindInterface:
die = newdie(&dwtypes, DW_ABRV_IFACETYPE, name) die = newdie(&dwtypes, DW_ABRV_IFACETYPE, name, 0)
dotypedef(&dwtypes, name, die) dotypedef(&dwtypes, name, die)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
nfields := int(decodetype_ifacemethodcount(gotype)) nfields := int(decodetype_ifacemethodcount(gotype))
...@@ -1008,31 +949,35 @@ func defgotype(gotype *LSym) *DWDie { ...@@ -1008,31 +949,35 @@ func defgotype(gotype *LSym) *DWDie {
newrefattr(die, DW_AT_type, defgotype(s)) newrefattr(die, DW_AT_type, defgotype(s))
case obj.KindMap: case obj.KindMap:
die = newdie(&dwtypes, DW_ABRV_MAPTYPE, name) die = newdie(&dwtypes, DW_ABRV_MAPTYPE, name, 0)
s := decodetype_mapkey(gotype) s := decodetype_mapkey(gotype)
newrefattr(die, DW_AT_go_key, defgotype(s)) newrefattr(die, DW_AT_go_key, defgotype(s))
s = decodetype_mapvalue(gotype) s = decodetype_mapvalue(gotype)
newrefattr(die, DW_AT_go_elem, defgotype(s)) 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: case obj.KindPtr:
die = newdie(&dwtypes, DW_ABRV_PTRTYPE, name) die = newdie(&dwtypes, DW_ABRV_PTRTYPE, name, 0)
dotypedef(&dwtypes, name, die) dotypedef(&dwtypes, name, die)
s := decodetype_ptrelem(gotype) s := decodetype_ptrelem(gotype)
newrefattr(die, DW_AT_type, defgotype(s)) newrefattr(die, DW_AT_type, defgotype(s))
case obj.KindSlice: case obj.KindSlice:
die = newdie(&dwtypes, DW_ABRV_SLICETYPE, name) die = newdie(&dwtypes, DW_ABRV_SLICETYPE, name, 0)
dotypedef(&dwtypes, name, die) dotypedef(&dwtypes, name, die)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
s := decodetype_arrayelem(gotype) 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: 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) newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
case obj.KindStruct: case obj.KindStruct:
die = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, name) die = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, name, 0)
dotypedef(&dwtypes, name, die) dotypedef(&dwtypes, name, die)
newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0) newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, bytesize, 0)
nfields := decodetype_structfieldcount(gotype) nfields := decodetype_structfieldcount(gotype)
...@@ -1045,32 +990,41 @@ func defgotype(gotype *LSym) *DWDie { ...@@ -1045,32 +990,41 @@ func defgotype(gotype *LSym) *DWDie {
if f == "" { if f == "" {
f = s.Name[5:] // skip "type." 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)) newrefattr(fld, DW_AT_type, defgotype(s))
newmemberoffsetattr(fld, int32(decodetype_structfieldoffs(gotype, i))) newmemberoffsetattr(fld, int32(decodetype_structfieldoffs(gotype, i)))
} }
case obj.KindUnsafePointer: case obj.KindUnsafePointer:
die = newdie(&dwtypes, DW_ABRV_BARE_PTRTYPE, name) die = newdie(&dwtypes, DW_ABRV_BARE_PTRTYPE, name, 0)
default: default:
Diag("dwarf: definition of unknown kind %d: %s", kind, gotype.Name) Diag("dwarf: definition of unknown kind %d: %s", kind, gotype.Name)
die = newdie(&dwtypes, DW_ABRV_TYPEDECL, name) die = newdie(&dwtypes, DW_ABRV_TYPEDECL, name, 0)
newrefattr(die, DW_AT_type, mustFind(&dwtypes, "<unspecified>")) newrefattr(die, DW_AT_type, mustFind("<unspecified>"))
} }
newattr(die, DW_AT_go_kind, DW_CLS_CONSTANT, int64(kind), 0) newattr(die, DW_AT_go_kind, DW_CLS_CONSTANT, int64(kind), 0)
if _, ok := prototypedies[gotype.Name]; ok {
prototypedies[gotype.Name] = die
}
return die return die
} }
func nameFromDIESym(dwtype *LSym) string {
return strings.TrimSuffix(dwtype.Name[len(infoprefix):], ".def")
}
// Find or construct *T given T. // Find or construct *T given T.
func defptrto(dwtype *DWDie) *DWDie { func defptrto(dwtype *LSym) *LSym {
ptrname := fmt.Sprintf("*%s", getattr(dwtype, DW_AT_name).data) ptrname := "*" + nameFromDIESym(dwtype)
die := find(&dwtypes, ptrname) die := find(ptrname)
if die == nil { if die == nil {
die = newdie(&dwtypes, DW_ABRV_PTRTYPE, ptrname) pdie := newdie(&dwtypes, DW_ABRV_PTRTYPE, ptrname, 0)
newrefattr(die, DW_AT_type, dwtype) newrefattr(pdie, DW_AT_type, dwtype)
return pdie.sym
} }
return die return die
...@@ -1084,7 +1038,7 @@ func copychildrenexcept(dst *DWDie, src *DWDie, except *DWDie) { ...@@ -1084,7 +1038,7 @@ func copychildrenexcept(dst *DWDie, src *DWDie, except *DWDie) {
if src == except { if src == except {
continue 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 { for a := src.attr; a != nil; a = a.link {
newattr(c, a.atr, int(a.cls), a.value, a.data) newattr(c, a.atr, int(a.cls), a.value, a.data)
} }
...@@ -1100,9 +1054,11 @@ func copychildren(dst *DWDie, src *DWDie) { ...@@ -1100,9 +1054,11 @@ func copychildren(dst *DWDie, src *DWDie) {
// Search children (assumed to have DW_TAG_member) for the one named // Search children (assumed to have DW_TAG_member) for the one named
// field and set its DW_AT_type to dwtype // field and set its DW_AT_type to dwtype
func substitutetype(structdie *DWDie, field string, dwtype *DWDie) { func substitutetype(structdie *DWDie, field string, dwtype *LSym) {
child := mustFind(structdie, field) child := findchild(structdie, field)
if child == nil { if child == nil {
Exitf("dwarf substitutetype: %s does not have member %s",
getattr(structdie, DW_AT_name).data, field)
return return
} }
...@@ -1114,8 +1070,17 @@ func substitutetype(structdie *DWDie, field string, dwtype *DWDie) { ...@@ -1114,8 +1070,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) { func synthesizestringtypes(die *DWDie) {
prototype := walktypedef(defgotype(lookup_or_diag("type.runtime.stringStructDWARF"))) prototype := walktypedef(findprotodie("type.runtime.stringStructDWARF"))
if prototype == nil { if prototype == nil {
return return
} }
...@@ -1129,7 +1094,7 @@ func synthesizestringtypes(die *DWDie) { ...@@ -1129,7 +1094,7 @@ func synthesizestringtypes(die *DWDie) {
} }
func synthesizeslicetypes(die *DWDie) { func synthesizeslicetypes(die *DWDie) {
prototype := walktypedef(defgotype(lookup_or_diag("type.runtime.slice"))) prototype := walktypedef(findprotodie("type.runtime.slice"))
if prototype == nil { if prototype == nil {
return return
} }
...@@ -1139,7 +1104,7 @@ func synthesizeslicetypes(die *DWDie) { ...@@ -1139,7 +1104,7 @@ func synthesizeslicetypes(die *DWDie) {
continue continue
} }
copychildren(die, prototype) 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)) substitutetype(die, "array", defptrto(elem))
} }
} }
...@@ -1163,9 +1128,21 @@ const ( ...@@ -1163,9 +1128,21 @@ const (
BucketSize = 8 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) { func synthesizemaptypes(die *DWDie) {
hash := walktypedef(defgotype(lookup_or_diag("type.runtime.hmap"))) hash := walktypedef(findprotodie("type.runtime.hmap"))
bucket := walktypedef(defgotype(lookup_or_diag("type.runtime.bmap"))) bucket := walktypedef(findprotodie("type.runtime.bmap"))
if hash == nil { if hash == nil {
return return
...@@ -1175,97 +1152,92 @@ func synthesizemaptypes(die *DWDie) { ...@@ -1175,97 +1152,92 @@ func synthesizemaptypes(die *DWDie) {
if die.abbrev != DW_ABRV_MAPTYPE { if die.abbrev != DW_ABRV_MAPTYPE {
continue continue
} }
gotype := getattr(die, DW_AT_type).data.(*LSym)
keytype := walktypedef(getattr(die, DW_AT_go_key).data.(*DWDie)) keytype := decodetype_mapkey(gotype)
valtype := walktypedef(getattr(die, DW_AT_go_elem).data.(*DWDie)) 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. // 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 indirect_key, indirect_val := false, false
if keysize > MaxKeySize { if keysize > MaxKeySize {
keysize = Thearch.Ptrsize keysize = int64(Thearch.Ptrsize)
indirect_key = true indirect_key = true
} }
if valsize > MaxValSize { if valsize > MaxValSize {
valsize = Thearch.Ptrsize valsize = int64(Thearch.Ptrsize)
indirect_val = true indirect_val = true
} }
// Construct type to represent an array of BucketSize keys // Construct type to represent an array of BucketSize keys
dwhk := newdie(&dwtypes, DW_ABRV_ARRAYTYPE, mkinternaltypename("[]key", getattr(keytype, DW_AT_name).data.(string), "")) keyname := nameFromDIESym(keytype)
dwhks := mkinternaltype(DW_ABRV_ARRAYTYPE, "[]key", keyname, "", func(dwhk *DWDie) {
newattr(dwhk, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize*int64(keysize), 0) newattr(dwhk, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize*int64(keysize), 0)
t := keytype t := keytype
if indirect_key { if indirect_key {
t = defptrto(keytype) t = defptrto(keytype)
} }
newrefattr(dwhk, DW_AT_type, t) newrefattr(dwhk, DW_AT_type, t)
fld := newdie(dwhk, DW_ABRV_ARRAYRANGE, "size") fld := newdie(dwhk, DW_ABRV_ARRAYRANGE, "size", 0)
newattr(fld, DW_AT_count, DW_CLS_CONSTANT, BucketSize, 0) newattr(fld, DW_AT_count, DW_CLS_CONSTANT, BucketSize, 0)
newrefattr(fld, DW_AT_type, mustFind(&dwtypes, "uintptr")) newrefattr(fld, DW_AT_type, mustFind("uintptr"))
})
// Construct type to represent an array of BucketSize values // Construct type to represent an array of BucketSize values
dwhv := newdie(&dwtypes, DW_ABRV_ARRAYTYPE, mkinternaltypename("[]val", getattr(valtype, DW_AT_name).data.(string), "")) valname := nameFromDIESym(valtype)
dwhvs := mkinternaltype(DW_ABRV_ARRAYTYPE, "[]val", valname, "", func(dwhv *DWDie) {
newattr(dwhv, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize*int64(valsize), 0) newattr(dwhv, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize*int64(valsize), 0)
t = valtype t := valtype
if indirect_val { if indirect_val {
t = defptrto(valtype) t = defptrto(valtype)
} }
newrefattr(dwhv, DW_AT_type, t) newrefattr(dwhv, DW_AT_type, t)
fld = newdie(dwhv, DW_ABRV_ARRAYRANGE, "size") fld := newdie(dwhv, DW_ABRV_ARRAYRANGE, "size", 0)
newattr(fld, DW_AT_count, DW_CLS_CONSTANT, BucketSize, 0) newattr(fld, DW_AT_count, DW_CLS_CONSTANT, BucketSize, 0)
newrefattr(fld, DW_AT_type, mustFind(&dwtypes, "uintptr")) newrefattr(fld, DW_AT_type, mustFind("uintptr"))
})
// Construct bucket<K,V> // 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))) dwhbs := mkinternaltype(DW_ABRV_STRUCTTYPE, "bucket", keyname, valname, func(dwhb *DWDie) {
// Copy over all fields except the field "data" from the generic
// Copy over all fields except the field "data" from the generic bucket. // bucket. "data" will be replaced with keys/values below.
// "data" will be replaced with keys/values below. copychildrenexcept(dwhb, bucket, findchild(bucket, "data"))
copychildrenexcept(dwhb, bucket, find(bucket, "data"))
fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "keys") fld := newdie(dwhb, DW_ABRV_STRUCTFIELD, "keys", 0)
newrefattr(fld, DW_AT_type, dwhk) newrefattr(fld, DW_AT_type, dwhks)
newmemberoffsetattr(fld, BucketSize) newmemberoffsetattr(fld, BucketSize)
fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "values") fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "values", 0)
newrefattr(fld, DW_AT_type, dwhv) newrefattr(fld, DW_AT_type, dwhvs)
newmemberoffsetattr(fld, BucketSize+BucketSize*int32(keysize)) newmemberoffsetattr(fld, BucketSize+BucketSize*int32(keysize))
fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "overflow") fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "overflow", 0)
newrefattr(fld, DW_AT_type, defptrto(dwhb)) newrefattr(fld, DW_AT_type, defptrto(dwhb.sym))
newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))) newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize)))
if Thearch.Regsize > Thearch.Ptrsize { if Thearch.Regsize > Thearch.Ptrsize {
fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "pad") fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "pad", 0)
newrefattr(fld, DW_AT_type, mustFind(&dwtypes, "uintptr")) newrefattr(fld, DW_AT_type, mustFind("uintptr"))
newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))+int32(Thearch.Ptrsize)) newmemberoffsetattr(fld, BucketSize+BucketSize*(int32(keysize)+int32(valsize))+int32(Thearch.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*int64(keysize)+BucketSize*int64(valsize)+int64(Thearch.Regsize), 0)
})
// Construct hash<K,V> // 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))) dwhs := mkinternaltype(DW_ABRV_STRUCTTYPE, "hash", keyname, valname, func(dwh *DWDie) {
copychildren(dwh, hash) copychildren(dwh, hash)
substitutetype(dwh, "buckets", defptrto(dwhb)) substitutetype(dwh, "buckets", defptrto(dwhbs))
substitutetype(dwh, "oldbuckets", defptrto(dwhb)) substitutetype(dwh, "oldbuckets", defptrto(dwhbs))
newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT, getattr(hash, DW_AT_byte_size).value, nil) 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> // 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) { func synthesizechantypes(die *DWDie) {
sudog := walktypedef(defgotype(lookup_or_diag("type.runtime.sudog"))) sudog := walktypedef(findprotodie("type.runtime.sudog"))
waitq := walktypedef(defgotype(lookup_or_diag("type.runtime.waitq"))) waitq := walktypedef(findprotodie("type.runtime.waitq"))
hchan := walktypedef(defgotype(lookup_or_diag("type.runtime.hchan"))) hchan := walktypedef(findprotodie("type.runtime.hchan"))
if sudog == nil || waitq == nil || hchan == nil { if sudog == nil || waitq == nil || hchan == nil {
return return
} }
...@@ -1276,16 +1248,13 @@ func synthesizechantypes(die *DWDie) { ...@@ -1276,16 +1248,13 @@ func synthesizechantypes(die *DWDie) {
if die.abbrev != DW_ABRV_CHANTYPE { if die.abbrev != DW_ABRV_CHANTYPE {
continue continue
} }
elemsize := Thearch.Ptrsize elemgotype := getattr(die, DW_AT_type).data.(*LSym)
elemtype := getattr(die, DW_AT_go_elem).data.(*DWDie) elemsize := decodetype_size(elemgotype)
a := getattr(elemtype, DW_AT_byte_size) elemname := elemgotype.Name[5:]
if a != nil { elemtype := walksymtypedef(defgotype(elemgotype))
elemsize = int(a.value)
}
// sudog<T> // sudog<T>
dws := newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("sudog", getattr(elemtype, DW_AT_name).data.(string), "")) dwss := mkinternaltype(DW_ABRV_STRUCTTYPE, "sudog", elemname, "", func(dws *DWDie) {
copychildren(dws, sudog) copychildren(dws, sudog)
substitutetype(dws, "elem", elemtype) substitutetype(dws, "elem", elemtype)
if elemsize > 8 { if elemsize > 8 {
...@@ -1294,24 +1263,26 @@ func synthesizechantypes(die *DWDie) { ...@@ -1294,24 +1263,26 @@ func synthesizechantypes(die *DWDie) {
elemsize = 0 elemsize = 0
} }
newattr(dws, DW_AT_byte_size, DW_CLS_CONSTANT, int64(sudogsize)+int64(elemsize), nil) newattr(dws, DW_AT_byte_size, DW_CLS_CONSTANT, int64(sudogsize)+int64(elemsize), nil)
})
// waitq<T> // 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) copychildren(dww, waitq)
substitutetype(dww, "first", defptrto(dws)) substitutetype(dww, "first", defptrto(dwss))
substitutetype(dww, "last", defptrto(dws)) substitutetype(dww, "last", defptrto(dwss))
newattr(dww, DW_AT_byte_size, DW_CLS_CONSTANT, getattr(waitq, DW_AT_byte_size).value, nil) newattr(dww, DW_AT_byte_size, DW_CLS_CONSTANT, getattr(waitq, DW_AT_byte_size).value, nil)
})
// hchan<T> // 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) copychildren(dwh, hchan)
substitutetype(dwh, "recvq", dww) substitutetype(dwh, "recvq", dwws)
substitutetype(dwh, "sendq", dww) substitutetype(dwh, "sendq", dwws)
newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT, getattr(hchan, DW_AT_byte_size).value, nil) 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 +1302,13 @@ func defdwsymb(sym *LSym, s string, t int, v int64, size int64, ver int, gotype ...@@ -1331,13 +1302,13 @@ func defdwsymb(sym *LSym, s string, t int, v int64, size int64, ver int, gotype
var dv *DWDie var dv *DWDie
var dt *DWDie var dt *LSym
switch t { switch t {
default: default:
return return
case 'd', 'b', 'D', 'B': case 'd', 'b', 'D', 'B':
dv = newdie(&dwglobals, DW_ABRV_VARIABLE, s) dv = newdie(&dwglobals, DW_ABRV_VARIABLE, s, ver)
newabslocexprattr(dv, v, sym) newabslocexprattr(dv, v, sym)
if ver == 0 { if ver == 0 {
newattr(dv, DW_AT_external, DW_CLS_FLAG, 1, 0) newattr(dv, DW_AT_external, DW_CLS_FLAG, 1, 0)
...@@ -1386,23 +1357,23 @@ const ( ...@@ -1386,23 +1357,23 @@ const (
OPCODE_BASE = 10 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 { if LINE_BASE <= delta_lc && delta_lc < LINE_BASE+LINE_RANGE {
var opcode int64 = OPCODE_BASE + (delta_lc - LINE_BASE) + (LINE_RANGE * delta_pc) var opcode int64 = OPCODE_BASE + (delta_lc - LINE_BASE) + (LINE_RANGE * delta_pc)
if OPCODE_BASE <= opcode && opcode < 256 { if OPCODE_BASE <= opcode && opcode < 256 {
Cput(uint8(opcode)) Adduint8(Ctxt, s, uint8(opcode))
return return
} }
} }
if delta_pc != 0 { if delta_pc != 0 {
Cput(DW_LNS_advance_pc) Adduint8(Ctxt, s, DW_LNS_advance_pc)
sleb128put(delta_pc) sleb128put(s, delta_pc)
} }
Cput(DW_LNS_advance_line) Adduint8(Ctxt, s, DW_LNS_advance_line)
sleb128put(delta_lc) sleb128put(s, delta_lc)
Cput(DW_LNS_copy) Adduint8(Ctxt, s, DW_LNS_copy)
} }
func newcfaoffsetattr(die *DWDie, offs int32) { func newcfaoffsetattr(die *DWDie, offs int32) {
...@@ -1428,26 +1399,6 @@ func mkvarname(name string, da int) string { ...@@ -1428,26 +1399,6 @@ func mkvarname(name string, da int) string {
* Walk prog table, emit line program and build DIE tree. * 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 { func getCompilationDir() string {
if dir, err := os.Getwd(); err == nil { if dir, err := os.Getwd(); err == nil {
return dir return dir
...@@ -1455,28 +1406,30 @@ func getCompilationDir() string { ...@@ -1455,28 +1406,30 @@ func getCompilationDir() string {
return "/" return "/"
} }
func writelines() { func writelines(prev *LSym) *LSym {
if linesec == nil { if linesec == nil {
linesec = Linklookup(Ctxt, ".dwarfline", 0) linesec = Linklookup(Ctxt, ".debug_line", 0)
} }
linesec.Type = obj.SDWARFSECT
linesec.R = linesec.R[:0] linesec.R = linesec.R[:0]
ls := linesec
prev.Next = ls
unitstart := int64(-1) unitstart := int64(-1)
headerstart := int64(-1)
headerend := int64(-1) headerend := int64(-1)
epc := int64(0) epc := int64(0)
var epcs *LSym var epcs *LSym
lineo = Cpos()
var dwinfo *DWDie var dwinfo *DWDie
flushunit(dwinfo, epc, epcs, unitstart, int32(headerend-unitstart-10))
unitstart = Cpos()
lang := DW_LANG_Go lang := DW_LANG_Go
s := Ctxt.Textp s := Ctxt.Textp
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_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) 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. // OS X linker requires compilation dir or absolute path in comp unit name to output debug info.
compDir := getCompilationDir() compDir := getCompilationDir()
...@@ -1484,26 +1437,30 @@ func writelines() { ...@@ -1484,26 +1437,30 @@ func writelines() {
// Write .debug_line Line Number Program Header (sec 6.2.4) // Write .debug_line Line Number Program Header (sec 6.2.4)
// Fields marked with (*) must be changed for 64-bit dwarf // Fields marked with (*) must be changed for 64-bit dwarf
Thearch.Lput(0) // unit_length (*), will be filled in by flushunit. unit_length_offset := ls.Size
Thearch.Wput(2) // dwarf version (appendix F) Adduint32(Ctxt, ls, 0) // unit_length (*), filled in at end.
Thearch.Lput(0) // header_length (*), filled in by flushunit. 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 // cpos == unitstart + 4 + 2 + 4
Cput(1) // minimum_instruction_length Adduint8(Ctxt, ls, 1) // minimum_instruction_length
Cput(1) // default_is_stmt Adduint8(Ctxt, ls, 1) // default_is_stmt
Cput(LINE_BASE & 0xFF) // line_base Adduint8(Ctxt, ls, LINE_BASE&0xFF) // line_base
Cput(LINE_RANGE) // line_range Adduint8(Ctxt, ls, LINE_RANGE) // line_range
Cput(OPCODE_BASE) // opcode_base Adduint8(Ctxt, ls, OPCODE_BASE) // opcode_base
Cput(0) // standard_opcode_lengths[1] Adduint8(Ctxt, ls, 0) // standard_opcode_lengths[1]
Cput(1) // standard_opcode_lengths[2] Adduint8(Ctxt, ls, 1) // standard_opcode_lengths[2]
Cput(1) // standard_opcode_lengths[3] Adduint8(Ctxt, ls, 1) // standard_opcode_lengths[3]
Cput(1) // standard_opcode_lengths[4] Adduint8(Ctxt, ls, 1) // standard_opcode_lengths[4]
Cput(1) // standard_opcode_lengths[5] Adduint8(Ctxt, ls, 1) // standard_opcode_lengths[5]
Cput(0) // standard_opcode_lengths[6] Adduint8(Ctxt, ls, 0) // standard_opcode_lengths[6]
Cput(0) // standard_opcode_lengths[7] Adduint8(Ctxt, ls, 0) // standard_opcode_lengths[7]
Cput(0) // standard_opcode_lengths[8] Adduint8(Ctxt, ls, 0) // standard_opcode_lengths[8]
Cput(1) // standard_opcode_lengths[9] Adduint8(Ctxt, ls, 1) // standard_opcode_lengths[9]
Cput(0) // include_directories (empty) Adduint8(Ctxt, ls, 0) // include_directories (empty)
files := make([]*LSym, Ctxt.Nhistfile) files := make([]*LSym, Ctxt.Nhistfile)
...@@ -1512,25 +1469,28 @@ func writelines() { ...@@ -1512,25 +1469,28 @@ func writelines() {
} }
for i := 0; int32(i) < Ctxt.Nhistfile; i++ { for i := 0; int32(i) < Ctxt.Nhistfile; i++ {
strnput(files[i].Name, len(files[i].Name)+4) Addstring(ls, files[i].Name)
Adduint8(Ctxt, ls, 0)
Adduint8(Ctxt, ls, 0)
Adduint8(Ctxt, ls, 0)
} }
// 4 zeros: the string termination + 3 fields. // 4 zeros: the string termination + 3 fields.
Cput(0) Adduint8(Ctxt, ls, 0)
// terminate file_names. // terminate file_names.
headerend = Cpos() headerend = ls.Size
Cput(0) // start extended opcode Adduint8(Ctxt, ls, 0) // start extended opcode
uleb128put(1 + int64(Thearch.Ptrsize)) uleb128put(ls, 1+int64(Thearch.Ptrsize))
Cput(DW_LNE_set_address) Adduint8(Ctxt, ls, DW_LNE_set_address)
pc := s.Value pc := s.Value
line := 1 line := 1
file := 1 file := 1
if Linkmode == LinkExternal { if Linkmode == LinkExternal {
adddwarfrel(linesec, s, lineo, Thearch.Ptrsize, 0) Addaddr(Ctxt, ls, s)
} else { } else {
addrput(pc) addrput(ls, pc)
} }
var pcfile Pciter var pcfile Pciter
...@@ -1538,7 +1498,7 @@ func writelines() { ...@@ -1538,7 +1498,7 @@ func writelines() {
for Ctxt.Cursym = Ctxt.Textp; Ctxt.Cursym != nil; Ctxt.Cursym = Ctxt.Cursym.Next { for Ctxt.Cursym = Ctxt.Textp; Ctxt.Cursym != nil; Ctxt.Cursym = Ctxt.Cursym.Next {
s = Ctxt.Cursym 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) newattr(dwfunc, DW_AT_low_pc, DW_CLS_ADDRESS, s.Value, s)
epc = s.Value + s.Size epc = s.Value + s.Size
epcs = s epcs = s
...@@ -1568,12 +1528,12 @@ func writelines() { ...@@ -1568,12 +1528,12 @@ func writelines() {
} }
if int32(file) != pcfile.value { if int32(file) != pcfile.value {
Cput(DW_LNS_set_file) Adduint8(Ctxt, ls, DW_LNS_set_file)
uleb128put(int64(pcfile.value)) uleb128put(ls, int64(pcfile.value))
file = int(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) pc = s.Value + int64(pcline.pc)
line = int(pcline.value) line = int(pcline.value)
...@@ -1610,7 +1570,7 @@ func writelines() { ...@@ -1610,7 +1570,7 @@ func writelines() {
continue continue
} }
var n string var n string
if find(dwfunc, a.Asym.Name) != nil { if findchild(dwfunc, a.Asym.Name) != nil {
n = mkvarname(a.Asym.Name, da) n = mkvarname(a.Asym.Name, da)
} else { } else {
n = a.Asym.Name n = a.Asym.Name
...@@ -1621,7 +1581,7 @@ func writelines() { ...@@ -1621,7 +1581,7 @@ func writelines() {
n = n[i+1:] n = n[i+1:]
} }
dwvar := newdie(dwfunc, dt, n) dwvar := newdie(dwfunc, dt, n, 0)
newcfaoffsetattr(dwvar, int32(offs)) newcfaoffsetattr(dwvar, int32(offs))
newrefattr(dwvar, DW_AT_type, defgotype(a.Gotype)) newrefattr(dwvar, DW_AT_type, defgotype(a.Gotype))
...@@ -1642,8 +1602,16 @@ func writelines() { ...@@ -1642,8 +1602,16 @@ func writelines() {
} }
} }
flushunit(dwinfo, epc, epcs, unitstart, int32(headerend-unitstart-10)) Adduint8(Ctxt, ls, 0) // start extended opcode
linesize = Cpos() - lineo 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
} }
/* /*
...@@ -1675,47 +1643,49 @@ func appendPCDeltaCFA(b []byte, deltapc, cfa int64) []byte { ...@@ -1675,47 +1643,49 @@ func appendPCDeltaCFA(b []byte, deltapc, cfa int64) []byte {
return b return b
} }
func writeframes() { func writeframes(prev *LSym) *LSym {
if framesec == nil { if framesec == nil {
framesec = Linklookup(Ctxt, ".dwarfframe", 0) framesec = Linklookup(Ctxt, ".debug_frame", 0)
} }
framesec.Type = obj.SDWARFSECT
framesec.R = framesec.R[:0] framesec.R = framesec.R[:0]
frameo = Cpos() fs := framesec
prev.Next = fs
// Emit the CIE, Section 6.4.1 // Emit the CIE, Section 6.4.1
Thearch.Lput(CIERESERVE) // initial length, must be multiple of thearch.ptrsize Adduint32(Ctxt, fs, CIERESERVE) // initial length, must be multiple of thearch.ptrsize
Thearch.Lput(0xffffffff) // cid. Adduint32(Ctxt, fs, 0xffffffff) // cid.
Cput(3) // dwarf version (appendix F) Adduint8(Ctxt, fs, 3) // dwarf version (appendix F)
Cput(0) // augmentation "" Adduint8(Ctxt, fs, 0) // augmentation ""
uleb128put(1) // code_alignment_factor uleb128put(fs, 1) // code_alignment_factor
sleb128put(DATAALIGNMENTFACTOR) // guess sleb128put(fs, DATAALIGNMENTFACTOR) // guess
uleb128put(int64(Thearch.Dwarfreglr)) // return_address_register uleb128put(fs, int64(Thearch.Dwarfreglr)) // return_address_register
Cput(DW_CFA_def_cfa) Adduint8(Ctxt, fs, DW_CFA_def_cfa)
uleb128put(int64(Thearch.Dwarfregsp)) // register SP (**ABI-dependent, defined in l.h) uleb128put(fs, int64(Thearch.Dwarfregsp)) // register SP (**ABI-dependent, defined in l.h)
if haslinkregister() { if haslinkregister() {
uleb128put(int64(0)) // offset uleb128put(fs, int64(0)) // offset
} else { } else {
uleb128put(int64(Thearch.Ptrsize)) // offset uleb128put(fs, int64(Thearch.Ptrsize)) // offset
} }
Cput(DW_CFA_offset_extended) Adduint8(Ctxt, fs, DW_CFA_offset_extended)
uleb128put(int64(Thearch.Dwarfreglr)) // return address uleb128put(fs, int64(Thearch.Dwarfreglr)) // return address
if haslinkregister() { if haslinkregister() {
uleb128put(int64(0) / DATAALIGNMENTFACTOR) // at cfa - 0 uleb128put(fs, int64(0)/DATAALIGNMENTFACTOR) // at cfa - 0
} else { } else {
uleb128put(int64(-Thearch.Ptrsize) / DATAALIGNMENTFACTOR) // at cfa - x*4 uleb128put(fs, int64(-Thearch.Ptrsize)/DATAALIGNMENTFACTOR) // at cfa - x*4
} }
// 4 is to exclude the length field. // 4 is to exclude the length field.
pad := CIERESERVE + frameo + 4 - Cpos() pad := CIERESERVE + 4 - fs.Size
if pad < 0 { 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 deltaBuf []byte
var pcsp Pciter var pcsp Pciter
...@@ -1754,21 +1724,17 @@ func writeframes() { ...@@ -1754,21 +1724,17 @@ func writeframes() {
// 4 bytes: Pointer to the CIE above, at offset 0 // 4 bytes: Pointer to the CIE above, at offset 0
// ptrsize: initial location // ptrsize: initial location
// ptrsize: address range // ptrsize: address range
Thearch.Lput(uint32(4 + 2*Thearch.Ptrsize + len(deltaBuf))) // length (excludes itself) Adduint32(Ctxt, fs, uint32(4+2*Thearch.Ptrsize+len(deltaBuf))) // length (excludes itself)
if Linkmode == LinkExternal { if Linkmode == LinkExternal {
adddwarfrel(framesec, framesym, frameo, 4, 0) // CIE offset adddwarfref(Ctxt, fs, framesec, 4)
adddwarfrel(framesec, s, frameo, Thearch.Ptrsize, 0) // initial location
} else { } else {
Thearch.Lput(0) // CIE offset Adduint32(Ctxt, fs, 0) // CIE offset
addrput(s.Value) // initial location
} }
addrput(s.Size) // address range Addaddr(Ctxt, fs, s)
addrput(fs, s.Size) // address range
Cwrite(deltaBuf) Addbytes(Ctxt, fs, deltaBuf)
} }
return fs
Cflush()
framesize = Cpos() - frameo
} }
/* /*
...@@ -1778,12 +1744,14 @@ const ( ...@@ -1778,12 +1744,14 @@ const (
COMPUNITHEADERSIZE = 4 + 2 + 4 + 1 COMPUNITHEADERSIZE = 4 + 2 + 4 + 1
) )
func writeinfo() { func writeinfo(prev *LSym) *LSym {
fwdcount = 0
if infosec == nil { if infosec == nil {
infosec = Linklookup(Ctxt, ".dwarfinfo", 0) infosec = Linklookup(Ctxt, ".debug_info", 0)
} }
infosec.R = infosec.R[:0] infosec.R = infosec.R[:0]
infosec.Type = obj.SDWARFINFO
infosec.Attr |= AttrReachable
prev.Next, prev = infosec, infosec
if arangessec == nil { if arangessec == nil {
arangessec = Linklookup(Ctxt, ".dwarfaranges", 0) arangessec = Linklookup(Ctxt, ".dwarfaranges", 0)
...@@ -1791,32 +1759,30 @@ func writeinfo() { ...@@ -1791,32 +1759,30 @@ func writeinfo() {
arangessec.R = arangessec.R[:0] arangessec.R = arangessec.R[:0]
for compunit := dwroot.child; compunit != nil; compunit = compunit.link { 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) // Write .debug_info Compilation Unit Header (sec 7.5.1)
// Fields marked with (*) must be changed for 64-bit dwarf // Fields marked with (*) must be changed for 64-bit dwarf
// This must match COMPUNITHEADERSIZE above. // This must match COMPUNITHEADERSIZE above.
Thearch.Lput(0) // unit_length (*), will be filled in later. Adduint32(Ctxt, s, 0) // unit_length (*), will be filled in later.
Thearch.Wput(2) // dwarf version (appendix F) Adduint16(Ctxt, s, 2) // dwarf version (appendix F)
// debug_abbrev_offset (*) // debug_abbrev_offset (*)
if Linkmode == LinkExternal { adddwarfref(Ctxt, s, abbrevsym, 4)
adddwarfrel(infosec, abbrevsym, infoo, 4, 0)
} else {
Thearch.Lput(0)
}
Cput(uint8(Thearch.Ptrsize)) // address_size
putdie(compunit) Adduint8(Ctxt, s, uint8(Thearch.Ptrsize)) // address_size
here := Cpos() prev = putdie(prev, compunit)
Cseek(unitstart) cusize := s.Size - 4 // exclude the length field.
Thearch.Lput(uint32(here - unitstart - 4)) // exclude the length field. for child := s.Next; child != nil; child = child.Next {
Cseek(here) cusize += child.Size
} }
Cflush() setuint32(Ctxt, s, 0, uint32(cusize))
newattr(compunit, DW_AT_byte_size, DW_CLS_CONSTANT, int64(cusize), 0)
}
return prev
} }
/* /*
...@@ -1837,48 +1803,49 @@ func ispubtype(die *DWDie) bool { ...@@ -1837,48 +1803,49 @@ func ispubtype(die *DWDie) bool {
return die.abbrev >= DW_ABRV_NULLTYPE return die.abbrev >= DW_ABRV_NULLTYPE
} }
func writepub(ispub func(*DWDie) bool) int64 { func writepub(sname string, ispub func(*DWDie) bool, prev *LSym) *LSym {
sectionstart := Cpos() s := Linklookup(Ctxt, sname, 0)
s.Type = obj.SDWARFSECT
prev.Next = s
for compunit := dwroot.child; compunit != nil; compunit = compunit.link { for compunit := dwroot.child; compunit != nil; compunit = compunit.link {
unitend := infoo + infosize sectionstart := s.Size
unitstart := compunit.offs - COMPUNITHEADERSIZE culength := uint32(getattr(compunit, DW_AT_byte_size).value) + 4
if compunit.link != nil {
unitend = compunit.link.offs - COMPUNITHEADERSIZE
}
// Write .debug_pubnames/types Header (sec 6.1.1) // Write .debug_pubnames/types Header (sec 6.1.1)
Thearch.Lput(0) // unit_length (*), will be filled in later. Adduint32(Ctxt, s, 0) // unit_length (*), will be filled in later.
Thearch.Wput(2) // dwarf version (appendix F) Adduint16(Ctxt, s, 2) // dwarf version (appendix F)
Thearch.Lput(uint32(unitstart)) // debug_info_offset (of the Comp unit Header) adddwarfref(Ctxt, s, compunit.sym, 4) // debug_info_offset (of the Comp unit Header)
Thearch.Lput(uint32(unitend - unitstart)) // debug_info_length Adduint32(Ctxt, s, culength) // debug_info_length
for die := compunit.child; die != nil; die = die.link { for die := compunit.child; die != nil; die = die.link {
if !ispub(die) { if !ispub(die) {
continue continue
} }
Thearch.Lput(uint32(die.offs - unitstart))
dwa := getattr(die, DW_AT_name) 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() setuint32(Ctxt, s, sectionstart, uint32(s.Size-sectionstart)-4) // exclude the length field.
Cseek(sectionstart)
Thearch.Lput(uint32(here - sectionstart - 4)) // exclude the length field.
Cseek(here)
} }
return sectionstart return s
} }
/* /*
* emit .debug_aranges. _info must have been written before, * emit .debug_aranges. _info must have been written before,
* because we need die->offs of dw_globals. * because we need die->offs of dw_globals.
*/ */
func writearanges() int64 { func writearanges(prev *LSym) *LSym {
sectionstart := Cpos() 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 // The first tuple is aligned to a multiple of the size of a single tuple
// (twice the size of an address) // (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(Thearch.Ptrsize*2))) // don't count unit_length field itself
...@@ -1894,78 +1861,46 @@ func writearanges() int64 { ...@@ -1894,78 +1861,46 @@ func writearanges() int64 {
} }
// Write .debug_aranges Header + entry (sec 6.1.2) // Write .debug_aranges Header + entry (sec 6.1.2)
Thearch.Lput(uint32(headersize) + 4*uint32(Thearch.Ptrsize) - 4) // unit_length (*) unitlength := uint32(headersize) + 4*uint32(Thearch.Ptrsize) - 4
Thearch.Wput(2) // dwarf version (appendix F) Adduint32(Ctxt, s, unitlength) // unit_length (*)
Adduint16(Ctxt, s, 2) // dwarf version (appendix F)
value := compunit.offs - COMPUNITHEADERSIZE // debug_info_offset adddwarfref(Ctxt, s, compunit.sym, 4)
if Linkmode == LinkExternal {
adddwarfrel(arangessec, infosym, sectionstart, 4, value)
} else {
Thearch.Lput(uint32(value))
}
Cput(uint8(Thearch.Ptrsize)) // address_size
Cput(0) // segment_size
strnput("", headersize-(4+2+4+1+1)) // align to thearch.ptrsize
if Linkmode == LinkExternal { Adduint8(Ctxt, s, uint8(Thearch.Ptrsize)) // address_size
adddwarfrel(arangessec, b.data.(*LSym), sectionstart, Thearch.Ptrsize, b.value-(b.data.(*LSym)).Value) Adduint8(Ctxt, s, 0) // segment_size
} else { padding := headersize - (4 + 2 + 4 + 1 + 1)
addrput(b.value) for i := 0; i < padding; i++ {
Adduint8(Ctxt, s, 0)
} }
addrput(e.value - b.value) Addaddrplus(Ctxt, s, b.data.(*LSym), b.value-(b.data.(*LSym)).Value)
addrput(0) addrput(s, e.value-b.value)
addrput(0) addrput(s, 0)
addrput(s, 0)
} }
if s.Size > 0 {
Cflush() prev.Next = s
return sectionstart prev = s
}
func writegdbscript() int64 {
sectionstart := Cpos()
if gdbscript != "" {
Cput(1) // magic 1 byte?
strnput(gdbscript, len(gdbscript)+1)
Cflush()
} }
return prev
return sectionstart
} }
func align(size int64) { func writegdbscript(prev *LSym) *LSym {
if HEADTYPE == obj.Hwindows { // Only Windows PE need section align.
strnput("", int(Rnd(size, PEFILEALIGN)-size))
}
}
func writedwarfreloc(s *LSym) int64 { if gdbscript != "" {
start := Cpos() s := Linklookup(Ctxt, ".debug_gdb_scripts", 0)
for ri := 0; ri < len(s.R); ri++ { s.Type = obj.SDWARFSECT
r := &s.R[ri] prev.Next = s
i := -1 prev = s
if Iself { Adduint8(Ctxt, s, 1) // magic 1 byte?
i = Thearch.Elfreloc1(r, int64(r.Off)) Addstring(s, gdbscript)
} 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)
}
} }
return start return prev
} }
func addmachodwarfsect(prev *Section, name string) *Section { var prototypedies map[string]*DWDie
sect := addsection(&Segdwarf, name, 04)
sect.Extnum = prev.Extnum + 1
sym := Linklookup(Ctxt, name, 0)
sym.Sect = sect
return sect
}
/* /*
* This is the main entry point for generating dwarf. After emitting * This is the main entry point for generating dwarf. After emitting
...@@ -1976,58 +1911,49 @@ func addmachodwarfsect(prev *Section, name string) *Section { ...@@ -1976,58 +1911,49 @@ func addmachodwarfsect(prev *Section, name string) *Section {
* passes. * passes.
* *
*/ */
func Dwarfemitdebugsections() { func dwarfgeneratedebugsyms() {
if Debug['w'] != 0 { // disable dwarf if Debug['w'] != 0 { // disable dwarf
return return
} }
if HEADTYPE == obj.Hplan9 {
return
}
if Linkmode == LinkExternal { if Linkmode == LinkExternal {
if !Iself && HEADTYPE != obj.Hdarwin { if !Iself && HEADTYPE != obj.Hdarwin {
return 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) if Debug['v'] != 0 {
framesym.Attr |= AttrHidden fmt.Fprintf(&Bso, "%5.2f dwarf\n", obj.Cputime())
}
} }
// For diagnostic messages. // For diagnostic messages.
newattr(&dwtypes, DW_AT_name, DW_CLS_STRING, int64(len("dwtypes")), "dwtypes") 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. // 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_NULLTYPE, "void", 0)
newdie(&dwtypes, DW_ABRV_BARE_PTRTYPE, "unsafe.Pointer") 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_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(Thearch.Ptrsize), 0)
newattr(die, DW_AT_go_kind, DW_CLS_CONSTANT, obj.KindUintptr, 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. // Needed by the prettyprinter code for interface inspection.
defgotype(lookup_or_diag("type.runtime._type")) defgotype(lookup_or_diag("type.runtime._type"))
...@@ -2036,12 +1962,10 @@ func Dwarfemitdebugsections() { ...@@ -2036,12 +1962,10 @@ func Dwarfemitdebugsections() {
genasmsym(defdwsymb) genasmsym(defdwsymb)
writeabbrev() dwarfp = writeabbrev()
align(abbrevsize) last := dwarfp
writelines() last = writelines(last)
align(linesize) last = writeframes(last)
writeframes()
align(framesize)
synthesizestringtypes(dwtypes.child) synthesizestringtypes(dwtypes.child)
synthesizeslicetypes(dwtypes.child) synthesizeslicetypes(dwtypes.child)
...@@ -2055,403 +1979,61 @@ func Dwarfemitdebugsections() { ...@@ -2055,403 +1979,61 @@ func Dwarfemitdebugsections() {
movetomodule(&dwtypes) movetomodule(&dwtypes)
movetomodule(&dwglobals) movetomodule(&dwglobals)
infoo = Cpos() // Need to reorder symbols so SDWARFINFO is after all SDWARFSECT
writeinfo() // (but we need to generate dies before writepub)
infoe := Cpos() writeinfo(last)
pubnameso = infoe infosyms := last.Next
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() last = writepub(".debug_pubnames", ispubname, last)
gdbscriptsize = Cpos() - gdbscripto last = writepub(".debug_pubtypes", ispubtype, last)
align(gdbscriptsize) last = writearanges(last)
last = writegdbscript(last)
for Cpos()&7 != 0 { last.Next = infosyms
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)
} }
/* /*
* Elf. * 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) { func dwarfaddshstrings(shstrtab *LSym) {
if Debug['w'] != 0 { // disable dwarf if Debug['w'] != 0 { // disable dwarf
return return
} }
elfstrdbg[ElfStrDebugAbbrev] = Addstring(shstrtab, ".debug_abbrev") Addstring(shstrtab, ".debug_abbrev")
elfstrdbg[ElfStrDebugAranges] = Addstring(shstrtab, ".debug_aranges") Addstring(shstrtab, ".debug_aranges")
elfstrdbg[ElfStrDebugFrame] = Addstring(shstrtab, ".debug_frame") Addstring(shstrtab, ".debug_frame")
elfstrdbg[ElfStrDebugInfo] = Addstring(shstrtab, ".debug_info") Addstring(shstrtab, ".debug_info")
elfstrdbg[ElfStrDebugLine] = Addstring(shstrtab, ".debug_line") Addstring(shstrtab, ".debug_line")
elfstrdbg[ElfStrDebugLoc] = Addstring(shstrtab, ".debug_loc") Addstring(shstrtab, ".debug_pubnames")
elfstrdbg[ElfStrDebugMacinfo] = Addstring(shstrtab, ".debug_macinfo") Addstring(shstrtab, ".debug_pubtypes")
elfstrdbg[ElfStrDebugPubNames] = Addstring(shstrtab, ".debug_pubnames") Addstring(shstrtab, ".debug_gdb_scripts")
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")
if Linkmode == LinkExternal { if Linkmode == LinkExternal {
elfstrdbg[ElfStrRelDebugInfo] = Addstring(shstrtab, elfRelType+".debug_info") Addstring(shstrtab, elfRelType+".debug_info")
elfstrdbg[ElfStrRelDebugAranges] = Addstring(shstrtab, elfRelType+".debug_aranges") Addstring(shstrtab, elfRelType+".debug_aranges")
elfstrdbg[ElfStrRelDebugLine] = Addstring(shstrtab, elfRelType+".debug_line") Addstring(shstrtab, elfRelType+".debug_line")
elfstrdbg[ElfStrRelDebugFrame] = Addstring(shstrtab, elfRelType+".debug_frame") Addstring(shstrtab, elfRelType+".debug_frame")
Addstring(shstrtab, elfRelType+".debug_pubnames")
infosym = Linklookup(Ctxt, ".debug_info", 0) Addstring(shstrtab, elfRelType+".debug_pubtypes")
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
} }
} }
// Add section symbols for DWARF debug info. This is called before // Add section symbols for DWARF debug info. This is called before
// dwarfaddelfheaders. // dwarfaddelfheaders.
func dwarfaddelfsectionsyms() { 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])
if elfRelType == ".rela" {
sh.type_ = SHT_RELA
} else {
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 if Debug['w'] != 0 { // disable dwarf
return 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 { if Linkmode != LinkExternal {
ms = newMachoSeg("__DWARF", nsect) return
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
} }
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)
} }
/* /*
...@@ -2461,13 +2043,12 @@ func dwarfaddpeheaders() { ...@@ -2461,13 +2043,12 @@ func dwarfaddpeheaders() {
if Debug['w'] != 0 { // disable dwarf if Debug['w'] != 0 { // disable dwarf
return return
} }
for sect := Segdwarf.Sect; sect != nil; sect = sect.Next {
newPEDWARFSection(".debug_abbrev", abbrevsize) h := newPEDWARFSection(sect.Name, int64(sect.Length))
newPEDWARFSection(".debug_line", linesize) fileoff := sect.Vaddr - Segdwarf.Vaddr + Segdwarf.Fileoff
newPEDWARFSection(".debug_frame", framesize) if uint64(h.PointerToRawData) != fileoff {
newPEDWARFSection(".debug_info", infosize) Diag("%s.PointerToRawData = %#x, want %#x", sect.Name, h.PointerToRawData, fileoff)
newPEDWARFSection(".debug_pubnames", pubnamessize) errorexit()
newPEDWARFSection(".debug_pubtypes", pubtypessize) }
newPEDWARFSection(".debug_aranges", arangessize) }
newPEDWARFSection(".debug_gdb_scripts", gdbscriptsize)
} }
...@@ -1622,6 +1622,9 @@ func elfshbits(sect *Section) *ElfShdr { ...@@ -1622,6 +1622,9 @@ func elfshbits(sect *Section) *ElfShdr {
sh.flags |= SHF_TLS sh.flags |= SHF_TLS
sh.type_ = SHT_NOBITS sh.type_ = SHT_NOBITS
} }
if strings.HasPrefix(sect.Name, ".debug") {
sh.flags = 0
}
if Linkmode != LinkExternal { if Linkmode != LinkExternal {
sh.addr = sect.Vaddr sh.addr = sect.Vaddr
...@@ -1739,6 +1742,9 @@ func Elfemitreloc() { ...@@ -1739,6 +1742,9 @@ func Elfemitreloc() {
for sect := Segdata.Sect; sect != nil; sect = sect.Next { for sect := Segdata.Sect; sect != nil; sect = sect.Next {
elfrelocsect(sect, datap) elfrelocsect(sect, datap)
} }
for sect := Segdwarf.Sect; sect != nil; sect = sect.Next {
elfrelocsect(sect, dwarfp)
}
} }
func addgonote(sectionName string, tag uint32, desc []byte) { func addgonote(sectionName string, tag uint32, desc []byte) {
...@@ -2067,6 +2073,9 @@ func Asmbelfsetup() { ...@@ -2067,6 +2073,9 @@ func Asmbelfsetup() {
for sect := Segdata.Sect; sect != nil; sect = sect.Next { for sect := Segdata.Sect; sect != nil; sect = sect.Next {
elfshalloc(sect) elfshalloc(sect)
} }
for sect := Segdwarf.Sect; sect != nil; sect = sect.Next {
elfshalloc(sect)
}
} }
func Asmbelf(symo int64) { func Asmbelf(symo int64) {
...@@ -2432,6 +2441,9 @@ elfobj: ...@@ -2432,6 +2441,9 @@ elfobj:
for sect := Segdata.Sect; sect != nil; sect = sect.Next { for sect := Segdata.Sect; sect != nil; sect = sect.Next {
elfshbits(sect) elfshbits(sect)
} }
for sect := Segdwarf.Sect; sect != nil; sect = sect.Next {
elfshbits(sect)
}
if Linkmode == LinkExternal { if Linkmode == LinkExternal {
for sect := Segtext.Sect; sect != nil; sect = sect.Next { for sect := Segtext.Sect; sect != nil; sect = sect.Next {
...@@ -2443,7 +2455,14 @@ elfobj: ...@@ -2443,7 +2455,14 @@ elfobj:
for sect := Segdata.Sect; sect != nil; sect = sect.Next { for sect := Segdata.Sect; sect != nil; sect = sect.Next {
elfshreloc(sect) 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 // add a .note.GNU-stack section to mark the stack as non-executable
sh := elfshname(".note.GNU-stack") sh := elfshname(".note.GNU-stack")
...@@ -2467,8 +2486,6 @@ elfobj: ...@@ -2467,8 +2486,6 @@ elfobj:
sh.off = uint64(symo) + uint64(Symsize) sh.off = uint64(symo) + uint64(Symsize)
sh.size = uint64(len(Elfstrdat)) sh.size = uint64(len(Elfstrdat))
sh.addralign = 1 sh.addralign = 1
dwarfaddelfheaders()
} }
/* Main header */ /* Main header */
......
...@@ -356,7 +356,7 @@ func machoshbits(mseg *MachoSeg, sect *Section, segname string) { ...@@ -356,7 +356,7 @@ func machoshbits(mseg *MachoSeg, sect *Section, segname string) {
buf := "__" + strings.Replace(sect.Name[1:], ".", "_", -1) buf := "__" + strings.Replace(sect.Name[1:], ".", "_", -1)
var msect *MachoSect var msect *MachoSect
if sect.Rwx&1 == 0 && (Thearch.Thechar == '7' || // arm64 if sect.Rwx&1 == 0 && segname != "__DWARF" && (Thearch.Thechar == '7' || // arm64
(Thearch.Thechar == '6' && (Buildmode == BuildmodeCShared || Buildmode == BuildmodeCArchive))) { // amd64 (Thearch.Thechar == '6' && (Buildmode == BuildmodeCShared || Buildmode == BuildmodeCArchive))) { // amd64
// Darwin external linker on arm64 and on amd64 in c-shared/c-archive buildmode // Darwin external linker on arm64 and on amd64 in c-shared/c-archive buildmode
// complains about absolute relocs in __TEXT, so if the section is not // complains about absolute relocs in __TEXT, so if the section is not
...@@ -411,6 +411,10 @@ func machoshbits(mseg *MachoSeg, sect *Section, segname string) { ...@@ -411,6 +411,10 @@ func machoshbits(mseg *MachoSeg, sect *Section, segname string) {
msect.name = "__mod_init_func" msect.name = "__mod_init_func"
msect.flag = 9 // S_MOD_INIT_FUNC_POINTERS msect.flag = 9 // S_MOD_INIT_FUNC_POINTERS
} }
if segname == "__DWARF" {
msect.flag |= 0x02000000
}
} }
func Asmbmacho() { func Asmbmacho() {
...@@ -492,6 +496,20 @@ func Asmbmacho() { ...@@ -492,6 +496,20 @@ func Asmbmacho() {
machoshbits(ms, sect, "__DATA") 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 { if Linkmode != LinkExternal {
switch Thearch.Thechar { switch Thearch.Thechar {
default: default:
...@@ -586,11 +604,6 @@ func Asmbmacho() { ...@@ -586,11 +604,6 @@ func Asmbmacho() {
ml.data[1] = 10<<16 | 7<<8 | 0<<0 // SDK 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() a := machowrite()
if int32(a) > HEADR { if int32(a) > HEADR {
Exitf("HEADR too small: %d > %d", a, HEADR) Exitf("HEADR too small: %d > %d", a, HEADR)
...@@ -876,5 +889,7 @@ func Machoemitreloc() { ...@@ -876,5 +889,7 @@ func Machoemitreloc() {
for sect := Segdata.Sect; sect != nil; sect = sect.Next { for sect := Segdata.Sect; sect != nil; sect = sect.Next {
machorelocsect(sect, datap) machorelocsect(sect, datap)
} }
dwarfemitreloc() for sect := Segdwarf.Sect; sect != nil; sect = sect.Next {
machorelocsect(sect, dwarfp)
}
} }
...@@ -195,18 +195,6 @@ func putelfsectionsym(s *LSym, shndx int) { ...@@ -195,18 +195,6 @@ func putelfsectionsym(s *LSym, shndx int) {
numelfsym++ 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() { func Asmelfsym() {
// the first symbol entry is reserved // the first symbol entry is reserved
putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_NOTYPE, 0, 0) putelfsyment(0, 0, 0, STB_LOCAL<<4|STT_NOTYPE, 0, 0)
......
...@@ -147,6 +147,9 @@ func asmb() { ...@@ -147,6 +147,9 @@ func asmb() {
ld.Cseek(int64(ld.Segdata.Fileoff)) ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen)) 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 */ /* output symbol table */
ld.Symsize = 0 ld.Symsize = 0
...@@ -161,7 +164,7 @@ func asmb() { ...@@ -161,7 +164,7 @@ func asmb() {
switch ld.HEADTYPE { switch ld.HEADTYPE {
default: default:
if ld.Iself { 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))) symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND)))
} }
...@@ -180,11 +183,6 @@ func asmb() { ...@@ -180,11 +183,6 @@ func asmb() {
ld.Cflush() ld.Cflush()
ld.Cwrite(ld.Elfstrdat) 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 { if ld.Linkmode == ld.LinkExternal {
ld.Elfemitreloc() ld.Elfemitreloc()
} }
......
...@@ -868,6 +868,9 @@ func asmb() { ...@@ -868,6 +868,9 @@ func asmb() {
ld.Cseek(int64(ld.Segdata.Fileoff)) ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen)) 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 */ /* output symbol table */
ld.Symsize = 0 ld.Symsize = 0
...@@ -882,7 +885,7 @@ func asmb() { ...@@ -882,7 +885,7 @@ func asmb() {
switch ld.HEADTYPE { switch ld.HEADTYPE {
default: default:
if ld.Iself { 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))) symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND)))
} }
...@@ -901,11 +904,6 @@ func asmb() { ...@@ -901,11 +904,6 @@ func asmb() {
ld.Cflush() ld.Cflush()
ld.Cwrite(ld.Elfstrdat) 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 { if ld.Linkmode == ld.LinkExternal {
ld.Elfemitreloc() ld.Elfemitreloc()
} }
......
...@@ -539,6 +539,9 @@ func asmb() { ...@@ -539,6 +539,9 @@ func asmb() {
ld.Cseek(int64(ld.Segdata.Fileoff)) ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen)) 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 */ /* output symbol table */
ld.Symsize = 0 ld.Symsize = 0
...@@ -552,7 +555,7 @@ func asmb() { ...@@ -552,7 +555,7 @@ func asmb() {
fmt.Fprintf(&ld.Bso, "%5.2f sym\n", obj.Cputime()) fmt.Fprintf(&ld.Bso, "%5.2f sym\n", obj.Cputime())
} }
ld.Bso.Flush() 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))) symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND)))
ld.Cseek(int64(symo)) ld.Cseek(int64(symo))
...@@ -566,7 +569,6 @@ func asmb() { ...@@ -566,7 +569,6 @@ func asmb() {
if ld.Debug['v'] != 0 { 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 { if ld.Linkmode == ld.LinkExternal {
ld.Elfemitreloc() ld.Elfemitreloc()
......
...@@ -643,19 +643,11 @@ func asmb() { ...@@ -643,19 +643,11 @@ func asmb() {
ld.Cseek(int64(ld.Segdata.Fileoff)) ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen)) 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) machlink := uint32(0)
if ld.HEADTYPE == obj.Hdarwin { 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()) machlink = uint32(ld.Domacholink())
} }
...@@ -672,7 +664,7 @@ func asmb() { ...@@ -672,7 +664,7 @@ func asmb() {
switch ld.HEADTYPE { switch ld.HEADTYPE {
default: default:
if ld.Iself { 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))) symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND)))
} }
...@@ -683,7 +675,7 @@ func asmb() { ...@@ -683,7 +675,7 @@ func asmb() {
symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(ld.INITRND))) + uint64(machlink)) symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(ld.INITRND))) + uint64(machlink))
case obj.Hwindows: 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)) symo = uint32(ld.Rnd(int64(symo), ld.PEFILEALIGN))
} }
...@@ -698,11 +690,6 @@ func asmb() { ...@@ -698,11 +690,6 @@ func asmb() {
ld.Cflush() ld.Cflush()
ld.Cwrite(ld.Elfstrdat) 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 { if ld.Linkmode == ld.LinkExternal {
ld.Elfemitreloc() ld.Elfemitreloc()
} }
...@@ -726,7 +713,6 @@ func asmb() { ...@@ -726,7 +713,6 @@ func asmb() {
if ld.Debug['v'] != 0 { 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: case obj.Hdarwin:
if ld.Linkmode == ld.LinkExternal { if ld.Linkmode == ld.LinkExternal {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment