How to use ldid?

Vitalii picture Vitalii · Oct 7, 2012 · Viewed 18.4k times · Source

I am trying to run unsigned application on iOS 5.1/iPhone 4s (jailbroken). What I did:

  1. Disable code signing in XCode.

  2. Built unsigned iPhone app.

  3. Copied it to my iPhone via SSH to location /User/me/development/HelloWorld.app

  4. Now I try to simulate its signing to run this application on iPhone. I run follwing commands:

.

cd /User/me/development
chmod -R 777 HelloWorld.app
ldid -S HelloWorld

However, I receive following error:

util/ldid.cpp(567): _assert(78:arch != NULL)

What are possible reason of such error and now to fix it?

Answer

Nate picture Nate · Oct 8, 2012

1) Using ldid -S is the correct usage. Not lowercase (-s).

2) Usually, when I get this error, it's because I built my app with the wrong architectures. Most older versions of ldid that I've used cannot sign fat binaries (but see Update below). Fat binaries are ones with more than one architecture inside. For example, a dual armv6 and armv7 executable. Or with Xcode 4.5, it's probably defaulting to armv7 and armv7s.

In the project build settings, use the Architectures, Valid Architectures and Build Active Architecture Only settings to determine which architecture executable is built. For jailbreak development, I usually set Build Active Architecture Only to YES. And valid archictures set to armv6 and armv7.

3) Also, some older versions of ldid cannot sign armv7 executables. If you get the pre-built copy from KennyTM's site here, it supports armv7. Note that this ldid is built for Mac OS X, so it's designed to be run on the executable on your Mac, after building without signing in Xcode, but before you upload to your iPhone.

Newer phones can generally run executables built for older architectures, but not the other way around. So, build for the oldest architecture you want to support. You just will lose some optimizations in the newer architectures (which most people don't care too much about ... let me know if your app needs these optimizations, and I'll post more).

So, if you want to support old devices (iPhone < 3GS), I would set Architectures to only armv6, making sure to remove the default setting of $(ARCHS_STANDARD_32_BIT). If you only need support for relatively new ones, then pick armv7, but make sure you use a version of ldid that can sign armv7 binaries.

Edit: to determine if the executable you were trying to sign was a fat one, run this at the command line:

> cd HelloJB.app

> ls
HelloJB     Info.plist  PkgInfo     date.zip    en.lproj

> lipo -info HelloJB 
Non-fat file: HelloJB is architecture: armv7

As you can see in the above output, my HelloJB executable is not fat, and only has armv7 code.

Update

I believe that the pre-built version of ldid found here can now sign fat executables, although there are still ldid versions floating around that cannot. Also, I think that if you install a recent version of iOSOpenDev, it will give you a version of ldid that can sign fat executables (default install location of /opt/iOSOpenDev/bin/ldid).