拆解c程序时神秘的printf参数

时间:2015-05-16 15:04:16

标签: c assembly stack printf

所以我有这个c代码:

#include <stdio.h>

int main(void)
{
    int a;
    int b;
    int c;

    a=b=c=5;

    printf("Hi%d%d%dHi",a,b,c);
}

我用ubuntu编译了它:

gcc program.c -o program -ggdb -m32 -O2

然后将其拆解:

objdump -M intel program -d

在main printf()中调用如下:

mov    DWORD PTR [esp+0x10],0x5
mov    DWORD PTR [esp+0xc],0x5
mov    DWORD PTR [esp+0x8],0x5
mov    DWORD PTR [esp+0x4],0x8048500
mov    DWORD PTR [esp],0x1
call   8048330 <__printf_chk@plt>

我现在想知道的是这意味着什么:

mov    DWORD PTR [esp],0x1

我知道前4个mov指令的用途,但我无法弄清楚为什么'1'会被压入堆栈。此外,只有在打开优化时才会出现此mov。有什么想法吗?

1 个答案:

答案 0 :(得分:5)

如果您(或编译器)定义__printf_chk并启用了优化,则GNU C库(glibc)将使用printf而不是_FORTIFY_SOURCE。该函数的_chk版本的行为就像它替换的函数一样,除了它应该check for stack overflow并且可能验证参数。额外的第一个参数表示应该进行多少检查和验证。

看看actual glibc implmenation它似乎没有对编译器自动提供的内容进行任何额外的堆栈检查(因此不需要),并且参数的验证非常少。它将检查%n是否仅出现在只读格式字符串上,并检查是否使用了特殊的%m$参数说明符,它们用于所有参数而没有任何间隙。