Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 3 Jul 2014 06:52:26 +0000 (UTC)
From:      Justin Hibbits <jhibbits@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r268207 - head/sys/dev/hwpmc
Message-ID:  <201407030652.s636qQ1I073493@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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
 	}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201407030652.s636qQ1I073493>