Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/ptrace: Fix build with gcc 4.6

gcc (rightfully) complains that we are accessing beyond the
end of the fpr array (we do, to access the fpscr).

The only sane thing to do (whether anything in that code can be
called remotely sane is debatable) is to special case fpscr and
handle it as a separate statement.

I initially tried to do it it by making the array access conditional
to index < PT_FPSCR and using a 3rd else leg but for some reason gcc
was unable to understand it and still spewed the warning.

So I ended up with something a tad more intricated but it seems to
build on 32-bit and on 64-bit with and without VSX.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

+14 -4
+14 -4
arch/powerpc/kernel/ptrace.c
··· 1497 1497 if (index < PT_FPR0) { 1498 1498 tmp = ptrace_get_reg(child, (int) index); 1499 1499 } else { 1500 + unsigned int fpidx = index - PT_FPR0; 1501 + 1500 1502 flush_fp_to_thread(child); 1501 - tmp = ((unsigned long *)child->thread.fpr) 1502 - [TS_FPRWIDTH * (index - PT_FPR0)]; 1503 + if (fpidx < (PT_FPSCR - PT_FPR0)) 1504 + tmp = ((unsigned long *)child->thread.fpr) 1505 + [fpidx * TS_FPRWIDTH]; 1506 + else 1507 + tmp = child->thread.fpscr.val; 1503 1508 } 1504 1509 ret = put_user(tmp, datalp); 1505 1510 break; ··· 1530 1525 if (index < PT_FPR0) { 1531 1526 ret = ptrace_put_reg(child, index, data); 1532 1527 } else { 1528 + unsigned int fpidx = index - PT_FPR0; 1529 + 1533 1530 flush_fp_to_thread(child); 1534 - ((unsigned long *)child->thread.fpr) 1535 - [TS_FPRWIDTH * (index - PT_FPR0)] = data; 1531 + if (fpidx < (PT_FPSCR - PT_FPR0)) 1532 + ((unsigned long *)child->thread.fpr) 1533 + [fpidx * TS_FPRWIDTH] = data; 1534 + else 1535 + child->thread.fpscr.val = data; 1536 1536 ret = 0; 1537 1537 } 1538 1538 break;