This is the mail archive of the archer@sourceware.org mailing list for the Archer 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]

[PATCH 2/4] 'catch syscall' feature -- Architecture-dependent part


This is the architecture-dependent part of the patch.

Because of that problem in PPC64 (see message 0/4), probably I'll have
to edit this patch to make sure that the architecture supports syscall
catchpoints. IMO, this can be done checking the
'gdbarch_get_syscall_number_p'. I think I'll let this modification to
the second review of this patch :-).

Regards,

-- 
Sérgio Durigan Júnior
Linux on Power Toolchain - Software Engineer
Linux Technology Center - LTC
IBM Brazil

2008-09-29  Sergio Durigan Junior  <sergiodj@linux.vnet.ibm.com>

	* linux-nat.c: Define some helpful variables to track wether we have
	support for the needed ptrace() option.
	(linux_test_for_tracesysgood): New.
	(linux_supports_tracesysgood): New.
	(linux_enable_tracesysgood): New.
	(linux_passed_by_entrypoint): New.
	(linux_enable_event_reporting): Save the current used ptrace()
	options.
	(linux_child_post_startup_inferior): Create the entry breakpoint.
	(linux_child_insert_syscall_catchpoint): New.
	(linux_child_remove_syscall_catchpoint): New.
	(linux_nat_create_inferior): Properly setting the flag which indicates
	if the inferior have already passed through its entrypoint.
	(linux_handle_extended_wait): Handle the case which the inferior stops
	because it has called or returned from a syscall.
	(linux_nat_filter_event): Likewise.
	(linux_target_install_ops): Install the necessary functions to handle
	syscall catchpoints and entry breakpoints.
	* ppc-linux-tdep.c: Define the syscalls names for both PPC and PPC64.
	(ppc_linux_get_syscall_number): New.
	(ppc_linux_syscall_name_from_number): New.
	(ppc64_linux_syscall_name_from_number): New.
	(ppc_linux_syscall_number_from_name): New.
	(ppc64_linux_syscall_number_from_name): New.
	(ppc_linux_init_abi): Set the correct functions for syscall
	catchpoint.

diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index a0dc634..67ef708 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -57,6 +57,10 @@
 # endif
 #endif /* HAVE_PERSONALITY */
 
+/* To be used when one needs to know wether a
+   WSTOPSIG (status) is a syscall */
+#define TRAP_IS_SYSCALL (SIGTRAP | 0x80)
+
 /* This comment documents high-level logic of this file. 
 
 Waiting for events in sync mode
@@ -269,17 +273,29 @@ struct simple_pid_list *stopped_pids;
 
 static int linux_supports_tracefork_flag = -1;
 
+/* This variable is a tri-state flag: -1 for unknown, 0 if PTRACE_O_TRACESYSGOOD
+   can not be used, 1 if it can.  */
+
+static int linux_supports_tracesysgood_flag = -1;
+
 /* If we have PTRACE_O_TRACEFORK, this flag indicates whether we also have
    PTRACE_O_TRACEVFORKDONE.  */
 
 static int linux_supports_tracevforkdone_flag = -1;
 
+/* If the inferior have passed through its entrypoint (AT_ENTRY),
+   then this flag is set to 1. Otherwise, its value is 0. */
+static int linux_passed_by_entrypoint_flag = 0;
+
 /* Async mode support */
 
 /* Zero if the async mode, although enabled, is masked, which means
    linux_nat_wait should behave as if async mode was off.  */
 static int linux_nat_async_mask_value = 1;
 
+/* Stores the current used ptrace() options. */
+static int current_ptrace_options = 0;
+
 /* The read/write ends of the pipe registered as waitable file in the
    event loop.  */
 static int linux_nat_event_pipe[2] = { -1, -1 };
@@ -609,6 +625,41 @@ linux_test_for_tracefork (int original_pid)
   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.  */
 
@@ -628,12 +679,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);
@@ -641,15 +714,16 @@ linux_enable_event_reporting (ptid_t ptid)
   if (! linux_supports_tracefork (pid))
     return;
 
-  options = PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACEEXEC
-    | PTRACE_O_TRACECLONE;
+  current_ptrace_options |= PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK
+    | PTRACE_O_TRACEEXEC | PTRACE_O_TRACECLONE;
+
   if (linux_supports_tracevforkdone (pid))
-    options |= PTRACE_O_TRACEVFORKDONE;
+    current_ptrace_options |= PTRACE_O_TRACEVFORKDONE;
 
   /* Do not enable PTRACE_O_TRACEEXIT until GDB is more prepared to support
      read-only process state.  */
 
-  ptrace (PTRACE_SETOPTIONS, pid, 0, options);
+  ptrace (PTRACE_SETOPTIONS, pid, 0, current_ptrace_options);
 }
 
 static void
@@ -664,6 +738,12 @@ linux_child_post_startup_inferior (ptid_t ptid)
 {
   linux_enable_event_reporting (ptid);
   check_for_thread_db ();
+  /* We have to create the entry breakpoint here because
+     if we have 'catch syscall' enabled, we ought to know
+     when to enable PTRACE_O_TRACESYSGOOD. Otherwise, we would
+     start catching syscalls from ld.so/libc (which is not
+     what we want). */
+  create_entry_breakpoint ();
 }
 
 static int
@@ -890,6 +970,19 @@ linux_child_insert_exec_catchpoint (int pid)
     error (_("Your system does not support exec catchpoints."));
 }
 
+static void
+linux_child_insert_syscall_catchpoint (int pid)
+{
+  if (! linux_supports_tracesysgood (pid))
+    error (_("Your system does not support syscall catchpoints."));
+}
+
+static int
+linux_child_remove_syscall_catchpoint (int pid)
+{
+  return 0;
+}
+
 /* On GNU/Linux there are no real LWP's.  The closest thing to LWP's
    are processes sharing the same VM space.  A multi-threaded process
    is basically a group of such processes.  However, such a grouping
@@ -1310,6 +1403,9 @@ linux_nat_create_inferior (char *exec_file, char *allargs, char **env,
   int personality_orig = 0, personality_set = 0;
 #endif /* HAVE_PERSONALITY */
 
+  /* We are sarting, so we still have not passed through our entrypoint. */
+  linux_passed_by_entrypoint_flag = 0;
+
   /* The fork_child mechanism is synchronous and calls target_wait, so
      we have to mask the async mode.  */
 
@@ -1940,6 +2036,27 @@ linux_handle_extended_wait (struct lwp_info *lp, int status,
       return 0;
     }
 
+  /* Used for 'catch syscall' feature. */
+  if (WSTOPSIG (status) == TRAP_IS_SYSCALL)
+    {
+      if (catch_syscall_enabled () == 0)
+          ourstatus->kind = TARGET_WAITKIND_IGNORE;
+      else
+        {
+          struct regcache *regcache = get_thread_regcache (lp->ptid);
+          struct gdbarch *gdbarch = get_regcache_arch (regcache);
+          struct thread_info *th_info = find_thread_pid (lp->ptid);
+
+          ourstatus->kind = 
+            (th_info->syscall_state == TARGET_WAITKIND_SYSCALL_ENTRY) ?
+            TARGET_WAITKIND_SYSCALL_RETURN : TARGET_WAITKIND_SYSCALL_ENTRY;
+          th_info->syscall_state = ourstatus->kind;
+          ourstatus->value.syscall_number =
+            (int) gdbarch_get_syscall_number (gdbarch, lp->ptid);
+        }
+      return 0;
+    }
+
   internal_error (__FILE__, __LINE__,
 		  _("unknown ptrace event %d"), event);
 }
@@ -2550,11 +2667,16 @@ linux_nat_filter_event (int lwpid, int status, int options)
     }
 
   /* Save the trap's siginfo in case we need it later.  */
-  if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP)
+  if (WIFSTOPPED (status)
+      && (WSTOPSIG (status) == SIGTRAP || WSTOPSIG (status) == TRAP_IS_SYSCALL))
     save_siginfo (lp);
 
-  /* Handle GNU/Linux's extended waitstatus for trace events.  */
-  if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
+  /* Handle GNU/Linux's extended waitstatus for trace events.
+     It is necessary to check if WSTOPSIG is signaling a that
+     the inferior is entering/exiting a system call. */
+  if (WIFSTOPPED (status)
+      && ((WSTOPSIG (status) == TRAP_IS_SYSCALL)
+          || (WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)))
     {
       if (debug_linux_nat)
 	fprintf_unfiltered (gdb_stdlog,
@@ -4000,6 +4122,8 @@ linux_target_install_ops (struct target_ops *t)
   t->to_insert_fork_catchpoint = linux_child_insert_fork_catchpoint;
   t->to_insert_vfork_catchpoint = linux_child_insert_vfork_catchpoint;
   t->to_insert_exec_catchpoint = linux_child_insert_exec_catchpoint;
+  t->to_insert_syscall_catchpoint = linux_child_insert_syscall_catchpoint;
+  t->to_remove_syscall_catchpoint = linux_child_remove_syscall_catchpoint;
   t->to_pid_to_exec_file = linux_child_pid_to_exec_file;
   t->to_post_startup_inferior = linux_child_post_startup_inferior;
   t->to_post_attach = linux_child_post_attach;
@@ -4007,6 +4131,9 @@ linux_target_install_ops (struct target_ops *t)
   t->to_find_memory_regions = linux_nat_find_memory_regions;
   t->to_make_corefile_notes = linux_nat_make_corefile_notes;
 
+  t->to_enable_tracesysgood = linux_enable_tracesysgood;
+  t->to_passed_by_entrypoint = linux_passed_by_entrypoint;
+
   super_xfer_partial = t->to_xfer_partial;
   t->to_xfer_partial = linux_xfer_partial;
 }
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 2804857..f46b753 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -47,6 +47,142 @@
 #include "features/rs6000/powerpc-vsx64l.c"
 #include "features/rs6000/powerpc-e500l.c"
 
+/* Total number of syscalls */
+#define N_SYSCALLS 301
+
+/* Syscalls names for PPC 32-bit */
+static const char *syscalls_names[] = {
+    "restart_syscall", "exit", "fork", "read",
+    "write", "open", "close", "waitpid", "creat",
+    "link", "unlink", "execve", "chdir", "time",
+    "mknod", "chmod", "lchown", "break", "oldstat",
+    "lseek", "getpid", "mount", "umount", "setuid",
+    "getuid", "stime", "ptrace", "alarm", "oldfstat",
+    "pause", "utime", "stty", "gtty", "access", "nice",
+    "ftime", "sync", "kill", "rename", "mkdir", "rmdir",
+    "dup", "pipe", "times", "prof", "brk", "setgid",
+    "getgid", "signal", "geteuid", "getegid", "acct",
+    "umount2", "lock", "ioctl", "fcntl", "mpx", "setpgid",
+    "ulimit", "oldolduname", "umask", "chroot", "ustat",
+    "dup2", "getppid", "getpgrp", "setsid", "sigaction",
+    "sgetmask", "ssetmask", "setreuid", "setregid",
+    "sigsuspend", "sigpending", "sethostname", "setrlimit",
+    "getrlimit", "getrusage", "gettimeofday", "settimeofday",
+    "getgroups", "setgroups", "select", "symlink", "oldlstat",
+    "readlink",  "uselib", "swapon", "reboot", "readdir",
+    "mmap", "munmap", "truncate", "ftruncate", "fchmod",
+    "fchown", "getpriority", "setpriority", "profil",
+    "statfs", "fstatfs", "ioperm", "socketcall", "syslog",
+    "setitimer", "getitimer", "stat", "lstat", "fstat",
+    "olduname", "iopl", "vhangup", "idle", "vm86", "wait4",
+    "swapoff", "sysinfo", "ipc", "fsync", "sigreturn",
+    "clone", "setdomainname", "uname", "modify_ldt",
+    "adjtimex", "mprotect", "sigprocmask", "create_module",
+    "init_module", "delete_module", "get_kernel_syms",
+    "quotactl", "getpgid", "fchdir", "bdflush", "sysfs",
+    "personality", "afs_syscall", "setfsuid", "setfsgid",
+    "_llseek", "getdents", "_newselect", "flock", "msync",
+    "readv", "writev", "getsid", "fdatasync", "_sysctl",
+    "mlock", "munlock", "mlockall", "munlockall",
+    "sched_setparam", "sched_getparam", "sched_setscheduler",
+    "sched_getscheduler", "sched_yield", 
+    "sched_get_priority_max", "sched_get_priority_min",
+    "sched_rr_get_interval", "nanosleep", "mremap",
+    "setresuid", "getresuid", "query_module", "poll",
+    "nfsservctl", "setresgid", "getresgid", "prctl",
+    "rt_sigreturn", "rt_sigaction", "rt_sigprocmask",
+    "rt_sigpending", "rt_sigtimedwait", "rt_sigqueueinfo",
+    "rt_sigsuspend", "pread64", "pwrite64", "chown",
+    "getcwd", "capget", "capset", "sigaltstack", "sendfile",
+    "getpmsg", "putpmsg", "vfork", "ugetrlimit", "readahead",
+    "mmap2", "truncate64", "ftruncate64", "stat64", "lstat64",
+    "fstat64", "pciconfig_read", "pciconfig_write",
+    "pciconfig_iobase", "multiplexer", "getdents64",
+    "pivot_root", "fcntl64", "madvise", "mincore", "gettid",
+    "tkill", "setxattr", "lsetxattr", "fsetxattr", 
+    "getxattr", "lgetxattr", "fgetxattr", "listxattr",
+    "llistxattr", "flistxattr", "removexattr", "lremovexattr",
+    "fremovexattr", "futex", "sched_setaffinity",
+    "sched_getaffinity", "", "tuxcall", "sendfile64",
+    "io_setup", "io_destroy", "io_getevents", "io_submit",
+    "io_cancel", "set_tid_address", "fadvise64", "exit_group",
+    "lookup_dcookie", "epoll_create", "epoll_ctl",
+    "epoll_wait", "remap_file_pages", "timer_create",
+    "timer_settime", "timer_gettime", "timer_getoverrun",
+    "timer_delete", "clock_settime", "clock_gettime",
+    "clock_getres", "clock_nanosleep", "swapcontext",
+    "tgkill", "utimes", "statfs64", "fstatfs64", "fadvise64_64",
+    "rtas", "sys_debug_setcontext", "", "", "mbind",
+    "get_mempolicy", "set_mempolicy", "mq_open", "mq_unlink",
+    "mq_timedsend", "mq_timedreceive", "mq_notify",
+    "mq_getsetattr", "kexec_load", "add_key", "request_key",
+    "keyctl", "waitid", "ioprio_set", "ioprio_get",
+    "inotify_init", "inotify_add_watch", "inotify_rm_watch",
+    "spu_run", "spu_create", "pselect6", "ppoll", "unshare",
+    "", "", "", "openat", "mkdirat", "mknodat", "fchownat",
+    "futimesat", "fstatat64", "unlinkat", "renameat",
+    "linkat", "symlinkat", "readlinkat", "fchmodat",
+    "faccessat", "", ""
+};
+
+/* Syscalls names for PPC 64-bit */
+static const char *syscalls_names64[] = {
+    "restart_syscall", "exit", "fork", "read", "write", "open",
+    "close", "waitpid", "creat", "link", "unlink", "execve",
+    "chdir", "time", "mknod", "chmod", "lchown", "break", "oldstat",
+    "lseek", "getpid", "mount", "umount", "setuid", "getuid", "stime",
+    "ptrace", "alarm", "oldfstat", "pause", "utime", "stty", "gtty",
+    "access", "nice", "ftime", "sync", "kill", "rename", "mkdir",
+    "rmdir", "dup", "pipe", "times", "prof", "brk", "setgid",
+    "getgid", "signal", "geteuid", "getegid", "acct", "umount2",
+    "lock", "ioctl", "fcntl", "mpx", "setpgid", "ulimit",
+    "oldolduname", "umask", "chroot", "ustat", "dup2", "getppid",
+    "getpgrp", "setsid", "sigaction", "sgetmask", "ssetmask",
+    "setreuid", "setregid", "sigsuspend", "sigpending", "sethostname",
+    "setrlimit", "getrlimit", "getrusage", "gettimeofday", "settimeofday",
+    "getgroups", "setgroups", "select", "symlink", "oldlstat",
+    "readlink", "uselib", "swapon", "reboot", "readdir", "mmap",
+    "munmap", "truncate", "ftruncate", "fchmod", "fchown", "getpriority",
+    "setpriority", "profil", "statfs", "fstatfs", "ioperm", "socketcall",
+    "syslog", "setitimer", "getitimer", "stat", "lstat", "fstat",
+    "olduname", "iopl", "vhangup", "idle", "vm86", "wait4", "swapoff",
+    "sysinfo", "ipc", "fsync", "sigreturn", "clone", "setdomainname",
+    "uname", "modify_ldt", "adjtimex", "mprotect", "sigprocmask",
+    "create_module", "init_module", "delete_module", "get_kernel_syms",
+    "quotactl", "getpgid", "fchdir", "bdflush", "sysfs", "personality",
+    "afs_syscall", "setfsuid", "setfsgid", "_llseek", "getdents",
+    "_newselect", "flock", "msync", "readv", "writev", "getsid",
+    "fdatasync", "_sysctl", "mlock", "munlock", "mlockall",
+    "munlockall", "sched_setparam", "sched_getparam", "sched_setscheduler",
+    "sched_getscheduler", "sched_yield", "sched_get_priority_max",
+    "sched_get_priority_min", "sched_rr_get_interval", "nanosleep",
+    "mremap", "setresuid", "getresuid", "query_module", "poll",
+    "nfsservctl", "setresgid", "getresgid", "prctl", "rt_sigreturn",
+    "rt_sigaction", "rt_sigprocmask", "rt_sigpending", "rt_sigtimedwait",
+    "rt_sigqueueinfo", "rt_sigsuspend", "pread64", "pwrite64", "chown",
+    "getcwd", "capget", "capset", "sigaltstack", "sendfile", "getpmsg",
+    "putpmsg", "vfork", "ugetrlimit", "readahead", "", "", "", "", "", "",
+    "pciconfig_read", "pciconfig_write", "pciconfig_iobase", "multiplexer",
+    "getdents64", "pivot_root", "", "madvise", "mincore", "gettid", "tkill",
+    "setxattr", "lsetxattr", "fsetxattr", "getxattr", "lgetxattr", "fgetxattr",
+    "listxattr", "llistxattr", "flistxattr", "removexattr", "lremovexattr",
+    "fremovexattr", "futex", "sched_setaffinity", "sched_getaffinity",
+    "", "tuxcall", "", "io_setup", "io_destroy", "io_getevents", "io_submit",
+    "io_cancel", "set_tid_address", "fadvise64", "exit_group", "lookup_dcookie",
+    "epoll_create", "epoll_ctl", "epoll_wait", "remap_file_pages",
+    "timer_create", "timer_settime", "timer_gettime", "timer_getoverrun",
+    "timer_delete", "clock_settime", "clock_gettime", "clock_getres",
+    "clock_nanosleep", "swapcontext", "tgkill", "utimes", "statfs64",
+    "fstatfs64", "", "rtas", "sys_debug_setcontext", "", "", "mbind",
+    "get_mempolicy", "set_mempolicy", "mq_open", "mq_unlink", "mq_timedsend",
+    "mq_timedreceive", "mq_notify", "mq_getsetattr", "kexec_load", "add_key",
+    "request_key", "keyctl", "waitid", "ioprio_set", "ioprio_get",
+    "inotify_init", "inotify_add_watch", "inotify_rm_watch", "spu_run",
+    "spu_create", "pselect6", "ppoll", "unshare", "", "", "",
+    "openat", "mkdirat", "mknodat", "fchownat", "futimesat", "newfstatat",
+    "unlinkat", "renameat", "linkat", "symlinkat", "readlinkat",
+    "fchmodat", "faccessat", "", ""
+};
 
 /* ppc_linux_memory_remove_breakpoints attempts to remove a breakpoint
    in much the same fashion as memory_remove_breakpoint in mem-break.c,
@@ -1003,6 +1139,83 @@ ppc_linux_trap_reg_p (struct gdbarch *gdbarch)
          && register_size (gdbarch, PPC_TRAP_REGNUM) > 0;
 }
 
+/* Return the current system call's number present in the
+   r0 register. When the function fails, it returns -1. */
+LONGEST
+ppc_linux_get_syscall_number (struct gdbarch *gdbarch,
+                              ptid_t ptid)
+{
+  struct regcache *regcache = get_thread_regcache (ptid);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  /* The content of a register */
+  gdb_byte *buf;
+  /* The result */
+  LONGEST ret;
+
+  /* Make sure we're in a 32- or 64-bit machine */
+  gdb_assert (tdep->wordsize == 4 || tdep->wordsize == 8);
+
+  buf = (gdb_byte *) xmalloc (tdep->wordsize * sizeof (gdb_byte));
+
+  /* Getting the system call number from the register.
+     When dealing with PowerPC architecture, this information
+     is stored at 0th register. */
+  regcache_cooked_read (regcache, tdep->ppc_gp0_regnum, buf);
+
+  ret = extract_signed_integer (buf, tdep->wordsize);
+  xfree (buf);
+
+  return ret;
+}
+
+const char *
+ppc_linux_syscall_name_from_number (struct gdbarch *gdbarch,
+                                    int syscall_number)
+{
+  if (syscall_number < 0
+      || syscall_number >= N_SYSCALLS)
+    return NULL;
+
+  return syscalls_names[syscall_number];
+}
+
+const char *
+ppc64_linux_syscall_name_from_number (struct gdbarch *gdbarch,
+                                      int syscall_number)
+{
+  if (syscall_number < 0
+      || syscall_number >= N_SYSCALLS)
+    return NULL;
+
+  return syscalls_names64[syscall_number];
+}
+
+int
+ppc_linux_syscall_number_from_name (struct gdbarch *gdbarch,
+                                    const char *syscall_name)
+{
+  int i;
+
+  for (i = 0; i < N_SYSCALLS; i++)
+    if (strcmp (syscall_name, syscalls_names[i]) == 0)
+      return i;
+
+  return UNKNOWN_SYSCALL;
+}
+
+int
+ppc64_linux_syscall_number_from_name (struct gdbarch *gdbarch,
+                                      const char *syscall_name)
+{
+  int i;
+
+  for (i = 0; i < N_SYSCALLS; i++)
+    if (strcmp (syscall_name, syscalls_names64[i]) == 0)
+      return i;
+
+  return UNKNOWN_SYSCALL;
+}
+
 static void
 ppc_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
 {
@@ -1074,8 +1287,13 @@ ppc_linux_init_abi (struct gdbarch_info info,
   /* Handle inferior calls during interrupted system calls.  */
   set_gdbarch_write_pc (gdbarch, ppc_linux_write_pc);
 
+  set_gdbarch_get_syscall_number (gdbarch, ppc_linux_get_syscall_number);
+
   if (tdep->wordsize == 4)
     {
+      set_gdbarch_syscall_name_from_number (gdbarch, ppc_linux_syscall_name_from_number);
+      set_gdbarch_syscall_number_from_name (gdbarch, ppc_linux_syscall_number_from_name);
+
       /* Until November 2001, gcc did not comply with the 32 bit SysV
 	 R4 ABI requirement that structures less than or equal to 8
 	 bytes should be returned in registers.  Instead GCC was using
@@ -1100,6 +1318,9 @@ ppc_linux_init_abi (struct gdbarch_info info,
   
   if (tdep->wordsize == 8)
     {
+      set_gdbarch_syscall_name_from_number (gdbarch, ppc64_linux_syscall_name_from_number);
+      set_gdbarch_syscall_number_from_name (gdbarch, ppc64_linux_syscall_number_from_name);
+
       /* Handle PPC GNU/Linux 64-bit function pointers (which are really
 	 function descriptors).  */
       set_gdbarch_convert_from_func_ptr_addr



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