clang: lib/Driver/SanitizerArgs.cpp Source File (original) (raw)

1

2

3

4

5

6

7

13#include "llvm/ADT/SmallVector.h"

14#include "llvm/ADT/StringRef.h"

15#include "llvm/ADT/StringSwitch.h"

16#include "llvm/Support/Path.h"

17#include "llvm/Support/SpecialCaseList.h"

18#include "llvm/Support/VirtualFileSystem.h"

19#include "llvm/TargetParser/AArch64TargetParser.h"

20#include "llvm/TargetParser/RISCVTargetParser.h"

21#include "llvm/TargetParser/TargetParser.h"

22#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"

23#include

24

25using namespace clang;

28

30 SanitizerKind::Undefined | SanitizerKind::Integer |

31 SanitizerKind::LocalBounds | SanitizerKind::ImplicitConversion |

32 SanitizerKind::Nullability | SanitizerKind::CFI |

33 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;

35 SanitizerKind::Vptr | SanitizerKind::CFI;

39 SanitizerKind::Function | SanitizerKind::KCFI;

41 SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Type |

42 SanitizerKind::Thread | SanitizerKind::Memory | SanitizerKind::DataFlow |

43 SanitizerKind::NumericalStability;

45 SanitizerKind::Address | SanitizerKind::HWAddress |

46 SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |

47 SanitizerKind::Type | SanitizerKind::MemtagStack |

48 SanitizerKind::MemtagHeap | SanitizerKind::MemtagGlobals |

49 SanitizerKind::Memory | SanitizerKind::KernelMemory | SanitizerKind::Leak |

50 SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds |

51 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |

52 SanitizerKind::DataFlow | SanitizerKind::Fuzzer |

53 SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |

54 SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack |

55 SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI |

56 SanitizerKind::NumericalStability;

58 SanitizerKind::Undefined | SanitizerKind::Integer |

59 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |

60 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;

62 SanitizerKind::Unreachable | SanitizerKind::Return;

64 SanitizerKind::KernelHWAddress |

65 SanitizerKind::KCFI;

68 (SanitizerKind::Undefined & ~SanitizerKind::Vptr) | SanitizerKind::Integer |

69 SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |

70 SanitizerKind::LocalBounds | SanitizerKind::CFI |

71 SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;

74 SanitizerKind::CFI | SanitizerKind::LocalBounds;

76 SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |

77 SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |

78 SanitizerKind::CFIUnrelatedCast;

80 TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack |

81 SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |

82 SanitizerKind::MemtagGlobals | SanitizerKind::KCFI;

83

104};

105

110};

111

112

113

115 bool DiagnoseErrors);

116

117

118

119

122

123

124

126 bool DiagnoseErrors);

127

128

129

131 const llvm::opt::Arg *A,

132 bool DiagnoseErrors);

133

134

135

137 bool DiagnoseErrors);

138

139

140

141

142

144 const llvm::opt::ArgList &Args,

146

147

148

149

150

153

154

155

157

158

159

161 const llvm::opt::ArgList &Args) {

162 if (Triple.isPS5())

163 return true;

164 return Args.hasFlagNoClaim(options::OPT_mexecute_only,

165 options::OPT_mno_execute_only, false);

166}

167

169 std::vectorstd::string &SCLFiles,

170 unsigned MalformedSCLErrorDiagID,

171 bool DiagnoseErrors) {

172 if (SCLFiles.empty())

173 return;

174

175 std::string BLError;

176 std::unique_ptrllvm::SpecialCaseList SCL(

177 llvm::SpecialCaseList::create(SCLFiles, D.getVFS(), BLError));

178 if (!SCL.get() && DiagnoseErrors)

179 D.Diag(MalformedSCLErrorDiagID) << BLError;

180}

181

183 std::vectorstd::string &IgnorelistFiles,

184 bool DiagnoseErrors) {

185 struct Ignorelist {

186 const char *File;

188 } Ignorelists[] = {{"asan_ignorelist.txt", SanitizerKind::Address},

189 {"hwasan_ignorelist.txt", SanitizerKind::HWAddress},

190 {"memtag_ignorelist.txt", SanitizerKind::MemTag},

191 {"msan_ignorelist.txt", SanitizerKind::Memory},

192 {"nsan_ignorelist.txt", SanitizerKind::NumericalStability},

193 {"tsan_ignorelist.txt", SanitizerKind::Thread},

194 {"tysan_blacklist.txt", SanitizerKind::Type},

195 {"dfsan_abilist.txt", SanitizerKind::DataFlow},

196 {"cfi_ignorelist.txt", SanitizerKind::CFI},

197 {"ubsan_ignorelist.txt",

198 SanitizerKind::Undefined | SanitizerKind::Integer |

199 SanitizerKind::Nullability |

200 SanitizerKind::FloatDivideByZero}};

201

202 for (auto BL : Ignorelists) {

203 if (!(Kinds & BL.Mask))

204 continue;

205

207 llvm::sys::path::append(Path, "share", BL.File);

208 if (D.getVFS().exists(Path))

209 IgnorelistFiles.push_back(std::string(Path));

210 else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors)

211

212

213 D.Diag(clang::diag::err_drv_missing_sanitizer_ignorelist) << Path;

214 }

216 D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist,

217 DiagnoseErrors);

218}

219

220

221

223 const llvm::opt::ArgList &Args,

224 std::vectorstd::string &SCLFiles,

225 llvm::opt::OptSpecifier SCLOptionID,

226 llvm::opt::OptSpecifier NoSCLOptionID,

227 unsigned MalformedSCLErrorDiagID,

228 bool DiagnoseErrors) {

229 for (const auto *Arg : Args) {

230

231 if (Arg->getOption().matches(SCLOptionID)) {

232 Arg->claim();

233 std::string SCLPath = Arg->getValue();

234 if (D.getVFS().exists(SCLPath)) {

235 SCLFiles.push_back(SCLPath);

236 } else if (DiagnoseErrors) {

237 D.Diag(clang::diag::err_drv_no_such_file) << SCLPath;

238 }

239

240 } else if (Arg->getOption().matches(NoSCLOptionID)) {

241 Arg->claim();

242 SCLFiles.clear();

243 }

244 }

246 DiagnoseErrors);

247}

248

249

250

252#define SANITIZER(NAME, ID)

253#define SANITIZER_GROUP(NAME, ID, ALIAS) \

254 if (Kinds & SanitizerKind::ID) \

255 Kinds |= SanitizerKind::ID##Group;

256#include "clang/Basic/Sanitizers.def"

257 return Kinds;

258}

259

260

261

262

263

264

265

