1 | /* |
2 | * Copyright (C) 2014 Apple Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions |
6 | * are met: |
7 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
20 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
21 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
23 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | #include "BPlatform.h" |
27 | #include "Environment.h" |
28 | #include "ProcessCheck.h" |
29 | #include <cstdlib> |
30 | #include <cstring> |
31 | #if BOS(DARWIN) |
32 | #include <mach-o/dyld.h> |
33 | #elif BOS(UNIX) |
34 | #include <dlfcn.h> |
35 | #endif |
36 | |
37 | #if BUSE(CHECK_NANO_MALLOC) |
38 | extern "C" { |
39 | #if __has_include(<malloc_private.h>) |
40 | #include <malloc_private.h> |
41 | #endif |
42 | int malloc_engaged_nano(void); |
43 | } |
44 | #endif |
45 | |
46 | namespace bmalloc { |
47 | |
48 | static bool isMallocEnvironmentVariableSet() |
49 | { |
50 | const char* list[] = { |
51 | "Malloc" , |
52 | "MallocLogFile" , |
53 | "MallocGuardEdges" , |
54 | "MallocDoNotProtectPrelude" , |
55 | "MallocDoNotProtectPostlude" , |
56 | "MallocStackLogging" , |
57 | "MallocStackLoggingNoCompact" , |
58 | "MallocStackLoggingDirectory" , |
59 | "MallocScribble" , |
60 | "MallocCheckHeapStart" , |
61 | "MallocCheckHeapEach" , |
62 | "MallocCheckHeapSleep" , |
63 | "MallocCheckHeapAbort" , |
64 | "MallocErrorAbort" , |
65 | "MallocCorruptionAbort" , |
66 | "MallocHelp" |
67 | }; |
68 | size_t size = sizeof(list) / sizeof(const char*); |
69 | |
70 | for (size_t i = 0; i < size; ++i) { |
71 | if (getenv(list[i])) |
72 | return true; |
73 | } |
74 | |
75 | return false; |
76 | } |
77 | |
78 | static bool isLibgmallocEnabled() |
79 | { |
80 | char* variable = getenv("DYLD_INSERT_LIBRARIES" ); |
81 | if (!variable) |
82 | return false; |
83 | if (!strstr(variable, "libgmalloc" )) |
84 | return false; |
85 | return true; |
86 | } |
87 | |
88 | static bool isSanitizerEnabled() |
89 | { |
90 | #if BOS(DARWIN) |
91 | static const char sanitizerPrefix[] = "/libclang_rt." ; |
92 | static const char asanName[] = "asan_" ; |
93 | static const char tsanName[] = "tsan_" ; |
94 | uint32_t imageCount = _dyld_image_count(); |
95 | for (uint32_t i = 0; i < imageCount; ++i) { |
96 | const char* imageName = _dyld_get_image_name(i); |
97 | if (!imageName) |
98 | continue; |
99 | if (const char* s = strstr(imageName, sanitizerPrefix)) { |
100 | const char* sanitizerName = s + sizeof(sanitizerPrefix) - 1; |
101 | if (!strncmp(sanitizerName, asanName, sizeof(asanName) - 1)) |
102 | return true; |
103 | if (!strncmp(sanitizerName, tsanName, sizeof(tsanName) - 1)) |
104 | return true; |
105 | } |
106 | } |
107 | return false; |
108 | #elif BOS(UNIX) |
109 | void* handle = dlopen(nullptr, RTLD_NOW); |
110 | if (!handle) |
111 | return false; |
112 | bool result = !!dlsym(handle, "__asan_init" ) || !!dlsym(handle, "__tsan_init" ); |
113 | dlclose(handle); |
114 | return result; |
115 | #else |
116 | return false; |
117 | #endif |
118 | } |
119 | |
120 | #if BUSE(CHECK_NANO_MALLOC) |
121 | static bool isNanoMallocEnabled() |
122 | { |
123 | int result = !!malloc_engaged_nano(); |
124 | return result; |
125 | } |
126 | #endif |
127 | |
128 | DEFINE_STATIC_PER_PROCESS_STORAGE(Environment); |
129 | |
130 | Environment::Environment(std::lock_guard<Mutex>&) |
131 | : m_isDebugHeapEnabled(computeIsDebugHeapEnabled()) |
132 | { |
133 | } |
134 | |
135 | bool Environment::computeIsDebugHeapEnabled() |
136 | { |
137 | if (isMallocEnvironmentVariableSet()) |
138 | return true; |
139 | if (isLibgmallocEnabled()) |
140 | return true; |
141 | if (isSanitizerEnabled()) |
142 | return true; |
143 | #if BUSE(CHECK_NANO_MALLOC) |
144 | if (!isNanoMallocEnabled() && !shouldProcessUnconditionallyUseBmalloc()) |
145 | return true; |
146 | #endif |
147 | return false; |
148 | } |
149 | |
150 | } // namespace bmalloc |
151 | |