iosobjective-cjailbreakdlopentweak

What's wrong with my code to dynamically get constants with dlsym in jailbroken iOS?


I need to use kIOSurfaceWidth in my code to capture the screen shot, but for Apple has removed the PrivateFrameworks from iOS 9.3, so I have to load the IOSurface.frameworks dynamically at runtime. I use the code as below, but return not null it after dlsym, but when I try to NSLog the value of kIOSurfaceWidth, it crashes. Could anyone give me some help?

static CFStringRef _kIOSurfaceWidth;

static void load()
{
    void* handle = dlopen("/System/Library/PrivateFrameworks/IOSurface.framework/IOSurface", RTLD_LAZY);

    _kIOSurfaceWidth = dlsym(RTLD_DEFAULT, "kIOSurfaceWidth");
    if (!_kIOSurfaceWidth) LOG_GENERAL(@">>>>>>>> _kIOSurfaceWidth is NULL");
    else NSLOG(@"_kIOSurfaceWidth is %@", (NSString *)CFBridgingRelease(_kIOSurfaceWidth));
}

Solution

  • dlsym() gives you the address of the symbol, not its value. Change your code like so:

    static CFStringRef *_kIOSurfaceWidth;
    
    static void load()
    {
        void* handle = dlopen("/System/Library/PrivateFrameworks/IOSurface.framework/IOSurface", RTLD_LAZY);
    
        _kIOSurfaceWidth = dlsym(RTLD_DEFAULT, "kIOSurfaceWidth");
        if (!_kIOSurfaceWidth) LOG_GENERAL(@">>>>>>>> _kIOSurfaceWidth is NULL");
        else NSLog(@"*_kIOSurfaceWidth is %@", *_kIOSurfaceWidth);
    }
    

    You also had other problems. Your log line was using kIOSurfaceWidth without a leading underscore (_), so it wasn't referring to your variable.

    You were calling CFBridgingRelease() which is not appropriate unless you have an ownership reference. It's only appropriate in a case where you would be entitled to use CFRelease(), which is why it's named similarly. There should be no need to do a cast, bridging or otherwise, just to pass the string reference as a parameter to NSLog().