āĻāĻāĻ¨āĻŋāĻā§āĻ¸-āĻāĻ° āĻŽāĻ¤ā§ āĻ āĻĒāĻžāĻ°ā§āĻāĻŋāĻ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽā§, āĻŦāĻšāĻŋāĻ°ā§āĻŦāĻŋāĻļā§āĻŦ āĻāĻŦāĻ āĻ āĻĒāĻžāĻ°ā§āĻāĻŋāĻ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽā§āĻ° āĻ¸āĻžāĻĨā§ āĻāĻāĻāĻŋ āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽā§āĻ° āĻ¯ā§āĻāĻžāĻ¯ā§āĻ āĻāĻāĻāĻŋ āĻā§āĻ āĻĢāĻžāĻāĻļāĻ¨ - āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ā§āĻ° āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§ āĻāĻā§āĨ¤ āĻāĻ° āĻŽāĻžāĻ¨ā§ āĻšāĻ˛ āĻ¯ā§ āĻĄāĻŋāĻŦāĻžāĻāĻŋāĻ āĻāĻĻā§āĻĻā§āĻļā§āĻ¯ā§ āĻāĻāĻŋ āĻĒā§āĻ°āĻ¸ā§āĻ¸ āĻĻā§āĻŦāĻžāĻ°āĻž āĻāĻžāĻ°ā§āĻ¯āĻāĻ° āĻāĻ°āĻž āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛āĻā§āĻ˛āĻŋāĻ° āĻāĻĒāĻ° āĻā§āĻĒā§āĻ¤āĻāĻ°āĻŦā§āĻ¤ā§āĻ¤āĻŋ āĻāĻ°āĻ¤ā§ āĻāĻĒāĻ¯ā§āĻā§ āĻšāĻ¤ā§ āĻĒāĻžāĻ°ā§āĨ¤
āĻāĻāĻāĻŋ āĻāĻāĻāĻŋāĻ˛āĻŋāĻāĻŋ āĻāĻĒāĻ¨āĻžāĻā§ āĻ˛āĻŋāĻ¨āĻžāĻā§āĻ¸ā§ āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽāĻā§āĻ˛āĻŋāĻ° "āĻāĻ¨āĻŋāĻˇā§āĻ āĻā§āĻŦāĻ¨" āĻ¨āĻŋāĻ°ā§āĻā§āĻˇāĻŖ āĻāĻ°āĻ¤ā§ āĻ¸āĻšāĻžāĻ¯āĻŧāĻ¤āĻž āĻāĻ°ā§ strace
, āĻ¯āĻž āĻāĻ āĻ¨āĻŋāĻŦāĻ¨ā§āĻ§ā§āĻ° āĻŦāĻŋāĻˇāĻ¯āĻŧ. āĻā§āĻĒā§āĻ¤āĻāĻ° āĻ¸āĻ°āĻā§āĻāĻžāĻŽ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ°ā§āĻ° āĻāĻĻāĻžāĻšāĻ°āĻŖ āĻāĻāĻāĻŋ āĻ¸āĻāĻā§āĻˇāĻŋāĻĒā§āĻ¤ āĻāĻ¤āĻŋāĻšāĻžāĻ¸ā§āĻ° āĻ¸āĻžāĻĨā§ āĻ°āĻ¯āĻŧā§āĻā§ strace
āĻāĻŦāĻ āĻāĻ āĻ§āĻ°āĻ¨ā§āĻ° āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽā§āĻ° āĻĄāĻŋāĻāĻžāĻāĻ¨ā§āĻ° āĻŦāĻ°ā§āĻŖāĻ¨āĻžāĨ¤
āĻ¸āĻ¨ā§āĻ¤ā§āĻˇā§āĻ
āĻĒā§āĻ°āĻāĻžāĻ¤āĻŋāĻ° āĻāĻ¤āĻĒāĻ¤ā§āĻ¤āĻŋ āĻ¸āĻāĻā§āĻˇā§āĻĒā§ āĻ¸ā§āĻā§āĻ°ā§āĻ¸ āĻĄāĻŋāĻāĻžāĻāĻ¸: āĻĒāĻŋāĻāĻ˛ā§āĻ āĻā§āĻ°ā§āĻ¸ āĻŦā§āĻ¸āĻŋāĻ: āĻ¸ā§āĻā§āĻ°ā§āĻ¸ āĻāĻ˛āĻŽāĻžāĻ¨ āĻāĻāĻāĻŋ āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽ āĻāĻžāĻ˛āĻžāĻ¨ā§ āĻŦā§āĻ¸āĻŋāĻ: āĻāĻĄāĻŧā§ āĻ¯āĻžāĻāĻ¯āĻŧāĻžāĻ° āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻ¯āĻŧ āĻ¯ā§āĻāĻĻāĻžāĻ¨ āĻāĻĻāĻžāĻšāĻ°āĻŖ: āĻā§āĻ°ā§āĻ¯āĻžāĻāĻŋāĻ āĻāĻžāĻāĻ˛ā§āĻĄ āĻĒā§āĻ°āĻ¸ā§āĻ¸ āĻāĻĻāĻžāĻšāĻ°āĻŖ: āĻšā§āĻ¯āĻžāĻ¨ā§āĻĄā§āĻ˛ā§āĻ° āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤ā§ āĻĢāĻžāĻāĻ˛ āĻĒāĻžāĻĨ āĻāĻĻāĻžāĻšāĻ°āĻŖ: āĻĢāĻžāĻāĻ˛ āĻ ā§āĻ¯āĻžāĻā§āĻ¸ā§āĻ¸ āĻā§āĻ°ā§āĻ¯āĻžāĻāĻŋāĻ āĻāĻĻāĻžāĻšāĻ°āĻŖ: āĻŽāĻžāĻ˛ā§āĻāĻŋāĻĨā§āĻ°ā§āĻĄā§āĻĄ āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽ āĻŽāĻžāĻ¸ā§āĻāĻžāĻ° āĻā§āĻ˛āĻžāĻ¸: āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ā§āĻ° āĻ¸āĻŽāĻ¯āĻŧ āĻĒā§āĻ°āĻ¸ā§āĻ¸ āĻ¸ā§āĻā§āĻ¯āĻžāĻ āĻŽāĻžāĻ¸ā§āĻāĻžāĻ° āĻā§āĻ˛āĻžāĻ¸: āĻ¤ā§āĻ°ā§āĻāĻŋ āĻāĻ¨āĻā§āĻāĻļāĻ¨ āĻāĻ¤ā§āĻ¤āĻ°āĻāĻžāĻˇ
āĻĒā§āĻ°āĻāĻžāĻ¤āĻŋāĻ° āĻāĻ¤āĻĒāĻ¤ā§āĻ¤āĻŋ
āĻāĻāĻ¨āĻŋāĻā§āĻ¸ā§ āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽ āĻāĻŦāĻ āĻāĻāĻ¸ āĻāĻžāĻ°ā§āĻ¨ā§āĻ˛ā§āĻ° āĻŽāĻ§ā§āĻ¯ā§ āĻĒā§āĻ°āĻ§āĻžāĻ¨ āĻāĻ¨ā§āĻāĻžāĻ°āĻĢā§āĻ¸ āĻšāĻ˛ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛āĨ¤ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛, syscalls), āĻŦāĻšāĻŋāĻ°ā§āĻŦāĻŋāĻļā§āĻŦā§āĻ° āĻ¸āĻžāĻĨā§ āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽāĻā§āĻ˛āĻŋāĻ° āĻŽāĻŋāĻĨāĻ¸ā§āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻ¤āĻžāĻĻā§āĻ° āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§ āĻāĻāĻā§āĻāĻŋāĻ¯āĻŧāĻžāĻāĻžāĻŦā§ āĻāĻā§āĨ¤
āĻāĻŋāĻ¨ā§āĻ¤ā§ āĻāĻāĻ¨āĻŋāĻā§āĻ¸ā§āĻ° āĻĒā§āĻ°āĻĨāĻŽ āĻĒāĻžāĻŦāĻ˛āĻŋāĻ āĻ¸āĻāĻ¸ā§āĻāĻ°āĻŖā§ (ptrace
.
ptrace āĻĒā§āĻ°āĻžāĻĨāĻŽāĻŋāĻāĻāĻžāĻŦā§ āĻāĻ¨ā§āĻāĻžāĻ°ā§āĻā§āĻāĻŋāĻ āĻĄāĻŋāĻŦāĻžāĻāĻžāĻ°āĻĻā§āĻ° āĻāĻ¨ā§āĻ¯ āĻ¤ā§āĻ°āĻŋ āĻāĻ°āĻž āĻšāĻ¯āĻŧā§āĻāĻŋāĻ˛, āĻāĻŋāĻ¨ā§āĻ¤ā§ 80 āĻāĻ° āĻĻāĻļāĻā§āĻ° āĻļā§āĻˇā§āĻ° āĻĻāĻŋāĻā§ (āĻŦāĻžāĻŖāĻŋāĻā§āĻ¯āĻŋāĻ āĻ¯ā§āĻā§
trace
āĻ¸ā§āĻ°ā§āĻ¯ āĻĨā§āĻā§āĨ¤ āĻā§āĻ˛ā§āĻ¨ āĻāĻŦāĻ āĻāĻ¸āĻ˛ āĻāĻāĻ¯āĻŧāĻ SunOS-āĻāĻ° āĻāĻĻā§āĻĻā§āĻļā§āĻ¯ā§ āĻāĻ°āĻž āĻšāĻ¯āĻŧā§āĻāĻŋāĻ˛, āĻāĻŋāĻ¨ā§āĻ¤ā§ 1994 āĻ¸āĻžāĻ˛ā§āĻ° āĻŽāĻ§ā§āĻ¯ā§ strace
āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ V, āĻ¸ā§āĻ˛āĻžāĻ°āĻŋāĻ¸ āĻāĻŦāĻ āĻā§āĻ°āĻŽāĻŦāĻ°ā§āĻ§āĻŽāĻžāĻ¨ āĻāĻ¨āĻĒā§āĻ°āĻŋāĻ¯āĻŧ āĻ˛āĻŋāĻ¨āĻžāĻā§āĻ¸ā§ āĻĒā§āĻ°ā§āĻ āĻāĻ°āĻž āĻšāĻ¯āĻŧā§āĻāĻŋāĻ˛āĨ¤
āĻāĻ āĻ¸ā§āĻā§āĻ°ā§āĻ¸ āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻ˛āĻŋāĻ¨āĻžāĻā§āĻ¸ āĻ¸āĻŽāĻ°ā§āĻĨāĻ¨ āĻāĻ°ā§ āĻāĻŦāĻ āĻāĻ° āĻāĻĒāĻ° āĻ¨āĻŋāĻ°ā§āĻāĻ° āĻāĻ°ā§ ptrace
, āĻ
āĻ¨ā§āĻ āĻāĻā§āĻ¸āĻā§āĻ¨āĻļāĻ¨ āĻ¸āĻā§āĻā§ overgrown.
āĻāĻ§ā§āĻ¨āĻŋāĻ (āĻāĻŦāĻ āĻā§āĻŦ āĻ¸āĻā§āĻ°āĻŋāĻ¯āĻŧ) āĻ°āĻā§āĻˇāĻŖāĻžāĻŦā§āĻā§āĻˇāĻŖāĻāĻžāĻ°ā§ strace
-
āĻāĻāĻžāĻ āĻā§āĻ°ā§āĻ¤ā§āĻŦāĻĒā§āĻ°ā§āĻŖ āĻ¯ā§ āĻ˛āĻŋāĻ¨āĻžāĻā§āĻ¸, āĻĢā§āĻ°āĻŋāĻŦāĻŋāĻāĻ¸āĻĄāĻŋ, āĻāĻĒā§āĻ¨āĻŦāĻŋāĻāĻ¸āĻĄāĻŋ āĻāĻŦāĻ āĻāĻ¤āĻŋāĻšā§āĻ¯āĻŦāĻžāĻšā§ āĻāĻāĻ¨āĻŋāĻā§āĻ¸ā§ āĻĻā§āĻ°ā§āĻ āĻāĻ¤āĻŋāĻšāĻžāĻ¸ āĻāĻŦāĻ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ āĻ¸āĻ¤ā§āĻ¤ā§āĻŦā§āĻ ptrace āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ āĻāĻŦāĻ āĻā§āĻ°ā§āĻ¸āĻžāĻ°āĻā§āĻ˛āĻŋ POSIX-āĻ āĻ āĻ¨ā§āĻ¤āĻ°ā§āĻā§āĻā§āĻ¤ āĻāĻ°āĻž āĻšāĻ¯āĻŧāĻ¨āĻŋāĨ¤
āĻ¸āĻāĻā§āĻˇā§āĻĒā§ āĻ¸ā§āĻā§āĻ°ā§āĻ¸ āĻĄāĻŋāĻāĻžāĻāĻ¸: āĻĒāĻŋāĻāĻ˛ā§āĻ āĻā§āĻ°ā§āĻ¸
"āĻāĻĒāĻ¨āĻŋ āĻāĻāĻŋ āĻŦā§āĻāĻ¤ā§ āĻĒāĻžāĻ°āĻŦā§āĻ¨ āĻŦāĻ˛ā§ āĻāĻļāĻž āĻāĻ°āĻž āĻšāĻā§āĻā§ āĻ¨āĻž" (āĻĄā§āĻ¨āĻŋāĻ¸ āĻ°āĻŋāĻāĻŋ, āĻ¸āĻāĻ¸ā§āĻāĻ°āĻŖ 6 āĻāĻāĻ¨āĻŋāĻā§āĻ¸ āĻ¸ā§āĻ°ā§āĻ¸ āĻā§āĻĄā§ āĻŽāĻ¨ā§āĻ¤āĻŦā§āĻ¯)
āĻļā§āĻļāĻŦāĻāĻžāĻ˛ āĻĨā§āĻā§āĻ, āĻāĻŽāĻŋ āĻŦā§āĻ˛ā§āĻ¯āĻžāĻ āĻŦāĻā§āĻ¸āĻā§āĻ˛āĻŋ āĻĻāĻžāĻāĻĄāĻŧāĻžāĻ¤ā§ āĻĒāĻžāĻ°āĻŋ āĻ¨āĻž: āĻāĻŽāĻŋ āĻā§āĻ˛āĻ¨āĻž āĻ¨āĻŋāĻ¯āĻŧā§ āĻā§āĻ˛āĻ¤āĻžāĻŽ āĻ¨āĻž, āĻ¤āĻŦā§ āĻ¤āĻžāĻĻā§āĻ° āĻāĻ āĻ¨ āĻŦā§āĻāĻžāĻ° āĻā§āĻˇā§āĻāĻž āĻāĻ°āĻ¤āĻžāĻŽ (āĻĒā§āĻ°āĻžāĻĒā§āĻ¤āĻŦāĻ¯āĻŧāĻ¸ā§āĻāĻ°āĻž "āĻŦā§āĻ°ā§āĻ" āĻļāĻŦā§āĻĻāĻāĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°ā§ āĻ¤āĻŦā§ āĻŽāĻ¨ā§āĻĻ āĻāĻŋāĻšā§āĻŦāĻžāĻā§ āĻŦāĻŋāĻļā§āĻŦāĻžāĻ¸ āĻāĻ°āĻŦā§āĻ¨ āĻ¨āĻž)āĨ¤ āĻ¸āĻŽā§āĻāĻŦāĻ¤ āĻāĻ āĻāĻžāĻ°āĻŖā§āĻ āĻĒā§āĻ°āĻĨāĻŽ āĻāĻāĻ¨āĻŋāĻā§āĻ¸ā§āĻ° āĻ āĻ¨āĻžāĻ¨ā§āĻˇā§āĻ āĻžāĻ¨āĻŋāĻ āĻ¸āĻāĻ¸ā§āĻā§āĻ¤āĻŋ āĻāĻŦāĻ āĻāĻ§ā§āĻ¨āĻŋāĻ āĻāĻĒā§āĻ¨-āĻ¸ā§āĻ°ā§āĻ¸ āĻāĻ¨ā§āĻĻā§āĻ˛āĻ¨ āĻāĻŽāĻžāĻ° āĻā§āĻŦ āĻāĻžāĻāĻžāĻāĻžāĻāĻŋāĨ¤
āĻāĻ āĻ¨āĻŋāĻŦāĻ¨ā§āĻ§āĻāĻŋāĻ° āĻāĻĻā§āĻĻā§āĻļā§āĻ¯ā§, āĻ¸ā§āĻā§āĻ°ā§āĻ¸ā§āĻ° āĻ¸ā§āĻ°ā§āĻ¸ āĻā§āĻĄāĻāĻŋ āĻŦāĻŋāĻā§āĻāĻŋāĻ¨ā§āĻ¨ āĻāĻ°āĻž āĻ
āĻ¯ā§āĻā§āĻ¤āĻŋāĻ, āĻ¯āĻž āĻāĻ¯āĻŧā§āĻ āĻĻāĻļāĻ āĻ§āĻ°ā§ āĻŦā§āĻĄāĻŧā§āĻā§āĨ¤ āĻ¤āĻŦā§ āĻĒāĻžāĻ āĻāĻĻā§āĻ° āĻāĻ¨ā§āĻ¯ āĻā§āĻ¨ āĻā§āĻĒāĻ¨ā§āĻ¯āĻŧāĻ¤āĻž āĻĨāĻžāĻāĻž āĻāĻāĻŋāĻ¤ āĻ¨āĻ¯āĻŧāĨ¤ āĻ
āĻ¤āĻāĻŦ, āĻāĻ āĻāĻžāĻ¤ā§āĻ¯āĻŧ āĻ¸ā§āĻā§āĻ°ā§āĻ¸ āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽāĻā§āĻ˛āĻŋāĻ° āĻĒāĻ°āĻŋāĻāĻžāĻ˛āĻ¨āĻžāĻ° āĻ¨ā§āĻ¤āĻŋ āĻĻā§āĻāĻžāĻ¨ā§āĻ° āĻāĻ¨ā§āĻ¯, āĻāĻŽāĻŋ āĻāĻāĻāĻŋ āĻā§āĻˇā§āĻĻā§āĻ° āĻā§āĻ°ā§āĻ¸āĻžāĻ°ā§āĻ° āĻāĻ¨ā§āĻ¯ āĻā§āĻĄ āĻ¸āĻ°āĻŦāĻ°āĻžāĻš āĻāĻ°āĻŦ -
$ 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
āĻĒāĻŋāĻāĻ˛ā§āĻ āĻā§āĻ°ā§āĻ¸ āĻĒā§āĻ°āĻžāĻ¯āĻŧ āĻļāĻ¤ āĻļāĻ¤ āĻ˛āĻŋāĻ¨āĻžāĻā§āĻ¸ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛āĻā§ āĻ¸ā§āĻŦā§āĻā§āĻ¤āĻŋ āĻĻā§āĻ¯āĻŧ (āĻĻā§āĻā§āĻ¨āĨ¤
āĻāĻ¸ā§āĻ¨ āĻāĻŽāĻžāĻĻā§āĻ° āĻā§āĻ˛ā§āĻ¨ā§āĻ° āĻāĻžāĻ āĻĻā§āĻāĻŋāĨ¤ āĻ˛āĻŋāĻ¨āĻžāĻā§āĻ¸ā§āĻ° āĻā§āĻˇā§āĻ¤ā§āĻ°ā§, āĻĄāĻŋāĻŦāĻžāĻāĻžāĻ° āĻāĻŦāĻ āĻā§āĻ°ā§āĻ¸āĻžāĻ°āĻ°āĻž āĻāĻĒāĻ°ā§ āĻāĻ˛ā§āĻ˛āĻŋāĻāĻŋāĻ¤ āĻšāĻŋāĻ¸āĻžāĻŦā§, ptrace āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°ā§āĨ¤ āĻāĻāĻŋ āĻĒā§āĻ°āĻĨāĻŽ āĻāĻ°ā§āĻā§āĻŽā§āĻ¨ā§āĻā§ āĻāĻŽāĻžāĻ¨ā§āĻĄ āĻļāĻ¨āĻžāĻā§āĻ¤āĻāĻžāĻ°ā§āĻā§ āĻĒāĻžāĻ¸ āĻāĻ°ā§ āĻāĻžāĻ āĻāĻ°ā§, āĻ¯āĻžāĻ° āĻŽāĻ§ā§āĻ¯ā§ āĻāĻŽāĻžāĻĻā§āĻ° āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻĒā§āĻ°āĻ¯āĻŧā§āĻāĻ¨ PTRACE_TRACEME
, PTRACE_SYSCALL
и PTRACE_GETREGS
.
āĻā§āĻ°ā§āĻ¸āĻžāĻ° āĻ¸ā§āĻŦāĻžāĻāĻžāĻŦāĻŋāĻ āĻāĻāĻ¨āĻŋāĻā§āĻ¸ āĻļā§āĻ˛ā§āĻ¤ā§ āĻļā§āĻ°ā§ āĻšāĻ¯āĻŧ: 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 */
/* A traced mode has to be enabled. A parent will have to wait(2) for it
* to happen. */
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
/* Replace itself with a program to be run. */
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, ®isters) == -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, ®isters) == -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);
}
āĻāĻāĻžāĻ āĻĒā§āĻ°ā§ āĻā§āĻ°ā§āĻ¸āĻžāĻ°āĨ¤ āĻāĻāĻ¨ āĻāĻĒāĻ¨āĻŋ āĻāĻžāĻ¨ā§āĻ¨ āĻ¯ā§ āĻĒāĻ°āĻŦāĻ°ā§āĻ¤ā§ āĻĒā§āĻ°ā§āĻāĻŋāĻ āĻā§āĻĨāĻžāĻ¯āĻŧ āĻļā§āĻ°ā§ āĻāĻ°āĻŦā§āĻ¨
āĻŦā§āĻ¸āĻŋāĻ: āĻ¸ā§āĻā§āĻ°ā§āĻ¸ āĻāĻ˛āĻŽāĻžāĻ¨ āĻāĻāĻāĻŋ āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽ āĻāĻžāĻ˛āĻžāĻ¨ā§
āĻĒā§āĻ°āĻĨāĻŽ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ°ā§āĻ° āĻā§āĻˇā§āĻ¤ā§āĻ°ā§ strace
, āĻ¸āĻŽā§āĻāĻŦāĻ¤ āĻāĻāĻŋ āĻ¸āĻŦāĻā§āĻ¯āĻŧā§ āĻ¸āĻšāĻ āĻĒāĻĻā§āĻ§āĻ¤āĻŋ āĻāĻĻā§āĻ§ā§āĻ¤ āĻāĻ°āĻž āĻŽā§āĻ˛ā§āĻ¯āĻŦāĻžāĻ¨ - āĻāĻāĻāĻŋ āĻ
ā§āĻ¯āĻžāĻĒā§āĻ˛āĻŋāĻā§āĻļāĻ¨ āĻāĻžāĻ˛ā§ āĻāĻ°āĻž strace
.
āĻāĻāĻāĻŋ āĻ¸āĻžāĻ§āĻžāĻ°āĻŖ āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽā§āĻ° āĻāĻ˛āĻā§āĻ˛āĻŋāĻ° āĻ
āĻ¨ā§āĻ¤āĻšā§āĻ¨ āĻ¤āĻžāĻ˛āĻŋāĻāĻžāĻ¯āĻŧ āĻ¨āĻž āĻ¯āĻžāĻāĻ¯āĻŧāĻžāĻ° āĻāĻ¨ā§āĻ¯, āĻāĻŽāĻ°āĻž āĻ˛āĻŋāĻāĻŋ write
:
int main(int argc, char *argv[])
{
char str[] = "write me to stdoutn";
/* write(2) is a simple wrapper around a syscall so it should be easy to
* find in the syscall trace. */
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 ./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, "177ELF21133>1260342"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030544, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7a2a631000
mmap(NULL, 4131552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f7a2a04c000
mprotect(0x7f7a2a233000, 2097152, PROT_NONE) = 0
mmap(0x7f7a2a433000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7f7a2a433000
mmap(0x7f7a2a439000, 15072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f7a2a439000
close(3) = 0
arch_prctl(ARCH_SET_FS, 0x7f7a2a6324c0) = 0
mprotect(0x7f7a2a433000, 16384, PROT_READ) = 0
mprotect(0x55ff52b52000, 4096, PROT_READ) = 0
mprotect(0x7f7a2a664000, 4096, PROT_READ) = 0
munmap(0x7f7a2a633000, 197410) = 0
write(1, "write me to stdoutn", 20write me to stdout
) = 20
exit_group(0) = ?
āĻā§āĻŦ "āĻļāĻŦā§āĻĻāĻ¯ā§āĻā§āĻ¤" āĻāĻŦāĻ āĻā§āĻŦ āĻļāĻŋāĻā§āĻˇāĻžāĻŽā§āĻ˛āĻ āĻ¨āĻ¯āĻŧāĨ¤ āĻāĻāĻžāĻ¨ā§ āĻĻā§āĻāĻŋ āĻ¸āĻŽāĻ¸ā§āĻ¯āĻž āĻ°āĻ¯āĻŧā§āĻā§: āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽā§āĻ° āĻāĻāĻāĻĒā§āĻ āĻāĻāĻāĻĒā§āĻā§āĻ° āĻ¸āĻžāĻĨā§ āĻŽāĻŋāĻļā§āĻ°āĻŋāĻ¤ āĻšāĻ¯āĻŧ strace
āĻāĻŦāĻ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ā§āĻ° āĻĒā§āĻ°āĻžāĻā§āĻ°ā§āĻ¯ āĻ¯āĻž āĻāĻŽāĻžāĻĻā§āĻ° āĻāĻā§āĻ°āĻšā§āĻ° āĻ¨āĻ¯āĻŧāĨ¤
āĻāĻĒāĻ¨āĻŋ -o āĻ¸ā§āĻāĻ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°ā§ āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽā§āĻ° āĻ¸ā§āĻā§āĻ¯āĻžāĻ¨ā§āĻĄāĻžāĻ°ā§āĻĄ āĻāĻāĻāĻĒā§āĻ āĻ¸ā§āĻā§āĻ°ā§āĻŽ āĻāĻŦāĻ āĻ¸ā§āĻā§āĻ°ā§āĻ¸ āĻ¤ā§āĻ°ā§āĻāĻŋ āĻāĻāĻāĻĒā§āĻ āĻāĻ˛āĻžāĻĻāĻž āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨, āĻ¯āĻž āĻāĻāĻāĻŋ āĻāĻ°ā§āĻā§āĻŽā§āĻ¨ā§āĻ āĻĢāĻžāĻāĻ˛ā§ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ā§āĻ° āĻ¤āĻžāĻ˛āĻŋāĻāĻž āĻĒā§āĻ¨āĻāĻ¨āĻŋāĻ°ā§āĻĻā§āĻļ āĻāĻ°ā§āĨ¤
āĻāĻāĻŋ "āĻ
āĻ¤āĻŋāĻ°āĻŋāĻā§āĻ¤" āĻāĻ˛āĻā§āĻ˛āĻŋāĻ° āĻ¸āĻŽāĻ¸ā§āĻ¯āĻž āĻŽā§āĻāĻžāĻŦā§āĻ˛āĻž āĻāĻ°āĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻ
āĻŦāĻļā§āĻˇā§ˇ āĻāĻ¸ā§āĻ¨ āĻ§āĻ°ā§ āĻ¨āĻŋāĻ āĻ¯ā§ āĻāĻŽāĻ°āĻž āĻā§āĻŦāĻ˛ āĻāĻ˛āĻā§āĻ˛āĻŋāĻ¤ā§ āĻāĻā§āĻ°āĻšā§ write
. āĻāĻžāĻŦāĻŋ -e
āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛āĻā§āĻ˛āĻŋ āĻĢāĻŋāĻ˛ā§āĻāĻžāĻ° āĻāĻ°āĻž āĻšāĻŦā§ āĻāĻŽāĻ¨ āĻāĻā§āĻ¸āĻĒā§āĻ°ā§āĻļāĻ¨āĻā§āĻ˛āĻŋ āĻāĻĒāĻ¨āĻžāĻā§ āĻ¨āĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āĻ āĻāĻ°āĻ¤ā§ āĻĻā§āĻ¯āĻŧāĨ¤ āĻ¸āĻŦāĻā§āĻ¯āĻŧā§ āĻāĻ¨āĻĒā§āĻ°āĻŋāĻ¯āĻŧ āĻļāĻ°ā§āĻ¤ āĻŦāĻŋāĻāĻ˛ā§āĻĒ, āĻ¸ā§āĻŦāĻžāĻāĻžāĻŦāĻŋāĻāĻāĻžāĻŦā§āĻ, trace=*
, āĻ¯āĻž āĻĻāĻŋāĻ¯āĻŧā§ āĻāĻĒāĻ¨āĻŋ āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻāĻŽāĻžāĻĻā§āĻ° āĻāĻā§āĻ°āĻšā§āĻ° āĻāĻ˛āĻā§āĻ˛āĻŋ āĻā§āĻĄāĻŧā§ āĻ¯ā§āĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨āĨ¤
āĻ¯āĻāĻ¨ āĻāĻāĻ āĻ¸āĻžāĻĨā§ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻž āĻšāĻ¯āĻŧ -o
и -e
āĻāĻŽāĻ°āĻž āĻĒāĻžāĻŦ:
$ strace -e trace=write -owrite-simple.log ./write-simple
write me to stdout
$ cat write-simple.log
write(1, "write me to stdoutn", 20
) = 20
+++ exited with 0 +++
āĻ¸ā§āĻ¤āĻ°āĻžāĻ, āĻāĻĒāĻ¨āĻŋ āĻĻā§āĻā§āĻ¨, āĻāĻāĻŋ āĻĒāĻĄāĻŧāĻž āĻ āĻ¨ā§āĻ āĻ¸āĻšāĻāĨ¤
āĻāĻĒāĻ¨āĻŋ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛āĻā§āĻ˛āĻŋāĻ āĻ¸āĻ°āĻžāĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨, āĻāĻĻāĻžāĻšāĻ°āĻŖāĻ¸ā§āĻŦāĻ°ā§āĻĒ āĻ¯ā§āĻā§āĻ˛āĻŋ āĻŽā§āĻŽāĻ°āĻŋ āĻŦāĻ°āĻžāĻĻā§āĻĻ āĻāĻŦāĻ āĻĢā§āĻ°āĻŋ āĻāĻ°āĻžāĻ° āĻ¸āĻžāĻĨā§ āĻ¸āĻŽā§āĻĒāĻ°ā§āĻāĻŋāĻ¤:
$ strace -e trace=!brk,mmap,mprotect,munmap -owrite-simple.log ./write-simple
write me to stdout
$ cat write-simple.log
execve("./write-simple", ["./write-simple"], 0x7ffe9972a498 /* 69 vars */) = 0
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=124066, ...}) = 0
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, "177ELF21133>1260342"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030544, ...}) = 0
close(3) = 0
arch_prctl(ARCH_SET_FS, 0x7f00f0be74c0) = 0
write(1, "write me to stdoutn", 20) = 20
exit_group(0) = ?
+++ exited with 0 +++
āĻŦāĻžāĻĻ āĻĻā§āĻāĻ¯āĻŧāĻž āĻāĻ˛āĻā§āĻ˛āĻŋāĻ° āĻ¤āĻžāĻ˛āĻŋāĻāĻžāĻ¯āĻŧ āĻāĻ¸ā§āĻā§āĻĒāĻĄ āĻŦāĻŋāĻ¸ā§āĻŽāĻ¯āĻŧāĻŦā§āĻ§āĻ āĻāĻŋāĻšā§āĻ¨āĻāĻŋ āĻ¨ā§āĻ āĻāĻ°ā§āĻ¨: āĻāĻāĻŋ āĻāĻŽāĻžāĻ¨ā§āĻĄ āĻļā§āĻ˛ āĻĻā§āĻŦāĻžāĻ°āĻž āĻĒā§āĻ°āĻ¯āĻŧā§āĻāĻ¨ā§āĻ¯āĻŧāĨ¤ āĻā§āĻ˛).
glibc āĻāĻ° āĻāĻŽāĻžāĻ° āĻ¸āĻāĻ¸ā§āĻāĻ°āĻŖā§, āĻāĻāĻāĻŋ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻāĻŋ āĻŦāĻ¨ā§āĻ§ āĻāĻ°ā§ āĻĻā§āĻ¯āĻŧ exit_group
, āĻāĻ¤āĻŋāĻšā§āĻ¯āĻāĻ¤ āĻ¨āĻ¯āĻŧ _exit
. āĻāĻāĻŋ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛āĻā§āĻ˛āĻŋāĻ° āĻ¸āĻžāĻĨā§ āĻāĻžāĻ āĻāĻ°āĻžāĻ° āĻ
āĻ¸ā§āĻŦāĻŋāĻ§āĻž: āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽāĻžāĻ° āĻ¯ā§ āĻāĻ¨ā§āĻāĻžāĻ°āĻĢā§āĻ¸ā§āĻ° āĻ¸āĻžāĻĨā§ āĻāĻžāĻ āĻāĻ°ā§ āĻ¤āĻž āĻ¸āĻ°āĻžāĻ¸āĻ°āĻŋ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛āĻā§āĻ˛āĻŋāĻ° āĻ¸āĻžāĻĨā§ āĻ¸āĻŽā§āĻĒāĻ°ā§āĻāĻŋāĻ¤ āĻ¨āĻ¯āĻŧāĨ¤ āĻ
āĻ§āĻŋāĻāĻ¨ā§āĻ¤ā§, āĻāĻāĻŋ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ āĻāĻŦāĻ āĻĒā§āĻ˛ā§āĻ¯āĻžāĻāĻĢāĻ°ā§āĻŽā§āĻ° āĻāĻĒāĻ° āĻ¨āĻŋāĻ°ā§āĻāĻ° āĻāĻ°ā§ āĻ¨āĻŋāĻ¯āĻŧāĻŽāĻŋāĻ¤ āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤āĻ¨ āĻšāĻ¯āĻŧāĨ¤
āĻŦā§āĻ¸āĻŋāĻ: āĻāĻĄāĻŧā§ āĻ¯āĻžāĻāĻ¯āĻŧāĻžāĻ° āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻ¯āĻŧ āĻ¯ā§āĻāĻĻāĻžāĻ¨
āĻĒā§āĻ°āĻžāĻĨāĻŽāĻŋāĻāĻāĻžāĻŦā§, ptrace āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ āĻ¯āĻžāĻ° āĻāĻĒāĻ° āĻāĻāĻŋ āĻ¨āĻŋāĻ°ā§āĻŽāĻŋāĻ¤ āĻšāĻ¯āĻŧā§āĻāĻŋāĻ˛ strace
, āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻāĻāĻāĻŋ āĻŦāĻŋāĻļā§āĻˇ āĻŽā§āĻĄā§ āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽ āĻāĻžāĻ˛āĻžāĻ¨ā§āĻ° āĻ¸āĻŽāĻ¯āĻŧ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻž āĻ¯ā§āĻ¤ā§ āĻĒāĻžāĻ°ā§āĨ¤ āĻ¸āĻāĻ¸ā§āĻāĻ°āĻŖ 6 āĻāĻāĻ¨āĻŋāĻā§āĻ¸ā§āĻ° āĻĻāĻŋāĻ¨ā§ āĻāĻ āĻ¸ā§āĻŽāĻžāĻŦāĻĻā§āĻ§āĻ¤āĻž āĻ¯ā§āĻā§āĻ¤āĻŋāĻ¸āĻā§āĻāĻ¤ āĻŦāĻ˛ā§ āĻŽāĻ¨ā§ āĻšāĻ¤ā§ āĻĒāĻžāĻ°ā§āĨ¤ āĻāĻāĻāĻžāĻ˛, āĻāĻāĻŋ āĻāĻ° āĻ¯āĻĨā§āĻˇā§āĻ āĻ¨āĻ¯āĻŧ: āĻāĻāĻ¨āĻ āĻāĻāĻ¨āĻ āĻāĻĒāĻ¨āĻžāĻā§ āĻāĻāĻāĻŋ āĻāĻžāĻā§āĻ° āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽā§āĻ° āĻ¸āĻŽāĻ¸ā§āĻ¯āĻžāĻā§āĻ˛āĻŋ āĻ¤āĻĻāĻ¨ā§āĻ¤ āĻāĻ°āĻ¤ā§ āĻšāĻŦā§āĨ¤ āĻāĻāĻāĻŋ āĻ¸āĻžāĻ§āĻžāĻ°āĻŖ āĻāĻĻāĻžāĻšāĻ°āĻŖ āĻšāĻ˛ āĻāĻāĻāĻŋ āĻšā§āĻ¯āĻžāĻ¨ā§āĻĄā§āĻ˛ āĻŦāĻž āĻā§āĻŽā§āĻ° āĻāĻĒāĻ° āĻ
āĻŦāĻ°ā§āĻĻā§āĻ§ āĻāĻāĻāĻŋ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻžāĨ¤ āĻ¤āĻžāĻ āĻāĻ§ā§āĻ¨āĻŋāĻ strace
āĻĢā§āĻ˛āĻžāĻ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻ¯āĻŧ āĻ¯ā§āĻāĻĻāĻžāĻ¨ āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨.
āĻšāĻŋāĻŽāĻžāĻ¯āĻŧāĻŋāĻ¤ āĻāĻĻāĻžāĻšāĻ°āĻŖ
int main(int argc, char *argv[])
{
(void) argc; (void) argv;
char str[] = "write men";
write(STDOUT_FILENO, str, sizeof(str));
/* Sleep indefinitely or until a signal arrives */
pause();
write(STDOUT_FILENO, str, sizeof(str));
return EXIT_SUCCESS;
}
āĻāĻ¸ā§āĻ¨ āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽāĻāĻŋ āĻ¤ā§āĻ°āĻŋ āĻāĻ°āĻŋ āĻāĻŦāĻ āĻ¨āĻŋāĻļā§āĻāĻŋāĻ¤ āĻāĻ°ā§āĻ¨ āĻ¯ā§ āĻāĻāĻŋ āĻšāĻŋāĻŽāĻžāĻ¯āĻŧāĻŋāĻ¤ āĻšāĻ¯āĻŧā§āĻā§:
$ gcc examples/write-sleep.c -o write-sleep
$ ./write-sleep
./write-sleep
write me
^C
$
āĻāĻāĻ¨ āĻāĻ° āĻ¸āĻžāĻĨā§ āĻ¯ā§āĻ āĻĻā§āĻāĻ¯āĻŧāĻžāĻ° āĻā§āĻˇā§āĻāĻž āĻāĻ°āĻž āĻ¯āĻžāĻ:
$ ./write-sleep &
[1] 15329
write me
$ strace -p 15329
strace: Process 15329 attached
pause(
^Cstrace: Process 15329 detached
<detached ...>
āĻāĻ˛ āĻĻā§āĻŦāĻžāĻ°āĻž āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽ āĻ
āĻŦāĻ°ā§āĻĻā§āĻ§ pause
. āĻāĻ¸ā§āĻ¨ āĻĻā§āĻāĻŋ āĻ¸ā§ āĻ¸āĻāĻā§āĻ¤āĻā§āĻ˛āĻŋāĻ¤ā§ āĻā§āĻāĻžāĻŦā§ āĻĒā§āĻ°āĻ¤āĻŋāĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻāĻžāĻ¨āĻžāĻ¯āĻŧ:
$ strace -o write-sleep.log -p 15329 &
strace: Process 15329 attached
$
$ kill -CONT 15329
$ cat write-sleep.log
pause() = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGCONT {si_signo=SIGCONT, si_code=SI_USER, si_pid=14989, si_uid=1001} ---
pause(
$
$ kill -TERM 15329
$ cat write-sleep.log
pause() = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGCONT {si_signo=SIGCONT, si_code=SI_USER, si_pid=14989, si_uid=1001} ---
pause() = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=14989, si_uid=1001} ---
+++ killed by SIGTERM +++
āĻāĻŽāĻ°āĻž āĻšāĻŋāĻŽāĻžāĻ¯āĻŧāĻŋāĻ¤ āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽ āĻāĻžāĻ˛ā§ āĻāĻ°ā§āĻāĻŋ āĻāĻŦāĻ āĻāĻāĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°ā§ āĻ¯ā§āĻāĻĻāĻžāĻ¨ āĻāĻ°ā§āĻāĻŋ strace
. āĻĻā§āĻāĻŋ āĻāĻŋāĻ¨āĻŋāĻ¸ āĻĒāĻ°āĻŋāĻˇā§āĻāĻžāĻ° āĻšāĻ¯āĻŧā§ āĻā§āĻ˛: āĻĒāĻ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ āĻšā§āĻ¯āĻžāĻ¨ā§āĻĄāĻ˛āĻžāĻ° āĻāĻžāĻĄāĻŧāĻžāĻ āĻ¸āĻŋāĻāĻ¨ā§āĻ¯āĻžāĻ˛ āĻāĻĒā§āĻā§āĻˇāĻž āĻāĻ°ā§ āĻāĻŦāĻ āĻāĻ°āĻ āĻŽāĻāĻžāĻ° āĻŦāĻŋāĻˇāĻ¯āĻŧ āĻšāĻ˛, āĻ¸ā§āĻā§āĻ°ā§āĻ¸ āĻŽāĻ¨āĻŋāĻāĻ°āĻā§āĻ˛āĻŋ āĻā§āĻŦāĻ˛ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛āĻ āĻ¨āĻ¯āĻŧ, āĻāĻ¨āĻāĻžāĻŽāĻŋāĻ āĻ¸āĻŋāĻāĻ¨ā§āĻ¯āĻžāĻ˛āĻāĨ¤
āĻāĻĻāĻžāĻšāĻ°āĻŖ: āĻā§āĻ°ā§āĻ¯āĻžāĻāĻŋāĻ āĻāĻžāĻāĻ˛ā§āĻĄ āĻĒā§āĻ°āĻ¸ā§āĻ¸
āĻāĻāĻāĻŋ āĻāĻ˛ āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻ¸āĻā§āĻā§ āĻāĻžāĻ fork
- āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻāĻāĻ¨āĻŋāĻā§āĻ¸ā§āĻ° āĻāĻŋāĻ¤ā§āĻ¤āĻŋāĨ¤ āĻāĻ¸ā§āĻ¨ āĻĻā§āĻāĻŋ āĻāĻŋāĻāĻžāĻŦā§ āĻ¸ā§āĻā§āĻ°ā§āĻ¸ āĻāĻāĻāĻŋ āĻ¸āĻšāĻ "āĻĒā§āĻ°āĻāĻ¨āĻ¨" āĻāĻ° āĻāĻĻāĻžāĻšāĻ°āĻŖ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°ā§ āĻāĻāĻāĻŋ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻāĻžāĻā§āĻ° āĻ¸āĻžāĻĨā§ āĻāĻžāĻ āĻāĻ°ā§
int main(int argc, char *argv[])
{
pid_t parent_pid = getpid();
pid_t child_pid = fork();
if (child_pid == 0) {
/* A child is born! */
child_pid = getpid();
/* In the end of the day printf is just a call to write(2). */
printf("child (self=%d)n", child_pid);
exit(EXIT_SUCCESS);
}
printf("parent (self=%d, child=%d)n", parent_pid, child_pid);
wait(NULL);
exit(EXIT_SUCCESS);
}
āĻāĻāĻžāĻ¨ā§ āĻŽā§āĻ˛ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻāĻŋ āĻāĻāĻāĻŋ āĻļāĻŋāĻļā§ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻ¤ā§āĻ°āĻŋ āĻāĻ°ā§, āĻāĻāĻ¯āĻŧāĻ āĻ¸ā§āĻā§āĻ¯āĻžāĻ¨ā§āĻĄāĻžāĻ°ā§āĻĄ āĻāĻāĻāĻĒā§āĻā§ āĻ˛ā§āĻāĻž:
$ gcc examples/fork-write.c -o fork-write
$ ./fork-write
parent (self=11274, child=11275)
child (self=11275)
āĻĄāĻŋāĻĢāĻ˛ā§āĻāĻ°ā§āĻĒā§, āĻāĻŽāĻ°āĻž āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻĒā§āĻ¯āĻžāĻ°ā§āĻ¨ā§āĻ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻĨā§āĻā§ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ āĻĻā§āĻāĻ¤ā§ āĻĒāĻžāĻŦ:
$ strace -e trace=write -ofork-write.log ./fork-write
child (self=22049)
parent (self=22048, child=22049)
$ cat fork-write.log
write(1, "parent (self=22048, child=22049)"..., 33) = 33
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=22049, si_uid=1001, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++
āĻĒāĻ¤āĻžāĻāĻž āĻāĻĒāĻ¨āĻžāĻā§ āĻĒā§āĻ°ā§ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻāĻžāĻ āĻā§āĻ°ā§āĻ¯āĻžāĻ āĻāĻ°āĻ¤ā§ āĻ¸āĻžāĻšāĻžāĻ¯ā§āĻ¯ āĻāĻ°ā§ -f
, āĻ¯āĻž strace
āĻļāĻŋāĻļā§ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻ¯āĻŧ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ āĻ¨āĻŋāĻ°ā§āĻā§āĻˇāĻŖ āĻāĻ°ā§āĨ¤ āĻāĻāĻŋ āĻāĻāĻāĻĒā§āĻā§āĻ° āĻĒā§āĻ°āĻ¤āĻŋāĻāĻŋ āĻ˛āĻžāĻāĻ¨ā§ āĻ¯ā§āĻ āĻāĻ°ā§ pid
āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻ¯āĻž āĻāĻāĻāĻŋ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻāĻāĻĒā§āĻ āĻāĻ°ā§:
$ strace -f -e trace=write -ofork-write.log ./fork-write
parent (self=22710, child=22711)
child (self=22711)
$ cat fork-write.log
22710 write(1, "parent (self=22710, child=22711)"..., 33) = 33
22711 write(1, "child (self=22711)n", 19) = 19
22711 +++ exited with 0 +++
22710 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=22711, si_uid=1001, si_status=0, si_utime=0, si_stime=0} ---
22710 +++ exited with 0 +++
āĻāĻ āĻĒā§āĻ°āĻ¸āĻā§āĻā§, āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ā§āĻ° āĻā§āĻ°ā§āĻĒ āĻĻā§āĻŦāĻžāĻ°āĻž āĻĢāĻŋāĻ˛ā§āĻāĻžāĻ° āĻāĻ°āĻž āĻĻāĻ°āĻāĻžāĻ°ā§ āĻšāĻ¤ā§ āĻĒāĻžāĻ°ā§:
$ strace -f -e trace=%process -ofork-write.log ./fork-write
parent (self=23610, child=23611)
child (self=23611)
$ cat fork-write.log
23610 execve("./fork-write", ["./fork-write"], 0x7fff696ff720 /* 63 vars */) = 0
23610 arch_prctl(ARCH_SET_FS, 0x7f3d03ba44c0) = 0
23610 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f3d03ba4790) = 23611
23610 wait4(-1, <unfinished ...>
23611 exit_group(0) = ?
23611 +++ exited with 0 +++
23610 <... wait4 resumed> NULL, 0, NULL) = 23611
23610 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=23611, si_uid=1001, si_status=0, si_utime=0, si_stime=0} ---
23610 exit_group(0) = ?
23610 +++ exited with 0 +++
āĻāĻĒāĻžāĻ¯āĻŧ āĻĻā§āĻŦāĻžāĻ°āĻž, āĻā§āĻ¨ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ āĻāĻāĻāĻŋ āĻ¨āĻ¤ā§āĻ¨ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻ¤ā§āĻ°āĻŋ āĻāĻ°āĻ¤ā§ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻž āĻšāĻ¯āĻŧ?
āĻāĻĻāĻžāĻšāĻ°āĻŖ: āĻšā§āĻ¯āĻžāĻ¨ā§āĻĄā§āĻ˛ā§āĻ° āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤ā§ āĻĢāĻžāĻāĻ˛ āĻĒāĻžāĻĨ
āĻĢāĻžāĻāĻ˛ āĻŦāĻ°ā§āĻŖāĻ¨āĻžāĻāĻžāĻ°ā§ āĻāĻžāĻ¨āĻž āĻ āĻŦāĻļā§āĻ¯āĻ āĻĻāĻ°āĻāĻžāĻ°ā§, āĻ¤āĻŦā§ āĻāĻāĻāĻŋ āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽ āĻ ā§āĻ¯āĻžāĻā§āĻ¸ā§āĻ¸ āĻāĻ°ā§ āĻāĻŽāĻ¨ āĻ¨āĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āĻ āĻĢāĻžāĻāĻ˛āĻā§āĻ˛āĻŋāĻ° āĻ¨āĻžāĻŽāĻā§āĻ˛āĻŋāĻ āĻāĻžāĻā§ āĻāĻ¸āĻ¤ā§ āĻĒāĻžāĻ°ā§āĨ¤
āĻĒāĻ°āĻŦāĻ°ā§āĻ¤ā§
void do_write(int out_fd)
{
char str[] = "write me to a filen";
if (sizeof(str) != write(out_fd, str, sizeof(str))){
perror("write");
exit(EXIT_FAILURE);
}
}
int main(int argc, char *argv[])
{
char tmp_filename_template[] = "/tmp/output_fileXXXXXX";
int out_fd = mkstemp(tmp_filename_template);
if (out_fd == -1) {
perror("mkstemp");
exit(EXIT_FAILURE);
}
do_write(out_fd);
return EXIT_SUCCESS;
}
āĻāĻāĻāĻŋ āĻ¸āĻžāĻ§āĻžāĻ°āĻŖ āĻāĻ˛ā§āĻ° āĻ¸āĻŽāĻ¯āĻŧ strace
āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ā§ āĻĒāĻžāĻ¸ āĻāĻ°āĻž āĻŦāĻ°ā§āĻŖāĻ¨āĻžāĻāĻžāĻ°ā§ āĻ¨āĻŽā§āĻŦāĻ°ā§āĻ° āĻŽāĻžāĻ¨ āĻĻā§āĻāĻžāĻŦā§:
$ strace -e trace=write -o write-tmp-file.log ./write-tmp-file
$ cat write-tmp-file.log
write(3, "write me to a filen", 20) = 20
+++ exited with 0 +++
āĻĒāĻ¤āĻžāĻāĻž āĻ¨āĻŋāĻ¯āĻŧā§ -y
āĻāĻāĻāĻŋāĻ˛āĻŋāĻāĻŋ āĻĢāĻžāĻāĻ˛āĻāĻŋāĻ° āĻĒāĻĨ āĻĻā§āĻāĻžāĻ¯āĻŧ āĻ¯āĻžāĻ° āĻ¸āĻžāĻĨā§ āĻŦāĻ°ā§āĻŖāĻ¨āĻžāĻāĻžāĻ°ā§āĻ° āĻŽāĻŋāĻ˛ āĻ°āĻ¯āĻŧā§āĻā§:
$ strace -y -e trace=write -o write-tmp-file.log ./write-tmp-file
$ cat write-tmp-file.log
write(3</tmp/output_fileCf5MyW>, "write me to a filen", 20) = 20
+++ exited with 0 +++
āĻāĻĻāĻžāĻšāĻ°āĻŖ: āĻĢāĻžāĻāĻ˛ āĻ ā§āĻ¯āĻžāĻā§āĻ¸ā§āĻ¸ āĻā§āĻ°ā§āĻ¯āĻžāĻāĻŋāĻ
āĻāĻ°ā§āĻāĻāĻŋ āĻĻāĻ°āĻāĻžāĻ°ā§ āĻŦā§āĻļāĻŋāĻˇā§āĻā§āĻ¯: āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻāĻāĻāĻŋ āĻ¨āĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āĻ āĻĢāĻžāĻāĻ˛ā§āĻ° āĻ¸āĻžāĻĨā§ āĻ¯ā§āĻā§āĻ¤ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ āĻĒā§āĻ°āĻĻāĻ°ā§āĻļāĻ¨ āĻāĻ°ā§āĻ¨āĨ¤ āĻĒāĻ°āĻŦāĻ°ā§āĻ¤ā§
void do_write(int out_fd)
{
char str[] = "write me to a filen";
if (sizeof(str) != write(out_fd, str, sizeof(str))){
perror("write");
exit(EXIT_FAILURE);
}
}
int main(int argc, char *argv[])
{
/*
* Path will be provided by the first program argument.
* */
const char *path = argv[1];
/*
* Open an existing file for writing in append mode.
* */
int out_fd = open(path, O_APPEND | O_WRONLY);
if (out_fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
do_write(out_fd);
return EXIT_SUCCESS;
}
āĻĄāĻŋāĻĢāĻ˛ā§āĻāĻ°ā§āĻĒā§ strace
āĻ
āĻ¨ā§āĻ āĻ
āĻĒā§āĻ°āĻ¯āĻŧā§āĻāĻ¨ā§āĻ¯āĻŧ āĻ¤āĻĨā§āĻ¯ āĻĒā§āĻ°āĻĻāĻ°ā§āĻļāĻ¨ āĻāĻ°ā§āĨ¤ āĻĒāĻ¤āĻžāĻāĻž -P
āĻāĻāĻāĻŋ āĻ¯ā§āĻā§āĻ¤āĻŋ āĻĻāĻŋāĻ¯āĻŧā§ āĻ¸ā§āĻā§āĻ°ā§āĻ¸ āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻ¨āĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āĻ āĻĢāĻžāĻāĻ˛ā§ āĻāĻ˛ āĻĒā§āĻ°āĻŋāĻ¨ā§āĻ āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§:
$ strace -y -P/tmp/test_file.log -o write-file.log ./write-file /tmp/test_file.log
$ cat write-file.log
openat(AT_FDCWD, "/tmp/test_file.log", O_WRONLY|O_APPEND) = 3</tmp/test_file.log>
write(3</tmp/test_file.log>, "write me to a filen", 20) = 20
+++ exited with 0 +++
āĻāĻĻāĻžāĻšāĻ°āĻŖ: āĻŽāĻžāĻ˛ā§āĻāĻŋāĻĨā§āĻ°ā§āĻĄā§āĻĄ āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽ
āĻāĻāĻāĻŋāĻ˛āĻŋāĻāĻŋ strace
āĻŽāĻžāĻ˛ā§āĻāĻŋ-āĻĨā§āĻ°ā§āĻĄā§āĻĄā§āĻ° āĻ¸āĻžāĻĨā§ āĻāĻžāĻ āĻāĻ°āĻžāĻ° āĻ¸āĻŽāĻ¯āĻŧāĻ āĻ¸āĻžāĻšāĻžāĻ¯ā§āĻ¯ āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§
void *thread(void *arg)
{
(void) arg;
printf("Secondary thread: workingn");
sleep(1);
printf("Secondary thread: donen");
return NULL;
}
int main(int argc, char *argv[])
{
printf("Initial thread: launching a threadn");
pthread_t thr;
if (0 != pthread_create(&thr, NULL, thread, NULL)) {
fprintf(stderr, "Initial thread: failed to create a thread");
exit(EXIT_FAILURE);
}
printf("Initial thread: joining a threadn");
if (0 != pthread_join(thr, NULL)) {
fprintf(stderr, "Initial thread: failed to join a thread");
exit(EXIT_FAILURE);
};
printf("Initial thread: done");
exit(EXIT_SUCCESS);
}
āĻ¸ā§āĻŦāĻžāĻāĻžāĻŦāĻŋāĻāĻāĻžāĻŦā§āĻ, āĻāĻāĻŋ āĻ āĻŦāĻļā§āĻ¯āĻ āĻ˛āĻŋāĻā§āĻāĻžāĻ°āĻā§ āĻāĻāĻāĻŋ āĻŦāĻŋāĻļā§āĻˇ āĻļā§āĻā§āĻā§āĻāĻž āĻ¸āĻš āĻ¸āĻāĻāĻ˛āĻŋāĻ¤ āĻāĻ°āĻž āĻāĻāĻŋāĻ¤ - -pthread āĻĒāĻ¤āĻžāĻāĻž:
$ gcc examples/thread-write.c -pthread -o thread-write
$ ./thread-write
/thread-write
Initial thread: launching a thread
Initial thread: joining a thread
Secondary thread: working
Secondary thread: done
Initial thread: done
$
āĻĒāĻ¤āĻžāĻāĻž -f
, āĻ¨āĻŋāĻ¯āĻŧāĻŽāĻŋāĻ¤ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻ° āĻā§āĻˇā§āĻ¤ā§āĻ°ā§, āĻĒā§āĻ°āĻ¤āĻŋāĻāĻŋ āĻ˛āĻžāĻāĻ¨ā§āĻ° āĻļā§āĻ°ā§āĻ¤ā§ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻāĻŋāĻ° āĻĒāĻŋāĻĄ āĻ¯ā§āĻ āĻāĻ°āĻŦā§āĨ¤
āĻ¸ā§āĻŦāĻžāĻāĻžāĻŦāĻŋāĻāĻāĻžāĻŦā§āĻ, āĻāĻŽāĻ°āĻž POSIX āĻĨā§āĻ°ā§āĻĄ āĻ¸ā§āĻā§āĻ¯āĻžāĻ¨ā§āĻĄāĻžāĻ°ā§āĻĄ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ā§āĻ° āĻ āĻ°ā§āĻĨā§ āĻāĻāĻāĻŋ āĻĨā§āĻ°ā§āĻĄ āĻļāĻ¨āĻžāĻā§āĻ¤āĻāĻžāĻ°ā§ āĻ¸āĻŽā§āĻĒāĻ°ā§āĻā§ āĻāĻĨāĻž āĻŦāĻ˛āĻāĻŋ āĻ¨āĻž, āĻ¤āĻŦā§ āĻ˛āĻŋāĻ¨āĻžāĻā§āĻ¸ā§ āĻāĻžāĻ¸ā§āĻ āĻļāĻŋāĻĄāĻŋāĻāĻ˛āĻžāĻ°ā§āĻ° āĻĻā§āĻŦāĻžāĻ°āĻž āĻŦā§āĻ¯āĻŦāĻšā§āĻ¤ āĻ¸āĻāĻā§āĻ¯āĻž āĻ¸āĻŽā§āĻĒāĻ°ā§āĻā§ āĻāĻĨāĻž āĻŦāĻ˛āĻāĻŋāĨ¤ āĻĒāĻ°ā§āĻ°āĻāĻŋāĻ° āĻĻā§āĻˇā§āĻāĻŋāĻā§āĻŖ āĻĨā§āĻā§, āĻā§āĻ¨āĻ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻŦāĻž āĻĨā§āĻ°ā§āĻĄ āĻ¨ā§āĻ - āĻāĻŽāĻ¨ āĻāĻžāĻ āĻ°āĻ¯āĻŧā§āĻā§ āĻ¯āĻž āĻŽā§āĻļāĻŋāĻ¨ā§āĻ° āĻāĻĒāĻ˛āĻŦā§āĻ§ āĻā§āĻ°āĻā§āĻ˛āĻŋāĻ° āĻŽāĻ§ā§āĻ¯ā§ āĻŦāĻŋāĻ¤āĻ°āĻŖ āĻāĻ°āĻž āĻĻāĻ°āĻāĻžāĻ°āĨ¤
āĻāĻāĻžāĻ§āĻŋāĻ āĻĨā§āĻ°ā§āĻĄā§ āĻāĻžāĻ āĻāĻ°āĻžāĻ° āĻ¸āĻŽāĻ¯āĻŧ, āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ āĻ āĻ¨ā§āĻ āĻŦā§āĻļāĻŋ āĻšāĻ¯āĻŧā§ āĻ¯āĻžāĻ¯āĻŧ:
$ strace -f -othread-write.log ./thread-write
$ wc -l thread-write.log
60 thread-write.log
āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻŦā§āĻ¯āĻŦāĻ¸ā§āĻĨāĻžāĻĒāĻ¨āĻž āĻāĻŦāĻ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ā§āĻ° āĻŽāĻ§ā§āĻ¯ā§ āĻ¨āĻŋāĻā§āĻā§ āĻ¸ā§āĻŽāĻžāĻŦāĻĻā§āĻ§ āĻ°āĻžāĻāĻž āĻŦā§āĻ§āĻāĻŽā§āĻ¯ write
:
$ strace -f -e trace="%process,write" -othread-write.log ./thread-write
$ cat thread-write.log
18211 execve("./thread-write", ["./thread-write"], 0x7ffc6b8d58f0 /* 64 vars */) = 0
18211 arch_prctl(ARCH_SET_FS, 0x7f38ea3b7740) = 0
18211 write(1, "Initial thread: launching a thre"..., 35) = 35
18211 clone(child_stack=0x7f38e9ba2fb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f38e9ba39d0, tls=0x7f38e9ba3700, child_tidptr=0x7f38e9ba39d0) = 18212
18211 write(1, "Initial thread: joining a thread"..., 33) = 33
18212 write(1, "Secondary thread: workingn", 26) = 26
18212 write(1, "Secondary thread: donen", 23) = 23
18212 exit(0) = ?
18212 +++ exited with 0 +++
18211 write(1, "Initial thread: done", 20) = 20
18211 exit_group(0) = ?
18211 +++ exited with 0 +++
āĻāĻĒāĻžāĻ¯āĻŧ āĻĻā§āĻŦāĻžāĻ°āĻž, āĻĒā§āĻ°āĻļā§āĻ¨. āĻāĻāĻāĻŋ āĻ¨āĻ¤ā§āĻ¨ āĻĨā§āĻ°ā§āĻĄ āĻ¤ā§āĻ°āĻŋ āĻāĻ°āĻ¤ā§ āĻā§āĻ¨ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻž āĻšāĻ¯āĻŧ? āĻāĻŋāĻāĻžāĻŦā§ āĻĨā§āĻ°ā§āĻĄā§āĻ° āĻāĻ¨ā§āĻ¯ āĻāĻ āĻāĻ˛ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻāĻ˛ āĻĨā§āĻā§ āĻāĻ˛āĻžāĻĻāĻž?
āĻŽāĻžāĻ¸ā§āĻāĻžāĻ° āĻā§āĻ˛āĻžāĻ¸: āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ā§āĻ° āĻ¸āĻŽāĻ¯āĻŧ āĻĒā§āĻ°āĻ¸ā§āĻ¸ āĻ¸ā§āĻā§āĻ¯āĻžāĻ
āĻ¸āĻŽā§āĻĒā§āĻ°āĻ¤āĻŋ āĻšāĻžāĻāĻŋāĻ° āĻāĻāĻāĻ¨ strace
āĻā§āĻˇāĻŽāĻ¤āĻž - āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ā§āĻ° āĻ¸āĻŽāĻ¯āĻŧ āĻĢāĻžāĻāĻļāĻ¨ āĻāĻ˛ā§āĻ° āĻ¸ā§āĻā§āĻ¯āĻžāĻ āĻĒā§āĻ°āĻĻāĻ°ā§āĻļāĻ¨ āĻāĻ°āĻžāĨ¤ āĻ¸āĻ°āĻ˛
void do_write(void)
{
char str[] = "write me to stdoutn";
if (sizeof(str) != write(STDOUT_FILENO, str, sizeof(str))){
perror("write");
exit(EXIT_FAILURE);
}
}
int main(int argc, char *argv[])
{
do_write();
return EXIT_SUCCESS;
}
āĻ¸ā§āĻŦāĻžāĻāĻžāĻŦāĻŋāĻāĻāĻžāĻŦā§āĻ, āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽā§āĻ° āĻāĻāĻāĻĒā§āĻ āĻĒāĻ¤āĻžāĻāĻž āĻāĻžāĻĄāĻŧāĻžāĻ āĻā§āĻŦ āĻŦāĻĄāĻŧ āĻšāĻ¯āĻŧā§ āĻāĻ ā§ -k
(āĻāĻ˛ āĻ¸ā§āĻā§āĻ¯āĻžāĻ āĻĄāĻŋāĻ¸āĻĒā§āĻ˛ā§), āĻāĻāĻŋ āĻ¨āĻžāĻŽā§āĻ° āĻĻā§āĻŦāĻžāĻ°āĻž āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛āĻā§āĻ˛āĻŋāĻā§ āĻĢāĻŋāĻ˛ā§āĻāĻžāĻ° āĻāĻ°āĻž āĻŦā§āĻ§āĻāĻŽā§āĻ¯ āĻšāĻ¯āĻŧ:
$ gcc examples/write-simple.c -o write-simple
$ strace -k -e trace=write -o write-simple.log ./write-simple
write me to stdout
$ cat write-simple.log
write(1, "write me to stdoutn", 20) = 20
> /lib/x86_64-linux-gnu/libc-2.27.so(__write+0x14) [0x110154]
> /home/vkazanov/projects-my/strace-post/write-simple(do_write+0x50) [0x78a]
> /home/vkazanov/projects-my/strace-post/write-simple(main+0x14) [0x7d1]
> /lib/x86_64-linux-gnu/libc-2.27.so(__libc_start_main+0xe7) [0x21b97]
> /home/vkazanov/projects-my/strace-post/write-simple(_start+0x2a) [0x65a]
+++ exited with 0 +++
āĻŽāĻžāĻ¸ā§āĻāĻžāĻ° āĻā§āĻ˛āĻžāĻ¸: āĻ¤ā§āĻ°ā§āĻāĻŋ āĻāĻ¨āĻā§āĻāĻļāĻ¨
āĻāĻŦāĻ āĻāĻ°āĻ āĻāĻāĻāĻŋ āĻ¨āĻ¤ā§āĻ¨ āĻāĻŦāĻ āĻā§āĻŦ āĻĻāĻ°āĻāĻžāĻ°ā§ āĻŦā§āĻļāĻŋāĻˇā§āĻā§āĻ¯: āĻ¤ā§āĻ°ā§āĻāĻŋ āĻāĻ¨āĻā§āĻāĻļāĻ¨āĨ¤ āĻāĻāĻžāĻ¨ā§
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void do_write(const char *str, ssize_t len)
{
if (len != write(STDOUT_FILENO, str, (size_t)len)){
perror("write");
exit(EXIT_FAILURE);
}
}
int main(int argc, char *argv[])
{
(void) argc; (void) argv;
char str1[] = "write me 1n";
do_write(str1, sizeof(str1));
char str2[] = "write me 2n";
do_write(str2, sizeof(str2));
return EXIT_SUCCESS;
}
āĻāĻ¸ā§āĻ¨ āĻāĻāĻ¯āĻŧ āĻāĻ˛ āĻ˛āĻŋāĻā§āĻ¨ āĻā§āĻ°ā§āĻ¸ āĻāĻ°ā§āĻ¨:
$ gcc examples/write-twice.c -o write-twice
$ ./write-twice
write me 1
write me 2
$ strace -e trace=write -owrite-twice.log ./write-twice
write me 1
write me 2
$ cat write-twice.log
write(1, "write me 1n", 12) = 12
write(1, "write me 2n", 12) = 12
+++ exited with 0 +++
āĻāĻāĻ¨ āĻāĻŽāĻ°āĻž āĻāĻā§āĻ¸āĻĒā§āĻ°ā§āĻļāĻ¨ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻŋ inject
āĻāĻāĻāĻŋ āĻ¤ā§āĻ°ā§āĻāĻŋ āĻ¸āĻ¨ā§āĻ¨āĻŋāĻŦā§āĻļ āĻāĻ°āĻžāĻ¨ EBADF
āĻ¸āĻŦ āĻ˛āĻŋāĻāĻ¤ā§ āĻāĻ˛:
$ strace -e trace=write -e inject=write:error=EBADF -owrite-twice.log ./write-twice
$ cat write-twice.log
write(1, "write me 1n", 12) = -1 EBADF (Bad file descriptor) (INJECTED)
write(3, "write: Bad file descriptorn", 27) = -1 EBADF (Bad file descriptor) (INJECTED)
+++ exited with 1 +++
āĻāĻāĻž āĻāĻāĻ°ā§āĻˇāĻŖā§āĻ¯āĻŧ āĻāĻŋ āĻ¤ā§āĻ°ā§āĻāĻŋ āĻĢā§āĻ°āĻ¤ āĻšāĻ¯āĻŧ āĻ¸āĻŦ āĻā§āĻ¯āĻžāĻ˛ā§āĻā§āĻ write
, āĻāĻ¯āĻŧā§āĻ° āĻĒāĻŋāĻāĻ¨ā§ āĻ˛ā§āĻāĻžāĻ¨ā§ āĻāĻ˛ āĻ¸āĻšāĨ¤ āĻāĻāĻŋ āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻĒā§āĻ°āĻĨāĻŽ āĻāĻ˛āĻā§āĻ˛āĻŋāĻ° āĻāĻ¨ā§āĻ¯ āĻāĻāĻāĻŋ āĻ¤ā§āĻ°ā§āĻāĻŋ āĻĢā§āĻ°āĻ¤ āĻĻā§āĻāĻ¯āĻŧāĻž āĻŦā§āĻ§āĻāĻŽā§āĻ¯ āĻšāĻ¯āĻŧ:
$ strace -e trace=write -e inject=write:error=EBADF:when=1 -owrite-twice.log ./write-twice
write: Bad file descriptor
$ cat write-twice.log
write(1, "write me 1n", 12) = -1 EBADF (Bad file descriptor) (INJECTED)
write(3, "write: Bad file descriptorn", 27) = 27
+++ exited with 1 +++
āĻ āĻĨāĻŦāĻž āĻĻā§āĻŦāĻŋāĻ¤ā§āĻ¯āĻŧāĻāĻŋ:
$ strace -e trace=write -e inject=write:error=EBADF:when=2 -owrite-twice.log ./write-twice
write me 1
write: Bad file descriptor
$ cat write-twice.log
write(1, "write me 1n", 12) = 12
write(1, "write me 2n", 12) = -1 EBADF (Bad file descriptor) (INJECTED)
write(3, "write: Bad file descriptorn", 27) = 27
+++ exited with 1 +++
āĻ¤ā§āĻ°ā§āĻāĻŋāĻ° āĻ§āĻ°āĻ¨ āĻ¨āĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āĻ āĻāĻ°āĻžāĻ° āĻĒā§āĻ°āĻ¯āĻŧā§āĻāĻ¨ āĻ¨ā§āĻ:
$ strace -e trace=write -e fault=write:when=1 -owrite-twice.log ./write-twice
$ cat write-twice.log
write(1, "write me 1n", 12) = -1 ENOSYS (Function not implemented) (INJECTED)
write(3, "write: Function not implementedn", 32) = 32
+++ exited with 1 +++
āĻ āĻ¨ā§āĻ¯āĻžāĻ¨ā§āĻ¯ āĻĒāĻ¤āĻžāĻāĻžāĻ° āĻ¸āĻžāĻĨā§ āĻāĻāĻ¤ā§āĻ°ā§, āĻāĻĒāĻ¨āĻŋ āĻāĻāĻāĻŋ āĻ¨āĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āĻ āĻĢāĻžāĻāĻ˛ā§āĻ° āĻ ā§āĻ¯āĻžāĻā§āĻ¸ā§āĻ¸ "āĻŦā§āĻ°ā§āĻ" āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨āĨ¤ āĻāĻĻāĻžāĻšāĻ°āĻŖ:
$ strace -y -P/tmp/test_file.log -e inject=file:error=ENOENT -o write-file.log ./write-file /tmp/test_file.log
open: No such file or directory
$ cat write-file.log
openat(AT_FDCWD, "/tmp/test_file.log", O_WRONLY|O_APPEND) = -1 ENOENT (No such file or directory) (INJECTED)
+++ exited with 1 +++
āĻ¤ā§āĻ°ā§āĻāĻŋ āĻāĻ¨āĻā§āĻāĻļāĻ¨ āĻāĻžāĻĄāĻŧāĻžāĻ,
āĻāĻ¤ā§āĻ¤āĻ°āĻāĻžāĻˇ
āĻāĻāĻāĻŋāĻ˛āĻŋāĻāĻŋ strace
- āĻāĻāĻāĻŋ āĻ¸āĻšāĻ āĻāĻŦāĻ āĻ¨āĻŋāĻ°ā§āĻāĻ°āĻ¯ā§āĻā§āĻ¯ āĻā§āĻ˛āĨ¤ āĻāĻŋāĻ¨ā§āĻ¤ā§ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻāĻ˛ āĻāĻžāĻĄāĻŧāĻžāĻ, āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽ āĻĒāĻ°āĻŋāĻāĻžāĻ˛āĻ¨āĻžāĻ° āĻ
āĻ¨ā§āĻ¯āĻžāĻ¨ā§āĻ¯ āĻĻāĻŋāĻ āĻāĻŦāĻ āĻ
āĻĒāĻžāĻ°ā§āĻāĻŋāĻ āĻ¸āĻŋāĻ¸ā§āĻā§āĻŽ āĻĄāĻŋāĻŦāĻžāĻ āĻāĻ°āĻž āĻ¯ā§āĻ¤ā§ āĻĒāĻžāĻ°ā§āĨ¤ āĻāĻĻāĻžāĻšāĻ°āĻŖāĻ¸ā§āĻŦāĻ°ā§āĻĒ, āĻāĻāĻŋ āĻāĻ¤āĻŋāĻļā§āĻ˛āĻāĻžāĻŦā§ āĻ˛āĻŋāĻā§āĻāĻ¯ā§āĻā§āĻ¤ āĻ˛āĻžāĻāĻŦā§āĻ°ā§āĻ°āĻŋāĻ¤ā§ āĻāĻ˛ āĻā§āĻ°ā§āĻ¯āĻžāĻ āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§āĨ¤ strace
- āĻāĻŽāĻžāĻ° āĻ¨āĻŋāĻā§āĻ° āĻāĻŦāĻ āĻ
āĻ¨ā§āĻ¯āĻžāĻ¨ā§āĻ¯ āĻ˛ā§āĻā§āĻĻā§āĻ° āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽāĻā§āĻ˛āĻŋāĻ° āĻ¸āĻžāĻĨā§ āĻ¸āĻŽāĻ¸ā§āĻ¯āĻžāĻ° āĻā§āĻˇā§āĻ¤ā§āĻ°ā§ āĻĒā§āĻ°āĻ¤āĻŋāĻ°āĻā§āĻˇāĻžāĻ° āĻĒā§āĻ°āĻĨāĻŽ āĻ˛āĻžāĻāĻ¨, āĻāĻŦāĻ āĻāĻŽāĻŋ āĻāĻāĻŋ āĻ¸āĻĒā§āĻ¤āĻžāĻšā§ āĻ
āĻ¨ā§āĻ¤āĻ¤ āĻāĻ¯āĻŧā§āĻāĻŦāĻžāĻ° āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻŋāĨ¤
āĻ¸āĻāĻā§āĻˇā§āĻĒā§, āĻāĻĒāĻ¨āĻŋ āĻ¯āĻĻāĻŋ āĻāĻāĻ¨āĻŋāĻā§āĻ¸ āĻĒāĻāĻ¨ā§āĻĻ āĻāĻ°ā§āĻ¨ āĻ¤āĻŦā§ āĻĒāĻĄāĻŧā§āĻ¨ man 1 strace
āĻāĻŦāĻ āĻāĻĒāĻ¨āĻžāĻ° āĻĒā§āĻ°ā§āĻā§āĻ°āĻžāĻŽ āĻ āĻāĻāĻāĻŋ āĻ¨āĻŋāĻ°ā§āĻĻā§āĻŦāĻŋāĻ§āĻžāĻ¯āĻŧ!
āĻāĻ¤ā§āĻ¸: www.habr.com