authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-01-17 06:02:54+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-04-25 21:49:39+02:00
logdbaea8d67e680121f4e917458a99bc538b473d9d
treee3af41c263074ee293a1640b0011d92a4e8163c4
parente79b4e907a3ceed4984a252fb2bccab7f31ec383
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

libtsan: update to LLVM 22


74 files changed, 1910 insertions(+), 555 deletions(-)

lib/libtsan/LICENSE.TXT created+311
...@@ -0,0 +1,311 @@
1==============================================================================
2The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
3==============================================================================
4
5 Apache License
6 Version 2.0, January 2004
7 http://www.apache.org/licenses/
8
9 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
10
11 1. Definitions.
12
13 "License" shall mean the terms and conditions for use, reproduction,
14 and distribution as defined by Sections 1 through 9 of this document.
15
16 "Licensor" shall mean the copyright owner or entity authorized by
17 the copyright owner that is granting the License.
18
19 "Legal Entity" shall mean the union of the acting entity and all
20 other entities that control, are controlled by, or are under common
21 control with that entity. For the purposes of this definition,
22 "control" means (i) the power, direct or indirect, to cause the
23 direction or management of such entity, whether by contract or
24 otherwise, or (ii) ownership of fifty percent (50%) or more of the
25 outstanding shares, or (iii) beneficial ownership of such entity.
26
27 "You" (or "Your") shall mean an individual or Legal Entity
28 exercising permissions granted by this License.
29
30 "Source" form shall mean the preferred form for making modifications,
31 including but not limited to software source code, documentation
32 source, and configuration files.
33
34 "Object" form shall mean any form resulting from mechanical
35 transformation or translation of a Source form, including but
36 not limited to compiled object code, generated documentation,
37 and conversions to other media types.
38
39 "Work" shall mean the work of authorship, whether in Source or
40 Object form, made available under the License, as indicated by a
41 copyright notice that is included in or attached to the work
42 (an example is provided in the Appendix below).
43
44 "Derivative Works" shall mean any work, whether in Source or Object
45 form, that is based on (or derived from) the Work and for which the
46 editorial revisions, annotations, elaborations, or other modifications
47 represent, as a whole, an original work of authorship. For the purposes
48 of this License, Derivative Works shall not include works that remain
49 separable from, or merely link (or bind by name) to the interfaces of,
50 the Work and Derivative Works thereof.
51
52 "Contribution" shall mean any work of authorship, including
53 the original version of the Work and any modifications or additions
54 to that Work or Derivative Works thereof, that is intentionally
55 submitted to Licensor for inclusion in the Work by the copyright owner
56 or by an individual or Legal Entity authorized to submit on behalf of
57 the copyright owner. For the purposes of this definition, "submitted"
58 means any form of electronic, verbal, or written communication sent
59 to the Licensor or its representatives, including but not limited to
60 communication on electronic mailing lists, source code control systems,
61 and issue tracking systems that are managed by, or on behalf of, the
62 Licensor for the purpose of discussing and improving the Work, but
63 excluding communication that is conspicuously marked or otherwise
64 designated in writing by the copyright owner as "Not a Contribution."
65
66 "Contributor" shall mean Licensor and any individual or Legal Entity
67 on behalf of whom a Contribution has been received by Licensor and
68 subsequently incorporated within the Work.
69
70 2. Grant of Copyright License. Subject to the terms and conditions of
71 this License, each Contributor hereby grants to You a perpetual,
72 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
73 copyright license to reproduce, prepare Derivative Works of,
74 publicly display, publicly perform, sublicense, and distribute the
75 Work and such Derivative Works in Source or Object form.
76
77 3. Grant of Patent License. Subject to the terms and conditions of
78 this License, each Contributor hereby grants to You a perpetual,
79 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
80 (except as stated in this section) patent license to make, have made,
81 use, offer to sell, sell, import, and otherwise transfer the Work,
82 where such license applies only to those patent claims licensable
83 by such Contributor that are necessarily infringed by their
84 Contribution(s) alone or by combination of their Contribution(s)
85 with the Work to which such Contribution(s) was submitted. If You
86 institute patent litigation against any entity (including a
87 cross-claim or counterclaim in a lawsuit) alleging that the Work
88 or a Contribution incorporated within the Work constitutes direct
89 or contributory patent infringement, then any patent licenses
90 granted to You under this License for that Work shall terminate
91 as of the date such litigation is filed.
92
93 4. Redistribution. You may reproduce and distribute copies of the
94 Work or Derivative Works thereof in any medium, with or without
95 modifications, and in Source or Object form, provided that You
96 meet the following conditions:
97
98 (a) You must give any other recipients of the Work or
99 Derivative Works a copy of this License; and
100
101 (b) You must cause any modified files to carry prominent notices
102 stating that You changed the files; and
103
104 (c) You must retain, in the Source form of any Derivative Works
105 that You distribute, all copyright, patent, trademark, and
106 attribution notices from the Source form of the Work,
107 excluding those notices that do not pertain to any part of
108 the Derivative Works; and
109
110 (d) If the Work includes a "NOTICE" text file as part of its
111 distribution, then any Derivative Works that You distribute must
112 include a readable copy of the attribution notices contained
113 within such NOTICE file, excluding those notices that do not
114 pertain to any part of the Derivative Works, in at least one
115 of the following places: within a NOTICE text file distributed
116 as part of the Derivative Works; within the Source form or
117 documentation, if provided along with the Derivative Works; or,
118 within a display generated by the Derivative Works, if and
119 wherever such third-party notices normally appear. The contents
120 of the NOTICE file are for informational purposes only and
121 do not modify the License. You may add Your own attribution
122 notices within Derivative Works that You distribute, alongside
123 or as an addendum to the NOTICE text from the Work, provided
124 that such additional attribution notices cannot be construed
125 as modifying the License.
126
127 You may add Your own copyright statement to Your modifications and
128 may provide additional or different license terms and conditions
129 for use, reproduction, or distribution of Your modifications, or
130 for any such Derivative Works as a whole, provided Your use,
131 reproduction, and distribution of the Work otherwise complies with
132 the conditions stated in this License.
133
134 5. Submission of Contributions. Unless You explicitly state otherwise,
135 any Contribution intentionally submitted for inclusion in the Work
136 by You to the Licensor shall be under the terms and conditions of
137 this License, without any additional terms or conditions.
138 Notwithstanding the above, nothing herein shall supersede or modify
139 the terms of any separate license agreement you may have executed
140 with Licensor regarding such Contributions.
141
142 6. Trademarks. This License does not grant permission to use the trade
143 names, trademarks, service marks, or product names of the Licensor,
144 except as required for reasonable and customary use in describing the
145 origin of the Work and reproducing the content of the NOTICE file.
146
147 7. Disclaimer of Warranty. Unless required by applicable law or
148 agreed to in writing, Licensor provides the Work (and each
149 Contributor provides its Contributions) on an "AS IS" BASIS,
150 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
151 implied, including, without limitation, any warranties or conditions
152 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
153 PARTICULAR PURPOSE. You are solely responsible for determining the
154 appropriateness of using or redistributing the Work and assume any
155 risks associated with Your exercise of permissions under this License.
156
157 8. Limitation of Liability. In no event and under no legal theory,
158 whether in tort (including negligence), contract, or otherwise,
159 unless required by applicable law (such as deliberate and grossly
160 negligent acts) or agreed to in writing, shall any Contributor be
161 liable to You for damages, including any direct, indirect, special,
162 incidental, or consequential damages of any character arising as a
163 result of this License or out of the use or inability to use the
164 Work (including but not limited to damages for loss of goodwill,
165 work stoppage, computer failure or malfunction, or any and all
166 other commercial damages or losses), even if such Contributor
167 has been advised of the possibility of such damages.
168
169 9. Accepting Warranty or Additional Liability. While redistributing
170 the Work or Derivative Works thereof, You may choose to offer,
171 and charge a fee for, acceptance of support, warranty, indemnity,
172 or other liability obligations and/or rights consistent with this
173 License. However, in accepting such obligations, You may act only
174 on Your own behalf and on Your sole responsibility, not on behalf
175 of any other Contributor, and only if You agree to indemnify,
176 defend, and hold each Contributor harmless for any liability
177 incurred by, or claims asserted against, such Contributor by reason
178 of your accepting any such warranty or additional liability.
179
180 END OF TERMS AND CONDITIONS
181
182 APPENDIX: How to apply the Apache License to your work.
183
184 To apply the Apache License to your work, attach the following
185 boilerplate notice, with the fields enclosed by brackets "[]"
186 replaced with your own identifying information. (Don't include
187 the brackets!) The text should be enclosed in the appropriate
188 comment syntax for the file format. We also recommend that a
189 file or class name and description of purpose be included on the
190 same "printed page" as the copyright notice for easier
191 identification within third-party archives.
192
193 Copyright [yyyy] [name of copyright owner]
194
195 Licensed under the Apache License, Version 2.0 (the "License");
196 you may not use this file except in compliance with the License.
197 You may obtain a copy of the License at
198
199 http://www.apache.org/licenses/LICENSE-2.0
200
201 Unless required by applicable law or agreed to in writing, software
202 distributed under the License is distributed on an "AS IS" BASIS,
203 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
204 See the License for the specific language governing permissions and
205 limitations under the License.
206
207
208---- LLVM Exceptions to the Apache 2.0 License ----
209
210As an exception, if, as a result of your compiling your source code, portions
211of this Software are embedded into an Object form of such source code, you
212may redistribute such embedded portions in such Object form without complying
213with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
214
215In addition, if you combine or link compiled forms of this Software with
216software that is licensed under the GPLv2 ("Combined Software") and if a
217court of competent jurisdiction determines that the patent provision (Section
2183), the indemnity provision (Section 9) or other Section of the License
219conflicts with the conditions of the GPLv2, you may retroactively and
220prospectively choose to deem waived or otherwise exclude such Section(s) of
221the License, but only in their entirety and only with respect to the Combined
222Software.
223
224==============================================================================
225Software from third parties included in the LLVM Project:
226==============================================================================
227The LLVM Project contains third party software which is under different license
228terms. All such code will be identified clearly using at least one of two
229mechanisms:
2301) It will be in a separate directory tree with its own `LICENSE.txt` or
231 `LICENSE` file at the top containing the specific license and restrictions
232 which apply to that software, or
2332) It will contain specific license and restriction terms at the top of every
234 file.
235
236==============================================================================
237Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
238==============================================================================
239
240The compiler_rt library is dual licensed under both the University of Illinois
241"BSD-Like" license and the MIT license. As a user of this code you may choose
242to use it under either license. As a contributor, you agree to allow your code
243to be used under both.
244
245Full text of the relevant licenses is included below.
246
247==============================================================================
248
249University of Illinois/NCSA
250Open Source License
251
252Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
253
254All rights reserved.
255
256Developed by:
257
258 LLVM Team
259
260 University of Illinois at Urbana-Champaign
261
262 http://llvm.org
263
264Permission is hereby granted, free of charge, to any person obtaining a copy of
265this software and associated documentation files (the "Software"), to deal with
266the Software without restriction, including without limitation the rights to
267use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
268of the Software, and to permit persons to whom the Software is furnished to do
269so, subject to the following conditions:
270
271 * Redistributions of source code must retain the above copyright notice,
272 this list of conditions and the following disclaimers.
273
274 * Redistributions in binary form must reproduce the above copyright notice,
275 this list of conditions and the following disclaimers in the
276 documentation and/or other materials provided with the distribution.
277
278 * Neither the names of the LLVM Team, University of Illinois at
279 Urbana-Champaign, nor the names of its contributors may be used to
280 endorse or promote products derived from this Software without specific
281 prior written permission.
282
283THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
284IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
285FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
286CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
287LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
288OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
289SOFTWARE.
290
291==============================================================================
292
293Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
294
295Permission is hereby granted, free of charge, to any person obtaining a copy
296of this software and associated documentation files (the "Software"), to deal
297in the Software without restriction, including without limitation the rights
298to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
299copies of the Software, and to permit persons to whom the Software is
300furnished to do so, subject to the following conditions:
301
302The above copyright notice and this permission notice shall be included in
303all copies or substantial portions of the Software.
304
305THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
306IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
307FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
308AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
309LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
310OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
311THE SOFTWARE.
lib/libtsan/builtins/assembly.h+41-8
...@@ -14,7 +14,7 @@...@@ -14,7 +14,7 @@
14#ifndef COMPILERRT_ASSEMBLY_H14#ifndef COMPILERRT_ASSEMBLY_H
15#define COMPILERRT_ASSEMBLY_H15#define COMPILERRT_ASSEMBLY_H
1616
17#if defined(__linux__) && defined(__CET__)17#ifdef __CET__
18#if __has_include(<cet.h>)18#if __has_include(<cet.h>)
19#include <cet.h>19#include <cet.h>
20#endif20#endif
...@@ -71,19 +71,35 @@...@@ -71,19 +71,35 @@
7171
72#endif72#endif
7373
74#if defined(__aarch64__) && defined(__ELF__) && \
75 defined(COMPILER_RT_EXECUTE_ONLY_CODE)
76// The assembler always creates an implicit '.text' section with default flags
77// (SHF_ALLOC | SHF_EXECINSTR), which is incompatible with the execute-only
78// '.text' section we want to create here because of the missing
79// SHF_AARCH64_PURECODE section flag. To solve this, we use 'unique,0' to
80// differentiate the two sections. The output will therefore have two separate
81// sections named '.text', where code will be placed into the execute-only
82// '.text' section, and the implicitly-created one will be empty.
83#define TEXT_SECTION \
84 .section .text,"axy",@progbits,unique,0
85#else
86#define TEXT_SECTION \
87 .text
88#endif
89
74#if defined(__arm__) || defined(__aarch64__) || defined(__arm64ec__)90#if defined(__arm__) || defined(__aarch64__) || defined(__arm64ec__)
75#define FUNC_ALIGN \91#define FUNC_ALIGN \
76 .text SEPARATOR \
77 .balign 16 SEPARATOR92 .balign 16 SEPARATOR
78#else93#else
79#define FUNC_ALIGN94#define FUNC_ALIGN
80#endif95#endif
8196
82// BTI and PAC gnu property note97// BTI, PAC, and GCS gnu property note
83#define NT_GNU_PROPERTY_TYPE_0 598#define NT_GNU_PROPERTY_TYPE_0 5
84#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc000000099#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
85#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI 1100#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI 1
86#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC 2101#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC 2
102#define GNU_PROPERTY_AARCH64_FEATURE_1_GCS 4
87103
88#if defined(__ARM_FEATURE_BTI_DEFAULT)104#if defined(__ARM_FEATURE_BTI_DEFAULT)
89#define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI105#define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI
...@@ -97,6 +113,12 @@...@@ -97,6 +113,12 @@
97#define PAC_FLAG 0113#define PAC_FLAG 0
98#endif114#endif
99115
116#if defined(__ARM_FEATURE_GCS_DEFAULT)
117#define GCS_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_GCS
118#else
119#define GCS_FLAG 0
120#endif
121
100#define GNU_PROPERTY(type, value) \122#define GNU_PROPERTY(type, value) \
101 .pushsection .note.gnu.property, "a" SEPARATOR \123 .pushsection .note.gnu.property, "a" SEPARATOR \
102 .p2align 3 SEPARATOR \124 .p2align 3 SEPARATOR \
...@@ -118,11 +140,12 @@...@@ -118,11 +140,12 @@
118#define BTI_J140#define BTI_J
119#endif141#endif
120142
121#if (BTI_FLAG | PAC_FLAG) != 0143#if (BTI_FLAG | PAC_FLAG | GCS_FLAG) != 0
122#define GNU_PROPERTY_BTI_PAC \144#define GNU_PROPERTY_BTI_PAC_GCS \
123 GNU_PROPERTY(GNU_PROPERTY_AARCH64_FEATURE_1_AND, BTI_FLAG | PAC_FLAG)145 GNU_PROPERTY(GNU_PROPERTY_AARCH64_FEATURE_1_AND, \
146 BTI_FLAG | PAC_FLAG | GCS_FLAG)
124#else147#else
125#define GNU_PROPERTY_BTI_PAC148#define GNU_PROPERTY_BTI_PAC_GCS
126#endif149#endif
127150
128#if defined(__clang__) || defined(__GCC_HAVE_DWARF2_CFI_ASM)151#if defined(__clang__) || defined(__GCC_HAVE_DWARF2_CFI_ASM)
...@@ -247,6 +270,7 @@...@@ -247,6 +270,7 @@
247#endif270#endif
248271
249#define DEFINE_COMPILERRT_FUNCTION(name) \272#define DEFINE_COMPILERRT_FUNCTION(name) \
273 TEXT_SECTION SEPARATOR \
250 DEFINE_CODE_STATE \274 DEFINE_CODE_STATE \
251 FILE_LEVEL_DIRECTIVE SEPARATOR \275 FILE_LEVEL_DIRECTIVE SEPARATOR \
252 .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \276 .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
...@@ -256,6 +280,7 @@...@@ -256,6 +280,7 @@
256 FUNC_SYMBOL(SYMBOL_NAME(name)):280 FUNC_SYMBOL(SYMBOL_NAME(name)):
257281
258#define DEFINE_COMPILERRT_THUMB_FUNCTION(name) \282#define DEFINE_COMPILERRT_THUMB_FUNCTION(name) \
283 TEXT_SECTION SEPARATOR \
259 DEFINE_CODE_STATE \284 DEFINE_CODE_STATE \
260 FILE_LEVEL_DIRECTIVE SEPARATOR \285 FILE_LEVEL_DIRECTIVE SEPARATOR \
261 .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \286 .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
...@@ -265,6 +290,7 @@...@@ -265,6 +290,7 @@
265 FUNC_SYMBOL(SYMBOL_NAME(name)):290 FUNC_SYMBOL(SYMBOL_NAME(name)):
266291
267#define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name) \292#define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name) \
293 TEXT_SECTION SEPARATOR \
268 DEFINE_CODE_STATE \294 DEFINE_CODE_STATE \
269 FILE_LEVEL_DIRECTIVE SEPARATOR \295 FILE_LEVEL_DIRECTIVE SEPARATOR \
270 .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \296 .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
...@@ -274,6 +300,7 @@...@@ -274,6 +300,7 @@
274 FUNC_SYMBOL(SYMBOL_NAME(name)):300 FUNC_SYMBOL(SYMBOL_NAME(name)):
275301
276#define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name) \302#define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name) \
303 TEXT_SECTION SEPARATOR \
277 DEFINE_CODE_STATE \304 DEFINE_CODE_STATE \
278 .globl FUNC_SYMBOL(name) SEPARATOR \305 .globl FUNC_SYMBOL(name) SEPARATOR \
279 SYMBOL_IS_FUNC(name) SEPARATOR \306 SYMBOL_IS_FUNC(name) SEPARATOR \
...@@ -282,6 +309,7 @@...@@ -282,6 +309,7 @@
282 FUNC_SYMBOL(name):309 FUNC_SYMBOL(name):
283310
284#define DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(name) \311#define DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(name) \
312 TEXT_SECTION SEPARATOR \
285 DEFINE_CODE_STATE \313 DEFINE_CODE_STATE \
286 FUNC_ALIGN \314 FUNC_ALIGN \
287 .globl FUNC_SYMBOL(name) SEPARATOR \315 .globl FUNC_SYMBOL(name) SEPARATOR \
...@@ -296,7 +324,7 @@...@@ -296,7 +324,7 @@
296 .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \324 .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
297 SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \325 SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
298 DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \326 DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \
299 .set FUNC_SYMBOL(SYMBOL_NAME(name)), FUNC_SYMBOL(target) SEPARATOR327 .set FUNC_SYMBOL(SYMBOL_NAME(name)), FUNC_SYMBOL(SYMBOL_NAME(target)) SEPARATOR
300328
301#if defined(__ARM_EABI__)329#if defined(__ARM_EABI__)
302#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) \330#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) \
...@@ -329,4 +357,9 @@...@@ -329,4 +357,9 @@
329#endif357#endif
330#endif358#endif
331359
360#if defined(__ASSEMBLER__) && (defined(__i386__) || defined(__amd64__)) && \
361 !defined(__arm64ec__)
362.att_syntax
363#endif
364
332#endif // COMPILERRT_ASSEMBLY_H365#endif // COMPILERRT_ASSEMBLY_H
lib/libtsan/interception/interception_win.cpp+4
...@@ -646,6 +646,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {...@@ -646,6 +646,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
646 case 0xC033: // 33 C0 : xor eax, eax646 case 0xC033: // 33 C0 : xor eax, eax
647 case 0xC933: // 33 C9 : xor ecx, ecx647 case 0xC933: // 33 C9 : xor ecx, ecx
648 case 0xD233: // 33 D2 : xor edx, edx648 case 0xD233: // 33 D2 : xor edx, edx
649 case 0xFF33: // 33 FF : xor edi, edi
649 case 0x9066: // 66 90 : xchg %ax,%ax (Two-byte NOP)650 case 0x9066: // 66 90 : xchg %ax,%ax (Two-byte NOP)
650 case 0xDB84: // 84 DB : test bl,bl651 case 0xDB84: // 84 DB : test bl,bl
651 case 0xC084: // 84 C0 : test al,al652 case 0xC084: // 84 C0 : test al,al
...@@ -764,6 +765,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {...@@ -764,6 +765,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
764765
765 switch (0x00FFFFFF & *(u32 *)address) {766 switch (0x00FFFFFF & *(u32 *)address) {
766 case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax]767 case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax]
768 case 0x02b70f: // 0f b7 02 : movzx eax, WORD PTR [rdx]
767 case 0xc00b4d: // 4d 0b c0 : or r8, r8769 case 0xc00b4d: // 4d 0b c0 : or r8, r8
768 case 0xc03345: // 45 33 c0 : xor r8d, r8d770 case 0xc03345: // 45 33 c0 : xor r8d, r8d
769 case 0xc08548: // 48 85 c0 : test rax, rax771 case 0xc08548: // 48 85 c0 : test rax, rax
...@@ -799,6 +801,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {...@@ -799,6 +801,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
799 case 0xc9854d: // 4d 85 c9 : test r9, r9801 case 0xc9854d: // 4d 85 c9 : test r9, r9
800 case 0xc98b4c: // 4c 8b c9 : mov r9, rcx802 case 0xc98b4c: // 4c 8b c9 : mov r9, rcx
801 case 0xd12948: // 48 29 d1 : sub rcx, rdx803 case 0xd12948: // 48 29 d1 : sub rcx, rdx
804 case 0xc22b4c: // 4c 2b c2 : sub r8, rdx
802 case 0xca2b48: // 48 2b ca : sub rcx, rdx805 case 0xca2b48: // 48 2b ca : sub rcx, rdx
803 case 0xca3b48: // 48 3b ca : cmp rcx, rdx806 case 0xca3b48: // 48 3b ca : cmp rcx, rdx
804 case 0xd12b48: // 48 2b d1 : sub rdx, rcx807 case 0xd12b48: // 48 2b d1 : sub rdx, rcx
...@@ -813,6 +816,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {...@@ -813,6 +816,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
813 case 0xd9f748: // 48 f7 d9 : neg rcx816 case 0xd9f748: // 48 f7 d9 : neg rcx
814 case 0xc03145: // 45 31 c0 : xor r8d,r8d817 case 0xc03145: // 45 31 c0 : xor r8d,r8d
815 case 0xc93145: // 45 31 c9 : xor r9d,r9d818 case 0xc93145: // 45 31 c9 : xor r9d,r9d
819 case 0xd23345: // 45 33 d2 : xor r10d, r10d
816 case 0xdb3345: // 45 33 db : xor r11d, r11d820 case 0xdb3345: // 45 33 db : xor r11d, r11d
817 case 0xc08445: // 45 84 c0 : test r8b,r8b821 case 0xc08445: // 45 84 c0 : test r8b,r8b
818 case 0xd28445: // 45 84 d2 : test r10b,r10b822 case 0xd28445: // 45 84 d2 : test r10b,r10b
lib/libtsan/sanitizer_common/sanitizer_allocator_primary32.h+1
...@@ -288,6 +288,7 @@ class SizeClassAllocator32 {...@@ -288,6 +288,7 @@ class SizeClassAllocator32 {
288 uptr ComputeRegionId(uptr mem) const {288 uptr ComputeRegionId(uptr mem) const {
289 if (SANITIZER_SIGN_EXTENDED_ADDRESSES)289 if (SANITIZER_SIGN_EXTENDED_ADDRESSES)
290 mem &= (kSpaceSize - 1);290 mem &= (kSpaceSize - 1);
291 mem -= kSpaceBeg;
291 const uptr res = mem >> kRegionSizeLog;292 const uptr res = mem >> kRegionSizeLog;
292 CHECK_LT(res, kNumPossibleRegions);293 CHECK_LT(res, kNumPossibleRegions);
293 return res;294 return res;
lib/libtsan/sanitizer_common/sanitizer_allocator_primary64.h+18
...@@ -113,6 +113,24 @@ class SizeClassAllocator64 {...@@ -113,6 +113,24 @@ class SizeClassAllocator64 {
113 // ~(uptr)0.113 // ~(uptr)0.
114 void Init(s32 release_to_os_interval_ms, uptr heap_start = 0) {114 void Init(s32 release_to_os_interval_ms, uptr heap_start = 0) {
115 uptr TotalSpaceSize = kSpaceSize + AdditionalSize();115 uptr TotalSpaceSize = kSpaceSize + AdditionalSize();
116
117 uptr MaxAddr = GetMaxUserVirtualAddress();
118 // VReport does not call the sanitizer allocator.
119 VReport(3, "Max user virtual address: 0x%zx\n", MaxAddr);
120 VReport(3, "Total space size for primary allocator: 0x%zx\n",
121 TotalSpaceSize);
122 // TODO: revise the check if we ever configure sanitizers to deliberately
123 // map beyond the 2**48 barrier (note that Linux pretends the VMA is
124 // limited to 48-bit for backwards compatibility, but allows apps to
125 // explicitly specify an address beyond that).
126 if (heap_start + TotalSpaceSize >= MaxAddr) {
127 // We can't easily adjust the requested heap size, because kSpaceSize is
128 // const (for optimization) and used throughout the code.
129 VReport(0, "Error: heap size %zx exceeds max user virtual address %zx\n",
130 TotalSpaceSize, MaxAddr);
131 VReport(
132 0, "Try using a kernel that allows a larger virtual address space\n");
133 }
116 PremappedHeap = heap_start != 0;134 PremappedHeap = heap_start != 0;
117 if (PremappedHeap) {135 if (PremappedHeap) {
118 CHECK(!kUsingConstantSpaceBeg);136 CHECK(!kUsingConstantSpaceBeg);
lib/libtsan/sanitizer_common/sanitizer_common.h+15-2
...@@ -78,8 +78,8 @@ uptr GetMmapGranularity();...@@ -78,8 +78,8 @@ uptr GetMmapGranularity();
78uptr GetMaxVirtualAddress();78uptr GetMaxVirtualAddress();
79uptr GetMaxUserVirtualAddress();79uptr GetMaxUserVirtualAddress();
80// Threads80// Threads
81tid_t GetTid();81ThreadID GetTid();
82int TgKill(pid_t pid, tid_t tid, int sig);82int TgKill(pid_t pid, ThreadID tid, int sig);
83uptr GetThreadSelf();83uptr GetThreadSelf();
84void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,84void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
85 uptr *stack_bottom);85 uptr *stack_bottom);
...@@ -390,6 +390,9 @@ void ReportDeadlySignal(const SignalContext &sig, u32 tid,...@@ -390,6 +390,9 @@ void ReportDeadlySignal(const SignalContext &sig, u32 tid,
390void SetAlternateSignalStack();390void SetAlternateSignalStack();
391void UnsetAlternateSignalStack();391void UnsetAlternateSignalStack();
392392
393bool IsSignalHandlerFromSanitizer(int signum);
394bool SetSignalHandlerFromSanitizer(int signum, bool new_state);
395
393// Construct a one-line string:396// Construct a one-line string:
394// SUMMARY: SanitizerToolName: error_message397// SUMMARY: SanitizerToolName: error_message
395// and pass it to __sanitizer_report_error_summary.398// and pass it to __sanitizer_report_error_summary.
...@@ -484,6 +487,13 @@ inline uptr Log2(uptr x) {...@@ -484,6 +487,13 @@ inline uptr Log2(uptr x) {
484 return LeastSignificantSetBitIndex(x);487 return LeastSignificantSetBitIndex(x);
485}488}
486489
490inline bool IntervalsAreSeparate(uptr start1, uptr end1, uptr start2,
491 uptr end2) {
492 CHECK_LE(start1, end1);
493 CHECK_LE(start2, end2);
494 return (end1 < start2) || (end2 < start1);
495}
496
487// Don't use std::min, std::max or std::swap, to minimize dependency497// Don't use std::min, std::max or std::swap, to minimize dependency
488// on libstdc++.498// on libstdc++.
489template <class T>499template <class T>
...@@ -734,6 +744,7 @@ enum ModuleArch {...@@ -734,6 +744,7 @@ enum ModuleArch {
734 kModuleArchARMV7S,744 kModuleArchARMV7S,
735 kModuleArchARMV7K,745 kModuleArchARMV7K,
736 kModuleArchARM64,746 kModuleArchARM64,
747 kModuleArchARM64E,
737 kModuleArchLoongArch64,748 kModuleArchLoongArch64,
738 kModuleArchRISCV64,749 kModuleArchRISCV64,
739 kModuleArchHexagon750 kModuleArchHexagon
...@@ -807,6 +818,8 @@ inline const char *ModuleArchToString(ModuleArch arch) {...@@ -807,6 +818,8 @@ inline const char *ModuleArchToString(ModuleArch arch) {
807 return "armv7k";818 return "armv7k";
808 case kModuleArchARM64:819 case kModuleArchARM64:
809 return "arm64";820 return "arm64";
821 case kModuleArchARM64E:
822 return "arm64e";
810 case kModuleArchLoongArch64:823 case kModuleArchLoongArch64:
811 return "loongarch64";824 return "loongarch64";
812 case kModuleArchRISCV64:825 case kModuleArchRISCV64:
lib/libtsan/sanitizer_common/sanitizer_common_interceptors.inc+30-4
...@@ -1285,8 +1285,34 @@ INTERCEPTOR(int, puts, char *s) {...@@ -1285,8 +1285,34 @@ INTERCEPTOR(int, puts, char *s) {
1285#endif1285#endif
12861286
1287#if SANITIZER_INTERCEPT_PRCTL1287#if SANITIZER_INTERCEPT_PRCTL
1288INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,1288
1289 unsigned long arg4, unsigned long arg5) {1289# if defined(__aarch64__)
1290// https://llvm.org/docs/PointerAuth.html
1291// AArch64 is currently the only architecture with full PAC support.
1292// Avoid adding PAC instructions to prevent crashes caused by
1293// prctl(PR_PAC_RESET_KEYS, ...). Since PR_PAC_RESET_KEYS resets the
1294// authentication key, using the old key afterward will lead to a crash.
1295
1296# if defined(__ARM_FEATURE_BTI_DEFAULT)
1297# define BRANCH_PROTECTION_ATTRIBUTE \
1298 __attribute__((target("branch-protection=bti")))
1299# else
1300# define BRANCH_PROTECTION_ATTRIBUTE \
1301 __attribute__((target("branch-protection=none")))
1302# endif
1303
1304# define PRCTL_INTERCEPTOR(ret_type, func, ...) \
1305 DEFINE_REAL(ret_type, func, __VA_ARGS__) \
1306 DECLARE_WRAPPER(ret_type, func, __VA_ARGS__) \
1307 extern "C" INTERCEPTOR_ATTRIBUTE BRANCH_PROTECTION_ATTRIBUTE ret_type \
1308 WRAP(func)(__VA_ARGS__)
1309
1310# else
1311# define PRCTL_INTERCEPTOR INTERCEPTOR
1312# endif
1313
1314PRCTL_INTERCEPTOR(int, prctl, int option, unsigned long arg2,
1315 unsigned long arg3, unsigned long arg4, unsigned long arg5) {
1290 void *ctx;1316 void *ctx;
1291 COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);1317 COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
1292 static const int PR_SET_NAME = 15;1318 static const int PR_SET_NAME = 15;
...@@ -1300,7 +1326,7 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,...@@ -1300,7 +1326,7 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
1300 static const int PR_SET_SECCOMP = 22;1326 static const int PR_SET_SECCOMP = 22;
1301 static const int SECCOMP_MODE_FILTER = 2;1327 static const int SECCOMP_MODE_FILTER = 2;
1302# endif1328# endif
1303 if (option == PR_SET_VMA && arg2 == 0UL) {1329 if (option == PR_SET_VMA && arg2 == 0UL && arg5 != 0UL) {
1304 char *name = (char *)arg5;1330 char *name = (char *)arg5;
1305 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);1331 COMMON_INTERCEPTOR_READ_RANGE(ctx, name, internal_strlen(name) + 1);
1306 }1332 }
...@@ -1326,7 +1352,7 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,...@@ -1326,7 +1352,7 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, unsigned long arg3,
1326 }1352 }
1327 return res;1353 return res;
1328}1354}
1329#define INIT_PRCTL COMMON_INTERCEPT_FUNCTION(prctl)1355# define INIT_PRCTL COMMON_INTERCEPT_FUNCTION(prctl)
1330#else1356#else
1331#define INIT_PRCTL1357#define INIT_PRCTL
1332#endif // SANITIZER_INTERCEPT_PRCTL1358#endif // SANITIZER_INTERCEPT_PRCTL
lib/libtsan/sanitizer_common/sanitizer_common_interceptors_ioctl.inc+4
...@@ -344,12 +344,16 @@ static void ioctl_table_fill() {...@@ -344,12 +344,16 @@ static void ioctl_table_fill() {
344 _(SOUND_PCM_WRITE_CHANNELS, WRITE, sizeof(int));344 _(SOUND_PCM_WRITE_CHANNELS, WRITE, sizeof(int));
345 _(SOUND_PCM_WRITE_FILTER, WRITE, sizeof(int));345 _(SOUND_PCM_WRITE_FILTER, WRITE, sizeof(int));
346 _(TCFLSH, NONE, 0);346 _(TCFLSH, NONE, 0);
347# if SANITIZER_TERMIOS_IOCTL_CONSTANTS
347 _(TCGETS, WRITE, struct_termios_sz);348 _(TCGETS, WRITE, struct_termios_sz);
349# endif
348 _(TCSBRK, NONE, 0);350 _(TCSBRK, NONE, 0);
349 _(TCSBRKP, NONE, 0);351 _(TCSBRKP, NONE, 0);
352# if SANITIZER_TERMIOS_IOCTL_CONSTANTS
350 _(TCSETS, READ, struct_termios_sz);353 _(TCSETS, READ, struct_termios_sz);
351 _(TCSETSF, READ, struct_termios_sz);354 _(TCSETSF, READ, struct_termios_sz);
352 _(TCSETSW, READ, struct_termios_sz);355 _(TCSETSW, READ, struct_termios_sz);
356# endif
353 _(TCXONC, NONE, 0);357 _(TCXONC, NONE, 0);
354 _(TIOCGLCKTRMIOS, WRITE, struct_termios_sz);358 _(TIOCGLCKTRMIOS, WRITE, struct_termios_sz);
355 _(TIOCGSOFTCAR, WRITE, sizeof(int));359 _(TIOCGSOFTCAR, WRITE, sizeof(int));
lib/libtsan/sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S+2-1
...@@ -5,6 +5,7 @@...@@ -5,6 +5,7 @@
55
6ASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA)6ASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA)
77
8TEXT_SECTION
8.comm _ZN14__interception10real_vforkE,8,89.comm _ZN14__interception10real_vforkE,8,8
9.globl ASM_WRAPPER_NAME(vfork)10.globl ASM_WRAPPER_NAME(vfork)
10ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))11ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
...@@ -43,6 +44,6 @@ ASM_SIZE(vfork)...@@ -43,6 +44,6 @@ ASM_SIZE(vfork)
43ASM_INTERCEPTOR_TRAMPOLINE(vfork)44ASM_INTERCEPTOR_TRAMPOLINE(vfork)
44ASM_TRAMPOLINE_ALIAS(vfork, vfork)45ASM_TRAMPOLINE_ALIAS(vfork, vfork)
4546
46GNU_PROPERTY_BTI_PAC47GNU_PROPERTY_BTI_PAC_GCS
4748
48#endif49#endif
lib/libtsan/sanitizer_common/sanitizer_common_interceptors_vfork_i386.inc.S+2
...@@ -2,6 +2,8 @@...@@ -2,6 +2,8 @@
22
3#include "sanitizer_common/sanitizer_asm.h"3#include "sanitizer_common/sanitizer_asm.h"
44
5.att_syntax
6
5.comm _ZN14__interception10real_vforkE,4,47.comm _ZN14__interception10real_vforkE,4,4
6.globl ASM_WRAPPER_NAME(vfork)8.globl ASM_WRAPPER_NAME(vfork)
7ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))9ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
lib/libtsan/sanitizer_common/sanitizer_common_interceptors_vfork_x86_64.inc.S+2
...@@ -2,6 +2,8 @@...@@ -2,6 +2,8 @@
22
3#include "sanitizer_common/sanitizer_asm.h"3#include "sanitizer_common/sanitizer_asm.h"
44
5.att_syntax
6
5.comm _ZN14__interception10real_vforkE,8,87.comm _ZN14__interception10real_vforkE,8,8
6.globl ASM_WRAPPER_NAME(vfork)8.globl ASM_WRAPPER_NAME(vfork)
7ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))9ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
lib/libtsan/sanitizer_common/sanitizer_common_syscalls.inc+18
...@@ -143,6 +143,12 @@ struct sanitizer_kernel_sockaddr {...@@ -143,6 +143,12 @@ struct sanitizer_kernel_sockaddr {
143 char sa_data[14];143 char sa_data[14];
144};144};
145145
146struct sanitizer_kernel_open_how {
147 u64 flags;
148 u64 mode;
149 u64 resolve;
150};
151
146// Real sigset size is always passed as a syscall argument.152// Real sigset size is always passed as a syscall argument.
147// Declare it "void" to catch sizeof(kernel_sigset_t).153// Declare it "void" to catch sizeof(kernel_sigset_t).
148typedef void kernel_sigset_t;154typedef void kernel_sigset_t;
...@@ -2843,6 +2849,18 @@ PRE_SYSCALL(openat)(long dfd, const void *filename, long flags, long mode) {...@@ -2843,6 +2849,18 @@ PRE_SYSCALL(openat)(long dfd, const void *filename, long flags, long mode) {
2843POST_SYSCALL(openat)2849POST_SYSCALL(openat)
2844(long res, long dfd, const void *filename, long flags, long mode) {}2850(long res, long dfd, const void *filename, long flags, long mode) {}
28452851
2852PRE_SYSCALL(openat2)(long dfd, const void* filename,
2853 const sanitizer_kernel_open_how* how, uptr howlen) {
2854 if (filename)
2855 PRE_READ(filename, __sanitizer::internal_strlen((const char*)filename) + 1);
2856
2857 if (how)
2858 PRE_READ(how, howlen);
2859}
2860
2861POST_SYSCALL(openat2)(long res, long dfd, const void* filename,
2862 const sanitizer_kernel_open_how* how, uptr howlen) {}
2863
2846PRE_SYSCALL(newfstatat)2864PRE_SYSCALL(newfstatat)
2847(long dfd, const void *filename, void *statbuf, long flag) {2865(long dfd, const void *filename, void *statbuf, long flag) {
2848 if (filename)2866 if (filename)
lib/libtsan/sanitizer_common/sanitizer_coverage_interface.inc deleted-43
...@@ -1,43 +0,0 @@
1//===-- sanitizer_coverage_interface.inc ----------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8// Sanitizer Coverage interface list.
9//===----------------------------------------------------------------------===//
10INTERFACE_FUNCTION(__sanitizer_cov_dump)
11INTERFACE_FUNCTION(__sanitizer_cov_reset)
12INTERFACE_FUNCTION(__sanitizer_dump_coverage)
13INTERFACE_FUNCTION(__sanitizer_dump_trace_pc_guard_coverage)
14INTERFACE_WEAK_FUNCTION(__sancov_default_options)
15INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp)
16INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp1)
17INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp2)
18INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp4)
19INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp8)
20INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp1)
21INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp2)
22INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp4)
23INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_const_cmp8)
24INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_div4)
25INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_div8)
26INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_gep)
27INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_guard)
28INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_guard_init)
29INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_indir)
30INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load1)
31INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load2)
32INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load4)
33INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load8)
34INTERFACE_WEAK_FUNCTION(__sanitizer_cov_load16)
35INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store1)
36INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store2)
37INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store4)
38INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store8)
39INTERFACE_WEAK_FUNCTION(__sanitizer_cov_store16)
40INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_switch)
41INTERFACE_WEAK_FUNCTION(__sanitizer_cov_8bit_counters_init)
42INTERFACE_WEAK_FUNCTION(__sanitizer_cov_bool_flag_init)
43INTERFACE_WEAK_FUNCTION(__sanitizer_cov_pcs_init)
lib/libtsan/sanitizer_common/sanitizer_file.cpp+40-12
...@@ -36,9 +36,17 @@ void RawWrite(const char *buffer) {...@@ -36,9 +36,17 @@ void RawWrite(const char *buffer) {
3636
37void ReportFile::ReopenIfNecessary() {37void ReportFile::ReopenIfNecessary() {
38 mu->CheckLocked();38 mu->CheckLocked();
39 if (fd == kStdoutFd || fd == kStderrFd) return;
40
41 uptr pid = internal_getpid();39 uptr pid = internal_getpid();
40 if (fallbackToStderrActive && fd_pid != pid) {
41 // If fallbackToStderrActive is set then we fellback to stderr. If this is a
42 // new process, mark fd as invalid so we attempt to open again.
43 CHECK_EQ(fd, kStderrFd);
44 fd = kInvalidFd;
45 fallbackToStderrActive = false;
46 }
47 if (fd == kStdoutFd || fd == kStderrFd)
48 return;
49
42 // If in tracer, use the parent's file.50 // If in tracer, use the parent's file.
43 if (pid == stoptheworld_tracer_pid)51 if (pid == stoptheworld_tracer_pid)
44 pid = stoptheworld_tracer_ppid;52 pid = stoptheworld_tracer_ppid;
...@@ -48,8 +56,7 @@ void ReportFile::ReopenIfNecessary() {...@@ -48,8 +56,7 @@ void ReportFile::ReopenIfNecessary() {
48 // process, close it now.56 // process, close it now.
49 if (fd_pid == pid)57 if (fd_pid == pid)
50 return;58 return;
51 else59 CloseFile(fd);
52 CloseFile(fd);
53 }60 }
5461
55 const char *exe_name = GetProcessName();62 const char *exe_name = GetProcessName();
...@@ -65,18 +72,24 @@ void ReportFile::ReopenIfNecessary() {...@@ -65,18 +72,24 @@ void ReportFile::ReopenIfNecessary() {
65 error_t err;72 error_t err;
66 fd = OpenFile(full_path, WrOnly, &err);73 fd = OpenFile(full_path, WrOnly, &err);
67 if (fd == kInvalidFd) {74 if (fd == kInvalidFd) {
68 const char *ErrorMsgPrefix = "ERROR: Can't open file: ";75 bool fallback = common_flags()->log_fallback_to_stderr;
76 const char *ErrorMsgPrefix =
77 fallback ? "WARNING: Can't open file, falling back to stderr: "
78 : "ERROR: Can't open file: ";
69 WriteToFile(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix));79 WriteToFile(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix));
70 WriteToFile(kStderrFd, full_path, internal_strlen(full_path));80 WriteToFile(kStderrFd, full_path, internal_strlen(full_path));
71 char errmsg[100];81 char errmsg[100];
72 internal_snprintf(errmsg, sizeof(errmsg), " (reason: %d)\n", err);82 internal_snprintf(errmsg, sizeof(errmsg), " (reason: %d)\n", err);
73 WriteToFile(kStderrFd, errmsg, internal_strlen(errmsg));83 WriteToFile(kStderrFd, errmsg, internal_strlen(errmsg));
74 Die();84 if (!fallback)
85 Die();
86 fallbackToStderrActive = true;
87 fd = kStderrFd;
75 }88 }
76 fd_pid = pid;89 fd_pid = pid;
77}90}
7891
79static void RecursiveCreateParentDirs(char *path) {92static void RecursiveCreateParentDirs(char *path, fd_t &fd) {
80 if (path[0] == '\0')93 if (path[0] == '\0')
81 return;94 return;
82 for (int i = 1; path[i] != '\0'; ++i) {95 for (int i = 1; path[i] != '\0'; ++i) {
...@@ -85,12 +98,19 @@ static void RecursiveCreateParentDirs(char *path) {...@@ -85,12 +98,19 @@ static void RecursiveCreateParentDirs(char *path) {
85 continue;98 continue;
86 path[i] = '\0';99 path[i] = '\0';
87 if (!DirExists(path) && !CreateDir(path)) {100 if (!DirExists(path) && !CreateDir(path)) {
88 const char *ErrorMsgPrefix = "ERROR: Can't create directory: ";101 bool fallback = common_flags()->log_fallback_to_stderr;
102 const char *ErrorMsgPrefix =
103 fallback ? "WARNING: Can't create directory, falling back to stderr: "
104 : "ERROR: Can't create directory: ";
89 WriteToFile(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix));105 WriteToFile(kStderrFd, ErrorMsgPrefix, internal_strlen(ErrorMsgPrefix));
90 WriteToFile(kStderrFd, path, internal_strlen(path));106 WriteToFile(kStderrFd, path, internal_strlen(path));
91 const char *ErrorMsgSuffix = "\n";107 const char *ErrorMsgSuffix = "\n";
92 WriteToFile(kStderrFd, ErrorMsgSuffix, internal_strlen(ErrorMsgSuffix));108 WriteToFile(kStderrFd, ErrorMsgSuffix, internal_strlen(ErrorMsgSuffix));
93 Die();109 if (!fallback)
110 Die();
111 path[i] = save;
112 fd = kStderrFd;
113 return;
94 }114 }
95 path[i] = save;115 path[i] = save;
96 }116 }
...@@ -108,6 +128,9 @@ static void ParseAndSetPath(const char *pattern, char *dest,...@@ -108,6 +128,9 @@ static void ParseAndSetPath(const char *pattern, char *dest,
108 CHECK(dest);128 CHECK(dest);
109 CHECK_GE(dest_size, 1);129 CHECK_GE(dest_size, 1);
110 dest[0] = '\0';130 dest[0] = '\0';
131 // Return empty string if empty string was passed
132 if (internal_strlen(pattern) == 0)
133 return;
111 uptr next_substr_start_idx = 0;134 uptr next_substr_start_idx = 0;
112 for (uptr i = 0; i < internal_strlen(pattern) - 1; i++) {135 for (uptr i = 0; i < internal_strlen(pattern) - 1; i++) {
113 if (pattern[i] != '%')136 if (pattern[i] != '%')
...@@ -161,12 +184,17 @@ void ReportFile::SetReportPath(const char *path) {...@@ -161,12 +184,17 @@ void ReportFile::SetReportPath(const char *path) {
161 if (path) {184 if (path) {
162 uptr len = internal_strlen(path);185 uptr len = internal_strlen(path);
163 if (len > sizeof(path_prefix) - 100) {186 if (len > sizeof(path_prefix) - 100) {
164 const char *message = "ERROR: Path is too long: ";187 bool fallback = common_flags()->log_fallback_to_stderr;
188 const char *message =
189 fallback ? "WARNING: Path is too long, falling back to stderr: "
190 : "ERROR: Path is too long: ";
165 WriteToFile(kStderrFd, message, internal_strlen(message));191 WriteToFile(kStderrFd, message, internal_strlen(message));
166 WriteToFile(kStderrFd, path, 8);192 WriteToFile(kStderrFd, path, 8);
167 message = "...\n";193 message = "...\n";
168 WriteToFile(kStderrFd, message, internal_strlen(message));194 WriteToFile(kStderrFd, message, internal_strlen(message));
169 Die();195 if (!fallback)
196 Die();
197 path = "stderr";
170 }198 }
171 }199 }
172200
...@@ -180,7 +208,7 @@ void ReportFile::SetReportPath(const char *path) {...@@ -180,7 +208,7 @@ void ReportFile::SetReportPath(const char *path) {
180 fd = kStdoutFd;208 fd = kStdoutFd;
181 } else {209 } else {
182 ParseAndSetPath(path, path_prefix, kMaxPathLength);210 ParseAndSetPath(path, path_prefix, kMaxPathLength);
183 RecursiveCreateParentDirs(path_prefix);211 RecursiveCreateParentDirs(path_prefix, fd);
184 }212 }
185}213}
186214
lib/libtsan/sanitizer_common/sanitizer_file.h+3
...@@ -43,6 +43,9 @@ struct ReportFile {...@@ -43,6 +43,9 @@ struct ReportFile {
43 // PID of the process that opened fd. If a fork() occurs,43 // PID of the process that opened fd. If a fork() occurs,
44 // the PID of child will be different from fd_pid.44 // the PID of child will be different from fd_pid.
45 uptr fd_pid;45 uptr fd_pid;
46 // Set to true if the last attempt to open the logfile failed, perhaps due to
47 // permission errors
48 bool fallbackToStderrActive = false;
4649
47 private:50 private:
48 void ReopenIfNecessary();51 void ReopenIfNecessary();
lib/libtsan/sanitizer_common/sanitizer_flags.inc+7
...@@ -65,6 +65,8 @@ COMMON_FLAG(...@@ -65,6 +65,8 @@ COMMON_FLAG(
65 bool, log_to_syslog, (bool)SANITIZER_ANDROID || (bool)SANITIZER_APPLE,65 bool, log_to_syslog, (bool)SANITIZER_ANDROID || (bool)SANITIZER_APPLE,
66 "Write all sanitizer output to syslog in addition to other means of "66 "Write all sanitizer output to syslog in addition to other means of "
67 "logging.")67 "logging.")
68COMMON_FLAG(bool, log_fallback_to_stderr, false,
69 "When set, fallback to stderr if we are unable to open log path.")
68COMMON_FLAG(70COMMON_FLAG(
69 int, verbosity, 0,71 int, verbosity, 0,
70 "Verbosity level (0 - silent, 1 - a bit of output, 2+ - more output).")72 "Verbosity level (0 - silent, 1 - a bit of output, 2+ - more output).")
...@@ -111,6 +113,11 @@ COMMON_FLAG(HandleSignalMode, handle_sigfpe, kHandleSignalYes,...@@ -111,6 +113,11 @@ COMMON_FLAG(HandleSignalMode, handle_sigfpe, kHandleSignalYes,
111COMMON_FLAG(bool, allow_user_segv_handler, true,113COMMON_FLAG(bool, allow_user_segv_handler, true,
112 "Deprecated. True has no effect, use handle_sigbus=1. If false, "114 "Deprecated. True has no effect, use handle_sigbus=1. If false, "
113 "handle_*=1 will be upgraded to handle_*=2.")115 "handle_*=1 will be upgraded to handle_*=2.")
116COMMON_FLAG(bool, cloak_sanitizer_signal_handlers, false,
117 "If set, signal/sigaction will pretend that sanitizers did not "
118 "preinstall any signal handlers. If the user subsequently installs "
119 "a signal handler, this will disable cloaking for the respective "
120 "signal.")
114COMMON_FLAG(bool, use_sigaltstack, true,121COMMON_FLAG(bool, use_sigaltstack, true,
115 "If set, uses alternate stack for signal handling.")122 "If set, uses alternate stack for signal handling.")
116COMMON_FLAG(bool, detect_deadlocks, true,123COMMON_FLAG(bool, detect_deadlocks, true,
lib/libtsan/sanitizer_common/sanitizer_fuchsia.cpp+30-3
...@@ -14,6 +14,7 @@...@@ -14,6 +14,7 @@
14#include "sanitizer_fuchsia.h"14#include "sanitizer_fuchsia.h"
15#if SANITIZER_FUCHSIA15#if SANITIZER_FUCHSIA
1616
17# include <limits.h>
17# include <pthread.h>18# include <pthread.h>
18# include <stdlib.h>19# include <stdlib.h>
19# include <unistd.h>20# include <unistd.h>
...@@ -68,7 +69,7 @@ int internal_dlinfo(void *handle, int request, void *p) { UNIMPLEMENTED(); }...@@ -68,7 +69,7 @@ int internal_dlinfo(void *handle, int request, void *p) { UNIMPLEMENTED(); }
6869
69uptr GetThreadSelf() { return reinterpret_cast<uptr>(thrd_current()); }70uptr GetThreadSelf() { return reinterpret_cast<uptr>(thrd_current()); }
7071
71tid_t GetTid() { return GetThreadSelf(); }72ThreadID GetTid() { return GetThreadSelf(); }
7273
73void Abort() { abort(); }74void Abort() { abort(); }
7475
...@@ -117,11 +118,37 @@ uptr GetMmapGranularity() { return _zx_system_get_page_size(); }...@@ -117,11 +118,37 @@ uptr GetMmapGranularity() { return _zx_system_get_page_size(); }
117118
118sanitizer_shadow_bounds_t ShadowBounds;119sanitizer_shadow_bounds_t ShadowBounds;
119120
121// Any sanitizer that utilizes shadow should explicitly call whenever it's
122// appropriate for that sanitizer to reference shadow bounds. For ASan, this is
123// done in `InitializeShadowMemory` and for HWASan, this is done in
124// `InitShadow`.
120void InitShadowBounds() { ShadowBounds = __sanitizer_shadow_bounds(); }125void InitShadowBounds() { ShadowBounds = __sanitizer_shadow_bounds(); }
121126
127// TODO(leonardchan): It's not immediately clear from a user perspective if
128// `GetMaxUserVirtualAddress` should be called exatly once on runtime startup
129// or can be called multiple times. Currently it looks like most instances of
130// `GetMaxUserVirtualAddress` are meant to be called once, but if someone
131// decides to call this multiple times in the future, we should have a separate
132// function that's ok to call multiple times. Ideally we would just invoke this
133// syscall once. Also for Fuchsia, this syscall technically gets invoked twice
134// since `__sanitizer_shadow_bounds` also invokes this syscall under the hood.
122uptr GetMaxUserVirtualAddress() {135uptr GetMaxUserVirtualAddress() {
123 InitShadowBounds();136 zx_info_vmar_t info;
124 return ShadowBounds.memory_limit - 1;137 zx_status_t status = _zx_object_get_info(_zx_vmar_root_self(), ZX_INFO_VMAR,
138 &info, sizeof(info), NULL, NULL);
139 CHECK_EQ(status, ZX_OK);
140
141 // Find the top of the accessible address space.
142 uintptr_t top = info.base + info.len;
143
144 // Round it up to a power-of-two size. There may be some pages at
145 // the top that can't actually be mapped, but for purposes of the
146 // the shadow, we'll pretend they could be.
147 int bit = (sizeof(uintptr_t) * CHAR_BIT) - __builtin_clzl(top);
148 if (top != (uintptr_t)1 << bit)
149 top = (uintptr_t)1 << (bit + 1);
150
151 return top - 1;
125}152}
126153
127uptr GetMaxVirtualAddress() { return GetMaxUserVirtualAddress(); }154uptr GetMaxVirtualAddress() { return GetMaxUserVirtualAddress(); }
lib/libtsan/sanitizer_common/sanitizer_haiku.cpp+2-2
...@@ -231,12 +231,12 @@ uptr internal_execve(const char *filename, char *const argv[],...@@ -231,12 +231,12 @@ uptr internal_execve(const char *filename, char *const argv[],
231}231}
232232
233# if 0233# if 0
234tid_t GetTid() {234ThreadID GetTid() {
235 DEFINE__REAL(int, _lwp_self);235 DEFINE__REAL(int, _lwp_self);
236 return _REAL(_lwp_self);236 return _REAL(_lwp_self);
237}237}
238238
239int TgKill(pid_t pid, tid_t tid, int sig) {239int TgKill(pid_t pid, ThreadID tid, int sig) {
240 DEFINE__REAL(int, _lwp_kill, int a, int b);240 DEFINE__REAL(int, _lwp_kill, int a, int b);
241 (void)pid;241 (void)pid;
242 return _REAL(_lwp_kill, tid, sig);242 return _REAL(_lwp_kill, tid, sig);
lib/libtsan/sanitizer_common/sanitizer_internal_defs.h+1-1
...@@ -209,7 +209,7 @@ typedef long ssize;...@@ -209,7 +209,7 @@ typedef long ssize;
209typedef sptr ssize;209typedef sptr ssize;
210#endif210#endif
211211
212typedef u64 tid_t;212typedef u64 ThreadID;
213213
214// ----------- ATTENTION -------------214// ----------- ATTENTION -------------
215// This header should NOT include any other headers to avoid portability issues.215// This header should NOT include any other headers to avoid portability issues.
lib/libtsan/sanitizer_common/sanitizer_libc.cpp+8
...@@ -190,6 +190,14 @@ uptr internal_strlcat(char *dst, const char *src, uptr maxlen) {...@@ -190,6 +190,14 @@ uptr internal_strlcat(char *dst, const char *src, uptr maxlen) {
190 return dstlen + srclen;190 return dstlen + srclen;
191}191}
192192
193char* internal_strcat(char* dst, const char* src) {
194 uptr len = internal_strlen(dst);
195 uptr i;
196 for (i = 0; src[i]; i++) dst[len + i] = src[i];
197 dst[len + i] = 0;
198 return dst;
199}
200
193char *internal_strncat(char *dst, const char *src, uptr n) {201char *internal_strncat(char *dst, const char *src, uptr n) {
194 uptr len = internal_strlen(dst);202 uptr len = internal_strlen(dst);
195 uptr i;203 uptr i;
lib/libtsan/sanitizer_common/sanitizer_libc.h+1
...@@ -59,6 +59,7 @@ char *internal_strdup(const char *s);...@@ -59,6 +59,7 @@ char *internal_strdup(const char *s);
59uptr internal_strlen(const char *s);59uptr internal_strlen(const char *s);
60uptr internal_strlcat(char *dst, const char *src, uptr maxlen);60uptr internal_strlcat(char *dst, const char *src, uptr maxlen);
61char *internal_strncat(char *dst, const char *src, uptr n);61char *internal_strncat(char *dst, const char *src, uptr n);
62char* internal_strcat(char* dst, const char* src);
62int internal_strncmp(const char *s1, const char *s2, uptr n);63int internal_strncmp(const char *s1, const char *s2, uptr n);
63uptr internal_strlcpy(char *dst, const char *src, uptr maxlen);64uptr internal_strlcpy(char *dst, const char *src, uptr maxlen);
64char *internal_strncpy(char *dst, const char *src, uptr n);65char *internal_strncpy(char *dst, const char *src, uptr n);
lib/libtsan/sanitizer_common/sanitizer_linux.cpp+15-7
...@@ -635,7 +635,7 @@ bool DirExists(const char *path) {...@@ -635,7 +635,7 @@ bool DirExists(const char *path) {
635}635}
636636
637# if !SANITIZER_NETBSD637# if !SANITIZER_NETBSD
638tid_t GetTid() {638ThreadID GetTid() {
639# if SANITIZER_FREEBSD639# if SANITIZER_FREEBSD
640 long Tid;640 long Tid;
641 thr_self(&Tid);641 thr_self(&Tid);
...@@ -649,7 +649,7 @@ tid_t GetTid() {...@@ -649,7 +649,7 @@ tid_t GetTid() {
649# endif649# endif
650}650}
651651
652int TgKill(pid_t pid, tid_t tid, int sig) {652int TgKill(pid_t pid, ThreadID tid, int sig) {
653# if SANITIZER_LINUX653# if SANITIZER_LINUX
654 return internal_syscall(SYSCALL(tgkill), pid, tid, sig);654 return internal_syscall(SYSCALL(tgkill), pid, tid, sig);
655# elif SANITIZER_FREEBSD655# elif SANITIZER_FREEBSD
...@@ -1091,7 +1091,7 @@ ThreadLister::ThreadLister(pid_t pid) : buffer_(4096) {...@@ -1091,7 +1091,7 @@ ThreadLister::ThreadLister(pid_t pid) : buffer_(4096) {
1091}1091}
10921092
1093ThreadLister::Result ThreadLister::ListThreads(1093ThreadLister::Result ThreadLister::ListThreads(
1094 InternalMmapVector<tid_t> *threads) {1094 InternalMmapVector<ThreadID> *threads) {
1095 int descriptor = internal_open(task_path_.data(), O_RDONLY | O_DIRECTORY);1095 int descriptor = internal_open(task_path_.data(), O_RDONLY | O_DIRECTORY);
1096 if (internal_iserror(descriptor)) {1096 if (internal_iserror(descriptor)) {
1097 Report("Can't open %s for reading.\n", task_path_.data());1097 Report("Can't open %s for reading.\n", task_path_.data());
...@@ -1146,7 +1146,7 @@ ThreadLister::Result ThreadLister::ListThreads(...@@ -1146,7 +1146,7 @@ ThreadLister::Result ThreadLister::ListThreads(
1146 }1146 }
1147}1147}
11481148
1149const char *ThreadLister::LoadStatus(tid_t tid) {1149const char *ThreadLister::LoadStatus(ThreadID tid) {
1150 status_path_.clear();1150 status_path_.clear();
1151 status_path_.AppendF("%s/%llu/status", task_path_.data(), tid);1151 status_path_.AppendF("%s/%llu/status", task_path_.data(), tid);
1152 auto cleanup = at_scope_exit([&] {1152 auto cleanup = at_scope_exit([&] {
...@@ -1159,7 +1159,7 @@ const char *ThreadLister::LoadStatus(tid_t tid) {...@@ -1159,7 +1159,7 @@ const char *ThreadLister::LoadStatus(tid_t tid) {
1159 return buffer_.data();1159 return buffer_.data();
1160}1160}
11611161
1162bool ThreadLister::IsAlive(tid_t tid) {1162bool ThreadLister::IsAlive(ThreadID tid) {
1163 // /proc/%d/task/%d/status uses same call to detect alive threads as1163 // /proc/%d/task/%d/status uses same call to detect alive threads as
1164 // proc_task_readdir. See task_state implementation in Linux.1164 // proc_task_readdir. See task_state implementation in Linux.
1165 static const char kPrefix[] = "\nPPid:";1165 static const char kPrefix[] = "\nPPid:";
...@@ -1289,7 +1289,7 @@ uptr GetPageSize() {...@@ -1289,7 +1289,7 @@ uptr GetPageSize() {
12891289
1290uptr ReadBinaryName(/*out*/ char *buf, uptr buf_len) {1290uptr ReadBinaryName(/*out*/ char *buf, uptr buf_len) {
1291# if SANITIZER_HAIKU1291# if SANITIZER_HAIKU
1292 int cookie = 0;1292 int32 cookie = 0;
1293 image_info info;1293 image_info info;
1294 const char *argv0 = "<UNKNOWN>";1294 const char *argv0 = "<UNKNOWN>";
1295 while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) {1295 while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) {
...@@ -1989,7 +1989,10 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {...@@ -1989,7 +1989,10 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const {
1989# elif SANITIZER_NETBSD1989# elif SANITIZER_NETBSD
1990 uptr err = ucontext->uc_mcontext.__gregs[_REG_ERR];1990 uptr err = ucontext->uc_mcontext.__gregs[_REG_ERR];
1991# elif SANITIZER_HAIKU1991# elif SANITIZER_HAIKU
1992 uptr err = ucontext->uc_mcontext.r13;1992 uptr err = 0; // FIXME: ucontext->uc_mcontext.r13;
1993 // The err register was added on the main branch and not
1994 // available with the current release. To be reverted later.
1995 // https://github.com/haiku/haiku/commit/11adda21aa4e6b24f71a496868a44d7607bc3764
1993# elif SANITIZER_SOLARIS && defined(__i386__)1996# elif SANITIZER_SOLARIS && defined(__i386__)
1994 const int Err = 13;1997 const int Err = 13;
1995 uptr err = ucontext->uc_mcontext.gregs[Err];1998 uptr err = ucontext->uc_mcontext.gregs[Err];
...@@ -2619,6 +2622,11 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {...@@ -2619,6 +2622,11 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
2619 *pc = ucontext->uc_mcontext.mc_eip;2622 *pc = ucontext->uc_mcontext.mc_eip;
2620 *bp = ucontext->uc_mcontext.mc_ebp;2623 *bp = ucontext->uc_mcontext.mc_ebp;
2621 *sp = ucontext->uc_mcontext.mc_esp;2624 *sp = ucontext->uc_mcontext.mc_esp;
2625# elif SANITIZER_HAIKU
2626 ucontext_t *ucontext = (ucontext_t *)context;
2627 *pc = ucontext->uc_mcontext.eip;
2628 *bp = ucontext->uc_mcontext.ebp;
2629 *sp = ucontext->uc_mcontext.esp;
2622# else2630# else
2623 ucontext_t *ucontext = (ucontext_t *)context;2631 ucontext_t *ucontext = (ucontext_t *)context;
2624# if SANITIZER_SOLARIS2632# if SANITIZER_SOLARIS
lib/libtsan/sanitizer_common/sanitizer_linux.h+3-3
...@@ -108,11 +108,11 @@ class ThreadLister {...@@ -108,11 +108,11 @@ class ThreadLister {
108 Incomplete,108 Incomplete,
109 Ok,109 Ok,
110 };110 };
111 Result ListThreads(InternalMmapVector<tid_t> *threads);111 Result ListThreads(InternalMmapVector<ThreadID> *threads);
112 const char *LoadStatus(tid_t tid);112 const char *LoadStatus(ThreadID tid);
113113
114 private:114 private:
115 bool IsAlive(tid_t tid);115 bool IsAlive(ThreadID tid);
116116
117 InternalScopedString task_path_;117 InternalScopedString task_path_;
118 InternalScopedString status_path_;118 InternalScopedString status_path_;
lib/libtsan/sanitizer_common/sanitizer_linux_libcdep.cpp+1
...@@ -29,6 +29,7 @@...@@ -29,6 +29,7 @@
29# include "sanitizer_solaris.h"29# include "sanitizer_solaris.h"
3030
31# if SANITIZER_HAIKU31# if SANITIZER_HAIKU
32# define _GNU_SOURCE
32# define _DEFAULT_SOURCE33# define _DEFAULT_SOURCE
33# endif34# endif
3435
lib/libtsan/sanitizer_common/sanitizer_mac.cpp+255-104
...@@ -22,6 +22,11 @@...@@ -22,6 +22,11 @@
22# endif22# endif
23# include <stdio.h>23# include <stdio.h>
2424
25// Start searching for available memory region past PAGEZERO, which is
26// 4KB on 32-bit and 4GB on 64-bit.
27# define GAP_SEARCH_START_ADDRESS \
28 ((SANITIZER_WORDSIZE == 32) ? 0x000000001000 : 0x000100000000)
29
25# include "sanitizer_common.h"30# include "sanitizer_common.h"
26# include "sanitizer_file.h"31# include "sanitizer_file.h"
27# include "sanitizer_flags.h"32# include "sanitizer_flags.h"
...@@ -58,9 +63,11 @@ extern char ***_NSGetArgv(void);...@@ -58,9 +63,11 @@ extern char ***_NSGetArgv(void);
58# include <dlfcn.h> // for dladdr()63# include <dlfcn.h> // for dladdr()
59# include <errno.h>64# include <errno.h>
60# include <fcntl.h>65# include <fcntl.h>
66# include <inttypes.h>
61# include <libkern/OSAtomic.h>67# include <libkern/OSAtomic.h>
62# include <mach-o/dyld.h>68# include <mach-o/dyld.h>
63# include <mach/mach.h>69# include <mach/mach.h>
70# include <mach/mach_error.h>
64# include <mach/mach_time.h>71# include <mach/mach_time.h>
65# include <mach/vm_statistics.h>72# include <mach/vm_statistics.h>
66# include <malloc/malloc.h>73# include <malloc/malloc.h>
...@@ -96,8 +103,16 @@ extern "C" {...@@ -96,8 +103,16 @@ extern "C" {
96 natural_t *nesting_depth,103 natural_t *nesting_depth,
97 vm_region_recurse_info_t info,104 vm_region_recurse_info_t info,
98 mach_msg_type_number_t *infoCnt);105 mach_msg_type_number_t *infoCnt);
106
107 extern const void* _dyld_get_shared_cache_range(size_t* length);
99}108}
100109
110# if !SANITIZER_GO
111// Weak symbol no-op when TSan is not linked
112SANITIZER_WEAK_ATTRIBUTE extern void __tsan_set_in_internal_write_call(
113 bool value) {}
114# endif
115
101namespace __sanitizer {116namespace __sanitizer {
102117
103#include "sanitizer_syscall_generic.inc"118#include "sanitizer_syscall_generic.inc"
...@@ -168,7 +183,15 @@ uptr internal_read(fd_t fd, void *buf, uptr count) {...@@ -168,7 +183,15 @@ uptr internal_read(fd_t fd, void *buf, uptr count) {
168}183}
169184
170uptr internal_write(fd_t fd, const void *buf, uptr count) {185uptr internal_write(fd_t fd, const void *buf, uptr count) {
186# if SANITIZER_GO
171 return write(fd, buf, count);187 return write(fd, buf, count);
188# else
189 // We need to disable interceptors when writing in TSan
190 __tsan_set_in_internal_write_call(true);
191 uptr res = write(fd, buf, count);
192 __tsan_set_in_internal_write_call(false);
193 return res;
194# endif
172}195}
173196
174uptr internal_stat(const char *path, void *buf) {197uptr internal_stat(const char *path, void *buf) {
...@@ -258,53 +281,43 @@ int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,...@@ -258,53 +281,43 @@ int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
258 (size_t)newlen);281 (size_t)newlen);
259}282}
260283
261static fd_t internal_spawn_impl(const char *argv[], const char *envp[],284bool internal_spawn(const char* argv[], const char* envp[], pid_t* pid,
262 pid_t *pid) {285 fd_t fd_stdin, fd_t fd_stdout) {
263 fd_t primary_fd = kInvalidFd;286 // NOTE: Caller ensures that fd_stdin and fd_stdout are not 0, 1, or 2, since
264 fd_t secondary_fd = kInvalidFd;287 // this can break communication.
288 //
289 // NOTE: Caller is responsible for closing fd_stdin after the process has
290 // died.
265291
292 int res;
266 auto fd_closer = at_scope_exit([&] {293 auto fd_closer = at_scope_exit([&] {
267 internal_close(primary_fd);294 // NOTE: We intentionally do not close fd_stdin since this can
268 internal_close(secondary_fd);295 // cause us to receive a fatal SIGPIPE if the process dies.
296 internal_close(fd_stdout);
269 });297 });
270298
271 // We need a new pseudoterminal to avoid buffering problems. The 'atos' tool
272 // in particular detects when it's talking to a pipe and forgets to flush the
273 // output stream after sending a response.
274 primary_fd = posix_openpt(O_RDWR);
275 if (primary_fd == kInvalidFd)
276 return kInvalidFd;
277
278 int res = grantpt(primary_fd) || unlockpt(primary_fd);
279 if (res != 0) return kInvalidFd;
280
281 // Use TIOCPTYGNAME instead of ptsname() to avoid threading problems.
282 char secondary_pty_name[128];
283 res = ioctl(primary_fd, TIOCPTYGNAME, secondary_pty_name);
284 if (res == -1) return kInvalidFd;
285
286 secondary_fd = internal_open(secondary_pty_name, O_RDWR);
287 if (secondary_fd == kInvalidFd)
288 return kInvalidFd;
289
290 // File descriptor actions299 // File descriptor actions
291 posix_spawn_file_actions_t acts;300 posix_spawn_file_actions_t acts;
292 res = posix_spawn_file_actions_init(&acts);301 res = posix_spawn_file_actions_init(&acts);
293 if (res != 0) return kInvalidFd;302 if (res != 0)
303 return false;
294304
295 auto acts_cleanup = at_scope_exit([&] {305 auto acts_cleanup = at_scope_exit([&] {
296 posix_spawn_file_actions_destroy(&acts);306 posix_spawn_file_actions_destroy(&acts);
297 });307 });
298308
299 res = posix_spawn_file_actions_adddup2(&acts, secondary_fd, STDIN_FILENO) ||309 res = posix_spawn_file_actions_adddup2(&acts, fd_stdin, STDIN_FILENO) ||
300 posix_spawn_file_actions_adddup2(&acts, secondary_fd, STDOUT_FILENO) ||310 posix_spawn_file_actions_adddup2(&acts, fd_stdout, STDOUT_FILENO) ||
301 posix_spawn_file_actions_addclose(&acts, secondary_fd);311 posix_spawn_file_actions_addclose(&acts, fd_stdin) ||
302 if (res != 0) return kInvalidFd;312 posix_spawn_file_actions_addclose(&acts, fd_stdout);
313 if (res != 0)
314 return false;
303315
304 // Spawn attributes316 // Spawn attributes
305 posix_spawnattr_t attrs;317 posix_spawnattr_t attrs;
306 res = posix_spawnattr_init(&attrs);318 res = posix_spawnattr_init(&attrs);
307 if (res != 0) return kInvalidFd;319 if (res != 0)
320 return false;
308321
309 auto attrs_cleanup = at_scope_exit([&] {322 auto attrs_cleanup = at_scope_exit([&] {
310 posix_spawnattr_destroy(&attrs);323 posix_spawnattr_destroy(&attrs);
...@@ -313,50 +326,17 @@ static fd_t internal_spawn_impl(const char *argv[], const char *envp[],...@@ -313,50 +326,17 @@ static fd_t internal_spawn_impl(const char *argv[], const char *envp[],
313 // In the spawned process, close all file descriptors that are not explicitly326 // In the spawned process, close all file descriptors that are not explicitly
314 // described by the file actions object. This is Darwin-specific extension.327 // described by the file actions object. This is Darwin-specific extension.
315 res = posix_spawnattr_setflags(&attrs, POSIX_SPAWN_CLOEXEC_DEFAULT);328 res = posix_spawnattr_setflags(&attrs, POSIX_SPAWN_CLOEXEC_DEFAULT);
316 if (res != 0) return kInvalidFd;329 if (res != 0)
330 return false;
317331
318 // posix_spawn332 // posix_spawn
319 char **argv_casted = const_cast<char **>(argv);333 char **argv_casted = const_cast<char **>(argv);
320 char **envp_casted = const_cast<char **>(envp);334 char **envp_casted = const_cast<char **>(envp);
321 res = posix_spawn(pid, argv[0], &acts, &attrs, argv_casted, envp_casted);335 res = posix_spawn(pid, argv[0], &acts, &attrs, argv_casted, envp_casted);
322 if (res != 0) return kInvalidFd;336 if (res != 0)
323337 return false;
324 // Disable echo in the new terminal, disable CR.
325 struct termios termflags;
326 tcgetattr(primary_fd, &termflags);
327 termflags.c_oflag &= ~ONLCR;
328 termflags.c_lflag &= ~ECHO;
329 tcsetattr(primary_fd, TCSANOW, &termflags);
330
331 // On success, do not close primary_fd on scope exit.
332 fd_t fd = primary_fd;
333 primary_fd = kInvalidFd;
334
335 return fd;
336}
337
338fd_t internal_spawn(const char *argv[], const char *envp[], pid_t *pid) {
339 // The client program may close its stdin and/or stdout and/or stderr thus
340 // allowing open/posix_openpt to reuse file descriptors 0, 1 or 2. In this
341 // case the communication is broken if either the parent or the child tries to
342 // close or duplicate these descriptors. We temporarily reserve these
343 // descriptors here to prevent this.
344 fd_t low_fds[3];
345 size_t count = 0;
346
347 for (; count < 3; count++) {
348 low_fds[count] = posix_openpt(O_RDWR);
349 if (low_fds[count] >= STDERR_FILENO)
350 break;
351 }
352
353 fd_t fd = internal_spawn_impl(argv, envp, pid);
354
355 for (; count > 0; count--) {
356 internal_close(low_fds[count]);
357 }
358338
359 return fd;339 return true;
360}340}
361341
362uptr internal_rename(const char *oldpath, const char *newpath) {342uptr internal_rename(const char *oldpath, const char *newpath) {
...@@ -394,8 +374,8 @@ bool DirExists(const char *path) {...@@ -394,8 +374,8 @@ bool DirExists(const char *path) {
394 return S_ISDIR(st.st_mode);374 return S_ISDIR(st.st_mode);
395}375}
396376
397tid_t GetTid() {377ThreadID GetTid() {
398 tid_t tid;378 ThreadID tid;
399 pthread_threadid_np(nullptr, &tid);379 pthread_threadid_np(nullptr, &tid);
400 return tid;380 return tid;
401}381}
...@@ -769,11 +749,17 @@ void internal_join_thread(void *th) { pthread_join((pthread_t)th, 0); }...@@ -769,11 +749,17 @@ void internal_join_thread(void *th) { pthread_join((pthread_t)th, 0); }
769static Mutex syslog_lock;749static Mutex syslog_lock;
770# endif750# endif
771751
752# if SANITIZER_DRIVERKIT
753# define SANITIZER_OS_LOG os_log
754# else
755# define SANITIZER_OS_LOG os_log_error
756# endif
757
772void WriteOneLineToSyslog(const char *s) {758void WriteOneLineToSyslog(const char *s) {
773#if !SANITIZER_GO759#if !SANITIZER_GO
774 syslog_lock.CheckLocked();760 syslog_lock.CheckLocked();
775 if (GetMacosAlignedVersion() >= MacosVersion(10, 12)) {761 if (GetMacosAlignedVersion() >= MacosVersion(10, 12)) {
776 os_log_error(OS_LOG_DEFAULT, "%{public}s", s);762 SANITIZER_OS_LOG(OS_LOG_DEFAULT, "%{public}s", s);
777 } else {763 } else {
778#pragma clang diagnostic push764#pragma clang diagnostic push
779// as_log is deprecated.765// as_log is deprecated.
...@@ -837,22 +823,22 @@ void LogMessageOnPrintf(const char *str) {...@@ -837,22 +823,22 @@ void LogMessageOnPrintf(const char *str) {
837823
838void LogFullErrorReport(const char *buffer) {824void LogFullErrorReport(const char *buffer) {
839# if !SANITIZER_GO825# if !SANITIZER_GO
840 // Log with os_log_error. This will make it into the crash log.826 // When logging with os_log_error this will make it into the crash log.
841 if (internal_strncmp(SanitizerToolName, "AddressSanitizer",827 if (internal_strncmp(SanitizerToolName, "AddressSanitizer",
842 sizeof("AddressSanitizer") - 1) == 0)828 sizeof("AddressSanitizer") - 1) == 0)
843 os_log_error(OS_LOG_DEFAULT, "Address Sanitizer reported a failure.");829 SANITIZER_OS_LOG(OS_LOG_DEFAULT, "Address Sanitizer reported a failure.");
844 else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer",830 else if (internal_strncmp(SanitizerToolName, "UndefinedBehaviorSanitizer",
845 sizeof("UndefinedBehaviorSanitizer") - 1) == 0)831 sizeof("UndefinedBehaviorSanitizer") - 1) == 0)
846 os_log_error(OS_LOG_DEFAULT,832 SANITIZER_OS_LOG(OS_LOG_DEFAULT,
847 "Undefined Behavior Sanitizer reported a failure.");833 "Undefined Behavior Sanitizer reported a failure.");
848 else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer",834 else if (internal_strncmp(SanitizerToolName, "ThreadSanitizer",
849 sizeof("ThreadSanitizer") - 1) == 0)835 sizeof("ThreadSanitizer") - 1) == 0)
850 os_log_error(OS_LOG_DEFAULT, "Thread Sanitizer reported a failure.");836 SANITIZER_OS_LOG(OS_LOG_DEFAULT, "Thread Sanitizer reported a failure.");
851 else837 else
852 os_log_error(OS_LOG_DEFAULT, "Sanitizer tool reported a failure.");838 SANITIZER_OS_LOG(OS_LOG_DEFAULT, "Sanitizer tool reported a failure.");
853839
854 if (common_flags()->log_to_syslog)840 if (common_flags()->log_to_syslog)
855 os_log_error(OS_LOG_DEFAULT, "Consult syslog for more information.");841 SANITIZER_OS_LOG(OS_LOG_DEFAULT, "Consult syslog for more information.");
856842
857 // Log to syslog.843 // Log to syslog.
858 // The logging on OS X may call pthread_create so we need the threading844 // The logging on OS X may call pthread_create so we need the threading
...@@ -933,7 +919,17 @@ static void DisableMmapExcGuardExceptions() {...@@ -933,7 +919,17 @@ static void DisableMmapExcGuardExceptions() {
933 RTLD_DEFAULT, "task_set_exc_guard_behavior");919 RTLD_DEFAULT, "task_set_exc_guard_behavior");
934 if (set_behavior == nullptr) return;920 if (set_behavior == nullptr) return;
935 const task_exc_guard_behavior_t task_exc_guard_none = 0;921 const task_exc_guard_behavior_t task_exc_guard_none = 0;
936 set_behavior(mach_task_self(), task_exc_guard_none);922 kern_return_t res = set_behavior(mach_task_self(), task_exc_guard_none);
923 if (res != KERN_SUCCESS) {
924 Report(
925 "WARN: task_set_exc_guard_behavior returned %d (%s), "
926 "mmap may fail unexpectedly.\n",
927 res, mach_error_string(res));
928 if (res == KERN_DENIED)
929 Report(
930 "HINT: Check that task_set_exc_guard_behavior is allowed by "
931 "sandbox.\n");
932 }
937}933}
938934
939static void VerifyInterceptorsWorking();935static void VerifyInterceptorsWorking();
...@@ -1100,6 +1096,67 @@ static void StripEnv() {...@@ -1100,6 +1096,67 @@ static void StripEnv() {
1100}1096}
1101#endif // SANITIZER_GO1097#endif // SANITIZER_GO
11021098
1099// Prints out a consolidated memory map: contiguous regions
1100// are merged together.
1101static void PrintVmmap() {
1102 const mach_vm_address_t max_vm_address = GetMaxVirtualAddress() + 1;
1103 mach_vm_address_t address = GAP_SEARCH_START_ADDRESS;
1104 kern_return_t kr = KERN_SUCCESS;
1105
1106 Report("Memory map:\n");
1107 mach_vm_address_t last = 0;
1108 mach_vm_address_t lastsz = 0;
1109
1110 while (1) {
1111 mach_vm_size_t vmsize = 0;
1112 natural_t depth = 0;
1113 vm_region_submap_short_info_data_64_t vminfo;
1114 mach_msg_type_number_t count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
1115 kr = mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth,
1116 (vm_region_info_t)&vminfo, &count);
1117
1118 if (kr == KERN_DENIED) {
1119 Report(
1120 "ERROR: mach_vm_region_recurse got KERN_DENIED when printing memory "
1121 "map.\n");
1122 Report(
1123 "HINT: Check whether mach_vm_region_recurse is allowed by "
1124 "sandbox.\n");
1125 }
1126
1127 if (kr == KERN_SUCCESS && address < max_vm_address) {
1128 if (last + lastsz == address) {
1129 // This region is contiguous with the last; merge together.
1130 lastsz += vmsize;
1131 } else {
1132 if (lastsz)
1133 Printf("|| `[%p, %p]` || size=0x%016" PRIx64 " ||\n", (void*)last,
1134 (void*)(last + lastsz), lastsz);
1135
1136 last = address;
1137 lastsz = vmsize;
1138 }
1139 address += vmsize;
1140 } else {
1141 // We've reached the end of the memory map. Print the last remaining
1142 // region, if there is one.
1143 if (lastsz)
1144 Printf("|| `[%p, %p]` || size=0x%016" PRIx64 " ||\n", (void*)last,
1145 (void*)(last + lastsz), lastsz);
1146
1147 break;
1148 }
1149 }
1150}
1151
1152static void ReportShadowAllocFail(uptr shadow_size_bytes, uptr alignment) {
1153 Report(
1154 "FATAL: Failed to allocate shadow memory. Tried to allocate %p bytes "
1155 "(alignment=%p).\n",
1156 (void*)shadow_size_bytes, (void*)alignment);
1157 PrintVmmap();
1158}
1159
1103char **GetArgv() {1160char **GetArgv() {
1104 return *_NSGetArgv();1161 return *_NSGetArgv();
1105}1162}
...@@ -1207,10 +1264,11 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,...@@ -1207,10 +1264,11 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
1207 if (new_max_vm < max_occupied_addr) {1264 if (new_max_vm < max_occupied_addr) {
1208 Report("Unable to find a memory range for dynamic shadow.\n");1265 Report("Unable to find a memory range for dynamic shadow.\n");
1209 Report(1266 Report(
1210 "space_size = %p, largest_gap_found = %p, max_occupied_addr = %p, "1267 "\tspace_size = %p\n\tlargest_gap_found = %p\n\tmax_occupied_addr "
1211 "new_max_vm = %p\n",1268 "= %p\n\tnew_max_vm = %p\n",
1212 (void *)space_size, (void *)largest_gap_found,1269 (void*)space_size, (void*)largest_gap_found, (void*)max_occupied_addr,
1213 (void *)max_occupied_addr, (void *)new_max_vm);1270 (void*)new_max_vm);
1271 ReportShadowAllocFail(shadow_size_bytes, alignment);
1214 CHECK(0 && "cannot place shadow");1272 CHECK(0 && "cannot place shadow");
1215 }1273 }
1216 RestrictMemoryToMaxAddress(new_max_vm);1274 RestrictMemoryToMaxAddress(new_max_vm);
...@@ -1221,6 +1279,7 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,...@@ -1221,6 +1279,7 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
1221 nullptr, nullptr);1279 nullptr, nullptr);
1222 if (shadow_start == 0) {1280 if (shadow_start == 0) {
1223 Report("Unable to find a memory range after restricting VM.\n");1281 Report("Unable to find a memory range after restricting VM.\n");
1282 ReportShadowAllocFail(shadow_size_bytes, alignment);
1224 CHECK(0 && "cannot place shadow after restricting vm");1283 CHECK(0 && "cannot place shadow after restricting vm");
1225 }1284 }
1226 }1285 }
...@@ -1229,6 +1288,25 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,...@@ -1229,6 +1288,25 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
1229 return shadow_start;1288 return shadow_start;
1230}1289}
12311290
1291// Returns a list of ranges which must be covered by shadow memory,
1292// and cannot overlap with any fixed mappings made by a sanitizer.
1293// This can ensure that the sanitizer runtime does not map over
1294// platform-reserved regions.
1295void GetAppReservedRanges(InternalMmapVector<ReservedRange>& ranges) {
1296 ranges.clear();
1297
1298# if SANITIZER_OSX
1299 // On macOS, the first 512GB are platform-reserved (some of which
1300 // may also be available to applications).
1301 ranges.push_back({0x1000UL, 0x8000000000UL});
1302# endif
1303
1304 VReport(2, "App ranges:\n");
1305 for (auto& [range_start, range_end] : ranges) {
1306 VReport(2, " [%p, %p]\n", range_start, range_end);
1307 }
1308}
1309
1232uptr MapDynamicShadowAndAliases(uptr shadow_size, uptr alias_size,1310uptr MapDynamicShadowAndAliases(uptr shadow_size, uptr alias_size,
1233 uptr num_aliases, uptr ring_buffer_size) {1311 uptr num_aliases, uptr ring_buffer_size) {
1234 CHECK(false && "HWASan aliasing is unimplemented on Mac");1312 CHECK(false && "HWASan aliasing is unimplemented on Mac");
...@@ -1236,40 +1314,61 @@ uptr MapDynamicShadowAndAliases(uptr shadow_size, uptr alias_size,...@@ -1236,40 +1314,61 @@ uptr MapDynamicShadowAndAliases(uptr shadow_size, uptr alias_size,
1236}1314}
12371315
1238uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,1316uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
1239 uptr *largest_gap_found,1317 uptr* largest_gap_found,
1240 uptr *max_occupied_addr) {1318 uptr* max_occupied_addr) {
1241 typedef vm_region_submap_short_info_data_64_t RegionInfo;
1242 enum { kRegionInfoSize = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 };
1243 // Start searching for available memory region past PAGEZERO, which is
1244 // 4KB on 32-bit and 4GB on 64-bit.
1245 mach_vm_address_t start_address =
1246 (SANITIZER_WORDSIZE == 32) ? 0x000000001000 : 0x000100000000;
1247
1248 const mach_vm_address_t max_vm_address = GetMaxVirtualAddress() + 1;1319 const mach_vm_address_t max_vm_address = GetMaxVirtualAddress() + 1;
1249 mach_vm_address_t address = start_address;1320 mach_vm_address_t address = GAP_SEARCH_START_ADDRESS;
1250 mach_vm_address_t free_begin = start_address;1321 mach_vm_address_t free_begin = GAP_SEARCH_START_ADDRESS;
1322
1323 // Restrict the search to be after any reserved ranges
1324 InternalMmapVector<ReservedRange> app_ranges;
1325 GetAppReservedRanges(app_ranges);
1326
1327 for (auto& [range_start, range_end] : app_ranges) {
1328 address = Max(address, (mach_vm_address_t)range_end);
1329 free_begin = Max(free_begin, (mach_vm_address_t)range_end);
1330 }
1331
1251 kern_return_t kr = KERN_SUCCESS;1332 kern_return_t kr = KERN_SUCCESS;
1252 if (largest_gap_found) *largest_gap_found = 0;1333 if (largest_gap_found) *largest_gap_found = 0;
1253 if (max_occupied_addr) *max_occupied_addr = 0;1334 if (max_occupied_addr) *max_occupied_addr = 0;
1254 while (kr == KERN_SUCCESS) {1335 while (kr == KERN_SUCCESS) {
1255 mach_vm_size_t vmsize = 0;1336 mach_vm_size_t vmsize = 0;
1256 natural_t depth = 0;1337 natural_t depth = 0;
1257 RegionInfo vminfo;1338 vm_region_submap_short_info_data_64_t vminfo;
1258 mach_msg_type_number_t count = kRegionInfoSize;1339 mach_msg_type_number_t count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
1259 kr = mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth,1340 kr = mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth,
1260 (vm_region_info_t)&vminfo, &count);1341 (vm_region_info_t)&vminfo, &count);
12611342
1262 // There are cases where going beyond the processes' max vm does1343 if (kr == KERN_SUCCESS) {
1263 // not return KERN_INVALID_ADDRESS so we check for going beyond that1344 // There are cases where going beyond the processes' max vm does
1264 // max address as well.1345 // not return KERN_INVALID_ADDRESS so we check for going beyond that
1265 if (kr == KERN_INVALID_ADDRESS || address > max_vm_address) {1346 // max address as well.
1347 if (address > max_vm_address) {
1348 address = max_vm_address;
1349 kr = -1; // break after this iteration.
1350 }
1351
1352 if (max_occupied_addr)
1353 *max_occupied_addr = address + vmsize;
1354 } else if (kr == KERN_INVALID_ADDRESS) {
1266 // No more regions beyond "address", consider the gap at the end of VM.1355 // No more regions beyond "address", consider the gap at the end of VM.
1267 address = max_vm_address;1356 address = max_vm_address;
1268 vmsize = 0;1357
1269 kr = -1; // break after this iteration.1358 // We will break after this iteration anyway since kr != KERN_SUCCESS
1359 } else if (kr == KERN_DENIED) {
1360 Report("ERROR: Unable to find a memory range for dynamic shadow.\n");
1361 Report("HINT: Ensure mach_vm_region_recurse is allowed under sandbox.\n");
1362 Die();
1270 } else {1363 } else {
1271 if (max_occupied_addr) *max_occupied_addr = address + vmsize;1364 Report(
1365 "WARNING: mach_vm_region_recurse returned unexpected code %d (%s)\n",
1366 kr, mach_error_string(kr));
1367 DCHECK(false && "mach_vm_region_recurse returned unexpected code");
1368 break; // address is not valid unless KERN_SUCCESS, therefore we must not
1369 // use it.
1272 }1370 }
1371
1273 if (free_begin != address) {1372 if (free_begin != address) {
1274 // We found a free region [free_begin..address-1].1373 // We found a free region [free_begin..address-1].
1275 uptr gap_start = RoundUpTo((uptr)free_begin + left_padding, alignment);1374 uptr gap_start = RoundUpTo((uptr)free_begin + left_padding, alignment);
...@@ -1292,6 +1391,58 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,...@@ -1292,6 +1391,58 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
1292 return 0;1391 return 0;
1293}1392}
12941393
1394// This function (when used during initialization when there is
1395// only a single thread), can be used to verify that a range
1396// of memory hasn't already been mapped, and won't be mapped
1397// later in the shared cache.
1398//
1399// If the syscall mach_vm_region_recurse fails (due to sandbox),
1400// we assume that the memory is not mapped so that execution can continue.
1401//
1402// NOTE: range_end is inclusive
1403//
1404// WARNING: This function must NOT allocate memory, since it is
1405// used in InitializeShadowMemory between where we search for
1406// space for shadow and where we actually allocate it.
1407bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
1408 mach_vm_size_t vmsize = 0;
1409 natural_t depth = 0;
1410 vm_region_submap_short_info_data_64_t vminfo;
1411 mach_msg_type_number_t count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
1412 mach_vm_address_t address = range_start;
1413
1414 // First, check if the range is already mapped.
1415 kern_return_t kr =
1416 mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth,
1417 (vm_region_info_t)&vminfo, &count);
1418
1419 if (kr == KERN_DENIED) {
1420 Report(
1421 "WARN: mach_vm_region_recurse returned KERN_DENIED when checking "
1422 "whether an address is mapped.\n");
1423 Report("HINT: Is mach_vm_region_recurse allowed by sandbox?\n");
1424 }
1425
1426 if (kr == KERN_SUCCESS && !IntervalsAreSeparate(address, address + vmsize - 1,
1427 range_start, range_end)) {
1428 // Overlaps with already-mapped memory
1429 return false;
1430 }
1431
1432 size_t cacheLength;
1433 uptr cacheStart = (uptr)_dyld_get_shared_cache_range(&cacheLength);
1434
1435 if (cacheStart &&
1436 !IntervalsAreSeparate(cacheStart, cacheStart + cacheLength - 1,
1437 range_start, range_end)) {
1438 // Overlaps with shared cache region
1439 return false;
1440 }
1441
1442 // We believe this address is available.
1443 return true;
1444}
1445
1295// FIXME implement on this platform.1446// FIXME implement on this platform.
1296void GetMemoryProfile(fill_profile_f cb, uptr *stats) {}1447void GetMemoryProfile(fill_profile_f cb, uptr *stats) {}
12971448
lib/libtsan/sanitizer_common/sanitizer_mac.h+5
...@@ -58,8 +58,13 @@ struct DarwinKernelVersion : VersionBase<DarwinKernelVersion> {...@@ -58,8 +58,13 @@ struct DarwinKernelVersion : VersionBase<DarwinKernelVersion> {
58 DarwinKernelVersion(u16 major, u16 minor) : VersionBase(major, minor) {}58 DarwinKernelVersion(u16 major, u16 minor) : VersionBase(major, minor) {}
59};59};
6060
61struct ReservedRange {
62 uptr beg, end;
63};
64
61MacosVersion GetMacosAlignedVersion();65MacosVersion GetMacosAlignedVersion();
62DarwinKernelVersion GetDarwinKernelVersion();66DarwinKernelVersion GetDarwinKernelVersion();
67void GetAppReservedRanges(InternalMmapVector<ReservedRange>& ranges);
6368
64char **GetEnviron();69char **GetEnviron();
6570
lib/libtsan/sanitizer_common/sanitizer_netbsd.cpp+2-2
...@@ -229,12 +229,12 @@ uptr internal_execve(const char *filename, char *const argv[],...@@ -229,12 +229,12 @@ uptr internal_execve(const char *filename, char *const argv[],
229 return _sys_execve(filename, argv, envp);229 return _sys_execve(filename, argv, envp);
230}230}
231231
232tid_t GetTid() {232ThreadID GetTid() {
233 DEFINE__REAL(int, _lwp_self);233 DEFINE__REAL(int, _lwp_self);
234 return _REAL(_lwp_self);234 return _REAL(_lwp_self);
235}235}
236236
237int TgKill(pid_t pid, tid_t tid, int sig) {237int TgKill(pid_t pid, ThreadID tid, int sig) {
238 DEFINE__REAL(int, _lwp_kill, int a, int b);238 DEFINE__REAL(int, _lwp_kill, int a, int b);
239 (void)pid;239 (void)pid;
240 return _REAL(_lwp_kill, tid, sig);240 return _REAL(_lwp_kill, tid, sig);
lib/libtsan/sanitizer_common/sanitizer_platform.h+27-1
...@@ -319,7 +319,11 @@...@@ -319,7 +319,11 @@
319#endif319#endif
320320
321// The first address that can be returned by mmap.321// The first address that can be returned by mmap.
322#define SANITIZER_MMAP_BEGIN 0322#if SANITIZER_AIX && SANITIZER_WORDSIZE == 64
323# define SANITIZER_MMAP_BEGIN 0x0a00'0000'0000'0000ULL
324#else
325# define SANITIZER_MMAP_BEGIN 0
326#endif
323327
324// The range of addresses which can be returned my mmap.328// The range of addresses which can be returned my mmap.
325// FIXME: this value should be different on different platforms. Larger values329// FIXME: this value should be different on different platforms. Larger values
...@@ -482,4 +486,26 @@...@@ -482,4 +486,26 @@
482# define SANITIZER_START_BACKGROUND_THREAD_IN_ASAN_INTERNAL 0486# define SANITIZER_START_BACKGROUND_THREAD_IN_ASAN_INTERNAL 0
483#endif487#endif
484488
489#if SANITIZER_LINUX
490# if SANITIZER_GLIBC
491// Workaround for
492// glibc/commit/3d3572f59059e2b19b8541ea648a6172136ec42e
493// Linux: Keep termios ioctl constants strictly internal
494# if __GLIBC_PREREQ(2, 41)
495# define SANITIZER_TERMIOS_IOCTL_CONSTANTS 0
496# else
497# define SANITIZER_TERMIOS_IOCTL_CONSTANTS 1
498# endif
499# else
500# define SANITIZER_TERMIOS_IOCTL_CONSTANTS 1
501# endif
502#endif
503
504#if SANITIZER_APPLE && SANITIZER_WORDSIZE == 64
505// MTE uses the lower half of the top byte.
506# define STRIP_MTE_TAG(addr) ((addr) & ~((uptr)0x0f << 56))
507#else
508# define STRIP_MTE_TAG(addr) (addr)
509#endif
510
485#endif // SANITIZER_PLATFORM_H511#endif // SANITIZER_PLATFORM_H
lib/libtsan/sanitizer_common/sanitizer_platform_interceptors.h+5-4
...@@ -167,7 +167,7 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,...@@ -167,7 +167,7 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
167167
168#define SANITIZER_INTERCEPT_STRLEN SI_NOT_FUCHSIA168#define SANITIZER_INTERCEPT_STRLEN SI_NOT_FUCHSIA
169#define SANITIZER_INTERCEPT_STRNLEN (SI_NOT_MAC && SI_NOT_FUCHSIA)169#define SANITIZER_INTERCEPT_STRNLEN (SI_NOT_MAC && SI_NOT_FUCHSIA)
170#define SANITIZER_INTERCEPT_STRCMP (SI_NOT_FUCHSIA && SI_NOT_AIX)170#define SANITIZER_INTERCEPT_STRCMP SI_NOT_FUCHSIA
171#define SANITIZER_INTERCEPT_STRSTR SI_NOT_FUCHSIA171#define SANITIZER_INTERCEPT_STRSTR SI_NOT_FUCHSIA
172#define SANITIZER_INTERCEPT_STRCASESTR (SI_POSIX && SI_NOT_AIX)172#define SANITIZER_INTERCEPT_STRCASESTR (SI_POSIX && SI_NOT_AIX)
173#define SANITIZER_INTERCEPT_STRTOK SI_NOT_FUCHSIA173#define SANITIZER_INTERCEPT_STRTOK SI_NOT_FUCHSIA
...@@ -179,8 +179,8 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,...@@ -179,8 +179,8 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
179#define SANITIZER_INTERCEPT_TEXTDOMAIN SI_LINUX_NOT_ANDROID || SI_SOLARIS179#define SANITIZER_INTERCEPT_TEXTDOMAIN SI_LINUX_NOT_ANDROID || SI_SOLARIS
180#define SANITIZER_INTERCEPT_STRCASECMP SI_POSIX180#define SANITIZER_INTERCEPT_STRCASECMP SI_POSIX
181#define SANITIZER_INTERCEPT_MEMSET 1181#define SANITIZER_INTERCEPT_MEMSET 1
182#define SANITIZER_INTERCEPT_MEMMOVE SI_NOT_AIX182#define SANITIZER_INTERCEPT_MEMMOVE 1
183#define SANITIZER_INTERCEPT_MEMCPY SI_NOT_AIX183#define SANITIZER_INTERCEPT_MEMCPY 1
184#define SANITIZER_INTERCEPT_MEMCMP SI_NOT_FUCHSIA184#define SANITIZER_INTERCEPT_MEMCMP SI_NOT_FUCHSIA
185#define SANITIZER_INTERCEPT_BCMP \185#define SANITIZER_INTERCEPT_BCMP \
186 SANITIZER_INTERCEPT_MEMCMP && \186 SANITIZER_INTERCEPT_MEMCMP && \
...@@ -551,7 +551,8 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,...@@ -551,7 +551,8 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
551#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_NETBSD)551#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_NETBSD)
552#define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID552#define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID
553#define SANITIZER_INTERCEPT_WCSLEN 1553#define SANITIZER_INTERCEPT_WCSLEN 1
554#define SANITIZER_INTERCEPT_WCSCAT SI_POSIX554#define SANITIZER_INTERCEPT_WCSNLEN 1
555#define SANITIZER_INTERCEPT_WCSCAT (SI_POSIX || SI_WINDOWS)
555#define SANITIZER_INTERCEPT_WCSDUP SI_POSIX556#define SANITIZER_INTERCEPT_WCSDUP SI_POSIX
556#define SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION (!SI_WINDOWS && SI_NOT_FUCHSIA)557#define SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION (!SI_WINDOWS && SI_NOT_FUCHSIA)
557#define SANITIZER_INTERCEPT_BSD_SIGNAL SI_ANDROID558#define SANITIZER_INTERCEPT_BSD_SIGNAL SI_ANDROID
lib/libtsan/sanitizer_common/sanitizer_platform_limits_posix.cpp+4-4
...@@ -779,16 +779,16 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);...@@ -779,16 +779,16 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
779 unsigned IOCTL_SOUND_PCM_WRITE_FILTER = SOUND_PCM_WRITE_FILTER;779 unsigned IOCTL_SOUND_PCM_WRITE_FILTER = SOUND_PCM_WRITE_FILTER;
780#endif // SOUND_VERSION780#endif // SOUND_VERSION
781 unsigned IOCTL_TCFLSH = TCFLSH;781 unsigned IOCTL_TCFLSH = TCFLSH;
782 unsigned IOCTL_TCGETA = TCGETA;782# if SANITIZER_TERMIOS_IOCTL_CONSTANTS
783 unsigned IOCTL_TCGETS = TCGETS;783 unsigned IOCTL_TCGETS = TCGETS;
784# endif
784 unsigned IOCTL_TCSBRK = TCSBRK;785 unsigned IOCTL_TCSBRK = TCSBRK;
785 unsigned IOCTL_TCSBRKP = TCSBRKP;786 unsigned IOCTL_TCSBRKP = TCSBRKP;
786 unsigned IOCTL_TCSETA = TCSETA;787# if SANITIZER_TERMIOS_IOCTL_CONSTANTS
787 unsigned IOCTL_TCSETAF = TCSETAF;
788 unsigned IOCTL_TCSETAW = TCSETAW;
789 unsigned IOCTL_TCSETS = TCSETS;788 unsigned IOCTL_TCSETS = TCSETS;
790 unsigned IOCTL_TCSETSF = TCSETSF;789 unsigned IOCTL_TCSETSF = TCSETSF;
791 unsigned IOCTL_TCSETSW = TCSETSW;790 unsigned IOCTL_TCSETSW = TCSETSW;
791# endif
792 unsigned IOCTL_TCXONC = TCXONC;792 unsigned IOCTL_TCXONC = TCXONC;
793 unsigned IOCTL_TIOCGLCKTRMIOS = TIOCGLCKTRMIOS;793 unsigned IOCTL_TIOCGLCKTRMIOS = TIOCGLCKTRMIOS;
794 unsigned IOCTL_TIOCGSOFTCAR = TIOCGSOFTCAR;794 unsigned IOCTL_TIOCGSOFTCAR = TIOCGSOFTCAR;
lib/libtsan/sanitizer_common/sanitizer_platform_limits_posix.h+32-6
...@@ -32,6 +32,8 @@...@@ -32,6 +32,8 @@
32# elif SANITIZER_GLIBC || SANITIZER_ANDROID32# elif SANITIZER_GLIBC || SANITIZER_ANDROID
33# define SANITIZER_HAS_STAT64 133# define SANITIZER_HAS_STAT64 1
34# define SANITIZER_HAS_STATFS64 134# define SANITIZER_HAS_STATFS64 1
35# elif SANITIZER_HAIKU
36# include <stdint.h>
35# endif37# endif
3638
37# if defined(__sparc__)39# if defined(__sparc__)
...@@ -102,6 +104,8 @@ const unsigned struct_kernel_stat_sz = SANITIZER_ANDROID...@@ -102,6 +104,8 @@ const unsigned struct_kernel_stat_sz = SANITIZER_ANDROID
102 ? FIRST_32_SECOND_64(104, 128)104 ? FIRST_32_SECOND_64(104, 128)
103# if defined(_ABIN32) && _MIPS_SIM == _ABIN32105# if defined(_ABIN32) && _MIPS_SIM == _ABIN32
104 : FIRST_32_SECOND_64(176, 216);106 : FIRST_32_SECOND_64(176, 216);
107# elif SANITIZER_MUSL
108 : FIRST_32_SECOND_64(160, 208);
105# else109# else
106 : FIRST_32_SECOND_64(160, 216);110 : FIRST_32_SECOND_64(160, 216);
107# endif111# endif
...@@ -476,6 +480,30 @@ struct __sanitizer_cmsghdr {...@@ -476,6 +480,30 @@ struct __sanitizer_cmsghdr {
476 int cmsg_level;480 int cmsg_level;
477 int cmsg_type;481 int cmsg_type;
478};482};
483# elif SANITIZER_MUSL
484struct __sanitizer_msghdr {
485 void *msg_name;
486 unsigned msg_namelen;
487 struct __sanitizer_iovec *msg_iov;
488 int msg_iovlen;
489# if SANITIZER_WORDSIZE == 64
490 int __pad1;
491# endif
492 void *msg_control;
493 unsigned msg_controllen;
494# if SANITIZER_WORDSIZE == 64
495 int __pad2;
496# endif
497 int msg_flags;
498};
499struct __sanitizer_cmsghdr {
500 unsigned cmsg_len;
501# if SANITIZER_WORDSIZE == 64
502 int __pad1;
503# endif
504 int cmsg_level;
505 int cmsg_type;
506};
479# else507# else
480// In POSIX, int msg_iovlen; socklen_t msg_controllen; socklen_t cmsg_len; but508// In POSIX, int msg_iovlen; socklen_t msg_controllen; socklen_t cmsg_len; but
481// many implementations don't conform to the standard.509// many implementations don't conform to the standard.
...@@ -603,7 +631,7 @@ typedef unsigned long __sanitizer_sigset_t;...@@ -603,7 +631,7 @@ typedef unsigned long __sanitizer_sigset_t;
603# elif SANITIZER_APPLE631# elif SANITIZER_APPLE
604typedef unsigned __sanitizer_sigset_t;632typedef unsigned __sanitizer_sigset_t;
605# elif SANITIZER_HAIKU633# elif SANITIZER_HAIKU
606typedef unsigned long __sanitizer_sigset_t;634typedef uint64_t __sanitizer_sigset_t;
607# elif SANITIZER_LINUX635# elif SANITIZER_LINUX
608struct __sanitizer_sigset_t {636struct __sanitizer_sigset_t {
609 // The size is determined by looking at sizeof of real sigset_t on linux.637 // The size is determined by looking at sizeof of real sigset_t on linux.
...@@ -1312,16 +1340,14 @@ extern unsigned IOCTL_SNDCTL_COPR_SENDMSG;...@@ -1312,16 +1340,14 @@ extern unsigned IOCTL_SNDCTL_COPR_SENDMSG;
1312extern unsigned IOCTL_SNDCTL_COPR_WCODE;1340extern unsigned IOCTL_SNDCTL_COPR_WCODE;
1313extern unsigned IOCTL_SNDCTL_COPR_WDATA;1341extern unsigned IOCTL_SNDCTL_COPR_WDATA;
1314extern unsigned IOCTL_TCFLSH;1342extern unsigned IOCTL_TCFLSH;
1315extern unsigned IOCTL_TCGETA;
1316extern unsigned IOCTL_TCGETS;
1317extern unsigned IOCTL_TCSBRK;1343extern unsigned IOCTL_TCSBRK;
1318extern unsigned IOCTL_TCSBRKP;1344extern unsigned IOCTL_TCSBRKP;
1319extern unsigned IOCTL_TCSETA;1345# if SANITIZER_TERMIOS_IOCTL_CONSTANTS
1320extern unsigned IOCTL_TCSETAF;1346extern unsigned IOCTL_TCGETS;
1321extern unsigned IOCTL_TCSETAW;
1322extern unsigned IOCTL_TCSETS;1347extern unsigned IOCTL_TCSETS;
1323extern unsigned IOCTL_TCSETSF;1348extern unsigned IOCTL_TCSETSF;
1324extern unsigned IOCTL_TCSETSW;1349extern unsigned IOCTL_TCSETSW;
1350# endif
1325extern unsigned IOCTL_TCXONC;1351extern unsigned IOCTL_TCXONC;
1326extern unsigned IOCTL_TIOCGLCKTRMIOS;1352extern unsigned IOCTL_TIOCGLCKTRMIOS;
1327extern unsigned IOCTL_TIOCGSOFTCAR;1353extern unsigned IOCTL_TIOCGSOFTCAR;
lib/libtsan/sanitizer_common/sanitizer_posix.cpp+3-12
...@@ -225,17 +225,9 @@ void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, OFF_T offset) {...@@ -225,17 +225,9 @@ void *MapWritableFileToMemory(void *addr, uptr size, fd_t fd, OFF_T offset) {
225 return (void *)p;225 return (void *)p;
226}226}
227227
228static inline bool IntervalsAreSeparate(uptr start1, uptr end1,228# if !SANITIZER_APPLE
229 uptr start2, uptr end2) {
230 CHECK(start1 <= end1);
231 CHECK(start2 <= end2);
232 return (end1 < start2) || (end2 < start1);
233}
234
235// FIXME: this is thread-unsafe, but should not cause problems most of the time.229// FIXME: this is thread-unsafe, but should not cause problems most of the time.
236// When the shadow is mapped only a single thread usually exists (plus maybe230// When the shadow is mapped only a single thread usually exists
237// several worker threads on Mac, which aren't expected to map big chunks of
238// memory).
239bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {231bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
240 MemoryMappingLayout proc_maps(/*cache_enabled*/true);232 MemoryMappingLayout proc_maps(/*cache_enabled*/true);
241 if (proc_maps.Error())233 if (proc_maps.Error())
...@@ -251,7 +243,6 @@ bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {...@@ -251,7 +243,6 @@ bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
251 return true;243 return true;
252}244}
253245
254#if !SANITIZER_APPLE
255void DumpProcessMap() {246void DumpProcessMap() {
256 MemoryMappingLayout proc_maps(/*cache_enabled*/true);247 MemoryMappingLayout proc_maps(/*cache_enabled*/true);
257 const sptr kBufSize = 4095;248 const sptr kBufSize = 4095;
...@@ -265,7 +256,7 @@ void DumpProcessMap() {...@@ -265,7 +256,7 @@ void DumpProcessMap() {
265 Report("End of process memory map.\n");256 Report("End of process memory map.\n");
266 UnmapOrDie(filename, kBufSize);257 UnmapOrDie(filename, kBufSize);
267}258}
268#endif259# endif
269260
270const char *GetPwd() {261const char *GetPwd() {
271 return GetEnv("PWD");262 return GetEnv("PWD");
lib/libtsan/sanitizer_common/sanitizer_posix.h+2-1
...@@ -67,7 +67,8 @@ uptr internal_ptrace(int request, int pid, void *addr, void *data);...@@ -67,7 +67,8 @@ uptr internal_ptrace(int request, int pid, void *addr, void *data);
67uptr internal_waitpid(int pid, int *status, int options);67uptr internal_waitpid(int pid, int *status, int options);
6868
69int internal_fork();69int internal_fork();
70fd_t internal_spawn(const char *argv[], const char *envp[], pid_t *pid);70bool internal_spawn(const char* argv[], const char* envp[], pid_t* pid,
71 fd_t fd_stdin, fd_t fd_stdout);
7172
72int internal_sysctl(const int *name, unsigned int namelen, void *oldp,73int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
73 uptr *oldlenp, const void *newp, uptr newlen);74 uptr *oldlenp, const void *newp, uptr newlen);
lib/libtsan/sanitizer_common/sanitizer_posix_libcdep.cpp+19
...@@ -47,6 +47,8 @@ typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);...@@ -47,6 +47,8 @@ typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
4747
48namespace __sanitizer {48namespace __sanitizer {
4949
50[[maybe_unused]] static atomic_uint8_t signal_handler_is_from_sanitizer[64];
51
50u32 GetUid() {52u32 GetUid() {
51 return getuid();53 return getuid();
52}54}
...@@ -210,6 +212,20 @@ void UnsetAlternateSignalStack() {...@@ -210,6 +212,20 @@ void UnsetAlternateSignalStack() {
210 UnmapOrDie(oldstack.ss_sp, oldstack.ss_size);212 UnmapOrDie(oldstack.ss_sp, oldstack.ss_size);
211}213}
212214
215bool IsSignalHandlerFromSanitizer(int signum) {
216 return atomic_load(&signal_handler_is_from_sanitizer[signum],
217 memory_order_relaxed);
218}
219
220bool SetSignalHandlerFromSanitizer(int signum, bool new_state) {
221 if (signum < 0 || static_cast<unsigned>(signum) >=
222 ARRAY_SIZE(signal_handler_is_from_sanitizer))
223 return false;
224
225 return atomic_exchange(&signal_handler_is_from_sanitizer[signum], new_state,
226 memory_order_relaxed);
227}
228
213static void MaybeInstallSigaction(int signum,229static void MaybeInstallSigaction(int signum,
214 SignalHandlerType handler) {230 SignalHandlerType handler) {
215 if (GetHandleSignalMode(signum) == kHandleSignalNo) return;231 if (GetHandleSignalMode(signum) == kHandleSignalNo) return;
...@@ -223,6 +239,9 @@ static void MaybeInstallSigaction(int signum,...@@ -223,6 +239,9 @@ static void MaybeInstallSigaction(int signum,
223 if (common_flags()->use_sigaltstack) sigact.sa_flags |= SA_ONSTACK;239 if (common_flags()->use_sigaltstack) sigact.sa_flags |= SA_ONSTACK;
224 CHECK_EQ(0, internal_sigaction(signum, &sigact, nullptr));240 CHECK_EQ(0, internal_sigaction(signum, &sigact, nullptr));
225 VReport(1, "Installed the sigaction for signal %d\n", signum);241 VReport(1, "Installed the sigaction for signal %d\n", signum);
242
243 if (common_flags()->cloak_sanitizer_signal_handlers)
244 SetSignalHandlerFromSanitizer(signum, true);
226}245}
227246
228void InstallDeadlySignalHandlers(SignalHandlerType handler) {247void InstallDeadlySignalHandlers(SignalHandlerType handler) {
lib/libtsan/sanitizer_common/sanitizer_procmaps_mac.cpp+102-37
...@@ -20,18 +20,21 @@...@@ -20,18 +20,21 @@
20#include <mach/mach.h>20#include <mach/mach.h>
2121
22// These are not available in older macOS SDKs.22// These are not available in older macOS SDKs.
23#ifndef CPU_SUBTYPE_X86_64_H23# ifndef CPU_SUBTYPE_X86_64_H
24#define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t)8) /* Haswell */24# define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t)8) /* Haswell */
25#endif25# endif
26#ifndef CPU_SUBTYPE_ARM_V7S26# ifndef CPU_SUBTYPE_ARM_V7S
27#define CPU_SUBTYPE_ARM_V7S ((cpu_subtype_t)11) /* Swift */27# define CPU_SUBTYPE_ARM_V7S ((cpu_subtype_t)11) /* Swift */
28#endif28# endif
29#ifndef CPU_SUBTYPE_ARM_V7K29# ifndef CPU_SUBTYPE_ARM_V7K
30#define CPU_SUBTYPE_ARM_V7K ((cpu_subtype_t)12)30# define CPU_SUBTYPE_ARM_V7K ((cpu_subtype_t)12)
31#endif31# endif
32#ifndef CPU_TYPE_ARM6432# ifndef CPU_TYPE_ARM64
33#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)33# define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
34#endif34# endif
35# ifndef CPU_SUBTYPE_ARM64E
36# define CPU_SUBTYPE_ARM64E ((cpu_subtype_t)2)
37# endif
3538
36namespace __sanitizer {39namespace __sanitizer {
3740
...@@ -42,7 +45,6 @@ struct MemoryMappedSegmentData {...@@ -42,7 +45,6 @@ struct MemoryMappedSegmentData {
42 const char *current_load_cmd_addr;45 const char *current_load_cmd_addr;
43 u32 lc_type;46 u32 lc_type;
44 uptr base_virt_addr;47 uptr base_virt_addr;
45 uptr addr_mask;
46};48};
4749
48template <typename Section>50template <typename Section>
...@@ -51,12 +53,62 @@ static void NextSectionLoad(LoadedModule *module, MemoryMappedSegmentData *data,...@@ -51,12 +53,62 @@ static void NextSectionLoad(LoadedModule *module, MemoryMappedSegmentData *data,
51 const Section *sc = (const Section *)data->current_load_cmd_addr;53 const Section *sc = (const Section *)data->current_load_cmd_addr;
52 data->current_load_cmd_addr += sizeof(Section);54 data->current_load_cmd_addr += sizeof(Section);
5355
54 uptr sec_start = (sc->addr & data->addr_mask) + data->base_virt_addr;56 uptr sec_start = sc->addr + data->base_virt_addr;
55 uptr sec_end = sec_start + sc->size;57 uptr sec_end = sec_start + sc->size;
56 module->addAddressRange(sec_start, sec_end, /*executable=*/false, isWritable,58 module->addAddressRange(sec_start, sec_end, /*executable=*/false, isWritable,
57 sc->sectname);59 sc->sectname);
58}60}
5961
62static bool VerifyMemoryMapping(MemoryMappingLayout* mapping) {
63 InternalMmapVector<LoadedModule> modules;
64 modules.reserve(128); // matches DumpProcessMap
65 mapping->DumpListOfModules(&modules);
66
67 InternalMmapVector<LoadedModule::AddressRange> segments;
68 for (uptr i = 0; i < modules.size(); ++i) {
69 for (auto& range : modules[i].ranges()) {
70 if (range.beg == range.end)
71 continue;
72 segments.push_back(range);
73 }
74 }
75
76 // Verify that none of the segments overlap:
77 // 1. Sort the segments by the start address
78 // 2. Check that every segment starts after the previous one ends.
79 Sort(segments.data(), segments.size(),
80 [](LoadedModule::AddressRange& a, LoadedModule::AddressRange& b) {
81 return a.beg < b.beg;
82 });
83
84 // To avoid spam, we only print the report message once-per-process.
85 static bool invalid_module_map_reported = false;
86 bool well_formed = true;
87
88 for (size_t i = 1; i < segments.size(); i++) {
89 uptr cur_start = segments[i].beg;
90 uptr prev_end = segments[i - 1].end;
91 if (cur_start < prev_end) {
92 well_formed = false;
93 VReport(2, "Overlapping mappings: %s start = %p, %s end = %p\n",
94 segments[i].name, (void*)cur_start, segments[i - 1].name,
95 (void*)prev_end);
96 if (!invalid_module_map_reported) {
97 Report(
98 "WARN: Invalid dyld module map detected. This is most likely a bug "
99 "in the sanitizer.\n");
100 Report("WARN: Backtraces may be unreliable.\n");
101 invalid_module_map_reported = true;
102 }
103 }
104 }
105
106 for (auto& m : modules) m.clear();
107
108 mapping->Reset();
109 return well_formed;
110}
111
60void MemoryMappedSegment::AddAddressRanges(LoadedModule *module) {112void MemoryMappedSegment::AddAddressRanges(LoadedModule *module) {
61 // Don't iterate over sections when the caller hasn't set up the113 // Don't iterate over sections when the caller hasn't set up the
62 // data pointer, when there are no sections, or when the segment114 // data pointer, when there are no sections, or when the segment
...@@ -82,6 +134,7 @@ void MemoryMappedSegment::AddAddressRanges(LoadedModule *module) {...@@ -82,6 +134,7 @@ void MemoryMappedSegment::AddAddressRanges(LoadedModule *module) {
82134
83MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {135MemoryMappingLayout::MemoryMappingLayout(bool cache_enabled) {
84 Reset();136 Reset();
137 VerifyMemoryMapping(this);
85}138}
86139
87MemoryMappingLayout::~MemoryMappingLayout() {140MemoryMappingLayout::~MemoryMappingLayout() {
...@@ -123,7 +176,7 @@ void MemoryMappingLayout::Reset() {...@@ -123,7 +176,7 @@ void MemoryMappingLayout::Reset() {
123// The dyld load address should be unchanged throughout process execution,176// The dyld load address should be unchanged throughout process execution,
124// and it is expensive to compute once many libraries have been loaded,177// and it is expensive to compute once many libraries have been loaded,
125// so cache it here and do not reset.178// so cache it here and do not reset.
126static mach_header *dyld_hdr = 0;179static const mach_header* dyld_hdr = 0;
127static const char kDyldPath[] = "/usr/lib/dyld";180static const char kDyldPath[] = "/usr/lib/dyld";
128static const int kDyldImageIdx = -1;181static const int kDyldImageIdx = -1;
129182
...@@ -187,17 +240,22 @@ typedef struct dyld_shared_cache_dylib_text_info...@@ -187,17 +240,22 @@ typedef struct dyld_shared_cache_dylib_text_info
187240
188extern bool _dyld_get_shared_cache_uuid(uuid_t uuid);241extern bool _dyld_get_shared_cache_uuid(uuid_t uuid);
189extern const void *_dyld_get_shared_cache_range(size_t *length);242extern const void *_dyld_get_shared_cache_range(size_t *length);
243extern intptr_t _dyld_get_image_slide(const struct mach_header* mh);
190extern int dyld_shared_cache_iterate_text(244extern int dyld_shared_cache_iterate_text(
191 const uuid_t cacheUuid,245 const uuid_t cacheUuid,
192 void (^callback)(const dyld_shared_cache_dylib_text_info *info));246 void (^callback)(const dyld_shared_cache_dylib_text_info *info));
247SANITIZER_WEAK_IMPORT const struct mach_header* _dyld_get_dyld_header(void);
193} // extern "C"248} // extern "C"
194249
195static mach_header *GetDyldImageHeaderViaSharedCache() {250static const mach_header* GetDyldImageHeaderViaSharedCache() {
196 uuid_t uuid;251 uuid_t uuid;
197 bool hasCache = _dyld_get_shared_cache_uuid(uuid);252 bool hasCache = _dyld_get_shared_cache_uuid(uuid);
198 if (!hasCache)253 if (!hasCache)
199 return nullptr;254 return nullptr;
200255
256 if (&_dyld_get_dyld_header != nullptr)
257 return _dyld_get_dyld_header();
258
201 size_t cacheLength;259 size_t cacheLength;
202 __block uptr cacheStart = (uptr)_dyld_get_shared_cache_range(&cacheLength);260 __block uptr cacheStart = (uptr)_dyld_get_shared_cache_range(&cacheLength);
203 CHECK(cacheStart && cacheLength);261 CHECK(cacheStart && cacheLength);
...@@ -255,23 +313,21 @@ static bool NextSegmentLoad(MemoryMappedSegment *segment,...@@ -255,23 +313,21 @@ static bool NextSegmentLoad(MemoryMappedSegment *segment,
255 layout_data->current_load_cmd_count--;313 layout_data->current_load_cmd_count--;
256 if (((const load_command *)lc)->cmd == kLCSegment) {314 if (((const load_command *)lc)->cmd == kLCSegment) {
257 const SegmentCommand* sc = (const SegmentCommand *)lc;315 const SegmentCommand* sc = (const SegmentCommand *)lc;
258 uptr base_virt_addr, addr_mask;316 if (internal_strcmp(sc->segname, "__LINKEDIT") == 0) {
259 if (layout_data->current_image == kDyldImageIdx) {317 // The LINKEDIT sections are for internal linker use, and may alias
260 base_virt_addr = (uptr)get_dyld_hdr();318 // with the LINKEDIT section for other modules. (If we included them,
261 // vmaddr is masked with 0xfffff because on macOS versions < 10.12,319 // our memory map would contain overlappping sections.)
262 // it contains an absolute address rather than an offset for dyld.320 return false;
263 // To make matters even more complicated, this absolute address321 }
264 // isn't actually the absolute segment address, but the offset portion322
265 // of the address is accurate when combined with the dyld base address,323 uptr base_virt_addr;
266 // and the mask will give just this offset.324 if (layout_data->current_image == kDyldImageIdx)
267 addr_mask = 0xfffff;325 base_virt_addr = (uptr)_dyld_get_image_slide(get_dyld_hdr());
268 } else {326 else
269 base_virt_addr =327 base_virt_addr =
270 (uptr)_dyld_get_image_vmaddr_slide(layout_data->current_image);328 (uptr)_dyld_get_image_vmaddr_slide(layout_data->current_image);
271 addr_mask = ~0;
272 }
273329
274 segment->start = (sc->vmaddr & addr_mask) + base_virt_addr;330 segment->start = sc->vmaddr + base_virt_addr;
275 segment->end = segment->start + sc->vmsize;331 segment->end = segment->start + sc->vmsize;
276 // Most callers don't need section information, so only fill this struct332 // Most callers don't need section information, so only fill this struct
277 // when required.333 // when required.
...@@ -281,9 +337,9 @@ static bool NextSegmentLoad(MemoryMappedSegment *segment,...@@ -281,9 +337,9 @@ static bool NextSegmentLoad(MemoryMappedSegment *segment,
281 (const char *)lc + sizeof(SegmentCommand);337 (const char *)lc + sizeof(SegmentCommand);
282 seg_data->lc_type = kLCSegment;338 seg_data->lc_type = kLCSegment;
283 seg_data->base_virt_addr = base_virt_addr;339 seg_data->base_virt_addr = base_virt_addr;
284 seg_data->addr_mask = addr_mask;
285 internal_strncpy(seg_data->name, sc->segname,340 internal_strncpy(seg_data->name, sc->segname,
286 ARRAY_SIZE(seg_data->name));341 ARRAY_SIZE(seg_data->name));
342 seg_data->name[ARRAY_SIZE(seg_data->name) - 1] = 0;
287 }343 }
288344
289 // Return the initial protection.345 // Return the initial protection.
...@@ -297,6 +353,7 @@ static bool NextSegmentLoad(MemoryMappedSegment *segment,...@@ -297,6 +353,7 @@ static bool NextSegmentLoad(MemoryMappedSegment *segment,
297 ? kDyldPath353 ? kDyldPath
298 : _dyld_get_image_name(layout_data->current_image);354 : _dyld_get_image_name(layout_data->current_image);
299 internal_strncpy(segment->filename, src, segment->filename_size);355 internal_strncpy(segment->filename, src, segment->filename_size);
356 segment->filename[segment->filename_size - 1] = 0;
300 }357 }
301 segment->arch = layout_data->current_arch;358 segment->arch = layout_data->current_arch;
302 internal_memcpy(segment->uuid, layout_data->current_uuid, kModuleUUIDSize);359 internal_memcpy(segment->uuid, layout_data->current_uuid, kModuleUUIDSize);
...@@ -311,18 +368,26 @@ ModuleArch ModuleArchFromCpuType(cpu_type_t cputype, cpu_subtype_t cpusubtype) {...@@ -311,18 +368,26 @@ ModuleArch ModuleArchFromCpuType(cpu_type_t cputype, cpu_subtype_t cpusubtype) {
311 case CPU_TYPE_I386:368 case CPU_TYPE_I386:
312 return kModuleArchI386;369 return kModuleArchI386;
313 case CPU_TYPE_X86_64:370 case CPU_TYPE_X86_64:
314 if (cpusubtype == CPU_SUBTYPE_X86_64_ALL) return kModuleArchX86_64;371 if (cpusubtype == CPU_SUBTYPE_X86_64_ALL)
315 if (cpusubtype == CPU_SUBTYPE_X86_64_H) return kModuleArchX86_64H;372 return kModuleArchX86_64;
373 if (cpusubtype == CPU_SUBTYPE_X86_64_H)
374 return kModuleArchX86_64H;
316 CHECK(0 && "Invalid subtype of x86_64");375 CHECK(0 && "Invalid subtype of x86_64");
317 return kModuleArchUnknown;376 return kModuleArchUnknown;
318 case CPU_TYPE_ARM:377 case CPU_TYPE_ARM:
319 if (cpusubtype == CPU_SUBTYPE_ARM_V6) return kModuleArchARMV6;378 if (cpusubtype == CPU_SUBTYPE_ARM_V6)
320 if (cpusubtype == CPU_SUBTYPE_ARM_V7) return kModuleArchARMV7;379 return kModuleArchARMV6;
321 if (cpusubtype == CPU_SUBTYPE_ARM_V7S) return kModuleArchARMV7S;380 if (cpusubtype == CPU_SUBTYPE_ARM_V7)
322 if (cpusubtype == CPU_SUBTYPE_ARM_V7K) return kModuleArchARMV7K;381 return kModuleArchARMV7;
382 if (cpusubtype == CPU_SUBTYPE_ARM_V7S)
383 return kModuleArchARMV7S;
384 if (cpusubtype == CPU_SUBTYPE_ARM_V7K)
385 return kModuleArchARMV7K;
323 CHECK(0 && "Invalid subtype of ARM");386 CHECK(0 && "Invalid subtype of ARM");
324 return kModuleArchUnknown;387 return kModuleArchUnknown;
325 case CPU_TYPE_ARM64:388 case CPU_TYPE_ARM64:
389 if (cpusubtype == CPU_SUBTYPE_ARM64E)
390 return kModuleArchARM64E;
326 return kModuleArchARM64;391 return kModuleArchARM64;
327 default:392 default:
328 CHECK(0 && "Invalid CPU type");393 CHECK(0 && "Invalid CPU type");
lib/libtsan/sanitizer_common/sanitizer_redefine_builtins.h+1-1
...@@ -15,7 +15,7 @@...@@ -15,7 +15,7 @@
15# define SANITIZER_REDEFINE_BUILTINS_H15# define SANITIZER_REDEFINE_BUILTINS_H
1616
17// The asm hack only works with GCC and Clang.17// The asm hack only works with GCC and Clang.
18# if !defined(_WIN32) && !defined(_AIX)18# if !defined(_WIN32) && !defined(_AIX) && !defined(__APPLE__)
1919
20asm(R"(20asm(R"(
21 .set memcpy, __sanitizer_internal_memcpy21 .set memcpy, __sanitizer_internal_memcpy
lib/libtsan/sanitizer_common/sanitizer_signal_interceptors.inc+40-2
...@@ -45,6 +45,8 @@ using namespace __sanitizer;...@@ -45,6 +45,8 @@ using namespace __sanitizer;
45INTERCEPTOR(uptr, bsd_signal, int signum, uptr handler) {45INTERCEPTOR(uptr, bsd_signal, int signum, uptr handler) {
46 SIGNAL_INTERCEPTOR_ENTER();46 SIGNAL_INTERCEPTOR_ENTER();
47 if (GetHandleSignalMode(signum) == kHandleSignalExclusive) return 0;47 if (GetHandleSignalMode(signum) == kHandleSignalExclusive) return 0;
48
49 // TODO: support cloak_sanitizer_signal_handlers
48 SIGNAL_INTERCEPTOR_SIGNAL_IMPL(bsd_signal, signum, handler);50 SIGNAL_INTERCEPTOR_SIGNAL_IMPL(bsd_signal, signum, handler);
49}51}
50#define INIT_BSD_SIGNAL COMMON_INTERCEPT_FUNCTION(bsd_signal)52#define INIT_BSD_SIGNAL COMMON_INTERCEPT_FUNCTION(bsd_signal)
...@@ -56,19 +58,55 @@ INTERCEPTOR(uptr, bsd_signal, int signum, uptr handler) {...@@ -56,19 +58,55 @@ INTERCEPTOR(uptr, bsd_signal, int signum, uptr handler) {
56INTERCEPTOR(uptr, signal, int signum, uptr handler) {58INTERCEPTOR(uptr, signal, int signum, uptr handler) {
57 SIGNAL_INTERCEPTOR_ENTER();59 SIGNAL_INTERCEPTOR_ENTER();
58 if (GetHandleSignalMode(signum) == kHandleSignalExclusive)60 if (GetHandleSignalMode(signum) == kHandleSignalExclusive)
61 // The user can neither view nor change the signal handler, regardless of
62 // the cloak_sanitizer_signal_handlers setting. This differs from
63 // sigaction().
59 return (uptr) nullptr;64 return (uptr) nullptr;
60 SIGNAL_INTERCEPTOR_SIGNAL_IMPL(signal, signum, handler);65
66 uptr ret = +[](auto signal, int signum, uptr handler) {
67 SIGNAL_INTERCEPTOR_SIGNAL_IMPL(signal, signum, handler);
68 }(signal, signum, handler);
69
70 if (ret != sig_err && SetSignalHandlerFromSanitizer(signum, false))
71 // If the user sets a signal handler, it becomes uncloaked, even if they
72 // reuse a sanitizer's signal handler.
73 ret = sig_dfl;
74
75 return ret;
61}76}
62#define INIT_SIGNAL COMMON_INTERCEPT_FUNCTION(signal)77#define INIT_SIGNAL COMMON_INTERCEPT_FUNCTION(signal)
6378
64INTERCEPTOR(int, sigaction_symname, int signum,79INTERCEPTOR(int, sigaction_symname, int signum,
65 const __sanitizer_sigaction *act, __sanitizer_sigaction *oldact) {80 const __sanitizer_sigaction *act, __sanitizer_sigaction *oldact) {
66 SIGNAL_INTERCEPTOR_ENTER();81 SIGNAL_INTERCEPTOR_ENTER();
82
67 if (GetHandleSignalMode(signum) == kHandleSignalExclusive) {83 if (GetHandleSignalMode(signum) == kHandleSignalExclusive) {
68 if (!oldact) return 0;84 if (!oldact) return 0;
69 act = nullptr;85 act = nullptr;
86 // If cloak_sanitizer_signal_handlers=true, the user can neither view nor
87 // change the signal handle.
88 // If false, the user can view but not change the signal handler. This
89 // differs from signal().
70 }90 }
71 SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signum, act, oldact);91
92 int ret = +[](int signum, const __sanitizer_sigaction* act,
93 __sanitizer_sigaction* oldact) {
94 SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signum, act, oldact);
95 }(signum, act, oldact);
96
97 if (act) {
98 if (ret == 0 && SetSignalHandlerFromSanitizer(signum, false)) {
99 // If the user sets a signal handler, it becomes uncloaked, even if they
100 // reuse a sanitizer's signal handler.
101
102 if (oldact)
103 oldact->handler = reinterpret_cast<__sanitizer_sighandler_ptr>(sig_dfl);
104 }
105 } else if (ret == 0 && oldact && IsSignalHandlerFromSanitizer(signum)) {
106 oldact->handler = reinterpret_cast<__sanitizer_sighandler_ptr>(sig_dfl);
107 }
108
109 return ret;
72}110}
73#define INIT_SIGACTION COMMON_INTERCEPT_FUNCTION(sigaction_symname)111#define INIT_SIGACTION COMMON_INTERCEPT_FUNCTION(sigaction_symname)
74112
lib/libtsan/sanitizer_common/sanitizer_stoptheworld.h+1-1
...@@ -38,7 +38,7 @@ class SuspendedThreadsList {...@@ -38,7 +38,7 @@ class SuspendedThreadsList {
38 }38 }
3939
40 virtual uptr ThreadCount() const { UNIMPLEMENTED(); }40 virtual uptr ThreadCount() const { UNIMPLEMENTED(); }
41 virtual tid_t GetThreadID(uptr index) const { UNIMPLEMENTED(); }41 virtual ThreadID GetThreadID(uptr index) const { UNIMPLEMENTED(); }
4242
43 protected:43 protected:
44 ~SuspendedThreadsList() {}44 ~SuspendedThreadsList() {}
lib/libtsan/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp+83-12
...@@ -94,17 +94,17 @@ class SuspendedThreadsListLinux final : public SuspendedThreadsList {...@@ -94,17 +94,17 @@ class SuspendedThreadsListLinux final : public SuspendedThreadsList {
94 public:94 public:
95 SuspendedThreadsListLinux() { thread_ids_.reserve(1024); }95 SuspendedThreadsListLinux() { thread_ids_.reserve(1024); }
9696
97 tid_t GetThreadID(uptr index) const override;97 ThreadID GetThreadID(uptr index) const override;
98 uptr ThreadCount() const override;98 uptr ThreadCount() const override;
99 bool ContainsTid(tid_t thread_id) const;99 bool ContainsTid(ThreadID thread_id) const;
100 void Append(tid_t tid);100 void Append(ThreadID tid);
101101
102 PtraceRegistersStatus GetRegistersAndSP(uptr index,102 PtraceRegistersStatus GetRegistersAndSP(uptr index,
103 InternalMmapVector<uptr> *buffer,103 InternalMmapVector<uptr> *buffer,
104 uptr *sp) const override;104 uptr *sp) const override;
105105
106 private:106 private:
107 InternalMmapVector<tid_t> thread_ids_;107 InternalMmapVector<ThreadID> thread_ids_;
108};108};
109109
110// Structure for passing arguments into the tracer thread.110// Structure for passing arguments into the tracer thread.
...@@ -137,10 +137,10 @@ class ThreadSuspender {...@@ -137,10 +137,10 @@ class ThreadSuspender {
137 private:137 private:
138 SuspendedThreadsListLinux suspended_threads_list_;138 SuspendedThreadsListLinux suspended_threads_list_;
139 pid_t pid_;139 pid_t pid_;
140 bool SuspendThread(tid_t thread_id);140 bool SuspendThread(ThreadID thread_id);
141};141};
142142
143bool ThreadSuspender::SuspendThread(tid_t tid) {143bool ThreadSuspender::SuspendThread(ThreadID tid) {
144 int pterrno;144 int pterrno;
145 if (internal_iserror(internal_ptrace(PTRACE_ATTACH, tid, nullptr, nullptr),145 if (internal_iserror(internal_ptrace(PTRACE_ATTACH, tid, nullptr, nullptr),
146 &pterrno)) {146 &pterrno)) {
...@@ -210,7 +210,7 @@ void ThreadSuspender::KillAllThreads() {...@@ -210,7 +210,7 @@ void ThreadSuspender::KillAllThreads() {
210bool ThreadSuspender::SuspendAllThreads() {210bool ThreadSuspender::SuspendAllThreads() {
211 ThreadLister thread_lister(pid_);211 ThreadLister thread_lister(pid_);
212 bool retry = true;212 bool retry = true;
213 InternalMmapVector<tid_t> threads;213 InternalMmapVector<ThreadID> threads;
214 threads.reserve(128);214 threads.reserve(128);
215 for (int i = 0; i < 30 && retry; ++i) {215 for (int i = 0; i < 30 && retry; ++i) {
216 retry = false;216 retry = false;
...@@ -226,7 +226,7 @@ bool ThreadSuspender::SuspendAllThreads() {...@@ -226,7 +226,7 @@ bool ThreadSuspender::SuspendAllThreads() {
226 case ThreadLister::Ok:226 case ThreadLister::Ok:
227 break;227 break;
228 }228 }
229 for (tid_t tid : threads) {229 for (ThreadID tid : threads) {
230 // Are we already attached to this thread?230 // Are we already attached to this thread?
231 // Currently this check takes linear time, however the number of threads231 // Currently this check takes linear time, however the number of threads
232 // is usually small.232 // is usually small.
...@@ -403,7 +403,77 @@ struct ScopedSetTracerPID {...@@ -403,7 +403,77 @@ struct ScopedSetTracerPID {
403 }403 }
404};404};
405405
406// This detects whether ptrace is blocked (e.g., by seccomp), by forking and
407// then attempting ptrace.
408// This separate check is necessary because StopTheWorld() creates a thread
409// with a shared virtual address space and shared TLS, and therefore
410// cannot use waitpid() due to the shared errno.
411static void TestPTrace() {
412# if SANITIZER_SPARC
413 // internal_fork() on SPARC actually calls __fork(). We can't safely fork,
414 // because it's possible seccomp has been configured to disallow fork() but
415 // allow clone().
416 VReport(1, "WARNING: skipping TestPTrace() because this is SPARC\n");
417 VReport(1,
418 "If seccomp blocks ptrace, LeakSanitizer may hang without further "
419 "notice\n");
420 VReport(
421 1,
422 "If seccomp does not block ptrace, you can safely ignore this warning\n");
423# else
424 // Heuristic: only check the first time this is called. This is not always
425 // correct (e.g., user manually triggers leak detection, then updates
426 // seccomp, then leak detection is triggered again).
427 static bool checked = false;
428 if (checked)
429 return;
430 checked = true;
431
432 // Hopefully internal_fork() is not too expensive, thanks to copy-on-write.
433 // Besides, this is only called the first time.
434 // Note that internal_fork() on non-SPARC Linux actually calls
435 // SYSCALL(clone); thus, it is reasonable to use it because if seccomp kills
436 // TestPTrace(), it would have killed StopTheWorld() anyway.
437 int pid = internal_fork();
438
439 if (pid < 0) {
440 int rverrno;
441 if (internal_iserror(pid, &rverrno))
442 VReport(0, "WARNING: TestPTrace() failed to fork (errno %d)\n", rverrno);
443
444 // We don't abort the sanitizer - it's still worth letting the sanitizer
445 // try.
446 return;
447 }
448
449 if (pid == 0) {
450 // Child subprocess
451
452 // TODO: consider checking return value of internal_ptrace, to handle
453 // SCMP_ACT_ERRNO. However, be careful not to consume too many
454 // resources performing a proper ptrace.
455 internal_ptrace(PTRACE_ATTACH, 0, nullptr, nullptr);
456 internal__exit(0);
457 } else {
458 int wstatus;
459 internal_waitpid(pid, &wstatus, 0);
460
461 // Handle SCMP_ACT_KILL
462 if (WIFSIGNALED(wstatus)) {
463 VReport(0,
464 "WARNING: ptrace appears to be blocked (is seccomp enabled?). "
465 "LeakSanitizer may hang.\n");
466 VReport(0, "Child exited with signal %d.\n", WTERMSIG(wstatus));
467 // We don't abort the sanitizer - it's still worth letting the sanitizer
468 // try.
469 }
470 }
471# endif
472}
473
406void StopTheWorld(StopTheWorldCallback callback, void *argument) {474void StopTheWorld(StopTheWorldCallback callback, void *argument) {
475 TestPTrace();
476
407 StopTheWorldScope in_stoptheworld;477 StopTheWorldScope in_stoptheworld;
408 // Prepare the arguments for TracerThread.478 // Prepare the arguments for TracerThread.
409 struct TracerThreadArgument tracer_thread_argument;479 struct TracerThreadArgument tracer_thread_argument;
...@@ -457,7 +527,8 @@ void StopTheWorld(StopTheWorldCallback callback, void *argument) {...@@ -457,7 +527,8 @@ void StopTheWorld(StopTheWorldCallback callback, void *argument) {
457 internal_prctl(PR_SET_PTRACER, tracer_pid, 0, 0, 0);527 internal_prctl(PR_SET_PTRACER, tracer_pid, 0, 0, 0);
458 // Allow the tracer thread to start.528 // Allow the tracer thread to start.
459 tracer_thread_argument.mutex.Unlock();529 tracer_thread_argument.mutex.Unlock();
460 // NOTE: errno is shared between this thread and the tracer thread.530 // NOTE: errno is shared between this thread and the tracer thread
531 // (clone was called without CLONE_SETTLS / newtls).
461 // internal_waitpid() may call syscall() which can access/spoil errno,532 // internal_waitpid() may call syscall() which can access/spoil errno,
462 // so we can't call it now. Instead we for the tracer thread to finish using533 // so we can't call it now. Instead we for the tracer thread to finish using
463 // the spin loop below. Man page for sched_yield() says "In the Linux534 // the spin loop below. Man page for sched_yield() says "In the Linux
...@@ -546,7 +617,7 @@ static constexpr uptr kExtraRegs[] = {0};...@@ -546,7 +617,7 @@ static constexpr uptr kExtraRegs[] = {0};
546#error "Unsupported architecture"617#error "Unsupported architecture"
547#endif // SANITIZER_ANDROID && defined(__arm__)618#endif // SANITIZER_ANDROID && defined(__arm__)
548619
549tid_t SuspendedThreadsListLinux::GetThreadID(uptr index) const {620ThreadID SuspendedThreadsListLinux::GetThreadID(uptr index) const {
550 CHECK_LT(index, thread_ids_.size());621 CHECK_LT(index, thread_ids_.size());
551 return thread_ids_[index];622 return thread_ids_[index];
552}623}
...@@ -555,14 +626,14 @@ uptr SuspendedThreadsListLinux::ThreadCount() const {...@@ -555,14 +626,14 @@ uptr SuspendedThreadsListLinux::ThreadCount() const {
555 return thread_ids_.size();626 return thread_ids_.size();
556}627}
557628
558bool SuspendedThreadsListLinux::ContainsTid(tid_t thread_id) const {629bool SuspendedThreadsListLinux::ContainsTid(ThreadID thread_id) const {
559 for (uptr i = 0; i < thread_ids_.size(); i++) {630 for (uptr i = 0; i < thread_ids_.size(); i++) {
560 if (thread_ids_[i] == thread_id) return true;631 if (thread_ids_[i] == thread_id) return true;
561 }632 }
562 return false;633 return false;
563}634}
564635
565void SuspendedThreadsListLinux::Append(tid_t tid) {636void SuspendedThreadsListLinux::Append(ThreadID tid) {
566 thread_ids_.push_back(tid);637 thread_ids_.push_back(tid);
567}638}
568639
lib/libtsan/sanitizer_common/sanitizer_stoptheworld_mac.cpp+3-3
...@@ -23,7 +23,7 @@...@@ -23,7 +23,7 @@
2323
24namespace __sanitizer {24namespace __sanitizer {
25typedef struct {25typedef struct {
26 tid_t tid;26 ThreadID tid;
27 thread_t thread;27 thread_t thread;
28} SuspendedThreadInfo;28} SuspendedThreadInfo;
2929
...@@ -31,7 +31,7 @@ class SuspendedThreadsListMac final : public SuspendedThreadsList {...@@ -31,7 +31,7 @@ class SuspendedThreadsListMac final : public SuspendedThreadsList {
31 public:31 public:
32 SuspendedThreadsListMac() = default;32 SuspendedThreadsListMac() = default;
3333
34 tid_t GetThreadID(uptr index) const override;34 ThreadID GetThreadID(uptr index) const override;
35 thread_t GetThread(uptr index) const;35 thread_t GetThread(uptr index) const;
36 uptr ThreadCount() const override;36 uptr ThreadCount() const override;
37 bool ContainsThread(thread_t thread) const;37 bool ContainsThread(thread_t thread) const;
...@@ -111,7 +111,7 @@ typedef x86_thread_state32_t regs_struct;...@@ -111,7 +111,7 @@ typedef x86_thread_state32_t regs_struct;
111#error "Unsupported architecture"111#error "Unsupported architecture"
112#endif112#endif
113113
114tid_t SuspendedThreadsListMac::GetThreadID(uptr index) const {114ThreadID SuspendedThreadsListMac::GetThreadID(uptr index) const {
115 CHECK_LT(index, threads_.size());115 CHECK_LT(index, threads_.size());
116 return threads_[index].tid;116 return threads_[index].tid;
117}117}
lib/libtsan/sanitizer_common/sanitizer_stoptheworld_netbsd_libcdep.cpp+7-7
...@@ -52,17 +52,17 @@ class SuspendedThreadsListNetBSD final : public SuspendedThreadsList {...@@ -52,17 +52,17 @@ class SuspendedThreadsListNetBSD final : public SuspendedThreadsList {
52 public:52 public:
53 SuspendedThreadsListNetBSD() { thread_ids_.reserve(1024); }53 SuspendedThreadsListNetBSD() { thread_ids_.reserve(1024); }
5454
55 tid_t GetThreadID(uptr index) const;55 ThreadID GetThreadID(uptr index) const;
56 uptr ThreadCount() const;56 uptr ThreadCount() const;
57 bool ContainsTid(tid_t thread_id) const;57 bool ContainsTid(ThreadID thread_id) const;
58 void Append(tid_t tid);58 void Append(ThreadID tid);
5959
60 PtraceRegistersStatus GetRegistersAndSP(uptr index,60 PtraceRegistersStatus GetRegistersAndSP(uptr index,
61 InternalMmapVector<uptr> *buffer,61 InternalMmapVector<uptr> *buffer,
62 uptr *sp) const;62 uptr *sp) const;
6363
64 private:64 private:
65 InternalMmapVector<tid_t> thread_ids_;65 InternalMmapVector<ThreadID> thread_ids_;
66};66};
6767
68struct TracerThreadArgument {68struct TracerThreadArgument {
...@@ -313,7 +313,7 @@ void StopTheWorld(StopTheWorldCallback callback, void *argument) {...@@ -313,7 +313,7 @@ void StopTheWorld(StopTheWorldCallback callback, void *argument) {
313 }313 }
314}314}
315315
316tid_t SuspendedThreadsListNetBSD::GetThreadID(uptr index) const {316ThreadID SuspendedThreadsListNetBSD::GetThreadID(uptr index) const {
317 CHECK_LT(index, thread_ids_.size());317 CHECK_LT(index, thread_ids_.size());
318 return thread_ids_[index];318 return thread_ids_[index];
319}319}
...@@ -322,7 +322,7 @@ uptr SuspendedThreadsListNetBSD::ThreadCount() const {...@@ -322,7 +322,7 @@ uptr SuspendedThreadsListNetBSD::ThreadCount() const {
322 return thread_ids_.size();322 return thread_ids_.size();
323}323}
324324
325bool SuspendedThreadsListNetBSD::ContainsTid(tid_t thread_id) const {325bool SuspendedThreadsListNetBSD::ContainsTid(ThreadID thread_id) const {
326 for (uptr i = 0; i < thread_ids_.size(); i++) {326 for (uptr i = 0; i < thread_ids_.size(); i++) {
327 if (thread_ids_[i] == thread_id)327 if (thread_ids_[i] == thread_id)
328 return true;328 return true;
...@@ -330,7 +330,7 @@ bool SuspendedThreadsListNetBSD::ContainsTid(tid_t thread_id) const {...@@ -330,7 +330,7 @@ bool SuspendedThreadsListNetBSD::ContainsTid(tid_t thread_id) const {
330 return false;330 return false;
331}331}
332332
333void SuspendedThreadsListNetBSD::Append(tid_t tid) {333void SuspendedThreadsListNetBSD::Append(ThreadID tid) {
334 thread_ids_.push_back(tid);334 thread_ids_.push_back(tid);
335}335}
336336
lib/libtsan/sanitizer_common/sanitizer_stoptheworld_win.cpp+2-2
...@@ -38,7 +38,7 @@ struct SuspendedThreadsListWindows final : public SuspendedThreadsList {...@@ -38,7 +38,7 @@ struct SuspendedThreadsListWindows final : public SuspendedThreadsList {
38 InternalMmapVector<uptr> *buffer,38 InternalMmapVector<uptr> *buffer,
39 uptr *sp) const override;39 uptr *sp) const override;
4040
41 tid_t GetThreadID(uptr index) const override;41 ThreadID GetThreadID(uptr index) const override;
42 uptr ThreadCount() const override;42 uptr ThreadCount() const override;
43};43};
4444
...@@ -68,7 +68,7 @@ PtraceRegistersStatus SuspendedThreadsListWindows::GetRegistersAndSP(...@@ -68,7 +68,7 @@ PtraceRegistersStatus SuspendedThreadsListWindows::GetRegistersAndSP(
68 return REGISTERS_AVAILABLE;68 return REGISTERS_AVAILABLE;
69}69}
7070
71tid_t SuspendedThreadsListWindows::GetThreadID(uptr index) const {71ThreadID SuspendedThreadsListWindows::GetThreadID(uptr index) const {
72 CHECK_LT(index, threadIds.size());72 CHECK_LT(index, threadIds.size());
73 return threadIds[index];73 return threadIds[index];
74}74}
lib/libtsan/sanitizer_common/sanitizer_symbolizer_internal.h+5-1
...@@ -83,7 +83,7 @@ class SymbolizerProcess {...@@ -83,7 +83,7 @@ class SymbolizerProcess {
83 const char *SendCommand(const char *command);83 const char *SendCommand(const char *command);
8484
85 protected:85 protected:
86 ~SymbolizerProcess() {}86 ~SymbolizerProcess();
8787
88 /// The maximum number of arguments required to invoke a tool process.88 /// The maximum number of arguments required to invoke a tool process.
89 static const unsigned kArgVMax = 16;89 static const unsigned kArgVMax = 16;
...@@ -114,6 +114,10 @@ class SymbolizerProcess {...@@ -114,6 +114,10 @@ class SymbolizerProcess {
114 fd_t input_fd_;114 fd_t input_fd_;
115 fd_t output_fd_;115 fd_t output_fd_;
116116
117 // We hold on to the child's stdin fd (the read end of the pipe)
118 // so that when we write to it, we don't get a SIGPIPE
119 fd_t child_stdin_fd_;
120
117 InternalMmapVector<char> buffer_;121 InternalMmapVector<char> buffer_;
118122
119 static const uptr kMaxTimesRestarted = 5;123 static const uptr kMaxTimesRestarted = 5;
lib/libtsan/sanitizer_common/sanitizer_symbolizer_libcdep.cpp+11-1
...@@ -476,10 +476,11 @@ const char *LLVMSymbolizer::FormatAndSendCommand(const char *command_prefix,...@@ -476,10 +476,11 @@ const char *LLVMSymbolizer::FormatAndSendCommand(const char *command_prefix,
476 return symbolizer_process_->SendCommand(buffer_);476 return symbolizer_process_->SendCommand(buffer_);
477}477}
478478
479SymbolizerProcess::SymbolizerProcess(const char *path, bool use_posix_spawn)479SymbolizerProcess::SymbolizerProcess(const char* path, bool use_posix_spawn)
480 : path_(path),480 : path_(path),
481 input_fd_(kInvalidFd),481 input_fd_(kInvalidFd),
482 output_fd_(kInvalidFd),482 output_fd_(kInvalidFd),
483 child_stdin_fd_(kInvalidFd),
483 times_restarted_(0),484 times_restarted_(0),
484 failed_to_start_(false),485 failed_to_start_(false),
485 reported_invalid_path_(false),486 reported_invalid_path_(false),
...@@ -488,6 +489,11 @@ SymbolizerProcess::SymbolizerProcess(const char *path, bool use_posix_spawn)...@@ -488,6 +489,11 @@ SymbolizerProcess::SymbolizerProcess(const char *path, bool use_posix_spawn)
488 CHECK_NE(path_[0], '\0');489 CHECK_NE(path_[0], '\0');
489}490}
490491
492SymbolizerProcess::~SymbolizerProcess() {
493 if (child_stdin_fd_ != kInvalidFd)
494 CloseFile(child_stdin_fd_);
495}
496
491static bool IsSameModule(const char *path) {497static bool IsSameModule(const char *path) {
492 if (const char *ProcessName = GetProcessName()) {498 if (const char *ProcessName = GetProcessName()) {
493 if (const char *SymbolizerName = StripModuleName(path)) {499 if (const char *SymbolizerName = StripModuleName(path)) {
...@@ -533,6 +539,10 @@ bool SymbolizerProcess::Restart() {...@@ -533,6 +539,10 @@ bool SymbolizerProcess::Restart() {
533 CloseFile(input_fd_);539 CloseFile(input_fd_);
534 if (output_fd_ != kInvalidFd)540 if (output_fd_ != kInvalidFd)
535 CloseFile(output_fd_);541 CloseFile(output_fd_);
542 if (child_stdin_fd_ != kInvalidFd) {
543 CloseFile(child_stdin_fd_);
544 child_stdin_fd_ = kInvalidFd; // Don't free in destructor
545 }
536 return StartSymbolizerSubprocess();546 return StartSymbolizerSubprocess();
537}547}
538548
lib/libtsan/sanitizer_common/sanitizer_symbolizer_mac.cpp+86-29
...@@ -78,13 +78,25 @@ class AtosSymbolizerProcess final : public SymbolizerProcess {...@@ -78,13 +78,25 @@ class AtosSymbolizerProcess final : public SymbolizerProcess {
78 }78 }
7979
80 bool ReachedEndOfOutput(const char *buffer, uptr length) const override {80 bool ReachedEndOfOutput(const char *buffer, uptr length) const override {
81 return (length >= 1 && buffer[length - 1] == '\n');81 if (common_flags()->symbolize_inline_frames) {
82 // When running with -i, atos sends two newlines at the end of each
83 // address it symbolizes. This indicates the end of the set of frames
84 // for a particular address.
85 return length >= 2 && buffer[length - 1] == '\n' &&
86 buffer[length - 2] == '\n';
87 } else {
88 // When running without -i, atos only sends a single newline at
89 // the end of each address it symbolizes.
90 return length >= 1 && buffer[length - 1] == '\n';
91 }
82 }92 }
8393
84 void GetArgV(const char *path_to_binary,94 void GetArgV(const char *path_to_binary,
85 const char *(&argv)[kArgVMax]) const override {95 const char *(&argv)[kArgVMax]) const override {
86 int i = 0;96 int i = 0;
87 argv[i++] = path_to_binary;97 argv[i++] = path_to_binary;
98 if (common_flags()->symbolize_inline_frames)
99 argv[i++] = "-i";
88 argv[i++] = "-p";100 argv[i++] = "-p";
89 argv[i++] = &pid_str_[0];101 argv[i++] = &pid_str_[0];
90 if (GetMacosAlignedVersion() == MacosVersion(10, 9)) {102 if (GetMacosAlignedVersion() == MacosVersion(10, 9)) {
...@@ -102,12 +114,16 @@ class AtosSymbolizerProcess final : public SymbolizerProcess {...@@ -102,12 +114,16 @@ class AtosSymbolizerProcess final : public SymbolizerProcess {
102114
103#undef K_ATOS_ENV_VAR115#undef K_ATOS_ENV_VAR
104116
105static bool ParseCommandOutput(const char *str, uptr addr, char **out_name,117// Parses a single frame (one line) from str, and returns the pointer to the
106 char **out_module, char **out_file, uptr *line,118// next character to parse (i.e. after the newline) if successful. If
107 uptr *start_address) {119// it fails, returns NULL.
120static const char* ParseCommandOutput(const char* str, uptr addr,
121 char** out_name, char** out_module,
122 char** out_file, uptr* line,
123 uptr* start_address) {
108 // Trim ending newlines.124 // Trim ending newlines.
109 char *trim;125 char *trim;
110 ExtractTokenUpToDelimiter(str, "\n", &trim);126 str = ExtractTokenUpToDelimiter(str, "\n", &trim);
111127
112 // The line from `atos` is in one of these formats:128 // The line from `atos` is in one of these formats:
113 // myfunction (in library.dylib) (sourcefile.c:17)129 // myfunction (in library.dylib) (sourcefile.c:17)
...@@ -124,7 +140,7 @@ static bool ParseCommandOutput(const char *str, uptr addr, char **out_name,...@@ -124,7 +140,7 @@ static bool ParseCommandOutput(const char *str, uptr addr, char **out_name,
124 if (rest[0] == '\0') {140 if (rest[0] == '\0') {
125 InternalFree(symbol_name);141 InternalFree(symbol_name);
126 InternalFree(trim);142 InternalFree(trim);
127 return false;143 return NULL;
128 }144 }
129145
130 if (internal_strncmp(symbol_name, "0x", 2) != 0)146 if (internal_strncmp(symbol_name, "0x", 2) != 0)
...@@ -149,7 +165,7 @@ static bool ParseCommandOutput(const char *str, uptr addr, char **out_name,...@@ -149,7 +165,7 @@ static bool ParseCommandOutput(const char *str, uptr addr, char **out_name,
149 }165 }
150166
151 InternalFree(trim);167 InternalFree(trim);
152 return true;168 return str;
153}169}
154170
155AtosSymbolizer::AtosSymbolizer(const char *path, LowLevelAllocator *allocator)171AtosSymbolizer::AtosSymbolizer(const char *path, LowLevelAllocator *allocator)
...@@ -161,31 +177,72 @@ bool AtosSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {...@@ -161,31 +177,72 @@ bool AtosSymbolizer::SymbolizePC(uptr addr, SymbolizedStack *stack) {
161 char command[32];177 char command[32];
162 internal_snprintf(command, sizeof(command), "0x%zx\n", addr);178 internal_snprintf(command, sizeof(command), "0x%zx\n", addr);
163 const char *buf = process_->SendCommand(command);179 const char *buf = process_->SendCommand(command);
164 if (!buf) return false;180 if (!buf)
165 uptr line;
166 uptr start_address = AddressInfo::kUnknown;
167 if (!ParseCommandOutput(buf, addr, &stack->info.function, &stack->info.module,
168 &stack->info.file, &line, &start_address)) {
169 Report("WARNING: atos failed to symbolize address \"0x%zx\"\n", addr);
170 return false;181 return false;
171 }
172 stack->info.line = (int)line;
173
174 if (start_address == AddressInfo::kUnknown) {
175 // Fallback to dladdr() to get function start address if atos doesn't report
176 // it.
177 Dl_info info;
178 int result = dladdr((const void *)addr, &info);
179 if (result)
180 start_address = reinterpret_cast<uptr>(info.dli_saddr);
181 }
182182
183 // Only assign to `function_offset` if we were able to get the function's183 SymbolizedStack* last = stack;
184 // start address and we got a sensible `start_address` (dladdr doesn't always184 bool top_frame = true;
185 // ensure that `addr >= sym_addr`).185
186 if (start_address != AddressInfo::kUnknown && addr >= start_address) {186 // Parse one line of input (i.e. one frame).
187 stack->info.function_offset = addr - start_address;187 //
188 // When symbolize_inline_frames=true, an empty line
189 // (i.e. \n at the beginning of a line) indicates that the last
190 // frame has been sent.
191 //
192 // When symbolize_inline_frames=false, the symbolizer will send only
193 // one frame (without a empty line), so loop runs exactly once
194 // and hits an early `break`.
195 while (*buf != '\n') {
196 uptr line;
197 uptr start_address = AddressInfo::kUnknown;
198
199 SymbolizedStack* cur;
200 if (top_frame) {
201 cur = stack;
202 } else {
203 cur = SymbolizedStack::New(stack->info.address);
204 cur->info.FillModuleInfo(stack->info.module, stack->info.module_offset,
205 stack->info.module_arch);
206 last->next = cur;
207 last = cur;
208 }
209
210 // Parse one line of input (i.e. one frame)
211 // If this succeeds, buf will be updated to point to the first character
212 // after the newline.
213 buf = ParseCommandOutput(buf, addr, &cur->info.function, &cur->info.module,
214 &cur->info.file, &line, &start_address);
215
216 // Upon failure, ParseCommandOutput returns NULL.
217 if (!buf) {
218 Report("WARNING: atos failed to symbolize address \"0x%zx\"\n", addr);
219 return false;
220 }
221 cur->info.line = (int)line;
222
223 if (top_frame && start_address == AddressInfo::kUnknown) {
224 // Fallback to dladdr() to get function start address if atos doesn't
225 // report it.
226 Dl_info info;
227 int result = dladdr((const void*)addr, &info);
228 if (result)
229 start_address = reinterpret_cast<uptr>(info.dli_saddr);
230 }
231
232 // Only assign to `function_offset` if we were able to get the function's
233 // start address and we got a sensible `start_address` (dladdr doesn't
234 // always ensure that `addr >= sym_addr`).
235 if (start_address != AddressInfo::kUnknown && addr >= start_address) {
236 cur->info.function_offset = addr - start_address;
237 }
238
239 // atos only sends one line when inline frames are off
240 if (!common_flags()->symbolize_inline_frames)
241 break;
242
243 top_frame = false;
188 }244 }
245
189 return true;246 return true;
190}247}
191248
lib/libtsan/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp+27-16
...@@ -156,30 +156,34 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {...@@ -156,30 +156,34 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
156 Printf("\n");156 Printf("\n");
157 }157 }
158158
159 fd_t infd[2] = {}, outfd[2] = {};
160 if (!CreateTwoHighNumberedPipes(infd, outfd)) {
161 Report(
162 "WARNING: Can't create a socket pair to start "
163 "external symbolizer (errno: %d)\n",
164 errno);
165 return false;
166 }
167
159 if (use_posix_spawn_) {168 if (use_posix_spawn_) {
160# if SANITIZER_APPLE169# if SANITIZER_APPLE
161 fd_t fd = internal_spawn(argv, const_cast<const char **>(GetEnvP()), &pid);170 bool success = internal_spawn(argv, const_cast<const char**>(GetEnvP()),
162 if (fd == kInvalidFd) {171 &pid, outfd[0], infd[1]);
172 if (!success) {
163 Report("WARNING: failed to spawn external symbolizer (errno: %d)\n",173 Report("WARNING: failed to spawn external symbolizer (errno: %d)\n",
164 errno);174 errno);
175 internal_close(infd[0]);
176 internal_close(outfd[1]);
165 return false;177 return false;
166 }178 }
167179
168 input_fd_ = fd;180 // We intentionally hold on to the read-end so that we don't get a SIGPIPE
169 output_fd_ = fd;181 child_stdin_fd_ = outfd[0];
182
170# else // SANITIZER_APPLE183# else // SANITIZER_APPLE
171 UNIMPLEMENTED();184 UNIMPLEMENTED();
172# endif // SANITIZER_APPLE185# endif // SANITIZER_APPLE
173 } else {186 } else {
174 fd_t infd[2] = {}, outfd[2] = {};
175 if (!CreateTwoHighNumberedPipes(infd, outfd)) {
176 Report(
177 "WARNING: Can't create a socket pair to start "
178 "external symbolizer (errno: %d)\n",
179 errno);
180 return false;
181 }
182
183 pid = StartSubprocess(path_, argv, GetEnvP(), /* stdin */ outfd[0],187 pid = StartSubprocess(path_, argv, GetEnvP(), /* stdin */ outfd[0],
184 /* stdout */ infd[1]);188 /* stdout */ infd[1]);
185 if (pid < 0) {189 if (pid < 0) {
...@@ -187,11 +191,11 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {...@@ -187,11 +191,11 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
187 internal_close(outfd[1]);191 internal_close(outfd[1]);
188 return false;192 return false;
189 }193 }
190
191 input_fd_ = infd[0];
192 output_fd_ = outfd[1];
193 }194 }
194195
196 input_fd_ = infd[0];
197 output_fd_ = outfd[1];
198
195 CHECK_GT(pid, 0);199 CHECK_GT(pid, 0);
196200
197 // Check that symbolizer subprocess started successfully.201 // Check that symbolizer subprocess started successfully.
...@@ -505,6 +509,13 @@ static void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list,...@@ -505,6 +509,13 @@ static void ChooseSymbolizerTools(IntrusiveList<SymbolizerTool> *list,
505 }509 }
506510
507# if SANITIZER_APPLE511# if SANITIZER_APPLE
512 if (list->empty()) {
513 Report(
514 "WARN: No external symbolizers found. Symbols may be missing or "
515 "unreliable.\n");
516 Report(
517 "HINT: Is PATH set? Does sandbox allow file-read of /usr/bin/atos?\n");
518 }
508 VReport(2, "Using dladdr symbolizer.\n");519 VReport(2, "Using dladdr symbolizer.\n");
509 list->push_back(new (*allocator) DlAddrSymbolizer());520 list->push_back(new (*allocator) DlAddrSymbolizer());
510# endif // SANITIZER_APPLE521# endif // SANITIZER_APPLE
lib/libtsan/sanitizer_common/sanitizer_thread_registry.cpp+5-4
...@@ -80,7 +80,7 @@ void ThreadContextBase::SetFinished() {...@@ -80,7 +80,7 @@ void ThreadContextBase::SetFinished() {
80 OnFinished();80 OnFinished();
81}81}
8282
83void ThreadContextBase::SetStarted(tid_t _os_id, ThreadType _thread_type,83void ThreadContextBase::SetStarted(ThreadID _os_id, ThreadType _thread_type,
84 void *arg) {84 void *arg) {
85 status = ThreadStatusRunning;85 status = ThreadStatusRunning;
86 os_id = _os_id;86 os_id = _os_id;
...@@ -228,7 +228,8 @@ static bool FindThreadContextByOsIdCallback(ThreadContextBase *tctx,...@@ -228,7 +228,8 @@ static bool FindThreadContextByOsIdCallback(ThreadContextBase *tctx,
228 tctx->status != ThreadStatusDead);228 tctx->status != ThreadStatusDead);
229}229}
230230
231ThreadContextBase *ThreadRegistry::FindThreadContextByOsIDLocked(tid_t os_id) {231ThreadContextBase *ThreadRegistry::FindThreadContextByOsIDLocked(
232 ThreadID os_id) {
232 return FindThreadContextLocked(FindThreadContextByOsIdCallback,233 return FindThreadContextLocked(FindThreadContextByOsIdCallback,
233 (void *)os_id);234 (void *)os_id);
234}235}
...@@ -322,8 +323,8 @@ ThreadStatus ThreadRegistry::FinishThread(u32 tid) {...@@ -322,8 +323,8 @@ ThreadStatus ThreadRegistry::FinishThread(u32 tid) {
322 return prev_status;323 return prev_status;
323}324}
324325
325void ThreadRegistry::StartThread(u32 tid, tid_t os_id, ThreadType thread_type,326void ThreadRegistry::StartThread(u32 tid, ThreadID os_id,
326 void *arg) {327 ThreadType thread_type, void *arg) {
327 ThreadRegistryLock l(this);328 ThreadRegistryLock l(this);
328 running_threads_++;329 running_threads_++;
329 ThreadContextBase *tctx = threads_[tid];330 ThreadContextBase *tctx = threads_[tid];
lib/libtsan/sanitizer_common/sanitizer_thread_registry.h+4-4
...@@ -43,7 +43,7 @@ class ThreadContextBase {...@@ -43,7 +43,7 @@ class ThreadContextBase {
43 const u32 tid; // Thread ID. Main thread should have tid = 0.43 const u32 tid; // Thread ID. Main thread should have tid = 0.
44 u64 unique_id; // Unique thread ID.44 u64 unique_id; // Unique thread ID.
45 u32 reuse_count; // Number of times this tid was reused.45 u32 reuse_count; // Number of times this tid was reused.
46 tid_t os_id; // PID (used for reporting).46 ThreadID os_id; // PID (used for reporting).
47 uptr user_id; // Some opaque user thread id (e.g. pthread_t).47 uptr user_id; // Some opaque user thread id (e.g. pthread_t).
48 char name[64]; // As annotated by user.48 char name[64]; // As annotated by user.
4949
...@@ -62,7 +62,7 @@ class ThreadContextBase {...@@ -62,7 +62,7 @@ class ThreadContextBase {
62 void SetDead();62 void SetDead();
63 void SetJoined(void *arg);63 void SetJoined(void *arg);
64 void SetFinished();64 void SetFinished();
65 void SetStarted(tid_t _os_id, ThreadType _thread_type, void *arg);65 void SetStarted(ThreadID _os_id, ThreadType _thread_type, void *arg);
66 void SetCreated(uptr _user_id, u64 _unique_id, bool _detached,66 void SetCreated(uptr _user_id, u64 _unique_id, bool _detached,
67 u32 _parent_tid, u32 _stack_tid, void *arg);67 u32 _parent_tid, u32 _stack_tid, void *arg);
68 void Reset();68 void Reset();
...@@ -126,7 +126,7 @@ class SANITIZER_MUTEX ThreadRegistry {...@@ -126,7 +126,7 @@ class SANITIZER_MUTEX ThreadRegistry {
126 // is found.126 // is found.
127 ThreadContextBase *FindThreadContextLocked(FindThreadCallback cb,127 ThreadContextBase *FindThreadContextLocked(FindThreadCallback cb,
128 void *arg);128 void *arg);
129 ThreadContextBase *FindThreadContextByOsIDLocked(tid_t os_id);129 ThreadContextBase *FindThreadContextByOsIDLocked(ThreadID os_id);
130130
131 void SetThreadName(u32 tid, const char *name);131 void SetThreadName(u32 tid, const char *name);
132 void SetThreadNameByUserId(uptr user_id, const char *name);132 void SetThreadNameByUserId(uptr user_id, const char *name);
...@@ -134,7 +134,7 @@ class SANITIZER_MUTEX ThreadRegistry {...@@ -134,7 +134,7 @@ class SANITIZER_MUTEX ThreadRegistry {
134 void JoinThread(u32 tid, void *arg);134 void JoinThread(u32 tid, void *arg);
135 // Finishes thread and returns previous status.135 // Finishes thread and returns previous status.
136 ThreadStatus FinishThread(u32 tid);136 ThreadStatus FinishThread(u32 tid);
137 void StartThread(u32 tid, tid_t os_id, ThreadType thread_type, void *arg);137 void StartThread(u32 tid, ThreadID os_id, ThreadType thread_type, void *arg);
138 u32 ConsumeThreadUserId(uptr user_id);138 u32 ConsumeThreadUserId(uptr user_id);
139 void SetThreadUserId(u32 tid, uptr user_id);139 void SetThreadUserId(u32 tid, uptr user_id);
140140
lib/libtsan/sanitizer_common/sanitizer_win.cpp+1-3
...@@ -108,9 +108,7 @@ int internal_dlinfo(void *handle, int request, void *p) {...@@ -108,9 +108,7 @@ int internal_dlinfo(void *handle, int request, void *p) {
108108
109// In contrast to POSIX, on Windows GetCurrentThreadId()109// In contrast to POSIX, on Windows GetCurrentThreadId()
110// returns a system-unique identifier.110// returns a system-unique identifier.
111tid_t GetTid() {111ThreadID GetTid() { return GetCurrentThreadId(); }
112 return GetCurrentThreadId();
113}
114112
115uptr GetThreadSelf() {113uptr GetThreadSelf() {
116 return GetTid();114 return GetTid();
lib/libtsan/tsan_debugging.cpp+2-2
...@@ -165,7 +165,7 @@ int __tsan_get_report_mutex(void *report, uptr idx, uptr *mutex_id, void **addr,...@@ -165,7 +165,7 @@ int __tsan_get_report_mutex(void *report, uptr idx, uptr *mutex_id, void **addr,
165}165}
166166
167SANITIZER_INTERFACE_ATTRIBUTE167SANITIZER_INTERFACE_ATTRIBUTE
168int __tsan_get_report_thread(void *report, uptr idx, int *tid, tid_t *os_id,168int __tsan_get_report_thread(void *report, uptr idx, int *tid, ThreadID *os_id,
169 int *running, const char **name, int *parent_tid,169 int *running, const char **name, int *parent_tid,
170 void **trace, uptr trace_size) {170 void **trace, uptr trace_size) {
171 const ReportDesc *rep = (ReportDesc *)report;171 const ReportDesc *rep = (ReportDesc *)report;
...@@ -242,7 +242,7 @@ const char *__tsan_locate_address(uptr addr, char *name, uptr name_size,...@@ -242,7 +242,7 @@ const char *__tsan_locate_address(uptr addr, char *name, uptr name_size,
242242
243SANITIZER_INTERFACE_ATTRIBUTE243SANITIZER_INTERFACE_ATTRIBUTE
244int __tsan_get_alloc_stack(uptr addr, uptr *trace, uptr size, int *thread_id,244int __tsan_get_alloc_stack(uptr addr, uptr *trace, uptr size, int *thread_id,
245 tid_t *os_id) {245 ThreadID *os_id) {
246 MBlock *b = 0;246 MBlock *b = 0;
247 Allocator *a = allocator();247 Allocator *a = allocator();
248 if (a->PointerIsMine((void *)addr)) {248 if (a->PointerIsMine((void *)addr)) {
lib/libtsan/tsan_flags.cpp+37
...@@ -20,6 +20,43 @@...@@ -20,6 +20,43 @@
20#include "tsan_rtl.h"20#include "tsan_rtl.h"
21#include "ubsan/ubsan_flags.h"21#include "ubsan/ubsan_flags.h"
2222
23#if SANITIZER_APPLE && !SANITIZER_GO
24namespace __sanitizer {
25
26template <>
27inline bool FlagHandler<LockDuringWriteSetting>::Parse(const char *value) {
28 if (internal_strcmp(value, "on") == 0) {
29 *t_ = kLockDuringAllWrites;
30 return true;
31 }
32 if (internal_strcmp(value, "disable_for_current_process") == 0) {
33 *t_ = kNoLockDuringWritesCurrentProcess;
34 return true;
35 }
36 if (internal_strcmp(value, "disable_for_all_processes") == 0) {
37 *t_ = kNoLockDuringWritesAllProcesses;
38 return true;
39 }
40 Printf("ERROR: Invalid value for signal handler option: '%s'\n", value);
41 return false;
42}
43
44template <>
45inline bool FlagHandler<LockDuringWriteSetting>::Format(char *buffer,
46 uptr size) {
47 switch (*t_) {
48 case kLockDuringAllWrites:
49 return FormatString(buffer, size, "on");
50 case kNoLockDuringWritesCurrentProcess:
51 return FormatString(buffer, size, "disable_for_current_process");
52 case kNoLockDuringWritesAllProcesses:
53 return FormatString(buffer, size, "disable_for_all_processes");
54 }
55}
56
57} // namespace __sanitizer
58#endif // SANITIZER_APPLE && !SANITIZER_GO
59
23namespace __tsan {60namespace __tsan {
2461
25// Can be overriden in frontend.62// Can be overriden in frontend.
lib/libtsan/tsan_flags.h+8
...@@ -16,6 +16,14 @@...@@ -16,6 +16,14 @@
16#include "sanitizer_common/sanitizer_flags.h"16#include "sanitizer_common/sanitizer_flags.h"
17#include "sanitizer_common/sanitizer_deadlock_detector_interface.h"17#include "sanitizer_common/sanitizer_deadlock_detector_interface.h"
1818
19#if SANITIZER_APPLE && !SANITIZER_GO
20enum LockDuringWriteSetting {
21 kLockDuringAllWrites,
22 kNoLockDuringWritesCurrentProcess,
23 kNoLockDuringWritesAllProcesses,
24};
25#endif
26
19namespace __tsan {27namespace __tsan {
2028
21struct Flags : DDFlags {29struct Flags : DDFlags {
lib/libtsan/tsan_flags.inc+12
...@@ -80,3 +80,15 @@ TSAN_FLAG(bool, shared_ptr_interceptor, true,...@@ -80,3 +80,15 @@ TSAN_FLAG(bool, shared_ptr_interceptor, true,
80TSAN_FLAG(bool, print_full_thread_history, false,80TSAN_FLAG(bool, print_full_thread_history, false,
81 "If set, prints thread creation stacks for the threads involved in "81 "If set, prints thread creation stacks for the threads involved in "
82 "the report and their ancestors up to the main thread.")82 "the report and their ancestors up to the main thread.")
83
84#if SANITIZER_APPLE && !SANITIZER_GO
85TSAN_FLAG(LockDuringWriteSetting, lock_during_write, kLockDuringAllWrites,
86 "Determines whether to obtain a lock while writing logs or error "
87 "reports. "
88 "\"on\" - [default] lock during all writes. "
89 "\"disable_for_current_process\" - don't lock during all writes in "
90 "the current process, but do lock for all writes in child "
91 "processes."
92 "\"disable_for_all_processes\" - don't lock during all writes in "
93 "the current process and it's children processes.")
94#endif
lib/libtsan/tsan_interceptors.h+9-1
...@@ -1,6 +1,9 @@...@@ -1,6 +1,9 @@
1#ifndef TSAN_INTERCEPTORS_H1#ifndef TSAN_INTERCEPTORS_H
2#define TSAN_INTERCEPTORS_H2#define TSAN_INTERCEPTORS_H
33
4#if SANITIZER_APPLE && !SANITIZER_GO
5# include "sanitizer_common/sanitizer_mac.h"
6#endif
4#include "sanitizer_common/sanitizer_stacktrace.h"7#include "sanitizer_common/sanitizer_stacktrace.h"
5#include "tsan_rtl.h"8#include "tsan_rtl.h"
69
...@@ -43,7 +46,12 @@ inline bool in_symbolizer() {...@@ -43,7 +46,12 @@ inline bool in_symbolizer() {
43#endif46#endif
4447
45inline bool MustIgnoreInterceptor(ThreadState *thr) {48inline bool MustIgnoreInterceptor(ThreadState *thr) {
46 return !thr->is_inited || thr->ignore_interceptors || thr->in_ignored_lib;49 return !thr->is_inited || thr->ignore_interceptors || thr->in_ignored_lib
50#if SANITIZER_APPLE && !SANITIZER_GO
51 || (flags()->lock_during_write != kLockDuringAllWrites &&
52 thr->in_internal_write_call)
53#endif
54 ;
47}55}
4856
49} // namespace __tsan57} // namespace __tsan
lib/libtsan/tsan_interceptors_mac.cpp+19
...@@ -281,6 +281,25 @@ TSAN_INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) {...@@ -281,6 +281,25 @@ TSAN_INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) {
281 Acquire(thr, pc, (uptr)lock);281 Acquire(thr, pc, (uptr)lock);
282}282}
283283
284// os_unfair_lock_lock_with_flags was introduced in macOS 15
285# if defined(__MAC_15_0) || defined(__IPHONE_18_0) || defined(__TVOS_18_0) || \
286 defined(__VISIONOS_2_0) || defined(__WATCHOS_11_0)
287# pragma clang diagnostic push
288# pragma clang diagnostic ignored "-Wunguarded-availability-new"
289// We're just intercepting this - if it doesn't exist on the platform, then the
290// process shouldn't have called it in the first place.
291TSAN_INTERCEPTOR(void, os_unfair_lock_lock_with_flags, os_unfair_lock_t lock,
292 os_unfair_lock_flags_t flags) {
293 if (!cur_thread()->is_inited || cur_thread()->is_dead) {
294 return REAL(os_unfair_lock_lock_with_flags)(lock, flags);
295 }
296 SCOPED_TSAN_INTERCEPTOR(os_unfair_lock_lock_with_flags, lock, flags);
297 REAL(os_unfair_lock_lock_with_flags)(lock, flags);
298 Acquire(thr, pc, (uptr)lock);
299}
300# pragma clang diagnostic pop
301# endif
302
284TSAN_INTERCEPTOR(void, os_unfair_lock_lock_with_options, os_unfair_lock_t lock,303TSAN_INTERCEPTOR(void, os_unfair_lock_lock_with_options, os_unfair_lock_t lock,
285 u32 options) {304 u32 options) {
286 if (!cur_thread()->is_inited || cur_thread()->is_dead) {305 if (!cur_thread()->is_inited || cur_thread()->is_dead) {
lib/libtsan/tsan_interceptors_posix.cpp+78-32
...@@ -22,6 +22,7 @@...@@ -22,6 +22,7 @@
22#include "sanitizer_common/sanitizer_internal_defs.h"22#include "sanitizer_common/sanitizer_internal_defs.h"
23#include "sanitizer_common/sanitizer_libc.h"23#include "sanitizer_common/sanitizer_libc.h"
24#include "sanitizer_common/sanitizer_linux.h"24#include "sanitizer_common/sanitizer_linux.h"
25#include "sanitizer_common/sanitizer_placement_new.h"
25#include "sanitizer_common/sanitizer_platform_interceptors.h"26#include "sanitizer_common/sanitizer_platform_interceptors.h"
26#include "sanitizer_common/sanitizer_platform_limits_netbsd.h"27#include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
27#include "sanitizer_common/sanitizer_platform_limits_posix.h"28#include "sanitizer_common/sanitizer_platform_limits_posix.h"
...@@ -30,6 +31,9 @@...@@ -30,6 +31,9 @@
30#include "sanitizer_common/sanitizer_tls_get_addr.h"31#include "sanitizer_common/sanitizer_tls_get_addr.h"
31#include "sanitizer_common/sanitizer_vector.h"32#include "sanitizer_common/sanitizer_vector.h"
32#include "tsan_fd.h"33#include "tsan_fd.h"
34#if SANITIZER_APPLE && !SANITIZER_GO
35# include "tsan_flags.h"
36#endif
33#include "tsan_interceptors.h"37#include "tsan_interceptors.h"
34#include "tsan_interface.h"38#include "tsan_interface.h"
35#include "tsan_mman.h"39#include "tsan_mman.h"
...@@ -78,17 +82,6 @@ struct ucontext_t {...@@ -78,17 +82,6 @@ struct ucontext_t {
78};82};
79#endif83#endif
8084
81#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 || \
82 defined(__s390x__)
83#define PTHREAD_ABI_BASE "GLIBC_2.3.2"
84#elif defined(__aarch64__) || SANITIZER_PPC64V2
85#define PTHREAD_ABI_BASE "GLIBC_2.17"
86#elif SANITIZER_LOONGARCH64
87#define PTHREAD_ABI_BASE "GLIBC_2.36"
88#elif SANITIZER_RISCV64
89# define PTHREAD_ABI_BASE "GLIBC_2.27"
90#endif
91
92extern "C" int pthread_attr_init(void *attr);85extern "C" int pthread_attr_init(void *attr);
93extern "C" int pthread_attr_destroy(void *attr);86extern "C" int pthread_attr_destroy(void *attr);
94DECLARE_REAL(int, pthread_attr_getdetachstate, void *, void *)87DECLARE_REAL(int, pthread_attr_getdetachstate, void *, void *)
...@@ -340,11 +333,6 @@ void ScopedInterceptor::DisableIgnoresImpl() {...@@ -340,11 +333,6 @@ void ScopedInterceptor::DisableIgnoresImpl() {
340}333}
341334
342#define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func)335#define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func)
343#if SANITIZER_FREEBSD || SANITIZER_NETBSD
344# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION(func)
345#else
346# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION_VER(func, ver)
347#endif
348#if SANITIZER_FREEBSD336#if SANITIZER_FREEBSD
349# define TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(func) \337# define TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(func) \
350 INTERCEPT_FUNCTION(_pthread_##func)338 INTERCEPT_FUNCTION(_pthread_##func)
...@@ -1145,6 +1133,22 @@ TSAN_INTERCEPTOR(int, pthread_create,...@@ -1145,6 +1133,22 @@ TSAN_INTERCEPTOR(int, pthread_create,
11451133
1146TSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) {1134TSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) {
1147 SCOPED_INTERCEPTOR_RAW(pthread_join, th, ret);1135 SCOPED_INTERCEPTOR_RAW(pthread_join, th, ret);
1136#if SANITIZER_ANDROID
1137 {
1138 // In Bionic, if the target thread has already exited when pthread_detach is
1139 // called, pthread_detach will call pthread_join internally to clean it up.
1140 // In that case, the thread has already been consumed by the pthread_detach
1141 // interceptor.
1142 Tid tid = ctx->thread_registry.FindThread(
1143 [](ThreadContextBase* tctx, void* arg) {
1144 return tctx->user_id == (uptr)arg;
1145 },
1146 th);
1147 if (tid == kInvalidTid) {
1148 return REAL(pthread_join)(th, ret);
1149 }
1150 }
1151#endif
1148 Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);1152 Tid tid = ThreadConsumeTid(thr, pc, (uptr)th);
1149 ThreadIgnoreBegin(thr, pc);1153 ThreadIgnoreBegin(thr, pc);
1150 int res = BLOCK_REAL(pthread_join)(th, ret);1154 int res = BLOCK_REAL(pthread_join)(th, ret);
...@@ -1664,6 +1668,14 @@ TSAN_INTERCEPTOR(int, pthread_barrier_wait, void *b) {...@@ -1664,6 +1668,14 @@ TSAN_INTERCEPTOR(int, pthread_barrier_wait, void *b) {
16641668
1665TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) {1669TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) {
1666 SCOPED_INTERCEPTOR_RAW(pthread_once, o, f);1670 SCOPED_INTERCEPTOR_RAW(pthread_once, o, f);
1671#if SANITIZER_APPLE && !SANITIZER_GO
1672 if (flags()->lock_during_write != kLockDuringAllWrites &&
1673 cur_thread_init()->in_internal_write_call) {
1674 // This is needed to make it through process launch without hanging
1675 f();
1676 return 0;
1677 }
1678#endif
1667 if (o == 0 || f == 0)1679 if (o == 0 || f == 0)
1668 return errno_EINVAL;1680 return errno_EINVAL;
1669 atomic_uint32_t *a;1681 atomic_uint32_t *a;
...@@ -2141,13 +2153,29 @@ static void ReportErrnoSpoiling(ThreadState *thr, uptr pc, int sig) {...@@ -2141,13 +2153,29 @@ static void ReportErrnoSpoiling(ThreadState *thr, uptr pc, int sig) {
2141 // StackTrace::GetNestInstructionPc(pc) is used because return address is2153 // StackTrace::GetNestInstructionPc(pc) is used because return address is
2142 // expected, OutputReport() will undo this.2154 // expected, OutputReport() will undo this.
2143 ObtainCurrentStack(thr, StackTrace::GetNextInstructionPc(pc), &stack);2155 ObtainCurrentStack(thr, StackTrace::GetNextInstructionPc(pc), &stack);
2144 ThreadRegistryLock l(&ctx->thread_registry);2156 // Use alloca, because malloc during signal handling deadlocks
2145 ScopedReport rep(ReportTypeErrnoInSignal);2157 ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
2146 rep.SetSigNum(sig);2158 bool suppressed;
2147 if (!IsFiredSuppression(ctx, ReportTypeErrnoInSignal, stack)) {2159 // Take a new scope as Apple platforms require the below locks released
2148 rep.AddStack(stack, true);2160 // before symbolizing in order to avoid a deadlock
2149 OutputReport(thr, rep);2161 {
2162 ThreadRegistryLock l(&ctx->thread_registry);
2163 new (rep) ScopedReport(ReportTypeErrnoInSignal);
2164 rep->SetSigNum(sig);
2165 suppressed = IsFiredSuppression(ctx, ReportTypeErrnoInSignal, stack);
2166 if (!suppressed)
2167 rep->AddStack(stack, true);
2168#if SANITIZER_APPLE
2169 } // Close this scope to release the locks before writing report
2170#endif
2171 if (!suppressed)
2172 OutputReport(thr, *rep);
2173
2174 // Need to manually destroy this because we used placement new to allocate
2175 rep->~ScopedReport();
2176#if !SANITIZER_APPLE
2150 }2177 }
2178#endif
2151}2179}
21522180
2153static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire,2181static void CallUserSignalHandler(ThreadState *thr, bool sync, bool acquire,
...@@ -2411,7 +2439,11 @@ TSAN_INTERCEPTOR(int, vfork, int fake) {...@@ -2411,7 +2439,11 @@ TSAN_INTERCEPTOR(int, vfork, int fake) {
2411}2439}
2412#endif2440#endif
24132441
2414#if SANITIZER_LINUX2442#if SANITIZER_LINUX && !SANITIZER_ANDROID
2443// Bionic's pthread_create internally calls clone. When the CLONE_THREAD flag is
2444// set, clone does not create a new process but a new thread. This is a
2445// workaround for Android. Disabling the interception of clone solves the
2446// problem in most scenarios.
2415TSAN_INTERCEPTOR(int, clone, int (*fn)(void *), void *stack, int flags,2447TSAN_INTERCEPTOR(int, clone, int (*fn)(void *), void *stack, int flags,
2416 void *arg, int *parent_tid, void *tls, pid_t *child_tid) {2448 void *arg, int *parent_tid, void *tls, pid_t *child_tid) {
2417 SCOPED_INTERCEPTOR_RAW(clone, fn, stack, flags, arg, parent_tid, tls,2449 SCOPED_INTERCEPTOR_RAW(clone, fn, stack, flags, arg, parent_tid, tls,
...@@ -2888,12 +2920,12 @@ TSAN_INTERCEPTOR(void, _lwp_exit) {...@@ -2888,12 +2920,12 @@ TSAN_INTERCEPTOR(void, _lwp_exit) {
2888#endif2920#endif
28892921
2890#if SANITIZER_FREEBSD2922#if SANITIZER_FREEBSD
2891TSAN_INTERCEPTOR(void, thr_exit, tid_t *state) {2923TSAN_INTERCEPTOR(void, thr_exit, ThreadID *state) {
2892 SCOPED_TSAN_INTERCEPTOR(thr_exit, state);2924 SCOPED_TSAN_INTERCEPTOR(thr_exit, state);
2893 DestroyThreadState();2925 DestroyThreadState();
2894 REAL(thr_exit(state));2926 REAL(thr_exit(state));
2895}2927}
2896#define TSAN_MAYBE_INTERCEPT_THR_EXIT TSAN_INTERCEPT(thr_exit)2928# define TSAN_MAYBE_INTERCEPT_THR_EXIT TSAN_INTERCEPT(thr_exit)
2897#else2929#else
2898#define TSAN_MAYBE_INTERCEPT_THR_EXIT2930#define TSAN_MAYBE_INTERCEPT_THR_EXIT
2899#endif2931#endif
...@@ -3024,12 +3056,26 @@ void InitializeInterceptors() {...@@ -3024,12 +3056,26 @@ void InitializeInterceptors() {
3024 TSAN_INTERCEPT(pthread_timedjoin_np);3056 TSAN_INTERCEPT(pthread_timedjoin_np);
3025 #endif3057 #endif
30263058
3027 TSAN_INTERCEPT_VER(pthread_cond_init, PTHREAD_ABI_BASE);3059 // In glibc versions older than 2.36, dlsym(RTLD_NEXT, "pthread_cond_init")
3028 TSAN_INTERCEPT_VER(pthread_cond_signal, PTHREAD_ABI_BASE);3060 // may return an outdated symbol (max(2.2,base_version)) if the port was
3029 TSAN_INTERCEPT_VER(pthread_cond_broadcast, PTHREAD_ABI_BASE);3061 // introduced before 2.3.2 (when the new pthread_cond_t was introduced).
3030 TSAN_INTERCEPT_VER(pthread_cond_wait, PTHREAD_ABI_BASE);3062#if SANITIZER_GLIBC && !__GLIBC_PREREQ(2, 36) && \
3031 TSAN_INTERCEPT_VER(pthread_cond_timedwait, PTHREAD_ABI_BASE);3063 (defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 || \
3032 TSAN_INTERCEPT_VER(pthread_cond_destroy, PTHREAD_ABI_BASE);3064 defined(__s390x__))
3065 INTERCEPT_FUNCTION_VER(pthread_cond_init, "GLIBC_2.3.2");
3066 INTERCEPT_FUNCTION_VER(pthread_cond_signal, "GLIBC_2.3.2");
3067 INTERCEPT_FUNCTION_VER(pthread_cond_broadcast, "GLIBC_2.3.2");
3068 INTERCEPT_FUNCTION_VER(pthread_cond_wait, "GLIBC_2.3.2");
3069 INTERCEPT_FUNCTION_VER(pthread_cond_timedwait, "GLIBC_2.3.2");
3070 INTERCEPT_FUNCTION_VER(pthread_cond_destroy, "GLIBC_2.3.2");
3071#else
3072 INTERCEPT_FUNCTION(pthread_cond_init);
3073 INTERCEPT_FUNCTION(pthread_cond_signal);
3074 INTERCEPT_FUNCTION(pthread_cond_broadcast);
3075 INTERCEPT_FUNCTION(pthread_cond_wait);
3076 INTERCEPT_FUNCTION(pthread_cond_timedwait);
3077 INTERCEPT_FUNCTION(pthread_cond_destroy);
3078#endif
30333079
3034 TSAN_MAYBE_PTHREAD_COND_CLOCKWAIT;3080 TSAN_MAYBE_PTHREAD_COND_CLOCKWAIT;
30353081
...@@ -3120,7 +3166,7 @@ void InitializeInterceptors() {...@@ -3120,7 +3166,7 @@ void InitializeInterceptors() {
31203166
3121 TSAN_INTERCEPT(fork);3167 TSAN_INTERCEPT(fork);
3122 TSAN_INTERCEPT(vfork);3168 TSAN_INTERCEPT(vfork);
3123#if SANITIZER_LINUX3169#if SANITIZER_LINUX && !SANITIZER_ANDROID
3124 TSAN_INTERCEPT(clone);3170 TSAN_INTERCEPT(clone);
3125#endif3171#endif
3126#if !SANITIZER_ANDROID3172#if !SANITIZER_ANDROID
lib/libtsan/tsan_interface.h+3-3
...@@ -16,7 +16,7 @@...@@ -16,7 +16,7 @@
16#define TSAN_INTERFACE_H16#define TSAN_INTERFACE_H
1717
18#include <sanitizer_common/sanitizer_internal_defs.h>18#include <sanitizer_common/sanitizer_internal_defs.h>
19using __sanitizer::tid_t;19using __sanitizer::ThreadID;
20using __sanitizer::uptr;20using __sanitizer::uptr;
2121
22// This header should NOT include any other headers.22// This header should NOT include any other headers.
...@@ -175,7 +175,7 @@ int __tsan_get_report_mutex(void *report, uptr idx, uptr *mutex_id, void **addr,...@@ -175,7 +175,7 @@ int __tsan_get_report_mutex(void *report, uptr idx, uptr *mutex_id, void **addr,
175175
176// Returns information about threads included in the report.176// Returns information about threads included in the report.
177SANITIZER_INTERFACE_ATTRIBUTE177SANITIZER_INTERFACE_ATTRIBUTE
178int __tsan_get_report_thread(void *report, uptr idx, int *tid, tid_t *os_id,178int __tsan_get_report_thread(void *report, uptr idx, int *tid, ThreadID *os_id,
179 int *running, const char **name, int *parent_tid,179 int *running, const char **name, int *parent_tid,
180 void **trace, uptr trace_size);180 void **trace, uptr trace_size);
181181
...@@ -192,7 +192,7 @@ const char *__tsan_locate_address(uptr addr, char *name, uptr name_size,...@@ -192,7 +192,7 @@ const char *__tsan_locate_address(uptr addr, char *name, uptr name_size,
192// Returns the allocation stack for a heap pointer.192// Returns the allocation stack for a heap pointer.
193SANITIZER_INTERFACE_ATTRIBUTE193SANITIZER_INTERFACE_ATTRIBUTE
194int __tsan_get_alloc_stack(uptr addr, uptr *trace, uptr size, int *thread_id,194int __tsan_get_alloc_stack(uptr addr, uptr *trace, uptr size, int *thread_id,
195 tid_t *os_id);195 ThreadID *os_id);
196196
197#endif // SANITIZER_GO197#endif // SANITIZER_GO
198198
lib/libtsan/tsan_interface_ann.cpp+23-9
...@@ -437,16 +437,30 @@ void __tsan_mutex_post_divert(void *addr, unsigned flagz) {...@@ -437,16 +437,30 @@ void __tsan_mutex_post_divert(void *addr, unsigned flagz) {
437}437}
438438
439static void ReportMutexHeldWrongContext(ThreadState *thr, uptr pc) {439static void ReportMutexHeldWrongContext(ThreadState *thr, uptr pc) {
440 ThreadRegistryLock l(&ctx->thread_registry);440 // Use alloca, because malloc during signal handling deadlocks
441 ScopedReport rep(ReportTypeMutexHeldWrongContext);441 ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
442 for (uptr i = 0; i < thr->mset.Size(); ++i) {442 // Take a new scope as Apple platforms require the below locks released
443 MutexSet::Desc desc = thr->mset.Get(i);443 // before symbolizing in order to avoid a deadlock
444 rep.AddMutex(desc.addr, desc.stack_id);444 {
445 ThreadRegistryLock l(&ctx->thread_registry);
446 new (rep) ScopedReport(ReportTypeMutexHeldWrongContext);
447 for (uptr i = 0; i < thr->mset.Size(); ++i) {
448 MutexSet::Desc desc = thr->mset.Get(i);
449 rep->AddMutex(desc.addr, desc.stack_id);
450 }
451 VarSizeStackTrace trace;
452 ObtainCurrentStack(thr, pc, &trace);
453 rep->AddStack(trace, true);
454#if SANITIZER_APPLE
455 } // Close this scope to release the locks
456#endif
457 OutputReport(thr, *rep);
458
459 // Need to manually destroy this because we used placement new to allocate
460 rep->~ScopedReport();
461#if !SANITIZER_APPLE
445 }462 }
446 VarSizeStackTrace trace;463#endif
447 ObtainCurrentStack(thr, pc, &trace);
448 rep.AddStack(trace, true);
449 OutputReport(thr, rep);
450}464}
451465
452INTERFACE_ATTRIBUTE466INTERFACE_ATTRIBUTE
lib/libtsan/tsan_mman.cpp+18-4
...@@ -182,10 +182,24 @@ static void SignalUnsafeCall(ThreadState *thr, uptr pc) {...@@ -182,10 +182,24 @@ static void SignalUnsafeCall(ThreadState *thr, uptr pc) {
182 ObtainCurrentStack(thr, pc, &stack);182 ObtainCurrentStack(thr, pc, &stack);
183 if (IsFiredSuppression(ctx, ReportTypeSignalUnsafe, stack))183 if (IsFiredSuppression(ctx, ReportTypeSignalUnsafe, stack))
184 return;184 return;
185 ThreadRegistryLock l(&ctx->thread_registry);185 // Use alloca, because malloc during signal handling deadlocks
186 ScopedReport rep(ReportTypeSignalUnsafe);186 ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
187 rep.AddStack(stack, true);187 // Take a new scope as Apple platforms require the below locks released
188 OutputReport(thr, rep);188 // before symbolizing in order to avoid a deadlock
189 {
190 ThreadRegistryLock l(&ctx->thread_registry);
191 new (rep) ScopedReport(ReportTypeSignalUnsafe);
192 rep->AddStack(stack, true);
193#if SANITIZER_APPLE
194 } // Close this scope to release the locks
195#endif
196 OutputReport(thr, *rep);
197
198 // Need to manually destroy this because we used placement new to allocate
199 rep->~ScopedReport();
200#if !SANITIZER_APPLE
201 }
202#endif
189}203}
190204
191205
lib/libtsan/tsan_platform.h+44-7
...@@ -681,6 +681,32 @@ struct MappingGoMips64_47 {...@@ -681,6 +681,32 @@ struct MappingGoMips64_47 {
681 static const uptr kShadowAdd = 0x200000000000ull;681 static const uptr kShadowAdd = 0x200000000000ull;
682};682};
683683
684/* Go on linux/riscv64 (39-bit VMA)
6850000 0001 0000 - 000f 0000 0000: executable and heap (60 GiB)
686000f 0000 0000 - 0010 0000 0000: -
6870010 0000 0000 - 0030 0000 0000: shadow - 128 GiB ( ~ 2 * app)
6880030 0000 0000 - 0038 0000 0000: metainfo - 32 GiB ( ~ 0.5 * app)
6890038 0000 0000 - 0040 0000 0000: -
690*/
691struct MappingGoRiscv64_39 {
692 static const uptr kMetaShadowBeg = 0x003000000000ull;
693 static const uptr kMetaShadowEnd = 0x003800000000ull;
694 static const uptr kShadowBeg = 0x001000000000ull;
695 static const uptr kShadowEnd = 0x003000000000ull;
696 static const uptr kLoAppMemBeg = 0x000000010000ull;
697 static const uptr kLoAppMemEnd = 0x000f00000000ull;
698 static const uptr kMidAppMemBeg = 0;
699 static const uptr kMidAppMemEnd = 0;
700 static const uptr kHiAppMemBeg = 0;
701 static const uptr kHiAppMemEnd = 0;
702 static const uptr kHeapMemBeg = 0;
703 static const uptr kHeapMemEnd = 0;
704 static const uptr kVdsoBeg = 0;
705 static const uptr kShadowMsk = 0;
706 static const uptr kShadowXor = 0;
707 static const uptr kShadowAdd = 0x001000000000ull;
708};
709
684/* Go on linux/riscv64 (48-bit VMA)710/* Go on linux/riscv64 (48-bit VMA)
6850000 0001 0000 - 00e0 0000 0000: executable and heap (896 GiB)7110000 0001 0000 - 00e0 0000 0000: executable and heap (896 GiB)
68600e0 0000 0000 - 2000 0000 0000: -71200e0 0000 0000 - 2000 0000 0000: -
...@@ -689,13 +715,13 @@ struct MappingGoMips64_47 {...@@ -689,13 +715,13 @@ struct MappingGoMips64_47 {
6893000 0000 0000 - 3100 0000 0000: metainfo - 1 TiB ( ~ 1 * app)7153000 0000 0000 - 3100 0000 0000: metainfo - 1 TiB ( ~ 1 * app)
6903100 0000 0000 - 8000 0000 0000: -7163100 0000 0000 - 8000 0000 0000: -
691*/717*/
692struct MappingGoRiscv64 {718struct MappingGoRiscv64_48 {
693 static const uptr kMetaShadowBeg = 0x300000000000ull;719 static const uptr kMetaShadowBeg = 0x300000000000ull;
694 static const uptr kMetaShadowEnd = 0x310000000000ull;720 static const uptr kMetaShadowEnd = 0x310000000000ull;
695 static const uptr kShadowBeg = 0x200000000000ull;721 static const uptr kShadowBeg = 0x200000000000ull;
696 static const uptr kShadowEnd = 0x240000000000ull;722 static const uptr kShadowEnd = 0x240000000000ull;
697 static const uptr kLoAppMemBeg = 0x000000010000ull;723 static const uptr kLoAppMemBeg = 0x000000010000ull;
698 static const uptr kLoAppMemEnd = 0x000e00000000ull;724 static const uptr kLoAppMemEnd = 0x00e000000000ull;
699 static const uptr kMidAppMemBeg = 0;725 static const uptr kMidAppMemBeg = 0;
700 static const uptr kMidAppMemEnd = 0;726 static const uptr kMidAppMemEnd = 0;
701 static const uptr kHiAppMemBeg = 0;727 static const uptr kHiAppMemBeg = 0;
...@@ -756,7 +782,12 @@ ALWAYS_INLINE auto SelectMapping(Arg arg) {...@@ -756,7 +782,12 @@ ALWAYS_INLINE auto SelectMapping(Arg arg) {
756# elif defined(__loongarch_lp64)782# elif defined(__loongarch_lp64)
757 return Func::template Apply<MappingGoLoongArch64_47>(arg);783 return Func::template Apply<MappingGoLoongArch64_47>(arg);
758# elif SANITIZER_RISCV64784# elif SANITIZER_RISCV64
759 return Func::template Apply<MappingGoRiscv64>(arg);785 switch (vmaSize) {
786 case 39:
787 return Func::template Apply<MappingGoRiscv64_39>(arg);
788 case 48:
789 return Func::template Apply<MappingGoRiscv64_48>(arg);
790 }
760# elif SANITIZER_WINDOWS791# elif SANITIZER_WINDOWS
761 return Func::template Apply<MappingGoWindows>(arg);792 return Func::template Apply<MappingGoWindows>(arg);
762# else793# else
...@@ -827,7 +858,8 @@ void ForEachMapping() {...@@ -827,7 +858,8 @@ void ForEachMapping() {
827 Func::template Apply<MappingGoAarch64>();858 Func::template Apply<MappingGoAarch64>();
828 Func::template Apply<MappingGoLoongArch64_47>();859 Func::template Apply<MappingGoLoongArch64_47>();
829 Func::template Apply<MappingGoMips64_47>();860 Func::template Apply<MappingGoMips64_47>();
830 Func::template Apply<MappingGoRiscv64>();861 Func::template Apply<MappingGoRiscv64_39>();
862 Func::template Apply<MappingGoRiscv64_48>();
831 Func::template Apply<MappingGoS390x>();863 Func::template Apply<MappingGoS390x>();
832}864}
833865
...@@ -926,7 +958,9 @@ struct IsAppMemImpl {...@@ -926,7 +958,9 @@ struct IsAppMemImpl {
926};958};
927959
928ALWAYS_INLINE960ALWAYS_INLINE
929bool IsAppMem(uptr mem) { return SelectMapping<IsAppMemImpl>(mem); }961bool IsAppMem(uptr mem) {
962 return SelectMapping<IsAppMemImpl>(STRIP_MTE_TAG(mem));
963}
930964
931struct IsShadowMemImpl {965struct IsShadowMemImpl {
932 template <typename Mapping>966 template <typename Mapping>
...@@ -965,7 +999,8 @@ struct MemToShadowImpl {...@@ -965,7 +999,8 @@ struct MemToShadowImpl {
965999
966ALWAYS_INLINE1000ALWAYS_INLINE
967RawShadow *MemToShadow(uptr x) {1001RawShadow *MemToShadow(uptr x) {
968 return reinterpret_cast<RawShadow *>(SelectMapping<MemToShadowImpl>(x));1002 return reinterpret_cast<RawShadow*>(
1003 SelectMapping<MemToShadowImpl>(STRIP_MTE_TAG(x)));
969}1004}
9701005
971struct MemToMetaImpl {1006struct MemToMetaImpl {
...@@ -979,7 +1014,9 @@ struct MemToMetaImpl {...@@ -979,7 +1014,9 @@ struct MemToMetaImpl {
979};1014};
9801015
981ALWAYS_INLINE1016ALWAYS_INLINE
982u32 *MemToMeta(uptr x) { return SelectMapping<MemToMetaImpl>(x); }1017u32* MemToMeta(uptr x) {
1018 return SelectMapping<MemToMetaImpl>(STRIP_MTE_TAG(x));
1019}
9831020
984struct ShadowToMemImpl {1021struct ShadowToMemImpl {
985 template <typename Mapping>1022 template <typename Mapping>
lib/libtsan/tsan_platform_linux.cpp+42-14
...@@ -393,9 +393,9 @@ void InitializePlatformEarly() {...@@ -393,9 +393,9 @@ void InitializePlatformEarly() {
393 Die();393 Die();
394 }394 }
395# else395# else
396 if (vmaSize != 48) {396 if (vmaSize != 39 && vmaSize != 48) {
397 Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");397 Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
398 Printf("FATAL: Found %zd - Supported 48\n", vmaSize);398 Printf("FATAL: Found %zd - Supported 39 and 48\n", vmaSize);
399 Die();399 Die();
400 }400 }
401# endif401# endif
...@@ -415,7 +415,7 @@ void InitializePlatform() {...@@ -415,7 +415,7 @@ void InitializePlatform() {
415 // is not compiled with -pie.415 // is not compiled with -pie.
416#if !SANITIZER_GO416#if !SANITIZER_GO
417 {417 {
418# if SANITIZER_LINUX && (defined(__aarch64__) || defined(__loongarch_lp64))418# if INIT_LONGJMP_XOR_KEY
419 // Initialize the xor key used in {sig}{set,long}jump.419 // Initialize the xor key used in {sig}{set,long}jump.
420 InitializeLongjmpXorKey();420 InitializeLongjmpXorKey();
421# endif421# endif
...@@ -486,8 +486,20 @@ int ExtractRecvmsgFDs(void *msgp, int *fds, int nfd) {...@@ -486,8 +486,20 @@ int ExtractRecvmsgFDs(void *msgp, int *fds, int nfd) {
486486
487// Reverse operation of libc stack pointer mangling487// Reverse operation of libc stack pointer mangling
488static uptr UnmangleLongJmpSp(uptr mangled_sp) {488static uptr UnmangleLongJmpSp(uptr mangled_sp) {
489#if defined(__x86_64__)489# if SANITIZER_ANDROID && INIT_LONGJMP_XOR_KEY
490# if SANITIZER_LINUX490 if (longjmp_xor_key == 0) {
491 // bionic libc initialization process: __libc_init_globals ->
492 // __libc_init_vdso (calls strcmp) -> __libc_init_setjmp_cookie. strcmp is
493 // intercepted by TSan, so during TSan initialization the setjmp_cookie
494 // remains uninitialized. On Android, longjmp_xor_key must be set on first
495 // use.
496 InitializeLongjmpXorKey();
497 CHECK_NE(longjmp_xor_key, 0);
498 }
499# endif
500
501# if defined(__x86_64__)
502# if SANITIZER_LINUX
491 // Reverse of:503 // Reverse of:
492 // xor %fs:0x30, %rsi504 // xor %fs:0x30, %rsi
493 // rol $0x11, %rsi505 // rol $0x11, %rsi
...@@ -542,13 +554,23 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {...@@ -542,13 +554,23 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
542# else554# else
543# define LONG_JMP_SP_ENV_SLOT 2555# define LONG_JMP_SP_ENV_SLOT 2
544# endif556# endif
545#elif SANITIZER_LINUX557# elif SANITIZER_ANDROID
546# ifdef __aarch64__558# ifdef __aarch64__
547# define LONG_JMP_SP_ENV_SLOT 13559# define LONG_JMP_SP_ENV_SLOT 3
548# elif defined(__loongarch__)560# elif SANITIZER_RISCV64
549# define LONG_JMP_SP_ENV_SLOT 1561# define LONG_JMP_SP_ENV_SLOT 3
550# elif defined(__mips64)562# elif defined(__x86_64__)
551# define LONG_JMP_SP_ENV_SLOT 1563# define LONG_JMP_SP_ENV_SLOT 6
564# else
565# error unsupported
566# endif
567# elif SANITIZER_LINUX
568# ifdef __aarch64__
569# define LONG_JMP_SP_ENV_SLOT 13
570# elif defined(__loongarch__)
571# define LONG_JMP_SP_ENV_SLOT 1
572# elif defined(__mips64)
573# define LONG_JMP_SP_ENV_SLOT 1
552# elif SANITIZER_RISCV64574# elif SANITIZER_RISCV64
553# define LONG_JMP_SP_ENV_SLOT 13575# define LONG_JMP_SP_ENV_SLOT 13
554# elif defined(__s390x__)576# elif defined(__s390x__)
...@@ -556,7 +578,7 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {...@@ -556,7 +578,7 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
556# else578# else
557# define LONG_JMP_SP_ENV_SLOT 6579# define LONG_JMP_SP_ENV_SLOT 6
558# endif580# endif
559#endif581# endif
560582
561uptr ExtractLongJmpSp(uptr *env) {583uptr ExtractLongJmpSp(uptr *env) {
562 uptr mangled_sp = env[LONG_JMP_SP_ENV_SLOT];584 uptr mangled_sp = env[LONG_JMP_SP_ENV_SLOT];
...@@ -653,7 +675,13 @@ ThreadState *cur_thread() {...@@ -653,7 +675,13 @@ ThreadState *cur_thread() {
653 }675 }
654 CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &oldset, nullptr));676 CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &oldset, nullptr));
655 }677 }
656 return thr;678
679 // Skia calls mallopt(M_THREAD_DISABLE_MEM_INIT, 1), which sets the least
680 // significant bit of TLS_SLOT_SANITIZER to 1. Scudo allocator uses this bit
681 // as a flag to disable memory initialization. This is a workaround to get the
682 // correct ThreadState pointer.
683 uptr addr = reinterpret_cast<uptr>(thr);
684 return reinterpret_cast<ThreadState*>(addr & ~1ULL);
657}685}
658686
659void set_cur_thread(ThreadState *thr) {687void set_cur_thread(ThreadState *thr) {
lib/libtsan/tsan_platform_mac.cpp+16-3
...@@ -226,9 +226,20 @@ static void ThreadTerminateCallback(uptr thread) {...@@ -226,9 +226,20 @@ static void ThreadTerminateCallback(uptr thread) {
226void InitializePlatformEarly() {226void InitializePlatformEarly() {
227# if !SANITIZER_GO && SANITIZER_IOS227# if !SANITIZER_GO && SANITIZER_IOS
228 uptr max_vm = GetMaxUserVirtualAddress() + 1;228 uptr max_vm = GetMaxUserVirtualAddress() + 1;
229 if (max_vm != HiAppMemEnd()) {229 if (max_vm < HiAppMemEnd()) {
230 Printf("ThreadSanitizer: unsupported vm address limit %p, expected %p.\n",230 Report(
231 (void *)max_vm, (void *)HiAppMemEnd());231 "ThreadSanitizer: Unsupported virtual memory layout:\n\tVM address "
232 "limit = %p\n\tExpected %p.\n",
233 (void*)max_vm, (void*)HiAppMemEnd());
234 Die();
235 }
236 // In some configurations, the max_vm is expanded, but much of this space is
237 // already mapped. TSAN will not work in this configuration.
238 if (!MemoryRangeIsAvailable(HiAppMemEnd() - 1, HiAppMemEnd() - 1)) {
239 Report(
240 "ThreadSanitizer: Unsupported virtual memory layout: Address %p is "
241 "already mapped.\n",
242 (void*)(HiAppMemEnd() - 1));
232 Die();243 Die();
233 }244 }
234#endif245#endif
...@@ -248,7 +259,9 @@ void InitializePlatform() {...@@ -248,7 +259,9 @@ void InitializePlatform() {
248259
249 ThreadEventCallbacks callbacks = {260 ThreadEventCallbacks callbacks = {
250 .create = ThreadCreateCallback,261 .create = ThreadCreateCallback,
262 .start = nullptr,
251 .terminate = ThreadTerminateCallback,263 .terminate = ThreadTerminateCallback,
264 .destroy = nullptr,
252 };265 };
253 InstallPthreadIntrospectionHook(callbacks);266 InstallPthreadIntrospectionHook(callbacks);
254#endif267#endif
lib/libtsan/tsan_report.h+14-1
...@@ -12,6 +12,8 @@...@@ -12,6 +12,8 @@
12#ifndef TSAN_REPORT_H12#ifndef TSAN_REPORT_H
13#define TSAN_REPORT_H13#define TSAN_REPORT_H
1414
15#include "sanitizer_common/sanitizer_internal_defs.h"
16#include "sanitizer_common/sanitizer_stacktrace.h"
15#include "sanitizer_common/sanitizer_symbolizer.h"17#include "sanitizer_common/sanitizer_symbolizer.h"
16#include "sanitizer_common/sanitizer_thread_registry.h"18#include "sanitizer_common/sanitizer_thread_registry.h"
17#include "sanitizer_common/sanitizer_vector.h"19#include "sanitizer_common/sanitizer_vector.h"
...@@ -56,6 +58,7 @@ struct ReportMop {...@@ -56,6 +58,7 @@ struct ReportMop {
56 bool atomic;58 bool atomic;
57 uptr external_tag;59 uptr external_tag;
58 Vector<ReportMopMutex> mset;60 Vector<ReportMopMutex> mset;
61 StackTrace stack_trace;
59 ReportStack *stack;62 ReportStack *stack;
6063
61 ReportMop();64 ReportMop();
...@@ -79,25 +82,34 @@ struct ReportLocation {...@@ -79,25 +82,34 @@ struct ReportLocation {
79 int fd = 0;82 int fd = 0;
80 bool fd_closed = false;83 bool fd_closed = false;
81 bool suppressable = false;84 bool suppressable = false;
85 StackID stack_id = 0;
82 ReportStack *stack = nullptr;86 ReportStack *stack = nullptr;
83};87};
8488
85struct ReportThread {89struct ReportThread {
86 Tid id;90 Tid id;
87 tid_t os_id;91 ThreadID os_id;
88 bool running;92 bool running;
89 ThreadType thread_type;93 ThreadType thread_type;
90 char *name;94 char *name;
91 Tid parent_tid;95 Tid parent_tid;
96 StackID stack_id;
92 ReportStack *stack;97 ReportStack *stack;
98 bool suppressable;
93};99};
94100
95struct ReportMutex {101struct ReportMutex {
96 int id;102 int id;
97 uptr addr;103 uptr addr;
104 StackID stack_id;
98 ReportStack *stack;105 ReportStack *stack;
99};106};
100107
108struct AddedLocationAddr {
109 uptr addr;
110 usize locs_idx;
111};
112
101class ReportDesc {113class ReportDesc {
102 public:114 public:
103 ReportType typ;115 ReportType typ;
...@@ -105,6 +117,7 @@ class ReportDesc {...@@ -105,6 +117,7 @@ class ReportDesc {
105 Vector<ReportStack*> stacks;117 Vector<ReportStack*> stacks;
106 Vector<ReportMop*> mops;118 Vector<ReportMop*> mops;
107 Vector<ReportLocation*> locs;119 Vector<ReportLocation*> locs;
120 Vector<AddedLocationAddr> added_location_addrs;
108 Vector<ReportMutex*> mutexes;121 Vector<ReportMutex*> mutexes;
109 Vector<ReportThread*> threads;122 Vector<ReportThread*> threads;
110 Vector<Tid> unique_tids;123 Vector<Tid> unique_tids;
lib/libtsan/tsan_rtl.cpp+14
...@@ -40,6 +40,13 @@ SANITIZER_WEAK_DEFAULT_IMPL...@@ -40,6 +40,13 @@ SANITIZER_WEAK_DEFAULT_IMPL
40void __tsan_test_only_on_fork() {}40void __tsan_test_only_on_fork() {}
41#endif41#endif
4242
43#if SANITIZER_APPLE && !SANITIZER_GO
44// Override weak symbol from sanitizer_common
45extern void __tsan_set_in_internal_write_call(bool value) {
46 __tsan::cur_thread_init()->in_internal_write_call = value;
47}
48#endif
49
43namespace __tsan {50namespace __tsan {
4451
45#if !SANITIZER_GO52#if !SANITIZER_GO
...@@ -893,6 +900,13 @@ void ForkChildAfter(ThreadState* thr, uptr pc, bool start_thread) {...@@ -893,6 +900,13 @@ void ForkChildAfter(ThreadState* thr, uptr pc, bool start_thread) {
893 ThreadIgnoreBegin(thr, pc);900 ThreadIgnoreBegin(thr, pc);
894 ThreadIgnoreSyncBegin(thr, pc);901 ThreadIgnoreSyncBegin(thr, pc);
895 }902 }
903
904# if SANITIZER_APPLE && !SANITIZER_GO
905 // This flag can have inheritance disabled - we are the child so act
906 // accordingly
907 if (flags()->lock_during_write == kNoLockDuringWritesCurrentProcess)
908 flags()->lock_during_write = kLockDuringAllWrites;
909# endif
896}910}
897#endif911#endif
898912
lib/libtsan/tsan_rtl.h+7-2
...@@ -236,6 +236,10 @@ struct alignas(SANITIZER_CACHE_LINE_SIZE) ThreadState {...@@ -236,6 +236,10 @@ struct alignas(SANITIZER_CACHE_LINE_SIZE) ThreadState {
236236
237 const ReportDesc *current_report;237 const ReportDesc *current_report;
238238
239#if SANITIZER_APPLE && !SANITIZER_GO
240 bool in_internal_write_call;
241#endif
242
239 explicit ThreadState(Tid tid);243 explicit ThreadState(Tid tid);
240};244};
241245
...@@ -420,6 +424,7 @@ class ScopedReportBase {...@@ -420,6 +424,7 @@ class ScopedReportBase {
420 void AddSleep(StackID stack_id);424 void AddSleep(StackID stack_id);
421 void SetCount(int count);425 void SetCount(int count);
422 void SetSigNum(int sig);426 void SetSigNum(int sig);
427 void SymbolizeStackElems(void);
423428
424 const ReportDesc *GetReport() const;429 const ReportDesc *GetReport() const;
425430
...@@ -498,7 +503,7 @@ void ForkChildAfter(ThreadState *thr, uptr pc, bool start_thread);...@@ -498,7 +503,7 @@ void ForkChildAfter(ThreadState *thr, uptr pc, bool start_thread);
498503
499void ReportRace(ThreadState *thr, RawShadow *shadow_mem, Shadow cur, Shadow old,504void ReportRace(ThreadState *thr, RawShadow *shadow_mem, Shadow cur, Shadow old,
500 AccessType typ);505 AccessType typ);
501bool OutputReport(ThreadState *thr, const ScopedReport &srep);506bool OutputReport(ThreadState *thr, ScopedReport &srep);
502bool IsFiredSuppression(Context *ctx, ReportType type, StackTrace trace);507bool IsFiredSuppression(Context *ctx, ReportType type, StackTrace trace);
503bool IsExpectedReport(uptr addr, uptr size);508bool IsExpectedReport(uptr addr, uptr size);
504509
...@@ -559,7 +564,7 @@ void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc);...@@ -559,7 +564,7 @@ void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc);
559void ThreadIgnoreSyncEnd(ThreadState *thr);564void ThreadIgnoreSyncEnd(ThreadState *thr);
560565
561Tid ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached);566Tid ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached);
562void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,567void ThreadStart(ThreadState *thr, Tid tid, ThreadID os_id,
563 ThreadType thread_type);568 ThreadType thread_type);
564void ThreadFinish(ThreadState *thr);569void ThreadFinish(ThreadState *thr);
565Tid ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid);570Tid ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid);
lib/libtsan/tsan_rtl_aarch64.S+3-5
...@@ -4,10 +4,8 @@...@@ -4,10 +4,8 @@
4#include "sanitizer_common/sanitizer_asm.h"4#include "sanitizer_common/sanitizer_asm.h"
5#include "builtins/assembly.h"5#include "builtins/assembly.h"
66
7#if !defined(__APPLE__)7TEXT_SECTION
8.section .text8#if defined(__APPLE__)
9#else
10.section __TEXT,__text
11.align 39.align 3
12#endif10#endif
1311
...@@ -222,6 +220,6 @@ ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp))...@@ -222,6 +220,6 @@ ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp))
222220
223NO_EXEC_STACK_DIRECTIVE221NO_EXEC_STACK_DIRECTIVE
224222
225GNU_PROPERTY_BTI_PAC223GNU_PROPERTY_BTI_PAC_GCS
226224
227#endif225#endif
lib/libtsan/tsan_rtl_access.cpp+8-3
...@@ -419,6 +419,11 @@ NOINLINE void TraceRestartMemoryAccess(ThreadState* thr, uptr pc, uptr addr,...@@ -419,6 +419,11 @@ NOINLINE void TraceRestartMemoryAccess(ThreadState* thr, uptr pc, uptr addr,
419419
420ALWAYS_INLINE USED void MemoryAccess(ThreadState* thr, uptr pc, uptr addr,420ALWAYS_INLINE USED void MemoryAccess(ThreadState* thr, uptr pc, uptr addr,
421 uptr size, AccessType typ) {421 uptr size, AccessType typ) {
422#if SANITIZER_APPLE && !SANITIZER_GO
423 // Swift symbolizer can be intercepted and deadlock without this
424 if (thr->in_symbolizer)
425 return;
426#endif
422 RawShadow* shadow_mem = MemToShadow(addr);427 RawShadow* shadow_mem = MemToShadow(addr);
423 UNUSED char memBuf[4][64];428 UNUSED char memBuf[4][64];
424 DPrintf2("#%d: Access: %d@%d %p/%zd typ=0x%x {%s, %s, %s, %s}\n", thr->tid,429 DPrintf2("#%d: Access: %d@%d %p/%zd typ=0x%x {%s, %s, %s, %s}\n", thr->tid,
...@@ -684,7 +689,7 @@ void MemoryAccessRangeT(ThreadState* thr, uptr pc, uptr addr, uptr size) {...@@ -684,7 +689,7 @@ void MemoryAccessRangeT(ThreadState* thr, uptr pc, uptr addr, uptr size) {
684 DCHECK(IsAppMem(addr + size - 1));689 DCHECK(IsAppMem(addr + size - 1));
685 }690 }
686 if (!IsShadowMem(shadow_mem)) {691 if (!IsShadowMem(shadow_mem)) {
687 Printf("Bad shadow start addr: %p (%p)\n", shadow_mem, (void*)addr);692 Printf("Bad shadow start addr: %p (%p)\n", (void*)shadow_mem, (void*)addr);
688 DCHECK(IsShadowMem(shadow_mem));693 DCHECK(IsShadowMem(shadow_mem));
689 }694 }
690695
...@@ -693,12 +698,12 @@ void MemoryAccessRangeT(ThreadState* thr, uptr pc, uptr addr, uptr size) {...@@ -693,12 +698,12 @@ void MemoryAccessRangeT(ThreadState* thr, uptr pc, uptr addr, uptr size) {
693 RawShadow* shadow_mem_end =698 RawShadow* shadow_mem_end =
694 shadow_mem + rounded_size / kShadowCell * kShadowCnt;699 shadow_mem + rounded_size / kShadowCell * kShadowCnt;
695 if (!IsShadowMem(shadow_mem_end - 1)) {700 if (!IsShadowMem(shadow_mem_end - 1)) {
696 Printf("Bad shadow end addr: %p (%p)\n", shadow_mem_end - 1,701 Printf("Bad shadow end addr: %p (%p)\n", (void*)(shadow_mem_end - 1),
697 (void*)(addr + size - 1));702 (void*)(addr + size - 1));
698 Printf(703 Printf(
699 "Shadow start addr (ok): %p (%p); size: 0x%zx; rounded_size: 0x%zx; "704 "Shadow start addr (ok): %p (%p); size: 0x%zx; rounded_size: 0x%zx; "
700 "kShadowMultiplier: %zx\n",705 "kShadowMultiplier: %zx\n",
701 shadow_mem, (void*)addr, size, rounded_size, kShadowMultiplier);706 (void*)shadow_mem, (void*)addr, size, rounded_size, kShadowMultiplier);
702 DCHECK(IsShadowMem(shadow_mem_end - 1));707 DCHECK(IsShadowMem(shadow_mem_end - 1));
703 }708 }
704#endif709#endif
lib/libtsan/tsan_rtl_amd64.S+2
...@@ -3,6 +3,8 @@...@@ -3,6 +3,8 @@
33
4#include "sanitizer_common/sanitizer_asm.h"4#include "sanitizer_common/sanitizer_asm.h"
55
6.att_syntax
7
6#if !defined(__APPLE__)8#if !defined(__APPLE__)
7.section .text9.section .text
8#else10#else
lib/libtsan/tsan_rtl_mutex.cpp+94-49
...@@ -11,14 +11,15 @@...@@ -11,14 +11,15 @@
11//===----------------------------------------------------------------------===//11//===----------------------------------------------------------------------===//
1212
13#include <sanitizer_common/sanitizer_deadlock_detector_interface.h>13#include <sanitizer_common/sanitizer_deadlock_detector_interface.h>
14#include <sanitizer_common/sanitizer_placement_new.h>
14#include <sanitizer_common/sanitizer_stackdepot.h>15#include <sanitizer_common/sanitizer_stackdepot.h>
1516
16#include "tsan_rtl.h"
17#include "tsan_flags.h"17#include "tsan_flags.h"
18#include "tsan_sync.h"18#include "tsan_platform.h"
19#include "tsan_report.h"19#include "tsan_report.h"
20#include "tsan_rtl.h"
20#include "tsan_symbolize.h"21#include "tsan_symbolize.h"
21#include "tsan_platform.h"22#include "tsan_sync.h"
2223
23namespace __tsan {24namespace __tsan {
2425
...@@ -55,14 +56,28 @@ static void ReportMutexMisuse(ThreadState *thr, uptr pc, ReportType typ,...@@ -55,14 +56,28 @@ static void ReportMutexMisuse(ThreadState *thr, uptr pc, ReportType typ,
55 return;56 return;
56 if (!ShouldReport(thr, typ))57 if (!ShouldReport(thr, typ))
57 return;58 return;
58 ThreadRegistryLock l(&ctx->thread_registry);59 // Use alloca, because malloc during signal handling deadlocks
59 ScopedReport rep(typ);60 ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
60 rep.AddMutex(addr, creation_stack_id);61 // Take a new scope as Apple platforms require the below locks released
61 VarSizeStackTrace trace;62 // before symbolizing in order to avoid a deadlock
62 ObtainCurrentStack(thr, pc, &trace);63 {
63 rep.AddStack(trace, true);64 ThreadRegistryLock l(&ctx->thread_registry);
64 rep.AddLocation(addr, 1);65 new (rep) ScopedReport(typ);
65 OutputReport(thr, rep);66 rep->AddMutex(addr, creation_stack_id);
67 VarSizeStackTrace trace;
68 ObtainCurrentStack(thr, pc, &trace);
69 rep->AddStack(trace, true);
70 rep->AddLocation(addr, 1);
71#if SANITIZER_APPLE
72 } // Close this scope to release the locks
73#endif
74 OutputReport(thr, *rep);
75
76 // Need to manually destroy this because we used placement new to allocate
77 rep->~ScopedReport();
78#if !SANITIZER_APPLE
79 }
80#endif
66}81}
6782
68static void RecordMutexLock(ThreadState *thr, uptr pc, uptr addr,83static void RecordMutexLock(ThreadState *thr, uptr pc, uptr addr,
...@@ -528,51 +543,81 @@ void AfterSleep(ThreadState *thr, uptr pc) {...@@ -528,51 +543,81 @@ void AfterSleep(ThreadState *thr, uptr pc) {
528void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r) {543void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r) {
529 if (r == 0 || !ShouldReport(thr, ReportTypeDeadlock))544 if (r == 0 || !ShouldReport(thr, ReportTypeDeadlock))
530 return;545 return;
531 ThreadRegistryLock l(&ctx->thread_registry);546 // Use alloca, because malloc during signal handling deadlocks
532 ScopedReport rep(ReportTypeDeadlock);547 ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
533 for (int i = 0; i < r->n; i++) {548 // Take a new scope as Apple platforms require the below locks released
534 rep.AddMutex(r->loop[i].mtx_ctx0, r->loop[i].stk[0]);549 // before symbolizing in order to avoid a deadlock
535 rep.AddUniqueTid((int)r->loop[i].thr_ctx);550 {
536 rep.AddThread((int)r->loop[i].thr_ctx);551 ThreadRegistryLock l(&ctx->thread_registry);
537 }552 new (rep) ScopedReport(ReportTypeDeadlock);
538 uptr dummy_pc = 0x42;553 for (int i = 0; i < r->n; i++) {
539 for (int i = 0; i < r->n; i++) {554 rep->AddMutex(r->loop[i].mtx_ctx0, r->loop[i].stk[0]);
540 for (int j = 0; j < (flags()->second_deadlock_stack ? 2 : 1); j++) {555 rep->AddUniqueTid((int)r->loop[i].thr_ctx);
541 u32 stk = r->loop[i].stk[j];556 rep->AddThread((int)r->loop[i].thr_ctx);
542 if (stk && stk != kInvalidStackID) {557 }
543 rep.AddStack(StackDepotGet(stk), true);558 uptr dummy_pc = 0x42;
544 } else {559 for (int i = 0; i < r->n; i++) {
545 // Sometimes we fail to extract the stack trace (FIXME: investigate),560 for (int j = 0; j < (flags()->second_deadlock_stack ? 2 : 1); j++) {
546 // but we should still produce some stack trace in the report.561 u32 stk = r->loop[i].stk[j];
547 rep.AddStack(StackTrace(&dummy_pc, 1), true);562 StackTrace stack;
563 if (stk && stk != kInvalidStackID) {
564 stack = StackDepotGet(stk);
565 } else {
566 // Sometimes we fail to extract the stack trace (FIXME: investigate),
567 // but we should still produce some stack trace in the report.
568 stack = StackTrace(&dummy_pc, 1);
569 }
570 rep->AddStack(stack, true);
548 }571 }
549 }572 }
573#if SANITIZER_APPLE
574 } // Close this scope to release the locks
575#endif
576 OutputReport(thr, *rep);
577
578 // Need to manually destroy this because we used placement new to allocate
579 rep->~ScopedReport();
580#if !SANITIZER_APPLE
550 }581 }
551 OutputReport(thr, rep);582#endif
552}583}
553584
554void ReportDestroyLocked(ThreadState *thr, uptr pc, uptr addr,585void ReportDestroyLocked(ThreadState *thr, uptr pc, uptr addr,
555 FastState last_lock, StackID creation_stack_id) {586 FastState last_lock, StackID creation_stack_id) {
556 // We need to lock the slot during RestoreStack because it protects587 // Use alloca, because malloc during signal handling deadlocks
557 // the slot journal.588 ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
558 Lock slot_lock(&ctx->slots[static_cast<uptr>(last_lock.sid())].mtx);589 // Take a new scope as Apple platforms require the below locks released
559 ThreadRegistryLock l0(&ctx->thread_registry);590 // before symbolizing in order to avoid a deadlock
560 Lock slots_lock(&ctx->slot_mtx);591 {
561 ScopedReport rep(ReportTypeMutexDestroyLocked);592 // We need to lock the slot during RestoreStack because it protects
562 rep.AddMutex(addr, creation_stack_id);593 // the slot journal.
563 VarSizeStackTrace trace;594 Lock slot_lock(&ctx->slots[static_cast<uptr>(last_lock.sid())].mtx);
564 ObtainCurrentStack(thr, pc, &trace);595 ThreadRegistryLock l0(&ctx->thread_registry);
565 rep.AddStack(trace, true);596 Lock slots_lock(&ctx->slot_mtx);
566597 new (rep) ScopedReport(ReportTypeMutexDestroyLocked);
567 Tid tid;598 rep->AddMutex(addr, creation_stack_id);
568 DynamicMutexSet mset;599 VarSizeStackTrace trace;
569 uptr tag;600 ObtainCurrentStack(thr, pc, &trace);
570 if (!RestoreStack(EventType::kLock, last_lock.sid(), last_lock.epoch(), addr,601 rep->AddStack(trace, true);
571 0, kAccessWrite, &tid, &trace, mset, &tag))602
572 return;603 Tid tid;
573 rep.AddStack(trace, true);604 DynamicMutexSet mset;
574 rep.AddLocation(addr, 1);605 uptr tag;
575 OutputReport(thr, rep);606 if (!RestoreStack(EventType::kLock, last_lock.sid(), last_lock.epoch(),
607 addr, 0, kAccessWrite, &tid, &trace, mset, &tag))
608 return;
609 rep->AddStack(trace, true);
610 rep->AddLocation(addr, 1);
611#if SANITIZER_APPLE
612 } // Close this scope to release the locks
613#endif
614 OutputReport(thr, *rep);
615
616 // Need to manually destroy this because we used placement new to allocate
617 rep->~ScopedReport();
618#if !SANITIZER_APPLE
619 }
620#endif
576}621}
577622
578} // namespace __tsan623} // namespace __tsan
lib/libtsan/tsan_rtl_report.cpp+132-65
...@@ -11,10 +11,12 @@...@@ -11,10 +11,12 @@
11//===----------------------------------------------------------------------===//11//===----------------------------------------------------------------------===//
1212
13#include "sanitizer_common/sanitizer_common.h"13#include "sanitizer_common/sanitizer_common.h"
14#include "sanitizer_common/sanitizer_internal_defs.h"
14#include "sanitizer_common/sanitizer_libc.h"15#include "sanitizer_common/sanitizer_libc.h"
15#include "sanitizer_common/sanitizer_placement_new.h"16#include "sanitizer_common/sanitizer_placement_new.h"
16#include "sanitizer_common/sanitizer_stackdepot.h"17#include "sanitizer_common/sanitizer_stackdepot.h"
17#include "sanitizer_common/sanitizer_stacktrace.h"18#include "sanitizer_common/sanitizer_stacktrace.h"
19#include "tsan_defs.h"
18#include "tsan_fd.h"20#include "tsan_fd.h"
19#include "tsan_flags.h"21#include "tsan_flags.h"
20#include "tsan_mman.h"22#include "tsan_mman.h"
...@@ -109,7 +111,13 @@ static ReportStack *SymbolizeStack(StackTrace trace) {...@@ -109,7 +111,13 @@ static ReportStack *SymbolizeStack(StackTrace trace) {
109 // instruction.111 // instruction.
110 if ((pc & kExternalPCBit) == 0)112 if ((pc & kExternalPCBit) == 0)
111 pc1 = StackTrace::GetPreviousInstructionPc(pc);113 pc1 = StackTrace::GetPreviousInstructionPc(pc);
112 SymbolizedStack *ent = SymbolizeCode(pc1);114 SymbolizedStack* ent = SymbolizeCode(pc1, si == trace.size - 1);
115#if SANITIZER_GO
116 if (ent == nullptr) {
117 // Go might have 0 frames for this PC (wrapper frames aren't reported).
118 continue;
119 }
120#endif
113 CHECK_NE(ent, 0);121 CHECK_NE(ent, 0);
114 SymbolizedStack *last = ent;122 SymbolizedStack *last = ent;
115 while (last->next) {123 while (last->next) {
...@@ -187,10 +195,8 @@ void ScopedReportBase::AddMemoryAccess(uptr addr, uptr external_tag, Shadow s,...@@ -187,10 +195,8 @@ void ScopedReportBase::AddMemoryAccess(uptr addr, uptr external_tag, Shadow s,
187 mop->size = size;195 mop->size = size;
188 mop->write = !(typ & kAccessRead);196 mop->write = !(typ & kAccessRead);
189 mop->atomic = typ & kAccessAtomic;197 mop->atomic = typ & kAccessAtomic;
190 mop->stack = SymbolizeStack(stack);
191 mop->external_tag = external_tag;198 mop->external_tag = external_tag;
192 if (mop->stack)199 mop->stack_trace = stack;
193 mop->stack->suppressable = true;
194 for (uptr i = 0; i < mset->Size(); i++) {200 for (uptr i = 0; i < mset->Size(); i++) {
195 MutexSet::Desc d = mset->Get(i);201 MutexSet::Desc d = mset->Get(i);
196 int id = this->AddMutex(d.addr, d.stack_id);202 int id = this->AddMutex(d.addr, d.stack_id);
...@@ -199,6 +205,56 @@ void ScopedReportBase::AddMemoryAccess(uptr addr, uptr external_tag, Shadow s,...@@ -199,6 +205,56 @@ void ScopedReportBase::AddMemoryAccess(uptr addr, uptr external_tag, Shadow s,
199 }205 }
200}206}
201207
208void ScopedReportBase::SymbolizeStackElems() {
209 // symbolize memory ops
210 for (usize i = 0, size = rep_->mops.Size(); i < size; i++) {
211 ReportMop *mop = rep_->mops[i];
212 mop->stack = SymbolizeStack(mop->stack_trace);
213 if (mop->stack)
214 mop->stack->suppressable = true;
215 }
216
217 // symbolize locations
218 for (usize i = 0, size = rep_->locs.Size(); i < size; i++) {
219 // added locations have a NULL placeholder - don't dereference them
220 if (ReportLocation *loc = rep_->locs[i])
221 loc->stack = SymbolizeStackId(loc->stack_id);
222 }
223
224 // symbolize any added locations
225 for (usize i = 0, size = rep_->added_location_addrs.Size(); i < size; i++) {
226 AddedLocationAddr *added_loc = &rep_->added_location_addrs[i];
227 if (ReportLocation *loc = SymbolizeData(added_loc->addr)) {
228 loc->suppressable = true;
229 rep_->locs[added_loc->locs_idx] = loc;
230 }
231 }
232
233 // Filter out any added location placeholders that could not be symbolized
234 usize j = 0;
235 for (usize i = 0, size = rep_->locs.Size(); i < size; i++) {
236 if (rep_->locs[i] != nullptr) {
237 rep_->locs[j] = rep_->locs[i];
238 j++;
239 }
240 }
241 rep_->locs.Resize(j);
242
243 // symbolize threads
244 for (usize i = 0, size = rep_->threads.Size(); i < size; i++) {
245 ReportThread *rt = rep_->threads[i];
246 rt->stack = SymbolizeStackId(rt->stack_id);
247 if (rt->stack)
248 rt->stack->suppressable = rt->suppressable;
249 }
250
251 // symbolize mutexes
252 for (usize i = 0, size = rep_->mutexes.Size(); i < size; i++) {
253 ReportMutex *rm = rep_->mutexes[i];
254 rm->stack = SymbolizeStackId(rm->stack_id);
255 }
256}
257
202void ScopedReportBase::AddUniqueTid(Tid unique_tid) {258void ScopedReportBase::AddUniqueTid(Tid unique_tid) {
203 rep_->unique_tids.PushBack(unique_tid);259 rep_->unique_tids.PushBack(unique_tid);
204}260}
...@@ -216,10 +272,8 @@ void ScopedReportBase::AddThread(const ThreadContext *tctx, bool suppressable) {...@@ -216,10 +272,8 @@ void ScopedReportBase::AddThread(const ThreadContext *tctx, bool suppressable) {
216 rt->name = internal_strdup(tctx->name);272 rt->name = internal_strdup(tctx->name);
217 rt->parent_tid = tctx->parent_tid;273 rt->parent_tid = tctx->parent_tid;
218 rt->thread_type = tctx->thread_type;274 rt->thread_type = tctx->thread_type;
219 rt->stack = 0;275 rt->stack_id = tctx->creation_stack_id;
220 rt->stack = SymbolizeStackId(tctx->creation_stack_id);276 rt->suppressable = suppressable;
221 if (rt->stack)
222 rt->stack->suppressable = suppressable;
223}277}
224278
225#if !SANITIZER_GO279#if !SANITIZER_GO
...@@ -270,7 +324,7 @@ int ScopedReportBase::AddMutex(uptr addr, StackID creation_stack_id) {...@@ -270,7 +324,7 @@ int ScopedReportBase::AddMutex(uptr addr, StackID creation_stack_id) {
270 rep_->mutexes.PushBack(rm);324 rep_->mutexes.PushBack(rm);
271 rm->id = rep_->mutexes.Size() - 1;325 rm->id = rep_->mutexes.Size() - 1;
272 rm->addr = addr;326 rm->addr = addr;
273 rm->stack = SymbolizeStackId(creation_stack_id);327 rm->stack_id = creation_stack_id;
274 return rm->id;328 return rm->id;
275}329}
276330
...@@ -288,7 +342,7 @@ void ScopedReportBase::AddLocation(uptr addr, uptr size) {...@@ -288,7 +342,7 @@ void ScopedReportBase::AddLocation(uptr addr, uptr size) {
288 loc->fd_closed = closed;342 loc->fd_closed = closed;
289 loc->fd = fd;343 loc->fd = fd;
290 loc->tid = creat_tid;344 loc->tid = creat_tid;
291 loc->stack = SymbolizeStackId(creat_stack);345 loc->stack_id = creat_stack;
292 rep_->locs.PushBack(loc);346 rep_->locs.PushBack(loc);
293 AddThread(creat_tid);347 AddThread(creat_tid);
294 return;348 return;
...@@ -310,7 +364,7 @@ void ScopedReportBase::AddLocation(uptr addr, uptr size) {...@@ -310,7 +364,7 @@ void ScopedReportBase::AddLocation(uptr addr, uptr size) {
310 loc->heap_chunk_size = b->siz;364 loc->heap_chunk_size = b->siz;
311 loc->external_tag = b->tag;365 loc->external_tag = b->tag;
312 loc->tid = b->tid;366 loc->tid = b->tid;
313 loc->stack = SymbolizeStackId(b->stk);367 loc->stack_id = b->stk;
314 rep_->locs.PushBack(loc);368 rep_->locs.PushBack(loc);
315 AddThread(b->tid);369 AddThread(b->tid);
316 return;370 return;
...@@ -324,11 +378,8 @@ void ScopedReportBase::AddLocation(uptr addr, uptr size) {...@@ -324,11 +378,8 @@ void ScopedReportBase::AddLocation(uptr addr, uptr size) {
324 AddThread(tctx);378 AddThread(tctx);
325 }379 }
326#endif380#endif
327 if (ReportLocation *loc = SymbolizeData(addr)) {381 rep_->added_location_addrs.PushBack({addr, rep_->locs.Size()});
328 loc->suppressable = true;382 rep_->locs.PushBack(nullptr);
329 rep_->locs.PushBack(loc);
330 return;
331 }
332}383}
333384
334#if !SANITIZER_GO385#if !SANITIZER_GO
...@@ -628,11 +679,12 @@ static bool HandleRacyStacks(ThreadState *thr, VarSizeStackTrace traces[2]) {...@@ -628,11 +679,12 @@ static bool HandleRacyStacks(ThreadState *thr, VarSizeStackTrace traces[2]) {
628 return false;679 return false;
629}680}
630681
631bool OutputReport(ThreadState *thr, const ScopedReport &srep) {682bool OutputReport(ThreadState *thr, ScopedReport &srep) {
632 // These should have been checked in ShouldReport.683 // These should have been checked in ShouldReport.
633 // It's too late to check them here, we have already taken locks.684 // It's too late to check them here, we have already taken locks.
634 CHECK(flags()->report_bugs);685 CHECK(flags()->report_bugs);
635 CHECK(!thr->suppress_reports);686 CHECK(!thr->suppress_reports);
687 srep.SymbolizeStackElems();
636 atomic_store_relaxed(&ctx->last_symbolize_time_ns, NanoTime());688 atomic_store_relaxed(&ctx->last_symbolize_time_ns, NanoTime());
637 const ReportDesc *rep = srep.GetReport();689 const ReportDesc *rep = srep.GetReport();
638 CHECK_EQ(thr->current_report, nullptr);690 CHECK_EQ(thr->current_report, nullptr);
...@@ -761,65 +813,80 @@ void ReportRace(ThreadState *thr, RawShadow *shadow_mem, Shadow cur, Shadow old,...@@ -761,65 +813,80 @@ void ReportRace(ThreadState *thr, RawShadow *shadow_mem, Shadow cur, Shadow old,
761 DynamicMutexSet mset1;813 DynamicMutexSet mset1;
762 MutexSet *mset[kMop] = {&thr->mset, mset1};814 MutexSet *mset[kMop] = {&thr->mset, mset1};
763815
764 // We need to lock the slot during RestoreStack because it protects816 // Use alloca, because malloc during signal handling deadlocks
765 // the slot journal.817 ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
766 Lock slot_lock(&ctx->slots[static_cast<uptr>(s[1].sid())].mtx);818 // Take a new scope as Apple platforms require the below locks released
767 ThreadRegistryLock l0(&ctx->thread_registry);819 // before symbolizing in order to avoid a deadlock
768 Lock slots_lock(&ctx->slot_mtx);820 {
769 if (SpuriousRace(old))821 // We need to lock the slot during RestoreStack because it protects
770 return;822 // the slot journal.
771 if (!RestoreStack(EventType::kAccessExt, s[1].sid(), s[1].epoch(), addr1,823 Lock slot_lock(&ctx->slots[static_cast<uptr>(s[1].sid())].mtx);
772 size1, typ1, &tids[1], &traces[1], mset[1], &tags[1])) {824 ThreadRegistryLock l0(&ctx->thread_registry);
773 StoreShadow(&ctx->last_spurious_race, old.raw());825 Lock slots_lock(&ctx->slot_mtx);
774 return;826 if (SpuriousRace(old))
775 }827 return;
828 if (!RestoreStack(EventType::kAccessExt, s[1].sid(), s[1].epoch(), addr1,
829 size1, typ1, &tids[1], &traces[1], mset[1], &tags[1])) {
830 StoreShadow(&ctx->last_spurious_race, old.raw());
831 return;
832 }
776833
777 if (IsFiredSuppression(ctx, rep_typ, traces[1]))834 if (IsFiredSuppression(ctx, rep_typ, traces[1]))
778 return;835 return;
779836
780 if (HandleRacyStacks(thr, traces))837 if (HandleRacyStacks(thr, traces))
781 return;838 return;
782839
783 // If any of the accesses has a tag, treat this as an "external" race.840 // If any of the accesses has a tag, treat this as an "external" race.
784 uptr tag = kExternalTagNone;841 uptr tag = kExternalTagNone;
785 for (uptr i = 0; i < kMop; i++) {842 for (uptr i = 0; i < kMop; i++) {
786 if (tags[i] != kExternalTagNone) {843 if (tags[i] != kExternalTagNone) {
787 rep_typ = ReportTypeExternalRace;844 rep_typ = ReportTypeExternalRace;
788 tag = tags[i];845 tag = tags[i];
789 break;846 break;
847 }
790 }848 }
791 }
792849
793 ScopedReport rep(rep_typ, tag);850 new (rep) ScopedReport(rep_typ, tag);
794 for (uptr i = 0; i < kMop; i++)851 for (uptr i = 0; i < kMop; i++)
795 rep.AddMemoryAccess(addr, tags[i], s[i], tids[i], traces[i], mset[i]);852 rep->AddMemoryAccess(addr, tags[i], s[i], tids[i], traces[i], mset[i]);
796853
797 for (uptr i = 0; i < kMop; i++) {854 for (uptr i = 0; i < kMop; i++) {
798 ThreadContext *tctx = static_cast<ThreadContext *>(855 ThreadContext *tctx = static_cast<ThreadContext *>(
799 ctx->thread_registry.GetThreadLocked(tids[i]));856 ctx->thread_registry.GetThreadLocked(tids[i]));
800 rep.AddThread(tctx);857 rep->AddThread(tctx);
801 }858 }
802859
803 rep.AddLocation(addr_min, addr_max - addr_min);860 rep->AddLocation(addr_min, addr_max - addr_min);
804861
805 if (flags()->print_full_thread_history) {862 if (flags()->print_full_thread_history) {
806 const ReportDesc *rep_desc = rep.GetReport();863 const ReportDesc *rep_desc = rep->GetReport();
807 for (uptr i = 0; i < rep_desc->threads.Size(); i++) {864 for (uptr i = 0; i < rep_desc->threads.Size(); i++) {
808 Tid parent_tid = rep_desc->threads[i]->parent_tid;865 Tid parent_tid = rep_desc->threads[i]->parent_tid;
809 if (parent_tid == kMainTid || parent_tid == kInvalidTid)866 if (parent_tid == kMainTid || parent_tid == kInvalidTid)
810 continue;867 continue;
811 ThreadContext *parent_tctx = static_cast<ThreadContext *>(868 ThreadContext *parent_tctx = static_cast<ThreadContext *>(
812 ctx->thread_registry.GetThreadLocked(parent_tid));869 ctx->thread_registry.GetThreadLocked(parent_tid));
813 rep.AddThread(parent_tctx);870 rep->AddThread(parent_tctx);
871 }
814 }872 }
815 }
816873
817#if !SANITIZER_GO874#if !SANITIZER_GO
818 if (!((typ0 | typ1) & kAccessFree) &&875 if (!((typ0 | typ1) & kAccessFree) &&
819 s[1].epoch() <= thr->last_sleep_clock.Get(s[1].sid()))876 s[1].epoch() <= thr->last_sleep_clock.Get(s[1].sid()))
820 rep.AddSleep(thr->last_sleep_stack_id);877 rep->AddSleep(thr->last_sleep_stack_id);
878#endif
879
880#if SANITIZER_APPLE
881 } // Close this scope to release the locks
882#endif
883 OutputReport(thr, *rep);
884
885 // Need to manually destroy this because we used placement new to allocate
886 rep->~ScopedReport();
887#if !SANITIZER_APPLE
888 }
821#endif889#endif
822 OutputReport(thr, rep);
823}890}
824891
825void PrintCurrentStack(ThreadState *thr, uptr pc) {892void PrintCurrentStack(ThreadState *thr, uptr pc) {
lib/libtsan/tsan_rtl_thread.cpp+31-9
...@@ -88,15 +88,33 @@ void ThreadFinalize(ThreadState *thr) {...@@ -88,15 +88,33 @@ void ThreadFinalize(ThreadState *thr) {
88#if !SANITIZER_GO88#if !SANITIZER_GO
89 if (!ShouldReport(thr, ReportTypeThreadLeak))89 if (!ShouldReport(thr, ReportTypeThreadLeak))
90 return;90 return;
91 ThreadRegistryLock l(&ctx->thread_registry);
92 Vector<ThreadLeak> leaks;91 Vector<ThreadLeak> leaks;
93 ctx->thread_registry.RunCallbackForEachThreadLocked(CollectThreadLeaks,92 {
94 &leaks);93 ThreadRegistryLock l(&ctx->thread_registry);
94 ctx->thread_registry.RunCallbackForEachThreadLocked(CollectThreadLeaks,
95 &leaks);
96 }
97
95 for (uptr i = 0; i < leaks.Size(); i++) {98 for (uptr i = 0; i < leaks.Size(); i++) {
96 ScopedReport rep(ReportTypeThreadLeak);99 // Use alloca, because malloc during signal handling deadlocks
97 rep.AddThread(leaks[i].tctx, true);100 ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
98 rep.SetCount(leaks[i].count);101 // Take a new scope as Apple platforms require the below locks released
99 OutputReport(thr, rep);102 // before symbolizing in order to avoid a deadlock
103 {
104 ThreadRegistryLock l(&ctx->thread_registry);
105 new (rep) ScopedReport(ReportTypeThreadLeak);
106 rep->AddThread(leaks[i].tctx, true);
107 rep->SetCount(leaks[i].count);
108# if SANITIZER_APPLE
109 } // Close this scope to release the locks
110# endif
111 OutputReport(thr, *rep);
112
113 // Need to manually destroy this because we used placement new to allocate
114 rep->~ScopedReport();
115# if !SANITIZER_APPLE
116 }
117# endif
100 }118 }
101#endif119#endif
102}120}
...@@ -149,7 +167,7 @@ struct OnStartedArgs {...@@ -149,7 +167,7 @@ struct OnStartedArgs {
149 uptr tls_size;167 uptr tls_size;
150};168};
151169
152void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,170void ThreadStart(ThreadState *thr, Tid tid, ThreadID os_id,
153 ThreadType thread_type) {171 ThreadType thread_type) {
154 ctx->thread_registry.StartThread(tid, os_id, thread_type, thr);172 ctx->thread_registry.StartThread(tid, os_id, thread_type, thr);
155 if (!thr->ignore_sync) {173 if (!thr->ignore_sync) {
...@@ -188,10 +206,14 @@ void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,...@@ -188,10 +206,14 @@ void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id,
188 }206 }
189#endif207#endif
190208
191#if !SANITIZER_GO209#if !SANITIZER_GO && !SANITIZER_ANDROID
192 // Don't imitate stack/TLS writes for the main thread,210 // Don't imitate stack/TLS writes for the main thread,
193 // because its initialization is synchronized with all211 // because its initialization is synchronized with all
194 // subsequent threads anyway.212 // subsequent threads anyway.
213 // Because thr is created by MmapOrDie, the thr object
214 // is not in tls, the pointer to the thr object is in
215 // TLS_SLOT_SANITIZER slot. So skip this check on
216 // Android platform.
195 if (tid != kMainTid) {217 if (tid != kMainTid) {
196 if (stk_addr && stk_size) {218 if (stk_addr && stk_size) {
197 const uptr pc = StackTrace::GetNextInstructionPc(219 const uptr pc = StackTrace::GetNextInstructionPc(
lib/libtsan/tsan_symbolize.cpp+1-1
...@@ -79,7 +79,7 @@ static void AddFrame(void *ctx, const char *function_name, const char *file,...@@ -79,7 +79,7 @@ static void AddFrame(void *ctx, const char *function_name, const char *file,
79 info->column = column;79 info->column = column;
80}80}
8181
82SymbolizedStack *SymbolizeCode(uptr addr) {82SymbolizedStack* SymbolizeCode(uptr addr, bool leaf) {
83 // Check if PC comes from non-native land.83 // Check if PC comes from non-native land.
84 if (addr & kExternalPCBit) {84 if (addr & kExternalPCBit) {
85 SymbolizedStackBuilder ssb = {nullptr, nullptr, addr};85 SymbolizedStackBuilder ssb = {nullptr, nullptr, addr};
lib/libtsan/tsan_symbolize.h+1-1
...@@ -19,7 +19,7 @@ namespace __tsan {...@@ -19,7 +19,7 @@ namespace __tsan {
1919
20void EnterSymbolizer();20void EnterSymbolizer();
21void ExitSymbolizer();21void ExitSymbolizer();
22SymbolizedStack *SymbolizeCode(uptr addr);22SymbolizedStack* SymbolizeCode(uptr addr, bool leaf);
23ReportLocation *SymbolizeData(uptr addr);23ReportLocation *SymbolizeData(uptr addr);
24void SymbolizeFlush();24void SymbolizeFlush();
2525
lib/libtsan/tsan_trace.h+1-1
...@@ -190,7 +190,7 @@ struct Trace {...@@ -190,7 +190,7 @@ struct Trace {
190 Mutex mtx;190 Mutex mtx;
191 IList<TraceHeader, &TraceHeader::trace_parts, TracePart> parts;191 IList<TraceHeader, &TraceHeader::trace_parts, TracePart> parts;
192 // First node non-queued into ctx->trace_part_recycle.192 // First node non-queued into ctx->trace_part_recycle.
193 TracePart* local_head;193 TracePart* local_head = nullptr;
194 // Final position in the last part for finished threads.194 // Final position in the last part for finished threads.
195 Event* final_pos = nullptr;195 Event* final_pos = nullptr;
196 // Number of trace parts allocated on behalf of this trace specifically.196 // Number of trace parts allocated on behalf of this trace specifically.