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: [PATCH 0/4] catch syscall -- try 4 -- Introduction


Hi,

I got some error when I try to patch these patches to cvs-head.

So I update them.  They just for try.  If you need official version,
you still need mail to Sérgio.  :)

Thanks,
Hui

On Mon, Jan 26, 2009 at 08:30, Sérgio Durigan Júnior
<sergiodj@linux.vnet.ibm.com> wrote:
> Hello everybody,
>
> It's been a while since I don't post anything related to this patch, so
> I apologize. I've been busy with some other activities, so I had to use
> my spare time to work on this now.
>
> Here goes the fourth version of the catch syscall patch. For those of
> you who have been following the improvements, there's not so much to see
> in this version if you compare it to the previous one; even though, it's
> worth taking a look at it because there are lots of bug fixes (the vast
> majority were fixed by Jan K. , to whom I'd like to give my special
> thanks). The basic functionality remains the same.
>
> Many thanks to Jan K., Phil Muldoon, Rick Moseley and Tom Tromey for
> dedicating their time to this activity. Also, thanks to teawater and
> Daniel Jacobowitz for bringing this patch back to discussion.
>
> The division of the patch is basically the same: the first part contains
> architecture-independent code; the second contains
> architecture-dependent; the third is for the XML support code; and the
> fourth contains code for the build system, testacase and documentation.
> Please, apply all four patches in order to have GDB compiled correctly.
>
> Please, comment, test and review.
>
> Regards,
>
> --
> Sérgio Durigan Júnior
> Linux on Power Toolchain - Software Engineer
> Linux Technology Center - LTC
> IBM Brazil
>
>
---
 gdb/i386-linux-nat.c  |    8 ++-
 gdb/i386-linux-tdep.c |   32 ++++++++++++
 gdb/linux-nat.c       |  129 ++++++++++++++++++++++++++++++++++++++++++++++----
 gdb/linux-nat.h       |    7 ++
 gdb/linux-tdep.c      |   95 ++++++++++++++++++++++++++++++++++++
 gdb/linux-tdep.h      |    2 
 gdb/ppc-linux-tdep.c  |   48 ++++++++++++++++++
 7 files changed, 312 insertions(+), 9 deletions(-)

--- a/gdb/i386-linux-nat.c
+++ b/gdb/i386-linux-nat.c
@@ -748,7 +748,13 @@ i386_linux_resume (ptid_t ptid, int step
 {
   int pid = PIDGET (ptid);
 
-  int request = PTRACE_CONT;
+  int request;
+
+  if (target_passed_by_entrypoint () > 0
+      && catch_syscall_enabled () > 0)
+   request = PTRACE_SYSCALL;
+  else
+    request = PTRACE_CONT;
 
   if (step)
     {
--- a/gdb/i386-linux-tdep.c
+++ b/gdb/i386-linux-tdep.c
@@ -37,6 +37,10 @@
 #include "symtab.h"
 #include "arch-utils.h"
 #include "regset.h"
+#include "linux-tdep.h"
+
+/* The syscall's XML filename for i386.  */
+#define XML_SYSCALL_FILENAME_I386 "syscalls/i386-linux.xml"
 
 /* Supported register note sections.  */
 static struct core_regset_section i386_linux_regset_sections[] =
@@ -349,6 +353,26 @@ i386_linux_write_pc (struct regcache *re
 }
 
 
+static LONGEST
+i386_linux_get_syscall_number (struct gdbarch *gdbarch,
+                               ptid_t ptid)
+{
+  struct regcache *regcache = get_thread_regcache (ptid);
+  /* The content of a register.  */
+  gdb_byte buf[4];
+  /* The result.  */
+  LONGEST ret;
+
+  /* Getting the system call number from the register.
+     When dealing with x86 architecture, this information
+     is stored at %eax register.  */
+  regcache_cooked_read (regcache, I386_LINUX_ORIG_EAX_REGNUM, buf);
+
+  ret = extract_signed_integer (buf, 4);
+
+  return ret;
+}
+
 /* The register sets used in GNU/Linux ELF core-dumps are identical to
    the register sets in `struct user' that are used for a.out
    core-dumps.  These are also used by ptrace(2).  The corresponding
@@ -419,6 +443,9 @@ i386_linux_init_abi (struct gdbarch_info
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
+  /* Initializing common functions.  */
+  linux_tdep_init (gdbarch);
+
   /* GNU/Linux uses ELF.  */
   i386_elf_init_abi (info, gdbarch);
 
@@ -471,6 +498,11 @@ i386_linux_init_abi (struct gdbarch_info
   set_gdbarch_displaced_step_location (gdbarch,
                                        displaced_step_at_entry_point);
 
+  /* Functions for 'catch syscall'.  */
+  set_gdbarch_xml_syscall_filename (gdbarch, XML_SYSCALL_FILENAME_I386);
+  set_gdbarch_get_syscall_number (gdbarch,
+                                  i386_linux_get_syscall_number);
+
   set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
 }
 
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -61,6 +61,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
@@ -281,17 +285,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 };
@@ -636,6 +652,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.  */
 
@@ -655,12 +706,34 @@ linux_supports_tracevforkdone (int pid)
   return linux_supports_tracevforkdone_flag;
 }
 
+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);
@@ -668,15 +741,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
@@ -933,6 +1007,16 @@ linux_child_insert_exec_catchpoint (int 
     error (_("Your system does not support exec catchpoints."));
 }
 
+static int
+linux_child_set_syscall_catchpoint (int pid, int needed, int any_count,
+				    int table_size, int *table)
+{
+  if (! linux_supports_tracesysgood (pid))
+    error (_("Your system does not support syscall catchpoints."));
+  /* We ignore the arguments.  */
+  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
@@ -1354,6 +1438,9 @@ linux_nat_create_inferior (struct target
   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.  */
 
@@ -1996,6 +2083,26 @@ 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);
+
+          ourstatus->kind =
+            (lp->syscall_state == TARGET_WAITKIND_SYSCALL_ENTRY) ?
+            TARGET_WAITKIND_SYSCALL_RETURN : TARGET_WAITKIND_SYSCALL_ENTRY;
+          lp->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);
 }
@@ -2606,11 +2713,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,
@@ -4256,6 +4368,7 @@ 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_set_syscall_catchpoint = linux_child_set_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;
--- a/gdb/linux-nat.h
+++ b/gdb/linux-nat.h
@@ -70,6 +70,13 @@ struct lwp_info
      or to a local variable in lin_lwp_wait.  */
   struct target_waitstatus waitstatus;
 
+  /* Signal wether we are in a SYSCALL_ENTRY or
+     in a SYSCALL_RETURN event.
+     Values:
+     - TARGET_WAITKIND_SYSCALL_ENTRY
+     - TARGET_WAITKIND_SYSCALL_RETURN */
+  int syscall_state;
+
   /* Next LWP in list.  */
   struct lwp_info *next;
 };
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -19,6 +19,23 @@
 
 #include "defs.h"
 #include "gdbtypes.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "regcache.h"
+#include "value.h"
+#include "osabi.h"
+#include "regset.h"
+#include "solib-svr4.h"
+#include "trad-frame.h"
+#include "frame-unwind.h"
+#include "tramp-frame.h"
+#include "xml-syscall.h"
 
 /* This function is suitable for architectures that don't
    extend/override the standard siginfo structure.  */
@@ -136,3 +153,81 @@ linux_get_siginfo_type (struct gdbarch *
 
   return siginfo_type;
 }
+
+/* Structure used to store information about the available syscalls in
+   the system.  */
+static const struct syscalls_info *sysinfo = NULL;
+
+/* A flag to tell if we already initialized the structure above.  */
+static int have_initialized_sysinfo = 0;
+
+/* The filename of the syscall's XML.  */
+static const char *xml_syscall_file = NULL;
+
+/* Initializes the syscalls_info structure according to the
+   architecture.  */
+static void
+init_sysinfo (struct gdbarch *gdbarch)
+{
+  /* Did we already try to initialize the structure?  */
+  if (have_initialized_sysinfo)
+    return;
+
+  if (xml_syscall_file == NULL)
+    xml_syscall_file = gdbarch_xml_syscall_filename (gdbarch);
+
+  sysinfo = xml_init_syscalls_info (xml_syscall_file);
+
+  have_initialized_sysinfo = 1;
+
+  if (sysinfo == NULL)
+    {
+      if (xml_syscall_file)
+        /* The initialization failed.  Let's show a warning
+           message to the user (just this time) and leave.  */
+        warning (_("Could not load the syscall XML file '%s'.\n\
+GDB will not be able to display syscall names."), xml_syscall_file);
+      else
+        /* There's no file to open. Let's warn the user.  */
+        warning (_("There is no XML file to open.\n\
+GDB will not be able to display syscall names."));
+    }
+}
+
+static void
+linux_get_syscall_by_number (struct gdbarch *gdbarch,
+                             int syscall_number,
+                             struct syscall *s)
+{
+  init_sysinfo (gdbarch);
+
+  s->number = syscall_number;
+  s->name = xml_get_syscall_name (sysinfo, syscall_number);
+}
+
+static void
+linux_get_syscall_by_name (struct gdbarch *gdbarch,
+                           const char *syscall_name,
+                           struct syscall *s)
+{
+  init_sysinfo (gdbarch);
+
+  s->number = xml_get_syscall_number (sysinfo, syscall_name);
+  s->name = syscall_name;
+}
+
+static const char **
+linux_get_syscall_names (struct gdbarch *gdbarch)
+{
+  init_sysinfo (gdbarch);
+
+  return xml_list_of_syscalls (sysinfo);
+}
+
+void
+linux_tdep_init (struct gdbarch *gdbarch)
+{
+  set_gdbarch_get_syscall_by_number (gdbarch, linux_get_syscall_by_number);
+  set_gdbarch_get_syscall_by_name (gdbarch, linux_get_syscall_by_name);
+  set_gdbarch_get_syscall_names (gdbarch, linux_get_syscall_names);
+}
--- a/gdb/linux-tdep.h
+++ b/gdb/linux-tdep.h
@@ -22,4 +22,6 @@
 
 struct type *linux_get_siginfo_type (struct gdbarch *);
 
+extern void linux_tdep_init (struct gdbarch *gdbarch);
+
 #endif /* linux-tdep.h */
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -38,6 +38,7 @@
 #include "trad-frame.h"
 #include "frame-unwind.h"
 #include "tramp-frame.h"
+#include "linux-tdep.h"
 
 #include "features/rs6000/powerpc-32l.c"
 #include "features/rs6000/powerpc-altivec32l.c"
@@ -53,6 +54,9 @@
 #include "features/rs6000/powerpc-isa205-vsx64l.c"
 #include "features/rs6000/powerpc-e500l.c"
 
+/* The syscall's XML filename for PPC and PPC64.  */
+#define XML_SYSCALL_FILENAME_PPC "syscalls/ppc-linux.xml"
+#define XML_SYSCALL_FILENAME_PPC64 "syscalls/ppc64-linux.xml"
 
 /* ppc_linux_memory_remove_breakpoints attempts to remove a breakpoint
    in much the same fashion as memory_remove_breakpoint in mem-break.c,
@@ -1009,6 +1013,38 @@ 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.  */
+static 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);
+  struct cleanup *cleanbuf;
+  /* 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));
+
+  cleanbuf = make_cleanup (xfree, buf);
+
+  /* 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);
+  do_cleanups (cleanbuf);
+
+  return ret;
+}
+
 static void
 ppc_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
 {
@@ -1069,6 +1105,9 @@ ppc_linux_init_abi (struct gdbarch_info 
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info;
 
+  /* Initializing common methods.  */
+  linux_tdep_init (gdbarch);
+
   /* PPC GNU/Linux uses either 64-bit or 128-bit long doubles; where
      128-bit, they are IBM long double, not IEEE quad long double as
      in the System V ABI PowerPC Processor Supplement.  We can safely
@@ -1080,6 +1119,9 @@ ppc_linux_init_abi (struct gdbarch_info 
   /* Handle inferior calls during interrupted system calls.  */
   set_gdbarch_write_pc (gdbarch, ppc_linux_write_pc);
 
+  /* Get the syscall number from the arch's register.  */
+  set_gdbarch_get_syscall_number (gdbarch, ppc_linux_get_syscall_number);
+
   if (tdep->wordsize == 4)
     {
       /* Until November 2001, gcc did not comply with the 32 bit SysV
@@ -1099,6 +1141,9 @@ ppc_linux_init_abi (struct gdbarch_info 
       set_solib_svr4_fetch_link_map_offsets
         (gdbarch, svr4_ilp32_fetch_link_map_offsets);
 
+      /* Setting the correct XML syscall filename.  */
+      set_gdbarch_xml_syscall_filename (gdbarch, XML_SYSCALL_FILENAME_PPC);
+
       /* Trampolines.  */
       tramp_frame_prepend_unwinder (gdbarch, &ppc32_linux_sigaction_tramp_frame);
       tramp_frame_prepend_unwinder (gdbarch, &ppc32_linux_sighandler_tramp_frame);
@@ -1116,6 +1161,9 @@ ppc_linux_init_abi (struct gdbarch_info 
       set_solib_svr4_fetch_link_map_offsets
         (gdbarch, svr4_lp64_fetch_link_map_offsets);
 
+      /* Setting the correct XML syscall filename.  */
+      set_gdbarch_xml_syscall_filename (gdbarch, XML_SYSCALL_FILENAME_PPC64);
+
       /* Trampolines.  */
       tramp_frame_prepend_unwinder (gdbarch, &ppc64_linux_sigaction_tramp_frame);
       tramp_frame_prepend_unwinder (gdbarch, &ppc64_linux_sighandler_tramp_frame);
---
 gdb/breakpoint.c |  476 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 gdb/breakpoint.h |   39 ++++
 gdb/defs.h       |    3 
 gdb/gdbarch.c    |  155 +++++++++++++++++
 gdb/gdbarch.h    |   45 +++++
 gdb/gdbarch.sh   |   24 ++
 gdb/inf-child.c  |   10 +
 gdb/inf-ptrace.c |    8 
 gdb/infcmd.c     |    5 
 gdb/infrun.c     |   87 +++++++++-
 gdb/linux-nat.c  |    3 
 gdb/main.c       |   37 ++++
 gdb/maint.c      |    8 
 gdb/target.c     |    8 
 gdb/target.h     |   38 ++++
 15 files changed, 929 insertions(+), 17 deletions(-)

--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -191,6 +191,8 @@ static int is_hardware_watchpoint (struc
 
 static void insert_breakpoint_locations (void);
 
+static int syscall_catchpoint_p (struct breakpoint *b);
+
 static const char *
 bpdisp_text (enum bpdisp disp)
 {
@@ -341,6 +343,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 (syscall_catchpoint_p (b))
+      b->syscall_number = UNKNOWN_SYSCALL;
+}
+
 /* Used in run_command to zero the hit count when a new run starts. */
 
 void
@@ -4134,6 +4148,8 @@ set_raw_breakpoint_without_location (enu
   b->frame_id = null_frame_id;
   b->forked_inferior_pid = null_ptid;
   b->exec_pathname = NULL;
+  b->syscalls_to_be_caught = NULL;
+  b->syscall_number = UNKNOWN_SYSCALL;
   b->ops = NULL;
   b->condition_not_parsed = 0;
 
@@ -4653,7 +4669,238 @@ static struct breakpoint_ops catch_vfork
   print_mention_catch_vfork
 };
 
-/* Create a new breakpoint of the bp_catchpoint kind and return it.
+/* We keep a count of the number of times the user has requested a
+   particular syscall to be tracked, and pass this information to the
+   target.  This lets capable targets implement filtering directly.  */
+
+/* Number of times that "any" syscall is requested.  */
+static int any_syscall_count;
+
+/* Count of each system call.  */
+static int *syscalls_counts;
+
+/* Number of system entries in SYSCALLS_COUNTS.  */
+static int syscalls_size;
+
+/* This counts all syscall catch requests, so we can readily determine
+   if any catching is necessary.  */
+static int total_syscalls_count;
+
+/* Implement the "insert" breakpoint_ops method for syscall
+   catchpoints.  */
+
+static void
+insert_catch_syscall (struct breakpoint *b)
+{
+  ++total_syscalls_count;
+  if (!b->syscalls_to_be_caught)
+    ++any_syscall_count;
+  else
+    {
+      struct syscall_filter *iter;
+      for (iter = b->syscalls_to_be_caught; iter; iter = iter->next)
+	{
+	  if (iter->syscall >= syscalls_size)
+	    {
+	      syscalls_counts = xrealloc (syscalls_counts,
+					  (iter->syscall + 1) * sizeof (int));
+	      memset (&syscalls_counts[syscalls_size], 0,
+		      (iter->syscall + 1 - syscalls_size) * sizeof (int));
+	    }
+	  ++syscalls_counts[iter->syscall];
+	}
+    }
+
+  target_set_syscall_catchpoint (PIDGET (inferior_ptid),
+				 total_syscalls_count != 0,
+				 any_syscall_count,
+				 syscalls_size,
+				 syscalls_counts);
+}
+
+/* Implement the "remove" breakpoint_ops method for syscall
+   catchpoints.  */
+
+static int
+remove_catch_syscall (struct breakpoint *b)
+{
+  --total_syscalls_count;
+  if (!b->syscalls_to_be_caught)
+    --any_syscall_count;
+  else
+    {
+      struct syscall_filter *iter;
+      for (iter = b->syscalls_to_be_caught; iter; iter = iter->next)
+	{
+	  if (iter->syscall >= syscalls_size)
+	    {
+	      /* Shouldn't happen.  */
+	      continue;
+	    }
+	  --syscalls_counts[iter->syscall];
+	}
+    }
+
+  return target_set_syscall_catchpoint (PIDGET (inferior_ptid),
+					total_syscalls_count != 0,
+					any_syscall_count,
+					syscalls_size,
+					syscalls_counts);
+}
+
+/* Implement the "breakpoint_hit" breakpoint_ops method for syscall
+   catchpoints.  */
+
+static int
+breakpoint_hit_catch_syscall (struct breakpoint *b)
+{
+  /* 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.  */
+  int syscall_number = 0;
+
+  if (!inferior_has_called_syscall (inferior_ptid, &syscall_number))
+    return 0;
+
+  /* Now, checking if the syscall is the same.  */
+  if (b->syscalls_to_be_caught)
+    {
+      struct syscall_filter *iter;
+      for (iter = b->syscalls_to_be_caught; iter; iter = iter->next)
+	if (syscall_number == iter->syscall)
+	  break;
+      /* Not the same.  */
+      if (!iter)
+	return 0;
+    }
+
+  /* It's the same syscall.  We can update the breakpoint struct
+     with the correct information.  */
+  b->syscall_number = syscall_number;
+
+  return 1;
+}
+
+/* Implement the "print_it" breakpoint_ops method for syscall
+   catchpoints.  */
+
+static enum print_stop_action
+print_it_catch_syscall (struct breakpoint *b)
+{
+  /* These are 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".  */
+  ptid_t ptid;
+  struct target_waitstatus last;
+  struct syscall s;
+
+  gdbarch_get_syscall_by_number (current_gdbarch, b->syscall_number, &s);
+
+  get_last_target_status (&ptid, &last);
+
+  annotate_catchpoint (b->number);
+  printf_filtered (_("\nCatchpoint %d ("), b->number);
+
+  if (last.kind == TARGET_WAITKIND_SYSCALL_ENTRY)
+    printf_filtered (_("call to "));
+  else
+    printf_filtered (_("returned from "));
+
+  printf_filtered (_("syscall "));
+
+  if (s.name == NULL)
+    printf_filtered (_("%d"), b->syscall_number);
+  else
+    printf_filtered (_("'%s'"), s.name);
+
+  printf_filtered (_("), "));
+
+  return PRINT_SRC_AND_LOC;
+}
+
+/* Implement the "print_one" breakpoint_ops method for syscall
+   catchpoints.  */
+
+static void
+print_one_catch_syscall (struct breakpoint *b, CORE_ADDR *last_addr)
+{
+  struct value_print_options opts;
+  struct syscall s;
+
+  gdbarch_get_syscall_by_number (current_gdbarch, b->syscall_number, &s);
+
+  get_user_print_options (&opts);
+  /* 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 (opts.addressprint)
+    ui_out_field_skip (uiout, "addr");
+  annotate_field (5);
+  ui_out_text (uiout, "syscall \"");
+  if (b->syscall_number != UNKNOWN_SYSCALL)
+    {
+      if (s.name)
+        ui_out_field_string (uiout, "what", s.name);
+      else
+        ui_out_field_int (uiout, "what", b->syscall_number);
+    }
+  else
+    ui_out_field_string (uiout, "what", "<any syscall>");
+  ui_out_text (uiout, "\" ");
+}
+
+/* Implement the "print_mention" breakpoint_ops method for syscall
+   catchpoints.  */
+
+static void
+print_mention_catch_syscall (struct breakpoint *b)
+{
+  if (b->syscalls_to_be_caught)
+    {
+      struct syscall_filter *iter;
+      printf_filtered (_("Catchpoint %d (syscall(s)"), b->number);
+      for (iter = b->syscalls_to_be_caught; iter; iter = iter->next)
+        {
+          struct syscall s;
+          gdbarch_get_syscall_by_number (current_gdbarch, iter->syscall, &s);
+
+          if (s.name)
+            printf_filtered (" '%s'", s.name);
+          else
+            printf_filtered (" %d", iter->syscall);
+        }
+      printf_filtered (")");
+    }
+  else
+    printf_filtered (_("Catchpoint %d (any syscall)"),
+                     b->number);
+}
+
+/* The breakpoint_ops structure to be used in syscall catchpoints.  */
+
+static struct breakpoint_ops catch_syscall_breakpoint_ops =
+{
+  insert_catch_syscall,
+  remove_catch_syscall,
+  breakpoint_hit_catch_syscall,
+  print_it_catch_syscall,
+  print_one_catch_syscall,
+  print_mention_catch_syscall
+};
+
+/* Returns non-zero if 'b' is a syscall catchpoint.  */
+
+static int
+syscall_catchpoint_p (struct breakpoint *b)
+{
+  return (b->ops == &catch_syscall_breakpoint_ops);
+}
+
+/* Create a new breakpoint of the bp_catchpoint kind and return it,
+   but does NOT mention it nor update the global location list.
+   This is useful if you need to fill more fields in the
+   struct breakpoint before calling mention.
  
    If TEMPFLAG is non-zero, then make the breakpoint temporary.
    If COND_STRING is not NULL, then store it in the breakpoint.
@@ -4661,16 +4908,13 @@ static struct breakpoint_ops catch_vfork
    to the catchpoint.  */
 
 static struct breakpoint *
-create_catchpoint (int tempflag, char *cond_string,
-                   struct breakpoint_ops *ops)
+create_catchpoint_without_mention (int tempflag, char *cond_string,
+                                   struct breakpoint_ops *ops)
 {
   struct symtab_and_line sal;
   struct breakpoint *b;
 
   init_sal (&sal);
-  sal.pc = 0;
-  sal.symtab = NULL;
-  sal.line = 0;
 
   b = set_raw_breakpoint (sal, bp_catchpoint);
   set_breakpoint_count (breakpoint_count + 1);
@@ -4684,6 +4928,23 @@ create_catchpoint (int tempflag, char *c
   b->disposition = tempflag ? disp_del : disp_donttouch;
   b->ops = ops;
 
+  return b;
+}
+
+/* Create a new breakpoint of the bp_catchpoint kind and return it.
+
+   If TEMPFLAG is non-zero, then make the breakpoint temporary.
+   If COND_STRING is not NULL, then store it in the breakpoint.
+   OPS, if not NULL, is the breakpoint_ops structure associated
+   to the catchpoint.  */
+
+static struct breakpoint *
+create_catchpoint (int tempflag, char *cond_string,
+                   struct breakpoint_ops *ops)
+{
+  struct breakpoint *b =
+    create_catchpoint_without_mention (tempflag, cond_string, ops);
+
   mention (b);
   update_global_location_list (1);
 
@@ -4768,6 +5029,23 @@ static struct breakpoint_ops catch_exec_
   print_mention_catch_exec
 };
 
+static void
+create_syscall_event_catchpoint (int tempflag, struct syscall_filter *filter,
+                                 struct breakpoint_ops *ops)
+{
+  struct breakpoint *b =
+    create_catchpoint_without_mention (tempflag, NULL, ops);
+
+  b->syscalls_to_be_caught = filter;
+  /* We still don't know the syscall that will be caught :-).  */
+  b->syscall_number = UNKNOWN_SYSCALL;
+
+  /* Now, we have to mention the breakpoint and update the global
+     location list.  */
+  mention (b);
+  update_global_location_list (1);
+}
+
 static int
 hw_breakpoint_used_count (void)
 {
@@ -6660,6 +6938,122 @@ catch_ada_exception_command (char *arg, 
                                    from_tty);
 }
 
+/* Cleanup function for a syscall filter list.  */
+static void
+clean_up_filters (void *arg)
+{
+  struct syscall_filter *iter = *(struct syscall_filter **) arg;
+  while (iter)
+    {
+      struct syscall_filter *next = iter->next;
+      xfree (iter);
+      iter = next;
+    }
+}
+
+/* Splits the argument using space as delimiter.  Returns an xmalloc'd
+   filter list, or NULL if no filtering is required.  */
+static struct syscall_filter *
+catch_syscall_split_args (char *arg)
+{
+  struct syscall_filter *result = NULL;
+  struct cleanup *cleanup = make_cleanup (clean_up_filters, &result);
+
+  while (*arg != '\0')
+    {
+      int i, syscall_number;
+      char *endptr;
+      char cur_name[128];
+      struct syscall_filter *new_filter;
+      struct syscall s;
+
+      /* Skip whitespace.  */
+      while (isspace (*arg))
+        arg++;
+
+      for (i = 0; arg[i] && !isspace (arg[i]); ++i)
+	cur_name[i] = arg[i];
+      cur_name[i] = '\0';
+      arg += i;
+
+      /* Check if the user provided a syscall name or a number.  */
+      syscall_number = (int) strtol (cur_name, &endptr, 10);
+      if (*endptr == '\0')
+        {
+          gdbarch_get_syscall_by_number (current_gdbarch,
+                                         syscall_number, &s);
+
+          if (s.name == NULL)
+            /* We can issue just a warning, but still create the catchpoint.
+               This is because, even not knowing the syscall name that
+               this number represents, we can still try to catch the syscall
+               number.  */
+            warning (_("The number '%d' does not represent a known syscall."),
+                     syscall_number);
+        }
+      else
+        {
+          /* We have a name.  Let's check if it's valid and convert it
+             to a number.  */
+          gdbarch_get_syscall_by_name (current_gdbarch, cur_name, &s);
+
+          if (s.number == UNKNOWN_SYSCALL)
+            /* Here we have to issue an error instead of a warning, because
+               GDB cannot do anything useful if there's no syscall number to
+               be caught.  */
+            error (_("Unknown syscall name '%s'."), cur_name);
+        }
+
+      /* Ok, it's valid.  */
+      new_filter = XNEW (struct syscall_filter);
+      new_filter->syscall = s.number;
+      new_filter->next = result;
+      result = new_filter;
+    }
+
+  discard_cleanups (cleanup);
+  return result;
+}
+
+/* Implement the "catch syscall" command.  */
+
+static void
+catch_syscall_command_1 (char *arg, int from_tty, struct cmd_list_element *command)
+{
+  int tempflag;
+  struct syscall_filter *filter;
+  struct syscall s;
+
+  /* Checking if the feature if supported.  */
+  if (gdbarch_get_syscall_number_p (current_gdbarch) == 0)
+    error (_("The feature 'catch syscall' is not supported on \
+this architeture yet."));
+
+  tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
+
+  ep_skip_leading_whitespace (&arg);
+
+  /* We need to do this first "dummy" translation in order
+     to get the syscall XML file loaded or, most important,
+     to display a warning to the user if there's no XML file
+     for his/her architecture.  */
+  gdbarch_get_syscall_by_number (current_gdbarch, 0, &s);
+
+  /* The allowed syntax is:
+     catch syscall
+     catch syscall <name | number> [<name | number> ... <name | number>]
+
+     Let's check if there's a syscall name.  */
+
+  if (arg != NULL)
+    filter = catch_syscall_split_args (arg);
+  else
+    filter = NULL;
+
+  create_syscall_event_catchpoint (tempflag, filter,
+				   &catch_syscall_breakpoint_ops);
+}
+
 /* Implement the "catch assert" command.  */
 
 static void
@@ -7126,6 +7520,7 @@ delete_breakpoint (struct breakpoint *bp
     xfree (bpt->source_file);
   if (bpt->exec_pathname != NULL)
     xfree (bpt->exec_pathname);
+  clean_up_filters (&bpt->syscalls_to_be_caught);
 
   /* Be sure no bpstat's are pointing at it after it's been freed.  */
   /* FIXME, how can we find all bpstat's?
@@ -8033,6 +8428,57 @@ 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 (syscall_catchpoint_p (bp)
+      && bp->enable_state != bp_disabled
+      && bp->enable_state != bp_call_disabled)
+    return 1;
+  else
+    return 0;
+}
+
+int
+catch_syscall_enabled (void)
+{
+  return total_syscalls_count != 0;
+}
+
+int
+catching_syscall_number (int syscall_number)
+{
+  struct breakpoint *bp;
+
+  ALL_BREAKPOINTS (bp)
+    if (is_syscall_catchpoint_enabled (bp))
+      {
+	if (bp->syscalls_to_be_caught)
+	  {
+	    struct syscall_filter *iter;
+	    for (iter = bp->syscalls_to_be_caught; iter; iter = iter->next)
+	      if (syscall_number == iter->syscall)
+		return 1;
+	  }
+	else
+	  return 1;
+      }
+
+  return 0;
+}
+
+/* Complete syscall names.  Used by "catch syscall".  */
+static char **
+catch_syscall_completer (struct cmd_list_element *self,
+			 char *text, char *word)
+{
+  const char **list =
+    gdbarch_get_syscall_names (current_gdbarch);
+  return (list == NULL) ? NULL : complete_on_enum (list, text, word);
+}
+
 
 /* This help string is used for the break, hbreak, tbreak and thbreak commands.
    It is defined as a macro to prevent duplication.
@@ -8065,6 +8511,8 @@ static void
 add_catch_command (char *name, char *docstring,
 		   void (*sfunc) (char *args, int from_tty,
 				  struct cmd_list_element *command),
+                   char ** (*completion_function) (struct cmd_list_element *self,
+			     			   char *text, char *word),
 		   void *user_data_catch,
 		   void *user_data_tcatch)
 {
@@ -8074,11 +8522,13 @@ add_catch_command (char *name, char *doc
 		     &catch_cmdlist);
   set_cmd_sfunc (command, sfunc);
   set_cmd_context (command, user_data_catch);
+  set_cmd_completer (command, completion_function);
 
   command = add_cmd (name, class_breakpoint, NULL, docstring,
 		     &tcatch_cmdlist);
   set_cmd_sfunc (command, sfunc);
   set_cmd_context (command, user_data_tcatch);
+  set_cmd_completer (command, completion_function);
 }
 
 void
@@ -8353,36 +8803,50 @@ Set temporary catchpoints to catch event
 Catch an exception, when caught.\n\
 With an argument, catch only exceptions with the given name."),
 		     catch_catch_command,
+                     NULL,
 		     CATCH_PERMANENT,
 		     CATCH_TEMPORARY);
   add_catch_command ("throw", _("\
 Catch an exception, when thrown.\n\
 With an argument, catch only exceptions with the given name."),
 		     catch_throw_command,
+                     NULL,
 		     CATCH_PERMANENT,
 		     CATCH_TEMPORARY);
   add_catch_command ("fork", _("Catch calls to fork."),
 		     catch_fork_command_1,
+                     NULL,
 		     (void *) (uintptr_t) catch_fork_permanent,
 		     (void *) (uintptr_t) catch_fork_temporary);
   add_catch_command ("vfork", _("Catch calls to vfork."),
 		     catch_fork_command_1,
+                     NULL,
 		     (void *) (uintptr_t) catch_vfork_permanent,
 		     (void *) (uintptr_t) catch_vfork_temporary);
   add_catch_command ("exec", _("Catch calls to exec."),
 		     catch_exec_command_1,
+                     NULL,
 		     CATCH_PERMANENT,
 		     CATCH_TEMPORARY);
+  add_catch_command ("syscall", _("\
+Catch system calls.\n\
+With an argument, catch only that syscall."),
+                         catch_syscall_command_1,
+                         catch_syscall_completer,
+                         CATCH_PERMANENT,
+                         CATCH_TEMPORARY);
   add_catch_command ("exception", _("\
 Catch Ada exceptions, when raised.\n\
 With an argument, catch only exceptions with the given name."),
 		     catch_ada_exception_command,
+                     NULL,
 		     CATCH_PERMANENT,
 		     CATCH_TEMPORARY);
   add_catch_command ("assert", _("\
 Catch failed Ada assertions, when raised.\n\
 With an argument, catch only exceptions with the given name."),
 		     catch_assert_command,
+                     NULL,
 		     CATCH_PERMANENT,
 		     CATCH_TEMPORARY);
 
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -33,7 +33,8 @@ struct block;
 
 #define	BREAKPOINT_MAX	16
 
-/* Type of breakpoint. */
+
+/* Type of breakpoint.  */
 /* FIXME In the future, we should fold all other breakpoint-like things into
    here.  This includes:
 
@@ -337,6 +338,17 @@ enum watchpoint_triggered
   watch_triggered_yes  
 };
 
+/* A syscall filter is represented as a linked list of syscall
+   numbers.  */
+struct syscall_filter
+{
+  /* The system call to accept.  */
+  int syscall;
+
+  /* The next filter.  */
+  struct syscall_filter *next;
+};
+
 typedef struct bp_location *bp_location_p;
 DEF_VEC_P(bp_location_p);
 
@@ -442,6 +454,20 @@ 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;
+
+    /* Syscall numbers used for the 'catch syscall' feature.
+       If no syscall has been specified for filtering, its value is NULL.
+       Otherwise, it holds a list of all syscalls to be caught.
+       The list elements are allocated with xmalloc.  */
+    struct syscall_filter *syscalls_to_be_caught;
+
     /* Methods associated with this breakpoint.  */
     struct breakpoint_ops *ops;
 
@@ -783,6 +809,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 **);
@@ -857,6 +885,15 @@ 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);
+
 /* Tell a breakpoint to be quiet.  */
 extern void make_breakpoint_silent (struct breakpoint *);
 
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -151,6 +151,9 @@ extern int dbx_commands;
 /* System root path, used to find libraries etc.  */
 extern char *gdb_sysroot;
 
+/* GDB datadir, used to store data files.  */
+extern char *gdb_datadir;
+
 /* Search path for separate debug files.  */
 extern char *debug_file_directory;
 
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -241,6 +241,11 @@ struct gdbarch
   gdbarch_target_signal_to_host_ftype *target_signal_to_host;
   gdbarch_get_siginfo_type_ftype *get_siginfo_type;
   gdbarch_record_special_symbol_ftype *record_special_symbol;
+  gdbarch_get_syscall_number_ftype *get_syscall_number;
+  gdbarch_get_syscall_by_number_ftype *get_syscall_by_number;
+  gdbarch_get_syscall_by_name_ftype *get_syscall_by_name;
+  gdbarch_get_syscall_names_ftype *get_syscall_names;
+  const char * xml_syscall_filename;
   int has_global_solist;
 };
 
@@ -374,6 +379,11 @@ struct gdbarch startup_gdbarch =
   default_target_signal_to_host,  /* target_signal_to_host */
   0,  /* get_siginfo_type */
   0,  /* record_special_symbol */
+  0,  /* get_syscall_number */
+  0,  /* get_syscall_by_number */
+  0,  /* get_syscall_by_name */
+  0,  /* get_syscall_names */
+  0,  /* xml_syscall_filename */
   0,  /* has_global_solist */
   /* startup_gdbarch() */
 };
@@ -628,6 +638,11 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of target_signal_to_host, invalid_p == 0 */
   /* Skip verify of get_siginfo_type, has predicate */
   /* Skip verify of record_special_symbol, has predicate */
+  /* Skip verify of get_syscall_number, has predicate */
+  /* Skip verify of get_syscall_by_number, has predicate */
+  /* Skip verify of get_syscall_by_name, has predicate */
+  /* Skip verify of get_syscall_names, has predicate */
+  /* Skip verify of xml_syscall_filename, invalid_p == 0 */
   /* Skip verify of has_global_solist, invalid_p == 0 */
   buf = ui_file_xstrdup (log, &dummy);
   make_cleanup (xfree, buf);
@@ -844,6 +859,30 @@ gdbarch_dump (struct gdbarch *gdbarch, s
                       "gdbarch_dump: get_siginfo_type = <0x%lx>\n",
                       (long) gdbarch->get_siginfo_type);
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_get_syscall_by_name_p() = %d\n",
+                      gdbarch_get_syscall_by_name_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: get_syscall_by_name = <0x%lx>\n",
+                      (long) gdbarch->get_syscall_by_name);
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_get_syscall_by_number_p() = %d\n",
+                      gdbarch_get_syscall_by_number_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: get_syscall_by_number = <0x%lx>\n",
+                      (long) gdbarch->get_syscall_by_number);
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_get_syscall_names_p() = %d\n",
+                      gdbarch_get_syscall_names_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: get_syscall_names = <0x%lx>\n",
+                      (long) gdbarch->get_syscall_names);
+  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: has_global_solist = %s\n",
                       plongest (gdbarch->has_global_solist));
   fprintf_unfiltered (file,
@@ -1107,6 +1146,9 @@ gdbarch_dump (struct gdbarch *gdbarch, s
   fprintf_unfiltered (file,
                       "gdbarch_dump: write_pc = <%s>\n",
                       host_address_to_string (gdbarch->write_pc));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: xml_syscall_filename = %s\n",
+                      gdbarch->xml_syscall_filename);
   if (gdbarch->dump_tdep != NULL)
     gdbarch->dump_tdep (gdbarch, file);
 }
@@ -3277,6 +3319,119 @@ set_gdbarch_record_special_symbol (struc
 }
 
 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_get_syscall_by_number_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->get_syscall_by_number != NULL;
