2012-02-09 22 views
6

Potrzebuję wydrukować stos śledzenia z obsługi sygnału 64-bitowej aplikacji M ++ z uruchomionym systemem Linux. Chociaż znalazłem kilka przykładów kodu, żaden z nich się nie kompiluje. Mój punkt blokowania polega na uzyskaniu adresu osoby dzwoniącej (punktu, w którym wygenerowano sygnał) ze struktury ucontext_t. Wszystkie informacje, które mogłem znaleźć, wskazują na rejestr EIP jako ucontext.gregs [REG_EIP] lub ucontext.eip. Wygląda na to, że oba są specyficzne dla x86. Potrzebuję 64-bitowego kodu zgodnego z procesorami Intel i AMD. Czy ktokolwiek może pomóc?Drukowanie ścieżki stosu z nośnika sygnału

+0

Nie zdziwiłbym się, gdyby nie było to możliwe. Czy próbowałeś robić to na 32-bitach? A także, która dystrybucja? –

+0

W 64-bitowym rejestrze jest RIP. Jestem pewien, że gdzieś tam będzie. –

+0

To jest Red Hat 4.1.2-50. Nie może być aplikacją 32-bitową, ponieważ pracujemy z dużymi obszarami pamięci do 60 GB GB – GMichael

Odpowiedz

1

Zwykłym sposobem uzyskiwania ślad stosu jest podjęcie adres zmiennej lokalnej , następnie dodać trochę magiczną liczbę do niej, w zależności od sposobu kompilator generuje kod (który może zależeć od opcji optymalizacji wykorzystywanych do skompilować kod) i od tego miejsca wrócić. Wszystko zależy od systemu, ale jest to wykonalne, jeśli wiesz, co robisz.

czy to działa z obsługi sygnału jest inna kwestia. Nie wiedzieć o platformie opisujesz, ale wiele systemów zainstalować osobny stos do obsługi sygnałów, bez linkiem do przerwany w stosie użytkownika dostępnej pamięci.

+0

Czy masz na myśli żadnego związku z powrotem do przerwanego stosie? –

+0

@wood_brian Brak dostępnej pamięci dla użytkownika. (System operacyjny oczywiście przechowuje informacje w pewien sposób.) –

+0

Napisałeś przerwane statyczne. Myślałem, że masz na myśli przerwany stos. –

4

istnieje funkcja glibc backtrace. Strona podręcznika wymienia przykładowe się wezwanie:

#define SIZE 100 
void myfunc3(void) { 
     int j, nptrs; 

     void *buffer[100]; 
     char **strings; 

     nptrs = backtrace(buffer, SIZE); 
     printf("backtrace() returned %d addresses\n", nptrs); 

     /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO) 
      would produce similar output to the following: */ 

     strings = backtrace_symbols(buffer, nptrs); 
     if (strings == NULL) { 
      perror("backtrace_symbols"); 
      exit(EXIT_FAILURE); 
     } 

     for (j = 0; j < nptrs; j++) 
      printf("%s\n", strings[j]); 

     free(strings); 
    } 

zobaczyć stronę man, aby uzyskać więcej kontekstu.

trudno powiedzieć, czy to naprawdę jest gwarantowane do pracy z obsługi sygnału, ponieważ tylko kilka list POSIX reentrant funkcje, które są gwarantowane do pracy. Pamiętaj: program obsługi sygnału może zostać wywołany, podczas gdy reszta procesu jest w samym środku połączenia malloc.

Domyślam się, że to zwykle działa, ale może się nie udać od czasu do czasu. Do debugowania może to być wystarczająco dobre.