@@ -217,9 +217,9 @@ func machoCombineDwarf(ctxt *Link, exef *os.File, exem *macho.File, dsym, outexe
217
217
linkoffset := uint64 (linkstart ) - linkseg .Offset
218
218
switch cmd .Cmd {
219
219
case macho .LoadCmdSegment64 :
220
- err = machoUpdateSegment (reader , linkseg , linkoffset , & macho. Segment64 {}, & macho. Section64 {} )
220
+ err = machoUpdateSegment (reader , linkseg , linkoffset )
221
221
case macho .LoadCmdSegment :
222
- err = machoUpdateSegment ( reader , linkseg , linkoffset , & macho. Segment32 {}, & macho. Section32 {} )
222
+ panic ( "unexpected 32-bit segment" )
223
223
case LC_DYLD_INFO , LC_DYLD_INFO_ONLY :
224
224
err = machoUpdateLoadCommand (reader , linkseg , linkoffset , & dyldInfoCmd {}, "RebaseOff" , "BindOff" , "WeakBindOff" , "LazyBindOff" , "ExportOff" )
225
225
case macho .LoadCmdSymtab :
@@ -313,70 +313,56 @@ func machoCompressSection(sectBytes []byte) (compressed bool, contents []byte, e
313
313
314
314
// machoUpdateSegment updates the load command for a moved segment.
315
315
// 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 {
320
319
return err
321
320
}
322
- segValue := reflect .ValueOf (seg )
323
- offset := reflect .Indirect (segValue ).FieldByName ("Offset" )
324
321
325
322
// Only the linkedit segment moved, anything before that is fine.
326
- if offset . Uint () < linkseg .Offset {
323
+ if seg . Offset < linkseg .Offset {
327
324
return nil
328
325
}
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 {
331
328
return err
332
329
}
333
330
// 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 )
335
332
}
336
333
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
340
336
if nsect == 0 {
341
337
return nil
342
338
}
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 {
354
345
return err
355
346
}
356
347
if compressedSects != nil {
357
348
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
362
351
if cSect .Offset != 0 {
363
- offsetField . SetUint ( uint64 ( cSect .Offset ) + deltaOffset )
352
+ sect . Offset = cSect .Offset + uint32 ( deltaOffset )
364
353
}
365
354
if cSect .Addr != 0 {
366
- addrField . SetUint ( cSect .Addr )
355
+ sect . Addr = cSect .Addr
367
356
}
368
357
} 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 )
374
360
}
375
- if addrField . Uint () != 0 {
376
- addrField . SetUint ( addrField . Uint () )
361
+ if sect . Reloff != 0 {
362
+ sect . Reloff += uint32 ( deltaOffset )
377
363
}
378
364
}
379
- if err := r .WriteAt (sectOffset , sect . Interface () ); err != nil {
365
+ if err := r .WriteAt (sectOffset , & sect ); err != nil {
380
366
return err
381
367
}
382
368
sectOffset += sectSize
@@ -386,32 +372,27 @@ func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, deltaOffset u
386
372
387
373
// machoUpdateDwarfHeader updates the DWARF segment load command.
388
374
func machoUpdateDwarfHeader (r * loadCmdReader , compressedSects []* macho.Section , dwarfsize uint64 , dwarfstart int64 , realdwarf * macho.Segment ) error {
389
- var seg , sect interface {}
390
375
cmd , err := r .Next ()
391
376
if err != nil {
392
377
return err
393
378
}
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" )
400
381
}
401
- if err := r .ReadAt (0 , seg ); err != nil {
382
+ var seg macho.Segment64
383
+ if err := r .ReadAt (0 , & seg ); err != nil {
402
384
return err
403
385
}
404
- segv := reflect .ValueOf (seg ).Elem ()
405
- segv .FieldByName ("Offset" ).SetUint (uint64 (dwarfstart ))
386
+ seg .Offset = uint64 (dwarfstart )
406
387
407
388
if compressedSects != nil {
408
389
var segSize uint64
409
390
for _ , newSect := range compressedSects {
410
391
segSize += newSect .Size
411
392
}
412
- segv . FieldByName ( " Filesz" ). SetUint ( segSize )
393
+ seg . Filesz = segSize
413
394
} else {
414
- segv . FieldByName ( " Filesz" ). SetUint ( dwarfsize )
395
+ seg . Filesz = dwarfsize
415
396
}
416
397
417
398
// We want the DWARF segment to be considered non-loadable, so
@@ -424,14 +405,14 @@ func machoUpdateDwarfHeader(r *loadCmdReader, compressedSects []*macho.Section,
424
405
// in ImageLoaderMachO.cpp (various versions can be found online, see
425
406
// https://opensource.apple.com/source/dyld/dyld-519.2.2/src/ImageLoaderMachO.cpp.auto.html
426
407
// 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
430
411
431
- if err := r .WriteAt (0 , seg ); err != nil {
412
+ if err := r .WriteAt (0 , & seg ); err != nil {
432
413
return err
433
414
}
434
- return machoUpdateSections (* r , segv , reflect . ValueOf ( sect ) , uint64 (dwarfstart )- realdwarf .Offset , compressedSects )
415
+ return machoUpdateSections (* r , & seg , uint64 (dwarfstart )- realdwarf .Offset , compressedSects )
435
416
}
436
417
437
418
func machoUpdateLoadCommand (r loadCmdReader , linkseg * macho.Segment , linkoffset uint64 , cmd interface {}, fields ... string ) error {
0 commit comments