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