Loose-Info.com
Last Update 2021/01/15
TOP - 各種テスト - gcc - -fno-builtin-関数

-fno-builtin-関数
関数で指定した接頭辞が __builtin_ で始まらない組み込み関数の認識を無効化

テスト概要

printf関数と__builtin_printf関数を含むコードのコンパイルを実行
-fno-builtin-printfの有無による生成されたバイナリファイルの内容を比較

実行環境

GCC-8.2.0
GNU C Library 2.28
GNU Binutils 2.31.1


コード例・出力内容中の表記

・実行例中の太字表記部分は、コマンドなどの入力された文字列を示します。
・「」や「...」の着色省略表記は、 実際のソースコードや出力内容などを省略加工した部分を示します。
・出力例中の赤字のコメントは必要に応じて、改行した上で挿入しています。

使用ファイル


main.c
/* -fno-builtin-関数 オプション動作確認用ソースファイル */ #include <stdio.h> #include <stdlib.h> int main(void) { printf("printf[1]\n"); printf("printf[2] %d\n",1); __builtin_printf("__builtin_printf\n"); printf("abs %d\n", abs(-1)); printf("__builtin_abs %d\n", __builtin_abs(-2)); return 0; }

その1

-fno-builtin-printfオプション無しでコンパイル

コンパイル実行
$ gcc -v -g -Wall main.c <--- デバッグ情報生成のため-gオプションを付加 Using built-in specs. /usr/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/cc1 -quiet -v main.c ... GNU C17 (GCC) version 8.2.0 (x86_64-pc-linux-gnu) compiled by GNU C version 8.2.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version none as -v --64 -o /tmp/ccpVAalN.o /tmp/cc59ZXCW.s /usr/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/collect2 ... COLLECT_GCC_OPTIONS='-v' '-g' '-Wall' '-mtune=generic' '-march=x86-64' $ ./a.out printf[1] printf[2] 1 __builtin_printf abs 1 __builtin_abs 2 $ objdump -S -d a.out <--- objdumpで実行形式ファイルを逆アセンブル a.out: file format elf64-x86-64 Disassembly of section .plt: 0000000000401020 <.plt>: 401020: ff 35 e2 2f 00 00 pushq 0x2fe2(%rip) # 404008 <_GLOBAL_OFFSET_TABLE_+0x8> 401026: ff 25 e4 2f 00 00 jmpq *0x2fe4(%rip) # 404010 <_GLOBAL_OFFSET_TABLE_+0x10> 40102c: 0f 1f 40 00 nopl 0x0(%rax) 0000000000401030 <puts@plt>: <--- ソースファイル中に記述のないputs 401030: ff 25 e2 2f 00 00 jmpq *0x2fe2(%rip) # 404018 <puts@GLIBC_2.2.5> 401036: 68 00 00 00 00 pushq $0x0 40103b: e9 e0 ff ff ff jmpq 401020 <.plt> 0000000000401040 <printf@plt>: 401040: ff 25 da 2f 00 00 jmpq *0x2fda(%rip) # 404020 <printf@GLIBC_2.2.5> 401046: 68 01 00 00 00 pushq $0x1 40104b: e9 d0 ff ff ff jmpq 401020 <.plt> pltセクション内にabsの記述は無し 0000000000401122 <main>: #include <stdio.h> #include <stdlib.h> int main(void) { 401122: 55 push %rbp 401123: 48 89 e5 mov %rsp,%rbp printf("printf[1]\n"); 401126: bf 04 20 40 00 mov $0x402004,%edi 40112b: e8 00 ff ff ff callq 401030 <puts@plt> 1引数のprintfはputsに書き換え発生 printf("printf[2] %d\n",1); 401130: be 01 00 00 00 mov $0x1,%esi 401135: bf 0e 20 40 00 mov $0x40200e,%edi 40113a: b8 00 00 00 00 mov $0x0,%eax 40113f: e8 fc fe ff ff callq 401040 <printf@plt> 2引数はprintfの呼び出し __builtin_printf("__builtin_printf\n"); 401144: bf 1c 20 40 00 mov $0x40201c,%edi 401149: e8 e2 fe ff ff callq 401030 <puts@plt> __builtin_で始まるprintfは組み込み関数と認識されputsで置き換え printf("abs %d\n", abs(-1)); 40114e: be 01 00 00 00 mov $0x1,%esi abs関数ではなくコンパイラによる事前演算 401153: bf 2d 20 40 00 mov $0x40202d,%edi 401158: b8 00 00 00 00 mov $0x0,%eax 40115d: e8 de fe ff ff callq 401040 <printf@plt> printf("__builtin_abs %d\n", __builtin_abs(-2)); 401162: be 02 00 00 00 mov $0x2,%esi __builtin_で始まるabsは組み込み関数と認識されコンパイラにより事前演算 401167: bf 35 20 40 00 mov $0x402035,%edi 40116c: b8 00 00 00 00 mov $0x0,%eax 401171: e8 ca fe ff ff callq 401040 <printf@plt> return 0; 401176: b8 00 00 00 00 mov $0x0,%eax } 40117b: 5d pop %rbp 40117c: c3 retq 40117d: 0f 1f 00 nopl (%rax)

