On 11/18, Roland McGrath wrote: > > > Once again. The tracee sleeps in SYSCALL_ENTER. The tracer resumes > > the tracee via utrace_control(UTRACE_SINGLESTEP). > > Right. This is another strange corner. It doesn't necessarily make > especially good sense intrinsically for single-step to have this meaning > from this place. But it's the status quo in the ptrace interface.
Yes. > > So, I think we should do something like > > > > tracehook_report_syscall_exit(step) > > > > // do not use step at all > > if (task_utrace_flags() != 0) > > utrace_report_syscall_exit(); > > The trouble here is that the arch code looks like this: > > step = test_thread_flag(TIF_SINGLESTEP); > if (step || test_thread_flag(TIF_SYSCALL_TRACE)) > tracehook_report_syscall_exit(regs, step); > > i.e. unless syscall tracing is enabled, we won't even get there at all. You are right, I missed this. > > utrace_report_syscall_exit() > > > > if (UTRACE_EVENT(SYSCALL_EXIT)) > > REPORT(report_syscall_exit); > > > > if (utrace->resume == UTRACE_SINGLESTEP || > > utrace->resume == UTRACE_BLOCKSTEP) > > send_sigtrap(); > > > > What do you think? > > This can't work in the REPORT case. There start_report() will have reset > utrace->resume, Yes, yes, the pseudo-code above was just for illustration. > (This would go with un-reverting f19442c and reverting 3bd4be9.) > > --- a/kernel/utrace.c > +++ b/kernel/utrace.c > @@ -1584,20 +1584,25 @@ static inline u32 do_report_syscall_entr > UTRACE_EVENT(SYSCALL_ENTRY), report_syscall_entry, > resume_report | report->result | report->action, > engine, current, regs); > - finish_report(task, utrace, report, false); > + > + /* > + * Now we'll stop if asked. If we're proceeding with the syscall, > + * now we'll first enable single-step if asked. That leaves the > + * task in "stepping" state so tracehook_report_syscall_exit() and > + * the arch code that calls it will know. > + */ > + finish_resume_report(task, utrace, report); Hmm. not sure I understand how this can work. I mean, this won't enable stepping (in this particular case we are discussing). > - } else if (utrace->resume == UTRACE_REPORT) { > + } else if (utrace->resume <= UTRACE_REPORT) { perhaps, you meant ">= UTRACE_REPORT" ? In this case yes, UTRACE_SINGLESTEP will be noticed after resume, and ptrace or another engine can reassert it during the next reporting loop, and then finish_resume_report() will enable the stepping. But we can't trust ">=", another engine can do utrace_control(INTERRUPT) and change ->resume before the tracee resumes. OK, probably I missed the implemenation details, but I think I got the idea, and this should fix the step-after-syscall_enter problem. But. We have the same problem with utrace_finish_vfork(), no? Instead of fixing utrace_report_syscall_entry(), perhaps we should change utrace_stop() path to enable the stepping if needed, but this means we return to "synchronous" utrace_control(UTRACE_XXXSTEP). Oleg.