Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Узнать адрес вызывающей функции (адрес возврата) в GCC  (Прочитано 21486 раз)
0 Пользователей и 1 Гость смотрят эту тему.
PredatorAlpha
Помогающий

us
Offline Offline

« : 20-09-2011 07:22 » 

Добрый день.
Для отладочных целей надо узнать адрес вызывающей функции (адрес возврата) для некой функции в GCC. По идее, этот адрес лежит в стеке, как и локальные переменные. Есть ли какой-то способ у компилятора это узнать?

Добавлено:
Вопрос закрыт.
__builtin_return_address
http://gcc.gnu.org/onlinedocs/gcc/Return-Address.html
« Последнее редактирование: 20-09-2011 16:02 от PredatorAlpha » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 20-09-2011 08:25 » 

В смысле — "у компилятора"? На этапе компиляции? Или что ты имел в виду? Макрос какой-нибудь? Нет, макросы тут не помогут, т.к. адрес возврата динамический и заранее неизвестен (и их может быть несколько). Или смещение в стеке, где хранится адрес? В общем, поясни, чтобы не гадать.
« Последнее редактирование: 20-09-2011 08:27 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
PredatorAlpha
Помогающий

us
Offline Offline

« Ответ #2 : 20-09-2011 08:39 » 

На этапе компиляции. Возможно, у компилятора есть какие-то макросы (??) , что могут прочитать адрес из стека, или вернуть его адрес в стеке.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #3 : 20-09-2011 08:58 » 

PredatorAlpha, Функции распределяются в адрессном пространстве динамически, на этапе линковки. Так что процесс компиляции уже прошел, следовательно на этапе компиляции никакой макрос и не опция компиляции не поможет. Единственное что, можно попросить линковшик выдать маппинг функций.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
PredatorAlpha
Помогающий

us
Offline Offline

« Ответ #4 : 20-09-2011 11:19 » 

Finch, ты что-то не понял. Меня интересует, кто вызвал функцию. Кадр стека одинаков, независимо от того, куда слинкует код функции линковщик.
Теоретически, к адресу возврата можно обратиться так же, как и к локальной переменной. Понятно, что потом надо будет вручную посмотреть в маппинг, что бы узнать, какой функции соответствует адрес возврата.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #5 : 20-09-2011 11:22 » 

PredatorAlpha, А зачем нужен такой хакинг? Я лично не представляю задачу, где бы это пригодилось.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #6 : 20-09-2011 13:12 » 

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

Совершенно верно.

Есть ли какой-то способ у компилятора это узнать?

У компилятора - однозначно нет. Почему именно - одну из причин объяснил Finch. Кроме того, во время компиляции функции неизвестно, кто ее будет вызывать и сколько раз.

А вот на этапе выполнения программы - вполне реально. Правда, решение будет зависеть от реализации. Например, для PC адрес возврата лежит в stack frame по адресу [EBP + 0x4]. Видимо, придется делать ассемблерную вставку.
Записан

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
PredatorAlpha
Помогающий

us
Offline Offline

« Ответ #7 : 20-09-2011 13:22 » 

А вот на этапе выполнения программы - вполне реально. Правда, решение будет зависеть от реализации. Например, для PC адрес возврата лежит в stack frame по адресу [EBP + 0x4]. Видимо, придется делать ассемблерную вставку.
Наверно таки да, прийдётся...
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #8 : 20-09-2011 14:02 » 

PredatorAlpha, А зачем делать хакинг с ассемблером, когда можно по контрольным точккам поставить sprintf(2, "") ?
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 20-09-2011 14:06 » 

Цитата: Finch
можно по контрольным точккам поставить sprintf(2, "")
Это чего такое?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #10 : 20-09-2011 14:17 » 

Ошибочка вышла. Улыбаюсь Нужно fprintf. 2 это дескриптор консоли ошибок. 
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
PredatorAlpha
Помогающий

us
Offline Offline

« Ответ #11 : 20-09-2011 14:20 » 

PredatorAlpha, А зачем делать хакинг с ассемблером, когда можно по контрольным точккам поставить sprintf(2, "") ?
Вообще-то что-то похожее и делается. Но иногда очень интересно узнать, кто всё-таки вызвал эту функцию.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #12 : 20-09-2011 14:22 » 

