0

次の C コードを GCC でコンパイルし、gdb でアセンブリに逆アセンブルしました。64 ビット Intel i5 プロセッサを搭載した Macbook Pro を使用しています。「main()」では、「char* name[2]」に 2 つの char ポインターがあり、スタック ポインターを 2 ワード (16 バイト) 減らす必要がありますか? ただし、gdbで逆アセンブルすると、20減少します...誰かが私を理解するのを助けることができますか? C コード:

#include <stdio.h>
#include <unistd.h>
int main(void)
{   
    char* name[2];
    name[0] = "/bin/sh";
    name[1]= NULL;
    execve(name[0],name,NULL);
}

gdb 逆アセンブル コード:

GNU gdb 6.3.50-20050815 (Apple version gdb-1708) (Thu Nov  3 21:59:02 UTC 2011)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin"...Reading symbols for shared libraries .. done

(gdb) disassemble main
Dump of assembler code for function main:
0x0000000100000ee0 <main+0>:    push   %rbp
0x0000000100000ee1 <main+1>:    mov    %rsp,%rbp
0x0000000100000ee4 <main+4>:    sub    $0x20,%rsp
0x0000000100000ee8 <main+8>:    lea    -0x18(%rbp),%rax
0x0000000100000eec <main+12>:   lea    0x61(%rip),%rcx        # 0x100000f54
0x0000000100000ef3 <main+19>:   mov    %rcx,-0x18(%rbp)
0x0000000100000ef7 <main+23>:   movq   $0x0,-0x10(%rbp)
0x0000000100000eff <main+31>:   mov    -0x18(%rbp),%rcx
0x0000000100000f03 <main+35>:   mov    $0x0,%rdx
0x0000000100000f0d <main+45>:   mov    %rcx,%rdi
0x0000000100000f10 <main+48>:   mov    %rax,%rsi
0x0000000100000f13 <main+51>:   callq  0x100000f22 <dyld_stub_execve>
0x0000000100000f18 <main+56>:   mov    -0x4(%rbp),%eax
0x0000000100000f1b <main+59>:   add    $0x20,%rsp
0x0000000100000f1f <main+63>:   pop    %rbp
0x0000000100000f20 <main+64>:   retq   
End of assembler dump.
4

3 に答える 3

4

したがって、アセンブリを読み取ると、name[0] はスタックの -0x18 にあり、name 1は -0x10 にあります。また、前述のとおり、戻り値には -0x4 が使用されます。

0x20 は実際には 32 であるため、12 バイトが残ります。範囲は -32 から -24 で、範囲は -8 から -4 です。-8 から -4 は間違いなくアラインメントであり、-32 から -24 も (16 バイト アラインメントの場合) であると推測します。

編集:実際には 48 バイトが差し引かれることに注意してください。main を呼び出す callq 命令は、RSP から 8 バイトを減算し、push %rbpさらに 8 バイトを減算します。

検証済みの 16 バイト アラインメント: x86-64 System V ABIセクション 3.2.2 (旧バージョンの PDF への直接リンク)

于 2012-11-04T21:24:51.160 に答える
1

この「奇妙な」スタックフレーム形式は、呼び出しの場合に明らかに使用される「遅延バインディング」呼び出し規約と関係があると思います。dyld_stub_execveつまり、実際には、それ自体ではなく、遅延バインディング stub を呼び出していexecveます。呼び出し後に読み取られる結果コード-0x4(%rbp)は、バインドが失敗した場合に返されるエラー コードである可能性があります。

ライブラリを静的にリンクすると、呼び出し用に用意されたスタック フレームがより従来型に見えると思います。

PS私の答えはおそらく純粋なナンセンスです.スタックフレーム形成コードは適切なコンパイル中に生成されますが、静的ライブラリまたは共有ライブラリを使用するかどうかの決定はリンク時にのみ行われます.

于 2012-11-04T21:16:14.893 に答える
0

行について話している場合<main+4>、20 を引いているわけではありません (基数 10)。基数 16 で 20 を引いてい16^1 * 2 + 16^0 * 0ます。これは 32、つまり 2 単語のサイズです。

于 2012-11-04T21:17:05.120 に答える