问题
I am trying to create a dynamic library for iOS and load it at runtime. After taking a look at this question and this answer, I have been doing it using iOSOpenDev and deploying everything on my iPhone. The xCode project for the dylib is called KDylibTwo and the files I modiefied are:
KDylibTwo.h
#import <Foundation/Foundation.h>
@interface KDylibTwo : NSObject
-(void)run;
@end
KDylibTwo.m
#import "KDylibTwo.h"
@implementation KDylibTwo
-(id)init
{
if ((self = [super init]))
{
}
return self;
}
-(void)run{
NSLog(@"KDylibTwo loadded.");
}
@end
In order to test if my library works, after building it for profiling (the way iOSOpenDev deploys it on iPhone), I can find it stored on my device at /usr/lib/libKDylibTwo.dylib
and built a tweak (again using iOSOpenDev), hooking the SpringBoard as follows:
#include <dlfcn.h>
%hook SBApplicationIcon
-(void)launch{
NSLog(@"\n\n\n\n\n\n\nSBHook For libKDylibTwo.dylib");
void* dylibLink = dlopen("/usr/lib/libKDylibTwo.dylib", RTLD_NOW);
if(dylibLink == NULL) {
NSLog(@"Loading failed.");
} else {
NSLog(@"Dylib loaded.");
void (*function)(void);
*(void **)(&function) = dlsym(dylibLink, "run");
if (function) {
NSLog(@"Function found.");
(*function)();
} else {
NSLog(@"Function NOT found");
}
}
NSLog(@"End of code");
%log;
%orig;
}
%end
After installing the tweak on the device and tapping on an icon (that would fire the hooked code), the Console output looks like:
Aug 28 13:03:35 Pudge SpringBoard[18254] <Warning>: SBHook For libKDylibTwo.dylib
Aug 28 13:03:35 Pudge SpringBoard[18254] <Warning>: Dylib loaded.
Aug 28 13:03:35 Pudge SpringBoard[18254] <Warning>: Function NOT found
Aug 28 13:03:35 Pudge SpringBoard[18254] <Warning>: End of code
Aug 28 13:03:35 Pudge SpringBoard[18254] <Warning>: -[<SBApplicationIcon: 0x1d5008c0> launch]
My question is what am I doing wrong and the the library's function is not called or executed! I think I should clarify that I am only talking about jailbroken devices and not App Store development, so please don't go ahead posting that it cannot be done!
Thank you in advance,
Panagiotis.
回答1:
As Victor Ronin pointed out, "dlsym" is for C symbols. To obtain objective-C class from dylib that you linked at runtime you can use objc runtime functions. In your case:
void* dylibLink = dlopen("/usr/lib/libKDylibTwo.dylib", RTLD_NOW);
id KDylibTwo = [[objc_getClass("KDylibTwo") alloc] init];
[KDylibTwo run];
First line is linking your library at runtime. This is required in order to use code inside of it.
Second line creates instance of class KDylibTwo
. objc_getClass
function returns class object that you can later use to create instances of this class like you would with any objective-C class - using alloc
and init
methods. Once you obtained class object with objc_getClass
you can work with him like nothing happend. At this point you can forget that you dynamically linked you library at runtime.
Third line is calling run
method. As you can see, it's normal objective-C syntax. Nothing is changed because you linked your library at runtime. You can call any method you want.
回答2:
I have never used dlsym to get a pointer to objective c method (I believe it's not possible to call objective c method through dlsym, but I may be wrong).
However, most important bit of information that second parameter of dlsym should be the symbol name.
Symbol name "run" will work only for C function. Something like:
EXPORT void run()
{
NSLog(@"Run");
}
Object C method has more complex symbol names and as I said, I am not sure whether they could be passed to dlsym at all.
来源:https://stackoverflow.com/questions/18484989/ios-6-1-dynamic-library-build-and-link