0

RTL 形式の gcc の制御フロー グラフ ダンプを取得し、graphviz を使用して視覚化しました。ただし、どのジャンプ/コールが直接的でどれが間接的かはまだ不明です。それらを互いに区別するための提案はありますか?

4

1 に答える 1

2

コンパイラは呼び出し先を正確に認識しているため、直接呼び出しには通常、RTL の一部としてsymbol_refが含まれます。間接呼び出しの場合、1 つ以上のレジスターを使用したメモリー参照がありますが、シンボルが存在しません。したがって、メモリ RTL サブ式は、mov 命令で見られる標準のメモリ読み取りおよび書き込み形式に似ています。

たとえば、Linux カーネル 3.19の関数do_early_param内の最初の呼び出し命令は直接呼び出しです。

callq  ffffffffc1657839 <strcmp>

それぞれのRTLは

(call_insn/i:TI 19 18 134 4 (set (reg:SI 0 ax)                          
    (call (mem:QI (symbol_ref:DI ("strcmp") [flags 0x41] <function_decl 0x2b2f6f0e1a00 strcmp>) [0 __builtin_strcmp S1 A8])
        (const_int 0 [0]))) init/main.c:436 631 {*call_value}               
 (expr_list:REG_DEAD (reg:DI 5 di)                                          
    (expr_list:REG_DEAD (reg:DI 4 si)                                       
        (expr_list:REG_EH_REGION (const_int 0 [0])                          
            (nil))))                                                        
(expr_list:REG_FRAME_RELATED_EXPR (use (reg:DI 5 di))                       
    (expr_list:REG_FRAME_RELATED_EXPR (use (reg:DI 4 si))                   
        (nil))))

後で、間接呼び出しがあります。

 callq  *0x8(%rbx)

に変換されます

  (call_insn:TI 38 37 140 7 (set (reg:SI 0 ax)                            
        (call (mem:QI (mem/f:DI (plus:DI (reg/v/f:DI 3 bx [orig:60 p ] [60])    
                        (const_int 8 [0x8])) [0 MEM[base: p_1, offset: 8B]+0 S8 A64]) [0 *D.45869_10 S1 A8]) 
            (const_int 0 [0]))) init/main.c:439 631 {*call_value}               
     (expr_list:REG_DEAD (reg:DI 5 di)                                          
        (nil))                                                                  
    (expr_list:REG_FRAME_RELATED_EXPR (use (reg:DI 5 di))                       
        (nil)))

(symbol_ref なし)。JMP 命令の場合、間接 JMP は実際にはテール コールであり、RTL で CALL_P 命令として表示される可能性があることに注意してください。たとえば、関数mtrr_bp_initでは、

 jmpq   *%rax

RTLではどれが

 (call_insn/j:TI 144 143 145 25 (call (mem:QI (reg/f:DI 0 ax [orig:151 mtrr_if.32_31->set_all ] [151]) [0 *D.30602_32 S1 A8])
        (const_int 0 [0])) arch/x86/kernel/cpu/mtrr/main.c:744 623 {*sibcall}   
     (expr_list:REG_DEAD (reg/f:DI 0 ax [orig:151 mtrr_if.32_31->set_all ] [151])
        (nil))                                                                  
    (nil))

それ以外では、通常、間接 jmp は PARALLEL RTL 式として表示されます。たとえば、関数update_mp_table内では、次のように表示されます。

jmpq   *-0x3eff7188(,%rax,8)

RTLでは次のとおりです。

    (jump_insn:TI 173 170 174 22 (parallel [                              
            (set (pc)                                                           
                (mem/u/c:DI (plus:DI (mult:DI (reg:DI 0 ax [orig:182 *mpt_138 ] [182])
                            (const_int 8 [0x8]))                                
                        (label_ref:DI 175)) [0 S8 A8]))                         
            (use (label_ref 175))                                               
        ]) arch/x86/kernel/mpparse.c:741 613 {*tablejump_1}                     
     (expr_list:REG_DEAD (reg:DI 0 ax [orig:182 *mpt_138 ] [182])               
        (insn_list:REG_LABEL_OPERAND 175 (nil)))                                
 -> 175)
于 2015-09-28T18:33:41.713 に答える