Re: [PATCH] D24628: [ASAN] Pass previous stack information through __sanitizer_finish_switch_fiber
andriigrynenko added inline comments. Comment at: test/asan/TestCases/Linux/swapcontext_annotation.cc:176-199 @@ -164,7 +175,26 @@ ret += Run(argc - 1, 0, stack); +// CHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]] +// CHECK: Main context from: [[CHILD_STACK]] 524288 ret += Run(argc - 1, 1, stack); +// CHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]] +// CHECK: Main context from: [[CHILD_STACK]] 524288 ret += Run(argc - 1, 2, stack); +// CHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]] +// CHECK: NextChild stack: [[NEXT_CHILD_STACK:0x[0-9a-f]*]] +// CHECK: NextChild from: [[CHILD_STACK]] 524288 +// CHECK: Main context from: [[NEXT_CHILD_STACK]] 524288 ret += Run(argc - 1, 0, heap); +// CHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]] +// CHECK: Main context from: [[CHILD_STACK]] 524288 ret += Run(argc - 1, 1, heap); +// CHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]] +// CHECK: Main context from: [[CHILD_STACK]] 524288 ret += Run(argc - 1, 2, heap); +// CHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]] +// CHECK: NextChild stack: [[NEXT_CHILD_STACK:0x[0-9a-f]*]] +// CHECK: NextChild from: [[CHILD_STACK]] 524288 +// CHECK: Main context from: [[NEXT_CHILD_STACK]] 524288 + +// CHECK: Iteration 0 passed +printf("Iteration %d passed\n", i); } dvyukov wrote: > andriigrynenko wrote: > > This only checks the first iteration of the loop. Can I do it better with > > FileCheck ? > Yes, you can add CHECKs for the second iteration as well. > @dvyukov: What I meant is that I didn't see a way to have some kind of loop in these CHECKs. I don't want to copy-paste these same CHECKs 30 times :) https://reviews.llvm.org/D24628 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D24628: [ASAN] Pass previous stack information through __sanitizer_finish_switch_fiber
andriigrynenko updated this revision to Diff 72571. andriigrynenko added a comment. Do CHECKs for all iterations of the loop. https://reviews.llvm.org/D24628 Files: include/sanitizer/common_interface_defs.h lib/asan/asan_thread.cc lib/asan/asan_thread.h test/asan/TestCases/Linux/swapcontext_annotation.cc Index: test/asan/TestCases/Linux/swapcontext_annotation.cc === --- test/asan/TestCases/Linux/swapcontext_annotation.cc +++ test/asan/TestCases/Linux/swapcontext_annotation.cc @@ -1,12 +1,17 @@ // Check that ASan plays well with annotated makecontext/swapcontext. -// RUN: %clangxx_asan -lpthread -O0 %s -o %t && %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -lpthread -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -lpthread -O2 %s -o %t && %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -lpthread -O3 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -std=c++11 -lpthread -O0 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -std=c++11 -lpthread -O1 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -std=c++11 -lpthread -O2 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -std=c++11 -lpthread -O3 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -std=c++11 -lpthread -O0 %s -o %t && %run %t 2>&1 | FileCheck <( seq 60 | xargs -i -- grep LOOPCHECK %s ) --check-prefix LOOPCHECK +// RUN: %clangxx_asan -std=c++11 -lpthread -O1 %s -o %t && %run %t 2>&1 | FileCheck <( seq 60 | xargs -i -- grep LOOPCHECK %s ) --check-prefix LOOPCHECK +// RUN: %clangxx_asan -std=c++11 -lpthread -O2 %s -o %t && %run %t 2>&1 | FileCheck <( seq 60 | xargs -i -- grep LOOPCHECK %s ) --check-prefix LOOPCHECK +// RUN: %clangxx_asan -std=c++11 -lpthread -O3 %s -o %t && %run %t 2>&1 | FileCheck <( seq 60 | xargs -i -- grep LOOPCHECK %s ) --check-prefix LOOPCHECK + // // This test is too subtle to try on non-x86 arch for now. -// REQUIRES: x86_64-supported-target,i386-supported-target +// REQUIRES: x86-target-arch #include #include @@ -25,9 +30,12 @@ const int kStackSize = 1 << 20; -void *main_thread_stack; +const void *main_thread_stack; size_t main_thread_stacksize; +const void *from_stack; +size_t from_stacksize; + __attribute__((noinline, noreturn)) void LongJump(jmp_buf env) { longjmp(env, 1); _exit(1); @@ -44,14 +52,18 @@ void NextChild() { CallNoReturn(); - __sanitizer_finish_switch_fiber(); + __sanitizer_finish_switch_fiber(nullptr, &from_stack, &from_stacksize); + + printf("NextChild from: %p %zu\n", from_stack, from_stacksize); char x[32] = {0}; // Stack gets poisoned. printf("NextChild: %p\n", x); CallNoReturn(); - __sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize); + __sanitizer_start_switch_fiber(nullptr, + main_thread_stack, + main_thread_stacksize); CallNoReturn(); if (swapcontext(&next_child_context, &orig_context) < 0) { perror("swapcontext"); @@ -61,30 +73,39 @@ void Child(int mode) { CallNoReturn(); - __sanitizer_finish_switch_fiber(); + __sanitizer_finish_switch_fiber(nullptr, + &main_thread_stack, + &main_thread_stacksize); char x[32] = {0}; // Stack gets poisoned. printf("Child: %p\n", x); CallNoReturn(); // (a) Do nothing, just return to parent function. // (b) Jump into the original function. Stack remains poisoned unless we do // something. // (c) Jump to another function which will then jump back to the main function if (mode == 0) { -__sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize); +__sanitizer_start_switch_fiber(nullptr, + main_thread_stack, + main_thread_stacksize); CallNoReturn(); } else if (mode == 1) { -__sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize); +__sanitizer_start_switch_fiber(nullptr, + main_thread_stack, + main_thread_stacksize); CallNoReturn(); if (swapcontext(&child_context, &orig_context) < 0) { perror("swapcontext"); _exit(1); } } else if (mode == 2) { +printf("NextChild stack: %p\n", next_child_stack); + getcontext(&next_child_context); next_child_context.uc_stack.ss_sp = next_child_stack; next_child_context.uc_stack.ss_size = kStackSize / 2; makecontext(&next_child_context, (void (*)())NextChild, 0); -__sanitizer_start_switch_fiber(next_child_context.uc_stack.ss_sp, +__sanitizer_start_switch_fiber(nullptr, + next_child_context.uc_stack.ss_sp, next_child_context.uc_stack.ss_size); CallNoReturn(); if (swapcontext(&child_context, &next_child_c
[PATCH] D24628: [ASAN] Pass previous stack information through __sanitizer_finish_switch_fiber
andriigrynenko created this revision. andriigrynenko added reviewers: kcc, blastrock, dvyukov, filcab. andriigrynenko added a subscriber: cfe-commits. andriigrynenko set the repository for this revision to rL LLVM. Herald added a subscriber: kubabrecka. This patch extends __sanitizer_finish_switch_fiber method to optionally return previous stack base and size. This solves the problem of coroutines/fibers library not knowing the original stack context from which the library is used. It's incorrect to assume that such context is always the default stack of current thread (e.g. one such library may be used from a fiber/coroutine created by another library). Bulding a separate stack tracking mechanism would not only duplicate AsanThread, but also require each coroutines/fibers library to integrate with it. Repository: rL LLVM https://reviews.llvm.org/D24628 Files: compiler-rt/include/sanitizer/common_interface_defs.h compiler-rt/lib/asan/asan_thread.cc compiler-rt/lib/asan/asan_thread.h Index: compiler-rt/lib/asan/asan_thread.h === --- compiler-rt/lib/asan/asan_thread.h +++ compiler-rt/lib/asan/asan_thread.h @@ -94,7 +94,8 @@ } void StartSwitchFiber(FakeStack **fake_stack_save, uptr bottom, uptr size); - void FinishSwitchFiber(FakeStack *fake_stack_save); + void FinishSwitchFiber(FakeStack *fake_stack_save, uptr *bottom_old, + uptr *size_old); bool has_fake_stack() { return !atomic_load(&stack_switching_, memory_order_relaxed) && Index: compiler-rt/lib/asan/asan_thread.cc === --- compiler-rt/lib/asan/asan_thread.cc +++ compiler-rt/lib/asan/asan_thread.cc @@ -141,7 +141,9 @@ current_fake_stack->Destroy(this->tid()); } -void AsanThread::FinishSwitchFiber(FakeStack *fake_stack_save) { +void AsanThread::FinishSwitchFiber(FakeStack *fake_stack_save, + uptr *bottom_old, + uptr *size_old) { if (!atomic_load(&stack_switching_, memory_order_relaxed)) { Report("ERROR: finishing a fiber switch that has not started\n"); Die(); @@ -152,6 +154,12 @@ fake_stack_ = fake_stack_save; } + if (bottom_old) { +*bottom_old = stack_bottom_; + } + if (size_old) { +*size_old = stack_top_ - stack_bottom_; + } stack_bottom_ = next_stack_bottom_; stack_top_ = next_stack_top_; atomic_store(&stack_switching_, 0, memory_order_release); @@ -447,12 +455,16 @@ } SANITIZER_INTERFACE_ATTRIBUTE -void __sanitizer_finish_switch_fiber(void* fakestack) { +void __sanitizer_finish_switch_fiber(void* fakestack, + const void **bottom_old, + uptr *size_old) { AsanThread *t = GetCurrentThread(); if (!t) { VReport(1, "__asan_finish_switch_fiber called from unknown thread\n"); return; } - t->FinishSwitchFiber((FakeStack*)fakestack); + t->FinishSwitchFiber((FakeStack*)fakestack, + (uptr*)bottom_old, + (uptr*)size_old); } } Index: compiler-rt/include/sanitizer/common_interface_defs.h === --- compiler-rt/include/sanitizer/common_interface_defs.h +++ compiler-rt/include/sanitizer/common_interface_defs.h @@ -169,7 +169,9 @@ // use-after-return detection. void __sanitizer_start_switch_fiber(void **fake_stack_save, const void *bottom, size_t size); - void __sanitizer_finish_switch_fiber(void *fake_stack_save); + void __sanitizer_finish_switch_fiber(void *fake_stack_save, + const void **bottom_old, + size_t *size_old); #ifdef __cplusplus } // extern "C" #endif Index: compiler-rt/lib/asan/asan_thread.h === --- compiler-rt/lib/asan/asan_thread.h +++ compiler-rt/lib/asan/asan_thread.h @@ -94,7 +94,8 @@ } void StartSwitchFiber(FakeStack **fake_stack_save, uptr bottom, uptr size); - void FinishSwitchFiber(FakeStack *fake_stack_save); + void FinishSwitchFiber(FakeStack *fake_stack_save, uptr *bottom_old, + uptr *size_old); bool has_fake_stack() { return !atomic_load(&stack_switching_, memory_order_relaxed) && Index: compiler-rt/lib/asan/asan_thread.cc === --- compiler-rt/lib/asan/asan_thread.cc +++ compiler-rt/lib/asan/asan_thread.cc @@ -141,7 +141,9 @@ current_fake_stack->Destroy(this->tid()); } -void AsanThread::FinishSwitchFiber(FakeStack *fake_stack_save) { +void AsanThread::FinishSwitchFiber(FakeStack *fake_stack_save, + uptr *bottom_old, + uptr *size_old) { if (!atomic_load(&stack_swi
Re: [PATCH] D24628: [ASAN] Pass previous stack information through __sanitizer_finish_switch_fiber
andriigrynenko updated this revision to Diff 71677. andriigrynenko added a comment. fix the unit test https://reviews.llvm.org/D24628 Files: include/sanitizer/common_interface_defs.h lib/asan/asan_thread.cc lib/asan/asan_thread.h test/asan/TestCases/Linux/swapcontext_annotation.cc Index: test/asan/TestCases/Linux/swapcontext_annotation.cc === --- test/asan/TestCases/Linux/swapcontext_annotation.cc +++ test/asan/TestCases/Linux/swapcontext_annotation.cc @@ -6,7 +6,7 @@ // RUN: %clangxx_asan -lpthread -O3 %s -o %t && %run %t 2>&1 | FileCheck %s // // This test is too subtle to try on non-x86 arch for now. -// REQUIRES: x86_64-supported-target,i386-supported-target +// REQUIRES: x86-target-arch #include #include @@ -44,14 +44,16 @@ void NextChild() { CallNoReturn(); - __sanitizer_finish_switch_fiber(); + __sanitizer_finish_switch_fiber(NULL, NULL, NULL); char x[32] = {0}; // Stack gets poisoned. printf("NextChild: %p\n", x); CallNoReturn(); - __sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize); + __sanitizer_start_switch_fiber(NULL, + main_thread_stack, + main_thread_stacksize); CallNoReturn(); if (swapcontext(&next_child_context, &orig_context) < 0) { perror("swapcontext"); @@ -61,19 +63,23 @@ void Child(int mode) { CallNoReturn(); - __sanitizer_finish_switch_fiber(); + __sanitizer_finish_switch_fiber(NULL, NULL, NULL); char x[32] = {0}; // Stack gets poisoned. printf("Child: %p\n", x); CallNoReturn(); // (a) Do nothing, just return to parent function. // (b) Jump into the original function. Stack remains poisoned unless we do // something. // (c) Jump to another function which will then jump back to the main function if (mode == 0) { -__sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize); +__sanitizer_start_switch_fiber(NULL, + main_thread_stack, + main_thread_stacksize); CallNoReturn(); } else if (mode == 1) { -__sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize); +__sanitizer_start_switch_fiber(NULL, + main_thread_stack, + main_thread_stacksize); CallNoReturn(); if (swapcontext(&child_context, &orig_context) < 0) { perror("swapcontext"); @@ -84,7 +90,8 @@ next_child_context.uc_stack.ss_sp = next_child_stack; next_child_context.uc_stack.ss_size = kStackSize / 2; makecontext(&next_child_context, (void (*)())NextChild, 0); -__sanitizer_start_switch_fiber(next_child_context.uc_stack.ss_sp, +__sanitizer_start_switch_fiber(NULL, + next_child_context.uc_stack.ss_sp, next_child_context.uc_stack.ss_size); CallNoReturn(); if (swapcontext(&child_context, &next_child_context) < 0) { @@ -105,15 +112,16 @@ } makecontext(&child_context, (void (*)())Child, 1, mode); CallNoReturn(); - __sanitizer_start_switch_fiber(child_context.uc_stack.ss_sp, + __sanitizer_start_switch_fiber(NULL, + child_context.uc_stack.ss_sp, child_context.uc_stack.ss_size); CallNoReturn(); if (swapcontext(&orig_context, &child_context) < 0) { perror("swapcontext"); _exit(1); } CallNoReturn(); - __sanitizer_finish_switch_fiber(); + __sanitizer_finish_switch_fiber(NULL, NULL, NULL); CallNoReturn(); // Touch childs's stack to make sure it's unpoisoned. Index: lib/asan/asan_thread.h === --- lib/asan/asan_thread.h +++ lib/asan/asan_thread.h @@ -94,7 +94,8 @@ } void StartSwitchFiber(FakeStack **fake_stack_save, uptr bottom, uptr size); - void FinishSwitchFiber(FakeStack *fake_stack_save); + void FinishSwitchFiber(FakeStack *fake_stack_save, uptr *bottom_old, + uptr *size_old); bool has_fake_stack() { return !atomic_load(&stack_switching_, memory_order_relaxed) && Index: lib/asan/asan_thread.cc === --- lib/asan/asan_thread.cc +++ lib/asan/asan_thread.cc @@ -141,7 +141,9 @@ current_fake_stack->Destroy(this->tid()); } -void AsanThread::FinishSwitchFiber(FakeStack *fake_stack_save) { +void AsanThread::FinishSwitchFiber(FakeStack *fake_stack_save, + uptr *bottom_old, + uptr *size_old) { if (!atomic_load(&stack_switching_, memory_order_relaxed)) { Report("ERROR: finishing a fiber switch that has not started\n"); Die(); @@ -152,6 +154,12 @@ fake_stack_ = fake_stack_save; } + if (bottom_old) { +*bottom_old = stack_bottom_; + } + i
Re: [PATCH] D24628: [ASAN] Pass previous stack information through __sanitizer_finish_switch_fiber
andriigrynenko added inline comments. Comment at: test/asan/TestCases/Linux/swapcontext_annotation.cc:9 @@ -8,3 +8,3 @@ // This test is too subtle to try on non-x86 arch for now. -// REQUIRES: x86_64-supported-target,i386-supported-target +// REQUIRES: x86-target-arch The test was actually broken in trunk (not updated for the fakestack argument). Apparently it was never run (considered unsupported) because of wrong targets here. https://reviews.llvm.org/D24628 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D24628: [ASAN] Pass previous stack information through __sanitizer_finish_switch_fiber
andriigrynenko updated this revision to Diff 71698. andriigrynenko added a comment. update unit test to use non-null values https://reviews.llvm.org/D24628 Files: include/sanitizer/common_interface_defs.h lib/asan/asan_thread.cc lib/asan/asan_thread.h test/asan/TestCases/Linux/swapcontext_annotation.cc Index: test/asan/TestCases/Linux/swapcontext_annotation.cc === --- test/asan/TestCases/Linux/swapcontext_annotation.cc +++ test/asan/TestCases/Linux/swapcontext_annotation.cc @@ -6,10 +6,11 @@ // RUN: %clangxx_asan -lpthread -O3 %s -o %t && %run %t 2>&1 | FileCheck %s // // This test is too subtle to try on non-x86 arch for now. -// REQUIRES: x86_64-supported-target,i386-supported-target +// REQUIRES: x86-target-arch #include #include +#include #include #include #include @@ -25,7 +26,7 @@ const int kStackSize = 1 << 20; -void *main_thread_stack; +const void *main_thread_stack; size_t main_thread_stacksize; __attribute__((noinline, noreturn)) void LongJump(jmp_buf env) { @@ -44,14 +45,16 @@ void NextChild() { CallNoReturn(); - __sanitizer_finish_switch_fiber(); + __sanitizer_finish_switch_fiber(NULL, NULL, NULL); char x[32] = {0}; // Stack gets poisoned. printf("NextChild: %p\n", x); CallNoReturn(); - __sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize); + __sanitizer_start_switch_fiber(NULL, + main_thread_stack, + main_thread_stacksize); CallNoReturn(); if (swapcontext(&next_child_context, &orig_context) < 0) { perror("swapcontext"); @@ -61,19 +64,25 @@ void Child(int mode) { CallNoReturn(); - __sanitizer_finish_switch_fiber(); + __sanitizer_finish_switch_fiber(NULL, + &main_thread_stack, + &main_thread_stacksize); char x[32] = {0}; // Stack gets poisoned. printf("Child: %p\n", x); CallNoReturn(); // (a) Do nothing, just return to parent function. // (b) Jump into the original function. Stack remains poisoned unless we do // something. // (c) Jump to another function which will then jump back to the main function if (mode == 0) { -__sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize); +__sanitizer_start_switch_fiber(NULL, + main_thread_stack, + main_thread_stacksize); CallNoReturn(); } else if (mode == 1) { -__sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize); +__sanitizer_start_switch_fiber(NULL, + main_thread_stack, + main_thread_stacksize); CallNoReturn(); if (swapcontext(&child_context, &orig_context) < 0) { perror("swapcontext"); @@ -84,7 +93,8 @@ next_child_context.uc_stack.ss_sp = next_child_stack; next_child_context.uc_stack.ss_size = kStackSize / 2; makecontext(&next_child_context, (void (*)())NextChild, 0); -__sanitizer_start_switch_fiber(next_child_context.uc_stack.ss_sp, +__sanitizer_start_switch_fiber(NULL, + next_child_context.uc_stack.ss_sp, next_child_context.uc_stack.ss_size); CallNoReturn(); if (swapcontext(&child_context, &next_child_context) < 0) { @@ -105,15 +115,17 @@ } makecontext(&child_context, (void (*)())Child, 1, mode); CallNoReturn(); - __sanitizer_start_switch_fiber(child_context.uc_stack.ss_sp, + void* fake_stack_save; + __sanitizer_start_switch_fiber(&fake_stack_save, + child_context.uc_stack.ss_sp, child_context.uc_stack.ss_size); CallNoReturn(); if (swapcontext(&orig_context, &child_context) < 0) { perror("swapcontext"); _exit(1); } CallNoReturn(); - __sanitizer_finish_switch_fiber(); + __sanitizer_finish_switch_fiber(fake_stack_save, NULL, NULL); CallNoReturn(); // Touch childs's stack to make sure it's unpoisoned. @@ -125,17 +137,7 @@ void handler(int sig) { CallNoReturn(); } -void InitStackBounds() { - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_getattr_np(pthread_self(), &attr); - pthread_attr_getstack(&attr, &main_thread_stack, &main_thread_stacksize); - pthread_attr_destroy(&attr); -} - int main(int argc, char **argv) { - InitStackBounds(); - // set up a signal that will spam and trigger __asan_handle_no_return at // tricky moments struct sigaction act = {}; Index: lib/asan/asan_thread.h === --- lib/asan/asan_thread.h +++ lib/asan/asan_thread.h @@ -94,7 +94,8 @@ } void StartSwitchFiber(FakeStack **fake_stack_save, uptr bottom, uptr size); - void FinishSwitchFiber(FakeStack *fake_stack_save); + void FinishSwitchFiber(Fak
Re: [PATCH] D24628: [ASAN] Pass previous stack information through __sanitizer_finish_switch_fiber
andriigrynenko updated this revision to Diff 71717. andriigrynenko added a comment. Addressing comments. https://reviews.llvm.org/D24628 Files: include/sanitizer/common_interface_defs.h lib/asan/asan_thread.cc lib/asan/asan_thread.h test/asan/TestCases/Linux/swapcontext_annotation.cc Index: test/asan/TestCases/Linux/swapcontext_annotation.cc === --- test/asan/TestCases/Linux/swapcontext_annotation.cc +++ test/asan/TestCases/Linux/swapcontext_annotation.cc @@ -1,12 +1,12 @@ // Check that ASan plays well with annotated makecontext/swapcontext. -// RUN: %clangxx_asan -lpthread -O0 %s -o %t && %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -lpthread -O1 %s -o %t && %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -lpthread -O2 %s -o %t && %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -lpthread -O3 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -std=c++11 -lpthread -O0 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -std=c++11 -lpthread -O1 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -std=c++11 -lpthread -O2 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_asan -std=c++11 -lpthread -O3 %s -o %t && %run %t 2>&1 | FileCheck %s // // This test is too subtle to try on non-x86 arch for now. -// REQUIRES: x86_64-supported-target,i386-supported-target +// REQUIRES: x86-target-arch #include #include @@ -25,9 +25,12 @@ const int kStackSize = 1 << 20; -void *main_thread_stack; +const void *main_thread_stack; size_t main_thread_stacksize; +const void *from_stack; +size_t from_stacksize; + __attribute__((noinline, noreturn)) void LongJump(jmp_buf env) { longjmp(env, 1); _exit(1); @@ -44,14 +47,18 @@ void NextChild() { CallNoReturn(); - __sanitizer_finish_switch_fiber(); + __sanitizer_finish_switch_fiber(nullptr, &from_stack, &from_stacksize); + + printf("NextChild from: %p %zu\n", from_stack, from_stacksize); char x[32] = {0}; // Stack gets poisoned. printf("NextChild: %p\n", x); CallNoReturn(); - __sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize); + __sanitizer_start_switch_fiber(nullptr, + main_thread_stack, + main_thread_stacksize); CallNoReturn(); if (swapcontext(&next_child_context, &orig_context) < 0) { perror("swapcontext"); @@ -61,30 +68,39 @@ void Child(int mode) { CallNoReturn(); - __sanitizer_finish_switch_fiber(); + __sanitizer_finish_switch_fiber(nullptr, + &main_thread_stack, + &main_thread_stacksize); char x[32] = {0}; // Stack gets poisoned. printf("Child: %p\n", x); CallNoReturn(); // (a) Do nothing, just return to parent function. // (b) Jump into the original function. Stack remains poisoned unless we do // something. // (c) Jump to another function which will then jump back to the main function if (mode == 0) { -__sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize); +__sanitizer_start_switch_fiber(nullptr, + main_thread_stack, + main_thread_stacksize); CallNoReturn(); } else if (mode == 1) { -__sanitizer_start_switch_fiber(main_thread_stack, main_thread_stacksize); +__sanitizer_start_switch_fiber(nullptr, + main_thread_stack, + main_thread_stacksize); CallNoReturn(); if (swapcontext(&child_context, &orig_context) < 0) { perror("swapcontext"); _exit(1); } } else if (mode == 2) { +printf("NextChild stack: %p\n", next_child_stack); + getcontext(&next_child_context); next_child_context.uc_stack.ss_sp = next_child_stack; next_child_context.uc_stack.ss_size = kStackSize / 2; makecontext(&next_child_context, (void (*)())NextChild, 0); -__sanitizer_start_switch_fiber(next_child_context.uc_stack.ss_sp, +__sanitizer_start_switch_fiber(nullptr, + next_child_context.uc_stack.ss_sp, next_child_context.uc_stack.ss_size); CallNoReturn(); if (swapcontext(&child_context, &next_child_context) < 0) { @@ -105,16 +121,21 @@ } makecontext(&child_context, (void (*)())Child, 1, mode); CallNoReturn(); - __sanitizer_start_switch_fiber(child_context.uc_stack.ss_sp, + void* fake_stack_save; + __sanitizer_start_switch_fiber(&fake_stack_save, + child_context.uc_stack.ss_sp, child_context.uc_stack.ss_size); CallNoReturn(); if (swapcontext(&orig_context, &child_context) < 0) { perror("swapcontext"); _exit(1); } CallNoReturn(); - __sanitizer_finish_switch_fiber(); + __sanitizer_finish_switch_fiber(fake_stack_save, +
Re: [PATCH] D24628: [ASAN] Pass previous stack information through __sanitizer_finish_switch_fiber
andriigrynenko added inline comments. Comment at: test/asan/TestCases/Linux/swapcontext_annotation.cc:176-199 @@ -164,7 +175,26 @@ ret += Run(argc - 1, 0, stack); +// CHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]] +// CHECK: Main context from: [[CHILD_STACK]] 524288 ret += Run(argc - 1, 1, stack); +// CHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]] +// CHECK: Main context from: [[CHILD_STACK]] 524288 ret += Run(argc - 1, 2, stack); +// CHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]] +// CHECK: NextChild stack: [[NEXT_CHILD_STACK:0x[0-9a-f]*]] +// CHECK: NextChild from: [[CHILD_STACK]] 524288 +// CHECK: Main context from: [[NEXT_CHILD_STACK]] 524288 ret += Run(argc - 1, 0, heap); +// CHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]] +// CHECK: Main context from: [[CHILD_STACK]] 524288 ret += Run(argc - 1, 1, heap); +// CHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]] +// CHECK: Main context from: [[CHILD_STACK]] 524288 ret += Run(argc - 1, 2, heap); +// CHECK: Child stack: [[CHILD_STACK:0x[0-9a-f]*]] +// CHECK: NextChild stack: [[NEXT_CHILD_STACK:0x[0-9a-f]*]] +// CHECK: NextChild from: [[CHILD_STACK]] 524288 +// CHECK: Main context from: [[NEXT_CHILD_STACK]] 524288 + +// CHECK: Iteration 0 passed +printf("Iteration %d passed\n", i); } This only checks the first iteration of the loop. Can I do it better with FileCheck ? https://reviews.llvm.org/D24628 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits