sanitizer_mac.cc revision e85c83dcee3d35068e6670ab32545953d4330335
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 15ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#ifdef __APPLE__ 16ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 17e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include "sanitizer_common.h" 1894b5036ee6ba866e1702848855b6d687d1e70afaAlexey Samsonov#include "sanitizer_internal_defs.h" 19ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include "sanitizer_libc.h" 206895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_procmaps.h" 21ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 223dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov#include <crt_externs.h> // for _NSGetEnviron 23e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <fcntl.h> 246895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include <mach-o/dyld.h> 256895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include <mach-o/loader.h> 26e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <pthread.h> 270969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov#include <sched.h> 28ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/mman.h> 29e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/resource.h> 30c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <sys/stat.h> 31c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <sys/types.h> 32a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov#include <unistd.h> 3348526014de78e21f7ed027a60670016bc7f5d292Dmitry Vyukov#include <libkern/OSAtomic.h> 34ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 35ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovnamespace __sanitizer { 36ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 37e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ---------------------- sanitizer_libc.h 38ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovvoid *internal_mmap(void *addr, size_t length, int prot, int flags, 39ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov int fd, u64 offset) { 40ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov return mmap(addr, length, prot, flags, fd, offset); 41ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov} 42ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 431f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonovint internal_munmap(void *addr, uptr length) { 441f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov return munmap(addr, length); 451f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov} 461f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov 47a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovint internal_close(fd_t fd) { 48a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov return close(fd); 49a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 50a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 51ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonovfd_t internal_open(const char *filename, int flags) { 52ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov return open(filename, flags); 53ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov} 54ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov 55e85c83dcee3d35068e6670ab32545953d4330335Alexey Samsonovfd_t internal_open(const char *filename, int flags, u32 mode) { 56ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov return open(filename, flags, mode); 57ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov} 58ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov 59ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonovfd_t OpenFile(const char *filename, bool write) { 60ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov return internal_open(filename, 61ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov write ? O_WRONLY | O_CREAT : O_RDONLY, 0660); 62c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov} 63c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov 64a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_read(fd_t fd, void *buf, uptr count) { 65a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov return read(fd, buf, count); 66a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 67a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 68a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_write(fd_t fd, const void *buf, uptr count) { 69a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov return write(fd, buf, count); 70a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 71a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 728e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovuptr internal_filesize(fd_t fd) { 73668accc51f93df21fb0273d2ff10f7c86e757813Alexey Samsonov struct stat st; 748e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov if (fstat(fd, &st)) 758e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov return -1; 768e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov return (uptr)st.st_size; 778e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov} 788e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov 798e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovint internal_dup2(int oldfd, int newfd) { 808e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov return dup2(oldfd, newfd); 818e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov} 828e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov 83d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonovuptr internal_readlink(const char *path, char *buf, uptr bufsize) { 84d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov return readlink(path, buf, bufsize); 85d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov} 86d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov 870969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonovint internal_sched_yield() { 880969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov return sched_yield(); 890969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov} 900969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov 91e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_common.h 9293b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonovbool FileExists(const char *filename) { 9393b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov struct stat st; 9493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov if (stat(filename, &st)) 9593b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov return false; 9693b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov // Sanity check: filename is a regular file. 9793b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov return S_ISREG(st.st_mode); 9893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov} 9993b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov 100e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukovuptr GetTid() { 101e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov return reinterpret_cast<uptr>(pthread_self()); 102e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov} 103e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov 104ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonovvoid GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, 105e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr *stack_bottom) { 106e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK(stack_top); 107e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK(stack_bottom); 108e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr stacksize = pthread_get_stacksize_np(pthread_self()); 109e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov void *stackaddr = pthread_get_stackaddr_np(pthread_self()); 110e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov *stack_top = (uptr)stackaddr; 111ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonov *stack_bottom = *stack_top - stacksize; 112e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov} 113e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 1143dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonovconst char *GetEnv(const char *name) { 1153dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov char ***env_ptr = _NSGetEnviron(); 1163dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov CHECK(env_ptr); 1173dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov char **environ = *env_ptr; 1183dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov CHECK(environ); 1193dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov uptr name_len = internal_strlen(name); 1203dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov while (*environ != 0) { 1213dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov uptr len = internal_strlen(*environ); 1223dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (len > name_len) { 1233dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov const char *p = *environ; 1243dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (!internal_memcmp(p, name, name_len) && 1253dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov p[name_len] == '=') { // Match. 1263dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return *environ + name_len + 1; // String starting after =. 1273dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov } 1283dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov } 1293dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov environ++; 1303dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov } 1313dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return 0; 1323dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov} 133e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 134d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonovvoid ReExec() { 135d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov UNIMPLEMENTED(); 136d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov} 137d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov 13825742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenkovoid PrepareForSandboxing() { 13925742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko // Nothing here for now. 14025742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko} 14125742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko 142e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_procmaps.h 1436895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 144e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey SamsonovMemoryMappingLayout::MemoryMappingLayout() { 1456895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov Reset(); 1466895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 1476895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 148e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey SamsonovMemoryMappingLayout::~MemoryMappingLayout() { 1496895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 1506895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 1516895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// More information about Mach-O headers can be found in mach-o/loader.h 1526895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Each Mach-O image has a header (mach_header or mach_header_64) starting with 1536895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// a magic number, and a list of linker load commands directly following the 1546895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// header. 1556895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// A load command is at least two 32-bit words: the command type and the 1566895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// command size in bytes. We're interested only in segment load commands 1576895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// (LC_SEGMENT and LC_SEGMENT_64), which tell that a part of the file is mapped 1586895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// into the task's address space. 1596895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// The |vmaddr|, |vmsize| and |fileoff| fields of segment_command or 1606895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// segment_command_64 correspond to the memory address, memory size and the 1616895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// file offset of the current memory segment. 1626895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Because these fields are taken from the images as is, one needs to add 1636895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// _dyld_get_image_vmaddr_slide() to get the actual addresses at runtime. 1646895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 165e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovvoid MemoryMappingLayout::Reset() { 1666895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // Count down from the top. 1676895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // TODO(glider): as per man 3 dyld, iterating over the headers with 1686895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // _dyld_image_count is thread-unsafe. We need to register callbacks for 169e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov // adding and removing images which will invalidate the MemoryMappingLayout 170e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov // state. 1716895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_image_ = _dyld_image_count(); 1726895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_load_cmd_count_ = -1; 1736895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_load_cmd_addr_ = 0; 1746895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_magic_ = 0; 1758bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko current_filetype_ = 0; 1766895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 1776895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 17893da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko// static 17993da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::CacheMemoryMappings() { 18093da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko // No-op on Mac for now. 18193da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko} 18293da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko 18393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::LoadFromCache() { 18493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko // No-op on Mac for now. 18593da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko} 18693da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko 1876895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Next and NextSegmentLoad were inspired by base/sysinfo.cc in 1886895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Google Perftools, http://code.google.com/p/google-perftools. 1896895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 1906895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// NextSegmentLoad scans the current image for the next segment load command 1916895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// and returns the start and end addresses and file offset of the corresponding 1926895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// segment. 1936895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Note that the segment addresses are not necessarily sorted. 1946895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonovtemplate<u32 kLCSegment, typename SegmentCommand> 195e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::NextSegmentLoad( 1966895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov uptr *start, uptr *end, uptr *offset, 1976895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov char filename[], uptr filename_size) { 1986895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov const char* lc = current_load_cmd_addr_; 1996895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_load_cmd_addr_ += ((const load_command *)lc)->cmdsize; 2006895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (((const load_command *)lc)->cmd == kLCSegment) { 2016895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov const sptr dlloff = _dyld_get_image_vmaddr_slide(current_image_); 2026895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov const SegmentCommand* sc = (const SegmentCommand *)lc; 2036895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (start) *start = sc->vmaddr + dlloff; 2046895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (end) *end = sc->vmaddr + sc->vmsize + dlloff; 2058bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko if (offset) { 2068bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko if (current_filetype_ == /*MH_EXECUTE*/ 0x2) { 2078bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko *offset = sc->vmaddr; 2088bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko } else { 2098bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko *offset = sc->fileoff; 2108bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko } 2118bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko } 2126895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (filename) { 2136895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov internal_strncpy(filename, _dyld_get_image_name(current_image_), 2146895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov filename_size); 2156895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2166895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov return true; 2176895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2186895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov return false; 2196895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 2206895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 221e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset, 222e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov char filename[], uptr filename_size) { 2236895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov for (; current_image_ >= 0; current_image_--) { 2246895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov const mach_header* hdr = _dyld_get_image_header(current_image_); 2256895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (!hdr) continue; 2266895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (current_load_cmd_count_ < 0) { 2276895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // Set up for this image; 2286895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_load_cmd_count_ = hdr->ncmds; 2296895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_magic_ = hdr->magic; 2308bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko current_filetype_ = hdr->filetype; 2316895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov switch (current_magic_) { 2326895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#ifdef MH_MAGIC_64 2336895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov case MH_MAGIC_64: { 2346895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header_64); 2356895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov break; 2366895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2376895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#endif 2386895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov case MH_MAGIC: { 2396895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header); 2406895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov break; 2416895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2426895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov default: { 2436895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov continue; 2446895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2456895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2466895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2476895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 2486895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov for (; current_load_cmd_count_ >= 0; current_load_cmd_count_--) { 2496895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov switch (current_magic_) { 2506895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // current_magic_ may be only one of MH_MAGIC, MH_MAGIC_64. 2516895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#ifdef MH_MAGIC_64 2526895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov case MH_MAGIC_64: { 2536895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>( 2546895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov start, end, offset, filename, filename_size)) 2556895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov return true; 2566895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov break; 2576895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2586895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#endif 2596895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov case MH_MAGIC: { 2606895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (NextSegmentLoad<LC_SEGMENT, struct segment_command>( 2616895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov start, end, offset, filename, filename_size)) 2626895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov return true; 2636895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov break; 2646895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2656895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2666895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2676895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // If we get here, no more load_cmd's in this image talk about 2686895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // segments. Go on to the next image. 2696895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2706895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov return false; 2716895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 2726895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 273e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset, 274e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov char filename[], 275e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov uptr filename_size) { 2766895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov return IterateForObjectNameAndOffset(addr, offset, filename, filename_size); 2776895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 2786895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 279f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry VyukovBlockingMutex::BlockingMutex(LinkerInitialized) { 280f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov // We assume that OS_SPINLOCK_INIT is zero 281f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 282f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 283f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Lock() { 284f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_)); 285f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov CHECK(OS_SPINLOCK_INIT == 0); 286f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov CHECK(owner_ != (uptr)pthread_self()); 287f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov OSSpinLockLock((OSSpinLock*)&opaque_storage_); 288f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov CHECK(!owner_); 289f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov owner_ = (uptr)pthread_self(); 290f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 291f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 292f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Unlock() { 293f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov CHECK(owner_ == (uptr)pthread_self()); 294f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov owner_ = 0; 295f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov OSSpinLockUnlock((OSSpinLock*)&opaque_storage_); 296f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 297f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 298ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov} // namespace __sanitizer 299ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 300ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif // __APPLE__ 301