OpenBSD.cpp revision 360784
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/Options.h"
15#include "clang/Driver/SanitizerArgs.h"
16#include "llvm/Option/ArgList.h"
17
18using namespace clang::driver;
19using namespace clang::driver::tools;
20using namespace clang::driver::toolchains;
21using namespace clang;
22using namespace llvm::opt;
23
24void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
25                                      const InputInfo &Output,
26                                      const InputInfoList &Inputs,
27                                      const ArgList &Args,
28                                      const char *LinkingOutput) const {
29  claimNoWarnArgs(Args);
30  ArgStringList CmdArgs;
31
32  switch (getToolChain().getArch()) {
33  case llvm::Triple::x86:
34    // When building 32-bit code on OpenBSD/amd64, we have to explicitly
35    // instruct as in the base system to assemble 32-bit code.
36    CmdArgs.push_back("--32");
37    break;
38
39  case llvm::Triple::ppc:
40    CmdArgs.push_back("-mppc");
41    CmdArgs.push_back("-many");
42    break;
43
44  case llvm::Triple::sparc:
45  case llvm::Triple::sparcel: {
46    CmdArgs.push_back("-32");
47    std::string CPU = getCPUName(Args, getToolChain().getTriple());
48    CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
49    AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
50    break;
51  }
52
53  case llvm::Triple::sparcv9: {
54    CmdArgs.push_back("-64");
55    std::string CPU = getCPUName(Args, getToolChain().getTriple());
56    CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
57    AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
58    break;
59  }
60
61  case llvm::Triple::mips64:
62  case llvm::Triple::mips64el: {
63    StringRef CPUName;
64    StringRef ABIName;
65    mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
66
67    CmdArgs.push_back("-mabi");
68    CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data());
69
70    if (getToolChain().getTriple().isLittleEndian())
71      CmdArgs.push_back("-EL");
72    else
73      CmdArgs.push_back("-EB");
74
75    AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
76    break;
77  }
78
79  default:
80    break;
81  }
82
83  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
84
85  CmdArgs.push_back("-o");
86  CmdArgs.push_back(Output.getFilename());
87
88  for (const auto &II : Inputs)
89    CmdArgs.push_back(II.getFilename());
90
91  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
92  C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
93}
94
95void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
96                                   const InputInfo &Output,
97                                   const InputInfoList &Inputs,
98                                   const ArgList &Args,
99                                   const char *LinkingOutput) const {
100  const toolchains::OpenBSD &ToolChain =
101      static_cast<const toolchains::OpenBSD &>(getToolChain());
102  const Driver &D = getToolChain().getDriver();
103  ArgStringList CmdArgs;
104
105  // Silence warning for "clang -g foo.o -o foo"
106  Args.ClaimAllArgs(options::OPT_g_Group);
107  // and "clang -emit-llvm foo.o -o foo"
108  Args.ClaimAllArgs(options::OPT_emit_llvm);
109  // and for "clang -w foo.o -o foo". Other warning options are already
110  // handled somewhere else.
111  Args.ClaimAllArgs(options::OPT_w);
112
113  if (ToolChain.getArch() == llvm::Triple::mips64)
114    CmdArgs.push_back("-EB");
115  else if (ToolChain.getArch() == llvm::Triple::mips64el)
116    CmdArgs.push_back("-EL");
117
118  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) {
119    CmdArgs.push_back("-e");
120    CmdArgs.push_back("__start");
121  }
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    CmdArgs.push_back("-Bdynamic");
130    if (Args.hasArg(options::OPT_shared)) {
131      CmdArgs.push_back("-shared");
132    } else {
133      CmdArgs.push_back("-dynamic-linker");
134      CmdArgs.push_back("/usr/libexec/ld.so");
135    }
136  }
137
138  if (Args.hasArg(options::OPT_pie))
139    CmdArgs.push_back("-pie");
140  if (Args.hasArg(options::OPT_nopie) || Args.hasArg(options::OPT_pg))
141    CmdArgs.push_back("-nopie");
142
143  if (Output.isFilename()) {
144    CmdArgs.push_back("-o");
145    CmdArgs.push_back(Output.getFilename());
146  } else {
147    assert(Output.isNothing() && "Invalid output.");
148  }
149
150  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
151    const char *crt0 = nullptr;
152    const char *crtbegin = nullptr;
153    if (!Args.hasArg(options::OPT_shared)) {
154      if (Args.hasArg(options::OPT_pg))
155        crt0 = "gcrt0.o";
156      else if (Args.hasArg(options::OPT_static) &&
157               !Args.hasArg(options::OPT_nopie))
158        crt0 = "rcrt0.o";
159      else
160        crt0 = "crt0.o";
161      crtbegin = "crtbegin.o";
162    } else {
163      crtbegin = "crtbeginS.o";
164    }
165
166    if (crt0)
167      CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt0)));
168    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
169  }
170
171  Args.AddAllArgs(CmdArgs, options::OPT_L);
172  ToolChain.AddFilePathLibArgs(Args, CmdArgs);
173  Args.AddAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_e,
174                            options::OPT_s, options::OPT_t,
175                            options::OPT_Z_Flag, options::OPT_r});
176
177  bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
178  bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
179  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
180
181  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
182    if (D.CCCIsCXX()) {
183      if (ToolChain.ShouldLinkCXXStdlib(Args))
184        ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
185      if (Args.hasArg(options::OPT_pg))
186        CmdArgs.push_back("-lm_p");
187      else
188        CmdArgs.push_back("-lm");
189    }
190    if (NeedsSanitizerDeps) {
191      CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins"));
192      linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
193    }
194    if (NeedsXRayDeps) {
195      CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins"));
196      linkXRayRuntimeDeps(ToolChain, CmdArgs);
197    }
198    // FIXME: For some reason GCC passes -lgcc before adding
199    // the default system libraries. Just mimic this for now.
200    CmdArgs.push_back("-lcompiler_rt");
201
202    if (Args.hasArg(options::OPT_pthread)) {
203      if (!Args.hasArg(options::OPT_shared) && Args.hasArg(options::OPT_pg))
204        CmdArgs.push_back("-lpthread_p");
205      else
206        CmdArgs.push_back("-lpthread");
207    }
208
209    if (!Args.hasArg(options::OPT_shared)) {
210      if (Args.hasArg(options::OPT_pg))
211        CmdArgs.push_back("-lc_p");
212      else
213        CmdArgs.push_back("-lc");
214    }
215
216    CmdArgs.push_back("-lcompiler_rt");
217  }
218
219  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
220    const char *crtend = nullptr;
221    if (!Args.hasArg(options::OPT_shared))
222      crtend = "crtend.o";
223    else
224      crtend = "crtendS.o";
225
226    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
227  }
228
229  const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
230  C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
231}
232
233SanitizerMask OpenBSD::getSupportedSanitizers() const {
234  const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
235  const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
236
237  // For future use, only UBsan at the moment
238  SanitizerMask Res = ToolChain::getSupportedSanitizers();
239
240  if (IsX86 || IsX86_64) {
241    Res |= SanitizerKind::Vptr;
242    Res |= SanitizerKind::Fuzzer;
243    Res |= SanitizerKind::FuzzerNoLink;
244  }
245
246  return Res;
247}
248
249/// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly.
250
251OpenBSD::OpenBSD(const Driver &D, const llvm::Triple &Triple,
252                 const ArgList &Args)
253    : Generic_ELF(D, Triple, Args) {
254  getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
255}
256
257void OpenBSD::AddCXXStdlibLibArgs(const ArgList &Args,
258                                  ArgStringList &CmdArgs) const {
259  bool Profiling = Args.hasArg(options::OPT_pg);
260
261  CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++");
262  CmdArgs.push_back(Profiling ? "-lc++abi_p" : "-lc++abi");
263}
264
265Tool *OpenBSD::buildAssembler() const {
266  return new tools::openbsd::Assembler(*this);
267}
268
269Tool *OpenBSD::buildLinker() const { return new tools::openbsd::Linker(*this); }
270
271void OpenBSD::addClangTargetOptions(const ArgList &DriverArgs,
272                                    ArgStringList &CC1Args,
273                                    Action::OffloadKind) const {
274  // Support for .init_array is still new (Aug 2016).
275  if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
276                          options::OPT_fno_use_init_array, false))
277    CC1Args.push_back("-fno-use-init-array");
278}
279