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