diff options
author | jkoshy <jkoshy@FreeBSD.org> | 2005-06-30 19:01:26 +0000 |
---|---|---|
committer | jkoshy <jkoshy@FreeBSD.org> | 2005-06-30 19:01:26 +0000 |
commit | 3cade8d074f10ed4002c26e30494d70bb274b767 (patch) | |
tree | 65d154e0d10e4dfd78924cb57c52e53ed80a41dd /sys | |
parent | ca20bf4b48c565fd16ea813e7cce4e94862c31aa (diff) | |
download | FreeBSD-src-3cade8d074f10ed4002c26e30494d70bb274b767.zip FreeBSD-src-3cade8d074f10ed4002c26e30494d70bb274b767.tar.gz |
MFP4:
- pmcstat(8) gprof output mode fixes:
lib/libpmc/pmclog.{c,h}, sys/sys/pmclog.h:
+ Add a 'is_usermode' field to the PMCLOG_PCSAMPLE event
+ Add an 'entryaddr' field to the PMCLOG_PROCEXEC event,
so that pmcstat(8) can determine where the runtime loader
/libexec/ld-elf.so.1 is getting loaded.
sys/kern/kern_exec.c:
+ Use a local struct to group the entry address of the image being
exec()'ed and the process credential changed flag to the exec
handling hook inside hwpmc(4).
usr.sbin/pmcstat/*:
+ Support "-k kernelpath", "-D sampledir".
+ Implement the ELF bits of 'gmon.out' profile generation in a new
file "pmcstat_log.c". Move all log related functions to this
file.
+ Move local definitions and prototypes to "pmcstat.h"
- Other bug fixes:
+ lib/libpmc/pmclog.c: correctly handle EOF in pmclog_read().
+ sys/dev/hwpmc_mod.c: unconditionally log a PROCEXIT event to all
attached PMCs when a process exits.
+ sys/sys/pmc.h: correct a function prototype.
+ Improve usage checks in pmcstat(8).
Approved by: re (blanket hwpmc)
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/hwpmc/hwpmc_logging.c | 17 | ||||
-rw-r--r-- | sys/dev/hwpmc/hwpmc_mod.c | 37 | ||||
-rw-r--r-- | sys/kern/kern_exec.c | 9 | ||||
-rw-r--r-- | sys/sys/pmc.h | 2 | ||||
-rw-r--r-- | sys/sys/pmckern.h | 5 | ||||
-rw-r--r-- | sys/sys/pmclog.h | 6 |
6 files changed, 48 insertions, 28 deletions
diff --git a/sys/dev/hwpmc/hwpmc_logging.c b/sys/dev/hwpmc/hwpmc_logging.c index 5ae7bc6..bca14bd 100644 --- a/sys/dev/hwpmc/hwpmc_logging.c +++ b/sys/dev/hwpmc/hwpmc_logging.c @@ -138,14 +138,16 @@ CTASSERT(sizeof(struct pmclog_mappingchange) == PATH_MAX + 5*4 + 2*sizeof(uintfptr_t)); CTASSERT(offsetof(struct pmclog_mappingchange,pl_pathname) == 5*4 + 2*sizeof(uintfptr_t)); -CTASSERT(sizeof(struct pmclog_pcsample) == 5*4 + sizeof(uintfptr_t)); +CTASSERT(sizeof(struct pmclog_pcsample) == 6*4 + sizeof(uintfptr_t)); CTASSERT(sizeof(struct pmclog_pmcallocate) == 6*4); CTASSERT(sizeof(struct pmclog_pmcattach) == 5*4 + PATH_MAX); CTASSERT(offsetof(struct pmclog_pmcattach,pl_pathname) == 5*4); CTASSERT(sizeof(struct pmclog_pmcdetach) == 5*4); CTASSERT(sizeof(struct pmclog_proccsw) == 5*4 + 8); -CTASSERT(sizeof(struct pmclog_procexec) == 4*4 + PATH_MAX); -CTASSERT(offsetof(struct pmclog_procexec,pl_pathname) == 4*4); +CTASSERT(sizeof(struct pmclog_procexec) == 5*4 + PATH_MAX + + sizeof(uintfptr_t)); +CTASSERT(offsetof(struct pmclog_procexec,pl_pathname) == 5*4 + + sizeof(uintfptr_t)); CTASSERT(sizeof(struct pmclog_procexit) == 5*4 + 8); CTASSERT(sizeof(struct pmclog_procfork) == 5*4); CTASSERT(sizeof(struct pmclog_sysexit) == 4*4); @@ -755,6 +757,7 @@ pmclog_process_pcsample(struct pmc *pm, struct pmc_sample *ps) PMCLOG_EMIT32(ps->ps_pid); PMCLOG_EMITADDR(ps->ps_pc); PMCLOG_EMIT32(pm->pm_id); + PMCLOG_EMIT32(ps->ps_usermode); PMCLOG_DESPATCH(po); } @@ -834,7 +837,8 @@ pmclog_process_proccsw(struct pmc *pm, struct pmc_process *pp, pmc_value_t v) } void -pmclog_process_procexec(struct pmc_owner *po, pid_t pid, char *path) +pmclog_process_procexec(struct pmc_owner *po, pmc_id_t pmid, pid_t pid, + uintfptr_t startaddr, char *path) { int pathlen, recordlen; @@ -845,6 +849,8 @@ pmclog_process_procexec(struct pmc_owner *po, pid_t pid, char *path) PMCLOG_RESERVE(po, PROCEXEC, recordlen); PMCLOG_EMIT32(pid); + PMCLOG_EMITADDR(startaddr); + PMCLOG_EMIT32(pmid); PMCLOG_EMITSTRING(path,pathlen); PMCLOG_DESPATCH(po); } @@ -859,9 +865,6 @@ pmclog_process_procexit(struct pmc *pm, struct pmc_process *pp) int ri; struct pmc_owner *po; - KASSERT(pm->pm_flags & PMC_F_LOG_PROCEXIT, - ("[pmc,%d] log-process-exit called gratuitously", __LINE__)); - ri = PMC_TO_ROWINDEX(pm); PMCDBG(LOG,EXT,1,"pm=%p pid=%d v=%jx", pm, pp->pp_proc->p_pid, pp->pp_pmcs[ri].pp_pmcval); diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c index 962c15b..867722c 100644 --- a/sys/dev/hwpmc/hwpmc_mod.c +++ b/sys/dev/hwpmc/hwpmc_mod.c @@ -661,16 +661,16 @@ pmc_force_context_switch(void) */ static void -pmc_getprocname(struct proc *p, char **fullpath, char **freepath) +pmc_getfilename(struct vnode *v, char **fullpath, char **freepath) { struct thread *td; td = curthread; *fullpath = "unknown"; *freepath = NULL; - vn_lock(p->p_textvp, LK_EXCLUSIVE | LK_RETRY, td); - vn_fullpath(td, p->p_textvp, fullpath, freepath); - VOP_UNLOCK(p->p_textvp, 0, td); + vn_lock(v, LK_EXCLUSIVE | LK_RETRY, td); + vn_fullpath(td, v, fullpath, freepath); + VOP_UNLOCK(v, 0, td); } /* @@ -951,7 +951,7 @@ pmc_attach_one_process(struct proc *p, struct pmc *pm) /* issue an attach event to a configured log file */ if (pm->pm_owner->po_flags & PMC_PO_OWNS_LOGFILE) { - pmc_getprocname(p, &fullpath, &freepath); + pmc_getfilename(p->p_textvp, &fullpath, &freepath); pmclog_process_pmcattach(pm, p->p_pid, fullpath); if (freepath) FREE(freepath, M_TEMP); @@ -1442,7 +1442,6 @@ pmc_hook_handler(struct thread *td, int function, void *arg) case PMC_FN_PROCESS_EXEC: { - int *credentials_changed; char *fullpath, *freepath; unsigned int ri; int is_using_hwpmcs; @@ -1450,16 +1449,20 @@ pmc_hook_handler(struct thread *td, int function, void *arg) struct proc *p; struct pmc_owner *po; struct pmc_process *pp; + struct pmckern_procexec *pk; sx_assert(&pmc_sx, SX_XLOCKED); p = td->td_proc; - pmc_getprocname(p, &fullpath, &freepath); + pmc_getfilename(p->p_textvp, &fullpath, &freepath); + + pk = (struct pmckern_procexec *) arg; /* Inform owners of SS mode PMCs of the exec event. */ LIST_FOREACH(po, &pmc_ss_owners, po_ssnext) if (po->po_flags & PMC_PO_OWNS_LOGFILE) - pmclog_process_procexec(po, p->p_pid, fullpath); + pmclog_process_procexec(po, PMC_ID_INVALID, + p->p_pid, pk->pm_entryaddr, fullpath); PROC_LOCK(p); is_using_hwpmcs = p->p_flag & P_HWPMC; @@ -1499,19 +1502,19 @@ pmc_hook_handler(struct thread *td, int function, void *arg) po = pm->pm_owner; if (po->po_sscount == 0 && po->po_flags & PMC_PO_OWNS_LOGFILE) - pmclog_process_procexec(po, p->p_pid, + pmclog_process_procexec(po, pm->pm_id, + p->p_pid, pk->pm_entryaddr, fullpath); } if (freepath) FREE(freepath, M_TEMP); - credentials_changed = arg; PMCDBG(PRC,EXC,1, "exec proc=%p (%d, %s) cred-changed=%d", - p, p->p_pid, p->p_comm, *credentials_changed); + p, p->p_pid, p->p_comm, pk->pm_credentialschanged); - if (*credentials_changed == 0) /* credentials didn't change */ + if (pk->pm_credentialschanged == 0) /* no change */ break; /* @@ -3457,7 +3460,7 @@ pmc_syscall_handler(struct thread *td, void *syscall_args) */ int -pmc_process_interrupt(int cpu, struct pmc *pm, intfptr_t pc, int usermode) +pmc_process_interrupt(int cpu, struct pmc *pm, uintfptr_t pc, int usermode) { int error, ri; struct thread *td; @@ -3474,7 +3477,7 @@ pmc_process_interrupt(int cpu, struct pmc *pm, intfptr_t pc, int usermode) atomic_add_int(&pmc_stats.pm_intr_bufferfull, 1); atomic_set_int(&pm->pm_flags, PMC_F_IS_STALLED); PMCDBG(SAM,INT,1,"(spc) cpu=%d pm=%p pc=%jx um=%d wr=%d rd=%d", - cpu, pm, (int64_t) pc, usermode, + cpu, pm, (uint64_t) pc, usermode, (int) (psb->ps_write - psb->ps_samples), (int) (psb->ps_read - psb->ps_samples)); error = ENOMEM; @@ -3483,7 +3486,7 @@ pmc_process_interrupt(int cpu, struct pmc *pm, intfptr_t pc, int usermode) /* fill in entry */ PMCDBG(SAM,INT,1,"cpu=%d pm=%p pc=%jx um=%d wr=%d rd=%d", cpu, pm, - (int64_t) pc, usermode, + (uint64_t) pc, usermode, (int) (psb->ps_write - psb->ps_samples), (int) (psb->ps_read - psb->ps_samples)); @@ -3549,7 +3552,7 @@ pmc_process_samples(int cpu) goto entrydone; PMCDBG(SAM,OPS,1,"cpu=%d pm=%p pc=%jx um=%d wr=%d rd=%d", cpu, - pm, (int64_t) ps->ps_pc, ps->ps_usermode, + pm, (uint64_t) ps->ps_pc, ps->ps_usermode, (int) (psb->ps_write - psb->ps_samples), (int) (psb->ps_read - psb->ps_samples)); @@ -3768,7 +3771,7 @@ pmc_process_exit(void *arg __unused, struct proc *p) */ for (ri = 0; ri < md->pmd_npmc; ri++) if ((pm = pp->pp_pmcs[ri].pp_pmc) != NULL) { - if (pm->pm_flags & PMC_F_LOG_PROCEXIT) + if (pm->pm_flags & PMC_F_NEEDS_LOGFILE) pmclog_process_procexit(pm, pp); pmc_unlink_target_process(pm, pp); } diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 3640180..719f5bb 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -301,6 +301,9 @@ do_execve(td, args, mac_p) struct label *interplabel = NULL; int will_transition; #endif +#ifdef HWPMC_HOOKS + struct pmckern_procexec pe; +#endif vfslocked = 0; imgp = &image_params; @@ -681,8 +684,10 @@ interpret: */ if (PMC_SYSTEM_SAMPLING_ACTIVE() || PMC_PROC_IS_USING_PMCS(p)) { PROC_UNLOCK(p); - PMC_CALL_HOOK_X(td, PMC_FN_PROCESS_EXEC, - (void *) &credential_changing); + pe.pm_credentialschanged = credential_changing; + pe.pm_entryaddr = imgp->entry_addr; + + PMC_CALL_HOOK_X(td, PMC_FN_PROCESS_EXEC, (void *) &pe); } else PROC_UNLOCK(p); #else /* !HWPMC_HOOKS */ diff --git a/sys/sys/pmc.h b/sys/sys/pmc.h index 5126f32..e872ffb 100644 --- a/sys/sys/pmc.h +++ b/sys/sys/pmc.h @@ -995,7 +995,7 @@ MALLOC_DECLARE(M_PMC); struct pmc_mdep *pmc_md_initialize(void); /* MD init function */ int pmc_getrowdisp(int _ri); -int pmc_process_interrupt(int _cpu, struct pmc *_pm, intfptr_t _pc, +int pmc_process_interrupt(int _cpu, struct pmc *_pm, uintfptr_t _pc, int _usermode); #endif /* _KERNEL */ diff --git a/sys/sys/pmckern.h b/sys/sys/pmckern.h index 5f2e158..0d689b2 100644 --- a/sys/sys/pmckern.h +++ b/sys/sys/pmckern.h @@ -44,6 +44,11 @@ #define PMC_FN_CSW_OUT 3 #define PMC_FN_DO_SAMPLES 4 +struct pmckern_procexec { + int pm_credentialschanged; + uintptr_t pm_entryaddr; +}; + /* hook */ extern int (*pmc_hook)(struct thread *_td, int _function, void *_arg); extern int (*pmc_intr)(int _cpu, uintptr_t _pc, int _usermode); diff --git a/sys/sys/pmclog.h b/sys/sys/pmclog.h index 97aa2f6..026c667 100644 --- a/sys/sys/pmclog.h +++ b/sys/sys/pmclog.h @@ -113,6 +113,7 @@ struct pmclog_pcsample { uint32_t pl_pid; uintfptr_t pl_pc; /* 8 byte aligned */ uint32_t pl_pmcid; + uint32_t pl_usermode; } __packed; struct pmclog_pmcallocate { @@ -145,6 +146,8 @@ struct pmclog_proccsw { struct pmclog_procexec { PMCLOG_ENTRY_HEADER uint32_t pl_pid; + uintfptr_t pl_start; /* keep 8 byte aligned */ + uint32_t pl_pmcid; char pl_pathname[PATH_MAX]; } __packed; @@ -217,7 +220,8 @@ void pmclog_process_pmcattach(struct pmc *_pm, pid_t _pid, char *_path); void pmclog_process_pmcdetach(struct pmc *_pm, pid_t _pid); void pmclog_process_proccsw(struct pmc *_pm, struct pmc_process *_pp, pmc_value_t _v); -void pmclog_process_procexec(struct pmc_owner *_po, pid_t _pid, char *_path); +void pmclog_process_procexec(struct pmc_owner *_po, pmc_id_t _pmid, pid_t _pid, + uintfptr_t _startaddr, char *_path); void pmclog_process_procexit(struct pmc *_pm, struct pmc_process *_pp); void pmclog_process_procfork(struct pmc_owner *_po, pid_t _oldpid, pid_t _newpid); void pmclog_process_sysexit(struct pmc_owner *_po, pid_t _pid); |