I'm looking for a way to make an NSInvocation
invoke a specific IMP
. By default, it invokes the "lowest" IMP
it can find (ie, the most-recently-overridden version), but I'm looking for a way to make it invoke an IMP
from higher up in the inheritance chain. The IMP
I want to invoke is determined dynamically, or else I'd be able to use the super
keyword or something like that.
My thought was to use the -forwardInvocation:
mechanism to capture a message (easy and already working) and then alter the IMP
so it goes to a method that is neither the super
implementation nor the furthest descendent's implementation. (hard)
The only thing I've found that comes remotely close is AspectObjectiveC, but that requires libffi, which makes it non-iOS compatible. Ideally I'd like this to be cross platform.
Any ideas?
disclaimer: i'm just experimenting
Trying out @bbum's idea of a trampoline function
So I think I've got things mostly set up; I've got the following trampoline that gets correctly added via class_addMethod()
, and it does get entered:
id dd_trampolineFunction(id self, SEL _cmd, ...) {
IMP imp = [self retrieveTheProperIMP];
self = [self retrieveTheProperSelfObject];
asm(
"jmp %0\n"
:
: "r" (imp)
);
return nil; //to shut up the compiler
}
I've verified that both the proper self and the proper IMP are the right things prior to the JMP, and the _cmd
parameter is also coming in properly. (in other words, I correctly added this method).
However, something is going on. I sometimes find myself jumping to a method (usually not the right one) with a nil self
and _cmd
. Other times I'll just crash in the middle of nowhere with an EXC_BAD_ACCESS. Ideas? (it's been a long time since I've done anything in assembly...) I'm testing this on x86_64.