Commit 8b83306c authored by Ryan Brown's avatar Ryan Brown Committed by Russ Cox

cmd/internal/ld: output dwarf in external link mode on darwin

Fixes #8973

Change-Id: Idd53fc6d9e6971ae31ed72a3df3cfdce0bfbc1fd
Reviewed-on: https://go-review.googlesource.com/8661Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
parent 9c9e36b3
...@@ -533,14 +533,12 @@ func asmb() { ...@@ -533,14 +533,12 @@ func asmb() {
fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime()) fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
} }
if ld.Debug['w'] == 0 { // TODO(minux): enable DWARF Support dwarfoff := uint32(ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Length), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND)))
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.Cseek(int64(dwarfoff))
ld.Segdwarf.Fileoff = uint64(ld.Cpos()) ld.Segdwarf.Fileoff = uint64(ld.Cpos())
ld.Dwarfemitdebugsections() ld.Dwarfemitdebugsections()
ld.Segdwarf.Filelen = uint64(ld.Cpos()) - ld.Segdwarf.Fileoff ld.Segdwarf.Filelen = uint64(ld.Cpos()) - ld.Segdwarf.Fileoff
}
machlink = uint32(ld.Domacholink()) machlink = uint32(ld.Domacholink())
} }
...@@ -567,7 +565,7 @@ func asmb() { ...@@ -567,7 +565,7 @@ func asmb() {
symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen) symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
case obj.Hdarwin: case obj.Hdarwin:
symo = uint32(ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Filelen), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND)) + int64(machlink)) symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(ld.INITRND))) + uint64(machlink))
} }
ld.Cseek(int64(symo)) ld.Cseek(int64(symo))
......
...@@ -710,7 +710,7 @@ func asmb() { ...@@ -710,7 +710,7 @@ func asmb() {
symo = int64(ld.Segdata.Fileoff + ld.Segdata.Filelen) symo = int64(ld.Segdata.Fileoff + ld.Segdata.Filelen)
case obj.Hdarwin: case obj.Hdarwin:
symo = int64(ld.Segdata.Fileoff + uint64(ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND))) + uint64(machlink)) symo = int64(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(ld.INITRND))) + uint64(machlink))
case obj.Hlinux, case obj.Hlinux,
obj.Hfreebsd, obj.Hfreebsd,
......
...@@ -317,14 +317,12 @@ func asmb() { ...@@ -317,14 +317,12 @@ func asmb() {
fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime()) fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
} }
if ld.Debug['w'] == 0 { // TODO(minux): enable DWARF Support dwarfoff := uint32(ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Length), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND)))
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.Cseek(int64(dwarfoff))
ld.Segdwarf.Fileoff = uint64(ld.Cpos()) ld.Segdwarf.Fileoff = uint64(ld.Cpos())
ld.Dwarfemitdebugsections() ld.Dwarfemitdebugsections()
ld.Segdwarf.Filelen = uint64(ld.Cpos()) - ld.Segdwarf.Fileoff ld.Segdwarf.Filelen = uint64(ld.Cpos()) - ld.Segdwarf.Fileoff
}
machlink = uint32(ld.Domacholink()) machlink = uint32(ld.Domacholink())
} }
...@@ -351,7 +349,7 @@ func asmb() { ...@@ -351,7 +349,7 @@ func asmb() {
symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen) symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
case obj.Hdarwin: case obj.Hdarwin:
symo = uint32(ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Filelen), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND)) + int64(machlink)) symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(ld.INITRND))) + uint64(machlink))
} }
ld.Cseek(int64(symo)) ld.Cseek(int64(symo))
......
...@@ -551,7 +551,7 @@ func asmb() { ...@@ -551,7 +551,7 @@ func asmb() {
symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen) symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
case obj.Hdarwin: case obj.Hdarwin:
symo = uint32(ld.Segdata.Fileoff + uint64(ld.Rnd(int64(ld.Segdata.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.Segdata.Fileoff + ld.Segdata.Filelen)
......
...@@ -17,6 +17,7 @@ package ld ...@@ -17,6 +17,7 @@ package ld
import ( import (
"cmd/internal/obj" "cmd/internal/obj"
"fmt" "fmt"
"os"
"strings" "strings"
) )
...@@ -240,6 +241,7 @@ var abbrevs = [DW_NABRV]DWAbbrev{ ...@@ -240,6 +241,7 @@ var abbrevs = [DW_NABRV]DWAbbrev{
{DW_AT_low_pc, DW_FORM_addr}, {DW_AT_low_pc, DW_FORM_addr},
{DW_AT_high_pc, DW_FORM_addr}, {DW_AT_high_pc, DW_FORM_addr},
{DW_AT_stmt_list, DW_FORM_data4}, {DW_AT_stmt_list, DW_FORM_data4},
{DW_AT_comp_dir, DW_FORM_string},
}, },
}, },
...@@ -694,6 +696,9 @@ func adddwarfrel(sec *LSym, sym *LSym, offsetbase int64, siz int, addend int64) ...@@ -694,6 +696,9 @@ func adddwarfrel(sec *LSym, sym *LSym, offsetbase int64, siz int, addend int64)
if Iself && Thearch.Thechar == '6' { if Iself && Thearch.Thechar == '6' {
addend = 0 addend = 0
} }
if HEADTYPE == obj.Hdarwin {
addend += sym.Value
}
switch siz { switch siz {
case 4: case 4:
Thearch.Lput(uint32(addend)) Thearch.Lput(uint32(addend))
...@@ -1547,6 +1552,13 @@ func flushunit(dwinfo *DWDie, pc int64, pcsym *LSym, unitstart int64, header_len ...@@ -1547,6 +1552,13 @@ func flushunit(dwinfo *DWDie, pc int64, pcsym *LSym, unitstart int64, header_len
} }
} }
func getCompilationDir() string {
if dir, err := os.Getwd(); err == nil {
return dir
}
return "/"
}
func writelines() { func writelines() {
if linesec == nil { if linesec == nil {
linesec = Linklookup(Ctxt, ".dwarfline", 0) linesec = Linklookup(Ctxt, ".dwarfline", 0)
...@@ -1571,6 +1583,9 @@ func writelines() { ...@@ -1571,6 +1583,9 @@ func writelines() {
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, unitstart-lineo, 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.
compDir := getCompilationDir()
newattr(dwinfo, DW_AT_comp_dir, DW_CLS_STRING, int64(len(compDir)), compDir)
// 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
...@@ -2083,6 +2098,14 @@ func writedwarfreloc(s *LSym) int64 { ...@@ -2083,6 +2098,14 @@ func writedwarfreloc(s *LSym) int64 {
return start return start
} }
func addmachodwarfsect(prev *Section, name string) *Section {
sect := addsection(&Segdwarf, name, 04)
sect.Extnum = prev.Extnum + 1
sym := Linklookup(Ctxt, name, 0)
sym.Sect = sect
return sect
}
/* /*
* This is the main entry point for generating dwarf. After emitting * This is the main entry point for generating dwarf. After emitting
* the mandatory debug_abbrev section, it calls writelines() to set up * the mandatory debug_abbrev section, it calls writelines() to set up
...@@ -2097,8 +2120,32 @@ func Dwarfemitdebugsections() { ...@@ -2097,8 +2120,32 @@ func Dwarfemitdebugsections() {
return return
} }
if Linkmode == LinkExternal && !Iself { if Linkmode == LinkExternal {
return if !Iself && HEADTYPE != obj.Hdarwin {
return
}
if HEADTYPE == obj.Hdarwin {
sect := Segdata.Sect
// find the last section.
for sect.Next != nil {
sect = sect.Next
}
sect = addmachodwarfsect(sect, ".debug_abbrev")
sect = addmachodwarfsect(sect, ".debug_line")
sect = addmachodwarfsect(sect, ".debug_frame")
sect = addmachodwarfsect(sect, ".debug_info")
}
infosym = Linklookup(Ctxt, ".debug_info", 0)
infosym.Hide = 1
abbrevsym = Linklookup(Ctxt, ".debug_abbrev", 0)
abbrevsym.Hide = 1
linesym = Linklookup(Ctxt, ".debug_line", 0)
linesym.Hide = 1
framesym = Linklookup(Ctxt, ".debug_frame", 0)
framesym.Hide = 1
} }
// For diagnostic messages. // For diagnostic messages.
...@@ -2191,6 +2238,15 @@ func Dwarfemitdebugsections() { ...@@ -2191,6 +2238,15 @@ func Dwarfemitdebugsections() {
for Cpos()&7 != 0 { for Cpos()&7 != 0 {
Cput(0) Cput(0)
} }
if HEADTYPE != obj.Hdarwin {
dwarfemitreloc()
}
}
func dwarfemitreloc() {
if Debug['w'] != 0 { // disable dwarf
return
}
inforeloco = writedwarfreloc(infosec) inforeloco = writedwarfreloc(infosec)
inforelocsize = Cpos() - inforeloco inforelocsize = Cpos() - inforeloco
align(inforelocsize) align(inforelocsize)
...@@ -2263,18 +2319,6 @@ func dwarfaddshstrings(shstrtab *LSym) { ...@@ -2263,18 +2319,6 @@ func dwarfaddshstrings(shstrtab *LSym) {
elfstrdbg[ElfStrRelDebugLine] = Addstring(shstrtab, ".rel.debug_line") elfstrdbg[ElfStrRelDebugLine] = Addstring(shstrtab, ".rel.debug_line")
elfstrdbg[ElfStrRelDebugFrame] = Addstring(shstrtab, ".rel.debug_frame") elfstrdbg[ElfStrRelDebugFrame] = Addstring(shstrtab, ".rel.debug_frame")
} }
infosym = Linklookup(Ctxt, ".debug_info", 0)
infosym.Hide = 1
abbrevsym = Linklookup(Ctxt, ".debug_abbrev", 0)
abbrevsym.Hide = 1
linesym = Linklookup(Ctxt, ".debug_line", 0)
linesym.Hide = 1
framesym = Linklookup(Ctxt, ".debug_frame", 0)
framesym.Hide = 1
} }
} }
...@@ -2420,14 +2464,15 @@ func dwarfaddelfheaders() { ...@@ -2420,14 +2464,15 @@ func dwarfaddelfheaders() {
/* /*
* Macho * Macho
*/ */
func dwarfaddmachoheaders() { func dwarfaddmachoheaders(ms *MachoSeg) {
if Debug['w'] != 0 { // disable dwarf if Debug['w'] != 0 { // disable dwarf
return return
} }
// Zero vsize segments won't be loaded in memory, even so they // Zero vsize segments won't be loaded in memory, even so they
// have to be page aligned in the file. // have to be page aligned in the file.
fakestart := abbrevo &^ 0xfff fakestart := Rnd(int64(Segdwarf.Fileoff), 0x1000)
addr := Segdata.Vaddr + Segdata.Length
nsect := 4 nsect := 4
if pubnamessize > 0 { if pubnamessize > 0 {
...@@ -2443,57 +2488,94 @@ func dwarfaddmachoheaders() { ...@@ -2443,57 +2488,94 @@ func dwarfaddmachoheaders() {
nsect++ nsect++
} }
ms := newMachoSeg("__DWARF", nsect) if Linkmode != LinkExternal {
ms.fileoffset = uint64(fakestart) ms = newMachoSeg("__DWARF", nsect)
ms.filesize = uint64(abbrevo) - uint64(fakestart) ms.fileoffset = uint64(fakestart)
ms.vaddr = ms.fileoffset + Segdata.Vaddr - Segdata.Fileoff ms.filesize = Segdwarf.Filelen
ms.vaddr = addr
}
msect := newMachoSect(ms, "__debug_abbrev", "__DWARF") msect := newMachoSect(ms, "__debug_abbrev", "__DWARF")
msect.off = uint32(abbrevo) msect.off = uint32(abbrevo)
msect.size = uint64(abbrevsize) msect.size = uint64(abbrevsize)
msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff msect.addr = addr
ms.filesize += msect.size addr += msect.size
msect.flag = 0x02000000
if abbrevsym != nil {
abbrevsym.Value = int64(msect.addr)
}
msect = newMachoSect(ms, "__debug_line", "__DWARF") msect = newMachoSect(ms, "__debug_line", "__DWARF")
msect.off = uint32(lineo) msect.off = uint32(lineo)
msect.size = uint64(linesize) msect.size = uint64(linesize)
msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff msect.addr = addr
ms.filesize += msect.size 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 = newMachoSect(ms, "__debug_frame", "__DWARF")
msect.off = uint32(frameo) msect.off = uint32(frameo)
msect.size = uint64(framesize) msect.size = uint64(framesize)
msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff msect.addr = addr
ms.filesize += msect.size 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 = newMachoSect(ms, "__debug_info", "__DWARF")
msect.off = uint32(infoo) msect.off = uint32(infoo)
msect.size = uint64(infosize) msect.size = uint64(infosize)
msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff msect.addr = addr
ms.filesize += msect.size 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 { if pubnamessize > 0 {
msect := newMachoSect(ms, "__debug_pubnames", "__DWARF") msect := newMachoSect(ms, "__debug_pubnames", "__DWARF")
msect.off = uint32(pubnameso) msect.off = uint32(pubnameso)
msect.size = uint64(pubnamessize) msect.size = uint64(pubnamessize)
msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff msect.addr = addr
ms.filesize += msect.size addr += msect.size
msect.flag = 0x02000000
} }
if pubtypessize > 0 { if pubtypessize > 0 {
msect := newMachoSect(ms, "__debug_pubtypes", "__DWARF") msect := newMachoSect(ms, "__debug_pubtypes", "__DWARF")
msect.off = uint32(pubtypeso) msect.off = uint32(pubtypeso)
msect.size = uint64(pubtypessize) msect.size = uint64(pubtypessize)
msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff msect.addr = addr
ms.filesize += msect.size addr += msect.size
msect.flag = 0x02000000
} }
if arangessize > 0 { if arangessize > 0 {
msect := newMachoSect(ms, "__debug_aranges", "__DWARF") msect := newMachoSect(ms, "__debug_aranges", "__DWARF")
msect.off = uint32(arangeso) msect.off = uint32(arangeso)
msect.size = uint64(arangessize) msect.size = uint64(arangessize)
msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff msect.addr = addr
ms.filesize += msect.size 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) // TODO(lvd) fix gdb/python to load MachO (16 char section name limit)
...@@ -2501,8 +2583,9 @@ func dwarfaddmachoheaders() { ...@@ -2501,8 +2583,9 @@ func dwarfaddmachoheaders() {
msect := newMachoSect(ms, "__debug_gdb_scripts", "__DWARF") msect := newMachoSect(ms, "__debug_gdb_scripts", "__DWARF")
msect.off = uint32(gdbscripto) msect.off = uint32(gdbscripto)
msect.size = uint64(gdbscriptsize) msect.size = uint64(gdbscriptsize)
msect.addr = uint64(msect.off) + Segdata.Vaddr - Segdata.Fileoff msect.addr = addr
ms.filesize += msect.size addr += msect.size
msect.flag = 0x02000000
} }
} }
......
...@@ -922,7 +922,7 @@ func hostlink() { ...@@ -922,7 +922,7 @@ func hostlink() {
} }
if HEADTYPE == obj.Hdarwin { if HEADTYPE == obj.Hdarwin {
argv = append(argv, "-Wl,-no_pie,-pagezero_size,4000000") argv = append(argv, "-Wl,-no_pie,-pagezero_size,4000000,-headerpad,1144")
} }
if HEADTYPE == obj.Hopenbsd { if HEADTYPE == obj.Hopenbsd {
argv = append(argv, "-Wl,-nopie") argv = append(argv, "-Wl,-nopie")
...@@ -1029,6 +1029,25 @@ func hostlink() { ...@@ -1029,6 +1029,25 @@ func hostlink() {
if out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput(); err != nil { if out, err := exec.Command(argv[0], argv[1:]...).CombinedOutput(); err != nil {
Exitf("running %s failed: %v\n%s", argv[0], err, out) Exitf("running %s failed: %v\n%s", argv[0], err, out)
} }
if Debug['s'] == 0 && debug_s == 0 && HEADTYPE == obj.Hdarwin {
dsym := fmt.Sprintf("%s/go.dwarf", tmpdir)
if out, err := exec.Command("dsymutil", "-f", outfile, "-o", dsym).CombinedOutput(); err != nil {
Ctxt.Cursym = nil
Exitf("%s: running dsymutil failed: %v\n%s", os.Args[0], err, out)
}
combinedOutput := fmt.Sprintf("%s/go.combined", tmpdir)
if err := machoCombineDwarf(outfile, dsym, combinedOutput); err != nil {
Ctxt.Cursym = nil
Exitf("%s: combining dwarf failed: %v", os.Args[0], err)
}
origOutput := fmt.Sprintf("%s/go.orig", tmpdir)
os.Rename(outfile, origOutput)
if err := os.Rename(combinedOutput, outfile); err != nil {
Ctxt.Cursym = nil
Exitf("%s: rename(%s, %s) failed: %v", os.Args[0], combinedOutput, outfile, err)
}
}
} }
func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, whence int) { func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, whence int) {
......
...@@ -443,7 +443,8 @@ func Asmbmacho() { ...@@ -443,7 +443,8 @@ func Asmbmacho() {
ms = newMachoSeg("", 40) ms = newMachoSeg("", 40)
ms.fileoffset = Segtext.Fileoff ms.fileoffset = Segtext.Fileoff
ms.filesize = Segdata.Fileoff + Segdata.Filelen - Segtext.Fileoff ms.filesize = Segdwarf.Fileoff + Segdwarf.Filelen - Segtext.Fileoff
ms.vsize = ms.filesize
} }
/* segment for zero page */ /* segment for zero page */
...@@ -561,8 +562,8 @@ func Asmbmacho() { ...@@ -561,8 +562,8 @@ func Asmbmacho() {
} }
// TODO: dwarf headers go in ms too // TODO: dwarf headers go in ms too
if Debug['s'] == 0 && Linkmode != LinkExternal { if Debug['s'] == 0 {
dwarfaddmachoheaders() dwarfaddmachoheaders(ms)
} }
a := machowrite() a := machowrite()
...@@ -850,4 +851,5 @@ func Machoemitreloc() { ...@@ -850,4 +851,5 @@ 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()
} }
This diff is collapsed.
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