3.11 Варианты программной инструментации
GCC поддерживает ряд параметров командной строки, которые управляют добавлением инструментации во время выполнения в генерируемый код. Например, одной целью инструментации является сбор статистики профилирования для поиска «горячих точек» программы, анализа покрытия кода или оптимизации на основе профилей. Другой класс программной инструментации — добавление проверок во время выполнения для обнаружения ошибок программирования, таких как обращение по некорректному указателю или обращение к элементам массива за пределами допустимого диапазона, а также преднамеренно злонамеренные атаки, такие как переполнение стека или захват таблицы виртуальных функций C++. Также есть общий крючок, который можно использовать для реализации других форм трассировки или инструментации на уровне функций для отладки или анализа программы.
-p-
Создать дополнительный код для записи информации о профилировании, подходящей для программы анализа
prof. Необходимо использовать этот параметр при компиляции файлов исходного кода, для которых требуется информация, и при компоновке. -pg-
Создать дополнительный код для записи информации о профилировании, подходящей для программы анализа
gprof. Необходимо использовать этот параметр при компиляции файлов исходного кода, для которых требуется информация, и при компоновке. -fprofile-arcs-
Добавить код для инструментирования дуг потока программы. Во время выполнения программа записывает, сколько раз выполняется и обрабатывается (или возвращается) каждый ответвление и вызов. На целевых платформах, поддерживающих конструкторы с приоритетной поддержкой, профилирование корректно обрабатывает конструкторы, деструкторы и C++ конструкторы (и деструкторы) классов, используемых как тип глобальной переменной.
При завершении скомпилированной программы она сохраняет эти данные в файл с именем auxname.gcda для каждого файла исходного кода. Эти данные могут использоваться для профилирования оптимизаций (-fbranch-probabilities) или для анализа покрытия тестов (-ftest-coverage). auxname каждого объектного файла генерируется из имени выходного файла, если он явно указан и не является конечным исполняемым файлом, иначе это базовое имя файла исходного кода. В обоих случаях удаляется любой суффикс (например, foo.gcda для входного файла dir/foo.c или dir/foo.gcda для указанного выходного файла -o dir/foo.o). См. Перекрёстное профилирование.
--coverage-
Этот параметр используется для компиляции и компоновки кода, инструментированного для анализа покрытия. Параметр является синонимом для -fprofile-arcs -ftest-coverage (при компиляции) и -lgcov (при компоновке). Для получения более подробной информации см. документацию по этим параметрам.
- Компилируйте файлы исходного кода с помощью -fprofile-arcs плюс параметры оптимизации и генерации кода. Для анализа покрытия тестов используйте дополнительный параметр -ftest-coverage. Вам не нужно профилировать каждый файл исходного кода в программе.
- Компилируйте файлы исходного кода дополнительно с помощью -fprofile-abs-path для создания абсолютных имен путей в файлах .gcno. Это позволяет
gcovнайти правильные исходники в проектах, где компиляция происходит с различными рабочими каталогами. - Компонуйте ваши объектные файлы с помощью -lgcov или -fprofile-arcs (последнее подразумевает первое).
- Запустите программу с представительной рабочей нагрузкой, чтобы сгенерировать информацию о профилировании дуг. Это можно повторить любое количество раз. Вы можете запускать одновременные экземпляры вашей программы, и при условии, что система файлов поддерживает блокировку, файлы данных будут правильно обновлены. Если не используется строгий вариант ISO C,
forkвызовы обнаруживаются и правильно обрабатываются без двойного подсчёта. - Для оптимизации, основанной на профилировании, снова скомпилируйте файлы исходного кода с теми же параметрами оптимизации и генерации кода плюс -fbranch-probabilities (см. Параметры, управляющие оптимизацией).
- Для анализа покрытия тестов используйте
gcovдля создания удобочитаемой информации из файлов .gcno и .gcda. Для получения дополнительной информации обратитесь к документацииgcov.
С -fprofile-arcs для каждой функции вашей программы GCC создаёт граф потока программы, затем находит остовное дерево для графа. Инструментировать необходимо только дуги, которые не находятся в остовном дереве: компилятор добавляет код для подсчёта количества раз выполнения этих дуг. Если дуга является единственным выходом или единственным входом в блок, код инструментирования можно добавить в блок; в противном случае необходимо создать новый базовый блок для размещения кода инструментирования.
-ftest-coverage-
Создать файл заметок, который
gcovутилита анализа покрытия кода (см.gcov—Программа анализа покрытия тестов) может использовать для отображения покрытия программы. Каждый файл исходного кода имеет файл заметок с именем auxname.gcno. Для описания auxname и инструкций по генерации данных анализа покрытия см. параметр -fprofile-arcs выше. Данные покрытия тестов соответствуют файлам исходного кода более точно, если оптимизация не применяется. -fprofile-abs-path-
Автоматически преобразовывать относительные имена файлов исходного кода в абсолютные имена путей в файлах .gcno. Это позволяет
gcovнаходить правильные исходники в проектах, где компиляция происходит с различными рабочими каталогами. -fprofile-dir=path-
Установить каталог для поиска файлов данных профилирования в path. Этот параметр влияет только на данные профилирования, генерируемые -fprofile-generate, -ftest-coverage, -fprofile-arcs и используемые -fprofile-use и -fbranch-probabilities и его связанными параметрами. Можно использовать как абсолютные, так и относительные пути. По умолчанию GCC использует текущий каталог в качестве path, таким образом, файл данных профилирования появляется в том же каталоге, что и объектный файл.
-fprofile-generate-fprofile-generate=path-
Включить параметры, обычно используемые для инструментирования приложения, чтобы создать профиль, полезный для последующей повторной компиляции с оптимизацией на основе обратной связи профилирования. Необходимо использовать -fprofile-generate как при компиляции, так и при компоновке программы.
Включаются следующие параметры: -fprofile-arcs, -fprofile-values, -fvpt.
Если указан path, GCC ищет файлы данных обратной связи профилирования в path. См. -fprofile-dir.
Для оптимизации программы на основе собранной информации о профилировании используйте -fprofile-use. См. Параметры оптимизации для получения дополнительной информации.
-fprofile-update=method-
Изменить метод обновления для приложения, инструментированного для оптимизации на основе обратной связи профилирования. Аргумент method должен быть одним из ‘single’, ‘atomic’ или ‘prefer-atomic’. Первый полезен для однопоточных приложений, а второй предотвращает повреждение профиля, генерируя потокобезопасный код.
Предупреждение: Когда приложение не объединяет все потоки должным образом (или создаёт отсоединяемый поток), файл профиля может быть повреждён.
Использование ‘prefer-atomic’ будет преобразовано либо в ‘atomic’, если это поддерживается целевой платформой, либо в ‘single’ в противном случае. Драйвер GCC автоматически выбирает ‘prefer-atomic’, когда -pthread присутствует в командной строке.
-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 и/или -fcheck-pointer-bounds. -fsanitize=kernel-address-
Включить AddressSanitizer для ядра Linux. Для получения более подробной информации см. https://github.com/google/kasan/wiki. Параметр не может быть использован совместно с -fcheck-pointer-bounds.
-fsanitize=pointer-compare-
Инструментировать операции сравнения (<, <=, >, >=) с операндами указателей. Параметр необходимо использовать совместно с -fsanitize=kernel-address или -fsanitize=address. Параметр не может быть использован совместно с -fsanitize=thread и/или -fcheck-pointer-bounds. Примечание: по умолчанию проверка отключена во время выполнения. Чтобы включить её, добавьте
detect_invalid_pointer_pairs=2в переменную средыASAN_OPTIONS. Используяdetect_invalid_pointer_pairs=1, проверяется только некорректная операция, когда оба указателя не равны null. -fsanitize=pointer-subtract-
Инструментировать вычитание с операндами указателей. Параметр необходимо использовать совместно с -fsanitize=kernel-address или -fsanitize=address. Параметр не может быть использован совместно с -fsanitize=thread и/или -fcheck-pointer-bounds. Примечание: по умолчанию проверка отключена во время выполнения. Чтобы включить её, добавьте
detect_invalid_pointer_pairs=2в переменную средыASAN_OPTIONS. Используяdetect_invalid_pointer_pairs=1, проверяется только некорректная операция, когда оба указателя не равны null. -fsanitize=thread-
Включить ThreadSanitizer, быстрый детектор гонок данных. Инструкции доступа к памяти инструментируются для обнаружения гонок данных. Для получения более подробной информации см. https://github.com/google/sanitizers/wiki#threadsanitizer. Поведение во время выполнения можно изменить, используя переменную среды
TSAN_OPTIONS; см. https://github.com/google/sanitizers/wiki/ThreadSanitizerFlags для списка поддерживаемых параметров. Параметр не может быть использован совместно с -fsanitize=address, -fsanitize=leak и/или -fcheck-pointer-bounds.Обратите внимание, что инструментированные атомарные функции не могут генерировать исключения при работе с недопустимыми адресами памяти при отсутствии исключений от вызовов (-fnon-call-exceptions).
-fsanitize=leak-
Включить LeakSanitizer, детектор утечек памяти. Этот параметр важен только для компоновки исполняемых файлов, и исполняемый файл компонуется с библиотекой, которая переопределяет
mallocи другие функции выделения памяти. Для получения более подробной информации см. https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer. Поведение во время выполнения можно изменить, используя переменную средыLSAN_OPTIONS. Параметр не может быть использован совместно с -fsanitize=thread. -fsanitize=undefined
-
Включить UndefinedBehaviorSanitizer, быстрый детектор неопределённого поведения. Различные вычисления снабжаются инструментированием для обнаружения неопределённого поведения во время выполнения. Текущие подварианты:
-fsanitize=shift-
Этот вариант включает проверку, что результат операции сдвига не неопределён. Обратите внимание, что то, что именно считается неопределённым, немного отличается между C и C++, а также между ISO C90 и C99 и т.д. Этот вариант имеет два подварианта, -fsanitize=shift-base и -fsanitize=shift-exponent.
-fsanitize=shift-exponent-
Этот вариант включает проверку, что второй аргумент операции сдвига не отрицательный и меньше точности первого аргумента, преобразованного к типу с большей точностью.
-fsanitize=shift-base-
Если второй аргумент операции сдвига находится в пределах диапазона, проверяется, что результат операции сдвига не неопределён. Обратите внимание, что то, что именно считается неопределённым, немного отличается между C и C++, а также между ISO C90 и C99 и т.д.
-fsanitize=integer-divide-by-zero-
Обнаружить целочисленное деление на ноль, а также
INT_MIN / -1деление. -fsanitize=unreachable-
С этим вариантом компилятор преобразует вызов
__builtin_unreachableв вызов сообщения об ошибке вместо него. При достижении вызова__builtin_unreachable, поведение неопределённо. -fsanitize=vla-bound-
Этот вариант инструктирует компилятор проверять, что размер массива переменной длины положителен.
-fsanitize=null-
Этот вариант включает проверку указателей. В частности, приложение, построенное с включённым этим вариантом, выведет сообщение об ошибке, когда попытается обратиться по адресу NULL-указателя, или если ссылка (возможно, ссылка на rvalue) привязана к NULL-указателю, или если метод вызывается на объекте, на который указывает NULL-указатель.
-fsanitize=return-
Этот вариант включает проверку операторов возврата. Программы, построенные с включённым этим вариантом, выведут сообщение об ошибке, когда конец функции с не-void типом достигнут, но значение не возвращено. Этот вариант работает только в C++.
-fsanitize=signed-integer-overflow-
Этот вариант включает проверку переполнения знакового целого. Мы проверяем, что результат
+,*, и как унарной, так и бинарной-не переполняется в знаковом арифметическом формате. Обратите внимание, что необходимо учитывать правила продвижения целых типов. То есть следующее не является переполнением:signed char a = SCHAR_MAX; a++;
-fsanitize=bounds-
Этот вариант включает инструментирование границ массива. Обнаруживаются различные обращения за пределы границ. Члены массивов с гибким размером, массивы, подобные членам массивов с гибким размером, и инициализаторы переменных со статической областью хранения не инструментируются. Этот вариант нельзя использовать совместно с -fcheck-pointer-bounds.
-fsanitize=bounds-strict-
Этот вариант включает жёсткое инструментирование границ массива. Обнаруживаются большинство обращений за пределы границ, включая члены массивов с гибким размером и массивы, подобные членам массивов с гибким размером. Инициализаторы переменных со статической областью хранения не инструментируются. Этот вариант нельзя использовать совместно с -fcheck-pointer-bounds.
-fsanitize=alignment-
Этот вариант включает проверку выравнивания указателей при обращении по ним, или при привязке ссылки к недостаточно выровненному объекту, или при вызове метода или конструктора на недостаточно выровненном объекте.
-fsanitize=object-size-
Этот вариант включает инструментирование операций с памятью, использующих функцию
__builtin_object_size. Обнаруживаются различные обращения по указателям за пределы границ. -fsanitize=float-divide-by-zero-
Обнаружить деление с плавающей точкой на ноль. В отличие от других похожих вариантов, -fsanitize=float-divide-by-zero не включается -fsanitize=undefined, так как деление с плавающей точкой на ноль может быть законным способом получения бесконечностей и NaN.
-fsanitize=float-cast-overflow-
Этот вариант включает проверку преобразования типов с плавающей точкой в целочисленный тип. Мы проверяем, что результат преобразования не переполняется. В отличие от других похожих вариантов, -fsanitize=float-cast-overflow не включается -fsanitize=undefined. Этот вариант не работает хорошо с включёнными
FE_INVALIDисключениями. -fsanitize=nonnull-attribute-
Этот вариант включает инструментирование вызовов, проверяя, что значения null не передаются аргументам, помеченным как требующие не-null значение атрибутом функции
nonnull. -fsanitize=returns-nonnull-attribute-
Этот вариант включает инструментирование операторов возврата в функциях, помеченных атрибутом функции
returns_nonnull, для обнаружения возвращаемых значений null из таких функций. -fsanitize=bool-
Этот вариант включает инструментирование загрузки из bool. Если загружено значение отличное от 0/1, выдаётся ошибка во время выполнения.
-fsanitize=enum-
Этот вариант включает инструментирование загрузки из типа перечисления. Если загружено значение, выходящее за пределы диапазона значений для типа перечисления, выдаётся ошибка во время выполнения.
-fsanitize=vptr-
Этот вариант включает инструментирование вызовов функций-членов C++, доступа к членам и некоторых преобразований между указателями на базовый и производный классы, чтобы проверить, что ссылка на объект имеет правильный динамический тип.
-fsanitize=pointer-overflow-
Этот вариант включает инструментирование арифметики указателей. Если арифметика указателей переполняется, выдаётся ошибка во время выполнения.
-fsanitize=builtin-
Этот вариант включает инструментирование аргументов выбранных встроенных функций. Если невалидное значение передано такому аргументу, выдаётся ошибка во время выполнения. Например, передача 0 как аргумента к
__builtin_ctzили__builtin_clzвызывает неопределённое поведение и диагностируется этим вариантом.
В то время как -ftrapv вызывает генерацию ловушек для знаковых переполнений, -fsanitize=undefined выдаёт сообщение об ошибке. В настоящее время это работает только для языков семейства C.
-fno-sanitize=all-
Этот вариант отключает все ранее включённые инструменты проверки. -fsanitize=all не допускается, так как некоторые инструменты не могут использоваться вместе.
-fasan-shadow-offset=number-
Этот вариант заставляет GCC использовать пользовательский смещение тени в проверках AddressSanitizer. Это полезно для экспериментов с различными макетами памяти тени в ядре AddressSanitizer.
-fsanitize-sections=s1,s2,...-
Проверка глобальных переменных в выбранных пользовательских секциях. si может содержать подстановочные знаки.
-fsanitize-recover[=opts]-
-fsanitize-recover= управляет режимом восстановления ошибок для инструментов проверки, упомянутых в списке через запятую opts. Включение этого варианта для компонента проверки приводит к попытке продолжить выполнение программы так, как будто ошибки не произошло. Это означает, что несколько ошибок во время выполнения могут быть сообщены в одной сессии работы программы, и код выхода программы может указывать на успех, даже если ошибки были сообщены. Вариант -fno-sanitize-recover= может быть использован для изменения этого поведения: только первая обнаруженная ошибка сообщается, и программа завершается с ненулевым кодом выхода.
В настоящее время эта функция работает только для -fsanitize=undefined (и его подвариантов, за исключением -fsanitize=unreachable и -fsanitize=return), -fsanitize=float-cast-overflow, -fsanitize=float-divide-by-zero, -fsanitize=bounds-strict, -fsanitize=kernel-address и -fsanitize=address. Для этих инструментов проверки режим восстановления включён по умолчанию, за исключением -fsanitize=address, для которого эта функция является экспериментальной. -fsanitize-recover=all и -fno-sanitize-recover=all также принимаются, первый включает восстановление для всех инструментов, которые его поддерживают, а второй отключает восстановление для всех инструментов, которые его поддерживают.
Даже если режим восстановления включён со стороны компилятора, он должен быть также включён со стороны библиотеки времени выполнения, иначе ошибки остаются фатальными. Библиотека времени выполнения по умолчанию использует
halt_on_error=0для ThreadSanitizer и UndefinedBehaviorSanitizer, а по умолчанию для AddressSanitizer являетсяhalt_on_error=1. Это можно переопределить, установив флагhalt_on_errorв соответствующей переменной среды.Синтаксис без явного параметра opts устарел. Он эквивалентен указанию списка opts:
undefined,float-cast-overflow,float-divide-by-zero,bounds-strict
-fsanitize-address-use-after-scope-
Включить проверку локальных переменных для обнаружения ошибок использования после выхода из области видимости. Этот вариант устанавливает -fstack-reuse в ‘none’.
-fsanitize-undefined-trap-on-error-
Вариант -fsanitize-undefined-trap-on-error инструктирует компилятор сообщать об неопределённом поведении, используя
__builtin_trapвместоlibubsanбиблиотечной функции. Преимущество в том, что библиотекаlibubsanне требуется и не подключается, поэтому это пригодно даже в средах без подключения к библиотекам. -fsanitize-coverage=trace-pc-
Включить инструментирование кода для направленного на основе покрытия fuzzing. Вставляет вызов
__sanitizer_cov_trace_pcв каждый базовый блок. -fsanitize-coverage=trace-cmp-
Включить инструментирование кода, направленного на fuzzing с учётом потока данных. Вставляет вызов
__sanitizer_cov_trace_cmp1,__sanitizer_cov_trace_cmp2,__sanitizer_cov_trace_cmp4или__sanitizer_cov_trace_cmp8для целочисленных сравнений с обеими операндами переменными или__sanitizer_cov_trace_const_cmp1,__sanitizer_cov_trace_const_cmp2,__sanitizer_cov_trace_const_cmp4или__sanitizer_cov_trace_const_cmp8для целочисленных сравнений с одним операндом константой,__sanitizer_cov_trace_cmpfили__sanitizer_cov_trace_cmpdдля сравнений с плавающей точкой или double, и__sanitizer_cov_trace_switchдля операторов switch. -fbounds-check-
Для фронтендов, которые его поддерживают, генерировать дополнительный код для проверки того, что индексы, используемые для доступа к массивам, находятся в объявленном диапазоне. В настоящее время это поддерживается только фронтендом Fortran, где этот вариант по умолчанию равен false.
-fcheck-pointer-bounds
-
Включить инструментацию Pointer Bounds Checker. Каждая ссылка на память снабжается проверкой указателя, используемого для доступа к памяти, на соответствие границам, связанным с этим указателем.
В настоящее время реализация доступна только для Intel MPX, поэтому для включения этой функции требуется целевая платформа x86 GNU/Linux и опция -mmpx. Инструментация на основе MPX требует библиотеки времени выполнения для включения MPX в аппаратном обеспечении и обработки сигналов нарушения границ. По умолчанию при использовании опций -fcheck-pointer-bounds и -mmpx для компоновки программы, драйвер GCC компонует с библиотеками libmpx и libmpxwrappers. Проверка границ при вызовах динамических библиотек требует компоновщика с поддержкой -z bndplt; если GCC был сконфигурирован с компоновщиком без поддержки этой опции (включая компоновщик Gold и более старые версии ld), выдается предупреждение, если вы компонуете с -mmpx без указания также -static, поскольку общая эффективность защиты проверки границ снижается. См. также -static-libmpxwrappers.
Инструментация на основе MPX может быть использована для отладки, а также может быть включена в производственный код для повышения безопасности программы. В зависимости от использования, у вас могут быть разные требования к библиотеке времени выполнения. Текущая версия библиотеки времени выполнения MPX больше ориентирована на использование в качестве инструмента отладки. Использование библиотеки времени выполнения MPX подразумевает -lpthread. См. также -static-libmpx. Поведение библиотеки времени выполнения можно настроить с помощью различных
CHKP_RT_*переменных среды. Для получения более подробной информации см. https://gcc.gnu.org/wiki/Intel%20MPX%20support%20in%20the%20GCC%20compiler.Сгенерированная инструментация может контролироваться различными опциями -fchkp-* и атрибутом поля структуры
bnd_variable_size(см. Атрибуты типов) иbnd_legacy, а такжеbnd_instrumentатрибутами функций (см. Атрибуты функций). GCC также предоставляет ряд встроенных функций для управления Pointer Bounds Checker. Более подробную информацию см. в разделе Встроенные функции Pointer Bounds Checker. -fchkp-check-incomplete-type-
Генерировать проверки границ указателей для переменных с неполным типом. Включено по умолчанию.
-fchkp-narrow-bounds-
Управляет границами, используемыми Pointer Bounds Checker для указателей на поля объекта. Если сужение включено, используются границы поля. В противном случае используются границы объекта. См. также -fchkp-narrow-to-innermost-array и -fchkp-first-field-has-own-bounds. Включено по умолчанию.
-fchkp-first-field-has-own-bounds-
Принудительно заставляет Pointer Bounds Checker использовать суженные границы для адреса первого поля в структуре. По умолчанию указатель на первое поле имеет те же границы, что и указатель на всю структуру.
-fchkp-flexible-struct-trailing-arrays-
Принудительно заставляет Pointer Bounds Checker обрабатывать все хвостовые массивы в структурах как потенциально гибкие. По умолчанию только поля массива с нулевой длиной или отмеченные атрибутом bnd_variable_size обрабатываются как гибкие.
-fchkp-narrow-to-innermost-array-
Принудительно заставляет Pointer Bounds Checker использовать границы самых внутренних массивов в случае доступа к вложенному статическому массиву. По умолчанию эта опция отключена, и используются границы внешнего массива.
-fchkp-optimize-
Включает оптимизации Pointer Bounds Checker. Включено по умолчанию на уровнях оптимизации -O, -O2, -O3.
-fchkp-use-fast-string-functions-
Включает использование
*_nobndверсий функций строк (без копирования границ) Pointer Bounds Checker. Отключено по умолчанию. -fchkp-use-nochk-string-functions-
Включает использование
*_nochkверсий функций строк (без проверки границ) Pointer Bounds Checker. Отключено по умолчанию. -fchkp-use-static-bounds-
Разрешить Pointer Bounds Checker генерировать статические границы, содержащие границы статических переменных. Включено по умолчанию.
-fchkp-use-static-const-bounds-
Использовать статически инициализированные границы для константных границ вместо генерации их каждый раз по мере необходимости. По умолчанию включено, когда включена -fchkp-use-static-bounds.
-fchkp-treat-zero-dynamic-size-as-infinite-
С этой опцией объекты с неполным типом, размер которых динамически получен равен нулю, обрабатываются Pointer Bounds Checker как имеющие бесконечный размер. Эта опция может быть полезна, если программа связана с библиотекой, в которой отсутствует информация о размере для некоторых символов. Отключено по умолчанию.
-fchkp-check-read-
Инструктирует Pointer Bounds Checker генерировать проверки для всех чтений из памяти. Включено по умолчанию.
-fchkp-check-write-
Инструктирует Pointer Bounds Checker генерировать проверки для всех записей в память. Включено по умолчанию.
-fchkp-store-bounds-
Инструктирует Pointer Bounds Checker генерировать сохранения границ для записи указателя. Включено по умолчанию.
-fchkp-instrument-calls-
Инструктирует Pointer Bounds Checker передавать границы указателя в вызовы. Включено по умолчанию.
-fchkp-instrument-marked-only-
Инструктирует Pointer Bounds Checker выполнять инструментацию только для функций, помеченных атрибутом
bnd_instrument(см. Атрибуты функций). Отключено по умолчанию. -fchkp-use-wrappers-
Разрешает Pointer Bounds Checker заменять вызовы встроенных функций вызовами функций-оберток. При компоновке программы с использованием -fchkp-use-wrappers, драйвер GCC автоматически подключает libmpxwrappers. См. также -static-libmpxwrappers. Включено по умолчанию.
-fcf-protection=[full|branch|return|none]-
Включить инструментацию кода для перемещений потока управления, чтобы повысить безопасность программы путем проверки того, что целевые адреса инструкций перемещения потока управления (например, косвенный вызов функции, возврат функции, косвенный переход) являются допустимыми. Это предотвращает перенаправление потока управления на непредвиденный целевой адрес. Это предназначено для защиты от таких угроз, как Return-oriented Programming (ROP), и аналогичного программирования на основе вызовов/переходов (COP/JOP).
Значение
branchсообщает компилятору о реализации проверки валидности перемещения потока управления в точке инструкций косвенного перехода, т.е. инструкций вызова/перехода. Значениеreturnреализует проверку валидности в точке возврата из функции. Значениеfullявляется псевдонимом для указания какbranch, так иreturn. Значениеnoneотключает инструментацию.Макрос
__CET__определяется при использовании -fcf-protection. Первый бит__CET__устанавливается в 1 для значенияbranch, а второй бит__CET__устанавливается в 1 для значенияreturn.Вы также можете использовать атрибут
nocf_checkдля определения функций и вызовов, которые следует пропустить из инструментации (см. Атрибуты функций).В настоящее время целевая платформа x86 GNU/Linux предоставляет реализацию на основе технологии Intel Control-flow Enforcement Technology (CET).
-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. Его обычно недостаточно для защиты от атак типа stack-clash. Для защиты от них вам нужна ‘-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 и более поздних.
-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);Первый аргумент — адрес начала текущей функции, который можно точно найти в таблице символов.
Эта инструментация также выполняется для функций, расширенных по inline в другие функции. Вызовы профилирования показывают, где концептуально выполняется вход и выход в inline-функцию. Это означает, что должны быть доступны адресованные версии таких функций. Если все ваши использования функции расширены inline, это может означать дополнительное увеличение размера кода. Если вы используете
extern inlineв вашем коде C, должна быть предоставлена адресованная версия таких функций. (Это обычно так и есть, но если вам повезёт, и оптимизатор всегда расширяет функции inline, вы можете обойтись без предоставления статических копий.)Функции могут иметь атрибут
no_instrument_function, в этом случае эта инструментация не выполняется. Это можно использовать, например, для профилирующих функций, перечисленных выше, высокоприоритетных прерываний и любых функций, из которых профилирующие функции не могут быть вызваны безопасно (возможно, обработчики сигналов, если профилирующие процедуры генерируют вывод или выделяют память). -finstrument-functions-exclude-file-list=file,file,…-
Указать список функций, исключённых из инструментации (см. описание -finstrument-functions). Если файл, содержащий определение функции, совпадает с одним из file, то эта функция не подвергается инструментации. Совпадение выполняется по подстрокам: если параметр file является подстрокой имени файла, то это считается соответствием.
Например:
-finstrument-functions-exclude-file-list=/bits/stl,include/sys
исключает любую встроенную функцию, определённую в файлах, имена путей которых содержат /bits/stl или include/sys.
Если по какой-то причине вы хотите включить символ ‘,’ в один из sym, напишите ‘\,’. Например, -finstrument-functions-exclude-file-list='\,\,tmp' (обратите внимание на одинарные кавычки, окружающие параметр).
-finstrument-functions-exclude-function-list=sym,sym,…-
Это аналогично -finstrument-functions-exclude-file-list, но этот параметр устанавливает список имён функций, которые будут исключены из инструментации. Имя функции, с которым производится сравнение, — это её имя, видимое пользователю, например,
vector<int> blah(const vector<int> &), а не внутреннее, замаскированное имя (например,_Z4blahRSt6vectorIiSaIiEE). Сопоставление выполняется по подстрокам: если параметр sym является подстрокой имени функции, это считается соответствием. Для идентификаторов C99 и расширенных идентификаторов C++ имя функции должно быть задано в UTF-8, а не с использованием универсальных имён символов. -fpatchable-function-entry=N[,M]-
Генерировать N команд NOP в начале каждой функции, с точкой входа в функцию перед M-ой командой NOP. Если M опущено, он по умолчанию равен
0, поэтому точка входа в функцию соответствует адресу сразу после первой команды NOP. Команды NOP резервируют дополнительное пространство, которое может использоваться для вставки желаемой инструментации во время выполнения, при условии, что сегмент кода может быть записан. Размер пространства косвенно контролируется числом команд NOP; используемая команда NOP соответствует команде, выдаваемой внутренним интерфейсом GCC back-endgen_nop. Это поведение зависит от целевой платформы и может также зависеть от архитектурного варианта и/или других параметров компиляции.Для идентификации во время выполнения начальные адреса этих областей, соответствующие адресам входа в соответствующую функцию минус M, также собираются в сегменте
__patchable_function_entriesрезультирующего двоичного файла.Обратите внимание, что значение
__attribute__ ((patchable_function_entry (N,M)))имеет приоритет над параметром командной строки -fpatchable-function-entry=N,M. Это можно использовать для увеличения размера области или для её полного удаления по отдельной функции. ЕслиN=0, место расположения заполнения не записывается.Команды NOP вставляются в — и, возможно, перед, в зависимости от M — адрес входа в функцию, даже перед прологом.
Далее: Параметры препроцессора, Предыдущий: Параметры оптимизации, Вверх: Вызов GCC [Содержание][Индекс]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-8.5.0/gcc/Instrumentation-Options.html