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_e); 260 Args.AddAllArgs(CmdArgs, options::OPT_s); 261 Args.AddAllArgs(CmdArgs, options::OPT_t); 262 Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag); 263 Args.AddAllArgs(CmdArgs, options::OPT_r); 264 265 bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs); 266 bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); 267 AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); 268 269 const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(Args); 270 if (SanArgs.needsSharedRt()) { 271 CmdArgs.push_back("-rpath"); 272 CmdArgs.push_back(Args.MakeArgString(ToolChain.getCompilerRTPath())); 273 } 274 275 VersionTuple OsVersion = Triple.getOSVersion(); 276 bool useLibgcc = true; 277 if (OsVersion >= VersionTuple(7) || OsVersion.getMajor() == 0) { 278 switch (ToolChain.getArch()) { 279 case llvm::Triple::aarch64: 280 case llvm::Triple::aarch64_be: 281 case llvm::Triple::arm: 282 case llvm::Triple::armeb: 283 case llvm::Triple::thumb: 284 case llvm::Triple::thumbeb: 285 case llvm::Triple::ppc: 286 case llvm::Triple::ppc64: 287 case llvm::Triple::ppc64le: 288 case llvm::Triple::sparc: 289 case llvm::Triple::sparcv9: 290 case llvm::Triple::x86: 291 case llvm::Triple::x86_64: 292 useLibgcc = false; 293 break; 294 default: 295 break; 296 } 297 } 298 299 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, 300 options::OPT_r)) { 301 // Use the static OpenMP runtime with -static-openmp 302 bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && 303 !Args.hasArg(options::OPT_static); 304 addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP); 305 306 if (D.CCCIsCXX()) { 307 if (ToolChain.ShouldLinkCXXStdlib(Args)) 308 ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); 309 CmdArgs.push_back("-lm"); 310 } 311 if (NeedsSanitizerDeps) 312 linkSanitizerRuntimeDeps(ToolChain, CmdArgs); 313 if (NeedsXRayDeps) 314 linkXRayRuntimeDeps(ToolChain, CmdArgs); 315 if (Args.hasArg(options::OPT_pthread)) 316 CmdArgs.push_back("-lpthread"); 317 CmdArgs.push_back("-lc"); 318 319 if (useLibgcc) { 320 if (Args.hasArg(options::OPT_static)) { 321 // libgcc_eh depends on libc, so resolve as much as possible, 322 // pull in any new requirements from libc and then get the rest 323 // of libgcc. 324 CmdArgs.push_back("-lgcc_eh"); 325 CmdArgs.push_back("-lc"); 326 CmdArgs.push_back("-lgcc"); 327 } else { 328 CmdArgs.push_back("-lgcc"); 329 CmdArgs.push_back("--as-needed"); 330 CmdArgs.push_back("-lgcc_s"); 331 CmdArgs.push_back("--no-as-needed"); 332 } 333 } 334 } 335 336 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, 337 options::OPT_r)) { 338 if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) 339 CmdArgs.push_back( 340 Args.MakeArgString(ToolChain.GetFilePath("crtendS.o"))); 341 else 342 CmdArgs.push_back( 343 Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); 344 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); 345 } 346 347 ToolChain.addProfileRTLibs(Args, CmdArgs); 348 349 const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); 350 C.addCommand(std::make_unique<Command>(JA, *this, 351 ResponseFileSupport::AtFileCurCP(), 352 Exec, CmdArgs, Inputs, Output)); 353 } 354 355 /// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly. 356 357 NetBSD::NetBSD(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) 358 : Generic_ELF(D, Triple, Args) { 359 if (!Args.hasArg(options::OPT_nostdlib)) { 360 // When targeting a 32-bit platform, try the special directory used on 361 // 64-bit hosts, and only fall back to the main library directory if that 362 // doesn't work. 363 // FIXME: It'd be nicer to test if this directory exists, but I'm not sure 364 // what all logic is needed to emulate the '=' prefix here. 365 switch (Triple.getArch()) { 366 case llvm::Triple::x86: 367 getFilePaths().push_back("=/usr/lib/i386"); 368 break; 369 case llvm::Triple::arm: 370 case llvm::Triple::armeb: 371 case llvm::Triple::thumb: 372 case llvm::Triple::thumbeb: 373 switch (Triple.getEnvironment()) { 374 case llvm::Triple::EABI: 375 case llvm::Triple::GNUEABI: 376 getFilePaths().push_back("=/usr/lib/eabi"); 377 break; 378 case llvm::Triple::EABIHF: 379 case llvm::Triple::GNUEABIHF: 380 getFilePaths().push_back("=/usr/lib/eabihf"); 381 break; 382 default: 383 getFilePaths().push_back("=/usr/lib/oabi"); 384 break; 385 } 386 break; 387 case llvm::Triple::mips64: 388 case llvm::Triple::mips64el: 389 if (tools::mips::hasMipsAbiArg(Args, "o32")) 390 getFilePaths().push_back("=/usr/lib/o32"); 391 else if (tools::mips::hasMipsAbiArg(Args, "64")) 392 getFilePaths().push_back("=/usr/lib/64"); 393 break; 394 case llvm::Triple::ppc: 395 getFilePaths().push_back("=/usr/lib/powerpc"); 396 break; 397 case llvm::Triple::sparc: 398 getFilePaths().push_back("=/usr/lib/sparc"); 399 break; 400 default: 401 break; 402 } 403 404 getFilePaths().push_back("=/usr/lib"); 405 } 406 } 407 408 Tool *NetBSD::buildAssembler() const { 409 return new tools::netbsd::Assembler(*this); 410 } 411 412 Tool *NetBSD::buildLinker() const { return new tools::netbsd::Linker(*this); } 413 414 ToolChain::CXXStdlibType NetBSD::GetDefaultCXXStdlibType() const { 415 VersionTuple OsVersion = getTriple().getOSVersion(); 416 if (OsVersion >= VersionTuple(7) || OsVersion.getMajor() == 0) { 417 switch (getArch()) { 418 case llvm::Triple::aarch64: 419 case llvm::Triple::aarch64_be: 420 case llvm::Triple::arm: 421 case llvm::Triple::armeb: 422 case llvm::Triple::thumb: 423 case llvm::Triple::thumbeb: 424 case llvm::Triple::ppc: 425 case llvm::Triple::ppc64: 426 case llvm::Triple::ppc64le: 427 case llvm::Triple::sparc: 428 case llvm::Triple::sparcv9: 429 case llvm::Triple::x86: 430 case llvm::Triple::x86_64: 431 return ToolChain::CST_Libcxx; 432 default: 433 break; 434 } 435 } 436 return ToolChain::CST_Libstdcxx; 437 } 438 439 void NetBSD::AddClangSystemIncludeArgs( 440 const llvm::opt::ArgList &DriverArgs, 441 llvm::opt::ArgStringList &CC1Args) const { 442 const Driver &D = getDriver(); 443 444 if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc)) 445 return; 446 447 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 448 SmallString<128> Dir(D.ResourceDir); 449 llvm::sys::path::append(Dir, "include"); 450 addSystemInclude(DriverArgs, CC1Args, Dir.str()); 451 } 452 453 if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 454 return; 455 456 // Check for configure-time C include directories. 457 StringRef CIncludeDirs(C_INCLUDE_DIRS); 458 if (CIncludeDirs != "") { 459 SmallVector<StringRef, 5> dirs; 460 CIncludeDirs.split(dirs, ":"); 461 for (StringRef dir : dirs) { 462 StringRef Prefix = 463 llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : ""; 464 addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir); 465 } 466 return; 467 } 468 469 addExternCSystemInclude(DriverArgs, CC1Args, 470 concat(D.SysRoot, "/usr/include")); 471 } 472 473 void NetBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, 474 llvm::opt::ArgStringList &CC1Args) const { 475 const std::string Candidates[] = { 476 // directory relative to build tree 477 getDriver().Dir + "/../include/c++/v1", 478 // system install with full upstream path 479 getDriver().SysRoot + "/usr/include/c++/v1", 480 // system install from src 481 getDriver().SysRoot + "/usr/include/c++", 482 }; 483 484 for (const auto &IncludePath : Candidates) { 485 if (!getVFS().exists(IncludePath + "/__config")) 486 continue; 487 488 // Use the first candidate that looks valid. 489 addSystemInclude(DriverArgs, CC1Args, IncludePath); 490 return; 491 } 492 } 493 494 void NetBSD::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, 495 llvm::opt::ArgStringList &CC1Args) const { 496 addLibStdCXXIncludePaths(getDriver().SysRoot + "/usr/include/g++", "", "", 497 DriverArgs, CC1Args); 498 } 499 500 llvm::ExceptionHandling NetBSD::GetExceptionModel(const ArgList &Args) const { 501 // NetBSD uses Dwarf exceptions on ARM. 502 llvm::Triple::ArchType TArch = getTriple().getArch(); 503 if (TArch == llvm::Triple::arm || TArch == llvm::Triple::armeb || 504 TArch == llvm::Triple::thumb || TArch == llvm::Triple::thumbeb) 505 return llvm::ExceptionHandling::DwarfCFI; 506 return llvm::ExceptionHandling::None; 507 } 508 509 SanitizerMask NetBSD::getSupportedSanitizers() const { 510 const bool IsX86 = getTriple().getArch() == llvm::Triple::x86; 511 const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; 512 SanitizerMask Res = ToolChain::getSupportedSanitizers(); 513 if (IsX86 || IsX86_64) { 514 Res |= SanitizerKind::Address; 515 Res |= SanitizerKind::PointerCompare; 516 Res |= SanitizerKind::PointerSubtract; 517 Res |= SanitizerKind::Function; 518 Res |= SanitizerKind::Leak; 519 Res |= SanitizerKind::SafeStack; 520 Res |= SanitizerKind::Scudo; 521 Res |= SanitizerKind::Vptr; 522 } 523 if (IsX86_64) { 524 Res |= SanitizerKind::DataFlow; 525 Res |= SanitizerKind::Fuzzer; 526 Res |= SanitizerKind::FuzzerNoLink; 527 Res |= SanitizerKind::HWAddress; 528 Res |= SanitizerKind::KernelAddress; 529 Res |= SanitizerKind::KernelHWAddress; 530 Res |= SanitizerKind::KernelMemory; 531 Res |= SanitizerKind::Memory; 532 Res |= SanitizerKind::Thread; 533 } 534 return Res; 535 } 536 537 void NetBSD::addClangTargetOptions(const ArgList &DriverArgs, 538 ArgStringList &CC1Args, 539 Action::OffloadKind) const { 540 const SanitizerArgs &SanArgs = getSanitizerArgs(DriverArgs); 541 if (SanArgs.hasAnySanitizer()) 542 CC1Args.push_back("-D_REENTRANT"); 543 544 VersionTuple OsVersion = getTriple().getOSVersion(); 545 bool UseInitArrayDefault = 546 OsVersion >= VersionTuple(9) || OsVersion.getMajor() == 0 || 547 getTriple().getArch() == llvm::Triple::aarch64 || 548 getTriple().getArch() == llvm::Triple::aarch64_be || 549 getTriple().getArch() == llvm::Triple::arm || 550 getTriple().getArch() == llvm::Triple::armeb; 551 552 if (!DriverArgs.hasFlag(options::OPT_fuse_init_array, 553 options::OPT_fno_use_init_array, UseInitArrayDefault)) 554 CC1Args.push_back("-fno-use-init-array"); 555 } 556