1 | //===--- Fuchsia.cpp - Fuchsia ToolChain Implementations --------*- C++ -*-===// |
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 | |
9 | #include "Fuchsia.h" |
10 | #include "clang/Config/config.h" |
11 | #include "clang/Driver/CommonArgs.h" |
12 | #include "clang/Driver/Compilation.h" |
13 | #include "clang/Driver/Driver.h" |
14 | #include "clang/Driver/MultilibBuilder.h" |
15 | #include "clang/Driver/Options.h" |
16 | #include "clang/Driver/SanitizerArgs.h" |
17 | #include "llvm/Option/ArgList.h" |
18 | #include "llvm/Support/FileSystem.h" |
19 | #include "llvm/Support/Path.h" |
20 | #include "llvm/Support/VirtualFileSystem.h" |
21 | |
22 | using namespace clang::driver; |
23 | using namespace clang::driver::toolchains; |
24 | using namespace clang::driver::tools; |
25 | using namespace clang; |
26 | using namespace llvm::opt; |
27 | |
28 | using tools::addMultilibFlag; |
29 | |
30 | void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, |
31 | const InputInfo &Output, |
32 | const InputInfoList &Inputs, |
33 | const ArgList &Args, |
34 | const char *LinkingOutput) const { |
35 | const auto &ToolChain = static_cast<const Fuchsia &>(getToolChain()); |
36 | const Driver &D = ToolChain.getDriver(); |
37 | |
38 | const llvm::Triple &Triple = ToolChain.getEffectiveTriple(); |
39 | |
40 | ArgStringList CmdArgs; |
41 | |
42 | // Silence warning for "clang -g foo.o -o foo" |
43 | Args.ClaimAllArgs(options::OPT_g_Group); |
44 | // and "clang -emit-llvm foo.o -o foo" |
45 | Args.ClaimAllArgs(options::OPT_emit_llvm); |
46 | // and for "clang -w foo.o -o foo". Other warning options are already |
47 | // handled somewhere else. |
48 | Args.ClaimAllArgs(options::OPT_w); |
49 | |
50 | CmdArgs.push_back(Elt: "-z" ); |
51 | CmdArgs.push_back(Elt: "max-page-size=4096" ); |
52 | |
53 | CmdArgs.push_back(Elt: "-z" ); |
54 | CmdArgs.push_back(Elt: "now" ); |
55 | |
56 | CmdArgs.push_back(Elt: "-z" ); |
57 | CmdArgs.push_back(Elt: "start-stop-visibility=hidden" ); |
58 | |
59 | const char *Exec = Args.MakeArgString(Str: ToolChain.GetLinkerPath()); |
60 | if (llvm::sys::path::filename(path: Exec).equals_insensitive(RHS: "ld.lld" ) || |
61 | llvm::sys::path::stem(path: Exec).equals_insensitive(RHS: "ld.lld" )) { |
62 | CmdArgs.push_back(Elt: "-z" ); |
63 | CmdArgs.push_back(Elt: "rodynamic" ); |
64 | CmdArgs.push_back(Elt: "-z" ); |
65 | CmdArgs.push_back(Elt: "separate-loadable-segments" ); |
66 | CmdArgs.push_back(Elt: "-z" ); |
67 | CmdArgs.push_back(Elt: "rel" ); |
68 | CmdArgs.push_back(Elt: "--pack-dyn-relocs=relr" ); |
69 | } |
70 | |
71 | if (!D.SysRoot.empty()) |
72 | CmdArgs.push_back(Elt: Args.MakeArgString(Str: "--sysroot=" + D.SysRoot)); |
73 | |
74 | if (!Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_r)) |
75 | CmdArgs.push_back(Elt: "-pie" ); |
76 | |
77 | if (Args.hasArg(options::OPT_rdynamic)) |
78 | CmdArgs.push_back(Elt: "-export-dynamic" ); |
79 | |
80 | if (Args.hasArg(options::OPT_s)) |
81 | CmdArgs.push_back(Elt: "-s" ); |
82 | |
83 | if (Args.hasArg(options::OPT_r)) { |
84 | CmdArgs.push_back(Elt: "-r" ); |
85 | } else { |
86 | CmdArgs.push_back(Elt: "--build-id" ); |
87 | CmdArgs.push_back(Elt: "--hash-style=gnu" ); |
88 | } |
89 | |
90 | if (ToolChain.getArch() == llvm::Triple::aarch64) { |
91 | CmdArgs.push_back(Elt: "--execute-only" ); |
92 | |
93 | std::string CPU = getCPUName(D, Args, T: Triple); |
94 | if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53" ) |
95 | CmdArgs.push_back(Elt: "--fix-cortex-a53-843419" ); |
96 | } |
97 | |
98 | CmdArgs.push_back(Elt: "--eh-frame-hdr" ); |
99 | |
100 | if (Args.hasArg(options::OPT_static)) |
101 | CmdArgs.push_back(Elt: "-Bstatic" ); |
102 | else if (Args.hasArg(options::OPT_shared)) |
103 | CmdArgs.push_back(Elt: "-shared" ); |
104 | |
105 | const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(JobArgs: Args); |
106 | |
107 | if (!Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_r)) { |
108 | std::string Dyld = D.DyldPrefix; |
109 | if (SanArgs.needsAsanRt() && SanArgs.needsSharedRt()) |
110 | Dyld += "asan/" ; |
111 | if (SanArgs.needsHwasanRt() && SanArgs.needsSharedRt()) |
112 | Dyld += "hwasan/" ; |
113 | if (SanArgs.needsTsanRt() && SanArgs.needsSharedRt()) |
114 | Dyld += "tsan/" ; |
115 | Dyld += "ld.so.1" ; |
116 | CmdArgs.push_back(Elt: "-dynamic-linker" ); |
117 | CmdArgs.push_back(Elt: Args.MakeArgString(Str: Dyld)); |
118 | } |
119 | |
120 | if (Triple.isRISCV64()) { |
121 | CmdArgs.push_back(Elt: "-X" ); |
122 | if (Args.hasArg(options::OPT_mno_relax)) |
123 | CmdArgs.push_back(Elt: "--no-relax" ); |
124 | } |
125 | |
126 | CmdArgs.push_back(Elt: "-o" ); |
127 | CmdArgs.push_back(Elt: Output.getFilename()); |
128 | |
129 | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, |
130 | options::OPT_r)) { |
131 | if (!Args.hasArg(options::OPT_shared)) { |
132 | CmdArgs.push_back(Elt: Args.MakeArgString(Str: ToolChain.GetFilePath(Name: "Scrt1.o" ))); |
133 | } |
134 | } |
135 | |
136 | Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u}); |
137 | |
138 | ToolChain.AddFilePathLibArgs(Args, CmdArgs); |
139 | |
140 | if (D.isUsingLTO()) |
141 | addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs, |
142 | IsThinLTO: D.getLTOMode() == LTOK_Thin); |
143 | |
144 | addLinkerCompressDebugSectionsOption(TC: ToolChain, Args, CmdArgs); |
145 | AddLinkerInputs(TC: ToolChain, Inputs, Args, CmdArgs, JA); |
146 | |
147 | // Sample these options first so they are claimed even under -nostdlib et al. |
148 | bool NoLibc = Args.hasArg(options::OPT_nolibc); |
149 | bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && |
150 | !Args.hasArg(options::OPT_static); |
151 | bool Pthreads = Args.hasArg(options::OPT_pthread, options::OPT_pthreads); |
152 | bool SplitStack = Args.hasArg(options::OPT_fsplit_stack); |
153 | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, |
154 | options::OPT_r)) { |
155 | if (Args.hasArg(options::OPT_static)) |
156 | CmdArgs.push_back(Elt: "-Bdynamic" ); |
157 | |
158 | if (D.CCCIsCXX()) { |
159 | if (ToolChain.ShouldLinkCXXStdlib(Args)) { |
160 | CmdArgs.push_back(Elt: "--push-state" ); |
161 | CmdArgs.push_back(Elt: "--as-needed" ); |
162 | if (OnlyLibstdcxxStatic) |
163 | CmdArgs.push_back(Elt: "-Bstatic" ); |
164 | ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); |
165 | if (OnlyLibstdcxxStatic) |
166 | CmdArgs.push_back(Elt: "-Bdynamic" ); |
167 | CmdArgs.push_back(Elt: "-lm" ); |
168 | CmdArgs.push_back(Elt: "--pop-state" ); |
169 | } |
170 | } |
171 | |
172 | // Note that Fuchsia never needs to link in sanitizer runtime deps. Any |
173 | // sanitizer runtimes with system dependencies use the `.deplibs` feature |
174 | // instead. |
175 | addSanitizerRuntimes(TC: ToolChain, Args, CmdArgs); |
176 | |
177 | addXRayRuntime(TC: ToolChain, Args, CmdArgs); |
178 | |
179 | ToolChain.addProfileRTLibs(Args, CmdArgs); |
180 | |
181 | AddRunTimeLibs(TC: ToolChain, D, CmdArgs, Args); |
182 | |
183 | if (Pthreads) |
184 | CmdArgs.push_back(Elt: "-lpthread" ); |
185 | |
186 | if (SplitStack) |
187 | CmdArgs.push_back(Elt: "--wrap=pthread_create" ); |
188 | |
189 | if (!NoLibc) |
190 | CmdArgs.push_back(Elt: "-lc" ); |
191 | } |
192 | |
193 | C.addCommand(C: std::make_unique<Command>(args: JA, args: *this, |
194 | args: ResponseFileSupport::AtFileCurCP(), |
195 | args&: Exec, args&: CmdArgs, args: Inputs, args: Output)); |
196 | } |
197 | |
198 | void fuchsia::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA, |
199 | const InputInfo &Output, |
200 | const InputInfoList &Inputs, |
201 | const ArgList &Args, |
202 | const char *LinkingOutput) const { |
203 | const Driver &D = getToolChain().getDriver(); |
204 | |
205 | // Silence warning for "clang -g foo.o -o foo" |
206 | Args.ClaimAllArgs(options::OPT_g_Group); |
207 | // and "clang -emit-llvm foo.o -o foo" |
208 | Args.ClaimAllArgs(options::OPT_emit_llvm); |
209 | // and for "clang -w foo.o -o foo". Other warning options are already |
210 | // handled somewhere else. |
211 | Args.ClaimAllArgs(options::OPT_w); |
212 | // Silence warnings when linking C code with a C++ '-stdlib' argument. |
213 | Args.ClaimAllArgs(options::OPT_stdlib_EQ); |
214 | |
215 | // ar tool command "llvm-ar <options> <output_file> <input_files>". |
216 | ArgStringList CmdArgs; |
217 | // Create and insert file members with a deterministic index. |
218 | CmdArgs.push_back(Elt: "rcsD" ); |
219 | CmdArgs.push_back(Elt: Output.getFilename()); |
220 | |
221 | for (const auto &II : Inputs) { |
222 | if (II.isFilename()) { |
223 | CmdArgs.push_back(Elt: II.getFilename()); |
224 | } |
225 | } |
226 | |
227 | // Delete old output archive file if it already exists before generating a new |
228 | // archive file. |
229 | const char *OutputFileName = Output.getFilename(); |
230 | if (Output.isFilename() && llvm::sys::fs::exists(Path: OutputFileName)) { |
231 | if (std::error_code EC = llvm::sys::fs::remove(path: OutputFileName)) { |
232 | D.Diag(diag::DiagID: err_drv_unable_to_remove_file) << EC.message(); |
233 | return; |
234 | } |
235 | } |
236 | |
237 | const char *Exec = Args.MakeArgString(Str: getToolChain().GetStaticLibToolPath()); |
238 | C.addCommand(C: std::make_unique<Command>(args: JA, args: *this, |
239 | args: ResponseFileSupport::AtFileCurCP(), |
240 | args&: Exec, args&: CmdArgs, args: Inputs, args: Output)); |
241 | } |
242 | |
243 | /// Fuchsia - Fuchsia tool chain which can call as(1) and ld(1) directly. |
244 | |
245 | Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple, |
246 | const ArgList &Args) |
247 | : ToolChain(D, Triple, Args) { |
248 | getProgramPaths().push_back(Elt: getDriver().Dir); |
249 | |
250 | if (!D.SysRoot.empty()) { |
251 | SmallString<128> P(D.SysRoot); |
252 | llvm::sys::path::append(path&: P, a: "lib" ); |
253 | getFilePaths().push_back(Elt: std::string(P)); |
254 | } |
255 | |
256 | auto FilePaths = [&](const Multilib &M) -> std::vector<std::string> { |
257 | std::vector<std::string> FP; |
258 | if (std::optional<std::string> Path = getStdlibPath()) { |
259 | SmallString<128> P(*Path); |
260 | llvm::sys::path::append(path&: P, a: M.gccSuffix()); |
261 | FP.push_back(x: std::string(P)); |
262 | } |
263 | return FP; |
264 | }; |
265 | |
266 | Multilibs.push_back(M: Multilib()); |
267 | // Use the noexcept variant with -fno-exceptions to avoid the extra overhead. |
268 | Multilibs.push_back(M: MultilibBuilder("noexcept" , {}, {}) |
269 | .flag(Flag: "-fexceptions" , /*Disallow=*/true) |
270 | .flag(Flag: "-fno-exceptions" ) |
271 | .makeMultilib()); |
272 | // ASan has higher priority because we always want the instrumentated version. |
273 | Multilibs.push_back(M: MultilibBuilder("asan" , {}, {}) |
274 | .flag(Flag: "-fsanitize=address" ) |
275 | .makeMultilib()); |
276 | // Use the asan+noexcept variant with ASan and -fno-exceptions. |
277 | Multilibs.push_back(M: MultilibBuilder("asan+noexcept" , {}, {}) |
278 | .flag(Flag: "-fsanitize=address" ) |
279 | .flag(Flag: "-fexceptions" , /*Disallow=*/true) |
280 | .flag(Flag: "-fno-exceptions" ) |
281 | .makeMultilib()); |
282 | // HWASan has higher priority because we always want the instrumentated |
283 | // version. |
284 | Multilibs.push_back(M: MultilibBuilder("hwasan" , {}, {}) |
285 | .flag(Flag: "-fsanitize=hwaddress" ) |
286 | .makeMultilib()); |
287 | // Use the hwasan+noexcept variant with HWASan and -fno-exceptions. |
288 | Multilibs.push_back(M: MultilibBuilder("hwasan+noexcept" , {}, {}) |
289 | .flag(Flag: "-fsanitize=hwaddress" ) |
290 | .flag(Flag: "-fexceptions" , /*Disallow=*/true) |
291 | .flag(Flag: "-fno-exceptions" ) |
292 | .makeMultilib()); |
293 | // Use Itanium C++ ABI for the compat multilib. |
294 | Multilibs.push_back(M: MultilibBuilder("compat" , {}, {}) |
295 | .flag(Flag: "-fc++-abi=itanium" ) |
296 | .makeMultilib()); |
297 | |
298 | Multilibs.FilterOut(F: [&](const Multilib &M) { |
299 | std::vector<std::string> RD = FilePaths(M); |
300 | return llvm::all_of(Range&: RD, P: [&](std::string P) { return !getVFS().exists(Path: P); }); |
301 | }); |
302 | |
303 | Multilib::flags_list Flags; |
304 | bool Exceptions = |
305 | Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, true); |
306 | addMultilibFlag(Enabled: Exceptions, Flag: "-fexceptions" , Flags); |
307 | addMultilibFlag(Enabled: !Exceptions, Flag: "-fno-exceptions" , Flags); |
308 | addMultilibFlag(Enabled: getSanitizerArgs(JobArgs: Args).needsAsanRt(), Flag: "-fsanitize=address" , |
309 | Flags); |
310 | addMultilibFlag(Enabled: getSanitizerArgs(JobArgs: Args).needsHwasanRt(), |
311 | Flag: "-fsanitize=hwaddress" , Flags); |
312 | |
313 | addMultilibFlag(Args.getLastArgValue(options::Id: OPT_fcxx_abi_EQ) == "itanium" , |
314 | "-fc++-abi=itanium" , Flags); |
315 | |
316 | Multilibs.setFilePathsCallback(FilePaths); |
317 | |
318 | if (Multilibs.select(D, Flags, SelectedMultilibs)) { |
319 | // Ensure that -print-multi-directory only outputs one multilib directory. |
320 | Multilib LastSelected = SelectedMultilibs.back(); |
321 | SelectedMultilibs = {LastSelected}; |
322 | |
323 | if (!SelectedMultilibs.back().isDefault()) |
324 | if (const auto &PathsCallback = Multilibs.filePathsCallback()) |
325 | for (const auto &Path : PathsCallback(SelectedMultilibs.back())) |
326 | // Prepend the multilib path to ensure it takes the precedence. |
327 | getFilePaths().insert(I: getFilePaths().begin(), Elt: Path); |
328 | } |
329 | } |
330 | |
331 | std::string Fuchsia::ComputeEffectiveClangTriple(const ArgList &Args, |
332 | types::ID InputType) const { |
333 | llvm::Triple Triple(ComputeLLVMTriple(Args, InputType)); |
334 | return Triple.str(); |
335 | } |
336 | |
337 | Tool *Fuchsia::buildLinker() const { return new tools::fuchsia::Linker(*this); } |
338 | |
339 | Tool *Fuchsia::buildStaticLibTool() const { |
340 | return new tools::fuchsia::StaticLibTool(*this); |
341 | } |
342 | |
343 | ToolChain::RuntimeLibType |
344 | Fuchsia::GetRuntimeLibType(const ArgList &Args) const { |
345 | if (Arg *A = Args.getLastArg(clang::driver::options::OPT_rtlib_EQ)) { |
346 | StringRef Value = A->getValue(); |
347 | if (Value != "compiler-rt" ) |
348 | getDriver().Diag(clang::diag::DiagID: err_drv_invalid_rtlib_name) |
349 | << A->getAsString(Args); |
350 | } |
351 | |
352 | return ToolChain::RLT_CompilerRT; |
353 | } |
354 | |
355 | ToolChain::CXXStdlibType Fuchsia::GetCXXStdlibType(const ArgList &Args) const { |
356 | if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { |
357 | StringRef Value = A->getValue(); |
358 | if (Value != "libc++" ) |
359 | getDriver().Diag(diag::DiagID: err_drv_invalid_stdlib_name) |
360 | << A->getAsString(Args); |
361 | } |
362 | |
363 | return ToolChain::CST_Libcxx; |
364 | } |
365 | |
366 | void Fuchsia::addClangTargetOptions(const ArgList &DriverArgs, |
367 | ArgStringList &CC1Args, |
368 | Action::OffloadKind) const { |
369 | if (!DriverArgs.hasFlag(options::OPT_fuse_init_array, |
370 | options::OPT_fno_use_init_array, true)) |
371 | CC1Args.push_back(Elt: "-fno-use-init-array" ); |
372 | } |
373 | |
374 | void Fuchsia::AddClangSystemIncludeArgs(const ArgList &DriverArgs, |
375 | ArgStringList &CC1Args) const { |
376 | const Driver &D = getDriver(); |
377 | |
378 | if (DriverArgs.hasArg(options::OPT_nostdinc)) |
379 | return; |
380 | |
381 | if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { |
382 | SmallString<128> P(D.ResourceDir); |
383 | llvm::sys::path::append(path&: P, a: "include" ); |
384 | addSystemInclude(DriverArgs, CC1Args, Path: P); |
385 | } |
386 | |
387 | if (DriverArgs.hasArg(options::OPT_nostdlibinc)) |
388 | return; |
389 | |
390 | // Check for configure-time C include directories. |
391 | StringRef CIncludeDirs(C_INCLUDE_DIRS); |
392 | if (CIncludeDirs != "" ) { |
393 | SmallVector<StringRef, 5> dirs; |
394 | CIncludeDirs.split(A&: dirs, Separator: ":" ); |
395 | for (StringRef dir : dirs) { |
396 | StringRef Prefix = |
397 | llvm::sys::path::is_absolute(path: dir) ? "" : StringRef(D.SysRoot); |
398 | addExternCSystemInclude(DriverArgs, CC1Args, Path: Prefix + dir); |
399 | } |
400 | return; |
401 | } |
402 | |
403 | if (!D.SysRoot.empty()) { |
404 | SmallString<128> P(D.SysRoot); |
405 | llvm::sys::path::append(path&: P, a: "include" ); |
406 | addExternCSystemInclude(DriverArgs, CC1Args, Path: P.str()); |
407 | } |
408 | } |
409 | |
410 | void Fuchsia::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, |
411 | ArgStringList &CC1Args) const { |
412 | if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc, |
413 | options::OPT_nostdincxx)) |
414 | return; |
415 | |
416 | const Driver &D = getDriver(); |
417 | std::string Target = getTripleString(); |
418 | |
419 | auto AddCXXIncludePath = [&](StringRef Path) { |
420 | std::string Version = detectLibcxxVersion(IncludePath: Path); |
421 | if (Version.empty()) |
422 | return; |
423 | |
424 | // First add the per-target multilib include dir. |
425 | if (!SelectedMultilibs.empty() && !SelectedMultilibs.back().isDefault()) { |
426 | const Multilib &M = SelectedMultilibs.back(); |
427 | SmallString<128> TargetDir(Path); |
428 | llvm::sys::path::append(path&: TargetDir, a: Target, b: M.gccSuffix(), c: "c++" , d: Version); |
429 | if (getVFS().exists(Path: TargetDir)) { |
430 | addSystemInclude(DriverArgs, CC1Args, Path: TargetDir); |
431 | } |
432 | } |
433 | |
434 | // Second add the per-target include dir. |
435 | SmallString<128> TargetDir(Path); |
436 | llvm::sys::path::append(path&: TargetDir, a: Target, b: "c++" , c: Version); |
437 | if (getVFS().exists(Path: TargetDir)) |
438 | addSystemInclude(DriverArgs, CC1Args, Path: TargetDir); |
439 | |
440 | // Third the generic one. |
441 | SmallString<128> Dir(Path); |
442 | llvm::sys::path::append(path&: Dir, a: "c++" , b: Version); |
443 | addSystemInclude(DriverArgs, CC1Args, Path: Dir); |
444 | }; |
445 | |
446 | switch (GetCXXStdlibType(Args: DriverArgs)) { |
447 | case ToolChain::CST_Libcxx: { |
448 | SmallString<128> P(D.Dir); |
449 | llvm::sys::path::append(path&: P, a: ".." , b: "include" ); |
450 | AddCXXIncludePath(P); |
451 | break; |
452 | } |
453 | |
454 | default: |
455 | llvm_unreachable("invalid stdlib name" ); |
456 | } |
457 | } |
458 | |
459 | void Fuchsia::AddCXXStdlibLibArgs(const ArgList &Args, |
460 | ArgStringList &CmdArgs) const { |
461 | switch (GetCXXStdlibType(Args)) { |
462 | case ToolChain::CST_Libcxx: |
463 | CmdArgs.push_back(Elt: "-lc++" ); |
464 | if (Args.hasArg(options::OPT_fexperimental_library)) |
465 | CmdArgs.push_back(Elt: "-lc++experimental" ); |
466 | break; |
467 | |
468 | case ToolChain::CST_Libstdcxx: |
469 | llvm_unreachable("invalid stdlib name" ); |
470 | } |
471 | } |
472 | |
473 | SanitizerMask Fuchsia::getSupportedSanitizers() const { |
474 | SanitizerMask Res = ToolChain::getSupportedSanitizers(); |
475 | Res |= SanitizerKind::Address; |
476 | Res |= SanitizerKind::HWAddress; |
477 | Res |= SanitizerKind::PointerCompare; |
478 | Res |= SanitizerKind::PointerSubtract; |
479 | Res |= SanitizerKind::Fuzzer; |
480 | Res |= SanitizerKind::FuzzerNoLink; |
481 | Res |= SanitizerKind::Leak; |
482 | Res |= SanitizerKind::SafeStack; |
483 | Res |= SanitizerKind::Scudo; |
484 | Res |= SanitizerKind::Thread; |
485 | return Res; |
486 | } |
487 | |
488 | SanitizerMask Fuchsia::getDefaultSanitizers() const { |
489 | SanitizerMask Res; |
490 | switch (getTriple().getArch()) { |
491 | case llvm::Triple::aarch64: |
492 | case llvm::Triple::riscv64: |
493 | Res |= SanitizerKind::ShadowCallStack; |
494 | break; |
495 | case llvm::Triple::x86_64: |
496 | Res |= SanitizerKind::SafeStack; |
497 | break; |
498 | default: |
499 | break; |
500 | } |
501 | return Res; |
502 | } |
503 | |