开发者

What happens when a method is called? Where are the arguments pushed?

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 b开发者_如何学Cecause 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