ptrace系统调用允许父进程检查附加的subprocess。 例如,在linux中, strace (用ptrace系统调用实现)可以检查subprocess调用的系统调用。
当附加的subprocess调用系统调用时,可以通知ptracing父进程。 但是,究竟发生了什么呢? 我想知道这个机制背后的技术细节。
先谢谢你。
windows 8 Metro本地主机查找
c ++检查光盘状态
如何在linux上编译.cpp文件?
C – 用ncurses获取中性背景
basic_filebuf :: underflow错误在/ proc / pID / stat中读取ifstream文件
C ++ / Cli错误,除非使用Pthread创build委托实例,否则不能使用函数的地址
在C#中使用windows窗体创build多个窗体?
未定义的引用仅使用MinGW GCC
在windowsterminal输出unicode字符
DLL加载通知
当附加的子进程调用系统调用时,可以通知ptracing父进程。 但是,究竟发生了什么呢?
父进程使用PTRACE_ATTACH调用ptrace ,他的孩子用PTRACE_TRACEME选项调用ptrace 。 这对将通过填充task_struct ( kernel / ptrace.c:sys_ptrace中的一些字段来连接两个进程,child将在struct task_struct ptrace字段中具有PT_PTRACED标志,并且ptracer进程的pID作为父进程并在ptrace_entry列表中 – __ptrace_link ; parent将记录孩子的pID列表)。
然后strace会用PTRACE_SYSCALL标志来调用ptrace来注册它自己作为syscall调试器,在子进程的struct thread_info设置thread_flag TIF_SYSCALL_TRACE (通过像set_tsk_thread_flag(child,TIF_SYSCALL_TRACE); )。 arch/x86/include/asm/thread_info.h :
67 /* 68 * thread information flags 69 * - these are process state flags that varIoUs assembly files 70 * may need to access ...*/ 75 #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ 99 #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
在每个系统调用入口或出口处,体系结构特定的系统调用入口代码将检查这个_TIF_SYSCALL_TRACE标志 (直接在syscall的汇编实现中,例如ENTRY(system_call) x86 arch/x86/kernel/entry_32.S : jnz syscall_trace_entry ENTRY(system_call) syscall_exit_work ),如果它被设置,ptracer将被通知信号(SIGTRAP),子将被临时停止。 这通常在syscall_trace_enter和syscall_trace_leave :
1457 long syscall_trace_enter(struct pt_regs *regs) 1483 if ((ret || test_thread_flag(TIF_SYSCALL_TRACE)) && 1484 tracehook_report_syscall_entry(regs)) 1485 ret = -1L; 1507 voID syscall_trace_leave(struct pt_regs *regs) 1531 if (step || test_thread_flag(TIF_SYSCALL_TRACE)) 1532 tracehook_report_syscall_exit(regs,step);
tracehook_report_syscall_*是这里的实际工作者,他们将调用ptrace_report_syscall 。 include/linux/tracehook.h :
80 /** 81 * tracehook_report_syscall_entry - task is about to attempt a system call 82 * @regs: user register state of current task 83 * 84 * This will be called if %TIF_SYSCALL_TRACE has been set,when the 85 * current task has just entered the kernel for a system call. 86 * Full user register state is available here. Changing the values 87 * in @regs can affect the system call number and arguments to be trIEd. 88 * It is safe to block here,preventing the system call from beginning. 89 * 90 * Returns zero normally,or nonzero if the calling arch code should abort 91 * the system call. That must prevent normal entry so no system call is 92 * made. If @task ever returns to user mode after this,its register state 93 * is unspecifIEd,but should be something harmless like an %ENOSYS error 94 * return. It should preserve enough information so that syscall_rollback() 95 * can work (see asm-generic/syscall.h). 96 * 97 * Called without locks,just after entering kernel mode. 98 */ 99 static inline __must_check int tracehook_report_syscall_entry( 100 struct pt_regs *regs) 101 { 102 return ptrace_report_syscall(regs); 103 } 104 105 /** 106 * tracehook_report_syscall_exit - task has just finished a system call 107 * @regs: user register state of current task 108 * @step: nonzero if simulating single-step or block-step 109 * 110 * This will be called if %TIF_SYSCALL_TRACE has been set,when the 111 * current task has just finished an attempted system call. Full 112 * user register state is available here. It is safe to block here,113 * preventing signals from being processed. 114 * 115 * If @step is nonzero,this report is also in lIEu of the normal 116 * trap that would follow the system call instruction because 117 * user_enable_block_step() or user_enable_single_step() was used. 118 * In this case,%TIF_SYSCALL_TRACE might not be set. 119 * 120 * Called without locks,just before checking for pending signals. 121 */ 122 static inline voID tracehook_report_syscall_exit(struct pt_regs *regs,int step) 123 { ... 130 131 ptrace_report_syscall(regs); 132 }
而ptrace_report_syscall通过ptrace_notify / ptrace_do_notify为调试器或strace 生成SIGTRAP :
55 /* 56 * ptrace report for syscall entry and exit looks IDentical. 57 */ 58 static inline int ptrace_report_syscall(struct pt_regs *regs) 59 { 60 int ptrace = current->ptrace; 61 62 if (!(ptrace & PT_PTRACED)) 63 return 0; 64 65 ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); 66 67 /* 68 * this isn't the same as continuing with a signal,but it will do 69 * for normal use. strace only continues with a signal if the 70 * stopPing signal is not SIGTRAP. -brl 71 */ 72 if (current->exit_code) { 73 send_sig(current->exit_code,current,1); 74 current->exit_code = 0; 75 } 76 77 return fatal_signal_pending(current); 78 }
ptrace_notify在kernel/signal.c ptrace_notify中实现,它将停止子进程并将sig_info传递给ptracer:
1961 static voID ptrace_do_notify(int signr,int exit_code,int why) 1962 { 1963 siginfo_t info; 1964 1965 memset(&info,sizeof info); 1966 info.si_signo = signr; 1967 info.si_code = exit_code; 1968 info.si_pID = task_pID_vnr(current); 1969 info.si_uID = from_kuID_munged(current_user_ns(),current_uID()); 1970 1971 /* Let the deBUGger run. */ 1972 ptrace_stop(exit_code,why,1,&info); 1973 } 1974 1975 voID ptrace_notify(int exit_code) 1976 { 1977 BUG_ON((exit_code & (0x7f | ~0xffff)) != SIGTRAP); 1978 if (unlikely(current->task_works)) 1979 task_work_run(); 1980 1981 spin_lock_irq(¤t->sighand->siglock); 1982 ptrace_do_notify(SIGTRAP,exit_code,CLD_TRAPPED); 1983 spin_unlock_irq(¤t->sighand->siglock); 1984 }
ptrace_stop与3.13中的ptrace_stop文件在1839行。
总结以上是内存溢出为你收集整理的ptrace如何在Linux中工作?全部内容,希望文章能够帮你解决ptrace如何在Linux中工作?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)