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