GCC 支持许多命令行选项,这些选项控制将运行时检测添加到其通常生成的代码中。例如,检测的一个目的是收集分析统计信息,以用于查找程序热点、代码覆盖率分析或按配置文件优化。另一类程序检测是添加运行时检查,以检测编程错误,如无效的指针取消引用或越界数组访问,以及故意的恶意攻击,如堆栈粉碎或C++ vtable 劫持。还有一个通用的钩子,可用于实现其他形式的跟踪或函数级检测,以进行调试或程序分析。
-p
-pg
生成额外的代码以编写适合于分析程序(用于)或(用于)的配置文件信息。在编译要访问其数据的源文件时,必须使用此选项,并且在链接时也必须使用它。prof
-pgprof
-pg
使用这些选项进行编译时,可以使用 function 属性来禁止分析各个函数。请参见常见函数属性。no_instrument_function
-fprofile-arcs
添加代码,以便检测程序流弧。在执行期间,程序记录每个分支和调用的执行次数以及获取或返回的次数。在支持具有优先级支持的构造函数的目标上,分析会正确处理用作全局变量类型的类的构造函数、析构函数和C++构造函数(和析构函数)。
当编译的程序退出时,它会将此数据保存到为每个源文件调用的文件中。该数据可用于配置文件定向优化 (),或用于测试覆盖率分析 ()。每个对象文件都是从输出文件的名称生成的,如果显式指定并且它不是最终的可执行文件,否则它是源文件的基名。在这两种情况下,任何后缀都会被删除(例如 对于输入文件 ,或指定为 的输出文件)。auxname.gcda-fbranch-probabilities-ftest-coverageauxnamefoo.gcdadir/foo.cdir/foo.gcda-o dir/foo.o
请注意,如果命令行直接链接源文件,则相应的文件将以输出文件的不加符名称为前缀。例如: 将生成 和 文件。.gcdagcc a.c b.c -o binary
binary-a.gcdabinary-b.gcda
请参见交叉分析。
--coverage
此选项用于编译和链接为覆盖率分析而检测的代码。该选项是(编译时)和(链接时)的同义词。有关更多详细信息,请参阅这些选项的文档。-fprofile-arcs-ftest-coverage-lgcov
gcov
fork
此外,只要源文件和编译器选项不变,就可以多次重新编译对象文件,并且相应的文件会合并。.gcda
gcov
.gcno.gcdagcov
使用 ,对于程序的每个函数,GCC 创建一个程序流图,然后为该图查找生成树。只有不在生成树上的弧才需要检测:编译器添加代码来计算这些弧的执行次数。当弧线是块的唯一出口或唯一入口时,可以将检测代码添加到块中;否则,必须创建一个新的基本块来保存检测代码。-fprofile-arcs
-ftest-coverage
生成代码覆盖率实用程序(请参阅 gcov — 测试覆盖率程序)可用于显示程序覆盖率的注释文件。每个源文件的注释文件称为 。有关如何生成测试覆盖率数据的说明和说明,请参阅上面的选项。如果不进行优化,覆盖率数据将与源文件更紧密地匹配。gcov
auxname.gcno-fprofile-arcsauxname
-fprofile-abs-path
自动将文件中的相对源文件名转换为绝对路径名。这允许在使用不同工作目录进行编译的项目中找到正确的源。.gcnogcov
-fprofile-dir=path
将要搜索 中的配置文件数据文件的目录设置为 。此选项仅影响由 、 和 生成的配置文件数据及其相关选项。绝对路径和相对路径均可使用。默认情况下,GCC 将当前目录用作 ,因此配置文件数据文件显示在与对象文件相同的目录中。为了防止文件名冲突,如果对象文件名不是绝对路径,我们会修改文件的绝对路径,并将其用作文件的文件名。请参阅中有关文件命名的详细信息。请参阅类似的选项 。path-fprofile-generate-ftest-coverage-fprofile-arcs-fprofile-use-fbranch-probabilitiespathsourcename.gcda.gcda-fprofile-arcs-fprofile-note
当可执行文件在大规模并行环境中运行时,建议将配置文件保存到不同的文件夹。这可以通过在运行时导出的变量来完成:path
%p
进程 ID。
%q{VAR}
环境变量的值VAR
-fprofile-generate
-fprofile-generate=path
启用通常用于检测应用程序的选项,以生成配置文件,以便以后通过基于配置文件反馈的优化进行重新编译。在编译和链接程序时必须同时使用这两种方法。-fprofile-generate
将启用以下选项:、、和 。-fprofile-arcs-fprofile-values-finline-functions-fipa-bit-cp
如果指定,GCC 将查看 以查找配置文件反馈数据文件。看。pathpath-fprofile-dir
要根据收集的配置文件信息优化程序,请使用 。有关详细信息,请参阅优化选项。-fprofile-use
-fprofile-info-section
-fprofile-info-section=name
在指定部分中注册配置文件信息,而不是使用构造函数/析构函数。节名称是如果已指定,否则节名默认为 。指向 生成的配置文件信息的指针放置在每个翻译单元的指定部分中。此选项通过构造函数禁用配置文件信息注册,并通过析构函数禁用配置文件信息处理。此选项不适用于 GNU/Linux 等托管环境。它面向独立环境(例如嵌入式系统),这些环境的资源有限,不支持构造函数/析构函数或 C 库文件 I/O。name.gcov_info
-fprofile-arcs
链接器可以收集连续内存块中的输入部分,并定义开始和结束符号。定义链接器输出部分的 GNU 链接器脚本示例如下:
.gcov_info :
{
PROVIDE (__gcov_info_start = .);
KEEP (*(.gcov_info))
PROVIDE (__gcov_info_end = .);
}
该程序可以转储在此链接器集中注册的分析信息,例如:
#include
#include
#include
extern const struct gcov_info *const __gcov_info_start[];
extern const struct gcov_info *const __gcov_info_end[];
static void
dump (const void *d, unsigned n, void *arg)
{
const unsigned char *c = d;
for (unsigned i = 0; i < n; ++i)
printf ("%02x", c[i]);
}
static void
filename (const char *f, void *arg)
{
__gcov_filename_to_gcfn (f, dump, arg );
}
static void *
allocate (unsigned length, void *arg)
{
return malloc (length);
}
static void
dump_gcov_info (void)
{
const struct gcov_info *const *info = __gcov_info_start;
const struct gcov_info *const *end = __gcov_info_end;
/* Obfuscate variable to prevent compiler optimizations. */
__asm__ ("" : "+r" (info));
while (info != end)
{
void *arg = NULL;
__gcov_info_to_gcda (*info, filename, dump, allocate, arg);
putchar ('\n');
++info;
}
}
int
main (void)
{
dump_gcov_info ();
return 0;
}
的子命令可用于反序列化 由 和 函数生成的数据流,并将配置文件信息合并到主机文件系统上的文件中。merge-stream
gcov-tool
__gcov_filename_to_gcfn
__gcov_info_to_gcda
.gcda
-fprofile-note=path
如果指定,GCC 会将文件保存到该位置。如果将该选项与多个源文件组合在一起,则该文件将被覆盖。path.gcnopath.gcno
-fprofile-prefix-path=path
此选项可以与 GCC 结合使用,并通知 GCC 构建的源代码树的基目录在哪里。默认情况下,将包含具有构建项目中所有对象文件的损坏绝对路径的文件。当用于构建已检测二进制文件的目录与用于构建使用配置文件反馈优化的二进制文件的目录不同时,这是不希望的,因为在优化的生成过程中将找不到配置文件数据。在此类设置中,指向构建的基目录可用于去除路径的不相关部分,并保留相对于主构建目录的所有文件名。profile-generate=profile_dirprofile-use=profile_dirprofile_dir-fprofile-prefix-path=pathpath
-fprofile-prefix-map=old=new
当编译驻留在目录中的文件时,记录描述它们的分析信息(with ),就好像文件驻留在目录中一样。另请参阅。old--coveragenew-ffile-prefix-map
-fprofile-update=method
更改为基于配置文件反馈的优化而检测的应用程序的更新方法。参数应为“”、“”或“”之一。第一个对于单线程应用程序很有用,而第二个通过发出线程安全代码来防止配置文件损坏。methodsingleatomicprefer-atomic
警告:当应用程序未正确联接所有线程(或创建分离线程)时,配置文件仍可能已损坏。
使用 '' 将转换为 ''(当目标支持时)或转换为 '' 否则。GCC 驱动程序在命令行中存在时自动选择“”。prefer-atomicatomicsingleprefer-atomic-pthread
-fprofile-filter-files=regex
Instrument 仅从名称与任何正则表达式匹配(用分号分隔)的文件的功能。
例如,将仅检测和所有以“模块”开头的 C 文件。-fprofile-filter-files=main\.c;module.*\.cmain.c
-fprofile-exclude-files=regex
Instrument 仅从名称与任何正则表达式(用分号分隔)不匹配的文件的功能。
例如,将阻止对位于文件夹中的所有文件进行检测。-fprofile-exclude-files=/usr/.*/usr/
-fprofile-reproducible=[multithreaded|parallel-runs|serial]
控制 由 收集的配置文件的再现性级别。这使得重建具有相同结果的程序成为可能,例如,对于分发包非常有用。-fprofile-generate
通过收集的配置文件是可重现的,前提是训练的程序在每次调用训练运行时的行为相同,它不是多线程的,并且配置文件数据流始终以相同的顺序完成。请注意,配置文件流式处理发生在程序运行结束时,但也发生在调用函数之前。-fprofile-reproducible=serial-fprofile-generatefork
请注意,程序的某些部分执行计数通常取决于临时文件名的长度或内存空间随机化(这可能会影响哈希表冲突率)。程序的这种不可重现部分可以按函数属性进行注释。 with 可用于转储收集的数据并验证它们确实是可重现的。no_instrument_function
gcov-dump
-l
使用收集的配置文件保持可重现性,无论数据流式传输到gcda文件的顺序如何。此设置使得可以并行运行已检测程序的多个实例(例如 with )。这会降低收集数据的质量,尤其是间接呼叫分析。-fprofile-reproducible=parallel-runsmake -j
-fsanitize=address
启用地址清理器,一个快速的内存错误检测器。对内存访问指令进行检测,以检测越界和释放后使用的 bug。该选项启用 。有关更多详细信息,请参阅 https://github.com/google/sanitizers/wiki/AddressSanitizer。使用环境变量可以影响运行时行为。当设置为 时,可用选项将在检测程序启动时显示。有关受支持选项的列表,请参阅 https://github.com/google/sanitizers/wiki/AddressSanitizerFlags#run-time-flags。该选项不能与 或 结合使用。请注意,目前唯一支持的目标就是 AArch64。-fsanitize-address-use-after-scopeASAN_OPTIONS
help=1
-fsanitize=thread-fsanitize=hwaddress-fsanitize=hwaddress
-fsanitize=kernel-address
启用 AddressSanitizer for Linux 内核。有关更多详细信息,请参阅 https://github.com/google/kasan。
-fsanitize=hwaddress
启用硬件辅助地址清理程序,它使用硬件功能忽略指针的顶部字节,以允许以较低的内存开销检测内存错误。对内存访问指令进行检测,以检测越界和释放后使用的 bug。该选项启用 。有关更多详细信息,请参阅 https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html。使用环境变量可以影响运行时行为。当设置为 时,可用选项将在检测程序启动时显示。该选项不能与 或 结合使用,目前仅在 AArch64 上可用。-fsanitize-address-use-after-scopeHWASAN_OPTIONS
help=1
-fsanitize=thread-fsanitize=address
-fsanitize=kernel-hwaddress
启用硬件辅助地址清理程序以编译 Linux 内核。类似于但使用替代的检测方法,并且类似于编译 Linux 内核所需的但具有检测差异。这些差异是为了避免 hwasan 库初始化调用,并考虑堆栈指针在其顶部字节中具有不同的值。-fsanitize=kernel-address-fsanitize=hwaddress
注意:此选项与 不同于 .默认情况下,检测堆栈和 alloca 调用处于打开状态,但仍可以通过分别指定命令行选项和来实现。未为内核检测实现使用随机帧标记。-fsanitize=hwaddress--param hwasan-instrument-stack=1--param hwasan-instrument-allocas=1
-fsanitize=pointer-compare
使用指针操作数的仪器比较操作(<、<=、>、>=)。该选项必须与 之一组合,或者该选项不能与 组合使用。注: 默认情况下,检查在运行时处于禁用状态。要启用它,请添加到环境变量 。仅当两个指针都非 null 时,使用“检测”操作才无效。-fsanitize=kernel-address-fsanitize=address-fsanitize=threaddetect_invalid_pointer_pairs=2
ASAN_OPTIONS
detect_invalid_pointer_pairs=1
-fsanitize=pointer-subtract
使用指针操作数进行仪器减法。该选项必须与 之一组合,或者该选项不能与 组合使用。注: 默认情况下,检查在运行时处于禁用状态。要启用它,请添加到环境变量 。仅当两个指针都非 null 时,使用“检测”操作才无效。-fsanitize=kernel-address-fsanitize=address-fsanitize=threaddetect_invalid_pointer_pairs=2
ASAN_OPTIONS
detect_invalid_pointer_pairs=1
-fsanitize=shadow-call-stack
启用 ShadowCallStack,这是一种安全增强机制,用于保护程序免受返回地址覆盖(例如堆栈缓冲区溢出)。它的工作原理是将函数的返回地址保存到函数序言中单独分配的影子调用堆栈,并从函数尾声中的影子调用堆栈还原返回地址。检测仅发生在需要将返回地址保存到堆栈的函数中。
目前它只支持aarch64平台。它是专门为启用CONFIG_SHADOW_CALL_STACK选项的linux内核设计的。对于用户空间程序,libc 和 libgcc 中当前未提供运行时支持。想要在用户空间中使用此功能的用户需要为运行时提供自己的支持。应该注意的是,这可能会导致违反ABI规则。
在aarch64上,检测使用平台寄存器。这通常意味着任何可能与使用ShadowCallStack编译的代码在同一线程上运行的代码都必须使用标志进行编译,否则没有编译的函数可能会破坏并因此损坏影子堆栈指针。x18
-ffixed-x18-ffixed-x18x18
此外,由于没有用户空间运行时支持,因此使用 ShadowCallStack 编译的代码不能使用异常处理。用于关闭例外。-fno-exceptions
有关更多详细信息,请参阅 https://clang.llvm.org/docs/ShadowCallStack.html。
-fsanitize=thread
启用 ThreadSanitizer,一个快速的数据竞跑检测器。检测内存访问指令以检测数据争用错误。有关更多详细信息,请参阅 https://github.com/google/sanitizers/wiki#threadsanitizer。运行时行为可以使用环境变量来影响;有关受支持选项的列表,请参阅 https://github.com/google/sanitizers/wiki/ThreadSanitizerFlags。该选项不能与 、 组合使用。TSAN_OPTIONS
-fsanitize=address-fsanitize=leak
请注意,当对具有非调用异常的无效内存地址进行操作时,经过清理的原子内置组件无法引发异常 ()。-fnon-call-exceptions
-fsanitize=leak
启用泄漏消毒器,内存泄漏检测器。此选项仅对可执行文件的链接很重要,并且可执行文件是针对重写和其他分配器函数的库链接的。有关更多详细信息,请参阅 https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer。使用环境变量可以影响运行时行为。该选项不能与 结合使用。malloc
LSAN_OPTIONS
-fsanitize=thread
-fsanitize=undefined
启用未定义的行为消毒器,这是一个快速的未定义行为检测器。检测各种计算以检测运行时未定义的行为。有关更多详细信息,请参阅 https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html。使用环境变量可以影响运行时行为。当前子选项包括:UBSAN_OPTIONS
-fsanitize=shift
此选项用于检查班次操作的结果是否未定义。请注意,C和C++之间以及ISO C90和C99等之间究竟被认为是未定义的略有不同。此选项有两个子选项,以及 。-fsanitize=shift-base-fsanitize=shift-exponent
-fsanitize=shift-exponent
此选项用于检查移位操作的第二个参数是否为负,并且是否小于提升的第一个参数的精度。
-fsanitize=shift-base
如果移位操作的第二个参数在范围内,请检查移位操作的结果是否未定义。请注意,C和C++之间以及ISO C90和C99等之间究竟被认为是未定义的略有不同。
-fsanitize=integer-divide-by-zero
检测整数除以零。
-fsanitize=unreachable
使用此选项,编译器会将调用转换为诊断消息调用。到达呼叫时,行为未定义。__builtin_unreachable
__builtin_unreachable
-fsanitize=vla-bound
此选项指示编译器检查可变长度数组的大小是否为正。
-fsanitize=null
此选项启用指针检查。特别是,在启用此选项的情况下生成的应用程序在尝试取消引用 NULL 指针时,或者如果引用(可能是右值引用)绑定到 NULL 指针,或者在 NULL 指针指向的对象上调用方法时,将发出错误消息。
-fsanitize=return
此选项启用返回语句检查。在启用此选项的情况下生成的程序将在到达非 void 函数的末尾时发出错误消息,但未实际返回值。此选项仅适用于C++。
-fsanitize=signed-integer-overflow
此选项启用有符号整数溢出检查。我们检查 、 、 和一元和二进制的结果在有符号算术中是否不溢出。这还会检测有符号的分部。请注意,必须考虑整数升级规则。也就是说,以下内容不是溢出:+
*
-
INT_MIN / -1
signed char a = SCHAR_MAX;
a++;
-fsanitize=bounds
此选项启用数组边界的检测。检测到各种越界访问。不检测灵活的数组成员、灵活的阵列成员类数组以及具有静态存储的变量初始值设定项。
-fsanitize=bounds-strict
此选项启用对数组边界的严格检测。大多数越界访问都会被检测到,包括灵活的数组成员和灵活的数组成员类数组。不检测具有静态存储的变量的初始值设定项。
-fsanitize=alignment
此选项允许在取消引用指针时检查指针的对齐情况,或者在将引用绑定到未充分对齐的目标时,或者在未充分对齐的对象上调用方法或构造函数时检查指针的对齐方式。
-fsanitize=object-size
此选项允许使用该函数检测内存引用。检测到各种越界指针访问。__builtin_object_size
-fsanitize=float-divide-by-zero
检测浮点除以零。与其他类似选项不同,不启用 由 ,因为浮点除以零可以是获得无穷大和 NaNs 的合法方式。-fsanitize=float-divide-by-zero-fsanitize=undefined
-fsanitize=float-cast-overflow
此选项启用浮点类型到整数的转换检查。我们检查转换结果是否溢出。与其他类似选项不同,不是 由 启用的。此选项在启用异常的情况下效果不佳。-fsanitize=float-cast-overflow-fsanitize=undefinedFE_INVALID
-fsanitize=nonnull-attribute
此选项启用调用检测,检查 null 值是否未传递给函数属性标记为需要非 null 值的参数。nonnull
-fsanitize=returns-nonnull-attribute
此选项允许在标有函数属性的函数中检测返回语句,以检测从此类函数返回的 null 值。returns_nonnull
-fsanitize=bool
此选项允许检测来自布尔的负载。如果加载的值不是 0/1,则会发出运行时错误。
-fsanitize=enum
此选项允许从枚举类型检测负载。如果加载的值超出枚举类型的值范围,则会发出运行时错误。
-fsanitize=vptr
此选项允许检测C++成员函数调用、成员访问以及指向基类和派生类的指针之间的某些转换,以验证引用的对象是否具有正确的动态类型。
-fsanitize=pointer-overflow
此选项启用指针算术的检测。如果指针算术溢出,则会发出运行时错误。
-fsanitize=builtin
此选项允许对所选内置函数的参数进行检测。如果将无效值传递给此类参数,则会发出运行时错误。例如,将 0 作为参数传递给 或 调用未定义的行为,并通过此选项进行诊断。__builtin_ctz
__builtin_clz
虽然会导致发出已签名溢出的陷阱,但会给出诊断消息。这目前仅适用于 C 语言系列。-ftrapv-fsanitize=undefined
-fno-sanitize=all
此选项将禁用以前启用的所有清理程序。 不允许使用,因为某些消毒剂不能一起使用。-fsanitize=all
-fasan-shadow-offset=number
此选项强制 GCC 在地址清理程序检查中使用自定义阴影偏移。它对于在内核地址清理程序中试验不同的卷影内存布局非常有用。
-fsanitize-sections=s1,s2,...
清理所选用户定义节中的全局变量。 可能包含通配符。si
-fsanitize-recover[=opts]
-fsanitize-recover=控制 以逗号分隔的 列表中提及的清理程序的错误恢复模式。为清理程序组件启用此选项会导致它尝试继续运行程序,就好像没有发生错误一样。这意味着可以在单个程序运行中报告多个运行时错误,并且即使报告了错误,程序的退出代码也可能指示成功。该选项可用于更改此行为:仅报告第一个检测到的错误,然后程序以非零退出代码退出。opts-fno-sanitize-recover=
目前,此功能仅适用于 (及其子选项,除 和 )、、 、 和 .对于这些消毒程序,默认情况下会打开错误恢复,但 除外,此功能是实验性的。 并且也被接受,前者为支持它的所有消毒剂启用恢复,后者禁用所有支持它的消毒器的恢复。-fsanitize=undefined-fsanitize=unreachable-fsanitize=return-fsanitize=float-cast-overflow-fsanitize=float-divide-by-zero-fsanitize=bounds-strict-fsanitize=kernel-address-fsanitize=address-fsanitize=address-fsanitize-recover=all-fno-sanitize-recover=all
即使在编译器端打开了恢复模式,也需要在运行时库端启用它,否则故障仍然是致命的。对于 ThreadSanitizer 和 UndefinedBehaviorSanitizer,运行时库的默认值为 ,而 AddressSanitizer 的默认值为 。这可以通过在相应的环境变量中设置标志来覆盖。halt_on_error=0
halt_on_error=1
halt_on_error
不推荐使用没有显式参数的语法。它等效于指定以下各项的列表:optsopts
undefined,float-cast-overflow,float-divide-by-zero,bounds-strict
-fsanitize-address-use-after-scope
启用局部变量的清理,以检测作用域后使用错误。该选项设置为“”。-fstack-reusenone
-fsanitize-undefined-trap-on-error
该选项指示编译器使用库例程而不是库例程报告未定义的行为。这样做的好处是不需要库,也不会链接,因此即使在独立环境中也可以使用。-fsanitize-undefined-trap-on-error__builtin_trap
libubsan
libubsan
-fsanitize-coverage=trace-pc
启用覆盖率引导的模糊测试代码检测。将 调用 插入到每个基本块中。__sanitizer_cov_trace_pc
-fsanitize-coverage=trace-cmp
启用数据流引导的模糊测试代码检测。插入对 、 的调用,或用于与两个操作数变量或 、 的整数比较,或与一个操作数常量进行整数比较,或用于浮点型或双重比较以及 switch 语句。__sanitizer_cov_trace_cmp1
__sanitizer_cov_trace_cmp2
__sanitizer_cov_trace_cmp4
__sanitizer_cov_trace_cmp8
__sanitizer_cov_trace_const_cmp1
__sanitizer_cov_trace_const_cmp2
__sanitizer_cov_trace_const_cmp4
__sanitizer_cov_trace_const_cmp8
__sanitizer_cov_trace_cmpf
__sanitizer_cov_trace_cmpd
__sanitizer_cov_trace_switch
-fcf-protection=[full|branch|return|none|check]
启用控制流传输的代码检测,通过检查控制流传输指令(如间接函数调用、函数返回、间接跳转)的目标地址是否有效来提高程序安全性。这可以防止将控制流转移到意外目标。这旨在防止诸如面向返回编程(ROP)和类似的面向调用/jmp编程(COP / JOP)之类的威胁。
该值告诉编译器在间接分支指令(即 call/jmp 指令)点实现对控制流传输有效性的检查。该值实现从函数返回时的有效性检查。该值是用于同时指定 和 的别名。该值将关闭检测。branch
return
full
branch
return
none
该值用于具有链路时优化 (LTO) 的最终链路。如果使用不同的值编译 LTO 对象文件,则会发出错误。该值在编译时被忽略。check
-fcf-protectioncheck
宏在使用时定义。对于值,的第一位设置为 1,第二位设置为 1 表示 。__CET__
-fcf-protection__CET__
branch
__CET__
return
还可以使用该属性来确定应从检测中跳过哪些函数和调用(请参阅函数属性)。nocf_check
目前,x86 GNU/Linux 目标提供了基于英特尔控制流实施技术 (CET) 的实现,适用于 i686 处理器或更高版本。
-fharden-compares
对于在 gimple 优化中幸存下来且不是条件分支中的条件的每个逻辑测试(例如,为条件移动测试的条件,或存储在布尔变量中),发出额外的代码来计算和验证反转的条件,并在结果不匹配时调用。与“”一起使用可覆盖所有条件。__builtin_trap
-fharden-conditional-branches
-fharden-conditional-branches
对于每个在 gimple 优化中幸存下来的非矢量化条件分支,发出额外的代码来计算和验证反转的条件,并在结果意外时进行调用。与“”一起使用可覆盖所有条件。__builtin_trap
-fharden-compares
-fstack-protector
发出额外的代码以检查缓冲区溢出,例如堆栈粉碎攻击。这是通过将保护变量添加到具有易受攻击对象的函数来完成的。这包括调用 的函数,以及缓冲区大于或等于 8 字节的函数。在进入函数时初始化防护装置,然后在函数退出时检查防护装置。如果防护检查失败,则会打印一条错误消息,程序将退出。仅考虑实际在堆栈上分配的变量,优化的变量或在寄存器中分配的变量不计算在内。alloca
-fstack-protector-all
就像除了所有功能都受到保护。-fstack-protector
-fstack-protector-strong
类似但包括要保护的其他函数 — 具有本地数组定义或具有对本地帧地址的引用的函数。仅考虑实际在堆栈上分配的变量,优化的变量或在寄存器中分配的变量不计算在内。-fstack-protector
-fstack-protector-explicit
喜欢但只保护那些具有该属性的函数。-fstack-protectorstack_protect
-fstack-check
生成代码以验证您没有超出堆栈的边界。如果在具有多个线程的环境中运行,则应指定此标志,但您很少需要在单线程环境中指定它,因为如果只有一个堆栈,则在几乎所有系统上都会自动检测到堆栈溢出。
请注意,此开关实际上不会导致执行检查。操作系统或语言运行时必须这样做。该开关会导致生成代码,以确保他们看到正在扩展的堆栈。
您还可以指定一个字符串参数:''表示不检查,''表示强制使用旧式检查,''表示使用最佳检查方法,等效于裸露。nogenericspecific-fstack-check
旧式检查是一种通用机制,不需要编译器中特定的目标支持,但具有以下缺点:
请注意,如果编译器中未添加目标支持,则旧式堆栈检查也是 '' 的回退方法。specific
''是为Ada检测无限递归和堆栈溢出的需求而设计的。'' 是编译 Ada 代码时的绝佳选择。通常不足以防止堆栈冲突攻击。为了防止那些你想要的''。-fstack-check=specific-fstack-clash-protection
-fstack-clash-protection
生成代码以防止堆栈冲突样式攻击。启用此选项后,编译器一次仅分配一页堆栈空间,并且在分配后立即访问每个页面。因此,它可以防止分配跳过操作系统提供的任何堆栈保护页面。
大多数目标不完全支持堆栈冲突保护。但是,在这些目标上将保护动态堆栈分配。 如果目标支持 ,则还可以为静态堆栈分配提供有限的保护。-fstack-clash-protection-fstack-clash-protection-fstack-check=specific
-fstack-limit-register=reg
-fstack-limit-symbol=sym
-fno-stack-limit
生成代码以确保堆栈不会增长到超过某个值,即寄存器的值或交易品种的地址。如果需要更大的堆栈,则会在运行时引发信号。对于大多数目标,信号在堆栈超过边界之前被提升,因此可以在不采取特殊预防措施的情况下捕获信号。
例如,如果堆栈从绝对地址 '' 开始向下增长,则可以使用这些标志并强制实施 128KB 的堆栈限制。请注意,这可能仅适用于 GNU 链接器。0x80000000-fstack-limit-symbol=__stack_limit-Wl,--defsym,__stack_limit=0x7ffe0000
您可以使用函数属性在本地覆盖堆栈限制检查(请参阅函数属性)。no_stack_limit
-fsplit-stack
生成代码以在堆栈溢出之前自动拆分堆栈。生成的程序具有不连续的堆栈,仅当程序无法分配更多内存时,该堆栈才会溢出。这在运行线程程序时最有用,因为不再需要计算要用于每个线程的良好堆栈大小。目前,这仅针对运行 GNU/Linux 的 x86 目标实现。
当使用不编译的代码调用代码编译时,可能没有太多的堆栈空间可供后者运行。如果不能选择使用 编译所有代码(包括库代码),则链接器可以修复这些调用,以便编译的代码在没有库代码的情况下始终具有较大的堆栈。对此的支持在 GNU binutils 2.21 版及更高版本的黄金链接器中实现。-fsplit-stack-fsplit-stack-fsplit-stack-fsplit-stack
-fvtable-verify=[std|preinit|none]
此选项仅在编译C++代码时可用。它打开(或关闭,如果使用)安全功能,该功能在运行时验证,对于每个虚拟调用,用于进行调用的 vtable 指针是否对对象类型有效,并且未被损坏或覆盖。如果在运行时检测到无效的 vtable 指针,则会报告错误并立即停止程序的执行。-fvtable-verify=none
此选项会导致在程序启动时生成运行时数据结构,这些结构用于验证 vtable 指针。选项“”和“”控制构建这些数据结构的时间。在这两种情况下,数据结构都是在执行到达 之前构建的。使用会导致在加载和初始化共享库后生成数据结构。 导致在加载和初始化共享库之前生成它们。stdpreinitmain
-fvtable-verify=std-fvtable-verify=preinit
如果此选项在命令行中多次出现并指定了不同的值,则“”的优先级高于“”和“”;“” 优先于 “”。nonestdpreinitpreinitstd
-fvtv-debug
当与 或 结合使用时,将导致调用 vtable 验证功能的运行时函数的调试版本。此标志还使编译器记录有关为每个类查找的 vtable 指针的信息。此信息将写入由环境变量命名的目录中命名的文件(如果已定义)或当前工作目录(否则)。-fvtable-verify=std-fvtable-verify=preinitvtv_set_ptr_data.logVTV_LOGS_DIR
注: 此功能将数据追加到日志文件。如果需要新的日志文件,请确保删除任何现有日志文件。
-fvtv-counts
这是一个调试标志。当与 或 结合使用时,这会导致编译器跟踪它遇到的虚拟调用的总数和它插入的验证数。它还计算对插入的某些运行时库函数的调用次数,并为每个编译单元记录此信息。编译器将此信息写入由环境变量命名的目录中命名的文件(如果已定义),否则写入当前工作目录。它还计算每个类的 vtable 指针集的大小,并将此信息写入同一目录中。-fvtable-verify=std-fvtable-verify=preinitvtv_count_data.logVTV_LOGS_DIR
vtv_class_set_sizes.log
注: 此功能将数据追加到日志文件中。若要获取新的日志文件,请确保删除任何现有日志文件。
-finstrument-functions
生成函数进入和退出的检测调用。在函数进入之后和函数退出之前,将使用当前函数及其调用站点的地址调用以下分析函数。(在某些平台上,在当前函数之外不起作用,因此调用站点信息可能不可用于分析函数,否则。__builtin_return_address
void __cyg_profile_func_enter (void *this_fn,
void *call_site);
void __cyg_profile_func_exit (void *this_fn,
void *call_site);
第一个参数是当前函数的起始地址,可以在符号表中精确查找。
对于在其他函数中内联扩展的函数,也会执行此检测。从概念上讲,分析调用指示内联函数的输入和退出位置。这意味着此类函数的可寻址版本必须可用。如果函数的所有用法都以内联方式扩展,这可能意味着代码大小的额外扩展。如果在 C 代码中使用,则必须提供此类函数的可寻址版本。(通常情况下是这样,但是如果你很幸运,并且优化器总是内联扩展函数,那么你可能已经没有提供静态副本了。extern inline
一个函数可以被赋予属性,在这种情况下,这个检测是不完成的。例如,这可以用于上面列出的性能分析函数、高优先级中断例程以及无法从中安全调用性能分析函数的任何函数(如果性能分析例程生成输出或分配内存,则可能是信号处理程序)。请参见常见函数属性。no_instrument_function
-finstrument-functions-exclude-file-list=file,file,…
设置从检测中排除的函数的列表(请参阅 的说明)。如果包含函数定义的文件与 之一匹配,则不会检测该函数。匹配在子字符串上完成:如果参数是文件名的子字符串,则将其视为匹配项。-finstrument-functionsfilefile
例如:
-finstrument-functions-exclude-file-list=/bits/stl,include/sys
排除在路径名包含 或 的文件中定义的任何内联函数。/bits/stlinclude/sys
如果由于某种原因,您希望在其中一个中包含字母“”,请写“”。例如,(请注意选项两边的单引号)。,sym\,-finstrument-functions-exclude-file-list='\,\,tmp'
-finstrument-functions-exclude-function-list=sym,sym,…
这类似于 ,但此选项设置要从检测中排除的函数名称列表。要匹配的函数名称是其用户可见的名称,例如 ,而不是内部损坏的名称(例如,)。匹配在子字符串上完成:如果参数是函数名称的子字符串,则将其视为匹配项。对于 C99 和C++扩展标识符,函数名称必须以 UTF-8 格式提供,而不是使用通用字符名称。-finstrument-functions-exclude-file-listvector
_Z4blahRSt6vectorIiSaIiEE
sym
-fpatchable-function-entry=N[,M]
在每个函数的开头生成 NOP,函数入口点在第 th 个 NOP 之前。如果省略,则默认为函数入口指向第一个 NOP 处的地址。NOP 指令保留额外的空间,可用于在运行时修补任何所需的检测,前提是代码段是可写的。空间量可以通过NOP的数量间接控制;使用的NOP指令对应于内部GCC后端接口发出的指令。此行为是特定于目标的,还可能取决于体系结构变体和/或其他编译选项。NMM0
gen_nop
对于运行时标识,这些区域的起始地址(对应于它们各自的函数条目减号)在生成的二进制文件的部分中另外收集。M__patchable_function_entries
请注意,的值优先于命令行选项 。这可用于增加区域大小或在单个函数上完全删除它。如果 为,则不会记录焊盘位置。__attribute__ ((patchable_function_entry (N,M)))
-fpatchable-function-entry=N,MN=0
NOP 指令插入到函数输入地址,甚至可能在此之前插入函数输入地址,甚至在序言之前。M
的最大值为 65535。NM
参考官方资料:检测选项(使用 GNU 编译器集合 (GCC))