270 int OptOutID) {

271 assert(!(AlwaysIn & AlwaysOut) &&

272 "parseSanitizeArgs called with contradictory in/out requirements");

273

275

276

279 for (const auto *Arg : Args) {

280 if (Arg->getOption().matches(OptInID)) {

282

283

285 Add & AlwaysOut & ~DiagnosedAlwaysOutViolations) {

286 if (DiagnoseErrors) {

288 SetToDiagnose.Mask |= KindsToDiagnose;

289 D.Diag(diag::err_drv_unsupported_option_argument)

290 << Arg->getSpelling() << toString(SetToDiagnose);

291 DiagnosedAlwaysOutViolations |= KindsToDiagnose;

292 }

293 }

295 Arg->claim();

296 } else if (Arg->getOption().matches(OptOutID)) {

298

299

301 Remove & AlwaysIn & ~DiagnosedAlwaysInViolations) {

302 if (DiagnoseErrors) {

304 SetToDiagnose.Mask |= KindsToDiagnose;

305 D.Diag(diag::err_drv_unsupported_option_argument)

306 << Arg->getSpelling() << toString(SetToDiagnose);

307 DiagnosedAlwaysInViolations |= KindsToDiagnose;

308 }

309 }

310 Output &= ~expandSanitizerGroups(Remove);

311 Arg->claim();

312 }

313 }

314

315 return Output;

316}

317

319 const llvm::opt::ArgList &Args,

320 bool DiagnoseErrors) {

323

324

325

326

327

329 NeverTrap, options::OPT_fsanitize_trap_EQ,

330 options::OPT_fno_sanitize_trap_EQ);

331}

332

335 bool DiagnoseErrors) {

337 for (const auto *Arg : Args)

338 if (Arg->getOption().matches(options::OPT_fsanitize_skip_hot_cutoff_EQ)) {

339 Arg->claim();

341 }

342

343 return Cutoffs;

344}

345

348}

349

351

355 return false;

356

358 CoverageFeatures;

359}

360

362

363

364

366 ~TrapSanitizers.Mask);

367}

368

370 return !(Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&

371 CfiCrossDso && !ImplicitCfiRuntime;

372}

373

375 return (Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&

376 CfiCrossDso && !ImplicitCfiRuntime;

377}

378

380

383}

384

386 return static_cast<bool>(Sanitizers.Mask & NeedsLTO);

387}

388

390 const llvm::opt::ArgList &Args,

391 bool DiagnoseErrors) {

392 SanitizerMask AllRemove;

393

394

395 SanitizerMask AllAddedKinds;

396

397

398

399

400 SanitizerMask DiagnosedKinds;

401

404

405 CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,

406 options::OPT_fno_sanitize_cfi_cross_dso, false);

407

409

413

414 MinimalRuntime =

415 Args.hasFlag(options::OPT_fsanitize_minimal_runtime,

416 options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);

417

418

419 Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);

420 bool RemoveObjectSizeAtO0 =

421 !OptLevel || OptLevel->getOption().matches(options::OPT_O0);

422

423 for (const llvm::opt::Arg *Arg : llvm::reverse(Args)) {

424 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {

425 Arg->claim();

427

428 if (RemoveObjectSizeAtO0) {

429 AllRemove |= SanitizerKind::ObjectSize;

430

431

432

433 if ((Add & SanitizerKind::ObjectSize) && DiagnoseErrors)

434 D.Diag(diag::warn_drv_object_size_disabled_O0)

435 << Arg->getAsString(Args);

436 }

437

439

440

441 Add &= ~AllRemove;

442

443

444

446 Add & InvalidTrappingKinds & ~DiagnosedKinds) {

447 if (DiagnoseErrors) {

449 D.Diag(diag::err_drv_argument_not_allowed_with)

450 << Desc << "-fsanitize-trap=undefined";

451 }

452 DiagnosedKinds |= KindsToDiagnose;

453 }

454 Add &= ~InvalidTrappingKinds;

455

456 if (MinimalRuntime) {

459 if (DiagnoseErrors) {

461 D.Diag(diag::err_drv_argument_not_allowed_with)

462 << Desc << "-fsanitize-minimal-runtime";

463 }

464 DiagnosedKinds |= KindsToDiagnose;

465 }

466 Add &= ~NotAllowedWithMinimalRuntime;

467 }

468

469 if (llvm::opt::Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {

470 StringRef CM = A->getValue();

471 if (CM != "small" &&

472 (Add & SanitizerKind::Function & ~DiagnosedKinds)) {

473 if (DiagnoseErrors)

474 D.Diag(diag::err_drv_argument_only_allowed_with)

475 << "-fsanitize=function"

476 << "-mcmodel=small";

478 DiagnosedKinds |= SanitizerKind::Function;

479 }

480 }

481

482

483

484 const llvm::Triple &Triple = TC.getTriple();

488 if (DiagnoseErrors) {

490 llvm::opt::Arg *A = Args.getLastArgNoClaim(

491 options::OPT_mexecute_only, options::OPT_mno_execute_only);

492 if (A && A->getOption().matches(options::OPT_mexecute_only))

493 D.Diag(diag::err_drv_argument_not_allowed_with)

494 << Desc << A->getAsString(Args);

495 else

496 D.Diag(diag::err_drv_unsupported_opt_for_target)

497 << Desc << Triple.str();

498 }

499 DiagnosedKinds |= KindsToDiagnose;

500 }

501 Add &= ~NotAllowedWithExecuteOnly;

502 }

503

504

505

506

507

508

509

510

511

512

513

514 if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {

515 if (DiagnoseErrors)

516 D.Diag(diag::err_drv_argument_not_allowed_with)

517 << "-fsanitize=cfi-mfcall"

518 << "-fsanitize-cfi-cross-dso";

520 DiagnosedKinds |= SanitizerKind::CFIMFCall;

521 }

522

523 if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {

524 if (DiagnoseErrors) {

526 D.Diag(diag::err_drv_unsupported_opt_for_target)

528 }

529 DiagnosedKinds |= KindsToDiagnose;

530 }

531 Add &= Supported;

532

533

534

535

537 if (const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg()) {

538 assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&

539 "RTTI disabled without -fno-rtti option?");

540

541

542 if (DiagnoseErrors)

543 D.Diag(diag::err_drv_argument_not_allowed_with)

544 << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args);

545 } else {

546

547

548 if (DiagnoseErrors)

549 D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);

550 }

551

552

553 AllRemove |= SanitizerKind::Vptr;

554 }

555

557

558 Add &= ~AllRemove;

559

560

561 Add &= ~InvalidTrappingKinds;

562 if (MinimalRuntime) {

563 Add &= ~NotAllowedWithMinimalRuntime;

564 }

565

566

568 Add &= ~NotAllowedWithExecuteOnly;

569 if (CfiCrossDso)

571

572

