在<<stacktrace如何实现>>的最后介绍stacktrace的时候,是x86 calling convention决定了ebp/esp(base pointer/stack pointer)的使用,通过ebp/esp得到backtrace. 下图是一个概况:
gcc x86 calling convention也规定了参数如何传递
1. 32bit规定,函数参数存放在stack上,第一个参数在stack的地址最小,最后一个参数的地址最大。第一个参数紧跟在函数返回地址后面。如上图中的ret eip; arg 1; arg 2.
后来有了个fastcall
的attribute,可以把前两个参数放在register(ecx/edx)上传递,其他的通过stack传递。
The relevant attribute is __attribute__((fastcall))
. Functions declared with this attribute are called with their first eligible argument in ECX and the second in EDX.
GCC passes arguments on stack in your case because the Linux-x86 ABI specifies that. With the fastcall function attribute you can change that, which of course breaks the ABI and causes all kinds of problems due to that.
A solution could be to swith to x86-64, where the ABI specifies that (some) arguments are passed by registers. Or if you like bleeding edge stuff, the newish x32 ABI is similar to the x86-64 ABI but with 32-bit pointers.
2. x86_64规定,参数可以通过registers传递。可用的registers比较多。
更多的内容可以参考链接的文章<Calling conventionsfor different C++ compilers and operating systems>,里面有一节介绍calling convention。
整个系列的文章<Software optimization resources>
参考:
1. https://stackoverflow.com/questions/11575502/make-gcc-pass-the-arguments-by-register