sanitizer_mac.cc revision 93b4cafd631b661b4b612ccdc0938f7f1e1c86d6
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>
33ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
34ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovnamespace __sanitizer {
35ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
36e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ---------------------- sanitizer_libc.h
37ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovvoid *internal_mmap(void *addr, size_t length, int prot, int flags,
38ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov                    int fd, u64 offset) {
39ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov  return mmap(addr, length, prot, flags, fd, offset);
40ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov}
41ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
421f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonovint internal_munmap(void *addr, uptr length) {
431f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov  return munmap(addr, length);
441f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov}
451f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov
46a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovint internal_close(fd_t fd) {
47a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov  return close(fd);
48a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
49a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
50c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonovfd_t internal_open(const char *filename, bool write) {
51c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov  return open(filename,
5278381e4b40e6b4dad7b77adb7fa56dfd13b1f31cAlexey Samsonov              write ? O_WRONLY | O_CREAT : O_RDONLY, 0660);
53c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov}
54c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov
55a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_read(fd_t fd, void *buf, uptr count) {
56a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov  return read(fd, buf, count);
57a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
58a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
59a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_write(fd_t fd, const void *buf, uptr count) {
60a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov  return write(fd, buf, count);
61a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
62a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
638e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovuptr internal_filesize(fd_t fd) {
64668accc51f93df21fb0273d2ff10f7c86e757813Alexey Samsonov  struct stat st;
658e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov  if (fstat(fd, &st))
668e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov    return -1;
678e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov  return (uptr)st.st_size;
688e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
698e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
708e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovint internal_dup2(int oldfd, int newfd) {
718e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov  return dup2(oldfd, newfd);
728e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
738e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
74d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonovuptr internal_readlink(const char *path, char *buf, uptr bufsize) {
75d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov  return readlink(path, buf, bufsize);
76d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov}
77d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov
780969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonovint internal_sched_yield() {
790969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov  return sched_yield();
800969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov}
810969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov
82e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_common.h
8393b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonovbool FileExists(const char *filename) {
8493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  struct stat st;
8593b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  if (stat(filename, &st))
8693b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov    return false;
8793b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  // Sanity check: filename is a regular file.
8893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  return S_ISREG(st.st_mode);
8993b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov}
9093b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov
91e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukovuptr GetTid() {
92e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov  return reinterpret_cast<uptr>(pthread_self());
93e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov}
94e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov
95ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonovvoid GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
96e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov                                uptr *stack_bottom) {
97e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  CHECK(stack_top);
98e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  CHECK(stack_bottom);
99e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  uptr stacksize = pthread_get_stacksize_np(pthread_self());
100e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  void *stackaddr = pthread_get_stackaddr_np(pthread_self());
101e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  *stack_top = (uptr)stackaddr;
102ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonov  *stack_bottom = *stack_top - stacksize;
103e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov}
104e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov
1053dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonovconst char *GetEnv(const char *name) {
1063dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  char ***env_ptr = _NSGetEnviron();
1073dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  CHECK(env_ptr);
1083dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  char **environ = *env_ptr;
1093dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  CHECK(environ);
1103dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  uptr name_len = internal_strlen(name);
1113dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  while (*environ != 0) {
1123dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    uptr len = internal_strlen(*environ);
1133dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    if (len > name_len) {
1143dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov      const char *p = *environ;
1153dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov      if (!internal_memcmp(p, name, name_len) &&
1163dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov          p[name_len] == '=') {  // Match.
1173dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov        return *environ + name_len + 1;  // String starting after =.
1183dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov      }
1193dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    }
1203dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    environ++;
1213dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  }
1223dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  return 0;
1233dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov}
124e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov
125d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonovvoid ReExec() {
126d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  UNIMPLEMENTED();
127d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov}
128d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov
129e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_procmaps.h
1306895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
131e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey SamsonovMemoryMappingLayout::MemoryMappingLayout() {
1326895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  Reset();
1336895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
1346895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
135e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey SamsonovMemoryMappingLayout::~MemoryMappingLayout() {
1366895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
1376895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
1386895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// More information about Mach-O headers can be found in mach-o/loader.h
1396895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Each Mach-O image has a header (mach_header or mach_header_64) starting with
1406895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// a magic number, and a list of linker load commands directly following the
1416895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// header.
1426895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// A load command is at least two 32-bit words: the command type and the
1436895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// command size in bytes. We're interested only in segment load commands
1446895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// (LC_SEGMENT and LC_SEGMENT_64), which tell that a part of the file is mapped
1456895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// into the task's address space.
1466895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// The |vmaddr|, |vmsize| and |fileoff| fields of segment_command or
1476895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// segment_command_64 correspond to the memory address, memory size and the
1486895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// file offset of the current memory segment.
1496895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Because these fields are taken from the images as is, one needs to add
1506895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// _dyld_get_image_vmaddr_slide() to get the actual addresses at runtime.
1516895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
152e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovvoid MemoryMappingLayout::Reset() {
1536895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // Count down from the top.
1546895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // TODO(glider): as per man 3 dyld, iterating over the headers with
1556895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // _dyld_image_count is thread-unsafe. We need to register callbacks for
156e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov  // adding and removing images which will invalidate the MemoryMappingLayout
157e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov  // state.
1586895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  current_image_ = _dyld_image_count();
1596895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  current_load_cmd_count_ = -1;
1606895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  current_load_cmd_addr_ = 0;
1616895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  current_magic_ = 0;
1628bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko  current_filetype_ = 0;
1636895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
1646895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
1656895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Next and NextSegmentLoad were inspired by base/sysinfo.cc in
1666895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Google Perftools, http://code.google.com/p/google-perftools.
1676895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
1686895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// NextSegmentLoad scans the current image for the next segment load command
1696895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// and returns the start and end addresses and file offset of the corresponding
1706895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// segment.
1716895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov// Note that the segment addresses are not necessarily sorted.
1726895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonovtemplate<u32 kLCSegment, typename SegmentCommand>
173e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::NextSegmentLoad(
1746895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    uptr *start, uptr *end, uptr *offset,
1756895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    char filename[], uptr filename_size) {
1766895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  const char* lc = current_load_cmd_addr_;
1776895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  current_load_cmd_addr_ += ((const load_command *)lc)->cmdsize;
1786895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (((const load_command *)lc)->cmd == kLCSegment) {
1796895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    const sptr dlloff = _dyld_get_image_vmaddr_slide(current_image_);
1806895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    const SegmentCommand* sc = (const SegmentCommand *)lc;
1816895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    if (start) *start = sc->vmaddr + dlloff;
1826895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    if (end) *end = sc->vmaddr + sc->vmsize + dlloff;
1838bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko    if (offset) {
1848bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko      if (current_filetype_ == /*MH_EXECUTE*/ 0x2) {
1858bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko        *offset = sc->vmaddr;
1868bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko      } else {
1878bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko        *offset = sc->fileoff;
1888bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko      }
1898bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko    }
1906895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    if (filename) {
1916895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      internal_strncpy(filename, _dyld_get_image_name(current_image_),
1926895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov                       filename_size);
1936895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    }
1946895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    return true;
1956895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  }
1966895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  return false;
1976895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
1986895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
199e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
200e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov                               char filename[], uptr filename_size) {
2016895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  for (; current_image_ >= 0; current_image_--) {
2026895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    const mach_header* hdr = _dyld_get_image_header(current_image_);
2036895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    if (!hdr) continue;
2046895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    if (current_load_cmd_count_ < 0) {
2056895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      // Set up for this image;
2066895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      current_load_cmd_count_ = hdr->ncmds;
2076895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      current_magic_ = hdr->magic;
2088bf8b7943848973398be0c3ad99855e20da6d6faAlexander Potapenko      current_filetype_ = hdr->filetype;
2096895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      switch (current_magic_) {
2106895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#ifdef MH_MAGIC_64
2116895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        case MH_MAGIC_64: {
2126895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov          current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header_64);
2136895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov          break;
2146895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        }
2156895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#endif
2166895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        case MH_MAGIC: {
2176895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov          current_load_cmd_addr_ = (char*)hdr + sizeof(mach_header);
2186895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov          break;
2196895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        }
2206895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        default: {
2216895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov          continue;
2226895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        }
2236895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      }
2246895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    }
2256895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
2266895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    for (; current_load_cmd_count_ >= 0; current_load_cmd_count_--) {
2276895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      switch (current_magic_) {
2286895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        // current_magic_ may be only one of MH_MAGIC, MH_MAGIC_64.
2296895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#ifdef MH_MAGIC_64
2306895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        case MH_MAGIC_64: {
2316895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov          if (NextSegmentLoad<LC_SEGMENT_64, struct segment_command_64>(
2326895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov                  start, end, offset, filename, filename_size))
2336895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov            return true;
2346895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov          break;
2356895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        }
2366895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#endif
2376895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        case MH_MAGIC: {
2386895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov          if (NextSegmentLoad<LC_SEGMENT, struct segment_command>(
2396895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov                  start, end, offset, filename, filename_size))
2406895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov            return true;
2416895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov          break;
2426895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov        }
2436895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      }
2446895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    }
2456895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    // If we get here, no more load_cmd's in this image talk about
2466895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    // segments.  Go on to the next image.
2476895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  }
2486895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  return false;
2496895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
2506895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
251e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset,
252e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov                                                 char filename[],
253e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov                                                 uptr filename_size) {
2546895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  return IterateForObjectNameAndOffset(addr, offset, filename, filename_size);
2556895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
2566895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
257ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov}  // namespace __sanitizer
258ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
259ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif  // __APPLE__
260