Strace Π² Linux: история, устройство ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅

Strace Π² Linux: история, устройство ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅

Π’ Unix-ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΈΡ‚Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΎΠ½Π½ΠΈ систСми комуникацията Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° с външния свят ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΎΠ½Π½Π°Ρ‚Π° систСма става Ρ‡Ρ€Π΅Π· малък Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ β€” систСмни ΠΏΠΎΠ²ΠΈΡ†ΠΈ. Π‘Π»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»Π½ΠΎ, Π·Π° отстраняванС Π½Π° Π³Ρ€Π΅ΡˆΠΊΠΈ, Π΅ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ Π΄Π° сС Π½Π°Π±Π»ΡŽΠ΄Π°Π²Π°Ρ‚ ΠΈΠ·ΠΏΡŠΠ»Π½ΡΠ²Π°Π½ΠΈΡ‚Π΅ процСси Ρ‡Ρ€Π΅Π· систСмни ΠΏΠΎΠ²ΠΈΡ†ΠΈ.

Π£Ρ‚ΠΈΠ»ΠΈΡ‚Π°Ρ‚Π°, която ΠΏΠΎΠΌΠ°Π³Π° Π·Π° слСдСнС Π½Π° 'интимния ΠΆΠΈΠ²ΠΎΡ‚' Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ Π² Linux, strace, Π΅ ΠΏΡ€Π΅Π΄ΠΌΠ΅Ρ‚ Π½Π° Ρ‚Π°Π·ΠΈ статия. ΠŸΡ€ΠΈΠΌΠ΅Ρ€ΠΈ Π·Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° 'шпионски' инструмСнти Π²ΠΊΠ»ΡŽΡ‡Π²Π°Ρ‚ ΠΊΡ€Π°Ρ‚ΠΊΠ° история strace ΠΈ описаниС Π½Π° устройството Π½Π° ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ.

Π‘ΡŠΠ΄ΡŠΡ€ΠΆΠ°Π½ΠΈΠ΅

ΠŸΡ€ΠΎΠΈΠ·Ρ…ΠΎΠ΄ Π½Π° Π²ΠΈΠ΄ΠΎΠ²Π΅Ρ‚Π΅

ΠžΡΠ½ΠΎΠ²Π½ΠΈΡΡ‚ интСрфСйс ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ ΠΈ ядрото Π½Π° ОБ Π² Unix са систСмнитС ΠΏΠΎΠ²ΠΈΡ†ΠΈ (Π°Π½Π³Π». system calls, syscalls), взаимодСйствиСто Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ‚Π΅ с външния свят става СдинствСно Ρ‡Ρ€Π΅Π· тях.

Но Π² ΠΏΡŠΡ€Π²Π°Ρ‚Π° ΠΏΡƒΠ±Π»ΠΈΡ‡Π½Π° вСрсия Π½Π° Unix (Version 6 Unix, 1975 Π³ΠΎΠ΄ΠΈΠ½Π°) нямашС ΡƒΠ΄ΠΎΠ±Π½ΠΈ Π½Π°Ρ‡ΠΈΠ½ΠΈ Π·Π° прослСдяванС ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° потрСбитСлскитС процСси. Π—Π° Ρ€Π΅ΡˆΠ°Π²Π°Π½Π΅ Π½Π° Ρ‚ΠΎΠ·ΠΈ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ, Bell Labs Π² слСдващата вСрсия (Version 7 Unix, 1979 Π³ΠΎΠ΄ΠΈΠ½Π°) ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠΈΡ…Π° Π½ΠΎΠ² систСмСн ΠΏΠΎΠ²ΠΈΠΊ β€” ptrace.

