mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-14 12:23:58 +00:00
Add procstat_getauxv function to retrieve a process auxiliary vector.
MFC after: 1 month
This commit is contained in:
parent
729e63c34b
commit
2ff020d3c3
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=249681
|
@ -17,11 +17,13 @@ FBSD_1.2 {
|
||||||
|
|
||||||
FBSD_1.3 {
|
FBSD_1.3 {
|
||||||
procstat_freeargv;
|
procstat_freeargv;
|
||||||
|
procstat_freeauxv;
|
||||||
procstat_freeenvv;
|
procstat_freeenvv;
|
||||||
procstat_freegroups;
|
procstat_freegroups;
|
||||||
procstat_freevmmap;
|
procstat_freevmmap;
|
||||||
procstat_get_shm_info;
|
procstat_get_shm_info;
|
||||||
procstat_getargv;
|
procstat_getargv;
|
||||||
|
procstat_getauxv;
|
||||||
procstat_getenvv;
|
procstat_getenvv;
|
||||||
procstat_getgroups;
|
procstat_getgroups;
|
||||||
procstat_getosrel;
|
procstat_getosrel;
|
||||||
|
|
|
@ -195,6 +195,10 @@ procstat_core_get(struct procstat_core *core, enum psc_type type, void *buf,
|
||||||
n_type = NT_PROCSTAT_PSSTRINGS;
|
n_type = NT_PROCSTAT_PSSTRINGS;
|
||||||
structsize = sizeof(vm_offset_t);
|
structsize = sizeof(vm_offset_t);
|
||||||
break;
|
break;
|
||||||
|
case PSC_TYPE_AUXV:
|
||||||
|
n_type = NT_PROCSTAT_AUXV;
|
||||||
|
structsize = sizeof(Elf_Auxinfo);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
warnx("unknown core stat type: %d", type);
|
warnx("unknown core stat type: %d", type);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
|
@ -40,6 +40,7 @@ enum psc_type {
|
||||||
PSC_TYPE_PSSTRINGS,
|
PSC_TYPE_PSSTRINGS,
|
||||||
PSC_TYPE_ARGV,
|
PSC_TYPE_ARGV,
|
||||||
PSC_TYPE_ENVV,
|
PSC_TYPE_ENVV,
|
||||||
|
PSC_TYPE_AUXV,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct procstat_core;
|
struct procstat_core;
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
.Nm procstat_open_sysctl ,
|
.Nm procstat_open_sysctl ,
|
||||||
.Nm procstat_close ,
|
.Nm procstat_close ,
|
||||||
.Nm procstat_getargv ,
|
.Nm procstat_getargv ,
|
||||||
|
.Nm procstat_getauxv ,
|
||||||
.Nm procstat_getenvv ,
|
.Nm procstat_getenvv ,
|
||||||
.Nm procstat_getfiles ,
|
.Nm procstat_getfiles ,
|
||||||
.Nm procstat_getgroups ,
|
.Nm procstat_getgroups ,
|
||||||
|
@ -42,6 +43,7 @@
|
||||||
.Nm procstat_getumask ,
|
.Nm procstat_getumask ,
|
||||||
.Nm procstat_getvmmap ,
|
.Nm procstat_getvmmap ,
|
||||||
.Nm procstat_freeargv ,
|
.Nm procstat_freeargv ,
|
||||||
|
.Nm procstat_freeauxv ,
|
||||||
.Nm procstat_freeenvv ,
|
.Nm procstat_freeenvv ,
|
||||||
.Nm procstat_freefiles ,
|
.Nm procstat_freefiles ,
|
||||||
.Nm procstat_freegroups ,
|
.Nm procstat_freegroups ,
|
||||||
|
@ -67,6 +69,11 @@
|
||||||
.Fa "struct procstat *procstat"
|
.Fa "struct procstat *procstat"
|
||||||
.Fc
|
.Fc
|
||||||
.Ft void
|
.Ft void
|
||||||
|
.Fo procstat_freeauxv
|
||||||
|
.Fa "struct procstat *procstat"
|
||||||
|
.Fa "Elf_Auxinfo *auxv"
|
||||||
|
.Fc
|
||||||
|
.Ft void
|
||||||
.Fo procstat_freeenvv
|
.Fo procstat_freeenvv
|
||||||
.Fa "struct procstat *procstat"
|
.Fa "struct procstat *procstat"
|
||||||
.Fc
|
.Fc
|
||||||
|
@ -129,6 +136,12 @@
|
||||||
.Fa "size_t nchr"
|
.Fa "size_t nchr"
|
||||||
.Fa "char *errbuf"
|
.Fa "char *errbuf"
|
||||||
.Fc
|
.Fc
|
||||||
|
.Ft "Elf_Auxinfo *"
|
||||||
|
.Fo procstat_getauxv
|
||||||
|
.Fa "struct procstat *procstat"
|
||||||
|
.Fa "struct kinfo_proc *kp"
|
||||||
|
.Fa "unsigned int *count"
|
||||||
|
.Fc
|
||||||
.Ft "char **"
|
.Ft "char **"
|
||||||
.Fo procstat_getenvv
|
.Fo procstat_getenvv
|
||||||
.Fa "struct procstat *procstat"
|
.Fa "struct procstat *procstat"
|
||||||
|
@ -321,6 +334,19 @@ The caller may free the allocated memory with a subsequent
|
||||||
function call.
|
function call.
|
||||||
.Pp
|
.Pp
|
||||||
The
|
The
|
||||||
|
.Fn procstat_getauxv
|
||||||
|
function gets a pointer to the
|
||||||
|
.Vt procstat
|
||||||
|
structure, a pointer to
|
||||||
|
.Vt kinfo_proc
|
||||||
|
structure, and returns the auxiliary vector as a dynamically allocated array of
|
||||||
|
.Vt Elf_Auxinfo
|
||||||
|
elements.
|
||||||
|
The caller is responsible to free the allocated memory with a subsequent
|
||||||
|
.Fn procstat_freeauxv
|
||||||
|
function call.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
.Fn procstat_getfiles
|
.Fn procstat_getfiles
|
||||||
function gets a pointer to the
|
function gets a pointer to the
|
||||||
.Vt procstat
|
.Vt procstat
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
#include <sys/elf.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/resourcevar.h>
|
#include <sys/resourcevar.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
|
@ -110,6 +111,9 @@ static char **getargv(struct procstat *procstat, struct kinfo_proc *kp,
|
||||||
static char *getmnton(kvm_t *kd, struct mount *m);
|
static char *getmnton(kvm_t *kd, struct mount *m);
|
||||||
static struct kinfo_vmentry * kinfo_getvmmap_core(struct procstat_core *core,
|
static struct kinfo_vmentry * kinfo_getvmmap_core(struct procstat_core *core,
|
||||||
int *cntp);
|
int *cntp);
|
||||||
|
static Elf_Auxinfo *procstat_getauxv_core(struct procstat_core *core,
|
||||||
|
unsigned int *cntp);
|
||||||
|
static Elf_Auxinfo *procstat_getauxv_sysctl(pid_t pid, unsigned int *cntp);
|
||||||
static struct filestat_list *procstat_getfiles_kvm(
|
static struct filestat_list *procstat_getfiles_kvm(
|
||||||
struct procstat *procstat, struct kinfo_proc *kp, int mmapped);
|
struct procstat *procstat, struct kinfo_proc *kp, int mmapped);
|
||||||
static struct filestat_list *procstat_getfiles_sysctl(
|
static struct filestat_list *procstat_getfiles_sysctl(
|
||||||
|
@ -2075,3 +2079,151 @@ procstat_getosrel(struct procstat *procstat, struct kinfo_proc *kp, int *osrelp)
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define PROC_AUXV_MAX 256
|
||||||
|
|
||||||
|
#if __ELF_WORD_SIZE == 64
|
||||||
|
static const char *elf32_sv_names[] = {
|
||||||
|
"Linux ELF32",
|
||||||
|
"FreeBSD ELF32",
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
is_elf32_sysctl(pid_t pid)
|
||||||
|
{
|
||||||
|
int error, name[4];
|
||||||
|
size_t len, i;
|
||||||
|
static char sv_name[256];
|
||||||
|
|
||||||
|
name[0] = CTL_KERN;
|
||||||
|
name[1] = KERN_PROC;
|
||||||
|
name[2] = KERN_PROC_SV_NAME;
|
||||||
|
name[3] = pid;
|
||||||
|
len = sizeof(sv_name);
|
||||||
|
error = sysctl(name, 4, sv_name, &len, NULL, 0);
|
||||||
|
if (error != 0 || len == 0)
|
||||||
|
return (0);
|
||||||
|
for (i = 0; i < sizeof(elf32_sv_names) / sizeof(*elf32_sv_names); i++) {
|
||||||
|
if (strncmp(sv_name, elf32_sv_names[i], sizeof(sv_name)) == 0)
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Elf_Auxinfo *
|
||||||
|
procstat_getauxv32_sysctl(pid_t pid, unsigned int *cntp)
|
||||||
|
{
|
||||||
|
Elf_Auxinfo *auxv;
|
||||||
|
Elf32_Auxinfo *auxv32;
|
||||||
|
void *ptr;
|
||||||
|
size_t len;
|
||||||
|
unsigned int i, count;
|
||||||
|
int name[4];
|
||||||
|
|
||||||
|
name[0] = CTL_KERN;
|
||||||
|
name[1] = KERN_PROC;
|
||||||
|
name[2] = KERN_PROC_AUXV;
|
||||||
|
name[3] = pid;
|
||||||
|
len = PROC_AUXV_MAX * sizeof(Elf32_Auxinfo);
|
||||||
|
auxv = NULL;
|
||||||
|
auxv32 = malloc(len);
|
||||||
|
if (auxv32 == NULL) {
|
||||||
|
warn("malloc(%zu)", len);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (sysctl(name, 4, auxv32, &len, NULL, 0) == -1) {
|
||||||
|
if (errno != ESRCH && errno != EPERM)
|
||||||
|
warn("sysctl: kern.proc.auxv: %d: %d", pid, errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
count = len / sizeof(Elf_Auxinfo);
|
||||||
|
auxv = malloc(count * sizeof(Elf_Auxinfo));
|
||||||
|
if (auxv == NULL) {
|
||||||
|
warn("malloc(%zu)", count * sizeof(Elf_Auxinfo));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
/*
|
||||||
|
* XXX: We expect that values for a_type on a 32-bit platform
|
||||||
|
* are directly mapped to values on 64-bit one, which is not
|
||||||
|
* necessarily true.
|
||||||
|
*/
|
||||||
|
auxv[i].a_type = auxv32[i].a_type;
|
||||||
|
ptr = &auxv32[i].a_un;
|
||||||
|
auxv[i].a_un.a_val = *((uint32_t *)ptr);
|
||||||
|
}
|
||||||
|
*cntp = count;
|
||||||
|
out:
|
||||||
|
free(auxv32);
|
||||||
|
return (auxv);
|
||||||
|
}
|
||||||
|
#endif /* __ELF_WORD_SIZE == 64 */
|
||||||
|
|
||||||
|
static Elf_Auxinfo *
|
||||||
|
procstat_getauxv_sysctl(pid_t pid, unsigned int *cntp)
|
||||||
|
{
|
||||||
|
Elf_Auxinfo *auxv;
|
||||||
|
int name[4];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
#if __ELF_WORD_SIZE == 64
|
||||||
|
if (is_elf32_sysctl(pid))
|
||||||
|
return (procstat_getauxv32_sysctl(pid, cntp));
|
||||||
|
#endif
|
||||||
|
name[0] = CTL_KERN;
|
||||||
|
name[1] = KERN_PROC;
|
||||||
|
name[2] = KERN_PROC_AUXV;
|
||||||
|
name[3] = pid;
|
||||||
|
len = PROC_AUXV_MAX * sizeof(Elf_Auxinfo);
|
||||||
|
auxv = malloc(len);
|
||||||
|
if (auxv == NULL) {
|
||||||
|
warn("malloc(%zu)", len);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
if (sysctl(name, 4, auxv, &len, NULL, 0) == -1) {
|
||||||
|
if (errno != ESRCH && errno != EPERM)
|
||||||
|
warn("sysctl: kern.proc.auxv: %d: %d", pid, errno);
|
||||||
|
free(auxv);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
*cntp = len / sizeof(Elf_Auxinfo);
|
||||||
|
return (auxv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Elf_Auxinfo *
|
||||||
|
procstat_getauxv_core(struct procstat_core *core, unsigned int *cntp)
|
||||||
|
{
|
||||||
|
Elf_Auxinfo *auxv;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
auxv = procstat_core_get(core, PSC_TYPE_AUXV, NULL, &len);
|
||||||
|
if (auxv == NULL)
|
||||||
|
return (NULL);
|
||||||
|
*cntp = len / sizeof(Elf_Auxinfo);
|
||||||
|
return (auxv);
|
||||||
|
}
|
||||||
|
|
||||||
|
Elf_Auxinfo *
|
||||||
|
procstat_getauxv(struct procstat *procstat, struct kinfo_proc *kp,
|
||||||
|
unsigned int *cntp)
|
||||||
|
{
|
||||||
|
switch(procstat->type) {
|
||||||
|
case PROCSTAT_KVM:
|
||||||
|
warnx("kvm method is not supported");
|
||||||
|
return (NULL);
|
||||||
|
case PROCSTAT_SYSCTL:
|
||||||
|
return (procstat_getauxv_sysctl(kp->ki_pid, cntp));
|
||||||
|
case PROCSTAT_CORE:
|
||||||
|
return (procstat_getauxv_core(procstat->core, cntp));
|
||||||
|
default:
|
||||||
|
warnx("unknown access method: %d", procstat->type);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
procstat_freeauxv(struct procstat *procstat __unused, Elf_Auxinfo *auxv)
|
||||||
|
{
|
||||||
|
|
||||||
|
free(auxv);
|
||||||
|
}
|
||||||
|
|
|
@ -29,6 +29,14 @@
|
||||||
#ifndef _LIBPROCSTAT_H_
|
#ifndef _LIBPROCSTAT_H_
|
||||||
#define _LIBPROCSTAT_H_
|
#define _LIBPROCSTAT_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: sys/elf.h conflicts with zfs_context.h. Workaround this by not
|
||||||
|
* including conflicting parts when building zfs code.
|
||||||
|
*/
|
||||||
|
#ifndef ZFS
|
||||||
|
#include <sys/elf.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Vnode types.
|
* Vnode types.
|
||||||
*/
|
*/
|
||||||
|
@ -148,6 +156,9 @@ STAILQ_HEAD(filestat_list, filestat);
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
void procstat_close(struct procstat *procstat);
|
void procstat_close(struct procstat *procstat);
|
||||||
void procstat_freeargv(struct procstat *procstat);
|
void procstat_freeargv(struct procstat *procstat);
|
||||||
|
#ifndef ZFS
|
||||||
|
void procstat_freeauxv(struct procstat *procstat, Elf_Auxinfo *auxv);
|
||||||
|
#endif
|
||||||
void procstat_freeenvv(struct procstat *procstat);
|
void procstat_freeenvv(struct procstat *procstat);
|
||||||
void procstat_freegroups(struct procstat *procstat, gid_t *groups);
|
void procstat_freegroups(struct procstat *procstat, gid_t *groups);
|
||||||
void procstat_freeprocs(struct procstat *procstat, struct kinfo_proc *p);
|
void procstat_freeprocs(struct procstat *procstat, struct kinfo_proc *p);
|
||||||
|
@ -171,6 +182,10 @@ int procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst,
|
||||||
struct vnstat *vn, char *errbuf);
|
struct vnstat *vn, char *errbuf);
|
||||||
char **procstat_getargv(struct procstat *procstat, struct kinfo_proc *p,
|
char **procstat_getargv(struct procstat *procstat, struct kinfo_proc *p,
|
||||||
size_t nchr);
|
size_t nchr);
|
||||||
|
#ifndef ZFS
|
||||||
|
Elf_Auxinfo *procstat_getauxv(struct procstat *procstat,
|
||||||
|
struct kinfo_proc *kp, unsigned int *cntp);
|
||||||
|
#endif
|
||||||
char **procstat_getenvv(struct procstat *procstat, struct kinfo_proc *p,
|
char **procstat_getenvv(struct procstat *procstat, struct kinfo_proc *p,
|
||||||
size_t nchr);
|
size_t nchr);
|
||||||
gid_t *procstat_getgroups(struct procstat *procstat, struct kinfo_proc *kp,
|
gid_t *procstat_getgroups(struct procstat *procstat, struct kinfo_proc *kp,
|
||||||
|
|
Loading…
Reference in a new issue