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).
Обратите внимание, что если команда непосредственно компонует исходные файлы, соответствующие файлы .gcda будут иметь префикс с именем выходного файла без суффикса. Например,
gcc a.c b.c -o binaryсгенерирует файлы binary-a.gcda и binary-b.gcda. -fcondition-coverage-
Добавляет код для инструментирования условий программы. Во время выполнения программа записывает, какие условия в условном операторе влияют на принятие решения, что может использоваться для проверки того, что все условия в булевой функции проверяются и оказывают независимое влияние на результат решения. Результат можно прочитать с помощью
gcov --conditions.См. Перемещение файлов данных для поддержки кросс-профилирования.
-
--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 создает набор битов и записывает используемые булевы значения, которые оказывают независимое влияние на результат выражения.
-
-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-arcs. См. аналогичный параметр -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, размещается в указанном разделе для каждого трансляционного блока. Этот параметр отключает регистрацию информации о профиле через конструктор и отключает обработку информации о профиле через деструктор. Этот параметр не предназначен для использования в размещённых средах, таких как 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 в расположение path. Если вы используете этот параметр с несколькими исходными файлами, файл .gcno будет перезаписан.
-
-fprofile-prefix-path=path
-
Этот параметр можно использовать в сочетании с profile-generate=profile_dir и profile-use=profile_dir, чтобы указать GCC базовый каталог построенного дерева исходного кода. По умолчанию profile_dir будет содержать файлы с искажёнными абсолютными путями всех файлов объектов в построенном проекте. Это нежелательно, когда каталог, используемый для построения инструментированного двоичного файла, отличается от каталога, используемого для построения оптимизированного двоичного файла с обратной связью профиля, так как данные профиля не будут найдены во время оптимизированного построения. В таких настройках можно использовать -fprofile-prefix-path=path с path, указывающим на базовый каталог построения, чтобы удалить нерелевантную часть пути и сохранить все имена файлов относительно основного каталога построения.
-
-fprofile-prefix-map=old=new -
При компиляции файлов, находящихся в каталоге old, записывать информацию о профилировании (с --coverage), описывая их так, как будто файлы находятся в каталоге new вместо этого. См. также -ffile-prefix-map и -fcanon-prefix-map.
-
-fprofile-update=method -
Изменить метод обновления для приложения, инструментированного для оптимизации на основе обратной связи профиля. Аргумент method должен быть одним из ‘single’, ‘atomic’ или ‘prefer-atomic’. Первый полезен для однопоточных приложений, а второй предотвращает повреждение профиля, генерируя потокобезопасный код.
Предупреждение: Когда приложение не правильно объединяет все потоки (или создаёт откреплённый поток), файл профиля всё ещё может быть повреждён.
Использование ‘prefer-atomic’ будет преобразовано либо в ‘atomic’, если это поддерживается целевой платформой, или в ‘single’ в противном случае. Драйвер GCC автоматически выбирает ‘prefer-atomic’, когда -pthread присутствует в командной строке, в противном случае по умолчанию используется метод ‘single’.
Если выбран ‘atomic’, то информация о профиле обновляется с использованием атомных операций по возможности. В идеале, информация о профиле обновляется с помощью атомных операций в аппаратном обеспечении. Однако, если целевая платформа не поддерживает необходимые атомные операции в аппаратном обеспечении, но доступна 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). Это снижает качество собранных данных, в частности профилирования косвенных вызовов. -
-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.Для получения более точных трассировок стека можно использовать такие параметры, как -O0, -O1 или -Og (которые, например, предотвращают большинство инлайнингов функций), -fno-optimize-sibling-calls (который предотвращает оптимизацию вызовов братьев и вызовов по хвосту; этот параметр неявно используется для -O0, -O1 или -Og) или -fno-ipa-icf (который отключает Identical Code Folding для функций). Поскольку несколько запусков программы могут приводить к трассировкам стека с различными адресами из-за ASLR (Address Space Layout Randomization), может потребоваться выключить ASLR. В Linux это можно сделать с помощью ‘setarch `uname -m` -R ./prog’.
-
-fsanitize=kernel-address -
Включить AddressSanitizer для ядра Linux. См. https://github.com/google/kernel-sanitizers для получения более подробной информации.
-
-fsanitize=hwaddress -
Включить 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 -
Включить 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. Для пользовательских программ поддержка в runtime в настоящее время не предоставляется в libc и libgcc. Пользователи, желающие использовать эту функцию в пользовательском пространстве, должны обеспечить собственную поддержку runtime. Следует отметить, что это может нарушить правила ABI.
На платформе aarch64 для инструментации используется регистр
x18. Это означает, что любой код, который может выполняться на том же потоке, что и код, скомпилированный с ShadowCallStack, должен быть скомпилирован со флагом -ffixed-x18, в противном случае функции, скомпилированные без -ffixed-x18, могут повредитьx18и, таким образом, испортить указатель на теневой стек.Кроме того, поскольку поддержка runtime в пользовательском пространстве отсутствует, код, скомпилированный с ShadowCallStack, не может использовать обработку исключений. Используйте -fno-exceptions для отключения исключений.
Более подробную информацию см. на странице https://clang.llvm.org/docs/ShadowCallStack.html.
-
-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 -
Обнаружение целочисленного деления на ноль.
-
-fsanitize=unreachable -
С этим параметром компилятор преобразует вызов
__builtin_unreachableв вызов сообщения об ошибке вместо этого. При достижении вызова__builtin_unreachableповедение является неопределённым. -
-fsanitize=vla-bound -
Этот параметр предписывает компилятору проверять, что размер массива с переменной длиной положителен.
-
-fsanitize=null -
Этот параметр включает проверку указателей. В частности, приложение, скомпилированное с включённым этим параметром, выведет сообщение об ошибке, когда попытается выполнить разыменование нулевого указателя или если ссылка (возможно, ссылка на rvalue) привязана к нулевому указателю или если метод вызывается на объекте, на который указывает нулевой указатель.
-
-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 -
Этот параметр включает инструментацию загрузки из типа перечисления. Если загружается значение, выходящее за пределы диапазона значений для типа перечисления, выдаётся ошибка во время выполнения.
-
-fsanitize=vptr -
Этот параметр включает инструментацию вызовов функций-членов C++, доступа к членам и некоторых преобразований между указателями на базовый и производный классы для проверки того, что на объект ссылается объект с правильным динамическим типом.
-
-fsanitize=pointer-overflow -
Этот параметр включает инструментацию арифметики указателей. Если арифметика указателей выходит за пределы допустимого диапазона, выдаётся ошибка во время выполнения.
-
-fsanitize=builtin -
Этот параметр включает инструментацию аргументов для выбранных встроенных функций. Если некорректное значение передаётся в такие аргументы, выдаётся ошибка во время выполнения. Например, передача 0 в качестве аргумента в
__builtin_ctzили__builtin_clzвызывает неопределённое поведение и диагностируется этим параметром.
Обратите внимание, что санитайзеры, как правило, увеличивают частоту ложных срабатываний, особенно в отношении -Wmaybe-uninitialized. Мы не рекомендуем сочетать -Werror и санитайзеры.
В то время как -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-trap[=opts] -
Параметр -fsanitize-trap= инструктирует компилятор сообщать об ошибках поведения, перечисленных в списке, разделённом запятыми, opts санлайзеров, используя
__builtin_trapвместо стандартнойlibubsanбиблиотеки. Если этот параметр включён для определенного санлайзера, он имеет приоритет над -fsanitizer-recover= для данного санлайзера,__builtin_trapбудет выведено и будет фатальным независимо от того, включено ли восстановление или выключено с помощью -fsanitize-recover=.Преимущество этого заключается в том, что
libubsanбиблиотека не требуется и не подключается, поэтому это может быть использовано даже в средах без библиотеки.В настоящее время эта функция работает с -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для сравнения чисел с плавающей точкой или двойной точности и__sanitizer_cov_trace_switchдля операторов switch. -
-fcf-protection=[full|branch|return|none|check] -
Включить инструментацию кода для передачи управления, чтобы повысить безопасность программы, проверяя, что целевые адреса инструкций передачи управления (например, косвенный вызов функции, возврат функции, косвенный переход) действительны. Это предотвращает перенаправление потока управления на неожиданную цель. Это призвано защитить от таких угроз, как Return-Oriented Programming (ROP), и аналогичных методов программирования, ориентированных на вызов/переход (COP/JOP).
Значение
branchсообщает компилятору о реализации проверки валидности передачи управления в точке инструкций косвенного перехода, т.е. инструкций вызова/перехода. Значениеreturnреализует проверку валидности в точке возврата из функции. Значениеfullявляется псевдонимом для указания какbranch, так иreturn. Значениеnoneотключает инструментацию.Для переопределения -fcf-protection необходимо добавить -fcf-protection=none, а затем -fcf-protection=xxx.
Значение
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 и более новых.
-
-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 в функциях-листьях.
-
-fhardcfr-check-exceptions -
Когда -fharden-control-flow-redundancy активен, проверять записанный путь выполнения относительно графа потока управления в точках выхода из исключений, как если бы тело функции было обернуто обработчиком очистки, который выполнял проверку и повторно поднимал исключение. Этот параметр включён по умолчанию; используйте -fno-hardcfr-check-exceptions для его отключения.
-
-fhardcfr-check-returning-calls -
Когда -fharden-control-flow-redundancy активен, проверять записанный путь выполнения по отношению к графику потока управления перед любым вызовом функции, сразу за которым следует возврат результата, если таковой имеется, чтобы не препятствовать оптимизации вызовов хвоста, является ли он в конечном итоге оптимизированным в вызов хвоста или нет.
Этот параметр включён по умолчанию, когда включены оптимизации вызовов-братьев (см. -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 -
Вывести дополнительный код для проверки переполнения буфера, например, атак переполнения стека. Это делается путем добавления защитной переменной к функциям с уязвимыми объектами. Это включает функции, которые вызывают
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 -
Генерировать код для предотвращения атак на столкновение стека. При включении этого параметра компилятор выделяет только одну страницу памяти стека за раз, и каждая страница обращается сразу после выделения. Таким образом, он предотвращает выделение, перескакивающее страницы защиты стека, предоставленные операционной системой.
Большинство платформ не полностью поддерживают защиту от столкновения стека. Однако на тех платформах -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 и более поздних.
-
-fstrub=disable -
Полностью отключить очистку стека, игнорируя все атрибуты
strub. См. Общие атрибуты типов. -
-fstrub=strict -
Функции по умолчанию работают в режиме
strubdisabled, и применяют строго ограничение, что только функции, связанные с режимамиstrub-callable(at-calls,callableиalways_inlineinternal), могут быть вызваны функциями с включенными режимамиstrub(at-callsиinternal). -
-fstrub=relaxed -
Восстановить значение по умолчанию очистки стека (
strub), а именно,strubвключается только по необходимости в соответствии с атрибутамиstrubфункций и типов данных.Relaxedозначает, что контексты очистки предотвращаются от вызова функций, явно связанных с режимом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
исключает любые встраиваемые функции, определённые в файлах, пути к которым содержат /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, используемая, соответствует команде, выводимой внутренним интерфейсом GCCgen_nop. Это поведение зависит от целевой архитектуры и может также зависеть от варианта архитектуры и/или других параметров компиляции.Для идентификации во время выполнения начальные адреса этих областей, которые соответствуют адресам их соответствующих точек входа в функции минус M, дополнительно собираются в разделе
__patchable_function_entriesрезультирующего двоичного файла.Обратите внимание, что значение
__attribute__ ((patchable_function_entry (N,M)))имеет приоритет над параметром командной строки -fpatchable-function-entry=N,M. Это можно использовать для увеличения размера области или её полного удаления для одной функции. ЕслиN=0, местоположение заполнения не записывается.Команды NOP вставляются в — и, возможно, перед, в зависимости от M — адрес входа в функцию, даже перед прологом. На PowerPC с ABI ELFv2 для функции с двумя точками входа локальная точка входа — это адрес входа в функцию.
Максимальное значение N и M — 65535. На PowerPC с ABI ELFv2 для функции с двумя точками входа поддерживаемые значения для M — 0, 2, 6 и 14.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Instrumentation-Options.html