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