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-note=path-
Если path указан, GCC сохраняет файл .gcno в местоположении path. Если вы объединяете параметр с несколькими исходными файлами, файл .gcno будет перезаписан.
-fprofile-prefix-path=path-
Этот параметр можно использовать в сочетании с profile-generate=profile_dir и profile-use=profile_dir для указания базового каталога дерева скомпилированных исходных файлов. По умолчанию 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=kernel-address-
Включить AddressSanitizer для ядра Linux. Подробнее см. https://github.com/google/kasan/wiki.
-fsanitize=pointer-compare-
Инструментировать операцию сравнения (<, <=, >, >=) с операндами-указателями. Параметр должен быть объединён с -fsanitize=kernel-address или -fsanitize=address. Параметр нельзя комбинировать с -fsanitize=thread. Примечание: По умолчанию проверка отключена во время выполнения. Для её включения добавьте
detect_invalid_pointer_pairs=2в переменную средыASAN_OPTIONS. Используяdetect_invalid_pointer_pairs=1, обнаруживаются неверные операции только при условии, что оба указателя не равны null. -fsanitize=pointer-subtract-
Инструментировать вычитание с операндами-указателями. Параметр должен быть объединён с -fsanitize=kernel-address или -fsanitize=address. Параметр нельзя комбинировать с -fsanitize=thread. Примечание: По умолчанию проверка отключена во время выполнения. Для её включения добавьте
detect_invalid_pointer_pairs=2в переменную средыASAN_OPTIONS. Используяdetect_invalid_pointer_pairs=1, обнаруживаются неверные операции только при условии, что оба указателя не равны null. -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, или если ссылка (возможно, ссылка на ссылку) связана с указателем 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. Это полезно для экспериментов с различными макетами тени памяти в санитизаторе ядра 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для сравнения float или 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. Он обычно недостаточен для защиты от атак типа stack-clash. Для защиты от них нужен флаг «-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 back-endgen_nop. Это поведение зависит от целевой платформы и может также зависеть от варианта архитектуры и/или других параметров компиляции.Для идентификации во время выполнения начальные адреса этих областей, которые соответствуют начальным адресам их соответствующих функций минус M, дополнительно собираются в разделе
__patchable_function_entriesрезультирующего двоичного файла.Обратите внимание, что значение
__attribute__ ((patchable_function_entry (N,M)))имеет приоритет над параметром командной строки -fpatchable-function-entry=N,M. Это можно использовать для увеличения размера области или для её полного удаления для отдельной функции. ЕслиN=0, расположение заполнителя не записывается.NOP-инструкции вставляются в — и, возможно, перед, в зависимости от M — адрес входа в функцию, даже перед прологом.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-10.5.0/gcc/Instrumentation-Options.html