__printf_chkが使用される条件に関する調査

# TL;DR
[LD_PRELOADでprintfを後から差し替える - Qiita](http://qiita.com/koara-local/items/d5205f94decade3ffbf1)
上の記事の検証の際に、 `printf` が `__printf_chk` に代わるケースが有ったので条件を調査した。

結論からすると、 `-D_FORTIFY_SOURCE=2` が指定されている際に差し替わることがわかった。
`_FORTIFY_SOURCE` については以下などを参照してください。
[Man page of FEATURE_TEST_MACROS](https://linuxjm.osdn.jp/html/LDP_man-pages/man7/feature_test_macros.7.html)

# 調査内容
`-D_FORTIFY_SOURCE=2` のある場合とない場合を確認する。

```shell-session:オプションなし
$ gcc -O1 print.c 
$ nm ./a.out 
0000000000600820 d _DYNAMIC
00000000006009f8 d _GLOBAL_OFFSET_TABLE_
0000000000400700 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w _Jv_RegisterClasses
0000000000400800 r __FRAME_END__
0000000000600818 d __JCR_END__
0000000000600818 d __JCR_LIST__
0000000000600a40 A __TMC_END__
0000000000600a3c A __bss_start
0000000000600a38 D __data_start
00000000004005b0 t __do_global_dtors_aux
0000000000600810 t __do_global_dtors_aux_fini_array_entry
0000000000400708 R __dso_handle
0000000000600808 t __frame_dummy_init_array_entry
                 w __gmon_start__
0000000000600810 t __init_array_end
0000000000600808 t __init_array_start
00000000004006f0 T __libc_csu_fini
0000000000400660 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
0000000000600a3c A _edata
0000000000600a50 A _end
00000000004006f4 T _fini
0000000000400478 T _init
00000000004004f0 T _start
000000000040051c t call_gmon_start
0000000000600a48 b completed.6108
0000000000600a38 W data_start
0000000000400540 t deregister_tm_clones
                 U fprintf@@GLIBC_2.2.5          # 変化なし
00000000004005d0 t frame_dummy
                 U fwrite@@GLIBC_2.2.5
00000000004005fc T main
                 U printf@@GLIBC_2.2.5           # 変化なし 
                 U puts@@GLIBC_2.2.5
0000000000400570 t register_tm_clones
0000000000600a40 B stdout@@GLIBC_2.2.5
```

```shell-session:_FORTIFY_SOURCE=2
$ gcc -D_FORTIFY_SOURCE=2 -O1 print.c 
$ nm ./a.out 
0000000000600860 d _DYNAMIC
0000000000600a38 d _GLOBAL_OFFSET_TABLE_
0000000000400740 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w _Jv_RegisterClasses
0000000000400840 r __FRAME_END__
0000000000600858 d __JCR_END__
0000000000600858 d __JCR_LIST__
0000000000600a80 A __TMC_END__
0000000000600a7c A __bss_start
0000000000600a78 D __data_start
00000000004005e0 t __do_global_dtors_aux
0000000000600850 t __do_global_dtors_aux_fini_array_entry
0000000000400748 R __dso_handle
                 U __fprintf_chk@@GLIBC_2.3.4                #__fprintf_chkに変化
0000000000600848 t __frame_dummy_init_array_entry
                 w __gmon_start__
0000000000600850 t __init_array_end
0000000000600848 t __init_array_start
0000000000400730 T __libc_csu_fini
00000000004006a0 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
                 U __printf_chk@@GLIBC_2.3.4                 #__printf_chkに変化
0000000000600a7c A _edata
0000000000600a90 A _end
0000000000400734 T _fini
00000000004004a8 T _init
0000000000400520 T _start
000000000040054c t call_gmon_start
0000000000600a88 b completed.6108
0000000000600a78 W data_start
0000000000400570 t deregister_tm_clones
0000000000400600 t frame_dummy
                 U fwrite@@GLIBC_2.2.5
000000000040062c T main
                 U puts@@GLIBC_2.2.5
00000000004005a0 t register_tm_clones
0000000000600a80 B stdout@@GLIBC_2.2.5
```

`printf`, `fprintf` がそれぞれ `__printf_chk`, `__fprintf_chk` に差し替わっていることがわかる。
差し替えの実装は `<bits/stdio2.h>` に存在している。

```c:/usr/include/bits/stdio2.h抜粋
#if __USE_FORTIFY_LEVEL > 1

extern int __fprintf_chk (FILE *__restrict __stream, int __flag,
			  __const char *__restrict __format, ...);
extern int __printf_chk (int __flag, __const char *__restrict __format, ...);
extern int __vfprintf_chk (FILE *__restrict __stream, int __flag,
			   __const char *__restrict __format, _G_va_list __ap);
extern int __vprintf_chk (int __flag, __const char *__restrict __format,
			  _G_va_list __ap);

# ifdef __va_arg_pack
__extern_always_inline int
fprintf (FILE *__restrict __stream, __const char *__restrict __fmt, ...)
{
  return __fprintf_chk (__stream, __USE_FORTIFY_LEVEL - 1, __fmt,
			__va_arg_pack ());
}

__extern_always_inline int
printf (__const char *__restrict __fmt, ...)
{
  return __printf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __va_arg_pack ());
}
# elif !defined __cplusplus
#  define printf(...) \
  __printf_chk (__USE_FORTIFY_LEVEL - 1, __VA_ARGS__)
#  define fprintf(stream, ...) \
  __fprintf_chk (stream, __USE_FORTIFY_LEVEL - 1, __VA_ARGS__)
# endif
```

単純にマクロで置き換えを行っていることがわかった。

# 参考
[Man page of FEATURE_TEST_MACROS](https://linuxjm.osdn.jp/html/LDP_man-pages/man7/feature_test_macros.7.html)
[security - difference between gcc -D_FORTIFY_SOURCE=1 and -D_FORTIFY_SOURCE=2 - Stack Overflow](http://stackoverflow.com/questions/13517526/difference-between-gcc-d-fortify-source-1-and-d-fortify-source-2)