diff options
author | Jay Foad <jay.foad@gmail.com> | 2014-11-14 15:30:39 +0000 |
---|---|---|
committer | Jay Foad <jay.foad@gmail.com> | 2014-11-14 15:30:39 +0000 |
commit | fd35da53328612f687c78d4af0d8546e3befc1e6 (patch) | |
tree | 653f5151ca18217648e1a923b2a77cabc2bfaf98 /lib/asan/asan_posix.cc | |
parent | 850ccaad05a80d95a122e0b873a87ac924dbf759 (diff) |
[ASan] Improved stack overflow detection for PowerPC64
Summary:
AsanOnSIGSEGV has some heuristics for detecting stack overflow, but
they don't cope with a PowerPC store-with-update instruction which
modifies sp and stores to the modified address in one instruction.
This patch adds some PowerPC-specific code to check for this case.
This fixes the last few cases of the stack-overflow test.
Reviewers: kcc, samsonov, eugenis
Reviewed By: eugenis
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D6253
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@222001 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/asan/asan_posix.cc')
-rw-r--r-- | lib/asan/asan_posix.cc | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/lib/asan/asan_posix.cc b/lib/asan/asan_posix.cc index b247ce32a..7b4db8736 100644 --- a/lib/asan/asan_posix.cc +++ b/lib/asan/asan_posix.cc @@ -44,11 +44,37 @@ void AsanOnSIGSEGV(int, void *siginfo, void *context) { // Access at a reasonable offset above SP, or slightly below it (to account // for x86_64 or PowerPC redzone, ARM push of multiple registers, etc) is // probably a stack overflow. + bool IsStackAccess = addr + 512 > sp && addr < sp + 0xFFFF; + +#if __powerpc64__ + // Large stack frames can be allocated with e.g. + // lis r0,-10000 + // stdux r1,r1,r0 # store sp to [sp-10000] and update sp by -10000 + // If the store faults then sp will not have been updated, so test above + // will not work, becase the fault address will be more than just "slightly" + // below sp. + if (!IsStackAccess && IsAccessibleMemoryRange(pc, 4)) { + u32 inst = *(unsigned *)pc; + u32 ra = (inst >> 16) & 0x1F; + u32 opcd = inst >> 26; + u32 xo = (inst >> 1) & 0x3FF; + // Check for store-with-update to sp. The instructions we accept are: + // stbu rs,d(ra) stbux rs,ra,rb + // sthu rs,d(ra) sthux rs,ra,rb + // stwu rs,d(ra) stwux rs,ra,rb + // stdu rs,ds(ra) stdux rs,ra,rb + // where ra is r1 (the stack pointer). + if (ra == 1 && + (opcd == 39 || opcd == 45 || opcd == 37 || opcd == 62 || + (opcd == 31 && (xo == 247 || xo == 439 || xo == 183 || xo == 181)))) + IsStackAccess = true; + } +#endif // __powerpc64__ + // We also check si_code to filter out SEGV caused by something else other // then hitting the guard page or unmapped memory, like, for example, // unaligned memory access. - if (addr + 512 > sp && addr < sp + 0xFFFF && - (code == si_SEGV_MAPERR || code == si_SEGV_ACCERR)) + if (IsStackAccess && (code == si_SEGV_MAPERR || code == si_SEGV_ACCERR)) ReportStackOverflow(pc, sp, bp, context, addr); else ReportSIGSEGV("SEGV", pc, sp, bp, context, addr); |