PredatorAlpha
Помогающий
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
Технический
Администратор
Offline
Пол:
|
|
« Ответ #1 : 20-09-2011 08:25 » |
|
В смысле — "у компилятора"? На этапе компиляции? Или что ты имел в виду? Макрос какой-нибудь? Нет, макросы тут не помогут, т.к. адрес возврата динамический и заранее неизвестен (и их может быть несколько). Или смещение в стеке, где хранится адрес? В общем, поясни, чтобы не гадать.
|
|
« Последнее редактирование: 20-09-2011 08:27 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
PredatorAlpha
Помогающий
Offline
|
|
« Ответ #2 : 20-09-2011 08:39 » |
|
На этапе компиляции. Возможно, у компилятора есть какие-то макросы (??) , что могут прочитать адрес из стека, или вернуть его адрес в стеке.
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #3 : 20-09-2011 08:58 » |
|
PredatorAlpha, Функции распределяются в адрессном пространстве динамически, на этапе линковки. Так что процесс компиляции уже прошел, следовательно на этапе компиляции никакой макрос и не опция компиляции не поможет. Единственное что, можно попросить линковшик выдать маппинг функций.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
PredatorAlpha
Помогающий
Offline
|
|
« Ответ #4 : 20-09-2011 11:19 » |
|
Finch, ты что-то не понял. Меня интересует, кто вызвал функцию. Кадр стека одинаков, независимо от того, куда слинкует код функции линковщик. Теоретически, к адресу возврата можно обратиться так же, как и к локальной переменной. Понятно, что потом надо будет вручную посмотреть в маппинг, что бы узнать, какой функции соответствует адрес возврата.
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #5 : 20-09-2011 11:22 » |
|
PredatorAlpha, А зачем нужен такой хакинг? Я лично не представляю задачу, где бы это пригодилось.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
Dale
|
|
« Ответ #6 : 20-09-2011 13:12 » |
|
Для отладочных целей надо узнать адрес вызывающей функции (адрес возврата) для некой функции в GCC. По идее, этот адрес лежит в стеке, как и локальные переменные. Совершенно верно. Есть ли какой-то способ у компилятора это узнать? У компилятора - однозначно нет. Почему именно - одну из причин объяснил Finch. Кроме того, во время компиляции функции неизвестно, кто ее будет вызывать и сколько раз. А вот на этапе выполнения программы - вполне реально. Правда, решение будет зависеть от реализации. Например, для PC адрес возврата лежит в stack frame по адресу [EBP + 0x4]. Видимо, придется делать ассемблерную вставку.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
PredatorAlpha
Помогающий
Offline
|
|
« Ответ #7 : 20-09-2011 13:22 » |
|
А вот на этапе выполнения программы - вполне реально. Правда, решение будет зависеть от реализации. Например, для PC адрес возврата лежит в stack frame по адресу [EBP + 0x4]. Видимо, придется делать ассемблерную вставку. Наверно таки да, прийдётся...
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #8 : 20-09-2011 14:02 » |
|
PredatorAlpha, А зачем делать хакинг с ассемблером, когда можно по контрольным точккам поставить sprintf(2, "") ?
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #9 : 20-09-2011 14:06 » |
|
можно по контрольным точккам поставить sprintf(2, "") Это чего такое?
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #10 : 20-09-2011 14:17 » |
|
Ошибочка вышла. Нужно fprintf. 2 это дескриптор консоли ошибок.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
PredatorAlpha
Помогающий
Offline
|
|
« Ответ #11 : 20-09-2011 14:20 » |
|
PredatorAlpha, А зачем делать хакинг с ассемблером, когда можно по контрольным точккам поставить sprintf(2, "") ?
Вообще-то что-то похожее и делается. Но иногда очень интересно узнать, кто всё-таки вызвал эту функцию.
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #12 : 20-09-2011 14:22 » |
|
PredatorAlpha, У тебя я так думаю не слишком много точек, которые напрямую вызывают функцию? Так зачем городить огород?
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
PredatorAlpha
Помогающий
Offline
|
|
« Ответ #13 : 20-09-2011 14:33 » |
|
Finch, всего пара сотен... приходится снизу плясать - вот когда вызвали с такими параметрами, то это она, искомая.
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #14 : 20-09-2011 14:43 » |
|
В таких случая хорошо помогает дебагер. В нормальном дебагере можно посмотреть стек вызовов. И делать точки останова по условиям.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
PredatorAlpha
Помогающий
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
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #16 : 20-09-2011 15:47 » |
|
Если нет DLL или чужих библиотек - т.е. все исходники свои и собираются в общее решение, то можно развить такую схему: #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
Помогающий
Offline
|
|
« Ответ #17 : 20-09-2011 16:03 » |
|
Dimka, спасибо, но уже нашёл! См. выше.
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
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
Технический
Администратор
Offline
Пол:
|
|
« Ответ #19 : 20-09-2011 17:35 » |
|
Для gdb также существуют графические frontend-ы (я когда-то пробовал DDD, но, возможно, есть и другие). На локальной машине нужно запустить сервер X-window, обеспечить к нему доступ от удаленного сервера (например, через ssh), установить переменную окружения DISPLAY и после этого можно запускать любые приложения X-window.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
PredatorAlpha
Помогающий
Offline
|
|
« Ответ #20 : 20-09-2011 18:55 » |
|
Спасибо, попробую!
|
|
|
Записан
|
|
|
|
|