Ptrace бСшС Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π΅Π½ ΠΏΡ€Π΅Π΄ΠΈΠΌΠ½ΠΎ Π·Π° ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½ΠΈ Π΄Π΅Π±ΡŠΠ³Π΅Ρ€ΠΈ, Π½ΠΎ Π² края Π½Π° 80-Ρ‚Π΅ (Π² Π΅Ρ€Π°Ρ‚Π° Π½Π° комСрсиалния Π²Π΅Ρ‡Π΅ System V Release 4) Π½Π° Π±Π°Π·Π°Ρ‚Π° Π½Π° Π½Π΅Π³ΠΎ сС появиха ΠΈ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ…Π° ΡˆΠΈΡ€ΠΎΠΊΠΎ разпространСниС насочСни Π΄Π΅Π±ΡŠΠ³Π΅Ρ€ΠΈ β€” трасировчици Π½Π° систСмни ΠΏΠΎΠ²ΠΈΡ†ΠΈ.

ΠŸΡŠΡ€Π²Π°Ρ‚Π° вСрсия Π½Π° strace бСшС ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΠ²Π°Π½Π° ΠΎΡ‚ Пол ΠšΡ€ΠΎΠ½Π΅Π½Π±ΡƒΡ€Π³ Π² Ρ€Π°Π·ΠΏΡ€Π°Ρ‚ΠΊΠ°Ρ‚Π° comp.sources.sun ΠΏΡ€Π΅Π· 1992 Π³ΠΎΠ΄ΠΈΠ½Π° ΠΊΠ°Ρ‚ΠΎ Π°Π»Ρ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Π° Π½Π° Π·Π°Ρ‚Π²ΠΎΡ€Π΅Π½Π°Ρ‚Π° ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Π° trace ΠΎΡ‚ Sun. Как ΠΊΠ»ΠΎΠ½Π°, Ρ‚Π°ΠΊΠ° ΠΈ ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»Π° бяха ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ΠΈ Π·Π° SunOS, Π½ΠΎ Π΄ΠΎ 1994 Π³ΠΎΠ΄ΠΈΠ½Π° strace бСшС ΠΏΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π° Π½Π° System V, Solaris ΠΈ нарастващия ΠΏΠΎ популярност Linux.

ДнСс strace ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ° само Linux ΠΈ Ρ€Π°Π·Ρ‡ΠΈΡ‚Π° Π½Π° всичко ΡΡŠΡ‰ΠΎΡ‚ΠΎ ptrace, ΠΊΠΎΠ΅Ρ‚ΠΎ Π΅ Π½Π°Ρ‚Ρ€ΡƒΠΏΠ°Π»ΠΎ мноТСство Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½ΠΈΡ.

Π‘ΡŠΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΈΡΡ‚ (ΠΈ доста Π°ΠΊΡ‚ΠΈΠ²Π΅Π½) ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ°Ρ‰ strace β€” Π”ΠΌΠΈΡ‚Ρ€ΠΈΠΉ Π›Π΅Π²ΠΈΠ½. Π‘Π»Π°Π³ΠΎΠ΄Π°Ρ€Π΅Π½ΠΈΠ΅ Π½Π° Π½Π΅Π³ΠΎ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Π°Ρ‚Π° ΠΏΡ€ΠΈΠ΄ΠΎΠ±ΠΈ Π½Π°ΠΏΡ€Π΅Π΄Π½Π°Π»ΠΈ Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΠΈ ΠΊΠ°Ρ‚ΠΎ инТСкция Π½Π° Π³Ρ€Π΅ΡˆΠΊΠΈ Π² систСмнитС ΠΏΠΎΠ²ΠΈΡ†ΠΈ, ΠΏΠΎΠ΄Π΄Ρ€ΡŠΠΆΠΊΠ° Π½Π° ΡˆΠΈΡ€ΠΎΠΊ ΡΠΏΠ΅ΠΊΡ‚ΡŠΡ€ ΠΎΡ‚ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€ΠΈ ΠΈ, Π½Π°ΠΉ-Π²Π°ΠΆΠ½ΠΎΡ‚ΠΎ, маскот.. НСофициални ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΡ†ΠΈ Ρ‚Π²ΡŠΡ€Π΄ΡΡ‚, Ρ‡Π΅ ΠΈΠ·Π±ΠΎΡ€ΡŠΡ‚ Π΅ ΠΏΠ°Π΄Π½Π°Π» Π²ΡŠΡ€Ρ…Ρƒ щрауса Π·Π°Ρ€Π°Π΄ΠΈ звучността Π½Π° руската Π΄ΡƒΠΌΠ° "страус" ΠΈ английското "strace".

Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° Π΅ Π²Π°ΠΆΠ½ΠΎ, Ρ‡Π΅ систСмният ΠΏΠΎΠ²ΠΈΠΊ ptrace ΠΈ трасировчицитС Ρ‚Π°ΠΊΠ° ΠΈ Π½Π΅ бяха Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈ Π² POSIX, Π²ΡŠΠΏΡ€Π΅ΠΊΠΈ Π΄ΡŠΠ»Π³Π°Ρ‚Π° си история ΠΈ Π½Π°Π»ΠΈΡ‡ΠΈΠ΅Ρ‚ΠΎ Π½Π° Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π² Linux, FreeBSD, OpenBSD ΠΈ Ρ‚Ρ€Π°Π΄ΠΈΡ†ΠΈΠΎΠ½Π½ΠΈ Unix.

Устройството Π½Π° strace Π² Π΄Π²Π° Π΄ΡƒΠΌΠΈ: Piglet Trace

"You are not expected to understand this" (ДСнис Π ΠΈΡ‡ΠΈ, ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€ Π² изходния ΠΊΠΎΠ΄ Π½Π° Version 6 Unix)

ΠžΡ‚ Ρ€Π°Π½Π½ΠΎ дСтство мразя Ρ‡Π΅Ρ€Π½ΠΈΡ‚Π΅ ΠΊΡƒΡ‚ΠΈΠΈ: с ΠΈΠ³Ρ€Π°Ρ‡ΠΊΠΈΡ‚Π΅ Π½Π΅ ΠΈΠ³Ρ€Π°Π΅Ρ…, Π° сС ΠΎΠΏΠΈΡ‚Π²Π°Ρ… Π΄Π° Ρ€Π°Π·Π±Π΅Ρ€Π° устройството ΠΈΠΌ (Π²ΡŠΠ·Ρ€Π°ΡΡ‚Π½ΠΈΡ‚Π΅ ΠΏΠΎΠ»Π·Π²Π°Ρ…Π° Π΄ΡƒΠΌΠ°Ρ‚Π° "Ρ‡ΡƒΠΏΠ΅Ρ…", Π½ΠΎ Π½Π΅ вярвайтС Π½Π° Π·Π»ΠΈΡ‚Π΅ Π΅Π·ΠΈΡ†ΠΈ). ВСроятно Π·Π°Ρ‚ΠΎΠ²Π° ΠΌΠΈ Π΅ Ρ‚ΠΎΠ»ΠΊΠΎΠ²Π° Π±Π»ΠΈΠ·ΠΊΠ° Π½Π΅Ρ„ΠΎΡ€ΠΌΠ°Π»Π½Π°Ρ‚Π° ΠΊΡƒΠ»Ρ‚ΡƒΡ€Π° Π½Π° ранния Unix ΠΈ ΡΡŠΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΡ‚ΠΎ open-source Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅.

Π’ Ρ€Π°ΠΌΠΊΠΈΡ‚Π΅ Π½Π° Ρ‚Π°Π·ΠΈ статия Ρ€Π°Π·Π³Π»Π΅ΠΆΠ΄Π°Π½Π΅Ρ‚ΠΎ Π½Π° изходния ΠΊΠΎΠ΄ Π½Π° стрСсирания strace Π½Π΅ Π΅ Ρ€Π°Π·ΡƒΠΌΠ½ΠΎ. Но ΠΈ Ρ‚Π°ΠΉΠ½ΠΈ Π·Π° Ρ‡ΠΈΡ‚Π°Ρ‚Π΅Π»ΠΈΡ‚Π΅ Π½Π΅ трябва Π΄Π° остават. Π—Π°Ρ‚ΠΎΠ²Π°, Π·Π° Π΄Π° ΠΏΠΎΠΊΠ°ΠΆΠ° ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠ° Π½Π° Ρ€Π°Π±ΠΎΡ‚Π° Π½Π° ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ strace, Ρ‰Π΅ ΠΏΡ€ΠΈΠ²Π΅Π΄Ρƒ ΠΊΠΎΠ΄Π° Π½Π° ΠΌΠΈΠ½ΠΈΠ°Ρ‚ΡŽΡ€Π΅Π½ трасировчик β€” Piglet Trace (ptr). Нищо особСно Π½Π΅ ΡƒΠΌΠ΅Π΅ Π΄Π° ΠΏΡ€Π°Π²ΠΈ, Π½ΠΎ Π½Π°ΠΉ-Π²Π°ΠΆΠ½ΠΎΡ‚ΠΎ β€” систСмнитС ΠΏΠΎΠ²ΠΈΡ†ΠΈ Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° β€” ΠΈΠ·Π²Π΅ΠΆΠ΄Π°:

$ gcc examples/piglet-trace.c -o ptr
$ ptr echo test > /dev/null
BRK(12) -> 94744690540544
ACCESS(21) -> 18446744073709551614
ACCESS(21) -> 18446744073709551614
unknown(257) -> 3
FSTAT(5) -> 0
MMAP(9) -> 140694657216512
CLOSE(3) -> 0
ACCESS(21) -> 18446744073709551614
unknown(257) -> 3
READ(0) -> 832
FSTAT(5) -> 0
MMAP(9) -> 140694657208320
MMAP(9) -> 140694650953728
MPROTECT(10) -> 0
MMAP(9) -> 140694655045632
MMAP(9) -> 140694655070208
CLOSE(3) -> 0
unknown(158) -> 0
MPROTECT(10) -> 0
MPROTECT(10) -> 0
MPROTECT(10) -> 0
MUNMAP(11) -> 0
BRK(12) -> 94744690540544
BRK(12) -> 94744690675712
unknown(257) -> 3
FSTAT(5) -> 0
MMAP(9) -> 140694646390784
CLOSE(3) -> 0
FSTAT(5) -> 0
IOCTL(16) -> 18446744073709551591
WRITE(1) -> 5
CLOSE(3) -> 0
CLOSE(3) -> 0
unknown(231)
Tracee terminated

Piglet Trace Ρ€Π°Π·ΠΏΠΎΠ·Π½Π°Π²Π° ΠΎΠΊΠΎΠ»ΠΎ стотици систСмни ΠΏΠΎΠ²ΠΈΠΊΠΎΠ²Π΅ Π½Π° Linux (Π²ΠΆ. Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π°) ΠΈ Ρ€Π°Π±ΠΎΡ‚ΠΈ само Π½Π° Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π°Ρ‚Π° x86-64. Π—Π° ΡƒΡ‡Π΅Π±Π½ΠΈ Ρ†Π΅Π»ΠΈ Ρ‚ΠΎΠ²Π° Π΅ Π΄ΠΎΡΡ‚Π°Ρ‚ΡŠΡ‡Π½ΠΎ.

НСка Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚Π° Π½Π° нашия ΠΊΠ»ΠΎΠ½. Π’ случай Π½Π° Linux, Π·Π° Π΄Π΅Π±ΡŠΠ³Π΅Ρ€ΠΈΡ‚Π΅ ΠΈ трасировчицитС сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°, ΠΊΠ°ΠΊΡ‚ΠΎ спомСнахмС ΠΏΠΎ-Π³ΠΎΡ€Π΅, систСмният ΠΏΠΎΠ²ΠΈΠΊ ptrace. Π’ΠΎΠΉ Ρ€Π°Π±ΠΎΡ‚ΠΈ, ΠΊΠ°Ρ‚ΠΎ ΠΏΡ€Π΅Π΄Π°Π²Π° Π² ΠΏΡŠΡ€Π²ΠΈΡ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΈΡ‚Π΅ Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄ΠΈΡ‚Π΅, ΠΎΡ‚ ΠΊΠΎΠΈΡ‚ΠΎ Π½ΠΈ трябват само PTRACE_TRACEME, PTRACE_SYSCALL ΠΈ PTRACE_GETREGS.

