Skip to content

Commit 83832fe

Browse files
committedAug 9, 2017
[asan] Complete the Fuchsia port
Submitted on behalf of Roland McGrath. Reviewers: kcc, eugenis, alekseyshl, vitalybuka Reviewed By: vitalybuka Subscribers: filcab, vitalybuka, srhines, kubamracek, mgorny, phosek, llvm-commits Tags: #sanitizers Differential Revision: https://reviews.llvm.org/D35865 llvm-svn: 310431
1 parent d8e3efd commit 83832fe

10 files changed

+248
-7
lines changed
 

‎compiler-rt/lib/asan/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ set(ASAN_SOURCES
88
asan_errors.cc
99
asan_fake_stack.cc
1010
asan_flags.cc
11+
asan_fuchsia.cc
1112
asan_globals.cc
1213
asan_globals_win.cc
1314
asan_interceptors.cc

‎compiler-rt/lib/asan/asan_fake_stack.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ void FakeStack::ForEachFakeFrame(RangeIteratorCallback callback, void *arg) {
171171
}
172172
}
173173

174-
#if SANITIZER_LINUX && !SANITIZER_ANDROID
174+
#if (SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_FUCHSIA
175175
static THREADLOCAL FakeStack *fake_stack_tls;
176176

177177
FakeStack *GetTLSFakeStack() {
@@ -183,7 +183,7 @@ void SetTLSFakeStack(FakeStack *fs) {
183183
#else
184184
FakeStack *GetTLSFakeStack() { return 0; }
185185
void SetTLSFakeStack(FakeStack *fs) { }
186-
#endif // SANITIZER_LINUX && !SANITIZER_ANDROID
186+
#endif // (SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_FUCHSIA
187187

188188
static FakeStack *GetFakeStack() {
189189
AsanThread *t = GetCurrentThread();

‎compiler-rt/lib/asan/asan_fuchsia.cc

+218
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
//===-- asan_fuchsia.cc --------------------------------------------------===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===---------------------------------------------------------------------===//
9+
//
10+
// This file is a part of AddressSanitizer, an address sanity checker.
11+
//
12+
// Fuchsia-specific details.
13+
//===---------------------------------------------------------------------===//
14+
15+
#include "sanitizer_common/sanitizer_fuchsia.h"
16+
#if SANITIZER_FUCHSIA
17+
18+
#include "asan_interceptors.h"
19+
#include "asan_internal.h"
20+
#include "asan_stack.h"
21+
#include "asan_thread.h"
22+
23+
#include <limits.h>
24+
#include <magenta/sanitizer.h>
25+
#include <magenta/syscalls.h>
26+
#include <magenta/threads.h>
27+
28+
namespace __asan {
29+
30+
// The system already set up the shadow memory for us.
31+
// __sanitizer::GetMaxVirtualAddress has already been called by
32+
// AsanInitInternal->InitializeHighMemEnd (asan_rtl.cc).
33+
// Just do some additional sanity checks here.
34+
void InitializeShadowMemory() {
35+
if (Verbosity()) PrintAddressSpaceLayout();
36+
37+
// Make sure SHADOW_OFFSET doesn't use __asan_shadow_memory_dynamic_address.
38+
__asan_shadow_memory_dynamic_address = kDefaultShadowSentinel;
39+
DCHECK(kLowShadowBeg != kDefaultShadowSentinel);
40+
__asan_shadow_memory_dynamic_address = kLowShadowBeg;
41+
42+
CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1);
43+
CHECK_EQ(kHighMemEnd, __sanitizer::ShadowBounds.memory_limit - 1);
44+
CHECK_EQ(kHighMemBeg, __sanitizer::ShadowBounds.shadow_limit);
45+
CHECK_EQ(kHighShadowBeg, __sanitizer::ShadowBounds.shadow_base);
46+
CHECK_EQ(kShadowGapEnd, __sanitizer::ShadowBounds.shadow_base - 1);
47+
CHECK_EQ(kLowShadowEnd, 0);
48+
CHECK_EQ(kLowShadowBeg, 0);
49+
}
50+
51+
void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
52+
UNIMPLEMENTED();
53+
}
54+
55+
void AsanCheckDynamicRTPrereqs() {}
56+
void AsanCheckIncompatibleRT() {}
57+
void InitializeAsanInterceptors() {}
58+
59+
void *AsanDoesNotSupportStaticLinkage() { return nullptr; }
60+
61+
void InitializePlatformExceptionHandlers() {}
62+
void AsanOnDeadlySignal(int signo, void *siginfo, void *context) {
63+
UNIMPLEMENTED();
64+
}
65+
66+
// We can use a plain thread_local variable for TSD.
67+
static thread_local void *per_thread;
68+
69+
void *AsanTSDGet() { return per_thread; }
70+
71+
void AsanTSDSet(void *tsd) { per_thread = tsd; }
72+
73+
// There's no initialization needed, and the passed-in destructor
74+
// will never be called. Instead, our own thread destruction hook
75+
// (below) will call AsanThread::TSDDtor directly.
76+
void AsanTSDInit(void (*destructor)(void *tsd)) {
77+
DCHECK(destructor == &PlatformTSDDtor);
78+
}
79+
80+
void PlatformTSDDtor(void *tsd) { UNREACHABLE(__func__); }
81+
82+
static inline size_t AsanThreadMmapSize() {
83+
return RoundUpTo(sizeof(AsanThread), PAGE_SIZE);
84+
}
85+
86+
struct AsanThread::InitOptions {
87+
uptr stack_bottom, stack_size;
88+
};
89+
90+
// Shared setup between thread creation and startup for the initial thread.
91+
static AsanThread *CreateAsanThread(StackTrace *stack, u32 parent_tid,
92+
uptr user_id, bool detached,
93+
const char *name, uptr stack_bottom,
94+
uptr stack_size) {
95+
// In lieu of AsanThread::Create.
96+
AsanThread *thread = (AsanThread *)MmapOrDie(AsanThreadMmapSize(), __func__);
97+
98+
AsanThreadContext::CreateThreadContextArgs args = {thread, stack};
99+
u32 tid =
100+
asanThreadRegistry().CreateThread(user_id, detached, parent_tid, &args);
101+
asanThreadRegistry().SetThreadName(tid, name);
102+
103+
// On other systems, AsanThread::Init() is called from the new
104+
// thread itself. But on Fuchsia we already know the stack address
105+
// range beforehand, so we can do most of the setup right now.
106+
const AsanThread::InitOptions options = {stack_bottom, stack_size};
107+
thread->Init(&options);
108+
109+
return thread;
110+
}
111+
112+
// This gets the same arguments passed to Init by CreateAsanThread, above.
113+
// We're in the creator thread before the new thread is actually started,
114+
// but its stack address range is already known. We don't bother tracking
115+
// the static TLS address range because the system itself already uses an
116+
// ASan-aware allocator for that.
117+
void AsanThread::SetThreadStackAndTls(const AsanThread::InitOptions *options) {
118+
DCHECK_NE(GetCurrentThread(), this);
119+
DCHECK_NE(GetCurrentThread(), nullptr);
120+
CHECK_NE(options->stack_bottom, 0);
121+
CHECK_NE(options->stack_size, 0);
122+
stack_bottom_ = options->stack_bottom;
123+
stack_top_ = options->stack_bottom + options->stack_size;
124+
}
125+
126+
// Called by __asan::AsanInitInternal (asan_rtl.c).
127+
AsanThread *CreateMainThread() {
128+
thrd_t self = thrd_current();
129+
char name[MX_MAX_NAME_LEN];
130+
CHECK_NE(__sanitizer::MainThreadStackBase, 0);
131+
CHECK_GT(__sanitizer::MainThreadStackSize, 0);
132+
AsanThread *t = CreateAsanThread(
133+
nullptr, 0, reinterpret_cast<uptr>(self), true,
134+
_mx_object_get_property(thrd_get_mx_handle(self), MX_PROP_NAME, name,
135+
sizeof(name)) == MX_OK
136+
? name
137+
: nullptr,
138+
__sanitizer::MainThreadStackBase, __sanitizer::MainThreadStackSize);
139+
SetCurrentThread(t);
140+
return t;
141+
}
142+
143+
// This is called before each thread creation is attempted. So, in
144+
// its first call, the calling thread is the initial and sole thread.
145+
static void *BeforeThreadCreateHook(uptr user_id, bool detached,
146+
const char *name, uptr stack_bottom,
147+
uptr stack_size) {
148+
EnsureMainThreadIDIsCorrect();
149+
// Strict init-order checking is thread-hostile.
150+
if (flags()->strict_init_order) StopInitOrderChecking();
151+
152+
GET_STACK_TRACE_THREAD;
153+
u32 parent_tid = GetCurrentTidOrInvalid();
154+
155+
return CreateAsanThread(&stack, parent_tid, user_id, detached, name,
156+
stack_bottom, stack_size);
157+
}
158+
159+
// This is called after creating a new thread (in the creating thread),
160+
// with the pointer returned by BeforeThreadCreateHook (above).
161+
static void ThreadCreateHook(void *hook, bool aborted) {
162+
AsanThread *thread = static_cast<AsanThread *>(hook);
163+
if (!aborted) {
164+
// The thread was created successfully.
165+
// ThreadStartHook is already running in the new thread.
166+
} else {
167+
// The thread wasn't created after all.
168+
// Clean up everything we set up in BeforeThreadCreateHook.
169+
asanThreadRegistry().FinishThread(thread->tid());
170+
UnmapOrDie(thread, AsanThreadMmapSize());
171+
}
172+
}
173+
174+
// This is called in the newly-created thread before it runs anything else,
175+
// with the pointer returned by BeforeThreadCreateHook (above).
176+
// cf. asan_interceptors.cc:asan_thread_start
177+
static void ThreadStartHook(void *hook, uptr os_id) {
178+
AsanThread *thread = static_cast<AsanThread *>(hook);
179+
SetCurrentThread(thread);
180+
181+
// In lieu of AsanThread::ThreadStart.
182+
asanThreadRegistry().StartThread(thread->tid(), os_id, /*workerthread*/ false,
183+
nullptr);
184+
}
185+
186+
// Each thread runs this just before it exits,
187+
// with the pointer returned by BeforeThreadCreateHook (above).
188+
// All per-thread destructors have already been called.
189+
static void ThreadExitHook(void *hook, uptr os_id) {
190+
AsanThread::TSDDtor(per_thread);
191+
}
192+
193+
} // namespace __asan
194+
195+
// These are declared (in extern "C") by <magenta/sanitizer.h>.
196+
// The system runtime will call our definitions directly.
197+
198+
void *__sanitizer_before_thread_create_hook(thrd_t thread, bool detached,
199+
const char *name, void *stack_base,
200+
size_t stack_size) {
201+
return __asan::BeforeThreadCreateHook(
202+
reinterpret_cast<uptr>(thread), detached, name,
203+
reinterpret_cast<uptr>(stack_base), stack_size);
204+
}
205+
206+
void __sanitizer_thread_create_hook(void *hook, thrd_t thread, int error) {
207+
__asan::ThreadCreateHook(hook, error != thrd_success);
208+
}
209+
210+
void __sanitizer_thread_start_hook(void *hook, thrd_t self) {
211+
__asan::ThreadStartHook(hook, reinterpret_cast<uptr>(self));
212+
}
213+
214+
void __sanitizer_thread_exit_hook(void *hook, thrd_t self) {
215+
__asan::ThreadExitHook(hook, reinterpret_cast<uptr>(self));
216+
}
217+
218+
#endif // SANITIZER_FUCHSIA

‎compiler-rt/lib/asan/asan_mapping.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,9 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000
144144

145145
#define SHADOW_SCALE kDefaultShadowScale
146146

147-
148-
#if SANITIZER_WORDSIZE == 32
147+
#if SANITIZER_FUCHSIA
148+
# define SHADOW_OFFSET (0)
149+
#elif SANITIZER_WORDSIZE == 32
149150
# if SANITIZER_ANDROID
150151
# define SHADOW_OFFSET (0)
151152
# elif defined(__mips__)

‎compiler-rt/lib/asan/asan_poisoning.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,11 @@ ALWAYS_INLINE void FastPoisonShadow(uptr aligned_beg, uptr aligned_size,
4646
// for mapping shadow and zeroing out pages doesn't "just work", so we should
4747
// probably provide higher-level interface for these operations.
4848
// For now, just memset on Windows.
49-
if (value ||
50-
SANITIZER_WINDOWS == 1 ||
49+
if (value || SANITIZER_WINDOWS == 1 ||
50+
// TODO(mcgrathr): Fuchsia doesn't allow the shadow mapping to be
51+
// changed at all. It doesn't currently have an efficient means
52+
// to zero a bunch of pages, but maybe we should add one.
53+
SANITIZER_FUCHSIA == 1 ||
5154
shadow_end - shadow_beg < common_flags()->clear_shadow_mmap_threshold) {
5255
REAL(memset)((void*)shadow_beg, value, shadow_end - shadow_beg);
5356
} else {

‎compiler-rt/lib/asan/asan_rtl.cc

+1
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,7 @@ void NOINLINE __asan_handle_no_return() {
528528
top = curr_thread->stack_top();
529529
bottom = ((uptr)&local_stack - PageSize) & ~(PageSize - 1);
530530
} else {
531+
CHECK(!SANITIZER_FUCHSIA);
531532
// If we haven't seen this thread, try asking the OS for stack bounds.
532533
uptr tls_addr, tls_size, stack_size;
533534
GetThreadStackAndTls(/*main=*/false, &bottom, &stack_size, &tls_addr,

‎compiler-rt/lib/asan/asan_shadow_setup.cc

+7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
// Set up the shadow memory.
1313
//===----------------------------------------------------------------------===//
1414

15+
#include "sanitizer_common/sanitizer_platform.h"
16+
17+
// asan_fuchsia.cc has its own InitializeShadowMemory implementation.
18+
#if !SANITIZER_FUCHSIA
19+
1520
#include "asan_internal.h"
1621
#include "asan_mapping.h"
1722

@@ -142,3 +147,5 @@ void InitializeShadowMemory() {
142147
}
143148

144149
} // namespace __asan
150+
151+
#endif // !SANITIZER_FUCHSIA

‎compiler-rt/lib/asan/asan_thread.cc

+6
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,10 @@ void AsanThread::Init() {
239239
&local);
240240
}
241241

242+
// Fuchsia doesn't use ThreadStart.
243+
// asan_fuchsia.c defines CreateMainThread and SetThreadStackAndTls.
244+
#if !SANITIZER_FUCHSIA
245+
242246
thread_return_t AsanThread::ThreadStart(
243247
tid_t os_id, atomic_uintptr_t *signal_thread_is_registered) {
244248
Init();
@@ -283,6 +287,8 @@ void AsanThread::SetThreadStackAndTls() {
283287
CHECK(AddrIsInStack((uptr)&local));
284288
}
285289

290+
#endif // !SANITIZER_FUCHSIA
291+
286292
void AsanThread::ClearShadowForThreadStackAndTLS() {
287293
PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
288294
if (tls_begin_ != tls_end_)

‎compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cc

+3
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ void InitTlsSize() {}
9797

9898
void PrintModuleMap() {}
9999

100+
void SignalContext::DumpAllRegisters(void *context) { UNIMPLEMENTED(); }
101+
const char *DescribeSignalOrException(int signo) { UNIMPLEMENTED(); }
102+
100103
struct UnwindTraceArg {
101104
BufferedStackTrace *stack;
102105
u32 max_depth;

‎compiler-rt/lib/sanitizer_common/sanitizer_thread_registry.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,8 @@ void ThreadRegistry::SetThreadName(u32 tid, const char *name) {
204204
CHECK_LT(tid, n_contexts_);
205205
ThreadContextBase *tctx = threads_[tid];
206206
CHECK_NE(tctx, 0);
207-
CHECK_EQ(ThreadStatusRunning, tctx->status);
207+
CHECK_EQ(SANITIZER_FUCHSIA ? ThreadStatusCreated : ThreadStatusRunning,
208+
tctx->status);
208209
tctx->SetName(name);
209210
}
210211

0 commit comments

Comments
 (0)