W programowaniu w trybie 32-bitowym używałam w swoich programach int 3
do zatrzymywania się w danej lokalizacji za pomocą debuggera (osadzanie instrukcji w źródle). Teraz w 64 bitach wydaje się nie działać, tworząc bardzo zwykły SIGSEGV pod gdb i niszcząc program poza nadzieją ("Program zakończony sygnałem SIGSEGV, Usterka segmentacji Program już nie istnieje."). Zastanawiam się, czy tryb 64-bitowy ma inny mechanizm, czy też powinienem zrobić cache-flush (int 3
jest dynamicznie generowanym opodem w tym przypadku (0xcc), to jakiś kod podobny do jit-like).Dlaczego int 3 generuje SIGSEGV w wersji 64-bitowej, zamiast zatrzymywać debugger?
Odpowiedz
Odpowiedź BarsMonster pokazuje, że __asm__("int3");
nie działa na 64-bitowych platformach. To jest - przynajmniej dzisiaj (2014) - nieprawda.
Poniższy kod będzie działać na platformie amd64
:
przerwania.c
int main() {
int i;
for(i=0; i<3;i++) {
__asm__("int3");
}
}
skompilować trywialnie: gcc -c breakpoint.c
i rozpocząć gdb a.out
:
(gdb) run
Starting program: /tmp/a.out
Program received signal SIGTRAP, Trace/breakpoint trap.
0x00000000004004fb in main()
Widzisz, gdb zatrzymuje się przy zerwaniu.
Powinieneś powiedzieć wersję jądra zamiast daty :-) –
__debugbreak()
Dzisiaj kolega przyszedł zapytać o jak dostać "int 3" funkcjonalność na platformach 64-bitowych się. Co to jest "int 3"? Jest to instrukcja montażu, która jest używana do tworzenia punktu przerwania. Co najmniej jest instrukcją dla procesora x86 , i jak można sobie wyobrazić, to jest bardzo specyficzna dla platformy.
Na platformach 64-bitowych nie ma żadnego wbudowanego zespołu , więc istnieje "__asm int 3". Co zrobić teraz? No cóż, jest mniej znany konstrukt, który jest o wiele lepszy w użyciu w tym działa na wszystkich platformach (x64, Itanium i x86), który jest __debugbreak(). To jest wewnętrzny kompilator Visual C++ (zdefiniowany w Visual C++ 2005 pod vc \ include \ intrin.h, z tonami innych fajnych właściwości) , który skutecznie działa "int 3" na wszystkich platformach.
DebugBreak, wywołanie funkcji Win32 jest wciąż dokoła, ale ogólnie za pomocą __debugbreak() jest moje preferencje, jeśli nie z innego powodu niż to nie jest rozmowa funkcji (jest to kompilator wewnętrzna), a don Aby uzyskać czytelny stos wywołań, trzeba zdebugować symbole .
Jeśli piszesz C++ prawdopodobnie nie chcesz pisać non-przenośne zespół, a to jest tylko jeden mniej miejsce gdzie trzeba.
http://blogs.msdn.com/b/kangsu/archive/2005/09/07/462232.aspx
To jest bardzo pouczająca odpowiedź, ale jak wskazałem w moim pytaniu, generowałem kod dynamicznie, a to wyklucza wewnętrzną kompilację. Nie wspominając o tym, że moim zwykłym kompilatorem nie jest Visual C++, ani moja platforma Windows. Co więcej, odpowiedź jest niedokładna, ponieważ int 3 istnieje i przynajmniej w 64 bitach linuks zachowuje się jak zwykle. Ponadto, w zależności od kompilatora, masz wbudowany zestaw w trybie 64-bitowym. – dsign
nadal działa tylko na x86? – Damian
To dobrze dla MS IDE, ale co, jeśli używam Eclipse i GCC? – Mawg
Ahh, mam go, przepraszam. Musiałem usunąć zabezpieczenia stron w celu wykonania. Int 3 nadal jest poprawną pułapką debugowania.
Szczegóły? Dociekliwe umysły chcieliby wiedzieć. – BeeOnRope
To pytanie było siedem lat temu, więc trudno jest zapamiętać szczegóły tego, co zrobiłem. Pamiętam, że było to dość proste, myślę, że dzwoniłem do mmap (2) i właśnie dodałem flagę PROT_EXEC. A może to mprotect (2) ...? – dsign
Prawdopodobnie wykonanie nigdy nie osiągnęło "int3", ponieważ kod znajdował się na stronie odczytu/zapisu/braku wykonania. Więc tylko skoki spowodowały uszkodzenie, niezależnie od zawartości. I tak, 'PROT_READ | PROT_EXEC | PROT_WRITE' dla mmap powinno być właściwe. Możesz też zacząć od strony do odczytu/zapisu, a następnie odwrócić ją do read/exec z mprotect po zakończeniu, więc nigdy nie masz odwzorowanej strony write + exec (ze względów bezpieczeństwa). –
Zalecam, abyś nigdy nie używał asm int 3
, ponieważ działa on dla wszystkich typów kompilacji. Możesz zapomnieć o linii gdzieś w kodzie i może to oznaczać duże problemy. Alternatywą jest użycie __debugbreak, która jest poprawna tylko w trybie debugowania.
- 1. SIGSEGV w zoptymalizowanej wersji kodu
- 2. Dlaczego nowy int (*) [3] jest błędem?
- 3. Dlaczego Roslyn generuje> porównanie zamiast a! = Tutaj?
- 4. ciąg :: size_type zamiast int
- 5. three.js: face4 generuje trójkąt zamiast kwadratu
- 6. dlaczego leży debugger F #?
- 7. Dlaczego FFT generuje liczby zespolone zamiast liczb rzeczywistych?
- 8. Dlaczego .NET używa int zamiast uint w niektórych klasach?
- 9. Dlaczego JsonResult generuje 500 błędów wewnętrznego serwera?
- 10. W C# dlaczego (char) (1) + (char) (2) daje int 3
- 11. Dlaczego ta grupa LINQ ma liczbę 3 zamiast 2?
- 12. Dlaczego obsługa sygnału idzie do nieskończonej pętli? - SIGSEGV
- 13. Dlaczego auto jest wyprowadzona do int zamiast uint16_t
- 14. EXC_BAD_ACCESS (SIGSEGV)
- 15. Keytool generuje odcisk palca SHA1 zamiast MD5?
- 16. Co SIGSEGV, błąd segmentacji w Qt
- 17. Visual Studio 2015 debugger używa lokalnego ApplicationHost.config zamiast konfiguracji globalnej
- 18. Dlaczego int * [] zanika w int **, ale nie int [] []?
- 19. Dlaczego metoda Observable.Generate() generuje wyjątek System.StackOverflowException?
- 20. Dlaczego metoda Znajdź generuje zapytanie TOP (2)?
- 21. Dlaczego moja aplikacja zawsze korzysta z najnowszej wersji GAC zamiast wersji referencyjnej?
- 22. Dlaczego Decimal.Divide (int, int) działa, ale nie (int/int)?
- 23. Dlaczego ten kod rekurencyjny generuje błąd segfault?
- 24. Dlaczego SELECT 0, ... zamiast SELECT
- 25. Dlaczego Java 8 wprowadzać * Integer.sum (int a, int b) *
- 26. EXC_BAD_ACCESS (SIGSEGV) - KERN_INVALID_ADDRESS
- 27. Dlaczego ten program C generuje liczbę ujemną?
- 28. Uruchom Python Debugger (pdb) w Sublime Text 3
- 29. Dlaczego Html.BeginForm generuje puste działanie?
- 30. Dlaczego program Mage.exe nie generuje atrybutu compatibleFrameworks?
Jaki system operacyjny/wersja? –