Π Π°Π±ΠΎΡ‚Π°Ρ‚Π° Π½Π° трасировчика Π·Π°ΠΏΠΎΡ‡Π²Π° ΠΏΠΎ обичайния Unix стил: fork(2) стартира Π΄ΠΎΡ‡Π΅Ρ€Π΅Π½ процСс, Π° Ρ‚ΠΎΠΉ ΠΎΡ‚ своя страна с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° exec(3) стартира изслСдваната ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°. ЕдинствСната Ρ‚ΡŠΠ½ΠΊΠΎΡΡ‚ Ρ‚ΡƒΠΊ Π΅ ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅Ρ‚ΠΎ Π½Π° ptrace(PTRACE_TRACEME) ΠΏΡ€Π΅Π΄ΠΈ exec: ΠΏΡ€ΠΎΡ†Π΅ΡΡŠΡ‚-ΠΏΠΎΡ‚ΠΎΠΌΡŠΠΊ ΠΎΡ‡Π°ΠΊΠ²Π°, Ρ‡Π΅ ΠΏΡ€ΠΎΡ†Π΅ΡΡŠΡ‚-Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π» Ρ‰Π΅ Π³ΠΎ наблюдава:

pid_t child_pid = fork();
switch (child_pid) {
case -1:
    err(EXIT_FAILURE, "fork");
case 0:
    /* Child here */
    /* Π Π΅ΠΆΠΈΠΌ трассировки Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½. Π ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΠ΄ΠΎΠΆΠ΄Π°Ρ‚ΡŒ(2) Π·Π° это, */
    ptrace(PTRACE_TRACEME, 0, NULL, NULL);
    /* Π—Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ сСбя ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΎΠΉ для выполнСния. */
    execvp(argv[1], argv + 1);
    err(EXIT_FAILURE, "exec");
}

ΠŸΡ€ΠΎΡ†Π΅ΡΡŠΡ‚-Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π» сСга трябва Π΄Π° ΠΈΠ·Π²ΠΈΠΊΠ° wait(2) Π² дочСрния процСс, Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ Π΄Π° сС ΡƒΠ²Π΅Ρ€ΠΈ, Ρ‡Π΅ ΠΏΡ€Π΅Π²ΠΊΠ»ΡŽΡ‡Π²Π°Π½Π΅Ρ‚ΠΎ Π² Ρ€Π΅ΠΆΠΈΠΌ Π½Π° трасировка Π΅ станало:

/* Parent */

/* First we wait for the child to set the traced mode (see
 * ptrace(PTRACE_TRACEME) above) */
if (waitpid(child_pid, NULL, 0) == -1)
    err(EXIT_FAILURE, "traceme -> waitpid");

На Ρ‚ΠΎΠ·ΠΈ Π΅Ρ‚Π°ΠΏ ΠΏΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΠΊΠ°Ρ‚Π° ΠΏΡ€ΠΈΠΊΠ»ΡŽΡ‡Π²Π° ΠΈ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΏΡ€Π΅ΠΌΠΈΠ½Π΅ΠΌ към наблюдСниС Π½Π° систСмнитС ΠΏΠΎΠ²ΠΈΡ†ΠΈ Π² Π±Π΅Π·ΠΊΡ€Π°Π΅Π½ Ρ†ΠΈΠΊΡŠΠ».