573 if (Add & SanitizerKind::UndefinedGroup) {

574 bool S = Args.hasFlagNoClaim(options::OPT_fno_strict_overflow,

575 options::OPT_fstrict_overflow, false);

576 if (Args.hasFlagNoClaim(options::OPT_fwrapv, options::OPT_fno_wrapv, S))

578 }

579 Add &= Supported;

580

581 if (Add & SanitizerKind::Fuzzer)

582 Add |= SanitizerKind::FuzzerNoLink;

583

584

585 if (Add & SanitizerKind::FuzzerNoLink) {

588

591 }

592

593 Kinds |= Add;

594 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {

595 Arg->claim();

598 }

599 }

600

601 std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {

602 std::make_pair(SanitizerKind::Address,

603 SanitizerKind::Thread | SanitizerKind::Memory),

604 std::make_pair(SanitizerKind::Type,

605 SanitizerKind::Address | SanitizerKind::KernelAddress |

606 SanitizerKind::Memory | SanitizerKind::Leak |

607 SanitizerKind::Thread | SanitizerKind::KernelAddress),

608 std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),

609 std::make_pair(SanitizerKind::Leak,

610 SanitizerKind::Thread | SanitizerKind::Memory),

611 std::make_pair(SanitizerKind::KernelAddress,

612 SanitizerKind::Address | SanitizerKind::Leak |

613 SanitizerKind::Thread | SanitizerKind::Memory),

614 std::make_pair(SanitizerKind::HWAddress,

615 SanitizerKind::Address | SanitizerKind::Thread |

616 SanitizerKind::Memory | SanitizerKind::KernelAddress),

617 std::make_pair(SanitizerKind::Scudo,

618 SanitizerKind::Address | SanitizerKind::HWAddress |

619 SanitizerKind::Leak | SanitizerKind::Thread |

620 SanitizerKind::Memory | SanitizerKind::KernelAddress),

621 std::make_pair(SanitizerKind::SafeStack,

623 : SanitizerKind::Leak) |

624 SanitizerKind::Address | SanitizerKind::HWAddress |

625 SanitizerKind::Thread | SanitizerKind::Memory |

626 SanitizerKind::KernelAddress),

627 std::make_pair(SanitizerKind::KernelHWAddress,

628 SanitizerKind::Address | SanitizerKind::HWAddress |

629 SanitizerKind::Leak | SanitizerKind::Thread |

630 SanitizerKind::Memory | SanitizerKind::KernelAddress |

631 SanitizerKind::SafeStack),

632 std::make_pair(SanitizerKind::KernelMemory,

633 SanitizerKind::Address | SanitizerKind::HWAddress |

634 SanitizerKind::Leak | SanitizerKind::Thread |

635 SanitizerKind::Memory | SanitizerKind::KernelAddress |

636 SanitizerKind::Scudo | SanitizerKind::SafeStack),

637 std::make_pair(SanitizerKind::MemTag, SanitizerKind::Address |

638 SanitizerKind::KernelAddress |

639 SanitizerKind::HWAddress |

640 SanitizerKind::KernelHWAddress),

641 std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function),

642 std::make_pair(SanitizerKind::Realtime,

643 SanitizerKind::Address | SanitizerKind::Thread |

644 SanitizerKind::Undefined | SanitizerKind::Memory)};

645

646

648

649

650

651 for (auto G : IncompatibleGroups) {

653 if ((Default & Group) && (Kinds & G.second))

655 }

656

658

659

660

663 }

664

665

666 if ((Kinds & NeedsLTO) && D.isUsingLTO() && DiagnoseErrors) {

667 D.Diag(diag::err_drv_argument_only_allowed_with)

669 }

670

671 if ((Kinds & SanitizerKind::ShadowCallStack) && TC.getTriple().isAArch64() &&

672 !llvm::AArch64::isX18ReservedByDefault(TC.getTriple()) &&

673 !Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {

674 D.Diag(diag::err_drv_argument_only_allowed_with)

676 << "-ffixed-x18";

677 }

678

679

680

681

682

683 if (~Supported & SanitizerKind::Vptr) {

685

686

687 if (TC.getTriple().isOSWindows())

689 if (KindsToDiagnose) {

691 S.Mask = KindsToDiagnose;

692 if (DiagnoseErrors)

693 D.Diag(diag::err_drv_unsupported_opt_for_target)

694 << ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str();

695 Kinds &= ~KindsToDiagnose;

696 }

697 }

698

699

700 for (auto G : IncompatibleGroups) {

702 if (Kinds & Group) {

703 if (SanitizerMask Incompatible = Kinds & G.second) {

704 if (DiagnoseErrors)

705 D.Diag(clang::diag::err_drv_argument_not_allowed_with)

708 Kinds &= ~Incompatible;

709 }

710 }

711 }

712

713

714

715

716

717

720 Unrecoverable, options::OPT_fsanitize_recover_EQ,

721 options::OPT_fno_sanitize_recover_EQ);

723 RecoverableKinds &= ~Unrecoverable;

724 RecoverableKinds &= Kinds;

725

726 TrappingKinds &= Kinds;

727 RecoverableKinds &= ~TrappingKinds;

728

729

732 options::OPT_fsanitize_merge_handlers_EQ,

733 options::OPT_fno_sanitize_merge_handlers_EQ);

734 MergeKinds &= Kinds;

735

736

738

739

740

741

742 if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))

744

745

746

748 D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ,

749 options::OPT_fno_sanitize_ignorelist,

750 clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors);

751

752

753 if (AllAddedKinds & SanitizerKind::Memory) {

754 if (Arg *A =

755 Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,

756 options::OPT_fno_sanitize_memory_track_origins)) {

757 if (!A->getOption().matches(

758 options::OPT_fno_sanitize_memory_track_origins)) {

759 StringRef S = A->getValue();

760 if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||

761 MsanTrackOrigins > 2) {

762 if (DiagnoseErrors)

763 D.Diag(clang::diag::err_drv_invalid_value)

764 << A->getAsString(Args) << S;

765 }

766 }

767 }

768 MsanUseAfterDtor = Args.hasFlag(

769 options::OPT_fsanitize_memory_use_after_dtor,

770 options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);

771 MsanParamRetval = Args.hasFlag(

772 options::OPT_fsanitize_memory_param_retval,

773 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);

774 } else if (AllAddedKinds & SanitizerKind::KernelMemory) {

775 MsanUseAfterDtor = false;

776 MsanParamRetval = Args.hasFlag(

777 options::OPT_fsanitize_memory_param_retval,

778 options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);

779 } else {

780 MsanUseAfterDtor = false;

781 MsanParamRetval = false;

782 }

783

784 if (AllAddedKinds & SanitizerKind::MemTag) {

785 StringRef S =

786 Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ, "sync");

