* [PATCH RFA] procfs.c related changes for AIX 5
@ 2001-03-05 18:58 Kevin Buettner
2001-03-06 1:11 ` Eli Zaretskii
[not found] ` <3AAEC861.2756C62A@cygnus.com>
0 siblings, 2 replies; 16+ messages in thread
From: Kevin Buettner @ 2001-03-05 18:58 UTC (permalink / raw)
To: Robert Lipe, David Taylor, Michael Snyder, Nick Duffek, Peter Schauer
Cc: gdb-patches
The patch below represent the changes needed to procfs.c and related files
for making GDB work natively on AIX5/IA-64.
Here is a high-level description of the more significant changes which
were required:
1) The operation code for writing to /proc/PID/ctl is an int (32-bits)
on AIX5/IA-64 and not a long (64-bits). At Michael Snyder's
suggestion, a new type called procfs_ctl_t was added to
proc-utils.h. By default, this type will be defined to be a long
(which is what Solaris and Unixware want), but a native port can
override this by defining PROC_CTL_WORD_TYPE in a suitable fashion
in the appropriate nm-*.h files.
There were many places in the code which assumed that the
operation code for writing to /proc/PID/ctl was a long. These
were all changed to be procfs_ctl_t instead.
2) AIX5 does not have a static set of syscalls. Consequently, there
is no sys/syscall.h file which provides a nice mapping of
symbolic names to syscall numbers. Instead, AIX5 provides
/proc/PID/sysent which contains the information necessary to map
strings to syscall numbers.
These syscall numbers are guaranteed (at least according to the
developer that I spoke with) to be fixed for the lifetime of a
process, but they can certainly vary between processes.
The changes needed to the code due to this change were fairly
significant:
a) sysset_t data structures (or data structures which contain
sysset_t) must be dynamically allocated. They must be
copied with memcpy() and explicitly freed when no longer
needed.
b) Comparisons against SYS_* constants no longer work. I've
introduced a number of predicate functions (such as
syscall_is_exit()) which will indicate whether a
given system call number is a particular system call. All code
which formerly relied on comparisons against a system call
number was rewritten to call one of these new predicate
functions instead.
3) AIX5 uses differently named types for representing sigset_t,
struct sigaction, and struct siginfo. In addition, due to the
fact that system call numbers are represented differently, the
premptyset, praddset, prdelset, and prismember macros (which are
also used to query/modify signal sets) no longer work for sets of
system calls. AIX5 has added macros for this. They are
premptysysset, praddsysset, prdelsysset, and prissyssetmember.
Fortunately, the changes needed for accomodating these differences
were fairly mechanical. But they still bulk up the final patch.
I have tested this patch on sparc-sun-solaris2.7 and
ia64-unknown-aix5.0 and see no ill effects. I would also like to test
it on Unixware, but do not have access to a Unixware machine at the
moment. As soon as my access to a Unixware machine is restored, I
will test this patch there too.
It's not clear to me who it is that needs to approve these changes;
Initially, I assumed it was Michael Snyder and/or David Taylor since
they are listed as the Solaris/SPARC maintainers. But, now that I
look at the list again, I also see that Nick Duffek and Peter Schauer
are listed as the Solaris/x86 maintainers. Also, Nick and Robert Lipe
are listed as the Unixware maintainers, and as noted earlier, these
changes will likely affect Unixware native support.
Anyway, I would appreciate it if one or more of these gentlemen would
look over the patches below and give approval (or not) as you see fit.
Thanks,
Kevin
* proc-utils.h (procfs_ctl_t): New typedef.
* proc-api.c (write_with_trace): Change type of ``opcode'' from
long to procfs_ctl_t. Don't assume that the target has defined
BREAKPOINT. Handle case in which PCRESET is the same as PCUNSET.
* proc-events.c (sys/syscall.h, sys/fault.h): Include these
files.
* procfs.c (sys/fault.h, sys/syscall.h): Include.
(SYSENT_PROC_NAME_FMT): Define.
(gdb_sigset_t, gdb_premptysysset, gdb_praddsysset, gdb_prdelsysset,
gdb_pr_issyssetmember, sigaction, siginfo): Conditionally
define as appropriate for AIX/non-AIX systems. Use these defines
as appropriate elsewhere in file.
(struct procinfo): Change type of saved_sigset and saved_sighold
from sigset_t to gdb_sigset_t. Make saved_exitset and
saved_entryset pointer variables. Add two new fields, num_syscalls
and syscall_names.
(DYNAMIC_SYSCALLS): Define when HAVE_PRSYSENT_T is defined.
(sysset_t_size, sysset_t_alloc): New functions.
(load_syscalls, free_syscalls, find_syscall): New functions for
platforms which define DYNAMIC_SYSCALLS.
(create_procinfo): Call load_syscalls.
(destroy_one_procinfo): Call free_syscalls.
(GDBRESET): Don't define twice.
(proc_modify_flag): Change type of operation code array `arg'
from long to procfs_ctl_t.
(proc_stop_process, proc_wait_for_stop, proc_run_process)
(proc_set_traced_signals, proc_set_traced_faults)
(proc_set_traced_sysentry, proc_set_traced_sysexit)
(proc_set_held_signals, proc_clear_current_fault)
(proc_set_current_signal, proc_clear_current_signal, proc_set_gregs)
(proc_set_fpregs, proc_kill, proc_set_watchpoint): Likewise for `cmd'.
(proc_set_traced_sysentry): Dynamically allocate variable sized
struct gdb_proc_ctl_pcsentry. Also, free it at function exit.
(proc_set_traced_sysexit): Dynamically allocate variable
sized struct gdb_proc_ctl_pcsexit. Also, free it at
function exit.
(proc_get_traced_sysentry, proc_get_traced_sysexit): Add new code
for reading the sysset_t struct on AIX5.
(procfs_debug_inferior): Don't assume that SYS_exit will be
defined. Add new code for finding certain syscalls on AIX5.
(syscall_is_lwp_exit, syscall_is_exit, syscall_is_exec)
(syscall_is_lwp_create): New functions.
(procfs_wait): Restructured code which checks for certain
system calls to use the new syscall_is_... functions.
(procfs_notice_signals): Account for the fact that saved_entryset
and saved_exitset in struct procinfo are now pointers.
(procfs_xfer_memory): Update declaration to include the
struct mem_attrib * parameter.
Index: proc-api.c
===================================================================
RCS file: /cvs/src/src/gdb/proc-api.c,v
retrieving revision 1.7
diff -u -p -r1.7 proc-api.c
--- proc-api.c 2001/02/19 11:47:16 1.7
+++ proc-api.c 2001/03/06 01:32:36
@@ -446,12 +446,12 @@ write_with_trace (int fd, void *varg, si
{
int i;
int ret;
- long *arg = (long *) varg;
+ procfs_ctl_t *arg = (procfs_ctl_t *) varg;
prepare_to_trace ();
if (procfs_trace)
{
- long opcode = arg[0];
+ procfs_ctl_t opcode = arg[0];
for (i = 0; rw_table[i].name != NULL; i++)
if (rw_table[i].value == opcode)
break;
@@ -475,8 +475,10 @@ write_with_trace (int fd, void *varg, si
case PCUNSET:
#endif
#ifdef PCRESET
+#if PCRESET != PCUNSET
case PCRESET:
#endif
+#endif
fprintf (procfs_file ? procfs_file : stdout,
"write (PCRESET, %s) %s\n",
arg[1] == PR_FORK ? "PR_FORK" :
@@ -551,6 +553,7 @@ write_with_trace (int fd, void *varg, si
break;
default:
{
+#ifdef BREAKPOINT
static unsigned char break_insn[] = BREAKPOINT;
if (len == sizeof (break_insn) &&
@@ -558,7 +561,9 @@ write_with_trace (int fd, void *varg, si
fprintf (procfs_file ? procfs_file : stdout,
"write (<breakpoint at 0x%08lx>) \n",
(unsigned long) lseek_offset);
- else if (rw_table[i].name)
+ else
+#endif
+ if (rw_table[i].name)
fprintf (procfs_file ? procfs_file : stdout,
"write (%s) %s\n",
rw_table[i].name,
Index: proc-events.c
===================================================================
RCS file: /cvs/src/src/gdb/proc-events.c,v
retrieving revision 1.3
diff -u -p -r1.3 proc-events.c
--- proc-events.c 2000/07/30 01:48:26 1.3
+++ proc-events.c 2001/03/06 01:32:38
@@ -40,8 +40,12 @@ Inc., 59 Temple Place - Suite 330, Bosto
#include <stdio.h>
#include <sys/types.h>
#include <sys/procfs.h>
+#ifdef HAVE_SYS_SYSCALL_H
#include <sys/syscall.h>
+#endif
+#ifdef HAVE_SYS_FAULT_H
#include <sys/fault.h>
+#endif
/* Much of the information used in the /proc interface, particularly for
printing status information, is kept as tables of structures of the
Index: proc-utils.h
===================================================================
RCS file: /cvs/src/src/gdb/proc-utils.h,v
retrieving revision 1.3
diff -u -p -r1.3 proc-utils.h
--- proc-utils.h 2000/05/07 23:09:45 1.3
+++ proc-utils.h 2001/03/06 01:32:38
@@ -92,3 +92,11 @@ extern void procfs_note (char *,
#define PROCFS_NOTE(X) procfs_note (X, __FILE__, __LINE__)
#define PROC_PRETTYFPRINT_STATUS(X,Y,Z,T) \
proc_prettyfprint_status (X, Y, Z, T)
+
+/* Define the type (and more importantly the width) of the control
+ word used to write to the /proc/PID/ctl file. */
+#if defined (PROC_CTL_WORD_TYPE)
+typedef PROC_CTL_WORD_TYPE procfs_ctl_t;
+#else
+typedef long procfs_ctl_t;
+#endif
Index: procfs.c
===================================================================
RCS file: /cvs/src/src/gdb/procfs.c,v
retrieving revision 1.22
diff -u -p -r1.22 procfs.c
--- procfs.c 2001/01/16 17:41:51 1.22
+++ procfs.c 2001/03/06 01:32:44
@@ -31,8 +31,12 @@ Inc., 59 Temple Place - Suite 330, Bosto
#endif
#include <sys/procfs.h>
+#ifdef HAVE_SYS_FAULT_H
#include <sys/fault.h>
+#endif
+#ifdef HAVE_SYS_SYSCALL_H
#include <sys/syscall.h>
+#endif
#include <sys/errno.h>
#include <sys/wait.h>
#include <signal.h>
@@ -49,6 +53,7 @@ Inc., 59 Temple Place - Suite 330, Bosto
* Solaris
* OSF
* Unixware
+ * AIX5
*
* /proc works by immitating a file system: you open a simulated file
* that represents the process you wish to interact with, and
@@ -114,7 +119,8 @@ static void procfs_mourn_inferior (void)
static void procfs_create_inferior (char *, char *, char **);
static int procfs_wait (int, struct target_waitstatus *);
static int procfs_xfer_memory (CORE_ADDR,
- char *, int, int, struct target_ops *);
+ char *, int, int, struct mem_attrib *,
+ struct target_ops *);
static int procfs_thread_alive (int);
@@ -179,7 +185,7 @@ init_procfs_ops (void)
*/
#ifdef NEW_PROC_API /* Solaris 7 && 8 method for watchpoints */
-#ifndef UNIXWARE
+#ifdef WA_READ
enum { READ_WATCHFLAG = WA_READ,
WRITE_WATCHFLAG = WA_WRITE,
EXEC_WATCHFLAG = WA_EXEC,
@@ -194,9 +200,68 @@ init_procfs_ops (void)
};
#endif
+/* gdb_sigset_t */
+#ifdef HAVE_PR_SIGSET_T
+typedef pr_sigset_t gdb_sigset_t;
+#else
+typedef sigset_t gdb_sigset_t;
+#endif
+
+/* sigaction */
+#ifdef HAVE_PR_SIGACTION64_T
+#define sigaction pr_sigaction64
+#endif
+
+/* siginfo */
+#ifdef HAVE_PR_SIGINFO64_T
+#define siginfo pr_siginfo64
+#endif
+
+/* gdb_premptysysset */
+#ifdef premptysysset
+#define gdb_premptysysset premptysysset
+#else
+#define gdb_premptysysset premptyset
+#endif
+/* praddsysset */
+#ifdef praddsysset
+#define gdb_praddsysset praddsysset
+#else
+#define gdb_praddsysset praddset
+#endif
+/* prdelsysset */
+#ifdef prdelsysset
+#define gdb_prdelsysset prdelsysset
+#else
+#define gdb_prdelsysset prdelset
+#endif
+/* prissyssetmember */
+#ifdef prissyssetmember
+#define gdb_pr_issyssetmember prissyssetmember
+#else
+#define gdb_pr_issyssetmember prismember
+#endif
+
+/* As a feature test, saying ``#if HAVE_PRSYSENT_T'' everywhere isn't
+ as intuitively descriptive as it could be, so we'll define
+ DYNAMIC_SYSCALLS to mean the same thing. Anyway, at the time of
+ this writing, this feature is only found on AIX5 systems and
+ basically means that the set of syscalls is not fixed. I.e,
+ there's no nice table that one can #include to get all of the
+ syscall numbers. Instead, they're stored in /proc/PID/sysent
+ for each process. We are at least guaranteed that they won't
+ change over the lifetime of the process. But each process could
+ (in theory) have different syscall numbers.
+*/
+#ifdef HAVE_PRSYSENT_T
+#define DYNAMIC_SYSCALLS
+#endif
+
+
+
/* =================== STRUCT PROCINFO "MODULE" =================== */
/* FIXME: this comment will soon be out of date W.R.T. threads. */
@@ -246,6 +311,7 @@ typedef prstatus_t gdb_prstatus_t;
typedef prstatus_t gdb_lwpstatus_t;
#endif /* NEW_PROC_API */
+
/* Provide default composite pid manipulation macros for systems that
don't have threads. */
@@ -284,16 +350,21 @@ typedef struct procinfo {
char pathname[MAX_PROC_NAME_SIZE]; /* Pathname to /proc entry */
fltset_t saved_fltset; /* Saved traced hardware fault set */
- sigset_t saved_sigset; /* Saved traced signal set */
- sigset_t saved_sighold; /* Saved held signal set */
- sysset_t saved_exitset; /* Saved traced system call exit set */
- sysset_t saved_entryset; /* Saved traced system call entry set */
+ gdb_sigset_t saved_sigset; /* Saved traced signal set */
+ gdb_sigset_t saved_sighold; /* Saved held signal set */
+ sysset_t *saved_exitset; /* Saved traced system call exit set */
+ sysset_t *saved_entryset; /* Saved traced system call entry set */
gdb_prstatus_t prstatus; /* Current process status info */
#ifndef NEW_PROC_API
gdb_fpregset_t fpregset; /* Current floating point registers */
#endif
+
+#ifdef DYNAMIC_SYSCALLS
+ int num_syscalls; /* Total number of syscalls */
+ char **syscall_names; /* Syscall number to name map */
+#endif
struct procinfo *thread_list;
@@ -315,6 +386,13 @@ static void do_destroy_procinfo_cleanup
static void dead_procinfo (procinfo * p, char *msg, int killp);
static int open_procinfo_files (procinfo * p, int which);
static void close_procinfo_files (procinfo * p);
+static int sysset_t_size (procinfo *p);
+static sysset_t *sysset_t_alloc (procinfo * pi);
+#ifdef DYNAMIC_SYSCALLS
+static void load_syscalls (procinfo *pi);
+static void free_syscalls (procinfo *pi);
+static int find_syscall (procinfo *pi, char *name);
+#endif /* DYNAMIC_SYSCALLS */
/* The head of the procinfo list: */
static procinfo * procinfo_list;
@@ -565,6 +643,10 @@ create_procinfo (int pid, int tid)
pi->pid = pid;
pi->tid = tid;
+#ifdef DYNAMIC_SYSCALLS
+ load_syscalls (pi);
+#endif
+
/* Chain into list. */
if (tid == 0)
{
@@ -631,6 +713,9 @@ destroy_one_procinfo (procinfo **list, p
close_procinfo_files (pi);
/* Step three: free the memory. */
+#ifdef DYNAMIC_SYSCALLS
+ free_syscalls (pi);
+#endif
xfree (pi);
}
@@ -691,6 +776,190 @@ dead_procinfo (procinfo *pi, char *msg,
error (msg);
}
+/*
+ * Function: sysset_t_size
+ *
+ * Returns the (complete) size of a sysset_t struct. Normally, this
+ * is just sizeof (syset_t), but in the case of Monterey/64, the actual
+ * size of sysset_t isn't known until runtime.
+ */
+
+static int
+sysset_t_size (procinfo * pi)
+{
+#ifndef DYNAMIC_SYSCALLS
+ return sizeof (sysset_t);
+#else
+ return sizeof (sysset_t) - sizeof (uint64_t)
+ + sizeof (uint64_t) * ((pi->num_syscalls + (8 * sizeof (uint64_t) - 1))
+ / (8 * sizeof (uint64_t)));
+#endif
+}
+
+/* Function: sysset_t_alloc
+
+ Allocate and (partially) initialize a sysset_t struct. */
+
+static sysset_t *
+sysset_t_alloc (procinfo * pi)
+{
+ sysset_t *ret;
+ int size = sysset_t_size (pi);
+ ret = xmalloc (size);
+#ifdef DYNAMIC_SYSCALLS
+ ret->pr_size = (pi->num_syscalls + (8 * sizeof (uint64_t) - 1))
+ / (8 * sizeof (uint64_t));
+#endif
+ return ret;
+}
+
+#ifdef DYNAMIC_SYSCALLS
+
+/* Function: load_syscalls
+
+ Extract syscall numbers and names from /proc/<pid>/sysent. Initialize
+ pi->num_syscalls with the number of syscalls and pi->syscall_names
+ with the names. (Certain numbers may be skipped in which case the
+ names for these numbers will be left as NULL.) */
+
+#define MAX_SYSCALL_NAME_LENGTH 256
+#define MAX_SYSCALLS 65536
+
+static void
+load_syscalls (procinfo *pi)
+{
+ char pathname[MAX_PROC_NAME_SIZE];
+ int sysent_fd;
+ prsysent_t header;
+ prsyscall_t *syscalls;
+ int i, size, maxcall;
+
+ pi->num_syscalls = 0;
+ pi->syscall_names = 0;
+
+ /* Open the file descriptor for the sysent file */
+ sprintf (pathname, "/proc/%d/sysent", pi->pid);
+ sysent_fd = open (pathname, O_RDONLY);
+ if (sysent_fd < 0)
+ {
+ error ("load_syscalls: Can't open /proc/%d/sysent", pi->pid);
+ }
+
+ size = sizeof header - sizeof (prsyscall_t);
+ if (read (sysent_fd, &header, size) != size)
+ {
+ error ("load_syscalls: Error reading /proc/%d/sysent", pi->pid);
+ }
+
+ if (header.pr_nsyscalls == 0)
+ {
+ error ("load_syscalls: /proc/%d/sysent contains no syscalls!", pi->pid);
+ }
+
+ size = header.pr_nsyscalls * sizeof (prsyscall_t);
+ syscalls = xmalloc (size);
+
+ if (read (sysent_fd, syscalls, size) != size)
+ {
+ xfree (syscalls);
+ error ("load_syscalls: Error reading /proc/%d/sysent", pi->pid);
+ }
+
+ /* Find maximum syscall number. This may not be the same as
+ pr_nsyscalls since that value refers to the number of entries
+ in the table. (Also, the docs indicate that some system
+ call numbers may be skipped.) */
+
+ maxcall = syscalls[0].pr_number;
+
+ for (i = 1; i < header.pr_nsyscalls; i++)
+ if (syscalls[i].pr_number > maxcall
+ && syscalls[i].pr_nameoff > 0
+ && syscalls[i].pr_number < MAX_SYSCALLS)
+ maxcall = syscalls[i].pr_number;
+
+ pi->num_syscalls = maxcall+1;
+ pi->syscall_names = xmalloc (pi->num_syscalls * sizeof (char *));
+
+ for (i = 0; i < pi->num_syscalls; i++)
+ pi->syscall_names[i] = NULL;
+
+ /* Read the syscall names in */
+ for (i = 0; i < header.pr_nsyscalls; i++)
+ {
+ char namebuf[MAX_SYSCALL_NAME_LENGTH];
+ int nread;
+ int callnum;
+
+ if (syscalls[i].pr_number >= MAX_SYSCALLS
+ || syscalls[i].pr_number < 0
+ || syscalls[i].pr_nameoff <= 0
+ || (lseek (sysent_fd, (off_t) syscalls[i].pr_nameoff, SEEK_SET)
+ != (off_t) syscalls[i].pr_nameoff))
+ continue;
+
+ nread = read (sysent_fd, namebuf, sizeof namebuf);
+ if (nread <= 0)
+ continue;
+
+ callnum = syscalls[i].pr_number;
+
+ if (pi->syscall_names[callnum] != NULL)
+ {
+ /* FIXME: Generate warning */
+ continue;
+ }
+
+ namebuf[nread-1] = '\0';
+ size = strlen (namebuf) + 1;
+ pi->syscall_names[callnum] = xmalloc (size);
+ strncpy (pi->syscall_names[callnum], namebuf, size-1);
+ pi->syscall_names[callnum][size-1] = '\0';
+ }
+
+ close (sysent_fd);
+ xfree (syscalls);
+}
+
+/* Function: free_syscalls
+
+ Free the space allocated for the syscall names from the procinfo
+ structure. */
+
+static void
+free_syscalls (procinfo *pi)
+{
+ if (pi->syscall_names)
+ {
+ int i;
+
+ for (i = 0; i < pi->num_syscalls; i++)
+ if (pi->syscall_names[i] != NULL)
+ xfree (pi->syscall_names[i]);
+
+ xfree (pi->syscall_names);
+ pi->syscall_names = 0;
+ }
+}
+
+/* Function: find_syscall
+
+ Given a name, look up (and return) the corresponding syscall number.
+ If no match is found, return -1. */
+
+static int
+find_syscall (procinfo *pi, char *name)
+{
+ int i;
+ for (i = 0; i < pi->num_syscalls; i++)
+ {
+ if (pi->syscall_names[i] && strcmp (name, pi->syscall_names[i]) == 0)
+ return i;
+ }
+ return -1;
+}
+#endif
+
/* =================== END, STRUCT PROCINFO "MODULE" =================== */
/* =================== /proc "MODULE" =================== */
@@ -731,11 +1000,11 @@ int proc_kill (procinfo * pi, int signo)
int proc_parent_pid (procinfo * pi);
int proc_get_nthreads (procinfo * pi);
int proc_get_current_thread (procinfo * pi);
-int proc_set_held_signals (procinfo * pi, sigset_t * sighold);
+int proc_set_held_signals (procinfo * pi, gdb_sigset_t * sighold);
int proc_set_traced_sysexit (procinfo * pi, sysset_t * sysset);
int proc_set_traced_sysentry (procinfo * pi, sysset_t * sysset);
int proc_set_traced_faults (procinfo * pi, fltset_t * fltset);
-int proc_set_traced_signals (procinfo * pi, sigset_t * sigset);
+int proc_set_traced_signals (procinfo * pi, gdb_sigset_t * sigset);
int proc_update_threads (procinfo * pi);
int proc_iterate_over_threads (procinfo * pi,
@@ -747,9 +1016,9 @@ gdb_fpregset_t *proc_get_fpregs (procinf
sysset_t *proc_get_traced_sysexit (procinfo * pi, sysset_t * save);
sysset_t *proc_get_traced_sysentry (procinfo * pi, sysset_t * save);
fltset_t *proc_get_traced_faults (procinfo * pi, fltset_t * save);
-sigset_t *proc_get_traced_signals (procinfo * pi, sigset_t * save);
-sigset_t *proc_get_held_signals (procinfo * pi, sigset_t * save);
-sigset_t *proc_get_pending_signals (procinfo * pi, sigset_t * save);
+gdb_sigset_t *proc_get_traced_signals (procinfo * pi, gdb_sigset_t * save);
+gdb_sigset_t *proc_get_held_signals (procinfo * pi, gdb_sigset_t * save);
+gdb_sigset_t *proc_get_pending_signals (procinfo * pi, gdb_sigset_t * save);
struct sigaction *proc_get_signal_actions (procinfo * pi,
struct sigaction *save);
@@ -1081,12 +1350,13 @@ proc_modify_flag (procinfo *pi, long fla
from one operating system to the next...) */
#ifdef PCUNSET
#define GDBRESET PCUNSET
-#endif
+#else
#ifdef PCRESET
#define GDBRESET PCRESET
#endif
+#endif
{
- long arg[2];
+ procfs_ctl_t arg[2];
if (mode == FLAG_SET) /* Set the flag (RLC, FORK, or ASYNC) */
arg[0] = PCSET;
@@ -1312,7 +1582,7 @@ proc_stop_process (procinfo *pi)
else
{
#ifdef NEW_PROC_API
- long cmd = PCSTOP;
+ procfs_ctl_t cmd = PCSTOP;
win = (write (pi->ctl_fd, (char *) &cmd, sizeof (cmd)) == sizeof (cmd));
#else /* ioctl method */
win = (ioctl (pi->ctl_fd, PIOCSTOP, &pi->prstatus) >= 0);
@@ -1355,7 +1625,7 @@ proc_wait_for_stop (procinfo *pi)
#ifdef NEW_PROC_API
{
- long cmd = PCWSTOP;
+ procfs_ctl_t cmd = PCWSTOP;
win = (write (pi->ctl_fd, (char *) &cmd, sizeof (cmd)) == sizeof (cmd));
/* We been runnin' and we stopped -- need to update status. */
pi->status_valid = 0;
@@ -1429,7 +1699,7 @@ proc_run_process (procinfo *pi, int step
#ifdef NEW_PROC_API
{
- long cmd[2];
+ procfs_ctl_t cmd[2];
cmd[0] = PCRUN;
cmd[1] = runflags;
@@ -1456,7 +1726,7 @@ proc_run_process (procinfo *pi, int step
*/
int
-proc_set_traced_signals (procinfo *pi, sigset_t *sigset)
+proc_set_traced_signals (procinfo *pi, gdb_sigset_t *sigset)
{
int win;
@@ -1473,13 +1743,13 @@ proc_set_traced_signals (procinfo *pi, s
#ifdef NEW_PROC_API
{
struct {
- long cmd;
+ procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
- char sigset[sizeof (sigset_t)];
+ char sigset[sizeof (gdb_sigset_t)];
} arg;
arg.cmd = PCSTRACE;
- memcpy (&arg.sigset, sigset, sizeof (sigset_t));
+ memcpy (&arg.sigset, sigset, sizeof (gdb_sigset_t));
win = (write (pi->ctl_fd, (char *) &arg, sizeof (arg)) == sizeof (arg));
}
@@ -1519,7 +1789,7 @@ proc_set_traced_faults (procinfo *pi, fl
#ifdef NEW_PROC_API
{
struct {
- long cmd;
+ procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
char fltset[sizeof (fltset_t)];
} arg;
@@ -1562,16 +1832,22 @@ proc_set_traced_sysentry (procinfo *pi,
#ifdef NEW_PROC_API
{
- struct {
- long cmd;
+ struct gdb_proc_ctl_pcsentry {
+ procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
char sysset[sizeof (sysset_t)];
- } arg;
+ } *argp;
+ int argp_size = sizeof (struct gdb_proc_ctl_pcsentry)
+ - sizeof (sysset_t)
+ + sysset_t_size (pi);
- arg.cmd = PCSENTRY;
- memcpy (&arg.sysset, sysset, sizeof (sysset_t));
+ argp = xmalloc (argp_size);
- win = (write (pi->ctl_fd, (char *) &arg, sizeof (arg)) == sizeof (arg));
+ argp->cmd = PCSENTRY;
+ memcpy (&argp->sysset, sysset, sysset_t_size (pi));
+
+ win = (write (pi->ctl_fd, (char *) argp, argp_size) == argp_size);
+ xfree (argp);
}
#else /* ioctl method */
win = (ioctl (pi->ctl_fd, PIOCSENTRY, sysset) >= 0);
@@ -1606,16 +1882,22 @@ proc_set_traced_sysexit (procinfo *pi, s
#ifdef NEW_PROC_API
{
- struct {
- long cmd;
+ struct gdb_proc_ctl_pcsexit {
+ procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
char sysset[sizeof (sysset_t)];
- } arg;
+ } *argp;
+ int argp_size = sizeof (struct gdb_proc_ctl_pcsexit)
+ - sizeof (sysset_t)
+ + sysset_t_size (pi);
- arg.cmd = PCSEXIT;
- memcpy (&arg.sysset, sysset, sizeof (sysset_t));
+ argp = xmalloc (argp_size);
- win = (write (pi->ctl_fd, (char *) &arg, sizeof (arg)) == sizeof (arg));
+ argp->cmd = PCSEXIT;
+ memcpy (&argp->sysset, sysset, sysset_t_size (pi));
+
+ win = (write (pi->ctl_fd, (char *) argp, argp_size) == argp_size);
+ xfree (argp);
}
#else /* ioctl method */
win = (ioctl (pi->ctl_fd, PIOCSEXIT, sysset) >= 0);
@@ -1634,7 +1916,7 @@ proc_set_traced_sysexit (procinfo *pi, s
*/
int
-proc_set_held_signals (procinfo *pi, sigset_t *sighold)
+proc_set_held_signals (procinfo *pi, gdb_sigset_t *sighold)
{
int win;
@@ -1651,13 +1933,13 @@ proc_set_held_signals (procinfo *pi, sig
#ifdef NEW_PROC_API
{
struct {
- long cmd;
+ procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
- char hold[sizeof (sigset_t)];
+ char hold[sizeof (gdb_sigset_t)];
} arg;
arg.cmd = PCSHOLD;
- memcpy (&arg.hold, sighold, sizeof (sigset_t));
+ memcpy (&arg.hold, sighold, sizeof (gdb_sigset_t));
win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg));
}
#else
@@ -1676,10 +1958,10 @@ proc_set_held_signals (procinfo *pi, sig
* Will also copy the sigset if 'save' is non-zero.
*/
-sigset_t *
-proc_get_pending_signals (procinfo *pi, sigset_t *save)
+gdb_sigset_t *
+proc_get_pending_signals (procinfo *pi, gdb_sigset_t *save)
{
- sigset_t *ret = NULL;
+ gdb_sigset_t *ret = NULL;
/*
* We should never have to apply this operation to any procinfo
@@ -1701,7 +1983,7 @@ proc_get_pending_signals (procinfo *pi,
ret = &pi->prstatus.pr_sigpend;
#endif
if (save && ret)
- memcpy (save, ret, sizeof (sigset_t));
+ memcpy (save, ret, sizeof (gdb_sigset_t));
return ret;
}
@@ -1750,10 +2032,10 @@ proc_get_signal_actions (procinfo *pi, s
* Will also copy the sigset if 'save' is non-zero.
*/
-sigset_t *
-proc_get_held_signals (procinfo *pi, sigset_t *save)
+gdb_sigset_t *
+proc_get_held_signals (procinfo *pi, gdb_sigset_t *save)
{
- sigset_t *ret = NULL;
+ gdb_sigset_t *ret = NULL;
/*
* We should never have to apply this operation to any procinfo
@@ -1777,14 +2059,14 @@ proc_get_held_signals (procinfo *pi, sig
#endif /* UNIXWARE */
#else /* not NEW_PROC_API */
{
- static sigset_t sigheld;
+ static gdb_sigset_t sigheld;
if (ioctl (pi->ctl_fd, PIOCGHOLD, &sigheld) >= 0)
ret = &sigheld;
}
#endif /* NEW_PROC_API */
if (save && ret)
- memcpy (save, ret, sizeof (sigset_t));
+ memcpy (save, ret, sizeof (gdb_sigset_t));
return ret;
}
@@ -1796,10 +2078,10 @@ proc_get_held_signals (procinfo *pi, sig
* Will also copy the sigset if 'save' is non-zero.
*/
-sigset_t *
-proc_get_traced_signals (procinfo *pi, sigset_t *save)
+gdb_sigset_t *
+proc_get_traced_signals (procinfo *pi, gdb_sigset_t *save)
{
- sigset_t *ret = NULL;
+ gdb_sigset_t *ret = NULL;
/*
* We should never have to apply this operation to any procinfo
@@ -1819,14 +2101,14 @@ proc_get_traced_signals (procinfo *pi, s
ret = &pi->prstatus.pr_sigtrace;
#else
{
- static sigset_t sigtrace;
+ static gdb_sigset_t sigtrace;
if (ioctl (pi->ctl_fd, PIOCGTRACE, &sigtrace) >= 0)
ret = &sigtrace;
}
#endif
if (save && ret)
- memcpy (save, ret, sizeof (sigset_t));
+ memcpy (save, ret, sizeof (gdb_sigset_t));
return ret;
}
@@ -1841,7 +2123,7 @@ proc_get_traced_signals (procinfo *pi, s
int
proc_trace_signal (procinfo *pi, int signo)
{
- sigset_t temp;
+ gdb_sigset_t temp;
/*
* We should never have to apply this operation to any procinfo
@@ -1875,7 +2157,7 @@ proc_trace_signal (procinfo *pi, int sig
int
proc_ignore_signal (procinfo *pi, int signo)
{
- sigset_t temp;
+ gdb_sigset_t temp;
/*
* We should never have to apply this operation to any procinfo
@@ -1968,17 +2250,48 @@ proc_get_traced_sysentry (procinfo *pi,
if (!proc_get_status (pi))
return NULL;
+#ifndef DYNAMIC_SYSCALLS
ret = &pi->prstatus.pr_sysentry;
-#else
+#else /* DYNAMIC_SYSCALLS */
+ {
+ static sysset_t *sysentry;
+ size_t size;
+
+ if (!sysentry)
+ sysentry = sysset_t_alloc (pi);
+ ret = sysentry;
+ if (pi->status_fd == 0 && open_procinfo_files (pi, FD_STATUS) == 0)
+ return NULL;
+ if (pi->prstatus.pr_sysentry_offset == 0)
+ {
+ gdb_premptysysset (sysentry);
+ }
+ else
+ {
+ int rsize;
+
+ if (lseek (pi->status_fd, (off_t) pi->prstatus.pr_sysentry_offset,
+ SEEK_SET)
+ != (off_t) pi->prstatus.pr_sysentry_offset)
+ return NULL;
+ size = sysset_t_size (pi);
+ gdb_premptysysset (sysentry);
+ rsize = read (pi->status_fd, sysentry, size);
+ if (rsize < 0)
+ return NULL;
+ }
+ }
+#endif /* DYNAMIC_SYSCALLS */
+#else /* !NEW_PROC_API */
{
static sysset_t sysentry;
if (ioctl (pi->ctl_fd, PIOCGENTRY, &sysentry) >= 0)
ret = &sysentry;
}
-#endif
+#endif /* NEW_PROC_API */
if (save && ret)
- memcpy (save, ret, sizeof (sysset_t));
+ memcpy (save, ret, sysset_t_size (pi));
return ret;
}
@@ -2010,7 +2323,37 @@ proc_get_traced_sysexit (procinfo *pi, s
if (!proc_get_status (pi))
return NULL;
+#ifndef DYNAMIC_SYSCALLS
ret = &pi->prstatus.pr_sysexit;
+#else /* DYNAMIC_SYSCALLS */
+ {
+ static sysset_t *sysexit;
+ size_t size;
+
+ if (!sysexit)
+ sysexit = sysset_t_alloc (pi);
+ ret = sysexit;
+ if (pi->status_fd == 0 && open_procinfo_files (pi, FD_STATUS) == 0)
+ return NULL;
+ if (pi->prstatus.pr_sysexit_offset == 0)
+ {
+ gdb_premptysysset (sysexit);
+ }
+ else
+ {
+ int rsize;
+
+ if (lseek (pi->status_fd, (off_t) pi->prstatus.pr_sysexit_offset, SEEK_SET)
+ != (off_t) pi->prstatus.pr_sysexit_offset)
+ return NULL;
+ size = sysset_t_size (pi);
+ gdb_premptysysset (sysexit);
+ rsize = read (pi->status_fd, sysexit, size);
+ if (rsize < 0)
+ return NULL;
+ }
+ }
+#endif /* DYNAMIC_SYSCALLS */
#else
{
static sysset_t sysexit;
@@ -2020,7 +2363,7 @@ proc_get_traced_sysexit (procinfo *pi, s
}
#endif
if (save && ret)
- memcpy (save, ret, sizeof (sysset_t));
+ memcpy (save, ret, sysset_t_size (pi));
return ret;
}
@@ -2050,7 +2393,7 @@ proc_clear_current_fault (procinfo *pi)
#ifdef NEW_PROC_API
{
- long cmd = PCCFAULT;
+ procfs_ctl_t cmd = PCCFAULT;
win = (write (pi->ctl_fd, (void *) &cmd, sizeof (cmd)) == sizeof (cmd));
}
#else
@@ -2078,7 +2421,7 @@ proc_set_current_signal (procinfo *pi, i
{
int win;
struct {
- long cmd;
+ procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
char sinfo[sizeof (struct siginfo)];
} arg;
@@ -2147,7 +2490,7 @@ proc_clear_current_signal (procinfo *pi)
#ifdef NEW_PROC_API
{
struct {
- long cmd;
+ procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
char sinfo[sizeof (struct siginfo)];
} arg;
@@ -2304,7 +2647,7 @@ proc_set_gregs (procinfo *pi)
{
#ifdef NEW_PROC_API
struct {
- long cmd;
+ procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
char gregs[sizeof (gdb_gregset_t)];
} arg;
@@ -2347,7 +2690,7 @@ proc_set_fpregs (procinfo *pi)
{
#ifdef NEW_PROC_API
struct {
- long cmd;
+ procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
char fpregs[sizeof (gdb_fpregset_t)];
} arg;
@@ -2409,7 +2752,7 @@ proc_kill (procinfo *pi, int signo)
else
{
#ifdef NEW_PROC_API
- long cmd[2];
+ procfs_ctl_t cmd[2];
cmd[0] = PCKILL;
cmd[1] = signo;
@@ -2468,7 +2811,7 @@ proc_set_watchpoint (procinfo *pi, CORE_
return 0;
#else
struct {
- long cmd;
+ procfs_ctl_t cmd;
char watch[sizeof (prwatch_t)];
} arg;
prwatch_t *pwatch;
@@ -3074,7 +3417,7 @@ proc_iterate_over_threads (procinfo *pi,
static int do_attach (int pid);
static void do_detach (int signo);
-static int register_gdb_signals (procinfo *, sigset_t *);
+static int register_gdb_signals (procinfo *, gdb_sigset_t *);
/*
* Function: procfs_debug_inferior
@@ -3091,9 +3434,10 @@ static int
procfs_debug_inferior (procinfo *pi)
{
fltset_t traced_faults;
- sigset_t traced_signals;
- sysset_t traced_syscall_entries;
- sysset_t traced_syscall_exits;
+ gdb_sigset_t traced_signals;
+ sysset_t *traced_syscall_entries;
+ sysset_t *traced_syscall_exits;
+ int status;
#ifdef PROCFS_DONT_TRACE_FAULTS
/* On some systems (OSF), we don't trace hardware faults.
@@ -3113,17 +3457,30 @@ procfs_debug_inferior (procinfo *pi)
if (!register_gdb_signals (pi, &traced_signals))
return __LINE__;
+
/* Register to trace the 'exit' system call (on entry). */
- premptyset (&traced_syscall_entries);
- praddset (&traced_syscall_entries, SYS_exit);
+ traced_syscall_entries = sysset_t_alloc (pi);
+ gdb_premptysysset (traced_syscall_entries);
+#ifdef SYS_exit
+ gdb_praddsysset (traced_syscall_entries, SYS_exit);
+#endif
#ifdef SYS_lwpexit
- praddset (&traced_syscall_entries, SYS_lwpexit); /* And _lwp_exit... */
+ gdb_praddsysset (traced_syscall_entries, SYS_lwpexit); /* And _lwp_exit... */
#endif
#ifdef SYS_lwp_exit
- praddset (&traced_syscall_entries, SYS_lwp_exit);
+ gdb_praddsysset (traced_syscall_entries, SYS_lwp_exit);
+#endif
+#ifdef DYNAMIC_SYSCALLS
+ {
+ int callnum = find_syscall (pi, "_exit");
+ if (callnum >= 0)
+ gdb_praddsysset (traced_syscall_entries, callnum);
+ }
#endif
- if (!proc_set_traced_sysentry (pi, &traced_syscall_entries))
+ status = proc_set_traced_sysentry (pi, traced_syscall_entries);
+ xfree (traced_syscall_entries);
+ if (!status)
return __LINE__;
#ifdef PRFS_STOPEXEC /* defined on OSF */
@@ -3149,29 +3506,42 @@ procfs_debug_inferior (procinfo *pi)
names. On the SGI, for example, there is no SYS_exec, but there
*is* a SYS_execv. So, we try to account for that. */
- premptyset (&traced_syscall_exits);
+ traced_syscall_exits = sysset_t_alloc (pi);
+ gdb_premptysysset (traced_syscall_exits);
#ifdef SYS_exec
- praddset (&traced_syscall_exits, SYS_exec);
+ gdb_praddsysset (traced_syscall_exits, SYS_exec);
#endif
#ifdef SYS_execve
- praddset (&traced_syscall_exits, SYS_execve);
+ gdb_praddsysset (traced_syscall_exits, SYS_execve);
#endif
#ifdef SYS_execv
- praddset (&traced_syscall_exits, SYS_execv);
+ gdb_praddsysset (traced_syscall_exits, SYS_execv);
#endif
#ifdef SYS_lwpcreate
- praddset (&traced_syscall_exits, SYS_lwpcreate);
- praddset (&traced_syscall_exits, SYS_lwpexit);
+ gdb_praddsysset (traced_syscall_exits, SYS_lwpcreate);
+ gdb_praddsysset (traced_syscall_exits, SYS_lwpexit);
#endif
#ifdef SYS_lwp_create /* FIXME: once only, please */
- praddset (&traced_syscall_exits, SYS_lwp_create);
- praddset (&traced_syscall_exits, SYS_lwp_exit);
+ gdb_praddsysset (traced_syscall_exits, SYS_lwp_create);
+ gdb_praddsysset (traced_syscall_exits, SYS_lwp_exit);
#endif
+#ifdef DYNAMIC_SYSCALLS
+ {
+ int callnum = find_syscall (pi, "execve");
+ if (callnum >= 0)
+ gdb_praddsysset (traced_syscall_exits, callnum);
+ callnum = find_syscall (pi, "ra_execve");
+ if (callnum >= 0)
+ gdb_praddsysset (traced_syscall_exits, callnum);
+ }
+#endif
- if (!proc_set_traced_sysexit (pi, &traced_syscall_exits))
+ status = proc_set_traced_sysexit (pi, traced_syscall_exits);
+ xfree (traced_syscall_exits);
+ if (!status)
return __LINE__;
#endif /* PRFS_STOPEXEC */
@@ -3270,10 +3640,10 @@ do_attach (int pid)
dead_procinfo (pi, "do_attach: couldn't save traced faults.", NOKILL);
if (!proc_get_traced_signals (pi, &pi->saved_sigset))
dead_procinfo (pi, "do_attach: couldn't save traced signals.", NOKILL);
- if (!proc_get_traced_sysentry (pi, &pi->saved_entryset))
+ if (!proc_get_traced_sysentry (pi, pi->saved_entryset))
dead_procinfo (pi, "do_attach: couldn't save traced syscall entries.",
NOKILL);
- if (!proc_get_traced_sysexit (pi, &pi->saved_exitset))
+ if (!proc_get_traced_sysexit (pi, pi->saved_exitset))
dead_procinfo (pi, "do_attach: couldn't save traced syscall exits.",
NOKILL);
if (!proc_get_held_signals (pi, &pi->saved_sighold))
@@ -3304,10 +3674,10 @@ do_detach (int signo)
if (!proc_set_traced_faults (pi, &pi->saved_fltset))
proc_warn (pi, "do_detach, set_traced_faults", __LINE__);
- if (!proc_set_traced_sysentry (pi, &pi->saved_entryset))
+ if (!proc_set_traced_sysentry (pi, pi->saved_entryset))
proc_warn (pi, "do_detach, set_traced_sysentry", __LINE__);
- if (!proc_set_traced_sysexit (pi, &pi->saved_exitset))
+ if (!proc_set_traced_sysexit (pi, pi->saved_exitset))
proc_warn (pi, "do_detach, set_traced_sysexit", __LINE__);
if (!proc_set_held_signals (pi, &pi->saved_sighold))
@@ -3463,6 +3833,73 @@ procfs_store_registers (int regno)
}
}
+static int
+syscall_is_lwp_exit (procinfo *pi, int scall)
+{
+
+#ifdef SYS_lwp_exit
+ if (scall == SYS_lwp_exit)
+ return 1;
+#endif
+#ifdef SYS_lwpexit
+ if (scall == SYS_lwpexit)
+ return 1;
+#endif
+ return 0;
+}
+
+static int
+syscall_is_exit (procinfo *pi, int scall)
+{
+#ifdef SYS_exit
+ if (scall == SYS_exit)
+ return 1;
+#endif
+#ifdef DYNAMIC_SYSCALLS
+ if (find_syscall (pi, "_exit") == scall)
+ return 1;
+#endif
+ return 0;
+}
+
+static int
+syscall_is_exec (procinfo *pi, int scall)
+{
+#ifdef SYS_exec
+ if (scall == SYS_exec)
+ return 1;
+#endif
+#ifdef SYS_execv
+ if (scall == SYS_execv)
+ return 1;
+#endif
+#ifdef SYS_execve
+ if (scall == SYS_execve)
+ return 1;
+#endif
+#ifdef DYNAMIC_SYSCALLS
+ if (find_syscall (pi, "_execve"))
+ return 1;
+ if (find_syscall (pi, "ra_execve"))
+ return 1;
+#endif
+ return 0;
+}
+
+static int
+syscall_is_lwp_create (procinfo *pi, int scall)
+{
+#ifdef SYS_lwp_create
+ if (scall == SYS_lwp_create)
+ return 1;
+#endif
+#ifdef SYS_lwpcreate
+ if (scall == SYS_lwpcreate)
+ return 1;
+#endif
+ return 0;
+}
+
/*
* Function: target_wait
*
@@ -3566,194 +4003,162 @@ wait_again:
wstat = (what << 8) | 0177;
break;
case PR_SYSENTRY:
- switch (what) {
-#ifdef SYS_lwp_exit
- case SYS_lwp_exit:
-#endif
-#ifdef SYS_lwpexit
- case SYS_lwpexit:
-#endif
-#if defined (SYS_lwp_exit) || defined (SYS_lwpexit)
- printf_filtered ("[%s exited]\n",
- target_pid_to_str (retval));
- delete_thread (retval);
- status->kind = TARGET_WAITKIND_SPURIOUS;
- return retval;
-#endif /* _lwp_exit */
-
- case SYS_exit:
- /* Handle SYS_exit call only */
- /* Stopped at entry to SYS_exit.
- Make it runnable, resume it, then use
- the wait system call to get its exit code.
- Proc_run_process always clears the current
- fault and signal.
- Then return its exit status. */
- pi->status_valid = 0;
- wstat = 0;
- /* FIXME: what we should do is return
- TARGET_WAITKIND_SPURIOUS. */
- if (!proc_run_process (pi, 0, 0))
- proc_error (pi, "target_wait, run_process", __LINE__);
- if (attach_flag)
- {
- /* Don't call wait: simulate waiting for exit,
- return a "success" exit code. Bogus: what if
- it returns something else? */
- wstat = 0;
- retval = inferior_pid; /* ? ? ? */
- }
- else
- {
- int temp = wait (&wstat);
-
- /* FIXME: shouldn't I make sure I get the right
- event from the right process? If (for
- instance) I have killed an earlier inferior
- process but failed to clean up after it
- somehow, I could get its termination event
- here. */
-
- /* If wait returns -1, that's what we return to GDB. */
- if (temp < 0)
- retval = temp;
- }
- break;
- default:
- printf_filtered ("procfs: trapped on entry to ");
- proc_prettyprint_syscall (proc_what (pi), 0);
- printf_filtered ("\n");
-#ifndef PIOCSSPCACT
+ if (syscall_is_lwp_exit (pi, what))
{
- long i, nsysargs, *sysargs;
-
- if ((nsysargs = proc_nsysarg (pi)) > 0 &&
- (sysargs = proc_sysargs (pi)) != NULL)
+ printf_filtered ("[%s exited]\n",
+ target_pid_to_str (retval));
+ delete_thread (retval);
+ status->kind = TARGET_WAITKIND_SPURIOUS;
+ return retval;
+ }
+ else if (syscall_is_exit (pi, what))
+ {
+ /* Handle SYS_exit call only */
+ /* Stopped at entry to SYS_exit.
+ Make it runnable, resume it, then use
+ the wait system call to get its exit code.
+ Proc_run_process always clears the current
+ fault and signal.
+ Then return its exit status. */
+ pi->status_valid = 0;
+ wstat = 0;
+ /* FIXME: what we should do is return
+ TARGET_WAITKIND_SPURIOUS. */
+ if (!proc_run_process (pi, 0, 0))
+ proc_error (pi, "target_wait, run_process", __LINE__);
+ if (attach_flag)
{
- printf_filtered ("%ld syscall arguments:\n", nsysargs);
- for (i = 0; i < nsysargs; i++)
- printf_filtered ("#%ld: 0x%08lx\n",
- i, sysargs[i]);
+ /* Don't call wait: simulate waiting for exit,
+ return a "success" exit code. Bogus: what if
+ it returns something else? */
+ wstat = 0;
+ retval = inferior_pid; /* ? ? ? */
}
+ else
+ {
+ int temp = wait (&wstat);
+ /* FIXME: shouldn't I make sure I get the right
+ event from the right process? If (for
+ instance) I have killed an earlier inferior
+ process but failed to clean up after it
+ somehow, I could get its termination event
+ here. */
+
+ /* If wait returns -1, that's what we return to GDB. */
+ if (temp < 0)
+ retval = temp;
+ }
}
-#endif
- if (status)
- {
- /* How to exit gracefully, returning "unknown event" */
- status->kind = TARGET_WAITKIND_SPURIOUS;
- return inferior_pid;
- }
- else
+ else
+ {
+ printf_filtered ("procfs: trapped on entry to ");
+ proc_prettyprint_syscall (proc_what (pi), 0);
+ printf_filtered ("\n");
+#ifndef PIOCSSPCACT
{
- /* How to keep going without returning to wfi: */
- target_resume (pid, 0, TARGET_SIGNAL_0);
- goto wait_again;
- }
- break;
- }
- break;
- case PR_SYSEXIT:
- switch (what) {
-#ifdef SYS_exec
- case SYS_exec:
-#endif
-#ifdef SYS_execv
- case SYS_execv:
-#endif
-#ifdef SYS_execve
- case SYS_execve:
-#endif
- /* Hopefully this is our own "fork-child" execing
- the real child. Hoax this event into a trap, and
- GDB will see the child about to execute its start
- address. */
- wstat = (SIGTRAP << 8) | 0177;
- break;
-#ifdef SYS_lwp_create
- case SYS_lwp_create:
-#endif
-#ifdef SYS_lwpcreate
- case SYS_lwpcreate:
-#endif
-#if defined(SYS_lwp_create) || defined(SYS_lwpcreate)
- /*
- * This syscall is somewhat like fork/exec.
- * We will get the event twice: once for the parent LWP,
- * and once for the child. We should already know about
- * the parent LWP, but the child will be new to us. So,
- * whenever we get this event, if it represents a new
- * thread, simply add the thread to the list.
- */
+ long i, nsysargs, *sysargs;
- /* If not in procinfo list, add it. */
- temp = proc_get_current_thread (pi);
- if (!find_procinfo (pi->pid, temp))
- create_procinfo (pi->pid, temp);
-
- temp = MERGEPID (pi->pid, temp);
- /* If not in GDB's thread list, add it. */
- if (!in_thread_list (temp))
- {
- printf_filtered ("[New %s]\n", target_pid_to_str (temp));
- add_thread (temp);
- }
- /* Return to WFI, but tell it to immediately resume. */
- status->kind = TARGET_WAITKIND_SPURIOUS;
- return inferior_pid;
-#endif /* _lwp_create */
+ if ((nsysargs = proc_nsysarg (pi)) > 0 &&
+ (sysargs = proc_sysargs (pi)) != NULL)
+ {
+ printf_filtered ("%ld syscall arguments:\n", nsysargs);
+ for (i = 0; i < nsysargs; i++)
+ printf_filtered ("#%ld: 0x%08lx\n",
+ i, sysargs[i]);
+ }
-#ifdef SYS_lwp_exit
- case SYS_lwp_exit:
-#endif
-#ifdef SYS_lwpexit
- case SYS_lwpexit:
+ }
#endif
-#if defined (SYS_lwp_exit) || defined (SYS_lwpexit)
- printf_filtered ("[%s exited]\n",
- target_pid_to_str (retval));
- delete_thread (retval);
- status->kind = TARGET_WAITKIND_SPURIOUS;
- return retval;
-#endif /* _lwp_exit */
-
-#ifdef SYS_sproc
- case SYS_sproc:
- /* Nothing to do here for now. The old procfs
- seemed to use this event to handle threads on
- older (non-LWP) systems, where I'm assuming that
- threads were actually separate processes. Irix,
- maybe? Anyway, low priority for now. */
-#endif
-#ifdef SYS_fork
- case SYS_fork:
- /* FIXME: do we need to handle this? Investigate. */
-#endif
-#ifdef SYS_vfork
- case SYS_vfork:
- /* FIXME: see above. */
-#endif
- default:
- printf_filtered ("procfs: trapped on exit from ");
- proc_prettyprint_syscall (proc_what (pi), 0);
- printf_filtered ("\n");
-#ifndef PIOCSSPCACT
+ if (status)
+ {
+ /* How to exit gracefully, returning "unknown event" */
+ status->kind = TARGET_WAITKIND_SPURIOUS;
+ return inferior_pid;
+ }
+ else
+ {
+ /* How to keep going without returning to wfi: */
+ target_resume (pid, 0, TARGET_SIGNAL_0);
+ goto wait_again;
+ }
+ }
+ break;
+ case PR_SYSEXIT:
+ if (syscall_is_exec (pi, what))
{
- long i, nsysargs, *sysargs;
+ /* Hopefully this is our own "fork-child" execing
+ the real child. Hoax this event into a trap, and
+ GDB will see the child about to execute its start
+ address. */
+ wstat = (SIGTRAP << 8) | 0177;
+ }
+ else if (syscall_is_lwp_create (pi, what))
+ {
+ /*
+ * This syscall is somewhat like fork/exec.
+ * We will get the event twice: once for the parent LWP,
+ * and once for the child. We should already know about
+ * the parent LWP, but the child will be new to us. So,
+ * whenever we get this event, if it represents a new
+ * thread, simply add the thread to the list.
+ */
- if ((nsysargs = proc_nsysarg (pi)) > 0 &&
- (sysargs = proc_sysargs (pi)) != NULL)
+ /* If not in procinfo list, add it. */
+ temp = proc_get_current_thread (pi);
+ if (!find_procinfo (pi->pid, temp))
+ create_procinfo (pi->pid, temp);
+
+ temp = MERGEPID (pi->pid, temp);
+ /* If not in GDB's thread list, add it. */
+ if (!in_thread_list (temp))
{
- printf_filtered ("%ld syscall arguments:\n", nsysargs);
- for (i = 0; i < nsysargs; i++)
- printf_filtered ("#%ld: 0x%08lx\n",
- i, sysargs[i]);
+ printf_filtered ("[New %s]\n", target_pid_to_str (temp));
+ add_thread (temp);
}
+ /* Return to WFI, but tell it to immediately resume. */
+ status->kind = TARGET_WAITKIND_SPURIOUS;
+ return inferior_pid;
+ }
+ else if (syscall_is_lwp_exit (pi, what))
+ {
+ printf_filtered ("[%s exited]\n",
+ target_pid_to_str (retval));
+ delete_thread (retval);
+ status->kind = TARGET_WAITKIND_SPURIOUS;
+ return retval;
+ }
+ else if (0)
+ {
+ /* FIXME: Do we need to handle SYS_sproc,
+ SYS_fork, or SYS_vfork here? The old procfs
+ seemed to use this event to handle threads on
+ older (non-LWP) systems, where I'm assuming
+ that threads were actually separate processes.
+ Irix, maybe? Anyway, low priority for now. */
}
+ else
+ {
+ printf_filtered ("procfs: trapped on exit from ");
+ proc_prettyprint_syscall (proc_what (pi), 0);
+ printf_filtered ("\n");
+#ifndef PIOCSSPCACT
+ {
+ long i, nsysargs, *sysargs;
+
+ if ((nsysargs = proc_nsysarg (pi)) > 0 &&
+ (sysargs = proc_sysargs (pi)) != NULL)
+ {
+ printf_filtered ("%ld syscall arguments:\n", nsysargs);
+ for (i = 0; i < nsysargs; i++)
+ printf_filtered ("#%ld: 0x%08lx\n",
+ i, sysargs[i]);
+ }
+ }
#endif
- status->kind = TARGET_WAITKIND_SPURIOUS;
- return inferior_pid;
- }
+ status->kind = TARGET_WAITKIND_SPURIOUS;
+ return inferior_pid;
+ }
break;
case PR_REQUESTED:
#if 0 /* FIXME */
@@ -3909,7 +4314,7 @@ wait_again:
static int
procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int dowrite,
- struct target_ops *target)
+ struct mem_attrib *attrib, struct target_ops *target)
{
procinfo *pi;
int nbytes = 0;
@@ -4143,7 +4548,7 @@ procfs_resume (int pid, int step, enum t
*/
static int
-register_gdb_signals (procinfo *pi, sigset_t *signals)
+register_gdb_signals (procinfo *pi, gdb_sigset_t *signals)
{
int signo;
@@ -4167,7 +4572,7 @@ register_gdb_signals (procinfo *pi, sigs
static void
procfs_notice_signals (int pid)
{
- sigset_t signals;
+ gdb_sigset_t signals;
procinfo *pi = find_procinfo_or_die (PIDGET (pid), 0);
if (proc_get_traced_signals (pi, &signals) &&
@@ -4366,7 +4771,7 @@ static void
procfs_init_inferior (int pid)
{
procinfo *pi;
- sigset_t signals;
+ gdb_sigset_t signals;
int fail;
/* This routine called on the parent side (GDB side)
@@ -4406,9 +4811,9 @@ procfs_init_inferior (int pid)
proc_error (pi, "init_inferior, get_held_signals", __LINE__);
if (!proc_get_traced_faults (pi, &pi->saved_fltset))
proc_error (pi, "init_inferior, get_traced_faults", __LINE__);
- if (!proc_get_traced_sysentry (pi, &pi->saved_entryset))
+ if (!proc_get_traced_sysentry (pi, pi->saved_entryset))
proc_error (pi, "init_inferior, get_traced_sysentry", __LINE__);
- if (!proc_get_traced_sysexit (pi, &pi->saved_exitset))
+ if (!proc_get_traced_sysexit (pi, pi->saved_exitset))
proc_error (pi, "init_inferior, get_traced_sysexit", __LINE__);
/* Register to trace selected signals in the child. */
@@ -4460,7 +4865,7 @@ procfs_set_exec_trap (void)
because it may be sharing data space with its parent. */
procinfo *pi;
- sysset_t exitset;
+ sysset_t *exitset;
if ((pi = create_procinfo (getpid (), 0)) == NULL)
perror_with_name ("procfs: create_procinfo failed in child.");
@@ -4503,18 +4908,31 @@ procfs_set_exec_trap (void)
names. On the SGI, for example, there is no SYS_exec, but there
*is* a SYS_execv. So, we try to account for that. */
- premptyset (&exitset);
+ exitset = sysset_t_alloc (pi);
+ gdb_premptysysset (exitset);
#ifdef SYS_exec
- praddset (&exitset, SYS_exec);
+ gdb_praddsysset (exitset, SYS_exec);
#endif
#ifdef SYS_execve
- praddset (&exitset, SYS_execve);
+ gdb_praddsysset (exitset, SYS_execve);
#endif
#ifdef SYS_execv
- praddset (&exitset, SYS_execv);
+ gdb_praddsysset (exitset, SYS_execv);
#endif
+#ifdef DYNAMIC_SYSCALLS
+ {
+ int callnum = find_syscall (pi, "execve");
+
+ if (callnum >= 0)
+ gdb_praddsysset (exitset, callnum);
- if (!proc_set_traced_sysexit (pi, &exitset))
+ callnum = find_syscall (pi, "ra_execve");
+ if (callnum >= 0)
+ gdb_praddsysset (exitset, callnum);
+ }
+#endif /* DYNAMIC_SYSCALLS */
+
+ if (!proc_set_traced_sysexit (pi, exitset))
{
proc_warn (pi, "set_exec_trap, set_traced_sysexit", __LINE__);
gdb_flush (gdb_stderr);
@@ -4738,6 +5156,7 @@ int
procfs_set_watchpoint (int pid, CORE_ADDR addr, int len, int rwflag, int after)
{
#ifndef UNIXWARE
+#ifndef AIX5
int pflags = 0;
procinfo *pi;
@@ -4777,7 +5196,8 @@ procfs_set_watchpoint (int pid, CORE_ADD
return 0; /* ignore */
proc_error (pi, "set_watchpoint", __LINE__);
}
-#endif
+#endif /* AIX5 */
+#endif /* UNIXWARE */
return 0;
}
@@ -4964,9 +5384,9 @@ proc_trace_syscalls (char *args, int fro
proc_error (pi, "proc-trace, get_traced_sysset", __LINE__);
if (mode == FLAG_SET)
- praddset (sysset, syscallnum);
+ gdb_praddsysset (sysset, syscallnum);
else
- prdelset (sysset, syscallnum);
+ gdb_prdelsysset (sysset, syscallnum);
if (entry_or_exit == PR_SYSENTRY)
{
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH RFA] procfs.c related changes for AIX 5
2001-03-05 18:58 [PATCH RFA] procfs.c related changes for AIX 5 Kevin Buettner
@ 2001-03-06 1:11 ` Eli Zaretskii
2001-03-06 1:29 ` Kevin Buettner
[not found] ` <3AAEC861.2756C62A@cygnus.com>
1 sibling, 1 reply; 16+ messages in thread
From: Eli Zaretskii @ 2001-03-06 1:11 UTC (permalink / raw)
To: Kevin Buettner
Cc: Robert Lipe, David Taylor, Michael Snyder, Nick Duffek,
Peter Schauer, gdb-patches
On Mon, 5 Mar 2001, Kevin Buettner wrote:
> 2) AIX5 does not have a static set of syscalls. Consequently, there
> is no sys/syscall.h file which provides a nice mapping of
> symbolic names to syscall numbers. Instead, AIX5 provides
> /proc/PID/sysent which contains the information necessary to map
> strings to syscall numbers.
>
> These syscall numbers are guaranteed (at least according to the
> developer that I spoke with) to be fixed for the lifetime of a
> process, but they can certainly vary between processes.
Won't this cause problems with debugging syscall-related code, since
the values for GDB and the debuggee may be different?
> The changes needed to the code due to this change were fairly
> significant:
>
> a) sysset_t data structures (or data structures which contain
> sysset_t) must be dynamically allocated. They must be
> copied with memcpy() and explicitly freed when no longer
> needed.
>
> b) Comparisons against SYS_* constants no longer work. I've
> introduced a number of predicate functions (such as
> syscall_is_exit()) which will indicate whether a
> given system call number is a particular system call. All code
> which formerly relied on comparisons against a system call
> number was rewritten to call one of these new predicate
> functions instead.
Shouldn't these be documented somehow in gdbint.texinfo?
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH RFA] procfs.c related changes for AIX 5
2001-03-06 1:11 ` Eli Zaretskii
@ 2001-03-06 1:29 ` Kevin Buettner
2001-03-06 1:41 ` Eli Zaretskii
0 siblings, 1 reply; 16+ messages in thread
From: Kevin Buettner @ 2001-03-06 1:29 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches
On Mar 6, 11:07am, Eli Zaretskii wrote:
> On Mon, 5 Mar 2001, Kevin Buettner wrote:
>
> > 2) AIX5 does not have a static set of syscalls. Consequently, there
> > is no sys/syscall.h file which provides a nice mapping of
> > symbolic names to syscall numbers. Instead, AIX5 provides
> > /proc/PID/sysent which contains the information necessary to map
> > strings to syscall numbers.
> >
> > These syscall numbers are guaranteed (at least according to the
> > developer that I spoke with) to be fixed for the lifetime of a
> > process, but they can certainly vary between processes.
>
> Won't this cause problems with debugging syscall-related code, since
> the values for GDB and the debuggee may be different?
GDB knows the pid of the debuggee and interogates its syscall
numbers in /proc/PID/sysent. I.e, it gets the syscall numbers
for the child process that it's debugging from the /proc filesystem.
If you're asking about actually debugging code that contains syscalls,
I'm not sure I see how this enters the picture. Does GDB have some
additional knowledge of syscall numbers somewhere that I'm not aware
of?
BTW, for a given release of the OS, I think there is a subset of the
syscall numbers that'll be fixed and won't change. So, in theory,
it'd be possible to use a table of #defines for these, but to the best
of my knowledge, IBM hasn't provided any in their header files.
> > The changes needed to the code due to this change were fairly
> > significant:
> >
> > a) sysset_t data structures (or data structures which contain
> > sysset_t) must be dynamically allocated. They must be
> > copied with memcpy() and explicitly freed when no longer
> > needed.
> >
> > b) Comparisons against SYS_* constants no longer work. I've
> > introduced a number of predicate functions (such as
> > syscall_is_exit()) which will indicate whether a
> > given system call number is a particular system call. All code
> > which formerly relied on comparisons against a system call
> > number was rewritten to call one of these new predicate
> > functions instead.
>
> Shouldn't these be documented somehow in gdbint.texinfo?
Probably. (I'll take a look.)
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH RFA] procfs.c related changes for AIX 5
2001-03-06 1:29 ` Kevin Buettner
@ 2001-03-06 1:41 ` Eli Zaretskii
0 siblings, 0 replies; 16+ messages in thread
From: Eli Zaretskii @ 2001-03-06 1:41 UTC (permalink / raw)
To: Kevin Buettner; +Cc: gdb-patches
On Tue, 6 Mar 2001, Kevin Buettner wrote:
> > > These syscall numbers are guaranteed (at least according to the
> > > developer that I spoke with) to be fixed for the lifetime of a
> > > process, but they can certainly vary between processes.
> >
> > Won't this cause problems with debugging syscall-related code, since
> > the values for GDB and the debuggee may be different?
>
> GDB knows the pid of the debuggee and interogates its syscall
> numbers in /proc/PID/sysent. I.e, it gets the syscall numbers
> for the child process that it's debugging from the /proc filesystem.
This probably takes care of most of the problems.
> If you're asking about actually debugging code that contains syscalls,
> I'm not sure I see how this enters the picture. Does GDB have some
> additional knowledge of syscall numbers somewhere that I'm not aware
> of?
It was just a thought; I didn't have any specifics in mind.
One possible complication is when GDB invokes a function from the
debuggee, and that function issues a system call. Again, just a
random thought.
> > Shouldn't these be documented somehow in gdbint.texinfo?
>
> Probably. (I'll take a look.)
Thanks!
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH RFA] procfs.c related changes for AIX 5
[not found] ` <msnyder@cygnus.com>
@ 2001-03-26 18:24 ` Kevin Buettner
0 siblings, 0 replies; 16+ messages in thread
From: Kevin Buettner @ 2001-03-26 18:24 UTC (permalink / raw)
To: gdb-patches
On Mar 13, 5:24pm, Michael Snyder wrote:
> Kevin Buettner wrote:
> >
> > The patch below represent the changes needed to procfs.c and related files
> > for making GDB work natively on AIX5/IA-64.
>
> Kevin,
>
> This patch looks fine. I just have a few requests:
>
> * struct sigaction and struct siginfo: could you use a typedef
> instead of a define? It will make debugging easier.
Done.
> * SYSENT_PROC_NAME_FMT: there is a changelog entry without a referent.
Good catch. I've removed this from the ChangeLog entries that were
just committed. Originally, I had added this, but during my merge
into the current sources, I discovered that it wasn't needed.
> * HAVE_SYS_SYSCALL_H, HAVE_SYS_FAULT_H: I didn't see any configury
> changes that would define these.
The configury changes have/had already been committed. See my
ChangeLog entry for 2001-03-05.
> Also, I think your changelog entries ought to say "include conditionally",
> rather than just "include". These headers were already being included.
You're right. I've fixed this too.
I've made the requested changes and have committed them. Prior to
the commit, I did test builds on AIX5, Solaris 8, and Unixware 7.
I've also tested for regressions on Unixware 7. (I had previously
tested for regressions on Solaris 8, but until recently, did not have
a Unixware 7 box to build on so I thought it prudent to test for
regressions there as well.)
The bulk of the patch is the same as what was originally posted, so
I won't repost the entire patch unless otherwise requested. The only
part which is different is from procfs.c and accomodates Michael's
request to use typedefs for struct sigaction and struct siginfo instead
of #define. Here it is...
@@ -195,9 +200,72 @@ init_procfs_ops (void)
};
#endif
+/* gdb_sigset_t */
+#ifdef HAVE_PR_SIGSET_T
+typedef pr_sigset_t gdb_sigset_t;
+#else
+typedef sigset_t gdb_sigset_t;
+#endif
+
+/* sigaction */
+#ifdef HAVE_PR_SIGACTION64_T
+typedef pr_sigaction64_t gdb_sigaction_t;
+#else
+typedef struct sigaction gdb_sigaction_t;
+#endif
+
+/* siginfo */
+#ifdef HAVE_PR_SIGINFO64_T
+typedef pr_siginfo64_t gdb_siginfo_t;
+#else
+typedef struct siginfo gdb_siginfo_t;
+#endif
+/* gdb_premptysysset */
+#ifdef premptysysset
+#define gdb_premptysysset premptysysset
+#else
+#define gdb_premptysysset premptyset
+#endif
+/* praddsysset */
+#ifdef praddsysset
+#define gdb_praddsysset praddsysset
+#else
+#define gdb_praddsysset praddset
+#endif
+
+/* prdelsysset */
+#ifdef prdelsysset
+#define gdb_prdelsysset prdelsysset
+#else
+#define gdb_prdelsysset prdelset
+#endif
+/* prissyssetmember */
+#ifdef prissyssetmember
+#define gdb_pr_issyssetmember prissyssetmember
+#else
+#define gdb_pr_issyssetmember prismember
+#endif
+
+/* As a feature test, saying ``#if HAVE_PRSYSENT_T'' everywhere isn't
+ as intuitively descriptive as it could be, so we'll define
+ DYNAMIC_SYSCALLS to mean the same thing. Anyway, at the time of
+ this writing, this feature is only found on AIX5 systems and
+ basically means that the set of syscalls is not fixed. I.e,
+ there's no nice table that one can #include to get all of the
+ syscall numbers. Instead, they're stored in /proc/PID/sysent
+ for each process. We are at least guaranteed that they won't
+ change over the lifetime of the process. But each process could
+ (in theory) have different syscall numbers.
+*/
+#ifdef HAVE_PRSYSENT_T
+#define DYNAMIC_SYSCALLS
+#endif
+
+
+
/* =================== STRUCT PROCINFO "MODULE" =================== */
/* FIXME: this comment will soon be out of date W.R.T. threads. */
^ permalink raw reply [flat|nested] 16+ messages in thread
* Pb when calling a nested function in the inferior
@ 2001-07-30 5:47 Joel Brobecker
2001-07-30 10:32 ` Michael Snyder
0 siblings, 1 reply; 16+ messages in thread
From: Joel Brobecker @ 2001-07-30 5:47 UTC (permalink / raw)
To: gdb-patches
Hi,
We have encountered a pb with gdb when one calls from gdb a nested
function which accesses some "semi-global" variables. Here,
"semi-global" means global to the nested function, but local to the
englobing function. I would appreciate some advice on what can be done
to correct the problem (if the problem can be solved, or helped, that
is). Needless to say, if something can be done, I will make the
necessary changes, and contribute them back.
Here is an example to illustrate the problem:
<<
int
main (void)
{
int first;
int result;
int
get_value (void)
{
return first;
}
first = 1;
result = get_value (); /* This is line 14 */
}
>>
%gcc -g -o hello hello.c
%gdb hello
(gdb) break hello.c:14
(gdb) run
(gdb) print first
$1 = 1
(gdb) p get_value ()
$2 = -1017254775 <<<--- This value is incorrect (should be 1)
I could reproduce this problem on several plateforms. I looked at it
more closely on Linux where I used the lastest gdb from CVS and here are
my conclusions: From the assembly code generated for hello.c, I can see
that get_value() expects the caller to place the value of variable
"first" into %ecx before the call. It does not seem that gdb is doing
this, so when the call is made, get_value reads a random value in %ecx,
thus leading to the strange value (in an equivalent program written this
time in Ada, it leads to a SIGSEGV).
FWIW, once you get past the line that invokes get_value() using "next",
the "p get_value()" command starts working fine, since the inferior did
setup the context which has not been destroyed since.
The question is: Is there a way for gdb to know that indeed get_value ()
needs some special context to be setup before being called. If yes,
then can it find out what special context is needed?
Thanks,
--
Joel
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Pb when calling a nested function in the inferior
2001-07-30 5:47 Pb when calling a nested function in the inferior Joel Brobecker
@ 2001-07-30 10:32 ` Michael Snyder
2001-07-30 11:31 ` Kevin Buettner
0 siblings, 1 reply; 16+ messages in thread
From: Michael Snyder @ 2001-07-30 10:32 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
Joel Brobecker wrote:
>
> Hi,
>
> We have encountered a pb with gdb when one calls from gdb a nested
> function which accesses some "semi-global" variables. Here,
> "semi-global" means global to the nested function, but local to the
> englobing function. I would appreciate some advice on what can be done
> to correct the problem (if the problem can be solved, or helped, that
> is). Needless to say, if something can be done, I will make the
> necessary changes, and contribute them back.
>
> Here is an example to illustrate the problem:
I've personally never used (or even seen) this
nested function syntax, so I don't know anything
useful about it. -- Michael
>
> <<
> int
> main (void)
> {
> int first;
> int result;
>
> int
> get_value (void)
> {
> return first;
> }
>
> first = 1;
> result = get_value (); /* This is line 14 */
> }
> >>
>
> %gcc -g -o hello hello.c
> %gdb hello
> (gdb) break hello.c:14
> (gdb) run
> (gdb) print first
> $1 = 1
> (gdb) p get_value ()
> $2 = -1017254775 <<<--- This value is incorrect (should be 1)
>
> I could reproduce this problem on several plateforms. I looked at it
> more closely on Linux where I used the lastest gdb from CVS and here are
> my conclusions: From the assembly code generated for hello.c, I can see
> that get_value() expects the caller to place the value of variable
> "first" into %ecx before the call. It does not seem that gdb is doing
> this, so when the call is made, get_value reads a random value in %ecx,
> thus leading to the strange value (in an equivalent program written this
> time in Ada, it leads to a SIGSEGV).
>
> FWIW, once you get past the line that invokes get_value() using "next",
> the "p get_value()" command starts working fine, since the inferior did
> setup the context which has not been destroyed since.
>
> The question is: Is there a way for gdb to know that indeed get_value ()
> needs some special context to be setup before being called. If yes,
> then can it find out what special context is needed?
>
> Thanks,
> --
> Joel
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Pb when calling a nested function in the inferior
2001-07-30 10:32 ` Michael Snyder
@ 2001-07-30 11:31 ` Kevin Buettner
2001-07-30 14:24 ` Joel Brobecker
0 siblings, 1 reply; 16+ messages in thread
From: Kevin Buettner @ 2001-07-30 11:31 UTC (permalink / raw)
To: Michael Snyder, Joel Brobecker; +Cc: gdb-patches
On Jul 30, 10:29am, Michael Snyder wrote:
> Joel Brobecker wrote:
> >
> > We have encountered a pb with gdb when one calls from gdb a nested
> > function which accesses some "semi-global" variables. Here,
> > "semi-global" means global to the nested function, but local to the
> > englobing function. I would appreciate some advice on what can be done
> > to correct the problem (if the problem can be solved, or helped, that
> > is). Needless to say, if something can be done, I will make the
> > necessary changes, and contribute them back.
> >
> > Here is an example to illustrate the problem:
>
> I've personally never used (or even seen) this
> nested function syntax, so I don't know anything
> useful about it. -- Michael
It's a gcc extension. Apparently, on i386, a pointer to the static
chain is passed in ecx. If Joel wants to fix this problem, it'd be a
good idea to see if the relevant ABI addresses this issue and then
make the appropriate changes. (The trick, I think, is to figure out
the correct value to load into ecx.)
Kevin
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Pb when calling a nested function in the inferior
2001-07-30 11:31 ` Kevin Buettner
@ 2001-07-30 14:24 ` Joel Brobecker
2001-07-30 15:41 ` Andrew Cagney
2001-07-30 15:49 ` Kevin Buettner
0 siblings, 2 replies; 16+ messages in thread
From: Joel Brobecker @ 2001-07-30 14:24 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Michael Snyder, gdb-patches
> > I've personally never used (or even seen) this
> > nested function syntax, so I don't know anything
> > useful about it. -- Michael
Yes, I hesitated a bit before posting this example, knowing that it was
a gcc extension. However, I thought it would make an easier to undertand
example rather than posting Ada95 code.
> It's a gcc extension. Apparently, on i386, a pointer to the static
> chain is passed in ecx. If Joel wants to fix this problem, it'd be a
> good idea to see if the relevant ABI addresses this issue and then
> make the appropriate changes. (The trick, I think, is to figure out
> the correct value to load into ecx.)
OK, I'll have a look and see what can be done. But before doing
anything, is there a way for gdb to detect that the function it is about
to call is nested? I think that, as a first step, having gdb diagnose
such cases and report a warning or an error would be an improvement.
Right now, it gives either an incorrect value or even crashes the
inferior.
Thanks for your help.
--
Joel
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Pb when calling a nested function in the inferior
2001-07-30 14:24 ` Joel Brobecker
@ 2001-07-30 15:41 ` Andrew Cagney
2001-07-30 15:49 ` Kevin Buettner
1 sibling, 0 replies; 16+ messages in thread
From: Andrew Cagney @ 2001-07-30 15:41 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Kevin Buettner, Michael Snyder, gdb-patches
>> > I've personally never used (or even seen) this
>> > nested function syntax, so I don't know anything
>> > useful about it. -- Michael
>
>
> Yes, I hesitated a bit before posting this example, knowing that it was
> a gcc extension. However, I thought it would make an easier to undertand
> example rather than posting Ada95 code.
Just an aside, that is definitly a good move. People are far more
likely to have GCC than Ada installed :-) Using this strategy should
also lead to a more robust test case (does this mean we're going to end
up with testsuite/gdb.ada and testsuite/gdb.gcc :-)
Regarding your question, I don't know. Perhaphs there is something in
the debug info?
Andrew
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Pb when calling a nested function in the inferior
2001-07-30 14:24 ` Joel Brobecker
2001-07-30 15:41 ` Andrew Cagney
@ 2001-07-30 15:49 ` Kevin Buettner
2001-07-31 0:24 ` Joel Brobecker
2001-08-23 3:40 ` Joel Brobecker
1 sibling, 2 replies; 16+ messages in thread
From: Kevin Buettner @ 2001-07-30 15:49 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Michael Snyder, gdb-patches
On Jul 30, 11:24pm, Joel Brobecker wrote:
> > > I've personally never used (or even seen) this
> > > nested function syntax, so I don't know anything
> > > useful about it. -- Michael
>
> Yes, I hesitated a bit before posting this example, knowing that it was
> a gcc extension. However, I thought it would make an easier to undertand
> example rather than posting Ada95 code.
Have you verified that the mechanisms used by gcc and by Ada95 for
passing the static chain are the same?
> > It's a gcc extension. Apparently, on i386, a pointer to the static
> > chain is passed in ecx. If Joel wants to fix this problem, it'd be a
> > good idea to see if the relevant ABI addresses this issue and then
> > make the appropriate changes. (The trick, I think, is to figure out
> > the correct value to load into ecx.)
>
> OK, I'll have a look and see what can be done. But before doing
> anything, is there a way for gdb to detect that the function it is about
> to call is nested? I think that, as a first step, having gdb diagnose
> such cases and report a warning or an error would be an improvement.
> Right now, it gives either an incorrect value or even crashes the
> inferior.
A couple of ideas come to mind:
1) In the version of gcc that I'm using the symbol that's associated
with get_value() is get_value.0. You could look for such symbols
and refuse to allow them to be called as inferior functions.
2) You could scan the prologue and look for a sequence of instructions
which looks like a save of the static chain. E.g, in your example,
I see:
0x804842c <get_value.0>: push %ebp
0x804842d <get_value.0+1>: mov %esp,%ebp
0x804842f <get_value.0+3>: sub $0x4,%esp
0x8048432 <get_value.0+6>: mov %ecx,0xfffffffc(%ebp)
0x8048435 <get_value.0+9>: mov 0xfffffffc(%ebp),%ecx
0x8048438 <get_value.0+12>: mov %ecx,%ecx
0x804843a <get_value.0+14>: mov 0xfffffffc(%ecx),%eax
0x804843d <get_value.0+17>: mov %eax,%eax
0x804843f <get_value.0+19>: leave
0x8048440 <get_value.0+20>: ret
It appears to me that ``mov %ecx,0xfffffffc(%ebp)'' is
responsible for saving the static chain pointer. If you could
detect this, you could print your error or warning. (You'd
want to make sure that no other instruction with a destination
of %ecx appears before this instruction in the prologue though;
if it does, it means it's doing something else.)
BTW, GDB isn't particularly graceful in its handling of the ``get_value.0''
symbol. E.g, observe what happens when I do ``x/i get_value.0'':
(gdb) x/i get_value.0
No symbol "get_value" in current context.
Kevin
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Pb when calling a nested function in the inferior
2001-07-30 15:49 ` Kevin Buettner
@ 2001-07-31 0:24 ` Joel Brobecker
2001-07-31 1:20 ` Kevin Buettner
2001-07-31 1:29 ` Kevin Buettner
2001-08-23 3:40 ` Joel Brobecker
1 sibling, 2 replies; 16+ messages in thread
From: Joel Brobecker @ 2001-07-31 0:24 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Michael Snyder, gdb-patches
> Have you verified that the mechanisms used by gcc and by Ada95 for
> passing the static chain are the same?
Yes. Actually, the code was exactly the same.
> 1) In the version of gcc that I'm using the symbol that's associated
> with get_value() is get_value.0. You could look for such symbols
> and refuse to allow them to be called as inferior functions.
this suggestion has my preference, being more general than the
suggestion below. Let me check it out.
> 2) You could scan the prologue and look for a sequence of instructions
> which looks like a save of the static chain. E.g, in your example,
> I see:
>
> 0x804842c <get_value.0>: push %ebp
> 0x804842d <get_value.0+1>: mov %esp,%ebp
> 0x804842f <get_value.0+3>: sub $0x4,%esp
> 0x8048432 <get_value.0+6>: mov %ecx,0xfffffffc(%ebp)
> 0x8048435 <get_value.0+9>: mov 0xfffffffc(%ebp),%ecx
> 0x8048438 <get_value.0+12>: mov %ecx,%ecx
> 0x804843a <get_value.0+14>: mov 0xfffffffc(%ecx),%eax
> 0x804843d <get_value.0+17>: mov %eax,%eax
> 0x804843f <get_value.0+19>: leave
> 0x8048440 <get_value.0+20>: ret
>
> It appears to me that ``mov %ecx,0xfffffffc(%ebp)'' is
> responsible for saving the static chain pointer. If you could
> detect this, you could print your error or warning. (You'd
> want to make sure that no other instruction with a destination
> of %ecx appears before this instruction in the prologue though;
> if it does, it means it's doing something else.)
>
> BTW, GDB isn't particularly graceful in its handling of the ``get_value.0''
> symbol. E.g, observe what happens when I do ``x/i get_value.0'':
>
> (gdb) x/i get_value.0
> No symbol "get_value" in current context.
That's curious. With my version of gdb, I don't get the same result
(using GNU gdb 2001-07-30-cvs (MI_OUT)):
(gdb) x/10i get_value.0
A parse error in expression, near `'.
(gdb) x/4i get_value
0x8048468 <get_value>: push %ebp
0x8048469 <get_value+1>: mov %esp,%ebp
0x804846b <get_value+3>: sub $0x4,%esp
0x804846e <get_value+6>: mov %ecx,0xfffffffc(%ebp)
--
Joel
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Pb when calling a nested function in the inferior
2001-07-31 0:24 ` Joel Brobecker
@ 2001-07-31 1:20 ` Kevin Buettner
2001-07-31 1:36 ` Joel Brobecker
2001-07-31 1:29 ` Kevin Buettner
1 sibling, 1 reply; 16+ messages in thread
From: Kevin Buettner @ 2001-07-31 1:20 UTC (permalink / raw)
To: Joel Brobecker, Kevin Buettner; +Cc: Michael Snyder, gdb-patches
On Jul 31, 9:24am, Joel Brobecker wrote:
> > BTW, GDB isn't particularly graceful in its handling of the ``get_value.0''
> > symbol. E.g, observe what happens when I do ``x/i get_value.0'':
> >
> > (gdb) x/i get_value.0
> > No symbol "get_value" in current context.
>
> That's curious. With my version of gdb, I don't get the same result
> (using GNU gdb 2001-07-30-cvs (MI_OUT)):
> (gdb) x/10i get_value.0
> A parse error in expression, near `'.
> (gdb) x/4i get_value
> 0x8048468 <get_value>: push %ebp
> 0x8048469 <get_value+1>: mov %esp,%ebp
> 0x804846b <get_value+3>: sub $0x4,%esp
> 0x804846e <get_value+6>: mov %ecx,0xfffffffc(%ebp)
Which vesion of gcc are you using? (I'm using 2.96 from Red Hat 7.0.)
Kevin
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Pb when calling a nested function in the inferior
2001-07-31 0:24 ` Joel Brobecker
2001-07-31 1:20 ` Kevin Buettner
@ 2001-07-31 1:29 ` Kevin Buettner
1 sibling, 0 replies; 16+ messages in thread
From: Kevin Buettner @ 2001-07-31 1:29 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Michael Snyder, gdb-patches
On Jul 31, 9:24am, Joel Brobecker wrote:
> That's curious. With my version of gdb, I don't get the same result
> (using GNU gdb 2001-07-30-cvs (MI_OUT)):
I forgot to mention that I'm using the same version. (Which is why
I asked about the gcc version...)
Kevin
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Pb when calling a nested function in the inferior
2001-07-31 1:20 ` Kevin Buettner
@ 2001-07-31 1:36 ` Joel Brobecker
0 siblings, 0 replies; 16+ messages in thread
From: Joel Brobecker @ 2001-07-31 1:36 UTC (permalink / raw)
To: Kevin Buettner; +Cc: Michael Snyder, gdb-patches
> > > (gdb) x/i get_value.0
> > > No symbol "get_value" in current context.
> >
> > That's curious. With my version of gdb, I don't get the same result
> > (using GNU gdb 2001-07-30-cvs (MI_OUT)):
> > (gdb) x/10i get_value.0
> > A parse error in expression, near `'.
> > (gdb) x/4i get_value
> > 0x8048468 <get_value>: push %ebp
> > 0x8048469 <get_value+1>: mov %esp,%ebp
> > 0x804846b <get_value+3>: sub $0x4,%esp
> > 0x804846e <get_value+6>: mov %ecx,0xfffffffc(%ebp)
>
> Which vesion of gcc are you using? (I'm using 2.96 from Red Hat 7.0.)
I'm using 2.95.2 20000220 (Debian GNU/Linux) (debian potato). I get the
same results with gcc 2.8.1.
--
Joel
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Pb when calling a nested function in the inferior
2001-07-30 15:49 ` Kevin Buettner
2001-07-31 0:24 ` Joel Brobecker
@ 2001-08-23 3:40 ` Joel Brobecker
1 sibling, 0 replies; 16+ messages in thread
From: Joel Brobecker @ 2001-08-23 3:40 UTC (permalink / raw)
To: gdb-patches
Hi,
I'm back on this issue I raised sometime ago: gdb calling a nested
subprogram.
> > OK, I'll have a look and see what can be done. But before doing
> > anything, is there a way for gdb to detect that the function it is about
> > to call is nested? I think that, as a first step, having gdb diagnose
> > such cases and report a warning or an error would be an improvement.
> > Right now, it gives either an incorrect value or even crashes the
> > inferior.
A few suggestions were made:
> 1) In the version of gcc that I'm using the symbol that's associated
> with get_value() is get_value.0. You could look for such symbols
> and refuse to allow them to be called as inferior functions.
I originally indicated my preference for this solution, but after
thinking a bit more about it, I don't think this will work, because
languages like C++ or Ada allow overloading. I don't know about the
convention used in C++, but in Ada with GNAT the name of the associated
symbol is made of the name of the subprogram with a suffix such as "__2"
for instance. I guess C++ does more or less the same.
> 2) You could scan the prologue and look for a sequence of instructions
> which looks like a save of the static chain. E.g, in your example,
> I see:
>
> 0x804842c <get_value.0>: push %ebp
> 0x804842d <get_value.0+1>: mov %esp,%ebp
> 0x804842f <get_value.0+3>: sub $0x4,%esp
> 0x8048432 <get_value.0+6>: mov %ecx,0xfffffffc(%ebp)
> 0x8048435 <get_value.0+9>: mov 0xfffffffc(%ebp),%ecx
> 0x8048438 <get_value.0+12>: mov %ecx,%ecx
> 0x804843a <get_value.0+14>: mov 0xfffffffc(%ecx),%eax
> 0x804843d <get_value.0+17>: mov %eax,%eax
> 0x804843f <get_value.0+19>: leave
> 0x8048440 <get_value.0+20>: ret
>
> It appears to me that ``mov %ecx,0xfffffffc(%ebp)'' is
> responsible for saving the static chain pointer. If you could
> detect this, you could print your error or warning. (You'd
> want to make sure that no other instruction with a destination
> of %ecx appears before this instruction in the prologue though;
> if it does, it means it's doing something else.)
I am not sure we really want to go in that direction. For one thing, it
is target dependent, so it will be hard to maintain. Besides, this will
become even more delicate when optimisations are turned on.
With my current limited knowledge of gdb, I came to the conclusion that
the only reliable way of detecting whether the subprogram is nested or
not, and how to set up the call is by having the compiler tell us about
this via the debug information. If there are other ideas that we can
explore, please let me know, I can investigate.
Stabs do not seem to address this issue at all, so I read the DWARF2
specifications.
I don't think the current specifications address completely this
specific issue, but I wanted to discuss this with some of the DWARF2
experts on this list.
I found the DW_AT_static_link attribute that will allow gdb to retrieve
a variable from the outer subprogram when inside the inner subprogram.
This, I think, is a nice flag that can be used to detect nested
subprogram. That would already allow us to perform a good improvement on
gdb, that is to warn a user that he is about to call a nested procedure
which is unsafe (at least for the moment).
On the other hand, there is apparently nothing that tells us that the
static chain needs to be saved in such place by doing such computation.
So we can't go one step further, which is to set up the static chain
before making the call.
A minor point: I tried to compile the small C example with DWARF2 using
a recent gcc snapshot, and got the following debug information:
<<
.byte 0x5 # uleb128 0x5; (DIE (0xa2) DW_TAG_subprogram)
.ascii "get_value\0" # DW_AT_name
.byte 0x1 # DW_AT_decl_file
.byte 0x9 # DW_AT_decl_line
.byte 0x1 # DW_AT_prototyped
.long 0x62 # DW_AT_type
.long .LFB1 # DW_AT_low_pc
.long .LFE1 # DW_AT_high_pc
.byte 0x1 # DW_AT_frame_base
.byte 0x55 # DW_OP_reg5
.byte 0x0 # end of children of DIE 0x69
>>
As far as I can see, gcc does not generate the DW_AT_static_link
attribute yet... Am I reading everything correctly? Should this
attribute be present? If yes, should we discuss this with the gcc folks?
One side question: How do I get the real register corresponding to
DW_OP_reg5? I looked in the gdb sources, and it did not seem obvious to
me. I also looked in the gcc sources, and the result I found looked
suspicious.
Thanks,
--
Joel
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2001-08-23 3:40 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-07-30 5:47 Pb when calling a nested function in the inferior Joel Brobecker
2001-07-30 10:32 ` Michael Snyder
2001-07-30 11:31 ` Kevin Buettner
2001-07-30 14:24 ` Joel Brobecker
2001-07-30 15:41 ` Andrew Cagney
2001-07-30 15:49 ` Kevin Buettner
2001-07-31 0:24 ` Joel Brobecker
2001-07-31 1:20 ` Kevin Buettner
2001-07-31 1:36 ` Joel Brobecker
2001-07-31 1:29 ` Kevin Buettner
2001-08-23 3:40 ` Joel Brobecker
-- strict thread matches above, loose matches on Subject: below --
2001-03-05 18:58 [PATCH RFA] procfs.c related changes for AIX 5 Kevin Buettner
2001-03-06 1:11 ` Eli Zaretskii
2001-03-06 1:29 ` Kevin Buettner
2001-03-06 1:41 ` Eli Zaretskii
[not found] ` <3AAEC861.2756C62A@cygnus.com>
[not found] ` <msnyder@cygnus.com>
2001-03-26 18:24 ` Kevin Buettner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox