Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way for dlopen to reload a dylib file on iOS?

Tags:

ios

dylib

dlopen

As the title says... I'm interested in dlopen(). I understand this isn't allowed by the app store but I'm curious about this on iOS.

The issue I have is that I can create a .dylib file and I can load this file at runtime with the following code

char *dylibPath = "/Applications/myapp.app/mydylib2.dylib";

void *libHandle = dlopen(dylibPath, RTLD_NOW);
if (libHandle != NULL) {
    NSString * (*someMethod)() = dlsym(libHandle, "someMethod");
    if (someMethod != NULL)  {
        NSLog(someMethod());
    }
    dlclose(libHandle);
}

This is taken from here.

The problem I have is that if I change mydylib2.dylib, dlopen doesn't load the recompiled .dylib file. Instead, it resolves an old version of the function someMethod.

For example, if someMethod first returns @"Hello" and I change this to be @"Hello World" and recompile, the code above will always return @"Hello" until I restart the app in the simulator.

Do any know why this is the case? and suggest a workaround so the this .dylib can be reloaded at runtime?

like image 952
Eamonn Moloney Avatar asked Sep 29 '12 13:09

Eamonn Moloney


Video Answer


1 Answers

Looking at the man page for dlclose it looks like there are a couple of reasons why the library wouldn't be unloaded.

There are a couple of cases in which a dynamic library will never be unloaded: 1) the main executable links against it, 2) An API that does not supoort unloading (e.g. NSAddImage()) was used to load it or some other dynamic library that depends on it, 3) the dynamic library is in dyld's shared cache.

I suspect your issue is the "dyld shared cache." You could try running:

sudo update_dyld_shared_cache -force

after you've replaced the library (not sure if this is available on the iOS though).

Have you checked the return value of dlclose to see if it was successful or failed?

like image 90
mttrb Avatar answered Sep 20 '22 21:09

mttrb