4

This is a much talked about subject, particularly of late. Hopefully this isn't a dupe as I've gone over all the other SO questions.

I'm not interested in whether this is legal or not. Whilst it's not 100% clear whether you can freely do what you want with a dylib on iOS8, it appears some amount of dynamic loading is allowed (see for example Can you build dynamic libraries for iOS and load them at runtime?).

What I care about is just making dlopen work (forget store submissions for now)! I've got a very basic iOS example where I manually do a dlopen followed by a dlsym to call a function in a homegrown dylib. This works fine on the simulator but fails on device. The device is an iPhone 4s running (non-jailbroken) iOS 7.1.2.

AFAIK it is legal to call dlopen even on iOS 7 as there are explicit Apple instructions for how to support this (see "Deploying a Containing App to Older Versions of iOS" here https://developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW3).

My guess is the root cause is something simple, like the dylib being in a folder which iOS doesn't like for binaries. Does anyone have any experience doing this and know what the restrictions are, or possibly knows what I'm doing wrong.

FYI my load code is:

NSString* resourcePath = [[NSBundle mainBundle] resourcePath];
NSString* dlPath = [NSString stringWithFormat: @"%@/frameworktest", resourcePath];
const char* cdlpath = [dlPath UTF8String];
void* hModule = dlopen(cdlpath, RTLD_LAZY);

The dylib (frameworktest) was created by creating a Cocoa Touch Framework, building and grabbing the dylib binary from the built framework and adding to the project resources (in the root folder). otool shows the dylib as an armv7 dynmic library targeting ios min version of 7.0. I can successfully fopen the file as well so I know I'm looking in the right folder.

I can step deep into the dlopen assembly. So far in fact that it became uninformative looking for obvious fails :)

Any ideas?

Community
  • 1
  • 1
Andrew Parker
  • 1,265
  • 1
  • 14
  • 23
  • 2
    Is your dylib signed? – duskwuff -inactive- Feb 18 '15 at 08:27
  • Are you getting an error? If so, you should state what it is. About all you say is *"...but fails on device"*. I also find `RTLD_GLOBAL | RTLD_LAZY` useful. I fallback to it if just `RTLD_LAZY` fails. (But that's on other OSes). If all else fails, you might try asking on [Jailbreak QA](http://www.jailbreakqa.com/). They often know about these types of corner cases. – jww Feb 18 '15 at 09:11
  • @duskwuff The dylib is as produced by the framework build, so unsigned (I would expect). Would it really need to be signed for debugging? Any idea how one would sign it (I will look into the proper method of building and packaging a framewoek - that may answer this and in general my question). – Andrew Parker Feb 18 '15 at 10:07
  • @jww Sorry, fail means dlopen returns a NULL ptr. No error messages. I tried adding some of the DYLD_XXX env variables but they didn't produce any useful trace (I didn't try them all mind you!). FYI I also tried dlsym with RTLD_MAIN_ONLY and this failed to find a known symbol in my exe. – Andrew Parker Feb 18 '15 at 10:13
  • 1
    *No error messages."* - so I'm clear... there's nothing in `errno`? *"Would it really need to be signed for debugging"* - yes... use `codesign -fs "Johnny Developer" mylib.dylib` to sign it. – jww Feb 18 '15 at 10:20

1 Answers1

3

Checking errno after the call to dlopen I see EPERM (not a big surprise I guess).

I've added a codesign phase to the build to explicity sign the dylib and it works now.

Some extra info: Interestingly, the sign phase for the app defaults to running over the whole .app bundle, not just the main app binary (never looked closely at that). So one might expect this to sign the dylib as well. In fact, when my custom phase runs codesign reports "replacing existing signature". However this might be coming from the original build of the framework. I checked the phases for that project and the framework is also signed (again, not just the dylib but the whole framework is passed to codesign). The sign parameters are the same. So somewhere along the trail the dylib is getting signed incorrectly I guess. I'll investigate this in more detail at some point and post back if there's any interesting info. My guess is I'm breaking the system by manually creating, extracting and packaging the dylib!

Thanks to @jww and @duskwuff for the suggestions!

Andrew Parker
  • 1,265
  • 1
  • 14
  • 23