2010-10-26 14 views
5

Mam następujący wniosek C:Nie można znaleźć funkcję rozbijając stosu za pomocą GDB

#include <stdio.h> 

void smash() 
{ 
    int i; 
    char buffer[16]; 
    for(i = 0; i < 17; i++) // <-- exceeds the limit of the buffer 
    { 
     buffer[i] = i; 
    } 
} 

int main() 
{ 
    printf("Starting\n"); 
    smash(); 
    return 0; 
} 

przekraczam skompilowaną stosując następującą wersję gcc:

armv5l-linux-gnueabi-gcc -v 
Using built-in specs. 
Target: armv5l-linux-gnueabi 
Configured with: /home/tarjeif/svn/builder/build_armv5l-linux-gnueabi/gcc-4.4.1/gcc-4.4.1/configure --target=armv5l-linux-gnueabi --host=i486-linux-gnu --build=i486-linux-gnu --prefix=/home/tarjeif/svn/builder/build_armv5l-linux-gnueabi/toolchain --with-sysroot=/home/tarjeif/svn/builder/build_armv5l-linux-gnueabi/toolchain --with-headers=/home/tarjeif/svn/builder/build_armv5l-linux-gnueabi/toolchain/include --enable-languages=c,c++ --with-gmp=/home/tarjeif/svn/builder/build_armv5l-linux-gnueabi/gmp-5.0.0/gmp-host-install --with-mpfr=/home/tarjeif/svn/builder/build_armv5l-linux-gnueabi/mpfr-2.4.2/mpfr-host-install --disable-nls --disable-libgcj --disable-libmudflap --disable-libssp --disable-libgomp --enable-checking=release --with-system-zlib --with-arch=armv5t --with-gnu-as --with-gnu-ld --enable-shared --enable-symvers=gnu --enable-__cxa_atexit --disable-nls --without-fp --enable-threads 
Thread model: posix 
gcc version 4.4.1 (GCC) 

wywoływany tak:

armv5l-linux-gnueabi-gcc -ggdb3 -fstack-protector-all -O0 test.c 

Po uruchomieniu na docelowym wyjściu:

Starting 
*** stack smashing detected ***: ./a.out terminated 
Aborted (core dumped) 

załadować wynikowy zrzut rdzenia w gdb uzyskując następujące ślad:

GNU gdb (GDB) 7.0.1 
Copyright (C) 2009 Free Software Foundation, Inc. 
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 
This is free software: you are free to change and redistribute it. 
There is NO WARRANTY, to the extent permitted by law. Type "show copying" 
and "show warranty" for details. 
This GDB was configured as "--host=i486-linux-gnu --target=armv5l-linux-gnueabi". 
For bug reporting instructions, please see: 
<http://www.gnu.org/software/gdb/bugs/>... 
Reading symbols from /home/andersn/workspace/stacktest/a.out...done. 
Reading symbols from /home/andersn/workspace/stacktest/linux/toolchain/lib/libc.so.6...done. 
Loaded symbols for /home/andersn/workspace/stacktest/linux/toolchain/lib/libc.so.6 
Reading symbols from /home/andersn/workspace/stacktest/linux/toolchain/lib/ld-linux.so.3...done. 
Loaded symbols for /home/andersn/workspace/stacktest/linux/toolchain/lib/ld-linux.so.3 
Reading symbols from /home/andersn/workspace/stacktest/linux/toolchain /lib/libgcc_s.so.1...done. 
Loaded symbols for /home/andersn/workspace/stacktest/linux/toolchain/lib/libgcc_s.so.1 
Core was generated by `./a.out'. 
Program terminated with signal 6, Aborted. 
#0 0x40052d4c in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:67 
67 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory. 
    in ../nptl/sysdeps/unix/sysv/linux/raise.c 
(gdb) bt 
#0 0x40052d4c in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:67 
#1 0x40054244 in *__GI_abort() at abort.c:92 
#2 0x40054244 in *__GI_abort() at abort.c:92 
#3 0x40054244 in *__GI_abort() at abort.c:92 
#4 0x40054244 in *__GI_abort() at abort.c:92 
#5 0x40054244 in *__GI_abort() at abort.c:92 
#6 0x40054244 in *__GI_abort() at abort.c:92 
... and so on ... 

Teraz pytanie: jestem całkowicie niezdolny do znalezienia funkcji powoduje stos rozbijając z GDB chociaż funkcja smash() nie zastępuje żadnych danych strukturalnych stosu, tylko sam ochraniacz stosu. Co powinienem zrobić?

+1

Myślę, że Twoje "i tak dalej" mogło pominąć niektóre ważne informacje. czy __GI_abort jest naprawdę dolną częścią stosu? – SoapBox

+0

Próbowałem kontynuować tworzenie GDB i osiągnąłem # 11087 zanim zrezygnowałem .... Wszystkie równe ramki. – anorm

+0

Zdecydowanie uszkadzasz stos - nie oczekuj, że plik core będzie miał starannie przyklejone ramki połączeń :) –

Odpowiedz

8

Problem polega na tym, że wersja GCC, która skompilowała docelowy plik libc.so.6, jest błędna i nie wyemitowała poprawnych deskryptorów rozwijania dla __GI_raise. Przy niepoprawnych deskryptorach rozwijania GDB wchodzi w pętlę podczas rozwijania stosu.

Można zbadać rozwijającej deskryptory z

readelf -wf /home/andersn/workspace/stacktest/linux/toolchain/lib/libc.so.6 

Spodziewam dostaniesz dokładnie taki sam wynik w GDB z dowolnego programu wywołującego przerwanie, np

#include <stdlib.h> 
void foo() { abort(); } 
int main() { foo(); return 0; } 

Niestety, nie ma wiele można zrobić, inne niż próbuje zbudować nowszej wersji GCC, a następnie odbudowy cały „świat” z nim.

+0

Tak, to powinno być to, w pigułce. Jednak może wystarczy odbudować libc.so z nowym kompilatorem. – user434507

+0

Przebudowywanie samego pliku libc.so.6 może nie być wystarczające: w końcu nie ma gwarancji, że foo() otrzyma poprawny deskryptor rozwijania ze "starym" GCC. –

0

Czy próbowałeś rozwiązać tę skargę: "../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.", aby sprawdzić, czy rzeczywiście może pomóc w rozwiązywaniu symboli?

+0

Nie, nie mam, ale GDB nie brakuje informacji o symbolu w danej lokalizacji, tylko plik kodu źródłowego dla aukcji. Jednak spróbuję twojej sugestii ... Dzięki – anorm

+0

Cóż, próbowałem tego bez powodzenia. GDB pokazał linię źródłową w raise.c, ale ślad jest nadal uszkodzony. – anorm

2

Nie jest tak, że GDB zawsze może sprawdzić, co się stało z uszkodzonym stosem, nawet z -fstack-protector-all (a nawet z -Wstack-protector, aby ostrzec o funkcjach z ramkami, które nie były chronione). Example.

W tych przypadkach ochraniacz sterty wykonał swoje zadanie (zabił niewłaściwie działającą aplikację), ale nie wykonał debuggera żadnych względów. (Klasycznym przykładem jest roztrzaskanie stosu, w którym wystąpił napis o wystarczająco dużym kroku, że przeskakuje on do kanarka.) W takich przypadkach może być konieczne przeszukanie binarne przez kod za pomocą punktów przerwania, aby zawęzić obszar kodu, który powoduje rozbijanie, a następnie pojedynczy krok po rozbiciu, aby zobaczyć, jak to się stało.

Powiązane problemy