Swizzling a method with variable arguments and forward the message - Bad Access

旧巷老猫 提交于 2019-12-04 07:19:43

The main problem here is how the variable arguments are passed to the function.

Usually, they are passed on the stack, but as far as I know, it's not the case with the ARM ABI, where registers are used, at least when possible.

So you've got two issues here.
First, the compiler may mess up those registers, while executing the code of your own method.
I'm not sure about this, as I don't know much about the ARM ABI, so you should check in the reference.

Second issue, more important, you are actually passing a single variable argument to obj_msgSend (the va_list). So the target method won't receive what it expects, obviously.

Imagine the following:

void bar( int x, ... )
{}

void foo( void )
{
    bar( 1, 2, 3, 4 );
}

On ARM, this will mean, for the foo function:

movs    r0, #1
movt    r0, #0
movs    r1, #2
movt    r1, #0
movs    r2, #3
movt    r2, #0
movs    r3, #4
movt    r3, #0
bl      _bar

Variables arguments are passed in R1, R2 and R3, and the int argument in R0.

So in your case, as a call to objc_msdSend was used to call your method, R0 should be the target object's pointer, R1 the selector's pointer, and variable arguments should begin on R2.

And when issuing your own call to objc_msdSend, you're at least overwriting the content of R2, with your va_list.

You should try not to care about the variable arguments. With a little luck, if the code previous to the objc_msgSend call (where you get the final selector) doesn't mess up those registers, the correct values should still be there, making them available for the target method.

This would of course only work on the real device, and not in the simulator (simulator is x86, so variadic parameters are here passed on the stack).

Unfortunately, no. This is why functions which take variable arguments should provide identical implementations which take va_lists. APIs which provided this functionality (e.g. objc_msgSendv) have been marked 'Unavailable" since ObjC 2. Perhaps it would also be good to figure out why this functionality was removed.

Variadic Macros would often solve the issue, but not in your case because you need a function pointer to swizzle.

So I think you will need to look to your system implementation to understand the mechanics of the VA List on your targeted implementations.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!