Make libprocstat(3) extract procstat notes from a process core file.
PR: kern/173723 Suggested by: jhb Glanced by: kib MFC after: 1 month
This commit is contained in:
parent
84eea68afc
commit
16ea6280bf
@ -6,6 +6,7 @@ LIB= procstat
|
||||
|
||||
SRCS= cd9660.c \
|
||||
common_kvm.c \
|
||||
core.c \
|
||||
libprocstat.c \
|
||||
msdosfs.c \
|
||||
udf.c
|
||||
@ -17,8 +18,8 @@ INCS= libprocstat.h
|
||||
CFLAGS+= -I. -I${.CURDIR} -D_KVM_VNODE
|
||||
SHLIB_MAJOR= 1
|
||||
|
||||
DPADD= ${LIBKVM} ${LIBUTIL}
|
||||
LDADD= -lkvm -lutil
|
||||
DPADD= ${LIBELF} ${LIBKVM} ${LIBUTIL}
|
||||
LDADD= -lelf -lkvm -lutil
|
||||
|
||||
MAN= libprocstat.3
|
||||
|
||||
|
@ -17,4 +17,5 @@ FBSD_1.2 {
|
||||
|
||||
FBSD_1.3 {
|
||||
procstat_get_shm_info;
|
||||
procstat_open_core;
|
||||
};
|
||||
|
262
lib/libprocstat/core.c
Normal file
262
lib/libprocstat/core.c
Normal file
@ -0,0 +1,262 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 Mikolaj Golub <trociny@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/elf.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <gelf.h>
|
||||
#include <libelf.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#define PROCSTAT_CORE_MAGIC 0x012DADB8
|
||||
struct procstat_core
|
||||
{
|
||||
int pc_magic;
|
||||
int pc_fd;
|
||||
Elf *pc_elf;
|
||||
GElf_Ehdr pc_ehdr;
|
||||
GElf_Phdr pc_phdr;
|
||||
};
|
||||
|
||||
static bool core_offset(struct procstat_core *core, off_t offset);
|
||||
static bool core_read(struct procstat_core *core, void *buf, size_t len);
|
||||
|
||||
struct procstat_core *
|
||||
procstat_core_open(const char *filename)
|
||||
{
|
||||
struct procstat_core *core;
|
||||
Elf *e;
|
||||
GElf_Ehdr ehdr;
|
||||
GElf_Phdr phdr;
|
||||
size_t nph;
|
||||
int fd, i;
|
||||
|
||||
if (elf_version(EV_CURRENT) == EV_NONE) {
|
||||
warnx("ELF library too old");
|
||||
return (NULL);
|
||||
}
|
||||
fd = open(filename, O_RDONLY, 0);
|
||||
if (fd == -1) {
|
||||
warn("open(%s)", filename);
|
||||
return (NULL);
|
||||
}
|
||||
e = elf_begin(fd, ELF_C_READ, NULL);
|
||||
if (e == NULL) {
|
||||
warnx("elf_begin: %s", elf_errmsg(-1));
|
||||
goto fail;
|
||||
}
|
||||
if (elf_kind(e) != ELF_K_ELF) {
|
||||
warnx("%s is not an ELF object", filename);
|
||||
goto fail;
|
||||
}
|
||||
if (gelf_getehdr(e, &ehdr) == NULL) {
|
||||
warnx("gelf_getehdr: %s", elf_errmsg(-1));
|
||||
goto fail;
|
||||
}
|
||||
if (ehdr.e_type != ET_CORE) {
|
||||
warnx("%s is not a CORE file", filename);
|
||||
goto fail;
|
||||
}
|
||||
if (elf_getphnum(e, &nph) == 0) {
|
||||
warnx("program headers not found");
|
||||
goto fail;
|
||||
}
|
||||
for (i = 0; i < ehdr.e_phnum; i++) {
|
||||
if (gelf_getphdr(e, i, &phdr) != &phdr) {
|
||||
warnx("gelf_getphdr: %s", elf_errmsg(-1));
|
||||
goto fail;
|
||||
}
|
||||
if (phdr.p_type == PT_NOTE)
|
||||
break;
|
||||
}
|
||||
if (i == ehdr.e_phnum) {
|
||||
warnx("NOTE program header not found");
|
||||
goto fail;
|
||||
}
|
||||
core = malloc(sizeof(struct procstat_core));
|
||||
if (core == NULL) {
|
||||
warn("malloc(%zu)", sizeof(struct procstat_core));
|
||||
goto fail;
|
||||
}
|
||||
core->pc_magic = PROCSTAT_CORE_MAGIC;
|
||||
core->pc_fd = fd;
|
||||
core->pc_elf = e;
|
||||
core->pc_ehdr = ehdr;
|
||||
core->pc_phdr = phdr;
|
||||
|
||||
return (core);
|
||||
fail:
|
||||
if (e != NULL)
|
||||
elf_end(e);
|
||||
close(fd);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void
|
||||
procstat_core_close(struct procstat_core *core)
|
||||
{
|
||||
|
||||
assert(core->pc_magic == PROCSTAT_CORE_MAGIC);
|
||||
|
||||
elf_end(core->pc_elf);
|
||||
close(core->pc_fd);
|
||||
free(core);
|
||||
}
|
||||
|
||||
void *
|
||||
procstat_core_get(struct procstat_core *core, enum psc_type type, void *buf,
|
||||
size_t *lenp)
|
||||
{
|
||||
Elf_Note nhdr;
|
||||
off_t offset, eoffset;
|
||||
void *freebuf;
|
||||
size_t len;
|
||||
u_int32_t n_type;
|
||||
int cstructsize, structsize;
|
||||
char nbuf[8];
|
||||
|
||||
assert(core->pc_magic == PROCSTAT_CORE_MAGIC);
|
||||
|
||||
switch(type) {
|
||||
case PSC_TYPE_PROC:
|
||||
n_type = NT_PROCSTAT_PROC;
|
||||
structsize = sizeof(struct kinfo_proc);
|
||||
break;
|
||||
case PSC_TYPE_FILES:
|
||||
n_type = NT_PROCSTAT_FILES;
|
||||
structsize = sizeof(struct kinfo_file);
|
||||
break;
|
||||
case PSC_TYPE_VMMAP:
|
||||
n_type = NT_PROCSTAT_VMMAP;
|
||||
structsize = sizeof(struct kinfo_vmentry);
|
||||
break;
|
||||
default:
|
||||
warnx("unknown core stat type: %d", type);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
offset = core->pc_phdr.p_offset;
|
||||
eoffset = offset + core->pc_phdr.p_filesz;
|
||||
|
||||
while (offset < eoffset) {
|
||||
if (!core_offset(core, offset))
|
||||
return (NULL);
|
||||
if (!core_read(core, &nhdr, sizeof(nhdr)))
|
||||
return (NULL);
|
||||
|
||||
offset += sizeof(nhdr) +
|
||||
roundup2(nhdr.n_namesz, sizeof(Elf32_Size)) +
|
||||
roundup2(nhdr.n_descsz, sizeof(Elf32_Size));
|
||||
|
||||
if (nhdr.n_namesz == 0 && nhdr.n_descsz == 0)
|
||||
break;
|
||||
if (nhdr.n_type != n_type)
|
||||
continue;
|
||||
if (nhdr.n_namesz != 8)
|
||||
continue;
|
||||
if (!core_read(core, nbuf, sizeof(nbuf)))
|
||||
return (NULL);
|
||||
if (strcmp(nbuf, "FreeBSD") != 0)
|
||||
continue;
|
||||
if (nhdr.n_descsz < sizeof(cstructsize)) {
|
||||
warnx("corrupted core file");
|
||||
return (NULL);
|
||||
}
|
||||
if (!core_read(core, &cstructsize, sizeof(cstructsize)))
|
||||
return (NULL);
|
||||
if (cstructsize != structsize) {
|
||||
warnx("version mismatch");
|
||||
return (NULL);
|
||||
}
|
||||
len = nhdr.n_descsz - sizeof(cstructsize);
|
||||
if (len == 0)
|
||||
return (NULL);
|
||||
if (buf != NULL) {
|
||||
len = MIN(len, *lenp);
|
||||
freebuf = NULL;
|
||||
} else {
|
||||
freebuf = buf = malloc(len);
|
||||
if (buf == NULL) {
|
||||
warn("malloc(%zu)", len);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
if (!core_read(core, buf, len)) {
|
||||
free(freebuf);
|
||||
return (NULL);
|
||||
}
|
||||
*lenp = len;
|
||||
return (buf);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static bool
|
||||
core_offset(struct procstat_core *core, off_t offset)
|
||||
{
|
||||
|
||||
assert(core->pc_magic == PROCSTAT_CORE_MAGIC);
|
||||
|
||||
if (lseek(core->pc_fd, offset, SEEK_SET) == -1) {
|
||||
warn("core: lseek(%jd)", (intmax_t)offset);
|
||||
return (false);
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
||||
static bool
|
||||
core_read(struct procstat_core *core, void *buf, size_t len)
|
||||
{
|
||||
ssize_t n;
|
||||
|
||||
assert(core->pc_magic == PROCSTAT_CORE_MAGIC);
|
||||
|
||||
n = read(core->pc_fd, buf, len);
|
||||
if (n == -1) {
|
||||
warn("core: read");
|
||||
return (false);
|
||||
}
|
||||
if (n < (ssize_t)len) {
|
||||
warnx("core: short read");
|
||||
return (false);
|
||||
}
|
||||
return (true);
|
||||
}
|
45
lib/libprocstat/core.h
Normal file
45
lib/libprocstat/core.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 Mikolaj Golub <trociny@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _CORE_H
|
||||
#define _CORE_H
|
||||
|
||||
enum psc_type {
|
||||
PSC_TYPE_PROC,
|
||||
PSC_TYPE_FILES,
|
||||
PSC_TYPE_VMMAP,
|
||||
};
|
||||
|
||||
struct procstat_core;
|
||||
|
||||
void procstat_core_close(struct procstat_core *core);
|
||||
void *procstat_core_get(struct procstat_core *core, enum psc_type type,
|
||||
void * buf, size_t *lenp);
|
||||
struct procstat_core *procstat_core_open(const char *filename);
|
||||
|
||||
#endif /* !_CORE_H_ */
|
@ -28,6 +28,7 @@
|
||||
.Dt LIBPROCSTAT 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm procstat_open_core ,
|
||||
.Nm procstat_open_kvm ,
|
||||
.Nm procstat_open_sysctl ,
|
||||
.Nm procstat_close ,
|
||||
@ -105,6 +106,8 @@
|
||||
.Fa "unsigned int *count"
|
||||
.Fc
|
||||
.Ft "struct procstat *"
|
||||
.Fn procstat_open_core "const char *filename"
|
||||
.Ft "struct procstat *"
|
||||
.Fn procstat_open_kvm "const char *nlistf" "const char *memf"
|
||||
.Ft "struct procstat *"
|
||||
.Fn procstat_open_sysctl void
|
||||
@ -116,7 +119,11 @@ retrieval from the running kernel via the
|
||||
.Xr sysctl 3
|
||||
library backend, and for post-mortem analysis via the
|
||||
.Xr kvm 3
|
||||
library backend.
|
||||
library backend, or from the process
|
||||
.Xr core 5
|
||||
file, searching for statistics in special
|
||||
.Xr elf 3
|
||||
note sections.
|
||||
.Pp
|
||||
The
|
||||
.Fn procstat_open_kvm
|
||||
@ -129,6 +136,16 @@ or
|
||||
library routines, respectively, to access kernel state information
|
||||
used to retrieve processes and files states.
|
||||
The
|
||||
.Fn procstat_open_core
|
||||
uses
|
||||
.Xr elf 3
|
||||
routines to access statistics stored as a set of notes in a process
|
||||
.Xr core 5
|
||||
file, written by the kernel at the moment of the process abnormal termination.
|
||||
The
|
||||
.Fa filename
|
||||
argument is the process core file name.
|
||||
The
|
||||
.Fa nlistf
|
||||
argument is the executable image of the kernel being examined.
|
||||
If this argument is
|
||||
@ -145,7 +162,7 @@ is assumed.
|
||||
See
|
||||
.Xr kvm_open 3
|
||||
for more details.
|
||||
Both functions dynamically allocate and return a
|
||||
The functions dynamically allocate and return a
|
||||
.Vt procstat
|
||||
structure pointer used in the rest of the
|
||||
.Nm libprocstat
|
||||
@ -250,10 +267,12 @@ argument indicates an actual error message in case of failure.
|
||||
.Xr pipe 2 ,
|
||||
.Xr shm_open 2 ,
|
||||
.Xr socket 2 ,
|
||||
.Xr elf 3 ,
|
||||
.Xr kvm 3 ,
|
||||
.Xr queue 3 ,
|
||||
.Xr sysctl 3 ,
|
||||
.Xr pts 4 ,
|
||||
.Xr core 5 ,
|
||||
.Xr vnode 9
|
||||
.Sh HISTORY
|
||||
The
|
||||
|
@ -96,11 +96,13 @@ __FBSDID("$FreeBSD$");
|
||||
#include <libprocstat.h>
|
||||
#include "libprocstat_internal.h"
|
||||
#include "common_kvm.h"
|
||||
#include "core.h"
|
||||
|
||||
int statfs(const char *, struct statfs *); /* XXX */
|
||||
|
||||
#define PROCSTAT_KVM 1
|
||||
#define PROCSTAT_SYSCTL 2
|
||||
#define PROCSTAT_CORE 3
|
||||
|
||||
static char *getmnton(kvm_t *kd, struct mount *m);
|
||||
static struct filestat_list *procstat_getfiles_kvm(
|
||||
@ -137,6 +139,8 @@ procstat_close(struct procstat *procstat)
|
||||
assert(procstat);
|
||||
if (procstat->type == PROCSTAT_KVM)
|
||||
kvm_close(procstat->kd);
|
||||
else if (procstat->type == PROCSTAT_CORE)
|
||||
procstat_core_close(procstat->core);
|
||||
free(procstat);
|
||||
}
|
||||
|
||||
@ -177,6 +181,27 @@ procstat_open_kvm(const char *nlistf, const char *memf)
|
||||
return (procstat);
|
||||
}
|
||||
|
||||
struct procstat *
|
||||
procstat_open_core(const char *filename)
|
||||
{
|
||||
struct procstat *procstat;
|
||||
struct procstat_core *core;
|
||||
|
||||
procstat = calloc(1, sizeof(*procstat));
|
||||
if (procstat == NULL) {
|
||||
warn("malloc()");
|
||||
return (NULL);
|
||||
}
|
||||
core = procstat_core_open(filename);
|
||||
if (core == NULL) {
|
||||
free(procstat);
|
||||
return (NULL);
|
||||
}
|
||||
procstat->type = PROCSTAT_CORE;
|
||||
procstat->core = core;
|
||||
return (procstat);
|
||||
}
|
||||
|
||||
struct kinfo_proc *
|
||||
procstat_getprocs(struct procstat *procstat, int what, int arg,
|
||||
unsigned int *count)
|
||||
@ -230,6 +255,15 @@ procstat_getprocs(struct procstat *procstat, int what, int arg,
|
||||
goto fail;
|
||||
}
|
||||
/* Perform simple consistency checks. */
|
||||
if ((len % sizeof(*p)) != 0 || p->ki_structsize != sizeof(*p)) {
|
||||
warnx("kinfo_proc structure size mismatch (len = %zu)", len);
|
||||
goto fail;
|
||||
}
|
||||
*count = len / sizeof(*p);
|
||||
return (p);
|
||||
} else if (procstat->type == PROCSTAT_CORE) {
|
||||
p = procstat_core_get(procstat->core, PSC_TYPE_PROC, NULL,
|
||||
&len);
|
||||
if ((len % sizeof(*p)) != 0 || p->ki_structsize != sizeof(*p)) {
|
||||
warnx("kinfo_proc structure size mismatch");
|
||||
goto fail;
|
||||
@ -258,13 +292,17 @@ procstat_freeprocs(struct procstat *procstat __unused, struct kinfo_proc *p)
|
||||
struct filestat_list *
|
||||
procstat_getfiles(struct procstat *procstat, struct kinfo_proc *kp, int mmapped)
|
||||
{
|
||||
|
||||
if (procstat->type == PROCSTAT_SYSCTL)
|
||||
return (procstat_getfiles_sysctl(procstat, kp, mmapped));
|
||||
else if (procstat->type == PROCSTAT_KVM)
|
||||
|
||||
switch(procstat->type) {
|
||||
case PROCSTAT_KVM:
|
||||
return (procstat_getfiles_kvm(procstat, kp, mmapped));
|
||||
else
|
||||
case PROCSTAT_SYSCTL:
|
||||
case PROCSTAT_CORE:
|
||||
return (procstat_getfiles_sysctl(procstat, kp, mmapped));
|
||||
default:
|
||||
warnx("unknown access method: %d", procstat->type);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -646,8 +684,62 @@ kinfo_uflags2fst(int fd)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct kinfo_file *
|
||||
kinfo_getfile_core(struct procstat_core *core, int *cntp)
|
||||
{
|
||||
int cnt;
|
||||
size_t len;
|
||||
char *buf, *bp, *eb;
|
||||
struct kinfo_file *kif, *kp, *kf;
|
||||
|
||||
buf = procstat_core_get(core, PSC_TYPE_FILES, NULL, &len);
|
||||
if (buf == NULL)
|
||||
return (NULL);
|
||||
/*
|
||||
* XXXMG: The code below is just copy&past from libutil.
|
||||
* The code duplication can be avoided if libutil
|
||||
* is extended to provide something like:
|
||||
* struct kinfo_file *kinfo_getfile_from_buf(const char *buf,
|
||||
* size_t len, int *cntp);
|
||||
*/
|
||||
|
||||
/* Pass 1: count items */
|
||||
cnt = 0;
|
||||
bp = buf;
|
||||
eb = buf + len;
|
||||
while (bp < eb) {
|
||||
kf = (struct kinfo_file *)(uintptr_t)bp;
|
||||
bp += kf->kf_structsize;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
kif = calloc(cnt, sizeof(*kif));
|
||||
if (kif == NULL) {
|
||||
free(buf);
|
||||
return (NULL);
|
||||
}
|
||||
bp = buf;
|
||||
eb = buf + len;
|
||||
kp = kif;
|
||||
/* Pass 2: unpack */
|
||||
while (bp < eb) {
|
||||
kf = (struct kinfo_file *)(uintptr_t)bp;
|
||||
/* Copy/expand into pre-zeroed buffer */
|
||||
memcpy(kp, kf, kf->kf_structsize);
|
||||
/* Advance to next packed record */
|
||||
bp += kf->kf_structsize;
|
||||
/* Set field size to fixed length, advance */
|
||||
kp->kf_structsize = sizeof(*kp);
|
||||
kp++;
|
||||
}
|
||||
free(buf);
|
||||
*cntp = cnt;
|
||||
return (kif); /* Caller must free() return value */
|
||||
}
|
||||
|
||||
static struct filestat_list *
|
||||
procstat_getfiles_sysctl(struct procstat *procstat, struct kinfo_proc *kp, int mmapped)
|
||||
procstat_getfiles_sysctl(struct procstat *procstat, struct kinfo_proc *kp,
|
||||
int mmapped)
|
||||
{
|
||||
struct kinfo_file *kif, *files;
|
||||
struct kinfo_vmentry *kve, *vmentries;
|
||||
@ -663,8 +755,16 @@ procstat_getfiles_sysctl(struct procstat *procstat, struct kinfo_proc *kp, int m
|
||||
assert(kp);
|
||||
if (kp->ki_fd == NULL)
|
||||
return (NULL);
|
||||
|
||||
files = kinfo_getfile(kp->ki_pid, &cnt);
|
||||
switch(procstat->type) {
|
||||
case PROCSTAT_SYSCTL:
|
||||
files = kinfo_getfile(kp->ki_pid, &cnt);
|
||||
break;
|
||||
case PROCSTAT_CORE:
|
||||
files = kinfo_getfile_core(procstat->core, &cnt);
|
||||
break;
|
||||
default:
|
||||
assert(!"invalid type");
|
||||
}
|
||||
if (files == NULL && errno != EPERM) {
|
||||
warn("kinfo_getfile()");
|
||||
return (NULL);
|
||||
@ -742,7 +842,8 @@ procstat_get_pipe_info(struct procstat *procstat, struct filestat *fst,
|
||||
if (procstat->type == PROCSTAT_KVM) {
|
||||
return (procstat_get_pipe_info_kvm(procstat->kd, fst, ps,
|
||||
errbuf));
|
||||
} else if (procstat->type == PROCSTAT_SYSCTL) {
|
||||
} else if (procstat->type == PROCSTAT_SYSCTL ||
|
||||
procstat->type == PROCSTAT_CORE) {
|
||||
return (procstat_get_pipe_info_sysctl(fst, ps, errbuf));
|
||||
} else {
|
||||
warnx("unknown access method: %d", procstat->type);
|
||||
@ -806,7 +907,8 @@ procstat_get_pts_info(struct procstat *procstat, struct filestat *fst,
|
||||
if (procstat->type == PROCSTAT_KVM) {
|
||||
return (procstat_get_pts_info_kvm(procstat->kd, fst, pts,
|
||||
errbuf));
|
||||
} else if (procstat->type == PROCSTAT_SYSCTL) {
|
||||
} else if (procstat->type == PROCSTAT_SYSCTL ||
|
||||
procstat->type == PROCSTAT_CORE) {
|
||||
return (procstat_get_pts_info_sysctl(fst, pts, errbuf));
|
||||
} else {
|
||||
warnx("unknown access method: %d", procstat->type);
|
||||
@ -868,7 +970,8 @@ procstat_get_shm_info(struct procstat *procstat, struct filestat *fst,
|
||||
if (procstat->type == PROCSTAT_KVM) {
|
||||
return (procstat_get_shm_info_kvm(procstat->kd, fst, shm,
|
||||
errbuf));
|
||||
} else if (procstat->type == PROCSTAT_SYSCTL) {
|
||||
} else if (procstat->type == PROCSTAT_SYSCTL ||
|
||||
procstat->type == PROCSTAT_CORE) {
|
||||
return (procstat_get_shm_info_sysctl(fst, shm, errbuf));
|
||||
} else {
|
||||
warnx("unknown access method: %d", procstat->type);
|
||||
@ -948,7 +1051,8 @@ procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst,
|
||||
if (procstat->type == PROCSTAT_KVM) {
|
||||
return (procstat_get_vnode_info_kvm(procstat->kd, fst, vn,
|
||||
errbuf));
|
||||
} else if (procstat->type == PROCSTAT_SYSCTL) {
|
||||
} else if (procstat->type == PROCSTAT_SYSCTL ||
|
||||
procstat->type == PROCSTAT_CORE) {
|
||||
return (procstat_get_vnode_info_sysctl(fst, vn, errbuf));
|
||||
} else {
|
||||
warnx("unknown access method: %d", procstat->type);
|
||||
@ -1150,7 +1254,8 @@ procstat_get_socket_info(struct procstat *procstat, struct filestat *fst,
|
||||
if (procstat->type == PROCSTAT_KVM) {
|
||||
return (procstat_get_socket_info_kvm(procstat->kd, fst, sock,
|
||||
errbuf));
|
||||
} else if (procstat->type == PROCSTAT_SYSCTL) {
|
||||
} else if (procstat->type == PROCSTAT_SYSCTL ||
|
||||
procstat->type == PROCSTAT_CORE) {
|
||||
return (procstat_get_socket_info_sysctl(fst, sock, errbuf));
|
||||
} else {
|
||||
warnx("unknown access method: %d", procstat->type);
|
||||
@ -1401,3 +1506,4 @@ getmnton(kvm_t *kd, struct mount *m)
|
||||
mhead = mt;
|
||||
return (mt->mntonname);
|
||||
}
|
||||
|
||||
|
@ -162,6 +162,7 @@ int procstat_get_socket_info(struct procstat *procstat, struct filestat *fst,
|
||||
struct sockstat *sock, char *errbuf);
|
||||
int procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst,
|
||||
struct vnstat *vn, char *errbuf);
|
||||
struct procstat *procstat_open_core(const char *filename);
|
||||
struct procstat *procstat_open_sysctl(void);
|
||||
struct procstat *procstat_open_kvm(const char *nlistf, const char *memf);
|
||||
__END_DECLS
|
||||
|
@ -34,6 +34,7 @@ struct procstat {
|
||||
kvm_t *kd;
|
||||
void *vmentries;
|
||||
void *files;
|
||||
struct procstat_core *core;
|
||||
};
|
||||
|
||||
#endif /* !_LIBPROCSTAT_INTERNAL_H_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user