sanitizer_mac.cc revision 24e13723f8477d8c42ab8b2a7f4f69fc089842f1
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> 42ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 43ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovnamespace __sanitizer { 44ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 45e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ---------------------- sanitizer_libc.h 46ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovvoid *internal_mmap(void *addr, size_t length, int prot, int flags, 47ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov int fd, u64 offset) { 48ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov return mmap(addr, length, prot, flags, fd, offset); 49ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov} 50ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 511f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonovint internal_munmap(void *addr, uptr length) { 521f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov return munmap(addr, length); 531f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov} 541f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov 55a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovint internal_close(fd_t fd) { 56a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov return close(fd); 57a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 58a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 59ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonovfd_t internal_open(const char *filename, int flags) { 60ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov return open(filename, flags); 61ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov} 62ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov 63e85c83dcee3d35068e6670ab32545953d4330335Alexey Samsonovfd_t internal_open(const char *filename, int flags, u32 mode) { 64ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov return open(filename, flags, mode); 65ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov} 66ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov 67ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonovfd_t OpenFile(const char *filename, bool write) { 68ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov return internal_open(filename, 69ee7cc4454421a176d23442382afd9a01d36e7ad4Alexey Samsonov write ? O_WRONLY | O_CREAT : O_RDONLY, 0660); 70c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov} 71c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov 72a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_read(fd_t fd, void *buf, uptr count) { 73a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov return read(fd, buf, count); 74a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 75a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 76a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_write(fd_t fd, const void *buf, uptr count) { 77a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov return write(fd, buf, count); 78a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov} 79a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov 804c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonovint internal_stat(const char *path, void *buf) { 817c50ee7dd9f2d6a0ed75c27e05b08534908a905aAlexey Samsonov return stat(path, (struct stat *)buf); 824c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 834c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 844c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonovint internal_lstat(const char *path, void *buf) { 857c50ee7dd9f2d6a0ed75c27e05b08534908a905aAlexey Samsonov return lstat(path, (struct stat *)buf); 864c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 874c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 884c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonovint internal_fstat(fd_t fd, void *buf) { 897c50ee7dd9f2d6a0ed75c27e05b08534908a905aAlexey Samsonov return fstat(fd, (struct stat *)buf); 904c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov} 914c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov 928e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovuptr internal_filesize(fd_t fd) { 93668accc51f93df21fb0273d2ff10f7c86e757813Alexey Samsonov struct stat st; 944c9317a7b61e136f832d2ede70f557963fd46bceAlexey Samsonov if (internal_fstat(fd, &st)) 958e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov return -1; 968e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov return (uptr)st.st_size; 978e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov} 988e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov 998e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovint internal_dup2(int oldfd, int newfd) { 1008e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov return dup2(oldfd, newfd); 1018e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov} 1028e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov 103d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonovuptr internal_readlink(const char *path, char *buf, uptr bufsize) { 104d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov return readlink(path, buf, bufsize); 105d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov} 106d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov 1070969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonovint internal_sched_yield() { 1080969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov return sched_yield(); 1090969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov} 1100969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov 111f882247088952deed954a19d745c2dd8871e2035Alexey Samsonovvoid internal__exit(int exitcode) { 112f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov _exit(exitcode); 113f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov} 114f882247088952deed954a19d745c2dd8871e2035Alexey Samsonov 115e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_common.h 11693b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonovbool FileExists(const char *filename) { 11793b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov struct stat st; 11893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov if (stat(filename, &st)) 11993b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov return false; 12093b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov // Sanity check: filename is a regular file. 12193b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov return S_ISREG(st.st_mode); 12293b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov} 12393b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov 124e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukovuptr GetTid() { 125e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov return reinterpret_cast<uptr>(pthread_self()); 126e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov} 127e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov 128ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonovvoid GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top, 129e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr *stack_bottom) { 130e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK(stack_top); 131e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK(stack_bottom); 132e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov uptr stacksize = pthread_get_stacksize_np(pthread_self()); 133e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov void *stackaddr = pthread_get_stackaddr_np(pthread_self()); 134e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov *stack_top = (uptr)stackaddr; 135ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonov *stack_bottom = *stack_top - stacksize; 136e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov} 137e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 1383dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonovconst char *GetEnv(const char *name) { 1393dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov char ***env_ptr = _NSGetEnviron(); 1403dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov CHECK(env_ptr); 1413dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov char **environ = *env_ptr; 1423dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov CHECK(environ); 1433dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov uptr name_len = internal_strlen(name); 1443dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov while (*environ != 0) { 1453dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov uptr len = internal_strlen(*environ); 1463dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (len > name_len) { 1473dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov const char *p = *environ; 1483dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov if (!internal_memcmp(p, name, name_len) && 1493dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov p[name_len] == '=') { // Match. 1503dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return *environ + name_len + 1; // String starting after =. 1513dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov } 1523dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov } 1533dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov environ++; 1543dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov } 1553dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov return 0; 1563dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov} 157e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 158d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonovvoid ReExec() { 159d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov UNIMPLEMENTED(); 160d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov} 161d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov 16225742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenkovoid PrepareForSandboxing() { 16325742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko // Nothing here for now. 16425742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko} 16525742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko 166e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_procmaps.h 1676895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 168e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey SamsonovMemoryMappingLayout::MemoryMappingLayout() { 1696895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov Reset(); 1706895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 1716895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 172e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey SamsonovMemoryMappingLayout::~MemoryMappingLayout() { 1736895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 1746895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 1756895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// More information about Mach-O headers can be found in mach-o/loader.h 1766895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Each Mach-O image has a header (mach_header or mach_header_64) starting with 1776895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// a magic number, and a list of linker load commands directly following the 1786895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// header. 1796895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// A load command is at least two 32-bit words: the command type and the 1806895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// command size in bytes. We're interested only in segment load commands 1816895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// (LC_SEGMENT and LC_SEGMENT_64), which tell that a part of the file is mapped 1826895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// into the task's address space. 1836895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// The |vmaddr|, |vmsize| and |fileoff| fields of segment_command or 1846895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// segment_command_64 correspond to the memory address, memory size and the 1856895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// file offset of the current memory segment. 1866895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Because these fields are taken from the images as is, one needs to add 1876895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// _dyld_get_image_vmaddr_slide() to get the actual addresses at runtime. 1886895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 189e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovvoid MemoryMappingLayout::Reset() { 1906895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // Count down from the top. 1916895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // TODO(glider): as per man 3 dyld, iterating over the headers with 1926895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // _dyld_image_count is thread-unsafe. We need to register callbacks for 193e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov // adding and removing images which will invalidate the MemoryMappingLayout 194e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov // state. 1956895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_image_ = _dyld_image_count(); 1966895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_load_cmd_count_ = -1; 1976895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_load_cmd_addr_ = 0; 1986895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_magic_ = 0; 1998bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko current_filetype_ = 0; 2006895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 2016895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 20293da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko// static 20393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::CacheMemoryMappings() { 20493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko // No-op on Mac for now. 20593da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko} 20693da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko 20793da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::LoadFromCache() { 20893da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko // No-op on Mac for now. 20993da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko} 21093da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko 2116895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Next and NextSegmentLoad were inspired by base/sysinfo.cc in 2126895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Google Perftools, http://code.google.com/p/google-perftools. 2136895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 2146895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// NextSegmentLoad scans the current image for the next segment load command 2156895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// and returns the start and end addresses and file offset of the corresponding 2166895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// segment. 2176895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Note that the segment addresses are not necessarily sorted. 2186895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonovtemplate<u32 kLCSegment, typename SegmentCommand> 219e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::NextSegmentLoad( 2206895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov uptr *start, uptr *end, uptr *offset, 22145717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov char filename[], uptr filename_size, uptr *protection) { 22245717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov if (protection) 22345717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov UNIMPLEMENTED(); 2246895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov const char* lc = current_load_cmd_addr_; 2256895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_load_cmd_addr_ += ((const load_command *)lc)->cmdsize; 2266895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (((const load_command *)lc)->cmd == kLCSegment) { 2276895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov const sptr dlloff = _dyld_get_image_vmaddr_slide(current_image_); 2286895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov const SegmentCommand* sc = (const SegmentCommand *)lc; 2296895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (start) *start = sc->vmaddr + dlloff; 2306895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (end) *end = sc->vmaddr + sc->vmsize + dlloff; 2318bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko if (offset) { 2328bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko if (current_filetype_ == /*MH_EXECUTE*/ 0x2) { 2338bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko *offset = sc->vmaddr; 2348bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko } else { 2358bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko *offset = sc->fileoff; 2368bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko } 2378bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko } 2386895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (filename) { 2396895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov internal_strncpy(filename, _dyld_get_image_name(current_image_), 2406895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov filename_size); 2416895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2426895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov return true; 2436895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2446895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov return false; 2456895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 2466895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 247e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset, 2484a1a495f29b63d44e012f6edcee6307ddac253efAlexey Samsonov char filename[], uptr filename_size, 2494a1a495f29b63d44e012f6edcee6307ddac253efAlexey Samsonov uptr *protection) { 2506895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov for (; current_image_ >= 0; current_image_--) { 2516895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov const mach_header* hdr = _dyld_get_image_header(current_image_); 2526895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (!hdr) continue; 2536895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (current_load_cmd_count_ < 0) { 2546895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // Set up for this image; 2556895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_load_cmd_count_ = hdr->ncmds; 2566895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_magic_ = hdr->magic; 2578bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko current_filetype_ = hdr->filetype; 2586895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov switch (current_magic_) { 2596895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#ifdef MH_MAGIC_64 2606895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov case MH_MAGIC_64: { 2616895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header_64); 2626895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov break; 2636895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2646895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#endif 2656895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov case MH_MAGIC: { 2666895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header); 2676895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov break; 2686895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2696895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov default: { 2706895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov continue; 2716895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2726895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2736895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2746895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 2756895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov for (; current_load_cmd_count_ >= 0; current_load_cmd_count_--) { 2766895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov switch (current_magic_) { 2776895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // current_magic_ may be only one of MH_MAGIC, MH_MAGIC_64. 2786895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#ifdef MH_MAGIC_64 2796895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov case MH_MAGIC_64: { 2806895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>( 2814a1a495f29b63d44e012f6edcee6307ddac253efAlexey Samsonov start, end, offset, filename, filename_size, protection)) 2826895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov return true; 2836895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov break; 2846895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2856895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#endif 2866895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov case MH_MAGIC: { 2876895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov if (NextSegmentLoad<LC_SEGMENT, struct segment_command>( 2884a1a495f29b63d44e012f6edcee6307ddac253efAlexey Samsonov start, end, offset, filename, filename_size, protection)) 2896895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov return true; 2906895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov break; 2916895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2926895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2936895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2946895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // If we get here, no more load_cmd's in this image talk about 2956895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov // segments. Go on to the next image. 2966895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov } 2976895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov return false; 2986895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 2996895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 300e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset, 301e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov char filename[], 3024a1a495f29b63d44e012f6edcee6307ddac253efAlexey Samsonov uptr filename_size, 30345717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov uptr *protection) { 30445717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov return IterateForObjectNameAndOffset(addr, offset, filename, filename_size, 30545717c9d5e39a434749ae10509111f9df1b2cdf4Alexey Samsonov protection); 3066895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov} 3076895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov 308f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry VyukovBlockingMutex::BlockingMutex(LinkerInitialized) { 309f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov // We assume that OS_SPINLOCK_INIT is zero 310f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 311f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 31293af5948d3e0c5bdc396f432dd0ae782f499c449Alexey SamsonovBlockingMutex::BlockingMutex() { 31393af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov internal_memset(this, 0, sizeof(*this)); 31493af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov} 31593af5948d3e0c5bdc396f432dd0ae782f499c449Alexey Samsonov 316f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Lock() { 317f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_)); 318f155fccd1f26f771c9f7f265a4c30faebdfb214fKostya Serebryany CHECK_EQ(OS_SPINLOCK_INIT, 0); 319f155fccd1f26f771c9f7f265a4c30faebdfb214fKostya Serebryany CHECK_NE(owner_, (uptr)pthread_self()); 320f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov OSSpinLockLock((OSSpinLock*)&opaque_storage_); 321f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov CHECK(!owner_); 322f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov owner_ = (uptr)pthread_self(); 323f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 324f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 325f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukovvoid BlockingMutex::Unlock() { 326f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov CHECK(owner_ == (uptr)pthread_self()); 327f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov owner_ = 0; 328f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov OSSpinLockUnlock((OSSpinLock*)&opaque_storage_); 329f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov} 330f4f51f2cc6fa936f0c65577f82e6b62989d546eeDmitry Vyukov 331ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonovvoid BlockingMutex::CheckLocked() { 332ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov CHECK_EQ((uptr)pthread_self(), owner_); 333ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov} 334ce700979f644c790c2d9d80f5cc2a1ada0380284Alexey Samsonov 335b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovuptr GetTlsSize() { 336b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov return 0; 337b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov} 338b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov 339b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanovvoid InitTlsSize() { 340b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov} 341b114ed83859d8d4964ac2284584733bcd2acf4f6Evgeniy Stepanov 342ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov} // namespace __sanitizer 343ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov 344ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif // __APPLE__ 345