Too many commands? Dyld Message: malformed mach-o: load commands size

Viewed 2617

Some iOS 9 devices in the wild seem to crash with the error message that I receive from the very basic crash reporting in Xcode only

dyld: malformed mach-o: load commands size (16464) > 16384

Unfortunately that's all the info I get. I can't even debug or reproduce locally. Can anyone hint me into the right direction here?

It occurs after updating my Cocoapods, so I guess there's one of them (or their dependency) that misbehaves.

After some investigation of my mach-O binary, I saw that the sizeofcmds is really 16464. If I understand correctly, there seems to be a load command size limit of 16384, can anyone confirm this?

Does that mean I should remove dylibs and everything should be fine?

4 Answers

At WWDC18 I went to an Apple engineer who is working on dyld. Here’s what he had to say:

  • The Dyld code is downloadable from https://opensource.apple.com (the one specific to us can be found inside macOS 10.12)
  • For iOS 9 the maximum size of load commands is indeed 16k aka 1 memory page (There’s no way around it! This is imposed by the OS itself. For customer service telling people to update to iOS 10 (all devices that run iOS 9 can except for iPhone 4S) would be viable.)
  • Since iOS 10 the maximum size of commands is 32k
  • Majority of the size of the load commands is determined by strings (paths) of the frameworks (use command otool -L to see them

Possible solutions:

  • Use less libraries (that was our goto solution thus far, but we will change to umbrella libraries (see below))
  • Shortening names (might screw up header lookup of cocoa pods, maybe use head maps to fix that inside the Xcode build process → maybe more (high-level) info in WWDC18 session “Behind the scenes of the Xcode Build Process”)
  • Try to build static archives for libraries (should not have dynamic resources otherwise make copy phases and figure out where resources are)
  • Build frameworks that re-export other frameworks (umbrella frameworks). Use -reexport-l as a linker flag (not done often) → gonna make some runtime overhead when starting the app, also uses a bit more memory (man ld → for info on re-exports)

The engineer recommended to file a bugreport via bugreport.apple.com, because in the future even hitting the 32k limit is possible.

Related