blob: db05b1be765210a78a45d338cdb9aab9918b4f0b [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Symbols.cpp ---------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Host/Symbols.h"
11
12// C Includes
13#include <dirent.h>
Jason Molenda055c57b2012-10-30 21:26:30 +000014#include <pwd.h>
Jim Ingham46d005d2014-04-02 22:53:21 +000015#include "lldb/Utility/SafeMachO.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016
17// C++ Includes
18// Other libraries and framework includes
19#include <CoreFoundation/CoreFoundation.h>
20
21// Project includes
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022#include "lldb/Core/ArchSpec.h"
23#include "lldb/Core/DataBuffer.h"
24#include "lldb/Core/DataExtractor.h"
Greg Claytonb9a01b32012-02-26 05:51:37 +000025#include "lldb/Core/Module.h"
Greg Clayton1f746072012-08-29 21:13:06 +000026#include "lldb/Core/ModuleSpec.h"
Johnny Chen82e5a262012-08-22 00:18:43 +000027#include "lldb/Core/StreamString.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000028#include "lldb/Core/Timer.h"
29#include "lldb/Core/UUID.h"
Greg Clayton7fb56d02011-02-01 01:31:41 +000030#include "lldb/Host/Endian.h"
Johnny Chenfdc80a5c2012-02-01 01:49:50 +000031#include "lldb/Host/Host.h"
Robert Flack31870e12015-04-24 18:09:54 +000032#include "lldb/Symbol/ObjectFile.h"
Greg Clayton293d5932011-02-01 05:15:02 +000033#include "lldb/Utility/CleanUp.h"
Daniel Dunbar5ae87322011-10-31 22:50:53 +000034#include "Host/macosx/cfcpp/CFCBundle.h"
Greg Claytonc8f814d2012-09-27 03:13:55 +000035#include "Host/macosx/cfcpp/CFCData.h"
Greg Claytonc982c762010-07-09 20:39:50 +000036#include "Host/macosx/cfcpp/CFCReleaser.h"
Greg Clayton8b82f082011-04-12 05:54:46 +000037#include "Host/macosx/cfcpp/CFCString.h"
Chris Lattner311adf32010-09-08 23:01:14 +000038#include "mach/machine.h"
Greg Claytonc982c762010-07-09 20:39:50 +000039
Chris Lattner30fdc8d2010-06-08 16:52:24 +000040using namespace lldb;
41using namespace lldb_private;
Greg Claytone1a916a2010-07-21 22:12:05 +000042using namespace llvm::MachO;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043
Todd Fiala013434e2014-07-09 01:29:05 +000044#if !defined (__arm__) && !defined (__arm64__) && !defined (__aarch64__) // No DebugSymbols on the iOS devices
Chris Lattner30fdc8d2010-06-08 16:52:24 +000045extern "C" {
Greg Claytonc982c762010-07-09 20:39:50 +000046
Chris Lattner30fdc8d2010-06-08 16:52:24 +000047CFURLRef DBGCopyFullDSYMURLForUUID (CFUUIDRef uuid, CFURLRef exec_url);
48CFDictionaryRef DBGCopyDSYMPropertyLists (CFURLRef dsym_url);
Greg Claytonc982c762010-07-09 20:39:50 +000049
50}
Greg Claytondce502e2011-11-04 03:34:56 +000051#endif
Chris Lattner30fdc8d2010-06-08 16:52:24 +000052
Robert Flack31870e12015-04-24 18:09:54 +000053int
Chris Lattner30fdc8d2010-06-08 16:52:24 +000054LocateMacOSXFilesUsingDebugSymbols
55(
Greg Claytonb9a01b32012-02-26 05:51:37 +000056 const ModuleSpec &module_spec,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000057 FileSpec *out_exec_fspec, // If non-NULL, try and find the executable
58 FileSpec *out_dsym_fspec // If non-NULL try and find the debug symbol file
59)
60{
61 int items_found = 0;
62
63 if (out_exec_fspec)
64 out_exec_fspec->Clear();
65
66 if (out_dsym_fspec)
67 out_dsym_fspec->Clear();
68
Todd Fiala013434e2014-07-09 01:29:05 +000069#if !defined (__arm__) && !defined (__arm64__) && !defined (__aarch64__) // No DebugSymbols on the iOS devices
Greg Claytondce502e2011-11-04 03:34:56 +000070
Greg Claytonb9a01b32012-02-26 05:51:37 +000071 const UUID *uuid = module_spec.GetUUIDPtr();
72 const ArchSpec *arch = module_spec.GetArchitecturePtr();
73
Chris Lattner30fdc8d2010-06-08 16:52:24 +000074 if (uuid && uuid->IsValid())
75 {
76 // Try and locate the dSYM file using DebugSymbols first
77 const UInt8 *module_uuid = (const UInt8 *)uuid->GetBytes();
78 if (module_uuid != NULL)
79 {
Greg Claytona63d08c2011-07-19 03:57:15 +000080 CFCReleaser<CFUUIDRef> module_uuid_ref(::CFUUIDCreateWithBytes (NULL,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000081 module_uuid[0],
82 module_uuid[1],
83 module_uuid[2],
84 module_uuid[3],
85 module_uuid[4],
86 module_uuid[5],
87 module_uuid[6],
88 module_uuid[7],
89 module_uuid[8],
90 module_uuid[9],
91 module_uuid[10],
92 module_uuid[11],
93 module_uuid[12],
94 module_uuid[13],
95 module_uuid[14],
96 module_uuid[15]));
97
98 if (module_uuid_ref.get())
99 {
100 CFCReleaser<CFURLRef> exec_url;
Greg Claytonb9a01b32012-02-26 05:51:37 +0000101 const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000102 if (exec_fspec)
103 {
104 char exec_cf_path[PATH_MAX];
105 if (exec_fspec->GetPath(exec_cf_path, sizeof(exec_cf_path)))
106 exec_url.reset(::CFURLCreateFromFileSystemRepresentation (NULL,
107 (const UInt8 *)exec_cf_path,
108 strlen(exec_cf_path),
109 FALSE));
110 }
111
112 CFCReleaser<CFURLRef> dsym_url (::DBGCopyFullDSYMURLForUUID(module_uuid_ref.get(), exec_url.get()));
113 char path[PATH_MAX];
114
115 if (dsym_url.get())
116 {
117 if (out_dsym_fspec)
118 {
119 if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1))
120 {
Jason Molendaa8805d32012-10-05 04:57:34 +0000121 out_dsym_fspec->SetFile(path, path[0] == '~');
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000122
123 if (out_dsym_fspec->GetFileType () == FileSpec::eFileTypeDirectory)
124 {
Greg Clayton103f0282012-09-12 02:03:59 +0000125 *out_dsym_fspec = Symbols::FindSymbolFileInBundle (*out_dsym_fspec, uuid, arch);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000126 if (*out_dsym_fspec)
127 ++items_found;
128 }
129 else
130 {
131 ++items_found;
132 }
133 }
134 }
135
Greg Claytond804d282012-03-15 21:01:31 +0000136 CFCReleaser<CFDictionaryRef> dict(::DBGCopyDSYMPropertyLists (dsym_url.get()));
137 CFDictionaryRef uuid_dict = NULL;
138 if (dict.get())
139 {
Jason Molendac16b4af2013-05-03 23:56:12 +0000140 CFCString uuid_cfstr (uuid->GetAsString().c_str());
Jason Molenda743e43962012-10-02 22:23:42 +0000141 uuid_dict = static_cast<CFDictionaryRef>(::CFDictionaryGetValue (dict.get(), uuid_cfstr.get()));
Greg Claytond804d282012-03-15 21:01:31 +0000142 if (uuid_dict)
143 {
144
145 CFStringRef actual_src_cfpath = static_cast<CFStringRef>(::CFDictionaryGetValue (uuid_dict, CFSTR("DBGSourcePath")));
146 if (actual_src_cfpath)
147 {
148 CFStringRef build_src_cfpath = static_cast<CFStringRef>(::CFDictionaryGetValue (uuid_dict, CFSTR("DBGBuildSourcePath")));
149 if (build_src_cfpath)
150 {
151 char actual_src_path[PATH_MAX];
152 char build_src_path[PATH_MAX];
153 ::CFStringGetFileSystemRepresentation (actual_src_cfpath, actual_src_path, sizeof(actual_src_path));
154 ::CFStringGetFileSystemRepresentation (build_src_cfpath, build_src_path, sizeof(build_src_path));
Greg Clayton96816e42012-07-13 01:20:25 +0000155 if (actual_src_path[0] == '~')
156 {
157 FileSpec resolved_source_path(actual_src_path, true);
158 resolved_source_path.GetPath(actual_src_path, sizeof(actual_src_path));
159 }
Greg Claytond804d282012-03-15 21:01:31 +0000160 module_spec.GetSourceMappingList().Append (ConstString(build_src_path), ConstString(actual_src_path), true);
161 }
162 }
163 }
164 }
165
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000166 if (out_exec_fspec)
167 {
Greg Claytonc859e2d2012-02-13 23:10:39 +0000168 bool success = false;
Greg Claytond804d282012-03-15 21:01:31 +0000169 if (uuid_dict)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000170 {
Greg Claytond804d282012-03-15 21:01:31 +0000171 CFStringRef exec_cf_path = static_cast<CFStringRef>(::CFDictionaryGetValue (uuid_dict, CFSTR("DBGSymbolRichExecutable")));
172 if (exec_cf_path && ::CFStringGetFileSystemRepresentation (exec_cf_path, path, sizeof(path)))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000173 {
Greg Claytond804d282012-03-15 21:01:31 +0000174 ++items_found;
175 out_exec_fspec->SetFile(path, path[0] == '~');
176 if (out_exec_fspec->Exists())
177 success = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000178 }
179 }
Greg Claytonc859e2d2012-02-13 23:10:39 +0000180
181 if (!success)
Greg Claytona63d08c2011-07-19 03:57:15 +0000182 {
183 // No dictionary, check near the dSYM bundle for an executable that matches...
184 if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1))
185 {
186 char *dsym_extension_pos = ::strstr (path, ".dSYM");
187 if (dsym_extension_pos)
188 {
189 *dsym_extension_pos = '\0';
190 FileSpec file_spec (path, true);
Robert Flack31870e12015-04-24 18:09:54 +0000191 ModuleSpecList module_specs;
192 ModuleSpec matched_module_spec;
Greg Claytona63d08c2011-07-19 03:57:15 +0000193 switch (file_spec.GetFileType())
194 {
195 case FileSpec::eFileTypeDirectory: // Bundle directory?
196 {
197 CFCBundle bundle (path);
198 CFCReleaser<CFURLRef> bundle_exe_url (bundle.CopyExecutableURL ());
199 if (bundle_exe_url.get())
200 {
201 if (::CFURLGetFileSystemRepresentation (bundle_exe_url.get(), true, (UInt8*)path, sizeof(path)-1))
202 {
203 FileSpec bundle_exe_file_spec (path, true);
Robert Flack31870e12015-04-24 18:09:54 +0000204 if (ObjectFile::GetModuleSpecifications(bundle_exe_file_spec, 0, 0, module_specs) &&
205 module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec))
206
Greg Claytona63d08c2011-07-19 03:57:15 +0000207 {
208 ++items_found;
209 *out_exec_fspec = bundle_exe_file_spec;
210 }
211 }
212 }
213 }
214 break;
Robert Flack31870e12015-04-24 18:09:54 +0000215
Greg Claytona63d08c2011-07-19 03:57:15 +0000216 case FileSpec::eFileTypePipe: // Forget pipes
217 case FileSpec::eFileTypeSocket: // We can't process socket files
218 case FileSpec::eFileTypeInvalid: // File doesn't exist...
219 break;
220
221 case FileSpec::eFileTypeUnknown:
222 case FileSpec::eFileTypeRegular:
223 case FileSpec::eFileTypeSymbolicLink:
224 case FileSpec::eFileTypeOther:
Robert Flack31870e12015-04-24 18:09:54 +0000225 if (ObjectFile::GetModuleSpecifications(file_spec, 0, 0, module_specs) &&
226 module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec))
227
Greg Claytona63d08c2011-07-19 03:57:15 +0000228 {
229 ++items_found;
230 *out_exec_fspec = file_spec;
231 }
232 break;
233 }
234 }
235 }
236 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000237 }
238 }
239 }
240 }
241 }
Todd Fiala013434e2014-07-09 01:29:05 +0000242#endif // #if !defined (__arm__) && !defined (__arm64__) && !defined (__aarch64__)
Greg Claytondce502e2011-11-04 03:34:56 +0000243
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000244 return items_found;
245}
246
Robert Flack31870e12015-04-24 18:09:54 +0000247FileSpec
248Symbols::FindSymbolFileInBundle (const FileSpec& dsym_bundle_fspec,
249 const lldb_private::UUID *uuid,
250 const ArchSpec *arch)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000251{
Robert Flack31870e12015-04-24 18:09:54 +0000252 char path[PATH_MAX];
253
254 FileSpec dsym_fspec;
255
256 if (dsym_bundle_fspec.GetPath(path, sizeof(path)))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000257 {
Robert Flack31870e12015-04-24 18:09:54 +0000258 ::strncat (path, "/Contents/Resources/DWARF", sizeof(path) - strlen(path) - 1);
259
260 lldb_utility::CleanUp <DIR *, int> dirp (opendir(path), NULL, closedir);
261 if (dirp.is_valid())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000262 {
Robert Flack31870e12015-04-24 18:09:54 +0000263 dsym_fspec.GetDirectory().SetCString(path);
264 struct dirent* dp;
265 while ((dp = readdir(dirp.get())) != NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000266 {
Robert Flack31870e12015-04-24 18:09:54 +0000267 // Only search directories
268 if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000269 {
Robert Flack31870e12015-04-24 18:09:54 +0000270 if (dp->d_namlen == 1 && dp->d_name[0] == '.')
271 continue;
272
273 if (dp->d_namlen == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.')
274 continue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000275 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000276
Robert Flack31870e12015-04-24 18:09:54 +0000277 if (dp->d_type == DT_REG || dp->d_type == DT_UNKNOWN)
278 {
279 dsym_fspec.GetFilename().SetCString(dp->d_name);
280 ModuleSpecList module_specs;
281 if (ObjectFile::GetModuleSpecifications(dsym_fspec, 0, 0, module_specs))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000282 {
Robert Flack31870e12015-04-24 18:09:54 +0000283 ModuleSpec spec;
284 for (size_t i = 0; i < module_specs.GetSize(); ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000285 {
Robert Flack31870e12015-04-24 18:09:54 +0000286 assert(module_specs.GetModuleSpecAtIndex(i, spec));
287 if ((uuid == NULL || (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) &&
288 (arch == NULL || (spec.GetArchitecturePtr() && spec.GetArchitecture().IsCompatibleMatch(*arch))))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000289 {
Robert Flack31870e12015-04-24 18:09:54 +0000290 return dsym_fspec;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000291 }
292 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000293 }
294 }
295 }
296 }
297 }
298 dsym_fspec.Clear();
Robert Flack31870e12015-04-24 18:09:54 +0000299 return dsym_fspec;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000300}
301
Greg Claytonb5f0fea2012-09-27 22:26:11 +0000302static bool
303GetModuleSpecInfoFromUUIDDictionary (CFDictionaryRef uuid_dict, ModuleSpec &module_spec)
304{
305 bool success = false;
306 if (uuid_dict != NULL && CFGetTypeID (uuid_dict) == CFDictionaryGetTypeID ())
307 {
308 std::string str;
309 CFStringRef cf_str;
310
311 cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGSymbolRichExecutable"));
312 if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
313 {
314 if (CFCString::FileSystemRepresentation(cf_str, str))
315 module_spec.GetFileSpec().SetFile (str.c_str(), true);
316 }
317
318 cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGDSYMPath"));
319 if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
320 {
321 if (CFCString::FileSystemRepresentation(cf_str, str))
322 {
323 module_spec.GetSymbolFileSpec().SetFile (str.c_str(), true);
324 success = true;
325 }
326 }
327
328 cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGArchitecture"));
329 if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
330 {
331 if (CFCString::FileSystemRepresentation(cf_str, str))
332 module_spec.GetArchitecture().SetTriple(str.c_str());
333 }
334
335 std::string DBGBuildSourcePath;
336 std::string DBGSourcePath;
337
338 cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGBuildSourcePath"));
339 if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
340 {
341 CFCString::FileSystemRepresentation(cf_str, DBGBuildSourcePath);
342 }
343
344 cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGSourcePath"));
345 if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
346 {
347 CFCString::FileSystemRepresentation(cf_str, DBGSourcePath);
348 }
349
350 if (!DBGBuildSourcePath.empty() && !DBGSourcePath.empty())
351 {
352 module_spec.GetSourceMappingList().Append (ConstString(DBGBuildSourcePath.c_str()), ConstString(DBGSourcePath.c_str()), true);
353 }
354 }
355 return success;
356}
Greg Claytonc8f814d2012-09-27 03:13:55 +0000357
358
359bool
Jason Molendabb860bd2012-10-09 01:17:11 +0000360Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec, bool force_lookup)
Greg Claytonc8f814d2012-09-27 03:13:55 +0000361{
362 bool success = false;
363 const UUID *uuid_ptr = module_spec.GetUUIDPtr();
Greg Claytonb5f0fea2012-09-27 22:26:11 +0000364 const FileSpec *file_spec_ptr = module_spec.GetFileSpecPtr();
Jason Molendabb860bd2012-10-09 01:17:11 +0000365
366 // It's expensive to check for the DBGShellCommands defaults setting, only do it once per
367 // lldb run and cache the result.
368 static bool g_have_checked_for_dbgshell_command = false;
369 static const char *g_dbgshell_command = NULL;
370 if (g_have_checked_for_dbgshell_command == false)
371 {
372 g_have_checked_for_dbgshell_command = true;
373 CFTypeRef defaults_setting = CFPreferencesCopyAppValue (CFSTR ("DBGShellCommands"), CFSTR ("com.apple.DebugSymbols"));
374 if (defaults_setting && CFGetTypeID (defaults_setting) == CFStringGetTypeID())
375 {
376 char cstr_buf[PATH_MAX];
377 if (CFStringGetCString ((CFStringRef) defaults_setting, cstr_buf, sizeof (cstr_buf), kCFStringEncodingUTF8))
378 {
379 g_dbgshell_command = strdup (cstr_buf); // this malloc'ed memory will never be freed
380 }
381 }
382 if (defaults_setting)
383 {
384 CFRelease (defaults_setting);
385 }
386 }
387
388 // When g_dbgshell_command is NULL, the user has not enabled the use of an external program
389 // to find the symbols, don't run it for them.
390 if (force_lookup == false && g_dbgshell_command == NULL)
391 {
392 return false;
393 }
394
Greg Claytonb5f0fea2012-09-27 22:26:11 +0000395 if (uuid_ptr || (file_spec_ptr && file_spec_ptr->Exists()))
Greg Claytonc8f814d2012-09-27 03:13:55 +0000396 {
397 static bool g_located_dsym_for_uuid_exe = false;
398 static bool g_dsym_for_uuid_exe_exists = false;
399 static char g_dsym_for_uuid_exe_path[PATH_MAX];
400 if (!g_located_dsym_for_uuid_exe)
401 {
402 g_located_dsym_for_uuid_exe = true;
403 const char *dsym_for_uuid_exe_path_cstr = getenv("LLDB_APPLE_DSYMFORUUID_EXECUTABLE");
404 FileSpec dsym_for_uuid_exe_spec;
405 if (dsym_for_uuid_exe_path_cstr)
406 {
407 dsym_for_uuid_exe_spec.SetFile(dsym_for_uuid_exe_path_cstr, true);
408 g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
409 }
410
411 if (!g_dsym_for_uuid_exe_exists)
412 {
Jason Molenda055c57b2012-10-30 21:26:30 +0000413 dsym_for_uuid_exe_spec.SetFile("/usr/local/bin/dsymForUUID", false);
Greg Claytonc8f814d2012-09-27 03:13:55 +0000414 g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
415 if (!g_dsym_for_uuid_exe_exists)
416 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000417 long bufsize;
Jason Molenda055c57b2012-10-30 21:26:30 +0000418 if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) != -1)
419 {
420 char buffer[bufsize];
421 struct passwd pwd;
422 struct passwd *tilde_rc = NULL;
423 // we are a library so we need to use the reentrant version of getpwnam()
424 if (getpwnam_r ("rc", &pwd, buffer, bufsize, &tilde_rc) == 0
425 && tilde_rc
426 && tilde_rc->pw_dir)
427 {
428 std::string dsymforuuid_path(tilde_rc->pw_dir);
429 dsymforuuid_path += "/bin/dsymForUUID";
430 dsym_for_uuid_exe_spec.SetFile(dsymforuuid_path.c_str(), false);
431 g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
432 }
433 }
Greg Claytonc8f814d2012-09-27 03:13:55 +0000434 }
435 }
Jason Molendabb860bd2012-10-09 01:17:11 +0000436 if (!g_dsym_for_uuid_exe_exists && g_dbgshell_command != NULL)
437 {
438 dsym_for_uuid_exe_spec.SetFile(g_dbgshell_command, true);
439 g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
440 }
441
Greg Claytonc8f814d2012-09-27 03:13:55 +0000442 if (g_dsym_for_uuid_exe_exists)
443 dsym_for_uuid_exe_spec.GetPath (g_dsym_for_uuid_exe_path, sizeof(g_dsym_for_uuid_exe_path));
444 }
445 if (g_dsym_for_uuid_exe_exists)
446 {
Jason Molendac16b4af2013-05-03 23:56:12 +0000447 std::string uuid_str;
Greg Claytonb5f0fea2012-09-27 22:26:11 +0000448 char file_path[PATH_MAX];
Greg Claytonb5f0fea2012-09-27 22:26:11 +0000449 file_path[0] = '\0';
Greg Claytonb5f0fea2012-09-27 22:26:11 +0000450
451 if (uuid_ptr)
Jason Molendac16b4af2013-05-03 23:56:12 +0000452 uuid_str = uuid_ptr->GetAsString();
Greg Claytonb5f0fea2012-09-27 22:26:11 +0000453
454 if (file_spec_ptr)
455 file_spec_ptr->GetPath(file_path, sizeof(file_path));
456
457 StreamString command;
Jason Molendac16b4af2013-05-03 23:56:12 +0000458 if (!uuid_str.empty())
459 command.Printf("%s --ignoreNegativeCache --copyExecutable %s", g_dsym_for_uuid_exe_path, uuid_str.c_str());
Jason Molenda5b941152014-10-17 01:38:10 +0000460 else if (file_path[0] != '\0')
Jason Molenda743e43962012-10-02 22:23:42 +0000461 command.Printf("%s --ignoreNegativeCache --copyExecutable %s", g_dsym_for_uuid_exe_path, file_path);
Greg Claytonb5f0fea2012-09-27 22:26:11 +0000462
463 if (!command.GetString().empty())
Greg Claytonc8f814d2012-09-27 03:13:55 +0000464 {
Greg Claytonb5f0fea2012-09-27 22:26:11 +0000465 int exit_status = -1;
466 int signo = -1;
467 std::string command_output;
468 Error error = Host::RunShellCommand (command.GetData(),
469 NULL, // current working directory
470 &exit_status, // Exit status
471 &signo, // Signal int *
472 &command_output, // Command output
473 30, // Large timeout to allow for long dsym download times
Nico Weber92b25b92015-01-15 17:55:24 +0000474 false); // Don't run in a shell (we don't need shell expansion)
Greg Claytonb5f0fea2012-09-27 22:26:11 +0000475 if (error.Success() && exit_status == 0 && !command_output.empty())
Greg Claytonc8f814d2012-09-27 03:13:55 +0000476 {
Greg Claytonb5f0fea2012-09-27 22:26:11 +0000477 CFCData data (CFDataCreateWithBytesNoCopy (NULL,
478 (const UInt8 *)command_output.data(),
479 command_output.size(),
480 kCFAllocatorNull));
481
482 CFCReleaser<CFDictionaryRef> plist((CFDictionaryRef)::CFPropertyListCreateFromXMLData (NULL, data.get(), kCFPropertyListImmutable, NULL));
483
Sean Callanan29214ab2013-02-08 23:17:17 +0000484 if (plist.get() && CFGetTypeID (plist.get()) == CFDictionaryGetTypeID ())
Greg Claytonc8f814d2012-09-27 03:13:55 +0000485 {
Jason Molendac16b4af2013-05-03 23:56:12 +0000486 if (!uuid_str.empty())
Greg Claytonc8f814d2012-09-27 03:13:55 +0000487 {
Jason Molendac16b4af2013-05-03 23:56:12 +0000488 CFCString uuid_cfstr(uuid_str.c_str());
Greg Claytonb5f0fea2012-09-27 22:26:11 +0000489 CFDictionaryRef uuid_dict = (CFDictionaryRef)CFDictionaryGetValue (plist.get(), uuid_cfstr.get());
490 success = GetModuleSpecInfoFromUUIDDictionary (uuid_dict, module_spec);
Greg Claytonc8f814d2012-09-27 03:13:55 +0000491 }
Greg Claytonb5f0fea2012-09-27 22:26:11 +0000492 else
Greg Claytonc8f814d2012-09-27 03:13:55 +0000493 {
Greg Claytonb5f0fea2012-09-27 22:26:11 +0000494 const CFIndex num_values = ::CFDictionaryGetCount(plist.get());
495 if (num_values > 0)
Greg Claytonc8f814d2012-09-27 03:13:55 +0000496 {
Greg Claytonb5f0fea2012-09-27 22:26:11 +0000497 std::vector<CFStringRef> keys (num_values, NULL);
498 std::vector<CFDictionaryRef> values (num_values, NULL);
499 ::CFDictionaryGetKeysAndValues(plist.get(), NULL, (const void **)&values[0]);
500 if (num_values == 1)
501 {
502 return GetModuleSpecInfoFromUUIDDictionary (values[0], module_spec);
503 }
504 else
505 {
506 for (CFIndex i=0; i<num_values; ++i)
507 {
508 ModuleSpec curr_module_spec;
509 if (GetModuleSpecInfoFromUUIDDictionary (values[i], curr_module_spec))
510 {
Sean Callananbf4b7be2012-12-13 22:07:14 +0000511 if (module_spec.GetArchitecture().IsCompatibleMatch(curr_module_spec.GetArchitecture()))
Greg Claytonb5f0fea2012-09-27 22:26:11 +0000512 {
513 module_spec = curr_module_spec;
514 return true;
515 }
516 }
517 }
518 }
Greg Claytonc8f814d2012-09-27 03:13:55 +0000519 }
520 }
521 }
522 }
523 }
524 }
525 }
526 return success;
527}
528