1 //===--- FreeBSD.cpp - FreeBSD 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 "FreeBSD.h" 10 #include "Arch/ARM.h" 11 #include "Arch/Mips.h" 12 #include "Arch/Sparc.h" 13 #include "CommonArgs.h" 14 #include "clang/Config/config.h" 15 #include "clang/Driver/Compilation.h" 16 #include "clang/Driver/DriverDiagnostic.h" 17 #include "clang/Driver/Options.h" 18 #include "clang/Driver/SanitizerArgs.h" 19 #include "llvm/Option/ArgList.h" 20 #include "llvm/Support/VirtualFileSystem.h" 21 22 using namespace clang::driver; 23 using namespace clang::driver::tools; 24 using namespace clang::driver::toolchains; 25 using namespace clang; 26 using namespace llvm::opt; 27 28 void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA, 29 const InputInfo &Output, 30 const InputInfoList &Inputs, 31 const ArgList &Args, 32 const char *LinkingOutput) const { 33 claimNoWarnArgs(Args); 34 ArgStringList CmdArgs; 35 const auto &D = getToolChain().getDriver(); 36 37 // When building 32-bit code on FreeBSD/amd64, we have to explicitly 38 // instruct as in the base system to assemble 32-bit code. 39 switch (getToolChain().getArch()) { 40 default: 41 break; 42 case llvm::Triple::x86: 43 CmdArgs.push_back("--32"); 44 break; 45 case llvm::Triple::ppc: 46 case llvm::Triple::ppcle: 47 CmdArgs.push_back("-a32"); 48 break; 49 case llvm::Triple::mips: 50 case llvm::Triple::mipsel: 51 case llvm::Triple::mips64: 52 case llvm::Triple::mips64el: { 53 StringRef CPUName; 54 StringRef ABIName; 55 mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); 56 57 CmdArgs.push_back("-march"); 58 CmdArgs.push_back(CPUName.data()); 59 60 CmdArgs.push_back("-mabi"); 61 CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data()); 62 63 if (getToolChain().getTriple().isLittleEndian()) 64 CmdArgs.push_back("-EL"); 65 else 66 CmdArgs.push_back("-EB"); 67 68 if (Arg *A = Args.getLastArg(options::OPT_G)) { 69 StringRef v = A->getValue(); 70 CmdArgs.push_back(Args.MakeArgString("-G" + v)); 71 A->claim(); 72 } 73 74 AddAssemblerKPIC(getToolChain(), Args, CmdArgs); 75 break; 76 } 77 case llvm::Triple::arm: 78 case llvm::Triple::armeb: 79 case llvm::Triple::thumb: 80 case llvm::Triple::thumbeb: { 81 arm::FloatABI ABI = arm::getARMFloatABI(getToolChain(), Args); 82 83 if (ABI == arm::FloatABI::Hard) 84 CmdArgs.push_back("-mfpu=vfp"); 85 else 86 CmdArgs.push_back("-mfpu=softvfp"); 87 88 switch (getToolChain().getTriple().getEnvironment()) { 89 case llvm::Triple::GNUEABIHF: 90 case llvm::Triple::GNUEABI: 91 case llvm::Triple::EABI: 92 CmdArgs.push_back("-meabi=5"); 93 break; 94 95 default: 96 CmdArgs.push_back("-matpcs"); 97 } 98 break; 99 } 100 case llvm::Triple::sparc: 101 case llvm::Triple::sparcel: 102 case llvm::Triple::sparcv9: { 103 std::string CPU = getCPUName(D, Args, getToolChain().getTriple()); 104 CmdArgs.push_back( 105 sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); 106 AddAssemblerKPIC(getToolChain(), Args, CmdArgs); 107 break; 108 } 109 } 110 111 for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ, 112 options::OPT_fdebug_prefix_map_EQ)) { 113 StringRef Map = A->getValue(); 114 if (!Map.contains('=')) 115 D.Diag(diag::err_drv_invalid_argument_to_option) 116 << Map << A->getOption().getName(); 117 else { 118 CmdArgs.push_back(Args.MakeArgString("--debug-prefix-map")); 119 CmdArgs.push_back(Args.MakeArgString(Map)); 120 } 121 A->claim(); 122 } 123 124 Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); 125 126 CmdArgs.push_back("-o"); 127 CmdArgs.push_back(Output.getFilename()); 128 129 for (const auto &II : Inputs) 130 CmdArgs.push_back(II.getFilename()); 131 132 const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); 133 C.addCommand(std::make_unique<Command>(JA, *this, 134 ResponseFileSupport::AtFileCurCP(), 135 Exec, CmdArgs, Inputs, Output)); 136 } 137 138 void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, 139 const InputInfo &Output, 140 const InputInfoList &Inputs, 141 const ArgList &Args, 142 const char *LinkingOutput) const { 143 const toolchains::FreeBSD &ToolChain = 144 static_cast<const toolchains::FreeBSD &>(getToolChain()); 145 const Driver &D = ToolChain.getDriver(); 146 const llvm::Triple::ArchType Arch = ToolChain.getArch(); 147 const bool IsPIE = 148 !Args.hasArg(options::OPT_shared) && 149 (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault(Args)); 150 ArgStringList CmdArgs; 151 152 // Silence warning for "clang -g foo.o -o foo" 153 Args.ClaimAllArgs(options::OPT_g_Group); 154 // and "clang -emit-llvm foo.o -o foo" 155 Args.ClaimAllArgs(options::OPT_emit_llvm); 156 // and for "clang -w foo.o -o foo". Other warning options are already 157 // handled somewhere else. 158 Args.ClaimAllArgs(options::OPT_w); 159 160 if (!D.SysRoot.empty()) 161 CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); 162 163 if (IsPIE) 164 CmdArgs.push_back("-pie"); 165 166 CmdArgs.push_back("--eh-frame-hdr"); 167 if (Args.hasArg(options::OPT_static)) { 168 CmdArgs.push_back("-Bstatic"); 169 } else { 170 if (Args.hasArg(options::OPT_rdynamic)) 171 CmdArgs.push_back("-export-dynamic"); 172 if (Args.hasArg(options::OPT_shared)) { 173 CmdArgs.push_back("-Bshareable"); 174 } else if (!Args.hasArg(options::OPT_r)) { 175 CmdArgs.push_back("-dynamic-linker"); 176 CmdArgs.push_back("/libexec/ld-elf.so.1"); 177 } 178 const llvm::Triple &T = ToolChain.getTriple(); 179 if (T.getOSMajorVersion() >= 9) { 180 if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc || T.isX86()) 181 CmdArgs.push_back("--hash-style=both"); 182 } 183 CmdArgs.push_back("--enable-new-dtags"); 184 } 185 186 // Explicitly set the linker emulation for platforms that might not 187 // be the default emulation for the linker. 188 switch (Arch) { 189 case llvm::Triple::x86: 190 CmdArgs.push_back("-m"); 191 CmdArgs.push_back("elf_i386_fbsd"); 192 break; 193 case llvm::Triple::ppc: 194 CmdArgs.push_back("-m"); 195 CmdArgs.push_back("elf32ppc_fbsd"); 196 break; 197 case llvm::Triple::ppcle: 198 CmdArgs.push_back("-m"); 199 // Use generic -- only usage is for freestanding. 200 CmdArgs.push_back("elf32lppc"); 201 break; 202 case llvm::Triple::mips: 203 CmdArgs.push_back("-m"); 204 CmdArgs.push_back("elf32btsmip_fbsd"); 205 break; 206 case llvm::Triple::mipsel: 207 CmdArgs.push_back("-m"); 208 CmdArgs.push_back("elf32ltsmip_fbsd"); 209 break; 210 case llvm::Triple::mips64: 211 CmdArgs.push_back("-m"); 212 if (tools::mips::hasMipsAbiArg(Args, "n32")) 213 CmdArgs.push_back("elf32btsmipn32_fbsd"); 214 else 215 CmdArgs.push_back("elf64btsmip_fbsd"); 216 break; 217 case llvm::Triple::mips64el: 218 CmdArgs.push_back("-m"); 219 if (tools::mips::hasMipsAbiArg(Args, "n32")) 220 CmdArgs.push_back("elf32ltsmipn32_fbsd"); 221 else 222 CmdArgs.push_back("elf64ltsmip_fbsd"); 223 break; 224 case llvm::Triple::riscv32: 225 CmdArgs.push_back("-m"); 226 CmdArgs.push_back("elf32lriscv"); 227 CmdArgs.push_back("-X"); 228 break; 229 case llvm::Triple::riscv64: 230 CmdArgs.push_back("-m"); 231 CmdArgs.push_back("elf64lriscv"); 232 CmdArgs.push_back("-X"); 233 break; 234 default: 235 break; 236 } 237 238 if (Arg *A = Args.getLastArg(options::OPT_G)) { 239 if (ToolChain.getTriple().isMIPS()) { 240 StringRef v = A->getValue(); 241 CmdArgs.push_back(Args.MakeArgString("-G" + v)); 242 A->claim(); 243 } 244 } 245 246 if (Output.isFilename()) { 247 CmdArgs.push_back("-o"); 248 CmdArgs.push_back(Output.getFilename()); 249 } else { 250 assert(Output.isNothing() && "Invalid output."); 251 } 252 253 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, 254 options::OPT_r)) { 255 const char *crt1 = nullptr; 256 if (!Args.hasArg(options::OPT_shared)) { 257 if (Args.hasArg(options::OPT_pg)) 258 crt1 = "gcrt1.o"; 259 else if (IsPIE) 260 crt1 = "Scrt1.o"; 261 else 262 crt1 = "crt1.o"; 263 } 264 if (crt1) 265 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1))); 266 267 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o"))); 268 269 const char *crtbegin = nullptr; 270 if (Args.hasArg(options::OPT_static)) 271 crtbegin = "crtbeginT.o"; 272 else if (Args.hasArg(options::OPT_shared) || IsPIE) 273 crtbegin = "crtbeginS.o"; 274 else 275 crtbegin = "crtbegin.o"; 276 277 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin))); 278 } 279 280 Args.AddAllArgs(CmdArgs, options::OPT_L); 281 ToolChain.AddFilePathLibArgs(Args, CmdArgs); 282 Args.AddAllArgs(CmdArgs, options::OPT_T_Group); 283 Args.AddAllArgs(CmdArgs, options::OPT_e); 284 Args.AddAllArgs(CmdArgs, options::OPT_s); 285 Args.AddAllArgs(CmdArgs, options::OPT_t); 286 Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag); 287 Args.AddAllArgs(CmdArgs, options::OPT_r); 288 289 if (D.isUsingLTO()) { 290 assert(!Inputs.empty() && "Must have at least one input."); 291 addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0], 292 D.getLTOMode() == LTOK_Thin); 293 } 294 295 bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs); 296 bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); 297 addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs); 298 AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); 299 300 unsigned Major = ToolChain.getTriple().getOSMajorVersion(); 301 bool Profiling = Args.hasArg(options::OPT_pg) && Major != 0 && Major < 14; 302 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, 303 options::OPT_r)) { 304 // Use the static OpenMP runtime with -static-openmp 305 bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && 306 !Args.hasArg(options::OPT_static); 307 addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP); 308 309 if (D.CCCIsCXX()) { 310 if (ToolChain.ShouldLinkCXXStdlib(Args)) 311 ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); 312 if (Profiling) 313 CmdArgs.push_back("-lm_p"); 314 else 315 CmdArgs.push_back("-lm"); 316 } 317 if (NeedsSanitizerDeps) 318 linkSanitizerRuntimeDeps(ToolChain, CmdArgs); 319 if (NeedsXRayDeps) 320 linkXRayRuntimeDeps(ToolChain, CmdArgs); 321 // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding 322 // the default system libraries. Just mimic this for now. 323 if (Profiling) 324 CmdArgs.push_back("-lgcc_p"); 325 else 326 CmdArgs.push_back("-lgcc"); 327 if (Args.hasArg(options::OPT_static)) { 328 CmdArgs.push_back("-lgcc_eh"); 329 } else if (Profiling) { 330 CmdArgs.push_back("-lgcc_eh_p"); 331 } else { 332 CmdArgs.push_back("--as-needed"); 333 CmdArgs.push_back("-lgcc_s"); 334 CmdArgs.push_back("--no-as-needed"); 335 } 336 337 if (Args.hasArg(options::OPT_pthread)) { 338 if (Profiling) 339 CmdArgs.push_back("-lpthread_p"); 340 else 341 CmdArgs.push_back("-lpthread"); 342 } 343 344 if (Profiling) { 345 if (Args.hasArg(options::OPT_shared)) 346 CmdArgs.push_back("-lc"); 347 else 348 CmdArgs.push_back("-lc_p"); 349 CmdArgs.push_back("-lgcc_p"); 350 } else { 351 CmdArgs.push_back("-lc"); 352 CmdArgs.push_back("-lgcc"); 353 } 354 355 if (Args.hasArg(options::OPT_static)) { 356 CmdArgs.push_back("-lgcc_eh"); 357 } else if (Profiling) { 358 CmdArgs.push_back("-lgcc_eh_p"); 359 } else { 360 CmdArgs.push_back("--as-needed"); 361 CmdArgs.push_back("-lgcc_s"); 362 CmdArgs.push_back("--no-as-needed"); 363 } 364 } 365 366 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, 367 options::OPT_r)) { 368 if (Args.hasArg(options::OPT_shared) || IsPIE) 369 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o"))); 370 else 371 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); 372 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); 373 } 374 375 ToolChain.addProfileRTLibs(Args, CmdArgs); 376 377 const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); 378 C.addCommand(std::make_unique<Command>(JA, *this, 379 ResponseFileSupport::AtFileCurCP(), 380 Exec, CmdArgs, Inputs, Output)); 381 } 382 383 /// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly. 384 385 FreeBSD::FreeBSD(const Driver &D, const llvm::Triple &Triple, 386 const ArgList &Args) 387 : Generic_ELF(D, Triple, Args) { 388 389 // When targeting 32-bit platforms, look for '/usr/lib32/crt1.o' and fall 390 // back to '/usr/lib' if it doesn't exist. 391 if ((Triple.getArch() == llvm::Triple::x86 || Triple.isMIPS32() || 392 Triple.isPPC32()) && 393 D.getVFS().exists(concat(getDriver().SysRoot, "/usr/lib32/crt1.o"))) 394 getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib32")); 395 else 396 getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib")); 397 } 398 399 ToolChain::CXXStdlibType FreeBSD::GetDefaultCXXStdlibType() const { 400 unsigned Major = getTriple().getOSMajorVersion(); 401 if (Major >= 10 || Major == 0) 402 return ToolChain::CST_Libcxx; 403 return ToolChain::CST_Libstdcxx; 404 } 405 406 unsigned FreeBSD::GetDefaultDwarfVersion() const { 407 if (getTriple().getOSMajorVersion() < 12) 408 return 2; 409 return 4; 410 } 411 412 void FreeBSD::AddClangSystemIncludeArgs( 413 const llvm::opt::ArgList &DriverArgs, 414 llvm::opt::ArgStringList &CC1Args) const { 415 const Driver &D = getDriver(); 416 417 if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc)) 418 return; 419 420 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 421 SmallString<128> Dir(D.ResourceDir); 422 llvm::sys::path::append(Dir, "include"); 423 addSystemInclude(DriverArgs, CC1Args, Dir.str()); 424 } 425 426 if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 427 return; 428 429 // Check for configure-time C include directories. 430 StringRef CIncludeDirs(C_INCLUDE_DIRS); 431 if (CIncludeDirs != "") { 432 SmallVector<StringRef, 5> dirs; 433 CIncludeDirs.split(dirs, ":"); 434 for (StringRef dir : dirs) { 435 StringRef Prefix = 436 llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : ""; 437 addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir); 438 } 439 return; 440 } 441 442 addExternCSystemInclude(DriverArgs, CC1Args, 443 concat(D.SysRoot, "/usr/include")); 444 } 445 446 void FreeBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, 447 llvm::opt::ArgStringList &CC1Args) const { 448 addSystemInclude(DriverArgs, CC1Args, 449 concat(getDriver().SysRoot, "/usr/include/c++/v1")); 450 } 451 452 void FreeBSD::addLibStdCxxIncludePaths( 453 const llvm::opt::ArgList &DriverArgs, 454 llvm::opt::ArgStringList &CC1Args) const { 455 addLibStdCXXIncludePaths(concat(getDriver().SysRoot, "/usr/include/c++/4.2"), 456 "", "", DriverArgs, CC1Args); 457 } 458 459 void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args, 460 ArgStringList &CmdArgs) const { 461 CXXStdlibType Type = GetCXXStdlibType(Args); 462 unsigned Major = getTriple().getOSMajorVersion(); 463 bool Profiling = Args.hasArg(options::OPT_pg) && Major != 0 && Major < 14; 464 465 switch (Type) { 466 case ToolChain::CST_Libcxx: 467 CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++"); 468 if (Args.hasArg(options::OPT_fexperimental_library)) 469 CmdArgs.push_back("-lc++experimental"); 470 break; 471 472 case ToolChain::CST_Libstdcxx: 473 CmdArgs.push_back(Profiling ? "-lstdc++_p" : "-lstdc++"); 474 break; 475 } 476 } 477 478 void FreeBSD::AddCudaIncludeArgs(const ArgList &DriverArgs, 479 ArgStringList &CC1Args) const { 480 CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); 481 } 482 483 void FreeBSD::AddHIPIncludeArgs(const ArgList &DriverArgs, 484 ArgStringList &CC1Args) const { 485 RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args); 486 } 487 488 Tool *FreeBSD::buildAssembler() const { 489 return new tools::freebsd::Assembler(*this); 490 } 491 492 Tool *FreeBSD::buildLinker() const { return new tools::freebsd::Linker(*this); } 493 494 llvm::ExceptionHandling FreeBSD::GetExceptionModel(const ArgList &Args) const { 495 // FreeBSD uses SjLj exceptions on ARM oabi. 496 switch (getTriple().getEnvironment()) { 497 case llvm::Triple::GNUEABIHF: 498 case llvm::Triple::GNUEABI: 499 case llvm::Triple::EABI: 500 return llvm::ExceptionHandling::None; 501 default: 502 if (getTriple().getArch() == llvm::Triple::arm || 503 getTriple().getArch() == llvm::Triple::thumb) 504 return llvm::ExceptionHandling::SjLj; 505 return llvm::ExceptionHandling::None; 506 } 507 } 508 509 bool FreeBSD::HasNativeLLVMSupport() const { return true; } 510 511 ToolChain::UnwindTableLevel 512 FreeBSD::getDefaultUnwindTableLevel(const ArgList &Args) const { 513 return UnwindTableLevel::Asynchronous; 514 } 515 516 bool FreeBSD::isPIEDefault(const llvm::opt::ArgList &Args) const { 517 return getSanitizerArgs(Args).requiresPIE(); 518 } 519 520 SanitizerMask FreeBSD::getSupportedSanitizers() const { 521 const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64; 522 const bool IsX86 = getTriple().getArch() == llvm::Triple::x86; 523 const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; 524 const bool IsMIPS64 = getTriple().isMIPS64(); 525 SanitizerMask Res = ToolChain::getSupportedSanitizers(); 526 Res |= SanitizerKind::Address; 527 Res |= SanitizerKind::PointerCompare; 528 Res |= SanitizerKind::PointerSubtract; 529 Res |= SanitizerKind::Vptr; 530 if (IsAArch64 || IsX86_64 || IsMIPS64) { 531 Res |= SanitizerKind::Leak; 532 Res |= SanitizerKind::Thread; 533 } 534 if (IsX86 || IsX86_64) { 535 Res |= SanitizerKind::Function; 536 } 537 if (IsAArch64 || IsX86 || IsX86_64) { 538 Res |= SanitizerKind::SafeStack; 539 Res |= SanitizerKind::Fuzzer; 540 Res |= SanitizerKind::FuzzerNoLink; 541 } 542 if (IsAArch64 || IsX86_64) { 543 Res |= SanitizerKind::KernelAddress; 544 Res |= SanitizerKind::KernelMemory; 545 Res |= SanitizerKind::Memory; 546 } 547 return Res; 548 } 549 550 void FreeBSD::addClangTargetOptions(const ArgList &DriverArgs, 551 ArgStringList &CC1Args, 552 Action::OffloadKind) const { 553 if (!DriverArgs.hasFlag(options::OPT_fuse_init_array, 554 options::OPT_fno_use_init_array, 555 getTriple().getOSMajorVersion() >= 12)) 556 CC1Args.push_back("-fno-use-init-array"); 557 } 558