ИзвикванС ptrace(PTRACE_SYSCALL) Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€Π°, Ρ‡Π΅ послСдващият wait Π½Π° родитСля ΠΏΡ€ΠΈΠΊΠ»ΡŽΡ‡ΠΈ ΠΈΠ»ΠΈ ΠΏΡ€Π΅Π΄ΠΈ ΠΈΠ·ΠΏΡŠΠ»Π½Π΅Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° систСмния ΠΏΠΎΠ²ΠΈΠΊ, ΠΈΠ»ΠΈ Π²Π΅Π΄Π½Π°Π³Π° слСд Π½Π΅Π³ΠΎΠ²ΠΎΡ‚ΠΎ Π·Π°Π²ΡŠΡ€ΡˆΠ²Π°Π½Π΅. ΠœΠ΅ΠΆΠ΄Ρƒ Π΄Π²Π΅Ρ‚Π΅ извиквания ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΎΡΡŠΡ‰Π΅ΡΡ‚Π²ΠΈΠΌ дСйствия: Π΄Π° Π·Π°ΠΌΠ΅Π½ΠΈΠΌ ΠΏΠΎΠ²ΠΈΠΊΠ° с Π°Π»Ρ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Π΅Π½, Π΄Π° ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈΠΌ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΈΡ‚Π΅ ΠΈΠ»ΠΈ Π²Ρ€ΡŠΡ‰Π°Π½Π°Ρ‚Π° стойност.

Π”ΠΎΡΡ‚Π°Ρ‚ΡŠΡ‡Π½ΠΎ Π΅ Π΄Π° ΠΈΠ·Π²ΠΈΠΊΠ°ΠΌΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ‚Π° Π΄Π²Π° ΠΏΡŠΡ‚ΠΈ ptrace(PTRACE_GETREGS), Π·Π° Π΄Π° ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ ΡΡŠΡΡ‚ΠΎΡΠ½ΠΈΠ΅Ρ‚ΠΎ Π½Π° рСгистра rax ΠΏΡ€Π΅Π΄ΠΈ ΠΏΠΎΠ²ΠΈΠΊΠ° (Π½ΠΎΠΌΠ΅Ρ€ Π½Π° систСмния ΠΏΠΎΠ²ΠΈΠΊ) ΠΈ Π²Π΅Π΄Π½Π°Π³Π° слСд (Π²ΡŠΡ€Π½Π°Ρ‚Π° стойност).

Π’ΡΡŠΡ‰Π½ΠΎΡΡ‚, Ρ†ΠΈΠΊΡŠΠ»ΡŠΡ‚:

/* A system call tracing loop, one interation per call. */
for (;;) {
    /* A non-portable structure defined for ptrace/GDB/strace usage mostly.
     * It allows to conveniently dump and access register state using
     * ptrace. */
    struct user_regs_struct registers;

    /* Enter syscall: continue execution until the next system call
     * beginning. Stop right before syscall.
     *
     * It's possible to change the system call number, system call
     * arguments, return value or even avoid executing the system call
     * completely. */
  if (ptrace(PTRACE_SYSCALL, child_pid, NULL, NULL) == -1)
      err(EXIT_FAILURE, "enter_syscall");
  if (waitpid(child_pid, NULL, 0) == -1)
      err(EXIT_FAILURE, "enter_syscall -> waitpid");

  /* According to the x86-64 system call convention on Linux (see man 2
   * syscall) the number identifying a syscall should be put into the rax
   * general purpose register, with the rest of the arguments residing in
   * other general purpose registers (rdi,rsi, rdx, r10, r8, r9). */
  if (ptrace(PTRACE_GETREGS, child_pid, NULL, &registers) == -1)
      err(EXIT_FAILURE, "enter_syscall -> getregs");

  /* Note how orig_rax is used here. That's because on x86-64 rax is used
   * both for executing a syscall, and returning a value from it. To
   * differentiate between the cases both rax and orig_rax are updated on
   * syscall entry/exit, and only rax is updated on exit. */
  print_syscall_enter(registers.orig_rax);

  /* Exit syscall: execute of the syscall, and stop on system
   * call exit.
   *
   * More system call tinkering possible: change the return value, record
   * time it took to finish the system call, etc. */
  if (ptrace(PTRACE_SYSCALL, child_pid, NULL, NULL) == -1)
      err(EXIT_FAILURE, "exit_syscall");
  if (waitpid(child_pid, NULL, 0) == -1)
      err(EXIT_FAILURE, "exit_syscall -> waitpid");

  /* Retrieve register state again as we want to inspect system call
   * return value. */
  if (ptrace(PTRACE_GETREGS, child_pid, NULL, &registers) == -1) {
      /* ESRCH is returned when a child terminates using a syscall and no
       * return value is possible, e.g. as a result of exit(2). */
      if (errno == ESRCH) {
          fprintf(stderr, "nTracee terminatedn");
          break;
      }
      err(EXIT_FAILURE, "exit_syscall -> getregs");
  }

  /* Done with this system call, let the next iteration handle the next
   * one */
  print_syscall_exit(registers.rax);
}

