Spec-Zone.ru › GCC 15

3.13 Опции инструментирования программ

GCC поддерживает ряд опций командной строки, которые управляют добавлением инструментирования времени выполнения к генерируемому им коду. Например, одна из целей инструментирования — сбор статистических данных профилирования для использования в поиске «горячих точек» программы, анализе покрытия кода или оптимизации на основе профиля. Другой класс инструментирования программ — добавление проверок во время выполнения для обнаружения таких ошибок программирования, как недействительные разыменования указателей или выходы за границы массива, а также намеренно вредоносных атак, таких как разрушение стека (stack smashing) или перехват таблицы виртуальных функций C++ (vtable hijacking). Существует также общий перехватчик (hook), который можно использовать для реализации других форм трассировки или инструментирования на уровне функций в целях отладки или анализа программ.

-p
-pg

Генерировать дополнительный код для записи информации профилирования, подходящей для программы анализа prof (для -p) или gprof (для -pg). Вы должны использовать эту опцию при компиляции исходных файлов, данные о которых вам нужны, а также при компоновке (линковке).

Вы можете использовать атрибут функции no_instrument_function для подавления профилирования отдельных функций при компиляции с этими опциями. См. Общие атрибуты функций.

-fprofile-arcs

Добавить код для инструментирования дуг (arcs) потока управления программы. Во время выполнения программа записывает, сколько раз выполнялась каждая ветвь и вызов, и сколько раз они были осуществлены или вернули управление. На целевых платформах, поддерживающих конструкторы с поддержкой приоритетов, профилирование корректно обрабатывает конструкторы, деструкторы и конструкторы (и деструкторы) C++ классов, которые используются в качестве типа глобальной переменной.

При завершении скомпилированной программы она сохраняет эти данные в файл с именем auxname.gcda для каждого исходного файла. Эти данные могут использоваться для оптимизации на основе профиля (-fbranch-probabilities) или для анализа покрытия тестами (-ftest-coverage). Имя auxname каждого объектного файла генерируется из имени выходного файла (если оно явно указано и не является финальным исполняемым файлом), в противном случае это базовое имя исходного файла. В обоих случаях любые суффиксы удаляются (например, foo.gcda для входного файла dir/foo.c или dir/foo.gcda для выходного файла, заданного как -o dir/foo.o).

Обратите внимание, что если командная строка напрямую связывает (линкует) исходные файлы, к соответствующим файлам .gcda будет добавлено в качестве префикса имя выходного файла без суффикса. Например, gcc a.c b.c -o binary сгенерирует файлы binary-a.gcda и binary-b.gcda.

-fcondition-coverage

Добавить код для инструментирования условий программы. Во время выполнения программа записывает, какие термы в условном выражении влияют на принятие решения. Это может использоваться для проверки того, что все термы в булевой функции протестированы и оказывают независимое влияние на результат решения. Результат можно прочитать с помощью gcov --conditions.

-fpath-coverage

Добавить код для отслеживания пройденных путей. Во время выполнения программа записывает пройденные простые пути (prime paths). Количество путей очень быстро растет с увеличением сложности, и во избежание взрывного роста времени компиляции GCC прекратит инструментирование, если примерное количество путей превышает предел, заданный опцией -fpath-coverage-limit. Результат можно прочитать с помощью gcov --prime-paths --prime-paths-lines --prime-paths-source, см. Пример использования простых путей в gcov.

-fpath-coverage-limit=limit

Порог, при достижении которого -fpath-coverage прекращает инструментирование функции. Этот предел является приблизительным и консервативным, поскольку GCC использует пессимистичную эвристику, которая слегка завышает текущее число путей, и останавливается, если предел достигнут до нахождения всех путей. Эта опция предназначена не для точного контроля над тем, какие функции инструментировать, а скорее для ограничения эффекта взрыва путей и поддержания разумного времени компиляции. Значение по умолчанию — 250000.

См. Перемещение файлов данных для поддержки кросс-профилирования.

--coverage

Эта опция используется для компиляции и компоновки кода, инструментированного для анализа покрытия. Эта опция является синонимом для -fprofile-arcs -ftest-coverage (при компиляции) и -lgcov (при компоновке). Дополнительные сведения см. в документации по этим опциям.

  • Компилируйте исходные файлы с опцией -fprofile-arcs плюс опции оптимизации и генерации кода. Для анализа покрытия тестами используйте дополнительную опцию -ftest-coverage. Вам не нужно профилировать каждый исходный файл в программе.
  • Дополнительно компилируйте исходные файлы с опцией -fprofile-abs-path для создания абсолютных путей в файлах .gcno. Это позволяет gcov находить правильные исходные файлы в проектах, где компиляция выполняется из разных рабочих каталогов.
  • Компонуйте объектные файлы с помощью -lgcov или -fprofile-arcs (последнее подразумевает первое).
  • Запустите программу на репрезентативной рабочей нагрузке для генерации информации профиля дуг. Это действие можно повторять любое количество раз. Вы можете запускать параллельные экземпляры вашей программы, и при условии, что файловая система поддерживает блокировку, файлы данных будут обновляться корректно. Если не используется строгий диалект ISO C, вызовы fork обнаруживаются и обрабатываются корректно без двойного подсчета.

    Кроме того, объектный файл можно перекомпилировать несколько раз, и соответствующий файл .gcda будет объединяться до тех пор, пока исходный файл и опции компилятора остаются неизменными.

  • Для оптимизации на основе профиля скомпилируйте исходные файлы снова с теми же опциями оптимизации и генерации кода плюс -fbranch-probabilities (см. Опции, управляющие оптимизацией).
  • Для анализа покрытия тестами используйте gcov для получения информации, понятной человеку, из файлов .gcno и .gcda. Дополнительную информацию см. в документации gcov.

С опцией -fprofile-arcs для каждой функции вашей программы GCC создает граф потока управления, а затем находит остовное дерево для этого графа. Инструментировать нужно только те дуги, которые не входят в остовное дерево: компилятор добавляет код для подсчета количества выполнений этих дуг. Когда дуга является единственным выходом или единственным входом в блок, код инструментирования может быть добавлен в сам блок; в противном случае для размещения кода инструментирования должен быть создан новый базовый блок.

С опцией -fcondition-coverage для каждого условного выражения в вашей программе GCC создает битовую маску (bitset) и записывает проверенные булевы значения, которые оказывают независимое влияние на результат этого выражения.

С опцией -fpath-coverage GCC находит, нумерует и записывает пройденные простые пути каждой функции, если только количество путей не превышает лимит, заданный опцией -fpath-coverage-limit. Если лимит превышен, функция не инструментируется, как если бы опция -fpath-coverage не использовалась. Простой путь — это самая длинная последовательность уникальных блоков (за исключением, возможно, первого и последнего), которая не является подпутем никакого другого пути.

-ftest-coverage

Создать файл примечаний (notes file), который утилита анализа покрытия кода gcov (см. gcov — программа покрытия тестами) может использовать для отображения покрытия программы. Файл примечаний каждого исходного файла называется auxname.gcno. Описание auxname и инструкции по генерации данных покрытия тестами см. в описании опции -fprofile-arcs выше. Данные покрытия более точно соответствуют исходным файлам, если вы не используете оптимизацию.

-fprofile-abs-path

Автоматически преобразовывать относительные имена исходных файлов в абсолютные пути в файлах .gcno. Это позволяет gcov находить правильные исходные файлы в проектах, где компиляция выполняется из разных рабочих каталогов.