+}
+
+void
+gdbarch_get_syscall_by_number (struct gdbarch *gdbarch, int syscall_number, struct syscall *s)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->get_syscall_by_number != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_get_syscall_by_number called\n");
+  gdbarch->get_syscall_by_number (gdbarch, syscall_number, s);
+}
+
+void
+set_gdbarch_get_syscall_by_number (struct gdbarch *gdbarch,
+                                   gdbarch_get_syscall_by_number_ftype get_syscall_by_number)
+{
+  gdbarch->get_syscall_by_number = get_syscall_by_number;
+}
+
+int
+gdbarch_get_syscall_by_name_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->get_syscall_by_name != NULL;
+}
+
+void
+gdbarch_get_syscall_by_name (struct gdbarch *gdbarch, const char *syscall_name, struct syscall *s)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->get_syscall_by_name != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_get_syscall_by_name called\n");
+  gdbarch->get_syscall_by_name (gdbarch, syscall_name, s);
+}
+
+void
+set_gdbarch_get_syscall_by_name (struct gdbarch *gdbarch,
+                                 gdbarch_get_syscall_by_name_ftype get_syscall_by_name)
+{
+  gdbarch->get_syscall_by_name = get_syscall_by_name;
+}
+
+int
+gdbarch_get_syscall_names_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->get_syscall_names != NULL;
+}
+
+const char **
+gdbarch_get_syscall_names (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->get_syscall_names != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_get_syscall_names called\n");
+  return gdbarch->get_syscall_names (gdbarch);
+}
+
+void
+set_gdbarch_get_syscall_names (struct gdbarch *gdbarch,
+                               gdbarch_get_syscall_names_ftype get_syscall_names)
+{
+  gdbarch->get_syscall_names = get_syscall_names;
+}
+
+const char *
+gdbarch_xml_syscall_filename (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  /* Skip verify of xml_syscall_filename, invalid_p == 0 */
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_xml_syscall_filename called\n");
+  return gdbarch->xml_syscall_filename;
+}
+
+void
+set_gdbarch_xml_syscall_filename (struct gdbarch *gdbarch,
+                                  const char * xml_syscall_filename)
+{
+  gdbarch->xml_syscall_filename = xml_syscall_filename;
+}
+
+int
 gdbarch_has_global_solist (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -52,6 +52,7 @@ struct bp_target_info;
 struct target_desc;
 struct displaced_step_closure;
 struct core_regset_section;
+struct syscall;
 
 extern struct gdbarch *current_gdbarch;
 extern struct gdbarch *target_gdbarch;
@@ -821,6 +822,47 @@ 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);
+
+/* Fills the struct syscall (passed as argument) with the corresponding
+   system call represented by syscall_number. */
+
+extern int gdbarch_get_syscall_by_number_p (struct gdbarch *gdbarch);
+
+typedef void (gdbarch_get_syscall_by_number_ftype) (struct gdbarch *gdbarch, int syscall_number, struct syscall *s);
+extern void gdbarch_get_syscall_by_number (struct gdbarch *gdbarch, int syscall_number, struct syscall *s);
+extern void set_gdbarch_get_syscall_by_number (struct gdbarch *gdbarch, gdbarch_get_syscall_by_number_ftype *get_syscall_by_number);
+
+/* Fills the struct syscall (passed as argument) with the corresponding
+   system call represented by syscall_name. */
+
+extern int gdbarch_get_syscall_by_name_p (struct gdbarch *gdbarch);
+
+typedef void (gdbarch_get_syscall_by_name_ftype) (struct gdbarch *gdbarch, const char *syscall_name, struct syscall *s);
+extern void gdbarch_get_syscall_by_name (struct gdbarch *gdbarch, const char *syscall_name, struct syscall *s);
+extern void set_gdbarch_get_syscall_by_name (struct gdbarch *gdbarch, gdbarch_get_syscall_by_name_ftype *get_syscall_by_name);
+
+/* Returns the array containing the syscall names for the architecture. */
+
+extern int gdbarch_get_syscall_names_p (struct gdbarch *gdbarch);
+
+typedef const char ** (gdbarch_get_syscall_names_ftype) (struct gdbarch *gdbarch);
+extern const char ** gdbarch_get_syscall_names (struct gdbarch *gdbarch);
+extern void set_gdbarch_get_syscall_names (struct gdbarch *gdbarch, gdbarch_get_syscall_names_ftype *get_syscall_names);
+
+/* Stores the name of syscall's XML file. Contains NULL if the file
+   was not set. */
+
+extern const char * gdbarch_xml_syscall_filename (struct gdbarch *gdbarch);
+extern void set_gdbarch_xml_syscall_filename (struct gdbarch *gdbarch, const char * xml_syscall_filename);
+
 /* True if the list of shared libraries is one and only for all
    processes, as opposed to a list of shared libraries per inferior.
    When this property is true, GDB assumes that since shared libraries
@@ -830,6 +872,9 @@ extern void set_gdbarch_record_special_s
 extern int gdbarch_has_global_solist (struct gdbarch *gdbarch);
 extern void set_gdbarch_has_global_solist (struct gdbarch *gdbarch, int has_global_solist);
 
+/* Definition for an unknown syscall, used basically in error-cases. */
+#define UNKNOWN_SYSCALL (-1)
+
 extern struct gdbarch_tdep *gdbarch_tdep (struct gdbarch *gdbarch);
 
 
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -713,6 +713,26 @@ M:struct type *:get_siginfo_type:void:
 # 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
+
+# Fills the struct syscall (passed as argument) with the corresponding
+# system call represented by syscall_number.
+M:void:get_syscall_by_number:int syscall_number, struct syscall *s:syscall_number, s
+
+# Fills the struct syscall (passed as argument) with the corresponding
+# system call represented by syscall_name.
+M:void:get_syscall_by_name:const char *syscall_name, struct syscall *s:syscall_name, s
+
+# Returns the array containing the syscall names for the architecture.
+M:const char **:get_syscall_names:void:
+
+# Stores the name of syscall's XML file. Contains NULL if the file
+# was not set.
+v:const char *:xml_syscall_filename:::0:0::0:gdbarch->xml_syscall_filename
+
 # True if the list of shared libraries is one and only for all
 # processes, as opposed to a list of shared libraries per inferior.
 # When this property is true, GDB assumes that since shared libraries
@@ -831,6 +851,7 @@ struct bp_target_info;
 struct target_desc;
 struct displaced_step_closure;
 struct core_regset_section;
+struct syscall;
 
 extern struct gdbarch *current_gdbarch;
 extern struct gdbarch *target_gdbarch;
@@ -900,6 +921,9 @@ done
 # close it off
 cat <<EOF
 
+/* Definition for an unknown syscall, used basically in error-cases. */
+#define UNKNOWN_SYSCALL (-1)
+
 extern struct gdbarch_tdep *gdbarch_tdep (struct gdbarch *gdbarch);
 
 
--- a/gdb/inf-child.c
+++ b/gdb/inf-child.c
@@ -145,6 +145,15 @@ inf_child_remove_exec_catchpoint (int pi
 }
 
 static int
+inf_child_set_syscall_catchpoint (int pid, int needed, int any_count,
+				  int table_size, int *table)
+{
+  /* This version of Unix doesn't support notification of syscall
+     events.  */
+  return 0;
+}
+
+static int
 inf_child_can_run (void)
 {
   return 1;
@@ -187,6 +196,7 @@ inf_child_target (void)
   t->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_set_syscall_catchpoint = inf_child_set_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;
--- a/gdb/inf-ptrace.c
+++ b/gdb/inf-ptrace.c
@@ -354,13 +354,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
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -466,6 +466,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);
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1046,7 +1046,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)
     {
@@ -1069,6 +1069,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;
     }
@@ -1509,7 +1514,7 @@ init_wait_for_inferior (void)
 
   breakpoint_init_inferior (inf_starting);
 
-  /* The first resume is not following a fork/vfork/exec. */
+  /* The first resume is not following a fork/vfork/exec/syscall.  */
   pending_follow.kind = TARGET_WAITKIND_SPURIOUS;	/* I.e., none. */
 
   clear_proceed_status ();
@@ -2129,6 +2134,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.  */
@@ -2423,9 +2472,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
@@ -2435,9 +2486,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)
@@ -5155,6 +5207,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;
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -684,6 +684,7 @@ linux_child_post_attach (int pid)
 {
   linux_enable_event_reporting (pid_to_ptid (pid));
   check_for_thread_db ();
+  linux_enable_tracesysgood (pid_to_ptid (pid));
 }
 
 static void
@@ -691,6 +692,7 @@ linux_child_post_startup_inferior (ptid_
 {
   linux_enable_event_reporting (ptid);
   check_for_thread_db ();
+  linux_enable_tracesysgood (ptid);
 }
 
 static int
@@ -4260,6 +4262,7 @@ linux_target_install_ops (struct target_
   t->to_follow_fork = linux_child_follow_fork;
   t->to_find_memory_regions = linux_nat_find_memory_regions;
   t->to_make_corefile_notes = linux_nat_make_corefile_notes;
+  t->to_passed_by_entrypoint = linux_passed_by_entrypoint;
 
   super_xfer_partial = t->to_xfer_partial;
   t->to_xfer_partial = linux_xfer_partial;
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -62,6 +62,9 @@ int dbx_commands = 0;
 /* System root path, used to find libraries etc.  */
 char *gdb_sysroot = 0;
 
+/* GDB datadir, used to store data files.  */
+char *gdb_datadir = 0;
+
 struct ui_file *gdb_stdout;
 struct ui_file *gdb_stderr;
 struct ui_file *gdb_stdlog;
@@ -359,6 +362,40 @@ captured_main (void *data)
 
   get_init_files (&system_gdbinit, &home_gdbinit, &local_gdbinit);
 
+#ifdef GDB_DATADIR_RELOCATABLE
+  gdb_datadir = make_relative_prefix (argv[0], BINDIR, GDB_DATADIR);
+  if (gdb_datadir)
+    {
+      struct stat s;
+      int res = 0;
+
+      if (stat (gdb_datadir, &s) == 0)
+	if (S_ISDIR (s.st_mode))
+	  res = 1;
+
+      if (res == 0)
+	{
+	  xfree (gdb_datadir);
+	  gdb_datadir = xstrdup (GDB_DATADIR);
+	}
+    }
+  else
+    gdb_datadir = xstrdup (GDB_DATADIR);
+#else
+  gdb_datadir = xstrdup (GDB_DATADIR);
+#endif /* GDB_DATADIR_RELOCATABLE */
+
+  /* Canonicalize the GDB's datadir path.  */
+  if (*gdb_datadir)
+    {
+      char *canon_debug = lrealpath (gdb_datadir);
+      if (canon_debug)
+	{
+	  xfree (gdb_datadir);
+	  gdb_datadir = canon_debug;
+	}
+    }
+
   /* There will always be an interpreter.  Either the one passed into
      this captured main, or one specified by the user at start up, or
      the console.  Initialize the interpreter to the one requested by 
--- a/gdb/maint.c
+++ b/gdb/maint.c
@@ -906,4 +906,12 @@ When enabled GDB is profiled."),
 			   show_maintenance_profile_p,
 			   &maintenance_set_cmdlist,
 			   &maintenance_show_cmdlist);
+  add_setshow_filename_cmd ("gdb_datadir", class_maintenance,
+                           &gdb_datadir, _("Set GDB's datadir path."),
+                           _("Show GDB's datadir path."),
+                           _("\
+When set, GDB uses the specified path to search for data files."),
+                           NULL, NULL,
+                           &maintenance_set_cmdlist,
+                           &maintenance_show_cmdlist);
 }
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -451,6 +451,8 @@ 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_set_syscall_catchpoint, t);
       INHERIT (to_has_exited, t);
       /* Do not inherit to_mourn_inferiour.  */
       INHERIT (to_can_run, t);
@@ -603,9 +605,15 @@ 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_set_syscall_catchpoint,
+	    (int (*) (int, int, int, int, int *))
+	    tcomplain);
   de_fault (to_has_exited,
 	    (int (*) (int, int, int *))
 	    return_zero);
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -139,7 +139,8 @@ 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;
@@ -147,10 +148,26 @@ struct target_waitstatus
 	ptid_t related_pid;
 	char *execd_pathname;
 	int syscall_id;
+	int syscall_number;
       }
     value;
   };
 
+/* The structure below stores information about a system call.
+   It is basically used in the "catch syscall" command, and in
+   every function that gives information about a system call.
+
+   It's also good to mention that its fields represent everything
+   that we currently know about a syscall in GDB.  */
+struct syscall
+  {
+    /* The syscall number.  */
+    int number;
+
+    /* The syscall name.  */
+    const char *name;
+  };
+
 /* Return a pretty printed form of target_waitstatus.
    Space for the result is malloc'd, caller must free.  */
 extern char *target_waitstatus_to_string (const struct target_waitstatus *);
@@ -400,6 +417,8 @@ 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);
+    int (*to_set_syscall_catchpoint) (int, int, int, int, int *);
     int (*to_has_exited) (int, int, int *);
     void (*to_mourn_inferior) (struct target_ops *);
     int (*to_can_run) (void);
@@ -733,6 +752,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 *);
@@ -891,6 +912,21 @@ 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.  NEEDED is nonzero if any syscall catch (of any
+   kind) is requested.  ANY_COUNT is nonzero if a generic
+   (filter-less) syscall catch is being requested.  TABLE is an array
+   of ints, indexed by syscall number.  An element in this array is
+   nonzero if that syscall should be caught.  TABLE_SIZE is the number
+   of elements in TABLE.  */
+
+#define target_set_syscall_catchpoint(pid, needed, any_count, table_size, table) \
+     (*current_target.to_set_syscall_catchpoint) (pid, needed, any_count, \
+						  table_size, table)
+
 /* Returns TRUE if PID has exited.  And, also sets EXIT_STATUS to the
    exit code of PID, if any.  */
 
---
 gdb/Makefile.in                          |   54 +++-
 gdb/config.in                            |    6 
 gdb/configure                            |   51 ++++
 gdb/configure.ac                         |   30 ++
 gdb/configure.tgt                        |   30 +-
 gdb/doc/gdb.texinfo                      |   92 +++++++
 gdb/testsuite/gdb.base/Makefile.in       |    2 
 gdb/testsuite/gdb.base/catch-syscall.c   |   25 ++
 gdb/testsuite/gdb.base/catch-syscall.exp |  386 +++++++++++++++++++++++++++++++
 9 files changed, 657 insertions(+), 19 deletions(-)

--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -172,6 +172,9 @@ LIBICONV = @LIBICONV@
 TARGET_SYSTEM_ROOT = @TARGET_SYSTEM_ROOT@
 TARGET_SYSTEM_ROOT_DEFINE = @TARGET_SYSTEM_ROOT_DEFINE@
 
+# Did the user give us a --with-gdb-datadir option?
+GDB_DATADIR_PATH = @GDB_DATADIR_PATH@
+
 # Helper code from gnulib.
 LIBGNU = gnulib/libgnu.a
 INCGNU = -I$(srcdir)/gnulib -Ignulib
@@ -459,6 +462,7 @@ TARGET_OBS = @TARGET_OBS@
 # All target-dependent objects files that require 64-bit CORE_ADDR
 # (used with --enable-targets=all --enable-64-bit-bfd).
 ALL_64_TARGET_OBS = \
+	linux-tdep.o \
 	alphabsd-tdep.o alphafbsd-tdep.o alpha-linux-tdep.o alpha-mdebug-tdep.o \
 	alphanbsd-tdep.o alphaobsd-tdep.o alpha-osf1-tdep.o alpha-tdep.o \
 	amd64fbsd-tdep.o amd64-linux-tdep.o amd64nbsd-tdep.o amd64obsd-tdep.o \
@@ -470,6 +474,7 @@ ALL_64_TARGET_OBS = \
 
 # All other target-dependent objects files (used with --enable-targets=all).
 ALL_TARGET_OBS = \
+	linux-tdep.o \
 	armbsd-tdep.o arm-linux-tdep.o armnbsd-tdep.o armobsd-tdep.o \
 	arm-tdep.o arm-wince-tdep.o \
 	avr-tdep.o \
@@ -661,6 +666,8 @@ SFILES = ada-exp.y ada-lang.c ada-typepr
 	valarith.c valops.c valprint.c value.c varobj.c vec.c \
 	wrapper.c \
 	xml-tdesc.c xml-support.c \
+	linux-tdep.c \
+	xml-syscall.c \
 	inferior.c
 
 LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
@@ -671,7 +678,7 @@ LINTFILES = $(SFILES) $(YYFILES) $(CONFI
 # wrong if TAGS has files twice).  Because this is tricky to get
 # right, it is probably easiest just to list .h files here directly.
 
-HFILES_NO_SRCDIR = osf-share/cma_debug_client.h	\
+HFILES_NO_SRCDIR = osf-share/cma_debug_client.h	linux-tdep.h \
 osf-share/HP800/cma_thread_io.h osf-share/cma_sequence.h \
 osf-share/cma_mutex.h osf-share/cma_semaphore_defs.h \
 osf-share/cma_list.h osf-share/cma_handle.h osf-share/cma_stack.h \
@@ -731,7 +738,7 @@ config/sparc/nm-sol2.h config/nm-linux.h
 config/rs6000/nm-rs6000.h top.h bsd-kvm.h gdb-stabs.h reggroups.h \
 annotate.h sim-regno.h dictionary.h dfp.h main.h frame-unwind.h	\
 remote-fileio.h i386-linux-tdep.h vax-tdep.h objc-lang.h \
-sentinel-frame.h bcache.h symfile.h windows-tdep.h linux-tdep.h
+sentinel-frame.h bcache.h symfile.h windows-tdep.h linux-tdep.h xml-syscall.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -810,10 +817,16 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $
 	trad-frame.o \
 	tramp-frame.o \
 	solib.o solib-null.o \
-	prologue-value.o memory-map.o xml-support.o \
+	prologue-value.o memory-map.o xml-support.o xml-syscall.o \
 	target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \
 	inferior.o osdata.o
 
+# Definitions for the syscall's XML files and dir
+XML_SYSCALLS_DIR = syscalls/
+XML_SYSCALLS_FILES = gdb-syscalls.dtd \
+		     ppc-linux.xml ppc64-linux.xml \
+		     i386-linux.xml amd64-linux.xml
+
 TSOBS = inflow.o
 
 SUBDIRS = @subdirs@
@@ -847,11 +860,38 @@ generated_files = config.h observer.h ob
 	$(COMPILE) $<
 	$(POSTCOMPILE)
 
-all: gdb$(EXEEXT) $(CONFIG_ALL)
+all: gdb$(EXEEXT) $(CONFIG_ALL) xml-syscall-copy
 	@$(MAKE) $(FLAGS_TO_PASS) DO=all "DODIRS=`echo $(SUBDIRS) | sed 's/testsuite//'`" subdir_do
 .PHONY: all-tui
 all-tui: $(TUI)$(EXEEXT)
 
+xml-syscall-copy:
+	if [ "`cd $(srcdir) && pwd`" != "`pwd`" ] ; then \
+	  mkdir -p ./$(XML_SYSCALLS_DIR) ; \
+	  list='$(XML_SYSCALLS_FILES)' ; \
+ 	  for file in $$list ; do \
+	    f=$(srcdir)/$(XML_SYSCALLS_DIR)/$$file ; \
+	    if test -f $$f ; then \
+	      $(INSTALL_DATA) $$f \
+	    	  ./$(XML_SYSCALLS_DIR) ; \
+	    fi ; \
+	  done ; \
+	fi ;
+
+# This target is responsible for properly installing the syscalls'
+# XML files in the system.
+xml-syscall-install:
+	$(SHELL) $(srcdir)/../mkinstalldirs \
+		$(DESTDIR)$(GDB_DATADIR_PATH)/$(XML_SYSCALLS_DIR) ; \
+	list='$(XML_SYSCALLS_FILES)' ; \
+	for file in $$list ; do \
+	  f=$(srcdir)/$(XML_SYSCALLS_DIR)/$$file ; \
+	  if test -f $$f ; then \
+	    $(INSTALL_DATA) $$f \
+	    	$(DESTDIR)$(GDB_DATADIR_PATH)/$(XML_SYSCALLS_DIR) ; \
+	  fi ; \
+	done ;
+
 installcheck:
 
 # The check target can not use subdir_do, because subdir_do does not
@@ -906,7 +946,10 @@ gdb.z:gdb.1
 # time it takes for make to check that all is up to date.
 # install-only is intended to address that need.
 install: all install-only
-install-only: $(CONFIG_INSTALL)
+
+# The "install-only" target also installs the syscalls' XML files in
+# the system.
+install-only: $(CONFIG_INSTALL) xml-syscall-install
 	transformed_name=`t='$(program_transform_name)'; \
 			  echo gdb | sed -e "$$t"` ; \
 		if test "x$$transformed_name" = x; then \
@@ -1262,6 +1305,7 @@ force_update:
 MAKEOVERRIDES=
 
 ALLDEPFILES = \
+	linux-tdep.c \
 	aix-thread.c \
 	alpha-nat.c alphabsd-nat.c alpha-linux-nat.c \
 	alpha-tdep.c alpha-mdebug-tdep.c \
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -42,6 +42,12 @@
    language is requested. */
 #undef ENABLE_NLS
 
+/* Global directory for GDB data files. */
+#undef GDB_DATADIR
+
+/* Define if GDB datadir should be relocated when GDB is moved. */
+#undef GDB_DATADIR_RELOCATABLE
+
 /* Define to be a string naming the default host character set. */
 #undef GDB_DEFAULT_HOST_CHARSET
 
--- a/gdb/configure
+++ b/gdb/configure
@@ -314,7 +314,7 @@ ac_subdirs_all="$ac_subdirs_all doc test
 ac_subdirs_all="$ac_subdirs_all gdbtk"
 ac_subdirs_all="$ac_subdirs_all multi-ice"
 ac_subdirs_all="$ac_subdirs_all gdbserver"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP RANLIB ac_ct_RANLIB build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os am__leading_dot DEPDIR CCDEPMODE MAKE GMAKE_TRUE GMAKE_FALSE SET_MAKE USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT localedir GL_COND_LIBTOOL_TRUE GL_COND_LIBTOOL_FALSE GNULIB_MEMMEM GNULIB_MEMPCPY GNULIB_MEMRCHR GNULIB_STPCPY GNULIB_STPNCPY GNULIB_STRCHRNUL GNULIB_STRDUP GNULIB_STRNDUP GNULIB_STRNLEN GNULIB_STRPBRK GNULIB_STRSEP GNULIB_STRSTR GNULIB_STRCASESTR GNULIB_STRTOK_R GNULIB_MBSLEN GNULIB_MBSNLEN GNULIB_MBSCHR GNULIB_MBSRCHR GNULIB_MBSSTR GNULIB_MBSCASECMP GNULIB_MBSNCASECMP GNULIB_MBSPCASECMP GNULIB_MBSCASESTR GNULIB_MBSCSPN GNULIB_MBSPBRK GNULIB_MBSSPN GNULIB_MBSSEP GNULIB_MBSTOK_R GNULIB_STRERROR GNULIB_STRSIGNAL HAVE_DECL_MEMMEM HAVE_MEMPCPY HAVE_DECL_MEMRCHR HAVE_STPCPY HAVE_STPNCPY HAVE_STRCHRNUL HAVE_DECL_STRDUP HAVE_STRNDUP HAVE_DECL_STRNDUP HAVE_DECL_STRNLEN HAVE_STRPBRK HAVE_STRSEP HAVE_STRCASESTR HAVE_DECL_STRTOK_R HAVE_DECL_STRERROR HAVE_DECL_STRSIGNAL REPLACE_STRERROR REPLACE_STRSIGNAL REPLACE_MEMMEM REPLACE_STRCASESTR REPLACE_STRSTR HAVE_LONG_LONG_INT HAVE_UNSIGNED_LONG_LONG_INT HAVE_INTTYPES_H HAVE_SYS_TYPES_H INCLUDE_NEXT NEXT_STDINT_H HAVE_STDINT_H HAVE_SYS_INTTYPES_H HAVE_SYS_BITYPES_H BITSIZEOF_PTRDIFF_T BITSIZEOF_SIG_ATOMIC_T BITSIZEOF_SIZE_T BITSIZEOF_WCHAR_T BITSIZEOF_WINT_T HAVE_SIGNED_SIG_ATOMIC_T HAVE_SIGNED_WCHAR_T HAVE_SIGNED_WINT_T PTRDIFF_T_SUFFIX SIG_ATOMIC_T_SUFFIX SIZE_T_SUFFIX WCHAR_T_SUFFIX WINT_T_SUFFIX STDINT_H NEXT_STRING_H GNULIB_WCWIDTH HAVE_DECL_WCWIDTH REPLACE_WCWIDTH WCHAR_H HAVE_WCHAR_H NEXT_WCHAR_H LIBGNU_LIBDEPS LIBGNU_LTLIBDEPS GNULIB_STDINT_H PACKAGE INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK AMTAR am__tar am__untar am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH am__fastdepCC_TRUE am__fastdepCC_FALSE subdirs TARGET_OBS PKGVERSION REPORT_BUGS_TO REPORT_BUGS_TEXI LN_S YACC AR ac_ct_AR DLLTOOL ac_ct_DLLTOOL WINDRES ac_ct_WINDRES MIG ac_ct_MIG READLINE READLINE_DEPS READLINE_CFLAGS HAVE_LIBEXPAT LIBEXPAT LTLIBEXPAT PYTHON_CFLAGS ALLOCA CONFIG_LDFLAGS TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE WARN_CFLAGS WERROR_CFLAGS SER_HARDWIRE WIN32LIBS LIBGUI GUI_CFLAGS_X WIN32LDAPP TCL_VERSION TCL_PATCH_LEVEL TCL_BIN_DIR TCL_SRC_DIR TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC TCL_INCLUDE TCL_LIBRARY TCL_DEPS TK_VERSION TK_BIN_DIR TK_SRC_DIR TK_LIB_FILE TK_LIB_FLAG TK_LIB_SPEC TK_STUB_LIB_FILE TK_STUB_LIB_FLAG TK_STUB_LIB_SPEC TK_INCLUDE TK_LIBRARY TK_DEPS TK_XINCLUDES X_CFLAGS X_LDFLAGS X_LIBS GDBTKLIBS GDBTK_CFLAGS GDBTK_SRC_DIR SIM SIM_OBS ENABLE_CFLAGS PROFILE_CFLAGS CONFIG_OBS CONFIG_DEPS CONFIG_SRCS CONFIG_ALL CONFIG_CLEAN CONFIG_INSTALL CONFIG_UNINSTALL target_subdir frags nm_h LIBICONV LIBOBJS LTLIBOBJS gl_LIBOBJS gl_LTLIBOBJS gltests_LIBOBJS gltests_LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP RANLIB ac_ct_RANLIB build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os am__leading_dot DEPDIR CCDEPMODE MAKE GMAKE_TRUE GMAKE_FALSE SET_MAKE USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT localedir GL_COND_LIBTOOL_TRUE GL_COND_LIBTOOL_FALSE GNULIB_MEMMEM GNULIB_MEMPCPY GNULIB_MEMRCHR GNULIB_STPCPY GNULIB_STPNCPY GNULIB_STRCHRNUL GNULIB_STRDUP GNULIB_STRNDUP GNULIB_STRNLEN GNULIB_STRPBRK GNULIB_STRSEP GNULIB_STRSTR GNULIB_STRCASESTR GNULIB_STRTOK_R GNULIB_MBSLEN GNULIB_MBSNLEN GNULIB_MBSCHR GNULIB_MBSRCHR GNULIB_MBSSTR GNULIB_MBSCASECMP GNULIB_MBSNCASECMP GNULIB_MBSPCASECMP GNULIB_MBSCASESTR GNULIB_MBSCSPN GNULIB_MBSPBRK GNULIB_MBSSPN GNULIB_MBSSEP GNULIB_MBSTOK_R GNULIB_STRERROR GNULIB_STRSIGNAL HAVE_DECL_MEMMEM HAVE_MEMPCPY HAVE_DECL_MEMRCHR HAVE_STPCPY HAVE_STPNCPY HAVE_STRCHRNUL HAVE_DECL_STRDUP HAVE_STRNDUP HAVE_DECL_STRNDUP HAVE_DECL_STRNLEN HAVE_STRPBRK HAVE_STRSEP HAVE_STRCASESTR HAVE_DECL_STRTOK_R HAVE_DECL_STRERROR HAVE_DECL_STRSIGNAL REPLACE_STRERROR REPLACE_STRSIGNAL REPLACE_MEMMEM REPLACE_STRCASESTR REPLACE_STRSTR HAVE_LONG_LONG_INT HAVE_UNSIGNED_LONG_LONG_INT HAVE_INTTYPES_H HAVE_SYS_TYPES_H INCLUDE_NEXT NEXT_STDINT_H HAVE_STDINT_H HAVE_SYS_INTTYPES_H HAVE_SYS_BITYPES_H BITSIZEOF_PTRDIFF_T BITSIZEOF_SIG_ATOMIC_T BITSIZEOF_SIZE_T BITSIZEOF_WCHAR_T BITSIZEOF_WINT_T HAVE_SIGNED_SIG_ATOMIC_T HAVE_SIGNED_WCHAR_T HAVE_SIGNED_WINT_T PTRDIFF_T_SUFFIX SIG_ATOMIC_T_SUFFIX SIZE_T_SUFFIX WCHAR_T_SUFFIX WINT_T_SUFFIX STDINT_H NEXT_STRING_H GNULIB_WCWIDTH HAVE_DECL_WCWIDTH REPLACE_WCWIDTH WCHAR_H HAVE_WCHAR_H NEXT_WCHAR_H LIBGNU_LIBDEPS LIBGNU_LTLIBDEPS GNULIB_STDINT_H PACKAGE INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK AMTAR am__tar am__untar am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH am__fastdepCC_TRUE am__fastdepCC_FALSE GDB_DATADIR_PATH subdirs TARGET_OBS PKGVERSION REPORT_BUGS_TO REPORT_BUGS_TEXI LN_S YACC AR ac_ct_AR DLLTOOL ac_ct_DLLTOOL WINDRES ac_ct_WINDRES MIG ac_ct_MIG READLINE READLINE_DEPS READLINE_CFLAGS HAVE_LIBEXPAT LIBEXPAT LTLIBEXPAT PYTHON_CFLAGS ALLOCA CONFIG_LDFLAGS TARGET_SYSTEM_ROOT TARGET_SYSTEM_ROOT_DEFINE WARN_CFLAGS WERROR_CFLAGS SER_HARDWIRE WIN32LIBS LIBGUI GUI_CFLAGS_X WIN32LDAPP TCL_VERSION TCL_PATCH_LEVEL TCL_BIN_DIR TCL_SRC_DIR TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC TCL_INCLUDE TCL_LIBRARY TCL_DEPS TK_VERSION TK_BIN_DIR TK_SRC_DIR TK_LIB_FILE TK_LIB_FLAG TK_LIB_SPEC TK_STUB_LIB_FILE TK_STUB_LIB_FLAG TK_STUB_LIB_SPEC TK_INCLUDE TK_LIBRARY TK_DEPS TK_XINCLUDES X_CFLAGS X_LDFLAGS X_LIBS GDBTKLIBS GDBTK_CFLAGS GDBTK_SRC_DIR SIM SIM_OBS ENABLE_CFLAGS PROFILE_CFLAGS CONFIG_OBS CONFIG_DEPS CONFIG_SRCS CONFIG_ALL CONFIG_CLEAN CONFIG_INSTALL CONFIG_UNINSTALL target_subdir frags nm_h LIBICONV LIBOBJS LTLIBOBJS gl_LIBOBJS gl_LTLIBOBJS gltests_LIBOBJS gltests_LTLIBOBJS'
 ac_subst_files='host_makefile_frag'
 ac_pwd=`pwd`
 
@@ -882,6 +882,8 @@ Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
   --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
   --with-separate-debug-dir=path   Look for global separate debug info in this path LIBDIR/debug
+  --with-gdb-datadir      look for global separate data files in this path
+                          [DATADIR/gdb]
   --with-libunwind            Use libunwind frame unwinding support
   --with-pkgversion=PKG   Use PKG in the version string in place of "GDB"
   --with-bugurl=URL       Direct users to URL to report a bug
@@ -7130,6 +7132,52 @@ _ACEOF
   ;;
 esac
 
+# GDB's datadir relocation
+
+gdbdatadir=${datadir}/gdb
+
+
+# Check whether --with-gdb-datadir or --without-gdb-datadir was given.
+if test "${with_gdb_datadir+set}" = set; then
+  withval="$with_gdb_datadir"
+  gdbdatadir="${withval}"
+fi;
+
+
+  test "x$prefix" = xNONE && prefix="$ac_default_prefix"
+  test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+  ac_define_dir=`eval echo $gdbdatadir`
+  ac_define_dir=`eval echo $ac_define_dir`
+
+cat >>confdefs.h <<_ACEOF
+#define GDB_DATADIR "$ac_define_dir"
+_ACEOF
+
+
+
+if test "x$exec_prefix" = xNONE || test "x$exec_prefix" = 'x${prefix}'; then
+  if test "x$prefix" = xNONE; then
+    test_prefix=/usr/local
+  else
+    test_prefix=$prefix
+  fi
+else
+  test_prefix=$exec_prefix
+fi
+
+case ${gdbdatadir} in
+  "${test_prefix}"|"${test_prefix}/"*|\
+  '${exec_prefix}'|'${exec_prefix}/'*)
+
+cat >>confdefs.h <<\_ACEOF
+#define GDB_DATADIR_RELOCATABLE 1
+_ACEOF
+
+  ;;
+esac
+GDB_DATADIR_PATH=${gdbdatadir}
+
+
 
 
 subdirs="$subdirs doc testsuite"
@@ -21865,6 +21913,7 @@ s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t
 s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t
 s,@am__fastdepCC_TRUE@,$am__fastdepCC_TRUE,;t t
 s,@am__fastdepCC_FALSE@,$am__fastdepCC_FALSE,;t t
+s,@GDB_DATADIR_PATH@,$GDB_DATADIR_PATH,;t t
 s,@subdirs@,$subdirs,;t t
 s,@TARGET_OBS@,$TARGET_OBS,;t t
 s,@PKGVERSION@,$PKGVERSION,;t t
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -118,6 +118,36 @@ case ${debugdir} in
   ;;
 esac
 
+# GDB's datadir relocation
+
+gdbdatadir=${datadir}/gdb
+
+AC_ARG_WITH([gdb-datadir],
+  [AS_HELP_STRING([--with-gdb-datadir],
+                  [look for global separate data files in this path [DATADIR/gdb]])], [gdbdatadir="${withval}"])
+
+AC_DEFINE_DIR(GDB_DATADIR, gdbdatadir,
+              [Global directory for GDB data files. ])
+
+if test "x$exec_prefix" = xNONE || test "x$exec_prefix" = 'x${prefix}'; then
+  if test "x$prefix" = xNONE; then
+    test_prefix=/usr/local
+  else
+    test_prefix=$prefix
+  fi
+else
+  test_prefix=$exec_prefix
+fi
+
+case ${gdbdatadir} in
+  "${test_prefix}"|"${test_prefix}/"*|\
+  '${exec_prefix}'|'${exec_prefix}/'*)
+    AC_DEFINE(GDB_DATADIR_RELOCATABLE, 1, [Define if GDB datadir should be relocated when GDB is moved.])
+  ;;
+esac
+GDB_DATADIR_PATH=${gdbdatadir}
+AC_SUBST(GDB_DATADIR_PATH)
+
 AC_CONFIG_SUBDIRS(doc testsuite)
 
 # Check whether to support alternative target configurations
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -36,7 +36,7 @@ alpha*-*-osf*)
 alpha*-*-linux*)
 	# Target: Little-endian Alpha running Linux
 	gdb_target_obs="alpha-tdep.o alpha-mdebug-tdep.o alpha-linux-tdep.o \
-			solib.o solib-svr4.o"
+			solib.o solib-svr4.o linux-tdep.o"
 	;;
 alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu)
 	# Target: FreeBSD/alpha
@@ -63,7 +63,7 @@ alpha*-*-*)
 am33_2.0*-*-linux*)
 	# Target: Matsushita mn10300 (AM33) running Linux
 	gdb_target_obs="mn10300-tdep.o mn10300-linux-tdep.o corelow.o \
-			solib.o solib-svr4.o"
+			solib.o solib-svr4.o linux-tdep.o"
 	;;
 
 arm*-wince-pe | arm*-*-mingw32ce*)
@@ -128,7 +128,7 @@ hppa*-*-hpux*)
 hppa*-*-linux*)
 	# Target: HP PA-RISC running Linux
 	gdb_target_obs="hppa-tdep.o hppa-linux-tdep.o glibc-tdep.o \
-			solib.o solib-svr4.o symfile-mem.o"
+			solib.o solib-svr4.o symfile-mem.o linux-tdep.o"
 	;;
 hppa*-*-netbsd*)
 	# Target: NetBSD/hppa
@@ -218,7 +218,7 @@ i[34567]86-*-*)
 ia64-*-linux*)
 	# Target: Intel IA-64 running GNU/Linux
 	gdb_target_obs="ia64-tdep.o ia64-linux-tdep.o \
-			solib.o solib-svr4.o symfile-mem.o"
+			solib.o solib-svr4.o symfile-mem.o linux-tdep.o"
 	build_gdbserver=yes
 	;;
 ia64*-*-*)
@@ -242,7 +242,8 @@ m32c-*-*)
 m32r*-*-linux*)
 	# Target: Renesas M32R running GNU/Linux
 	gdb_target_obs="m32r-tdep.o m32r-linux-tdep.o remote-m32r-sdi.o \
-			glibc-tdep.o solib.o solib-svr4.o symfile-mem.o"
+			glibc-tdep.o solib.o solib-svr4.o symfile-mem.o \
+			linux-tdep.o"
 	gdb_sim=../sim/m32r/libsim.a
 	build_gdbserver=yes
 	;;
@@ -267,7 +268,7 @@ fido-*-elf*)
 m68*-*-linux*)
 	# Target: Motorola m68k with a.out and ELF
 	gdb_target_obs="m68k-tdep.o m68klinux-tdep.o solib.o solib-svr4.o \
-			glibc-tdep.o symfile-mem.o"
+			glibc-tdep.o symfile-mem.o linux-tdep.o"
 	build_gdbserver=yes
 	;;
 m68*-*-netbsd* | m68*-*-knetbsd*-gnu)
@@ -303,7 +304,8 @@ mips*-sgi-irix6*)
 mips*-*-linux*)
 	# Target: Linux/MIPS
 	gdb_target_obs="mips-tdep.o mips-linux-tdep.o glibc-tdep.o \
-			corelow.o solib.o solib-svr4.o symfile-mem.o"
+			corelow.o solib.o solib-svr4.o symfile-mem.o \
+			linux-tdep.o"
 	gdb_sim=../sim/mips/libsim.a
 	build_gdbserver=yes
 	;;
@@ -354,7 +356,8 @@ powerpc-*-aix* | rs6000-*-*)
 powerpc-*-linux* | powerpc64-*-linux*)
 	# Target: PowerPC running Linux
 	gdb_target_obs="rs6000-tdep.o ppc-linux-tdep.o ppc-sysv-tdep.o \
-			solib.o solib-svr4.o corelow.o symfile-mem.o"
+			solib.o solib-svr4.o corelow.o symfile-mem.o \
+			linux-tdep.o"
 	gdb_sim=../sim/ppc/libsim.a
 	build_gdbserver=yes
 	;;
@@ -381,7 +384,8 @@ score-*-*)
 sh*-*-linux*)
 	# Target: GNU/Linux Super-H
 	gdb_target_obs="sh-tdep.o sh64-tdep.o sh-linux-tdep.o monitor.o \
-			dsrec.o solib.o solib-svr4.o symfile-mem.o glibc-tdep.o"
+			dsrec.o solib.o solib-svr4.o symfile-mem.o glibc-tdep.o \
+			linux-tdep.o"
 	gdb_sim=../sim/sh/libsim.a
 	build_gdbserver=yes
 	;;
@@ -409,13 +413,14 @@ sh*)
 sparc-*-linux*)
 	# Target: GNU/Linux SPARC
 	gdb_target_obs="sparc-tdep.o sparc-sol2-tdep.o sol2-tdep.o \
-			sparc-linux-tdep.o solib.o solib-svr4.o symfile-mem.o"
+			sparc-linux-tdep.o solib.o solib-svr4.o symfile-mem.o \
+			linux-tdep.o"
 	;;
 sparc64-*-linux*)
 	# Target: GNU/Linux UltraSPARC
 	gdb_target_obs="sparc64-tdep.o sparc64-sol2-tdep.o sol2-tdep.o \
 			sparc64-linux-tdep.o sparc-tdep.o sparc-sol2-tdep.o \
-			sparc-linux-tdep.o solib.o solib-svr4.o"
+			sparc-linux-tdep.o solib.o solib-svr4.o linux-tdep.o"
 	build_gdbserver=yes
 	;;
 sparc*-*-freebsd* | sparc*-*-kfreebsd*-gnu)
@@ -542,7 +547,8 @@ x86_64-*-openbsd*)
 xtensa*-*-linux*)	gdb_target=linux
 	# Target: GNU/Linux Xtensa
 	gdb_target_obs="xtensa-tdep.o xtensa-config.o xtensa-linux-tdep.o \
-			solib.o solib-svr4.o corelow.o symfile-mem.o"
+			solib.o solib-svr4.o corelow.o symfile-mem.o \
+			linux-tdep.o"
 	build_gdbserver=yes
 	;;
 xtensa*)
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -3636,6 +3636,98 @@ A failed Ada assertion.
 A call to @code{exec}.  This is currently only available for HP-UX
 and @sc{gnu}/Linux.
 
+@item syscall
+@itemx syscall @r{[}@var{name} @r{|} @var{number}@r{]} @r{...}
+@cindex break on a system call.
+A call to or return from a @code{syscall}.  If no argument is specified,
+then it catches a call to or return from any system call.
+
+@var{name} can be any valid system call name in the system.  You can
+use the @value{GDBN} command-line completion facilities to list the
+available choices.  @xref{Completion,, Command Completion}, for
+details on how to do this.
+
+You may also specify the system call numerically.  This may be useful
+if @value{GDBN} does not fully support your system's list of system
+calls.
+
+The example below illustrates how this command works if you don't provide
+arguments to it:
+
+@smallexample
+(@value{GDBP}) catch syscall
+Catchpoint 1 (syscall)
+(@value{GDBP}) r
+Starting program: /tmp/catch-syscall
+
+Catchpoint 1 (call to syscall 'close'), 0xffffe424 in __kernel_vsyscall ()
+(@value{GDBP}) c
+Continuing.
+
+Catchpoint 1 (returned from syscall 'close'), 0xffffe424 in __kernel_vsyscall ()
+(@value{GDBP})
+@end smallexample
+
+Here is an example of catching a system call by name:
+
+@smallexample
+(@value{GDBP}) catch syscall chroot
+Catchpoint 1 (syscall(s) 'chroot')
+(@value{GDBP}) r
+Starting program: /tmp/catch-syscall
+
+Catchpoint 1 (call to syscall 'chroot'), 0xffffe424 in __kernel_vsyscall ()
+(@value{GDBP}) c
+Continuing.
+
+Catchpoint 1 (returned from syscall 'chroot'), 0xffffe424 in __kernel_vsyscall ()
+(@value{GDBP})
+@end smallexample
+
+And last but not least, an example of specifying a system call
+numerically:
+
+@smallexample
+(@value{GDBP}) catch syscall 252
+Catchpoint 1 (syscall(s) 'exit_group')
+(@value{GDBP}) r
+Starting program: /tmp/catch-syscall
+
+Catchpoint 1 (call to syscall 'exit_group'), 0xffffe424 in __kernel_vsyscall ()
+(@value{GDBP}) c
+Continuing.
+
+Program exited normally.
+(@value{GDBP})
+@end smallexample
+
+If you configure @value{GDBN} using the @samp{--without-expat} option,
+it will not be able to display syscall names.  Also, if your
+architecture does not have an XML file describing its system calls,
+you will not be able to see the syscall names.  In either case, you
+will see a warning like this:
+
+@smallexample
+(@value{GDBP}) catch syscall
+warning: Could not open "syscalls/i386-linux.xml"
+warning: Could not load the syscall XML file 'syscalls/i386-linux.xml'.
+GDB will not be able to display syscall names.
+Catchpoint 1 (syscall)
+(@value{GDBP})
+@end smallexample
+
+Of course, the file name will change depending on your architecture and system.
+
+Still using the example above, you can also try to catch a syscall by its
+number.  In this case, you would see something like:
+
+@smallexample
+(@value{GDBP}) catch syscall 252
+Catchpoint 1 (syscall(s) 252)
+@end smallexample
+
+Again, in this case @value{GDBN} would not be able to display syscall's names.
+
 @item fork
 A call to @code{fork}.  This is currently only available for HP-UX
 and @sc{gnu}/Linux.
--- a/gdb/testsuite/gdb.base/Makefile.in
+++ b/gdb/testsuite/gdb.base/Makefile.in
@@ -12,7 +12,7 @@ EXECUTABLES = all-types annota1 bitfield
 	scope section_command setshow setvar shmain sigall signals \
 	solib solib_sl so-impl-ld so-indr-cl \
 	step-line step-test structs structs2 \
-	twice-tmp varargs vforked-prog watchpoint whatis
+	twice-tmp varargs vforked-prog watchpoint whatis catch-syscall
 
 MISCELLANEOUS = coremmap.data ../foobar.baz \
 	shr1.sl shr2.sl solib_sl.sl solib1.sl solib2.sl
