1 //===--- NetBSD.cpp - NetBSD 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 "NetBSD.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/Driver.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 netbsd::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 const toolchains::NetBSD &ToolChain = 34 static_cast<const toolchains::NetBSD &>(getToolChain()); 35 const Driver &D = ToolChain.getDriver(); 36 const llvm::Triple &Triple = ToolChain.getTriple(); 37 38 claimNoWarnArgs(Args); 39 ArgStringList CmdArgs; 40 41 // GNU as needs different flags for creating the correct output format 42 // on architectures with different ABIs or optional feature sets. 43 switch (ToolChain.getArch()) { 44 case llvm::Triple::x86: 45 CmdArgs.push_back("--32"); 46 break; 47 case llvm::Triple::arm: 48 case llvm::Triple::armeb: 49 case llvm::Triple::thumb: 50 case llvm::Triple::thumbeb: { 51 StringRef MArch, MCPU; 52 arm::getARMArchCPUFromArgs(Args, MArch, MCPU, /*FromAs*/ true); 53 std::string Arch = arm::getARMTargetCPU(MCPU, MArch, Triple); 54 CmdArgs.push_back(Args.MakeArgString("-mcpu=" + Arch)); 55 break; 56 } 57 58 case llvm::Triple::mips: 59 case llvm::Triple::mipsel: 60 case llvm::Triple::mips64: 61 case llvm::Triple::mips64el: { 62 StringRef CPUName; 63 StringRef ABIName; 64 mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); 65 66 CmdArgs.push_back("-march"); 67 CmdArgs.push_back(CPUName.data()); 68 69 CmdArgs.push_back("-mabi"); 70 CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data()); 71 72 if (Triple.isLittleEndian()) 73 CmdArgs.push_back("-EL"); 74 else 75 CmdArgs.push_back("-EB"); 76 77 AddAssemblerKPIC(ToolChain, Args, CmdArgs); 78 break; 79 } 80 81 case llvm::Triple::sparc: 82 case llvm::Triple::sparcel: { 83 CmdArgs.push_back("-32"); 84 std::string CPU = getCPUName(D, Args, Triple); 85 CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, Triple)); 86 AddAssemblerKPIC(ToolChain, Args, CmdArgs); 87 break; 88 } 89 90 case llvm::Triple::sparcv9: { 91 CmdArgs.push_back("-64"); 92 std::string CPU = getCPUName(D, Args, Triple); 93 CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, Triple)); 94 AddAssemblerKPIC(ToolChain, Args, CmdArgs); 95 break; 96 } 97 98 default: 99 break; 100 } 101 102 Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); 103 104 CmdArgs.push_back("-o"); 105 CmdArgs.push_back(Output.getFilename()); 106 107 for (const auto &II : Inputs) 108 CmdArgs.push_back(II.getFilename()); 109 110 const char *Exec = Args.MakeArgString((ToolChain.GetProgramPath("as"))); 111 C.addCommand(std::make_unique<Command>(JA, *this, 112 ResponseFileSupport::AtFileCurCP(), 113 Exec, CmdArgs, Inputs, Output)); 114 } 115 116 void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, 117 const InputInfo &Output, 118 const InputInfoList &Inputs, 119 const ArgList &Args, 120 const char *LinkingOutput) const { 121 const toolchains::NetBSD &ToolChain = 122 static_cast<const toolchains::NetBSD &>(getToolChain()); 123 const Driver &D = ToolChain.getDriver(); 124 const llvm::Triple &Triple = ToolChain.getTriple(); 125 126 ArgStringList CmdArgs; 127 128 if (!D.SysRoot.empty()) 129 CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); 130 131 CmdArgs.push_back("--eh-frame-hdr"); 132 if (Args.hasArg(options::OPT_static)) { 133 CmdArgs.push_back("-Bstatic"); 134 if (Args.hasArg(options::OPT_pie)) { 135 Args.AddAllArgs(CmdArgs, options::OPT_pie); 136 CmdArgs.push_back("--no-dynamic-linker"); 137 } 138 } else { 139 if (Args.hasArg(options::OPT_rdynamic)) 140 CmdArgs.push_back("-export-dynamic"); 141 if (Args.hasArg(options::OPT_shared)) { 142 CmdArgs.push_back("-Bshareable"); 143 } else if (!Args.hasArg(options::OPT_r)) { 144 Args.AddAllArgs(CmdArgs, options::OPT_pie); 145 CmdArgs.push_back("-dynamic-linker"); 146 CmdArgs.push_back("/libexec/ld.elf_so"); 147 } 148 } 149 150 // Many NetBSD architectures support more than one ABI. 151 // Determine the correct emulation for ld. 152 switch (ToolChain.getArch()) { 153 case llvm::Triple::x86: 154 CmdArgs.push_back("-m"); 155 CmdArgs.push_back("elf_i386"); 156 break; 157 case llvm::Triple::arm: 158 case llvm::Triple::thumb: 159 CmdArgs.push_back("-m"); 160 switch (Triple.getEnvironment()) { 161 case llvm::Triple::EABI: 162 case llvm::Triple::GNUEABI: 163 CmdArgs.push_back("armelf_nbsd_eabi"); 164 break; 165 case llvm::Triple::EABIHF: 166 case llvm::Triple::GNUEABIHF: 167 CmdArgs.push_back("armelf_nbsd_eabihf"); 168 break; 169 default: 170 CmdArgs.push_back("armelf_nbsd"); 171 break; 172 } 173 break; 174 case llvm::Triple::armeb: 175 case llvm::Triple::thumbeb: 176 arm::appendBE8LinkFlag(Args, CmdArgs, ToolChain.getEffectiveTriple()); 177 CmdArgs.push_back("-m"); 178 switch (Triple.getEnvironment()) { 179 case llvm::Triple::EABI: 180 case llvm::Triple::GNUEABI: 181 CmdArgs.push_back("armelfb_nbsd_eabi"); 182 break; 183 case llvm::Triple::EABIHF: 184 case llvm::Triple::GNUEABIHF: 185 CmdArgs.push_back("armelfb_nbsd_eabihf"); 186 break; 187 default: 188 CmdArgs.push_back("armelfb_nbsd"); 189 break; 190 } 191 break; 192 case llvm::Triple::mips64: 193 case llvm::Triple::mips64el: 194 if (mips::hasMipsAbiArg(Args, "32")) { 195 CmdArgs.push_back("-m"); 196 if (ToolChain.getArch() == llvm::Triple::mips64) 197 CmdArgs.push_back("elf32btsmip"); 198 else 199 CmdArgs.push_back("elf32ltsmip"); 200 } else if (mips::hasMipsAbiArg(Args, "64")) { 201 CmdArgs.push_back("-m"); 202 if (ToolChain.getArch() == llvm::Triple::mips64) 203 CmdArgs.push_back("elf64btsmip"); 204 else 205 CmdArgs.push_back("elf64ltsmip"); 206 } 207 break; 208 case llvm::Triple::ppc: 209 CmdArgs.push_back("-m"); 210 CmdArgs.push_back("elf32ppc_nbsd"); 211 break; 212 213 case llvm::Triple::ppc64: 214 case llvm::Triple::ppc64le: 215 CmdArgs.push_back("-m"); 216 CmdArgs.push_back("elf64ppc"); 217 break; 218 219 case llvm::Triple::sparc: 220 CmdArgs.push_back("-m"); 221 CmdArgs.push_back("elf32_sparc"); 222 break; 223 224 case llvm::Triple::sparcv9: 225 CmdArgs.push_back("-m"); 226 CmdArgs.push_back("elf64_sparc"); 227 break; 228 229 default: 230 break; 231 } 232 233 if (Output.isFilename()) { 234 CmdArgs.push_back("-o"); 235 CmdArgs.push_back(Output.getFilename()); 236 } else { 237 assert(Output.isNothing() && "Invalid output."); 238 } 239 240 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, 241 options::OPT_r)) { 242 if (!Args.hasArg(options::OPT_shared)) { 243 CmdArgs.push_back( 244 Args.MakeArgString(ToolChain.GetFilePath("crt0.o"))); 245 } 246 CmdArgs.push_back( 247 Args.MakeArgString(ToolChain.GetFilePath("crti.o"))); 248 if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) { 249 CmdArgs.push_back( 250 Args.MakeArgString(ToolChain.GetFilePath("crtbeginS.o"))); 251 } else { 252 CmdArgs.push_back( 253 Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o"))); 254 } 255 } 256 257 Args.AddAllArgs(CmdArgs, options::OPT_L); 258 Args.AddAllArgs(CmdArgs, options::OPT_T_Group); 259 Args.AddAllArgs(CmdArgs, options::OPT_s); 260 Args.AddAllArgs(CmdArgs, options::OPT_t); 261 Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag); 262 Args.AddAllArgs(CmdArgs, options::OPT_r); 263 264 bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs); 265 bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); 266 AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); 267 268 const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(Args); 269 if (SanArgs.needsSharedRt()) { 270 CmdArgs.push_back("-rpath"); 271 CmdArgs.push_back(Args.MakeArgString(ToolChain.getCompilerRTPath())); 272 } 273 274 bool useLibgcc = true; 275 switch (ToolChain.getArch()) { 276 case llvm::Triple::aarch64: 277 case llvm::Triple::aarch64_be: 278 case llvm::Triple::arm: 279 case llvm::Triple::armeb: 280 case llvm::Triple::thumb: 281 case llvm::Triple::thumbeb: 282 case llvm::Triple::ppc: 283 case llvm::Triple::ppc64: 284 case llvm::Triple::ppc64le: 285 case llvm::Triple::sparc: 286 case llvm::Triple::sparcv9: 287 case llvm::Triple::x86: 288 case llvm::Triple::x86_64: 289 useLibgcc = false; 290 break; 291 default: 292 break; 293 } 294 295 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, 296 options::OPT_r)) { 297 // Use the static OpenMP runtime with -static-openmp 298 bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && 299 !Args.hasArg(options::OPT_static); 300 addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP); 301 302 if (D.CCCIsCXX()) { 303 if (ToolChain.ShouldLinkCXXStdlib(Args)) 304 ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); 305 CmdArgs.push_back("-lm"); 306 } 307 if (NeedsSanitizerDeps) 308 linkSanitizerRuntimeDeps(ToolChain, CmdArgs); 309 if (NeedsXRayDeps) 310 linkXRayRuntimeDeps(ToolChain, CmdArgs); 311 if (Args.hasArg(options::OPT_pthread)) 312 CmdArgs.push_back("-lpthread"); 313 CmdArgs.push_back("-lc"); 314 315 if (useLibgcc) { 316 if (Args.hasArg(options::OPT_static)) { 317 // libgcc_eh depends on libc, so resolve as much as possible, 318 // pull in any new requirements from libc and then get the rest 319 // of libgcc. 320 CmdArgs.push_back("-lgcc_eh"); 321 CmdArgs.push_back("-lc"); 322 CmdArgs.push_back("-lgcc"); 323 } else { 324 CmdArgs.push_back("-lgcc"); 325 CmdArgs.push_back("--as-needed"); 326 CmdArgs.push_back("-lgcc_s"); 327 CmdArgs.push_back("--no-as-needed"); 328 } 329 } 330 } 331 332 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, 333 options::OPT_r)) { 334 if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) 335 CmdArgs.push_back( 336 Args.MakeArgString(ToolChain.GetFilePath("crtendS.o"))); 337 else 338 CmdArgs.push_back( 339 Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); 340 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); 341 } 342 343 ToolChain.addProfileRTLibs(Args, CmdArgs); 344 345 const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); 346 C.addCommand(std::make_unique<Command>(JA, *this, 347 ResponseFileSupport::AtFileCurCP(), 348 Exec, CmdArgs, Inputs, Output)); 349 } 350 351 /// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly. 352 353 NetBSD::NetBSD(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) 354 : Generic_ELF(D, Triple, Args) { 355 if (!Args.hasArg(options::OPT_nostdlib)) { 356 // When targeting a 32-bit platform, try the special directory used on 357 // 64-bit hosts, and only fall back to the main library directory if that 358 // doesn't work. 359 // FIXME: It'd be nicer to test if this directory exists, but I'm not sure 360 // what all logic is needed to emulate the '=' prefix here. 361 switch (Triple.getArch()) { 362 case llvm::Triple::x86: 363 getFilePaths().push_back("=/usr/lib/i386"); 364 break; 365 case llvm::Triple::arm: 366 case llvm::Triple::armeb: 367 case llvm::Triple::thumb: 368 case llvm::Triple::thumbeb: 369 switch (Triple.getEnvironment()) { 370 case llvm::Triple::EABI: 371 case llvm::Triple::GNUEABI: 372 getFilePaths().push_back("=/usr/lib/eabi"); 373 break; 374 case llvm::Triple::EABIHF: 375 case llvm::Triple::GNUEABIHF: 376 getFilePaths().push_back("=/usr/lib/eabihf"); 377 break; 378 default: 379 getFilePaths().push_back("=/usr/lib/oabi"); 380 break; 381 } 382 break; 383 case llvm::Triple::mips64: 384 case llvm::Triple::mips64el: 385 if (tools::mips::hasMipsAbiArg(Args, "o32")) 386 getFilePaths().push_back("=/usr/lib/o32"); 387 else if (tools::mips::hasMipsAbiArg(Args, "64")) 388 getFilePaths().push_back("=/usr/lib/64"); 389 break; 390 case llvm::Triple::ppc: 391 getFilePaths().push_back("=/usr/lib/powerpc"); 392 break; 393 case llvm::Triple::sparc: 394 getFilePaths().push_back("=/usr/lib/sparc"); 395 break; 396 default: 397 break; 398 } 399 400 getFilePaths().push_back("=/usr/lib"); 401 } 402 } 403 404 Tool *NetBSD::buildAssembler() const { 405 return new tools::netbsd::Assembler(*this); 406 } 407 408 Tool *NetBSD::buildLinker() const { return new tools::netbsd::Linker(*this); } 409 410 ToolChain::CXXStdlibType NetBSD::GetDefaultCXXStdlibType() const { 411 switch (getArch()) { 412 case llvm::Triple::aarch64: 413 case llvm::Triple::aarch64_be: 414 case llvm::Triple::arm: 415 case llvm::Triple::armeb: 416 case llvm::Triple::thumb: 417 case llvm::Triple::thumbeb: 418 case llvm::Triple::ppc: 419 case llvm::Triple::ppc64: 420 case llvm::Triple::ppc64le: 421 case llvm::Triple::sparc: 422 case llvm::Triple::sparcv9: 423 case llvm::Triple::x86: 424 case llvm::Triple::x86_64: 425 return ToolChain::CST_Libcxx; 426 default: 427 break; 428 } 429 return ToolChain::CST_Libstdcxx; 430 } 431 432 void NetBSD::AddClangSystemIncludeArgs( 433 const llvm::opt::ArgList &DriverArgs, 434 llvm::opt::ArgStringList &CC1Args) const { 435 const Driver &D = getDriver(); 436 437 if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc)) 438 return; 439 440 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 441 SmallString<128> Dir(D.ResourceDir); 442 llvm::sys::path::append(Dir, "include"); 443 addSystemInclude(DriverArgs, CC1Args, Dir.str()); 444 } 445 446 if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 447 return; 448 449 // Check for configure-time C include directories. 450 StringRef CIncludeDirs(C_INCLUDE_DIRS); 451 if (CIncludeDirs != "") { 452 SmallVector<StringRef, 5> dirs; 453 CIncludeDirs.split(dirs, ":"); 454 for (StringRef dir : dirs) { 455 StringRef Prefix = 456 llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : ""; 457 addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir); 458 } 459 return; 460 } 461 462 addExternCSystemInclude(DriverArgs, CC1Args, 463 concat(D.SysRoot, "/usr/include")); 464 } 465 466 void NetBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, 467 llvm::opt::ArgStringList &CC1Args) const { 468 const std::string Candidates[] = { 469 // directory relative to build tree 470 getDriver().Dir + "/../include/c++/v1", 471 // system install with full upstream path 472 getDriver().SysRoot + "/usr/include/c++/v1", 473 // system install from src 474 getDriver().SysRoot + "/usr/include/c++", 475 }; 476 477 for (const auto &IncludePath : Candidates) { 478 if (!getVFS().exists(IncludePath + "/__config")) 479 continue; 480 481 // Use the first candidate that looks valid. 482 addSystemInclude(DriverArgs, CC1Args, IncludePath); 483 return; 484 } 485 } 486 487 void NetBSD::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, 488 llvm::opt::ArgStringList &CC1Args) const { 489 addLibStdCXXIncludePaths(getDriver().SysRoot + "/usr/include/g++", "", "", 490 DriverArgs, CC1Args); 491 } 492 493 llvm::ExceptionHandling NetBSD::GetExceptionModel(const ArgList &Args) const { 494 // NetBSD uses Dwarf exceptions on ARM. 495 llvm::Triple::ArchType TArch = getTriple().getArch(); 496 if (TArch == llvm::Triple::arm || TArch == llvm::Triple::armeb || 497 TArch == llvm::Triple::thumb || TArch == llvm::Triple::thumbeb) 498 return llvm::ExceptionHandling::DwarfCFI; 499 return llvm::ExceptionHandling::None; 500 } 501 502 SanitizerMask NetBSD::getSupportedSanitizers() const { 503 const bool IsX86 = getTriple().getArch() == llvm::Triple::x86; 504 const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; 505 SanitizerMask Res = ToolChain::getSupportedSanitizers(); 506 if (IsX86 || IsX86_64) { 507 Res |= SanitizerKind::Address; 508 Res |= SanitizerKind::PointerCompare; 509 Res |= SanitizerKind::PointerSubtract; 510 Res |= SanitizerKind::Leak; 511 Res |= SanitizerKind::SafeStack; 512 Res |= SanitizerKind::Scudo; 513 Res |= SanitizerKind::Vptr; 514 } 515 if (IsX86_64) { 516 Res |= SanitizerKind::DataFlow; 517 Res |= SanitizerKind::Fuzzer; 518 Res |= SanitizerKind::FuzzerNoLink; 519 Res |= SanitizerKind::HWAddress; 520 Res |= SanitizerKind::KernelAddress; 521 Res |= SanitizerKind::KernelHWAddress; 522 Res |= SanitizerKind::KernelMemory; 523 Res |= SanitizerKind::Memory; 524 Res |= SanitizerKind::Thread; 525 } 526 return Res; 527 } 528 529 void NetBSD::addClangTargetOptions(const ArgList &DriverArgs, 530 ArgStringList &CC1Args, 531 Action::OffloadKind) const { 532 const SanitizerArgs &SanArgs = getSanitizerArgs(DriverArgs); 533 if (SanArgs.hasAnySanitizer()) 534 CC1Args.push_back("-D_REENTRANT"); 535 536 VersionTuple OsVersion = getTriple().getOSVersion(); 537 bool UseInitArrayDefault = 538 OsVersion >= VersionTuple(9) || OsVersion.getMajor() == 0 || 539 getTriple().getArch() == llvm::Triple::aarch64 || 540 getTriple().getArch() == llvm::Triple::aarch64_be || 541 getTriple().getArch() == llvm::Triple::arm || 542 getTriple().getArch() == llvm::Triple::armeb; 543 544 if (!DriverArgs.hasFlag(options::OPT_fuse_init_array, 545 options::OPT_fno_use_init_array, UseInitArrayDefault)) 546 CC1Args.push_back("-fno-use-init-array"); 547 } 548