-fprofile-dir=path

Установить каталог для поиска файлов данных профиля в path. Эта опция влияет только на данные профиля, сгенерированные опциями -fprofile-generate, -ftest-coverage, -fprofile-arcs и используемые опциями -fprofile-use, -fbranch-probabilities и связанными с ними. Могут использоваться как абсолютные, так и относительные пути. По умолчанию GCC использует текущий каталог в качестве path, поэтому файл данных профиля появляется в том же каталоге, что и объектный файл. Во избежание конфликтов имен, если имя объектного файла не является абсолютным путем, мы преобразуем абсолютный путь файла sourcename.gcda и используем его в качестве имени файла .gcda. Подробности об именовании файлов см. в описании -fprofile-arcs. См. похожую опцию -fprofile-note.

Когда исполняемый файл запускается в среде с массовым параллелизмом, рекомендуется сохранять профиль в разные папки. Это можно сделать с помощью переменных в path, которые экспортируются во время выполнения:

%p

идентификатор процесса (PID).

%q{VAR}

значение переменной окружения VAR

-fprofile-generate
-fprofile-generate=path

Включить опции, обычно используемые для инструментирования приложения с целью создания профиля, полезного для последующей рекомпиляции с оптимизацией на основе обратной связи профиля (profile-guided optimization). Вы должны использовать -fprofile-generate как при компиляции, так и при компоновке вашей программы.

Включаются следующие опции: -fprofile-arcs, -fprofile-values, -finline-functions и -fipa-bit-cp.

Если указан path, GCC ищет в этом каталоге файлы данных обратной связи профиля. См. -fprofile-dir.

Чтобы оптимизировать программу на основе собранной информации профиля, используйте -fprofile-use. Дополнительную информацию см. в разделе Опции, управляющие оптимизацией.

-fprofile-info-section
-fprofile-info-section=name

Зарегистрировать информацию профиля в указанной секции вместо использования конструктора/деструктора. Имя секции задается параметром name, если он указан, в противном случае по умолчанию используется имя .gcov_info. Указатель на информацию профиля, сгенерированную опцией -fprofile-arcs, помещается в указанную секцию для каждой единицы трансляции (translation unit). Эта опция отключает регистрацию информации профиля через конструктор и отключает обработку информации профиля через деструктор. Эта опция не предназначена для использования в хост-окружениях, таких как GNU/Linux. Она ориентирована на автономные окружения (например, встраиваемые системы) с ограниченными ресурсами, которые не поддерживают конструкторы/деструкторы или ввод-вывод файлов библиотек C.

Линковщик может собрать входные секции в непрерывный блок памяти и определить начальный и конечный символы. Ниже приведен пример скрипта компоновщика GNU, который определяет выходную секцию компоновщика:

.gcov_info      :
{
  PROVIDE (__gcov_info_start = .);
  KEEP (*(.gcov_info))
  PROVIDE (__gcov_info_end = .);
}

Программа может дампить информацию профилирования, зарегистрированную в этом наборе компоновщика, например, следующим образом:

#include <gcov.h>
#include <stdio.h>
#include <stdlib.h>

extern const struct gcov_info *const __gcov_info_start[];
extern const struct gcov_info *const __gcov_info_end[];

static void
dump (const void *d, unsigned n, void *arg)
{
  const unsigned char *c = d;

  for (unsigned i = 0; i < n; ++i)
    printf ("%02x", c[i]);
}

static void
filename (const char *f, void *arg)
{
  __gcov_filename_to_gcfn (f, dump, arg );
}

static void *
allocate (unsigned length, void *arg)
{
  return malloc (length);
}

static void
dump_gcov_info (void)
{
  const struct gcov_info *const *info = __gcov_info_start;
  const struct gcov_info *const *end = __gcov_info_end;

  /* Obfuscate variable to prevent compiler optimizations.  */
  __asm__ ("" : "+r" (info));

  while (info != end)
  {
    void *arg = NULL;
    __gcov_info_to_gcda (*info, filename, dump, allocate, arg);
    putchar ('\n');
    ++info;
  }
}

int
main (void)
{
  dump_gcov_info ();
  return 0;
}

Подкомманда merge-stream утилиты gcov-tool может использоваться для десериализации потока данных, сгенерированного функциями __gcov_filename_to_gcfn и __gcov_info_to_gcda, и слияния информации профиля в файлы .gcda в файловой системе хоста.

-fprofile-note=path

Если указан path, GCC сохраняет файл .gcno в указанный каталог. Если вы объедините эту опцию с несколькими исходными файлами, файл .gcno будет перезаписан.

-fprofile-prefix-path=path

Эту опцию можно использовать в сочетании с profile-generate=profile_dir и profile-use=profile_dir, чтобы сообщить GCC, где находится базовый каталог построенного дерева исходного кода. По умолчанию profile_dir будет содержать файлы с измененными (mangled) абсолютными путями всех объектных файлов в собираемом проекте. Это нежелательно, когда каталог, используемый для сборки инструментированного бинарного файла, отличается от каталога, используемого для сборки бинарного файла, оптимизированного с использованием обратной связи профиля, поскольку данные профиля не будут найдены во время оптимизированной сборки. В таких сценариях можно использовать -fprofile-prefix-path=path, где path указывает на базовый каталог сборки, чтобы отсечь нерелевантную часть пути и сохранить все имена файлов относительными к главному каталогу сборки.

-fprofile-prefix-map=old=new

При компиляции файлов, находящихся в каталоге old, записывать информацию профилирования (с помощью --coverage), описывающую их так, как будто файлы находятся в каталоге new. См. также -ffile-prefix-map и -fcanon-prefix-map.

-fprofile-update=method

Изменяет метод обновления для приложения, инструментированного для оптимизации на основе профиля обратной связи (profile feedback based optimization). Аргумент method должен быть одним из следующих: ‘single’, ‘atomic’ или ‘prefer-atomic’. Первый полезен для однопоточных приложений, в то время как второй предотвращает повреждение профиля путем генерации потокобезопасного кода.

Предупреждение: Если приложение некорректно ожидает завершения всех потоков (или создает отсоединенный поток), файл профиля все равно может быть поврежден.

Использование ‘prefer-atomic’ будет преобразовано либо в ‘atomic’, если это поддерживается целевой платформой, либо в ‘single’ в противном случае. Драйвер GCC автоматически выбирает ‘prefer-atomic’, когда в командной строке присутствует -pthread, в противном случае методом по умолчанию является ‘single’.

Если выбран ‘atomic’, то информация профиля обновляется с использованием атомарных операций по принципу наилучшего обеспечения (best-effort). В идеале информация профиля обновляется с помощью атомарных операций в аппаратном обеспечении. Однако если целевая платформа не поддерживает необходимые атомарные операции на уровне оборудования, но доступна libatomic, то информация профиля обновляется посредством вызовов libatomic. Если целевая платформа не поддерживает ни необходимые атомарные операции в оборудовании, ни libatomic, то информация профиля не обновляется атомарно и выдается предупреждение. В этом случае полученная информация профилирования может быть повреждена для многопоточных приложений.

Из соображений производительности, если для информации профилирования используются 64-битные счетчики, а целевая платформа поддерживает аппаратные атомарные операции только для 32 бит, критичные к производительности обновления профиля выполняются с использованием двух 32-битных атомарных операций для каждого обновления счетчика. Если сигнал прерывает эти две операции обновления счетчика, информация профилирования может оказаться в несогласованном состоянии.

