1 //===--- OpenBSD.cpp - OpenBSD 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 "OpenBSD.h" 10 #include "Arch/Mips.h" 11 #include "Arch/Sparc.h" 12 #include "CommonArgs.h" 13 #include "clang/Config/config.h" 14 #include "clang/Driver/Compilation.h" 15 #include "clang/Driver/Options.h" 16 #include "clang/Driver/SanitizerArgs.h" 17 #include "llvm/Option/ArgList.h" 18 #include "llvm/Support/Path.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 openbsd::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 switch (getToolChain().getArch()) { 36 case llvm::Triple::x86: 37 // When building 32-bit code on OpenBSD/amd64, we have to explicitly 38 // instruct as in the base system to assemble 32-bit code. 39 CmdArgs.push_back("--32"); 40 break; 41 42 case llvm::Triple::ppc: 43 CmdArgs.push_back("-mppc"); 44 CmdArgs.push_back("-many"); 45 break; 46 47 case llvm::Triple::sparcv9: { 48 CmdArgs.push_back("-64"); 49 std::string CPU = getCPUName(Args, getToolChain().getTriple()); 50 CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); 51 AddAssemblerKPIC(getToolChain(), Args, CmdArgs); 52 break; 53 } 54 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("-mabi"); 62 CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data()); 63 64 if (getToolChain().getTriple().isLittleEndian()) 65 CmdArgs.push_back("-EL"); 66 else 67 CmdArgs.push_back("-EB"); 68 69 AddAssemblerKPIC(getToolChain(), Args, CmdArgs); 70 break; 71 } 72 73 default: 74 break; 75 } 76 77 Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); 78 79 CmdArgs.push_back("-o"); 80 CmdArgs.push_back(Output.getFilename()); 81 82 for (const auto &II : Inputs) 83 CmdArgs.push_back(II.getFilename()); 84 85 const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); 86 C.addCommand(std::make_unique<Command>(JA, *this, 87 ResponseFileSupport::AtFileCurCP(), 88 Exec, CmdArgs, Inputs, Output)); 89 } 90 91 void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, 92 const InputInfo &Output, 93 const InputInfoList &Inputs, 94 const ArgList &Args, 95 const char *LinkingOutput) const { 96 const toolchains::OpenBSD &ToolChain = 97 static_cast<const toolchains::OpenBSD &>(getToolChain()); 98 const Driver &D = getToolChain().getDriver(); 99 ArgStringList CmdArgs; 100 101 // Silence warning for "clang -g foo.o -o foo" 102 Args.ClaimAllArgs(options::OPT_g_Group); 103 // and "clang -emit-llvm foo.o -o foo" 104 Args.ClaimAllArgs(options::OPT_emit_llvm); 105 // and for "clang -w foo.o -o foo". Other warning options are already 106 // handled somewhere else. 107 Args.ClaimAllArgs(options::OPT_w); 108 109 if (ToolChain.getArch() == llvm::Triple::mips64) 110 CmdArgs.push_back("-EB"); 111 else if (ToolChain.getArch() == llvm::Triple::mips64el) 112 CmdArgs.push_back("-EL"); 113 114 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) { 115 CmdArgs.push_back("-e"); 116 CmdArgs.push_back("__start"); 117 } 118 119 CmdArgs.push_back("--eh-frame-hdr"); 120 if (Args.hasArg(options::OPT_static)) { 121 CmdArgs.push_back("-Bstatic"); 122 } else { 123 if (Args.hasArg(options::OPT_rdynamic)) 124 CmdArgs.push_back("-export-dynamic"); 125 CmdArgs.push_back("-Bdynamic"); 126 if (Args.hasArg(options::OPT_shared)) { 127 CmdArgs.push_back("-shared"); 128 } else { 129 CmdArgs.push_back("-dynamic-linker"); 130 CmdArgs.push_back("/usr/libexec/ld.so"); 131 } 132 } 133 134 if (Args.hasArg(options::OPT_pie)) 135 CmdArgs.push_back("-pie"); 136 if (Args.hasArg(options::OPT_nopie) || Args.hasArg(options::OPT_pg)) 137 CmdArgs.push_back("-nopie"); 138 139 if (Output.isFilename()) { 140 CmdArgs.push_back("-o"); 141 CmdArgs.push_back(Output.getFilename()); 142 } else { 143 assert(Output.isNothing() && "Invalid output."); 144 } 145 146 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { 147 const char *crt0 = nullptr; 148 const char *crtbegin = nullptr; 149 if (!Args.hasArg(options::OPT_shared)) { 150 if (Args.hasArg(options::OPT_pg)) 151 crt0 = "gcrt0.o"; 152 else if (Args.hasArg(options::OPT_static) && 153 !Args.hasArg(options::OPT_nopie)) 154 crt0 = "rcrt0.o"; 155 else 156 crt0 = "crt0.o"; 157 crtbegin = "crtbegin.o"; 158 } else { 159 crtbegin = "crtbeginS.o"; 160 } 161 162 if (crt0) 163 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt0))); 164 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin))); 165 } 166 167 Args.AddAllArgs(CmdArgs, options::OPT_L); 168 ToolChain.AddFilePathLibArgs(Args, CmdArgs); 169 Args.AddAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_e, 170 options::OPT_s, options::OPT_t, 171 options::OPT_Z_Flag, options::OPT_r}); 172 173 bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs); 174 bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); 175 AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); 176 177 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { 178 // Use the static OpenMP runtime with -static-openmp 179 bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && 180 !Args.hasArg(options::OPT_static); 181 addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP); 182 183 if (D.CCCIsCXX()) { 184 if (ToolChain.ShouldLinkCXXStdlib(Args)) 185 ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); 186 if (Args.hasArg(options::OPT_pg)) 187 CmdArgs.push_back("-lm_p"); 188 else 189 CmdArgs.push_back("-lm"); 190 } 191 if (NeedsSanitizerDeps) { 192 CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins")); 193 linkSanitizerRuntimeDeps(ToolChain, CmdArgs); 194 } 195 if (NeedsXRayDeps) { 196 CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins")); 197 linkXRayRuntimeDeps(ToolChain, CmdArgs); 198 } 199 // FIXME: For some reason GCC passes -lgcc before adding 200 // the default system libraries. Just mimic this for now. 201 CmdArgs.push_back("-lcompiler_rt"); 202 203 if (Args.hasArg(options::OPT_pthread)) { 204 if (!Args.hasArg(options::OPT_shared) && Args.hasArg(options::OPT_pg)) 205 CmdArgs.push_back("-lpthread_p"); 206 else 207 CmdArgs.push_back("-lpthread"); 208 } 209 210 if (!Args.hasArg(options::OPT_shared)) { 211 if (Args.hasArg(options::OPT_pg)) 212 CmdArgs.push_back("-lc_p"); 213 else 214 CmdArgs.push_back("-lc"); 215 } 216 217 CmdArgs.push_back("-lcompiler_rt"); 218 } 219 220 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { 221 const char *crtend = nullptr; 222 if (!Args.hasArg(options::OPT_shared)) 223 crtend = "crtend.o"; 224 else 225 crtend = "crtendS.o"; 226 227 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend))); 228 } 229 230 ToolChain.addProfileRTLibs(Args, CmdArgs); 231 232 const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); 233 C.addCommand(std::make_unique<Command>(JA, *this, 234 ResponseFileSupport::AtFileCurCP(), 235 Exec, CmdArgs, Inputs, Output)); 236 } 237 238 SanitizerMask OpenBSD::getSupportedSanitizers() const { 239 const bool IsX86 = getTriple().getArch() == llvm::Triple::x86; 240 const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; 241 242 // For future use, only UBsan at the moment 243 SanitizerMask Res = ToolChain::getSupportedSanitizers(); 244 245 if (IsX86 || IsX86_64) { 246 Res |= SanitizerKind::Vptr; 247 Res |= SanitizerKind::Fuzzer; 248 Res |= SanitizerKind::FuzzerNoLink; 249 } 250 251 return Res; 252 } 253 254 /// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly. 255 256 OpenBSD::OpenBSD(const Driver &D, const llvm::Triple &Triple, 257 const ArgList &Args) 258 : Generic_ELF(D, Triple, Args) { 259 getFilePaths().push_back(getDriver().SysRoot + "/usr/lib"); 260 } 261 262 void OpenBSD::AddClangSystemIncludeArgs( 263 const llvm::opt::ArgList &DriverArgs, 264 llvm::opt::ArgStringList &CC1Args) const { 265 const Driver &D = getDriver(); 266 267 if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc)) 268 return; 269 270 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 271 SmallString<128> Dir(D.ResourceDir); 272 llvm::sys::path::append(Dir, "include"); 273 addSystemInclude(DriverArgs, CC1Args, Dir.str()); 274 } 275 276 if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 277 return; 278 279 // Check for configure-time C include directories. 280 StringRef CIncludeDirs(C_INCLUDE_DIRS); 281 if (CIncludeDirs != "") { 282 SmallVector<StringRef, 5> dirs; 283 CIncludeDirs.split(dirs, ":"); 284 for (StringRef dir : dirs) { 285 StringRef Prefix = 286 llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : ""; 287 addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir); 288 } 289 return; 290 } 291 292 addExternCSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/usr/include"); 293 } 294 295 void OpenBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, 296 llvm::opt::ArgStringList &CC1Args) const { 297 addSystemInclude(DriverArgs, CC1Args, 298 getDriver().SysRoot + "/usr/include/c++/v1"); 299 } 300 301 void OpenBSD::AddCXXStdlibLibArgs(const ArgList &Args, 302 ArgStringList &CmdArgs) const { 303 bool Profiling = Args.hasArg(options::OPT_pg); 304 305 CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++"); 306 CmdArgs.push_back(Profiling ? "-lc++abi_p" : "-lc++abi"); 307 CmdArgs.push_back(Profiling ? "-lpthread_p" : "-lpthread"); 308 } 309 310 std::string OpenBSD::getCompilerRT(const ArgList &Args, 311 StringRef Component, 312 FileType Type) const { 313 if (Component == "builtins") { 314 SmallString<128> Path(getDriver().SysRoot); 315 llvm::sys::path::append(Path, "/usr/lib/libcompiler_rt.a"); 316 return std::string(Path.str()); 317 } else { 318 SmallString<128> P(getDriver().ResourceDir); 319 std::string CRTBasename = 320 buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/false); 321 llvm::sys::path::append(P, "lib", CRTBasename); 322 if (getVFS().exists(P)) 323 return std::string(P.str()); 324 return ToolChain::getCompilerRT(Args, Component, Type); 325 } 326 } 327 328 Tool *OpenBSD::buildAssembler() const { 329 return new tools::openbsd::Assembler(*this); 330 } 331 332 Tool *OpenBSD::buildLinker() const { return new tools::openbsd::Linker(*this); } 333 334 bool OpenBSD::HasNativeLLVMSupport() const { return true; } 335