2013-09-24 6 views
4

Сегодня, когда я отлаживаю свой код на Linux, я вдруг обнаружил, что адрес функции в gdb отличается от того, что nm показывает. (Исполняемый файл статически связан.)Почему адрес функции, отображаемый gdb, отличается от адреса функции nm?

Я думал, что адреса, которые они показывают, должны были быть такими же, как и все логические адреса. Но сегодняшнее открытие меня смущает.

Кто-нибудь знает, почему они разные?

Я пишу следующую простую программу, чтобы проиллюстрировать, с чем я столкнулся.

void fo()    
{      
    return ;   
}      


void foo()    
{      
    fo();    
}      

int add(int a, int b) 
{      
    foo();    
    return a + b;  
}      

int main()    
{      
    int a = 1;   
    int b = 2;   
    add(a, b);   

    return 0;   
}     

выход нм является:

0000000000400584 T _Z2fov 
0000000000400595 T _Z3addii 
000000000040058a T _Z3foov 
00000000004005b3 T main 

, но когда я использую GDB для отладки скомпилированный исполняемый файл, поставив точку в строке 3.

(gdb) bt 
#0 fo() at test.cpp:4 
#1 0x0000000000400593 in foo() at test.cpp:9 
#2 0x00000000004005a8 in add (a=1, b=2) at test.cpp:14 
#3 0x00000000004005d8 in main() at test.cpp:22 

вы можете увидеть что выход gdb отличается от нм.

ответ

6

Поскольку nm показывает адрес начало функции, в то время как gdbStackTrace показывает, где именно исполнение имеет прогрессировало внутри функции. Именно он должен быть обратным адресом в кадре стека, то есть указателем на следующую команду, которая должна выполняться в функции, когда возвращается функция над ней в стеке.

Обратите внимание, что если вы просто спросите gdb для указателя функции, оценив выражение указателя функции, он должен указать тот же адрес, что и nm.

+0

Aha! Это оно! Большое спасибо. – Alex

+2

Если бинарный файл не был перемещен при загрузке и т. Д. И т. Д., Так далее и т. Д. – Vatine

+0

@Vatine, не могли бы вы сказать больше об этом? может ли двоичное перемещение повлиять на адрес символа? – Alex

Смежные вопросы