diff options
author | Rob Findley <rfindley@google.com> | 2020-09-11 14:23:34 -0400 |
---|---|---|
committer | Rob Findley <rfindley@google.com> | 2020-09-11 14:23:34 -0400 |
commit | f8b1c17aced24a1618c6984794be9770c5d260be (patch) | |
tree | 45af8d39b5c3d9f43d439ebec0a2ba42b49efe70 /src/cmd/link/internal/ld/macho_combine_dwarf.go | |
parent | e5d91ab096a9ff9673311f1a7f3f860a7f9c2062 (diff) | |
parent | 07c1788357cfe6a4ee5f6f6a54d4fe9f579fa844 (diff) | |
download | go-dev.types.tar.gz go-dev.types.zip |
[dev.types] all: merge master into dev.typesdev.types
Change-Id: Ia6964cb4e09153c15cc9c5b441373d1b3cb8f757
Diffstat (limited to 'src/cmd/link/internal/ld/macho_combine_dwarf.go')
-rw-r--r-- | src/cmd/link/internal/ld/macho_combine_dwarf.go | 112 |
1 files changed, 40 insertions, 72 deletions
diff --git a/src/cmd/link/internal/ld/macho_combine_dwarf.go b/src/cmd/link/internal/ld/macho_combine_dwarf.go index 9d9f916b8e..77ee8a4d62 100644 --- a/src/cmd/link/internal/ld/macho_combine_dwarf.go +++ b/src/cmd/link/internal/ld/macho_combine_dwarf.go @@ -16,10 +16,6 @@ import ( "unsafe" ) -const ( - pageAlign = 12 // 4096 = 1 << 12 -) - type loadCmd struct { Cmd macho.LoadCmd Len uint32 @@ -138,7 +134,7 @@ 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) + dwarfstart := Rnd(int64(linkseg.Offset), int64(*FlagRound)) if _, err := outf.Seek(dwarfstart, 0); err != nil { return err } @@ -166,7 +162,7 @@ func machoCombineDwarf(ctxt *Link, exef *os.File, exem *macho.File, dsym, outexe if _, err := exef.Seek(int64(linkseg.Offset), 0); err != nil { return err } - linkstart := machoCalcStart(linkseg.Offset, uint64(dwarfstart)+dwarfsize, pageAlign) + linkstart := Rnd(dwarfstart+int64(dwarfsize), int64(*FlagRound)) if _, err := outf.Seek(linkstart, 0); err != nil { return err } @@ -217,9 +213,9 @@ func machoCombineDwarf(ctxt *Link, exef *os.File, exem *macho.File, dsym, outexe linkoffset := uint64(linkstart) - linkseg.Offset switch cmd.Cmd { case macho.LoadCmdSegment64: - err = machoUpdateSegment(reader, linkseg, linkoffset, &macho.Segment64{}, &macho.Section64{}) + err = machoUpdateSegment(reader, linkseg, linkoffset) case macho.LoadCmdSegment: - err = machoUpdateSegment(reader, linkseg, linkoffset, &macho.Segment32{}, &macho.Section32{}) + panic("unexpected 32-bit segment") case LC_DYLD_INFO, LC_DYLD_INFO_ONLY: err = machoUpdateLoadCommand(reader, linkseg, linkoffset, &dyldInfoCmd{}, "RebaseOff", "BindOff", "WeakBindOff", "LazyBindOff", "ExportOff") case macho.LoadCmdSymtab: @@ -313,70 +309,56 @@ func machoCompressSection(sectBytes []byte) (compressed bool, contents []byte, e // 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, linkseg *macho.Segment, linkoffset uint64, seg, sect interface{}) error { - if err := r.ReadAt(0, seg); err != nil { +func machoUpdateSegment(r loadCmdReader, linkseg *macho.Segment, linkoffset uint64) error { + var seg macho.Segment64 + 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, anything before that is fine. - if offset.Uint() < linkseg.Offset { + if seg.Offset < linkseg.Offset { return nil } - offset.SetUint(offset.Uint() + linkoffset) - if err := r.WriteAt(0, seg); err != nil { + seg.Offset += 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), linkoffset, nil) + return machoUpdateSections(r, &seg, linkoffset, nil) } -func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, deltaOffset uint64, compressedSects []*macho.Section) error { - iseg := reflect.Indirect(seg) - nsect := iseg.FieldByName("Nsect").Uint() +func machoUpdateSections(r loadCmdReader, seg *macho.Segment64, deltaOffset uint64, compressedSects []*macho.Section) error { + nsect := seg.Nsect if nsect == 0 { return nil } - sectOffset := int64(iseg.Type().Size()) - - isect := reflect.Indirect(sect) - offsetField := isect.FieldByName("Offset") - reloffField := isect.FieldByName("Reloff") - addrField := isect.FieldByName("Addr") - nameField := isect.FieldByName("Name") - sizeField := isect.FieldByName("Size") - sectSize := int64(isect.Type().Size()) - for i := uint64(0); i < nsect; i++ { - if err := r.ReadAt(sectOffset, sect.Interface()); err != nil { + sectOffset := int64(unsafe.Sizeof(*seg)) + + var sect macho.Section64 + sectSize := int64(unsafe.Sizeof(sect)) + for i := uint32(0); i < nsect; i++ { + if err := r.ReadAt(sectOffset, §); err != nil { return err } if compressedSects != nil { cSect := compressedSects[i] - var name [16]byte - copy(name[:], []byte(cSect.Name)) - nameField.Set(reflect.ValueOf(name)) - sizeField.SetUint(cSect.Size) + copy(sect.Name[:], cSect.Name) + sect.Size = cSect.Size if cSect.Offset != 0 { - offsetField.SetUint(uint64(cSect.Offset) + deltaOffset) + sect.Offset = cSect.Offset + uint32(deltaOffset) } if cSect.Addr != 0 { - addrField.SetUint(cSect.Addr) + sect.Addr = cSect.Addr } } else { - if offsetField.Uint() != 0 { - offsetField.SetUint(offsetField.Uint() + deltaOffset) - } - if reloffField.Uint() != 0 { - reloffField.SetUint(reloffField.Uint() + deltaOffset) + if sect.Offset != 0 { + sect.Offset += uint32(deltaOffset) } - if addrField.Uint() != 0 { - addrField.SetUint(addrField.Uint()) + if sect.Reloff != 0 { + sect.Reloff += uint32(deltaOffset) } } - if err := r.WriteAt(sectOffset, sect.Interface()); err != nil { + if err := r.WriteAt(sectOffset, §); err != nil { return err } sectOffset += sectSize @@ -386,32 +368,27 @@ func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, deltaOffset u // machoUpdateDwarfHeader updates the DWARF segment load command. 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 { 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 cmd.Cmd != macho.LoadCmdSegment64 { + panic("not a Segment64") } - if err := r.ReadAt(0, seg); err != nil { + var seg macho.Segment64 + if err := r.ReadAt(0, &seg); err != nil { return err } - segv := reflect.ValueOf(seg).Elem() - segv.FieldByName("Offset").SetUint(uint64(dwarfstart)) + seg.Offset = uint64(dwarfstart) if compressedSects != nil { var segSize uint64 for _, newSect := range compressedSects { segSize += newSect.Size } - segv.FieldByName("Filesz").SetUint(segSize) + seg.Filesz = segSize } else { - segv.FieldByName("Filesz").SetUint(dwarfsize) + seg.Filesz = dwarfsize } // We want the DWARF segment to be considered non-loadable, so @@ -424,14 +401,14 @@ func machoUpdateDwarfHeader(r *loadCmdReader, compressedSects []*macho.Section, // in ImageLoaderMachO.cpp (various versions can be found online, see // https://opensource.apple.com/source/dyld/dyld-519.2.2/src/ImageLoaderMachO.cpp.auto.html // as one example). - segv.FieldByName("Addr").SetUint(0) - segv.FieldByName("Memsz").SetUint(0) - segv.FieldByName("Prot").SetUint(0) + seg.Addr = 0 + seg.Memsz = 0 + seg.Prot = 0 - if err := r.WriteAt(0, seg); err != nil { + if err := r.WriteAt(0, &seg); err != nil { return err } - return machoUpdateSections(*r, segv, reflect.ValueOf(sect), uint64(dwarfstart)-realdwarf.Offset, compressedSects) + return machoUpdateSections(*r, &seg, uint64(dwarfstart)-realdwarf.Offset, compressedSects) } func machoUpdateLoadCommand(r loadCmdReader, linkseg *macho.Segment, linkoffset uint64, cmd interface{}, fields ...string) error { @@ -451,12 +428,3 @@ func machoUpdateLoadCommand(r loadCmdReader, linkseg *macho.Segment, linkoffset } return nil } - -func machoCalcStart(origAddr, newAddr uint64, alignExp uint32) int64 { - align := uint64(1 << alignExp) - origMod, newMod := origAddr%align, newAddr%align - if origMod == newMod { - return int64(newAddr) - } - return int64(newAddr + align + origMod - newMod) -} |