787 if (S == "async" || S == "sync") {

788 MemtagMode = S.str();

789 } else {

790 D.Diag(clang::diag::err_drv_invalid_value_with_suggestion)

791 << "-fsanitize-memtag-mode=" << S << "{async, sync}";

792 MemtagMode = "sync";

793 }

794 }

795

796 if (AllAddedKinds & SanitizerKind::Thread) {

797 TsanMemoryAccess = Args.hasFlag(

798 options::OPT_fsanitize_thread_memory_access,

799 options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);

800 TsanFuncEntryExit = Args.hasFlag(

801 options::OPT_fsanitize_thread_func_entry_exit,

802 options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);

803 TsanAtomics =

804 Args.hasFlag(options::OPT_fsanitize_thread_atomics,

805 options::OPT_fno_sanitize_thread_atomics, TsanAtomics);

806 }

807

808 if (AllAddedKinds & SanitizerKind::CFI) {

809

810

811 NeedPIE |= CfiCrossDso;

812 CfiICallGeneralizePointers =

813 Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);

814

815 CfiICallNormalizeIntegers =

816 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);

817

818 if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)

819 D.Diag(diag::err_drv_argument_not_allowed_with)

820 << "-fsanitize-cfi-cross-dso"

821 << "-fsanitize-cfi-icall-generalize-pointers";

822

823 CfiCanonicalJumpTables =

824 Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,

825 options::OPT_fno_sanitize_cfi_canonical_jump_tables, true);

826 }

827

828 if (AllAddedKinds & SanitizerKind::KCFI) {

829 CfiICallNormalizeIntegers =

830 Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);

831

832 if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)

833 D.Diag(diag::err_drv_argument_not_allowed_with)

834 << "-fsanitize=kcfi"

836 }

837

838 Stats = Args.hasFlag(options::OPT_fsanitize_stats,

839 options::OPT_fno_sanitize_stats, false);

840

841 if (MinimalRuntime) {

844 if (IncompatibleMask && DiagnoseErrors)

845 D.Diag(clang::diag::err_drv_argument_not_allowed_with)

846 << "-fsanitize-minimal-runtime"

848

849 SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds;

850 if (NonTrappingCfi && DiagnoseErrors)

851 D.Diag(clang::diag::err_drv_argument_only_allowed_with)

852 << "fsanitize-minimal-runtime"

853 << "fsanitize-trap=cfi";

854 }

855

856 for (const auto *Arg : Args.filtered(

857 options::OPT_fsanitize_undefined_ignore_overflow_pattern_EQ)) {

858 Arg->claim();

859 OverflowPatternExclusions |=

861 }

862

863

864

865 for (const auto *Arg : Args) {

866 if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {

867 int LegacySanitizeCoverage;

868 if (Arg->getNumValues() == 1 &&

869 !StringRef(Arg->getValue(0))

870 .getAsInteger(0, LegacySanitizeCoverage)) {

871 CoverageFeatures = 0;

872 Arg->claim();

873 if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {

874 D.Diag(diag::warn_drv_deprecated_arg)

875 << Arg->getAsString(Args) << true

876 << "-fsanitize-coverage=trace-pc-guard";

877 }

878 continue;

879 }

881

882

883

885 Arg->claim();

886 } else {

887 CoverageFeatures = 0;

888 }

889 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {

890 Arg->claim();

891 CoverageFeatures &= ~parseCoverageFeatures(D, Arg, DiagnoseErrors);

892 }

893 }

894

895 if (DiagnoseErrors) {

897 D.Diag(clang::diag::err_drv_argument_not_allowed_with)

898 << "-fsanitize-coverage=func"

899 << "-fsanitize-coverage=bb";

901 D.Diag(clang::diag::err_drv_argument_not_allowed_with)

902 << "-fsanitize-coverage=func"

903 << "-fsanitize-coverage=edge";

905 D.Diag(clang::diag::err_drv_argument_not_allowed_with)

906 << "-fsanitize-coverage=bb"

907 << "-fsanitize-coverage=edge";

908

909

911 D.Diag(clang::diag::warn_drv_deprecated_arg)

912 << "-fsanitize-coverage=trace-bb" << true

913 << "-fsanitize-coverage=trace-pc-guard";

915 D.Diag(clang::diag::warn_drv_deprecated_arg)

916 << "-fsanitize-coverage=8bit-counters" << true

917 << "-fsanitize-coverage=trace-pc-guard";

918 }

919

925 if ((CoverageFeatures & InsertionPointTypes) &&

926 !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {

927 D.Diag(clang::diag::warn_drv_deprecated_arg)

928 << "-fsanitize-coverage=[func|bb|edge]" << true

929 << "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["

930 "control-flow]";

931 }

932

933

934 if (!(CoverageFeatures & InsertionPointTypes)) {

935 if (CoverageFeatures &

939

942 }

943

944

945

946

947

948 if (CoverageFeatures) {

950 D, Args, CoverageAllowlistFiles,

951 options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),

952 clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,

953 DiagnoseErrors);

955 D, Args, CoverageIgnorelistFiles,

956 options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),

957 clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,

958 DiagnoseErrors);

959 }

960

961

962 for (const auto *Arg :

963 Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,

964 options::OPT_fno_experimental_sanitize_metadata_EQ)) {

965 if (Arg->getOption().matches(

966 options::OPT_fexperimental_sanitize_metadata_EQ)) {

967 Arg->claim();

968 BinaryMetadataFeatures |=

970 } else {

971 Arg->claim();

972 BinaryMetadataFeatures &=

973 ~parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);

974 }

975 }

976

977

978 if (BinaryMetadataFeatures) {

980 D, Args, BinaryMetadataIgnorelistFiles,

981 options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,

982 OptSpecifier(),

983 clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,

984 DiagnoseErrors);

985 }

986

987 SharedRuntime = Args.hasFlag(

988 options::OPT_shared_libsan, options::OPT_static_libsan,

991 if (!SharedRuntime && TC.getTriple().isOSWindows()) {

992 Arg *A =

993 Args.getLastArg(options::OPT_shared_libsan, options::OPT_static_libsan);

994 D.Diag(clang::diag::err_drv_unsupported_opt_for_target)

995 << A->getSpelling() << TC.getTriple().str();

996 }

997

998 ImplicitCfiRuntime = TC.getTriple().isAndroid();

999

1000 if (AllAddedKinds & SanitizerKind::Address) {

1001 NeedPIE |= TC.getTriple().isOSFuchsia();

1002 if (Arg *A =

1003 Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {

1004 StringRef S = A->getValue();

1005

1006 if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||

1007 AsanFieldPadding > 2) &&

1008 DiagnoseErrors) {

1009 D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;

1010 }

1011 }

1012

1013 if (Arg *WindowsDebugRTArg =

1014 Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,

1015 options::OPT__SLASH_MDd, options::OPT__SLASH_MD,

1016 options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {

1017 switch (WindowsDebugRTArg->getOption().getID()) {

1018 case options::OPT__SLASH_MTd:

1019 case options::OPT__SLASH_MDd:

1020 case options::OPT__SLASH_LDd:

1021 if (DiagnoseErrors) {

1022 D.Diag(clang::diag::err_drv_argument_not_allowed_with)

1023 << WindowsDebugRTArg->getAsString(Args)

1025 D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);

1026 }

1027 }

1028 }

1029

1030 StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,

1031 options::OPT_fno_sanitize_stable_abi, false);

