3.12 Параметры инструментирования программы ¶
GCC поддерживает ряд командных параметров, которые управляют добавлением в генерируемый код инструментации, выполняемой во время работы. Например, одна из целей инструментирования — сбор статистических данных о производительности для выявления «горячих точек» программы, анализа покрытия кода или оптимизации, основанной на профилировании. Другой класс программной инструментирования — добавление проверок во время выполнения для обнаружения ошибок программирования, таких как обращение к недействительному указателю или доступ к массиву за пределами границ, а также умышленных вредоносных атак, таких как переполнение стека или захват таблицы виртуальных функций C++. Также имеется общий крючок, который можно использовать для реализации других форм отслеживания или инструментирования на уровне функций для отладки или анализа программы.
-
-p¶ -pg-
Генерирует дополнительный код для записи информации о профилировании, подходящей для программы анализа
prof(для -p) илиgprof(для -pg). Вы должны использовать этот параметр при компиляции исходных файлов, о которых вы хотите получить данные, а также при линковке.Вы можете использовать атрибут функции
no_instrument_functionдля подавления профилирования отдельных функций при компиляции с этими параметрами. См. Общие атрибуты функций. -fprofile-arcs-
Добавляет код, чтобы информация о потоке программы (дуги) была профилирована. Во время выполнения программа записывает, сколько раз выполняется каждый разветвляющийся и вызывающий участок кода, и сколько раз он выполняется или возвращается. На целевых платформах, поддерживающих конструкторы с поддержкой приоритетов, профилирование правильно обрабатывает конструкторы, деструкторы и C++ конструкторы (и деструкторы) классов, используемых как тип глобальной переменной.
При завершении скомпилированной программы она сохраняет эти данные в файл, называемый auxname.gcda для каждого исходного файла. Данные могут быть использованы для оптимизации, направленной на профилирование (-fbranch-probabilities), или для анализа охвата тестов (-ftest-coverage). auxname для каждого объектного файла генерируется из имени выходного файла, если он явно указан и это не окончательный исполняемый файл, в противном случае это имя без расширения исходного файла. В обоих случаях удаляется любой суффикс (например, foo.gcda для входного файла dir/foo.c, или dir/foo.gcda для выходного файла, указанного как -o dir/foo.o). См. Перемещение файлов данных для поддержки кросс-профилирования.
-
--coverage¶ -
Этот параметр используется для компиляции и линковки кода, инструментированного для анализа охвата. Параметр является синонимом -fprofile-arcs -ftest-coverage (при компиляции) и -lgcov (при линковке). См. документацию по этим параметрам для получения дополнительной информации.
- Скомпилируйте исходные файлы с -fprofile-arcs плюс параметры оптимизации и генерации кода. Для анализа охвата тестов используйте дополнительный параметр -ftest-coverage. Вам не нужно профилировать каждый исходный файл в программе.
- Скомпилируйте исходные файлы дополнительно с -fprofile-abs-path, чтобы создать абсолютные имена путей в файлах .gcno. Это позволяет
gcovнайти правильные исходники в проектах, где компиляции выполняются с различными рабочими каталогами. - Слинкуйте ваши объектные файлы с -lgcov или -fprofile-arcs (последний подразумевает первый).
- Запустите программу с представительным набором данных, чтобы сгенерировать информацию о профилировании дуг. Это может быть повторено любое количество раз. Вы можете запускать параллельные экземпляры вашей программы, и при условии, что файловая система поддерживает блокировку, данные файлов будут правильно обновлены. Если не используется строгий вариант ISO C,
forkвызовы обнаруживаются и правильно обрабатываются без двойного подсчета. - Для оптимизации, направленной на профилирование, снова скомпилируйте исходные файлы с теми же параметрами оптимизации и генерации кода плюс -fbranch-probabilities (см. Параметры, управляющие оптимизацией).
- Для анализа охвата тестов используйте
gcovдля получения удобочитаемой информации из файлов .gcno и .gcda. Обратитесь к документацииgcovдля получения дополнительной информации.
С -fprofile-arcs, для каждой функции вашей программы GCC создаёт граф потока программы, затем находит остовное дерево для графа. Только дуги, которые не входят в остовное дерево, должны быть инструментированы: компилятор добавляет код для подсчёта числа раз, когда эти дуги выполняются. Когда дуга является единственным выходом или единственным входом в блок, код инструментирования может быть добавлен в блок; в противном случае, должен быть создан новый базовый блок, чтобы содержать код инструментирования.
-ftest-coverage-
Создаёт файл заметок, который может использовать утилита анализа охвата
gcov(см.gcov—Программа анализа охвата тестов), чтобы показать охват программы. Файл заметок для каждого исходного файла называется auxname.gcno. Обратитесь к параметру -fprofile-arcs выше для описания auxname и инструкции по генерации данных анализа охвата тестов. Данные охвата соответствуют исходным файлам точнее, если вы не оптимизируете. -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-note.
Когда исполняемый файл запускается в массивной параллельной среде, рекомендуется сохранять профили в разных папках. Это можно сделать с переменными в path, которые экспортируются во время выполнения:
%p-
Идентификатор процесса.
%q{VAR}-
Значение переменной среды VAR
-fprofile-generate-fprofile-generate=path-
Включает параметры, обычно используемые для инструментирования приложения, чтобы получить профиль, полезный для последующей перекомпиляции с оптимизацией, основанной на обратной связи профилирования. Вы должны использовать -fprofile-generate при компиляции и линковке вашей программы.
Включены следующие параметры: -fprofile-arcs, -fprofile-values, -finline-functions и -fipa-bit-cp.
Если указан path, GCC ищет в path файлы данных обратной связи профиля. См. -fprofile-dir.
Для оптимизации программы на основе собранной информации профилирования используйте -fprofile-use. См. Параметры, управляющие оптимизацией, для получения дополнительной информации.
-fprofile-info-section-fprofile-info-section=name-
Регистрирует информацию о профилировании в указанном разделе вместо использования конструктора/деструктора. Имя раздела — name, если оно указано, в противном случае имя раздела по умолчанию
.gcov_info. Указатель на информацию о профилировании, сгенерированную -fprofile-arcs или -ftest-coverage, помещается в указанный раздел для каждого трансляционного блока. Этот параметр отключает регистрацию информации о профилировании через конструктор и отключает обработку информации о профилировании через деструктор. Этот параметр не предназначен для использования в гостевых средах, таких как GNU/Linux. Он ориентирован на системы с ограниченными ресурсами, которые не поддерживают конструкторы и деструкторы. Линкер может собрать входные разделы в непрерывный блок памяти и определить символы начала и конца. Поддержка времени выполнения может выгрузить информацию о профилировании, зарегистрированную в этом наборе линков, во время завершения программы, например, в последовательный порт. Следующий пример сценария линковки GNU, который определяет выходной раздел линковки:.gcov_info : { PROVIDE (__gcov_info_start = .); KEEP (*(.gcov_info)) PROVIDE (__gcov_info_end = .); } -fprofile-note=path-
Если указан path, GCC сохраняет файл .gcno в местоположение path. Если вы объединяете параметр с несколькими исходными файлами, файл .gcno будет перезаписан.
-fprofile-prefix-path=path-
Этот параметр можно использовать в сочетании с profile-generate=profile_dir и profile-use=profile_dir, чтобы сообщить GCC, где находится базовый каталог построенного дерева исходного кода. По умолчанию profile_dir будет содержать файлы с изменёнными абсолютными путями всех объектных файлов в построенном проекте. Это нежелательно, когда каталог, используемый для построения инструментированного двоичного файла, отличается от каталога, используемого для построения двоичного файла, оптимизированного с обратной связью профилирования, потому что данные профилирования не будут найдены во время оптимизированной сборки. В таких установках -fprofile-prefix-path=path с path, указывающим на базовый каталог сборки, может использоваться для удаления не относящейся части пути и сохранения всех имён файлов относительно основного каталога сборки.
-fprofile-update=method-
Изменяет метод обновления для приложения, инструментированного для оптимизации, основанной на обратной связи профилирования. Аргумент method должен быть одним из ‘single’, ‘atomic’ или ‘prefer-atomic’. Первый полезен для однопоточных приложений, а второй предотвращает повреждение профиля, вызывая безопасный для потоков код.
Предупреждение: Когда приложение не объединяет все потоки должным образом (или создаёт отделённый поток), файл профиля всё ещё может быть повреждён.
Использование ‘prefer-atomic’ будет преобразовано либо в ‘atomic’, если это поддерживается целевой платформой, либо в ‘single’ в противном случае. Драйвер GCC автоматически выбирает ‘prefer-atomic’ при наличии -pthread в командной строке.
-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). Это снижает качество собранных данных, особенно профилирования косвенных вызовов. -fsanitize=address-
Включить AddressSanitizer, быстрый детектор ошибок памяти. Инструкции доступа к памяти инструментируются для обнаружения ошибок выхода за пределы границ и использования памяти после освобождения. Параметр включает -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 в настоящее время — AArch64. -fsanitize=kernel-address-
Включить AddressSanitizer для ядра Linux. Подробнее см. https://github.com/google/kasan.
-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=thread-
Включить ThreadSanitizer, быстрый детектор гонок данных. Инструкции доступа к памяти инструментируются для обнаружения ошибок гонок данных. Подробнее см. https://github.com/google/sanitizers/wiki#threadsanitizer. Поведение во время выполнения можно настроить с помощью переменной среды
TSAN_OPTIONS; список поддерживаемых параметров см. по ссылке https://github.com/google/sanitizers/wiki/ThreadSanitizerFlags. Параметр нельзя комбинировать с -fsanitize=address, -fsanitize=leak.Обратите внимание, что санитизированные атомарные функции не могут генерировать исключения при работе с некорректными адресами памяти с исключениями, не связанными с вызовами (-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-
Обнаружить целочисленное деление на ноль, а также деление с
INT_MIN / -1остатком. -fsanitize=unreachable-
С этой опцией компилятор преобразует вызов
__builtin_unreachableв вызов сообщения об ошибке вместо этого. При достижении вызова__builtin_unreachableповедение является неопределённым. -fsanitize=vla-bound-
Эта опция предписывает компилятору проверить, что размер массива переменной длины положительный.
-fsanitize=null-
Эта опция включает проверку указателей. В частности, приложение, скомпилированное с включённой этой опцией, выдаст сообщение об ошибке, когда попытается получить доступ к значению по указателю со значением NULL, или если ссылка (возможно, ссылка на rvalue) связана с указателем со значением NULL, или если метод вызывается на объекте, на который указывает указатель со значением NULL.
-fsanitize=return-
Эта опция включает проверку операторов возврата. Программы, скомпилированные с включенной этой опцией, выдадут сообщение об ошибке, когда конец функции, не возвращающей значение типа void, будет достигнут, не вернув фактическое значение. Эта опция работает только в C++.
-fsanitize=signed-integer-overflow-
Эта опция включает проверку переполнения знакового целочисленного типа. Проверяется, что результат
+,*, и как унарных, так и бинарных-операций не приводит к переполнению в арифметике со знаком. Обратите внимание, что необходимо учитывать правила повышения целочисленных типов. Например, следующее не является переполнением:signed char a = SCHAR_MAX; a++;
-fsanitize=bounds-
Эта опция включает инструментацию границ массивов. Обнаруживаются различные обращения за пределы границ массива. Члены массивов со гибкими массивами, массивы, похожие на массивы с гибкими массивами, и инициализаторы переменных со статическим хранением не инструментируются.
-fsanitize=bounds-strict-
Эта опция включает строгую инструментацию границ массивов. Обнаруживаются большинство обращений за пределы границ, включая члены массивов с гибкими массивами и массивы, похожие на массивы с гибкими массивами. Инициализаторы переменных со статическим хранением не инструментируются.
-fsanitize=alignment-
Эта опция включает проверку выравнивания указателей при обращении к ним, или когда ссылка связана с недостаточно выровненной целью, или когда метод или конструктор вызывается на недостаточно выровненном объекте.
-fsanitize=object-size-
Эта опция включает инструментацию ссылок на память с использованием функции
__builtin_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-
Эта опция включает инструментацию загрузок из перечисления. Если загружено значение, не входящее в диапазон значений перечисления, выдаётся ошибка во время выполнения.
-fsanitize=vptr-
Эта опция включает инструментацию вызовов функций-членов C++, доступа к членам и некоторых преобразований между указателями на базовый и производный классы, чтобы проверить, что ссылка соответствует объекту с правильным динамическим типом.
-fsanitize=pointer-overflow-
Эта опция включает инструментацию арифметики указателей. Если арифметика указателей переполняет, выдаётся ошибка во время выполнения.
-fsanitize=builtin-
Эта опция включает инструментацию аргументов для выбранных встроенных функций. Если некорректное значение передано в такие аргументы, выдаётся ошибка во время выполнения. Например, передача 0 в качестве аргумента к
__builtin_ctzили__builtin_clzвызывает неопределённое поведение и диагностируется этой опцией.
В то время как -ftrapv вызывает генерацию ловушек для знаковых переполнений, -fsanitize=undefined даёт диагностическое сообщение. В настоящее время это работает только для языков семейства C.
-fno-sanitize=all-
Эта опция отключает все ранее включенные санлайзеры. -fsanitize=all запрещена, так как некоторые санлайзеры не могут быть использованы вместе.
-fasan-shadow-offset=number-
Эта опция заставляет GCC использовать пользовательский смещение тени в проверках AddressSanitizer. Это полезно для экспериментов с различными макетами памяти тени в Kernel AddressSanitizer.
-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 также принимаются, первое включает восстановление для всех санлайзеров, поддерживающих его, последнее отключает восстановление для всех санлайзеров, поддерживающих его.
Даже если режим восстановления включён на стороне компилятора, он должен быть также включён на стороне библиотеки времени выполнения, иначе ошибки всё равно являются фатальными. Библиотека времени выполнения по умолчанию устанавливает
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-
Включить санлайзинг локальных переменных для обнаружения ошибок использования после области видимости. Опция устанавливает -fstack-reuse в «none».
-fsanitize-undefined-trap-on-error-
Опция -fsanitize-undefined-trap-on-error предписывает компилятору сообщать об неопределённом поведении с помощью
__builtin_trapвместо функции библиотекиlibubsan. Преимущество заключается в том, что библиотекаlibubsanне нужна и не линкована, поэтому это может быть использовано даже в средах без наличия стандартной библиотеки. -fsanitize-coverage=trace-pc-
Включить инструментацию кода для направленного на основе покрытия fuzzing. Вставляет вызов
__sanitizer_cov_trace_pcв каждый базовый блок. -fsanitize-coverage=trace-cmp-
Включить инструментацию кода, направленного на основе потоков данных fuzzing. Вставляет вызов
__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для сравнений с плавающей точкой или double и__sanitizer_cov_trace_switchдля операторов switch. -fcf-protection=[full|branch|return|none|check]
-
Включить инструментацию кода для проверок передачи управления, чтобы повысить безопасность программы, проверяя, что целевые адреса инструкций передачи управления (таких как косвенный вызов функции, возврат из функции, косвенный переход) являются валидными. Это предотвращает отклонение потока управления к непредвиденному целевому адресу. Это предназначено для защиты от таких угроз, как Return-oriented Programming (ROP), и аналогичных методов программирования, ориентированных на вызовы/переходы (COP/JOP).
Значение
branchсообщает компилятору о реализации проверки валидности передачи управления в точке инструкций косвенного перехода, т.е. инструкций вызова/перехода. Значениеreturnреализует проверку валидности в точке возврата из функции. Значениеfullявляется псевдонимом для указания какbranch, так иreturn. Значениеnoneотключает интроспекцию.Значение
checkиспользуется для окончательной связи с оптимизацией на этапе компоновки (LTO). Если файлы объектов LTO скомпилированы с разными значениями -fcf-protection, будет выдано сообщение об ошибке. Значениеcheckигнорируется на этапе компиляции.Макрос
__CET__определяется при использовании -fcf-protection. Первый бит__CET__устанавливается в 1 для значенияbranch, а второй бит__CET__устанавливается в 1 дляreturn.Вы также можете использовать атрибут
nocf_check, чтобы определить, какие функции и вызовы следует пропустить из интроспекции (см. Определение атрибутов функций).В настоящее время целевая платформа x86 GNU/Linux предоставляет реализацию, основанную на технологии Intel Control-flow Enforcement Technology (CET), которая работает для процессоров i686 и более новых.
-fstack-protector-
Выводить дополнительный код для проверки переполнения буфера, например, атак типа stack smashing. Это делается путем добавления защитной переменной к функциям с уязвимыми объектами. Это включает функции, вызывающие
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. Он обычно недостаточно эффективен для защиты от атак с переполнением стека. Для защиты от них используйте «-fstack-clash-protection».
-fstack-clash-protection-
Генерировать код для предотвращения атак типа stack clash. При включении этого параметра компилятор будет выделять только одну страницу памяти стека за раз, и каждая страница будет обработана сразу после выделения. Это предотвращает выделение памяти, пропуская любую страницу защиты стека, предоставляемую операционной системой.
Большинство целевых платформ не полностью поддерживают защиту от stack clash. Однако на тех платформах -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-
Генерировать код для автоматического разделения стека перед его переполнением. Результирующая программа имеет несвязанный стек, который может переполниться только в том случае, если программа не может выделить больше памяти. Это наиболее полезно при запуске многопоточных программ, так как больше не нужно рассчитывать оптимальный размер стека для каждого потока. В настоящее время это реализовано только для целевых платформ x86, работающих под GNU/Linux.
Когда код, скомпилированный с -fsplit-stack, вызывает код, скомпилированный без -fsplit-stack, может быть недостаточно места в стеке для выполнения последнего кода. Если компиляция всего кода, включая библиотечный, с -fsplit-stack невозможна, компоновщик может исправить эти вызовы, чтобы код, скомпилированный без -fsplit-stack, всегда имел большой стек. Поддержка этого реализована в компоновщике gold в релизе GNU binutils 2.21 и более поздних.
-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-exclude-file-list=file,file,…-
Установить список функций, исключённых из инструментирования (см. описание -finstrument-functions). Если файл, содержащий определение функции, совпадает с одним из file, то эта функция не инструментируется. Сопоставление выполняется по подстрокам: если параметр file является подстрокой имени файла, это считается совпадением.
Например:
-finstrument-functions-exclude-file-list=/bits/stl,include/sys
исключает любые встраиваемые функции, определённые в файлах, пути к которым содержат /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> &), а не внутреннее изменённое имя (например,_Z4blahRSt6vectorIiSaIiEE). Сопоставление выполняется по подстрокам: если параметр sym является подстрокой имени функции, это считается совпадением. Для идентификаторов C99 и расширенных идентификаторов C++ имя функции должно быть указано в UTF-8, а не с использованием универсальных имён символов. -fpatchable-function-entry=N[,M]-
Сгенерировать N NOP-команд непосредственно в начале каждой функции, с точкой входа в функцию перед M-й NOP-командой. Если M опущено, оно по умолчанию равно
0, поэтому точка входа в функцию — это адрес непосредственно после первой NOP-команды. Команды NOP резервируют дополнительное место, которое может использоваться для вставки любого необходимого инструментирования во время выполнения, при условии, что сегмент кода доступен для записи. Размер места косвенно контролируется количеством NOP-команд; используемая команда NOP соответствует команде, выводимой внутренним интерфейсом GCC-бекендаgen_nop. Это поведение зависит от целевой платформы и может также зависеть от архитектурного варианта и/или других параметров компиляции.Для идентификации во время выполнения начальные адреса этих областей, которые соответствуют адресам их соответствующих входов в функции минус M, дополнительно собираются в секции
__patchable_function_entriesрезультирующего двоичного файла.Обратите внимание, что значение
__attribute__ ((patchable_function_entry (N,M)))имеет приоритет над параметром командной строки -fpatchable-function-entry=N,M. Это можно использовать для увеличения размера области или её полного удаления для отдельной функции. ЕслиN=0, никакое место закладки не записывается.Инструкции NOP вставляются в — и, возможно, перед, в зависимости от M — адрес входа в функцию, даже перед прологом.
Максимальное значение N и M равно 65535.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-11.4.0/gcc/Instrumentation-Options.html