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
							
						 | 
						
							
								  | 
								
									
									 « Ответ #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
							
						 | 
						
							
								  | 
								
									
									 « Ответ #19 : 20-09-2011 17:35 »   | 
								
								 | 
							  
							 
							Для gdb также существуют графические frontend-ы (я когда-то пробовал DDD, но, возможно, есть и другие). На локальной машине нужно запустить сервер X-window, обеспечить к нему доступ от удаленного сервера (например, через ssh), установить переменную окружения DISPLAY и после этого можно запускать любые приложения X-window.
  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
							 
							... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. 
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						
							PredatorAlpha
							
								Помогающий 
								
								 
								  Offline
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									«  Ответ #20 : 20-09-2011 18:55 »    | 
								
								 | 
							  
							 
							Спасибо, попробую! 
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	 |