Что именно происходит при компиляции с -funwind-tables? - PullRequest
0 голосов
/ 01 ноября 2018

От: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html

-fexceptions: включить обработку исключений. Создает дополнительный код, необходимый для распространения исключений. Для некоторых целей это означает, что GCC генерирует информацию о разворачивании кадра для всех функций,

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

Может ли кто-нибудь объяснить, с -funwind-tables, что означает «любые необходимые статические данные». На какие данные они ссылаются. И почему данные должны быть сгенерированы? Что произойдет, если эти данные не генерируются? Где эти данные используются для?

И там также написано "похоже на -fexception". Так что я думаю, что он также генерирует информацию о разворачивании кадров Что такое кадр для размотки информации? Кто использует информацию о кадре и как?

В некоторых сообщениях SO я читал, что программы должны компилироваться с этим флагом, чтобы _Unwind_Backtrace работал правильно. Пожалуйста, объясните, как _Unwind_Backtrace использует информацию, сгенерированную -funwind-tables.

1 Ответ

0 голосов
/ 02 ноября 2018

Статические данные, упомянутые для опции -funwind-tables, представляют собой информацию о разворачивании кадра, то есть данные, которые позволяют работающей программе проходить назад стек вызовов функций из заданной точки выполнения. Возвращение к стеку вызовов функций означает переход из контекста выполнения вызываемой функции в контекст вызывающей стороны, то есть то, что обычно происходит, когда вы возвращаете из функции, за исключением того, что информация о разворачивании кадра позволяет вам это делать. из произвольной точки внутри тела функции; Кроме того, вы не обязаны фактически выходить из вызываемой функции, вы можете просто «заглянуть» внутрь контекста вызывающей стороны (например, чтобы извлечь местоположение, из которого была вызвана вызываемая функция), также рекурсивно, но затем продолжить нормальный поток выполнения в вызываемая функция.

Чтобы сделать это, вам нужно иметь доступ к большему количеству информации о скомпилированном коде, чем то, что строго необходимо для того, чтобы программа следовала «нормальному» потоку выполнения. Эта информация (то есть информация о разворачивании фрейма) помещается компоновщиком в специальные разделы компоновщика (например, раздел .eh_frame для платформы x86 или разделы ARM.exidx и .ARM.extab для платформы ARM), предназначенные для этой цели; эти секции компоновщика такие же, которые необходимы в таких языках, как C ++, для реализации обработки исключений, когда поток выполнения может перейти от вызываемой функции к вызывающей стороне в результате возникновения исключения. Если вы отключите генерацию этих данных с помощью опции -fno-unwind-tables, вы не сможете вернуться назад к стеку вызовов функций или использовать исключения C ++.

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

_Unwind_Backtrace() - это функция, реализованная в основных библиотеках GCC (точнее, в libgcc_s), которая позволяет выполнять функцию обратного вызова (предоставляется в качестве аргумента) для каждого кадра в стеке вызовов, то есть начиная с контекста функции вызывающей стороны, переезд к своему абоненту и так далее. См. https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib--unwind-backtrace.html. Опять же, для того, чтобы эта функция могла выполнять свои функции, требуется доступ к информации о разворачивании кадра из соответствующих разделов компоновщика.

...