3.13 Опции инструментирования программ
GCC поддерживает ряд опций командной строки, которые управляют добавлением инструментирования времени выполнения к генерируемому им коду. Например, одна из целей инструментирования — сбор статистических данных профилирования для использования в поиске «горячих точек» программы, анализе покрытия кода или оптимизации на основе профиля. Другой класс инструментирования программ — добавление проверок во время выполнения для обнаружения таких ошибок программирования, как недействительные разыменования указателей или выходы за границы массива, а также намеренно вредоносных атак, таких как разрушение стека (stack smashing) или перехват таблицы виртуальных функций C++ (vtable hijacking). Существует также общий перехватчик (hook), который можно использовать для реализации других форм трассировки или инструментирования на уровне функций в целях отладки или анализа программ.
-
-p -pg-
Генерировать дополнительный код для записи информации профилирования, подходящей для программы анализа
prof(для -p) илиgprof(для -pg). Вы должны использовать эту опцию при компиляции исходных файлов, данные о которых вам нужны, а также при компоновке (линковке).Вы можете использовать атрибут функции
no_instrument_functionдля подавления профилирования отдельных функций при компиляции с этими опциями. См. Общие атрибуты функций. -
-fprofile-arcs -
Добавить код для инструментирования дуг (arcs) потока управления программы. Во время выполнения программа записывает, сколько раз выполнялась каждая ветвь и вызов, и сколько раз они были осуществлены или вернули управление. На целевых платформах, поддерживающих конструкторы с поддержкой приоритетов, профилирование корректно обрабатывает конструкторы, деструкторы и конструкторы (и деструкторы) C++ классов, которые используются в качестве типа глобальной переменной.
При завершении скомпилированной программы она сохраняет эти данные в файл с именем auxname.gcda для каждого исходного файла. Эти данные могут использоваться для оптимизации на основе профиля (-fbranch-probabilities) или для анализа покрытия тестами (-ftest-coverage). Имя auxname каждого объектного файла генерируется из имени выходного файла (если оно явно указано и не является финальным исполняемым файлом), в противном случае это базовое имя исходного файла. В обоих случаях любые суффиксы удаляются (например, foo.gcda для входного файла dir/foo.c или dir/foo.gcda для выходного файла, заданного как -o dir/foo.o).
Обратите внимание, что если командная строка напрямую связывает (линкует) исходные файлы, к соответствующим файлам .gcda будет добавлено в качестве префикса имя выходного файла без суффикса. Например,
gcc a.c b.c -o binaryсгенерирует файлы binary-a.gcda и binary-b.gcda. -fcondition-coverage-
Добавить код для инструментирования условий программы. Во время выполнения программа записывает, какие термы в условном выражении влияют на принятие решения. Это может использоваться для проверки того, что все термы в булевой функции протестированы и оказывают независимое влияние на результат решения. Результат можно прочитать с помощью
gcov --conditions. -fpath-coverage-
Добавить код для отслеживания пройденных путей. Во время выполнения программа записывает пройденные простые пути (prime paths). Количество путей очень быстро растет с увеличением сложности, и во избежание взрывного роста времени компиляции GCC прекратит инструментирование, если примерное количество путей превышает предел, заданный опцией -fpath-coverage-limit. Результат можно прочитать с помощью
gcov --prime-paths --prime-paths-lines --prime-paths-source, см. Пример использования простых путей в gcov. -fpath-coverage-limit=limit-
Порог, при достижении которого -fpath-coverage прекращает инструментирование функции. Этот предел является приблизительным и консервативным, поскольку GCC использует пессимистичную эвристику, которая слегка завышает текущее число путей, и останавливается, если предел достигнут до нахождения всех путей. Эта опция предназначена не для точного контроля над тем, какие функции инструментировать, а скорее для ограничения эффекта взрыва путей и поддержания разумного времени компиляции. Значение по умолчанию — 250000.
См. Перемещение файлов данных для поддержки кросс-профилирования.
-
--coverage -
Эта опция используется для компиляции и компоновки кода, инструментированного для анализа покрытия. Эта опция является синонимом для -fprofile-arcs -ftest-coverage (при компиляции) и -lgcov (при компоновке). Дополнительные сведения см. в документации по этим опциям.
- Компилируйте исходные файлы с опцией -fprofile-arcs плюс опции оптимизации и генерации кода. Для анализа покрытия тестами используйте дополнительную опцию -ftest-coverage. Вам не нужно профилировать каждый исходный файл в программе.
- Дополнительно компилируйте исходные файлы с опцией -fprofile-abs-path для создания абсолютных путей в файлах .gcno. Это позволяет
gcovнаходить правильные исходные файлы в проектах, где компиляция выполняется из разных рабочих каталогов. - Компонуйте объектные файлы с помощью -lgcov или -fprofile-arcs (последнее подразумевает первое).
- Запустите программу на репрезентативной рабочей нагрузке для генерации информации профиля дуг. Это действие можно повторять любое количество раз. Вы можете запускать параллельные экземпляры вашей программы, и при условии, что файловая система поддерживает блокировку, файлы данных будут обновляться корректно. Если не используется строгий диалект ISO C, вызовы
forkобнаруживаются и обрабатываются корректно без двойного подсчета.Кроме того, объектный файл можно перекомпилировать несколько раз, и соответствующий файл .gcda будет объединяться до тех пор, пока исходный файл и опции компилятора остаются неизменными.
- Для оптимизации на основе профиля скомпилируйте исходные файлы снова с теми же опциями оптимизации и генерации кода плюс -fbranch-probabilities (см. Опции, управляющие оптимизацией).
- Для анализа покрытия тестами используйте
gcovдля получения информации, понятной человеку, из файлов .gcno и .gcda. Дополнительную информацию см. в документацииgcov.
С опцией -fprofile-arcs для каждой функции вашей программы GCC создает граф потока управления, а затем находит остовное дерево для этого графа. Инструментировать нужно только те дуги, которые не входят в остовное дерево: компилятор добавляет код для подсчета количества выполнений этих дуг. Когда дуга является единственным выходом или единственным входом в блок, код инструментирования может быть добавлен в сам блок; в противном случае для размещения кода инструментирования должен быть создан новый базовый блок.
С опцией -fcondition-coverage для каждого условного выражения в вашей программе GCC создает битовую маску (bitset) и записывает проверенные булевы значения, которые оказывают независимое влияние на результат этого выражения.
С опцией -fpath-coverage GCC находит, нумерует и записывает пройденные простые пути каждой функции, если только количество путей не превышает лимит, заданный опцией -fpath-coverage-limit. Если лимит превышен, функция не инструментируется, как если бы опция -fpath-coverage не использовалась. Простой путь — это самая длинная последовательность уникальных блоков (за исключением, возможно, первого и последнего), которая не является подпутем никакого другого пути.
-
-ftest-coverage -
Создать файл примечаний (notes file), который утилита анализа покрытия кода
gcov(см.gcov— программа покрытия тестами) может использовать для отображения покрытия программы. Файл примечаний каждого исходного файла называется auxname.gcno. Описание auxname и инструкции по генерации данных покрытия тестами см. в описании опции -fprofile-arcs выше. Данные покрытия более точно соответствуют исходным файлам, если вы не используете оптимизацию. -
-fprofile-abs-path -
Автоматически преобразовывать относительные имена исходных файлов в абсолютные пути в файлах .gcno. Это позволяет
gcovнаходить правильные исходные файлы в проектах, где компиляция выполняется из разных рабочих каталогов. -
-fprofile-dir=path -
Установить каталог для поиска файлов данных профиля в path. Эта опция влияет только на данные профиля, сгенерированные опциями -fprofile-generate, -ftest-coverage, -fprofile-arcs и используемые опциями -fprofile-use, -fbranch-probabilities и связанными с ними. Могут использоваться как абсолютные, так и относительные пути. По умолчанию GCC использует текущий каталог в качестве path, поэтому файл данных профиля появляется в том же каталоге, что и объектный файл. Во избежание конфликтов имен, если имя объектного файла не является абсолютным путем, мы преобразуем абсолютный путь файла sourcename.gcda и используем его в качестве имени файла .gcda. Подробности об именовании файлов см. в описании -fprofile-arcs. См. похожую опцию -fprofile-note.
Когда исполняемый файл запускается в среде с массовым параллелизмом, рекомендуется сохранять профиль в разные папки. Это можно сделать с помощью переменных в path, которые экспортируются во время выполнения:
%p-
идентификатор процесса (PID).
%q{VAR}-
значение переменной окружения VAR
-
-fprofile-generate -fprofile-generate=path-
Включить опции, обычно используемые для инструментирования приложения с целью создания профиля, полезного для последующей рекомпиляции с оптимизацией на основе обратной связи профиля (profile-guided optimization). Вы должны использовать -fprofile-generate как при компиляции, так и при компоновке вашей программы.
Включаются следующие опции: -fprofile-arcs, -fprofile-values, -finline-functions и -fipa-bit-cp.
Если указан path, GCC ищет в этом каталоге файлы данных обратной связи профиля. См. -fprofile-dir.
Чтобы оптимизировать программу на основе собранной информации профиля, используйте -fprofile-use. Дополнительную информацию см. в разделе Опции, управляющие оптимизацией.
-
-fprofile-info-section -fprofile-info-section=name-
Зарегистрировать информацию профиля в указанной секции вместо использования конструктора/деструктора. Имя секции задается параметром name, если он указан, в противном случае по умолчанию используется имя
.gcov_info. Указатель на информацию профиля, сгенерированную опцией -fprofile-arcs, помещается в указанную секцию для каждой единицы трансляции (translation unit). Эта опция отключает регистрацию информации профиля через конструктор и отключает обработку информации профиля через деструктор. Эта опция не предназначена для использования в хост-окружениях, таких как GNU/Linux. Она ориентирована на автономные окружения (например, встраиваемые системы) с ограниченными ресурсами, которые не поддерживают конструкторы/деструкторы или ввод-вывод файлов библиотек C.Линковщик может собрать входные секции в непрерывный блок памяти и определить начальный и конечный символы. Ниже приведен пример скрипта компоновщика GNU, который определяет выходную секцию компоновщика:
.gcov_info : { PROVIDE (__gcov_info_start = .); KEEP (*(.gcov_info)) PROVIDE (__gcov_info_end = .); }Программа может дампить информацию профилирования, зарегистрированную в этом наборе компоновщика, например, следующим образом:
#include <gcov.h> #include <stdio.h> #include <stdlib.h> 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 -
Если указан path, GCC сохраняет файл .gcno в указанный каталог. Если вы объедините эту опцию с несколькими исходными файлами, файл .gcno будет перезаписан.
-
-fprofile-prefix-path=path -
Эту опцию можно использовать в сочетании с profile-generate=profile_dir и profile-use=profile_dir, чтобы сообщить GCC, где находится базовый каталог построенного дерева исходного кода. По умолчанию profile_dir будет содержать файлы с измененными (mangled) абсолютными путями всех объектных файлов в собираемом проекте. Это нежелательно, когда каталог, используемый для сборки инструментированного бинарного файла, отличается от каталога, используемого для сборки бинарного файла, оптимизированного с использованием обратной связи профиля, поскольку данные профиля не будут найдены во время оптимизированной сборки. В таких сценариях можно использовать -fprofile-prefix-path=path, где path указывает на базовый каталог сборки, чтобы отсечь нерелевантную часть пути и сохранить все имена файлов относительными к главному каталогу сборки.
-
-fprofile-prefix-map=old=new -
При компиляции файлов, находящихся в каталоге old, записывать информацию профилирования (с помощью --coverage), описывающую их так, как будто файлы находятся в каталоге new. См. также -ffile-prefix-map и -fcanon-prefix-map.
-
-fprofile-update=method
-
Изменяет метод обновления для приложения, инструментированного для оптимизации на основе профиля обратной связи (profile feedback based optimization). Аргумент method должен быть одним из следующих: ‘single’, ‘atomic’ или ‘prefer-atomic’. Первый полезен для однопоточных приложений, в то время как второй предотвращает повреждение профиля путем генерации потокобезопасного кода.
Предупреждение: Если приложение некорректно ожидает завершения всех потоков (или создает отсоединенный поток), файл профиля все равно может быть поврежден.
Использование ‘prefer-atomic’ будет преобразовано либо в ‘atomic’, если это поддерживается целевой платформой, либо в ‘single’ в противном случае. Драйвер GCC автоматически выбирает ‘prefer-atomic’, когда в командной строке присутствует -pthread, в противном случае методом по умолчанию является ‘single’.
Если выбран ‘atomic’, то информация профиля обновляется с использованием атомарных операций по принципу наилучшего обеспечения (best-effort). В идеале информация профиля обновляется с помощью атомарных операций в аппаратном обеспечении. Однако если целевая платформа не поддерживает необходимые атомарные операции на уровне оборудования, но доступна libatomic, то информация профиля обновляется посредством вызовов libatomic. Если целевая платформа не поддерживает ни необходимые атомарные операции в оборудовании, ни libatomic, то информация профиля не обновляется атомарно и выдается предупреждение. В этом случае полученная информация профилирования может быть повреждена для многопоточных приложений.
Из соображений производительности, если для информации профилирования используются 64-битные счетчики, а целевая платформа поддерживает аппаратные атомарные операции только для 32 бит, критичные к производительности обновления профиля выполняются с использованием двух 32-битных атомарных операций для каждого обновления счетчика. Если сигнал прерывает эти две операции обновления счетчика, информация профилирования может оказаться в несогласованном состоянии.
-
-fprofile-filter-files=regex -
Инструментировать только функции из файлов, имена которых соответствуют любому из регулярных выражений (разделенных точкой с запятой).
Например, -fprofile-filter-files=main\.c;module.*\.c инструментирует только main.c и все файлы на C, начинающиеся с «module».
-
-fprofile-exclude-files=regex -
Инструментировать только функции из файлов, имена которых не соответствуют ни одному из регулярных выражений (разделенных точкой с запятой).
Например, -fprofile-exclude-files=/usr/.* предотвратит инструментирование всех файлов, расположенных в папке /usr/.
-
-fprofile-reproducible=[multithreaded|parallel-runs|serial] -
Управление уровнем воспроизводимости профиля, собранного с помощью
-fprofile-generate. Это позволяет пересобрать программу с тем же результатом, что полезно, например, для дистрибутивных пакетов.При использовании -fprofile-reproducible=serial профиль, собранный с помощью -fprofile-generate, является воспроизводимым при условии, что обучаемая программа ведет себя одинаково при каждом вызове обучающего запуска, она не является многопоточной, а потоковая передача данных профиля всегда выполняется в одном и том же порядке. Обратите внимание, что потоковая передача профиля происходит в конце выполнения программы, а также перед вызовом функции
fork.Обратите внимание, что довольно часто количество выполнений какой-либо части программы зависит, например, от длины имен временных файлов или рандомизации пространства памяти (что может повлиять на частоту коллизий в хэш-таблице). Такие невоспроизводимые части программ могут быть помечены атрибутом функции
no_instrument_function.gcov-dumpс ключом -l может использоваться для вывода собранных данных и проверки того, что они действительно воспроизводимы.С параметром -fprofile-reproducible=parallel-runs собранный профиль остается воспроизводимым независимо от порядка передачи данных в файлы gcda. Эта настройка позволяет запускать несколько экземпляров инструментированной программы параллельно (например, с помощью
make -j). Это снижает качество собранных данных, в частности профилирования непрямых вызовов (indirect call profiling). -
-fsanitize=address -
Включает AddressSanitizer — быстрый детектор ошибок памяти. Инструкции доступа к памяти инструментируются для обнаружения ошибок выхода за границы буфера (out-of-bounds) и использования памяти после освобождения (use-after-free). Эта опция включает -fsanitize-address-use-after-scope. Дополнительные сведения см. по адресу https://github.com/google/sanitizers/wiki/AddressSanitizer. На поведение во время выполнения можно повлиять с помощью переменной окружения
ASAN_OPTIONS. Если задано значениеhelp=1, доступные параметры отображаются при запуске инструментированной программы. Список поддерживаемых параметров см. на странице https://github.com/google/sanitizers/wiki/AddressSanitizerFlags#run-time-flags. Эту опцию нельзя комбинировать с -fsanitize=thread или -fsanitize=hwaddress. Обратите внимание, что единственными целевыми платформами, на которых в настоящее время поддерживается -fsanitize=hwaddress, являются x86-64 (только с опциями-mlam=u48или-mlam=u57) и AArch64, причем в обоих случаях только в ABI с 64-битными указателями.При компиляции с -fsanitize=address вам также следует использовать -g для получения более информативного вывода. Чтобы получить более точные трассировки стека, можно использовать такие опции, как -O0, -O1 или -Og (которые, например, предотвращают встраивание большинства функций), -fno-optimize-sibling-calls (которая предотвращает оптимизацию одноуровневых (sibling) и хвостовых рекурсивных вызовов; эта опция является неявной для -O0, -O1 или -Og) или -fno-ipa-icf (которая отключает свертку идентичного кода (Identical Code Folding) для функций). Использование -fno-omit-frame-pointer также улучшает трассировку стека. Поскольку многократные запуски программы могут выдавать трассировки с разными адресами из-за ASLR (рандомизации размещения адресного пространства), может быть желательно отключить ASLR. В Linux этого можно добиться с помощью команды «setarch `uname -m` -R ./prog».
-
-fsanitize=kernel-address -
Включает AddressSanitizer для ядра Linux. Дополнительные сведения см. на странице https://github.com/google/kernel-sanitizers.
-
-fsanitize=hwaddress -
Включает Hardware-assisted AddressSanitizer (санитизатор адресов с аппаратной поддержкой), который использует аппаратную возможность игнорировать верхний байт указателя для обнаружения ошибок памяти с низкими накладными расходами памяти. Инструкции доступа к памяти инструментируются для обнаружения ошибок выхода за границы буфера и использования памяти после освобождения. Эта опция включает -fsanitize-address-use-after-scope. Дополнительные сведения см. по адресу https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html. На поведение во время выполнения можно повлиять с помощью переменной окружения
HWASAN_OPTIONS. Если задано значениеhelp=1, доступные параметры отображаются при запуске инструментированной программы. Эту опцию нельзя комбинировать с -fsanitize=thread или -fsanitize=address, и в настоящее время она доступна только на AArch64. -
-fsanitize=kernel-hwaddress -
Включает Hardware-assisted AddressSanitizer для компиляции ядра Linux. Аналогично -fsanitize=kernel-address, но с использованием альтернативного метода инструментирования, и аналогично -fsanitize=hwaddress, но с различиями в инструментировании, необходимыми для компиляции ядра Linux. Эти различия заключаются в избежании вызовов инициализации библиотеки hwasan и в учете того, что указатель стека имеет другое значение в своем верхнем байте.
Примечание: Эта опция имеет значения по умолчанию, отличные от -fsanitize=hwaddress. Инструментирование стека и вызовов alloca не включено по умолчанию, но все же возможно, если указать параметры командной строки --param hwasan-instrument-stack=1 и --param hwasan-instrument-allocas=1 соответственно. Использование случайного тега фрейма не реализовано для инструментирования ядра.
-
-fsanitize=pointer-compare -
Инструментирование операций сравнения (<, <=, >, >=) с операндами-указателями. Эту опцию необходимо комбинировать либо с -fsanitize=kernel-address, либо с -fsanitize=address. Эту опцию нельзя комбинировать с -fsanitize=thread.Примечание: По умолчанию проверка отключена во время выполнения. Чтобы включить ее, добавьте
detect_invalid_pointer_pairs=2в переменную окруженияASAN_OPTIONS. Использованиеdetect_invalid_pointer_pairs=1обнаруживает недопустимую операцию только тогда, когда оба указателя не равны нулю. -
-fsanitize=pointer-subtract -
Инструментирование вычитания с операндами-указателями. Эту опцию необходимо комбинировать либо с -fsanitize=kernel-address, либо с -fsanitize=address. Эту опцию нельзя комбинировать с -fsanitize=thread. Примечание: По умолчанию проверка отключена во время выполнения. Чтобы включить ее, добавьте
detect_invalid_pointer_pairs=2в переменную окруженияASAN_OPTIONS. Использованиеdetect_invalid_pointer_pairs=1обнаруживает недопустимую операцию только тогда, когда оба указателя не равны нулю. -
-fsanitize=shadow-call-stack -
Включает ShadowCallStack — механизм повышения безопасности, используемый для защиты программ от перезаписи адреса возврата (например, переполнения буфера стека). Он работает путем сохранения адреса возврата функции в отдельно выделенном теневом стеке вызовов в прологе функции и восстановления адреса возврата из теневого стека вызовов в эпилоге функции. Инструментирование происходит только в тех функциях, которым необходимо сохранять адрес возврата в стек.
В настоящее время поддерживается только платформа aarch64. Эта функция специально разработана для ядер Linux, в которых включена опция CONFIG_SHADOW_CALL_STACK. Для программ пользовательского пространства поддержка во время выполнения в настоящее время не предоставляется в libc и libgcc. Пользователи, которые хотят использовать эту функцию в пользовательском пространстве, должны обеспечить собственную поддержку для времени выполнения. Следует отметить, что это может привести к нарушению правил ABI.
На aarch64 инструментирование использует регистр платформы
x18. Обычно это означает, что любой код, который может выполняться в том же потоке, что и код, скомпилированный с помощью ShadowCallStack, должен быть скомпилирован с флагом -ffixed-x18, в противном случае функции, скомпилированные без -ffixed-x18, могут затеретьx18и тем самым повредить указатель теневого стека.Кроме того, поскольку поддержка среды выполнения в пользовательском пространстве отсутствует, код, скомпилированный с помощью ShadowCallStack, не может использовать обработку исключений. Используйте -fno-exceptions, чтобы отключить исключения.
Дополнительные сведения см. по адресу https://clang.llvm.org/docs/ShadowCallStack.html.
-
-fsanitize=thread -
Включает ThreadSanitizer — быстрый детектор состояния гонки (data race). Инструкции доступа к памяти инструментируются для обнаружения ошибок состояния гонки. Дополнительные сведения см. по адресу https://github.com/google/sanitizers/wiki#threadsanitizer. На поведение во время выполнения можно повлиять с помощью переменной окружения
TSAN_OPTIONS; список поддерживаемых параметров см. на странице https://github.com/google/sanitizers/wiki/ThreadSanitizerFlags. Эту опцию нельзя комбинировать с -fsanitize=address, -fsanitize=leak.При компиляции с -fsanitize=thread вы также должны использовать -g для получения более информативного вывода.
Обратите внимание, что санитизированные атомарные встроенные функции (builtins) не могут генерировать исключения при работе с недопустимыми адресами памяти с исключениями, не связанными с вызовами (-fnon-call-exceptions).
-
-fsanitize=leak -
Включает LeakSanitizer — детектор утечек памяти. Эта опция имеет значение только при компоновке исполняемых файлов. Исполняемый файл компонуется с библиотекой, которая переопределяет
mallocи другие функции аллокатора. Дополнительные сведения см. по адресу https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer. На поведение во время выполнения можно повлиять с помощью переменной окруженияLSAN_OPTIONS. Эту опцию нельзя комбинировать с -fsanitize=thread. -
-fsanitize=undefined
-
Включение UndefinedBehaviorSanitizer — быстрого детектора неопределенного поведения. Различные вычисления инструментируются для обнаружения неопределенного поведения во время выполнения. Дополнительные сведения см. на странице 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-указателя, или если ссылка (возможно, rvalue-ссылка) привязывается к NULL-указателю, или если метод вызывается для объекта, на который указывает NULL-указатель.
-
-fsanitize=return -
Этот параметр включает проверку оператора возврата. Программы, собранные с включенным этим параметром, будут выдавать сообщение об ошибке, когда достигается конец функции, не являющейся void, без фактического возврата значения. Этот параметр работает только в C++.
-
-fsanitize=signed-integer-overflow -
Этот параметр включает проверку переполнения знаковых целых чисел. Мы проверяем, что результат
+,*и как унарных, так и бинарных-не приводит к переполнению в знаковой арифметике. Это также обнаруживает знаковое делениеINT_MIN / -1. Обратите внимание, что необходимо учитывать правила продвижения целых чисел. То есть следующее не является переполнением:signed char a = SCHAR_MAX; a++;
-
-fsanitize=bounds -
Этот параметр включает инструментирование границ массива. Обнаружение различных выходов за границы. Члены гибких массивов, массивы, подобные членам гибких массивов, и инициализаторы переменных со статическим хранением не инструментируются, за исключением массивов, подобных членам гибких массивов, для которых параметры
-fstrict-flex-arraysили-fstrict-flex-arrays=либо атрибутыstrict_flex_arrayуказывают, что с ними не следует обращаться как с массивами, подобными членам гибких массивов. -
-fsanitize=bounds-strict -
Этот параметр включает строгой инструментирование границ массива. Обнаруживается большинство выходов за границы, включая массивы, подобные членам гибких массивов. Инициализаторы переменных со статическим хранением не инструментируются.
-
-fsanitize=alignment -
Этот параметр включает проверку выравнивания указателей при их разыменовании, или когда ссылка привязывается к недостаточно выровненной цели, или когда метод или конструктор вызывается для недостаточно выровненного объекта.
-
-fsanitize=object-size -
Этот параметр включает инструментирование ссылок на память с помощью функции
__builtin_dynamic_object_size. Обнаруживаются различные выходы указателей за границы. -
-fsanitize=float-divide-by-zero -
Обнаружение деления чисел с плавающей точкой на ноль. В отличие от других аналогичных параметров, -fsanitize=float-divide-by-zero не включается параметром -fsanitize=undefined, поскольку деление с плавающей точкой на ноль может быть законным способом получения бесконечностей и NaN.
-
-fsanitize=float-cast-overflow -
Этот параметр включает проверку преобразования типов с плавающей точкой в целые числа. Мы проверяем, что результат преобразования не переполняется. В отличие от других аналогичных параметров, -fsanitize=float-cast-overflow не включается параметром -fsanitize=undefined. Этот параметр плохо работает при включенных исключениях
FE_INVALID. -
-fsanitize=nonnull-attribute -
Этот параметр включает инструментирование вызовов, проверяя, что нулевые значения не передаются аргументам, помеченным атрибутом функции
nonnullкак требующие ненулевого значения. -
-fsanitize=returns-nonnull-attribute -
Этот параметр включает инструментирование операторов возврата в функциях, помеченных атрибутом функции
returns_nonnull, для обнаружения возврата нулевых значений из таких функций. -
-fsanitize=bool -
Этот параметр включает инструментирование загрузок из типа bool. Если загружается значение, отличное от 0/1, выдается ошибка времени выполнения.
-
-fsanitize=enum -
Этот параметр включает инструментирование загрузок из типа enum. Если загружается значение за пределами диапазона значений для типа enum, выдается ошибка времени выполнения.
-
-fsanitize=vptr -
Этот параметр включает инструментирование вызовов членов функций C++, обращений к членам и некоторых преобразований между указателями на базовые и производные классы для проверки того, что ссылочный объект имеет правильный динамический тип.
-
-fsanitize=pointer-overflow -
Этот параметр включает инструментирование указательной арифметики. Если указательная арифметика приводит к переполнению, выдается ошибка времени выполнения.
-
-fsanitize=builtin -
Этот параметр включает инструментирование аргументов для выбранных встроенных функций. Если таким аргументам передается неверное значение, выдается ошибка времени выполнения. Например, передача 0 в качестве аргумента в
__builtin_ctzили__builtin_clzвызывает неопределенное поведение, которое диагностируется этим параметром.
Обратите внимание, что санитайзеры имеют тенденцию увеличивать частоту ложноположительных предупреждений, наиболее заметно связанных с -Wmaybe-uninitialized. Мы не рекомендуем комбинировать -Werror и [использование] санитайзеров.
В то время как -ftrapv приводит к генерации прерываний (traps) для знаковых переполнений, -fsanitize=undefined выдает диагностическое сообщение. В настоящее время это работает только для семейства языков C.
-
-
-fno-sanitize=all -
Этот параметр отключает все ранее включенные санитайзеры. Использование -fsanitize=all не допускается, так как некоторые санитайзеры не могут использоваться вместе.
-
-fasan-shadow-offset=number -
Этот параметр заставляет GCC использовать пользовательское теневое смещение (shadow offset) в проверках AddressSanitizer. Это полезно для экспериментов с различными макетами теневой памяти в Kernel AddressSanitizer.
-
-fsanitize-sections=s1,s2,... -
Санитизация глобальных переменных в выбранных пользователем секциях. si может содержать подстановочные знаки (wildcards).
-
-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: первый включает восстановление для всех поддерживающих его санитайзеров, второй отключает восстановление для всех поддерживающих его санитайзеров.
Даже если режим восстановления включен на стороне компилятора, его необходимо включить и на стороне библиотеки среды выполнения, иначе сбои по-прежнему будут фатальными. В библиотеке среды выполнения по умолчанию используется значение
halt_on_error=0для ThreadSanitizer и UndefinedBehaviorSanitizer, в то время как значение по умолчанию для AddressSanitizer —halt_on_error=1. Это поведение можно переопределить, установив флагhalt_on_errorв соответствующей переменной окружения.Синтаксис без явного параметра opts является устаревшим. Он эквивалентен указанию списка opts, состоящего из:
undefined,float-cast-overflow,float-divide-by-zero,bounds-strict
-
-fsanitize-address-use-after-scope -
Включение санитизации локальных переменных для обнаружения ошибок использования после выхода из области видимости (use-after-scope). Параметр устанавливает для -fstack-reuse значение «none».
-
-fsanitize-trap[=opts] -
Параметр -fsanitize-trap= предписывает компилятору сообщать о неопределенном поведении для санитайзеров, указанных в разделенном запятыми списке opts, с использованием
__builtin_trap, а не подпрограммы библиотекиlibubsan. Если этот параметр включен для определенного санитайзера, он имеет приоритет над -fsanitize-recover= для этого санитайзера:__builtin_trapбудет генерироваться и будет фатальным независимо от того, включено или отключено восстановление с помощью -fsanitize-recover=.Преимущество этого заключается в том, что библиотека
libubsanне нужна и не компонуется, поэтому это можно использовать даже в автономных (freestanding) окружениях.В настоящее время эта функция работает с -fsanitize=undefined (и его подпараметрами, кроме -fsanitize=vptr), -fsanitize=float-cast-overflow, -fsanitize=float-divide-by-zero и -fsanitize=bounds-strict. Также может быть указан
-fsanitize-trap=all, что включает его для подпараметровundefined, -fsanitize=float-cast-overflow, -fsanitize=float-divide-by-zero и -fsanitize=bounds-strict. Если используется-fsanitize-trap=undefinedили-fsanitize-trap=allи в командной строке включен-fsanitize=vptr, инструментирование молча игнорируется, так как для инструментирования всегда требуется поддержкаlibubsan, а использование -fsanitize-trap=vptr запрещено. -
-fsanitize-undefined-trap-on-error -
Параметр -fsanitize-undefined-trap-on-error является устаревшим эквивалентом -fsanitize-trap=all.
-
-fsanitize-coverage=trace-pc -
Включение инструментирования кода фаззинга на основе покрытия. Вставляет вызов
__sanitizer_cov_trace_pcв каждый базовый блок. -
-fsanitize-coverage=trace-cmp -
Включение инструментирования кода фаззинга на основе потока данных. Вставляет вызов
__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для сравнений с плавающей точкой (float или double) и__sanitizer_cov_trace_switchдля операторов switch. -
-fcf-protection=[full|branch|return|none|check] -fcf-protection
-
Включите инструментирование кода для повышения безопасности программы путем проверки действительности целевых адресов инструкций передачи управления (таких как косвенный вызов функции, возврат функции, косвенный переход). Это предотвращает перенаправление потока управления на непредвиденную цель. Данная функция предназначена для защиты от таких угроз, как атаки, основанные на возврате (Return-oriented Programming — ROP), и аналогичные атаки, основанные на вызовах/переходах (COP/JOP).
Ключевые слова -fcf-protection= интерпретируются следующим образом.
Значение
branchпредписывает компилятору выполнять проверку правильности передачи управления в точках инструкций косвенного ветвления, то есть инструкций call/jmp.Значение
returnреализует проверку правильности в точке возврата из функции.Значение
fullявляется псевдонимом для одновременного указанияbranchиreturn.Значение
checkиспользуется для финального компоновщика с оптимизацией во время компоновки (LTO). Выдается ошибка, если объектные файлы LTO скомпилированы с разными значениями -fcf-protection. Значениеcheckигнорируется во время компиляции.Значение
noneотключает инструментирование.-fcf-protection является псевдонимом для -fcf-protection=full. Чтобы переопределить предыдущую опцию -fcf-protection в командной строке, добавьте -fcf-protection=none, а затем -fcf-protection=kind.
Макрос
__CET__определяется при использовании -fcf-protection. Первый бит__CET__устанавливается в 1 для значенияbranch, а второй бит__CET__устанавливается в 1 дляreturn.Вы также можете использовать атрибут
nocf_check, чтобы указать, какие функции и вызовы следует исключить из инструментирования (см. Объявление атрибутов функций).В настоящее время цель x86 GNU/Linux предоставляет реализацию на основе технологии Intel Control-flow Enforcement Technology (CET), которая работает для процессоров i686 или новее.
-
-fharden-compares -
Для каждого логического теста, который переживает оптимизации gimple и не является условием в условном ветвлении (например, условия, проверяемые для условных пересылок или для сохранения в булевых переменных), генерируйте дополнительный код для вычисления и проверки инвертированного условия, а также для вызова
__builtin_trap, если результаты не совпадают. Используйте с «-fharden-conditional-branches», чтобы охватить все условные выражения. -
-fharden-conditional-branches -
Для каждого невекторизованного условного ветвления, которое переживает оптимизации gimple, генерируйте дополнительный код для вычисления и проверки инвертированного условия, а также для вызова
__builtin_trap, если результат окажется неожиданным. Используйте с «-fharden-compares», чтобы охватить все условные выражения. -
-fharden-control-flow-redundancy -
Генерируйте дополнительный код для установки логических значений (булевых переменных) при входе в базовые блоки, а также для проверки и перехвата (аварийного завершения) при выходах из функций, если логические значения не образуют путь выполнения, совместимый с графом потока управления.
Проверка выполняется перед возвратами, перед обязательными хвостовыми вызовами (см. ниже) и, опционально, перед перехватом вылетающих исключений с помощью -fhardcfr-check-exceptions, перед возвращающими вызовами с помощью -fhardcfr-check-returning-calls и перед вызовами без возврата (noreturn) с помощью -fhardcfr-check-noreturn-calls. Доступны параметры настройки --param hardcfr-max-blocks и --param hardcfr-max-inline-blocks.
Оптимизация хвостовых вызовов происходит слишком поздно, чтобы повлиять на избыточность потока управления, но вызовы, аннотированные интерфейсами фронтенда языка как обязательные хвостовые вызовы, и любые вызовы, помеченные достаточно рано как потенциальные хвостовые вызовы, также должны вызывать проверку перед вызовом, однако эти возможности носят чисто теоретический характер, поскольку такие условия могут быть выполнены только при использовании пользовательских плагинов компилятора.
-
-fhardcfr-skip-leaf -
Отключите -fharden-control-flow-redundancy в концевых функциях (leaf functions).
-
-fhardcfr-check-exceptions -
Когда активна опция -fharden-control-flow-redundancy, проверяйте записанный путь выполнения по графу потока управления в точках выхода по исключениям, так, как если бы тело функции было обернуто обработчиком очистки, который выполнял бы проверку и повторно возбуждал исключение. Эта опция включена по умолчанию; используйте -fno-hardcfr-check-exceptions для ее отключения.
-
-fhardcfr-check-returning-calls -
Когда активна опция -fharden-control-flow-redundancy, проверяйте записанный путь выполнения по графу потока управления перед любым вызовом функции, за которым сразу следует возврат ее результата (если таковой имеется), чтобы не препятствовать оптимизации хвостового вызова, независимо от того, будет ли он в итоге оптимизирован в хвостовой вызов или нет.
Эта опция включается по умолчанию всякий раз, когда включена оптимизация вызовов родственных функций (sibling calls) (см. -foptimize-sibling-calls), но ее можно включить (или отключить, используя ее отрицательную форму) явно, независимо от оптимизаций.
-
-fhardcfr-check-noreturn-calls=[always|no-xthrow|nothrow|never] -
Когда активна опция -fharden-control-flow-redundancy, проверяйте записанный путь выполнения по графу потока управления перед вызовами
noreturn: всеми (always), теми, от которых не ожидается возврата управления вызывающей стороне через исключение (no-xthrow, по умолчанию), теми, которые также могут не возвращать управление вызывающей стороне через исключение (nothrow), или ни перед какими из них (never).Проверка перед функцией
noreturn, которая может вернуть управление вызывающей стороне через исключение, может привести к выполнению проверки более одного раза, если исключение перехватывается в вызывающей функции — будь то обработчиком или очисткой. Если также включена опция -fhardcfr-check-exceptions, компилятор попытается избежать связи вызоваnoreturnс неявно добавленным обработчиком очистки, так как это было бы избыточно по отношению к проверке, выполняемой перед вызовом; однако другие обработчики или очистки в функции, если они активированы, изменят записанный путь выполнения и проверят его снова при достижении другой контрольной точки. Контрольная точка даже может оказаться другим вызовомnoreturn, поэтому проверка в конечном итоге может выполняться несколько раз.Различные оптимизаторы могут приводить к тому, что вызовы будут помечены как
noreturnи/илиnothrowдаже при отсутствии соответствующих атрибутов, что может повлиять на размещение проверок перед вызовами, а также на добавление неявных обработчиков очистки для них. Эта непредсказуемость, а также тот факт, что генерация и повторное возбуждение исключений часто сводятся к неявному вызову функцийnoreturn, сделали no-xthrow настройкой по умолчанию для этой опции: она исключает из обработкиnoreturnтолько внутренние функции, используемые для (повторного) возбуждения исключений, на которые эти оптимизации не влияют. -
-fhardened -
Включите набор флагов для C и C++, которые улучшают безопасность генерируемого кода без влияния на его ABI. Точный набор включаемых флагов может изменяться между основными выпусками GCC, но в настоящее время он включает:
-D_FORTIFY_SOURCE=3 -D_GLIBCXX_ASSERTIONS -ftrivial-auto-var-init=zero -fPIE -pie -Wl,-z,relro,-z,now -fstack-protector-strong -fstack-clash-protection -fcf-protection=full (x86 GNU/Linux only)Список опций, включаемых параметром -fhardened, может быть сгенерирован с помощью опции --help=hardened.
Если системная библиотека glibc старше версии 2.35, вместо этого используется -D_FORTIFY_SOURCE=2.
Эта опция предназначена для использования в сборках для продакшена, а не только владельцами отладочных сборок.
В настоящее время -fhardened поддерживается только для целей GNU/Linux.
-fhardened включает конкретную опцию только в том случае, если она еще не была указана где-либо в командной строке. Например, -fhardened -fstack-protector включит только -fstack-protector, но не -fstack-protector-strong.
-
-fstack-protector -
Генерируйте дополнительный код для проверки переполнения буфера, такого как атаки по разрушению стека (stack smashing attacks). Это делается путем добавления защитной переменной (канарейки) к функциям с уязвимыми объектами. Сюда входят функции, которые вызывают
alloca, и функции с буферами размером 8 байт или более. Защитные переменные инициализируются при входе в функцию и проверяются при выходе из нее. Если проверка защиты не удалась, выводится сообщение об ошибке, и программа завершает работу. Учитываются только переменные, фактически выделенные в стеке; оптимизированные переменные или переменные, размещенные в регистрах, не учитываются. -
-fstack-protector-all -
Аналогично -fstack-protector, за исключением того, что защищены все функции.
-
-fstack-protector-strong -
Аналогично -fstack-protector, но включает дополнительные функции для защиты — те, которые имеют определения локальных массивов или содержат ссылки на адреса локального фрейма. Учитываются только переменные, фактически выделенные в стеке; оптимизированные переменные или переменные, размещенные в регистрах, не учитываются.
-
-fstack-protector-explicit -
Аналогично -fstack-protector, но защищает только те функции, которые имеют атрибут
stack_protect. -
-fstack-check -
Генерируйте код для проверки того, что вы не выходите за границы стека. Вы должны указать этот флаг, если вы работаете в среде с несколькими потоками, но вам редко нужно указывать его в однопоточной среде, поскольку переполнение стека автоматически обнаруживается практически на всех системах, если существует только один стек.
Обратите внимание, что этот переключатель на самом деле не производит проверку; ее должна выполнять операционная система или среда выполнения языка. Переключатель инициирует генерацию кода для обеспечения того, чтобы они видели расширение стека.
Вы можете дополнительно указать строковый параметр: «no» означает отсутствие проверки, «generic» означает принудительное использование проверки старого типа, «specific» означает использование лучшего метода проверки и эквивалентно голому ключу -fstack-check.
Проверка старого типа — это универсальный механизм, не требующий специальной поддержки цели в компиляторе, но обладающий следующими недостатками:
- Измененная стратегия выделения памяти для крупных объектов: они всегда выделяются динамически, если их размер превышает фиксированный порог. Обратите внимание, что это может изменить семантику некоторого кода.
- Фиксированное ограничение на размер статического фрейма функций: при его превышении определенной функцией проверка стека становится ненадежной, и компилятор выдает предупреждение.
- Неэффективность: производительность кода страдает как из-за измененной стратегии выделения памяти, так и из-за универсальной реализации.
Обратите внимание, что проверка стека старого типа также является резервным методом для значения «specific», если в компилятор не была добавлена поддержка для конкретной цели.
Параметр «-fstack-check=» разработан для нужд Ada по обнаружению бесконечной рекурсии и переполнения стека. «specific» — отличный выбор при компиляции кода на Ada. Обычно этого недостаточно для защиты от атак типа stack-clash (столкновение стеков). Для защиты от них вам понадобится -fstack-clash-protection.
-
-fstack-clash-protection -
Генерируйте код для предотвращения атак в стиле stack-clash. Когда эта опция включена, компилятор выделяет только одну страницу пространства стека за раз, и к каждой странице осуществляется доступ сразу после выделения. Таким образом, это предотвращает перепрыгивание выделения памяти через любые защитные страницы стека, предоставляемые операционной системой.
Большинство целевых платформ не полностью поддерживают защиту от столкновения стеков (stack clash protection). Однако на поддерживающих их платформах -fstack-clash-protection защищает динамические выделения стека. -fstack-clash-protection также может обеспечивать ограниченную защиту для статических выделений стека, если целевая платформа поддерживает -fstack-check=specific.
-
-fstack-limit-register=reg -fstack-limit-symbol=sym-fno-stack-limit-
Генерируйте код, гарантирующий, что стек не вырастет за определенное значение — либо значение регистра, либо адрес символа. Если требуется больший стек, во время выполнения генерируется сигнал. Для большинства целевых платформ сигнал генерируется до того, как стек выйдет за границу, поэтому можно перехватить сигнал без принятия специальных мер предосторожности.
Например, если стек начинается с абсолютного адреса «0x80000000» и растет вниз, вы можете использовать флаги -fstack-limit-symbol=__stack_limit и -Wl,--defsym,__stack_limit=0x7ffe0000, чтобы ограничить стек размером 128 КБ. Обратите внимание, что это может работать только с компоновщиком GNU.
Вы можете локально переопределить проверку лимита стека с помощью атрибута функции
no_stack_limit(см. Объявление атрибутов функций). -
-fsplit-stack -
Генерируйте код для автоматического разделения стека до его переполнения. Полученная программа имеет неразрывный (discontiguous) стек, который может переполниться только в том случае, если программа не в состоянии выделить больше памяти. Это наиболее полезно при запуске многопоточных программ, поскольку больше не нужно рассчитывать оптимальный размер стека для каждого потока. В настоящее время это реализовано только для архитектур x86 под управлением GNU/Linux.
Когда код, скомпилированный с -fsplit-stack, вызывает код, скомпилированный без -fsplit-stack, для выполнения последнего кода может оказаться недостаточно доступного пространства стека. Если компиляция всего кода, включая библиотечный, с опцией -fsplit-stack-fsplit-stack, всегда имел большой стек. Поддержка этого реализована в компоновщике gold в GNU binutils версии 2.21 и более поздних.
-
-fstrub=disable -
Полностью отключите очистку стека (stack scrubbing), игнорируя любые атрибуты
strub. См. раздел Общие атрибуты типов. -
-fstrub=strict
-
Функции по умолчанию используют режим
strubdisabledи строго применяют ограничение: функции с режимами, поддерживающимиstrub-callable(at-calls,callableиalways_inlineinternal), могут бытьcallableтолько функциями в режимах с поддержкойstrub(at-callsиinternal). -
-fstrub=relaxed -
Восстанавливает настройку очистки стека (
strub) по умолчанию, а именно:strubвключается только по мере необходимости в соответствии с атрибутамиstrub, связанными с типами функций и данных.Relaxedозначает, что контекстам очистки (strub contexts) запрещено вызывать только функции, явно связанные с режимомstrubdisabled. Этот параметр полезен только для переопределения других параметров -fstrub=*, которые предшествуют ему в командной строке. -
-fstrub=at-calls -
Включить режим
at-callsstrub, где это жизнеспособно. Основное назначение этого параметра — тестирование. Он задействует механизмstrubв сценариях, строго локальных для единицы трансляции. Этот режимstrubизменяет интерфейсы функций, поэтому любая функция, видимая для других единиц трансляции или для которой берется адрес, не будет затронута этим параметром. Параметры оптимизации также могут влиять на применимость. Подробную информацию о требованиях к применимости и допустимости см. в документации по атрибутуstrub. -
-fstrub=internal -
Включить режим
internalstrub, где это жизнеспособно. Основное назначение этого параметра — тестирование. Этот параметр предназначен для тщательного тестирования частей механизмаstrub, которые реализуют менее эффективный режимstrub, сохраняющий интерфейс. Функции, которые не затронет этот параметр, встречаются довольно редко. -
-fstrub=all -
Включить некоторый режим
strub, где это жизнеспособно. Когда жизнеспособны оба режима очистки (strub), предпочтение отдаетсяat-calls. -fdump-ipa-strubm добавляет атрибуты функций, которые показывают, какой режим был выбран для каждой функции. Основное назначение этого параметра — тестирование для тщательной проверки механизмаstrub. -
-fvtable-verify=[std|preinit|none] -
Этот параметр доступен только при компиляции кода C++. Он включает (или выключает при использовании -fvtable-verify=none) функцию безопасности, которая проверяет во время выполнения для каждого виртуального вызова, что указатель на vtable, через который выполняется вызов, является действительным для типа объекта и не был поврежден или перезаписан. Если во время выполнения обнаруживается недействительный указатель на vtable, сообщается об ошибке и выполнение программы немедленно прекращается.
Этот параметр приводит к созданию структур данных во время выполнения при запуске программы, которые используются для проверки указателей на vtable. Параметры ‘std’ и ‘preinit’ управляют моментом создания этих структур данных. В обоих случаях структуры данных создаются до того, как выполнение дойдет до
main. Использование -fvtable-verify=std приводит к тому, что структуры данных создаются после загрузки и инициализации разделяемых библиотек. -fvtable-verify=preinit приводит к тому, что они создаются до загрузки и инициализации разделяемых библиотек.Если этот параметр встречается в командной строке несколько раз с разными значениями, ‘none’ имеет наивысший приоритет по сравнению с ‘std’ и ‘preinit’; ‘preinit’ имеет приоритет над ‘std’.
-
-fvtv-debug -
При использовании в сочетании с -fvtable-verify=std или -fvtable-verify=preinit приводит к вызову отладочных версий функций среды выполнения для функции проверки vtable. Этот флаг также заставляет компилятор записывать в журнал информацию о том, какие указатели на vtable он находит для каждого класса. Эта информация записывается в файл с именем vtv_set_ptr_data.log в директории, указанной в переменной окружения
VTV_LOGS_DIR, если она определена, или в текущей рабочей директории в противном случае.Примечание: Эта функция дописывает данные в файл журнала. Если вам нужен чистый файл журнала, обязательно удалите существующий.
-
-fvtv-counts -
Это отладочный флаг. При использовании в сочетании с -fvtable-verify=std или -fvtable-verify=preinit он заставляет компилятор отслеживать общее количество обнаруженных виртуальных вызовов и количество вставленных проверок. Он также подсчитывает количество вызовов определенных функций библиотеки времени выполнения, которые он вставляет, и записывает эту информацию в журнал для каждой единицы компиляции. Компилятор записывает эту информацию в файл с именем vtv_count_data.log в директории, указанной в переменной окружения
VTV_LOGS_DIR, если она определена, или в текущей рабочей директории в противном случае. Он также подсчитывает размер наборов указателей vtable для каждого класса и записывает эту информацию в файл 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);Первым аргументом является адрес начала текущей функции, который можно точно найти в таблице символов.
Это инструментирование также выполняется для функций, развернутых в строку (инлайнированных) в других функциях. Вызовы профилирования показывают, где концептуально осуществляется вход в встроенную функцию и выход из нее. Это означает, что адресируемые версии таких функций должны быть доступны. Если все ваши использования функции развернуты в строку, это может означать дополнительное увеличение размера кода. Если вы используете
extern inlineв своем коде на C, должна быть предоставлена адресируемая версия таких функций. (Обычно это и так происходит, но если вам повезет и оптимизатор всегда разворачивает функции в строку, вам может сойти с рук отсутствие статических копий.)Функции может быть назначен атрибут
no_instrument_function, и в этом случае данное инструментирование не выполняется. Это может использоваться, например, для перечисленных выше профилирующих функций, процедур прерывания с высоким приоритетом и любых функций, из которых профилирующие функции нельзя вызывать безопасно (возможно, обработчики сигналов, если подпрограммы профилирования генерируют вывод или выделяют память). См. раздел Общие атрибуты функций. -
-finstrument-functions-once -
Это аналогично -finstrument-functions, но профилирующие функции вызываются только один раз для инструментированной функции, т. е. первая профилирующая функция вызывается после первого входа в инструментированную функцию, а вторая профилирующая функция вызывается перед выходом, соответствующим этому первому входу.
Определение
onceдля целей этого параметра немного расплывчато, поскольку реализация не защищена от гонок данных. В результате реализация гарантирует лишь то, что профилирующие функции вызываются по крайней мере один раз на процесс и не более одного раз на поток, но вызовы всегда парные, то есть если поток вызывает первую функцию, он вызовет и вторую функцию, если только он никогда не дойдет до выхода из инструментированной функции. -
-finstrument-functions-exclude-file-list=file,file,… -
Установите список функций, которые исключены из инструментирования (см. описание -finstrument-functions). Если файл, содержащий определение функции, совпадает с одним из file, то эта функция не инструментируется. Совпадение проверяется по подстрокам: если параметр file является подстрокой имени файла, это считается совпадением.
Например:
-finstrument-functions-exclude-file-list=/bits/stl,include/sys
исключает любую встраиваемую (inline) функцию, определенную в файлах, пути которых содержат /bits/stl или include/sys.
Если по какой-то причине вы хотите включить символ запятой ‘,’ в одно из значений sym, напишите ‘\,’. Например, -finstrument-functions-exclude-file-list='\,\,tmp' (обратите внимание на одинарные кавычки вокруг параметра).
-
-finstrument-functions-exclude-function-list=sym,sym,… -
Это аналогично -finstrument-functions-exclude-file-list, но этот параметр задает список имен функций, исключаемых из инструментирования. Сопоставляемое имя функции — это ее видимое для пользователя имя, такое как
vector<int> blah(const vector<int> &), а не внутреннее искаженное (mangled) имя (например,_Z4blahRSt6vectorIiSaIiEE). Совпадение проверяется по подстрокам: если параметр sym является подстрокой имени функции, это считается совпадением. Для расширенных идентификаторов C99 и C++ имя функции должно быть задано в кодировке UTF-8, а не с использованием универсальных имен символов. -
-fpatchable-function-entry=N[,M] -
Генерировать N инструкций NOP прямо в начале каждой функции, причем точка входа в функцию находится перед M-й инструкцией NOP. Если M опущено, по умолчанию используется
0, поэтому точка входа в функцию указывает на адрес прямо у первой инструкции NOP. Инструкции NOP резервируют дополнительное пространство, которое может быть использовано для патчинга любого желаемого инструментирования во время выполнения, при условии, что сегмент кода доступности для записи. Количество пространства можно контролировать косвенно через количество инструкций NOP; используемая инструкция NOP соответствует инструкции, выдаваемой внутренним интерфейсом бэкенда GCCgen_nop. Это поведение зависит от целевой платформы, а также может зависеть от варианта архитектуры и/или других параметров компиляции.Для идентификации во время выполнения начальные адреса этих областей, которые соответствуют точкам входа их соответствующих функций минус M, дополнительно собираются в секции
__patchable_function_entriesрезультирующего бинарного файла.Обратите внимание, что значение
__attribute__ ((patchable_function_entry (N,M)))имеет приоритет над параметром командной строки -fpatchable-function-entry=N,M. Это можно использовать для увеличения размера области или ее полного удаления для отдельной функции. ЕслиN=0, расположение заполнения не записывается.Инструкции NOP вставляются по адресу входа в функцию — и, возможно, перед ним, в зависимости от M —, даже перед прологом. На PowerPC с ABI ELFv2 для функции с двойными точками входа локальная точка входа по умолчанию является этим адресом входа в функцию. См. параметр -msplit-patch-nops, чтобы изменить это.
Максимальное значение N и M равно 65535. На PowerPC с ABI ELFv2 для функции с двойными точками входа поддерживаемыми значениями для M являются 0, 2, 6 и 14 при неиспользовании -msplit-patch-nops.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-15.3.0/gcc/Instrumentation-Options.html