Last Update 2021/01/15
-fno-builtin-関数
関数で指定した接頭辞が __builtin_ で始まらない組み込み関数の認識を無効化
テスト概要
printf関数と__builtin_printf関数を含むコードのコンパイルを実行
-fno-builtin-printfの有無による生成されたバイナリファイルの内容を比較
-fno-builtin-printfの有無による生成されたバイナリファイルの内容を比較
実行環境
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-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)
︙
-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)
︙