Π’ΠΎΠ²Π° Π΅ цСлият трасовик. Π‘Π΅Π³Π° Π·Π½Π°Π΅Ρ‚Π΅ ΠΎΡ‚ΠΊΡŠΠ΄Π΅ Π΄Π° Π·Π°ΠΏΠΎΡ‡Π½Π΅Ρ‚Π΅ Π½ΠΎΠ²ΠΎΡ‚ΠΎ ΠΏΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ DTrace Π½Π° Linux.

Основи: стартиранС Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° ΠΏΠΎΠ΄ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° strace

ΠšΠ°Ρ‚ΠΎ ΠΏΡŠΡ€Π²ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ strace, вСроятно, си струва Π΄Π° ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅ΠΌ Π½Π°ΠΉ-простия Π½Π°Ρ‡ΠΈΠ½ β€” стартиранС Π½Π° ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΏΠΎΠ΄ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° strace.

Π—Π° Π΄Π° Π½Π΅ сС Ρ€ΠΎΠ²ΠΈΠΌ Π² Π±Π΅Π·ΠΊΡ€Π°Π΅Π½ списък ΠΎΡ‚ ΠΏΠΎΠ²ΠΈΡ†ΠΈ Π½Π° Ρ‚ΠΈΠΏΠΈΡ‡Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°, Ρ‰Π΅ напишСм ΠΌΠΈΠ½ΠΈΠΌΠ°Π»Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° ΠΎΠΊΠΎΠ»ΠΎ write:

int main(int argc, char *argv[])
{
    char str[] = "write me to stdoutn";
    /* write(2) Π΅ прост ΠΎΠ±Π²ΠΈΠ²Π΅Π½ ΠΎΠΊΠΎΠ»ΠΎ систСмСн ΠΏΠΎΠ²ΠΈΠΊ, Ρ‚Π°ΠΊΠ° Ρ‡Π΅ трябва Π΄Π° Π΅ лСсно Π΄Π°
     * бъдС ΠΎΡ‚ΠΊΡ€ΠΈΡ‚ Π² трасСто Π½Π° систСмния ΠΏΠΎΠ²ΠΈΠΊ. */
    if (sizeof(str) != write(STDOUT_FILENO, str, sizeof(str))){
        perror("write");
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

НСка ΡΡŠΠ±Π΅Ρ€Π΅ΠΌ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° ΠΈ Π΄Π° сС ΡƒΠ²Π΅Ρ€ΠΈΠΌ, Ρ‡Π΅ Ρ€Π°Π±ΠΎΡ‚ΠΈ:

$ gcc examples/write-simple.c -o write-simple
$ ./write-simple
write me to stdout

И накрая, Π½Π΅ΠΊΠ° я стартирамС ΠΏΠΎΠ΄ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° strace:

$ strace ./write-simple
pexecve("./write", ["./write"], 0x7ffebd6145b0 /* 71 vars */) = 0
brk(NULL)                               = 0x55ff5489e000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=197410, ...}) = 0
mmap(NULL, 197410, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f7a2a633000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "177ELF2113        3 >
ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС с Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ πŸ”₯ ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС с Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ | ProHoster