svn commit: r268207 - head/sys/dev/hwpmc

Justin Hibbits jhibbits at FreeBSD.org
Thu Jul 3 06:52:27 UTC 2014


Author: jhibbits
Date: Thu Jul  3 06:52:26 2014
New Revision: 268207
URL: http://svnweb.freebsd.org/changeset/base/268207

Log:
  Fix a bug in hwpmc(4) callchain retrieval, for both user and kernel.
  
  The array index for the callchain is getting double-incremented -- both in the
  loop and the storing.  It should only be incremented in one location.
  
  Also, constrain the stack pointer range check.
  
  MFC after:	2 weeks

Modified:
  head/sys/dev/hwpmc/hwpmc_powerpc.c

Modified: head/sys/dev/hwpmc/hwpmc_powerpc.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_powerpc.c	Thu Jul  3 06:44:55 2014	(r268206)
+++ head/sys/dev/hwpmc/hwpmc_powerpc.c	Thu Jul  3 06:52:26 2014	(r268207)
@@ -55,20 +55,22 @@ int
 pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples,
     struct trapframe *tf)
 {
+	uintptr_t *osp, *sp;
 	int frames = 0;
-	uintptr_t *sp;
 
 	cc[frames++] = PMC_TRAPFRAME_TO_PC(tf);
 	sp = (uintptr_t *)PMC_TRAPFRAME_TO_FP(tf);
+	osp = NULL;
 
 	for (; frames < maxsamples; frames++) {
-		if (!INKERNEL(sp))
+		if (!INKERNEL(sp) || sp <= osp)
 			break;
 #ifdef __powerpc64__
-		cc[frames++] = sp[2];
+		cc[frames] = sp[2];
 #else
-		cc[frames++] = sp[1];
+		cc[frames] = sp[1];
 #endif
+		osp = sp;
 		sp = (uintptr_t *)*sp;
 	}
 	return (frames);
@@ -184,26 +186,28 @@ int
 pmc_save_user_callchain(uintptr_t *cc, int maxsamples,
     struct trapframe *tf)
 {
-	uintptr_t *sp;
+	uintptr_t *osp, *sp;
 	int frames = 0;
 
 	cc[frames++] = PMC_TRAPFRAME_TO_PC(tf);
 	sp = (uintptr_t *)PMC_TRAPFRAME_TO_FP(tf);
+	osp = NULL;
 
 	for (; frames < maxsamples; frames++) {
-		if (!INUSER(sp))
+		if (!INUSER(sp) || sp <= osp)
 			break;
+		osp = sp;
 #ifdef __powerpc64__
 		/* Check if 32-bit mode. */
 		if (!(tf->srr1 & PSL_SF)) {
-			cc[frames++] = fuword32((uint32_t *)sp + 1);
+			cc[frames] = fuword32((uint32_t *)sp + 1);
 			sp = (uintptr_t *)(uintptr_t)fuword32(sp);
 		} else {
-			cc[frames++] = fuword(sp + 2);
+			cc[frames] = fuword(sp + 2);
 			sp = (uintptr_t *)fuword(sp);
 		}
 #else
-		cc[frames++] = fuword32((uint32_t *)sp + 1);
+		cc[frames] = fuword32((uint32_t *)sp + 1);
 		sp = (uintptr_t *)fuword32(sp);
 #endif
 	}


More information about the svn-src-head mailing list