When you call an method, for example, [objectA message:arg1 argument:arg2], what happens to the arguments?
For example, when you call a method, the address of that method is pushed to the call stack. But what happens to the arguments? Aren't they pushed to some stack too? Otherwise, how does the code of the method know where to find its arguments?
The reason I ask is because when you get a stack trace, you get the address of the functions or methods that have been called in order. When a method or function returns, the one that called it still has a reference to its own arguments. So there must me a reference to arg1 and arg2 somewhere. Therefore, from a stack trace and stack symbols on an iOS device, you must be able to get the method or function that called any other method or function, and also get its arguments.
How do you get these arguments?
On this other question: objective C log method call, they show a method to get the NSMethodSignature of a method and using that you can get the number and type of argument.
With that, an knowing where the arguments are located, you could get every function or method that has been called and the arguments that were used to call them.
Any help would be appreciated.
UPDATES
2011-08-03
In reply to "fakeAccount22" comments, I would like to do this at run-time from within the app.
My question basically boils down to: at run-time and within the app, how do you access the call stack or the stack pointer in Objective-C for an iOS device? Is it different for Mac OSX?
The key moment here is that when you invoke
[objectA message:arg1 argument:arg2]
you don't call method but you're sending message. Why? Cause in the end this line is translated by compiler into this:
objc_msgSend(objectA, "message:argument:", arg1, arg2)
That's all the magic. Everything else works as in C. Here is quite good explanation.
That's why all Objective C methods could be translated to their C-analogous (well, they are actually do translated). E.g. your example looks like this:
return_type method(id self, SEL _cmd, arg1_type arg1, arg2_type arg2) {
//implementation
}
Beside what Max wrote, the names and arguments of a method are known because the compiler generates a huge load of debug information, generated from the source code, and the debugger can use that to find names of methods and the names and values of their arguments, etc. This debug info is usually not easily available when you run your code without the debugger, although it ought to be accessible somehow, if you know the format how it is stored. But note that it can change with every new compilation.
Before a function call, the arguments get pushed on the call stack by the calling code, and when the call to the function is made, the return address is pushed there too, by the processor. Inside the function, the stack pointer is stored and now the stack can also be used to store local variables. At the end of the function, the original stack pointer is restored (which makes the local variables invalid and inaccessible) and the processor pops the return address and continues with the code after the call. The caller code than removes the arguments from the stack and continues with the rest of its code.
FWIW, that is how it happens in C. There are other, similar schemes, where items are pushed on the stack in a different order or even passed in registers, or where the function clears the arguments from the stack. Such a scheme is called a calling convention. Obj-C uses the cdecl calling convention, which is more or less how I described it.
Related
I recently started a project where I require to do swizzling.
After going through many tutorials I got a question, What is the difference between Implementation and function pointer?
From memory, an IMP is a memory-address just like a function pointer, and can be invoked just like an ordinary C function. However it is guaranteed to use objective-C messaging convention, where:
The first argument is the object to operate on (self).
The second argument is the _cmd (SELECTOR) to be invoked. I believe this is so to support dynamic features, such as ObjC message forwarding where we could wrap the original implementation in a proxy, say to start a transaction or perform a security check, or, for a Cocoa specific example, add some property observation cruft, by magic, at run-time. While we already have the function signature, I could be helpful, in some cases, to know "how did I get here?" with the message signature.
Following arguments, if any, are according to the method contract.
my question as the title says.obviously, the first parameter was used for this pointer , in some taste of c++.what about the second one? thak you.
The signature of objc_msgSend() is:
id objc_msgSend(id self, SEL op, ...);
Every method call is compiled down to a call to this function. I.e., if you call:
[anArray objectAtIndex:42];
That will be compiled as if it were:
objc_msgSend(anArray, #selector(objectAtIndex:), 42);
Now, to your question, why do methods get compiled down to a function that has the SEL as the second argument. Or, more specifically, why is this method:
- (id)objectAtIndex:(NSUInteger)index;
Exactly equivalent to this C function:
id object_at_index(id object, SEL _cmd, NSUInteger index);
The answer is speed speed speed.
Speed
Specifically, by doing this, then objc_msgSend() never has to rewrite the stack frame* and it can also use a tail call optimization to jump directly to the method invocation. This is the same reason why you never see objc_msgSend() in backtraces in the debugger (save for when you actually crash/break in the messenger).
objc_msgSend() uses the object and the _cmd to look up the implementation of the method and then, quite literally, jumps to that implementation.
Very fast. Stack frame untouched.
And, as others have stated, having _cmd around in the method implementation can be handy for a variety of reasons. As well, it also means that the messenger can do neat tricks like proxy support via NSInvocation and the like.
*rewriting the stack frame can be insanely complex and expensive. Some of the arguments might be in registers some of the time, etc... All architecture dependent ABI nastiness. One of the biggest challenges to writing things like imp_implementationWithBlock() was figuring out how to do so without touching the stack because doing so would have been too slow and too bloated to be viable.
The purpose of having the second parameter contain the selector is to enable a common dispatch mechanism. As such, the method dispatch code always expects the second parameter to be the selector, and dispatches based on that, or follows the inheritance chain up, or even creates an NSInvocation and calls forwardInvocation:.
Generally, only system-level routines use the selector argument, although it's rather nice to have it when you hit an exception or are in the debugger trying to figure out what routine is giving you difficulties if you are using forwardInvocation
From the documentation:
Discussion
This data type is a pointer to the start of the function that implements the method. This function uses standard C calling conventions as implemented for the current CPU architecture. The first argument is a pointer to self (that is, the memory for the particular instance of this class, or, for a class method, a pointer to the metaclass). The second argument is the method selector. The method arguments follow.
In Objective-C when you call a method you need to know the target, the selector and the eventual arguments. Let's suppose that you are trying to do this manually: how can you know which method to call if you don't know the selector? Do you call some random method? No, you call the right method because you know the method name.
As you may be aware, blocks take -invoke:
void(^foo)() = ^{
NSLog(#"Do stuff");
};
[foo invoke]; // Logs 'Do stuff'
I would like to do the following:
void(^bar)(int) = ^(int k) {
NSLog(#"%d", k);
};
[bar invokeWithParameters:7]; // Want it to log '7', but no such instance method
The ordinary argument-less -invoke works on bar, but it prints a nonsense value.
I can't find a direct message of this kind I can send to a block, nor can I find the original documentation that would describe how blocks take -invoke.
Is there a list of messages accepted by blocks?
(Yes, I have tried to use class_copyMethodList to extract a list of methods from the runtime; there appear to be none.)
Edit: Yes, I'm also aware of invoking the block the usual way (bar(7);). What I'm really after is a selector for a method I can feed into library code that doesn't take blocks (per-se).
You can invoke it like a function:
bar(7);
There's even an example in the documentation that uses exactly the same signature. See Declaring and Using a Block.
The best reference on the behavior of blocks is the Block Language Specification(RTF) document. This mentions certain methods that are supported (copy, retain, etc.) but nothing about an -invoke method.
A blocks very definition is the sum total of "messages" that the block can receive, in terms of the calling parameters/ABI.
This is for a couple of reasons:
First, a block is not a function and a block pointer is not a function pointer. They cannot be used interchangeably.
Secondly, the C ABI is such that you have to have a declaration of the function begin called when the call site is being compiled if the parameters are to be encoded correctly.
The alternative is to use something like NSInvocation, which allows the arguments to be encoded individually, but even that still requires full C ABI knowledge for each individual argument.
Ultimately, if you can compile a call site that has all the parameters, be it an Objective-C method or a function call, to the fidelity necessary to make the compiler happy, you can convert that call site into a call to the block.
I.e. unless you clarify your question a bit, what you are asking for is either already supported or nigh impossible due to the vagaries of the C ABI.
i have singleton class , when calling one of the singleton methods more then once in the same time , and this method has local variables . does each method call of the singleton gets its own private stack , do i need to worry about sharing/mixing local variable data between calls ?
Using local variables in a class method (not important whether it is a singleton) is no different from using local variables in a regular function. The local variables will not get mixed up.
No, you do not need to worry about that. To correct your terminology: "does each method call of the singleton gets its own private stack" -- not its own stack but each method call gets its own stack frame so you are alright.
A singleton method is just the same as an ordinary function (in C++). Think of local variables in the same way.
Note that this does not apply to static local variables, which are specifically shared between method calls.
Each method will gets its own private stack. The only possibility to take care about sharing are static variables inside the class.... but as ur class is singleton that applies to the instance variables of ur class too. Local variables of the method would always be freash in the stack no need to take care about them.
I'm not sure if you're talking about recursion or multiple thread calls, so I'll assume you mean recursion.
Each time you call the method any local variables that are not declared static are allocated on the stack. The way this works is that each call has it's own stack "frame" When the call is finished, the stack frame is released (and all local variables are destroyed).
So when function foo() is called it's local variables are in a frame on the stack, let's call it frame A. If foo calls itself, another frame is added, let's call it B. During the life of this second call, both frames A and B exist, but A is essentially dormant (usually, the data in A can be modified indirectly, e.g. via pointers). When the second call exits the B frame is released and the A frame becomes active again. Finally, when the top call is finished, the A frame goes away.
Since there is a limited amount of stack space, you have to be careful not to create more frames than the stack can hold. If you do, the stack is said to "overflow".
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.
NSInvocation is just an object representation of a message send. As such, it can't invoke a specific IMP any more than a normal message send could. In order to have an invocation call a specific IMP, you'd either need to write a custom NSInvocation class that goes through the IMP-calling routine or you'd have to write a trampoline that implements the behavior and then create an invocation that represents a message to the trampoline (i.e. you basically wouldn't be using NSInvocation for much of anything).
Added long after the fact, for reference:
You can do it with private API. Put this category somewhere convenient:
#interface NSInvocation (naughty)
-(void)invokeUsingIMP:(IMP)imp;
#end
and voila, it does exactly what you'd expect. I dug up this gem from one of Mike Ash's old blog posts.
Private API tricks like this are great for research or in-house code. Just remember to excise it from your appstore-bound builds.
Given that you already have the IMP, you simply need a way to do a very raw forward of the method call to said IMP. And given that you are willing to use an NSInvocation like solution, then you could also build a similar proxy class.
If I were faced with this, I would create a simple proxying class that contained the IMP to be called and the target object (you'll need to set the self parameter). Then, I would write a trampoline function in assembly that takes the first argument, assumes it is an instance of the proxying class, grabs the self, stuffs it into the register holding argument 0, grabs the IMP and *JMPs to it as a tail call.
With trampoline in hand, you would then add that trampoline as an IMP for any selector on the proxying class that you want forwarded to a particular IMP....
To achieve any kind of generic mechanism like this, the key is to avoid anything having to do with rewriting the stack frame. Avoid the C ABI. Avoid moving arguments about.
An untested idea:
Could you use object_setClass() to force the selection of the IMP that you want? That is…
- (void)forwardInvocation:(NSInvocation *)invocation {
id target = [invocation target];
Class targetClass = classWithTheImpIWant();
Class originalClass = objc_setClass(target, targetClass);
[invocation invoke];
objc_setClass(target, originalClass);
}
I think your best choice is to use libffi. Have you seen the port to iOS at https://github.com/landonf/libffi-ios? I haven't tried the port, but i have successfully invoked IMP with arbitrary arguments on the Mac.
Have a look at JSCocoa https://github.com/parmanoir/jscocoa it includes code to help you prepare a ffi_cif structure from a Method and it also contains a version of libffi that should compile on iOS. (Haven't tested either)
You should probably have a look at how we swizzle the implementation of a certain method on an instance of an object in https://github.com/tuenti/TMInstanceMethodSwizzler
Basically, you swizzle the method for all object of a class so when its called it look up in a dictionary whats is the implementation which has to be called for the target object, falling back to the original implementation if not found.
You can also use the private invokeWithImp: method, but this is discouraged if you intent to submit the app to the store.
you could add the IMP to the class using class_addMethod under a new selector and invoke that selector.
the temporary method can't be removed though.