αžŠαžΆαž“αž“αŸ…αž€αŸ’αž“αž»αž„αž›αžΈαž“αž»αž…αŸ– αž”αŸ’αžšαžœαžαŸ’αžαž· αž€αžΆαžšαžšαž…αž“αžΆ αž“αž·αž„αž€αžΆαžšαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹

αžŠαžΆαž“αž“αŸ…αž€αŸ’αž“αž»αž„αž›αžΈαž“αž»αž…αŸ– αž”αŸ’αžšαžœαžαŸ’αžαž· αž€αžΆαžšαžšαž…αž“αžΆ αž“αž·αž„αž€αžΆαžšαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹

αž“αŸ…αž€αŸ’αž“αž»αž„αž”αŸ’αžšαž–αŸαž“αŸ’αž’αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžΆαžšαžŠαžΌαž…αž™αžΌαž“αžΈαž€ αž€αžΆαžšαž‘αŸ†αž“αžΆαž€αŸ‹αž‘αŸ†αž“αž„αžšαž”αžŸαŸ‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž‡αžΆαž˜αž½αž™αž–αž·αž—αž–αžαžΆαž„αž€αŸ’αžšαŸ… αž“αž·αž„αž”αŸ’αžšαž–αŸαž“αŸ’αž’αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžΆαžšαž€αžΎαžαž‘αžΎαž„αžαžΆαž˜αžšαž™αŸˆαžŸαŸ†αžŽαž»αŸ†αž˜αž»αžαž„αžΆαžšαžαžΌαž…αž˜αž½αž™ - αž€αžΆαžšαž αŸ…αž”αŸ’αžšαž–αŸαž“αŸ’αž’αŸ” αž“αŸαŸ‡αž˜αžΆαž“αž“αŸαž™αžαžΆαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž‚αŸ„αž›αž”αŸ†αžŽαž„αž”αŸ†αž”αžΆαžαŸ‹αž€αŸ†αž αž»αžŸ αžœαžΆαž’αžΆαž…αž˜αžΆαž“αž”αŸ’αžšαž™αŸ„αž‡αž“αŸαž€αŸ’αž“αž»αž„αž€αžΆαžšαžˆαŸ’αž›αž”αž™αž€αž€αžΆαžšαžŽαŸαž›αžΎαž€αžΆαžšαž αŸ…αž”αŸ’αžšαž–αŸαž“αŸ’αž’αžŠαŸ‚αž›αž€αŸ†αž–αž»αž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŠαŸ„αž™αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαŸ”

αž§αž”αž€αžšαžŽαŸαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž‡αž½αž™αž’αŸ’αž“αž€αžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™ "αž‡αžΈαžœαž·αžαž‡αž·αžαžŸαŸ’αž“αž·αž‘αŸ’αž’" αž“αŸƒαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž“αŸ…αž›αžΎαž›αžΈαž“αž»αž… straceαžŠαŸ‚αž›αž‡αžΆαž”αŸ’αžšαž’αžΆαž“αž”αž‘αž“αŸƒαž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡αŸ” αž§αž‘αžΆαž αžšαžŽαŸαž“αŸƒαž€αžΆαžšαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž§αž”αž€αžšαžŽαŸαž…αžΆαžšαž€αž˜αŸ’αž˜αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αž˜αžŠαŸ„αž™αž”αŸ’αžšαžœαžαŸ’αžαž·αžŸαž„αŸ’αžαŸαž” strace αž“αž·αž„αž€αžΆαžšαž–αž·αž–αžŽαŸŒαž“αžΆαž’αŸ†αž–αžΈαž€αžΆαžšαžšαž…αž“αžΆαž“αŸƒαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž”αŸ‚αž”αž“αŸαŸ‡αŸ”

αž˜αžΆαžαž·αž€αžΆ

αž”αŸ’αžšαž—αž–αžŠαžΎαž˜αž“αŸƒαž”αŸ’αžšαž—αŸαž‘αžŸαžαŸ’αžœ

αž…αŸ†αžŽαž»αž…αž”αŸ’αžšαž‘αžΆαž€αŸ‹αžŸαŸ†αžαžΆαž“αŸ‹αžšαžœαžΆαž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ αž“αž·αž„αžαžΊαžŽαŸ‚αž› OS αž“αŸ…αž€αŸ’αž“αž»αž„ Unix αž‚αžΊαž€αžΆαžšαž αŸ…αžαžΆαž˜αž”αŸ’αžšαž–αŸαž“αŸ’αž’αŸ” αž€αžΆαžšαž αŸ…αžαžΆαž˜αž”αŸ’αžšαž–αŸαž“αŸ’αž’, αžŸαŸ†αž‘αŸαž„αžšαŸ„αž‘αŸ) αž’αž“αŸ’αžαžšαž€αž˜αŸ’αž˜αž“αŸƒαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž‡αžΆαž˜αž½αž™αž–αž·αž—αž–αžαžΆαž„αž€αŸ’αžšαŸ…αž€αžΎαžαž‘αžΎαž„αžαžΆαž˜αžšαž™αŸˆαž–αž½αž€αžœαžΆαŸ”

αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž“αŸ…αž€αŸ’αž“αž»αž„αž€αŸ†αžŽαŸ‚αžŸαžΆαž’αžΆαžšαžŽαŸˆαžŠαŸ†αž”αžΌαž„αž“αŸƒαž™αžΌαž“αžΈαž€ (αž€αŸ†αžŽαŸ‚ 6 Unix, 1975) αž˜αž·αž“αž˜αžΆαž“αž˜αž’αŸ’αž™αŸ„αž”αžΆαž™αž„αžΆαž™αžŸαŸ’αžšαž½αž›αžŠαžΎαž˜αŸ’αž”αžΈαžαžΆαž˜αžŠαžΆαž“αž₯αžšαž·αž™αžΆαž”αžαž“αŸƒαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž“αŸ„αŸ‡αž‘αŸαŸ” αžŠαžΎαž˜αŸ’αž”αžΈαžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž”αž‰αŸ’αž αžΆαž“αŸαŸ‡ Bell Labs αž“αžΉαž„αž’αŸ’αžœαžΎαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž—αžΆαž–αž‘αŸ…αž€αŸ†αžŽαŸ‚αž”αž“αŸ’αž‘αžΆαž”αŸ‹ (αž€αŸ†αžŽαŸ‚ 7 Unix, ៑៩៧៩) αž”αžΆαž“αžŸαŸ’αž“αžΎαž€αžΆαžšαž αŸ…αž”αŸ’αžšαž–αŸαž“αŸ’αž’αžαŸ’αž˜αžΈ - ptrace.

ptrace αžαŸ’αžšαžΌαžœβ€‹αž”αžΆαž“β€‹αž”αž„αŸ’αž€αžΎαžβ€‹αž‘αžΎαž„β€‹αž‡αžΆβ€‹αž…αž˜αŸ’αž”αž„β€‹αžŸαž˜αŸ’αžšαžΆαž”αŸ‹β€‹αž€αžΆαžšβ€‹αž”αŸ†αž”αžΆαžαŸ‹β€‹αž€αŸ†αž αž»αžŸβ€‹αž’αž“αŸ’αžαžšαž€αž˜αŸ’αž˜ αž”αŸ‰αž»αž“αŸ’αžαŸ‚β€‹αž“αŸ…β€‹αž…αž»αž„β€‹αž‘αžŸαžœαžαŸ’αžŸαžšαŸβ€‹αž‘αžΈ 80 (αž€αŸ’αž“αž»αž„β€‹αžŸαž˜αŸαž™β€‹αž–αžΆαžŽαž·αž‡αŸ’αž‡αž€αž˜αŸ’αž˜ αž”αŸ’αžšαž–αŸαž“αŸ’αž’ V αž…αŸαž‰αž•αŸ’αžŸαžΆαž™ 4) αž“αŸ…αž›αžΎαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž“αŸαŸ‡ αž§αž”αž€αžšαžŽαŸαž”αŸ†αž”αžΆαžαŸ‹αž€αŸ†αž αž»αžŸαžŠαŸ‚αž›αž•αŸ’αžαŸ„αžαž€αžΆαžšαž™αž€αž…αž·αžαŸ’αžαž‘αž»αž€αžŠαžΆαž€αŸ‹αžαžΌαž…αž…αž„αŸ’αž’αŸ€αž-αž§αž”αž€αžšαžŽαŸαžαžΆαž˜αžŠαžΆαž“αž€αžΆαžšαž αŸ…αžαžΆαž˜αž”αŸ’αžšαž–αŸαž“αŸ’αž’-αž”αžΆαž“αž”αž„αŸ’αž αžΆαž‰αžαŸ’αž›αž½αž“ αž“αž·αž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž™αŸ‰αžΆαž„αž‘αžΌαž›αŸ†αž‘αžΌαž›αžΆαž™αŸ”

