1*760c2415Smrg //===-- sanitizer_fuchsia.cc ----------------------------------------------===//
28dd4bdcdSmrg //
38dd4bdcdSmrg // This file is distributed under the University of Illinois Open Source
48dd4bdcdSmrg // License. See LICENSE.TXT for details.
58dd4bdcdSmrg //
6*760c2415Smrg //===----------------------------------------------------------------------===//
78dd4bdcdSmrg //
88dd4bdcdSmrg // This file is shared between AddressSanitizer and other sanitizer
98dd4bdcdSmrg // run-time libraries and implements Fuchsia-specific functions from
108dd4bdcdSmrg // sanitizer_common.h.
11*760c2415Smrg //===----------------------------------------------------------------------===//
128dd4bdcdSmrg
138dd4bdcdSmrg #include "sanitizer_fuchsia.h"
148dd4bdcdSmrg #if SANITIZER_FUCHSIA
158dd4bdcdSmrg
168dd4bdcdSmrg #include "sanitizer_common.h"
178dd4bdcdSmrg #include "sanitizer_libc.h"
188dd4bdcdSmrg #include "sanitizer_mutex.h"
198dd4bdcdSmrg
208dd4bdcdSmrg #include <limits.h>
218dd4bdcdSmrg #include <pthread.h>
228dd4bdcdSmrg #include <stdlib.h>
238dd4bdcdSmrg #include <unistd.h>
248dd4bdcdSmrg #include <zircon/errors.h>
258dd4bdcdSmrg #include <zircon/process.h>
268dd4bdcdSmrg #include <zircon/syscalls.h>
278dd4bdcdSmrg
288dd4bdcdSmrg namespace __sanitizer {
298dd4bdcdSmrg
internal__exit(int exitcode)308dd4bdcdSmrg void NORETURN internal__exit(int exitcode) { _zx_process_exit(exitcode); }
318dd4bdcdSmrg
internal_sched_yield()328dd4bdcdSmrg uptr internal_sched_yield() {
338dd4bdcdSmrg zx_status_t status = _zx_nanosleep(0);
348dd4bdcdSmrg CHECK_EQ(status, ZX_OK);
358dd4bdcdSmrg return 0; // Why doesn't this return void?
368dd4bdcdSmrg }
378dd4bdcdSmrg
internal_nanosleep(zx_time_t ns)388dd4bdcdSmrg static void internal_nanosleep(zx_time_t ns) {
398dd4bdcdSmrg zx_status_t status = _zx_nanosleep(_zx_deadline_after(ns));
408dd4bdcdSmrg CHECK_EQ(status, ZX_OK);
418dd4bdcdSmrg }
428dd4bdcdSmrg
internal_sleep(unsigned int seconds)438dd4bdcdSmrg unsigned int internal_sleep(unsigned int seconds) {
448dd4bdcdSmrg internal_nanosleep(ZX_SEC(seconds));
458dd4bdcdSmrg return 0;
468dd4bdcdSmrg }
478dd4bdcdSmrg
NanoTime()48*760c2415Smrg u64 NanoTime() { return _zx_clock_get(ZX_CLOCK_UTC); }
49*760c2415Smrg
MonotonicNanoTime()50*760c2415Smrg u64 MonotonicNanoTime() { return _zx_clock_get(ZX_CLOCK_MONOTONIC); }
518dd4bdcdSmrg
internal_getpid()528dd4bdcdSmrg uptr internal_getpid() {
538dd4bdcdSmrg zx_info_handle_basic_t info;
548dd4bdcdSmrg zx_status_t status =
558dd4bdcdSmrg _zx_object_get_info(_zx_process_self(), ZX_INFO_HANDLE_BASIC, &info,
568dd4bdcdSmrg sizeof(info), NULL, NULL);
578dd4bdcdSmrg CHECK_EQ(status, ZX_OK);
588dd4bdcdSmrg uptr pid = static_cast<uptr>(info.koid);
598dd4bdcdSmrg CHECK_EQ(pid, info.koid);
608dd4bdcdSmrg return pid;
618dd4bdcdSmrg }
628dd4bdcdSmrg
internal_dlinfo(void * handle,int request,void * p)63*760c2415Smrg int internal_dlinfo(void *handle, int request, void *p) {
64*760c2415Smrg UNIMPLEMENTED();
65*760c2415Smrg }
66*760c2415Smrg
GetThreadSelf()678dd4bdcdSmrg uptr GetThreadSelf() { return reinterpret_cast<uptr>(thrd_current()); }
688dd4bdcdSmrg
GetTid()69*760c2415Smrg tid_t GetTid() { return GetThreadSelf(); }
708dd4bdcdSmrg
Abort()718dd4bdcdSmrg void Abort() { abort(); }
728dd4bdcdSmrg
Atexit(void (* function)(void))738dd4bdcdSmrg int Atexit(void (*function)(void)) { return atexit(function); }
748dd4bdcdSmrg
SleepForSeconds(int seconds)758dd4bdcdSmrg void SleepForSeconds(int seconds) { internal_sleep(seconds); }
768dd4bdcdSmrg
SleepForMillis(int millis)778dd4bdcdSmrg void SleepForMillis(int millis) { internal_nanosleep(ZX_MSEC(millis)); }
788dd4bdcdSmrg
GetThreadStackTopAndBottom(bool,uptr * stack_top,uptr * stack_bottom)798dd4bdcdSmrg void GetThreadStackTopAndBottom(bool, uptr *stack_top, uptr *stack_bottom) {
808dd4bdcdSmrg pthread_attr_t attr;
818dd4bdcdSmrg CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
828dd4bdcdSmrg void *base;
838dd4bdcdSmrg size_t size;
848dd4bdcdSmrg CHECK_EQ(pthread_attr_getstack(&attr, &base, &size), 0);
858dd4bdcdSmrg CHECK_EQ(pthread_attr_destroy(&attr), 0);
868dd4bdcdSmrg
878dd4bdcdSmrg *stack_bottom = reinterpret_cast<uptr>(base);
888dd4bdcdSmrg *stack_top = *stack_bottom + size;
898dd4bdcdSmrg }
908dd4bdcdSmrg
MaybeReexec()918dd4bdcdSmrg void MaybeReexec() {}
CheckASLR()92*760c2415Smrg void CheckASLR() {}
PlatformPrepareForSandboxing(__sanitizer_sandbox_arguments * args)93*760c2415Smrg void PlatformPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {}
DisableCoreDumperIfNecessary()948dd4bdcdSmrg void DisableCoreDumperIfNecessary() {}
InstallDeadlySignalHandlers(SignalHandlerType handler)958dd4bdcdSmrg void InstallDeadlySignalHandlers(SignalHandlerType handler) {}
SetAlternateSignalStack()968dd4bdcdSmrg void SetAlternateSignalStack() {}
UnsetAlternateSignalStack()978dd4bdcdSmrg void UnsetAlternateSignalStack() {}
InitTlsSize()988dd4bdcdSmrg void InitTlsSize() {}
998dd4bdcdSmrg
PrintModuleMap()1008dd4bdcdSmrg void PrintModuleMap() {}
1018dd4bdcdSmrg
IsStackOverflow() const1028dd4bdcdSmrg bool SignalContext::IsStackOverflow() const { return false; }
DumpAllRegisters(void * context)1038dd4bdcdSmrg void SignalContext::DumpAllRegisters(void *context) { UNIMPLEMENTED(); }
Describe() const1048dd4bdcdSmrg const char *SignalContext::Describe() const { UNIMPLEMENTED(); }
1058dd4bdcdSmrg
1068dd4bdcdSmrg enum MutexState : int { MtxUnlocked = 0, MtxLocked = 1, MtxSleeping = 2 };
1078dd4bdcdSmrg
BlockingMutex()1088dd4bdcdSmrg BlockingMutex::BlockingMutex() {
1098dd4bdcdSmrg // NOTE! It's important that this use internal_memset, because plain
1108dd4bdcdSmrg // memset might be intercepted (e.g., actually be __asan_memset).
1118dd4bdcdSmrg // Defining this so the compiler initializes each field, e.g.:
1128dd4bdcdSmrg // BlockingMutex::BlockingMutex() : BlockingMutex(LINKER_INITIALIZED) {}
1138dd4bdcdSmrg // might result in the compiler generating a call to memset, which would
1148dd4bdcdSmrg // have the same problem.
1158dd4bdcdSmrg internal_memset(this, 0, sizeof(*this));
1168dd4bdcdSmrg }
1178dd4bdcdSmrg
Lock()1188dd4bdcdSmrg void BlockingMutex::Lock() {
1198dd4bdcdSmrg CHECK_EQ(owner_, 0);
1208dd4bdcdSmrg atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
1218dd4bdcdSmrg if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
1228dd4bdcdSmrg return;
1238dd4bdcdSmrg while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) {
1248dd4bdcdSmrg zx_status_t status = _zx_futex_wait(reinterpret_cast<zx_futex_t *>(m),
1258dd4bdcdSmrg MtxSleeping, ZX_TIME_INFINITE);
1268dd4bdcdSmrg if (status != ZX_ERR_BAD_STATE) // Normal race.
1278dd4bdcdSmrg CHECK_EQ(status, ZX_OK);
1288dd4bdcdSmrg }
1298dd4bdcdSmrg }
1308dd4bdcdSmrg
Unlock()1318dd4bdcdSmrg void BlockingMutex::Unlock() {
1328dd4bdcdSmrg atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
1338dd4bdcdSmrg u32 v = atomic_exchange(m, MtxUnlocked, memory_order_release);
1348dd4bdcdSmrg CHECK_NE(v, MtxUnlocked);
1358dd4bdcdSmrg if (v == MtxSleeping) {
1368dd4bdcdSmrg zx_status_t status = _zx_futex_wake(reinterpret_cast<zx_futex_t *>(m), 1);
1378dd4bdcdSmrg CHECK_EQ(status, ZX_OK);
1388dd4bdcdSmrg }
1398dd4bdcdSmrg }
1408dd4bdcdSmrg
CheckLocked()1418dd4bdcdSmrg void BlockingMutex::CheckLocked() {
1428dd4bdcdSmrg atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
1438dd4bdcdSmrg CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
1448dd4bdcdSmrg }
1458dd4bdcdSmrg
GetPageSize()1468dd4bdcdSmrg uptr GetPageSize() { return PAGE_SIZE; }
1478dd4bdcdSmrg
GetMmapGranularity()1488dd4bdcdSmrg uptr GetMmapGranularity() { return PAGE_SIZE; }
1498dd4bdcdSmrg
1508dd4bdcdSmrg sanitizer_shadow_bounds_t ShadowBounds;
1518dd4bdcdSmrg
GetMaxUserVirtualAddress()152*760c2415Smrg uptr GetMaxUserVirtualAddress() {
1538dd4bdcdSmrg ShadowBounds = __sanitizer_shadow_bounds();
1548dd4bdcdSmrg return ShadowBounds.memory_limit - 1;
1558dd4bdcdSmrg }
1568dd4bdcdSmrg
GetMaxVirtualAddress()157*760c2415Smrg uptr GetMaxVirtualAddress() { return GetMaxUserVirtualAddress(); }
158*760c2415Smrg
DoAnonymousMmapOrDie(uptr size,const char * mem_type,bool raw_report,bool die_for_nomem)1598dd4bdcdSmrg static void *DoAnonymousMmapOrDie(uptr size, const char *mem_type,
1608dd4bdcdSmrg bool raw_report, bool die_for_nomem) {
1618dd4bdcdSmrg size = RoundUpTo(size, PAGE_SIZE);
1628dd4bdcdSmrg
1638dd4bdcdSmrg zx_handle_t vmo;
1648dd4bdcdSmrg zx_status_t status = _zx_vmo_create(size, 0, &vmo);
1658dd4bdcdSmrg if (status != ZX_OK) {
1668dd4bdcdSmrg if (status != ZX_ERR_NO_MEMORY || die_for_nomem)
1678dd4bdcdSmrg ReportMmapFailureAndDie(size, mem_type, "zx_vmo_create", status,
1688dd4bdcdSmrg raw_report);
1698dd4bdcdSmrg return nullptr;
1708dd4bdcdSmrg }
1718dd4bdcdSmrg _zx_object_set_property(vmo, ZX_PROP_NAME, mem_type,
1728dd4bdcdSmrg internal_strlen(mem_type));
1738dd4bdcdSmrg
1748dd4bdcdSmrg // TODO(mcgrathr): Maybe allocate a VMAR for all sanitizer heap and use that?
1758dd4bdcdSmrg uintptr_t addr;
176*760c2415Smrg status =
177*760c2415Smrg _zx_vmar_map(_zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0,
178*760c2415Smrg vmo, 0, size, &addr);
1798dd4bdcdSmrg _zx_handle_close(vmo);
1808dd4bdcdSmrg
1818dd4bdcdSmrg if (status != ZX_OK) {
1828dd4bdcdSmrg if (status != ZX_ERR_NO_MEMORY || die_for_nomem)
1838dd4bdcdSmrg ReportMmapFailureAndDie(size, mem_type, "zx_vmar_map", status,
1848dd4bdcdSmrg raw_report);
1858dd4bdcdSmrg return nullptr;
1868dd4bdcdSmrg }
1878dd4bdcdSmrg
1888dd4bdcdSmrg IncreaseTotalMmap(size);
1898dd4bdcdSmrg
1908dd4bdcdSmrg return reinterpret_cast<void *>(addr);
1918dd4bdcdSmrg }
1928dd4bdcdSmrg
MmapOrDie(uptr size,const char * mem_type,bool raw_report)1938dd4bdcdSmrg void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
1948dd4bdcdSmrg return DoAnonymousMmapOrDie(size, mem_type, raw_report, true);
1958dd4bdcdSmrg }
1968dd4bdcdSmrg
MmapNoReserveOrDie(uptr size,const char * mem_type)1978dd4bdcdSmrg void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
1988dd4bdcdSmrg return MmapOrDie(size, mem_type);
1998dd4bdcdSmrg }
2008dd4bdcdSmrg
MmapOrDieOnFatalError(uptr size,const char * mem_type)2018dd4bdcdSmrg void *MmapOrDieOnFatalError(uptr size, const char *mem_type) {
2028dd4bdcdSmrg return DoAnonymousMmapOrDie(size, mem_type, false, false);
2038dd4bdcdSmrg }
2048dd4bdcdSmrg
Init(uptr init_size,const char * name,uptr fixed_addr)205*760c2415Smrg uptr ReservedAddressRange::Init(uptr init_size, const char *name,
206*760c2415Smrg uptr fixed_addr) {
207*760c2415Smrg init_size = RoundUpTo(init_size, PAGE_SIZE);
208*760c2415Smrg DCHECK_EQ(os_handle_, ZX_HANDLE_INVALID);
2098dd4bdcdSmrg uintptr_t base;
210*760c2415Smrg zx_handle_t vmar;
2118dd4bdcdSmrg zx_status_t status =
212*760c2415Smrg _zx_vmar_allocate_old(_zx_vmar_root_self(), 0, init_size,
2138dd4bdcdSmrg ZX_VM_FLAG_CAN_MAP_READ | ZX_VM_FLAG_CAN_MAP_WRITE |
2148dd4bdcdSmrg ZX_VM_FLAG_CAN_MAP_SPECIFIC,
215*760c2415Smrg &vmar, &base);
2168dd4bdcdSmrg if (status != ZX_OK)
217*760c2415Smrg ReportMmapFailureAndDie(init_size, name, "zx_vmar_allocate", status);
218*760c2415Smrg base_ = reinterpret_cast<void *>(base);
219*760c2415Smrg size_ = init_size;
220*760c2415Smrg name_ = name;
221*760c2415Smrg os_handle_ = vmar;
2228dd4bdcdSmrg
223*760c2415Smrg return reinterpret_cast<uptr>(base_);
2248dd4bdcdSmrg }
2258dd4bdcdSmrg
DoMmapFixedOrDie(zx_handle_t vmar,uptr fixed_addr,uptr map_size,void * base,const char * name,bool die_for_nomem)226*760c2415Smrg static uptr DoMmapFixedOrDie(zx_handle_t vmar, uptr fixed_addr, uptr map_size,
227*760c2415Smrg void *base, const char *name, bool die_for_nomem) {
228*760c2415Smrg uptr offset = fixed_addr - reinterpret_cast<uptr>(base);
229*760c2415Smrg map_size = RoundUpTo(map_size, PAGE_SIZE);
2308dd4bdcdSmrg zx_handle_t vmo;
231*760c2415Smrg zx_status_t status = _zx_vmo_create(map_size, 0, &vmo);
2328dd4bdcdSmrg if (status != ZX_OK) {
2338dd4bdcdSmrg if (status != ZX_ERR_NO_MEMORY || die_for_nomem)
234*760c2415Smrg ReportMmapFailureAndDie(map_size, name, "zx_vmo_create", status);
235*760c2415Smrg return 0;
2368dd4bdcdSmrg }
237*760c2415Smrg _zx_object_set_property(vmo, ZX_PROP_NAME, name, internal_strlen(name));
238*760c2415Smrg DCHECK_GE(base + size_, map_size + offset);
2398dd4bdcdSmrg uintptr_t addr;
240*760c2415Smrg
241*760c2415Smrg status =
242*760c2415Smrg _zx_vmar_map(vmar, ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_SPECIFIC,
243*760c2415Smrg offset, vmo, 0, map_size, &addr);
2448dd4bdcdSmrg _zx_handle_close(vmo);
2458dd4bdcdSmrg if (status != ZX_OK) {
246*760c2415Smrg if (status != ZX_ERR_NO_MEMORY || die_for_nomem) {
247*760c2415Smrg ReportMmapFailureAndDie(map_size, name, "zx_vmar_map", status);
248*760c2415Smrg }
249*760c2415Smrg return 0;
250*760c2415Smrg }
251*760c2415Smrg IncreaseTotalMmap(map_size);
252*760c2415Smrg return addr;
2538dd4bdcdSmrg }
2548dd4bdcdSmrg
Map(uptr fixed_addr,uptr map_size)255*760c2415Smrg uptr ReservedAddressRange::Map(uptr fixed_addr, uptr map_size) {
256*760c2415Smrg return DoMmapFixedOrDie(os_handle_, fixed_addr, map_size, base_,
257*760c2415Smrg name_, false);
2588dd4bdcdSmrg }
2598dd4bdcdSmrg
MapOrDie(uptr fixed_addr,uptr map_size)260*760c2415Smrg uptr ReservedAddressRange::MapOrDie(uptr fixed_addr, uptr map_size) {
261*760c2415Smrg return DoMmapFixedOrDie(os_handle_, fixed_addr, map_size, base_,
262*760c2415Smrg name_, true);
2638dd4bdcdSmrg }
2648dd4bdcdSmrg
UnmapOrDieVmar(void * addr,uptr size,zx_handle_t target_vmar)265*760c2415Smrg void UnmapOrDieVmar(void *addr, uptr size, zx_handle_t target_vmar) {
266*760c2415Smrg if (!addr || !size) return;
267*760c2415Smrg size = RoundUpTo(size, PAGE_SIZE);
268*760c2415Smrg
269*760c2415Smrg zx_status_t status =
270*760c2415Smrg _zx_vmar_unmap(target_vmar, reinterpret_cast<uintptr_t>(addr), size);
271*760c2415Smrg if (status != ZX_OK) {
272*760c2415Smrg Report("ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p\n",
273*760c2415Smrg SanitizerToolName, size, size, addr);
274*760c2415Smrg CHECK("unable to unmap" && 0);
275*760c2415Smrg }
276*760c2415Smrg
277*760c2415Smrg DecreaseTotalMmap(size);
278*760c2415Smrg }
279*760c2415Smrg
Unmap(uptr addr,uptr size)280*760c2415Smrg void ReservedAddressRange::Unmap(uptr addr, uptr size) {
281*760c2415Smrg CHECK_LE(size, size_);
282*760c2415Smrg const zx_handle_t vmar = static_cast<zx_handle_t>(os_handle_);
283*760c2415Smrg if (addr == reinterpret_cast<uptr>(base_)) {
284*760c2415Smrg if (size == size_) {
285*760c2415Smrg // Destroying the vmar effectively unmaps the whole mapping.
286*760c2415Smrg _zx_vmar_destroy(vmar);
287*760c2415Smrg _zx_handle_close(vmar);
288*760c2415Smrg os_handle_ = static_cast<uptr>(ZX_HANDLE_INVALID);
289*760c2415Smrg DecreaseTotalMmap(size);
290*760c2415Smrg return;
291*760c2415Smrg }
292*760c2415Smrg } else {
293*760c2415Smrg CHECK_EQ(addr + size, reinterpret_cast<uptr>(base_) + size_);
294*760c2415Smrg }
295*760c2415Smrg // Partial unmapping does not affect the fact that the initial range is still
296*760c2415Smrg // reserved, and the resulting unmapped memory can't be reused.
297*760c2415Smrg UnmapOrDieVmar(reinterpret_cast<void *>(addr), size, vmar);
2988dd4bdcdSmrg }
2998dd4bdcdSmrg
3008dd4bdcdSmrg // This should never be called.
MmapFixedNoAccess(uptr fixed_addr,uptr size,const char * name)3018dd4bdcdSmrg void *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name) {
3028dd4bdcdSmrg UNIMPLEMENTED();
3038dd4bdcdSmrg }
3048dd4bdcdSmrg
MmapAlignedOrDieOnFatalError(uptr size,uptr alignment,const char * mem_type)3058dd4bdcdSmrg void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
3068dd4bdcdSmrg const char *mem_type) {
3078dd4bdcdSmrg CHECK_GE(size, PAGE_SIZE);
3088dd4bdcdSmrg CHECK(IsPowerOfTwo(size));
3098dd4bdcdSmrg CHECK(IsPowerOfTwo(alignment));
3108dd4bdcdSmrg
3118dd4bdcdSmrg zx_handle_t vmo;
3128dd4bdcdSmrg zx_status_t status = _zx_vmo_create(size, 0, &vmo);
3138dd4bdcdSmrg if (status != ZX_OK) {
3148dd4bdcdSmrg if (status != ZX_ERR_NO_MEMORY)
3158dd4bdcdSmrg ReportMmapFailureAndDie(size, mem_type, "zx_vmo_create", status, false);
3168dd4bdcdSmrg return nullptr;
3178dd4bdcdSmrg }
3188dd4bdcdSmrg _zx_object_set_property(vmo, ZX_PROP_NAME, mem_type,
3198dd4bdcdSmrg internal_strlen(mem_type));
3208dd4bdcdSmrg
3218dd4bdcdSmrg // TODO(mcgrathr): Maybe allocate a VMAR for all sanitizer heap and use that?
3228dd4bdcdSmrg
3238dd4bdcdSmrg // Map a larger size to get a chunk of address space big enough that
3248dd4bdcdSmrg // it surely contains an aligned region of the requested size. Then
3258dd4bdcdSmrg // overwrite the aligned middle portion with a mapping from the
3268dd4bdcdSmrg // beginning of the VMO, and unmap the excess before and after.
3278dd4bdcdSmrg size_t map_size = size + alignment;
3288dd4bdcdSmrg uintptr_t addr;
329*760c2415Smrg status =
330*760c2415Smrg _zx_vmar_map(_zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0,
331*760c2415Smrg vmo, 0, map_size, &addr);
3328dd4bdcdSmrg if (status == ZX_OK) {
3338dd4bdcdSmrg uintptr_t map_addr = addr;
3348dd4bdcdSmrg uintptr_t map_end = map_addr + map_size;
3358dd4bdcdSmrg addr = RoundUpTo(map_addr, alignment);
3368dd4bdcdSmrg uintptr_t end = addr + size;
3378dd4bdcdSmrg if (addr != map_addr) {
3388dd4bdcdSmrg zx_info_vmar_t info;
3398dd4bdcdSmrg status = _zx_object_get_info(_zx_vmar_root_self(), ZX_INFO_VMAR, &info,
3408dd4bdcdSmrg sizeof(info), NULL, NULL);
3418dd4bdcdSmrg if (status == ZX_OK) {
3428dd4bdcdSmrg uintptr_t new_addr;
343*760c2415Smrg status = _zx_vmar_map(
344*760c2415Smrg _zx_vmar_root_self(),
345*760c2415Smrg ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_SPECIFIC_OVERWRITE,
346*760c2415Smrg addr - info.base, vmo, 0, size, &new_addr);
3478dd4bdcdSmrg if (status == ZX_OK) CHECK_EQ(new_addr, addr);
3488dd4bdcdSmrg }
3498dd4bdcdSmrg }
3508dd4bdcdSmrg if (status == ZX_OK && addr != map_addr)
3518dd4bdcdSmrg status = _zx_vmar_unmap(_zx_vmar_root_self(), map_addr, addr - map_addr);
3528dd4bdcdSmrg if (status == ZX_OK && end != map_end)
3538dd4bdcdSmrg status = _zx_vmar_unmap(_zx_vmar_root_self(), end, map_end - end);
3548dd4bdcdSmrg }
3558dd4bdcdSmrg _zx_handle_close(vmo);
3568dd4bdcdSmrg
3578dd4bdcdSmrg if (status != ZX_OK) {
3588dd4bdcdSmrg if (status != ZX_ERR_NO_MEMORY)
3598dd4bdcdSmrg ReportMmapFailureAndDie(size, mem_type, "zx_vmar_map", status, false);
3608dd4bdcdSmrg return nullptr;
3618dd4bdcdSmrg }
3628dd4bdcdSmrg
3638dd4bdcdSmrg IncreaseTotalMmap(size);
3648dd4bdcdSmrg
3658dd4bdcdSmrg return reinterpret_cast<void *>(addr);
3668dd4bdcdSmrg }
3678dd4bdcdSmrg
UnmapOrDie(void * addr,uptr size)3688dd4bdcdSmrg void UnmapOrDie(void *addr, uptr size) {
369*760c2415Smrg UnmapOrDieVmar(addr, size, _zx_vmar_root_self());
3708dd4bdcdSmrg }
3718dd4bdcdSmrg
3728dd4bdcdSmrg // This is used on the shadow mapping, which cannot be changed.
3738dd4bdcdSmrg // Zircon doesn't have anything like MADV_DONTNEED.
ReleaseMemoryPagesToOS(uptr beg,uptr end)3748dd4bdcdSmrg void ReleaseMemoryPagesToOS(uptr beg, uptr end) {}
3758dd4bdcdSmrg
DumpProcessMap()3768dd4bdcdSmrg void DumpProcessMap() {
377*760c2415Smrg // TODO(mcgrathr): write it
378*760c2415Smrg return;
3798dd4bdcdSmrg }
3808dd4bdcdSmrg
IsAccessibleMemoryRange(uptr beg,uptr size)3818dd4bdcdSmrg bool IsAccessibleMemoryRange(uptr beg, uptr size) {
3828dd4bdcdSmrg // TODO(mcgrathr): Figure out a better way.
3838dd4bdcdSmrg zx_handle_t vmo;
3848dd4bdcdSmrg zx_status_t status = _zx_vmo_create(size, 0, &vmo);
3858dd4bdcdSmrg if (status == ZX_OK) {
386*760c2415Smrg status = _zx_vmo_write(vmo, reinterpret_cast<const void *>(beg), 0, size);
3878dd4bdcdSmrg _zx_handle_close(vmo);
3888dd4bdcdSmrg }
3898dd4bdcdSmrg return status == ZX_OK;
3908dd4bdcdSmrg }
3918dd4bdcdSmrg
3928dd4bdcdSmrg // FIXME implement on this platform.
GetMemoryProfile(fill_profile_f cb,uptr * stats,uptr stats_size)3938dd4bdcdSmrg void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) {}
3948dd4bdcdSmrg
ReadFileToBuffer(const char * file_name,char ** buff,uptr * buff_size,uptr * read_len,uptr max_len,error_t * errno_p)3958dd4bdcdSmrg bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
3968dd4bdcdSmrg uptr *read_len, uptr max_len, error_t *errno_p) {
3978dd4bdcdSmrg zx_handle_t vmo;
3988dd4bdcdSmrg zx_status_t status = __sanitizer_get_configuration(file_name, &vmo);
3998dd4bdcdSmrg if (status == ZX_OK) {
4008dd4bdcdSmrg uint64_t vmo_size;
4018dd4bdcdSmrg status = _zx_vmo_get_size(vmo, &vmo_size);
4028dd4bdcdSmrg if (status == ZX_OK) {
4038dd4bdcdSmrg if (vmo_size < max_len) max_len = vmo_size;
4048dd4bdcdSmrg size_t map_size = RoundUpTo(max_len, PAGE_SIZE);
4058dd4bdcdSmrg uintptr_t addr;
406*760c2415Smrg status = _zx_vmar_map(_zx_vmar_root_self(), ZX_VM_PERM_READ, 0, vmo, 0,
407*760c2415Smrg map_size, &addr);
4088dd4bdcdSmrg if (status == ZX_OK) {
4098dd4bdcdSmrg *buff = reinterpret_cast<char *>(addr);
4108dd4bdcdSmrg *buff_size = map_size;
4118dd4bdcdSmrg *read_len = max_len;
4128dd4bdcdSmrg }
4138dd4bdcdSmrg }
4148dd4bdcdSmrg _zx_handle_close(vmo);
4158dd4bdcdSmrg }
4168dd4bdcdSmrg if (status != ZX_OK && errno_p) *errno_p = status;
4178dd4bdcdSmrg return status == ZX_OK;
4188dd4bdcdSmrg }
4198dd4bdcdSmrg
RawWrite(const char * buffer)4208dd4bdcdSmrg void RawWrite(const char *buffer) {
421*760c2415Smrg constexpr size_t size = 128;
422*760c2415Smrg static _Thread_local char line[size];
423*760c2415Smrg static _Thread_local size_t lastLineEnd = 0;
424*760c2415Smrg static _Thread_local size_t cur = 0;
425*760c2415Smrg
426*760c2415Smrg while (*buffer) {
427*760c2415Smrg if (cur >= size) {
428*760c2415Smrg if (lastLineEnd == 0)
429*760c2415Smrg lastLineEnd = size;
430*760c2415Smrg __sanitizer_log_write(line, lastLineEnd);
431*760c2415Smrg internal_memmove(line, line + lastLineEnd, cur - lastLineEnd);
432*760c2415Smrg cur = cur - lastLineEnd;
433*760c2415Smrg lastLineEnd = 0;
434*760c2415Smrg }
435*760c2415Smrg if (*buffer == '\n')
436*760c2415Smrg lastLineEnd = cur + 1;
437*760c2415Smrg line[cur++] = *buffer++;
438*760c2415Smrg }
439*760c2415Smrg // Flush all complete lines before returning.
440*760c2415Smrg if (lastLineEnd != 0) {
441*760c2415Smrg __sanitizer_log_write(line, lastLineEnd);
442*760c2415Smrg internal_memmove(line, line + lastLineEnd, cur - lastLineEnd);
443*760c2415Smrg cur = cur - lastLineEnd;
444*760c2415Smrg lastLineEnd = 0;
445*760c2415Smrg }
4468dd4bdcdSmrg }
4478dd4bdcdSmrg
CatastrophicErrorWrite(const char * buffer,uptr length)4488dd4bdcdSmrg void CatastrophicErrorWrite(const char *buffer, uptr length) {
4498dd4bdcdSmrg __sanitizer_log_write(buffer, length);
4508dd4bdcdSmrg }
4518dd4bdcdSmrg
4528dd4bdcdSmrg char **StoredArgv;
4538dd4bdcdSmrg char **StoredEnviron;
4548dd4bdcdSmrg
GetArgv()4558dd4bdcdSmrg char **GetArgv() { return StoredArgv; }
4568dd4bdcdSmrg
GetEnv(const char * name)4578dd4bdcdSmrg const char *GetEnv(const char *name) {
4588dd4bdcdSmrg if (StoredEnviron) {
4598dd4bdcdSmrg uptr NameLen = internal_strlen(name);
4608dd4bdcdSmrg for (char **Env = StoredEnviron; *Env != 0; Env++) {
4618dd4bdcdSmrg if (internal_strncmp(*Env, name, NameLen) == 0 && (*Env)[NameLen] == '=')
4628dd4bdcdSmrg return (*Env) + NameLen + 1;
4638dd4bdcdSmrg }
4648dd4bdcdSmrg }
4658dd4bdcdSmrg return nullptr;
4668dd4bdcdSmrg }
4678dd4bdcdSmrg
ReadBinaryName(char * buf,uptr buf_len)4688dd4bdcdSmrg uptr ReadBinaryName(/*out*/ char *buf, uptr buf_len) {
469*760c2415Smrg const char *argv0 = "<UNKNOWN>";
470*760c2415Smrg if (StoredArgv && StoredArgv[0]) {
471*760c2415Smrg argv0 = StoredArgv[0];
472*760c2415Smrg }
4738dd4bdcdSmrg internal_strncpy(buf, argv0, buf_len);
4748dd4bdcdSmrg return internal_strlen(buf);
4758dd4bdcdSmrg }
4768dd4bdcdSmrg
ReadLongProcessName(char * buf,uptr buf_len)4778dd4bdcdSmrg uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) {
4788dd4bdcdSmrg return ReadBinaryName(buf, buf_len);
4798dd4bdcdSmrg }
4808dd4bdcdSmrg
4818dd4bdcdSmrg uptr MainThreadStackBase, MainThreadStackSize;
4828dd4bdcdSmrg
GetRandom(void * buffer,uptr length,bool blocking)4838dd4bdcdSmrg bool GetRandom(void *buffer, uptr length, bool blocking) {
4848dd4bdcdSmrg CHECK_LE(length, ZX_CPRNG_DRAW_MAX_LEN);
485*760c2415Smrg _zx_cprng_draw(buffer, length);
4868dd4bdcdSmrg return true;
4878dd4bdcdSmrg }
4888dd4bdcdSmrg
GetNumberOfCPUs()489*760c2415Smrg u32 GetNumberOfCPUs() {
490*760c2415Smrg return zx_system_get_num_cpus();
491*760c2415Smrg }
492*760c2415Smrg
GetRSS()493*760c2415Smrg uptr GetRSS() { UNIMPLEMENTED(); }
494*760c2415Smrg
4958dd4bdcdSmrg } // namespace __sanitizer
4968dd4bdcdSmrg
4978dd4bdcdSmrg using namespace __sanitizer; // NOLINT
4988dd4bdcdSmrg
4998dd4bdcdSmrg extern "C" {
__sanitizer_startup_hook(int argc,char ** argv,char ** envp,void * stack_base,size_t stack_size)5008dd4bdcdSmrg void __sanitizer_startup_hook(int argc, char **argv, char **envp,
5018dd4bdcdSmrg void *stack_base, size_t stack_size) {
5028dd4bdcdSmrg __sanitizer::StoredArgv = argv;
5038dd4bdcdSmrg __sanitizer::StoredEnviron = envp;
5048dd4bdcdSmrg __sanitizer::MainThreadStackBase = reinterpret_cast<uintptr_t>(stack_base);
5058dd4bdcdSmrg __sanitizer::MainThreadStackSize = stack_size;
5068dd4bdcdSmrg }
5078dd4bdcdSmrg
__sanitizer_set_report_path(const char * path)5088dd4bdcdSmrg void __sanitizer_set_report_path(const char *path) {
5098dd4bdcdSmrg // Handle the initialization code in each sanitizer, but no other calls.
5108dd4bdcdSmrg // This setting is never consulted on Fuchsia.
5118dd4bdcdSmrg DCHECK_EQ(path, common_flags()->log_path);
5128dd4bdcdSmrg }
5138dd4bdcdSmrg
__sanitizer_set_report_fd(void * fd)5148dd4bdcdSmrg void __sanitizer_set_report_fd(void *fd) {
5158dd4bdcdSmrg UNREACHABLE("not available on Fuchsia");
5168dd4bdcdSmrg }
5178dd4bdcdSmrg } // extern "C"
5188dd4bdcdSmrg
5198dd4bdcdSmrg #endif // SANITIZER_FUCHSIA
520