-fprofile-filter-files=regex

Инструментировать только функции из файлов, имена которых соответствуют любому из регулярных выражений (разделенных точкой с запятой).

Например, -fprofile-filter-files=main\.c;module.*\.c инструментирует только main.c и все файлы на C, начинающиеся с «module».

-fprofile-exclude-files=regex

Инструментировать только функции из файлов, имена которых не соответствуют ни одному из регулярных выражений (разделенных точкой с запятой).

Например, -fprofile-exclude-files=/usr/.* предотвратит инструментирование всех файлов, расположенных в папке /usr/.

-fprofile-reproducible=[multithreaded|parallel-runs|serial]

Управление уровнем воспроизводимости профиля, собранного с помощью -fprofile-generate. Это позволяет пересобрать программу с тем же результатом, что полезно, например, для дистрибутивных пакетов.

При использовании -fprofile-reproducible=serial профиль, собранный с помощью -fprofile-generate, является воспроизводимым при условии, что обучаемая программа ведет себя одинаково при каждом вызове обучающего запуска, она не является многопоточной, а потоковая передача данных профиля всегда выполняется в одном и том же порядке. Обратите внимание, что потоковая передача профиля происходит в конце выполнения программы, а также перед вызовом функции fork.

Обратите внимание, что довольно часто количество выполнений какой-либо части программы зависит, например, от длины имен временных файлов или рандомизации пространства памяти (что может повлиять на частоту коллизий в хэш-таблице). Такие невоспроизводимые части программ могут быть помечены атрибутом функции no_instrument_function. gcov-dump с ключом -l может использоваться для вывода собранных данных и проверки того, что они действительно воспроизводимы.

С параметром -fprofile-reproducible=parallel-runs собранный профиль остается воспроизводимым независимо от порядка передачи данных в файлы gcda. Эта настройка позволяет запускать несколько экземпляров инструментированной программы параллельно (например, с помощью make -j). Это снижает качество собранных данных, в частности профилирования непрямых вызовов (indirect call profiling).

-fsanitize=address

Включает AddressSanitizer — быстрый детектор ошибок памяти. Инструкции доступа к памяти инструментируются для обнаружения ошибок выхода за границы буфера (out-of-bounds) и использования памяти после освобождения (use-after-free). Эта опция включает -fsanitize-address-use-after-scope. Дополнительные сведения см. по адресу https://github.com/google/sanitizers/wiki/AddressSanitizer. На поведение во время выполнения можно повлиять с помощью переменной окружения ASAN_OPTIONS. Если задано значение help=1, доступные параметры отображаются при запуске инструментированной программы. Список поддерживаемых параметров см. на странице https://github.com/google/sanitizers/wiki/AddressSanitizerFlags#run-time-flags. Эту опцию нельзя комбинировать с -fsanitize=thread или -fsanitize=hwaddress. Обратите внимание, что единственными целевыми платформами, на которых в настоящее время поддерживается -fsanitize=hwaddress, являются x86-64 (только с опциями -mlam=u48 или -mlam=u57) и AArch64, причем в обоих случаях только в ABI с 64-битными указателями.

При компиляции с -fsanitize=address вам также следует использовать -g для получения более информативного вывода. Чтобы получить более точные трассировки стека, можно использовать такие опции, как -O0, -O1 или -Og (которые, например, предотвращают встраивание большинства функций), -fno-optimize-sibling-calls (которая предотвращает оптимизацию одноуровневых (sibling) и хвостовых рекурсивных вызовов; эта опция является неявной для -O0, -O1 или -Og) или -fno-ipa-icf (которая отключает свертку идентичного кода (Identical Code Folding) для функций). Использование -fno-omit-frame-pointer также улучшает трассировку стека. Поскольку многократные запуски программы могут выдавать трассировки с разными адресами из-за ASLR (рандомизации размещения адресного пространства), может быть желательно отключить ASLR. В Linux этого можно добиться с помощью команды «setarch `uname -m` -R ./prog».

-fsanitize=kernel-address

Включает AddressSanitizer для ядра Linux. Дополнительные сведения см. на странице https://github.com/google/kernel-sanitizers.

-fsanitize=hwaddress

Включает Hardware-assisted AddressSanitizer (санитизатор адресов с аппаратной поддержкой), который использует аппаратную возможность игнорировать верхний байт указателя для обнаружения ошибок памяти с низкими накладными расходами памяти. Инструкции доступа к памяти инструментируются для обнаружения ошибок выхода за границы буфера и использования памяти после освобождения. Эта опция включает -fsanitize-address-use-after-scope. Дополнительные сведения см. по адресу https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html. На поведение во время выполнения можно повлиять с помощью переменной окружения HWASAN_OPTIONS. Если задано значение help=1, доступные параметры отображаются при запуске инструментированной программы. Эту опцию нельзя комбинировать с -fsanitize=thread или -fsanitize=address, и в настоящее время она доступна только на AArch64.

-fsanitize=kernel-hwaddress

Включает Hardware-assisted AddressSanitizer для компиляции ядра Linux. Аналогично -fsanitize=kernel-address, но с использованием альтернативного метода инструментирования, и аналогично -fsanitize=hwaddress, но с различиями в инструментировании, необходимыми для компиляции ядра Linux. Эти различия заключаются в избежании вызовов инициализации библиотеки hwasan и в учете того, что указатель стека имеет другое значение в своем верхнем байте.

Примечание: Эта опция имеет значения по умолчанию, отличные от -fsanitize=hwaddress. Инструментирование стека и вызовов alloca не включено по умолчанию, но все же возможно, если указать параметры командной строки --param hwasan-instrument-stack=1 и --param hwasan-instrument-allocas=1 соответственно. Использование случайного тега фрейма не реализовано для инструментирования ядра.

-fsanitize=pointer-compare

Инструментирование операций сравнения (<, <=, >, >=) с операндами-указателями. Эту опцию необходимо комбинировать либо с -fsanitize=kernel-address, либо с -fsanitize=address. Эту опцию нельзя комбинировать с -fsanitize=thread.Примечание: По умолчанию проверка отключена во время выполнения. Чтобы включить ее, добавьте detect_invalid_pointer_pairs=2 в переменную окружения ASAN_OPTIONS. Использование detect_invalid_pointer_pairs=1 обнаруживает недопустимую операцию только тогда, когда оба указателя не равны нулю.

-fsanitize=pointer-subtract

Инструментирование вычитания с операндами-указателями. Эту опцию необходимо комбинировать либо с -fsanitize=kernel-address, либо с -fsanitize=address. Эту опцию нельзя комбинировать с -fsanitize=thread. Примечание: По умолчанию проверка отключена во время выполнения. Чтобы включить ее, добавьте detect_invalid_pointer_pairs=2 в переменную окружения ASAN_OPTIONS. Использование detect_invalid_pointer_pairs=1 обнаруживает недопустимую операцию только тогда, когда оба указателя не равны нулю.

-fsanitize=shadow-call-stack

Включает ShadowCallStack — механизм повышения безопасности, используемый для защиты программ от перезаписи адреса возврата (например, переполнения буфера стека). Он работает путем сохранения адреса возврата функции в отдельно выделенном теневом стеке вызовов в прологе функции и восстановления адреса возврата из теневого стека вызовов в эпилоге функции. Инструментирование происходит только в тех функциях, которым необходимо сохранять адрес возврата в стек.

