/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- PlatformDarwin.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 "PlatformDarwin.h" |
10 | | |
11 | | #include <cstring> |
12 | | |
13 | | #include <algorithm> |
14 | | #include <memory> |
15 | | #include <mutex> |
16 | | #include <optional> |
17 | | |
18 | | #include "lldb/Breakpoint/BreakpointLocation.h" |
19 | | #include "lldb/Breakpoint/BreakpointSite.h" |
20 | | #include "lldb/Core/Debugger.h" |
21 | | #include "lldb/Core/Module.h" |
22 | | #include "lldb/Core/ModuleSpec.h" |
23 | | #include "lldb/Core/PluginManager.h" |
24 | | #include "lldb/Core/Section.h" |
25 | | #include "lldb/Host/Host.h" |
26 | | #include "lldb/Host/HostInfo.h" |
27 | | #include "lldb/Host/XML.h" |
28 | | #include "lldb/Interpreter/CommandInterpreter.h" |
29 | | #include "lldb/Interpreter/OptionValueProperties.h" |
30 | | #include "lldb/Interpreter/OptionValueString.h" |
31 | | #include "lldb/Interpreter/Options.h" |
32 | | #include "lldb/Symbol/LocateSymbolFile.h" |
33 | | #include "lldb/Symbol/ObjectFile.h" |
34 | | #include "lldb/Symbol/SymbolFile.h" |
35 | | #include "lldb/Symbol/SymbolVendor.h" |
36 | | #include "lldb/Target/Platform.h" |
37 | | #include "lldb/Target/Process.h" |
38 | | #include "lldb/Target/Target.h" |
39 | | #include "lldb/Utility/LLDBLog.h" |
40 | | #include "lldb/Utility/Log.h" |
41 | | #include "lldb/Utility/ProcessInfo.h" |
42 | | #include "lldb/Utility/Status.h" |
43 | | #include "lldb/Utility/Timer.h" |
44 | | #include "llvm/ADT/STLExtras.h" |
45 | | #include "llvm/Support/Error.h" |
46 | | #include "llvm/Support/FileSystem.h" |
47 | | #include "llvm/Support/Threading.h" |
48 | | #include "llvm/Support/VersionTuple.h" |
49 | | |
50 | | #if defined(__APPLE__) |
51 | | #include <TargetConditionals.h> |
52 | | #endif |
53 | | |
54 | | using namespace lldb; |
55 | | using namespace lldb_private; |
56 | | |
57 | 0 | static Status ExceptionMaskValidator(const char *string, void *unused) { |
58 | 0 | Status error; |
59 | 0 | llvm::StringRef str_ref(string); |
60 | 0 | llvm::SmallVector<llvm::StringRef> candidates; |
61 | 0 | str_ref.split(candidates, '|'); |
62 | 0 | for (auto candidate : candidates) { |
63 | 0 | if (!(candidate == "EXC_BAD_ACCESS" |
64 | 0 | || candidate == "EXC_BAD_INSTRUCTION" |
65 | 0 | || candidate == "EXC_ARITHMETIC" |
66 | 0 | || candidate == "EXC_RESOURCE" |
67 | 0 | || candidate == "EXC_GUARD" |
68 | 0 | || candidate == "EXC_SYSCALL")) { |
69 | 0 | error.SetErrorStringWithFormat("invalid exception type: '%s'", |
70 | 0 | candidate.str().c_str()); |
71 | 0 | return error; |
72 | 0 | } |
73 | 0 | } |
74 | 0 | return {}; |
75 | 0 | } |
76 | | |
77 | | /// Destructor. |
78 | | /// |
79 | | /// The destructor is virtual since this class is designed to be |
80 | | /// inherited from by the plug-in instance. |
81 | 3.99k | PlatformDarwin::~PlatformDarwin() = default; |
82 | | |
83 | | // Static Variables |
84 | | static uint32_t g_initialize_count = 0; |
85 | | |
86 | 35.5k | void PlatformDarwin::Initialize() { |
87 | 35.5k | Platform::Initialize(); |
88 | | |
89 | 35.5k | if (g_initialize_count++ == 0) { |
90 | 3.94k | PluginManager::RegisterPlugin(PlatformDarwin::GetPluginNameStatic(), |
91 | 3.94k | PlatformDarwin::GetDescriptionStatic(), |
92 | 3.94k | PlatformDarwin::CreateInstance, |
93 | 3.94k | PlatformDarwin::DebuggerInitialize); |
94 | 3.94k | } |
95 | 35.5k | } |
96 | | |
97 | 27.5k | void PlatformDarwin::Terminate() { |
98 | 27.5k | if (g_initialize_count > 0) { |
99 | 27.5k | if (--g_initialize_count == 0) { |
100 | 3 | PluginManager::UnregisterPlugin(PlatformDarwin::CreateInstance); |
101 | 3 | } |
102 | 27.5k | } |
103 | | |
104 | 27.5k | Platform::Terminate(); |
105 | 27.5k | } |
106 | | |
107 | 3.94k | llvm::StringRef PlatformDarwin::GetDescriptionStatic() { |
108 | 3.94k | return "Darwin platform plug-in."; |
109 | 3.94k | } |
110 | | |
111 | 243 | PlatformSP PlatformDarwin::CreateInstance(bool force, const ArchSpec *arch) { |
112 | | // We only create subclasses of the PlatformDarwin plugin. |
113 | 243 | return PlatformSP(); |
114 | 243 | } |
115 | | |
116 | | #define LLDB_PROPERTIES_platformdarwin |
117 | | #include "PlatformMacOSXProperties.inc" |
118 | | |
119 | | #define LLDB_PROPERTIES_platformdarwin |
120 | | enum { |
121 | | #include "PlatformMacOSXPropertiesEnum.inc" |
122 | | }; |
123 | | |
124 | | class PlatformDarwinProperties : public Properties { |
125 | | public: |
126 | 9.93k | static llvm::StringRef GetSettingName() { |
127 | 9.93k | static constexpr llvm::StringLiteral g_setting_name("darwin"); |
128 | 9.93k | return g_setting_name; |
129 | 9.93k | } |
130 | | |
131 | 3.88k | PlatformDarwinProperties() : Properties() { |
132 | 3.88k | m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); |
133 | 3.88k | m_collection_sp->Initialize(g_platformdarwin_properties); |
134 | 3.88k | } |
135 | | |
136 | 3.88k | ~PlatformDarwinProperties() override = default; |
137 | | |
138 | 2.22k | const char *GetIgnoredExceptions() const { |
139 | 2.22k | const uint32_t idx = ePropertyIgnoredExceptions; |
140 | 2.22k | const OptionValueString *option_value = |
141 | 2.22k | m_collection_sp->GetPropertyAtIndexAsOptionValueString(idx); |
142 | 2.22k | assert(option_value); |
143 | 2.22k | return option_value->GetCurrentValue(); |
144 | 2.22k | } |
145 | | |
146 | 3.88k | OptionValueString *GetIgnoredExceptionValue() { |
147 | 3.88k | const uint32_t idx = ePropertyIgnoredExceptions; |
148 | 3.88k | OptionValueString *option_value = |
149 | 3.88k | m_collection_sp->GetPropertyAtIndexAsOptionValueString(idx); |
150 | 3.88k | assert(option_value); |
151 | 3.88k | return option_value; |
152 | 3.88k | } |
153 | | }; |
154 | | |
155 | 9.98k | static PlatformDarwinProperties &GetGlobalProperties() { |
156 | 9.98k | static PlatformDarwinProperties g_settings; |
157 | 9.98k | return g_settings; |
158 | 9.98k | } |
159 | | |
160 | | void PlatformDarwin::DebuggerInitialize( |
161 | 6.05k | lldb_private::Debugger &debugger) { |
162 | 6.05k | if (!PluginManager::GetSettingForPlatformPlugin( |
163 | 6.05k | debugger, PlatformDarwinProperties::GetSettingName())) { |
164 | 3.88k | const bool is_global_setting = false; |
165 | 3.88k | PluginManager::CreateSettingForPlatformPlugin( |
166 | 3.88k | debugger, GetGlobalProperties().GetValueProperties(), |
167 | 3.88k | "Properties for the Darwin platform plug-in.", is_global_setting); |
168 | 3.88k | OptionValueString *value = GetGlobalProperties().GetIgnoredExceptionValue(); |
169 | 3.88k | value->SetValidator(ExceptionMaskValidator); |
170 | 3.88k | } |
171 | 6.05k | } |
172 | | |
173 | | Args |
174 | 2.22k | PlatformDarwin::GetExtraStartupCommands() { |
175 | 2.22k | std::string ignored_exceptions |
176 | 2.22k | = GetGlobalProperties().GetIgnoredExceptions(); |
177 | 2.22k | if (ignored_exceptions.empty()) |
178 | 2.22k | return {}; |
179 | 0 | Args ret_args; |
180 | 0 | std::string packet = "QSetIgnoredExceptions:"; |
181 | 0 | packet.append(ignored_exceptions); |
182 | 0 | ret_args.AppendArgument(packet); |
183 | 0 | return ret_args; |
184 | 2.22k | } |
185 | | |
186 | | lldb_private::Status |
187 | | PlatformDarwin::PutFile(const lldb_private::FileSpec &source, |
188 | | const lldb_private::FileSpec &destination, uint32_t uid, |
189 | 1 | uint32_t gid) { |
190 | | // Unconditionally unlink the destination. If it is an executable, |
191 | | // simply opening it and truncating its contents would invalidate |
192 | | // its cached code signature. |
193 | 1 | Unlink(destination); |
194 | 1 | return PlatformPOSIX::PutFile(source, destination, uid, gid); |
195 | 1 | } |
196 | | |
197 | | FileSpecList PlatformDarwin::LocateExecutableScriptingResources( |
198 | 231k | Target *target, Module &module, Stream &feedback_stream) { |
199 | 231k | FileSpecList file_list; |
200 | 231k | if (target && |
201 | 231k | target->GetDebugger().GetScriptLanguage() == eScriptLanguagePython231k ) { |
202 | | // NB some extensions might be meaningful and should not be stripped - |
203 | | // "this.binary.file" |
204 | | // should not lose ".file" but GetFileNameStrippingExtension() will do |
205 | | // precisely that. Ideally, we should have a per-platform list of |
206 | | // extensions (".exe", ".app", ".dSYM", ".framework") which should be |
207 | | // stripped while leaving "this.binary.file" as-is. |
208 | | |
209 | 231k | FileSpec module_spec = module.GetFileSpec(); |
210 | | |
211 | 231k | if (module_spec) { |
212 | 231k | if (SymbolFile *symfile = module.GetSymbolFile()) { |
213 | 230k | ObjectFile *objfile = symfile->GetObjectFile(); |
214 | 230k | if (objfile) { |
215 | 230k | FileSpec symfile_spec(objfile->GetFileSpec()); |
216 | 230k | if (symfile_spec && |
217 | 230k | llvm::StringRef(symfile_spec.GetPath()) |
218 | 225k | .contains_insensitive(".dSYM/Contents/Resources/DWARF") && |
219 | 230k | FileSystem::Instance().Exists(symfile_spec)2.89k ) { |
220 | 5.66k | while (module_spec.GetFilename()) { |
221 | 5.66k | std::string module_basename( |
222 | 5.66k | module_spec.GetFilename().GetCString()); |
223 | 5.66k | std::string original_module_basename(module_basename); |
224 | | |
225 | 5.66k | bool was_keyword = false; |
226 | | |
227 | | // FIXME: for Python, we cannot allow certain characters in |
228 | | // module |
229 | | // filenames we import. Theoretically, different scripting |
230 | | // languages may have different sets of forbidden tokens in |
231 | | // filenames, and that should be dealt with by each |
232 | | // ScriptInterpreter. For now, we just replace dots with |
233 | | // underscores, but if we ever support anything other than |
234 | | // Python we will need to rework this |
235 | 5.66k | std::replace(module_basename.begin(), module_basename.end(), '.', |
236 | 5.66k | '_'); |
237 | 5.66k | std::replace(module_basename.begin(), module_basename.end(), ' ', |
238 | 5.66k | '_'); |
239 | 5.66k | std::replace(module_basename.begin(), module_basename.end(), '-', |
240 | 5.66k | '_'); |
241 | 5.66k | ScriptInterpreter *script_interpreter = |
242 | 5.66k | target->GetDebugger().GetScriptInterpreter(); |
243 | 5.66k | if (script_interpreter && |
244 | 5.66k | script_interpreter->IsReservedWord(module_basename.c_str())) { |
245 | 2 | module_basename.insert(module_basename.begin(), '_'); |
246 | 2 | was_keyword = true; |
247 | 2 | } |
248 | | |
249 | 5.66k | StreamString path_string; |
250 | 5.66k | StreamString original_path_string; |
251 | | // for OSX we are going to be in |
252 | | // .dSYM/Contents/Resources/DWARF/<basename> let us go to |
253 | | // .dSYM/Contents/Resources/Python/<basename>.py and see if the |
254 | | // file exists |
255 | 5.66k | path_string.Printf("%s/../Python/%s.py", |
256 | 5.66k | symfile_spec.GetDirectory().GetCString(), |
257 | 5.66k | module_basename.c_str()); |
258 | 5.66k | original_path_string.Printf( |
259 | 5.66k | "%s/../Python/%s.py", |
260 | 5.66k | symfile_spec.GetDirectory().GetCString(), |
261 | 5.66k | original_module_basename.c_str()); |
262 | 5.66k | FileSpec script_fspec(path_string.GetString()); |
263 | 5.66k | FileSystem::Instance().Resolve(script_fspec); |
264 | 5.66k | FileSpec orig_script_fspec(original_path_string.GetString()); |
265 | 5.66k | FileSystem::Instance().Resolve(orig_script_fspec); |
266 | | |
267 | | // if we did some replacements of reserved characters, and a |
268 | | // file with the untampered name exists, then warn the user |
269 | | // that the file as-is shall not be loaded |
270 | 5.66k | if (module_basename != original_module_basename && |
271 | 5.66k | FileSystem::Instance().Exists(orig_script_fspec)2.80k ) { |
272 | 0 | const char *reason_for_complaint = |
273 | 0 | was_keyword ? "conflicts with a keyword" |
274 | 0 | : "contains reserved characters"; |
275 | 0 | if (FileSystem::Instance().Exists(script_fspec)) |
276 | 0 | feedback_stream.Printf( |
277 | 0 | "warning: the symbol file '%s' contains a debug " |
278 | 0 | "script. However, its name" |
279 | 0 | " '%s' %s and as such cannot be loaded. LLDB will" |
280 | 0 | " load '%s' instead. Consider removing the file with " |
281 | 0 | "the malformed name to" |
282 | 0 | " eliminate this warning.\n", |
283 | 0 | symfile_spec.GetPath().c_str(), |
284 | 0 | original_path_string.GetData(), reason_for_complaint, |
285 | 0 | path_string.GetData()); |
286 | 0 | else |
287 | 0 | feedback_stream.Printf( |
288 | 0 | "warning: the symbol file '%s' contains a debug " |
289 | 0 | "script. However, its name" |
290 | 0 | " %s and as such cannot be loaded. If you intend" |
291 | 0 | " to have this script loaded, please rename '%s' to " |
292 | 0 | "'%s' and retry.\n", |
293 | 0 | symfile_spec.GetPath().c_str(), reason_for_complaint, |
294 | 0 | original_path_string.GetData(), path_string.GetData()); |
295 | 0 | } |
296 | | |
297 | 5.66k | if (FileSystem::Instance().Exists(script_fspec)) { |
298 | 3 | file_list.Append(script_fspec); |
299 | 3 | break; |
300 | 3 | } |
301 | | |
302 | | // If we didn't find the python file, then keep stripping the |
303 | | // extensions and try again |
304 | 5.66k | ConstString filename_no_extension( |
305 | 5.66k | module_spec.GetFileNameStrippingExtension()); |
306 | 5.66k | if (module_spec.GetFilename() == filename_no_extension) |
307 | 2.89k | break; |
308 | | |
309 | 2.77k | module_spec.SetFilename(filename_no_extension); |
310 | 2.77k | } |
311 | 2.89k | } |
312 | 230k | } |
313 | 230k | } |
314 | 231k | } |
315 | 231k | } |
316 | 231k | return file_list; |
317 | 231k | } |
318 | | |
319 | | Status PlatformDarwin::ResolveSymbolFile(Target &target, |
320 | | const ModuleSpec &sym_spec, |
321 | 20 | FileSpec &sym_file) { |
322 | 20 | sym_file = sym_spec.GetSymbolFileSpec(); |
323 | 20 | if (FileSystem::Instance().IsDirectory(sym_file)) { |
324 | 4 | sym_file = Symbols::FindSymbolFileInBundle(sym_file, sym_spec.GetUUIDPtr(), |
325 | 4 | sym_spec.GetArchitecturePtr()); |
326 | 4 | } |
327 | 20 | return {}; |
328 | 20 | } |
329 | | |
330 | | Status PlatformDarwin::GetSharedModule( |
331 | | const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, |
332 | | const FileSpecList *module_search_paths_ptr, |
333 | 0 | llvm::SmallVectorImpl<ModuleSP> *old_modules, bool *did_create_ptr) { |
334 | 0 | Status error; |
335 | 0 | module_sp.reset(); |
336 | |
|
337 | 0 | if (IsRemote()) { |
338 | | // If we have a remote platform always, let it try and locate the shared |
339 | | // module first. |
340 | 0 | if (m_remote_platform_sp) { |
341 | 0 | error = m_remote_platform_sp->GetSharedModule( |
342 | 0 | module_spec, process, module_sp, module_search_paths_ptr, old_modules, |
343 | 0 | did_create_ptr); |
344 | 0 | } |
345 | 0 | } |
346 | |
|
347 | 0 | if (!module_sp) { |
348 | | // Fall back to the local platform and find the file locally |
349 | 0 | error = Platform::GetSharedModule(module_spec, process, module_sp, |
350 | 0 | module_search_paths_ptr, old_modules, |
351 | 0 | did_create_ptr); |
352 | |
|
353 | 0 | const FileSpec &platform_file = module_spec.GetFileSpec(); |
354 | 0 | if (!module_sp && module_search_paths_ptr && platform_file) { |
355 | | // We can try to pull off part of the file path up to the bundle |
356 | | // directory level and try any module search paths... |
357 | 0 | FileSpec bundle_directory; |
358 | 0 | if (Host::GetBundleDirectory(platform_file, bundle_directory)) { |
359 | 0 | if (platform_file == bundle_directory) { |
360 | 0 | ModuleSpec new_module_spec(module_spec); |
361 | 0 | new_module_spec.GetFileSpec() = bundle_directory; |
362 | 0 | if (Host::ResolveExecutableInBundle(new_module_spec.GetFileSpec())) { |
363 | 0 | Status new_error(Platform::GetSharedModule( |
364 | 0 | new_module_spec, process, module_sp, nullptr, old_modules, |
365 | 0 | did_create_ptr)); |
366 | |
|
367 | 0 | if (module_sp) |
368 | 0 | return new_error; |
369 | 0 | } |
370 | 0 | } else { |
371 | 0 | char platform_path[PATH_MAX]; |
372 | 0 | char bundle_dir[PATH_MAX]; |
373 | 0 | platform_file.GetPath(platform_path, sizeof(platform_path)); |
374 | 0 | const size_t bundle_directory_len = |
375 | 0 | bundle_directory.GetPath(bundle_dir, sizeof(bundle_dir)); |
376 | 0 | char new_path[PATH_MAX]; |
377 | 0 | size_t num_module_search_paths = module_search_paths_ptr->GetSize(); |
378 | 0 | for (size_t i = 0; i < num_module_search_paths; ++i) { |
379 | 0 | const size_t search_path_len = |
380 | 0 | module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath( |
381 | 0 | new_path, sizeof(new_path)); |
382 | 0 | if (search_path_len < sizeof(new_path)) { |
383 | 0 | snprintf(new_path + search_path_len, |
384 | 0 | sizeof(new_path) - search_path_len, "/%s", |
385 | 0 | platform_path + bundle_directory_len); |
386 | 0 | FileSpec new_file_spec(new_path); |
387 | 0 | if (FileSystem::Instance().Exists(new_file_spec)) { |
388 | 0 | ModuleSpec new_module_spec(module_spec); |
389 | 0 | new_module_spec.GetFileSpec() = new_file_spec; |
390 | 0 | Status new_error(Platform::GetSharedModule( |
391 | 0 | new_module_spec, process, module_sp, nullptr, old_modules, |
392 | 0 | did_create_ptr)); |
393 | |
|
394 | 0 | if (module_sp) { |
395 | 0 | module_sp->SetPlatformFileSpec(new_file_spec); |
396 | 0 | return new_error; |
397 | 0 | } |
398 | 0 | } |
399 | 0 | } |
400 | 0 | } |
401 | 0 | } |
402 | 0 | } |
403 | 0 | } |
404 | 0 | } |
405 | 0 | if (module_sp) |
406 | 0 | module_sp->SetPlatformFileSpec(module_spec.GetFileSpec()); |
407 | 0 | return error; |
408 | 0 | } |
409 | | |
410 | | size_t |
411 | | PlatformDarwin::GetSoftwareBreakpointTrapOpcode(Target &target, |
412 | 70.6k | BreakpointSite *bp_site) { |
413 | 70.6k | const uint8_t *trap_opcode = nullptr; |
414 | 70.6k | uint32_t trap_opcode_size = 0; |
415 | 70.6k | bool bp_is_thumb = false; |
416 | | |
417 | 70.6k | llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine(); |
418 | 70.6k | switch (machine) { |
419 | 0 | case llvm::Triple::aarch64_32: |
420 | 0 | case llvm::Triple::aarch64: { |
421 | | // 'brk #0' or 0xd4200000 in BE byte order |
422 | 0 | static const uint8_t g_arm64_breakpoint_opcode[] = {0x00, 0x00, 0x20, 0xD4}; |
423 | 0 | trap_opcode = g_arm64_breakpoint_opcode; |
424 | 0 | trap_opcode_size = sizeof(g_arm64_breakpoint_opcode); |
425 | 0 | } break; |
426 | | |
427 | 0 | case llvm::Triple::thumb: |
428 | 0 | bp_is_thumb = true; |
429 | 0 | [[fallthrough]]; |
430 | 0 | case llvm::Triple::arm: { |
431 | 0 | static const uint8_t g_arm_breakpoint_opcode[] = {0xFE, 0xDE, 0xFF, 0xE7}; |
432 | 0 | static const uint8_t g_thumb_breakpooint_opcode[] = {0xFE, 0xDE}; |
433 | | |
434 | | // Auto detect arm/thumb if it wasn't explicitly specified |
435 | 0 | if (!bp_is_thumb) { |
436 | 0 | lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0)); |
437 | 0 | if (bp_loc_sp) |
438 | 0 | bp_is_thumb = bp_loc_sp->GetAddress().GetAddressClass() == |
439 | 0 | AddressClass::eCodeAlternateISA; |
440 | 0 | } |
441 | 0 | if (bp_is_thumb) { |
442 | 0 | trap_opcode = g_thumb_breakpooint_opcode; |
443 | 0 | trap_opcode_size = sizeof(g_thumb_breakpooint_opcode); |
444 | 0 | break; |
445 | 0 | } |
446 | 0 | trap_opcode = g_arm_breakpoint_opcode; |
447 | 0 | trap_opcode_size = sizeof(g_arm_breakpoint_opcode); |
448 | 0 | } break; |
449 | | |
450 | 0 | case llvm::Triple::ppc: |
451 | 0 | case llvm::Triple::ppc64: { |
452 | 0 | static const uint8_t g_ppc_breakpoint_opcode[] = {0x7F, 0xC0, 0x00, 0x08}; |
453 | 0 | trap_opcode = g_ppc_breakpoint_opcode; |
454 | 0 | trap_opcode_size = sizeof(g_ppc_breakpoint_opcode); |
455 | 0 | } break; |
456 | | |
457 | 70.6k | default: |
458 | 70.6k | return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site); |
459 | 70.6k | } |
460 | | |
461 | 0 | if (trap_opcode && trap_opcode_size) { |
462 | 0 | if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) |
463 | 0 | return trap_opcode_size; |
464 | 0 | } |
465 | 0 | return 0; |
466 | 0 | } |
467 | | |
468 | | bool PlatformDarwin::ModuleIsExcludedForUnconstrainedSearches( |
469 | 273k | lldb_private::Target &target, const lldb::ModuleSP &module_sp) { |
470 | 273k | if (!module_sp) |
471 | 0 | return false; |
472 | | |
473 | 273k | ObjectFile *obj_file = module_sp->GetObjectFile(); |
474 | 273k | if (!obj_file) |
475 | 0 | return false; |
476 | | |
477 | 273k | ObjectFile::Type obj_type = obj_file->GetType(); |
478 | 273k | return obj_type == ObjectFile::eTypeDynamicLinker; |
479 | 273k | } |
480 | | |
481 | | void PlatformDarwin::x86GetSupportedArchitectures( |
482 | 7.70k | std::vector<ArchSpec> &archs) { |
483 | 7.70k | ArchSpec host_arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); |
484 | 7.70k | archs.push_back(host_arch); |
485 | | |
486 | 7.70k | if (host_arch.GetCore() == ArchSpec::eCore_x86_64_x86_64h) { |
487 | 0 | archs.push_back(ArchSpec("x86_64-apple-macosx")); |
488 | 0 | archs.push_back(HostInfo::GetArchitecture(HostInfo::eArchKind32)); |
489 | 7.70k | } else { |
490 | 7.70k | ArchSpec host_arch64 = HostInfo::GetArchitecture(HostInfo::eArchKind64); |
491 | 7.70k | if (host_arch.IsExactMatch(host_arch64)) |
492 | 7.70k | archs.push_back(HostInfo::GetArchitecture(HostInfo::eArchKind32)); |
493 | 7.70k | } |
494 | 7.70k | } |
495 | | |
496 | 83 | static llvm::ArrayRef<const char *> GetCompatibleArchs(ArchSpec::Core core) { |
497 | 83 | switch (core) { |
498 | 83 | default: |
499 | 83 | [[fallthrough]]; |
500 | 83 | case ArchSpec::eCore_arm_arm64e: { |
501 | 83 | static const char *g_arm64e_compatible_archs[] = { |
502 | 83 | "arm64e", "arm64", "armv7", "armv7f", "armv7k", "armv7s", |
503 | 83 | "armv7m", "armv7em", "armv6m", "armv6", "armv5", "armv4", |
504 | 83 | "arm", "thumbv7", "thumbv7f", "thumbv7k", "thumbv7s", "thumbv7m", |
505 | 83 | "thumbv7em", "thumbv6m", "thumbv6", "thumbv5", "thumbv4t", "thumb", |
506 | 83 | }; |
507 | 83 | return {g_arm64e_compatible_archs}; |
508 | 83 | } |
509 | 0 | case ArchSpec::eCore_arm_arm64: { |
510 | 0 | static const char *g_arm64_compatible_archs[] = { |
511 | 0 | "arm64", "armv7", "armv7f", "armv7k", "armv7s", "armv7m", |
512 | 0 | "armv7em", "armv6m", "armv6", "armv5", "armv4", "arm", |
513 | 0 | "thumbv7", "thumbv7f", "thumbv7k", "thumbv7s", "thumbv7m", "thumbv7em", |
514 | 0 | "thumbv6m", "thumbv6", "thumbv5", "thumbv4t", "thumb", |
515 | 0 | }; |
516 | 0 | return {g_arm64_compatible_archs}; |
517 | 83 | } |
518 | 0 | case ArchSpec::eCore_arm_armv7: { |
519 | 0 | static const char *g_armv7_compatible_archs[] = { |
520 | 0 | "armv7", "armv6m", "armv6", "armv5", "armv4", "arm", |
521 | 0 | "thumbv7", "thumbv6m", "thumbv6", "thumbv5", "thumbv4t", "thumb", |
522 | 0 | }; |
523 | 0 | return {g_armv7_compatible_archs}; |
524 | 83 | } |
525 | 0 | case ArchSpec::eCore_arm_armv7f: { |
526 | 0 | static const char *g_armv7f_compatible_archs[] = { |
527 | 0 | "armv7f", "armv7", "armv6m", "armv6", "armv5", |
528 | 0 | "armv4", "arm", "thumbv7f", "thumbv7", "thumbv6m", |
529 | 0 | "thumbv6", "thumbv5", "thumbv4t", "thumb", |
530 | 0 | }; |
531 | 0 | return {g_armv7f_compatible_archs}; |
532 | 83 | } |
533 | 0 | case ArchSpec::eCore_arm_armv7k: { |
534 | 0 | static const char *g_armv7k_compatible_archs[] = { |
535 | 0 | "armv7k", "armv7", "armv6m", "armv6", "armv5", |
536 | 0 | "armv4", "arm", "thumbv7k", "thumbv7", "thumbv6m", |
537 | 0 | "thumbv6", "thumbv5", "thumbv4t", "thumb", |
538 | 0 | }; |
539 | 0 | return {g_armv7k_compatible_archs}; |
540 | 83 | } |
541 | 0 | case ArchSpec::eCore_arm_armv7s: { |
542 | 0 | static const char *g_armv7s_compatible_archs[] = { |
543 | 0 | "armv7s", "armv7", "armv6m", "armv6", "armv5", |
544 | 0 | "armv4", "arm", "thumbv7s", "thumbv7", "thumbv6m", |
545 | 0 | "thumbv6", "thumbv5", "thumbv4t", "thumb", |
546 | 0 | }; |
547 | 0 | return {g_armv7s_compatible_archs}; |
548 | 83 | } |
549 | 0 | case ArchSpec::eCore_arm_armv7m: { |
550 | 0 | static const char *g_armv7m_compatible_archs[] = { |
551 | 0 | "armv7m", "armv7", "armv6m", "armv6", "armv5", |
552 | 0 | "armv4", "arm", "thumbv7m", "thumbv7", "thumbv6m", |
553 | 0 | "thumbv6", "thumbv5", "thumbv4t", "thumb", |
554 | 0 | }; |
555 | 0 | return {g_armv7m_compatible_archs}; |
556 | 83 | } |
557 | 0 | case ArchSpec::eCore_arm_armv7em: { |
558 | 0 | static const char *g_armv7em_compatible_archs[] = { |
559 | 0 | "armv7em", "armv7", "armv6m", "armv6", "armv5", |
560 | 0 | "armv4", "arm", "thumbv7em", "thumbv7", "thumbv6m", |
561 | 0 | "thumbv6", "thumbv5", "thumbv4t", "thumb", |
562 | 0 | }; |
563 | 0 | return {g_armv7em_compatible_archs}; |
564 | 83 | } |
565 | 0 | case ArchSpec::eCore_arm_armv6m: { |
566 | 0 | static const char *g_armv6m_compatible_archs[] = { |
567 | 0 | "armv6m", "armv6", "armv5", "armv4", "arm", |
568 | 0 | "thumbv6m", "thumbv6", "thumbv5", "thumbv4t", "thumb", |
569 | 0 | }; |
570 | 0 | return {g_armv6m_compatible_archs}; |
571 | 83 | } |
572 | 0 | case ArchSpec::eCore_arm_armv6: { |
573 | 0 | static const char *g_armv6_compatible_archs[] = { |
574 | 0 | "armv6", "armv5", "armv4", "arm", |
575 | 0 | "thumbv6", "thumbv5", "thumbv4t", "thumb", |
576 | 0 | }; |
577 | 0 | return {g_armv6_compatible_archs}; |
578 | 83 | } |
579 | 0 | case ArchSpec::eCore_arm_armv5: { |
580 | 0 | static const char *g_armv5_compatible_archs[] = { |
581 | 0 | "armv5", "armv4", "arm", "thumbv5", "thumbv4t", "thumb", |
582 | 0 | }; |
583 | 0 | return {g_armv5_compatible_archs}; |
584 | 83 | } |
585 | 0 | case ArchSpec::eCore_arm_armv4: { |
586 | 0 | static const char *g_armv4_compatible_archs[] = { |
587 | 0 | "armv4", |
588 | 0 | "arm", |
589 | 0 | "thumbv4t", |
590 | 0 | "thumb", |
591 | 0 | }; |
592 | 0 | return {g_armv4_compatible_archs}; |
593 | 83 | } |
594 | 83 | } |
595 | 0 | return {}; |
596 | 83 | } |
597 | | |
598 | | /// The architecture selection rules for arm processors These cpu subtypes have |
599 | | /// distinct names (e.g. armv7f) but armv7 binaries run fine on an armv7f |
600 | | /// processor. |
601 | | void PlatformDarwin::ARMGetSupportedArchitectures( |
602 | 83 | std::vector<ArchSpec> &archs, std::optional<llvm::Triple::OSType> os) { |
603 | 83 | const ArchSpec system_arch = GetSystemArchitecture(); |
604 | 83 | const ArchSpec::Core system_core = system_arch.GetCore(); |
605 | 1.99k | for (const char *arch : GetCompatibleArchs(system_core)) { |
606 | 1.99k | llvm::Triple triple; |
607 | 1.99k | triple.setArchName(arch); |
608 | 1.99k | triple.setVendor(llvm::Triple::VendorType::Apple); |
609 | 1.99k | if (os) |
610 | 1.99k | triple.setOS(*os); |
611 | 1.99k | archs.push_back(ArchSpec(triple)); |
612 | 1.99k | } |
613 | 83 | } |
614 | | |
615 | 0 | static FileSpec GetXcodeSelectPath() { |
616 | 0 | static FileSpec g_xcode_select_filespec; |
617 | |
|
618 | 0 | if (!g_xcode_select_filespec) { |
619 | 0 | FileSpec xcode_select_cmd("/usr/bin/xcode-select"); |
620 | 0 | if (FileSystem::Instance().Exists(xcode_select_cmd)) { |
621 | 0 | int exit_status = -1; |
622 | 0 | int signo = -1; |
623 | 0 | std::string command_output; |
624 | 0 | Status status = |
625 | 0 | Host::RunShellCommand("/usr/bin/xcode-select --print-path", |
626 | 0 | FileSpec(), // current working directory |
627 | 0 | &exit_status, &signo, &command_output, |
628 | 0 | std::chrono::seconds(2), // short timeout |
629 | 0 | false); // don't run in a shell |
630 | 0 | if (status.Success() && exit_status == 0 && !command_output.empty()) { |
631 | 0 | size_t first_non_newline = command_output.find_last_not_of("\r\n"); |
632 | 0 | if (first_non_newline != std::string::npos) { |
633 | 0 | command_output.erase(first_non_newline + 1); |
634 | 0 | } |
635 | 0 | g_xcode_select_filespec = FileSpec(command_output); |
636 | 0 | } |
637 | 0 | } |
638 | 0 | } |
639 | |
|
640 | 0 | return g_xcode_select_filespec; |
641 | 0 | } |
642 | | |
643 | 1.08k | BreakpointSP PlatformDarwin::SetThreadCreationBreakpoint(Target &target) { |
644 | 1.08k | BreakpointSP bp_sp; |
645 | 1.08k | static const char *g_bp_names[] = { |
646 | 1.08k | "start_wqthread", "_pthread_wqthread", "_pthread_start", |
647 | 1.08k | }; |
648 | | |
649 | 1.08k | static const char *g_bp_modules[] = {"libsystem_c.dylib", |
650 | 1.08k | "libSystem.B.dylib"}; |
651 | | |
652 | 1.08k | FileSpecList bp_modules; |
653 | 3.24k | for (size_t i = 0; i < std::size(g_bp_modules); i++2.16k ) { |
654 | 2.16k | const char *bp_module = g_bp_modules[i]; |
655 | 2.16k | bp_modules.EmplaceBack(bp_module); |
656 | 2.16k | } |
657 | | |
658 | 1.08k | bool internal = true; |
659 | 1.08k | bool hardware = false; |
660 | 1.08k | LazyBool skip_prologue = eLazyBoolNo; |
661 | 1.08k | bp_sp = target.CreateBreakpoint(&bp_modules, nullptr, g_bp_names, |
662 | 1.08k | std::size(g_bp_names), eFunctionNameTypeFull, |
663 | 1.08k | eLanguageTypeUnknown, 0, skip_prologue, |
664 | 1.08k | internal, hardware); |
665 | 1.08k | bp_sp->SetBreakpointKind("thread-creation"); |
666 | | |
667 | 1.08k | return bp_sp; |
668 | 1.08k | } |
669 | | |
670 | | uint32_t |
671 | 0 | PlatformDarwin::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) { |
672 | 0 | const FileSpec &shell = launch_info.GetShell(); |
673 | 0 | if (!shell) |
674 | 0 | return 1; |
675 | | |
676 | 0 | std::string shell_string = shell.GetPath(); |
677 | 0 | const char *shell_name = strrchr(shell_string.c_str(), '/'); |
678 | 0 | if (shell_name == nullptr) |
679 | 0 | shell_name = shell_string.c_str(); |
680 | 0 | else |
681 | 0 | shell_name++; |
682 | |
|
683 | 0 | if (strcmp(shell_name, "sh") == 0) { |
684 | | // /bin/sh re-exec's itself as /bin/bash requiring another resume. But it |
685 | | // only does this if the COMMAND_MODE environment variable is set to |
686 | | // "legacy". |
687 | 0 | if (launch_info.GetEnvironment().lookup("COMMAND_MODE") == "legacy") |
688 | 0 | return 2; |
689 | 0 | return 1; |
690 | 0 | } else if (strcmp(shell_name, "csh") == 0 || |
691 | 0 | strcmp(shell_name, "tcsh") == 0 || |
692 | 0 | strcmp(shell_name, "zsh") == 0) { |
693 | | // csh and tcsh always seem to re-exec themselves. |
694 | 0 | return 2; |
695 | 0 | } else |
696 | 0 | return 1; |
697 | 0 | } |
698 | | |
699 | | lldb::ProcessSP PlatformDarwin::DebugProcess(ProcessLaunchInfo &launch_info, |
700 | | Debugger &debugger, Target &target, |
701 | 2.10k | Status &error) { |
702 | 2.10k | ProcessSP process_sp; |
703 | | |
704 | 2.10k | if (IsHost()) { |
705 | | // We are going to hand this process off to debugserver which will be in |
706 | | // charge of setting the exit status. However, we still need to reap it |
707 | | // from lldb. So, make sure we use a exit callback which does not set exit |
708 | | // status. |
709 | 2.10k | launch_info.SetMonitorProcessCallback( |
710 | 2.10k | &ProcessLaunchInfo::NoOpMonitorCallback); |
711 | 2.10k | process_sp = Platform::DebugProcess(launch_info, debugger, target, error); |
712 | 2.10k | } else { |
713 | 1 | if (m_remote_platform_sp) |
714 | 1 | process_sp = m_remote_platform_sp->DebugProcess(launch_info, debugger, |
715 | 1 | target, error); |
716 | 0 | else |
717 | 0 | error.SetErrorString("the platform is not currently connected"); |
718 | 1 | } |
719 | 2.10k | return process_sp; |
720 | 2.10k | } |
721 | | |
722 | 851 | void PlatformDarwin::CalculateTrapHandlerSymbolNames() { |
723 | 851 | m_trap_handlers.push_back(ConstString("_sigtramp")); |
724 | 851 | } |
725 | | |
726 | 0 | static FileSpec GetCommandLineToolsLibraryPath() { |
727 | 0 | static FileSpec g_command_line_tools_filespec; |
728 | |
|
729 | 0 | if (!g_command_line_tools_filespec) { |
730 | 0 | FileSpec command_line_tools_path(GetXcodeSelectPath()); |
731 | 0 | command_line_tools_path.AppendPathComponent("Library"); |
732 | 0 | if (FileSystem::Instance().Exists(command_line_tools_path)) { |
733 | 0 | g_command_line_tools_filespec = command_line_tools_path; |
734 | 0 | } |
735 | 0 | } |
736 | |
|
737 | 0 | return g_command_line_tools_filespec; |
738 | 0 | } |
739 | | |
740 | | FileSystem::EnumerateDirectoryResult PlatformDarwin::DirectoryEnumerator( |
741 | 453 | void *baton, llvm::sys::fs::file_type file_type, llvm::StringRef path) { |
742 | 453 | SDKEnumeratorInfo *enumerator_info = static_cast<SDKEnumeratorInfo *>(baton); |
743 | | |
744 | 453 | FileSpec spec(path); |
745 | 453 | if (XcodeSDK::SDKSupportsModules(enumerator_info->sdk_type, spec)) { |
746 | 151 | enumerator_info->found_path = spec; |
747 | 151 | return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext; |
748 | 151 | } |
749 | | |
750 | 302 | return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext; |
751 | 453 | } |
752 | | |
753 | | FileSpec PlatformDarwin::FindSDKInXcodeForModules(XcodeSDK::Type sdk_type, |
754 | 151 | const FileSpec &sdks_spec) { |
755 | | // Look inside Xcode for the required installed iOS SDK version |
756 | | |
757 | 151 | if (!FileSystem::Instance().IsDirectory(sdks_spec)) { |
758 | 0 | return FileSpec(); |
759 | 0 | } |
760 | | |
761 | 151 | const bool find_directories = true; |
762 | 151 | const bool find_files = false; |
763 | 151 | const bool find_other = true; // include symlinks |
764 | | |
765 | 151 | SDKEnumeratorInfo enumerator_info; |
766 | | |
767 | 151 | enumerator_info.sdk_type = sdk_type; |
768 | | |
769 | 151 | FileSystem::Instance().EnumerateDirectory( |
770 | 151 | sdks_spec.GetPath(), find_directories, find_files, find_other, |
771 | 151 | DirectoryEnumerator, &enumerator_info); |
772 | | |
773 | 151 | if (FileSystem::Instance().IsDirectory(enumerator_info.found_path)) |
774 | 151 | return enumerator_info.found_path; |
775 | 0 | else |
776 | 0 | return FileSpec(); |
777 | 151 | } |
778 | | |
779 | 151 | FileSpec PlatformDarwin::GetSDKDirectoryForModules(XcodeSDK::Type sdk_type) { |
780 | 151 | FileSpec sdks_spec = HostInfo::GetXcodeContentsDirectory(); |
781 | 151 | sdks_spec.AppendPathComponent("Developer"); |
782 | 151 | sdks_spec.AppendPathComponent("Platforms"); |
783 | | |
784 | 151 | switch (sdk_type) { |
785 | 151 | case XcodeSDK::Type::MacOSX: |
786 | 151 | sdks_spec.AppendPathComponent("MacOSX.platform"); |
787 | 151 | break; |
788 | 0 | case XcodeSDK::Type::iPhoneSimulator: |
789 | 0 | sdks_spec.AppendPathComponent("iPhoneSimulator.platform"); |
790 | 0 | break; |
791 | 0 | case XcodeSDK::Type::iPhoneOS: |
792 | 0 | sdks_spec.AppendPathComponent("iPhoneOS.platform"); |
793 | 0 | break; |
794 | 0 | case XcodeSDK::Type::WatchSimulator: |
795 | 0 | sdks_spec.AppendPathComponent("WatchSimulator.platform"); |
796 | 0 | break; |
797 | 0 | case XcodeSDK::Type::AppleTVSimulator: |
798 | 0 | sdks_spec.AppendPathComponent("AppleTVSimulator.platform"); |
799 | 0 | break; |
800 | 0 | default: |
801 | 0 | llvm_unreachable("unsupported sdk"); |
802 | 151 | } |
803 | | |
804 | 151 | sdks_spec.AppendPathComponent("Developer"); |
805 | 151 | sdks_spec.AppendPathComponent("SDKs"); |
806 | | |
807 | 151 | if (sdk_type == XcodeSDK::Type::MacOSX) { |
808 | 151 | llvm::VersionTuple version = HostInfo::GetOSVersion(); |
809 | | |
810 | 151 | if (!version.empty()) { |
811 | 151 | if (XcodeSDK::SDKSupportsModules(XcodeSDK::Type::MacOSX, version)) { |
812 | | // If the Xcode SDKs are not available then try to use the |
813 | | // Command Line Tools one which is only for MacOSX. |
814 | 151 | if (!FileSystem::Instance().Exists(sdks_spec)) { |
815 | 0 | sdks_spec = GetCommandLineToolsLibraryPath(); |
816 | 0 | sdks_spec.AppendPathComponent("SDKs"); |
817 | 0 | } |
818 | | |
819 | | // We slightly prefer the exact SDK for this machine. See if it is |
820 | | // there. |
821 | | |
822 | 151 | FileSpec native_sdk_spec = sdks_spec; |
823 | 151 | StreamString native_sdk_name; |
824 | 151 | native_sdk_name.Printf("MacOSX%u.%u.sdk", version.getMajor(), |
825 | 151 | version.getMinor().value_or(0)); |
826 | 151 | native_sdk_spec.AppendPathComponent(native_sdk_name.GetString()); |
827 | | |
828 | 151 | if (FileSystem::Instance().Exists(native_sdk_spec)) { |
829 | 0 | return native_sdk_spec; |
830 | 0 | } |
831 | 151 | } |
832 | 151 | } |
833 | 151 | } |
834 | | |
835 | 151 | return FindSDKInXcodeForModules(sdk_type, sdks_spec); |
836 | 151 | } |
837 | | |
838 | | std::tuple<llvm::VersionTuple, llvm::StringRef> |
839 | 87 | PlatformDarwin::ParseVersionBuildDir(llvm::StringRef dir) { |
840 | 87 | llvm::StringRef build; |
841 | 87 | llvm::StringRef version_str; |
842 | 87 | llvm::StringRef build_str; |
843 | 87 | std::tie(version_str, build_str) = dir.split(' '); |
844 | 87 | llvm::VersionTuple version; |
845 | 87 | if (!version.tryParse(version_str) || |
846 | 87 | build_str.empty()0 ) { |
847 | 87 | if (build_str.consume_front("(")) { |
848 | 4 | size_t pos = build_str.find(')'); |
849 | 4 | build = build_str.slice(0, pos); |
850 | 4 | } |
851 | 87 | } |
852 | | |
853 | 87 | return std::make_tuple(version, build); |
854 | 87 | } |
855 | | |
856 | | llvm::Expected<StructuredData::DictionarySP> |
857 | 6 | PlatformDarwin::FetchExtendedCrashInformation(Process &process) { |
858 | 6 | StructuredData::DictionarySP extended_crash_info = |
859 | 6 | std::make_shared<StructuredData::Dictionary>(); |
860 | | |
861 | 6 | StructuredData::ArraySP annotations = ExtractCrashInfoAnnotations(process); |
862 | 6 | if (annotations && annotations->GetSize()) |
863 | 4 | extended_crash_info->AddItem("Crash-Info Annotations", annotations); |
864 | | |
865 | 6 | StructuredData::DictionarySP app_specific_info = |
866 | 6 | ExtractAppSpecificInfo(process); |
867 | 6 | if (app_specific_info && app_specific_info->GetSize()0 ) |
868 | 0 | extended_crash_info->AddItem("Application Specific Information", |
869 | 0 | app_specific_info); |
870 | | |
871 | 6 | return extended_crash_info->GetSize() ? extended_crash_info4 : nullptr2 ; |
872 | 6 | } |
873 | | |
874 | | StructuredData::ArraySP |
875 | 6 | PlatformDarwin::ExtractCrashInfoAnnotations(Process &process) { |
876 | 6 | Log *log = GetLog(LLDBLog::Process); |
877 | | |
878 | 6 | ConstString section_name("__crash_info"); |
879 | 6 | Target &target = process.GetTarget(); |
880 | 6 | StructuredData::ArraySP array_sp = std::make_shared<StructuredData::Array>(); |
881 | | |
882 | 252 | for (ModuleSP module : target.GetImages().Modules()) { |
883 | 252 | SectionList *sections = module->GetSectionList(); |
884 | | |
885 | 252 | std::string module_name = module->GetSpecificationDescription(); |
886 | | |
887 | | // The DYDL module is skipped since it's always loaded when running the |
888 | | // binary. |
889 | 252 | if (module_name == "/usr/lib/dyld") |
890 | 6 | continue; |
891 | | |
892 | 246 | if (!sections) { |
893 | 0 | LLDB_LOG(log, "Module {0} doesn't have any section!", module_name); |
894 | 0 | continue; |
895 | 0 | } |
896 | | |
897 | 246 | SectionSP crash_info = sections->FindSectionByName(section_name); |
898 | 246 | if (!crash_info) { |
899 | 156 | LLDB_LOG(log, "Module {0} doesn't have section {1}!", module_name, |
900 | 156 | section_name); |
901 | 156 | continue; |
902 | 156 | } |
903 | | |
904 | 90 | addr_t load_addr = crash_info->GetLoadBaseAddress(&target); |
905 | | |
906 | 90 | if (load_addr == LLDB_INVALID_ADDRESS) { |
907 | 0 | LLDB_LOG(log, "Module {0} has an invalid '{1}' section load address: {2}", |
908 | 0 | module_name, section_name, load_addr); |
909 | 0 | continue; |
910 | 0 | } |
911 | | |
912 | 90 | Status error; |
913 | 90 | CrashInfoAnnotations annotations; |
914 | 90 | size_t expected_size = sizeof(CrashInfoAnnotations); |
915 | 90 | size_t bytes_read = process.ReadMemoryFromInferior(load_addr, &annotations, |
916 | 90 | expected_size, error); |
917 | | |
918 | 90 | if (expected_size != bytes_read || error.Fail()) { |
919 | 0 | LLDB_LOG(log, "Failed to read {0} section from memory in module {1}: {2}", |
920 | 0 | section_name, module_name, error); |
921 | 0 | continue; |
922 | 0 | } |
923 | | |
924 | | // initial support added for version 5 |
925 | 90 | if (annotations.version < 5) { |
926 | 0 | LLDB_LOG(log, |
927 | 0 | "Annotation version lower than 5 unsupported! Module {0} has " |
928 | 0 | "version {1} instead.", |
929 | 0 | module_name, annotations.version); |
930 | 0 | continue; |
931 | 0 | } |
932 | | |
933 | 90 | if (!annotations.message) { |
934 | 82 | LLDB_LOG(log, "No message available for module {0}.", module_name); |
935 | 82 | continue; |
936 | 82 | } |
937 | | |
938 | 8 | std::string message; |
939 | 8 | bytes_read = |
940 | 8 | process.ReadCStringFromMemory(annotations.message, message, error); |
941 | | |
942 | 8 | if (message.empty() || bytes_read != message.size() || error.Fail()) { |
943 | 0 | LLDB_LOG(log, "Failed to read the message from memory in module {0}: {1}", |
944 | 0 | module_name, error); |
945 | 0 | continue; |
946 | 0 | } |
947 | | |
948 | | // Remove trailing newline from message |
949 | 8 | if (message.back() == '\n') |
950 | 4 | message.pop_back(); |
951 | | |
952 | 8 | if (!annotations.message2) |
953 | 8 | LLDB_LOG(log, "No message2 available for module {0}.", module_name); |
954 | | |
955 | 8 | std::string message2; |
956 | 8 | bytes_read = |
957 | 8 | process.ReadCStringFromMemory(annotations.message2, message2, error); |
958 | | |
959 | 8 | if (!message2.empty() && bytes_read == message2.size()0 && error.Success()0 ) |
960 | 0 | if (message2.back() == '\n') |
961 | 0 | message2.pop_back(); |
962 | | |
963 | 8 | StructuredData::DictionarySP entry_sp = |
964 | 8 | std::make_shared<StructuredData::Dictionary>(); |
965 | | |
966 | 8 | entry_sp->AddStringItem("image", module->GetFileSpec().GetPath(false)); |
967 | 8 | entry_sp->AddStringItem("uuid", module->GetUUID().GetAsString()); |
968 | 8 | entry_sp->AddStringItem("message", message); |
969 | 8 | entry_sp->AddStringItem("message2", message2); |
970 | 8 | entry_sp->AddIntegerItem("abort-cause", annotations.abort_cause); |
971 | | |
972 | 8 | array_sp->AddItem(entry_sp); |
973 | 8 | } |
974 | | |
975 | 6 | return array_sp; |
976 | 6 | } |
977 | | |
978 | | StructuredData::DictionarySP |
979 | 6 | PlatformDarwin::ExtractAppSpecificInfo(Process &process) { |
980 | 6 | StructuredData::DictionarySP metadata_sp = process.GetMetadata(); |
981 | | |
982 | 6 | if (!metadata_sp || !metadata_sp->GetSize()0 || !metadata_sp->HasKey("asi")0 ) |
983 | 6 | return {}; |
984 | | |
985 | 0 | StructuredData::Dictionary *asi; |
986 | 0 | if (!metadata_sp->GetValueForKeyAsDictionary("asi", asi)) |
987 | 0 | return {}; |
988 | | |
989 | 0 | StructuredData::DictionarySP dict_sp = |
990 | 0 | std::make_shared<StructuredData::Dictionary>(); |
991 | |
|
992 | 0 | auto flatten_asi_dict = [&dict_sp](llvm::StringRef key, |
993 | 0 | StructuredData::Object *val) -> bool { |
994 | 0 | if (!val) |
995 | 0 | return false; |
996 | | |
997 | 0 | StructuredData::Array *arr = val->GetAsArray(); |
998 | 0 | if (!arr || !arr->GetSize()) |
999 | 0 | return false; |
1000 | | |
1001 | 0 | dict_sp->AddItem(key, arr->GetItemAtIndex(0)); |
1002 | 0 | return true; |
1003 | 0 | }; |
1004 | |
|
1005 | 0 | asi->ForEach(flatten_asi_dict); |
1006 | |
|
1007 | 0 | return dict_sp; |
1008 | 0 | } |
1009 | | |
1010 | | void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( |
1011 | 1.23k | Target *target, std::vector<std::string> &options, XcodeSDK::Type sdk_type) { |
1012 | 1.23k | const std::vector<std::string> apple_arguments = { |
1013 | 1.23k | "-x", "objective-c++", "-fobjc-arc", |
1014 | 1.23k | "-fblocks", "-D_ISO646_H", "-D__ISO646_H", |
1015 | 1.23k | "-fgnuc-version=4.2.1"}; |
1016 | | |
1017 | 1.23k | options.insert(options.end(), apple_arguments.begin(), apple_arguments.end()); |
1018 | | |
1019 | 1.23k | StreamString minimum_version_option; |
1020 | 1.23k | bool use_current_os_version = false; |
1021 | | // If the SDK type is for the host OS, use its version number. |
1022 | 1.23k | auto get_host_os = []() { return HostInfo::GetTargetTriple().getOS(); }; |
1023 | 1.23k | switch (sdk_type) { |
1024 | 1.23k | case XcodeSDK::Type::MacOSX: |
1025 | 1.23k | use_current_os_version = get_host_os() == llvm::Triple::MacOSX; |
1026 | 1.23k | break; |
1027 | 0 | case XcodeSDK::Type::iPhoneOS: |
1028 | 0 | use_current_os_version = get_host_os() == llvm::Triple::IOS; |
1029 | 0 | break; |
1030 | 0 | case XcodeSDK::Type::AppleTVOS: |
1031 | 0 | use_current_os_version = get_host_os() == llvm::Triple::TvOS; |
1032 | 0 | break; |
1033 | 0 | case XcodeSDK::Type::watchOS: |
1034 | 0 | use_current_os_version = get_host_os() == llvm::Triple::WatchOS; |
1035 | 0 | break; |
1036 | 0 | default: |
1037 | 0 | break; |
1038 | 1.23k | } |
1039 | | |
1040 | 1.23k | llvm::VersionTuple version; |
1041 | 1.23k | if (use_current_os_version) |
1042 | 1.23k | version = GetOSVersion(); |
1043 | 0 | else if (target) { |
1044 | | // Our OS doesn't match our executable so we need to get the min OS version |
1045 | | // from the object file |
1046 | 0 | ModuleSP exe_module_sp = target->GetExecutableModule(); |
1047 | 0 | if (exe_module_sp) { |
1048 | 0 | ObjectFile *object_file = exe_module_sp->GetObjectFile(); |
1049 | 0 | if (object_file) |
1050 | 0 | version = object_file->GetMinimumOSVersion(); |
1051 | 0 | } |
1052 | 0 | } |
1053 | | // Only add the version-min options if we got a version from somewhere |
1054 | 1.23k | if (!version.empty() && sdk_type != XcodeSDK::Type::Linux) { |
1055 | 1.23k | #define OPTION(PREFIX, NAME, VAR, ...) \ |
1056 | 3.95M | llvm::StringRef opt_##VAR = NAME; \ |
1057 | 3.95M | (void)opt_##VAR; |
1058 | 1.23k | #include "clang/Driver/Options.inc" |
1059 | 1.23k | #undef OPTION |
1060 | 1.23k | minimum_version_option << '-'; |
1061 | 1.23k | switch (sdk_type) { |
1062 | 1.23k | case XcodeSDK::Type::MacOSX: |
1063 | 1.23k | minimum_version_option << opt_mmacos_version_min_EQ; |
1064 | 1.23k | break; |
1065 | 0 | case XcodeSDK::Type::iPhoneSimulator: |
1066 | 0 | minimum_version_option << opt_mios_simulator_version_min_EQ; |
1067 | 0 | break; |
1068 | 0 | case XcodeSDK::Type::iPhoneOS: |
1069 | 0 | minimum_version_option << opt_mios_version_min_EQ; |
1070 | 0 | break; |
1071 | 0 | case XcodeSDK::Type::AppleTVSimulator: |
1072 | 0 | minimum_version_option << opt_mtvos_simulator_version_min_EQ; |
1073 | 0 | break; |
1074 | 0 | case XcodeSDK::Type::AppleTVOS: |
1075 | 0 | minimum_version_option << opt_mtvos_version_min_EQ; |
1076 | 0 | break; |
1077 | 0 | case XcodeSDK::Type::WatchSimulator: |
1078 | 0 | minimum_version_option << opt_mwatchos_simulator_version_min_EQ; |
1079 | 0 | break; |
1080 | 0 | case XcodeSDK::Type::watchOS: |
1081 | 0 | minimum_version_option << opt_mwatchos_version_min_EQ; |
1082 | 0 | break; |
1083 | 0 | case XcodeSDK::Type::bridgeOS: |
1084 | 0 | case XcodeSDK::Type::Linux: |
1085 | 0 | case XcodeSDK::Type::unknown: |
1086 | 0 | if (Log *log = GetLog(LLDBLog::Host)) { |
1087 | 0 | XcodeSDK::Info info; |
1088 | 0 | info.type = sdk_type; |
1089 | 0 | LLDB_LOGF(log, "Clang modules on %s are not supported", |
1090 | 0 | XcodeSDK::GetCanonicalName(info).c_str()); |
1091 | 0 | } |
1092 | 0 | return; |
1093 | 1.23k | } |
1094 | 1.23k | minimum_version_option << version.getAsString(); |
1095 | 1.23k | options.emplace_back(std::string(minimum_version_option.GetString())); |
1096 | 1.23k | } |
1097 | | |
1098 | 1.23k | FileSpec sysroot_spec; |
1099 | | |
1100 | 1.23k | if (target) { |
1101 | 1.23k | if (ModuleSP exe_module_sp = target->GetExecutableModule()) { |
1102 | 1.13k | auto path_or_err = ResolveSDKPathFromDebugInfo(*exe_module_sp); |
1103 | 1.13k | if (path_or_err) { |
1104 | 1.08k | sysroot_spec = FileSpec(*path_or_err); |
1105 | 1.08k | } else { |
1106 | 53 | LLDB_LOG_ERROR(GetLog(LLDBLog::Types | LLDBLog::Host), |
1107 | 53 | path_or_err.takeError(), |
1108 | 53 | "Failed to resolve SDK path: {0}"); |
1109 | 53 | } |
1110 | 1.13k | } |
1111 | 1.23k | } |
1112 | | |
1113 | 1.23k | if (!FileSystem::Instance().IsDirectory(sysroot_spec.GetPath())) { |
1114 | 151 | std::lock_guard<std::mutex> guard(m_mutex); |
1115 | 151 | sysroot_spec = GetSDKDirectoryForModules(sdk_type); |
1116 | 151 | } |
1117 | | |
1118 | 1.23k | if (FileSystem::Instance().IsDirectory(sysroot_spec.GetPath())) { |
1119 | 1.23k | options.push_back("-isysroot"); |
1120 | 1.23k | options.push_back(sysroot_spec.GetPath()); |
1121 | 1.23k | } |
1122 | 1.23k | } |
1123 | | |
1124 | 0 | ConstString PlatformDarwin::GetFullNameForDylib(ConstString basename) { |
1125 | 0 | if (basename.IsEmpty()) |
1126 | 0 | return basename; |
1127 | | |
1128 | 0 | StreamString stream; |
1129 | 0 | stream.Printf("lib%s.dylib", basename.GetCString()); |
1130 | 0 | return ConstString(stream.GetString()); |
1131 | 0 | } |
1132 | | |
1133 | 1.25k | llvm::VersionTuple PlatformDarwin::GetOSVersion(Process *process) { |
1134 | 1.25k | if (process && GetPluginName().contains("-simulator")0 ) { |
1135 | 0 | lldb_private::ProcessInstanceInfo proc_info; |
1136 | 0 | if (Host::GetProcessInfo(process->GetID(), proc_info)) { |
1137 | 0 | const Environment &env = proc_info.GetEnvironment(); |
1138 | |
|
1139 | 0 | llvm::VersionTuple result; |
1140 | 0 | if (!result.tryParse(env.lookup("SIMULATOR_RUNTIME_VERSION"))) |
1141 | 0 | return result; |
1142 | | |
1143 | 0 | std::string dyld_root_path = env.lookup("DYLD_ROOT_PATH"); |
1144 | 0 | if (!dyld_root_path.empty()) { |
1145 | 0 | dyld_root_path += "/System/Library/CoreServices/SystemVersion.plist"; |
1146 | 0 | ApplePropertyList system_version_plist(dyld_root_path.c_str()); |
1147 | 0 | std::string product_version; |
1148 | 0 | if (system_version_plist.GetValueAsString("ProductVersion", |
1149 | 0 | product_version)) { |
1150 | 0 | if (!result.tryParse(product_version)) |
1151 | 0 | return result; |
1152 | 0 | } |
1153 | 0 | } |
1154 | 0 | } |
1155 | | // For simulator platforms, do NOT call back through |
1156 | | // Platform::GetOSVersion() as it might call Process::GetHostOSVersion() |
1157 | | // which we don't want as it will be incorrect |
1158 | 0 | return llvm::VersionTuple(); |
1159 | 0 | } |
1160 | | |
1161 | 1.25k | return Platform::GetOSVersion(process); |
1162 | 1.25k | } |
1163 | | |
1164 | 0 | lldb_private::FileSpec PlatformDarwin::LocateExecutable(const char *basename) { |
1165 | | // A collection of SBFileSpec whose SBFileSpec.m_directory members are filled |
1166 | | // in with any executable directories that should be searched. |
1167 | 0 | static std::vector<FileSpec> g_executable_dirs; |
1168 | | |
1169 | | // Find the global list of directories that we will search for executables |
1170 | | // once so we don't keep doing the work over and over. |
1171 | 0 | static llvm::once_flag g_once_flag; |
1172 | 0 | llvm::call_once(g_once_flag, []() { |
1173 | | |
1174 | | // When locating executables, trust the DEVELOPER_DIR first if it is set |
1175 | 0 | FileSpec xcode_contents_dir = HostInfo::GetXcodeContentsDirectory(); |
1176 | 0 | if (xcode_contents_dir) { |
1177 | 0 | FileSpec xcode_lldb_resources = xcode_contents_dir; |
1178 | 0 | xcode_lldb_resources.AppendPathComponent("SharedFrameworks"); |
1179 | 0 | xcode_lldb_resources.AppendPathComponent("LLDB.framework"); |
1180 | 0 | xcode_lldb_resources.AppendPathComponent("Resources"); |
1181 | 0 | if (FileSystem::Instance().Exists(xcode_lldb_resources)) { |
1182 | 0 | FileSpec dir; |
1183 | 0 | dir.SetDirectory(xcode_lldb_resources.GetPathAsConstString()); |
1184 | 0 | g_executable_dirs.push_back(dir); |
1185 | 0 | } |
1186 | 0 | } |
1187 | | // Xcode might not be installed so we also check for the Command Line Tools. |
1188 | 0 | FileSpec command_line_tools_dir = GetCommandLineToolsLibraryPath(); |
1189 | 0 | if (command_line_tools_dir) { |
1190 | 0 | FileSpec cmd_line_lldb_resources = command_line_tools_dir; |
1191 | 0 | cmd_line_lldb_resources.AppendPathComponent("PrivateFrameworks"); |
1192 | 0 | cmd_line_lldb_resources.AppendPathComponent("LLDB.framework"); |
1193 | 0 | cmd_line_lldb_resources.AppendPathComponent("Resources"); |
1194 | 0 | if (FileSystem::Instance().Exists(cmd_line_lldb_resources)) { |
1195 | 0 | FileSpec dir; |
1196 | 0 | dir.SetDirectory(cmd_line_lldb_resources.GetPathAsConstString()); |
1197 | 0 | g_executable_dirs.push_back(dir); |
1198 | 0 | } |
1199 | 0 | } |
1200 | 0 | }); |
1201 | | |
1202 | | // Now search the global list of executable directories for the executable we |
1203 | | // are looking for |
1204 | 0 | for (const auto &executable_dir : g_executable_dirs) { |
1205 | 0 | FileSpec executable_file; |
1206 | 0 | executable_file.SetDirectory(executable_dir.GetDirectory()); |
1207 | 0 | executable_file.SetFilename(basename); |
1208 | 0 | if (FileSystem::Instance().Exists(executable_file)) |
1209 | 0 | return executable_file; |
1210 | 0 | } |
1211 | | |
1212 | 0 | return FileSpec(); |
1213 | 0 | } |
1214 | | |
1215 | | lldb_private::Status |
1216 | 2.10k | PlatformDarwin::LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) { |
1217 | | // Starting in Fall 2016 OSes, NSLog messages only get mirrored to stderr if |
1218 | | // the OS_ACTIVITY_DT_MODE environment variable is set. (It doesn't require |
1219 | | // any specific value; rather, it just needs to exist). We will set it here |
1220 | | // as long as the IDE_DISABLED_OS_ACTIVITY_DT_MODE flag is not set. Xcode |
1221 | | // makes use of IDE_DISABLED_OS_ACTIVITY_DT_MODE to tell |
1222 | | // LLDB *not* to muck with the OS_ACTIVITY_DT_MODE flag when they |
1223 | | // specifically want it unset. |
1224 | 2.10k | const char *disable_env_var = "IDE_DISABLED_OS_ACTIVITY_DT_MODE"; |
1225 | 2.10k | auto &env_vars = launch_info.GetEnvironment(); |
1226 | 2.10k | if (!env_vars.count(disable_env_var)) { |
1227 | | // We want to make sure that OS_ACTIVITY_DT_MODE is set so that we get |
1228 | | // os_log and NSLog messages mirrored to the target process stderr. |
1229 | 2.09k | env_vars.try_emplace("OS_ACTIVITY_DT_MODE", "enable"); |
1230 | 2.09k | } |
1231 | | |
1232 | | // Let our parent class do the real launching. |
1233 | 2.10k | return PlatformPOSIX::LaunchProcess(launch_info); |
1234 | 2.10k | } |
1235 | | |
1236 | | lldb_private::Status PlatformDarwin::FindBundleBinaryInExecSearchPaths( |
1237 | | const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, |
1238 | | const FileSpecList *module_search_paths_ptr, |
1239 | 365 | llvm::SmallVectorImpl<ModuleSP> *old_modules, bool *did_create_ptr) { |
1240 | 365 | const FileSpec &platform_file = module_spec.GetFileSpec(); |
1241 | | // See if the file is present in any of the module_search_paths_ptr |
1242 | | // directories. |
1243 | 365 | if (!module_sp && module_search_paths_ptr && platform_file) { |
1244 | | // create a vector of all the file / directory names in platform_file e.g. |
1245 | | // this might be |
1246 | | // /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation |
1247 | | // |
1248 | | // We'll need to look in the module_search_paths_ptr directories for both |
1249 | | // "UIFoundation" and "UIFoundation.framework" -- most likely the latter |
1250 | | // will be the one we find there. |
1251 | | |
1252 | 360 | std::vector<llvm::StringRef> path_parts = platform_file.GetComponents(); |
1253 | | // We want the components in reverse order. |
1254 | 360 | std::reverse(path_parts.begin(), path_parts.end()); |
1255 | 360 | const size_t path_parts_size = path_parts.size(); |
1256 | | |
1257 | 360 | size_t num_module_search_paths = module_search_paths_ptr->GetSize(); |
1258 | 419 | for (size_t i = 0; i < num_module_search_paths; ++i59 ) { |
1259 | 61 | Log *log_verbose = GetLog(LLDBLog::Host); |
1260 | 61 | LLDB_LOGF( |
1261 | 61 | log_verbose, |
1262 | 61 | "PlatformRemoteDarwinDevice::GetSharedModule searching for binary in " |
1263 | 61 | "search-path %s", |
1264 | 61 | module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath().c_str()); |
1265 | | // Create a new FileSpec with this module_search_paths_ptr plus just the |
1266 | | // filename ("UIFoundation"), then the parent dir plus filename |
1267 | | // ("UIFoundation.framework/UIFoundation") etc - up to four names (to |
1268 | | // handle "Foo.framework/Contents/MacOS/Foo") |
1269 | | |
1270 | 195 | for (size_t j = 0; j < 4 && j < path_parts_size - 1177 ; ++j134 ) { |
1271 | 136 | FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i)); |
1272 | | |
1273 | | // Add the components backwards. For |
1274 | | // .../PrivateFrameworks/UIFoundation.framework/UIFoundation path_parts |
1275 | | // is |
1276 | | // [0] UIFoundation |
1277 | | // [1] UIFoundation.framework |
1278 | | // [2] PrivateFrameworks |
1279 | | // |
1280 | | // and if 'j' is 2, we want to append path_parts[1] and then |
1281 | | // path_parts[0], aka 'UIFoundation.framework/UIFoundation', to the |
1282 | | // module_search_paths_ptr path. |
1283 | | |
1284 | 437 | for (int k = j; k >= 0; --k301 ) { |
1285 | 301 | path_to_try.AppendPathComponent(path_parts[k]); |
1286 | 301 | } |
1287 | | |
1288 | 136 | if (FileSystem::Instance().Exists(path_to_try)) { |
1289 | 2 | ModuleSpec new_module_spec(module_spec); |
1290 | 2 | new_module_spec.GetFileSpec() = path_to_try; |
1291 | 2 | Status new_error( |
1292 | 2 | Platform::GetSharedModule(new_module_spec, process, module_sp, |
1293 | 2 | nullptr, old_modules, did_create_ptr)); |
1294 | | |
1295 | 2 | if (module_sp) { |
1296 | 2 | module_sp->SetPlatformFileSpec(path_to_try); |
1297 | 2 | return new_error; |
1298 | 2 | } |
1299 | 2 | } |
1300 | 136 | } |
1301 | 61 | } |
1302 | 360 | } |
1303 | 363 | return Status(); |
1304 | 365 | } |
1305 | | |
1306 | | std::string PlatformDarwin::FindComponentInPath(llvm::StringRef path, |
1307 | 5 | llvm::StringRef component) { |
1308 | 5 | auto begin = llvm::sys::path::begin(path); |
1309 | 5 | auto end = llvm::sys::path::end(path); |
1310 | 21 | for (auto it = begin; it != end; ++it16 ) { |
1311 | 20 | if (it->contains(component)) { |
1312 | 4 | llvm::SmallString<128> buffer; |
1313 | 4 | llvm::sys::path::append(buffer, begin, ++it, |
1314 | 4 | llvm::sys::path::Style::posix); |
1315 | 4 | return buffer.str().str(); |
1316 | 4 | } |
1317 | 20 | } |
1318 | 1 | return {}; |
1319 | 5 | } |
1320 | | |
1321 | 0 | FileSpec PlatformDarwin::GetCurrentToolchainDirectory() { |
1322 | 0 | if (FileSpec fspec = HostInfo::GetShlibDir()) |
1323 | 0 | return FileSpec(FindComponentInPath(fspec.GetPath(), ".xctoolchain")); |
1324 | 0 | return {}; |
1325 | 0 | } |
1326 | | |
1327 | 0 | FileSpec PlatformDarwin::GetCurrentCommandLineToolsDirectory() { |
1328 | 0 | if (FileSpec fspec = HostInfo::GetShlibDir()) |
1329 | 0 | return FileSpec(FindComponentInPath(fspec.GetPath(), "CommandLineTools")); |
1330 | 0 | return {}; |
1331 | 0 | } |
1332 | | |
1333 | 0 | llvm::Triple::OSType PlatformDarwin::GetHostOSType() { |
1334 | | #if !defined(__APPLE__) |
1335 | | return llvm::Triple::MacOSX; |
1336 | | #else |
1337 | 0 | #if TARGET_OS_OSX |
1338 | 0 | return llvm::Triple::MacOSX; |
1339 | | #elif TARGET_OS_IOS |
1340 | | return llvm::Triple::IOS; |
1341 | | #elif TARGET_OS_WATCH |
1342 | | return llvm::Triple::WatchOS; |
1343 | | #elif TARGET_OS_TV |
1344 | | return llvm::Triple::TvOS; |
1345 | | #elif TARGET_OS_BRIDGE |
1346 | | return llvm::Triple::BridgeOS; |
1347 | | #else |
1348 | | #error "LLDB being compiled for an unrecognized Darwin OS" |
1349 | | #endif |
1350 | 0 | #endif // __APPLE__ |
1351 | 0 | } |
1352 | | |
1353 | | llvm::Expected<std::pair<XcodeSDK, bool>> |
1354 | 1.14k | PlatformDarwin::GetSDKPathFromDebugInfo(Module &module) { |
1355 | 1.14k | SymbolFile *sym_file = module.GetSymbolFile(); |
1356 | 1.14k | if (!sym_file) |
1357 | 0 | return llvm::createStringError( |
1358 | 0 | llvm::inconvertibleErrorCode(), |
1359 | 0 | llvm::formatv("No symbol file available for module '{0}'", |
1360 | 0 | module.GetFileSpec().GetFilename().AsCString(""))); |
1361 | | |
1362 | 1.14k | bool found_public_sdk = false; |
1363 | 1.14k | bool found_internal_sdk = false; |
1364 | 1.14k | XcodeSDK merged_sdk; |
1365 | 2.41k | for (unsigned i = 0; i < sym_file->GetNumCompileUnits(); ++i1.27k ) { |
1366 | 1.27k | if (auto cu_sp = sym_file->GetCompileUnitAtIndex(i)) { |
1367 | 1.27k | auto cu_sdk = sym_file->ParseXcodeSDK(*cu_sp); |
1368 | 1.27k | bool is_internal_sdk = cu_sdk.IsAppleInternalSDK(); |
1369 | 1.27k | found_public_sdk |= !is_internal_sdk; |
1370 | 1.27k | found_internal_sdk |= is_internal_sdk; |
1371 | | |
1372 | 1.27k | merged_sdk.Merge(cu_sdk); |
1373 | 1.27k | } |
1374 | 1.27k | } |
1375 | | |
1376 | 1.14k | const bool found_mismatch = found_internal_sdk && found_public_sdk3 ; |
1377 | | |
1378 | 1.14k | return std::pair{std::move(merged_sdk), found_mismatch}; |
1379 | 1.14k | } |
1380 | | |
1381 | | llvm::Expected<std::string> |
1382 | 1.13k | PlatformDarwin::ResolveSDKPathFromDebugInfo(Module &module) { |
1383 | 1.13k | auto sdk_or_err = GetSDKPathFromDebugInfo(module); |
1384 | 1.13k | if (!sdk_or_err) |
1385 | 0 | return llvm::createStringError( |
1386 | 0 | llvm::inconvertibleErrorCode(), |
1387 | 0 | llvm::formatv("Failed to parse SDK path from debug-info: {0}", |
1388 | 0 | llvm::toString(sdk_or_err.takeError()))); |
1389 | | |
1390 | 1.13k | auto [sdk, _] = std::move(*sdk_or_err); |
1391 | | |
1392 | 1.13k | auto path_or_err = HostInfo::GetSDKRoot(HostInfo::SDKOptions{sdk}); |
1393 | 1.13k | if (!path_or_err) |
1394 | 55 | return llvm::createStringError( |
1395 | 55 | llvm::inconvertibleErrorCode(), |
1396 | 55 | llvm::formatv("Error while searching for SDK (XcodeSDK '{0}'): {1}", |
1397 | 55 | sdk.GetString(), |
1398 | 55 | llvm::toString(path_or_err.takeError()))); |
1399 | | |
1400 | 1.08k | return path_or_err->str(); |
1401 | 1.13k | } |