ptrace如何在Linux中工作?

ptrace如何在Linux中工作?,第1张

概述ptrace如何在Linux中工作

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(&current->sighand->siglock); 1982 ptrace_do_notify(SIGTRAP,exit_code,CLD_TRAPPED); 1983 spin_unlock_irq(&current->sighand->siglock); 1984 }

ptrace_stop与3.13中的ptrace_stop文件在1839行。

总结

以上是内存溢出为你收集整理的ptrace如何在Linux中工作?全部内容,希望文章能够帮你解决ptrace如何在Linux中工作?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1289481.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-09
下一篇 2022-06-09

发表评论

登录后才能评论

评论列表(0条)

保存