--- /dev/null
+++ b/gdb/testsuite/gdb.base/catch-syscall.c
@@ -0,0 +1,25 @@
+/* This file is used to test the 'catch syscall' feature on GDB.
+
+   Please, if you are going to edit this file DO NOT change the syscalls
+   being called (nor the order of them).  If you really must do this, then
+   take a look at catch-syscall.exp and modify there too.
+
+   Written by Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com>
+   September, 2008 */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+int
+main (void)
+{
+	/* A close() with a wrong argument.  We are only
+	   interested in the syscall.  */
+	close (-1);
+
+	chroot (".");
+
+	/* The last syscall.  Do not change this.  */
+	_exit (0);
+}
--- /dev/null
+++ b/gdb/testsuite/gdb.base/catch-syscall.exp
@@ -0,0 +1,386 @@
+#   Copyright 1997, 1999, 2007, 2008 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+# This program tests the 'catch syscall' functionality.
+#
+# It was written by Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com>
+# on September/2008.
+
+if { [is_remote target] || ![isnative] } then {
+    continue
+}
+
+set prms_id 0
+set bug_id 0
+
+global srcfile
+set testfile "catch-syscall"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+# All (but the last) syscalls from the example code
+# They are ordered according to the file, so do not change this.
+set all_syscalls { "close" "chroot" }
+# The last syscall (exit()) does not return, so
+# we cannot expect the catchpoint to be triggered
+# twice.  It is a special case.
+set last_syscall "exit_group"
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+     untested catch-syscall.exp
+     return -1
+}
+
+# Until "catch syscall" is implemented on other targets...
+if {![istarget "hppa*-hp-hpux*"] && ![istarget "*-linux*"]} then {
+    continue
+}
+
+# This shall be updated whenever 'catch syscall' is implemented
+# on some architecture.
+#if { ![istarget "x86_64-*-linux*"] && ![istarget "i\[34567\]86-*-linux*"]
+if { ![istarget "i\[34567\]86-*-linux*"]
+     && ![istarget "powerpc-*-linux*"] && ![istarget "powerpc64-*-linux*"] } {
+     continue
+}
+
+# Internal procedure used to check if, before any syscall is caught,
+# the command 'info breakpoints' correctly lists the catchpoints AND
+# says that nothing was caught yet.
+proc check_init_info_breakpoints {} {
+    global gdb_prompt
+
+    # Verifying that the catchpoint appears in the 'info breakpoints'
+    # command, but with "<any syscall>".
+    set thistest "catch syscall appears in 'info breakpoints'"
+    gdb_test "info breakpoints" ".*catchpoint.*keep y.*syscall \"<any syscall>\".*" $thistest
+}
+
+# This procedure checks if, after a syscall catchpoint is hit, the
+# command 'info breakpoints' correctly lists the syscall name.
+proc check_info_breakpoints { syscall } {
+    global gdb_prompt
+
+    set thistest "syscall $syscall appears in 'info breakpoints'"
+    gdb_test "info breakpoints" ".*catchpoint.*keep y.*syscall (.)?${syscall}(.)?.*" $thistest
+}
+
+# This procedure checks if there was a call to a syscall.
+proc check_call_to_syscall { syscall } {
+    global gdb_prompt
+
+    set thistest "program has called $syscall"
+    gdb_test "continue" "Catchpoint .*(call to syscall .?${syscall}.?).*" $thistest
+
+    # Checking if the syscall is reported to be caught in
+    # 'info breakpoints'.
+    check_info_breakpoints "$syscall"
+}
+
+# This procedure checks if the syscall returned.
+proc check_return_from_syscall { syscall } {
+    global gdb_prompt
+
+    set thistest "syscall $syscall has returned"
+    gdb_test "continue" "Catchpoint .*(returned from syscall (.)?${syscall}(.)?).*" $thistest
+
+    # Checking if the syscall is reported to be caught in
+    # 'info breakpoints'.
+    check_info_breakpoints "$syscall"
+}
+
+# Internal procedure that performs two 'continue' commands and checks if
+# a syscall call AND return occur.
+proc check_continue { syscall } {
+    global gdb_prompt
+
+    # Testing if the 'continue' stops at the
+    # specified syscall_name.  If it does, then it should
+    # first print that the infeior has called the syscall,
+    # and after print that the syscall has returned.
+
+    # Testing if the inferiorr has called the syscall.
+    check_call_to_syscall $syscall
+    # And now, that the syscall has returned.
+    check_return_from_syscall $syscall
+}
+
+# Inserts a syscall catchpoint with an argument.
+proc insert_catch_syscall_with_arg { syscall } {
+    global gdb_prompt
+
+    # Trying to set the syscall
+    set thistest "catch syscall with arguments ($syscall)"
+    gdb_test "catch syscall $syscall" "Catchpoint .*(syscall\[(\]s\[)\] (.)?${syscall}(.)?).*" $thistest
+}
+
+proc check_for_program_end {} {
+    global gdb_prompt
+
+    # Deleting the catchpoints
+    delete_breakpoints
+
+    set thistest "successful program end"
+    gdb_test "continue" "Program exited normally.*" $thistest
+
+}
+
+proc test_catch_syscall_without_args {} {
+    global gdb_prompt all_syscalls last_syscall
+
+    # Trying to set the syscall
+    set thistest "setting catch syscall without arguments"
+    gdb_test "catch syscall" "Catchpoint .*(syscall).*" $thistest
+
+    check_init_info_breakpoints
+
+    # We have to check every syscall
+    foreach name $all_syscalls {
+        check_continue $name
+    }
+
+    # At last but not least, we check if the inferior
+    # has called the last (exit) syscall.
+    check_call_to_syscall $last_syscall
+
+    # Now let's see if the inferior correctly finishes.
+    check_for_program_end
+}
+
+proc test_catch_syscall_with_args {} {
+    global gdb_prompt
+    set syscall_name "close"
+
+    insert_catch_syscall_with_arg $syscall_name
+    check_init_info_breakpoints
+
+    # Can we continue until we catch the syscall?
+    check_continue $syscall_name
+
+    # Now let's see if the inferior correctly finishes.
+    check_for_program_end
+}
+
+proc test_catch_syscall_with_wrong_args {} {
+    global gdb_prompt
+    # mlock is not called from the source
+    set syscall_name "mlock"
+
+    insert_catch_syscall_with_arg $syscall_name
+    check_init_info_breakpoints
+
+    # Now, we must verify if the program stops with a continue.
+    # If it doesn't, everything is right (since we don't have
+    # a syscall named "mlock" in it).  Otherwise, this is a failure.
+    set thistest "catch syscall with unused syscall ($syscall_name)"
+    gdb_test "continue" "Program exited normally.*" $thistest
+}
+
+proc test_catch_syscall_restarting_inferior {} {
+    global gdb_prompt
+    set syscall_name "chroot"
+
+    insert_catch_syscall_with_arg $syscall_name
+    check_init_info_breakpoints
+
+    # Let's first reach the call of the syscall.
+    check_call_to_syscall $syscall_name
+
+    # Now, restart the program
+    rerun_to_main
+
+    # And check for call/return
+    check_continue $syscall_name
+
+    # Can we finish?
+    check_for_program_end
+}
+
+proc do_syscall_tests {} {
+    global gdb_prompt srcdir
+
+    # First, we need to set GDB datadir.
+    send_gdb "maintenance set gdb_datadir $srcdir/..\n"
+    gdb_expect 10 {
+	-re "$gdb_prompt $" {
+	    verbose "Setting GDB datadir to $srcdir/..." 2
+	}
+	timeout {
+	    error "Couldn't set GDB datadir."
+	}
+    }
+
+    # Verify that the 'catch syscall' help is available
+    set thistest "help catch syscall"
+    gdb_test "help catch syscall" "Catch system calls.*" $thistest
+
+    # Try to set a catchpoint to a nonsense syscall
+    set thistest "catch syscall to a nonsense syscall is prohibited"
+    gdb_test "catch syscall nonsense_syscall" "Unknown syscall name .*" $thistest
+
+    # Testing the 'catch syscall' command without arguments.
+    # This test should catch any syscalls.
+    if [runto_main] then { test_catch_syscall_without_args }
+
+    # Testing the 'catch syscall' command with arguments.
+    # This test should only catch the specified syscall.
+    if [runto_main] then { test_catch_syscall_with_args }
+
+    # Testing the 'catch syscall' command with WRONG arguments.
+    # This test should not trigger any catchpoints.
+    if [runto_main] then { test_catch_syscall_with_wrong_args }
+
+    # Testing the 'catch' syscall command during a restart of
+    # the inferior.
+    if [runto_main] then { test_catch_syscall_restarting_inferior }
+}
+
+proc test_catch_syscall_fail_noxml {} {
+    global gdb_prompt
+
+    # Sanitizing.
+    delete_breakpoints
+
+    # Testing to see if we receive a warning when calling "catch syscall"
+    # without XML support.
+    set thistest "Catch syscall displays a warning when there is no XML support"
+    gdb_test "catch syscall" "warning: Could not open .*warning: Could not load the syscall XML file .*GDB will not be able to display syscall names.*Catchpoint .*(syscall).*" $thistest
+
+    # Since the catchpoint was set, we must check if it's present at
+    # "info breakpoints"
+    check_init_info_breakpoints
+
+    # Sanitizing.
+    delete_breakpoints
+}
+
+proc test_catch_syscall_without_args_noxml {} {
+    # We will need the syscall names even not using it
+    # because we need to know know many syscalls are in
+    # the example file.
+    global gdb_prompt all_syscalls last_syscall
+
+    delete_breakpoints
+
+    set thistest "Catch syscall without arguments and without XML support"
+    gdb_test "catch syscall" "Catchpoint .*(syscall).*"
+
+    # Now, we should be able to set a catchpoint,
+    # and GDB shall not display the warning anymore.
+    foreach name $all_syscalls {
+        # Unfortunately, we don't know the syscall number
+        # that will be caught because this information is
+        # arch-dependent.  Thus, we try to catch anything
+        # similar to a number.
+        check_continue "\[0-9\]*"
+    }
+
+    # At last but not least, we check if the inferior
+    # has called the last (exit) syscall.
+    check_call_to_syscall "\[0-9\]*"
+
+    delete_breakpoints
+}
+
+proc test_catch_syscall_with_args_noxml {} {
+    global gdb_prompt
+
+    # The number of the "close" syscall.  This is our
+    # options for a "long-estabilished" syscall in all
+    # Linux architectures, but unfortunately x86_64 and
+    # a few other platforms don't "follow the convention".
+    # Because of this, we need this ugly check :-(.
+    set close_number ""
+    if { [istarget "x86_64-*-linux*"] } {
+        set close_number "3"
+    } else {
+        set close_number "6"
+    }
+
+    delete_breakpoints
+
+    insert_catch_syscall_with_arg $close_number
+    check_init_info_breakpoints
+
+    check_continue $close_number
+
+    delete_breakpoints
+}
+
+proc test_catch_syscall_with_wrong_args_noxml {} {
+    global gdb_prompt
+
+    delete_breakpoints
+
+    # Even without XML support, GDB should not accept unknown
+    # syscall names for the catchpoint.
+    set thistest "Catch a nonsense syscall without XML support"
+    gdb_test "catch syscall nonsense_syscall" "Unknown syscall name .nonsense_syscall.*" $thistest
+
+    delete_breakpoints
+}
+
+proc do_syscall_tests_without_xml {} {
+    global gdb_prompt srcdir
+
+    # In this case, we don't need to set GDB's datadir because
+    # we want GDB to display only numbers, not names.  So, let's
+    # begin with the tests.
+
+    # The first test is to see if GDB displays a warning when we
+    # try to catch syscalls without the XML support.
+    test_catch_syscall_fail_noxml
+
+    # Now, let's test if we can catch syscalls without XML support.
+    # We should succeed, but GDB is not supposed to print syscall names.
+    if [runto_main] then { test_catch_syscall_without_args_noxml }
+
+    # The only valid argument "catch syscall" should accept is the
+    # syscall number, and not the name (since it can't translate a
+    # name to a number).
+    #
+    # It's worth mentioning that we only try to catch the syscall
+    # close().  This is because the syscall number is an arch-dependent
+    # information, so we can't assume that we know every syscall number
+    # in this system.  Therefore, we have decided to use a "long-estabilished"
+    # system call, and close() just sounded the right choice :-).
+    if [runto_main] then { test_catch_syscall_with_args_noxml }
+
+    # Now, we'll try to provide a syscall name (valid or not) to the command,
+    # and expect it to fail.
+    if [runto_main] then { test_catch_syscall_with_wrong_args_noxml }
+}
+
+# Start with a fresh gdb
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# Execute the tests, using XML support
+do_syscall_tests
+
+# Restart gdb
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# Execute the tests, without XML support.  In this case, GDB will
+# only display syscall numbers, and not syscall names.
+do_syscall_tests_without_xml
diff --git a/gdb/syscalls/gdb-syscalls.dtd b/gdb/syscalls/gdb-syscalls.dtd
new file mode 100644
index 0000000..0d40ab4
--- /dev/null
+++ b/gdb/syscalls/gdb-syscalls.dtd
@@ -0,0 +1,21 @@
+<!-- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!-- The root element of a syscall info is <syscalls_info>.  -->
+
+<!ELEMENT syscalls_info		(syscall*)>
+
+<!-- Maybe the 'number' attribute will have to be changed from
+     ID to CDATA.  -->
+<!ELEMENT syscall		EMPTY>
+<!ATTLIST syscall
+	name			CDATA	#REQUIRED
+	number			ID	#REQUIRED>
+
+<!ELEMENT xi:include	(EMPTY)>
+<!ATTLIST xi:include
+	xmlns:xi	CDATA	#FIXED "http://www.w3.org/2001/XInclude";
+	href		CDATA	#REQUIRED>
diff --git a/gdb/syscalls/i386-linux.xml b/gdb/syscalls/i386-linux.xml
new file mode 100644
index 0000000..8044c7b
--- /dev/null
+++ b/gdb/syscalls/i386-linux.xml
@@ -0,0 +1,337 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-syscalls.dtd">
+
+<syscalls_info>
+  <syscall name="restart_syscall" number="0"/>
+  <syscall name="exit" number="1"/>
+  <syscall name="fork" number="2"/>
+  <syscall name="read" number="3"/>
+  <syscall name="write" number="4"/>
+  <syscall name="open" number="5"/>
+  <syscall name="close" number="6"/>
+  <syscall name="waitpid" number="7"/>
+  <syscall name="creat" number="8"/>
+  <syscall name="link" number="9"/>
+  <syscall name="unlink" number="10"/>
+  <syscall name="execve" number="11"/>
+  <syscall name="chdir" number="12"/>
+  <syscall name="time" number="13"/>
+  <syscall name="mknod" number="14"/>
+  <syscall name="chmod" number="15"/>
+  <syscall name="lchown" number="16"/>
+  <syscall name="break" number="17"/>
+  <syscall name="oldstat" number="18"/>
+  <syscall name="lseek" number="19"/>
+  <syscall name="getpid" number="20"/>
+  <syscall name="mount" number="21"/>
+  <syscall name="umount" number="22"/>
+  <syscall name="setuid" number="23"/>
+  <syscall name="getuid" number="24"/>
+  <syscall name="stime" number="25"/>
+  <syscall name="ptrace" number="26"/>
+  <syscall name="alarm" number="27"/>
+  <syscall name="oldfstat" number="28"/>
+  <syscall name="pause" number="29"/>
+  <syscall name="utime" number="30"/>
+  <syscall name="stty" number="31"/>
+  <syscall name="gtty" number="32"/>
+  <syscall name="access" number="33"/>
+  <syscall name="nice" number="34"/>
+  <syscall name="ftime" number="35"/>
+  <syscall name="sync" number="36"/>
+  <syscall name="kill" number="37"/>
+  <syscall name="rename" number="38"/>
+  <syscall name="mkdir" number="39"/>
+  <syscall name="rmdir" number="40"/>
+  <syscall name="dup" number="41"/>
+  <syscall name="pipe" number="42"/>
+  <syscall name="times" number="43"/>
+  <syscall name="prof" number="44"/>
+  <syscall name="brk" number="45"/>
+  <syscall name="setgid" number="46"/>
+  <syscall name="getgid" number="47"/>
+  <syscall name="signal" number="48"/>
+  <syscall name="geteuid" number="49"/>
+  <syscall name="getegid" number="50"/>
+  <syscall name="acct" number="51"/>
+  <syscall name="umount2" number="52"/>
+  <syscall name="lock" number="53"/>
+  <syscall name="ioctl" number="54"/>
+  <syscall name="fcntl" number="55"/>
+  <syscall name="mpx" number="56"/>
+  <syscall name="setpgid" number="57"/>
+  <syscall name="ulimit" number="58"/>
+  <syscall name="oldolduname" number="59"/>
+  <syscall name="umask" number="60"/>
+  <syscall name="chroot" number="61"/>
+  <syscall name="ustat" number="62"/>
+  <syscall name="dup2" number="63"/>
+  <syscall name="getppid" number="64"/>
+  <syscall name="getpgrp" number="65"/>
+  <syscall name="setsid" number="66"/>
+  <syscall name="sigaction" number="67"/>
+  <syscall name="sgetmask" number="68"/>
+  <syscall name="ssetmask" number="69"/>
+  <syscall name="setreuid" number="70"/>
+  <syscall name="setregid" number="71"/>
+  <syscall name="sigsuspend" number="72"/>
+  <syscall name="sigpending" number="73"/>
+  <syscall name="sethostname" number="74"/>
+  <syscall name="setrlimit" number="75"/>
+  <syscall name="getrlimit" number="76"/>
+  <syscall name="getrusage" number="77"/>
+  <syscall name="gettimeofday" number="78"/>
+  <syscall name="settimeofday" number="79"/>
+  <syscall name="getgroups" number="80"/>
+  <syscall name="setgroups" number="81"/>
+  <syscall name="select" number="82"/>
+  <syscall name="symlink" number="83"/>
+  <syscall name="oldlstat" number="84"/>
+  <syscall name="readlink" number="85"/>
+  <syscall name="uselib" number="86"/>
+  <syscall name="swapon" number="87"/>
+  <syscall name="reboot" number="88"/>
+  <syscall name="readdir" number="89"/>
+  <syscall name="mmap" number="90"/>
+  <syscall name="munmap" number="91"/>
+  <syscall name="truncate" number="92"/>
+  <syscall name="ftruncate" number="93"/>
+  <syscall name="fchmod" number="94"/>
+  <syscall name="fchown" number="95"/>
+  <syscall name="getpriority" number="96"/>
+  <syscall name="setpriority" number="97"/>
+  <syscall name="profil" number="98"/>
+  <syscall name="statfs" number="99"/>
+  <syscall name="fstatfs" number="100"/>
+  <syscall name="ioperm" number="101"/>
+  <syscall name="socketcall" number="102"/>
+  <syscall name="syslog" number="103"/>
+  <syscall name="setitimer" number="104"/>
+  <syscall name="getitimer" number="105"/>
+  <syscall name="stat" number="106"/>
+  <syscall name="lstat" number="107"/>
+  <syscall name="fstat" number="108"/>
+  <syscall name="olduname" number="109"/>
+  <syscall name="iopl" number="110"/>
+  <syscall name="vhangup" number="111"/>
+  <syscall name="idle" number="112"/>
+  <syscall name="vm86old" number="113"/>
+  <syscall name="wait4" number="114"/>
+  <syscall name="swapoff" number="115"/>
+  <syscall name="sysinfo" number="116"/>
+  <syscall name="ipc" number="117"/>
+  <syscall name="fsync" number="118"/>
+  <syscall name="sigreturn" number="119"/>
+  <syscall name="clone" number="120"/>
+  <syscall name="setdomainname" number="121"/>
+  <syscall name="uname" number="122"/>
+  <syscall name="modify_ldt" number="123"/>
+  <syscall name="adjtimex" number="124"/>
+  <syscall name="mprotect" number="125"/>
+  <syscall name="sigprocmask" number="126"/>
+  <syscall name="create_module" number="127"/>
+  <syscall name="init_module" number="128"/>
+  <syscall name="delete_module" number="129"/>
+  <syscall name="get_kernel_syms" number="130"/>
+  <syscall name="quotactl" number="131"/>
+  <syscall name="getpgid" number="132"/>
+  <syscall name="fchdir" number="133"/>
+  <syscall name="bdflush" number="134"/>
+  <syscall name="sysfs" number="135"/>
+  <syscall name="personality" number="136"/>
+  <syscall name="afs_syscall" number="137"/>
+  <syscall name="setfsuid" number="138"/>
+  <syscall name="setfsgid" number="139"/>
+  <syscall name="_llseek" number="140"/>
+  <syscall name="getdents" number="141"/>
+  <syscall name="_newselect" number="142"/>
+  <syscall name="flock" number="143"/>
+  <syscall name="msync" number="144"/>
+  <syscall name="readv" number="145"/>
+  <syscall name="writev" number="146"/>
+  <syscall name="getsid" number="147"/>
+  <syscall name="fdatasync" number="148"/>
+  <syscall name="_sysctl" number="149"/>
+  <syscall name="mlock" number="150"/>
+  <syscall name="munlock" number="151"/>
+  <syscall name="mlockall" number="152"/>
+  <syscall name="munlockall" number="153"/>
+  <syscall name="sched_setparam" number="154"/>
+  <syscall name="sched_getparam" number="155"/>
+  <syscall name="sched_setscheduler" number="156"/>
+  <syscall name="sched_getscheduler" number="157"/>
+  <syscall name="sched_yield" number="158"/>
+  <syscall name="sched_get_priority_max" number="159"/>
+  <syscall name="sched_get_priority_min" number="160"/>
+  <syscall name="sched_rr_get_interval" number="161"/>
+  <syscall name="nanosleep" number="162"/>
+  <syscall name="mremap" number="163"/>
+  <syscall name="setresuid" number="164"/>
+  <syscall name="getresuid" number="165"/>
+  <syscall name="vm86" number="166"/>
+  <syscall name="query_module" number="167"/>
+  <syscall name="poll" number="168"/>
+  <syscall name="nfsservctl" number="169"/>
+  <syscall name="setresgid" number="170"/>
+  <syscall name="getresgid" number="171"/>
+  <syscall name="prctl" number="172"/>
+  <syscall name="rt_sigreturn" number="173"/>
+  <syscall name="rt_sigaction" number="174"/>
+  <syscall name="rt_sigprocmask" number="175"/>
+  <syscall name="rt_sigpending" number="176"/>
+  <syscall name="rt_sigtimedwait" number="177"/>
+  <syscall name="rt_sigqueueinfo" number="178"/>
+  <syscall name="rt_sigsuspend" number="179"/>
+  <syscall name="pread64" number="180"/>
+  <syscall name="pwrite64" number="181"/>
+  <syscall name="chown" number="182"/>
+  <syscall name="getcwd" number="183"/>
+  <syscall name="capget" number="184"/>
+  <syscall name="capset" number="185"/>
+  <syscall name="sigaltstack" number="186"/>
+  <syscall name="sendfile" number="187"/>
+  <syscall name="getpmsg" number="188"/>
+  <syscall name="putpmsg" number="189"/>
+  <syscall name="vfork" number="190"/>
+  <syscall name="ugetrlimit" number="191"/>
+  <syscall name="mmap2" number="192"/>
+  <syscall name="truncate64" number="193"/>
+  <syscall name="ftruncate64" number="194"/>
+  <syscall name="stat64" number="195"/>
+  <syscall name="lstat64" number="196"/>
+  <syscall name="fstat64" number="197"/>
+  <syscall name="lchown32" number="198"/>
+  <syscall name="getuid32" number="199"/>
+  <syscall name="getgid32" number="200"/>
+  <syscall name="geteuid32" number="201"/>
+  <syscall name="getegid32" number="202"/>
+  <syscall name="setreuid32" number="203"/>
+  <syscall name="setregid32" number="204"/>
+  <syscall name="getgroups32" number="205"/>
+  <syscall name="setgroups32" number="206"/>
+  <syscall name="fchown32" number="207"/>
+  <syscall name="setresuid32" number="208"/>
+  <syscall name="getresuid32" number="209"/>
+  <syscall name="setresgid32" number="210"/>
+  <syscall name="getresgid32" number="211"/>
+  <syscall name="chown32" number="212"/>
+  <syscall name="setuid32" number="213"/>
+  <syscall name="setgid32" number="214"/>
+  <syscall name="setfsuid32" number="215"/>
+  <syscall name="setfsgid32" number="216"/>
+  <syscall name="pivot_root" number="217"/>
+  <syscall name="mincore" number="218"/>
+  <syscall name="madvise" number="219"/>
+  <syscall name="madvise1" number="220"/>
+  <syscall name="getdents64" number="221"/>
+  <syscall name="fcntl64" number="222"/>
+  <syscall name="" number="223"/>
+  <syscall name="gettid" number="224"/>
+  <syscall name="readahead" number="225"/>
+  <syscall name="setxattr" number="226"/>
+  <syscall name="lsetxattr" number="227"/>
+  <syscall name="fsetxattr" number="228"/>
+  <syscall name="getxattr" number="229"/>
+  <syscall name="lgetxattr" number="230"/>
+  <syscall name="fgetxattr" number="231"/>
+  <syscall name="listxattr" number="232"/>
+  <syscall name="llistxattr" number="233"/>
+  <syscall name="flistxattr" number="234"/>
+  <syscall name="removexattr" number="235"/>
+  <syscall name="lremovexattr" number="236"/>
+  <syscall name="fremovexattr" number="237"/>
+  <syscall name="tkill" number="238"/>
+  <syscall name="sendfile64" number="239"/>
+  <syscall name="futex" number="240"/>
+  <syscall name="sched_setaffinity" number="241"/>
+  <syscall name="sched_getaffinity" number="242"/>
+  <syscall name="set_thread_area" number="243"/>
+  <syscall name="get_thread_area" number="244"/>
+  <syscall name="io_setup" number="245"/>
+  <syscall name="io_destroy" number="246"/>
+  <syscall name="io_getevents" number="247"/>
+  <syscall name="io_submit" number="248"/>
+  <syscall name="io_cancel" number="249"/>
+  <syscall name="fadvise64" number="250"/>
+  <syscall name="" number="251"/>
+  <syscall name="exit_group" number="252"/>
+  <syscall name="lookup_dcookie" number="253"/>
+  <syscall name="epoll_create" number="254"/>
+  <syscall name="epoll_ctl" number="255"/>
+  <syscall name="epoll_wait" number="256"/>
+  <syscall name="remap_file_pages" number="257"/>
+  <syscall name="set_tid_address" number="258"/>
+  <syscall name="timer_create" number="259"/>
+  <syscall name="timer_settime" number="260"/>
+  <syscall name="timer_gettime" number="261"/>
+  <syscall name="timer_getoverrun" number="262"/>
+  <syscall name="timer_delete" number="263"/>
+  <syscall name="clock_settime" number="264"/>
+  <syscall name="clock_gettime" number="265"/>
+  <syscall name="clock_getres" number="266"/>
+  <syscall name="clock_nanosleep" number="267"/>
+  <syscall name="statfs64" number="268"/>
+  <syscall name="fstatfs64" number="269"/>
+  <syscall name="tgkill" number="270"/>
+  <syscall name="utimes" number="271"/>
+  <syscall name="fadvise64_64" number="272"/>
+  <syscall name="vserver" number="273"/>
+  <syscall name="mbind" number="274"/>
+  <syscall name="get_mempolicy" number="275"/>
+  <syscall name="set_mempolicy" number="276"/>
+  <syscall name="mq_open" number="277"/>
+  <syscall name="mq_unlink" number="278"/>
+  <syscall name="mq_timedsend" number="279"/>
+  <syscall name="mq_timedreceive" number="280"/>
+  <syscall name="mq_notify" number="281"/>
+  <syscall name="mq_getsetattr" number="282"/>
+  <syscall name="kexec_load" number="283"/>
+  <syscall name="waitid" number="284"/>
+  <syscall name="" number="285"/>
+  <syscall name="add_key" number="286"/>
+  <syscall name="request_key" number="287"/>
+  <syscall name="keyctl" number="288"/>
+  <syscall name="ioprio_set" number="289"/>
+  <syscall name="ioprio_get" number="290"/>
+  <syscall name="inotify_init" number="291"/>
+  <syscall name="inotify_add_watch" number="292"/>
+  <syscall name="inotify_rm_watch" number="293"/>
+  <syscall name="migrate_pages" number="294"/>
+  <syscall name="openat" number="295"/>
+  <syscall name="mkdirat" number="296"/>
+  <syscall name="mknodat" number="297"/>
+  <syscall name="fchownat" number="298"/>
+  <syscall name="futimesat" number="299"/>
+  <syscall name="fstatat64" number="300"/>
+  <syscall name="unlinkat" number="301"/>
+  <syscall name="renameat" number="302"/>
+  <syscall name="linkat" number="303"/>
+  <syscall name="symlinkat" number="304"/>
+  <syscall name="readlinkat" number="305"/>
+  <syscall name="fchmodat" number="306"/>
+  <syscall name="faccessat" number="307"/>
+  <syscall name="pselect6" number="308"/>
+  <syscall name="ppoll" number="309"/>
+  <syscall name="unshare" number="310"/>
+  <syscall name="set_robust_list" number="311"/>
+  <syscall name="get_robust_list" number="312"/>
+  <syscall name="splice" number="313"/>
+  <syscall name="sync_file_range" number="314"/>
+  <syscall name="tee" number="315"/>
+  <syscall name="vmsplice" number="316"/>
+  <syscall name="move_pages" number="317"/>
+  <syscall name="getcpu" number="318"/>
+  <syscall name="epoll_pwait" number="319"/>
+  <syscall name="utimensat" number="320"/>
+  <syscall name="signalfd" number="321"/>
+  <syscall name="timerfd_create" number="322"/>
+  <syscall name="eventfd" number="323"/>
+  <syscall name="fallocate" number="324"/>
+  <syscall name="timerfd_settime" number="325"/>
+</syscalls_info>
diff --git a/gdb/syscalls/ppc-linux.xml b/gdb/syscalls/ppc-linux.xml
new file mode 100644
index 0000000..4ac794f
--- /dev/null
+++ b/gdb/syscalls/ppc-linux.xml
@@ -0,0 +1,312 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-syscalls.dtd">
+
+<syscalls_info>
+  <syscall name="restart_syscall" number="0"/>
+  <syscall name="exit" number="1"/>
+  <syscall name="fork" number="2"/>
+  <syscall name="read" number="3"/>
+  <syscall name="write" number="4"/>
+  <syscall name="open" number="5"/>
+  <syscall name="close" number="6"/>
+  <syscall name="waitpid" number="7"/>
+  <syscall name="creat" number="8"/>
+  <syscall name="link" number="9"/>
+  <syscall name="unlink" number="10"/>
+  <syscall name="execve" number="11"/>
+  <syscall name="chdir" number="12"/>
+  <syscall name="time" number="13"/>
+  <syscall name="mknod" number="14"/>
+  <syscall name="chmod" number="15"/>
+  <syscall name="lchown" number="16"/>
+  <syscall name="break" number="17"/>
+  <syscall name="oldstat" number="18"/>
+  <syscall name="lseek" number="19"/>
+  <syscall name="getpid" number="20"/>
+  <syscall name="mount" number="21"/>
+  <syscall name="umount" number="22"/>
+  <syscall name="setuid" number="23"/>
+  <syscall name="getuid" number="24"/>
+  <syscall name="stime" number="25"/>
+  <syscall name="ptrace" number="26"/>
+  <syscall name="alarm" number="27"/>
+  <syscall name="oldfstat" number="28"/>
+  <syscall name="pause" number="29"/>
+  <syscall name="utime" number="30"/>
+  <syscall name="stty" number="31"/>
+  <syscall name="gtty" number="32"/>
+  <syscall name="access" number="33"/>
+  <syscall name="nice" number="34"/>
+  <syscall name="ftime" number="35"/>
+  <syscall name="sync" number="36"/>
+  <syscall name="kill" number="37"/>
+  <syscall name="rename" number="38"/>
+  <syscall name="mkdir" number="39"/>
+  <syscall name="rmdir" number="40"/>
+  <syscall name="dup" number="41"/>
+  <syscall name="pipe" number="42"/>
+  <syscall name="times" number="43"/>
+  <syscall name="prof" number="44"/>
+  <syscall name="brk" number="45"/>
+  <syscall name="setgid" number="46"/>
+  <syscall name="getgid" number="47"/>
+  <syscall name="signal" number="48"/>
+  <syscall name="geteuid" number="49"/>
+  <syscall name="getegid" number="50"/>
+  <syscall name="acct" number="51"/>
+  <syscall name="umount2" number="52"/>
+  <syscall name="lock" number="53"/>
+  <syscall name="ioctl" number="54"/>
+  <syscall name="fcntl" number="55"/>
+  <syscall name="mpx" number="56"/>
+  <syscall name="setpgid" number="57"/>
+  <syscall name="ulimit" number="58"/>
+  <syscall name="oldolduname" number="59"/>
+  <syscall name="umask" number="60"/>
+  <syscall name="chroot" number="61"/>
+  <syscall name="ustat" number="62"/>
+  <syscall name="dup2" number="63"/>
+  <syscall name="getppid" number="64"/>
+  <syscall name="getpgrp" number="65"/>
+  <syscall name="setsid" number="66"/>
+  <syscall name="sigaction" number="67"/>
+  <syscall name="sgetmask" number="68"/>
+  <syscall name="ssetmask" number="69"/>
+  <syscall name="setreuid" number="70"/>
+  <syscall name="setregid" number="71"/>
+  <syscall name="sigsuspend" number="72"/>
+  <syscall name="sigpending" number="73"/>
+  <syscall name="sethostname" number="74"/>
+  <syscall name="setrlimit" number="75"/>
+  <syscall name="getrlimit" number="76"/>
+  <syscall name="getrusage" number="77"/>
+  <syscall name="gettimeofday" number="78"/>
+  <syscall name="settimeofday" number="79"/>
+  <syscall name="getgroups" number="80"/>
+  <syscall name="setgroups" number="81"/>
+  <syscall name="select" number="82"/>
+  <syscall name="symlink" number="83"/>
+  <syscall name="oldlstat" number="84"/>
+  <syscall name="readlink" number="85"/>
+  <syscall name="uselib" number="86"/>
+  <syscall name="swapon" number="87"/>
+  <syscall name="reboot" number="88"/>
+  <syscall name="readdir" number="89"/>
+  <syscall name="mmap" number="90"/>
+  <syscall name="munmap" number="91"/>
+  <syscall name="truncate" number="92"/>
+  <syscall name="ftruncate" number="93"/>
+  <syscall name="fchmod" number="94"/>
+  <syscall name="fchown" number="95"/>
+  <syscall name="getpriority" number="96"/>
+  <syscall name="setpriority" number="97"/>
+  <syscall name="profil" number="98"/>
+  <syscall name="statfs" number="99"/>
+  <syscall name="fstatfs" number="100"/>
+  <syscall name="ioperm" number="101"/>
+  <syscall name="socketcall" number="102"/>
+  <syscall name="syslog" number="103"/>
+  <syscall name="setitimer" number="104"/>
+  <syscall name="getitimer" number="105"/>
+  <syscall name="stat" number="106"/>
+  <syscall name="lstat" number="107"/>
+  <syscall name="fstat" number="108"/>
+  <syscall name="olduname" number="109"/>
+  <syscall name="iopl" number="110"/>
+  <syscall name="vhangup" number="111"/>
+  <syscall name="idle" number="112"/>
+  <syscall name="vm86" number="113"/>
+  <syscall name="wait4" number="114"/>
+  <syscall name="swapoff" number="115"/>
+  <syscall name="sysinfo" number="116"/>
+  <syscall name="ipc" number="117"/>
+  <syscall name="fsync" number="118"/>
+  <syscall name="sigreturn" number="119"/>
+  <syscall name="clone" number="120"/>
+  <syscall name="setdomainname" number="121"/>
+  <syscall name="uname" number="122"/>
+  <syscall name="modify_ldt" number="123"/>
+  <syscall name="adjtimex" number="124"/>
+  <syscall name="mprotect" number="125"/>
+  <syscall name="sigprocmask" number="126"/>
+  <syscall name="create_module" number="127"/>
+  <syscall name="init_module" number="128"/>
+  <syscall name="delete_module" number="129"/>
+  <syscall name="get_kernel_syms" number="130"/>
+  <syscall name="quotactl" number="131"/>
+  <syscall name="getpgid" number="132"/>
+  <syscall name="fchdir" number="133"/>
+  <syscall name="bdflush" number="134"/>
+  <syscall name="sysfs" number="135"/>
+  <syscall name="personality" number="136"/>
+  <syscall name="afs_syscall" number="137"/>
+  <syscall name="setfsuid" number="138"/>
+  <syscall name="setfsgid" number="139"/>
+  <syscall name="_llseek" number="140"/>
+  <syscall name="getdents" number="141"/>
+  <syscall name="_newselect" number="142"/>
+  <syscall name="flock" number="143"/>
+  <syscall name="msync" number="144"/>
+  <syscall name="readv" number="145"/>
+  <syscall name="writev" number="146"/>
+  <syscall name="getsid" number="147"/>
+  <syscall name="fdatasync" number="148"/>
+  <syscall name="_sysctl" number="149"/>
+  <syscall name="mlock" number="150"/>
+  <syscall name="munlock" number="151"/>
+  <syscall name="mlockall" number="152"/>
+  <syscall name="munlockall" number="153"/>
+  <syscall name="sched_setparam" number="154"/>
+  <syscall name="sched_getparam" number="155"/>
+  <syscall name="sched_setscheduler" number="156"/>
+  <syscall name="sched_getscheduler" number="157"/>
+  <syscall name="sched_yield" number="158"/>
+  <syscall name="sched_get_priority_max" number="159"/>
+  <syscall name="sched_get_priority_min" number="160"/>
+  <syscall name="sched_rr_get_interval" number="161"/>
+  <syscall name="nanosleep" number="162"/>
+  <syscall name="mremap" number="163"/>
+  <syscall name="setresuid" number="164"/>
+  <syscall name="getresuid" number="165"/>
+  <syscall name="query_module" number="166"/>
+  <syscall name="poll" number="167"/>
+  <syscall name="nfsservctl" number="168"/>
+  <syscall name="setresgid" number="169"/>
+  <syscall name="getresgid" number="170"/>
+  <syscall name="prctl" number="171"/>
+  <syscall name="rt_sigreturn" number="172"/>
+  <syscall name="rt_sigaction" number="173"/>
+  <syscall name="rt_sigprocmask" number="174"/>
+  <syscall name="rt_sigpending" number="175"/>
+  <syscall name="rt_sigtimedwait" number="176"/>
+  <syscall name="rt_sigqueueinfo" number="177"/>
+  <syscall name="rt_sigsuspend" number="178"/>
+  <syscall name="pread64" number="179"/>
+  <syscall name="pwrite64" number="180"/>
+  <syscall name="chown" number="181"/>
+  <syscall name="getcwd" number="182"/>
+  <syscall name="capget" number="183"/>
+  <syscall name="capset" number="184"/>
+  <syscall name="sigaltstack" number="185"/>
+  <syscall name="sendfile" number="186"/>
+  <syscall name="getpmsg" number="187"/>
+  <syscall name="putpmsg" number="188"/>
+  <syscall name="vfork" number="189"/>
+  <syscall name="ugetrlimit" number="190"/>
+  <syscall name="readahead" number="191"/>
+  <syscall name="mmap2" number="192"/>
+  <syscall name="truncate64" number="193"/>
+  <syscall name="ftruncate64" number="194"/>
+  <syscall name="stat64" number="195"/>
+  <syscall name="lstat64" number="196"/>
+  <syscall name="fstat64" number="197"/>
+  <syscall name="pciconfig_read" number="198"/>
+  <syscall name="pciconfig_write" number="199"/>
+  <syscall name="pciconfig_iobase" number="200"/>
+  <syscall name="multiplexer" number="201"/>
+  <syscall name="getdents64" number="202"/>
+  <syscall name="pivot_root" number="203"/>
+  <syscall name="fcntl64" number="204"/>
+  <syscall name="madvise" number="205"/>
+  <syscall name="mincore" number="206"/>
+  <syscall name="gettid" number="207"/>
+  <syscall name="tkill" number="208"/>
+  <syscall name="setxattr" number="209"/>
+  <syscall name="lsetxattr" number="210"/>
+  <syscall name="fsetxattr" number="211"/>
+  <syscall name="getxattr" number="212"/>
+  <syscall name="lgetxattr" number="213"/>
+  <syscall name="fgetxattr" number="214"/>
+  <syscall name="listxattr" number="215"/>
+  <syscall name="llistxattr" number="216"/>
+  <syscall name="flistxattr" number="217"/>
+  <syscall name="removexattr" number="218"/>
+  <syscall name="lremovexattr" number="219"/>
+  <syscall name="fremovexattr" number="220"/>
+  <syscall name="futex" number="221"/>
+  <syscall name="sched_setaffinity" number="222"/>
+  <syscall name="sched_getaffinity" number="223"/>
+  <syscall name="" number="224"/>
+  <syscall name="tuxcall" number="225"/>
+  <syscall name="sendfile64" number="226"/>
+  <syscall name="io_setup" number="227"/>
+  <syscall name="io_destroy" number="228"/>
+  <syscall name="io_getevents" number="229"/>
+  <syscall name="io_submit" number="230"/>
+  <syscall name="io_cancel" number="231"/>
+  <syscall name="set_tid_address" number="232"/>
+  <syscall name="fadvise64" number="233"/>
+  <syscall name="exit_group" number="234"/>
+  <syscall name="lookup_dcookie" number="235"/>
+  <syscall name="epoll_create" number="236"/>
+  <syscall name="epoll_ctl" number="237"/>
+  <syscall name="epoll_wait" number="238"/>
+  <syscall name="remap_file_pages" number="239"/>
+  <syscall name="timer_create" number="240"/>
+  <syscall name="timer_settime" number="241"/>
+  <syscall name="timer_gettime" number="242"/>
+  <syscall name="timer_getoverrun" number="243"/>
+  <syscall name="timer_delete" number="244"/>
+  <syscall name="clock_settime" number="245"/>
+  <syscall name="clock_gettime" number="246"/>
+  <syscall name="clock_getres" number="247"/>
+  <syscall name="clock_nanosleep" number="248"/>
+  <syscall name="swapcontext" number="249"/>
+  <syscall name="tgkill" number="250"/>
+  <syscall name="utimes" number="251"/>
+  <syscall name="statfs64" number="252"/>
+  <syscall name="fstatfs64" number="253"/>
+  <syscall name="fadvise64_64" number="254"/>
+  <syscall name="rtas" number="255"/>
+  <syscall name="sys_debug_setcontext" number="256"/>
+  <syscall name="" number="257"/>
+  <syscall name="" number="258"/>
+  <syscall name="mbind" number="259"/>
+  <syscall name="get_mempolicy" number="260"/>
+  <syscall name="set_mempolicy" number="261"/>
+  <syscall name="mq_open" number="262"/>
+  <syscall name="mq_unlink" number="263"/>
+  <syscall name="mq_timedsend" number="264"/>
+  <syscall name="mq_timedreceive" number="265"/>
+  <syscall name="mq_notify" number="266"/>
+  <syscall name="mq_getsetattr" number="267"/>
+  <syscall name="kexec_load" number="268"/>
+  <syscall name="add_key" number="269"/>
+  <syscall name="request_key" number="270"/>
+  <syscall name="keyctl" number="271"/>
+  <syscall name="waitid" number="272"/>
+  <syscall name="ioprio_set" number="273"/>
+  <syscall name="ioprio_get" number="274"/>
+  <syscall name="inotify_init" number="275"/>
+  <syscall name="inotify_add_watch" number="276"/>
+  <syscall name="inotify_rm_watch" number="277"/>
+  <syscall name="spu_run" number="278"/>
+  <syscall name="spu_create" number="279"/>
+  <syscall name="pselect6" number="280"/>
+  <syscall name="ppoll" number="281"/>
+  <syscall name="unshare" number="282"/>
+  <syscall name="" number="283"/>
+  <syscall name="" number="284"/>
+  <syscall name="" number="285"/>
+  <syscall name="openat" number="286"/>
+  <syscall name="mkdirat" number="287"/>
+  <syscall name="mknodat" number="288"/>
+  <syscall name="fchownat" number="289"/>
+  <syscall name="futimesat" number="290"/>
+  <syscall name="fstatat64" number="291"/>
+  <syscall name="unlinkat" number="292"/>
+  <syscall name="renameat" number="293"/>
+  <syscall name="linkat" number="294"/>
+  <syscall name="symlinkat" number="295"/>
+  <syscall name="readlinkat" number="296"/>
+  <syscall name="fchmodat" number="297"/>
+  <syscall name="faccessat" number="298"/>
+  <syscall name="" number="299"/>
+  <syscall name="" number="300"/>
+</syscalls_info>
diff --git a/gdb/syscalls/ppc64-linux.xml b/gdb/syscalls/ppc64-linux.xml
new file mode 100644
index 0000000..2795de0
--- /dev/null
+++ b/gdb/syscalls/ppc64-linux.xml
@@ -0,0 +1,306 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-syscalls.dtd">
+
+<syscalls_info>
+  <syscall name="restart_syscall" number="0"/>
+  <syscall name="exit" number="1"/>
+  <syscall name="fork" number="2"/>
+  <syscall name="read" number="3"/>
+  <syscall name="write" number="4"/>
+  <syscall name="open" number="5"/>
+  <syscall name="close" number="6"/>
+  <syscall name="waitpid" number="7"/>
+  <syscall name="creat" number="8"/>
+  <syscall name="link" number="9"/>
+  <syscall name="unlink" number="10"/>
+  <syscall name="execve" number="11"/>
+  <syscall name="chdir" number="12"/>
+  <syscall name="time" number="13"/>
+  <syscall name="mknod" number="14"/>
+  <syscall name="chmod" number="15"/>
+  <syscall name="lchown" number="16"/>
+  <syscall name="break" number="17"/>
+  <syscall name="oldstat" number="18"/>
+  <syscall name="lseek" number="19"/>
+  <syscall name="getpid" number="20"/>
+  <syscall name="mount" number="21"/>
+  <syscall name="umount" number="22"/>
+  <syscall name="setuid" number="23"/>
+  <syscall name="getuid" number="24"/>
+  <syscall name="stime" number="25"/>
+  <syscall name="ptrace" number="26"/>
+  <syscall name="alarm" number="27"/>
+  <syscall name="oldfstat" number="28"/>
+  <syscall name="pause" number="29"/>
+  <syscall name="utime" number="30"/>
+  <syscall name="stty" number="31"/>
+  <syscall name="gtty" number="32"/>
+  <syscall name="access" number="33"/>
+  <syscall name="nice" number="34"/>
+  <syscall name="ftime" number="35"/>
+  <syscall name="sync" number="36"/>
+  <syscall name="kill" number="37"/>
+  <syscall name="rename" number="38"/>
+  <syscall name="mkdir" number="39"/>
+  <syscall name="rmdir" number="40"/>
+  <syscall name="dup" number="41"/>
+  <syscall name="pipe" number="42"/>
+  <syscall name="times" number="43"/>
+  <syscall name="prof" number="44"/>
+  <syscall name="brk" number="45"/>
+  <syscall name="setgid" number="46"/>
+  <syscall name="getgid" number="47"/>
+  <syscall name="signal" number="48"/>
+  <syscall name="geteuid" number="49"/>
+  <syscall name="getegid" number="50"/>
+  <syscall name="acct" number="51"/>
+  <syscall name="umount2" number="52"/>
+  <syscall name="lock" number="53"/>
+  <syscall name="ioctl" number="54"/>
+  <syscall name="fcntl" number="55"/>
+  <syscall name="mpx" number="56"/>
+  <syscall name="setpgid" number="57"/>
+  <syscall name="ulimit" number="58"/>
+  <syscall name="oldolduname" number="59"/>
+  <syscall name="umask" number="60"/>
+  <syscall name="chroot" number="61"/>
+  <syscall name="ustat" number="62"/>
+  <syscall name="dup2" number="63"/>
+  <syscall name="getppid" number="64"/>
+  <syscall name="getpgrp" number="65"/>
+  <syscall name="setsid" number="66"/>
+  <syscall name="sigaction" number="67"/>
+  <syscall name="sgetmask" number="68"/>
+  <syscall name="ssetmask" number="69"/>
+  <syscall name="setreuid" number="70"/>
+  <syscall name="setregid" number="71"/>
+  <syscall name="sigsuspend" number="72"/>
+  <syscall name="sigpending" number="73"/>
+  <syscall name="sethostname" number="74"/>
+  <syscall name="setrlimit" number="75"/>
+  <syscall name="getrlimit" number="76"/>
+  <syscall name="getrusage" number="77"/>
+  <syscall name="gettimeofday" number="78"/>
+  <syscall name="settimeofday" number="79"/>
+  <syscall name="getgroups" number="80"/>
+  <syscall name="setgroups" number="81"/>
+  <syscall name="select" number="82"/>
+  <syscall name="symlink" number="83"/>
+  <syscall name="oldlstat" number="84"/>
+  <syscall name="readlink" number="85"/>
+  <syscall name="uselib" number="86"/>
+  <syscall name="swapon" number="87"/>
+  <syscall name="reboot" number="88"/>
+  <syscall name="readdir" number="89"/>
+  <syscall name="mmap" number="90"/>
+  <syscall name="munmap" number="91"/>
+  <syscall name="truncate" number="92"/>
+  <syscall name="ftruncate" number="93"/>
+  <syscall name="fchmod" number="94"/>
+  <syscall name="fchown" number="95"/>
+  <syscall name="getpriority" number="96"/>
+  <syscall name="setpriority" number="97"/>
+  <syscall name="profil" number="98"/>
+  <syscall name="statfs" number="99"/>
+  <syscall name="fstatfs" number="100"/>
+  <syscall name="ioperm" number="101"/>
+  <syscall name="socketcall" number="102"/>
+  <syscall name="syslog" number="103"/>
+  <syscall name="setitimer" number="104"/>
+  <syscall name="getitimer" number="105"/>
+  <syscall name="stat" number="106"/>
+  <syscall name="lstat" number="107"/>
+  <syscall name="fstat" number="108"/>
+  <syscall name="olduname" number="109"/>
+  <syscall name="iopl" number="110"/>
+  <syscall name="vhangup" number="111"/>
+  <syscall name="idle" number="112"/>
+  <syscall name="vm86" number="113"/>
+  <syscall name="wait4" number="114"/>
+  <syscall name="swapoff" number="115"/>
+  <syscall name="sysinfo" number="116"/>
+  <syscall name="ipc" number="117"/>
+  <syscall name="fsync" number="118"/>
+  <syscall name="sigreturn" number="119"/>
+  <syscall name="clone" number="120"/>
+  <syscall name="setdomainname" number="121"/>
+  <syscall name="uname" number="122"/>
+  <syscall name="modify_ldt" number="123"/>
+  <syscall name="adjtimex" number="124"/>
+  <syscall name="mprotect" number="125"/>
+  <syscall name="sigprocmask" number="126"/>
+  <syscall name="create_module" number="127"/>
+  <syscall name="init_module" number="128"/>
+  <syscall name="delete_module" number="129"/>
+  <syscall name="get_kernel_syms" number="130"/>
+  <syscall name="quotactl" number="131"/>
+  <syscall name="getpgid" number="132"/>
+  <syscall name="fchdir" number="133"/>
+  <syscall name="bdflush" number="134"/>
+  <syscall name="sysfs" number="135"/>
+  <syscall name="personality" number="136"/>
+  <syscall name="afs_syscall" number="137"/>
+  <syscall name="setfsuid" number="138"/>
+  <syscall name="setfsgid" number="139"/>
+  <syscall name="_llseek" number="140"/>
+  <syscall name="getdents" number="141"/>
+  <syscall name="_newselect" number="142"/>
+  <syscall name="flock" number="143"/>
+  <syscall name="msync" number="144"/>
+  <syscall name="readv" number="145"/>
+  <syscall name="writev" number="146"/>
+  <syscall name="getsid" number="147"/>
+  <syscall name="fdatasync" number="148"/>
+  <syscall name="_sysctl" number="149"/>
+  <syscall name="mlock" number="150"/>
+  <syscall name="munlock" number="151"/>
+  <syscall name="mlockall" number="152"/>
+  <syscall name="munlockall" number="153"/>
+  <syscall name="sched_setparam" number="154"/>
+  <syscall name="sched_getparam" number="155"/>
+  <syscall name="sched_setscheduler" number="156"/>
+  <syscall name="sched_getscheduler" number="157"/>
+  <syscall name="sched_yield" number="158"/>
+  <syscall name="sched_get_priority_max" number="159"/>
+  <syscall name="sched_get_priority_min" number="160"/>
+  <syscall name="sched_rr_get_interval" number="161"/>
+  <syscall name="nanosleep" number="162"/>
+  <syscall name="mremap" number="163"/>
+  <syscall name="setresuid" number="164"/>
+  <syscall name="getresuid" number="165"/>
+  <syscall name="query_module" number="166"/>
+  <syscall name="poll" number="167"/>
+  <syscall name="nfsservctl" number="168"/>
+  <syscall name="setresgid" number="169"/>
+  <syscall name="getresgid" number="170"/>
+  <syscall name="prctl" number="171"/>
+  <syscall name="rt_sigreturn" number="172"/>
+  <syscall name="rt_sigaction" number="173"/>
+  <syscall name="rt_sigprocmask" number="174"/>
+  <syscall name="rt_sigpending" number="175"/>
+  <syscall name="rt_sigtimedwait" number="176"/>
+  <syscall name="rt_sigqueueinfo" number="177"/>
+  <syscall name="rt_sigsuspend" number="178"/>
+  <syscall name="pread64" number="179"/>
+  <syscall name="pwrite64" number="180"/>
+  <syscall name="chown" number="181"/>
+  <syscall name="getcwd" number="182"/>
+  <syscall name="capget" number="183"/>
+  <syscall name="capset" number="184"/>
+  <syscall name="sigaltstack" number="185"/>
+  <syscall name="sendfile" number="186"/>
+  <syscall name="getpmsg" number="187"/>
+  <syscall name="putpmsg" number="188"/>
+  <syscall name="vfork" number="189"/>
+  <syscall name="ugetrlimit" number="190"/>
+  <syscall name="readahead" number="191"/>
+  <syscall name="" number="192"/>
+  <syscall name="" number="193"/>
+  <syscall name="" number="194"/>
+  <syscall name="" number="195"/>
+  <syscall name="" number="196"/>
+  <syscall name="" number="197"/>
+  <syscall name="pciconfig_read" number="198"/>
+  <syscall name="pciconfig_write" number="199"/>
+  <syscall name="pciconfig_iobase" number="200"/>
+  <syscall name="multiplexer" number="201"/>
+  <syscall name="getdents64" number="202"/>
+  <syscall name="pivot_root" number="203"/>
+  <syscall name="" number="204"/>
+  <syscall name="madvise" number="205"/>
+  <syscall name="mincore" number="206"/>
+  <syscall name="gettid" number="207"/>
+  <syscall name="tkill" number="208"/>
+  <syscall name="setxattr" number="209"/>
+  <syscall name="lsetxattr" number="210"/>
+  <syscall name="fsetxattr" number="211"/>
+  <syscall name="getxattr" number="212"/>
+  <syscall name="lgetxattr" number="213"/>
+  <syscall name="fgetxattr" number="214"/>
+  <syscall name="listxattr" number="215"/>
+  <syscall name="llistxattr" number="216"/>
+  <syscall name="flistxattr" number="217"/>
+  <syscall name="removexattr" number="218"/>
+  <syscall name="lremovexattr" number="219"/>
+  <syscall name="fremovexattr" number="220"/>
+  <syscall name="futex" number="221"/>
+  <syscall name="sched_setaffinity" number="222"/>
+  <syscall name="sched_getaffinity" number="223"/>
+  <syscall name="" number="224"/>
+  <syscall name="tuxcall" number="225"/>
+  <syscall name="" number="226"/>
+  <syscall name="io_setup" number="227"/>
+  <syscall name="io_destroy" number="228"/>
+  <syscall name="io_getevents" number="229"/>
+  <syscall name="io_submit" number="230"/>
+  <syscall name="io_cancel" number="231"/>
+  <syscall name="set_tid_address" number="232"/>
+  <syscall name="fadvise64" number="233"/>
+  <syscall name="exit_group" number="234"/>
+  <syscall name="lookup_dcookie" number="235"/>
+  <syscall name="epoll_create" number="236"/>
+  <syscall name="epoll_ctl" number="237"/>
+  <syscall name="epoll_wait" number="238"/>
+  <syscall name="remap_file_pages" number="239"/>
+  <syscall name="timer_create" number="240"/>
+  <syscall name="timer_settime" number="241"/>
+  <syscall name="timer_gettime" number="242"/>
+  <syscall name="timer_getoverrun" number="243"/>
+  <syscall name="timer_delete" number="244"/>
+  <syscall name="clock_settime" number="245"/>
+  <syscall name="clock_gettime" number="246"/>
+  <syscall name="clock_getres" number="247"/>
+  <syscall name="clock_nanosleep" number="248"/>
+  <syscall name="swapcontext" number="249"/>
+  <syscall name="tgkill" number="250"/>
+  <syscall name="utimes" number="251"/>
+  <syscall name="statfs64" number="252"/>
+  <syscall name="fstatfs64" number="253"/>
+  <syscall name="" number="254"/>
+  <syscall name="rtas" number="255"/>
+  <syscall name="sys_debug_setcontext" number="256"/>
+  <syscall name="" number="257"/>
+  <syscall name="" number="258"/>
+  <syscall name="mbind" number="259"/>
+  <syscall name="get_mempolicy" number="260"/>
+  <syscall name="set_mempolicy" number="261"/>
+  <syscall name="mq_open" number="262"/>
+  <syscall name="mq_unlink" number="263"/>
+  <syscall name="mq_timedsend" number="264"/>
+  <syscall name="mq_timedreceive" number="265"/>
+  <syscall name="mq_notify" number="266"/>
+  <syscall name="mq_getsetattr" number="267"/>
+  <syscall name="kexec_load" number="268"/>
+  <syscall name="add_key" number="269"/>
+  <syscall name="request_key" number="270"/>
+  <syscall name="keyctl" number="271"/>
+  <syscall name="waitid" number="272"/>
+  <syscall name="ioprio_set" number="273"/>
+  <syscall name="ioprio_get" number="274"/>
+  <syscall name="inotify_init" number="275"/>
+  <syscall name="inotify_add_watch" number="276"/>
+  <syscall name="inotify_rm_watch" number="277"/>
+  <syscall name="spu_run" number="278"/>
+  <syscall name="spu_create" number="279"/>
+  <syscall name="pselect6" number="280"/>
+  <syscall name="ppoll" number="281"/>
+  <syscall name="unshare" number="282"/>
+  <syscall name="" number="283"/>
+  <syscall name="" number="284"/>
+  <syscall name="" number="285"/>
+  <syscall name="unlinkat" number="286"/>
+  <syscall name="renameat" number="287"/>
+  <syscall name="linkat" number="288"/>
+  <syscall name="symlinkat" number="289"/>
+  <syscall name="readlinkat" number="290"/>
+  <syscall name="fchmodat" number="291"/>
+  <syscall name="faccessat" number="292"/>
+  <syscall name="" number="293"/>
+  <syscall name="" number="294"/>
+</syscalls_info>
diff --git a/gdb/xml-syscall.c b/gdb/xml-syscall.c
new file mode 100644
index 0000000..498f58a
--- /dev/null
+++ b/gdb/xml-syscall.c
@@ -0,0 +1,423 @@
+/* Functions that provide the mechanism to parse a syscall XML file
+   and get its values.
+
+   Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
+   1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008
+   Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "xml-support.h"
+#include "xml-syscall.h"
+
+#include "filenames.h"
+
+#include "gdb_assert.h"
+
+#ifndef HAVE_LIBEXPAT
+
+/* Dummy functions to indicate that there's no support for fetching
+   syscalls information.  */
+
+static void
+syscall_warn_user (void)
+{
+  static int have_warned = 0;
+  if (!have_warned)
+    {
+      have_warned = 1;
+      warning (_("Can not parse XML syscalls information; XML support was "
+		 "disabled at compile time"));
+    }
+}
+
+const struct syscalls_info *
+xml_init_syscalls_info (const char *filename)
+{
+  syscall_warn_user ();
+  return NULL;
+}
+
+int
+xml_get_syscall_number (const struct syscalls_info *sysinfo,
+                        const char *syscall_name)
+{
+  syscall_warn_user ();
+  return UNKNOWN_SYSCALL;
+}
+
+const char *
+xml_get_syscall_name (const struct syscalls_info *sysinfo,
+                      int syscall_number)
+{
+  syscall_warn_user ();
+  return NULL;
+}
+
+int
+xml_number_of_syscalls (const struct syscalls_info *sysinfo)
+{
+  syscall_warn_user ();
+  return 0;
+}
+
+const char **
+xml_list_of_syscalls (const struct syscalls_info *sysinfo)
+{
+  syscall_warn_user ();
+  return NULL;
+}
+
+#else
+
+/* Structure which describes a syscall.  */
+
+typedef struct syscall_desc
+{
+  /* The syscall number.  */
+
+  int number;
+
+  /* The syscall name.  */
+
+  char *name;
+} *syscall_desc_p;
+DEF_VEC_P(syscall_desc_p);
+
+/* Structure that represents syscalls information.  */
+
+struct syscalls_info
+{
+  /* The syscalls.  */
+
+  VEC(syscall_desc_p) *syscalls;
+};
+
+/* Callback data for syscall information parsing.  */
+
+struct syscall_parsing_data
+{
+  /* The syscalls_info we are building.  */
+
+  struct syscalls_info *sysinfo;
+};
+
+
+static struct syscalls_info *
+allocate_syscalls_info (void)
+{
+  return XZALLOC (struct syscalls_info);
+}
+
+static void
+sysinfo_free_syscalls_desc (struct syscall_desc *sd)
+{
+  xfree (sd->name);
+}
+
+static void
+free_syscalls_info (void *arg)
+{
+  struct syscalls_info *sysinfo = arg;
+  struct syscall_desc *sysdesc;
+  int i;
+
+  for (i = 0;
+       VEC_iterate (syscall_desc_p, sysinfo->syscalls, i, sysdesc);
+       i++)
+    sysinfo_free_syscalls_desc (sysdesc);
+  VEC_free (syscall_desc_p, sysinfo->syscalls);
+
+  xfree (sysinfo);
+}
+
+struct cleanup *
+make_cleanup_free_syscalls_info (struct syscalls_info *sysinfo)
+{
+  return make_cleanup (free_syscalls_info, sysinfo);
+}
+
+/* Open FILENAME, read all its text into memory, close it, and return
+   the text.  If something goes wrong, return NULL and warn.  */
+
+static char *
+fetch_xml_from_file (const char *filename, void *baton)
+{
+  const char *dirname = baton;
+  FILE *file;
+  struct cleanup *back_to;
+  char *text;
+  size_t len, offset;
+
+  if (dirname && *dirname)
+    {
+      char *fullname = concat (dirname, "/", filename, (char *) NULL);
+      if (fullname == NULL)
+	nomem (0);
+      file = fopen (fullname, FOPEN_RT);
+      xfree (fullname);
+    }
+  else
+    file = fopen (filename, FOPEN_RT);
+
+  if (file == NULL)
+    return NULL;
+
+  back_to = make_cleanup_fclose (file);
+
+  /* Read in the whole file, one chunk at a time.  */
+  len = 4096;
+  offset = 0;
+  text = xmalloc (len);
+  make_cleanup (free_current_contents, &text);
+  while (1)
+    {
+      size_t bytes_read;
+
+      /* Continue reading where the last read left off.  Leave at least
+	 one byte so that we can NUL-terminate the result.  */
+      bytes_read = fread (text + offset, 1, len - offset - 1, file);
+      if (ferror (file))
+	{
+	  warning (_("Read error from \"%s\""), filename);
+	  do_cleanups (back_to);
+	  return NULL;
+	}
+
+      offset += bytes_read;
+
+      if (feof (file))
+	break;
+
+      len = len * 2;
+      text = xrealloc (text, len);
+    }
+
+  fclose (file);
+  discard_cleanups (back_to);
+
+  text[offset] = '\0';
+  return text;
+}
+
+static void
+syscall_create_syscall_desc (struct syscalls_info *sysinfo,
+                             const char *name, int number)
+{
+  struct syscall_desc *sysdesc = XZALLOC (struct syscall_desc);
+
+  sysdesc->name = xstrdup (name);
+  sysdesc->number = number;
+
+  VEC_safe_push (syscall_desc_p, sysinfo->syscalls, sysdesc);
+}
+
+/* Handle the start of a <syscalls_info> element.  */
+
+static void
+syscall_start_syscalls_info (struct gdb_xml_parser *parser,
+                             const struct gdb_xml_element *element,
+                             void *user_data,
+                             VEC(gdb_xml_value_s) *attributes)
+{
+  struct syscall_parsing_data *data = user_data;
+  struct syscalls_info *sysinfo = data->sysinfo;
+}
+
+/* Handle the start of a <syscall> element.  */
+
+static void
+syscall_start_syscall (struct gdb_xml_parser *parser,
+                       const struct gdb_xml_element *element,
+                       void *user_data, VEC(gdb_xml_value_s) *attributes)
+{
+  struct syscall_parsing_data *data = user_data;
+  struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
+  int len, i;
+  /* syscall info.  */
+  char *name = NULL;
+  int number = 0;
+
+  len = VEC_length (gdb_xml_value_s, attributes);
+
+  for (i = 0; i < len; i++)
+    {
+      if (strcmp (attrs[i].name, "name") == 0)
+        name = attrs[i].value;
+      else if (strcmp (attrs[i].name, "number") == 0)
+        number = * (ULONGEST *) attrs[i].value;
+      else
+        internal_error (__FILE__, __LINE__,
+                        _("Unknown attribute name '%s'."), attrs[i].name);
+    }
+
+  syscall_create_syscall_desc (data->sysinfo, name, number);
+}
+
+
+/* The elements and attributes of an XML syscall document.  */
+
+static const struct gdb_xml_attribute syscall_attr[] = {
+  { "number", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+  { "name", GDB_XML_AF_NONE, NULL, NULL },
+  { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element syscalls_info_children[] = {
+  { "syscall", syscall_attr, NULL,
+    GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
+    syscall_start_syscall, NULL },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element syselements[] = {
+  { "syscalls_info", NULL, syscalls_info_children,
+    GDB_XML_EF_NONE, syscall_start_syscalls_info, NULL },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+static struct syscalls_info *
+syscall_parse_xml (const char *document, xml_fetch_another fetcher,
+                   void *fetcher_baton)
+{
+  struct cleanup *result_cleanup;
+  struct gdb_xml_parser *parser;
+  struct syscall_parsing_data data;
+  char *expanded_text;
+  int i;
+
+  parser = gdb_xml_create_parser_and_cleanup (_("syscalls info"),
+					      syselements, &data);
+
+  memset (&data, 0, sizeof (struct syscall_parsing_data));
+  data.sysinfo = allocate_syscalls_info ();
+  result_cleanup = make_cleanup_free_syscalls_info (data.sysinfo);
+
+  if (gdb_xml_parse (parser, document) == 0)
+    {
+      /* Parsed successfully.  */
+      discard_cleanups (result_cleanup);
+      return data.sysinfo;
+    }
+  else
+    {
+      warning (_("Could not load XML syscalls info; ignoring"));
+      do_cleanups (result_cleanup);
+      return NULL;
+    }
+}
+
+const struct syscalls_info *
+xml_init_syscalls_info (const char *filename)
+{
+  char *full_file;
+  char *dirname;
+  struct syscalls_info *sysinfo;
+  struct cleanup *back_to;
+
+  full_file = fetch_xml_from_file (filename, gdb_datadir);
+  if (full_file == NULL)
+    {
+      warning (_("Could not open \"%s\""), filename);
+      return NULL;
+    }
+
+  back_to = make_cleanup (xfree, full_file);
+
+  dirname = ldirname (filename);
+  if (dirname != NULL)
+    make_cleanup (xfree, dirname);
+
+  sysinfo = syscall_parse_xml (full_file, fetch_xml_from_file, dirname);
+  do_cleanups (back_to);
+
+  return sysinfo;
+}
+
+int
+xml_get_syscall_number (const struct syscalls_info *sysinfo,
+                        const char *syscall_name)
+{
+  struct syscall_desc *sysdesc;
+  int i;
+
+  if (sysinfo == NULL
+      || syscall_name == NULL)
+    return UNKNOWN_SYSCALL;
+
+  for (i = 0;
+       VEC_iterate(syscall_desc_p, sysinfo->syscalls, i, sysdesc);
+       i++)
+    if (strcmp (sysdesc->name, syscall_name) == 0)
+      return sysdesc->number;
+
+  return UNKNOWN_SYSCALL;
+}
+
+const char *
+xml_get_syscall_name (const struct syscalls_info *sysinfo,
+                      int syscall_number)
+{
+  struct syscall_desc *sysdesc;
+  int i;
+
+  if (sysinfo == NULL
+      || syscall_number < 0)
+    return NULL;
+
+  for (i = 0;
+       VEC_iterate(syscall_desc_p, sysinfo->syscalls, i, sysdesc);
+       i++)
+    if (sysdesc->number == syscall_number)
+      return sysdesc->name;
+
+  return NULL;
+}
+
+int
+xml_number_of_syscalls (const struct syscalls_info *sysinfo)
+{
+  return (sysinfo == NULL ? 0 : VEC_length(syscall_desc_p,
+                                           sysinfo->syscalls));
+}
+
+const char **
+xml_list_of_syscalls (const struct syscalls_info *sysinfo)
+{
+  struct syscall_desc *sysdesc;
+  const char **names = NULL;
+  int nsyscalls;
+  int i;
+
+  if (sysinfo == NULL)
+    return NULL;
+
+  nsyscalls = VEC_length (syscall_desc_p, sysinfo->syscalls);
+  names = xmalloc ((nsyscalls + 1) * sizeof (char *));
+
+  for (i = 0;
+       VEC_iterate (syscall_desc_p, sysinfo->syscalls, i, sysdesc);
+       i++)
+    names[i] = sysdesc->name;
+
+  names[i] = NULL;
+
+  return names;
+}
+
+#endif /* HAVE_LIBEXPAT */
diff --git a/gdb/xml-syscall.h b/gdb/xml-syscall.h
new file mode 100644
index 0000000..ff11f20
--- /dev/null
+++ b/gdb/xml-syscall.h
@@ -0,0 +1,64 @@
+/* Functions that provide the mechanism to parse a syscall XML file
+   and get its values.
+
+   Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
+   1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008
+   Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef XML_SYSCALL_H
+#define XML_SYSCALL_H 1
+
+/* Structure that stores information about the system's
+   syscalls.  */
+
+struct syscalls_info;
+
+
+/* Function responsible for initializing the information
+   about the syscalls.  It reads the XML file and fills the
+   struct syscalls_info with the values.
+   
+   Returns the struct syscalls_info if the file is valid, NULL otherwise.  */
+
+const struct syscalls_info *xml_init_syscalls_info (const char *);
+
+/* Function that retrieves the syscall number corresponding to the given
+   name.
+
+   Returns the syscall number if found, or  otherwise.  */
+
+int xml_get_syscall_number (const struct syscalls_info *, const char *);
+
+/* Function that retrieves the syscall name corresponding to the given
+   number.
+
+   Returns the syscall name if found, NULL otherwise.  */
+const char *xml_get_syscall_name (const struct syscalls_info *, int);
+
+/* Function that returns the number of syscalls defined in the system.
+
+   Returns the number of syscalls, or zero otherwise.  */
+int xml_number_of_syscalls (const struct syscalls_info *);
+
+/* Function used to retrieve the list of syscalls in the system.  This list
+   is returned as an array of strings.
+
+   Returns the list of syscalls in the system, or NULL otherwise.  */
+const char **xml_list_of_syscalls (const struct syscalls_info *sysinfo);
+
+#endif /* XML_SYSCALL_H */

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