mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/internal/ld: output dwarf in external link mode on darwin
Fixes #8973 Change-Id: Idd53fc6d9e6971ae31ed72a3df3cfdce0bfbc1fd Reviewed-on: https://go-review.googlesource.com/8661 Reviewed-by: Russ Cox <rsc@golang.org> Run-TryBot: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
9c9e36b340
commit
8b83306cf2
8 changed files with 527 additions and 58 deletions
|
|
@ -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() {
|
||||||
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() {
|
||||||
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() {
|
||||||
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() {
|
||||||
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() {
|
||||||
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
|
||||||
import (
|
import (
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -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)
|
||||||
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() {
|
||||||
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 {
|
||||||
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() {
|
||||||
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() {
|
||||||
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) {
|
||||||
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() {
|
||||||
/*
|
/*
|
||||||
* 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() {
|
||||||
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() {
|
||||||
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() {
|
||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
||||||
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() {
|
||||||
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() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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() {
|
||||||
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()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
369
src/cmd/internal/ld/macho_combine_dwarf.go
Normal file
369
src/cmd/internal/ld/macho_combine_dwarf.go
Normal file
|
|
@ -0,0 +1,369 @@
|
||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ld
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"debug/macho"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var fakedwarf, realdwarf, linkseg *macho.Segment
|
||||||
|
var dwarfstart, linkstart int64
|
||||||
|
var linkoffset uint32
|
||||||
|
var machHeader *macho.FileHeader
|
||||||
|
var mappedHeader []byte
|
||||||
|
|
||||||
|
const (
|
||||||
|
LC_LOAD_DYLINKER = 0xe
|
||||||
|
LC_PREBOUND_DYLIB = 0x10
|
||||||
|
LC_LOAD_WEAK_DYLIB = 0x18
|
||||||
|
LC_UUID = 0x1b
|
||||||
|
LC_RPATH = 0x8000001c
|
||||||
|
LC_CODE_SIGNATURE = 0x1d
|
||||||
|
LC_SEGMENT_SPLIT_INFO = 0x1e
|
||||||
|
LC_REEXPORT_DYLIB = 0x8000001f
|
||||||
|
LC_ENCRYPTION_INFO = 0x21
|
||||||
|
LC_DYLD_INFO = 0x22
|
||||||
|
LC_DYLD_INFO_ONLY = 0x80000022
|
||||||
|
LC_VERSION_MIN_MACOSX = 0x24
|
||||||
|
LC_VERSION_MIN_IPHONEOS = 0x25
|
||||||
|
LC_FUNCTION_STARTS = 0x26
|
||||||
|
LC_MAIN = 0x80000028
|
||||||
|
LC_DATA_IN_CODE = 0x29
|
||||||
|
LC_SOURCE_VERSION = 0x2A
|
||||||
|
LC_DYLIB_CODE_SIGN_DRS = 0x2B
|
||||||
|
LC_ENCRYPTION_INFO_64 = 0x2C
|
||||||
|
|
||||||
|
dwarfMinAlign = 6 // 64 = 1 << 6
|
||||||
|
pageAlign = 12 // 4096 = 1 << 12
|
||||||
|
)
|
||||||
|
|
||||||
|
type loadCmd struct {
|
||||||
|
Cmd macho.LoadCmd
|
||||||
|
Len uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type dyldInfoCmd struct {
|
||||||
|
Cmd macho.LoadCmd
|
||||||
|
Len uint32
|
||||||
|
RebaseOff, RebaseLen uint32
|
||||||
|
BindOff, BindLen uint32
|
||||||
|
WeakBindOff, WeakBindLen uint32
|
||||||
|
LazyBindOff, LazyBindLen uint32
|
||||||
|
ExportOff, ExportLen uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type linkEditDataCmd struct {
|
||||||
|
Cmd macho.LoadCmd
|
||||||
|
Len uint32
|
||||||
|
DataOff, DataLen uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type encryptionInfoCmd struct {
|
||||||
|
Cmd macho.LoadCmd
|
||||||
|
Len uint32
|
||||||
|
CryptOff, CryptLen uint32
|
||||||
|
CryptId uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type loadCmdReader struct {
|
||||||
|
offset, next int64
|
||||||
|
f *os.File
|
||||||
|
order binary.ByteOrder
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *loadCmdReader) Next() (cmd loadCmd, err error) {
|
||||||
|
r.offset = r.next
|
||||||
|
if _, err = r.f.Seek(r.offset, 0); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = binary.Read(r.f, r.order, &cmd); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.next = r.offset + int64(cmd.Len)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r loadCmdReader) ReadAt(offset int64, data interface{}) error {
|
||||||
|
if _, err := r.f.Seek(r.offset+offset, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return binary.Read(r.f, r.order, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r loadCmdReader) WriteAt(offset int64, data interface{}) error {
|
||||||
|
if _, err := r.f.Seek(r.offset+offset, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return binary.Write(r.f, r.order, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// machoCombineDwarf merges dwarf info generated by dsymutil into a macho executable.
|
||||||
|
// With internal linking, DWARF is embedded into the executable, this lets us do the
|
||||||
|
// same for external linking.
|
||||||
|
// inexe is the path to the executable with no DWARF. It must have enough room in the macho
|
||||||
|
// header to add the DWARF sections. (Use ld's -headerpad option)
|
||||||
|
// dsym is the path to the macho file containing DWARF from dsymutil.
|
||||||
|
// outexe is the path where the combined executable should be saved.
|
||||||
|
func machoCombineDwarf(inexe, dsym, outexe string) error {
|
||||||
|
exef, err := os.Open(inexe)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dwarff, err := os.Open(dsym)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
outf, err := os.Create(outexe)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
outf.Chmod(0755)
|
||||||
|
|
||||||
|
exem, err := macho.NewFile(exef)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dwarfm, err := macho.NewFile(dwarff)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// The string table needs to be the last thing in the file
|
||||||
|
// for code signing to work. So we'll need to move the
|
||||||
|
// linkedit section, but all the others can be copied directly.
|
||||||
|
linkseg = exem.Segment("__LINKEDIT")
|
||||||
|
if linkseg == nil {
|
||||||
|
return fmt.Errorf("missing __LINKEDIT segment")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = exef.Seek(0, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := io.CopyN(outf, exef, int64(linkseg.Offset)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
realdwarf = dwarfm.Segment("__DWARF")
|
||||||
|
if realdwarf == nil {
|
||||||
|
return fmt.Errorf("missing __DWARF segment")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now copy the dwarf data into the output.
|
||||||
|
maxalign := uint32(dwarfMinAlign) //
|
||||||
|
for _, sect := range dwarfm.Sections {
|
||||||
|
if sect.Align > maxalign {
|
||||||
|
maxalign = sect.Align
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dwarfstart = machoCalcStart(realdwarf.Offset, linkseg.Offset, maxalign)
|
||||||
|
if _, err = outf.Seek(dwarfstart, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = dwarff.Seek(int64(realdwarf.Offset), 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := io.CopyN(outf, dwarff, int64(realdwarf.Filesz)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// And finally the linkedit section.
|
||||||
|
if _, err = exef.Seek(int64(linkseg.Offset), 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
linkstart = machoCalcStart(linkseg.Offset, uint64(dwarfstart)+realdwarf.Filesz, pageAlign)
|
||||||
|
linkoffset = uint32(linkstart - int64(linkseg.Offset))
|
||||||
|
if _, err = outf.Seek(linkstart, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := io.Copy(outf, exef); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we need to update the headers.
|
||||||
|
cmdOffset := unsafe.Sizeof(exem.FileHeader)
|
||||||
|
is64bit := exem.Magic == macho.Magic64
|
||||||
|
if is64bit {
|
||||||
|
// mach_header_64 has one extra uint32.
|
||||||
|
cmdOffset += unsafe.Sizeof(exem.Magic)
|
||||||
|
}
|
||||||
|
|
||||||
|
textsect := exem.Section("__text")
|
||||||
|
if linkseg == nil {
|
||||||
|
return fmt.Errorf("missing __text section")
|
||||||
|
}
|
||||||
|
|
||||||
|
dwarfCmdOffset := int64(cmdOffset) + int64(exem.FileHeader.Cmdsz)
|
||||||
|
availablePadding := int64(textsect.Offset) - dwarfCmdOffset
|
||||||
|
if availablePadding < int64(realdwarf.Len) {
|
||||||
|
return fmt.Errorf("No room to add dwarf info. Need at least %d padding bytes, found %d", realdwarf.Len, availablePadding)
|
||||||
|
}
|
||||||
|
// First, copy the dwarf load command into the header
|
||||||
|
if _, err = outf.Seek(dwarfCmdOffset, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := io.CopyN(outf, bytes.NewReader(realdwarf.Raw()), int64(realdwarf.Len)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = outf.Seek(int64(unsafe.Offsetof(exem.FileHeader.Ncmd)), 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = binary.Write(outf, exem.ByteOrder, exem.Ncmd+1); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = binary.Write(outf, exem.ByteOrder, exem.Cmdsz+realdwarf.Len); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
reader := loadCmdReader{next: int64(cmdOffset), f: outf, order: exem.ByteOrder}
|
||||||
|
for i := uint32(0); i < exem.Ncmd; i++ {
|
||||||
|
cmd, err := reader.Next()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch cmd.Cmd {
|
||||||
|
case macho.LoadCmdSegment64:
|
||||||
|
err = machoUpdateSegment(reader, &macho.Segment64{}, &macho.Section64{})
|
||||||
|
case macho.LoadCmdSegment:
|
||||||
|
err = machoUpdateSegment(reader, &macho.Segment32{}, &macho.Section32{})
|
||||||
|
case LC_DYLD_INFO, LC_DYLD_INFO_ONLY:
|
||||||
|
err = machoUpdateLoadCommand(reader, &dyldInfoCmd{}, "RebaseOff", "BindOff", "WeakBindOff", "LazyBindOff", "ExportOff")
|
||||||
|
case macho.LoadCmdSymtab:
|
||||||
|
err = machoUpdateLoadCommand(reader, &macho.SymtabCmd{}, "Symoff", "Stroff")
|
||||||
|
case macho.LoadCmdDysymtab:
|
||||||
|
err = machoUpdateLoadCommand(reader, &macho.DysymtabCmd{}, "Tocoffset", "Modtaboff", "Extrefsymoff", "Indirectsymoff", "Extreloff", "Locreloff")
|
||||||
|
case LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, LC_FUNCTION_STARTS, LC_DATA_IN_CODE, LC_DYLIB_CODE_SIGN_DRS:
|
||||||
|
err = machoUpdateLoadCommand(reader, &linkEditDataCmd{}, "DataOff")
|
||||||
|
case LC_ENCRYPTION_INFO, LC_ENCRYPTION_INFO_64:
|
||||||
|
err = machoUpdateLoadCommand(reader, &encryptionInfoCmd{}, "CryptOff")
|
||||||
|
case macho.LoadCmdDylib, macho.LoadCmdThread, macho.LoadCmdUnixThread, LC_PREBOUND_DYLIB, LC_UUID, LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_SOURCE_VERSION, LC_MAIN, LC_LOAD_DYLINKER, LC_LOAD_WEAK_DYLIB, LC_REEXPORT_DYLIB, LC_RPATH:
|
||||||
|
// Nothing to update
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("Unknown load command 0x%x (%s)\n", int(cmd.Cmd), cmd.Cmd)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return machoUpdateDwarfHeader(&reader)
|
||||||
|
}
|
||||||
|
|
||||||
|
// machoUpdateSegment updates the load command for a moved segment.
|
||||||
|
// Only the linkedit segment should move, and it should have 0 sections.
|
||||||
|
// seg should be a macho.Segment32 or macho.Segment64 as appropriate.
|
||||||
|
// sect should be a macho.Section32 or macho.Section64 as appropriate.
|
||||||
|
func machoUpdateSegment(r loadCmdReader, seg, sect interface{}) error {
|
||||||
|
if err := r.ReadAt(0, seg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
segValue := reflect.ValueOf(seg)
|
||||||
|
offset := reflect.Indirect(segValue).FieldByName("Offset")
|
||||||
|
|
||||||
|
// Only the linkedit segment moved, any thing before that is fine.
|
||||||
|
if offset.Uint() < linkseg.Offset {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
offset.SetUint(offset.Uint() + uint64(linkoffset))
|
||||||
|
if err := r.WriteAt(0, seg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// There shouldn't be any sections, but just to make sure...
|
||||||
|
return machoUpdateSections(r, segValue, reflect.ValueOf(sect), uint64(linkoffset))
|
||||||
|
}
|
||||||
|
|
||||||
|
func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, delta uint64) error {
|
||||||
|
iseg := reflect.Indirect(seg)
|
||||||
|
nsect := iseg.FieldByName("Nsect").Uint()
|
||||||
|
if nsect == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
sectOffset := int64(iseg.Type().Size())
|
||||||
|
|
||||||
|
isect := reflect.Indirect(sect)
|
||||||
|
offsetField := isect.FieldByName("Offset")
|
||||||
|
reloffField := isect.FieldByName("Reloff")
|
||||||
|
sectSize := int64(isect.Type().Size())
|
||||||
|
for i := uint64(0); i < nsect; i++ {
|
||||||
|
if err := r.ReadAt(sectOffset, sect.Interface()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if offsetField.Uint() != 0 {
|
||||||
|
offsetField.SetUint(offsetField.Uint() + delta)
|
||||||
|
}
|
||||||
|
if reloffField.Uint() != 0 {
|
||||||
|
reloffField.SetUint(reloffField.Uint() + delta)
|
||||||
|
}
|
||||||
|
if err := r.WriteAt(sectOffset, sect.Interface()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
sectOffset += sectSize
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// machoUpdateDwarfHeader updates the DWARF segment load command.
|
||||||
|
func machoUpdateDwarfHeader(r *loadCmdReader) error {
|
||||||
|
var seg, sect interface{}
|
||||||
|
cmd, err := r.Next()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if cmd.Cmd == macho.LoadCmdSegment64 {
|
||||||
|
seg = new(macho.Segment64)
|
||||||
|
sect = new(macho.Section64)
|
||||||
|
} else {
|
||||||
|
seg = new(macho.Segment32)
|
||||||
|
sect = new(macho.Section32)
|
||||||
|
}
|
||||||
|
if err := r.ReadAt(0, seg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
segValue := reflect.ValueOf(seg)
|
||||||
|
offset := reflect.Indirect(segValue).FieldByName("Offset")
|
||||||
|
|
||||||
|
delta := uint64(dwarfstart) - realdwarf.Offset
|
||||||
|
offset.SetUint(offset.Uint() + delta)
|
||||||
|
if err := r.WriteAt(0, seg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return machoUpdateSections(*r, segValue, reflect.ValueOf(sect), delta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func machoUpdateLoadCommand(r loadCmdReader, cmd interface{}, fields ...string) error {
|
||||||
|
if err := r.ReadAt(0, cmd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
value := reflect.Indirect(reflect.ValueOf(cmd))
|
||||||
|
|
||||||
|
for _, name := range fields {
|
||||||
|
field := value.FieldByName(name)
|
||||||
|
fieldval := field.Uint()
|
||||||
|
if fieldval >= linkseg.Offset {
|
||||||
|
field.SetUint(fieldval + uint64(linkoffset))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := r.WriteAt(0, cmd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func machoCalcStart(origAddr, newAddr uint64, alignExp uint32) int64 {
|
||||||
|
align := uint64(1 << alignExp)
|
||||||
|
if (origAddr % align) == (newAddr % align) {
|
||||||
|
return int64(newAddr)
|
||||||
|
}
|
||||||
|
padding := (align - (newAddr % align))
|
||||||
|
padding += origAddr % align
|
||||||
|
return int64(padding + newAddr)
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue