Many small changes to procfs.c to add base support for a new "info proc"

command that prints /proc specific information, changes to solib.c to
allow more flexible handling of finding the dynamic linker structures,
changes to utils.c and defs.h to add a new null_cleanup() function to
serve as an anchor point for cleanup chains with no obvious "first
cleanup".
This commit is contained in:
Fred Fish 1991-12-28 06:27:24 +00:00
parent 079399f6df
commit a39ad5ce42
3 changed files with 309 additions and 41 deletions

View File

@ -1,3 +1,24 @@
Fri Dec 27 22:21:30 1991 Fred Fish (fnf at cygnus.com)
* defs.h: Add definition of null_cleanup()
* procfs.c: Many small changes to add base support for a new
"info proc" command (currently only printing of the address
space mapping is implemented) and allow iteration over the
address space mapping, calling an arbitrary function for each
mapping (used for shared library support).
* solib.c: Change all ifdefs that checked for "sun" to check
for "!SVR4_SHARED_LIBS" instead. Rewrite lookup_base() to
handle locating the debug base address even when not currently
stopped at the dynamic linker entry point.
* utils.c: Add null_cleanup() as a known function that does
nothing to serve as a base for possibly long cleanup chains
with no specific "first cleanup" to serve as an anchor.
* xm-sysv4.h: Add define of SVR4_SHARED_LIBS
Fri Dec 27 10:11:33 1991 Per Bothner (bothner at cygnus.com)
* arm-opcode.h, m88k-opcode.h, pn-opcode.h, np1-opcode.h,

View File

@ -65,8 +65,11 @@ CORE_ADDR kernel_u_addr;
/* All access to the inferior, either one started by gdb or one that has
been attached to, is controlled by an instance of a procinfo structure,
defined below. Since gdb currently only handles one inferior at a time,
the procinfo structure is statically allocated and only one exists at
any given time. */
the procinfo structure for the inferior is statically allocated and
only one exists at any given time. There is a separate procinfo
structure for use by the "info proc" command, so that we can print
useful information about any random process without interfering with
the inferior's procinfo information. */
struct procinfo {
int valid; /* Nonzero if pid, fd, & pathname are valid */
@ -82,7 +85,9 @@ struct procinfo {
sigset_t trace; /* Current traced signal set */
sysset_t exitset; /* Current traced system call exit set */
sysset_t entryset; /* Current traced system call entry set */
} pi;
};
static struct procinfo pi; /* Inferior's process information */
/* Forward declarations of static functions so we don't have to worry
about ordering within this file. The EXFUN macro may be slightly
@ -91,8 +96,8 @@ struct procinfo {
definitions. */
static void EXFUN(proc_init_failed, (char *why));
static int EXFUN(open_proc_file, (int pid));
static void EXFUN(close_proc_file, (void));
static int EXFUN(open_proc_file, (int pid, struct procinfo *pip));
static void EXFUN(close_proc_file, (struct procinfo *pip));
static void EXFUN(unconditionally_kill_inferior, (void));
/*
@ -220,7 +225,7 @@ DEFUN_VOID(unconditionally_kill_inferior)
signo = SIGKILL;
(void) ioctl (pi.fd, PIOCKILL, &signo);
close_proc_file ();
close_proc_file (&pi);
wait ((int *) 0);
}
@ -374,7 +379,7 @@ void
DEFUN(inferior_proc_init, (int pid),
int pid)
{
if (!open_proc_file (pid))
if (!open_proc_file (pid, &pi))
{
proc_init_failed ("can't open process file");
}
@ -453,6 +458,52 @@ DEFUN_VOID(proc_set_exec_trap)
/*
GLOBAL FUNCTION
proc_iterate_over_mappings -- call function for every mapped space
SYNOPSIS
int proc_iterate_over_mappings (int (*func)())
DESCRIPTION
Given a pointer to a function, call that function for every
mapped address space, passing it an open file descriptor for
the file corresponding to that mapped address space (if any)
and the base address of the mapped space. Quit when we hit
the end of the mappings or the function returns nonzero.
*/
int
DEFUN(proc_iterate_over_mappings, (func),
int (*func)())
{
int nmap;
int fd;
int funcstat = 0;
struct prmap *prmaps;
struct prmap *prmap;
CORE_ADDR baseaddr = 0;
if (pi.valid && (ioctl (pi.fd, PIOCNMAP, &nmap) == 0))
{
prmaps = alloca ((nmap + 1) * sizeof (*prmaps));
if (ioctl (pi.fd, PIOCMAP, prmaps) == 0)
{
for (prmap = prmaps; prmap -> pr_size && funcstat == 0; ++prmap)
{
fd = proc_address_to_fd (prmap -> pr_vaddr, 0);
funcstat = (*func) (fd, prmap -> pr_vaddr);
close (fd);
}
}
}
return (funcstat);
}
/*
GLOBAL FUNCTION
proc_base_address -- find base address for segment containing address
@ -482,7 +533,7 @@ DEFUN(proc_base_address, (addr),
struct prmap *prmap;
CORE_ADDR baseaddr = 0;
if (ioctl (pi.fd, PIOCNMAP, &nmap) == 0)
if (pi.valid && (ioctl (pi.fd, PIOCNMAP, &nmap) == 0))
{
prmaps = alloca ((nmap + 1) * sizeof (*prmaps));
if (ioctl (pi.fd, PIOCMAP, prmaps) == 0)
@ -509,7 +560,7 @@ GLOBAL_FUNCTION
SYNOPSIS
int proc_address_to_fd (CORE_ADDR addr)
int proc_address_to_fd (CORE_ADDR addr, complain)
DESCRIPTION
@ -522,8 +573,9 @@ DESCRIPTION
*/
int
DEFUN(proc_address_to_fd, (addr),
CORE_ADDR addr)
DEFUN(proc_address_to_fd, (addr, complain),
CORE_ADDR addr AND
int complain)
{
int fd = -1;
@ -531,8 +583,11 @@ DEFUN(proc_address_to_fd, (addr),
{
if ((fd = ioctl (pi.fd, PIOCOPENM, (caddr_t *) &addr)) < 0)
{
print_sys_errmsg (pi.pathname, errno);
warning ("can't find mapped file for address 0x%x", addr);
if (complain)
{
print_sys_errmsg (pi.pathname, errno);
warning ("can't find mapped file for address 0x%x", addr);
}
}
}
return (fd);
@ -569,7 +624,7 @@ int
DEFUN(attach, (pid),
int pid)
{
if (!open_proc_file (pid))
if (!open_proc_file (pid, &pi))
{
perror_with_name (pi.pathname);
/* NOTREACHED */
@ -582,7 +637,7 @@ DEFUN(attach, (pid),
if (ioctl (pi.fd, PIOCSTATUS, &pi.prstatus) < 0)
{
print_sys_errmsg (pi.pathname, errno);
close_proc_file ();
close_proc_file (&pi);
error ("PIOCSTATUS failed");
}
if (pi.prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
@ -597,7 +652,7 @@ DEFUN(attach, (pid),
if (ioctl (pi.fd, PIOCSTOP, &pi.prstatus) < 0)
{
print_sys_errmsg (pi.pathname, errno);
close_proc_file ();
close_proc_file (&pi);
error ("PIOCSTOP failed");
}
}
@ -716,7 +771,7 @@ DEFUN(detach, (signal),
}
}
}
close_proc_file ();
close_proc_file (&pi);
attach_flag = 0;
}
@ -1046,7 +1101,7 @@ DEFUN(proc_init_failed, (why),
{
print_sys_errmsg (pi.pathname, errno);
(void) kill (pi.pid, SIGKILL);
close_proc_file ();
close_proc_file (&pi);
error (why);
/* NOTREACHED */
}
@ -1059,7 +1114,7 @@ LOCAL FUNCTION
SYNOPSIS
static void close_proc_file (void)
static void close_proc_file (struct procinfo *pip)
DESCRIPTION
@ -1071,20 +1126,21 @@ DESCRIPTION
*/
static void
DEFUN_VOID(close_proc_file)
DEFUN(close_proc_file, (pip),
struct procinfo *pip)
{
pi.pid = 0;
if (pi.valid)
pip -> pid = 0;
if (pip -> valid)
{
(void) close (pi.fd);
(void) close (pip -> fd);
}
pi.fd = -1;
if (pi.pathname)
pip -> fd = -1;
if (pip -> pathname)
{
free (pi.pathname);
pi.pathname = NULL;
free (pip -> pathname);
pip -> pathname = NULL;
}
pi.valid = 0;
pip -> valid = 0;
}
/*
@ -1095,7 +1151,7 @@ LOCAL FUNCTION
SYNOPSIS
static int open_proc_file (pid)
static int open_proc_file (pid, struct procinfo *pip)
DESCRIPTION
@ -1111,25 +1167,212 @@ DESCRIPTION
*/
static int
DEFUN(open_proc_file, (pid),
int pid)
DEFUN(open_proc_file, (pid, pip),
int pid AND
struct procinfo *pip)
{
pi.valid = 0;
if (pi.valid)
pip -> valid = 0;
if (pip -> valid)
{
(void) close (pi.fd);
(void) close (pip -> fd);
}
if (pi.pathname == NULL)
if (pip -> pathname == NULL)
{
pi.pathname = xmalloc (32);
pip -> pathname = xmalloc (32);
}
sprintf (pi.pathname, PROC_NAME_FMT, pid);
if ((pi.fd = open (pi.pathname, O_RDWR)) >= 0)
sprintf (pip -> pathname, PROC_NAME_FMT, pid);
if ((pip -> fd = open (pip -> pathname, O_RDWR)) >= 0)
{
pi.valid = 1;
pi.pid = pid;
pip -> valid = 1;
pip -> pid = pid;
}
return (pi.valid);
return (pip -> valid);
}
char *mappingflags (flags)
long flags;
{
static char asciiflags[7];
strcpy (asciiflags, "------");
if (flags & MA_STACK) asciiflags[0] = 's';
if (flags & MA_BREAK) asciiflags[1] = 'b';
if (flags & MA_SHARED) asciiflags[2] = 's';
if (flags & MA_READ) asciiflags[3] = 'r';
if (flags & MA_WRITE) asciiflags[4] = 'w';
if (flags & MA_EXEC) asciiflags[5] = 'x';
return (asciiflags);
}
static void
DEFUN(proc_info_address_map, (pip, verbose),
struct procinfo *pip AND
int verbose)
{
int nmap;
struct prmap *prmaps;
struct prmap *prmap;
printf_filtered ("Mapped address spaces:\n\n");
printf_filtered ("\t%10s %10s %10s %10s %6s\n",
"Start Addr",
" End Addr",
" Size",
" Offset",
"Flags");
if (ioctl (pip -> fd, PIOCNMAP, &nmap) == 0)
{
prmaps = alloca ((nmap + 1) * sizeof (*prmaps));
if (ioctl (pip -> fd, PIOCMAP, prmaps) == 0)
{
for (prmap = prmaps; prmap -> pr_size; ++prmap)
{
printf_filtered ("\t%#10x %#10x %#10x %#10x %6s\n",
prmap -> pr_vaddr,
prmap -> pr_vaddr + prmap -> pr_size - 1,
prmap -> pr_size,
prmap -> pr_off,
mappingflags (prmap -> pr_mflags));
}
}
}
printf_filtered ("\n\n");
}
/*
LOCAL FUNCTION
proc_info -- implement the "info proc" command
SYNOPSIS
void proc_info (char *args, int from_tty)
DESCRIPTION
Implement gdb's "info proc" command by using the /proc interface
to print status information about any currently running process.
Examples of the use of "info proc" are:
info proc Print short info about current inferior.
info proc verbose Print verbose info about current inferior.
info proc 123 Print short info about process pid 123.
info proc 123 verbose Print verbose info about process pid 123.
*/
static void
DEFUN(proc_info, (args, from_tty),
char *args AND
int from_tty)
{
int verbose = 0;
int pid;
struct procinfo pii;
struct procinfo *pip;
struct cleanup *old_chain;
char *nexttok;
extern char *strtok ();
old_chain = make_cleanup (null_cleanup, 0);
/* Default to using the current inferior if no pid specified */
pip = &pi;
/* Parse the args string, looking for "verbose" (or any abbrev) and
for a specific pid. If a specific pid is found, the process
file is opened. */
if (args != NULL)
{
while ((nexttok = strtok (args, " \t")) != NULL)
{
args = NULL;
if (strncmp (nexttok, "verbose", strlen (nexttok)) == 0)
{
verbose++;
}
else if ((pii.pid = atoi (nexttok)) > 0)
{
pid = pii.pid;
pip = &pii;
(void) memset (&pii, 0, sizeof (pii));
if (!open_proc_file (pid, pip))
{
perror_with_name (pip -> pathname);
/* NOTREACHED */
}
make_cleanup (close_proc_file, pip);
}
}
}
/* If we don't have a valid open process at this point, then we have no
inferior or didn't specify a specific pid. */
if (!pip -> valid)
{
error ("No process. Run an inferior or specify an explicit pid.");
}
if (ioctl (pip -> fd, PIOCSTATUS, &(pip -> prstatus)) < 0)
{
print_sys_errmsg (pip -> pathname, errno);
error ("PIOCSTATUS failed");
}
printf_filtered ("\nStatus information for %s:\n\n", pip -> pathname);
proc_info_address_map (pip, verbose);
#if 0
proc_info_flags (pip, verbose);
proc_info_why (pip, verbose);
proc_info_what (pip, verbose);
proc_info_info (pip, verbose);
proc_info_cursig (pip, verbose);
proc_info_sigpend (pip, verbose);
proc_info_sighold (pip, verbose);
proc_info_altstack (pip, verbose);
proc_info_action (pip, verbose);
proc_info_id (pip, verbose);
proc_info_times (pip, verbose);
proc_info_clname (pip,verbose);
proc_info_instr (pip, verbose);
proc_info_reg (pip, verbose);
#endif
/* All done, deal with closing any temporary process info structure,
freeing temporary memory , etc. */
do_cleanups (old_chain);
}
/*
GLOBAL FUNCTION
_initialize_proc_fs -- initialize the process file system stuff
SYNOPSIS
void _initialize_proc_fs (void)
DESCRIPTION
Do required initializations during gdb startup for using the
/proc file system interface.
*/
static char *proc_desc =
"Show current process status information using /proc entry.\n\
With no arguments, prints short form. With 'verbose' prints long form.";
void
_initialize_proc_fs ()
{
add_info ("proc", proc_info, proc_desc);
}
#endif /* USE_PROC_FS */

View File

@ -18,6 +18,10 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Use SVR4 style shared library support */
#define SVR4_SHARED_LIBS
/* SVR4 has /proc support, so use it instead of ptrace. */
#define USE_PROC_FS