1//===-- XcodeSDKModuleTests.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 "Plugins/Platform/MacOSX/PlatformMacOSX.h"
10#include "Plugins/SymbolFile/DWARF/DWARFCompileUnit.h"
11#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
12#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
13#include "TestingSupport/Symbol/YAMLModuleTester.h"
14#include "lldb/Core/PluginManager.h"
15#include "llvm/Support/Error.h"
16#include "llvm/Support/Path.h"
17#include "gmock/gmock.h"
18#include "gtest/gtest.h"
19
20using namespace lldb;
21using namespace lldb_private;
22using namespace lldb_private::plugin::dwarf;
23
24#ifdef __APPLE__
25namespace {
26class XcodeSDKModuleTests : public testing::Test {
27 SubsystemRAII<HostInfoBase, PlatformMacOSX> subsystems;
28};
29
30struct SDKPathParsingTestData {
31 /// Each path will be put into a new CU's
32 /// DW_AT_LLVM_sysroot.
33 std::vector<llvm::StringRef> input_sdk_paths;
34
35 /// 'true' if we expect \ref GetSDKPathFromDebugInfo
36 /// to notify us about an SDK mismatch.
37 bool expect_mismatch;
38
39 /// 'true if the test expects the parsed SDK to
40 /// be an internal one.
41 bool expect_internal_sdk;
42
43 /// A substring that the final parsed sdk
44 /// is expected to contain.
45 llvm::StringRef expect_sdk_path_pattern;
46};
47
48struct SDKPathParsingMultiparamTests
49 : public XcodeSDKModuleTests,
50 public testing::WithParamInterface<SDKPathParsingTestData> {
51 std::vector<std::string>
52 createCompileUnits(std::vector<llvm::StringRef> const &sdk_paths) {
53 std::vector<std::string> compile_units;
54
55 for (auto sdk_path : sdk_paths) {
56 compile_units.emplace_back(llvm::formatv(
57 R"(
58 - Version: 2
59 AddrSize: 8
60 AbbrevTableID: 0
61 AbbrOffset: 0x0
62 Entries:
63 - AbbrCode: 0x00000001
64 Values:
65 - Value: 0x000000000000000C
66 - CStr: {0}
67 - CStr: {1}
68 - AbbrCode: 0x00000000
69 )",
70 llvm::sys::path::filename(sdk_path, llvm::sys::path::Style::posix),
71 sdk_path));
72 }
73
74 return compile_units;
75 }
76};
77} // namespace
78
79TEST_F(XcodeSDKModuleTests, TestModuleGetXcodeSDK) {
80 const char *yamldata = R"(
81--- !ELF
82FileHeader:
83 Class: ELFCLASS64
84 Data: ELFDATA2LSB
85 Type: ET_EXEC
86 Machine: EM_386
87DWARF:
88 debug_str:
89 - MacOSX10.9.sdk
90 debug_abbrev:
91 - Table:
92 - Code: 0x00000001
93 Tag: DW_TAG_compile_unit
94 Children: DW_CHILDREN_no
95 Attributes:
96 - Attribute: DW_AT_language
97 Form: DW_FORM_data2
98 - Attribute: DW_AT_APPLE_sdk
99 Form: DW_FORM_strp
100 debug_info:
101 - Version: 2
102 AddrSize: 8
103 Entries:
104 - AbbrCode: 0x00000001
105 Values:
106 - Value: 0x000000000000000C
107 - Value: 0x0000000000000000
108 - AbbrCode: 0x00000000
109...
110)";
111
112 YAMLModuleTester t(yamldata);
113 DWARFUnit *dwarf_unit = t.GetDwarfUnit();
114 auto *dwarf_cu = llvm::cast<DWARFCompileUnit>(dwarf_unit);
115 ASSERT_TRUE(static_cast<bool>(dwarf_cu));
116 SymbolFileDWARF &sym_file = dwarf_cu->GetSymbolFileDWARF();
117 CompUnitSP comp_unit = sym_file.GetCompileUnitAtIndex(0);
118 ASSERT_TRUE(static_cast<bool>(comp_unit.get()));
119 ModuleSP module = t.GetModule();
120 ASSERT_EQ(module->GetSourceMappingList().GetSize(), 0u);
121 XcodeSDK sdk = sym_file.ParseXcodeSDK(*comp_unit);
122 ASSERT_EQ(sdk.GetType(), XcodeSDK::Type::MacOSX);
123 ASSERT_EQ(module->GetSourceMappingList().GetSize(), 1u);
124}
125
126TEST_F(XcodeSDKModuleTests, TestSDKPathFromDebugInfo_InvalidSDKPath) {
127 // Tests that parsing a CU with an invalid SDK directory name fails.
128
129 const char *yamldata = R"(
130--- !ELF
131FileHeader:
132 Class: ELFCLASS64
133 Data: ELFDATA2LSB
134 Type: ET_EXEC
135 Machine: EM_386
136DWARF:
137 debug_abbrev:
138 - Table:
139 - Code: 0x00000001
140 Tag: DW_TAG_compile_unit
141 Children: DW_CHILDREN_no
142 Attributes:
143 - Attribute: DW_AT_language
144 Form: DW_FORM_data2
145 - Attribute: DW_AT_APPLE_sdk
146 Form: DW_FORM_string
147 debug_info:
148 - Version: 2
149 AddrSize: 8
150 AbbrevTableID: 0
151 AbbrOffset: 0x0
152 Entries:
153 - AbbrCode: 0x00000001
154 Values:
155 - Value: 0x000000000000000C
156 - CStr: "1abc@defgh2"
157 - AbbrCode: 0x00000000
158...
159)";
160
161 YAMLModuleTester t(yamldata);
162 ModuleSP module = t.GetModule();
163 ASSERT_NE(module, nullptr);
164
165 auto path_or_err = PlatformDarwin::ResolveSDKPathFromDebugInfo(*module);
166 EXPECT_FALSE(static_cast<bool>(path_or_err));
167 llvm::consumeError(path_or_err.takeError());
168}
169
170TEST_F(XcodeSDKModuleTests, TestSDKPathFromDebugInfo_No_DW_AT_APPLE_sdk) {
171 // Tests that parsing a CU without a DW_AT_APPLE_sdk fails.
172
173 const char *yamldata = R"(
174--- !ELF
175FileHeader:
176 Class: ELFCLASS64
177 Data: ELFDATA2LSB
178 Type: ET_EXEC
179 Machine: EM_386
180DWARF:
181 debug_abbrev:
182 - Table:
183 - Code: 0x00000001
184 Tag: DW_TAG_compile_unit
185 Children: DW_CHILDREN_no
186 Attributes:
187 - Attribute: DW_AT_language
188 Form: DW_FORM_data2
189 - Attribute: DW_AT_LLVM_sysroot
190 Form: DW_FORM_string
191 debug_info:
192 - Version: 2
193 AddrSize: 8
194 AbbrevTableID: 0
195 AbbrOffset: 0x0
196 Entries:
197 - AbbrCode: 0x00000001
198 Values:
199 - Value: 0x000000000000000C
200 - CStr: "/Library/Developer/CommandLineTools/SDKs/iPhoneOS14.0.Internal.sdk"
201 - AbbrCode: 0x00000000
202...
203)";
204
205 YAMLModuleTester t(yamldata);
206 ModuleSP module = t.GetModule();
207 ASSERT_NE(module, nullptr);
208
209 auto path_or_err = PlatformDarwin::ResolveSDKPathFromDebugInfo(*module);
210 EXPECT_FALSE(static_cast<bool>(path_or_err));
211 llvm::consumeError(path_or_err.takeError());
212}
213
214TEST_P(SDKPathParsingMultiparamTests, TestSDKPathFromDebugInfo) {
215 // Tests that we can parse the SDK path from debug-info.
216 // In the presence of multiple compile units, one of which
217 // points to an internal SDK, we should pick the internal SDK.
218
219 std::string yamldata = R"(
220--- !ELF
221FileHeader:
222 Class: ELFCLASS64
223 Data: ELFDATA2LSB
224 Type: ET_EXEC
225 Machine: EM_386
226DWARF:
227 debug_abbrev:
228 - Table:
229 - Code: 0x00000001
230 Tag: DW_TAG_compile_unit
231 Children: DW_CHILDREN_no
232 Attributes:
233 - Attribute: DW_AT_language
234 Form: DW_FORM_data2
235 - Attribute: DW_AT_APPLE_sdk
236 Form: DW_FORM_string
237 - Attribute: DW_AT_LLVM_sysroot
238 Form: DW_FORM_string
239 debug_info:
240)";
241
242 auto [input_sdk_paths, expect_mismatch, expect_internal_sdk,
243 expect_sdk_path_pattern] = GetParam();
244
245 for (auto &&sdk : createCompileUnits(input_sdk_paths))
246 yamldata += std::move(sdk);
247
248 YAMLModuleTester t(yamldata);
249 DWARFUnit *dwarf_unit = t.GetDwarfUnit();
250 auto *dwarf_cu = llvm::cast<DWARFCompileUnit>(dwarf_unit);
251 ASSERT_TRUE(static_cast<bool>(dwarf_cu));
252 SymbolFileDWARF &sym_file = dwarf_cu->GetSymbolFileDWARF();
253 ASSERT_EQ(sym_file.GetNumCompileUnits(), input_sdk_paths.size());
254 ModuleSP module = t.GetModule();
255 ASSERT_NE(module, nullptr);
256
257 auto sdk_or_err = PlatformDarwin::GetSDKPathFromDebugInfo(*module);
258 ASSERT_TRUE(static_cast<bool>(sdk_or_err));
259
260 auto [sdk, found_mismatch] = *sdk_or_err;
261
262 EXPECT_EQ(found_mismatch, expect_mismatch);
263 EXPECT_EQ(sdk.IsAppleInternalSDK(), expect_internal_sdk);
264 EXPECT_NE(sdk.GetString().find(expect_sdk_path_pattern), std::string::npos);
265}
266
267SDKPathParsingTestData sdkPathParsingTestCases[] = {
268 /// Multiple CUs with a mix of internal and public SDKs
269 {.input_sdk_paths =
270 {"/Library/Developer/CommandLineTools/SDKs/MacOSX10.9.sdk",
271 "/invalid/path/to/something.invalid.sdk",
272 "/Library/Developer/CommandLineTools/SDKs/iPhoneOS14.0.Internal.sdk",
273 "/Library/Developer/CommandLineTools/SDKs/MacOSX10.9.sdk"},
274 .expect_mismatch = true,
275 .expect_internal_sdk = true,
276 .expect_sdk_path_pattern = "Internal.sdk"},
277
278 /// Single CU with a public SDK
279 {.input_sdk_paths =
280 {"/Library/Developer/CommandLineTools/SDKs/MacOSX10.9.sdk"},
281 .expect_mismatch = false,
282 .expect_internal_sdk = false,
283 .expect_sdk_path_pattern = "MacOSX10.9.sdk"},
284
285 /// Single CU with an internal SDK
286 {.input_sdk_paths =
287 {"/Library/Developer/CommandLineTools/SDKs/iPhoneOS14.0.Internal.sdk"},
288 .expect_mismatch = false,
289 .expect_internal_sdk = true,
290 .expect_sdk_path_pattern = "Internal.sdk"},
291
292 /// Two CUs with an internal SDK each
293 {.input_sdk_paths =
294 {"/Library/Developer/CommandLineTools/SDKs/iPhoneOS14.0.Internal.sdk",
295 "/Library/Developer/CommandLineTools/SDKs/iPhoneOS12.9.Internal.sdk"},
296 .expect_mismatch = false,
297 .expect_internal_sdk = true,
298 .expect_sdk_path_pattern = "Internal.sdk"},
299
300 /// Two CUs with an internal SDK each
301 {.input_sdk_paths =
302 {"/Library/Developer/CommandLineTools/SDKs/iPhoneOS14.1.sdk",
303 "/Library/Developer/CommandLineTools/SDKs/MacOSX11.3.sdk"},
304 .expect_mismatch = false,
305 .expect_internal_sdk = false,
306 .expect_sdk_path_pattern = "iPhoneOS14.1.sdk"},
307};
308
309INSTANTIATE_TEST_CASE_P(SDKPathParsingTests, SDKPathParsingMultiparamTests,
310 ::testing::ValuesIn(sdkPathParsingTestCases));
311#endif
312

source code of lldb/unittests/SymbolFile/DWARF/XcodeSDKModuleTests.cpp