R..*_*R.. 20 c linux x86-64 abi variadic-functions
任何人都有参考va_list
x86_64 ABI(在Linux上使用的那个)的表示?我正在尝试调试一些代码,其中堆栈或参数似乎已损坏,这将真正有助于理解我应该看到的内容......
Sku*_*del 29
我把我的评论写进了一个答案.
这可能有所帮助.这是一个参考,虽然轻量级(编辑:原始链接死亡;替换Wayback机器保留链接).
变量参数列表参考从第50页开始,然后继续,第52-53页文档va_list
:
va_list类型
va_list类型是一个数组,其中包含一个结构的单个元素,其中包含实现va_arg宏的必要信息.va_list类型的定义在图3.34中给出
// Figure 3.34
typedef struct {
unsigned int gp_offset;
unsigned int fp_offset;
void *overflow_arg_area;
void *reg_save_area;
} va_list[1];
Run Code Online (Sandbox Code Playgroud)
va_start宏
va_start宏按如下方式初始化结构:
reg_save_area
该元素指向寄存器保存区域的开始.
over?ow_arg_area
该指针用于获取在堆栈上传递的参数.它使用堆栈上传递的第一个参数的地址进行初始化(如果有),然后始终更新以指向堆栈上下一个参数的开始.
gp_offset
该元素保存从reg_save_area到保存下一个可用通用参数寄存器的位置的偏移量(以字节为单位).如果所有参数寄存器都已用尽,则将其设置为值48(6*8).
fp_offset
该元素保存从reg_save_area到保存下一个可用浮点参数寄存器的位置的偏移量(以字节为单位).如果所有参数寄存器都已用尽,则将其设置为值304(6*8 + 16*16).
R..*_*R.. 15
事实证明问题是gcc正在制作va_list
数组类型.我的功能是签名:
void foo(va_list ap);
Run Code Online (Sandbox Code Playgroud)
我想将指针传递ap
给另一个函数,所以我做了:
void foo(va_list ap)
{
bar(&ap);
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,数组类型衰减到函数参数列表中的指针类型,因此我不是将指针传递给原始结构,而是将指针传递给指针.
要解决此问题,我将代码更改为:
void foo(va_list ap)
{
va_list ap2;
va_copy(ap2, ap);
bar(&ap2);
va_end(ap2);
}
Run Code Online (Sandbox Code Playgroud)
这是我能想到的唯一可移植解决方案,它既考虑va_list
了阵列类型的可能性,又考虑了它不是的可能性.