1032

1033 AsanUseAfterScope = Args.hasFlag(

1034 options::OPT_fsanitize_address_use_after_scope,

1035 options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);

1036

1037 AsanPoisonCustomArrayCookie = Args.hasFlag(

1038 options::OPT_fsanitize_address_poison_custom_array_cookie,

1039 options::OPT_fno_sanitize_address_poison_custom_array_cookie,

1040 AsanPoisonCustomArrayCookie);

1041

1042 AsanOutlineInstrumentation =

1043 Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,

1044 options::OPT_fno_sanitize_address_outline_instrumentation,

1045 AsanOutlineInstrumentation);

1046

1047 AsanGlobalsDeadStripping = Args.hasFlag(

1048 options::OPT_fsanitize_address_globals_dead_stripping,

1049 options::OPT_fno_sanitize_address_globals_dead_stripping, true);

1050

1051

1052

1053

1054

1055 AsanUseOdrIndicator =

1056 Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,

1057 options::OPT_fno_sanitize_address_use_odr_indicator,

1059

1060 if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {

1061 AsanInvalidPointerCmp = true;

1062 }

1063

1064 if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {

1065 AsanInvalidPointerSub = true;

1066 }

1067

1068 if (TC.getTriple().isOSDarwin() &&

1069 (Args.hasArg(options::OPT_mkernel) ||

1070 Args.hasArg(options::OPT_fapple_kext))) {

1071 AsanDtorKind = llvm::AsanDtorKind::None;

1072 }

1073

1074 if (const auto *Arg =

1075 Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {

1077 if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {

1078 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)

1079 << Arg->getSpelling() << Arg->getValue();

1080 }

1081 AsanDtorKind = parsedAsanDtorKind;

1082 }

1083

1084 if (const auto *Arg = Args.getLastArg(

1085 options::OPT_sanitize_address_use_after_return_EQ)) {

1086 auto parsedAsanUseAfterReturn =

1088 if (parsedAsanUseAfterReturn ==

1089 llvm::AsanDetectStackUseAfterReturnMode::Invalid &&

1090 DiagnoseErrors) {

1091 TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)

1092 << Arg->getSpelling() << Arg->getValue();

1093 }

1094 AsanUseAfterReturn = parsedAsanUseAfterReturn;

1095 }

1096

1097 } else {

1098 AsanUseAfterScope = false;

1099

1101 SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;

1102 if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&

1103 DiagnoseErrors) {

1104 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)

1106 SanitizerKind::PointerCompare |

1107 SanitizerKind::PointerSubtract)

1108 << "-fsanitize=address";

1109 }

1110 }

1111

1112 if (AllAddedKinds & SanitizerKind::HWAddress) {

1113 if (Arg *HwasanAbiArg =

1114 Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {

1115 HwasanAbi = HwasanAbiArg->getValue();

1116 if (HwasanAbi != "platform" && HwasanAbi != "interceptor" &&

1117 DiagnoseErrors)

1118 D.Diag(clang::diag::err_drv_invalid_value)

1119 << HwasanAbiArg->getAsString(Args) << HwasanAbi;

1120 } else {

1121 HwasanAbi = "interceptor";

1122 }

1123 if (TC.getTriple().getArch() == llvm::Triple::x86_64)

1124 HwasanUseAliases = Args.hasFlag(

1125 options::OPT_fsanitize_hwaddress_experimental_aliasing,

1126 options::OPT_fno_sanitize_hwaddress_experimental_aliasing,

1127 HwasanUseAliases);

1128 }

1129

1130 if (AllAddedKinds & SanitizerKind::SafeStack) {

1131

1132 SafeStackRuntime =

1134 }

1135

1136 LinkRuntimes =

1137 Args.hasFlag(options::OPT_fsanitize_link_runtime,

1138 options::OPT_fno_sanitize_link_runtime, LinkRuntimes);

1139

1140

1141 LinkCXXRuntimes = D.CCCIsCXX();

1142 LinkCXXRuntimes =

1143 Args.hasFlag(options::OPT_fsanitize_link_cxx_runtime,

1144 options::OPT_fno_sanitize_link_cxx_runtime, LinkCXXRuntimes);

1145

1146 NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,

1147 options::OPT_fmemory_profile_EQ,

1148 options::OPT_fno_memory_profile, false);

1149

1150

1151 Sanitizers.Mask |= Kinds;

1152 RecoverableSanitizers.Mask |= RecoverableKinds;

1153 TrapSanitizers.Mask |= TrappingKinds;

1154 assert(!(RecoverableKinds & TrappingKinds) &&

1155 "Overlap between recoverable and trapping sanitizers");

1156

1157 MergeHandlers.Mask |= MergeKinds;

1158

1159

1160 SkipHotCutoffs.clear(~Sanitizers.Mask);

1161}

1162

1164 std::string Res;

1165#define SANITIZER(NAME, ID) \

1166 if (Sanitizers.has(SanitizerKind::ID)) { \

1167 if (!Res.empty()) \

1168 Res += ","; \

1169 Res += NAME; \

1170 }

1171#include "clang/Basic/Sanitizers.def"

1172 return Res;

1173}

1174

1178 return llvm::join(Res, ",");

1179}

1180

1182 llvm::opt::ArgStringList &CmdArgs,

1183 const char *SCLOptFlag,

1184 const std::vectorstd::string &SCLFiles) {

1185 for (const auto &SCLPath : SCLFiles) {

1187 SCLOpt += SCLPath;

1188 CmdArgs.push_back(Args.MakeArgString(SCLOpt));

1189 }

1190}

1191

1193 const llvm::opt::ArgList &Args,

1194 llvm::opt::ArgStringList &CmdArgs,

1195 StringRef SymbolName) {

1197 LinkerOptionFlag = "--linker-option=/include:";

1198 if (TC.getTriple().getArch() == llvm::Triple::x86) {

1199

1200 LinkerOptionFlag += '_';

1201 }

1202 LinkerOptionFlag += SymbolName;

1203 CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));

1204}

1205

1207 for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;

