Last Update 2021/01/05
-fno-builtinオプション
接頭辞が __builtin_ で始まらない組み込み関数の認識を無効化
テスト概要
接頭辞が __builtin_ で始まる関数と始まらない関数を含むコードのコンパイルを実行
-fno-builtinの有無による生成されたバイナリファイルの内容を比較
-fno-builtinの有無による生成されたバイナリファイルの内容を比較
実行環境
GCC-8.2.0
GNU C Library 2.28
GNU Binutils 2.31.1
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;
}
-fno-builtinオプション無しでコンパイル
コンパイル実行
$ 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/ccZlfzQL.o /tmp/ccT6YGtG.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)
︙
-fno-builtinオプションを使用してコンパイル
コンパイル実行
$ gcc -v -g -Wall -fno-builtin 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 ...
︙
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/ccgpiVi0.o /tmp/ccestti4.s
︙
/usr/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/collect2 ...
COLLECT_GCC_OPTIONS='-v' '-g' '-Wall' '-fno-builtin' '-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 <abs@plt>:
401040: ff 25 da 2f 00 00 jmpq *0x2fda(%rip) # 404020 <abs@GLIBC_2.2.5>
401046: 68 01 00 00 00 pushq $0x1
40104b: e9 d0 ff ff ff jmpq 401020 <.plt>
0000000000401050 <printf@plt>:
401050: ff 25 d2 2f 00 00 jmpq *0x2fd2(%rip) # 404028 <printf@GLIBC_2.2.5>
401056: 68 02 00 00 00 pushq $0x2
40105b: e9 c0 ff ff ff jmpq 401020 <.plt>
︙
0000000000401132 <main>:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
401132: 55 push %rbp
401133: 48 89 e5 mov %rsp,%rbp
printf("printf[1]\n");
401136: bf 04 20 40 00 mov $0x402004,%edi
40113b: b8 00 00 00 00 mov $0x0,%eax
401140: e8 0b ff ff ff callq 401050 <printf@plt>
1引数のprintfが組み込み関数と認識されずにprintfの呼び出し
printf("printf[2] %d\n",1);
401145: be 01 00 00 00 mov $0x1,%esi
40114a: bf 0f 20 40 00 mov $0x40200f,%edi
40114f: b8 00 00 00 00 mov $0x0,%eax
401154: e8 f7 fe ff ff callq 401050 <printf@plt>
__builtin_printf("__builtin_printf\n");
401159: bf 1d 20 40 00 mov $0x40201d,%edi
40115e: e8 cd fe ff ff callq 401030 <puts@plt>
__builtin_で始まるprintfは組み込み関数と認識されputsで置き換え
printf("abs %d\n", abs(-1));
401163: bf ff ff ff ff mov $0xffffffff,%edi
401168: e8 d3 fe ff ff callq 401040 <abs@plt> <printf@plt>
組み込み関数と認識されずにabsの呼び出し
40116d: 89 c6 mov %eax,%esi
40116f: bf 2e 20 40 00 mov $0x40202e,%edi
401174: b8 00 00 00 00 mov $0x0,%eax
401179: e8 d2 fe ff ff callq 401050 <printf@plt>
printf("__builtin_abs %d\n", __builtin_abs(-2));
40117e: be 02 00 00 00 mov $0x2,%esi <puts@plt>
__builtin_で始まるabsは組み込み関数と認識されコンパイラにより事前演算
401183: bf 36 20 40 00 mov $0x402036,%edi
401188: b8 00 00 00 00 mov $0x0,%eax
40118d: e8 be fe ff ff callq 401050 <printf@plt>
return 0;
401192: b8 00 00 00 00 mov $0x0,%eax
}
401197: 5d pop %rbp
401198: c3 retq
401199: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
︙