αžŠαŸ†αž”αžΌαž„ αž€αŸ†αžŽαŸ‚αžŠαžΌαž…αž‚αŸ’αž“αžΆαž“αŸƒ strace αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ„αŸ‡αž–αž»αž˜αŸ’αž–αžŠαŸ„αž™ Paul Cronenburg αž“αŸ…αž›αžΎαž”αž‰αŸ’αž‡αžΈαžŸαŸ†αž”αž»αžαŸ’αžšαžšαž½αž˜ comp.sources.sun αž€αŸ’αž“αž»αž„αž†αŸ’αž“αžΆαŸ† 1992 αž‡αžΆαž‡αž˜αŸ’αžšαžΎαžŸαž˜αž½αž™αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž§αž”αž€αžšαžŽαŸαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž”αž·αž‘αž‡αž·αžαŸ” trace αž–αžΈαž–αŸ’αžšαŸ‡αž’αžΆαž‘αž·αžαŸ’αž™αŸ” αž‘αžΆαŸ†αž„αž€αŸ’αž›αžΌαž“ αž“αž·αž„αžŠαžΎαž˜αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž˜αŸ’αžšαž»αž„αž‘αž»αž€αžŸαž˜αŸ’αžšαžΆαž”αŸ‹ SunOS αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž“αŸ…αž†αŸ’αž“αžΆαŸ† 1994 strace αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž‰αŸ’αž‡αžΌαž“αž‘αŸ… System V, Solaris αž“αž·αž„αž›αžΈαž“αž»αž…αžŠαŸ‚αž›αž€αŸ†αž–αž»αž„αž–αŸαž‰αž“αž·αž™αž˜αŸ”

αžŸαž–αŸ’αžœαžαŸ’αž„αŸƒαž“αŸαŸ‡ strace αž‚αžΆαŸ†αž‘αŸ’αžšαžαŸ‚αž›αžΈαž“αž»αž… αž“αž·αž„αž–αžΉαž„αž•αŸ’αž’αŸ‚αž€αž›αžΎαžŠαžΌαž…αž‚αŸ’αž“αžΆαŸ” ptrace, overgrown αž‡αžΆαž˜αž½αž™αž•αŸ’αž“αŸ‚αž€αž”αž“αŸ’αžαŸ‚αž˜αž‡αžΆαž…αŸ’αžšαžΎαž“αŸ”

αž’αŸ’αž“αž€αžαŸ‚αž‘αžΆαŸ†αž‘αŸ†αž“αžΎαž” (αž“αž·αž„αžŸαž€αž˜αŸ’αž˜αžαŸ’αž›αžΆαŸ†αž„) strace - αžŒαžΈαž˜αžΈαž‘αŸ’αžšαžΈ αž›αŸαžœαžΈαž“. αžŸαžΌαž˜αž’αžšαž‚αž»αžŽαžŠαž›αŸ‹αž‚αžΆαžαŸ‹ αž§αž”αž€αžšαžŽαŸαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž”αžΆαž“αž‘αž‘αž½αž›αž“αžΌαžœαž›αž€αŸ’αžαžŽαŸˆαž–αž·αžŸαŸαžŸαž€αž˜αŸ’αžšαž·αžαžαŸ’αž–αžŸαŸ‹αžŠαžΌαž…αž‡αžΆαž€αžΆαžšαž”αž‰αŸ’αž…αžΌαž›αž€αŸ†αž αž»αžŸαž‘αŸ…αž€αŸ’αž“αž»αž„αž”αŸ’αžšαž–αŸαž“αŸ’αž’αž αŸ…αž‘αžΌαžšαžŸαž–αŸ’αž‘ αž€αžΆαžšαž‚αžΆαŸ†αž‘αŸ’αžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžŸαŸ’αžαžΆαž”αžαŸ’αž™αž€αž˜αŸ’αž˜αžŠαŸαž’αŸ†αž‘αžΌαž›αžΆαž™ αž“αž·αž„αžŸαŸ†αžαžΆαž“αŸ‹αž”αŸ†αž•αž»αžαŸ” αž˜αŸ‰αžΆαžŸαŸ’αž€αžΌαž. αž”αŸ’αžšαž—αž–αž€αŸ’αžšαŸ…αž•αŸ’αž›αžΌαžœαž€αžΆαžšαž”αžΆαž“αž’αŸ‡αž’αžΆαž„αžαžΆαž‡αž˜αŸ’αžšαžΎαžŸαž“αŸαŸ‡αž”αžΆαž“αž’αŸ’αž›αžΆαž€αŸ‹αž›αžΎαžŸαžαŸ’αžœαž€αž€αŸαžšαžŠαŸ„αž™αžŸαžΆαžšαžαŸ‚αž–αžΆαž€αŸ’αž™αžŸαŸ†αžŠαžΈαžšαž”αžŸαŸ‹αžšαž»αžŸαŸ’αžŸαŸŠαžΈ "ostrich" αž“αž·αž„αž–αžΆαž€αŸ’αž™αž’αž„αŸ‹αž‚αŸ’αž›αŸαžŸ "strace" αŸ”