В настоящее время поддерживается только платформа aarch64. Эта функция специально разработана для ядер Linux, в которых включена опция CONFIG_SHADOW_CALL_STACK. Для программ пользовательского пространства поддержка во время выполнения в настоящее время не предоставляется в libc и libgcc. Пользователи, которые хотят использовать эту функцию в пользовательском пространстве, должны обеспечить собственную поддержку для времени выполнения. Следует отметить, что это может привести к нарушению правил ABI.

На aarch64 инструментирование использует регистр платформы x18. Обычно это означает, что любой код, который может выполняться в том же потоке, что и код, скомпилированный с помощью ShadowCallStack, должен быть скомпилирован с флагом -ffixed-x18, в противном случае функции, скомпилированные без -ffixed-x18, могут затереть x18 и тем самым повредить указатель теневого стека.

Кроме того, поскольку поддержка среды выполнения в пользовательском пространстве отсутствует, код, скомпилированный с помощью ShadowCallStack, не может использовать обработку исключений. Используйте -fno-exceptions, чтобы отключить исключения.

Дополнительные сведения см. по адресу https://clang.llvm.org/docs/ShadowCallStack.html.

-fsanitize=thread

Включает ThreadSanitizer — быстрый детектор состояния гонки (data race). Инструкции доступа к памяти инструментируются для обнаружения ошибок состояния гонки. Дополнительные сведения см. по адресу https://github.com/google/sanitizers/wiki#threadsanitizer. На поведение во время выполнения можно повлиять с помощью переменной окружения TSAN_OPTIONS; список поддерживаемых параметров см. на странице https://github.com/google/sanitizers/wiki/ThreadSanitizerFlags. Эту опцию нельзя комбинировать с -fsanitize=address, -fsanitize=leak.

При компиляции с -fsanitize=thread вы также должны использовать -g для получения более информативного вывода.

Обратите внимание, что санитизированные атомарные встроенные функции (builtins) не могут генерировать исключения при работе с недопустимыми адресами памяти с исключениями, не связанными с вызовами (-fnon-call-exceptions).

-fsanitize=leak

Включает LeakSanitizer — детектор утечек памяти. Эта опция имеет значение только при компоновке исполняемых файлов. Исполняемый файл компонуется с библиотекой, которая переопределяет malloc и другие функции аллокатора. Дополнительные сведения см. по адресу https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer. На поведение во время выполнения можно повлиять с помощью переменной окружения LSAN_OPTIONS. Эту опцию нельзя комбинировать с -fsanitize=thread.

-fsanitize=undefined

Включение UndefinedBehaviorSanitizer — быстрого детектора неопределенного поведения. Различные вычисления инструментируются для обнаружения неопределенного поведения во время выполнения. Дополнительные сведения см. на странице https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html. На поведение во время выполнения можно повлиять с помощью переменной окружения UBSAN_OPTIONS. Текущие подпараметры:

-fsanitize=shift

Этот параметр включает проверку того, что результат операции сдвига не является неопределенным. Обратите внимание, что то, что именно считается неопределенным, немного различается в C и C++, а также между ISO C90 и C99 и т. д. Этот параметр имеет два подпараметра: -fsanitize=shift-base и -fsanitize=shift-exponent.

-fsanitize=shift-exponent

Этот параметр включает проверку того, что второй аргумент операции сдвига не отрицателен и меньше точности приведенного первого аргумента.

-fsanitize=shift-base

Если второй аргумент операции сдвига находится в пределах допустимого диапазона, проверяется, что результат операции сдвига не является неопределенным. Обратите внимание, что то, что именно считается неопределенным, немного различается в C и C++, а также между ISO C90 и C99 и т. д.

-fsanitize=integer-divide-by-zero

Обнаружение целочисленного деления на ноль.

-fsanitize=unreachable

С помощью этого параметра компилятор вместо этого превращает вызов __builtin_unreachable в вызов сообщения диагностического характера. При достижении вызова __builtin_unreachable поведение является неопределенным.

-fsanitize=vla-bound

Этот параметр предписывает компилятору проверять, что размер массива переменной длины является положительным.

-fsanitize=null

Этот параметр включаем проверку указателей. В частности, приложение, собранное с включенным этим параметром, выдаст сообщение об ошибке при попытке разыменования NULL-указателя, или если ссылка (возможно, rvalue-ссылка) привязывается к NULL-указателю, или если метод вызывается для объекта, на который указывает NULL-указатель.

-fsanitize=return

Этот параметр включает проверку оператора возврата. Программы, собранные с включенным этим параметром, будут выдавать сообщение об ошибке, когда достигается конец функции, не являющейся void, без фактического возврата значения. Этот параметр работает только в C++.

-fsanitize=signed-integer-overflow

Этот параметр включает проверку переполнения знаковых целых чисел. Мы проверяем, что результат +, * и как унарных, так и бинарных - не приводит к переполнению в знаковой арифметике. Это также обнаруживает знаковое деление INT_MIN / -1. Обратите внимание, что необходимо учитывать правила продвижения целых чисел. То есть следующее не является переполнением:

signed char a = SCHAR_MAX;
a++;
-fsanitize=bounds

Этот параметр включает инструментирование границ массива. Обнаружение различных выходов за границы. Члены гибких массивов, массивы, подобные членам гибких массивов, и инициализаторы переменных со статическим хранением не инструментируются, за исключением массивов, подобных членам гибких массивов, для которых параметры -fstrict-flex-arrays или -fstrict-flex-arrays= либо атрибуты strict_flex_array указывают, что с ними не следует обращаться как с массивами, подобными членам гибких массивов.

-fsanitize=bounds-strict

Этот параметр включает строгой инструментирование границ массива. Обнаруживается большинство выходов за границы, включая массивы, подобные членам гибких массивов. Инициализаторы переменных со статическим хранением не инструментируются.

-fsanitize=alignment

Этот параметр включает проверку выравнивания указателей при их разыменовании, или когда ссылка привязывается к недостаточно выровненной цели, или когда метод или конструктор вызывается для недостаточно выровненного объекта.

-fsanitize=object-size

Этот параметр включает инструментирование ссылок на память с помощью функции __builtin_dynamic_object_size. Обнаруживаются различные выходы указателей за границы.

-fsanitize=float-divide-by-zero

Обнаружение деления чисел с плавающей точкой на ноль. В отличие от других аналогичных параметров, -fsanitize=float-divide-by-zero не включается параметром -fsanitize=undefined, поскольку деление с плавающей точкой на ноль может быть законным способом получения бесконечностей и NaN.

-fsanitize=float-cast-overflow

Этот параметр включает проверку преобразования типов с плавающей точкой в целые числа. Мы проверяем, что результат преобразования не переполняется. В отличие от других аналогичных параметров, -fsanitize=float-cast-overflow не включается параметром -fsanitize=undefined. Этот параметр плохо работает при включенных исключениях FE_INVALID.

-fsanitize=nonnull-attribute

Этот параметр включает инструментирование вызовов, проверяя, что нулевые значения не передаются аргументам, помеченным атрибутом функции nonnull как требующие ненулевого значения.

-fsanitize=returns-nonnull-attribute

Этот параметр включает инструментирование операторов возврата в функциях, помеченных атрибутом функции returns_nonnull, для обнаружения возврата нулевых значений из таких функций.

-fsanitize=bool

Этот параметр включает инструментирование загрузок из типа bool. Если загружается значение, отличное от 0/1, выдается ошибка времени выполнения.

-fsanitize=enum

Этот параметр включает инструментирование загрузок из типа enum. Если загружается значение за пределами диапазона значений для типа enum, выдается ошибка времени выполнения.

