This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [rfc] catch syscall


Just when I had given up on getting any replies...

Daniel Jacobowitz writes the following:
>
>On Sat, Jun 09, 2007 at 04:17:03PM -0400, Alan Curry wrote:
>> For a long time I've wanted to be able to mix strace-like syscall tracing
>> with the awesome power of gdb. Other people have mentioned the idea a few
>> times over the years, but nothing ever seems to get done. So I did something.
>
>Thank you!  I've always wanted this.  Every time I thought about it, I
>got hung up on all the argument decoding that strace knows how to do.

That is definitely the hard part.

>But just because we don't know how to decode arguments doesn't mean
>this isn't useful anyway.

A lot of syscalls can be printed nicely using existing gdb commands, like
this:

if $r0 == 4
  output "write("
  output $r3
  output ", "
  output *(char *)$r4@$r5
  output ", "
  output $r5
  output ")\n"
end

>
>For a patch of this size, we will need an FSF copyright assignment.
>Unless you or your employer have one in place already, you'll need to
>contact the FSF for this.  Let me know if you need one, and I'll send
>you the request form.

I haven't got one of those yet. And I've got no employer right now[1]

>
>>   1. PTRACE_O_TRACESYSGOOD is enabled to make syscall stops distinguishable
>>      from random SIGTRAPs
>>   2. When the inferior is resumed, if there is an enabled syscall catchpoint,
>>      PTRACE_SYSCALL is used instead of PTRACE_CONT.
>>   3. When the inferior stops, the special signal value 0x80|SIGTRAP is
>>      recognized and the syscall catchpoint claims responsibility for the
>>      stop.
>
>Sounds right to me.  If we can distinguish between entry and exit, it
>would be nice to do so; though as I recall from hacking on strace,
>this is tricky.

Actually it doesn't look too difficult in theory. As far as I can tell, a
syscall event is an exit if and only if the previous event was a syscall
entry and the program was continued with PTRACE_SYSCALL. (Interesting note
from my tests: if you're currently stopped at a syscall entry, stepi actually
steps further than cont. The PTRACE_SINGLESTEP completes the syscall and then
executes one userspace instruction, whereas cont maps to PTRACE_SYSCALL which
just finishes the syscall. This could be hacked around if it's a problem.)

We just need to keep track of a single bit of extra state for each inferior
thread, to know what type of syscall event is expected next. I'm just having
a hard time finding where per-inferior-thread information is supposed to be
stored.

>
>On a minor note, be careful about tabs please; our convention is to
>always use a tab in place of eight leading spaces, and I can tell from
>some parts of your diff that line up funny that you haven't.  Well,
>either that our your mail client ate them...

That's the ':set expandtab' that I usually use.

>
>I don't realy like the duplication in breakpoint.c.  I don't see a
>great way around it, either.  Maybe there should be a single
>target_insert_catchpoint method.

Well, I think I only added one of what there were already several of...

>
>> +#if 0
>> +	/* Ideally, print the syscall's __NR here, and maybe its name.
>> +           Getting the __NR and mapping it to a name are both arch-specific
>> +           so I'm saving it for later. It'll go something like this: */
>> +	if (b->syscall_name != NULL)
>> +	  {
>> +	    ui_out_field_string (uiout, "what", b->syscall_name);
>> +	  }
>> +#endif
>
>Yes, good choice to wait :-)  If we want to do this later, we can add
>gdbarch methods as needed.

It's just a matter of "which register do we peek at to get syscall number"
(one integer of per-arch information), and converting asm/unistd.h into a
static string table. But the hypothetical libstrace would do that and a lot
more.

>> +/* Nonzero if a syscall catchpoint is active. There must be a better place
>> +   for this, where it can be associated with a particular process if multiple
>> +   forks are being traced. Where should it be really? */
>> +
>> +extern int catching_syscalls;
>> +

>
>I guess this is as good as anywhere.  I don't see how to do it without
>the global while still reusing inf_ptrace_resume.

I was confused here because I created to_insert_syscall_catchpoint as a copy
of to_insert_{fork,vfork,exec}_catchpoint, and they all take a pid argument,
but don't use it. So I expected to find a struct full of tracking information
I could store a flag in, like this:
  get_task_struct(pid)->catching_syscalls = 1;
but couldn't find it. Then I realized the user interface of the "catch"
command doesn't really provide a way to request catching on a specific PID.
So why do those insert_*_catchpoint methods take an argument, if enabling a
catchpoint always applies to all the tasks being debugged?

>> +      stop_signal = TARGET_SIGNAL_TRAP;
>> +      pending_follow.kind = ecs->ws.kind;
>
>I don't think you need to mess with pending_follow.  It's an event;
>_LOADED may be a better model than _FORKED for the event handling
>side.

That was pure cut-and-paste. I haven't figured out what rules apply to the
use of pending_follow. Maybe it's the right place for that new
"next_syscall_event_will_be_exit" flag I was talking about.

>
>> +/* Determine which PTRACE_O_* flags are usable with the running kernel.
>>  
>> -   First, we try to enable fork tracing on ORIGINAL_PID.  If this fails,
>> +   First, we try to enable TRACESYSGOOD on ORIGINAL_PID.  If this fails, the
>> +   kernel is too old to support any of the flags.
>> +
>> +   Next, we try to enable fork tracing on ORIGINAL_PID.  If this fails,
>>     we know that the feature is not available.  This may change the tracing
>>     options for ORIGINAL_PID, but we'll be setting them shortly anyway.
>>  
>
>This won't actually work, I don't think.  Old kernels used to always
>allow TRACESYSGOOD or else silently ignore attempts to set it.  I
>might be wrong though - you have to go back quite a ways to find a
>kernel where this doesn't work.

I did go back and look at those old kernels. PTRACE_SETOPTIONS didn't exist
before TRACESYSGOOD, so it looks like you should get an EIO for invalid
ptrace command. The ignoring of unrecognized options only applies to the
kernels new enough to have PTRACE_SETOPTIONS (and therefore at least
TRACESYSGOOD). But I didn't actually try compiling and booting one of those
old kernels to confirm it.

>
>> +  catching_syscalls=0;
>
>Spaces around operators please.

If that's the worst thing I did, this has gone better than expected.

[1] Hint

-- 
Alan Curry
pacman@world.std.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]