//
// ASan-private header for asan_thread.cc.
//===----------------------------------------------------------------------===//
+
#ifndef ASAN_THREAD_H
#define ASAN_THREAD_H
class AsanThreadContext : public ThreadContextBase {
public:
explicit AsanThreadContext(int tid)
- : ThreadContextBase(tid),
- announced(false),
- destructor_iterations(kPthreadDestructorIterations),
- stack_id(0),
- thread(0) {
- }
+ : ThreadContextBase(tid), announced(false),
+ destructor_iterations(GetPthreadDestructorIterations()), stack_id(0),
+ thread(nullptr) {}
bool announced;
u8 destructor_iterations;
u32 stack_id;
AsanThread *thread;
- void OnCreated(void *arg);
- void OnFinished();
+ void OnCreated(void *arg) override;
+ void OnFinished() override;
};
// AsanThreadContext objects are never freed, so we need many of them.
// AsanThread are stored in TSD and destroyed when the thread dies.
class AsanThread {
public:
- static AsanThread *Create(thread_callback_t start_routine, void *arg);
+ static AsanThread *Create(thread_callback_t start_routine, void *arg,
+ u32 parent_tid, StackTrace *stack, bool detached);
static void TSDDtor(void *tsd);
void Destroy();
void Init(); // Should be called from the thread itself.
- thread_return_t ThreadStart(uptr os_id);
+ thread_return_t ThreadStart(uptr os_id,
+ atomic_uintptr_t *signal_thread_is_registered);
uptr stack_top() { return stack_top_; }
uptr stack_bottom() { return stack_bottom_; }
AsanThreadContext *context() { return context_; }
void set_context(AsanThreadContext *context) { context_ = context; }
- const char *GetFrameNameByAddr(uptr addr, uptr *offset, uptr *frame_pc);
+ struct StackFrameAccess {
+ uptr offset;
+ uptr frame_pc;
+ const char *frame_descr;
+ };
+ bool GetStackFrameAccessByAddr(uptr addr, StackFrameAccess *access);
bool AddrIsInStack(uptr addr) {
return addr >= stack_bottom_ && addr < stack_top_;
void DeleteFakeStack(int tid) {
if (!fake_stack_) return;
FakeStack *t = fake_stack_;
- fake_stack_ = 0;
- SetTLSFakeStack(0);
+ fake_stack_ = nullptr;
+ SetTLSFakeStack(nullptr);
t->Destroy(tid);
}
FakeStack *fake_stack() {
if (!__asan_option_detect_stack_use_after_return)
- return 0;
+ return nullptr;
if (!has_fake_stack())
return AsyncSignalSafeLazyInitFakeStack();
return fake_stack_;
bool isUnwinding() const { return unwinding_; }
void setUnwinding(bool b) { unwinding_ = b; }
+ // True if we are in a deadly signal handler.
+ bool isInDeadlySignal() const { return in_deadly_signal_; }
+ void setInDeadlySignal(bool b) { in_deadly_signal_ = b; }
+
AsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; }
AsanStats &stats() { return stats_; }
AsanThreadLocalMallocStorage malloc_storage_;
AsanStats stats_;
bool unwinding_;
+ bool in_deadly_signal_;
};
// ScopedUnwinding is a scope for stacktracing member of a context
AsanThread *thread;
};
-struct CreateThreadContextArgs {
+// ScopedDeadlySignal is a scope for handling deadly signals.
+class ScopedDeadlySignal {
+ public:
+ explicit ScopedDeadlySignal(AsanThread *t) : thread(t) {
+ if (thread) thread->setInDeadlySignal(true);
+ }
+ ~ScopedDeadlySignal() {
+ if (thread) thread->setInDeadlySignal(false);
+ }
+
+ private:
AsanThread *thread;
- StackTrace *stack;
};
// Returns a single instance of registry.
// Used to handle fork().
void EnsureMainThreadIDIsCorrect();
-} // namespace __asan
+} // namespace __asan
-#endif // ASAN_THREAD_H
+#endif // ASAN_THREAD_H