その2

-fno-builtin-printfオプションを使用してコンパイル

コンパイル実行
$ gcc -v -g -Wall -fno-builtin-printf main.c <--- デバッグ情報生成のため-gオプションを付加 Using built-in specs. /usr/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/cc1 -quiet -v main.c ... -fno-builtin-printf ... GNU C17 (GCC) version 8.2.0 (x86_64-pc-linux-gnu) compiled by GNU C version 8.2.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version none as -v --64 -o /tmp/ccDcoALi.o /tmp/ccPaSbVw.s /usr/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/collect2 ... COLLECT_GCC_OPTIONS='-v' '-g' '-Wall' '-fno-builtin-printf' '-mtune=generic' '-march=x86-64' $ ./a.out printf[1] printf[2] 1 __builtin_printf abs 1 __builtin_abs 2 $ objdump -S -d a.out <--- objdumpで実行形式ファイルを逆アセンブル a.out: file format elf64-x86-64 Disassembly of section .plt: 0000000000401020 <.plt>: 401020: ff 35 e2 2f 00 00 pushq 0x2fe2(%rip) # 404008 <_GLOBAL_OFFSET_TABLE_+0x8> 401026: ff 25 e4 2f 00 00 jmpq *0x2fe4(%rip) # 404010 <_GLOBAL_OFFSET_TABLE_+0x10> 40102c: 0f 1f 40 00 nopl 0x0(%rax) 0000000000401030 <puts@plt>: <--- ソースファイル中に記述のないputs 401030: ff 25 e2 2f 00 00 jmpq *0x2fe2(%rip) # 404018 <puts@GLIBC_2.2.5> 401036: 68 00 00 00 00 pushq $0x0 40103b: e9 e0 ff ff ff jmpq 401020 <.plt> 0000000000401040 <printf@plt>: 401040: ff 25 da 2f 00 00 jmpq *0x2fda(%rip) # 404020 <printf@GLIBC_2.2.5> 401046: 68 01 00 00 00 pushq $0x1 40104b: e9 d0 ff ff ff jmpq 401020 <.plt> pltセクション内にabsの記述は無し 0000000000401122 <main>: #include <stdio.h> #include <stdlib.h> int main(void) { 401122: 55 push %rbp 401123: 48 89 e5 mov %rsp,%rbp printf("printf[1]\n"); 401126: bf 04 20 40 00 mov $0x402004,%edi 40112b: b8 00 00 00 00 mov $0x0,%eax 401130: e8 0b ff ff ff callq 401040 <printf@plt> 1引数のprintfが組み込み関数と認識されずにprintfの呼び出し printf("printf[2] %d\n",1); 401135: be 01 00 00 00 mov $0x1,%esi 40113a: bf 0f 20 40 00 mov $0x40200f,%edi 40113f: b8 00 00 00 00 mov $0x0,%eax 401144: e8 f7 fe ff ff callq 401040 <printf@plt> __builtin_printf("__builtin_printf\n"); 401149: bf 1d 20 40 00 mov $0x40201d,%edi 40114e: e8 dd fe ff ff callq 401030 <puts@plt> __builtin_で始まるprintfは組み込み関数と認識されputsで置き換え printf("abs %d\n", abs(-1)); 401153: be 01 00 00 00 mov $0x1,%esi abs関数ではなくコンパイラによる事前演算 401158: bf 2e 20 40 00 mov $0x40202e,%edi 40115d: b8 00 00 00 00 mov $0x0,%eax 401162: e8 d9 fe ff ff callq 401040 <printf@plt> printf("__builtin_abs %d\n", __builtin_abs(-2)); 401167: be 02 00 00 00 mov $0x2,%esi __builtin_で始まるabsは組み込み関数と認識されコンパイラにより事前演算 40116c: bf 36 20 40 00 mov $0x402036,%edi 401171: b8 00 00 00 00 mov $0x0,%eax 401176: e8 c5 fe ff ff callq 401040 <printf@plt> return 0; 40117b: b8 00 00 00 00 mov $0x0,%eax } 401180: 5d pop %rbp 401181: c3 retq 401182: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 401189: 00 00 00 40118c: 0f 1f 40 00 nopl 0x0(%rax)