1208 ++Start) {

1209 auto It = std::find(Start, End, StringRef("+mte"));

1210 if (It == End)

1211 break;

1212 if (It > Start && *std::prev(It) == StringRef("-target-feature"))

1213 return true;

1214 Start = It;

1215 }

1216 return false;

1217}

1218

1220 llvm::opt::ArgStringList &CmdArgs,

1222

1223

1224

1226 return;

1227

1228 bool GPUSanitize = false;

1229 if (TC.getTriple().isAMDGPU()) {

1230 if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,

1231 true))

1232 return;

1233 GPUSanitize = true;

1234 }

1235

1236

1237

1238

1239 std::pair<int, const char *> CoverageFlags[] = {

1240 std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),

1241 std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),

1242 std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),

1243 std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),

1244 std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),

1245 std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),

1246 std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"),

1247 std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"),

1249 std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),

1251 "-fsanitize-coverage-trace-pc-guard"),

1253 "-fsanitize-coverage-inline-8bit-counters"),

1255 "-fsanitize-coverage-inline-bool-flag"),

1256 std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"),

1257 std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"),

1258 std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth"),

1259 std::make_pair(CoverageTraceLoads, "-fsanitize-coverage-trace-loads"),

1260 std::make_pair(CoverageTraceStores, "-fsanitize-coverage-trace-stores"),

1261 std::make_pair(CoverageControlFlow, "-fsanitize-coverage-control-flow")};

1262 for (auto F : CoverageFlags) {

1263 if (CoverageFeatures & F.first)

1264 CmdArgs.push_back(F.second);

1265 }

1267 Args, CmdArgs, "-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);

1269 CoverageIgnorelistFiles);

1270

1271 if (!GPUSanitize) {

1272

1273

1274 const std::pair<int, std::string> BinaryMetadataFlags[] = {

1278 for (const auto &F : BinaryMetadataFlags) {

1279 if (BinaryMetadataFeatures & F.first)

1280 CmdArgs.push_back(

1281 Args.MakeArgString("-fexperimental-sanitize-metadata=" + F.second));

1282 }

1284 "-fexperimental-sanitize-metadata-ignorelist=",

1285 BinaryMetadataIgnorelistFiles);

1286 }

1287

1289 Args.hasFlag(options::OPT_frtlib_defaultlib,

1290 options::OPT_fno_rtlib_defaultlib, true)) {

1291

1292

1293 CmdArgs.push_back(

1294 Args.MakeArgString("--dependent-lib=" +

1297 CmdArgs.push_back(Args.MakeArgString(

1298 "--dependent-lib=" +

1300 }

1302 Args.hasFlag(options::OPT_frtlib_defaultlib,

1303 options::OPT_fno_rtlib_defaultlib, true)) {

1304 CmdArgs.push_back(Args.MakeArgString(

1306

1307

1308

1309

1310

1311 CmdArgs.push_back(Args.MakeArgString(

1314 }

1315

1316 if (Sanitizers.empty())

1317 return;

1318 CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));

1319

1320 if (!RecoverableSanitizers.empty())

1321 CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +

1322 toString(RecoverableSanitizers)));

1323

1324 if (!TrapSanitizers.empty())

1325 CmdArgs.push_back(

1326 Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));

1327

1328 if (!MergeHandlers.empty())

1329 CmdArgs.push_back(

1330 Args.MakeArgString("-fsanitize-merge=" + toString(MergeHandlers)));

1331

1332 std::string SkipHotCutoffsStr = toString(SkipHotCutoffs);

1333 if (!SkipHotCutoffsStr.empty())

1334 CmdArgs.push_back(

1335 Args.MakeArgString("-fsanitize-skip-hot-cutoff=" + SkipHotCutoffsStr));

1336

1338 "-fsanitize-ignorelist=", UserIgnorelistFiles);

1340 "-fsanitize-system-ignorelist=", SystemIgnorelistFiles);

1341

1342 if (OverflowPatternExclusions)

1343 Args.AddAllArgs(

1344 CmdArgs, options::OPT_fsanitize_undefined_ignore_overflow_pattern_EQ);

1345

1346 if (MsanTrackOrigins)

1347 CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +

1348 Twine(MsanTrackOrigins)));

1349

1350 if (MsanUseAfterDtor)

1351 CmdArgs.push_back("-fsanitize-memory-use-after-dtor");

1352

1353 if (!MsanParamRetval)

1354 CmdArgs.push_back("-fno-sanitize-memory-param-retval");

1355

1356

1357 if (!TsanMemoryAccess) {

1358 CmdArgs.push_back("-mllvm");

1359 CmdArgs.push_back("-tsan-instrument-memory-accesses=0");

1360 CmdArgs.push_back("-mllvm");

1361 CmdArgs.push_back("-tsan-instrument-memintrinsics=0");

1362 }

1363 if (!TsanFuncEntryExit) {

1364 CmdArgs.push_back("-mllvm");

1365 CmdArgs.push_back("-tsan-instrument-func-entry-exit=0");

1366 }

1367 if (!TsanAtomics) {

1368 CmdArgs.push_back("-mllvm");

1369 CmdArgs.push_back("-tsan-instrument-atomics=0");

1370 }

1371

1372 if (HwasanUseAliases) {

1373 CmdArgs.push_back("-mllvm");

1374 CmdArgs.push_back("-hwasan-experimental-use-page-aliases=1");

1375 }

1376

1377 if (CfiCrossDso)

1378 CmdArgs.push_back("-fsanitize-cfi-cross-dso");

1379

1380 if (CfiICallGeneralizePointers)

1381 CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers");

1382

1383 if (CfiICallNormalizeIntegers)

1384 CmdArgs.push_back("-fsanitize-cfi-icall-experimental-normalize-integers");

1385

1386 if (CfiCanonicalJumpTables)

1387 CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables");

1388

1389 if (Stats)

1390 CmdArgs.push_back("-fsanitize-stats");

1391

1392 if (MinimalRuntime)

1393 CmdArgs.push_back("-fsanitize-minimal-runtime");

1394

1395 if (AsanFieldPadding)

1396 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +

1397 Twine(AsanFieldPadding)));

1398

1399 if (AsanUseAfterScope)

1400 CmdArgs.push_back("-fsanitize-address-use-after-scope");

1401

1402 if (AsanPoisonCustomArrayCookie)

1403 CmdArgs.push_back("-fsanitize-address-poison-custom-array-cookie");

1404

1405 if (AsanGlobalsDeadStripping)

1406 CmdArgs.push_back("-fsanitize-address-globals-dead-stripping");

1407

1408 if (!AsanUseOdrIndicator)

1409 CmdArgs.push_back("-fno-sanitize-address-use-odr-indicator");

1410

