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