Blame sysdeps/bsd/prockernel.c

Packit Service 407539
/* Copyright (C) 1998 Joshua Sled
Packit Service 407539
   This file is part of LibGTop 1.0.
Packit Service 407539
Packit Service 407539
   Contributed by Joshua Sled <jsled@xcf.berkeley.edu>, July 1998.
Packit Service 407539
Packit Service 407539
   LibGTop is free software; you can redistribute it and/or modify it
Packit Service 407539
   under the terms of the GNU General Public License as published by
Packit Service 407539
   the Free Software Foundation; either version 2 of the License,
Packit Service 407539
   or (at your option) any later version.
Packit Service 407539
Packit Service 407539
   LibGTop is distributed in the hope that it will be useful, but WITHOUT
Packit Service 407539
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
Packit Service 407539
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
Packit Service 407539
   for more details.
Packit Service 407539
Packit Service 407539
   You should have received a copy of the GNU General Public License
Packit Service 407539
   along with LibGTop; see the file COPYING. If not, write to the
Packit Service 407539
   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Packit Service 407539
   Boston, MA 02110-1301, USA.
Packit Service 407539
*/
Packit Service 407539
Packit Service 407539
#include <config.h>
Packit Service 407539
#include <glibtop.h>
Packit Service 407539
#include <glibtop/error.h>
Packit Service 407539
#include <glibtop/prockernel.h>
Packit Service 407539
Packit Service 407539
#include <glibtop_suid.h>
Packit Service 407539
Packit Service 407539
#include <kvm.h>
Packit Service 407539
#include <sys/param.h>
Packit Service 407539
#include <sys/sysctl.h>
Packit Service 407539
#include <sys/proc.h>
Packit Service 407539
#if (!defined __OpenBSD__) && (!defined __bsdi__)
Packit Service 407539
#include <sys/user.h>
Packit Service 407539
#endif
Packit Service 407539
#if !defined(__bsdi__) && !(defined(__FreeBSD__) && defined(__alpha__)) && \
Packit Service 407539
    !defined(__NetBSD__) 
Packit Service 407539
#include <machine/pcb.h>
Packit Service 407539
#endif
Packit Service 407539
Packit Service 407539
#include <unistd.h>
Packit Service 407539
#include <fcntl.h>
Packit Service 407539
Packit Service 407539
#ifdef __FreeBSD__
Packit Service 407539
#include <osreldate.h>
Packit Service 407539
#endif
Packit Service 407539
Packit Service 407539
#ifdef __NetBSD__
Packit Service 407539
#include <machine/vmparam.h>
Packit Service 407539
#include <machine/pmap.h>
Packit Service 407539
#ifdef __arm32__
Packit Service 407539
#define	KERNBASE	KERNEL_BASE
Packit Service 407539
#endif
Packit Service 407539
#endif
Packit Service 407539
Packit Service 407539
#ifdef __NetBSD__
Packit Service 407539
#include <machine/vmparam.h>
Packit Service 407539
#include <machine/pmap.h>
Packit Service 407539
#ifdef __arm32__
Packit Service 407539
#define	KERNBASE	KERNEL_BASE
Packit Service 407539
#endif
Packit Service 407539
#endif
Packit Service 407539
Packit Service 407539
Packit Service 407539
static const unsigned long _glibtop_sysdeps_proc_kernel_pstats =
Packit Service 407539
(1L << GLIBTOP_PROC_KERNEL_MIN_FLT) +
Packit Service 407539
(1L << GLIBTOP_PROC_KERNEL_MAJ_FLT) +
Packit Service 407539
(1L << GLIBTOP_PROC_KERNEL_CMIN_FLT) +
Packit Service 407539
(1L << GLIBTOP_PROC_KERNEL_CMAJ_FLT);
Packit Service 407539
Packit Service 407539
static const unsigned long _glibtop_sysdeps_proc_kernel_pcb =
Packit Service 407539
(1L << GLIBTOP_PROC_KERNEL_KSTK_EIP) +
Packit Service 407539
(1L << GLIBTOP_PROC_KERNEL_KSTK_ESP);
Packit Service 407539
Packit Service 407539
static const unsigned long _glibtop_sysdeps_proc_kernel_wchan =
Packit Service 407539
(1L << GLIBTOP_PROC_KERNEL_NWCHAN) +
Packit Service 407539
(1L << GLIBTOP_PROC_KERNEL_WCHAN);
Packit Service 407539
Packit Service 407539
/* Init function. */
Packit Service 407539
Packit Service 407539
void
Packit Service 407539
_glibtop_init_proc_kernel_p (glibtop *server)
Packit Service 407539
{
Packit Service 407539
	server->sysdeps.proc_kernel = _glibtop_sysdeps_proc_kernel_pstats |
Packit Service 407539
		_glibtop_sysdeps_proc_kernel_pcb |
Packit Service 407539
		_glibtop_sysdeps_proc_kernel_wchan;
Packit Service 407539
}
Packit Service 407539
Packit Service 407539
void
Packit Service 407539
glibtop_get_proc_kernel_p (glibtop *server,
Packit Service 407539
			   glibtop_proc_kernel *buf,
Packit Service 407539
			   pid_t pid)
Packit Service 407539
{
Packit Service 407539
	struct kinfo_proc *pinfo;
Packit Service 407539
#if !(defined(__FreeBSD__) || defined(__FreeBSD_kernel__))
Packit Service 407539
	struct user *u_addr = (struct user *)USRSTACK;
Packit Service 407539
	struct pstats pstats;
Packit Service 407539
	struct pcb pcb;
Packit Service 407539
#endif
Packit Service 407539
	int count;
Packit Service 407539
Packit Service 407539
	char filename [BUFSIZ];
Packit Service 407539
	struct stat statb;
Packit Service 407539
Packit Service 407539
	glibtop_init_p (server, (1L << GLIBTOP_SYSDEPS_PROC_KERNEL), 0);
Packit Service 407539
Packit Service 407539
	memset (buf, 0, sizeof (glibtop_proc_kernel));
Packit Service 407539
Packit Service 407539
	if (server->sysdeps.proc_time == 0)
Packit Service 407539
		return;
Packit Service 407539
Packit Service 407539
	/* It does not work for the swapper task. */
Packit Service 407539
	if (pid == 0) return;
Packit Service 407539
Packit Service 407539
	/* Get the process information */
Packit Service 407539
	pinfo = kvm_getprocs (server->machine->kd, KERN_PROC_PID, pid, &count);
Packit Service 407539
	if ((pinfo == NULL) || (count != 1)) {
Packit Service 407539
		glibtop_warn_io_r (server, "kvm_getprocs (%d)", pid);
Packit Service 407539
		return;
Packit Service 407539
	}
Packit Service 407539
Packit Service 407539
#if (defined(__FreeBSD__) && (__FreeBSD_version >= 500013)) || defined(__FreeBSD_kernel__)
Packit Service 407539
Packit Service 407539
#define	PROC_WCHAN	ki_wchan
Packit Service 407539
#define	PROC_WMESG	ki_wmesg
Packit Service 407539
#define	PROC_WMESG	ki_wmesg
Packit Service 407539
Packit Service 407539
#else
Packit Service 407539
Packit Service 407539
#define	PROC_WCHAN	kp_proc.p_wchan
Packit Service 407539
#define	PROC_WMESG	kp_proc.p_wmesg
Packit Service 407539
#define	PROC_WMESG	kp_eproc.e_wmesg
Packit Service 407539
Packit Service 407539
#endif
Packit Service 407539
Packit Service 407539
#if !defined(__NetBSD__) || !defined(SACTIVE)
Packit Service 407539
	buf->nwchan = (unsigned long) pinfo [0].PROC_WCHAN &~ KERNBASE;
Packit Service 407539
Packit Service 407539
	buf->flags |= (1L << GLIBTOP_PROC_KERNEL_NWCHAN);
Packit Service 407539
Packit Service 407539
	if (pinfo [0].PROC_WCHAN && pinfo [0].PROC_WMESG) {
Packit Service 407539
		g_strlcpy (buf->wchan, pinfo [0].PROC_WMESG,
Packit Service 407539
			 sizeof buf->wchan);
Packit Service 407539
		buf->flags |= (1L << GLIBTOP_PROC_KERNEL_WCHAN);
Packit Service 407539
	} else {
Packit Service 407539
		buf->wchan [0] = 0;
Packit Service 407539
	}
Packit Service 407539
#endif
Packit Service 407539
Packit Service 407539
#if !(defined(__FreeBSD__) || defined(__FreeBSD_kernel__))
Packit Service 407539
Packit Service 407539
	/* Taken from `saveuser ()' in `/usr/src/bin/ps/ps.c'. */
Packit Service 407539
Packit Service 407539
	/* [FIXME]: /usr/include/sys/user.h tells me that the user area
Packit Service 407539
	 *          may or may not be at the same kernel address in all
Packit Service 407539
	 *          processes, but I don't see any way to get that address.
Packit Service 407539
	 *          Since `ps' simply uses its own address, I think it's
Packit Service 407539
	 *          safe to do this here, too. */
Packit Service 407539
Packit Service 407539
	/* NOTE: You need to mount the /proc filesystem to make
Packit Service 407539
	 *       `kvm_uread' work. */
Packit Service 407539
Packit Service 407539
	sprintf (filename, "/proc/%d/mem", (int) pid);
Packit Service 407539
	if (stat (filename, &statb)) return;
Packit Service 407539
Packit Service 407539
	glibtop_suid_enter (server);
Packit Service 407539
Packit Service 407539
#if !defined(__NetBSD__) || !defined(SACTIVE)
Packit Service 407539
#ifdef __NetBSD__
Packit Service 407539
	/* On NetBSD, there is no kvm_uread(), and kvm_read() always reads
Packit Service 407539
	 * from kernel memory.  */
Packit Service 407539
Packit Service 407539
	if (kvm_read (server->machine->kd,
Packit Service 407539
#else
Packit Service 407539
Packit Service 407539
	if ((pinfo [0].kp_proc.p_flag & P_INMEM) &&
Packit Service 407539
	    kvm_uread (server->machine->kd, &(pinfo [0]).kp_proc,
Packit Service 407539
#endif
Packit Service 407539
		       (unsigned long) &u_addr->u_stats,
Packit Service 407539
		       (char *) &pstats, sizeof (pstats)) == sizeof (pstats))
Packit Service 407539
		{
Packit Service 407539
			/*
Packit Service 407539
			 * The u-area might be swapped out, and we can't get
Packit Service 407539
			 * at it because we have a crashdump and no swap.
Packit Service 407539
			 * If it's here fill in these fields, otherwise, just
Packit Service 407539
			 * leave them 0.
Packit Service 407539
			 */
Packit Service 407539
Packit Service 407539
			buf->min_flt = (guint64) pstats.p_ru.ru_minflt;
Packit Service 407539
			buf->maj_flt = (guint64) pstats.p_ru.ru_majflt;
Packit Service 407539
			buf->cmin_flt = (guint64) pstats.p_cru.ru_minflt;
Packit Service 407539
			buf->cmaj_flt = (guint64) pstats.p_cru.ru_majflt;
Packit Service 407539
Packit Service 407539
			buf->flags |= _glibtop_sysdeps_proc_kernel_pstats;
Packit Service 407539
		}
Packit Service 407539
Packit Service 407539
#ifdef __NetBSD__
Packit Service 407539
	if (kvm_read (server->machine->kd,
Packit Service 407539
#else
Packit Service 407539
	if ((pinfo [0].kp_proc.p_flag & P_INMEM) &&
Packit Service 407539
	    kvm_uread (server->machine->kd, &(pinfo [0]).kp_proc,
Packit Service 407539
#endif
Packit Service 407539
		       (unsigned long) &u_addr->u_pcb,
Packit Service 407539
		       (char *) &pcb, sizeof (pcb)) == sizeof (pcb))
Packit Service 407539
		{
Packit Service 407539
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
Packit Service 407539
#ifndef __alpha__
Packit Service 407539
#if (__FreeBSD_version >= 300003) || defined(__FreeBSD_kernel__)
Packit Service 407539
			buf->kstk_esp = (guint64) pcb.pcb_esp;
Packit Service 407539
			buf->kstk_eip = (guint64) pcb.pcb_eip;
Packit Service 407539
#else
Packit Service 407539
			buf->kstk_esp = (guint64) pcb.pcb_ksp;
Packit Service 407539
			buf->kstk_eip = (guint64) pcb.pcb_pc;
Packit Service 407539
#endif
Packit Service 407539
#else
Packit Service 407539
			/*xxx FreeBSD/Alpha? */
Packit Service 407539
#endif
Packit Service 407539
#else
Packit Service 407539
#ifdef __i386__
Packit Service 407539
			buf->kstk_esp = (guint64) pcb.pcb_tss.tss_esp0;
Packit Service 407539
#ifdef __bsdi__
Packit Service 407539
			buf->kstk_eip = (guint64) pcb.pcb_tss.tss_eip;
Packit Service 407539
#else
Packit Service 407539
			buf->kstk_eip = (guint64) pcb.pcb_tss.__tss_eip;
Packit Service 407539
#endif
Packit Service 407539
#else
Packit Service 407539
#if defined(__NetBSD__)
Packit Service 407539
#if defined(__m68k__)
Packit Service 407539
			buf->kstk_esp = (guint64) pcb.pcb_usp;
Packit Service 407539
			buf->kstk_eip = (guint64) 0;
Packit Service 407539
#elif defined(__x86_64__)
Packit Service 407539
			buf->kstk_esp = (guint64) pcb.pcb_usersp;
Packit Service 407539
			buf->kstk_eip = (guint64) 0;
Packit Service 407539
#elif (defined(__arm32__) || defined(__powerpc__))
Packit Service 407539
			buf->kstk_esp = (guint64) pcb.pcb_sp;
Packit Service 407539
			buf->kstk_eip = (guint64) 0;
Packit Service 407539
#elif defined(__mipsel__)
Packit Service 407539
			buf->kstk_esp = (guint64) pcb.pcb_context[8];
Packit Service 407539
			buf->kstk_eip = (guint64) 0;
Packit Service 407539
#elif defined(__sparc__)
Packit Service 407539
			buf->kstk_esp = (guint64) pcb.pcb_sp;
Packit Service 407539
			buf->kstk_eip = (guint64) pcb.pcb_pc;
Packit Service 407539
#elif defined(__alpha__)
Packit Service 407539
			buf->kstk_esp = (guint64) pcb.pcb_context[9];
Packit Service 407539
			buf->kstk_eip = (guint64) pcb.pcb_context[8];
Packit Service 407539
#else
Packit Service 407539
			/* provide some defaults for other platforms */
Packit Service 407539
			buf->kstk_esp = (guint64) 0;
Packit Service 407539
			buf->kstk_eip = (guint64) 0;
Packit Service 407539
#endif /* ${MACHINE_ARCH} */
Packit Service 407539
#endif /* __NetBSD__ */
Packit Service 407539
			buf->flags |= _glibtop_sysdeps_proc_kernel_pcb;
Packit Service 407539
#endif
Packit Service 407539
#endif
Packit Service 407539
		}
Packit Service 407539
#endif
Packit Service 407539
Packit Service 407539
	/* Taken from `wchan ()' in `/usr/src/bin/ps/print.c'. */
Packit Service 407539
Packit Service 407539
	glibtop_suid_leave (server);
Packit Service 407539
Packit Service 407539
#else
Packit Service 407539
	/* XXX: the code here was, quite frankly, junk, and almost
Packit Service 407539
	 * certainly wrong - remove it all, leave these fields
Packit Service 407539
	 * unpopulated, and give up until such time as the right
Packit Service 407539
	 * code is produced for both FreeBSD 4.x and 5.x
Packit Service 407539
	 */
Packit Service 407539
	return;
Packit Service 407539
#endif /* __FreeBSD__ */
Packit Service 407539
}