αžœαžΆαž€αŸαžŸαŸ†αžαžΆαž“αŸ‹αž•αž„αžŠαŸ‚αžšαžŠαŸ‚αž›αž€αžΆαžšαž αŸ…αžαžΆαž˜αž”αŸ’αžšαž–αŸαž“αŸ’αž’ ptrace αž“αž·αž„αž€αžΆαžšαžαžΆαž˜αžŠαžΆαž“αž˜αž·αž“αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž”αžΆαž“αžšαž½αž˜αž”αž‰αŸ’αž…αžΌαž›αž“αŸ…αž€αŸ’αž“αž»αž„ POSIX αž‘αŸ„αŸ‡αž”αžΈαž‡αžΆαž˜αžΆαž“αž”αŸ’αžšαžœαžαŸ’αžαž· αž“αž·αž„αž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαžŠαŸαž™αžΌαžšαž“αŸ…αž€αŸ’αž“αž»αž„ Linux, FreeBSD, OpenBSD αž“αž·αž„ Unix αž”αŸ’αžšαž–αŸƒαžŽαžΈαž€αŸαžŠαŸ„αž™αŸ”

αž§αž”αž€αžšαžŽαŸαžαžΆαž˜αžŠαžΆαž“αžŠαŸ„αž™αžŸαž„αŸ’αžαŸαž”αŸ– Piglet Trace

"αž’αŸ’αž“αž€αž˜αž·αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αž‚αŸαžšαŸ†αž–αžΉαž„αžαžΆαž“αžΉαž„αž™αž›αŸ‹αž–αžΈαžšαžΏαž„αž“αŸαŸ‡αž‘αŸ" (Dennis Ritchie, αž˜αžαž·αž™αŸ„αž”αž›αŸ‹αž“αŸ…αž€αŸ’αž“αž»αž„αž€αŸ†αžŽαŸ‚ 6 Unix αž”αŸ’αžšαž—αž–αž€αžΌαžŠ)

αžαžΆαŸ†αž„αž–αžΈαž€αž»αž˜αžΆαžšαž—αžΆαž–αž˜αž€ αžαŸ’αž‰αž»αŸ†αž˜αž·αž“αž’αžΆαž…αž‘αŸ’αžšαžΆαŸ†αž‘αŸ’αžšαž”αŸ’αžšαž’αž”αŸ‹αžαŸ’αž˜αŸ…αž”αžΆαž“αž‘αŸαŸ– αžαŸ’αž‰αž»αŸ†αž˜αž·αž“αž›αŸαž„αž‡αžΆαž˜αž½αž™αž”αŸ’αžšαžŠαžΆαž”αŸ‹αž€αŸ’αž˜αŸαž„αž›αŸαž„αž‘αŸ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž”αžΆαž“αž–αŸ’αž™αžΆαž™αžΆαž˜αž™αž›αŸ‹αž–αžΈαžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αžšαž”αžŸαŸ‹αžœαžΆ (αž˜αž“αž»αžŸαŸ’αžŸαž–αŸαž‰αžœαŸαž™αž”αŸ’αžšαžΎαž–αžΆαž€αŸ’αž™ "αž”αžΆαž€αŸ‹" αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž€αž»αŸ†αž‡αžΏαž’αžŽαŸ’αžαžΆαžαž’αžΆαž€αŸ’αžšαž€αŸ‹)αŸ” αž”αŸ’αžšαž αŸ‚αž›αž‡αžΆαž“αŸαŸ‡αž‡αžΆαž˜αžΌαž›αž αŸαžαž»αžŠαŸ‚αž›αžœαž”αŸ’αž”αž’αž˜αŸŒαž€αŸ’αžšαŸ…αž•αŸ’αž›αžΌαžœαž€αžΆαžšαžšαž”αžŸαŸ‹αž™αžΌαž“αžΈαž€αžŠαŸ†αž”αžΌαž„ αž“αž·αž„αž…αž›αž“αžΆαž”αŸ’αžšαž—αž–αž”αžΎαž€αž…αŸ†αž αž‘αŸ†αž“αžΎαž”αž‚αžΊαž“αŸ…αž‡αž·αžαžαŸ’αž‰αž»αŸ†αŸ”

αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž‚αŸ„αž›αž”αŸ†αžŽαž„αž“αŸƒαž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡ αžœαžΆαž˜αž·αž“αžŸαž˜αž αŸαžαž»αž•αž›αž‘αŸαž€αŸ’αž“αž»αž„αž€αžΆαžšαžšαž»αŸ‡αžšαžΎαž€αžΌαžŠαž”αŸ’αžšαž—αž–αž“αŸƒ strace αžŠαŸ‚αž›αž”αžΆαž“αž€αžΎαž“αž‘αžΎαž„αž‡αžΆαž„αž…αŸ’αžšαžΎαž“αž‘αžŸαžœαžαŸ’αžŸαžšαŸαž˜αž€αž αžΎαž™αŸ” αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž˜αž·αž“αž‚αž½αžšαž˜αžΆαž“αž’αžΆαžαŸŒαž€αŸ†αž”αžΆαŸ†αž„αž’αŸ’αžœαžΈαž‘αŸαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž’αŸ’αž“αž€αž’αžΆαž“ αžŠαžΌαž…αŸ’αž“αŸαŸ‡ αžŠαžΎαž˜αŸ’αž”αžΈαž”αž„αŸ’αž αžΆαž‰αž–αžΈαž‚αŸ„αž›αž€αžΆαžšαžŽαŸαž“αŸƒαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžΆαžšαž“αŸƒαž€αž˜αŸ’αž˜αžœαž·αž’αžΈ strace αž”αŸ‚αž”αž“αŸαŸ‡ αžαŸ’αž‰αž»αŸ†αž“αžΉαž„αž•αŸ’αžαž›αŸ‹αž›αŸαžαž€αžΌαžŠαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžαžΆαž˜αžŠαžΆαž“αžαŸ’αž“αžΆαžαžαžΌαž… - αžŠαžΆαž“αž€αžΌαž“αž‡αŸ’αžšαžΌαž€ (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 αž‘αž‘αž½αž›αžŸαŸ’αž‚αžΆαž›αŸ‹αž’αŸ†αž–αžΈαž€αžΆαžšαž αŸ…αž”αŸ’αžšαž–αŸαž“αŸ’αž’αž›αžΈαž“αž»αž…αžšαžΆαž”αŸ‹αžšαž™ (αžŸαžΌαž˜αž˜αžΎαž›αŸ” តុ) αž αžΎαž™αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžαŸ‚αž›αžΎαžŸαŸ’αžαžΆαž”αžαŸ’αž™αž€αž˜αŸ’αž˜ x86-64 αž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡αŸ” αž“αŸαŸ‡αž‚αžΊαž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαžΆαž“αŸ‹αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž‚αŸ„αž›αž”αŸ†αžŽαž„αž’αž”αŸ‹αžšαŸ†αŸ”

αžŸαžΌαž˜αž€αŸ’αžšαž‘αŸαž€αž˜αžΎαž›αž€αžΆαžšαž„αžΆαžšαžšαž”αžŸαŸ‹αž€αŸ’αž›αžΌαž“αžšαž”αžŸαŸ‹αž™αžΎαž„αŸ” αž“αŸ…αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαž“αŸƒαž›αžΈαž“αž»αž… αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž”αŸ†αž”αžΆαžαŸ‹αž€αŸ†αž αž»αžŸ αž“αž·αž„αž§αž”αž€αžšαžŽαŸαžαžΆαž˜αžŠαžΆαž“αž”αŸ’αžšαžΎ αžŠαžΌαž…αžŠαŸ‚αž›αž”αžΆαž“αžšαŸ€αž”αžšαžΆαž”αŸ‹αžαžΆαž„αž›αžΎ αž€αžΆαžšαž αŸ…αž”αŸ’αžšαž–αŸαž“αŸ’αž’ 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, &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);
}

αž“αŸ„αŸ‡αž αžΎαž™αž‡αžΆαžŠαžΆαž“αž‘αžΆαŸ†αž„αž˜αžΌαž›αŸ” αž₯αž‘αžΌαžœαž“αŸαŸ‡αž’αŸ’αž“αž€αžŠαžΉαž„αž–αžΈαž€αž“αŸ’αž›αŸ‚αž„αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž…αŸ’αžšαž€αž”αž“αŸ’αž‘αžΆαž”αŸ‹ αžŒαžΈαž’αžΈαžŠ αž“αŸ…αž›αžΎαž›αžΈαž“αž»αž…αŸ”

αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αŸ– αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžŠαŸ‚αž›αž€αŸ†αž–αž»αž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžš

αž‡αžΆαž€αžšαžŽαžΈαž”αŸ’αžšαžΎαž›αžΎαž€αžŠαŸ†αž”αžΌαž„ 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. αž“αŸαŸ‡αž‚αžΊαž‡αžΆαž€αžΆαžšαž›αŸ†αž”αžΆαž€αž€αŸ’αž“αž»αž„αž€αžΆαžšαž’αŸ’αžœαžΎαž€αžΆαžšαž‡αžΆαž˜αž½αž™αž€αžΆαžšαž αŸ…αž‘αžΌαžšαžŸαŸαž–αŸ’αž‘αž”αŸ’αžšαž–αŸαž“αŸ’αž’αŸ– αž…αŸ†αžŽαž»αž…αž”αŸ’αžšαž‘αžΆαž€αŸ‹αžŠαŸ‚αž›αž’αŸ’αž“αž€αžŸαžšαžŸαŸαžšαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž’αŸ’αžœαžΎαž€αžΆαžšαž‚αžΊαž˜αž·αž“αž‘αžΆαž€αŸ‹αž‘αž„αžŠαŸ„αž™αž•αŸ’αž‘αžΆαž›αŸ‹αž‘αŸ…αž“αžΉαž„αž€αžΆαžšαž αŸ…αžαžΆαž˜αž”αŸ’αžšαž–αŸαž“αŸ’αž’αž‘αŸαŸ” αž›αžΎαžŸαž–αžΈαž“αŸαŸ‡αž‘αŸ…αž‘αŸ€αž αžœαžΆαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž‡αžΆαž‘αŸ€αž„αž‘αžΆαžαŸ‹αž’αžΆαžŸαŸ’αžšαŸαž™αž›αžΎαž€αžΆαžšαž’αž“αž»αžœαžαŸ’αž αž“αž·αž„αžœαŸαž‘αž·αž€αžΆαŸ”

αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αŸ– αž…αžΌαž›αžšαž½αž˜αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž—αŸ’αž›αžΆαž˜αŸ—

αžŠαŸ†αž”αžΌαž„αž”αŸ’αžšαž–αŸαž“αŸ’αž’ ptrac αž αŸ…αžŠαŸ‚αž›αžœαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αžŸαžΆαž„αžŸαž„αŸ‹ straceαž’αžΆαž…αž”αŸ’αžšαžΎαž”αžΆαž“αžαŸ‚αž“αŸ…αž–αŸαž›αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž€αŸ’αž“αž»αž„αžšαž”αŸ€αž”αž–αž·αžŸαŸαžŸαž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡αŸ” αžŠαŸ‚αž“αž€αŸ†αžŽαžαŸ‹αž“αŸαŸ‡αž’αžΆαž…αžŸαŸ’αžαžΆαž”αŸ‹αž‘αŸ…αžŸαž˜αž αŸαžαž»αž•αž›αž“αŸ…αž€αŸ’αž“αž»αž„αžαŸ’αž„αŸƒαž“αŸƒαž€αŸ†αžŽαŸ‚ 6 Unix αŸ” αžŸαž–αŸ’αžœαžαŸ’αž„αŸƒαž“αŸαŸ‡ αžœαžΆαž›αŸ‚αž„αž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαžΆαž“αŸ‹αž‘αŸ€αžαž αžΎαž™αŸ– αž–αŸαž›αžαŸ’αž›αŸ‡αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαžŸαŸŠαžΎαž”αž’αž„αŸ’αž€αŸαžαž”αž‰αŸ’αž αžΆαž“αŸƒαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž€αžΆαžšαž„αžΆαžšαŸ” αž§αž‘αžΆαž αžšαžŽαŸαž’αž˜αŸ’αž˜αžαžΆαž‚αžΊαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž”αž·αž‘αž“αŸ…αž›αžΎαž…αŸ†αžŽαž»αž…αž‘αžΆαž‰ αž¬αž€αŸ†αž–αž»αž„αžŠαŸαž€αŸ” αžŠαžΌαž…αŸ’αž“αŸαŸ‡αž‘αŸ†αž“αžΎαž” 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. αžšαžΏαž„αž–αžΈαžšαž”αžΆαž“αž€αŸ’αž›αžΆαž™αž‘αŸ…αž‡αžΆαž…αŸ’αž”αžΆαžŸαŸ‹αŸ– αž€αžΆαžšαž αŸ…αž”αŸ’αžšαž–αŸαž“αŸ’αž’αž•αŸ’αž’αžΆαž€αž˜αž·αž“αž’αžΎαž–αžΎαž“αžΉαž„αžŸαž‰αŸ’αž‰αžΆαžŠαŸ„αž™αž‚αŸ’αž˜αžΆαž“αž§αž”αž€αžšαžŽαŸαžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™ αž αžΎαž™αž’αŸ’αžœαžΈαžŠαŸ‚αž›αž‚αž½αžšαž±αŸ’αž™αž…αžΆαž”αŸ‹αž’αžΆαžšαž˜αŸ’αž˜αžŽαŸαž‡αžΆαž„αž“αŸαŸ‡αž‘αŸ…αž‘αŸ€αžαž“αŸ„αŸ‡ strace monitors αž˜αž·αž“αžαŸ’αžšαžΉαž˜αžαŸ‚αž αŸ…αž”αŸ’αžšαž–αŸαž“αŸ’αž’αž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡αž‘αŸ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž€αŸαž˜αžΆαž“αžŸαž‰αŸ’αž‰αžΆαž…αžΌαž›αž•αž„αžŠαŸ‚αžšαŸ”

