1ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//===-- sanitizer_mac.cc --------------------------------------------------===//
2ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
3ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//                     The LLVM Compiler Infrastructure
4ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
5ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// This file is distributed under the University of Illinois Open Source
6ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// License. See LICENSE.TXT for details.
7ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
8ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//===----------------------------------------------------------------------===//
9ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
10ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// This file is shared between AddressSanitizer and ThreadSanitizer
11ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// run-time libraries and implements mac-specific functions from
12ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// sanitizer_libc.h.
13ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//===----------------------------------------------------------------------===//
14ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
1524e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#include "sanitizer_platform.h"
1624e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_MAC
1724e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov
182bf0d0332d3bb8b007e10ef14429279e12405262Alexander Potapenko// Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so
192bf0d0332d3bb8b007e10ef14429279e12405262Alexander Potapenko// the clients will most certainly use 64-bit ones as well.
202bf0d0332d3bb8b007e10ef14429279e12405262Alexander Potapenko#ifndef _DARWIN_USE_64_BIT_INODE
212bf0d0332d3bb8b007e10ef14429279e12405262Alexander Potapenko#define _DARWIN_USE_64_BIT_INODE 1
222bf0d0332d3bb8b007e10ef14429279e12405262Alexander Potapenko#endif
232bf0d0332d3bb8b007e10ef14429279e12405262Alexander Potapenko#include <stdio.h>
24ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
25e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include "sanitizer_common.h"
2694b5036ee6ba866e1702848855b6d687d1e70afaAlexey Samsonov#include "sanitizer_internal_defs.h"
27ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include "sanitizer_libc.h"
286895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_procmaps.h"
29ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
303dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov#include <crt_externs.h>  // for _NSGetEnviron
31e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <fcntl.h>
326895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include <mach-o/dyld.h>
336895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include <mach-o/loader.h>
34e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <pthread.h>
350969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov#include <sched.h>
36ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/mman.h>
37e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/resource.h>
38c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <sys/stat.h>
39c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <sys/types.h>
40a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov#include <unistd.h>
4148526014de78e21f7ed027a60670016bc7f5d292Dmitry Vyukov#include <libkern/OSAtomic.h>
4265246dc7e77c4e089898a1f15ead65f6087795efPeter Collingbourne#include <errno.h>
43ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
44ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovnamespace __sanitizer {
45ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
469578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne#include "sanitizer_syscall_generic.inc"
479578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne
48e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ---------------------- sanitizer_libc.h
4965246dc7e77c4e089898a1f15ead65f6087795efPeter Collingbourneuptr internal_mmap(void *addr, size_t length, int prot, int flags,
5065246dc7e77c4e089898a1f15ead65f6087795efPeter Collingbourne                   int fd, u64 offset) {
5165246dc7e77c4e089898a1f15ead65f6087795efPeter Collingbourne  return (uptr)mmap(addr, length, prot, flags, fd, offset);
52ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov}
53ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
5465246dc7e77c4e089898a1f15ead65f6087795efPeter Collingbourneuptr internal_munmap(void *addr, uptr length) {
551f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov  return munmap(addr, length);
561f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov}
571f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov
589578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_close(fd_t fd) {
59a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov  return close(fd);
60a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
61a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
629578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags) {
63ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov  return open(filename, flags);
64ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov}
65ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov
669578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_open(const char *filename, int flags, u32 mode) {
67ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov  return open(filename, flags, mode);
68ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov}
69ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov
709578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr OpenFile(const char *filename, bool write) {
71ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov  return internal_open(filename,
72ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov      write ? O_WRONLY | O_CREAT : O_RDONLY, 0660);
73c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov}
74c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov
75a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_read(fd_t fd, void *buf, uptr count) {
76a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov  return read(fd, buf, count);
77a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
78a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
79a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_write(fd_t fd, const void *buf, uptr count) {
80a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov  return write(fd, buf, count);
81a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
82a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
839578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_stat(const char *path, void *buf) {
847c50ee7dd9f2d6a0ed75c27e05b08534908a905aAlexey Samsonov  return stat(path, (struct stat *)buf);
854c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
864c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
879578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_lstat(const char *path, void *buf) {
887c50ee7dd9f2d6a0ed75c27e05b08534908a905aAlexey Samsonov  return lstat(path, (struct stat *)buf);
894c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
904c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
919578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_fstat(fd_t fd, void *buf) {
927c50ee7dd9f2d6a0ed75c27e05b08534908a905aAlexey Samsonov  return fstat(fd, (struct stat *)buf);
934c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov}
944c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov
958e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovuptr internal_filesize(fd_t fd) {
96668accc51f93df21fb0273d2ff10f7c86e757813Alexey Samsonov  struct stat st;
974c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov  if (internal_fstat(fd, &st))
988e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov    return -1;
998e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov  return (uptr)st.st_size;
1008e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
1018e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
1029578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_dup2(int oldfd, int newfd) {
1038e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov  return dup2(oldfd, newfd);
1048e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
1058e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
106d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonovuptr internal_readlink(const char *path, char *buf, uptr bufsize) {
107d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov  return readlink(path, buf, bufsize);
108d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov}
109d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov
1109578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourneuptr internal_sched_yield() {
1110969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov  return sched_yield();
1120969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov}
1130969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov
114f882247088952deed954a19d745c2dd8871e2035Alexey Samsonovvoid internal__exit(int exitcode) {
115f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov  _exit(exitcode);
116f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov}
117f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov
1180b694fcab9b2f33bdd6691cbea4e80a5c27191b1Peter Collingbourneuptr internal_getpid() {
1190b694fcab9b2f33bdd6691cbea4e80a5c27191b1Peter Collingbourne  return getpid();
1200b694fcab9b2f33bdd6691cbea4e80a5c27191b1Peter Collingbourne}
1210b694fcab9b2f33bdd6691cbea4e80a5c27191b1Peter Collingbourne
122e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_common.h
12393b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonovbool FileExists(const char *filename) {
12493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  struct stat st;
12593b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  if (stat(filename, &st))
12693b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov    return false;
12793b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  // Sanity check: filename is a regular file.
12893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  return S_ISREG(st.st_mode);
12993b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov}
13093b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov
131e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukovuptr GetTid() {
132e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov  return reinterpret_cast<uptr>(pthread_self());
133e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov}
134e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov
135ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonovvoid GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
136e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov                                uptr *stack_bottom) {
137e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  CHECK(stack_top);
138e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  CHECK(stack_bottom);
139e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  uptr stacksize = pthread_get_stacksize_np(pthread_self());
140e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  void *stackaddr = pthread_get_stackaddr_np(pthread_self());
141e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  *stack_top = (uptr)stackaddr;
142ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonov  *stack_bottom = *stack_top - stacksize;
143e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov}
144e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov
1453dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonovconst char *GetEnv(const char *name) {
1463dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  char ***env_ptr = _NSGetEnviron();
1473dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  CHECK(env_ptr);
1483dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  char **environ = *env_ptr;
1493dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  CHECK(environ);
1503dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  uptr name_len = internal_strlen(name);
1513dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  while (*environ != 0) {
1523dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    uptr len = internal_strlen(*environ);
1533dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    if (len > name_len) {
1543dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov      const char *p = *environ;
1553dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov      if (!internal_memcmp(p, name, name_len) &&
1563dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov          p[name_len] == '=') {  // Match.
1573dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov        return *environ + name_len + 1;  // String starting after =.
1583dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov      }
1593dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    }
1603dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    environ++;
1613dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  }
1623dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  return 0;
1633dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov}
164e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov
165d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonovvoid ReExec() {
166d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  UNIMPLEMENTED();
167d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov}
168d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov
16925742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenkovoid PrepareForSandboxing() {
17025742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko  // Nothing here for now.
17125742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko}
17225742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko
1734df343a31cf57c309cf102b9aef870458318f579Peter Collingbourneuptr GetPageSize() {
1744df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne  return sysconf(_SC_PAGESIZE);
1754df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne}
1764df343a31cf57c309cf102b9aef870458318f579Peter Collingbourne
177e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_procmaps.h
1786895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
1799ae2883d88dd28b9c5dc862107e6e6d12a35926eAlexander PotapenkoMemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
1806895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  Reset();
1816895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
1826895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
183e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey SamsonovMemoryMappingLayout::~MemoryMappingLayout() {
1846895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
1856895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
1866895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// More information about Mach-O headers can be found in mach-o/loader.h
1876895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Each Mach-O image has a header (mach_header or mach_header_64) starting with
1886895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// a magic number, and a list of linker load commands directly following the
1896895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// header.
1906895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// A load command is at least two 32-bit words: the command type and the
1916895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// command size in bytes. We're interested only in segment load commands
1926895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// (LC_SEGMENT and LC_SEGMENT_64), which tell that a part of the file is mapped
1936895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// into the task's address space.
1946895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// The |vmaddr|, |vmsize| and |fileoff| fields of segment_command or
1956895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// segment_command_64 correspond to the memory address, memory size and the
1966895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// file offset of the current memory segment.
1976895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Because these fields are taken from the images as is, one needs to add
1986895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// _dyld_get_image_vmaddr_slide() to get the actual addresses at runtime.
1996895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
200e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovvoid MemoryMappingLayout::Reset() {
2016895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // Count down from the top.
2026895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // TODO(glider): as per man 3 dyld, iterating over the headers with
2036895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // _dyld_image_count is thread-unsafe. We need to register callbacks for
204e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov  // adding and removing images which will invalidate the MemoryMappingLayout
205e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov  // state.
2066895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  current_image_ = _dyld_image_count();
2076895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  current_load_cmd_count_ = -1;
2086895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  current_load_cmd_addr_ = 0;
2096895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  current_magic_ = 0;
2108bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko  current_filetype_ = 0;
2116895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
2126895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
21393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko// static
21493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::CacheMemoryMappings() {
21593da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  // No-op on Mac for now.
21693da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko}
21793da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko
21893da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::LoadFromCache() {
21993da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  // No-op on Mac for now.
22093da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko}
22193da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko
2226895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Next and NextSegmentLoad were inspired by base/sysinfo.cc in
2236895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Google Perftools, http://code.google.com/p/google-perftools.
2246895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
2256895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// NextSegmentLoad scans the current image for the next segment load command
2266895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// and returns the start and end addresses and file offset of the corresponding
2276895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// segment.
2286895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Note that the segment addresses are not necessarily sorted.
2296895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonovtemplate<u32 kLCSegment, typename SegmentCommand>
230e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::NextSegmentLoad(
2316895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    uptr *start, uptr *end, uptr *offset,
23245717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov    char filename[], uptr filename_size, uptr *protection) {
23345717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  if (protection)
23445717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov    UNIMPLEMENTED();
2356895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  const char* lc = current_load_cmd_addr_;
2366895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  current_load_cmd_addr_ += ((const load_command *)lc)->cmdsize;
2376895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (((const load_command *)lc)->cmd == kLCSegment) {
2386895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    const sptr dlloff = _dyld_get_image_vmaddr_slide(current_image_);
2396895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    const SegmentCommand* sc = (const SegmentCommand *)lc;
2406895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    if (start) *start = sc->vmaddr + dlloff;
2416895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    if (end) *end = sc->vmaddr + sc->vmsize + dlloff;
2428bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko    if (offset) {
2438bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko      if (current_filetype_ == /*MH_EXECUTE*/ 0x2) {
2448bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko        *offset = sc->vmaddr;
2458bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko      } else {
2468bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko        *offset = sc->fileoff;
2478bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko      }
2488bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko    }
2496895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    if (filename) {
2506895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      internal_strncpy(filename, _dyld_get_image_name(current_image_),
2516895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov                       filename_size);
2526895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    }
2536895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    return true;
2546895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  }
2556895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  return false;
2566895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
2576895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
258e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
2594a1a495f29b63d44e012f6edcee6307ddac253efAlexey Samsonov                               char filename[], uptr filename_size,
2604a1a495f29b63d44e012f6edcee6307ddac253efAlexey Samsonov                               uptr *protection) {
2616895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  for (; current_image_ >= 0; current_image_--) {
2626895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    const mach_header* hdr = _dyld_get_image_header(current_image_);
2636895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    if (!hdr) continue;
2646895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    if (current_load_cmd_count_ < 0) {
2656895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      // Set up for this image;
2666895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      current_load_cmd_count_ = hdr->ncmds;
2676895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      current_magic_ = hdr->magic;
2688bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko      current_filetype_ = hdr->filetype;
2696895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      switch (current_magic_) {
2706895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#ifdef MH_MAGIC_64
2716895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        case MH_MAGIC_64: {
2726895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov          current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header_64);
2736895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov          break;
2746895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        }
2756895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#endif
2766895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        case MH_MAGIC: {
2776895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov          current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header);
2786895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov          break;
2796895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        }
2806895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        default: {
2816895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov          continue;
2826895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        }
2836895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      }
2846895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    }
2856895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
2866895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    for (; current_load_cmd_count_ >= 0; current_load_cmd_count_--) {
2876895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      switch (current_magic_) {
2886895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        // current_magic_ may be only one of MH_MAGIC, MH_MAGIC_64.
2896895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#ifdef MH_MAGIC_64
2906895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        case MH_MAGIC_64: {
2916895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov          if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>(
2924a1a495f29b63d44e012f6edcee6307ddac253efAlexey Samsonov                  start, end, offset, filename, filename_size, protection))
2936895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov            return true;
2946895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov          break;
2956895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        }
2966895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#endif
2976895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        case MH_MAGIC: {
2986895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov          if (NextSegmentLoad<LC_SEGMENT, struct segment_command>(
2994a1a495f29b63d44e012f6edcee6307ddac253efAlexey Samsonov                  start, end, offset, filename, filename_size, protection))
3006895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov            return true;
3016895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov          break;
3026895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        }
3036895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      }
3046895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    }
3056895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    // If we get here, no more load_cmd's in this image talk about
3066895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    // segments.  Go on to the next image.
3076895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  }
3086895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  return false;
3096895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
3106895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
311e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset,
312e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov                                                 char filename[],
3134a1a495f29b63d44e012f6edcee6307ddac253efAlexey Samsonov                                                 uptr filename_size,
31445717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov                                                 uptr *protection) {
31545717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov  return IterateForObjectNameAndOffset(addr, offset, filename, filename_size,
31645717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov                                       protection);
3176895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
3186895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
319f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry VyukovBlockingMutex::BlockingMutex(LinkerInitialized) {
320f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  // We assume that OS_SPINLOCK_INIT is zero
321f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
322f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
32393af5948d3e0c5bdc396f432dd0ae782f499c449Alexey SamsonovBlockingMutex::BlockingMutex() {
32493af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov  internal_memset(this, 0, sizeof(*this));
32593af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov}
32693af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov
327f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Lock() {
328f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_));
329f155fccd1f26f771c9f7f265a4c30faebdfb214fKostya Serebryany  CHECK_EQ(OS_SPINLOCK_INIT, 0);
330f155fccd1f26f771c9f7f265a4c30faebdfb214fKostya Serebryany  CHECK_NE(owner_, (uptr)pthread_self());
331f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  OSSpinLockLock((OSSpinLock*)&opaque_storage_);
332f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  CHECK(!owner_);
333f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  owner_ = (uptr)pthread_self();
334f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
335f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
336f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Unlock() {
337f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  CHECK(owner_ == (uptr)pthread_self());
338f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  owner_ = 0;
339f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov  OSSpinLockUnlock((OSSpinLock*)&opaque_storage_);
340f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov}
341f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov
342ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonovvoid BlockingMutex::CheckLocked() {
343ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov  CHECK_EQ((uptr)pthread_self(), owner_);
344ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov}
345ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov
346d4bb4a6a155eb42b67a584a189f55863893ce4a6Dmitry Vyukovu64 NanoTime() {
347d4bb4a6a155eb42b67a584a189f55863893ce4a6Dmitry Vyukov  return 0;
348d4bb4a6a155eb42b67a584a189f55863893ce4a6Dmitry Vyukov}
349d4bb4a6a155eb42b67a584a189f55863893ce4a6Dmitry Vyukov
350b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovuptr GetTlsSize() {
351b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov  return 0;
352b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov}
353b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov
354b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovvoid InitTlsSize() {
355b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov}
356b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov
35724323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveevvoid GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
35824323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev                          uptr *tls_addr, uptr *tls_size) {
3594a95e33cbfe350c50f6d2c224f7d1b036d680382Dmitry Vyukov#ifndef SANITIZER_GO
36024323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  uptr stack_top, stack_bottom;
36124323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
36224323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  *stk_addr = stack_bottom;
36324323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  *stk_size = stack_top - stack_bottom;
36424323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  *tls_addr = 0;
36524323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev  *tls_size = 0;
3664a95e33cbfe350c50f6d2c224f7d1b036d680382Dmitry Vyukov#else
3674a95e33cbfe350c50f6d2c224f7d1b036d680382Dmitry Vyukov  *stk_addr = 0;
3684a95e33cbfe350c50f6d2c224f7d1b036d680382Dmitry Vyukov  *stk_size = 0;
3694a95e33cbfe350c50f6d2c224f7d1b036d680382Dmitry Vyukov  *tls_addr = 0;
3704a95e33cbfe350c50f6d2c224f7d1b036d680382Dmitry Vyukov  *tls_size = 0;
3714a95e33cbfe350c50f6d2c224f7d1b036d680382Dmitry Vyukov#endif
37224323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev}
37324323de08fa8850712d56621bff29dbbbd0285a9Sergey Matveev
374ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov}  // namespace __sanitizer
375ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
37646f9395baf65e17f1a3f7a3a1deee72a1560ac53Alexey Samsonov#endif  // SANITIZER_MAC
377