2

独自のコンパイラで作成した asm プログラムがいくつかありますが、それらを実行したい場合、最後にセグメンテーション違反が発生します。すべての命令は思い通りに実行されますが、実行はセグメンテーション違反で終了します。

segfault を確認するために gdb を使用しようとすると、常に次の行で発生しているように見えます: 0x11ee90 <_dl_debug_state> push %ebp>

この行が何であるかさえわかりません。まず、セグメンテーション違反の原因となるのを防ぐ方法です。

これがその種のプログラムの例です:

    file    "test_appel.c"
    .text                
.globl f  
    .type f, @function  
f:                        
    pushl   %ebp                     
    movl    %esp,   %ebp               
    subl    $16,    %esp
    movl    8(%ebp), %eax 
    pushl   %eax                        
    movl    12(%ebp), %eax 
    popl    %ecx          
    imull   %ecx,   %eax  
    movl    %eax,   16(%ebp) 
    movl    16(%ebp), %eax 
    leave
    ret         
    .section    .rodata
.LC0:
    .string "appel à fonction pour la multiplication\n"
.LC1:
    .string "resultat 2 * 3 = %d\n"
    .text                
.globl main  
    .type main, @function  
main:                        
    pushl   %ebp                     
    movl    %esp,   %ebp               
    andl    $-16,   %esp  
    subl    $32,    %esp
    movl    $2, %eax 
    movl    %eax,   8(%ebp) 
    movl    $3, %eax 
    movl    %eax,   12(%ebp) 
    movl    12(%ebp), %eax 
    movl    %eax    ,4(%esp) 
    movl    8(%ebp), %eax 
    movl    %eax    ,0(%esp) 
    call    f
    movl    %eax,   4(%ebp) 
    movl    4(%esp),    %eax    
    movl    (%esp), %ecx     
    pushl   %eax             
    pushl   %ecx             
    movl     $.LC0, %eax 
    movl    %eax,   (%esp)  
    call    printf         
    popl    %ecx             
    popl    %eax             
    movl    %eax,   4(%esp)   
    movl    %ecx,   (%esp)    
    movl    4(%esp),%eax      
    movl    (%esp), %ecx     
    pushl   %eax             
    pushl   %ecx             
    movl    4(%ebp), %eax 
    movl    %eax,   %edx
    movl    %edx,   4(%esp)                    
    movl    $.LC1,  (%esp)  
    call    printf                            
    popl    %ecx             
    popl    %eax             
    movl    %eax,   4(%esp)   
    movl    %ecx,   (%esp)    
    leave
    ret  
4

3 に答える 3

2

segfault、それは常に次の行で発生するようです:0x11ee90 <_dl_debug_state> push %ebp>

これは、スタックが破損しているか、使い果たされていることを意味します。

実際、あなたのコンパイラは、スタック全体を破壊するコードを出力しているように見えます。特に、これらの指示:

movl    %eax,   8(%ebp)
...
movl    %eax,   12(%ebp) 

呼び出し元(libc の一部) のローカル変数が破損しているため、復帰後にクラッシュが発生してもまったく驚くことではありませんmain

あなたはおそらく発行するつもりでした:movl %eax, -8(%ebp)movl %eax, -12(%ebp).

于 2012-05-19T21:30:55.037 に答える
0

when i try to use gdb in order to look at the segfault, it appears that it always occurs at the line : 0x11ee90 <_dl_debug_state> push %ebp>

セグメンテーション違反は、関数呼び出し中にベース ポインター :%ebpがスタックにプッシュされているときに発生しています。これは、以前に発生したスタック破損の影響のようです。

GDB からの完全なスタック トレースもアドレス空間情報も共有していません。

gdb では、セグ フォールトが発生するdisassembleと、詳細情報を取得するためにa を実行し、btこれに到達するために呼び出されているすべての関数を取得するためにも実行します。

于 2012-05-19T21:30:17.283 に答える
0

問題は、リターン命令を破損していることです。ご存知のように、ebp + 4 には常に、呼び出された関数の実行後にコントロールがジャンプするリターン命令アドレスが含まれます。あなたの場合、次のようなステートメントがあります。

       movl    %eax,   4(%ebp)

'f()' の戻り値を ebp+4 に書き込んでいるため、戻り命令アドレスが破損しています。このステートメントを削除すると、セグメンテーション違反は発生しません。

于 2012-05-21T14:48:54.337 に答える