Skip to content

Commit ae3680b

Browse files
committed
cmd/link: rewrite some code without using reflection
In Mach-O DWARF combining, some code was written using reflection, so it could support both 32-bit and 64-bit Mach-O files without duplicating code. We no longer support 32-bit darwin platforms now. 32-bit support can go. Rewrite it with direct field access, for 64-bit only. Change-Id: If1338c3cd37cecf603f4df0c6eb0c890eaebfe5f Reviewed-on: https://go-review.googlesource.com/c/go/+/253557 Run-TryBot: Cherry Zhang <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Than McIntosh <[email protected]>
1 parent e8f9185 commit ae3680b

File tree

1 file changed

+38
-57
lines changed

1 file changed

+38
-57
lines changed

src/cmd/link/internal/ld/macho_combine_dwarf.go

Lines changed: 38 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,9 @@ func machoCombineDwarf(ctxt *Link, exef *os.File, exem *macho.File, dsym, outexe
217217
linkoffset := uint64(linkstart) - linkseg.Offset
218218
switch cmd.Cmd {
219219
case macho.LoadCmdSegment64:
220-
err = machoUpdateSegment(reader, linkseg, linkoffset, &macho.Segment64{}, &macho.Section64{})
220+
err = machoUpdateSegment(reader, linkseg, linkoffset)
221221
case macho.LoadCmdSegment:
222-
err = machoUpdateSegment(reader, linkseg, linkoffset, &macho.Segment32{}, &macho.Section32{})
222+
panic("unexpected 32-bit segment")
223223
case LC_DYLD_INFO, LC_DYLD_INFO_ONLY:
224224
err = machoUpdateLoadCommand(reader, linkseg, linkoffset, &dyldInfoCmd{}, "RebaseOff", "BindOff", "WeakBindOff", "LazyBindOff", "ExportOff")
225225
case macho.LoadCmdSymtab:
@@ -313,70 +313,56 @@ func machoCompressSection(sectBytes []byte) (compressed bool, contents []byte, e
313313

314314
// machoUpdateSegment updates the load command for a moved segment.
315315
// Only the linkedit segment should move, and it should have 0 sections.
316-
// seg should be a macho.Segment32 or macho.Segment64 as appropriate.
317-
// sect should be a macho.Section32 or macho.Section64 as appropriate.
318-
func machoUpdateSegment(r loadCmdReader, linkseg *macho.Segment, linkoffset uint64, seg, sect interface{}) error {
319-
if err := r.ReadAt(0, seg); err != nil {
316+
func machoUpdateSegment(r loadCmdReader, linkseg *macho.Segment, linkoffset uint64) error {
317+
var seg macho.Segment64
318+
if err := r.ReadAt(0, &seg); err != nil {
320319
return err
321320
}
322-
segValue := reflect.ValueOf(seg)
323-
offset := reflect.Indirect(segValue).FieldByName("Offset")
324321

325322
// Only the linkedit segment moved, anything before that is fine.
326-
if offset.Uint() < linkseg.Offset {
323+
if seg.Offset < linkseg.Offset {
327324
return nil
328325
}
329-
offset.SetUint(offset.Uint() + linkoffset)
330-
if err := r.WriteAt(0, seg); err != nil {
326+
seg.Offset += linkoffset
327+
if err := r.WriteAt(0, &seg); err != nil {
331328
return err
332329
}
333330
// There shouldn't be any sections, but just to make sure...
334-
return machoUpdateSections(r, segValue, reflect.ValueOf(sect), linkoffset, nil)
331+
return machoUpdateSections(r, &seg, linkoffset, nil)
335332
}
336333

337-
func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, deltaOffset uint64, compressedSects []*macho.Section) error {
338-
iseg := reflect.Indirect(seg)
339-
nsect := iseg.FieldByName("Nsect").Uint()
334+
func machoUpdateSections(r loadCmdReader, seg *macho.Segment64, deltaOffset uint64, compressedSects []*macho.Section) error {
335+
nsect := seg.Nsect
340336
if nsect == 0 {
341337
return nil
342338
}
343-
sectOffset := int64(iseg.Type().Size())
344-
345-
isect := reflect.Indirect(sect)
346-
offsetField := isect.FieldByName("Offset")
347-
reloffField := isect.FieldByName("Reloff")
348-
addrField := isect.FieldByName("Addr")
349-
nameField := isect.FieldByName("Name")
350-
sizeField := isect.FieldByName("Size")
351-
sectSize := int64(isect.Type().Size())
352-
for i := uint64(0); i < nsect; i++ {
353-
if err := r.ReadAt(sectOffset, sect.Interface()); err != nil {
339+
sectOffset := int64(unsafe.Sizeof(*seg))
340+
341+
var sect macho.Section64
342+
sectSize := int64(unsafe.Sizeof(sect))
343+
for i := uint32(0); i < nsect; i++ {
344+
if err := r.ReadAt(sectOffset, &sect); err != nil {
354345
return err
355346
}
356347
if compressedSects != nil {
357348
cSect := compressedSects[i]
358-
var name [16]byte
359-
copy(name[:], []byte(cSect.Name))
360-
nameField.Set(reflect.ValueOf(name))
361-
sizeField.SetUint(cSect.Size)
349+
copy(sect.Name[:], cSect.Name)
350+
sect.Size = cSect.Size
362351
if cSect.Offset != 0 {
363-
offsetField.SetUint(uint64(cSect.Offset) + deltaOffset)
352+
sect.Offset = cSect.Offset + uint32(deltaOffset)
364353
}
365354
if cSect.Addr != 0 {
366-
addrField.SetUint(cSect.Addr)
355+
sect.Addr = cSect.Addr
367356
}
368357
} else {
369-
if offsetField.Uint() != 0 {
370-
offsetField.SetUint(offsetField.Uint() + deltaOffset)
371-
}
372-
if reloffField.Uint() != 0 {
373-
reloffField.SetUint(reloffField.Uint() + deltaOffset)
358+
if sect.Offset != 0 {
359+
sect.Offset += uint32(deltaOffset)
374360
}
375-
if addrField.Uint() != 0 {
376-
addrField.SetUint(addrField.Uint())
361+
if sect.Reloff != 0 {
362+
sect.Reloff += uint32(deltaOffset)
377363
}
378364
}
379-
if err := r.WriteAt(sectOffset, sect.Interface()); err != nil {
365+
if err := r.WriteAt(sectOffset, &sect); err != nil {
380366
return err
381367
}
382368
sectOffset += sectSize
@@ -386,32 +372,27 @@ func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, deltaOffset u
386372

387373
// machoUpdateDwarfHeader updates the DWARF segment load command.
388374
func machoUpdateDwarfHeader(r *loadCmdReader, compressedSects []*macho.Section, dwarfsize uint64, dwarfstart int64, realdwarf *macho.Segment) error {
389-
var seg, sect interface{}
390375
cmd, err := r.Next()
391376
if err != nil {
392377
return err
393378
}
394-
if cmd.Cmd == macho.LoadCmdSegment64 {
395-
seg = new(macho.Segment64)
396-
sect = new(macho.Section64)
397-
} else {
398-
seg = new(macho.Segment32)
399-
sect = new(macho.Section32)
379+
if cmd.Cmd != macho.LoadCmdSegment64 {
380+
panic("not a Segment64")
400381
}
401-
if err := r.ReadAt(0, seg); err != nil {
382+
var seg macho.Segment64
383+
if err := r.ReadAt(0, &seg); err != nil {
402384
return err
403385
}
404-
segv := reflect.ValueOf(seg).Elem()
405-
segv.FieldByName("Offset").SetUint(uint64(dwarfstart))
386+
seg.Offset = uint64(dwarfstart)
406387

407388
if compressedSects != nil {
408389
var segSize uint64
409390
for _, newSect := range compressedSects {
410391
segSize += newSect.Size
411392
}
412-
segv.FieldByName("Filesz").SetUint(segSize)
393+
seg.Filesz = segSize
413394
} else {
414-
segv.FieldByName("Filesz").SetUint(dwarfsize)
395+
seg.Filesz = dwarfsize
415396
}
416397

417398
// We want the DWARF segment to be considered non-loadable, so
@@ -424,14 +405,14 @@ func machoUpdateDwarfHeader(r *loadCmdReader, compressedSects []*macho.Section,
424405
// in ImageLoaderMachO.cpp (various versions can be found online, see
425406
// https://opensource.apple.com/source/dyld/dyld-519.2.2/src/ImageLoaderMachO.cpp.auto.html
426407
// as one example).
427-
segv.FieldByName("Addr").SetUint(0)
428-
segv.FieldByName("Memsz").SetUint(0)
429-
segv.FieldByName("Prot").SetUint(0)
408+
seg.Addr = 0
409+
seg.Memsz = 0
410+
seg.Prot = 0
430411

431-
if err := r.WriteAt(0, seg); err != nil {
412+
if err := r.WriteAt(0, &seg); err != nil {
432413
return err
433414
}
434-
return machoUpdateSections(*r, segv, reflect.ValueOf(sect), uint64(dwarfstart)-realdwarf.Offset, compressedSects)
415+
return machoUpdateSections(*r, &seg, uint64(dwarfstart)-realdwarf.Offset, compressedSects)
435416
}
436417

437418
func machoUpdateLoadCommand(r loadCmdReader, linkseg *macho.Segment, linkoffset uint64, cmd interface{}, fields ...string) error {

0 commit comments

Comments
 (0)