[PATCH v2 1/2] gdbserver: Set Linux ptrace options ASAP
Pedro Alves
palves@redhat.com
Wed Dec 2 14:01:00 GMT 2015
On 12/01/2015 08:17 PM, Josh Stone wrote:
> OK, I think I've got it, and it's a real regression from 7.10 even for
> other events like fork. I'm not using --wrapper, so I'm not sure of the
> interaction there, but even gdbserver's simple fork+exec can show the
> problem. Basically, on the very first stop we don't set flags yet, so
> the first resume from there continues without the right flags.
>
> The sequence I was running into with syscalls goes like this:
>
> - start_inferior calls create_inferior to fork, then calls mywait
> - the forked process calls ptrace(PTRACE_TRACEME), then execs
> - linux_low_filter_event sees a raw SIGTRAP for the child after exec
> - (we haven't set PTRACE_O_TRACEEXEC yet, so SIGTRAP is expected)
> - arch setup is needed, so it hits the early return (new since 7.10)
> ... thus child->must_set_ptrace_flags is not dealt with
> - start_inferior calls target_arch_setup
> - GDB sends QCatchSyscalls:1
> - linux_resume_one_lwp_throw calls ptrace(PTRACE_SYSCALL)
> - but we still haven't set any flags, especially PTRACE_O_TRACESYSGOOD
> - linux_low_filter_event sees a raw SIGTRAP for the first syscall entry
> - now we finally deal with child->must_set_ptrace_flags
> - linux_resume_one_lwp_throw calls ptrace(PTRACE_SYSCALL)
> - linux_low_filter_event sees SYSCALL_SIGTRAP for the return
> - entry/return logic is confused now, thinks this is an entry
> - (but if there's any other event, entry/return will get back in sync)
>
>
> But this problem isn't particular to my syscall patches. Consider this
> simple forking program and use 'catch fork':
>
> #include <unistd.h>
> int main() { fork(); return 0; }
>
> Compiled normally, with dynamically-linked libc et al, you get:
> - SIGTRAP after exec, ignores child->must_set_ptrace_flags.
> - SIGTRAP for a swbreak, I guess some gdb setup, then it sets the
> necessary flags, especially PTRACE_O_TRACEFORK.
> - SIGTRAP for PTRACE_EVENT_FORK, hooray!
>
> But compiled statically:
> - SIGTRAP after exec, ignores child->must_set_ptrace_flags.
> - CLD_EXITED, flags were never set!
> - if I add a breakpoint on main, flags will be set when that's reached,
> and then we do get the PTRACE_EVENT_FORK after all.
Ouch. Thanks, I'm clear now. It'd be super if one of these examples
got converted to a test case.
>
> So, we need some point to get the right flags set before the program
> starts running for real. If you don't like the way I moved the flags
> before that arch-setup early return, then when should we do it?
>
> - Perhaps before the ptrace call in linux_resume_one_lwp_throw? Then if
> any state changes while the thread is still stopped, triggering new
> must_set_ptrace_flags, we'll deal with it before resuming. But I don't
> know if this would interact well with your wrapper concerns.
>
Yeah, badly.
> - Perhaps at the end of linux_arch_setup? AIUI this will be after
> everything you're worried about wrappers.
Something like that, yes. gdb/linux-nat.c also does something like
that:
static void
linux_child_post_startup_inferior (struct target_ops *self, ptid_t ptid)
{
linux_init_ptrace (ptid_get_pid (ptid), 0);
}
I think we should rename gdbserver's target_ops:target_arch_setup method/hook
to target_post_create_inferior along the way, and then linux-low.c's
implementation can both call linux_arch_setup and set the ptrace options.
Only Linux implements that target_ops method currently, so it should
be trivial.
Thanks,
Pedro Alves
More information about the Gdb-patches
mailing list