1411 if (AsanInvalidPointerCmp) {

1412 CmdArgs.push_back("-mllvm");

1413 CmdArgs.push_back("-asan-detect-invalid-pointer-cmp");

1414 }

1415

1416 if (AsanInvalidPointerSub) {

1417 CmdArgs.push_back("-mllvm");

1418 CmdArgs.push_back("-asan-detect-invalid-pointer-sub");

1419 }

1420

1421 if (AsanOutlineInstrumentation) {

1422 CmdArgs.push_back("-mllvm");

1423 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");

1424 }

1425

1426

1427

1428

1429 if (StableABI) {

1430 CmdArgs.push_back("-mllvm");

1431 CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");

1432 CmdArgs.push_back("-mllvm");

1433 CmdArgs.push_back("-asan-max-inline-poisoning-size=0");

1434 CmdArgs.push_back("-mllvm");

1435 CmdArgs.push_back("-asan-guard-against-version-mismatch=0");

1436 }

1437

1438

1439

1440 if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {

1441 CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-destructor=" +

1443 }

1444

1445 if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {

1446 CmdArgs.push_back(Args.MakeArgString(

1447 "-fsanitize-address-use-after-return=" +

1449 }

1450

1451 if (!HwasanAbi.empty()) {

1452 CmdArgs.push_back("-default-function-attr");

1453 CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));

1454 }

1455

1456 if (Sanitizers.has(SanitizerKind::HWAddress) && !HwasanUseAliases) {

1457 CmdArgs.push_back("-target-feature");

1458 CmdArgs.push_back("+tagged-globals");

1459 }

1460

1461

1462

1463

1464

1465

1466 if (Sanitizers.has(SanitizerKind::Memory) ||

1467 Sanitizers.has(SanitizerKind::Address))

1468 CmdArgs.push_back("-fno-assume-sane-operator-new");

1469

1470

1471

1472

1473

1474

1475 if (Sanitizers.has(SanitizerKind::FuzzerNoLink)) {

1476 CmdArgs.push_back("-fno-builtin-bcmp");

1477 CmdArgs.push_back("-fno-builtin-memcmp");

1478 CmdArgs.push_back("-fno-builtin-strncmp");

1479 CmdArgs.push_back("-fno-builtin-strcmp");

1480 CmdArgs.push_back("-fno-builtin-strncasecmp");

1481 CmdArgs.push_back("-fno-builtin-strcasecmp");

1482 CmdArgs.push_back("-fno-builtin-strstr");

1483 CmdArgs.push_back("-fno-builtin-strcasestr");

1484 CmdArgs.push_back("-fno-builtin-memmem");

1485 }

1486

1487

1488

1490 !Args.hasArg(options::OPT_fvisibility_EQ)) {

1491 TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)

1494 << "-fvisibility=";

1495 }

1496

1497 if (Sanitizers.has(SanitizerKind::MemtagStack) &&

1499 TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature);

1500}

1501

1503 bool DiagnoseErrors) {

1504 assert(

1505 (A->getOption().matches(options::OPT_fsanitize_EQ) ||

1506 A->getOption().matches(options::OPT_fno_sanitize_EQ) ||

1507 A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||

1508 A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||

1509 A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||

1510 A->getOption().matches(options::OPT_fno_sanitize_trap_EQ) ||

1511 A->getOption().matches(options::OPT_fsanitize_merge_handlers_EQ) ||

1512 A->getOption().matches(options::OPT_fno_sanitize_merge_handlers_EQ)) &&

1513 "Invalid argument in parseArgValues!");

1515 for (int i = 0, n = A->getNumValues(); i != n; ++i) {

1516 const char *Value = A->getValue(i);

1518

1519 if (A->getOption().matches(options::OPT_fsanitize_EQ) &&

1520 0 == strcmp("all", Value))

1522 else

1524

1525 if (Kind)

1526 Kinds |= Kind;

1527 else if (DiagnoseErrors)

1528 D.Diag(clang::diag::err_drv_unsupported_option_argument)

1529 << A->getSpelling() << Value;

1530 }

1531 return Kinds;

1532}

1533

1536 assert(A->getOption().matches(options::OPT_fsanitize_skip_hot_cutoff_EQ) &&

1537 "Invalid argument in parseArgCutoffs!");

1538 for (int i = 0, n = A->getNumValues(); i != n; ++i) {

1539 const char *Value = A->getValue(i);

1540

1541

1542

1544 DiagnoseErrors)

1545 D.Diag(clang::diag::err_drv_unsupported_option_argument)

1546 << A->getSpelling() << Value;

1547 }

1548}

1549

1551 const llvm::opt::Arg *A,

1552 bool DiagnoseErrors) {

1553 int Exclusions = 0;

1554 for (int i = 0, n = A->getNumValues(); i != n; ++i) {

1555 const char *Value = A->getValue(i);

1556 int E =

1557 llvm::StringSwitch(Value)

1560 .Case("add-unsigned-overflow-test",

1562 .Case("add-signed-overflow-test",

1566 .Default(0);

1567 if (E == 0)

1568 D.Diag(clang::diag::err_drv_unsupported_option_argument)

1569 << A->getSpelling() << Value;

1570 Exclusions |= E;

1571 }

1572 return Exclusions;

1573}

1574

1576 bool DiagnoseErrors) {

1577 assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||

1578 A->getOption().matches(options::OPT_fno_sanitize_coverage));

1579 int Features = 0;

1580 for (int i = 0, n = A->getNumValues(); i != n; ++i) {

1581 const char *Value = A->getValue(i);

1582 int F = llvm::StringSwitch(Value)

1602 .Default(0);

1603 if (F == 0 && DiagnoseErrors)

1604 D.Diag(clang::diag::err_drv_unsupported_option_argument)

1605 << A->getSpelling() << Value;

1606 Features |= F;

1607 }

1608 return Features;

1609}

1610

1612 bool DiagnoseErrors) {

1613 assert(

1614 A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||

1615 A->getOption().matches(

1616 options::OPT_fno_experimental_sanitize_metadata_EQ));

1617 int Features = 0;

1618 for (int i = 0, n = A->getNumValues(); i != n; ++i) {

1619 const char *Value = A->getValue(i);

1620 int F = llvm::StringSwitch(Value)

1624 .Case("all", ~0)

1625 .Default(0);

1626 if (F == 0 && DiagnoseErrors)

1627 D.Diag(clang::diag::err_drv_unsupported_option_argument)

1628 << A->getSpelling() << Value;

1629 Features |= F;

1630 }

1631 return Features;

1632}

1633

1636 for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),

1637 E = Args.rend();

1638 I != E; ++I) {

1639 const auto *Arg = *I;

1640 if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {

1643 if (AddKinds & Mask)

1645 } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {

1648 Mask &= ~RemoveKinds;

1649 }

1650 }

