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