αž§αž‘αžΆαž αžšαžŽαŸαŸ– αž€αžΆαžšαžαžΆαž˜αžŠαžΆαž“αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αž»αž˜αžΆαžš

αž’αŸ’αžœαžΎαž€αžΆαžšαž‡αžΆαž˜αž½αž™αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžαžΆαž˜αžšαž™αŸˆαž€αžΆαžšαž αŸ…αž‘αžΌαžšαžŸαŸαž–αŸ’αž‘ fork - αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž“αŸƒαž™αžΌαž“αžΈαž€αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αŸ” αžŸαžΌαž˜αž˜αžΎαž›αž–αžΈαžšαž”αŸ€αž”αžŠαŸ‚αž› strace αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž‡αžΆαž˜αž½αž™αž˜αŸ‚αž€αž’αžΆαž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŠαŸ„αž™αž”αŸ’αžšαžΎαž§αž‘αžΆαž αžšαžŽαŸαž“αŸƒ "αž€αžΆαžšαž”αž„αŸ’αž€αžΆαžαŸ‹" αžŸαžΆαž˜αž‰αŸ’αž‰ αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ:

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 αž”αŸ„αŸ‡αž–αž»αž˜αŸ’αž–αžαŸ‚αž€αžΆαžšαž αŸ…αž‘αŸ…αž―αž€αžŸαžΆαžšαžŠαŸ‚αž›αž”αžΆαž“αž”αž‰αŸ’αž‡αžΆαž€αŸ‹:

$ 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αžŠαžΌαž…αž“αŸ…αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαž“αŸƒαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž’αž˜αŸ’αž˜αžαžΆ αž“αžΉαž„αž”αž“αŸ’αžαŸ‚αž˜ pid αž“αŸƒαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž‘αŸ…αžŠαžΎαž˜αž”αž“αŸ’αž‘αžΆαžαŸ‹αž“αžΈαž˜αž½αž™αŸ—αŸ”

αžαžΆαž˜αž’αž˜αŸ’αž˜αž‡αžΆαžαž· αž™αžΎαž„αž˜αž·αž“αž“αž·αž™αžΆαž™αž’αŸ†αž–αžΈαž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αž’αžαŸ’αžαžŸαž‰αŸ’αž‰αžΆαžŽαžαŸ’αžŸαŸ‚αžŸαŸ’αžšαž‘αžΆαž™αž€αŸ’αž“αž»αž„αž“αŸαž™αž“αŸƒαž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαžŸαŸ’αžαž„αŸ‹αžŠαžΆαžš POSIX Threads αž‘αŸ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž’αŸ†αž–αžΈαž›αŸαžαžŠαŸ‚αž›αž”αŸ’αžšαžΎαžŠαŸ„αž™αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž€αŸ†αžŽαžαŸ‹αž–αŸαž›αž—αžΆαžšαž€αž·αž…αŸ’αž…αž“αŸ…αž€αŸ’αž“αž»αž„αž›αžΈαž“αž»αž…αŸ” αžαžΆαž˜αž‘αžŸαŸ’αžŸαž“αŸˆαž…αž»αž„αž€αŸ’αžšαŸ„αž™αž“αŸαŸ‡ αž˜αž·αž“αž˜αžΆαž“αžŠαŸ†αžŽαžΎαžšαž€αžΆαžš αž¬αžαŸ’αžŸαŸ‚αžŸαŸ’αžšαž‘αžΆαž™αž‘αŸ - αž˜αžΆαž“αž—αžΆαžšαž€αž·αž…αŸ’αž…αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž…αŸ‚αž€αž…αžΆαž™αž€αŸ’αž“αž»αž„αž…αŸ†αžŽαŸ„αž˜αžŸαŸ’αž“αžΌαž›αžŠαŸ‚αž›αž˜αžΆαž“αžŸαŸ’αžšαžΆαž”αŸ‹αžšαž”αžŸαŸ‹αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αŸ”

αž“αŸ…αž–αŸαž›αž’αŸ’αžœαžΎαž€αžΆαžšαž“αŸ…αž€αŸ’αž“αž»αž„αžαŸ’αžŸαŸ‚αžŸαŸ’αžšαž‘αžΆαž™αž…αŸ’αžšαžΎαž“ αž€αžΆαžšαž αŸ…αžαžΆαž˜αž”αŸ’αžšαž–αŸαž“αŸ’αž’αž€αŸ’αž›αžΆαž™αž‡αžΆαž…αŸ’αžšαžΎαž“αž–αŸαž€αŸ–

$ 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 +++