1651 llvm_unreachable("arg list didn't provide expected value");

1652}

1653

1655 assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&

1656 "Invalid argument in describeSanitizerArg!");

1657

1658 std::string Sanitizers;

1659 for (int i = 0, n = A->getNumValues(); i != n; ++i) {

1662 Mask) {

1663 if (!Sanitizers.empty())

1664 Sanitizers += ",";

1665 Sanitizers += A->getValue(i);

1666 }

1667 }

1668

1669 assert(!Sanitizers.empty() && "arg didn't provide expected value");

1670 return "-fsanitize=" + Sanitizers;

1671}

static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds, std::vector< std::string > &IgnorelistFiles, bool DiagnoseErrors)

static std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask)

Produce an argument string from argument A, which shows how it provides a value in Mask.

static SanitizerMask parseSanitizeTrapArgs(const Driver &D, const llvm::opt::ArgList &Args, bool DiagnoseErrors)

static SanitizerMask parseSanitizeArgs(const Driver &D, const llvm::opt::ArgList &Args, bool DiagnoseErrors, SanitizerMask Default, SanitizerMask AlwaysIn, SanitizerMask AlwaysOut, int OptInID, int OptOutID)

static void addIncludeLinkerOption(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, StringRef SymbolName)

static bool isExecuteOnlyTarget(const llvm::Triple &Triple, const llvm::opt::ArgList &Args)

Return true if an execute-only target disallows data access to code sections.

static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs)

static const SanitizerMask SupportsCoverage

static const SanitizerMask CFIClasses

static int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors)

Parse -f(no-)?sanitize-metadata= flag values, diagnosing any invalid components.

static const SanitizerMask TrappingSupported

static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors)

Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any invalid components.

static const SanitizerMask NeedsUnwindTables

static const SanitizerMask MergeDefault

static void addSpecialCaseListOpt(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const char *SCLOptFlag, const std::vector< std::string > &SCLFiles)

static const SanitizerMask NotAllowedWithMinimalRuntime

static const SanitizerMask AlwaysRecoverable

static std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args, SanitizerMask Mask)

Produce an argument string from ArgList Args, which shows how it provides some sanitizer kind from Ma...

static SanitizerMaskCutoffs parseSanitizeSkipHotCutoffArgs(const Driver &D, const llvm::opt::ArgList &Args, bool DiagnoseErrors)

static std::string toString(const clang::SanitizerSet &Sanitizers)

Produce a string containing comma-separated names of sanitizers in Sanitizers set.

static const SanitizerMask NeedsUbsanCxxRt

static const SanitizerMask TrappingDefault

static const SanitizerMask CompatibleWithMinimalRuntime

static const SanitizerMask Unrecoverable

static const SanitizerMask RecoverableByDefault

static void parseArgCutoffs(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors, SanitizerMaskCutoffs &Cutoffs)

Parse a -fsanitize==... or -fno-sanitize= argument's values, diagnosing any inval...

static const SanitizerMask NeedsLTO

static SanitizerMask setGroupBits(SanitizerMask Kinds)

Sets group bits for every group that has at least one representative already enabled in Kinds.

static const SanitizerMask NeedsUbsanRt

static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors)

Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid components.

static void validateSpecialCaseListFormat(const Driver &D, std::vector< std::string > &SCLFiles, unsigned MalformedSCLErrorDiagID, bool DiagnoseErrors)

static const SanitizerMask NotAllowedWithTrap

static void parseSpecialCaseListArg(const Driver &D, const llvm::opt::ArgList &Args, std::vector< std::string > &SCLFiles, llvm::opt::OptSpecifier SCLOptionID, llvm::opt::OptSpecifier NoSCLOptionID, unsigned MalformedSCLErrorDiagID, bool DiagnoseErrors)

Parse -f(no-)?sanitize-(coverage-)?(allow|ignore)list argument's values, diagnosing any invalid file ...

static int parseOverflowPatternExclusionValues(const Driver &D, const llvm::opt::Arg *A, bool DiagnoseErrors)

Parse -fsanitize-undefined-ignore-overflow-pattern= flag values, diagnosing any invalid values.

static const SanitizerMask NotAllowedWithExecuteOnly

@ CoverageInline8bitCounters

Defines the clang::SanitizerKind enum.

@ None

Don't exclude any overflow patterns from sanitizers.

@ AddUnsignedOverflowTest

if (a + b < a)

@ All

Exclude all overflow patterns (below)

@ AddSignedOverflowTest

if (a + b < a)

@ PostDecrInWhile

while (count–)

void clear(SanitizerMask K=SanitizerKind::All)

Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...

DiagnosticBuilder Diag(unsigned DiagID) const

bool needsFuzzerInterceptors() const

bool needsStatsRt() const

bool needsCfiDiagRt() const

bool needsUbsanRt() const

SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, bool DiagnoseErrors=true)

Parses the sanitizer arguments from an argument list.

bool needsHwasanRt() const

bool requiresMinimalRuntime() const

bool needsUnwindTables() const

bool needsDfsanRt() const

bool needsScudoRt() const

bool needsUbsanCXXRt() const

void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const

bool isCXX(ID Id)

isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).

The JSON file list parser is used to communicate input to InstallAPI.

StringRef AsanDtorKindToString(llvm::AsanDtorKind kind)

bool parseSanitizerWeightedValue(StringRef Value, bool AllowGroups, SanitizerMaskCutoffs &Cutoffs)

Parse a single weighted value (e.g., 'undefined=0.05') from a -fsanitize= or -fno-sanitize= value lis...

SanitizerMask expandSanitizerGroups(SanitizerMask Kinds)

For each sanitizer group bit set in Kinds, set the bits for sanitizers this group enables.

void serializeSanitizerMaskCutoffs(const SanitizerMaskCutoffs &Cutoffs, SmallVectorImpl< std::string > &Values)

Serialize a SanitizerMaskCutoffs into values for -fsanitize= or -fno-sanitize=.

SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups)

Parse a single value from a -fsanitize= or -fno-sanitize= value list.

llvm::AsanDtorKind AsanDtorKindFromString(StringRef kind)

llvm::AsanDetectStackUseAfterReturnMode AsanDetectStackUseAfterReturnModeFromString(StringRef modeStr)

StringRef AsanDetectStackUseAfterReturnModeToString(llvm::AsanDetectStackUseAfterReturnMode mode)

bool empty() const

Returns true if no sanitizers are enabled.

bool has(SanitizerMask K) const

Check if a certain (single) sanitizer is enabled.

SanitizerMask Mask

Bitmask of enabled sanitizers.

bool hasOneOf(SanitizerMask K) const

Check if one or more sanitizers are enabled.