diff --git a/src/cmd/link/internal/ld/macho_combine_dwarf.go b/src/cmd/link/internal/ld/macho_combine_dwarf.go index 72ee8affab..9d9f916b8e 100644 --- a/src/cmd/link/internal/ld/macho_combine_dwarf.go +++ b/src/cmd/link/internal/ld/macho_combine_dwarf.go @@ -16,11 +16,6 @@ import ( "unsafe" ) -var realdwarf, linkseg *macho.Segment -var dwarfstart, linkstart int64 -var dwarfaddr int64 -var linkoffset uint32 - const ( pageAlign = 12 // 4096 = 1 << 12 ) @@ -59,16 +54,18 @@ type loadCmdReader struct { order binary.ByteOrder } -func (r *loadCmdReader) Next() (cmd loadCmd, err error) { +func (r *loadCmdReader) Next() (loadCmd, error) { + var cmd loadCmd + r.offset = r.next - if _, err = r.f.Seek(r.offset, 0); err != nil { - return + if _, err := r.f.Seek(r.offset, 0); err != nil { + return cmd, err } - if err = binary.Read(r.f, r.order, &cmd); err != nil { - return + if err := binary.Read(r.f, r.order, &cmd); err != nil { + return cmd, err } r.next = r.offset + int64(cmd.Len) - return + return cmd, nil } func (r loadCmdReader) ReadAt(offset int64, data interface{}) error { @@ -100,33 +97,33 @@ func machoCombineDwarf(ctxt *Link, exef *os.File, exem *macho.File, dsym, outexe return err } defer dwarff.Close() - outf, err := os.Create(outexe) + outf, err := os.OpenFile(outexe, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755) if err != nil { return err } - outf.Chmod(0755) - + defer outf.Close() dwarfm, err := macho.NewFile(dwarff) if err != nil { return err } + defer dwarfm.Close() // 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") + linkseg := exem.Segment("__LINKEDIT") if linkseg == nil { return fmt.Errorf("missing __LINKEDIT segment") } - if _, err = exef.Seek(0, 0); err != nil { + 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") + realdwarf := dwarfm.Segment("__DWARF") if realdwarf == nil { return fmt.Errorf("missing __DWARF segment") } @@ -141,13 +138,12 @@ func machoCombineDwarf(ctxt *Link, exef *os.File, exem *macho.File, dsym, outexe // Now copy the dwarf data into the output. // 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 { + dwarfstart := machoCalcStart(realdwarf.Offset, linkseg.Offset, pageAlign) + if _, err := outf.Seek(dwarfstart, 0); err != nil { return err } - dwarfaddr = int64((linkseg.Addr + linkseg.Memsz + 1<= len(sectBytes) { + if buf.Len() >= len(sectBytes) { return false, sectBytes, nil } return true, buf.Bytes(), nil @@ -320,26 +315,26 @@ func machoCompressSection(sectBytes []byte) (compressed bool, contents []byte, e // 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 { +func machoUpdateSegment(r loadCmdReader, linkseg *macho.Segment, linkoffset uint64, 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. + // Only the linkedit segment moved, anything before that is fine. if offset.Uint() < linkseg.Offset { return nil } - offset.SetUint(offset.Uint() + uint64(linkoffset)) + offset.SetUint(offset.Uint() + 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), 0, nil) + return machoUpdateSections(r, segValue, reflect.ValueOf(sect), linkoffset, nil) } -func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, deltaOffset, deltaAddr uint64, compressedSects []*macho.Section) error { +func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, deltaOffset uint64, compressedSects []*macho.Section) error { iseg := reflect.Indirect(seg) nsect := iseg.FieldByName("Nsect").Uint() if nsect == 0 { @@ -368,7 +363,7 @@ func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, deltaOffset, offsetField.SetUint(uint64(cSect.Offset) + deltaOffset) } if cSect.Addr != 0 { - addrField.SetUint(cSect.Addr + deltaAddr) + addrField.SetUint(cSect.Addr) } } else { if offsetField.Uint() != 0 { @@ -378,7 +373,7 @@ func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, deltaOffset, reloffField.SetUint(reloffField.Uint() + deltaOffset) } if addrField.Uint() != 0 { - addrField.SetUint(addrField.Uint() + deltaAddr) + addrField.SetUint(addrField.Uint()) } } if err := r.WriteAt(sectOffset, sect.Interface()); err != nil { @@ -390,7 +385,7 @@ func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, deltaOffset, } // machoUpdateDwarfHeader updates the DWARF segment load command. -func machoUpdateDwarfHeader(r *loadCmdReader, compressedSects []*macho.Section, dwarfsize uint64) error { +func machoUpdateDwarfHeader(r *loadCmdReader, compressedSects []*macho.Section, dwarfsize uint64, dwarfstart int64, realdwarf *macho.Segment) error { var seg, sect interface{} cmd, err := r.Next() if err != nil { @@ -419,9 +414,6 @@ func machoUpdateDwarfHeader(r *loadCmdReader, compressedSects []*macho.Section, segv.FieldByName("Filesz").SetUint(dwarfsize) } - deltaOffset := uint64(dwarfstart) - realdwarf.Offset - deltaAddr := uint64(dwarfaddr) - realdwarf.Addr - // We want the DWARF segment to be considered non-loadable, so // force vmaddr and vmsize to zero. In addition, set the initial // protection to zero so as to make the dynamic loader happy, @@ -435,15 +427,14 @@ func machoUpdateDwarfHeader(r *loadCmdReader, compressedSects []*macho.Section, segv.FieldByName("Addr").SetUint(0) segv.FieldByName("Memsz").SetUint(0) segv.FieldByName("Prot").SetUint(0) - deltaAddr = 0 if err := r.WriteAt(0, seg); err != nil { return err } - return machoUpdateSections(*r, segv, reflect.ValueOf(sect), deltaOffset, deltaAddr, compressedSects) + return machoUpdateSections(*r, segv, reflect.ValueOf(sect), uint64(dwarfstart)-realdwarf.Offset, compressedSects) } -func machoUpdateLoadCommand(r loadCmdReader, cmd interface{}, fields ...string) error { +func machoUpdateLoadCommand(r loadCmdReader, linkseg *macho.Segment, linkoffset uint64, cmd interface{}, fields ...string) error { if err := r.ReadAt(0, cmd); err != nil { return err } @@ -451,9 +442,8 @@ func machoUpdateLoadCommand(r loadCmdReader, cmd interface{}, fields ...string) for _, name := range fields { field := value.FieldByName(name) - fieldval := field.Uint() - if fieldval >= linkseg.Offset { - field.SetUint(fieldval + uint64(linkoffset)) + if fieldval := field.Uint(); fieldval >= linkseg.Offset { + field.SetUint(fieldval + linkoffset) } } if err := r.WriteAt(0, cmd); err != nil { @@ -464,10 +454,9 @@ func machoUpdateLoadCommand(r loadCmdReader, cmd interface{}, fields ...string) func machoCalcStart(origAddr, newAddr uint64, alignExp uint32) int64 { align := uint64(1 << alignExp) - if (origAddr % align) == (newAddr % align) { + origMod, newMod := origAddr%align, newAddr%align + if origMod == newMod { return int64(newAddr) } - padding := (align - (newAddr % align)) - padding += origAddr % align - return int64(padding + newAddr) + return int64(newAddr + align + origMod - newMod) }