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