-fsanitize=vptr

Этот параметр включает инструментирование вызовов членов функций C++, обращений к членам и некоторых преобразований между указателями на базовые и производные классы для проверки того, что ссылочный объект имеет правильный динамический тип.

-fsanitize=pointer-overflow

Этот параметр включает инструментирование указательной арифметики. Если указательная арифметика приводит к переполнению, выдается ошибка времени выполнения.

-fsanitize=builtin

Этот параметр включает инструментирование аргументов для выбранных встроенных функций. Если таким аргументам передается неверное значение, выдается ошибка времени выполнения. Например, передача 0 в качестве аргумента в __builtin_ctz или __builtin_clz вызывает неопределенное поведение, которое диагностируется этим параметром.

Обратите внимание, что санитайзеры имеют тенденцию увеличивать частоту ложноположительных предупреждений, наиболее заметно связанных с -Wmaybe-uninitialized. Мы не рекомендуем комбинировать -Werror и [использование] санитайзеров.

В то время как -ftrapv приводит к генерации прерываний (traps) для знаковых переполнений, -fsanitize=undefined выдает диагностическое сообщение. В настоящее время это работает только для семейства языков C.

-fno-sanitize=all

Этот параметр отключает все ранее включенные санитайзеры. Использование -fsanitize=all не допускается, так как некоторые санитайзеры не могут использоваться вместе.

-fasan-shadow-offset=number

Этот параметр заставляет GCC использовать пользовательское теневое смещение (shadow offset) в проверках AddressSanitizer. Это полезно для экспериментов с различными макетами теневой памяти в Kernel AddressSanitizer.

-fsanitize-sections=s1,s2,...

Санитизация глобальных переменных в выбранных пользователем секциях. si может содержать подстановочные знаки (wildcards).

-fsanitize-recover[=opts]

-fsanitize-recover= управляет режимом восстановления после ошибок для санитайзеров, указанных в разделенном запятыми списке opts. Включение этого параметра для компонента санитайзера заставляет его попытаться продолжить выполнение программы так, будто никакой ошибки не произошло. Это означает, что в ходе одного запуска программы может быть сообщено о нескольких ошибках во время выполнения, а код выхода программы может указывать на успешное завершение даже при наличии ошибок. Для изменения этого поведения можно использовать параметр -fno-sanitize-recover=: сообщается только о первой обнаруженной ошибке, после чего программа завершает работу с ненулевым кодом выхода.

В настоящее время эта функция работает только для -fsanitize=undefined (и его подпараметров, кроме -fsanitize=unreachable и -fsanitize=return), -fsanitize=float-cast-overflow, -fsanitize=float-divide-by-zero, -fsanitize=bounds-strict, -fsanitize=kernel-address и -fsanitize=address. Для этих санитайзеров восстановление после ошибок включено по умолчанию, за исключением -fsanitize=address, для которого эта функция является экспериментальной. Также принимаются -fsanitize-recover=all и -fno-sanitize-recover=all: первый включает восстановление для всех поддерживающих его санитайзеров, второй отключает восстановление для всех поддерживающих его санитайзеров.

Даже если режим восстановления включен на стороне компилятора, его необходимо включить и на стороне библиотеки среды выполнения, иначе сбои по-прежнему будут фатальными. В библиотеке среды выполнения по умолчанию используется значение halt_on_error=0 для ThreadSanitizer и UndefinedBehaviorSanitizer, в то время как значение по умолчанию для AddressSanitizer — halt_on_error=1. Это поведение можно переопределить, установив флаг halt_on_error в соответствующей переменной окружения.

Синтаксис без явного параметра opts является устаревшим. Он эквивалентен указанию списка opts, состоящего из:

undefined,float-cast-overflow,float-divide-by-zero,bounds-strict
-fsanitize-address-use-after-scope

Включение санитизации локальных переменных для обнаружения ошибок использования после выхода из области видимости (use-after-scope). Параметр устанавливает для -fstack-reuse значение «none».

-fsanitize-trap[=opts]

Параметр -fsanitize-trap= предписывает компилятору сообщать о неопределенном поведении для санитайзеров, указанных в разделенном запятыми списке opts, с использованием __builtin_trap, а не подпрограммы библиотеки libubsan. Если этот параметр включен для определенного санитайзера, он имеет приоритет над -fsanitize-recover= для этого санитайзера: __builtin_trap будет генерироваться и будет фатальным независимо от того, включено или отключено восстановление с помощью -fsanitize-recover=.

Преимущество этого заключается в том, что библиотека libubsan не нужна и не компонуется, поэтому это можно использовать даже в автономных (freestanding) окружениях.

В настоящее время эта функция работает с -fsanitize=undefined (и его подпараметрами, кроме -fsanitize=vptr), -fsanitize=float-cast-overflow, -fsanitize=float-divide-by-zero и -fsanitize=bounds-strict. Также может быть указан -fsanitize-trap=all, что включает его для подпараметров undefined, -fsanitize=float-cast-overflow, -fsanitize=float-divide-by-zero и -fsanitize=bounds-strict. Если используется -fsanitize-trap=undefined или -fsanitize-trap=all и в командной строке включен -fsanitize=vptr, инструментирование молча игнорируется, так как для инструментирования всегда требуется поддержка libubsan, а использование -fsanitize-trap=vptr запрещено.

-fsanitize-undefined-trap-on-error

Параметр -fsanitize-undefined-trap-on-error является устаревшим эквивалентом -fsanitize-trap=all.

-fsanitize-coverage=trace-pc

Включение инструментирования кода фаззинга на основе покрытия. Вставляет вызов __sanitizer_cov_trace_pc в каждый базовый блок.

-fsanitize-coverage=trace-cmp

Включение инструментирования кода фаззинга на основе потока данных. Вставляет вызов __sanitizer_cov_trace_cmp1, __sanitizer_cov_trace_cmp2, __sanitizer_cov_trace_cmp4 или __sanitizer_cov_trace_cmp8 для целочисленного сравнения, когда оба операнда являются переменными, либо __sanitizer_cov_trace_const_cmp1, __sanitizer_cov_trace_const_cmp2, __sanitizer_cov_trace_const_cmp4 или __sanitizer_cov_trace_const_cmp8 для целочисленного сравнения с одной константой в качестве операнда, __sanitizer_cov_trace_cmpf или __sanitizer_cov_trace_cmpd для сравнений с плавающей точкой (float или double) и __sanitizer_cov_trace_switch для операторов switch.

-fcf-protection=[full|branch|return|none|check]
-fcf-protection

Включите инструментирование кода для повышения безопасности программы путем проверки действительности целевых адресов инструкций передачи управления (таких как косвенный вызов функции, возврат функции, косвенный переход). Это предотвращает перенаправление потока управления на непредвиденную цель. Данная функция предназначена для защиты от таких угроз, как атаки, основанные на возврате (Return-oriented Programming — ROP), и аналогичные атаки, основанные на вызовах/переходах (COP/JOP).

Ключевые слова -fcf-protection= интерпретируются следующим образом.

Значение branch предписывает компилятору выполнять проверку правильности передачи управления в точках инструкций косвенного ветвления, то есть инструкций call/jmp.

Значение return реализует проверку правильности в точке возврата из функции.

Значение full является псевдонимом для одновременного указания branch и return.

Значение check используется для финального компоновщика с оптимизацией во время компоновки (LTO). Выдается ошибка, если объектные файлы LTO скомпилированы с разными значениями -fcf-protection. Значение check игнорируется во время компиляции.

Значение none отключает инструментирование.

-fcf-protection является псевдонимом для -fcf-protection=full. Чтобы переопределить предыдущую опцию -fcf-protection в командной строке, добавьте -fcf-protection=none, а затем -fcf-protection=kind.

Макрос __CET__ определяется при использовании -fcf-protection. Первый бит __CET__ устанавливается в 1 для значения branch, а второй бит __CET__ устанавливается в 1 для return.

Вы также можете использовать атрибут nocf_check, чтобы указать, какие функции и вызовы следует исключить из инструментирования (см. Объявление атрибутов функций).

В настоящее время цель x86 GNU/Linux предоставляет реализацию на основе технологии Intel Control-flow Enforcement Technology (CET), которая работает для процессоров i686 или новее.

-fharden-compares

Для каждого логического теста, который переживает оптимизации gimple и не является условием в условном ветвлении (например, условия, проверяемые для условных пересылок или для сохранения в булевых переменных), генерируйте дополнительный код для вычисления и проверки инвертированного условия, а также для вызова __builtin_trap, если результаты не совпадают. Используйте с «-fharden-conditional-branches», чтобы охватить все условные выражения.

-fharden-conditional-branches

Для каждого невекторизованного условного ветвления, которое переживает оптимизации gimple, генерируйте дополнительный код для вычисления и проверки инвертированного условия, а также для вызова __builtin_trap, если результат окажется неожиданным. Используйте с «-fharden-compares», чтобы охватить все условные выражения.

-fharden-control-flow-redundancy

Генерируйте дополнительный код для установки логических значений (булевых переменных) при входе в базовые блоки, а также для проверки и перехвата (аварийного завершения) при выходах из функций, если логические значения не образуют путь выполнения, совместимый с графом потока управления.

Проверка выполняется перед возвратами, перед обязательными хвостовыми вызовами (см. ниже) и, опционально, перед перехватом вылетающих исключений с помощью -fhardcfr-check-exceptions, перед возвращающими вызовами с помощью -fhardcfr-check-returning-calls и перед вызовами без возврата (noreturn) с помощью -fhardcfr-check-noreturn-calls. Доступны параметры настройки --param hardcfr-max-blocks и --param hardcfr-max-inline-blocks.

Оптимизация хвостовых вызовов происходит слишком поздно, чтобы повлиять на избыточность потока управления, но вызовы, аннотированные интерфейсами фронтенда языка как обязательные хвостовые вызовы, и любые вызовы, помеченные достаточно рано как потенциальные хвостовые вызовы, также должны вызывать проверку перед вызовом, однако эти возможности носят чисто теоретический характер, поскольку такие условия могут быть выполнены только при использовании пользовательских плагинов компилятора.

-fhardcfr-skip-leaf

Отключите -fharden-control-flow-redundancy в концевых функциях (leaf functions).

-fhardcfr-check-exceptions

Когда активна опция -fharden-control-flow-redundancy, проверяйте записанный путь выполнения по графу потока управления в точках выхода по исключениям, так, как если бы тело функции было обернуто обработчиком очистки, который выполнял бы проверку и повторно возбуждал исключение. Эта опция включена по умолчанию; используйте -fno-hardcfr-check-exceptions для ее отключения.

-fhardcfr-check-returning-calls

Когда активна опция -fharden-control-flow-redundancy, проверяйте записанный путь выполнения по графу потока управления перед любым вызовом функции, за которым сразу следует возврат ее результата (если таковой имеется), чтобы не препятствовать оптимизации хвостового вызова, независимо от того, будет ли он в итоге оптимизирован в хвостовой вызов или нет.

Эта опция включается по умолчанию всякий раз, когда включена оптимизация вызовов родственных функций (sibling calls) (см. -foptimize-sibling-calls), но ее можно включить (или отключить, используя ее отрицательную форму) явно, независимо от оптимизаций.

-fhardcfr-check-noreturn-calls=[always|no-xthrow|nothrow|never]

Когда активна опция -fharden-control-flow-redundancy, проверяйте записанный путь выполнения по графу потока управления перед вызовами noreturn: всеми (always), теми, от которых не ожидается возврата управления вызывающей стороне через исключение (no-xthrow, по умолчанию), теми, которые также могут не возвращать управление вызывающей стороне через исключение (nothrow), или ни перед какими из них (never).

Проверка перед функцией noreturn, которая может вернуть управление вызывающей стороне через исключение, может привести к выполнению проверки более одного раза, если исключение перехватывается в вызывающей функции — будь то обработчиком или очисткой. Если также включена опция -fhardcfr-check-exceptions, компилятор попытается избежать связи вызова noreturn с неявно добавленным обработчиком очистки, так как это было бы избыточно по отношению к проверке, выполняемой перед вызовом; однако другие обработчики или очистки в функции, если они активированы, изменят записанный путь выполнения и проверят его снова при достижении другой контрольной точки. Контрольная точка даже может оказаться другим вызовом noreturn, поэтому проверка в конечном итоге может выполняться несколько раз.

Различные оптимизаторы могут приводить к тому, что вызовы будут помечены как noreturn и/или nothrow даже при отсутствии соответствующих атрибутов, что может повлиять на размещение проверок перед вызовами, а также на добавление неявных обработчиков очистки для них. Эта непредсказуемость, а также тот факт, что генерация и повторное возбуждение исключений часто сводятся к неявному вызову функций noreturn, сделали no-xthrow настройкой по умолчанию для этой опции: она исключает из обработки noreturn только внутренние функции, используемые для (повторного) возбуждения исключений, на которые эти оптимизации не влияют.

-fhardened

Включите набор флагов для C и C++, которые улучшают безопасность генерируемого кода без влияния на его ABI. Точный набор включаемых флагов может изменяться между основными выпусками GCC, но в настоящее время он включает:

-D_FORTIFY_SOURCE=3
-D_GLIBCXX_ASSERTIONS
-ftrivial-auto-var-init=zero
-fPIE  -pie  -Wl,-z,relro,-z,now
-fstack-protector-strong
-fstack-clash-protection
-fcf-protection=full (x86 GNU/Linux only)

Список опций, включаемых параметром -fhardened, может быть сгенерирован с помощью опции --help=hardened.

Если системная библиотека glibc старше версии 2.35, вместо этого используется -D_FORTIFY_SOURCE=2.

Эта опция предназначена для использования в сборках для продакшена, а не только владельцами отладочных сборок.

В настоящее время -fhardened поддерживается только для целей GNU/Linux.

-fhardened включает конкретную опцию только в том случае, если она еще не была указана где-либо в командной строке. Например, -fhardened -fstack-protector включит только -fstack-protector, но не -fstack-protector-strong.

-fstack-protector

Генерируйте дополнительный код для проверки переполнения буфера, такого как атаки по разрушению стека (stack smashing attacks). Это делается путем добавления защитной переменной (канарейки) к функциям с уязвимыми объектами. Сюда входят функции, которые вызывают alloca, и функции с буферами размером 8 байт или более. Защитные переменные инициализируются при входе в функцию и проверяются при выходе из нее. Если проверка защиты не удалась, выводится сообщение об ошибке, и программа завершает работу. Учитываются только переменные, фактически выделенные в стеке; оптимизированные переменные или переменные, размещенные в регистрах, не учитываются.

-fstack-protector-all

Аналогично -fstack-protector, за исключением того, что защищены все функции.

-fstack-protector-strong

Аналогично -fstack-protector, но включает дополнительные функции для защиты — те, которые имеют определения локальных массивов или содержат ссылки на адреса локального фрейма. Учитываются только переменные, фактически выделенные в стеке; оптимизированные переменные или переменные, размещенные в регистрах, не учитываются.

-fstack-protector-explicit

Аналогично -fstack-protector, но защищает только те функции, которые имеют атрибут stack_protect.

-fstack-check

Генерируйте код для проверки того, что вы не выходите за границы стека. Вы должны указать этот флаг, если вы работаете в среде с несколькими потоками, но вам редко нужно указывать его в однопоточной среде, поскольку переполнение стека автоматически обнаруживается практически на всех системах, если существует только один стек.

Обратите внимание, что этот переключатель на самом деле не производит проверку; ее должна выполнять операционная система или среда выполнения языка. Переключатель инициирует генерацию кода для обеспечения того, чтобы они видели расширение стека.

Вы можете дополнительно указать строковый параметр: «no» означает отсутствие проверки, «generic» означает принудительное использование проверки старого типа, «specific» означает использование лучшего метода проверки и эквивалентно голому ключу -fstack-check.

Проверка старого типа — это универсальный механизм, не требующий специальной поддержки цели в компиляторе, но обладающий следующими недостатками:

  1. Измененная стратегия выделения памяти для крупных объектов: они всегда выделяются динамически, если их размер превышает фиксированный порог. Обратите внимание, что это может изменить семантику некоторого кода.
  2. Фиксированное ограничение на размер статического фрейма функций: при его превышении определенной функцией проверка стека становится ненадежной, и компилятор выдает предупреждение.
  3. Неэффективность: производительность кода страдает как из-за измененной стратегии выделения памяти, так и из-за универсальной реализации.

Обратите внимание, что проверка стека старого типа также является резервным методом для значения «specific», если в компилятор не была добавлена поддержка для конкретной цели.

Параметр «-fstack-check=» разработан для нужд Ada по обнаружению бесконечной рекурсии и переполнения стека. «specific» — отличный выбор при компиляции кода на Ada. Обычно этого недостаточно для защиты от атак типа stack-clash (столкновение стеков). Для защиты от них вам понадобится -fstack-clash-protection.

-fstack-clash-protection

Генерируйте код для предотвращения атак в стиле stack-clash. Когда эта опция включена, компилятор выделяет только одну страницу пространства стека за раз, и к каждой странице осуществляется доступ сразу после выделения. Таким образом, это предотвращает перепрыгивание выделения памяти через любые защитные страницы стека, предоставляемые операционной системой.

Большинство целевых платформ не полностью поддерживают защиту от столкновения стеков (stack clash protection). Однако на поддерживающих их платформах -fstack-clash-protection защищает динамические выделения стека. -fstack-clash-protection также может обеспечивать ограниченную защиту для статических выделений стека, если целевая платформа поддерживает -fstack-check=specific.

-fstack-limit-register=reg
-fstack-limit-symbol=sym
-fno-stack-limit

Генерируйте код, гарантирующий, что стек не вырастет за определенное значение — либо значение регистра, либо адрес символа. Если требуется больший стек, во время выполнения генерируется сигнал. Для большинства целевых платформ сигнал генерируется до того, как стек выйдет за границу, поэтому можно перехватить сигнал без принятия специальных мер предосторожности.

Например, если стек начинается с абсолютного адреса «0x80000000» и растет вниз, вы можете использовать флаги -fstack-limit-symbol=__stack_limit и -Wl,--defsym,__stack_limit=0x7ffe0000, чтобы ограничить стек размером 128 КБ. Обратите внимание, что это может работать только с компоновщиком GNU.

Вы можете локально переопределить проверку лимита стека с помощью атрибута функции no_stack_limit (см. Объявление атрибутов функций).

-fsplit-stack

Генерируйте код для автоматического разделения стека до его переполнения. Полученная программа имеет неразрывный (discontiguous) стек, который может переполниться только в том случае, если программа не в состоянии выделить больше памяти. Это наиболее полезно при запуске многопоточных программ, поскольку больше не нужно рассчитывать оптимальный размер стека для каждого потока. В настоящее время это реализовано только для архитектур x86 под управлением GNU/Linux.

Когда код, скомпилированный с -fsplit-stack, вызывает код, скомпилированный без -fsplit-stack, для выполнения последнего кода может оказаться недостаточно доступного пространства стека. Если компиляция всего кода, включая библиотечный, с опцией -fsplit-stack-fsplit-stack, всегда имел большой стек. Поддержка этого реализована в компоновщике gold в GNU binutils версии 2.21 и более поздних.

-fstrub=disable

Полностью отключите очистку стека (stack scrubbing), игнорируя любые атрибуты strub. См. раздел Общие атрибуты типов.

-fstrub=strict

Функции по умолчанию используют режим strub disabled и строго применяют ограничение: функции с режимами, поддерживающими strub-callable (at-calls, callable и always_inline internal), могут быть callable только функциями в режимах с поддержкой strub (at-calls и internal).

-fstrub=relaxed

Восстанавливает настройку очистки стека (strub) по умолчанию, а именно: strub включается только по мере необходимости в соответствии с атрибутами strub, связанными с типами функций и данных. Relaxed означает, что контекстам очистки (strub contexts) запрещено вызывать только функции, явно связанные с режимом strub disabled. Этот параметр полезен только для переопределения других параметров -fstrub=*, которые предшествуют ему в командной строке.

-fstrub=at-calls

Включить режим at-calls strub, где это жизнеспособно. Основное назначение этого параметра — тестирование. Он задействует механизм strub в сценариях, строго локальных для единицы трансляции. Этот режим strub изменяет интерфейсы функций, поэтому любая функция, видимая для других единиц трансляции или для которой берется адрес, не будет затронута этим параметром. Параметры оптимизации также могут влиять на применимость. Подробную информацию о требованиях к применимости и допустимости см. в документации по атрибуту strub.

-fstrub=internal

Включить режим internal strub, где это жизнеспособно. Основное назначение этого параметра — тестирование. Этот параметр предназначен для тщательного тестирования частей механизма strub, которые реализуют менее эффективный режим strub, сохраняющий интерфейс. Функции, которые не затронет этот параметр, встречаются довольно редко.

-fstrub=all

Включить некоторый режим strub, где это жизнеспособно. Когда жизнеспособны оба режима очистки (strub), предпочтение отдается at-calls. -fdump-ipa-strubm добавляет атрибуты функций, которые показывают, какой режим был выбран для каждой функции. Основное назначение этого параметра — тестирование для тщательной проверки механизма strub.

-fvtable-verify=[std|preinit|none]

Этот параметр доступен только при компиляции кода C++. Он включает (или выключает при использовании -fvtable-verify=none) функцию безопасности, которая проверяет во время выполнения для каждого виртуального вызова, что указатель на vtable, через который выполняется вызов, является действительным для типа объекта и не был поврежден или перезаписан. Если во время выполнения обнаруживается недействительный указатель на vtable, сообщается об ошибке и выполнение программы немедленно прекращается.

Этот параметр приводит к созданию структур данных во время выполнения при запуске программы, которые используются для проверки указателей на vtable. Параметры ‘std’ и ‘preinit’ управляют моментом создания этих структур данных. В обоих случаях структуры данных создаются до того, как выполнение дойдет до main. Использование -fvtable-verify=std приводит к тому, что структуры данных создаются после загрузки и инициализации разделяемых библиотек. -fvtable-verify=preinit приводит к тому, что они создаются до загрузки и инициализации разделяемых библиотек.

Если этот параметр встречается в командной строке несколько раз с разными значениями, ‘none’ имеет наивысший приоритет по сравнению с ‘std’ и ‘preinit’; ‘preinit’ имеет приоритет над ‘std’.

-fvtv-debug

При использовании в сочетании с -fvtable-verify=std или -fvtable-verify=preinit приводит к вызову отладочных версий функций среды выполнения для функции проверки vtable. Этот флаг также заставляет компилятор записывать в журнал информацию о том, какие указатели на vtable он находит для каждого класса. Эта информация записывается в файл с именем vtv_set_ptr_data.log в директории, указанной в переменной окружения VTV_LOGS_DIR, если она определена, или в текущей рабочей директории в противном случае.

Примечание: Эта функция дописывает данные в файл журнала. Если вам нужен чистый файл журнала, обязательно удалите существующий.

-fvtv-counts

Это отладочный флаг. При использовании в сочетании с -fvtable-verify=std или -fvtable-verify=preinit он заставляет компилятор отслеживать общее количество обнаруженных виртуальных вызовов и количество вставленных проверок. Он также подсчитывает количество вызовов определенных функций библиотеки времени выполнения, которые он вставляет, и записывает эту информацию в журнал для каждой единицы компиляции. Компилятор записывает эту информацию в файл с именем vtv_count_data.log в директории, указанной в переменной окружения VTV_LOGS_DIR, если она определена, или в текущей рабочей директории в противном случае. Он также подсчитывает размер наборов указателей vtable для каждого класса и записывает эту информацию в файл vtv_class_set_sizes.log в той же директории.

Примечание: Эта функция дописывает данные в файлы журнала. Чтобы получить чистые файлы журнала, обязательно удалите существующие.

-finstrument-functions

Генерировать вызовы инструментирования при входе в функции и выходе из них. Сразу после входа в функцию и непосредственно перед выходом из нее следующие профилирующие функции вызываются с адресом текущей функции и места ее вызова. (На некоторых платформах __builtin_return_address не работает за пределами текущей функции, поэтому информация о месте вызова может быть недоступна профилирующим функциям иным образом.)

void __cyg_profile_func_enter (void *this_fn,
                               void *call_site);
void __cyg_profile_func_exit  (void *this_fn,
                               void *call_site);

Первым аргументом является адрес начала текущей функции, который можно точно найти в таблице символов.

Это инструментирование также выполняется для функций, развернутых в строку (инлайнированных) в других функциях. Вызовы профилирования показывают, где концептуально осуществляется вход в встроенную функцию и выход из нее. Это означает, что адресируемые версии таких функций должны быть доступны. Если все ваши использования функции развернуты в строку, это может означать дополнительное увеличение размера кода. Если вы используете extern inline в своем коде на C, должна быть предоставлена адресируемая версия таких функций. (Обычно это и так происходит, но если вам повезет и оптимизатор всегда разворачивает функции в строку, вам может сойти с рук отсутствие статических копий.)

Функции может быть назначен атрибут no_instrument_function, и в этом случае данное инструментирование не выполняется. Это может использоваться, например, для перечисленных выше профилирующих функций, процедур прерывания с высоким приоритетом и любых функций, из которых профилирующие функции нельзя вызывать безопасно (возможно, обработчики сигналов, если подпрограммы профилирования генерируют вывод или выделяют память). См. раздел Общие атрибуты функций.

-finstrument-functions-once

Это аналогично -finstrument-functions, но профилирующие функции вызываются только один раз для инструментированной функции, т. е. первая профилирующая функция вызывается после первого входа в инструментированную функцию, а вторая профилирующая функция вызывается перед выходом, соответствующим этому первому входу.

Определение once для целей этого параметра немного расплывчато, поскольку реализация не защищена от гонок данных. В результате реализация гарантирует лишь то, что профилирующие функции вызываются по крайней мере один раз на процесс и не более одного раз на поток, но вызовы всегда парные, то есть если поток вызывает первую функцию, он вызовет и вторую функцию, если только он никогда не дойдет до выхода из инструментированной функции.

-finstrument-functions-exclude-file-list=file,file,…

Установите список функций, которые исключены из инструментирования (см. описание -finstrument-functions). Если файл, содержащий определение функции, совпадает с одним из file, то эта функция не инструментируется. Совпадение проверяется по подстрокам: если параметр file является подстрокой имени файла, это считается совпадением.

Например:

-finstrument-functions-exclude-file-list=/bits/stl,include/sys

исключает любую встраиваемую (inline) функцию, определенную в файлах, пути которых содержат /bits/stl или include/sys.

Если по какой-то причине вы хотите включить символ запятой ‘,’ в одно из значений sym, напишите ‘\,’. Например, -finstrument-functions-exclude-file-list='\,\,tmp' (обратите внимание на одинарные кавычки вокруг параметра).

-finstrument-functions-exclude-function-list=sym,sym,…

Это аналогично -finstrument-functions-exclude-file-list, но этот параметр задает список имен функций, исключаемых из инструментирования. Сопоставляемое имя функции — это ее видимое для пользователя имя, такое как vector<int> blah(const vector<int> &), а не внутреннее искаженное (mangled) имя (например, _Z4blahRSt6vectorIiSaIiEE). Совпадение проверяется по подстрокам: если параметр sym является подстрокой имени функции, это считается совпадением. Для расширенных идентификаторов C99 и C++ имя функции должно быть задано в кодировке UTF-8, а не с использованием универсальных имен символов.

-fpatchable-function-entry=N[,M]

Генерировать N инструкций NOP прямо в начале каждой функции, причем точка входа в функцию находится перед M-й инструкцией NOP. Если M опущено, по умолчанию используется 0, поэтому точка входа в функцию указывает на адрес прямо у первой инструкции NOP. Инструкции NOP резервируют дополнительное пространство, которое может быть использовано для патчинга любого желаемого инструментирования во время выполнения, при условии, что сегмент кода доступности для записи. Количество пространства можно контролировать косвенно через количество инструкций NOP; используемая инструкция NOP соответствует инструкции, выдаваемой внутренним интерфейсом бэкенда GCC gen_nop. Это поведение зависит от целевой платформы, а также может зависеть от варианта архитектуры и/или других параметров компиляции.

Для идентификации во время выполнения начальные адреса этих областей, которые соответствуют точкам входа их соответствующих функций минус M, дополнительно собираются в секции __patchable_function_entries результирующего бинарного файла.

Обратите внимание, что значение __attribute__ ((patchable_function_entry (N,M))) имеет приоритет над параметром командной строки -fpatchable-function-entry=N,M. Это можно использовать для увеличения размера области или ее полного удаления для отдельной функции. Если N=0, расположение заполнения не записывается.

Инструкции NOP вставляются по адресу входа в функцию — и, возможно, перед ним, в зависимости от M —, даже перед прологом. На PowerPC с ABI ELFv2 для функции с двойными точками входа локальная точка входа по умолчанию является этим адресом входа в функцию. См. параметр -msplit-patch-nops, чтобы изменить это.

Максимальное значение N и M равно 65535. На PowerPC с ABI ELFv2 для функции с двойными точками входа поддерживаемыми значениями для M являются 0, 2, 6 и 14 при неиспользовании -msplit-patch-nops.

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-15.3.0/gcc/Instrumentation-Options.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API