diff options
| author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2012-05-12 12:33:10 +0000 |
|---|---|---|
| committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2012-05-12 12:33:10 +0000 |
| commit | d989be138678eb36c064890d1376ac9540149205 (patch) | |
| tree | 73f17d4df5b7d21b09d057db9d0479528d398c31 | |
| parent | 95d31bcba520ea6bcf4d2125ce2bfa4e2b386bd5 (diff) | |
| download | bcm5719-llvm-d989be138678eb36c064890d1376ac9540149205.tar.gz bcm5719-llvm-d989be138678eb36c064890d1376ac9540149205.zip | |
Fix GetFrameNameByAddr hitting stale stack guards.
In the current implementation AsanThread::GetFrameNameByAddr scans the
stack for a magic guard value to locate base address of the stack
frame. This is not reliable, especially on ARM, where the code that
stores this magic value has to construct it in a register from two
small intermediates; this register can then end up stored in a random
stack location in the prologue of another function.
With this change, GetFrameNameByAddr scans the shadow memory for the
signature of a left stack redzone instead. It is now possible to
remove the magic from the instrumentation pass for additional
performance gain. We keep it there for now just to make sure the new
algorithm does not fail in some corner case.
llvm-svn: 156710
| -rw-r--r-- | compiler-rt/lib/asan/asan_mapping.h | 1 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_thread.cc | 32 |
2 files changed, 23 insertions, 10 deletions
diff --git a/compiler-rt/lib/asan/asan_mapping.h b/compiler-rt/lib/asan/asan_mapping.h index 4824bf109b2..3912484c8b3 100644 --- a/compiler-rt/lib/asan/asan_mapping.h +++ b/compiler-rt/lib/asan/asan_mapping.h @@ -35,6 +35,7 @@ extern __attribute__((visibility("default"))) uintptr_t __asan_mapping_offset; #define SHADOW_GRANULARITY (1ULL << SHADOW_SCALE) #define MEM_TO_SHADOW(mem) (((mem) >> SHADOW_SCALE) | (SHADOW_OFFSET)) +#define SHADOW_TO_MEM(shadow) (((shadow) - SHADOW_OFFSET) << SHADOW_SCALE) #if __WORDSIZE == 64 static const size_t kHighMemEnd = 0x00007fffffffffffUL; diff --git a/compiler-rt/lib/asan/asan_thread.cc b/compiler-rt/lib/asan/asan_thread.cc index 315db7ef98f..0ebbe585d7c 100644 --- a/compiler-rt/lib/asan/asan_thread.cc +++ b/compiler-rt/lib/asan/asan_thread.cc @@ -116,17 +116,29 @@ const char *AsanThread::GetFrameNameByAddr(uintptr_t addr, uintptr_t *offset) { is_fake_stack = true; } uintptr_t aligned_addr = addr & ~(__WORDSIZE/8 - 1); // align addr. - uintptr_t *ptr = (uintptr_t*)aligned_addr; - while (ptr >= (uintptr_t*)bottom) { - if (ptr[0] == kCurrentStackFrameMagic || - (is_fake_stack && ptr[0] == kRetiredStackFrameMagic)) { - *offset = addr - (uintptr_t)ptr; - return (const char*)ptr[1]; - } - ptr--; + uint8_t *shadow_ptr = (uint8_t*)MemToShadow(aligned_addr); + uint8_t *shadow_bottom = (uint8_t*)MemToShadow(bottom); + + while (shadow_ptr >= shadow_bottom && + *shadow_ptr != kAsanStackLeftRedzoneMagic) { + shadow_ptr--; + } + + while (shadow_ptr >= shadow_bottom && + *shadow_ptr == kAsanStackLeftRedzoneMagic) { + shadow_ptr--; } - *offset = 0; - return "UNKNOWN"; + + if (shadow_ptr < shadow_bottom) { + *offset = 0; + return "UNKNOWN"; + } + + uintptr_t* ptr = (uintptr_t*)SHADOW_TO_MEM((uintptr_t)(shadow_ptr + 1)); + CHECK((ptr[0] == kCurrentStackFrameMagic) || + (is_fake_stack && ptr[0] == kRetiredStackFrameMagic)); + *offset = addr - (uintptr_t)ptr; + return (const char*)ptr[1]; } } // namespace __asan |

