Gnu Assembler(GAS)のCFIディレクティブは何のために使用されますか?


118

すべての行の後.CFIディレクティブがあるように思えるし、また、これらの元の広いvaritiesがあります。、 .cfi_startproc.cfi_endprocなど。 もっとここには

    .file   "temp.c"
    .text
.globl main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    movq    %rsp, %rbp
    .cfi_offset 6, -16
    .cfi_def_cfa_register 6
    movl    $0, %eax
    leave
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
.globl func
    .type   func, @function
func:
.LFB1:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    movq    %rsp, %rbp
    .cfi_offset 6, -16
    .cfi_def_cfa_register 6
    movl    %edi, -4(%rbp)
    movl    %esi, %eax
    movb    %al, -8(%rbp)
    leave
    ret
    .cfi_endproc
.LFE1:
    .size   func, .-func
    .ident  "GCC: (Ubuntu 4.4.1-4ubuntu9) 4.4.1"
    .section    .note.GNU-stack,"",@progbits

これらの目的がわかりませんでした。


3
ここcfi指示の説明GNU AS
Paschalis

関連:GCC / clangアセンブリの出力から「ノイズ」を取り除く方法は?、ディレクティブなしの命令だけが必要な場合。良い方法は、コードをgcc.godbolt.orgに配置して、さまざまなコンパイラ(x86以外を含む)のさまざまなバージョンからの素晴らしいフィルター処理されたasm出力を表示し、ソース行をasmブロックと一致させるために色で強調表示することです。
Peter Cordes 2017年

回答:


70

私はそれがCall Frame Informationの略で、呼び出しフレームを管理するためのGNU AS拡張機能だと感じています。DeveloperWorksから:

一部のアーキテクチャでは、例外処理はCall Frame Informationディレクティブで管理する必要があります。これらのディレクティブは、例外処理を指示するためにアセンブリで使用されます。これらのディレクティブは、何らかの理由(コードベースの移植性など)でGCCが生成した例外処理情報が十分でない場合に、Linux on POWERで使用できます。

これらは、例外処理の必要性に応じて、一部のプラットフォームで生成されるようです。

これらを無効にする場合は、Davidの回答をご覧ください。


5
また、.LFB0、.LFB1、.LFE0、.LFE1について一言

@claws-これらはコンパイラによって生成されたラベルです(から確認できます:)。stackoverflow.com/a/15285058/4294399を
Calculuswhiz

144

これらを無効にするには、gccオプションを使用します

-fno-asynchronous-unwind-tables

-fno-dwarf2-cfi-asm また必要になるかもしれません。


12
-fno-dwarf2-cfi-asmまた、必要となる場合があります
テクノサウルス2016年

人間が読めるasm出力で無効にする場合は、GCC / clangアセンブリ出力から「ノイズ」を削除する方法を参照してください他の便利なオプションやトリックについて。
Peter Cordes

30

CFIディレクティブはデバッグに使用されます。デバッガーがスタックを巻き戻すことができます。たとえば、プロシージャAがプロシージャBを呼び出し、次にプロシージャBが共通プロシージャCを呼び出した場合、プロシージャCは失敗します。次に、実際にCを呼び出した人物を知りたい場合、次にBを呼び出した人物を知りたい場合があります。

デバッガーは、スタックポインター(%rsp)を使用してこのスタックを巻き戻し、%rbpを登録できますが、それらを見つける方法を知っている必要があります。これがCFIディレクティブの出番です。

movq    %rsp, %rbp
.cfi_def_cfa_register 6

したがって、ここの最後の行は、「コールフレームアドレス」がレジスタ6(%rbp)にあることを示しています


2
しかし、cfiの例外処理の使用は、デバッグより頻繁である必要があると思います。
osgx 2014年

6
実際、CFAは「正規フレームアドレス」の略です。こちらをご覧ください
キャメロン


1
CFIディレクティブを使用すると-fomit-frame-pointer、RBP(gccまたはclang以降ではデフォルトでオンになっています)の代わりに、でコンパイルされたコードでもスタックを巻き戻すことができます-O1。これは、C ++例外処理やデバッガー/プロファイラーで使用されます。従来のRBPフレームポインターを使用するコードは、現在のRBP値は常に保存されたRBP値を指し、リンクされたリストを形成する前の値を指します。その場合、CFIは必要ありません。(フレームポインターを使用する関数では、CFI cfa_registerを使用すると、表示されているように、RSPを変更するたびにメタデータを追加する必要がなくなります。)
Peter Cordes

2

これらを無効にする-fno-exceptionsには、-fno-asynchronous-unwind-tables例外を使用しない限り、g ++は前述のとともに必要です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.