αž€αŸ’αžšαŸ…αž–αžΈαž€αžΆαžšαž…αžΆαž€αŸ‹αž”αž‰αŸ’αž…αžΌαž›αž€αŸ†αž αž»αžŸ αž’αžΆαž…αž’αŸ’αžœαžΎαž”αžΆαž“ αžŽαŸ‚αž“αžΆαŸ†αž€αžΆαžšαž–αž“αŸ’αž™αžΆαž–αŸαž›αž–αŸαž›αž αŸ…αž‘αžΌαžšαžŸαž–αŸ’αž‘ αž¬αž‘αž‘αž½αž›αžŸαž‰αŸ’αž‰αžΆαŸ”

Afterword

αž§αž”αž€αžšαžŽαŸαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ strace - αž§αž”αž€αžšαžŽαŸαžŸαžΆαž˜αž‰αŸ’αž‰αž“αž·αž„αž’αžΆαž…αž‘αž»αž€αž…αž·αžαŸ’αžαž”αžΆαž“αŸ” αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž”αž“αŸ’αžαŸ‚αž˜αž–αžΈαž›αžΎαž€αžΆαžšαž αŸ…αžαžΆαž˜αž”αŸ’αžšαž–αŸαž“αŸ’αž’ αž‘αž·αžŠαŸ’αž‹αž—αžΆαž–αž•αŸ’αžŸαŸαž„αž‘αŸ€αžαž“αŸƒαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžΆαžšαž“αŸƒαž€αž˜αŸ’αž˜αžœαž·αž’αžΈ αž“αž·αž„αž”αŸ’αžšαž–αŸαž“αŸ’αž’αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžΆαžšαž’αžΆαž…αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ†αž”αžΆαžαŸ‹αž€αŸ†αž αž»αžŸαŸ” αž§αž‘αžΆαž αžšαžŽαŸ αžœαžΆαž’αžΆαž…αžαžΆαž˜αžŠαžΆαž“αž€αžΆαžšαž αŸ…αž‘αŸ…αž€αžΆαž“αŸ‹αž”αžŽαŸ’αžŽαžΆαž›αŸαž™αžŠαŸ‚αž›αž—αŸ’αž‡αžΆαž”αŸ‹αžŠαŸ„αž™αžαžΆαž˜αžœαž“αŸ’αžαŸ” αžŠαžΆαž“αž–αž½αž€αž‚αŸαž’αžΆαž…αž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž›αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžΆαžšαž“αŸƒαž”αŸ’αžšαž–αŸαž“αŸ’αž’αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžΆαžš SystemTap ΠΈ αž αŸ’αžœαžΈαžαž“αž·αž„αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αž’αŸ’αž“αž€αžŸαŸŠαžΎαž”αž’αž„αŸ’αž€αŸαžαž™αŸ‰αžΆαž„αžŸαŸŠαžΈαž‡αž˜αŸ’αžšαŸ…αž’αŸ†αž–αžΈαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αž˜αŸ’αž˜αžœαž·αž’αžΈ αž›αŸ’αž’. αž‘αŸ„αŸ‡αž™αŸ‰αžΆαž„αžŽαžΆαž€αŸαžŠαŸ„αž™αžœαžΆαž‚αžΊαž‡αžΆ strace - αžαŸ’αžŸαŸ‚αž€αžΆαžšαž–αžΆαžšαžŠαŸ†αž”αžΌαž„αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαž˜αžΆαž“αž”αž‰αŸ’αž αžΆαž‡αžΆαž˜αž½αž™αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž•αŸ’αž‘αžΆαž›αŸ‹αžαŸ’αž›αž½αž“ αž“αž·αž„αž’αŸ’αž“αž€αžŠαž‘αŸƒ αž αžΎαž™αžαŸ’αž‰αž»αŸ†αž”αŸ’αžšαžΎαžœαžΆαž™αŸ‰αžΆαž„αž αŸ„αž…αžŽαžΆαžŸαŸ‹αž–αžΈαžšαž”αžΈαžŠαž„αž€αŸ’αž“αž»αž„αž˜αž½αž™αžŸαž”αŸ’αžαžΆαž αŸαŸ”

αžŸαžšαž»αž”αž˜αž€ αž”αžΎαžŸαŸ’αžšαž›αžΆαž‰αŸ‹αž™αžΌαž“αžΈαž€ αžŸαžΌαž˜αž’αžΆαž“ man 1 strace αž αžΎαž™αžšαžΈαž€αžšαžΆαž™αž€αŸ’αž“αž»αž„αž€αžΆαžšαž˜αžΎαž›αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž”αžŸαŸ‹αž’αŸ’αž“αž€!

αž”αŸ’αžšαž—αž–: www.habr.com

αž”αž“αŸ’αžαŸ‚αž˜αž˜αžαž·αž™αŸ„αž”αž›αŸ‹