1 //===-- ArchSpecTest.cpp --------------------------------------------------===//
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 "gtest/gtest.h"
10 
11 #include "lldb/Utility/ArchSpec.h"
12 #include "llvm/BinaryFormat/MachO.h"
13 #include "llvm/BinaryFormat/ELF.h"
14 
15 using namespace lldb;
16 using namespace lldb_private;
17 
18 TEST(ArchSpecTest, TestParseMachCPUDashSubtypeTripleSimple) {
19 
20   // Success conditions.  Valid cpu/subtype combinations using both - and .
21   ArchSpec AS;
22   EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-10", AS));
23   EXPECT_EQ(12u, AS.GetMachOCPUType());
24   EXPECT_EQ(10u, AS.GetMachOCPUSubType());
25 
26   AS = ArchSpec();
27   EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-15", AS));
28   EXPECT_EQ(12u, AS.GetMachOCPUType());
29   EXPECT_EQ(15u, AS.GetMachOCPUSubType());
30 
31   AS = ArchSpec();
32   EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12.15", AS));
33   EXPECT_EQ(12u, AS.GetMachOCPUType());
34   EXPECT_EQ(15u, AS.GetMachOCPUSubType());
35 
36   // Failure conditions.
37 
38   // Valid string, unknown cpu/subtype.
39   AS = ArchSpec();
40   EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("13.11", AS));
41   EXPECT_EQ(0u, AS.GetMachOCPUType());
42   EXPECT_EQ(0u, AS.GetMachOCPUSubType());
43 
44   // Missing / invalid cpu or subtype
45   AS = ArchSpec();
46   EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("13", AS));
47 
48   AS = ArchSpec();
49   EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("13.A", AS));
50 
51   AS = ArchSpec();
52   EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("A.13", AS));
53 
54   // Empty string.
55   AS = ArchSpec();
56   EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("", AS));
57 }
58 
59 TEST(ArchSpecTest, TestParseMachCPUDashSubtypeTripleExtra) {
60   ArchSpec AS;
61   EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-15-vendor-os", AS));
62   EXPECT_EQ(12u, AS.GetMachOCPUType());
63   EXPECT_EQ(15u, AS.GetMachOCPUSubType());
64   EXPECT_EQ("vendor", AS.GetTriple().getVendorName());
65   EXPECT_EQ("os", AS.GetTriple().getOSName());
66 
67   AS = ArchSpec();
68   EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-10-vendor-os-name", AS));
69   EXPECT_EQ(12u, AS.GetMachOCPUType());
70   EXPECT_EQ(10u, AS.GetMachOCPUSubType());
71   EXPECT_EQ("vendor", AS.GetTriple().getVendorName());
72   EXPECT_EQ("os", AS.GetTriple().getOSName());
73 
74   AS = ArchSpec();
75   EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-15-vendor.os-name", AS));
76   EXPECT_EQ(12u, AS.GetMachOCPUType());
77   EXPECT_EQ(15u, AS.GetMachOCPUSubType());
78   EXPECT_EQ("vendor.os", AS.GetTriple().getVendorName());
79   EXPECT_EQ("name", AS.GetTriple().getOSName());
80 
81   // These there should parse correctly, but the vendor / OS should be defaulted
82   // since they are unrecognized.
83   AS = ArchSpec();
84   EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-10-vendor", AS));
85   EXPECT_EQ(12u, AS.GetMachOCPUType());
86   EXPECT_EQ(10u, AS.GetMachOCPUSubType());
87   EXPECT_EQ("apple", AS.GetTriple().getVendorName());
88   EXPECT_EQ("", AS.GetTriple().getOSName());
89 
90   AS = ArchSpec();
91   EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("12.10.10", AS));
92 
93   AS = ArchSpec();
94   EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("12-10.10", AS));
95 }
96 
97 TEST(ArchSpecTest, TestSetTriple) {
98   ArchSpec AS;
99 
100   // Various flavors of valid triples.
101   EXPECT_TRUE(AS.SetTriple("12-10-apple-darwin"));
102   EXPECT_EQ(uint32_t(llvm::MachO::CPU_TYPE_ARM), AS.GetMachOCPUType());
103   EXPECT_EQ(10u, AS.GetMachOCPUSubType());
104   EXPECT_TRUE(llvm::StringRef(AS.GetTriple().str())
105                   .consume_front("armv7f-apple-darwin"));
106   EXPECT_EQ(ArchSpec::eCore_arm_armv7f, AS.GetCore());
107 
108   AS = ArchSpec();
109   EXPECT_TRUE(AS.SetTriple("18.100-apple-darwin"));
110   EXPECT_EQ(uint32_t(llvm::MachO::CPU_TYPE_POWERPC), AS.GetMachOCPUType());
111   EXPECT_EQ(100u, AS.GetMachOCPUSubType());
112   EXPECT_TRUE(llvm::StringRef(AS.GetTriple().str())
113                   .consume_front("powerpc-apple-darwin"));
114   EXPECT_EQ(ArchSpec::eCore_ppc_ppc970, AS.GetCore());
115 
116   AS = ArchSpec();
117   EXPECT_TRUE(AS.SetTriple("i686-pc-windows"));
118   EXPECT_EQ(llvm::Triple::x86, AS.GetTriple().getArch());
119   EXPECT_EQ(llvm::Triple::PC, AS.GetTriple().getVendor());
120   EXPECT_EQ(llvm::Triple::Win32, AS.GetTriple().getOS());
121   EXPECT_TRUE(
122       llvm::StringRef(AS.GetTriple().str()).consume_front("i686-pc-windows"));
123   EXPECT_STREQ("i686", AS.GetArchitectureName());
124   EXPECT_EQ(ArchSpec::eCore_x86_32_i686, AS.GetCore());
125 
126   // Various flavors of invalid triples.
127   AS = ArchSpec();
128   EXPECT_FALSE(AS.SetTriple("unknown-unknown-unknown"));
129 
130   AS = ArchSpec();
131   EXPECT_FALSE(AS.SetTriple("unknown"));
132 
133   AS = ArchSpec();
134   EXPECT_FALSE(AS.SetTriple(""));
135 }
136 
137 TEST(ArchSpecTest, MergeFrom) {
138   {
139     ArchSpec A;
140     ArchSpec B("x86_64-pc-linux");
141 
142     EXPECT_FALSE(A.IsValid());
143     ASSERT_TRUE(B.IsValid());
144     EXPECT_EQ(llvm::Triple::ArchType::x86_64, B.GetTriple().getArch());
145     EXPECT_EQ(llvm::Triple::VendorType::PC, B.GetTriple().getVendor());
146     EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS());
147     EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, B.GetCore());
148 
149     A.MergeFrom(B);
150     ASSERT_TRUE(A.IsValid());
151     EXPECT_EQ(llvm::Triple::ArchType::x86_64, A.GetTriple().getArch());
152     EXPECT_EQ(llvm::Triple::VendorType::PC, A.GetTriple().getVendor());
153     EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
154     EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, A.GetCore());
155   }
156   {
157     ArchSpec A("aarch64");
158     ArchSpec B("aarch64--linux-android");
159 
160     ArchSpec C("arm64_32");
161     ArchSpec D("arm64_32--watchos");
162 
163     EXPECT_TRUE(A.IsValid());
164     EXPECT_TRUE(B.IsValid());
165     EXPECT_TRUE(C.IsValid());
166     EXPECT_TRUE(D.IsValid());
167 
168     EXPECT_EQ(llvm::Triple::ArchType::aarch64, B.GetTriple().getArch());
169     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
170               B.GetTriple().getVendor());
171     EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS());
172     EXPECT_EQ(llvm::Triple::EnvironmentType::Android,
173               B.GetTriple().getEnvironment());
174 
175     A.MergeFrom(B);
176     EXPECT_EQ(llvm::Triple::ArchType::aarch64, A.GetTriple().getArch());
177     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
178               A.GetTriple().getVendor());
179     EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
180     EXPECT_EQ(llvm::Triple::EnvironmentType::Android,
181               A.GetTriple().getEnvironment());
182 
183     EXPECT_EQ(llvm::Triple::ArchType::aarch64_32, D.GetTriple().getArch());
184     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
185               D.GetTriple().getVendor());
186     EXPECT_EQ(llvm::Triple::OSType::WatchOS, D.GetTriple().getOS());
187 
188     C.MergeFrom(D);
189     EXPECT_EQ(llvm::Triple::ArchType::aarch64_32, C.GetTriple().getArch());
190     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
191               C.GetTriple().getVendor());
192     EXPECT_EQ(llvm::Triple::OSType::WatchOS, C.GetTriple().getOS());
193   }
194   {
195     ArchSpec A, B;
196     A.SetArchitecture(eArchTypeELF, llvm::ELF::EM_ARM,
197                       LLDB_INVALID_CPUTYPE, llvm::ELF::ELFOSABI_NONE);
198     B.SetArchitecture(eArchTypeELF, llvm::ELF::EM_ARM,
199                       LLDB_INVALID_CPUTYPE, llvm::ELF::ELFOSABI_LINUX);
200 
201     EXPECT_TRUE(A.IsValid());
202     EXPECT_TRUE(B.IsValid());
203 
204     EXPECT_EQ(llvm::Triple::ArchType::arm, B.GetTriple().getArch());
205     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
206               B.GetTriple().getVendor());
207     EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS());
208     EXPECT_EQ(llvm::Triple::EnvironmentType::UnknownEnvironment,
209               B.GetTriple().getEnvironment());
210 
211     A.MergeFrom(B);
212     EXPECT_EQ(llvm::Triple::ArchType::arm, A.GetTriple().getArch());
213     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
214               A.GetTriple().getVendor());
215     EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
216     EXPECT_EQ(llvm::Triple::EnvironmentType::UnknownEnvironment,
217               A.GetTriple().getEnvironment());
218   }
219   {
220     ArchSpec A("arm--linux-eabihf");
221     ArchSpec B("armv8l--linux-gnueabihf");
222 
223     EXPECT_TRUE(A.IsValid());
224     EXPECT_TRUE(B.IsValid());
225 
226     EXPECT_EQ(llvm::Triple::ArchType::arm, A.GetTriple().getArch());
227     EXPECT_EQ(llvm::Triple::ArchType::arm, B.GetTriple().getArch());
228 
229     EXPECT_EQ(ArchSpec::eCore_arm_generic, A.GetCore());
230     EXPECT_EQ(ArchSpec::eCore_arm_armv8l, B.GetCore());
231 
232     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
233               A.GetTriple().getVendor());
234     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
235               B.GetTriple().getVendor());
236 
237     EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
238     EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS());
239 
240     EXPECT_EQ(llvm::Triple::EnvironmentType::EABIHF,
241               A.GetTriple().getEnvironment());
242     EXPECT_EQ(llvm::Triple::EnvironmentType::GNUEABIHF,
243               B.GetTriple().getEnvironment());
244 
245     A.MergeFrom(B);
246     EXPECT_EQ(llvm::Triple::ArchType::arm, A.GetTriple().getArch());
247     EXPECT_EQ(ArchSpec::eCore_arm_armv8l, A.GetCore());
248     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
249               A.GetTriple().getVendor());
250     EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
251     EXPECT_EQ(llvm::Triple::EnvironmentType::EABIHF,
252               A.GetTriple().getEnvironment());
253   }
254 }
255 
256 TEST(ArchSpecTest, MergeFromMachOUnknown) {
257   class MyArchSpec : public ArchSpec {
258   public:
259     MyArchSpec() {
260       this->SetTriple("unknown-mach-64");
261       this->m_core = ArchSpec::eCore_uknownMach64;
262       this->m_byte_order = eByteOrderLittle;
263       this->m_flags = 0;
264     }
265   };
266 
267   MyArchSpec A;
268   ASSERT_TRUE(A.IsValid());
269   MyArchSpec B;
270   ASSERT_TRUE(B.IsValid());
271   A.MergeFrom(B);
272   ASSERT_EQ(A.GetCore(), ArchSpec::eCore_uknownMach64);
273 }
274 
275 TEST(ArchSpecTest, Compatibility) {
276   {
277     ArchSpec A("x86_64-apple-macosx10.12");
278     ArchSpec B("x86_64-apple-macosx10.12");
279     ASSERT_TRUE(A.IsExactMatch(B));
280     ASSERT_TRUE(A.IsCompatibleMatch(B));
281   }
282   {
283     // The version information is auxiliary to support availablity but
284     // doesn't affect compatibility.
285     ArchSpec A("x86_64-apple-macosx10.11");
286     ArchSpec B("x86_64-apple-macosx10.12");
287     ASSERT_TRUE(A.IsExactMatch(B));
288     ASSERT_TRUE(A.IsCompatibleMatch(B));
289   }
290   {
291     ArchSpec A("x86_64-apple-macosx10.13");
292     ArchSpec B("x86_64h-apple-macosx10.13");
293     ASSERT_FALSE(A.IsExactMatch(B));
294     ASSERT_TRUE(A.IsCompatibleMatch(B));
295   }
296   {
297     ArchSpec A("x86_64-apple-macosx");
298     ArchSpec B("x86_64-apple-ios-simulator");
299     ASSERT_FALSE(A.IsExactMatch(B));
300     ASSERT_FALSE(A.IsCompatibleMatch(B));
301   }
302   {
303     ArchSpec A("x86_64-*-*");
304     ArchSpec B("x86_64-apple-ios-simulator");
305     ASSERT_FALSE(A.IsExactMatch(B));
306     ASSERT_FALSE(A.IsCompatibleMatch(B));
307   }
308   {
309     ArchSpec A("arm64-*-*");
310     ArchSpec B("arm64-apple-ios");
311     ASSERT_FALSE(A.IsExactMatch(B));
312     // FIXME: This looks unintuitive and we should investigate whether
313     // this is the desired behavior.
314     ASSERT_FALSE(A.IsCompatibleMatch(B));
315   }
316   {
317     ArchSpec A("x86_64-*-*");
318     ArchSpec B("x86_64-apple-ios-simulator");
319     ASSERT_FALSE(A.IsExactMatch(B));
320     // FIXME: See above, though the extra environment complicates things.
321     ASSERT_FALSE(A.IsCompatibleMatch(B));
322   }
323   {
324     ArchSpec A("x86_64");
325     ArchSpec B("x86_64-apple-macosx10.14");
326     // FIXME: The exact match also looks unintuitive.
327     ASSERT_TRUE(A.IsExactMatch(B));
328     ASSERT_TRUE(A.IsCompatibleMatch(B));
329   }
330 }
331 
332 TEST(ArchSpecTest, OperatorBool) {
333   EXPECT_FALSE(ArchSpec());
334   EXPECT_TRUE(ArchSpec("x86_64-pc-linux"));
335 }
336 
337 TEST(ArchSpecTest, TripleComponentsWereSpecified) {
338   {
339     ArchSpec A("");
340     ArchSpec B("-");
341     ArchSpec C("--");
342     ArchSpec D("---");
343 
344     ASSERT_FALSE(A.TripleVendorWasSpecified());
345     ASSERT_FALSE(A.TripleOSWasSpecified());
346     ASSERT_FALSE(A.TripleEnvironmentWasSpecified());
347 
348     ASSERT_FALSE(B.TripleVendorWasSpecified());
349     ASSERT_FALSE(B.TripleOSWasSpecified());
350     ASSERT_FALSE(B.TripleEnvironmentWasSpecified());
351 
352     ASSERT_FALSE(C.TripleVendorWasSpecified());
353     ASSERT_FALSE(C.TripleOSWasSpecified());
354     ASSERT_FALSE(C.TripleEnvironmentWasSpecified());
355 
356     ASSERT_FALSE(D.TripleVendorWasSpecified());
357     ASSERT_FALSE(D.TripleOSWasSpecified());
358     ASSERT_FALSE(D.TripleEnvironmentWasSpecified());
359   }
360   {
361     // TODO: llvm::Triple::normalize treats the missing components from these
362     // triples as specified unknown components instead of unspecified
363     // components. We need to either change the behavior in llvm or work around
364     // this in lldb.
365     ArchSpec A("armv7");
366     ArchSpec B("armv7-");
367     ArchSpec C("armv7--");
368     ArchSpec D("armv7---");
369 
370     ASSERT_FALSE(A.TripleVendorWasSpecified());
371     ASSERT_FALSE(A.TripleOSWasSpecified());
372     ASSERT_FALSE(A.TripleEnvironmentWasSpecified());
373 
374     ASSERT_TRUE(B.TripleVendorWasSpecified());
375     ASSERT_FALSE(B.TripleOSWasSpecified());
376     ASSERT_FALSE(B.TripleEnvironmentWasSpecified());
377 
378     ASSERT_TRUE(C.TripleVendorWasSpecified());
379     ASSERT_TRUE(C.TripleOSWasSpecified());
380     ASSERT_FALSE(C.TripleEnvironmentWasSpecified());
381 
382     ASSERT_TRUE(D.TripleVendorWasSpecified());
383     ASSERT_TRUE(D.TripleOSWasSpecified());
384     ASSERT_TRUE(D.TripleEnvironmentWasSpecified());
385   }
386   {
387     ArchSpec A("x86_64-unknown");
388     ArchSpec B("powerpc-unknown-linux");
389     ArchSpec C("i386-pc-windows-msvc");
390     ArchSpec D("aarch64-unknown-linux-android");
391 
392     ASSERT_TRUE(A.TripleVendorWasSpecified());
393     ASSERT_FALSE(A.TripleOSWasSpecified());
394     ASSERT_FALSE(A.TripleEnvironmentWasSpecified());
395 
396     ASSERT_TRUE(B.TripleVendorWasSpecified());
397     ASSERT_TRUE(B.TripleOSWasSpecified());
398     ASSERT_FALSE(B.TripleEnvironmentWasSpecified());
399 
400     ASSERT_TRUE(C.TripleVendorWasSpecified());
401     ASSERT_TRUE(C.TripleOSWasSpecified());
402     ASSERT_TRUE(C.TripleEnvironmentWasSpecified());
403 
404     ASSERT_TRUE(D.TripleVendorWasSpecified());
405     ASSERT_TRUE(D.TripleOSWasSpecified());
406     ASSERT_TRUE(D.TripleEnvironmentWasSpecified());
407   }
408 }
409