From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 32276 invoked by alias); 1 Oct 2008 23:53:22 -0000 Received: (qmail 32256 invoked by uid 22791); 1 Oct 2008 23:53:14 -0000 X-Spam-Check-By: sourceware.org Received: from smtp-outbound-1.vmware.com (HELO smtp-outbound-1.vmware.com) (65.113.40.141) by sourceware.org (qpsmtpd/0.31) with ESMTP; Wed, 01 Oct 2008 23:52:14 +0000 Received: from mailhost4.vmware.com (mailhost4.vmware.com [10.16.67.124]) by smtp-outbound-1.vmware.com (Postfix) with ESMTP id C75AC67A5; Wed, 1 Oct 2008 16:52:11 -0700 (PDT) Received: from [10.20.92.59] (promb-2s-dhcp59.eng.vmware.com [10.20.92.59]) by mailhost4.vmware.com (Postfix) with ESMTP id 7E948C9A73; Wed, 1 Oct 2008 16:52:11 -0700 (PDT) Message-ID: <48E40CF3.5090702@vmware.com> Date: Wed, 01 Oct 2008 23:53:00 -0000 From: Michael Snyder User-Agent: Thunderbird 1.5.0.12 (X11/20080411) MIME-Version: 1.0 To: =?ISO-8859-1?Q?S=E9rgio_Durigan_J=FAnior?= CC: "gdb-patches@sourceware.org" Subject: Re: [PATCH 0/4] 'catch syscall' feature References: <1222798405.30389.22.camel@miki> <48E3FBE1.9030800@vmware.com> <1222902189.19318.8.camel@miki> In-Reply-To: <1222902189.19318.8.camel@miki> Content-Type: multipart/mixed; boundary="------------040706010100030701000506" X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-10/txt/msg00040.txt.bz2 This is a multi-part message in MIME format. --------------040706010100030701000506 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 8bit Content-length: 4464 Hi Sergio, AFAIK, we're still using the CVS repository as the official source repo. I don't use git. We also ask that patches be relative to the current top-of-tree. However, I've done my best to massage your patch into the current cvs tree. I'm attaching a CVS diff based on my best effort. Please let me know if you can spot any mistakes. I was able to build this, but it failed your test case (thanks very much for including a test case, by the way). I'm attaching my failing gdb.log. I want to thank you for the contribution while strongly encouraging you to resubmit it relative to CVS HEAD. Michael Sérgio Durigan Júnior wrote: > Hi Michael, > > IMHO, the patch won't apply on CVS HEAD indeed. Also, I've used git to > generate it, so it might be easy for you to get the specific revision to > apply my patch. > > The revision is: 337099393e64741ed0fbbb8c60ca3f6adb5d5974 > > You can easily checkout a copy of it by doing: > > #> git clone git://sourceware.org/git/gdb.git > #> git reset --hard 337099393e64741ed0fbbb8c60ca3f6adb5d5974 > > Then the patch should apply without errors. > > Well, to make things a little easier, that's the last ChangeLog entry > before mine: > > 2008-09-27 Tom Tromey > > * NEWS: Update. > * macrocmd.c (extract_identifier): Add is_parameter argument. > (macro_define_command): Update. > (macro_undef_command): Likewise. > * macroexp.c (stringify): New function. > (find_parameter): Likewise. > (gather_arguments): Add nargs argument. Handle varargs. > (substitute_args): Add is_varargs and va_arg_name arguments. > Handle varargs, splicing, stringification. Use find_parameter. > (expand): Handle varargs. > > > Hope that it helps :-). > > Regards, > > On Wed, 2008-10-01 at 15:38 -0700, Michael Snyder wrote: >> Hi Sergio, >> >> What source tree or snapshot is your diff taken from? >> I tried applying it to current cvs, and got a lot of >> failures and fuzzes. >> >> Sérgio Durigan Júnior wrote: >>> Hello guys, >>> >>> As this is my first "serious" patch to GDB, I'm sure there will be a lot >>> of mistakes in it :-). Anyway, I hope this adds something useful to the >>> program. >>> >>> The purpose of this patch is to implement a new feature in GDB called >>> "catch syscall". In this first moment, the feature should look something >>> like the 'strace' utility, but less "capable" (it still can't, for >>> example, get the syscall arguments and return code - although, the way I >>> see, this would be easy to do). >>> >>> With this feature, you can start over you GDB and tell it to start >>> catching syscalls in the inferior. Whenever a syscall is called (or >>> returns), GDB stops and tell you the name of it. You can also ask GDB to >>> "filter" the syscalls so that you'll only see calls/returns from that >>> specific syscall. >>> >>> For now the feature is only implemented for PPC32 and PPC64, but in a >>> future not so distant I intend to send patches for x86 and x86_64 too. >>> >>> I've tried to organize the code the best way I could, and I've >>> extensively used the codes for "catch fork", "catch exec" and "catch >>> unload" as an example. I'd be glad if you could give some opinions about >>> the way I did it :-). >>> >>> I've also splitted the patch into 4 logical "sequences", that are >>> organized in this way: >>> >>> - First part implements the architecture-independent part of the >>> feature. >>> - Second part implements the architecture-dependent (PPC32 and PPC64) >>> part of the feature. >>> - Third part refers to the documentation. >>> - Fourth part brings the testcase. >>> >>> Unfortunately, if one applies the patch and compiles GDB for PPC64, it >>> doesn't work properly. This is due to a bug which we have found that >>> makes the inferior segfault when there is a breakpoint inserted at its >>> entrypoint (AT_ENTRY). Luis Machado is taking a closer look into this >>> issue, so I think he'll have a solution soon :-). >>> >>> Special thanks goes to Thiago Bauermann, Luis Machado and Carlos Seo, >>> who helped me a lot with my never-ending questions about GDB. >>> >>> Regards, >>> >>> -- >>> Sérgio Durigan Júnior >>> Linux on Power Toolchain - Software Engineer >>> Linux Technology Center - LTC >>> IBM Brazil >>> >>> > -- > Sérgio Durigan Júnior > Linux on Power Toolchain - Software Engineer > Linux Technology Center - LTC > IBM Brazil > --------------040706010100030701000506 Content-Type: text/plain; name="sergio1.txt" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="sergio1.txt" Content-length: 45227 Index: breakpoint.c =================================================================== RCS file: /cvs/src/src/gdb/breakpoint.c,v retrieving revision 1.352 diff -u -p -r1.352 breakpoint.c --- breakpoint.c 16 Sep 2008 18:55:01 -0000 1.352 +++ breakpoint.c 1 Oct 2008 23:41:29 -0000 @@ -404,6 +404,18 @@ set_breakpoint_count (int num) value_from_longest (builtin_type_int32, (LONGEST) num)); } +/* Used in run_command to reset syscall catchpoints fields. */ + +void +clear_syscall_catchpoints_info (void) +{ + struct breakpoint *b; + + ALL_BREAKPOINTS (b) + if (b->type == bp_catch_syscall) + b->syscall_number = UNKNOWN_SYSCALL; +} + /* Used in run_command to zero the hit count when a new run starts. */ void @@ -810,6 +822,9 @@ insert_catchpoint (struct ui_out *uo, vo case bp_catch_exec: target_insert_exec_catchpoint (PIDGET (inferior_ptid)); break; + case bp_catch_syscall: + target_insert_syscall_catchpoint (PIDGET (inferior_ptid)); + break; default: internal_error (__FILE__, __LINE__, _("unknown breakpoint type")); break; @@ -1250,7 +1265,8 @@ Note: automatically using hardware break else if (bpt->owner->type == bp_catch_fork || bpt->owner->type == bp_catch_vfork - || bpt->owner->type == bp_catch_exec) + || bpt->owner->type == bp_catch_exec + || bpt->owner->type == bp_catch_syscall) { struct gdb_exception e = catch_exception (uiout, insert_catchpoint, bpt->owner, RETURN_MASK_ERROR); @@ -1708,6 +1724,9 @@ remove_breakpoint (struct bp_location *b case bp_catch_exec: val = target_remove_exec_catchpoint (PIDGET (inferior_ptid)); break; + case bp_catch_syscall: + val = target_remove_syscall_catchpoint (PIDGET (inferior_ptid)); + break; default: warning (_("Internal error, %s line %d."), __FILE__, __LINE__); break; @@ -1957,7 +1976,8 @@ ep_is_catchpoint (struct breakpoint *ep) || (ep->type == bp_catch_unload) || (ep->type == bp_catch_fork) || (ep->type == bp_catch_vfork) - || (ep->type == bp_catch_exec); + || (ep->type == bp_catch_exec) + || (ep->type == bp_catch_syscall); /* ??rehrauer: Add more kinds here, as are implemented... */ } @@ -2278,6 +2298,13 @@ print_it_typical (bpstat bs) struct cleanup *old_chain, *ui_out_chain; struct breakpoint *b; const struct bp_location *bl; + /* Used for "catch syscall". + + This is needed because we want to know in which state a + syscall is. It can be in the TARGET_WAITKIND_SYSCALL_ENTRY + or TARGET_WAITKIND_SYSCALL_RETURN, and depending on it we + must print "called syscall" or "returned from syscall". */ + struct thread_info *th_info = find_thread_pid (inferior_ptid); struct ui_stream *stb; int bp_temp = 0; stb = ui_out_stream_new (uiout); @@ -2329,6 +2356,14 @@ print_it_typical (bpstat bs) return PRINT_NOTHING; break; + case bp_entry_breakpoint: + /* Not sure how we will get here. + GDB should not stop for these breakpoints. */ + internal_error (__FILE__, __LINE__, + _("Entry Breakpoint: gdb should not stop!\n")); + return PRINT_NOTHING; + break; + case bp_overlay_event: /* By analogy with the thread event, GDB should not stop for these. */ printf_filtered (_("Overlay Event Breakpoint: gdb should not stop!\n")); @@ -2375,6 +2410,17 @@ print_it_typical (bpstat bs) return PRINT_SRC_AND_LOC; break; + case bp_catch_syscall: + annotate_catchpoint (b->number); + printf_filtered (_("\nCatchpoint %d (%s syscall '%s ()'), "), + b->number, + (th_info->syscall_state == TARGET_WAITKIND_SYSCALL_ENTRY) + ? "called" : "returned from", + gdbarch_syscall_name_from_number (current_gdbarch, + b->syscall_number)); + return PRINT_SRC_AND_LOC; + break; + case bp_watchpoint: case bp_hardware_watchpoint: annotate_watchpoint (b->number); @@ -2795,7 +2841,8 @@ bpstat_check_location (const struct bp_l && b->type != bp_hardware_breakpoint && b->type != bp_catch_fork && b->type != bp_catch_vfork - && b->type != bp_catch_exec) /* a non-watchpoint bp */ + && b->type != bp_catch_exec + && b->type != bp_catch_syscall) /* a non-watchpoint bp */ { if (bl->address != bp_addr) /* address doesn't match */ return 0; @@ -2869,6 +2916,25 @@ bpstat_check_location (const struct bp_l && !inferior_has_execd (inferior_ptid, &b->exec_pathname)) return 0; + /* We must check if we are catching specific syscalls in this breakpoint. + If we are, then we must guarantee that the called syscall is the same + syscall we are catching. */ + if (b->type == bp_catch_syscall) + { + int syscall_number; + if (!inferior_has_called_syscall (inferior_ptid, &syscall_number)) + return 0; + /* Now, checking if the syscall is the same. */ + if (b->syscall_to_be_caught != CATCHING_ANY_SYSCALL + && b->syscall_to_be_caught != syscall_number) + /* Not the same. */ + return 0; + + /* It's the same syscall. We can update the breakpoint struct + with the correct information. */ + b->syscall_number = syscall_number; + } + return 1; } @@ -3212,6 +3278,9 @@ bpstat_what (bpstat bs) /* We caught a shared library event. */ catch_shlib_event, + /* We are in a entry breakpoint. */ + entry_breakpoint, + /* This is just used to count how many enums there are. */ class_last }; @@ -3228,6 +3297,7 @@ bpstat_what (bpstat bs) #define sr BPSTAT_WHAT_STEP_RESUME #define shl BPSTAT_WHAT_CHECK_SHLIBS #define shlr BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK +#define entrybp BPSTAT_WHAT_ENTRY_BREAKPOINT /* "Can't happen." Might want to print an error message. abort() is not out of the question, but chances are GDB is just @@ -3272,30 +3342,33 @@ bpstat_what (bpstat bs) table[(int) class_last][(int) BPSTAT_WHAT_LAST] = { /* old action */ - /* kc ss sn sgl slr clr sr shl shlr + /* kc ss sn sgl slr clr sr shl shlr entrybp */ /*no_effect */ - {kc, ss, sn, sgl, slr, clr, sr, shl, shlr}, + {kc, ss, sn, sgl, slr, clr, sr, shl, shlr, shlr}, /*wp_silent */ - {ss, ss, sn, ss, ss, ss, sr, shl, shlr}, + {ss, ss, sn, ss, ss, ss, sr, shl, shlr, shlr}, /*wp_noisy */ - {sn, sn, sn, sn, sn, sn, sr, shl, shlr}, + {sn, sn, sn, sn, sn, sn, sr, shl, shlr, shlr}, /*bp_nostop */ - {sgl, ss, sn, sgl, slr, slr, sr, shl, shlr}, + {sgl, ss, sn, sgl, slr, slr, sr, shl, shlr, shlr}, /*bp_silent */ - {ss, ss, sn, ss, ss, ss, sr, shl, shlr}, + {ss, ss, sn, ss, ss, ss, sr, shl, shlr, shlr}, /*bp_noisy */ - {sn, sn, sn, sn, sn, sn, sr, shl, shlr}, + {sn, sn, sn, sn, sn, sn, sr, shl, shlr, shlr}, /*long_jump */ - {slr, ss, sn, slr, slr, err, sr, shl, shlr}, + {slr, ss, sn, slr, slr, err, sr, shl, shlr, shlr}, /*long_resume */ - {clr, ss, sn, err, err, err, sr, shl, shlr}, + {clr, ss, sn, err, err, err, sr, shl, shlr, shlr}, /*step_resume */ - {sr, sr, sr, sr, sr, sr, sr, sr, sr}, + {sr, sr, sr, sr, sr, sr, sr, sr, sr, sr}, /*shlib */ - {shl, shl, shl, shl, shl, shl, sr, shl, shlr}, + {shl, shl, shl, shl, shl, shl, sr, shl, shlr, shl}, /*catch_shlib */ - {shlr, shlr, shlr, shlr, shlr, shlr, sr, shlr, shlr} + {shlr, shlr, shlr, shlr, shlr, shlr, sr, shlr, shlr, shlr}, +/* entry_breakpoint */ + {entrybp, entrybp, entrybp, entrybp, entrybp, entrybp, sr, entrybp, + entrybp, entrybp} }; #undef kc @@ -3309,6 +3382,7 @@ bpstat_what (bpstat bs) #undef ts #undef shl #undef shlr +#undef entrybp enum bpstat_what_main_action current_action = BPSTAT_WHAT_KEEP_CHECKING; struct bpstat_what retval; @@ -3396,6 +3470,7 @@ bpstat_what (bpstat bs) case bp_catch_fork: case bp_catch_vfork: case bp_catch_exec: + case bp_catch_syscall: if (bs->stop) { if (bs->print) @@ -3414,6 +3489,12 @@ bpstat_what (bpstat bs) bs_class = bp_silent; retval.call_dummy = 1; break; + case bp_entry_breakpoint: + if (bs->stop) + bs_class = entry_breakpoint; + else + bs_class = no_effect; + break; } current_action = table[(int) bs_class][(int) current_action]; } @@ -3577,7 +3658,9 @@ print_one_breakpoint_location (struct br {bp_catch_unload, "catch unload"}, {bp_catch_fork, "catch fork"}, {bp_catch_vfork, "catch vfork"}, - {bp_catch_exec, "catch exec"} + {bp_catch_exec, "catch exec"}, + {bp_catch_syscall, "catch syscall"}, + {bp_entry_breakpoint, "entry breakpoint"} }; static char bpenables[] = "nynny"; @@ -3743,6 +3826,23 @@ print_one_breakpoint_location (struct br } break; + case bp_catch_syscall: + /* Field 4, the address, is omitted (which makes the columns + not line up too nicely with the headers, but the effect + is relatively readable). */ + if (addressprint) + ui_out_field_skip (uiout, "addr"); + annotate_field (5); + ui_out_text (uiout, "syscall \""); + if (b->syscall_number != UNKNOWN_SYSCALL) + ui_out_field_string (uiout, "what", + gdbarch_syscall_name_from_number (current_gdbarch, + b->syscall_number)); + else + ui_out_field_string (uiout, "what", ""); + ui_out_text (uiout, "\" "); + break; + case bp_breakpoint: case bp_hardware_breakpoint: case bp_until: @@ -3755,6 +3855,7 @@ print_one_breakpoint_location (struct br case bp_shlib_event: case bp_thread_event: case bp_overlay_event: + case bp_entry_breakpoint: if (addressprint) { annotate_field (4); @@ -3944,6 +4045,7 @@ user_settable_breakpoint (const struct b || b->type == bp_catch_fork || b->type == bp_catch_vfork || b->type == bp_catch_exec + || b->type == bp_catch_syscall || b->type == bp_hardware_breakpoint || b->type == bp_watchpoint || b->type == bp_read_watchpoint @@ -4150,6 +4252,7 @@ set_default_breakpoint (int valid, CORE_ bp_hardware_watchpoint bp_read_watchpoint bp_access_watchpoint + bp_catch_syscall bp_catch_exec bp_catch_fork bp_catch_vork */ @@ -4163,6 +4266,7 @@ breakpoint_address_is_meaningful (struct && type != bp_hardware_watchpoint && type != bp_read_watchpoint && type != bp_access_watchpoint + && type != bp_catch_syscall && type != bp_catch_exec && type != bp_catch_fork && type != bp_catch_vfork); @@ -4282,7 +4386,8 @@ adjust_breakpoint_address (CORE_ADDR bpa || bptype == bp_access_watchpoint || bptype == bp_catch_fork || bptype == bp_catch_vfork - || bptype == bp_catch_exec) + || bptype == bp_catch_exec + || bptype == bp_catch_syscall) { /* Watchpoints and the various bp_catch_* eventpoints should not have their addresses modified. */ @@ -4333,6 +4438,7 @@ allocate_bp_location (struct breakpoint case bp_watchpoint_scope: case bp_call_dummy: case bp_shlib_event: + case bp_entry_breakpoint: case bp_thread_event: case bp_overlay_event: case bp_catch_load: @@ -4351,6 +4457,7 @@ allocate_bp_location (struct breakpoint case bp_catch_fork: case bp_catch_vfork: case bp_catch_exec: + case bp_catch_syscall: loc->loc_type = bp_loc_other; break; default: @@ -4396,6 +4503,8 @@ set_raw_breakpoint_without_location (enu b->triggered_dll_pathname = NULL; b->forked_inferior_pid = null_ptid; b->exec_pathname = NULL; + b->syscall_to_be_caught = CATCHING_ANY_SYSCALL; + b->syscall_number = UNKNOWN_SYSCALL; b->ops = NULL; b->condition_not_parsed = 0; @@ -4618,6 +4727,31 @@ disable_overlay_breakpoints (void) } } +int +create_entry_breakpoint () +{ + CORE_ADDR taddr, entry_addr; + struct breakpoint *b; + + taddr = entry_point_address (); + /* Make certain that the address points at real code, and not a + function descriptor. */ + entry_addr = gdbarch_convert_from_func_ptr_addr (current_gdbarch, taddr, + ¤t_target); + + /* Setting the breakpoint */ + b = create_internal_breakpoint (entry_addr, bp_entry_breakpoint); + + b->enable_state = bp_enabled; + b->disposition = disp_del; + /* addr_string has to be used or breakpoint_re_set will delete me. */ + b->addr_string = xstrprintf ("AT_ENTRY (0x%s)", paddr (entry_addr)); + + update_global_location_list (1); + + return 1; +} + struct breakpoint * create_thread_event_breakpoint (CORE_ADDR address) { @@ -4817,6 +4951,31 @@ create_exec_event_catchpoint (int tempfl mention (b); } +static void +create_syscall_event_catchpoint (int tempflag, int syscall_number) +{ + struct symtab_and_line sal; + struct breakpoint *b; + int thread = -1; /* All threads. */ + + init_sal (&sal); + + b = set_raw_breakpoint (sal, bp_catch_syscall); + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; + b->cond_string = NULL; + b->thread = thread; + b->syscall_to_be_caught = syscall_number; + /* We still don't know the syscall that will be caught :-). */ + b->syscall_number = UNKNOWN_SYSCALL; + b->addr_string = NULL; + b->enable_state = bp_enabled; + b->disposition = tempflag ? disp_del : disp_donttouch; + update_global_location_list (1); + + mention (b); +} + static int hw_breakpoint_used_count (void) { @@ -5034,6 +5193,16 @@ mention (struct breakpoint *b) printf_filtered (_("Catchpoint %d (exec)"), b->number); break; + case bp_catch_syscall: + if (b->syscall_to_be_caught != CATCHING_ANY_SYSCALL) + printf_filtered (_("Catchpoint %d (syscall '%s ()')"), + b->number, + gdbarch_syscall_name_from_number (current_gdbarch, + b->syscall_to_be_caught)); + else + printf_filtered (_("Catchpoint %d (syscall)"), + b->number); + break; case bp_until: case bp_finish: @@ -5045,6 +5214,7 @@ mention (struct breakpoint *b) case bp_shlib_event: case bp_thread_event: case bp_overlay_event: + case bp_entry_breakpoint: break; } @@ -6795,6 +6965,36 @@ catch_ada_exception_command (char *arg, from_tty); } +/* Implement the "catch syscall" command. */ + +static void +catch_syscall_command_1 (char *arg, int from_tty, struct cmd_list_element *command) +{ + int tempflag; + int syscall_number = CATCHING_ANY_SYSCALL; + + tempflag = get_cmd_context (command) == CATCH_TEMPORARY; + + ep_skip_leading_whitespace (&arg); + + /* The allowed syntax is: + catch syscall + catch syscall + + Let's check if there's a syscall name. */ + + if (arg != NULL) + { + syscall_number = gdbarch_syscall_number_from_name (current_gdbarch, + (const char *) arg); + if (syscall_number == UNKNOWN_SYSCALL) + error (_("Invalid syscall name '%s'."), arg); + } + + /* Now let's create the catchpoint */ + create_syscall_event_catchpoint (tempflag, syscall_number); +} + /* Implement the "catch assert" command. */ static void @@ -7312,6 +7512,7 @@ delete_command (char *arg, int from_tty) b->type != bp_shlib_event && b->type != bp_thread_event && b->type != bp_overlay_event && + b->type != bp_entry_breakpoint && b->number >= 0) { breaks_to_delete = 1; @@ -7329,6 +7530,7 @@ delete_command (char *arg, int from_tty) b->type != bp_shlib_event && b->type != bp_thread_event && b->type != bp_overlay_event && + b->type != bp_entry_breakpoint && b->number >= 0) delete_breakpoint (b); } @@ -7620,6 +7822,7 @@ breakpoint_re_set_one (void *bint) case bp_catch_fork: case bp_catch_vfork: case bp_catch_exec: + case bp_catch_syscall: break; default: @@ -7639,6 +7842,9 @@ breakpoint_re_set_one (void *bint) Once it is set up, we do not want to touch it. */ case bp_thread_event: + /* Same for this one */ + case bp_entry_breakpoint: + /* Keep temporary breakpoints, which can be encountered when we step over a dlopen call and SOLIB_ADD is resetting the breakpoints. Otherwise these should have been blown away via the cleanup chain @@ -7893,6 +8099,7 @@ disable_command (char *args, int from_tt case bp_catch_fork: case bp_catch_vfork: case bp_catch_exec: + case bp_catch_syscall: case bp_hardware_breakpoint: case bp_watchpoint: case bp_hardware_watchpoint: @@ -8027,6 +8234,7 @@ enable_command (char *args, int from_tty case bp_catch_fork: case bp_catch_vfork: case bp_catch_exec: + case bp_catch_syscall: case bp_hardware_breakpoint: case bp_watchpoint: case bp_hardware_watchpoint: @@ -8209,6 +8417,45 @@ single_step_breakpoint_inserted_here_p ( return 0; } +/* Returns 0 if 'bp' is NOT a syscall catchpoint, + non-zero otherwise. */ +static int +is_syscall_catchpoint_enabled (struct breakpoint *bp) +{ + if (bp->type == bp_catch_syscall + && bp->enable_state != bp_disabled + && bp->enable_state != bp_call_disabled) + return 1; + else + return 0; +} + +int +catch_syscall_enabled (void) +{ + struct breakpoint *bp; + + ALL_BREAKPOINTS (bp) + if (is_syscall_catchpoint_enabled (bp)) + return 1; + + return 0; +} + +int +catching_syscall_number (int syscall_number) +{ + struct breakpoint *bp; + + ALL_BREAKPOINTS (bp) + if (is_syscall_catchpoint_enabled (bp)) + if (bp->syscall_to_be_caught == syscall_number + || bp->syscall_to_be_caught == CATCHING_ANY_SYSCALL) + return 1; + + return 0; +} + /* This help string is used for the break, hbreak, tbreak and thbreak commands. It is defined as a macro to prevent duplication. @@ -8549,6 +8796,12 @@ With an argument, catch only exceptions catch_exec_command_1, CATCH_PERMANENT, CATCH_TEMPORARY); + add_catch_command ("syscall", _("\ +Catch calls to syscalls.\n\ +With an argument, catch only calls of that syscall."), + catch_syscall_command_1, + CATCH_PERMANENT, + CATCH_TEMPORARY); add_catch_command ("load", _("\ Catch library loads.\n\ With an argument, catch only loads of that library."), @@ -8595,7 +8848,6 @@ an expression is either read or written. add_info ("watchpoints", breakpoints_info, _("Synonym for ``info breakpoints''.")); - /* XXX: cagney/2005-02-23: This should be a boolean, and should respond to changes - contrary to the description. */ add_setshow_zinteger_cmd ("can-use-hw-watchpoints", class_support, Index: breakpoint.h =================================================================== RCS file: /cvs/src/src/gdb/breakpoint.h,v retrieving revision 1.79 diff -u -p -r1.79 breakpoint.h --- breakpoint.h 22 Sep 2008 15:26:53 -0000 1.79 +++ breakpoint.h 1 Oct 2008 23:41:29 -0000 @@ -32,6 +32,11 @@ struct block; arrays that should be independent of the target architecture. */ #define BREAKPOINT_MAX 16 + +/* A number to represent wether we are catching any syscalls. */ + +#define CATCHING_ANY_SYSCALL (-1) + /* Type of breakpoint. */ /* FIXME In the future, we should fold all other breakpoint-like things into @@ -127,6 +132,14 @@ enum bptype bp_catch_fork, bp_catch_vfork, bp_catch_exec, + + /* This is not really a breakpoint, but the catchpoint which implements + the "catch syscall" functionality. */ + bp_catch_syscall, + + /* This type is used to signal an internal breakpoint located at + the AT_ENTRY address. */ + bp_entry_breakpoint, }; /* States of enablement of breakpoint. */ @@ -455,6 +468,21 @@ struct breakpoint triggered. */ char *exec_pathname; + /* Syscall number used for the 'catch syscall' feature. + If no syscall has been called, its value is UNKNOWN_SYSCALL. + Otherwise, it holds the system call number in the target. + + This field is only valid immediately after this catchpoint has + triggered. */ + int syscall_number; + + /* This field is used when we are "filtering" the syscalls + (i.e., when the user types "catch syscall ". + + It stores the syscall number in case we are in the "filter mode", + or CATCHING_ANY_SYSCALL otherwise. */ + int syscall_to_be_caught; + /* Methods associated with this breakpoint. */ struct breakpoint_ops *ops; @@ -536,6 +564,10 @@ enum bpstat_what_main_action resume out of the dynamic linker's callback, stop and print. */ BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK, + /* This internal breakpoint is used syscall catchpoints only after the + shell and the dynamic linker have already ran. */ + BPSTAT_WHAT_ENTRY_BREAKPOINT, + /* This is just used to keep track of how many enums there are. */ BPSTAT_WHAT_LAST }; @@ -805,6 +837,8 @@ extern void enable_watchpoints_after_int extern enum command_control_type commands_from_control_command (char *arg, struct command_line *cmd); +extern void clear_syscall_catchpoints_info (void); + extern void clear_breakpoint_hit_counts (void); extern int get_number (char **); @@ -884,4 +918,26 @@ extern int breakpoints_always_inserted_m in our opinion won't ever trigger. */ extern void breakpoint_retire_moribund (void); +/* Checks if we are catching syscalls or not. + Returns 0 if not, greater than 0 if we are. */ +extern int catch_syscall_enabled (void); + +/* Checks if we are catching syscalls with the specific + syscall_number. Used for "filtering" the catchpoints. + Returns 0 if not, greater than 0 if we are. */ +extern int catching_syscall_number (int syscall_number); + +/* Function used to set an internal breakpoint at the AT_ENTRY + (a.k.a. the entry point of the inferior). + + This is currently needed for us to know when to start setting + up catchpoints for syscalls in the inferior. If we don't do that, + then we would set a "catch syscall" too early, which would + catch syscalls from ld.so and/or libc (and we don't want that). + + Returns zero if there was an error setting this breakpoint, + or 1 if everything went OK. */ +extern int create_entry_breakpoint (void); + + #endif /* !defined (BREAKPOINT_H) */ Index: gdbarch.c =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.c,v retrieving revision 1.438 diff -u -p -r1.438 gdbarch.c --- gdbarch.c 11 Sep 2008 14:26:59 -0000 1.438 +++ gdbarch.c 1 Oct 2008 23:41:29 -0000 @@ -240,6 +240,9 @@ struct gdbarch gdbarch_target_signal_from_host_ftype *target_signal_from_host; gdbarch_target_signal_to_host_ftype *target_signal_to_host; gdbarch_record_special_symbol_ftype *record_special_symbol; + gdbarch_get_syscall_number_ftype *get_syscall_number; + gdbarch_syscall_name_from_number_ftype *syscall_name_from_number; + gdbarch_syscall_number_from_name_ftype *syscall_number_from_name; }; @@ -371,6 +374,9 @@ struct gdbarch startup_gdbarch = default_target_signal_from_host, /* target_signal_from_host */ default_target_signal_to_host, /* target_signal_to_host */ 0, /* record_special_symbol */ + 0, /* get_syscall_number */ + 0, /* syscall_name_from_number */ + 0, /* syscall_number_from_name */ /* startup_gdbarch() */ }; @@ -623,6 +629,9 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of target_signal_from_host, invalid_p == 0 */ /* Skip verify of target_signal_to_host, invalid_p == 0 */ /* Skip verify of record_special_symbol, has predicate */ + /* Skip verify of get_syscall_number, has predicate */ + /* Skip verify of syscall_name_from_number, has predicate */ + /* Skip verify of syscall_number_from_name, has predicate */ buf = ui_file_xstrdup (log, &dummy); make_cleanup (xfree, buf); if (strlen (buf) > 0) @@ -832,6 +841,12 @@ gdbarch_dump (struct gdbarch *gdbarch, s "gdbarch_dump: get_longjmp_target = <0x%lx>\n", (long) gdbarch->get_longjmp_target); fprintf_unfiltered (file, + "gdbarch_dump: gdbarch_get_syscall_number_p() = %d\n", + gdbarch_get_syscall_number_p (gdbarch)); + fprintf_unfiltered (file, + "gdbarch_dump: get_syscall_number = <0x%lx>\n", + (long) gdbarch->get_syscall_number); + fprintf_unfiltered (file, "gdbarch_dump: have_nonsteppable_watchpoint = %s\n", plongest (gdbarch->have_nonsteppable_watchpoint)); fprintf_unfiltered (file, @@ -1051,6 +1066,18 @@ gdbarch_dump (struct gdbarch *gdbarch, s "gdbarch_dump: static_transform_name = <0x%lx>\n", (long) gdbarch->static_transform_name); fprintf_unfiltered (file, + "gdbarch_dump: gdbarch_syscall_name_from_number_p() = %d\n", + gdbarch_syscall_name_from_number_p (gdbarch)); + fprintf_unfiltered (file, + "gdbarch_dump: syscall_name_from_number = <0x%lx>\n", + (long) gdbarch->syscall_name_from_number); + fprintf_unfiltered (file, + "gdbarch_dump: gdbarch_syscall_number_from_name_p() = %d\n", + gdbarch_syscall_number_from_name_p (gdbarch)); + fprintf_unfiltered (file, + "gdbarch_dump: syscall_number_from_name = <0x%lx>\n", + (long) gdbarch->syscall_number_from_name); + fprintf_unfiltered (file, "gdbarch_dump: target_desc = %s\n", plongest ((long) gdbarch->target_desc)); fprintf_unfiltered (file, @@ -3237,6 +3264,78 @@ set_gdbarch_record_special_symbol (struc gdbarch->record_special_symbol = record_special_symbol; } +int +gdbarch_get_syscall_number_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return gdbarch->get_syscall_number != NULL; +} + +LONGEST +gdbarch_get_syscall_number (struct gdbarch *gdbarch, ptid_t ptid) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->get_syscall_number != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_get_syscall_number called\n"); + return gdbarch->get_syscall_number (gdbarch, ptid); +} + +void +set_gdbarch_get_syscall_number (struct gdbarch *gdbarch, + gdbarch_get_syscall_number_ftype get_syscall_number) +{ + gdbarch->get_syscall_number = get_syscall_number; +} + +int +gdbarch_syscall_name_from_number_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return gdbarch->syscall_name_from_number != NULL; +} + +const char * +gdbarch_syscall_name_from_number (struct gdbarch *gdbarch, int syscall_number) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->syscall_name_from_number != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_syscall_name_from_number called\n"); + return gdbarch->syscall_name_from_number (gdbarch, syscall_number); +} + +void +set_gdbarch_syscall_name_from_number (struct gdbarch *gdbarch, + gdbarch_syscall_name_from_number_ftype syscall_name_from_number) +{ + gdbarch->syscall_name_from_number = syscall_name_from_number; +} + +int +gdbarch_syscall_number_from_name_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return gdbarch->syscall_number_from_name != NULL; +} + +int +gdbarch_syscall_number_from_name (struct gdbarch *gdbarch, const char *syscall_name) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->syscall_number_from_name != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_syscall_number_from_name called\n"); + return gdbarch->syscall_number_from_name (gdbarch, syscall_name); +} + +void +set_gdbarch_syscall_number_from_name (struct gdbarch *gdbarch, + gdbarch_syscall_number_from_name_ftype syscall_number_from_name) +{ + gdbarch->syscall_number_from_name = syscall_number_from_name; +} + /* Keep a registry of per-architecture data-pointers required by GDB modules. */ Index: gdbarch.h =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.h,v retrieving revision 1.389 diff -u -p -r1.389 gdbarch.h --- gdbarch.h 11 Sep 2008 14:26:59 -0000 1.389 +++ gdbarch.h 1 Oct 2008 23:41:29 -0000 @@ -811,6 +811,37 @@ typedef void (gdbarch_record_special_sym extern void gdbarch_record_special_symbol (struct gdbarch *gdbarch, struct objfile *objfile, asymbol *sym); extern void set_gdbarch_record_special_symbol (struct gdbarch *gdbarch, gdbarch_record_special_symbol_ftype *record_special_symbol); +/* Functions for the 'catch syscall' feature. + Get architecture-specific system calls information from registers. */ + +extern int gdbarch_get_syscall_number_p (struct gdbarch *gdbarch); + +typedef LONGEST (gdbarch_get_syscall_number_ftype) (struct gdbarch *gdbarch, ptid_t ptid); +extern LONGEST gdbarch_get_syscall_number (struct gdbarch *gdbarch, ptid_t ptid); +extern void set_gdbarch_get_syscall_number (struct gdbarch *gdbarch, gdbarch_get_syscall_number_ftype *get_syscall_number); + +/* Translate a syscall number to its corresponding name. */ + +extern int gdbarch_syscall_name_from_number_p (struct gdbarch *gdbarch); + +typedef const char * (gdbarch_syscall_name_from_number_ftype) (struct gdbarch *gdbarch, int syscall_number); +extern const char * gdbarch_syscall_name_from_number (struct gdbarch *gdbarch, int syscall_number); +extern void set_gdbarch_syscall_name_from_number (struct gdbarch *gdbarch, gdbarch_syscall_name_from_number_ftype *syscall_name_from_number); + +/* Translate a syscall name to its corresponding number. + + This function must return the syscall number if found, or + UNKNOWN_SYSCALL if not found. */ + +extern int gdbarch_syscall_number_from_name_p (struct gdbarch *gdbarch); + +typedef int (gdbarch_syscall_number_from_name_ftype) (struct gdbarch *gdbarch, const char *syscall_name); +extern int gdbarch_syscall_number_from_name (struct gdbarch *gdbarch, const char *syscall_name); +extern void set_gdbarch_syscall_number_from_name (struct gdbarch *gdbarch, gdbarch_syscall_number_from_name_ftype *syscall_number_from_name); + +/* Definition for an unknown syscall, used basically in error-cases. */ +#define UNKNOWN_SYSCALL (-1) + extern struct gdbarch_tdep *gdbarch_tdep (struct gdbarch *gdbarch); Index: gdbarch.sh =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.sh,v retrieving revision 1.479 diff -u -p -r1.479 gdbarch.sh --- gdbarch.sh 11 Sep 2008 14:27:00 -0000 1.479 +++ gdbarch.sh 1 Oct 2008 23:41:29 -0000 @@ -707,6 +707,20 @@ m:int:target_signal_to_host:enum target_ # Record architecture-specific information from the symbol table. M:void:record_special_symbol:struct objfile *objfile, asymbol *sym:objfile, sym + +# Functions for the 'catch syscall' feature. + +# Get architecture-specific system calls information from registers. +M:LONGEST:get_syscall_number:ptid_t ptid:ptid + +# Translate a syscall number to its corresponding name. +M:const char *:syscall_name_from_number:int syscall_number:syscall_number + +# Translate a syscall name to its corresponding number. +# +# This function must return the syscall number if found, or +# UNKNOWN_SYSCALL if not found. +M:int:syscall_number_from_name:const char *syscall_name:syscall_name EOF } @@ -888,6 +902,9 @@ done # close it off cat <to_follow_fork = inf_child_follow_fork; t->to_insert_exec_catchpoint = inf_child_insert_exec_catchpoint; t->to_remove_exec_catchpoint = inf_child_remove_exec_catchpoint; + t->to_insert_syscall_catchpoint = inf_child_insert_syscall_catchpoint; + t->to_remove_syscall_catchpoint = inf_child_remove_syscall_catchpoint; t->to_can_run = inf_child_can_run; t->to_pid_to_exec_file = inf_child_pid_to_exec_file; t->to_stratum = process_stratum; Index: inf-ptrace.c =================================================================== RCS file: /cvs/src/src/gdb/inf-ptrace.c,v retrieving revision 1.49 diff -u -p -r1.49 inf-ptrace.c --- inf-ptrace.c 22 Sep 2008 15:21:30 -0000 1.49 +++ inf-ptrace.c 1 Oct 2008 23:41:29 -0000 @@ -355,13 +355,19 @@ static void inf_ptrace_resume (ptid_t ptid, int step, enum target_signal signal) { pid_t pid = ptid_get_pid (ptid); - int request = PT_CONTINUE; + int request; if (pid == -1) /* Resume all threads. Traditionally ptrace() only supports single-threaded processes, so simply resume the inferior. */ pid = ptid_get_pid (inferior_ptid); + if (target_passed_by_entrypoint () > 0 + && catch_syscall_enabled () > 0) + request = PT_SYSCALL; + else + request = PT_CONTINUE; + if (step) { /* If this system does not support PT_STEP, a higher level Index: infcmd.c =================================================================== RCS file: /cvs/src/src/gdb/infcmd.c,v retrieving revision 1.212 diff -u -p -r1.212 infcmd.c --- infcmd.c 22 Sep 2008 15:20:08 -0000 1.212 +++ infcmd.c 1 Oct 2008 23:41:30 -0000 @@ -450,6 +450,11 @@ run_command_1 (char *args, int from_tty, init_wait_for_inferior (); clear_breakpoint_hit_counts (); + /* If we already caught a syscall catchpoint, then reset its + syscall_number information because we are starting all over + again. */ + clear_syscall_catchpoints_info (); + /* Clean up any leftovers from other runs. Some other things from this function should probably be moved into target_pre_inferior. */ target_pre_inferior (from_tty); Index: infrun.c =================================================================== RCS file: /cvs/src/src/gdb/infrun.c,v retrieving revision 1.322 diff -u -p -r1.322 infrun.c --- infrun.c 22 Sep 2008 15:26:53 -0000 1.322 +++ infrun.c 1 Oct 2008 23:41:30 -0000 @@ -964,7 +964,7 @@ a command like `return' or `jump' to con } } - /* If there were any forks/vforks/execs that were caught and are + /* If there were any forks/vforks/execs/syscalls that were caught and are now to be followed, then do so. */ switch (pending_follow.kind) { @@ -980,6 +980,11 @@ a command like `return' or `jump' to con pending_follow.kind = TARGET_WAITKIND_SPURIOUS; break; + case TARGET_WAITKIND_SYSCALL_ENTRY: + case TARGET_WAITKIND_SYSCALL_RETURN: + pending_follow.kind = TARGET_WAITKIND_SPURIOUS; + break; + default: break; } @@ -1386,8 +1391,8 @@ init_wait_for_inferior (void) breakpoint_init_inferior (inf_starting); - /* The first resume is not following a fork/vfork/exec. */ - pending_follow.kind = TARGET_WAITKIND_SPURIOUS; /* I.e., none. */ + /* The first resume is not following a fork/vfork/exec/syscall. */ + pending_follow.kind = TARGET_WAITKIND_SPURIOUS; /* I.e., none. */ clear_proceed_status (); @@ -1831,6 +1836,50 @@ ensure_not_running (void) error_is_running (); } +/* Auxiliary function that handles syscall entry/return events. + It returns 1 if the inferior should keep going (and GDB + should ignore the event), or 0 if the event deserves to be + processed. */ +static int +deal_with_syscall_event (struct execution_control_state *ecs) +{ + int syscall_number = gdbarch_get_syscall_number (current_gdbarch, + ecs->ptid); + if (catch_syscall_enabled () > 0 + && catching_syscall_number (syscall_number) > 0) + { + ecs->event_thread->stop_signal = TARGET_SIGNAL_TRAP; + pending_follow.kind = ecs->ws.kind; + + if (!ptid_equal (ecs->ptid, inferior_ptid)) + { + context_switch (ecs->ptid); + reinit_frame_cache (); + } + + stop_pc = read_pc (); + + ecs->event_thread->stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid); + + ecs->random_signal = !bpstat_explains_signal (ecs->event_thread->stop_bpstat); + + /* If no catchpoint triggered for this, then keep going. */ + if (ecs->random_signal) + { + ecs->event_thread->stop_signal = TARGET_SIGNAL_0; + keep_going (ecs); + return 1; + } + return 0; + } + else + { + resume (0, TARGET_SIGNAL_0); + prepare_to_wait (ecs); + return 1; + } +} + /* Given an execution control state that has been freshly filled in by an event from the inferior, figure out what it means and take appropriate action. */ @@ -2119,9 +2168,11 @@ handle_inferior_event (struct execution_ case TARGET_WAITKIND_SYSCALL_ENTRY: if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SYSCALL_ENTRY\n"); - resume (0, TARGET_SIGNAL_0); - prepare_to_wait (ecs); - return; + /* Getting the current syscall number */ + if (deal_with_syscall_event (ecs) != 0) + return; + goto process_event_stop_test; + break; /* Before examining the threads further, step this thread to get it entirely out of the syscall. (We get notice of the @@ -2131,9 +2182,10 @@ handle_inferior_event (struct execution_ case TARGET_WAITKIND_SYSCALL_RETURN: if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SYSCALL_RETURN\n"); - target_resume (ecs->ptid, 1, TARGET_SIGNAL_0); - prepare_to_wait (ecs); - return; + if (deal_with_syscall_event (ecs) != 0) + return; + goto process_event_stop_test; + break; case TARGET_WAITKIND_STOPPED: if (debug_infrun) @@ -2951,6 +3003,16 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME ( } break; + case BPSTAT_WHAT_ENTRY_BREAKPOINT: + /* We hit the AT_ENTRY breakpoint, and now we have to enable + the PTRACE_O_TRACESYSGOOD option in the inferior *if* we + are catching syscalls. */ + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_ENTRY_BREAKPOINT\n"); + target_enable_tracesysgood (ecs->ptid); + ecs->event_thread->stepping_over_breakpoint = 1; + break; + case BPSTAT_WHAT_LAST: /* Not a real code, but listed here to shut up gcc -Wall. */ @@ -4563,6 +4625,25 @@ inferior_has_execd (ptid_t pid, char **e return 1; } +int +inferior_has_called_syscall (ptid_t pid, int *syscall_number) +{ + struct target_waitstatus last; + ptid_t last_ptid; + + get_last_target_status (&last_ptid, &last); + + if (last.kind != TARGET_WAITKIND_SYSCALL_ENTRY && + last.kind != TARGET_WAITKIND_SYSCALL_RETURN) + return 0; + + if (!ptid_equal (last_ptid, pid)) + return 0; + + *syscall_number = last.value.syscall_number; + return 1; +} + /* Oft used ptids */ ptid_t null_ptid; ptid_t minus_one_ptid; Index: target.c =================================================================== RCS file: /cvs/src/src/gdb/target.c,v retrieving revision 1.184 diff -u -p -r1.184 target.c --- target.c 22 Sep 2008 15:21:30 -0000 1.184 +++ target.c 1 Oct 2008 23:41:30 -0000 @@ -426,6 +426,10 @@ update_current_target (void) /* Do not inherit to_follow_fork. */ INHERIT (to_insert_exec_catchpoint, t); INHERIT (to_remove_exec_catchpoint, t); + INHERIT (to_passed_by_entrypoint, t); + INHERIT (to_insert_syscall_catchpoint, t); + INHERIT (to_remove_syscall_catchpoint, t); + INHERIT (to_enable_tracesysgood, t); INHERIT (to_has_exited, t); INHERIT (to_mourn_inferior, t); INHERIT (to_can_run, t); @@ -581,9 +585,21 @@ update_current_target (void) de_fault (to_insert_exec_catchpoint, (void (*) (int)) tcomplain); + de_fault (to_passed_by_entrypoint, + (int (*) (void)) + tcomplain); de_fault (to_remove_exec_catchpoint, (int (*) (int)) tcomplain); + de_fault (to_insert_syscall_catchpoint, + (void (*) (int)) + tcomplain); + de_fault (to_remove_syscall_catchpoint, + (int (*) (int)) + tcomplain); + de_fault (to_enable_tracesysgood, + (void (*) (ptid_t)) + tcomplain); de_fault (to_has_exited, (int (*) (int, int, int *)) return_zero); @@ -2532,6 +2548,12 @@ debug_to_wait (ptid_t ptid, struct targe case TARGET_WAITKIND_EXECD: fprintf_unfiltered (gdb_stdlog, "execd\n"); break; + case TARGET_WAITKIND_SYSCALL_ENTRY: + fprintf_unfiltered (gdb_stdlog, "entered syscall\n"); + break; + case TARGET_WAITKIND_SYSCALL_RETURN: + fprintf_unfiltered (gdb_stdlog, "exited syscall\n"); + break; case TARGET_WAITKIND_SPURIOUS: fprintf_unfiltered (gdb_stdlog, "spurious\n"); break; Index: target.h =================================================================== RCS file: /cvs/src/src/gdb/target.h,v retrieving revision 1.130 diff -u -p -r1.130 target.h --- target.h 19 Aug 2008 13:22:14 -0000 1.130 +++ target.h 1 Oct 2008 23:41:30 -0000 @@ -135,14 +135,15 @@ struct target_waitstatus { enum target_waitkind kind; - /* Forked child pid, execd pathname, exit status or signal number. */ + /* Forked child pid, execd pathname, exit status, signal number or + syscall name. */ union { int integer; enum target_signal sig; ptid_t related_pid; char *execd_pathname; - int syscall_id; + int syscall_number; } value; }; @@ -393,6 +394,10 @@ struct target_ops int (*to_follow_fork) (struct target_ops *, int); void (*to_insert_exec_catchpoint) (int); int (*to_remove_exec_catchpoint) (int); + int (*to_passed_by_entrypoint) (void); + void (*to_insert_syscall_catchpoint) (int); + int (*to_remove_syscall_catchpoint) (int); + void (*to_enable_tracesysgood) (ptid_t); int (*to_has_exited) (int, int, int *); void (*to_mourn_inferior) (void); int (*to_can_run) (void); @@ -708,6 +713,8 @@ extern int inferior_has_vforked (ptid_t extern int inferior_has_execd (ptid_t pid, char **execd_pathname); +extern int inferior_has_called_syscall (ptid_t pid, int *syscall_number); + /* From exec.c */ extern void print_section_info (struct target_ops *, bfd *); @@ -867,6 +874,24 @@ int target_follow_fork (int follow_child #define target_remove_exec_catchpoint(pid) \ (*current_target.to_remove_exec_catchpoint) (pid) +/* Has the inferior already passed through its entrypoint? */ +#define target_passed_by_entrypoint() \ + (*current_target.to_passed_by_entrypoint) () + +/* Syscall catch functions */ + +#define target_insert_syscall_catchpoint(pid) \ + (*current_target.to_insert_syscall_catchpoint) (pid) + +#define target_remove_syscall_catchpoint(pid) \ + (*current_target.to_remove_syscall_catchpoint) (pid) + +/* Enable PTRACE_O_TRACESYSGOOD in the inferior. + This is mainly used for the "catch syscall" feature. */ + +#define target_enable_tracesysgood(ptid) \ + (*current_target.to_enable_tracesysgood) (ptid) + /* Returns TRUE if PID has exited. And, also sets EXIT_STATUS to the exit code of PID, if any. */ --------------040706010100030701000506 Content-Type: text/plain; name="sergio2.txt" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="sergio2.txt" Content-length: 20716 Index: linux-nat.c =================================================================== RCS file: /cvs/src/src/gdb/linux-nat.c,v retrieving revision 1.106 diff -u -p -r1.106 linux-nat.c --- linux-nat.c 25 Sep 2008 14:13:44 -0000 1.106 +++ linux-nat.c 1 Oct 2008 23:34:45 -0000 @@ -57,6 +57,10 @@ # endif #endif /* HAVE_PERSONALITY */ +/* To be used when one needs to know wether a + WSTOPSIG (status) is a syscall */ +#define TRAP_IS_SYSCALL (SIGTRAP | 0x80) + /* This comment documents high-level logic of this file. Waiting for events in sync mode @@ -269,17 +273,29 @@ struct simple_pid_list *stopped_pids; static int linux_supports_tracefork_flag = -1; +/* This variable is a tri-state flag: -1 for unknown, 0 if PTRACE_O_TRACESYSGOOD + can not be used, 1 if it can. */ + +static int linux_supports_tracesysgood_flag = -1; + /* If we have PTRACE_O_TRACEFORK, this flag indicates whether we also have PTRACE_O_TRACEVFORKDONE. */ static int linux_supports_tracevforkdone_flag = -1; +/* If the inferior have passed through its entrypoint (AT_ENTRY), + then this flag is set to 1. Otherwise, its value is 0. */ +static int linux_passed_by_entrypoint_flag = 0; + /* Async mode support */ /* Zero if the async mode, although enabled, is masked, which means linux_nat_wait should behave as if async mode was off. */ static int linux_nat_async_mask_value = 1; +/* Stores the current used ptrace() options. */ +static int current_ptrace_options = 0; + /* The read/write ends of the pipe registered as waitable file in the event loop. */ static int linux_nat_event_pipe[2] = { -1, -1 }; @@ -609,6 +625,41 @@ linux_test_for_tracefork (int original_p linux_nat_async_events (async_events_original_state); } +/* Determine if PTRACE_O_TRACESYSGOOD can be used to follow syscalls. + + We try to enable syscall 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. */ + +static void +linux_test_for_tracesysgood (int original_pid) +{ + int ret; + enum sigchld_state async_events_original_state; + + async_events_original_state = linux_nat_async_events (sigchld_sync); + + linux_supports_tracesysgood_flag = 0; + + ret = ptrace (PTRACE_SETOPTIONS, original_pid, 0, PTRACE_O_TRACESYSGOOD); + if (ret != 0) + return; + + linux_supports_tracesysgood_flag = 1; + linux_nat_async_events (async_events_original_state); +} + +/* Determine wether we support PTRACE_O_TRACESYSGOOD option available. + This function also sets linux_supports_tracesysgood_flag. */ + +static int +linux_supports_tracesysgood (int pid) +{ + if (linux_supports_tracesysgood_flag == -1) + linux_test_for_tracesysgood (pid); + return linux_supports_tracesysgood_flag; +} + /* Return non-zero iff we have tracefork functionality available. This function also sets linux_supports_tracefork_flag. */ @@ -629,11 +680,33 @@ linux_supports_tracevforkdone (int pid) } +static void +linux_enable_tracesysgood (ptid_t ptid) +{ + int pid = ptid_get_lwp (ptid); + + if (pid == 0) + pid = ptid_get_pid (ptid); + + if (linux_supports_tracesysgood (pid) == 0) + return; + + current_ptrace_options |= PTRACE_O_TRACESYSGOOD; + linux_passed_by_entrypoint_flag = 1; + + ptrace (PTRACE_SETOPTIONS, pid, 0, current_ptrace_options); +} + +static int +linux_passed_by_entrypoint (void) +{ + return linux_passed_by_entrypoint_flag; +} + void linux_enable_event_reporting (ptid_t ptid) { int pid = ptid_get_lwp (ptid); - int options; if (pid == 0) pid = ptid_get_pid (ptid); @@ -641,15 +714,16 @@ linux_enable_event_reporting (ptid_t pti if (! linux_supports_tracefork (pid)) return; - options = PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACEEXEC - | PTRACE_O_TRACECLONE; + current_ptrace_options |= PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK + | PTRACE_O_TRACEEXEC | PTRACE_O_TRACECLONE; + if (linux_supports_tracevforkdone (pid)) - options |= PTRACE_O_TRACEVFORKDONE; + current_ptrace_options |= PTRACE_O_TRACEVFORKDONE; /* Do not enable PTRACE_O_TRACEEXIT until GDB is more prepared to support read-only process state. */ - ptrace (PTRACE_SETOPTIONS, pid, 0, options); + ptrace (PTRACE_SETOPTIONS, pid, 0, current_ptrace_options); } static void @@ -664,6 +738,12 @@ linux_child_post_startup_inferior (ptid_ { linux_enable_event_reporting (ptid); check_for_thread_db (); + /* We have to create the entry breakpoint here because + if we have 'catch syscall' enabled, we ought to know + when to enable PTRACE_O_TRACESYSGOOD. Otherwise, we would + start catching syscalls from ld.so/libc (which is not + what we want). */ + create_entry_breakpoint (); } static int @@ -890,6 +970,19 @@ linux_child_insert_exec_catchpoint (int error (_("Your system does not support exec catchpoints.")); } +static void +linux_child_insert_syscall_catchpoint (int pid) +{ + if (! linux_supports_tracesysgood (pid)) + error (_("Your system does not support syscall catchpoints.")); +} + +static int +linux_child_remove_syscall_catchpoint (int pid) +{ + return 0; +} + /* On GNU/Linux there are no real LWP's. The closest thing to LWP's are processes sharing the same VM space. A multi-threaded process is basically a group of such processes. However, such a grouping @@ -1310,6 +1403,9 @@ linux_nat_create_inferior (char *exec_fi int personality_orig = 0, personality_set = 0; #endif /* HAVE_PERSONALITY */ + /* We are sarting, so we still have not passed through our entrypoint. */ + linux_passed_by_entrypoint_flag = 0; + /* The fork_child mechanism is synchronous and calls target_wait, so we have to mask the async mode. */ @@ -1940,6 +2036,27 @@ linux_handle_extended_wait (struct lwp_i return 0; } + /* Used for 'catch syscall' feature. */ + if (WSTOPSIG (status) == TRAP_IS_SYSCALL) + { + if (catch_syscall_enabled () == 0) + ourstatus->kind = TARGET_WAITKIND_IGNORE; + else + { + struct regcache *regcache = get_thread_regcache (lp->ptid); + struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct thread_info *th_info = find_thread_pid (lp->ptid); + + ourstatus->kind = + (th_info->syscall_state == TARGET_WAITKIND_SYSCALL_ENTRY) ? + TARGET_WAITKIND_SYSCALL_RETURN : TARGET_WAITKIND_SYSCALL_ENTRY; + th_info->syscall_state = ourstatus->kind; + ourstatus->value.syscall_number = + (int) gdbarch_get_syscall_number (gdbarch, lp->ptid); + } + return 0; + } + internal_error (__FILE__, __LINE__, _("unknown ptrace event %d"), event); } @@ -2550,11 +2667,16 @@ linux_nat_filter_event (int lwpid, int s } /* Save the trap's siginfo in case we need it later. */ - if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP) + if (WIFSTOPPED (status) + && (WSTOPSIG (status) == SIGTRAP || WSTOPSIG (status) == TRAP_IS_SYSCALL)) save_siginfo (lp); - /* Handle GNU/Linux's extended waitstatus for trace events. */ - if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0) + /* Handle GNU/Linux's extended waitstatus for trace events. + It is necessary to check if WSTOPSIG is signaling a that + the inferior is entering/exiting a system call. */ + if (WIFSTOPPED (status) + && ((WSTOPSIG (status) == TRAP_IS_SYSCALL) + || (WSTOPSIG (status) == SIGTRAP && status >> 16 != 0))) { if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, @@ -4000,6 +4122,8 @@ linux_target_install_ops (struct target_ t->to_insert_fork_catchpoint = linux_child_insert_fork_catchpoint; t->to_insert_vfork_catchpoint = linux_child_insert_vfork_catchpoint; t->to_insert_exec_catchpoint = linux_child_insert_exec_catchpoint; + t->to_insert_syscall_catchpoint = linux_child_insert_syscall_catchpoint; + t->to_remove_syscall_catchpoint = linux_child_remove_syscall_catchpoint; t->to_pid_to_exec_file = linux_child_pid_to_exec_file; t->to_post_startup_inferior = linux_child_post_startup_inferior; t->to_post_attach = linux_child_post_attach; @@ -4007,6 +4131,9 @@ linux_target_install_ops (struct target_ t->to_find_memory_regions = linux_nat_find_memory_regions; t->to_make_corefile_notes = linux_nat_make_corefile_notes; + t->to_enable_tracesysgood = linux_enable_tracesysgood; + t->to_passed_by_entrypoint = linux_passed_by_entrypoint; + super_xfer_partial = t->to_xfer_partial; t->to_xfer_partial = linux_xfer_partial; } Index: ppc-linux-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ppc-linux-tdep.c,v retrieving revision 1.107 diff -u -p -r1.107 ppc-linux-tdep.c --- ppc-linux-tdep.c 26 Aug 2008 15:16:41 -0000 1.107 +++ ppc-linux-tdep.c 1 Oct 2008 23:34:45 -0000 @@ -47,6 +47,142 @@ #include "features/rs6000/powerpc-vsx64l.c" #include "features/rs6000/powerpc-e500l.c" +/* Total number of syscalls */ +#define N_SYSCALLS 301 + +/* Syscalls names for PPC 32-bit */ +static const char *syscalls_names[] = { + "restart_syscall", "exit", "fork", "read", + "write", "open", "close", "waitpid", "creat", + "link", "unlink", "execve", "chdir", "time", + "mknod", "chmod", "lchown", "break", "oldstat", + "lseek", "getpid", "mount", "umount", "setuid", + "getuid", "stime", "ptrace", "alarm", "oldfstat", + "pause", "utime", "stty", "gtty", "access", "nice", + "ftime", "sync", "kill", "rename", "mkdir", "rmdir", + "dup", "pipe", "times", "prof", "brk", "setgid", + "getgid", "signal", "geteuid", "getegid", "acct", + "umount2", "lock", "ioctl", "fcntl", "mpx", "setpgid", + "ulimit", "oldolduname", "umask", "chroot", "ustat", + "dup2", "getppid", "getpgrp", "setsid", "sigaction", + "sgetmask", "ssetmask", "setreuid", "setregid", + "sigsuspend", "sigpending", "sethostname", "setrlimit", + "getrlimit", "getrusage", "gettimeofday", "settimeofday", + "getgroups", "setgroups", "select", "symlink", "oldlstat", + "readlink", "uselib", "swapon", "reboot", "readdir", + "mmap", "munmap", "truncate", "ftruncate", "fchmod", + "fchown", "getpriority", "setpriority", "profil", + "statfs", "fstatfs", "ioperm", "socketcall", "syslog", + "setitimer", "getitimer", "stat", "lstat", "fstat", + "olduname", "iopl", "vhangup", "idle", "vm86", "wait4", + "swapoff", "sysinfo", "ipc", "fsync", "sigreturn", + "clone", "setdomainname", "uname", "modify_ldt", + "adjtimex", "mprotect", "sigprocmask", "create_module", + "init_module", "delete_module", "get_kernel_syms", + "quotactl", "getpgid", "fchdir", "bdflush", "sysfs", + "personality", "afs_syscall", "setfsuid", "setfsgid", + "_llseek", "getdents", "_newselect", "flock", "msync", + "readv", "writev", "getsid", "fdatasync", "_sysctl", + "mlock", "munlock", "mlockall", "munlockall", + "sched_setparam", "sched_getparam", "sched_setscheduler", + "sched_getscheduler", "sched_yield", + "sched_get_priority_max", "sched_get_priority_min", + "sched_rr_get_interval", "nanosleep", "mremap", + "setresuid", "getresuid", "query_module", "poll", + "nfsservctl", "setresgid", "getresgid", "prctl", + "rt_sigreturn", "rt_sigaction", "rt_sigprocmask", + "rt_sigpending", "rt_sigtimedwait", "rt_sigqueueinfo", + "rt_sigsuspend", "pread64", "pwrite64", "chown", + "getcwd", "capget", "capset", "sigaltstack", "sendfile", + "getpmsg", "putpmsg", "vfork", "ugetrlimit", "readahead", + "mmap2", "truncate64", "ftruncate64", "stat64", "lstat64", + "fstat64", "pciconfig_read", "pciconfig_write", + "pciconfig_iobase", "multiplexer", "getdents64", + "pivot_root", "fcntl64", "madvise", "mincore", "gettid", + "tkill", "setxattr", "lsetxattr", "fsetxattr", + "getxattr", "lgetxattr", "fgetxattr", "listxattr", + "llistxattr", "flistxattr", "removexattr", "lremovexattr", + "fremovexattr", "futex", "sched_setaffinity", + "sched_getaffinity", "", "tuxcall", "sendfile64", + "io_setup", "io_destroy", "io_getevents", "io_submit", + "io_cancel", "set_tid_address", "fadvise64", "exit_group", + "lookup_dcookie", "epoll_create", "epoll_ctl", + "epoll_wait", "remap_file_pages", "timer_create", + "timer_settime", "timer_gettime", "timer_getoverrun", + "timer_delete", "clock_settime", "clock_gettime", + "clock_getres", "clock_nanosleep", "swapcontext", + "tgkill", "utimes", "statfs64", "fstatfs64", "fadvise64_64", + "rtas", "sys_debug_setcontext", "", "", "mbind", + "get_mempolicy", "set_mempolicy", "mq_open", "mq_unlink", + "mq_timedsend", "mq_timedreceive", "mq_notify", + "mq_getsetattr", "kexec_load", "add_key", "request_key", + "keyctl", "waitid", "ioprio_set", "ioprio_get", + "inotify_init", "inotify_add_watch", "inotify_rm_watch", + "spu_run", "spu_create", "pselect6", "ppoll", "unshare", + "", "", "", "openat", "mkdirat", "mknodat", "fchownat", + "futimesat", "fstatat64", "unlinkat", "renameat", + "linkat", "symlinkat", "readlinkat", "fchmodat", + "faccessat", "", "" +}; + +/* Syscalls names for PPC 64-bit */ +static const char *syscalls_names64[] = { + "restart_syscall", "exit", "fork", "read", "write", "open", + "close", "waitpid", "creat", "link", "unlink", "execve", + "chdir", "time", "mknod", "chmod", "lchown", "break", "oldstat", + "lseek", "getpid", "mount", "umount", "setuid", "getuid", "stime", + "ptrace", "alarm", "oldfstat", "pause", "utime", "stty", "gtty", + "access", "nice", "ftime", "sync", "kill", "rename", "mkdir", + "rmdir", "dup", "pipe", "times", "prof", "brk", "setgid", + "getgid", "signal", "geteuid", "getegid", "acct", "umount2", + "lock", "ioctl", "fcntl", "mpx", "setpgid", "ulimit", + "oldolduname", "umask", "chroot", "ustat", "dup2", "getppid", + "getpgrp", "setsid", "sigaction", "sgetmask", "ssetmask", + "setreuid", "setregid", "sigsuspend", "sigpending", "sethostname", + "setrlimit", "getrlimit", "getrusage", "gettimeofday", "settimeofday", + "getgroups", "setgroups", "select", "symlink", "oldlstat", + "readlink", "uselib", "swapon", "reboot", "readdir", "mmap", + "munmap", "truncate", "ftruncate", "fchmod", "fchown", "getpriority", + "setpriority", "profil", "statfs", "fstatfs", "ioperm", "socketcall", + "syslog", "setitimer", "getitimer", "stat", "lstat", "fstat", + "olduname", "iopl", "vhangup", "idle", "vm86", "wait4", "swapoff", + "sysinfo", "ipc", "fsync", "sigreturn", "clone", "setdomainname", + "uname", "modify_ldt", "adjtimex", "mprotect", "sigprocmask", + "create_module", "init_module", "delete_module", "get_kernel_syms", + "quotactl", "getpgid", "fchdir", "bdflush", "sysfs", "personality", + "afs_syscall", "setfsuid", "setfsgid", "_llseek", "getdents", + "_newselect", "flock", "msync", "readv", "writev", "getsid", + "fdatasync", "_sysctl", "mlock", "munlock", "mlockall", + "munlockall", "sched_setparam", "sched_getparam", "sched_setscheduler", + "sched_getscheduler", "sched_yield", "sched_get_priority_max", + "sched_get_priority_min", "sched_rr_get_interval", "nanosleep", + "mremap", "setresuid", "getresuid", "query_module", "poll", + "nfsservctl", "setresgid", "getresgid", "prctl", "rt_sigreturn", + "rt_sigaction", "rt_sigprocmask", "rt_sigpending", "rt_sigtimedwait", + "rt_sigqueueinfo", "rt_sigsuspend", "pread64", "pwrite64", "chown", + "getcwd", "capget", "capset", "sigaltstack", "sendfile", "getpmsg", + "putpmsg", "vfork", "ugetrlimit", "readahead", "", "", "", "", "", "", + "pciconfig_read", "pciconfig_write", "pciconfig_iobase", "multiplexer", + "getdents64", "pivot_root", "", "madvise", "mincore", "gettid", "tkill", + "setxattr", "lsetxattr", "fsetxattr", "getxattr", "lgetxattr", "fgetxattr", + "listxattr", "llistxattr", "flistxattr", "removexattr", "lremovexattr", + "fremovexattr", "futex", "sched_setaffinity", "sched_getaffinity", + "", "tuxcall", "", "io_setup", "io_destroy", "io_getevents", "io_submit", + "io_cancel", "set_tid_address", "fadvise64", "exit_group", "lookup_dcookie", + "epoll_create", "epoll_ctl", "epoll_wait", "remap_file_pages", + "timer_create", "timer_settime", "timer_gettime", "timer_getoverrun", + "timer_delete", "clock_settime", "clock_gettime", "clock_getres", + "clock_nanosleep", "swapcontext", "tgkill", "utimes", "statfs64", + "fstatfs64", "", "rtas", "sys_debug_setcontext", "", "", "mbind", + "get_mempolicy", "set_mempolicy", "mq_open", "mq_unlink", "mq_timedsend", + "mq_timedreceive", "mq_notify", "mq_getsetattr", "kexec_load", "add_key", + "request_key", "keyctl", "waitid", "ioprio_set", "ioprio_get", + "inotify_init", "inotify_add_watch", "inotify_rm_watch", "spu_run", + "spu_create", "pselect6", "ppoll", "unshare", "", "", "", + "openat", "mkdirat", "mknodat", "fchownat", "futimesat", "newfstatat", + "unlinkat", "renameat", "linkat", "symlinkat", "readlinkat", + "fchmodat", "faccessat", "", "" +}; /* ppc_linux_memory_remove_breakpoints attempts to remove a breakpoint in much the same fashion as memory_remove_breakpoint in mem-break.c, @@ -1003,6 +1139,83 @@ ppc_linux_trap_reg_p (struct gdbarch *gd && register_size (gdbarch, PPC_TRAP_REGNUM) > 0; } +/* Return the current system call's number present in the + r0 register. When the function fails, it returns -1. */ +LONGEST +ppc_linux_get_syscall_number (struct gdbarch *gdbarch, + ptid_t ptid) +{ + struct regcache *regcache = get_thread_regcache (ptid); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + /* The content of a register */ + gdb_byte *buf; + /* The result */ + LONGEST ret; + + /* Make sure we're in a 32- or 64-bit machine */ + gdb_assert (tdep->wordsize == 4 || tdep->wordsize == 8); + + buf = (gdb_byte *) xmalloc (tdep->wordsize * sizeof (gdb_byte)); + + /* Getting the system call number from the register. + When dealing with PowerPC architecture, this information + is stored at 0th register. */ + regcache_cooked_read (regcache, tdep->ppc_gp0_regnum, buf); + + ret = extract_signed_integer (buf, tdep->wordsize); + xfree (buf); + + return ret; +} + +const char * +ppc_linux_syscall_name_from_number (struct gdbarch *gdbarch, + int syscall_number) +{ + if (syscall_number < 0 + || syscall_number >= N_SYSCALLS) + return NULL; + + return syscalls_names[syscall_number]; +} + +const char * +ppc64_linux_syscall_name_from_number (struct gdbarch *gdbarch, + int syscall_number) +{ + if (syscall_number < 0 + || syscall_number >= N_SYSCALLS) + return NULL; + + return syscalls_names64[syscall_number]; +} + +int +ppc_linux_syscall_number_from_name (struct gdbarch *gdbarch, + const char *syscall_name) +{ + int i; + + for (i = 0; i < N_SYSCALLS; i++) + if (strcmp (syscall_name, syscalls_names[i]) == 0) + return i; + + return UNKNOWN_SYSCALL; +} + +int +ppc64_linux_syscall_number_from_name (struct gdbarch *gdbarch, + const char *syscall_name) +{ + int i; + + for (i = 0; i < N_SYSCALLS; i++) + if (strcmp (syscall_name, syscalls_names64[i]) == 0) + return i; + + return UNKNOWN_SYSCALL; +} + static void ppc_linux_write_pc (struct regcache *regcache, CORE_ADDR pc) { @@ -1074,8 +1287,13 @@ ppc_linux_init_abi (struct gdbarch_info /* Handle inferior calls during interrupted system calls. */ set_gdbarch_write_pc (gdbarch, ppc_linux_write_pc); + set_gdbarch_get_syscall_number (gdbarch, ppc_linux_get_syscall_number); + if (tdep->wordsize == 4) { + set_gdbarch_syscall_name_from_number (gdbarch, ppc_linux_syscall_name_from_number); + set_gdbarch_syscall_number_from_name (gdbarch, ppc_linux_syscall_number_from_name); + /* Until November 2001, gcc did not comply with the 32 bit SysV R4 ABI requirement that structures less than or equal to 8 bytes should be returned in registers. Instead GCC was using @@ -1100,6 +1318,9 @@ ppc_linux_init_abi (struct gdbarch_info if (tdep->wordsize == 8) { + set_gdbarch_syscall_name_from_number (gdbarch, ppc64_linux_syscall_name_from_number); + set_gdbarch_syscall_number_from_name (gdbarch, ppc64_linux_syscall_number_from_name); + /* Handle PPC GNU/Linux 64-bit function pointers (which are really function descriptors). */ set_gdbarch_convert_from_func_ptr_addr --------------040706010100030701000506 Content-Type: text/x-log; name="gdb.log" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="gdb.log" Content-length: 15294 Test Run By msnyder on Wed Oct 1 16:42:57 2008 Native configuration is i686-pc-linux-gnu === gdb tests === Schedule of variations: unix Running target unix Using /usr/share/dejagnu/baseboards/unix.exp as board description file for target. Using /usr/share/dejagnu/config/unix.exp as generic interface file for target. Using /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/config/unix.exp as tool-and-target-specific interface file. Running /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.exp ... Executing on host: gcc /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c -g -lm -o /misc/home/msnyder/build/native/src-current/gdb/testsuite/gdb.base/catch-syscall (timeout = 300) GNU gdb (GDB) 6.8.50.20081001-cvs Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i686-pc-linux-gnu". For bug reporting instructions, please see: . (gdb) set height 0 (gdb) set width 0 (gdb) dir Reinitialize source path to empty? (y or n) y Source directories searched: $cdir:$cwd (gdb) dir /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base Source directories searched: /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base:$cdir:$cwd (gdb) kill The program is not being run. (gdb) file /misc/home/msnyder/build/native/src-current/gdb/testsuite/gdb.base/catch-syscall Reading symbols from /misc/home/msnyder/build/native/src-current/gdb/testsuite/gdb.base/catch-syscall...done. (gdb) help catch syscall Catch calls to syscalls. With an argument, catch only calls of that syscall. (gdb) PASS: gdb.base/catch-syscall.exp: help catch syscall catch syscall nonsense_syscall /misc/home/msnyder/cvs/localhost/src-current/gdb/gdbarch.c:3326: internal-error: gdbarch_syscall_number_from_name: Assertion `gdbarch->syscall_number_from_name != NULL' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. Quit this debugging session? (y or n) FAIL: gdb.base/catch-syscall.exp: catch syscall to a nonsense syscall is prohibited (GDB internal error) n /misc/home/msnyder/cvs/localhost/src-current/gdb/gdbarch.c:3326: internal-error: gdbarch_syscall_number_from_name: Assertion `gdbarch->syscall_number_from_name != NULL' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. Create a core file of GDB? (y or n) n (gdb) delete breakpoints (gdb) info breakpoints No breakpoints or watchpoints. (gdb) break main Breakpoint 1 at 0x80483f8: file /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c, line 19. (gdb) run Starting program: /misc/home/msnyder/build/native/src-current/gdb/testsuite/gdb.base/catch-syscall Breakpoint 1, main () at /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c:19 19 close (-1); (gdb) catch syscall Catchpoint 2 (syscall) (gdb) PASS: gdb.base/catch-syscall.exp: setting catch syscall without arguments info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y 0x080483f8 in main at /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c:19 breakpoint already hit 1 time 2 catch syscall keep y syscall "" (gdb) PASS: gdb.base/catch-syscall.exp: catch syscall appears in 'info breakpoints' continue Continuing. Program exited normally. (gdb) FAIL: gdb.base/catch-syscall.exp: program has called 'close' info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y 0x080483f8 in main at /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c:19 breakpoint already hit 1 time 2 catch syscall keep y syscall "" (gdb) FAIL: gdb.base/catch-syscall.exp: syscall 'close' appears in 'info breakpoints' continue The program is not being run. (gdb) FAIL: gdb.base/catch-syscall.exp: syscall 'close' has returned (the program is no longer running) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y 0x080483f8 in main at /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c:19 breakpoint already hit 1 time 2 catch syscall keep y syscall "" (gdb) FAIL: gdb.base/catch-syscall.exp: syscall 'close' appears in 'info breakpoints' continue The program is not being run. (gdb) FAIL: gdb.base/catch-syscall.exp: program has called 'chroot' (the program is no longer running) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y 0x080483f8 in main at /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c:19 breakpoint already hit 1 time 2 catch syscall keep y syscall "" (gdb) FAIL: gdb.base/catch-syscall.exp: syscall 'chroot' appears in 'info breakpoints' continue The program is not being run. (gdb) FAIL: gdb.base/catch-syscall.exp: syscall 'chroot' has returned (the program is no longer running) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y 0x080483f8 in main at /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c:19 breakpoint already hit 1 time 2 catch syscall keep y syscall "" (gdb) FAIL: gdb.base/catch-syscall.exp: syscall 'chroot' appears in 'info breakpoints' continue The program is not being run. (gdb) FAIL: gdb.base/catch-syscall.exp: program has called 'exit_group' (the program is no longer running) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y 0x080483f8 in main at /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c:19 breakpoint already hit 1 time 2 catch syscall keep y syscall "" (gdb) FAIL: gdb.base/catch-syscall.exp: syscall 'exit_group' appears in 'info breakpoints' delete breakpoints Delete all breakpoints? (y or n) y (gdb) info breakpoints No breakpoints or watchpoints. (gdb) continue The program is not being run. (gdb) FAIL: gdb.base/catch-syscall.exp: successful program end (the program is no longer running) delete breakpoints (gdb) info breakpoints No breakpoints or watchpoints. (gdb) break main Breakpoint 3 at 0x80483f8: file /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c, line 19. (gdb) run Starting program: /misc/home/msnyder/build/native/src-current/gdb/testsuite/gdb.base/catch-syscall Breakpoint 3, main () at /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c:19 19 close (-1); (gdb) catch syscall close /misc/home/msnyder/cvs/localhost/src-current/gdb/gdbarch.c:3326: internal-error: gdbarch_syscall_number_from_name: Assertion `gdbarch->syscall_number_from_name != NULL' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. Quit this debugging session? (y or n) FAIL: gdb.base/catch-syscall.exp: catch syscall with arguments (close) (GDB internal error) n /misc/home/msnyder/cvs/localhost/src-current/gdb/gdbarch.c:3326: internal-error: gdbarch_syscall_number_from_name: Assertion `gdbarch->syscall_number_from_name != NULL' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. Create a core file of GDB? (y or n) n (gdb) info breakpoints Num Type Disp Enb Address What 3 breakpoint keep y 0x080483f8 in main at /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c:19 breakpoint already hit 1 time (gdb) FAIL: gdb.base/catch-syscall.exp: catch syscall appears in 'info breakpoints' continue Continuing. Program exited normally. (gdb) FAIL: gdb.base/catch-syscall.exp: program has called 'close' info breakpoints Num Type Disp Enb Address What 3 breakpoint keep y 0x080483f8 in main at /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c:19 breakpoint already hit 1 time (gdb) FAIL: gdb.base/catch-syscall.exp: syscall 'close' appears in 'info breakpoints' continue The program is not being run. (gdb) FAIL: gdb.base/catch-syscall.exp: syscall 'close' has returned (the program is no longer running) info breakpoints Num Type Disp Enb Address What 3 breakpoint keep y 0x080483f8 in main at /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c:19 breakpoint already hit 1 time (gdb) FAIL: gdb.base/catch-syscall.exp: syscall 'close' appears in 'info breakpoints' delete breakpoints Delete all breakpoints? (y or n) y (gdb) info breakpoints No breakpoints or watchpoints. (gdb) continue The program is not being run. (gdb) FAIL: gdb.base/catch-syscall.exp: successful program end (the program is no longer running) delete breakpoints (gdb) info breakpoints No breakpoints or watchpoints. (gdb) break main Breakpoint 4 at 0x80483f8: file /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c, line 19. (gdb) run Starting program: /misc/home/msnyder/build/native/src-current/gdb/testsuite/gdb.base/catch-syscall Breakpoint 4, main () at /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c:19 19 close (-1); (gdb) catch syscall mlock /misc/home/msnyder/cvs/localhost/src-current/gdb/gdbarch.c:3326: internal-error: gdbarch_syscall_number_from_name: Assertion `gdbarch->syscall_number_from_name != NULL' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. Quit this debugging session? (y or n) FAIL: gdb.base/catch-syscall.exp: catch syscall with arguments (mlock) (GDB internal error) n /misc/home/msnyder/cvs/localhost/src-current/gdb/gdbarch.c:3326: internal-error: gdbarch_syscall_number_from_name: Assertion `gdbarch->syscall_number_from_name != NULL' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. Create a core file of GDB? (y or n) n (gdb) info breakpoints Num Type Disp Enb Address What 4 breakpoint keep y 0x080483f8 in main at /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c:19 breakpoint already hit 1 time (gdb) FAIL: gdb.base/catch-syscall.exp: catch syscall appears in 'info breakpoints' continue Continuing. Program exited normally. (gdb) PASS: gdb.base/catch-syscall.exp: catch syscall with unused syscall (mlock) delete breakpoints Delete all breakpoints? (y or n) y (gdb) info breakpoints No breakpoints or watchpoints. (gdb) break main Breakpoint 5 at 0x80483f8: file /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c, line 19. (gdb) run Starting program: /misc/home/msnyder/build/native/src-current/gdb/testsuite/gdb.base/catch-syscall Breakpoint 5, main () at /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c:19 19 close (-1); (gdb) catch syscall chroot /misc/home/msnyder/cvs/localhost/src-current/gdb/gdbarch.c:3326: internal-error: gdbarch_syscall_number_from_name: Assertion `gdbarch->syscall_number_from_name != NULL' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. Quit this debugging session? (y or n) FAIL: gdb.base/catch-syscall.exp: catch syscall with arguments (chroot) (GDB internal error) n /misc/home/msnyder/cvs/localhost/src-current/gdb/gdbarch.c:3326: internal-error: gdbarch_syscall_number_from_name: Assertion `gdbarch->syscall_number_from_name != NULL' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. Create a core file of GDB? (y or n) n (gdb) info breakpoints Num Type Disp Enb Address What 5 breakpoint keep y 0x080483f8 in main at /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c:19 breakpoint already hit 1 time (gdb) FAIL: gdb.base/catch-syscall.exp: catch syscall appears in 'info breakpoints' continue Continuing. Program exited normally. (gdb) FAIL: gdb.base/catch-syscall.exp: program has called 'chroot' info breakpoints Num Type Disp Enb Address What 5 breakpoint keep y 0x080483f8 in main at /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c:19 breakpoint already hit 1 time (gdb) FAIL: gdb.base/catch-syscall.exp: syscall 'chroot' appears in 'info breakpoints' run Starting program: /misc/home/msnyder/build/native/src-current/gdb/testsuite/gdb.base/catch-syscall Breakpoint 5, main () at /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c:19 19 close (-1); (gdb) PASS: gdb.base/catch-syscall.exp: rerun to main continue Continuing. Program exited normally. (gdb) FAIL: gdb.base/catch-syscall.exp: program has called 'chroot' info breakpoints Num Type Disp Enb Address What 5 breakpoint keep y 0x080483f8 in main at /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c:19 breakpoint already hit 1 time (gdb) FAIL: gdb.base/catch-syscall.exp: syscall 'chroot' appears in 'info breakpoints' continue The program is not being run. (gdb) FAIL: gdb.base/catch-syscall.exp: syscall 'chroot' has returned (the program is no longer running) info breakpoints Num Type Disp Enb Address What 5 breakpoint keep y 0x080483f8 in main at /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.c:19 breakpoint already hit 1 time (gdb) FAIL: gdb.base/catch-syscall.exp: syscall 'chroot' appears in 'info breakpoints' delete breakpoints Delete all breakpoints? (y or n) y (gdb) info breakpoints No breakpoints or watchpoints. (gdb) continue The program is not being run. (gdb) FAIL: gdb.base/catch-syscall.exp: successful program end (the program is no longer running) testcase /misc/home/msnyder/cvs/localhost/src-current/gdb/testsuite/gdb.base/catch-syscall.exp completed in 0 seconds === gdb Summary === # of expected passes 5 # of unexpected failures 30 Executing on host: /misc/home/msnyder/build/native/src-current/gdb/testsuite/../../gdb/gdb -nw --command gdb_cmd (timeout = 300) GNU gdb (GDB) 6.8.50.20081001-cvs Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i686-pc-linux-gnu". For bug reporting instructions, please see: . /misc/home/msnyder/build/native/src-current/gdb/testsuite/../../gdb/gdb version 6.8.50.20081001-cvs -nx runtest completed at Wed Oct 1 16:42:58 2008 --------------040706010100030701000506--