Getting the IMP of the current method

Once in a very great while, you come across a weird situation where you want to know the IMP of the current method. I’ll just say right now that if you think you need this, you probably don’t. That’s how rare this situation is.

Regardless, it’s an interesting question. How do you get the function pointer for the currently-executing method?

A few years ago, Matt Gallagher came up with a clever solution to this using a compiler function called __builtin_return_address(). His code still works great with the LLVM 3.0 compiler. My only beef with it is that there’s a lot of looping going on. He’s looping over the entire superchain, over every single method, looking at the IMP's address and comparing them to another pointer.

Pretty Pretty

This morning I was thinking about a question on Stack Overflow and thought of another way to get the current IMP:

static inline IMP __CurrentIMP(const char *info, SEL _cmd) {
  IMP imp = NULL;
  if (info[0] == '-' || info[0] == '+') {
    NSString *tmp = [NSString stringWithCString:info+2 encoding:NSUTF8StringEncoding];
    NSRange r = [tmp rangeOfString:@" "];
    NSString *className = [tmp substringToIndex:r.location];
    Class thisClass = NSClassFromString(className);
    if (thisClass != nil) {
      Method m = NULL;
      if (info[0] == '+') {
        m = class_getClassMethod(thisClass, _cmd);
      } else {
        m = class_getInstanceMethod(thisClass, _cmd);
      }
      if (m != NULL) {
        imp = method_getImplementation(m);
      }
    }
  }
  return imp;
}

#define CurrentIMP __CurrentIMP(__PRETTY_FUNCTION__, _cmd)

So, what’s going on? Basically, we’re parsing a special string that’s generated by the compiler and then doing a single lookup. The important bit is the __PRETTY_FUNCTION__. This is a built-in “magic” value that, when compiled, becomes a very nice-looking description of the current function (it’s “pretty”).

For a regular C function, __PRETTY_FUNCTION__ becomes a const char* that includes the name of the function and some type information. The main() function has a __PRETTY_FUNCTION__ of this: "int main(int, const char **)". Ooooo, pretty! :)

An Objective-C method’s pretty description doesn’t include type information, but it does include some very important information. Let’s say we have a class Bar that has this method:

- (id)doAwesomeThingWithFoo:(Foo *)foo {
    ...
}

The pretty description for this is "-[Bar doAwesomeThingWithFoo:]". Here, we see two very important pieces of information:

  • The first character is a -, indicating that the method is an instance method
  • The name of the implementing class is clearly visible.

The selector is also in there, but we would have that anyway through _cmd, so that’s not very interesting. (We could forego passing in _cmd to the __CurrentIMP function and parse it out of the description, but since _cmd is there already, let’s use that.)

The really important thing to realize here is that the name of the class in the description is the class on which the method is implemented, and not the class of any instance. This makes sense, because this is all happening at compile time, not runtime.

Armed with these two pieces of information, we can quickly get the appropriate IMP. First, we do some really simple string parsing to extract the name of the class from the description, and turn it in to a Class object with the NSClassFromString function.

Now that we have the Class and the selector (we’re just using _cmd), we can get the IMP. However, we need to know which runtime function we should be using. For this, we can simply look at the first character in the description string. If it’s a +, then we use the class-specific function, otherwise we’ll use the instance-specific function.

These functions (class_getClassMethod and class_getInstanceMethod) both return Method references. From this Method, we can simply use method_getImplemention to get the method’s IMP. Simple!

Some may ask: why are we getting the Method reference instead of using the class_getMethodImplementation function, which returns an IMP directly? The answer for that is that while that would usually work, it would fail for methods that have large return values (i.e. where the size of the return value is larger than sizeof(id)). In that case, we’d have to use the class_getMethodImplementation_stret function, which means we’d have to get an NSMethodSignature object and check the methodReturnLength to decide which function to use. I figure that getting the Method and asking it for its IMP is probably simpler.

Now, there is a downside to this approach (that are not present in Matt’s implementation). Since this is relying on a compile time detail (the pretty description), this totally and utterly breaks when you start add methods, swizzling implementations, make IMPs from blocks, etc.

But for those times where you, for whatever reason, need to know what your IMP is, this works pretty well.


Steve Weller pointed on on Twitter that if you combine this code with Matt’s version, you can reasonably determine when a method has been swizzled. Cool!

  1. script-ease reblogged this from funwithobjc
  2. funwithobjc posted this
Short URL for this post: http://tmblr.co/Zt522yCmpqEs
blog comments powered by Disqus