aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xmisc/cgo/testcshared/test.bash7
-rw-r--r--src/cmd/link/internal/ld/macho_combine_dwarf.go52
2 files changed, 41 insertions, 18 deletions
diff --git a/misc/cgo/testcshared/test.bash b/misc/cgo/testcshared/test.bash
index 052ee0e758..0315fb07f5 100755
--- a/misc/cgo/testcshared/test.bash
+++ b/misc/cgo/testcshared/test.bash
@@ -179,6 +179,13 @@ if test "$output" != "PASS"; then
status=1
fi
+if test "$libext" = "dylib"; then
+ # make sure dylibs are well-formed
+ if ! otool -l libgo*.dylib >/dev/null; then
+ status=1
+ fi
+fi
+
if test $status = 0; then
echo "ok"
fi
diff --git a/src/cmd/link/internal/ld/macho_combine_dwarf.go b/src/cmd/link/internal/ld/macho_combine_dwarf.go
index dcc371ec05..8c6c4a86ac 100644
--- a/src/cmd/link/internal/ld/macho_combine_dwarf.go
+++ b/src/cmd/link/internal/ld/macho_combine_dwarf.go
@@ -17,6 +17,7 @@ import (
var realdwarf, linkseg *macho.Segment
var dwarfstart, linkstart int64
+var dwarfaddr, linkaddr int64
var linkoffset uint32
const (
@@ -41,8 +42,7 @@ const (
LC_DYLIB_CODE_SIGN_DRS = 0x2B
LC_ENCRYPTION_INFO_64 = 0x2C
- dwarfMinAlign = 6 // 64 = 1 << 6
- pageAlign = 12 // 4096 = 1 << 12
+ pageAlign = 12 // 4096 = 1 << 12
)
type loadCmd struct {
@@ -157,16 +157,13 @@ func machoCombineDwarf(inexe, dsym, outexe string) error {
}
// 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)
+ // Kernel requires all loaded segments to be page-aligned in the file,
+ // even though we mark this one as being 0 bytes of virtual address space.
+ dwarfstart = machoCalcStart(realdwarf.Offset, linkseg.Offset, pageAlign)
if _, err = outf.Seek(dwarfstart, 0); err != nil {
return err
}
+ dwarfaddr = int64((linkseg.Addr + linkseg.Memsz + 1<<pageAlign - 1) &^ (1<<pageAlign - 1))
if _, err = dwarff.Seek(int64(realdwarf.Offset), 0); err != nil {
return err
@@ -277,10 +274,10 @@ func machoUpdateSegment(r loadCmdReader, seg, sect interface{}) error {
return err
}
// There shouldn't be any sections, but just to make sure...
- return machoUpdateSections(r, segValue, reflect.ValueOf(sect), uint64(linkoffset))
+ return machoUpdateSections(r, segValue, reflect.ValueOf(sect), uint64(linkoffset), 0)
}
-func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, delta uint64) error {
+func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, deltaOffset, deltaAddr uint64) error {
iseg := reflect.Indirect(seg)
nsect := iseg.FieldByName("Nsect").Uint()
if nsect == 0 {
@@ -291,16 +288,20 @@ func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, delta uint64)
isect := reflect.Indirect(sect)
offsetField := isect.FieldByName("Offset")
reloffField := isect.FieldByName("Reloff")
+ addrField := isect.FieldByName("Addr")
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)
+ offsetField.SetUint(offsetField.Uint() + deltaOffset)
}
if reloffField.Uint() != 0 {
- reloffField.SetUint(reloffField.Uint() + delta)
+ reloffField.SetUint(reloffField.Uint() + deltaOffset)
+ }
+ if addrField.Uint() != 0 {
+ addrField.SetUint(addrField.Uint() + deltaAddr)
}
if err := r.WriteAt(sectOffset, sect.Interface()); err != nil {
return err
@@ -327,15 +328,30 @@ func machoUpdateDwarfHeader(r *loadCmdReader) error {
if err := r.ReadAt(0, seg); err != nil {
return err
}
- segValue := reflect.ValueOf(seg)
- offset := reflect.Indirect(segValue).FieldByName("Offset")
+ segv := reflect.ValueOf(seg).Elem()
+
+ segv.FieldByName("Offset").SetUint(uint64(dwarfstart))
+ segv.FieldByName("Addr").SetUint(uint64(dwarfaddr))
+
+ deltaOffset := uint64(dwarfstart) - realdwarf.Offset
+ deltaAddr := uint64(dwarfaddr) - realdwarf.Addr
+
+ // If we set Memsz to 0 (and might as well set Addr too),
+ // then the xnu kernel will bail out halfway through load_segment
+ // and not apply further sanity checks that we might fail in the future.
+ // We don't need the DWARF information actually available in memory.
+ // But if we do this for buildmode=c-shared then the user-space
+ // dynamic loader complains about memsz < filesz. Sigh.
+ if Buildmode != BuildmodeCShared {
+ segv.FieldByName("Addr").SetUint(0)
+ segv.FieldByName("Memsz").SetUint(0)
+ deltaAddr = 0
+ }
- 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)
+ return machoUpdateSections(*r, segv, reflect.ValueOf(sect), deltaOffset, deltaAddr)
}
func machoUpdateLoadCommand(r loadCmdReader, cmd interface{}, fields ...string) error {