1 //===-- driver.cpp - Clang GCC-Compatible Driver --------------------------===// 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 // This is the entry point to the clang driver; it is a thin wrapper 10 // for functionality in the Driver clang library. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/Driver/Driver.h" 15 #include "clang/Basic/DiagnosticOptions.h" 16 #include "clang/Basic/HeaderInclude.h" 17 #include "clang/Basic/Stack.h" 18 #include "clang/Config/config.h" 19 #include "clang/Driver/Compilation.h" 20 #include "clang/Driver/DriverDiagnostic.h" 21 #include "clang/Driver/Options.h" 22 #include "clang/Driver/ToolChain.h" 23 #include "clang/Frontend/ChainedDiagnosticConsumer.h" 24 #include "clang/Frontend/CompilerInvocation.h" 25 #include "clang/Frontend/SerializedDiagnosticPrinter.h" 26 #include "clang/Frontend/TextDiagnosticPrinter.h" 27 #include "clang/Frontend/Utils.h" 28 #include "llvm/ADT/ArrayRef.h" 29 #include "llvm/ADT/SmallString.h" 30 #include "llvm/ADT/SmallVector.h" 31 #include "llvm/ADT/StringSet.h" 32 #include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX 33 #include "llvm/Option/ArgList.h" 34 #include "llvm/Option/OptTable.h" 35 #include "llvm/Option/Option.h" 36 #include "llvm/Support/BuryPointer.h" 37 #include "llvm/Support/CommandLine.h" 38 #include "llvm/Support/CrashRecoveryContext.h" 39 #include "llvm/Support/ErrorHandling.h" 40 #include "llvm/Support/FileSystem.h" 41 #include "llvm/Support/LLVMDriver.h" 42 #include "llvm/Support/Path.h" 43 #include "llvm/Support/PrettyStackTrace.h" 44 #include "llvm/Support/Process.h" 45 #include "llvm/Support/Program.h" 46 #include "llvm/Support/Signals.h" 47 #include "llvm/Support/StringSaver.h" 48 #include "llvm/Support/TargetSelect.h" 49 #include "llvm/Support/Timer.h" 50 #include "llvm/Support/VirtualFileSystem.h" 51 #include "llvm/Support/raw_ostream.h" 52 #include "llvm/TargetParser/Host.h" 53 #include <memory> 54 #include <optional> 55 #include <set> 56 #include <system_error> 57 58 using namespace clang; 59 using namespace clang::driver; 60 using namespace llvm::opt; 61 62 std::string GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) { 63 if (!CanonicalPrefixes) { 64 SmallString<128> ExecutablePath(Argv0); 65 // Do a PATH lookup if Argv0 isn't a valid path. 66 if (!llvm::sys::fs::exists(ExecutablePath)) 67 if (llvm::ErrorOr<std::string> P = 68 llvm::sys::findProgramByName(ExecutablePath)) 69 ExecutablePath = *P; 70 return std::string(ExecutablePath); 71 } 72 73 // This just needs to be some symbol in the binary; C++ doesn't 74 // allow taking the address of ::main however. 75 void *P = (void*) (intptr_t) GetExecutablePath; 76 return llvm::sys::fs::getMainExecutable(Argv0, P); 77 } 78 79 static const char *GetStableCStr(llvm::StringSet<> &SavedStrings, StringRef S) { 80 return SavedStrings.insert(S).first->getKeyData(); 81 } 82 83 extern int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, 84 void *MainAddr); 85 extern int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, 86 void *MainAddr); 87 extern int cc1gen_reproducer_main(ArrayRef<const char *> Argv, 88 const char *Argv0, void *MainAddr, 89 const llvm::ToolContext &); 90 91 static void insertTargetAndModeArgs(const ParsedClangName &NameParts, 92 SmallVectorImpl<const char *> &ArgVector, 93 llvm::StringSet<> &SavedStrings) { 94 // Put target and mode arguments at the start of argument list so that 95 // arguments specified in command line could override them. Avoid putting 96 // them at index 0, as an option like '-cc1' must remain the first. 97 int InsertionPoint = 0; 98 if (ArgVector.size() > 0) 99 ++InsertionPoint; 100 101 if (NameParts.DriverMode) { 102 // Add the mode flag to the arguments. 103 ArgVector.insert(ArgVector.begin() + InsertionPoint, 104 GetStableCStr(SavedStrings, NameParts.DriverMode)); 105 } 106 107 if (NameParts.TargetIsValid) { 108 const char *arr[] = {"-target", GetStableCStr(SavedStrings, 109 NameParts.TargetPrefix)}; 110 ArgVector.insert(ArgVector.begin() + InsertionPoint, 111 std::begin(arr), std::end(arr)); 112 } 113 } 114 115 static void getCLEnvVarOptions(std::string &EnvValue, llvm::StringSaver &Saver, 116 SmallVectorImpl<const char *> &Opts) { 117 llvm::cl::TokenizeWindowsCommandLine(EnvValue, Saver, Opts); 118 // The first instance of '#' should be replaced with '=' in each option. 119 for (const char *Opt : Opts) 120 if (char *NumberSignPtr = const_cast<char *>(::strchr(Opt, '#'))) 121 *NumberSignPtr = '='; 122 } 123 124 template <class T> 125 static T checkEnvVar(const char *EnvOptSet, const char *EnvOptFile, 126 std::string &OptFile) { 127 const char *Str = ::getenv(EnvOptSet); 128 if (!Str) 129 return T{}; 130 131 T OptVal = Str; 132 if (const char *Var = ::getenv(EnvOptFile)) 133 OptFile = Var; 134 return OptVal; 135 } 136 137 static bool SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) { 138 TheDriver.CCPrintOptions = 139 checkEnvVar<bool>("CC_PRINT_OPTIONS", "CC_PRINT_OPTIONS_FILE", 140 TheDriver.CCPrintOptionsFilename); 141 if (checkEnvVar<bool>("CC_PRINT_HEADERS", "CC_PRINT_HEADERS_FILE", 142 TheDriver.CCPrintHeadersFilename)) { 143 TheDriver.CCPrintHeadersFormat = HIFMT_Textual; 144 TheDriver.CCPrintHeadersFiltering = HIFIL_None; 145 } else { 146 std::string EnvVar = checkEnvVar<std::string>( 147 "CC_PRINT_HEADERS_FORMAT", "CC_PRINT_HEADERS_FILE", 148 TheDriver.CCPrintHeadersFilename); 149 if (!EnvVar.empty()) { 150 TheDriver.CCPrintHeadersFormat = 151 stringToHeaderIncludeFormatKind(EnvVar.c_str()); 152 if (!TheDriver.CCPrintHeadersFormat) { 153 TheDriver.Diag(clang::diag::err_drv_print_header_env_var) 154 << 0 << EnvVar; 155 return false; 156 } 157 158 const char *FilteringStr = ::getenv("CC_PRINT_HEADERS_FILTERING"); 159 HeaderIncludeFilteringKind Filtering; 160 if (!stringToHeaderIncludeFiltering(FilteringStr, Filtering)) { 161 TheDriver.Diag(clang::diag::err_drv_print_header_env_var) 162 << 1 << FilteringStr; 163 return false; 164 } 165 166 if ((TheDriver.CCPrintHeadersFormat == HIFMT_Textual && 167 Filtering != HIFIL_None) || 168 (TheDriver.CCPrintHeadersFormat == HIFMT_JSON && 169 Filtering != HIFIL_Only_Direct_System)) { 170 TheDriver.Diag(clang::diag::err_drv_print_header_env_var_combination) 171 << EnvVar << FilteringStr; 172 return false; 173 } 174 TheDriver.CCPrintHeadersFiltering = Filtering; 175 } 176 } 177 178 TheDriver.CCLogDiagnostics = 179 checkEnvVar<bool>("CC_LOG_DIAGNOSTICS", "CC_LOG_DIAGNOSTICS_FILE", 180 TheDriver.CCLogDiagnosticsFilename); 181 TheDriver.CCPrintProcessStats = 182 checkEnvVar<bool>("CC_PRINT_PROC_STAT", "CC_PRINT_PROC_STAT_FILE", 183 TheDriver.CCPrintStatReportFilename); 184 TheDriver.CCPrintInternalStats = 185 checkEnvVar<bool>("CC_PRINT_INTERNAL_STAT", "CC_PRINT_INTERNAL_STAT_FILE", 186 TheDriver.CCPrintInternalStatReportFilename); 187 188 return true; 189 } 190 191 static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient, 192 const std::string &Path) { 193 // If the clang binary happens to be named cl.exe for compatibility reasons, 194 // use clang-cl.exe as the prefix to avoid confusion between clang and MSVC. 195 StringRef ExeBasename(llvm::sys::path::stem(Path)); 196 if (ExeBasename.equals_insensitive("cl")) 197 ExeBasename = "clang-cl"; 198 DiagClient->setPrefix(std::string(ExeBasename)); 199 } 200 201 static int ExecuteCC1Tool(SmallVectorImpl<const char *> &ArgV, 202 const llvm::ToolContext &ToolContext) { 203 // If we call the cc1 tool from the clangDriver library (through 204 // Driver::CC1Main), we need to clean up the options usage count. The options 205 // are currently global, and they might have been used previously by the 206 // driver. 207 llvm::cl::ResetAllOptionOccurrences(); 208 209 llvm::BumpPtrAllocator A; 210 llvm::cl::ExpansionContext ECtx(A, llvm::cl::TokenizeGNUCommandLine); 211 if (llvm::Error Err = ECtx.expandResponseFiles(ArgV)) { 212 llvm::errs() << toString(std::move(Err)) << '\n'; 213 return 1; 214 } 215 StringRef Tool = ArgV[1]; 216 void *GetExecutablePathVP = (void *)(intptr_t)GetExecutablePath; 217 if (Tool == "-cc1") 218 return cc1_main(ArrayRef(ArgV).slice(1), ArgV[0], GetExecutablePathVP); 219 if (Tool == "-cc1as") 220 return cc1as_main(ArrayRef(ArgV).slice(2), ArgV[0], GetExecutablePathVP); 221 if (Tool == "-cc1gen-reproducer") 222 return cc1gen_reproducer_main(ArrayRef(ArgV).slice(2), ArgV[0], 223 GetExecutablePathVP, ToolContext); 224 // Reject unknown tools. 225 llvm::errs() 226 << "error: unknown integrated tool '" << Tool << "'. " 227 << "Valid tools include '-cc1', '-cc1as' and '-cc1gen-reproducer'.\n"; 228 return 1; 229 } 230 231 int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) { 232 noteBottomOfStack(); 233 llvm::setBugReportMsg("PLEASE submit a bug report to " BUG_REPORT_URL 234 " and include the crash backtrace, preprocessed " 235 "source, and associated run script.\n"); 236 SmallVector<const char *, 256> Args(Argv, Argv + Argc); 237 238 if (llvm::sys::Process::FixupStandardFileDescriptors()) 239 return 1; 240 241 llvm::InitializeAllTargets(); 242 243 llvm::BumpPtrAllocator A; 244 llvm::StringSaver Saver(A); 245 246 const char *ProgName = 247 ToolContext.NeedsPrependArg ? ToolContext.PrependArg : ToolContext.Path; 248 249 bool ClangCLMode = 250 IsClangCL(getDriverMode(ProgName, llvm::ArrayRef(Args).slice(1))); 251 252 if (llvm::Error Err = expandResponseFiles(Args, ClangCLMode, A)) { 253 llvm::errs() << toString(std::move(Err)) << '\n'; 254 return 1; 255 } 256 257 // Handle -cc1 integrated tools. 258 if (Args.size() >= 2 && StringRef(Args[1]).starts_with("-cc1")) 259 return ExecuteCC1Tool(Args, ToolContext); 260 261 // Handle options that need handling before the real command line parsing in 262 // Driver::BuildCompilation() 263 bool CanonicalPrefixes = true; 264 for (int i = 1, size = Args.size(); i < size; ++i) { 265 // Skip end-of-line response file markers 266 if (Args[i] == nullptr) 267 continue; 268 if (StringRef(Args[i]) == "-canonical-prefixes") 269 CanonicalPrefixes = true; 270 else if (StringRef(Args[i]) == "-no-canonical-prefixes") 271 CanonicalPrefixes = false; 272 } 273 274 // Handle CL and _CL_ which permits additional command line options to be 275 // prepended or appended. 276 if (ClangCLMode) { 277 // Arguments in "CL" are prepended. 278 std::optional<std::string> OptCL = llvm::sys::Process::GetEnv("CL"); 279 if (OptCL) { 280 SmallVector<const char *, 8> PrependedOpts; 281 getCLEnvVarOptions(*OptCL, Saver, PrependedOpts); 282 283 // Insert right after the program name to prepend to the argument list. 284 Args.insert(Args.begin() + 1, PrependedOpts.begin(), PrependedOpts.end()); 285 } 286 // Arguments in "_CL_" are appended. 287 std::optional<std::string> Opt_CL_ = llvm::sys::Process::GetEnv("_CL_"); 288 if (Opt_CL_) { 289 SmallVector<const char *, 8> AppendedOpts; 290 getCLEnvVarOptions(*Opt_CL_, Saver, AppendedOpts); 291 292 // Insert at the end of the argument list to append. 293 Args.append(AppendedOpts.begin(), AppendedOpts.end()); 294 } 295 } 296 297 llvm::StringSet<> SavedStrings; 298 // Handle CCC_OVERRIDE_OPTIONS, used for editing a command line behind the 299 // scenes. 300 if (const char *OverrideStr = ::getenv("CCC_OVERRIDE_OPTIONS")) { 301 // FIXME: Driver shouldn't take extra initial argument. 302 driver::applyOverrideOptions(Args, OverrideStr, SavedStrings, 303 &llvm::errs()); 304 } 305 306 std::string Path = GetExecutablePath(ToolContext.Path, CanonicalPrefixes); 307 308 // Whether the cc1 tool should be called inside the current process, or if we 309 // should spawn a new clang subprocess (old behavior). 310 // Not having an additional process saves some execution time of Windows, 311 // and makes debugging and profiling easier. 312 bool UseNewCC1Process = CLANG_SPAWN_CC1; 313 for (const char *Arg : Args) 314 UseNewCC1Process = llvm::StringSwitch<bool>(Arg) 315 .Case("-fno-integrated-cc1", true) 316 .Case("-fintegrated-cc1", false) 317 .Default(UseNewCC1Process); 318 319 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = 320 CreateAndPopulateDiagOpts(Args); 321 322 TextDiagnosticPrinter *DiagClient 323 = new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); 324 FixupDiagPrefixExeName(DiagClient, ProgName); 325 326 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 327 328 DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient); 329 330 if (!DiagOpts->DiagnosticSerializationFile.empty()) { 331 auto SerializedConsumer = 332 clang::serialized_diags::create(DiagOpts->DiagnosticSerializationFile, 333 &*DiagOpts, /*MergeChildRecords=*/true); 334 Diags.setClient(new ChainedDiagnosticConsumer( 335 Diags.takeClient(), std::move(SerializedConsumer))); 336 } 337 338 auto VFS = llvm::vfs::getRealFileSystem(); 339 ProcessWarningOptions(Diags, *DiagOpts, *VFS, /*ReportDiags=*/false); 340 341 Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags, 342 /*Title=*/"clang LLVM compiler", VFS); 343 auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(ProgName); 344 TheDriver.setTargetAndMode(TargetAndMode); 345 // If -canonical-prefixes is set, GetExecutablePath will have resolved Path 346 // to the llvm driver binary, not clang. In this case, we need to use 347 // PrependArg which should be clang-*. Checking just CanonicalPrefixes is 348 // safe even in the normal case because PrependArg will be null so 349 // setPrependArg will be a no-op. 350 if (ToolContext.NeedsPrependArg || CanonicalPrefixes) 351 TheDriver.setPrependArg(ToolContext.PrependArg); 352 353 insertTargetAndModeArgs(TargetAndMode, Args, SavedStrings); 354 355 if (!SetBackdoorDriverOutputsFromEnvVars(TheDriver)) 356 return 1; 357 358 auto ExecuteCC1WithContext = 359 [&ToolContext](SmallVectorImpl<const char *> &ArgV) { 360 return ExecuteCC1Tool(ArgV, ToolContext); 361 }; 362 if (!UseNewCC1Process) { 363 TheDriver.CC1Main = ExecuteCC1WithContext; 364 // Ensure the CC1Command actually catches cc1 crashes 365 llvm::CrashRecoveryContext::Enable(); 366 } 367 368 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(Args)); 369 370 Driver::ReproLevel ReproLevel = Driver::ReproLevel::OnCrash; 371 if (Arg *A = C->getArgs().getLastArg(options::OPT_gen_reproducer_eq)) { 372 auto Level = 373 llvm::StringSwitch<std::optional<Driver::ReproLevel>>(A->getValue()) 374 .Case("off", Driver::ReproLevel::Off) 375 .Case("crash", Driver::ReproLevel::OnCrash) 376 .Case("error", Driver::ReproLevel::OnError) 377 .Case("always", Driver::ReproLevel::Always) 378 .Default(std::nullopt); 379 if (!Level) { 380 llvm::errs() << "Unknown value for " << A->getSpelling() << ": '" 381 << A->getValue() << "'\n"; 382 return 1; 383 } 384 ReproLevel = *Level; 385 } 386 if (!!::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")) 387 ReproLevel = Driver::ReproLevel::Always; 388 389 int Res = 1; 390 bool IsCrash = false; 391 Driver::CommandStatus CommandStatus = Driver::CommandStatus::Ok; 392 // Pretend the first command failed if ReproStatus is Always. 393 const Command *FailingCommand = nullptr; 394 if (!C->getJobs().empty()) 395 FailingCommand = &*C->getJobs().begin(); 396 if (C && !C->containsError()) { 397 SmallVector<std::pair<int, const Command *>, 4> FailingCommands; 398 Res = TheDriver.ExecuteCompilation(*C, FailingCommands); 399 400 for (const auto &P : FailingCommands) { 401 int CommandRes = P.first; 402 FailingCommand = P.second; 403 if (!Res) 404 Res = CommandRes; 405 406 // If result status is < 0, then the driver command signalled an error. 407 // If result status is 70, then the driver command reported a fatal error. 408 // On Windows, abort will return an exit code of 3. In these cases, 409 // generate additional diagnostic information if possible. 410 IsCrash = CommandRes < 0 || CommandRes == 70; 411 #ifdef _WIN32 412 IsCrash |= CommandRes == 3; 413 #endif 414 #if LLVM_ON_UNIX 415 // When running in integrated-cc1 mode, the CrashRecoveryContext returns 416 // the same codes as if the program crashed. See section "Exit Status for 417 // Commands": 418 // https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html 419 IsCrash |= CommandRes > 128; 420 #endif 421 CommandStatus = 422 IsCrash ? Driver::CommandStatus::Crash : Driver::CommandStatus::Error; 423 if (IsCrash) 424 break; 425 } 426 } 427 428 // Print the bug report message that would be printed if we did actually 429 // crash, but only if we're crashing due to FORCE_CLANG_DIAGNOSTICS_CRASH. 430 if (::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")) 431 llvm::dbgs() << llvm::getBugReportMsg(); 432 if (FailingCommand != nullptr && 433 TheDriver.maybeGenerateCompilationDiagnostics(CommandStatus, ReproLevel, 434 *C, *FailingCommand)) 435 Res = 1; 436 437 Diags.getClient()->finish(); 438 439 if (!UseNewCC1Process && IsCrash) { 440 // When crashing in -fintegrated-cc1 mode, bury the timer pointers, because 441 // the internal linked list might point to already released stack frames. 442 llvm::BuryPointer(llvm::TimerGroup::acquireTimerGlobals()); 443 } else { 444 // If any timers were active but haven't been destroyed yet, print their 445 // results now. This happens in -disable-free mode. 446 llvm::TimerGroup::printAll(llvm::errs()); 447 llvm::TimerGroup::clearAll(); 448 } 449 450 #ifdef _WIN32 451 // Exit status should not be negative on Win32, unless abnormal termination. 452 // Once abnormal termination was caught, negative status should not be 453 // propagated. 454 if (Res < 0) 455 Res = 1; 456 #endif 457 458 // If we have multiple failing commands, we return the result of the first 459 // failing command. 460 return Res; 461 } 462