7.6 Получение адреса возврата или кадра функции
Эти функции можно использовать для получения информации о вызывающих функциях.
-
Встроенная функция:
void *__builtin_return_address(unsigned int level) -
Эта функция возвращает адрес возврата текущей функции или одной из вызывающих её функций. Аргумент level задаёт количество кадров для просмотра вверх по стеку вызовов. Значение
0возвращает адрес возврата текущей функции, значение1— адрес возврата вызывающей функции, и так далее. При встраивании ожидаемое поведение заключается в том, что функция возвращает адрес функции, в которую происходит возврат. Чтобы обойти это поведение, используйте атрибут функцииnoinline.Аргумент level должен быть целочисленной константой.
На некоторых машинах может быть невозможно определить адрес возврата любой функции, кроме текущей; в таких случаях или при достижении вершины стека эта функция возвращает неопределённое значение. Кроме того,
__builtin_frame_addressможно использовать для определения того, достигнута ли вершина стека.Может потребоваться дополнительная постобработка возвращаемого значения; см.
__builtin_extract_return_addr.Представление адреса возврата, сохранённого в памяти, может отличаться от адреса, возвращаемого
__builtin_return_address. Например, на AArch64 сохранённый адрес может быть искажён механизмом подписи адреса возврата, тогда как адрес, возвращаемый__builtin_return_address, — нет.Вызов этой функции с ненулевым аргументом может привести к непредсказуемым последствиям, включая аварийное завершение вызывающей программы. Поэтому вызовы, считающиеся небезопасными, диагностируются, если задан параметр -Wframe-address. Такие вызовы следует выполнять только при отладке.
На целевых платформах, где адреса кода можно представить как
void *,void *addr = __builtin_extract_return_addr (__builtin_return_address (0));
возвращает адрес кода, по которому вернулась бы текущая функция. Например, такой адрес можно использовать с
dladdrили другими интерфейсами, работающими с адресами кода.
-
Встроенная функция:
void *__builtin_extract_return_addr(void *addr) -
Адрес, возвращаемый
__builtin_return_address, может потребоваться передать этой функции, чтобы получить фактически закодированный адрес. Например, на 31-разрядной платформе S/390 необходимо сбросить старший бит, а на платформах SPARC — прибавить смещение, чтобы получить адрес следующей выполняемой инструкции.Если коррекция не требуется, эта функция просто возвращает addr без изменений.
-
Встроенная функция:
void *__builtin_frob_return_addr(void *addr) Эта функция выполняет обратное действие по отношению к
__builtin_extract_return_addr.
-
Встроенная функция:
void *__builtin_frame_address(unsigned int level) -
Эта функция аналогична
__builtin_return_address, но возвращает адрес кадра функции, а не её адрес возврата. Вызов__builtin_frame_addressсо значением0возвращает адрес кадра текущей функции, со значением1— адрес кадра вызывающей функции, и так далее.Кадр — это область стека, в которой хранятся локальные переменные и сохранённые регистры. Обычно адрес кадра — это адрес первого слова, помещённого функцией в стек. Однако точное определение зависит от процессора и соглашения о вызовах. Если у процессора есть выделенный регистр указателя кадра и у функции есть кадр, то
__builtin_frame_addressвозвращает значение регистра указателя кадра.На некоторых машинах может быть невозможно определить адрес кадра любой функции, кроме текущей; в таких случаях или при достижении вершины стека эта функция возвращает
0, если начальный указатель кадра был правильно инициализирован кодом запуска.Вызов этой функции с ненулевым аргументом может привести к непредсказуемым последствиям, включая аварийное завершение вызывающей программы. Поэтому вызовы, считающиеся небезопасными, диагностируются, если задан параметр -Wframe-address. Такие вызовы следует выполнять только при отладке.
-
Встроенная функция:
void *__builtin_stack_address() -
Эта функция возвращает значение регистра указателя стека со смещением
STACK_ADDRESS_OFFSET, если оно определено.Концептуально возвращаемый этой встроенной функцией адрес является границей между областью стека, выделенной для использования вызывающей функцией, и областью, которую может изменить вызов функции и которую вызывающая функция может безопасно обнулить до или после (но не во время) последовательности вызова.
Аргументы вызываемой функции могут предварительно выделяться в составе кадра стека вызывающей функции или выделяться отдельно для каждого вызова, в зависимости от целевой платформы, поэтому они могут находиться по любую сторону этой границы.
Даже если указатель стека смещён, результат не смещён. Область сохранения регистров в SPARC считается изменяемой при вызовах, а не выделенной для использования вызывающей функцией, поскольку она никогда не используется во время выполнения самой вызывающей функции.
Красные зоны, которыми могут пользоваться только листовые функции, также считаются изменяемыми при вызовах, а не выделенными для использования вызывающей функцией. Это имеет лишь теоретическое значение, поскольку листовые функции не выполняют вызовов, однако постоянное смещение делает эту встроенную функцию более предсказуемой.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-15.3.0/gcc/Return-Address.html