PredatorAlpha, У тебя я так думаю не слишком много точек, которые напрямую вызывают функцию? Так зачем городить огород?
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
PredatorAlpha
Помогающий

us
Offline Offline

« Ответ #13 : 20-09-2011 14:33 » 

Finch, всего пара сотен... приходится снизу плясать - вот когда вызвали с такими параметрами, то это она, искомая.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #14 : 20-09-2011 14:43 » 

В таких случая хорошо помогает дебагер. В нормальном дебагере можно посмотреть стек вызовов. И делать точки останова по условиям.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
PredatorAlpha
Помогающий

us
Offline Offline

« Ответ #15 : 20-09-2011 15:39 » 

Finch, таки да. Проблема только в том, что отлаживаться приходится на удалённой машине в Линуксе, в котором у меня весьма скромные (мягко говоря) навыки. Это конечно мои личные проблемы, но..

Добавлено через 7 минут:
Кажется, нашёл!
http://gcc.gnu.org/onlinedocs/gcc/Return-Address.html
« Последнее редактирование: 20-09-2011 15:46 от PredatorAlpha » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #16 : 20-09-2011 15:47 » 

Если нет DLL или чужих библиотек - т.е. все исходники свои и собираются в общее решение, то можно развить такую схему:

Код: (C)
#include <stdio.h>

#define DEBUG

#ifndef DEBUG
/* Исходный заголовок */
void calledFunction(int x)
#else
/* Модифицированный заголовок */
void CalledFunction(char *file, int line, int x)
#endif
{
#ifdef DEBUG
        /* Отладочный вывод */
        printf("Line: %i, file: %s\n", line, file);
#endif
        /* Основной код функции */
}

#ifdef DEBUG
/* Макрос, заменяющий исходный вызов на модифицированный */
#define calledFunction(x) (CalledFunction(__FILE__, __LINE__, x))
#endif

void callingFunction1()
{
        /* Исходный вызов функции без изменений */
        calledFunction(0);
}

void callingFunction2()
{
        /* Исходный вызов функции без изменений */
        calledFunction(0);
}

int main()
{
        callingFunction1();
        callingFunction2();
        return 0;
}
На печать выведутся имена файлов и строки в них, в которых происходит вызов функции. Естественно, только те, которые в runtime сработали.
« Последнее редактирование: 20-09-2011 19:41 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
PredatorAlpha
Помогающий

us
Offline Offline

« Ответ #17 : 20-09-2011 16:03 » 

Dimka, спасибо, но уже нашёл! См. выше.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #18 : 20-09-2011 17:20 » 

PredatorAlpha, gdb никто еше не отменял Улыбаюсь Познакомся с ним, довольно мошный дебагер. Работает в командной строке. Принцип довольно простой. Открываеш файл $gdb youprogramm
Затем ставиш брекпоинты break nameof.cpp:25 например, где число это номер строки в файле. Или break main Где main это имя функции.
Запускаеш на исполнение run или r
Чтобы пойти на шаг вперед next или n
Следушая строка кода step
Чтобы продолжить исполнение continue или c
Показать автоматически состояние переменной display name_of_value
Одноразовый показ print name_of_value
Помошь help. Выведет список категорий помоши. Затем help Category
backtrace выводит состояние стека вызовов.
q выход из дебагера.
Как и в обычном Шелле, действуют клавиши истории команд. Клавиша вверх - предыдушая команда. И автодополнения клавиша tab

Вот скромненький список для начала работы.

Кстати как front-end можно использовать NetBeans IDE Позволяет также отлаживаться на удаленной машине. Правда этой его возможностью я не пользовался.
« Последнее редактирование: 20-09-2011 17:42 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #19 : 20-09-2011 17:35 » 

Для gdb также существуют графические frontend-ы (я когда-то пробовал DDD, но, возможно, есть и другие).
На локальной машине нужно запустить сервер X-window, обеспечить к нему доступ от удаленного сервера (например, через ssh), установить переменную окружения DISPLAY и после этого можно запускать любые приложения X-window.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
PredatorAlpha
Помогающий

us
Offline Offline

« Ответ #20 : 20-09-2011 18:55 » 

Спасибо, попробую!
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines