Próbuję zrozumieć kod wykonywalny generowany przez GCC (4.4.3) dla maszyny x86_64 działającej pod systemem Ubuntu Linux. W szczególności nie rozumiem, w jaki sposób kod śledzi ramki stosów. W dawnych czasach, w kodzie 32-bitowym, byłem przyzwyczajony do tego „prolog” w niemal każdej funkcji:x86_64 wywoływanie konwencji i ramek stosów
push %ebp
movl %esp, %ebp
Następnie, na końcu funkcji, nie przyjdzie to „epilog” albo
sub $xx, %esp # Where xx is a number based on GCC's accounting.
pop %ebp
ret
lub po prostu
leave
ret
który realizuje to samo:
- Ustaw wskaźnik stosu na szczycie aktualnej ramki, tuż pod adresem zwrotnym . Przywróć starą wartość wskaźnika ramki.
W kodzie 64-bitowym, jak widzę ją przez objdump demontażu, wiele funkcji nie przestrzegają tej konwencji - nie naciskać% RBP, a następnie zapisać% RSP do% RBP, w jaki sposób jak debugger GDB tworzy ślad zwrotny?
Moim prawdziwym celem jest próba znalezienia rozsądnego adresu, który mógłby zostać uznany za najwyższy (najwyższy adres) stosu użytkownika, gdy wykonanie osiągnie początek dowolnej funkcji w programie, gdzie być może wskaźnik stosu przesunął się w dół. Na przykład "początkowy" adres pierwotny argv byłby idealny - ale nie mam do niego dostępu z dowolnej funkcji, która wywołuje główne wywołania. Początkowo myślałem, że mogę użyć starej metody śledzenia wstecznego: ściganie zapisanych wartości wskaźnika ramki do momentu, gdy zapisana wartość będzie równa 0 - wtedy następny następny może być liczony jako najwyższa wartość praktyczna. (To nie jest to samo co uzyskanie adresu argv, ale będzie to robić - powiedzmy, aby znaleźć wartość wskaźnika stosu na _start lub jakikolwiek _start wywołuje [np. __libc_start_main].) Teraz nie wiem jak uzyskać równoważny adres w 64-bitowym kodzie.
Dzięki.
Hm rzeczywiście. I nie chodzi tylko o '-fomit-frame-pointer'. –
Czy próbowałeś -bar-omit-frame-wskaźnik? Czy możesz skompilować ten inny kod z tą flagą? –
Kod źródłowy do 'libunwind' może być przydatny. – Nemo