因为在c中,函数调用的环境是由编译器创建的,语言本身除了提供形式上的调用关系之外,并不提供对函数调用栈的访问,如果想对堆栈进行结构化的解释,需要编译器提供支持,gcc提供了访问堆栈的扩展接口,它们包括__builtin_apply_args(),
__builtin_apply()和
__builtin_return
()几个主要的函数,gcc扩展的这类函数可以帮助我们hack进函数调用的内部,做到单靠C语言本身完不成的工作。下面分析一下MIPS, ARM, X86和RISCV,Xtensa五种架构下,__builtin_apply_args对参数帧的构造和hack参数的方式.
MIPS
从图中可以看到,__builtin_apply_args()构造了两个参数帧结构,所以,可以有两种方式构造栈帧
void hack1(long a, long b, long c, long d, long e, long f)
{
......
unsigned long **v0 = (unsigned long **)__builtin_apply_args();
para0 = v[1];
para1 = v[2];
para2 = v[3];
para3 = v[4];
para4 = v[0][4];
para5 = v[0][5];
......
}
void hack2(long a, long b,