blob: acaf563907ec8b8bff407e44b9e04428b61fdc4d [file] [log] [blame]
Chris Lattner24943d22010-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>
Greg Clayton1674b122010-07-21 22:12:05 +000014#include "llvm/Support/MachO.h"
Chris Lattner24943d22010-06-08 16:52:24 +000015
16// C++ Includes
17// Other libraries and framework includes
18#include <CoreFoundation/CoreFoundation.h>
19
20// Project includes
Chris Lattner24943d22010-06-08 16:52:24 +000021#include "lldb/Core/ArchSpec.h"
22#include "lldb/Core/DataBuffer.h"
23#include "lldb/Core/DataExtractor.h"
24#include "lldb/Core/Timer.h"
25#include "lldb/Core/UUID.h"
Greg Claytoncd548032011-02-01 01:31:41 +000026#include "lldb/Host/Endian.h"
Greg Claytonad400272011-02-01 05:15:02 +000027#include "lldb/Utility/CleanUp.h"
Daniel Dunbara1ebbd22011-10-31 22:50:53 +000028#include "Host/macosx/cfcpp/CFCBundle.h"
Greg Clayton54e7afa2010-07-09 20:39:50 +000029#include "Host/macosx/cfcpp/CFCReleaser.h"
Greg Claytonb72d0f02011-04-12 05:54:46 +000030#include "Host/macosx/cfcpp/CFCString.h"
Chris Lattner5bc7b672010-09-08 23:01:14 +000031#include "mach/machine.h"
Greg Clayton54e7afa2010-07-09 20:39:50 +000032
Greg Clayton0fa51242011-07-19 03:57:15 +000033
Chris Lattner24943d22010-06-08 16:52:24 +000034using namespace lldb;
35using namespace lldb_private;
Greg Clayton1674b122010-07-21 22:12:05 +000036using namespace llvm::MachO;
Chris Lattner24943d22010-06-08 16:52:24 +000037
Greg Clayton3e4238d2011-11-04 03:34:56 +000038#if !defined (__arm__) // No DebugSymbols on the iOS devices
Chris Lattner24943d22010-06-08 16:52:24 +000039extern "C" {
Greg Clayton54e7afa2010-07-09 20:39:50 +000040
Chris Lattner24943d22010-06-08 16:52:24 +000041CFURLRef DBGCopyFullDSYMURLForUUID (CFUUIDRef uuid, CFURLRef exec_url);
42CFDictionaryRef DBGCopyDSYMPropertyLists (CFURLRef dsym_url);
Greg Clayton54e7afa2010-07-09 20:39:50 +000043
44}
Greg Clayton3e4238d2011-11-04 03:34:56 +000045#endif
Chris Lattner24943d22010-06-08 16:52:24 +000046
47static bool
48SkinnyMachOFileContainsArchAndUUID
49(
50 const FileSpec &file_spec,
51 const ArchSpec *arch,
Greg Clayton0467c782011-02-04 18:53:10 +000052 const lldb_private::UUID *uuid, // the UUID we are looking for
Chris Lattner24943d22010-06-08 16:52:24 +000053 off_t file_offset,
54 DataExtractor& data,
55 uint32_t data_offset,
56 const uint32_t magic
57)
58{
Greg Clayton1674b122010-07-21 22:12:05 +000059 assert(magic == HeaderMagic32 || magic == HeaderMagic32Swapped || magic == HeaderMagic64 || magic == HeaderMagic64Swapped);
60 if (magic == HeaderMagic32 || magic == HeaderMagic64)
Greg Claytoncd548032011-02-01 01:31:41 +000061 data.SetByteOrder (lldb::endian::InlHostByteOrder());
62 else if (lldb::endian::InlHostByteOrder() == eByteOrderBig)
Chris Lattner24943d22010-06-08 16:52:24 +000063 data.SetByteOrder (eByteOrderLittle);
64 else
65 data.SetByteOrder (eByteOrderBig);
66
67 uint32_t i;
68 const uint32_t cputype = data.GetU32(&data_offset); // cpu specifier
69 const uint32_t cpusubtype = data.GetU32(&data_offset); // machine specifier
70 data_offset+=4; // Skip mach file type
71 const uint32_t ncmds = data.GetU32(&data_offset); // number of load commands
72 const uint32_t sizeofcmds = data.GetU32(&data_offset); // the size of all the load commands
73 data_offset+=4; // Skip flags
74
75 // Check the architecture if we have a valid arch pointer
76 if (arch)
77 {
Greg Claytoncf015052010-06-11 03:25:34 +000078 ArchSpec file_arch(eArchTypeMachO, cputype, cpusubtype);
Chris Lattner24943d22010-06-08 16:52:24 +000079
80 if (file_arch != *arch)
81 return false;
82 }
83
84 // The file exists, and if a valid arch pointer was passed in we know
85 // if already matches, so we can return if we aren't looking for a specific
86 // UUID
87 if (uuid == NULL)
88 return true;
89
Greg Clayton1674b122010-07-21 22:12:05 +000090 if (magic == HeaderMagic64Swapped || magic == HeaderMagic64)
Chris Lattner24943d22010-06-08 16:52:24 +000091 data_offset += 4; // Skip reserved field for in mach_header_64
92
93 // Make sure we have enough data for all the load commands
Greg Clayton1674b122010-07-21 22:12:05 +000094 if (magic == HeaderMagic64Swapped || magic == HeaderMagic64)
Chris Lattner24943d22010-06-08 16:52:24 +000095 {
96 if (data.GetByteSize() < sizeof(struct mach_header_64) + sizeofcmds)
97 {
98 DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header_64) + sizeofcmds));
99 data.SetData (data_buffer_sp);
100 }
101 }
102 else
103 {
104 if (data.GetByteSize() < sizeof(struct mach_header) + sizeofcmds)
105 {
106 DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header) + sizeofcmds));
107 data.SetData (data_buffer_sp);
108 }
109 }
110
111 for (i=0; i<ncmds; i++)
112 {
113 const uint32_t cmd_offset = data_offset; // Save this data_offset in case parsing of the segment goes awry!
114 uint32_t cmd = data.GetU32(&data_offset);
115 uint32_t cmd_size = data.GetU32(&data_offset);
Greg Clayton1674b122010-07-21 22:12:05 +0000116 if (cmd == LoadCommandUUID)
Chris Lattner24943d22010-06-08 16:52:24 +0000117 {
Greg Clayton0467c782011-02-04 18:53:10 +0000118 lldb_private::UUID file_uuid (data.GetData(&data_offset, 16), 16);
Chris Lattner24943d22010-06-08 16:52:24 +0000119 return file_uuid == *uuid;
120 }
121 data_offset = cmd_offset + cmd_size;
122 }
123 return false;
124}
125
126bool
127UniversalMachOFileContainsArchAndUUID
128(
129 const FileSpec &file_spec,
130 const ArchSpec *arch,
Greg Clayton0467c782011-02-04 18:53:10 +0000131 const lldb_private::UUID *uuid,
Chris Lattner24943d22010-06-08 16:52:24 +0000132 off_t file_offset,
133 DataExtractor& data,
134 uint32_t data_offset,
135 const uint32_t magic
136)
137{
Greg Clayton1674b122010-07-21 22:12:05 +0000138 assert(magic == UniversalMagic || magic == UniversalMagicSwapped);
Chris Lattner24943d22010-06-08 16:52:24 +0000139
140 // Universal mach-o files always have their headers encoded as BIG endian
141 data.SetByteOrder(eByteOrderBig);
142
143 uint32_t i;
144 const uint32_t nfat_arch = data.GetU32(&data_offset); // number of structs that follow
145 const uint32_t fat_header_and_arch_size = sizeof(struct fat_header) + nfat_arch * sizeof(struct fat_arch);
146 if (data.GetByteSize() < fat_header_and_arch_size)
147 {
148 DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, fat_header_and_arch_size));
149 data.SetData (data_buffer_sp);
150 }
151
152 for (i=0; i<nfat_arch; i++)
153 {
154 cpu_type_t arch_cputype = data.GetU32(&data_offset); // cpu specifier (int)
155 cpu_subtype_t arch_cpusubtype = data.GetU32(&data_offset); // machine specifier (int)
156 uint32_t arch_offset = data.GetU32(&data_offset); // file offset to this object file
157 // uint32_t arch_size = data.GetU32(&data_offset); // size of this object file
158 // uint32_t arch_align = data.GetU32(&data_offset); // alignment as a power of 2
159 data_offset += 8; // Skip size and align as we don't need those
160 // Only process this slice if the cpu type/subtype matches
161 if (arch)
162 {
Greg Claytoncf015052010-06-11 03:25:34 +0000163 ArchSpec fat_arch(eArchTypeMachO, arch_cputype, arch_cpusubtype);
Chris Lattner24943d22010-06-08 16:52:24 +0000164 if (fat_arch != *arch)
165 continue;
166 }
167
168 // Create a buffer with only the arch slice date in it
169 DataExtractor arch_data;
170 DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset + arch_offset, 0x1000));
171 arch_data.SetData(data_buffer_sp);
172 uint32_t arch_data_offset = 0;
173 uint32_t arch_magic = arch_data.GetU32(&arch_data_offset);
174
175 switch (arch_magic)
176 {
Greg Clayton1674b122010-07-21 22:12:05 +0000177 case HeaderMagic32:
178 case HeaderMagic32Swapped:
179 case HeaderMagic64:
180 case HeaderMagic64Swapped:
Chris Lattner24943d22010-06-08 16:52:24 +0000181 if (SkinnyMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset + arch_offset, arch_data, arch_data_offset, arch_magic))
182 return true;
183 break;
184 }
185 }
186 return false;
187}
188
189static bool
190FileAtPathContainsArchAndUUID
191(
192 const FileSpec &file_spec,
193 const ArchSpec *arch,
Greg Clayton0467c782011-02-04 18:53:10 +0000194 const lldb_private::UUID *uuid
Chris Lattner24943d22010-06-08 16:52:24 +0000195)
196{
197 DataExtractor data;
198 off_t file_offset = 0;
199 DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, 0x1000));
200
201 if (data_buffer_sp && data_buffer_sp->GetByteSize() > 0)
202 {
203 data.SetData(data_buffer_sp);
204
205 uint32_t data_offset = 0;
206 uint32_t magic = data.GetU32(&data_offset);
207
208 switch (magic)
209 {
210 // 32 bit mach-o file
Greg Clayton1674b122010-07-21 22:12:05 +0000211 case HeaderMagic32:
212 case HeaderMagic32Swapped:
213 case HeaderMagic64:
214 case HeaderMagic64Swapped:
Chris Lattner24943d22010-06-08 16:52:24 +0000215 return SkinnyMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset, data, data_offset, magic);
216
217 // fat mach-o file
Greg Clayton1674b122010-07-21 22:12:05 +0000218 case UniversalMagic:
219 case UniversalMagicSwapped:
Chris Lattner24943d22010-06-08 16:52:24 +0000220 return UniversalMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset, data, data_offset, magic);
221
222 default:
223 break;
224 }
225 }
226 return false;
227}
228
229static FileSpec
230LocateDSYMMachFileInDSYMBundle
231(
232 const FileSpec& dsym_bundle_fspec,
Greg Clayton0467c782011-02-04 18:53:10 +0000233 const lldb_private::UUID *uuid,
Chris Lattner24943d22010-06-08 16:52:24 +0000234 const ArchSpec *arch)
235{
236 char path[PATH_MAX];
237
238 FileSpec dsym_fspec;
239
240 if (dsym_bundle_fspec.GetPath(path, sizeof(path)))
241 {
242 ::strncat (path, "/Contents/Resources/DWARF", sizeof(path) - strlen(path) - 1);
243
Greg Clayton52fd9842011-02-02 02:24:04 +0000244 lldb_utility::CleanUp <DIR *, int> dirp (opendir(path), NULL, closedir);
Greg Claytonad400272011-02-01 05:15:02 +0000245 if (dirp.is_valid())
Chris Lattner24943d22010-06-08 16:52:24 +0000246 {
Greg Clayton537a7a82010-10-20 20:54:39 +0000247 dsym_fspec.GetDirectory().SetCString(path);
Chris Lattner24943d22010-06-08 16:52:24 +0000248 struct dirent* dp;
Greg Claytonad400272011-02-01 05:15:02 +0000249 while ((dp = readdir(dirp.get())) != NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000250 {
251 // Only search directories
252 if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN)
253 {
254 if (dp->d_namlen == 1 && dp->d_name[0] == '.')
255 continue;
256
257 if (dp->d_namlen == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.')
258 continue;
259 }
260
261 if (dp->d_type == DT_REG || dp->d_type == DT_UNKNOWN)
262 {
Greg Clayton537a7a82010-10-20 20:54:39 +0000263 dsym_fspec.GetFilename().SetCString(dp->d_name);
Chris Lattner24943d22010-06-08 16:52:24 +0000264 if (FileAtPathContainsArchAndUUID (dsym_fspec, arch, uuid))
265 return dsym_fspec;
266 }
267 }
268 }
269 }
270 dsym_fspec.Clear();
271 return dsym_fspec;
272}
273
274static int
275LocateMacOSXFilesUsingDebugSymbols
276(
277 const FileSpec *exec_fspec, // An executable path that may or may not be correct if UUID is specified
278 const ArchSpec* arch, // Limit the search to files with this architecture if non-NULL
Greg Clayton0467c782011-02-04 18:53:10 +0000279 const lldb_private::UUID *uuid, // Match the UUID value if non-NULL,
Chris Lattner24943d22010-06-08 16:52:24 +0000280 FileSpec *out_exec_fspec, // If non-NULL, try and find the executable
281 FileSpec *out_dsym_fspec // If non-NULL try and find the debug symbol file
282)
283{
284 int items_found = 0;
285
286 if (out_exec_fspec)
287 out_exec_fspec->Clear();
288
289 if (out_dsym_fspec)
290 out_dsym_fspec->Clear();
291
Greg Clayton3e4238d2011-11-04 03:34:56 +0000292#if !defined (__arm__) // No DebugSymbols on the iOS devices
293
Chris Lattner24943d22010-06-08 16:52:24 +0000294 if (uuid && uuid->IsValid())
295 {
296 // Try and locate the dSYM file using DebugSymbols first
297 const UInt8 *module_uuid = (const UInt8 *)uuid->GetBytes();
298 if (module_uuid != NULL)
299 {
Greg Clayton0fa51242011-07-19 03:57:15 +0000300 CFCReleaser<CFUUIDRef> module_uuid_ref(::CFUUIDCreateWithBytes (NULL,
Chris Lattner24943d22010-06-08 16:52:24 +0000301 module_uuid[0],
302 module_uuid[1],
303 module_uuid[2],
304 module_uuid[3],
305 module_uuid[4],
306 module_uuid[5],
307 module_uuid[6],
308 module_uuid[7],
309 module_uuid[8],
310 module_uuid[9],
311 module_uuid[10],
312 module_uuid[11],
313 module_uuid[12],
314 module_uuid[13],
315 module_uuid[14],
316 module_uuid[15]));
317
318 if (module_uuid_ref.get())
319 {
320 CFCReleaser<CFURLRef> exec_url;
321
322 if (exec_fspec)
323 {
324 char exec_cf_path[PATH_MAX];
325 if (exec_fspec->GetPath(exec_cf_path, sizeof(exec_cf_path)))
326 exec_url.reset(::CFURLCreateFromFileSystemRepresentation (NULL,
327 (const UInt8 *)exec_cf_path,
328 strlen(exec_cf_path),
329 FALSE));
330 }
331
332 CFCReleaser<CFURLRef> dsym_url (::DBGCopyFullDSYMURLForUUID(module_uuid_ref.get(), exec_url.get()));
333 char path[PATH_MAX];
334
335 if (dsym_url.get())
336 {
337 if (out_dsym_fspec)
338 {
339 if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1))
340 {
Greg Clayton537a7a82010-10-20 20:54:39 +0000341 out_dsym_fspec->SetFile(path, false);
Chris Lattner24943d22010-06-08 16:52:24 +0000342
343 if (out_dsym_fspec->GetFileType () == FileSpec::eFileTypeDirectory)
344 {
345 *out_dsym_fspec = LocateDSYMMachFileInDSYMBundle (*out_dsym_fspec, uuid, arch);
346 if (*out_dsym_fspec)
347 ++items_found;
348 }
349 else
350 {
351 ++items_found;
352 }
353 }
354 }
355
356 if (out_exec_fspec)
357 {
358 CFCReleaser<CFDictionaryRef> dict(::DBGCopyDSYMPropertyLists (dsym_url.get()));;
359 if (dict.get())
360 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000361 char uuid_cstr_buf[64];
362 const char *uuid_cstr = uuid->GetAsCString (uuid_cstr_buf, sizeof(uuid_cstr_buf));
363 CFCString uuid_cfstr (uuid_cstr);
364 CFDictionaryRef uuid_dict = static_cast<CFDictionaryRef>(::CFDictionaryGetValue (dict.get(), uuid_cfstr.get()));
365 if (uuid_dict)
Chris Lattner24943d22010-06-08 16:52:24 +0000366 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000367 CFStringRef exec_cf_path = static_cast<CFStringRef>(::CFDictionaryGetValue (uuid_dict, CFSTR("DBGSymbolRichExecutable")));
368 if (exec_cf_path && ::CFStringGetFileSystemRepresentation (exec_cf_path, path, sizeof(path)))
369 {
370 ++items_found;
371 out_exec_fspec->SetFile(path, path[0] == '~');
372 }
Chris Lattner24943d22010-06-08 16:52:24 +0000373 }
374 }
Greg Clayton0fa51242011-07-19 03:57:15 +0000375 else
376 {
377 // No dictionary, check near the dSYM bundle for an executable that matches...
378 if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1))
379 {
380 char *dsym_extension_pos = ::strstr (path, ".dSYM");
381 if (dsym_extension_pos)
382 {
383 *dsym_extension_pos = '\0';
384 FileSpec file_spec (path, true);
385 switch (file_spec.GetFileType())
386 {
387 case FileSpec::eFileTypeDirectory: // Bundle directory?
388 {
389 CFCBundle bundle (path);
390 CFCReleaser<CFURLRef> bundle_exe_url (bundle.CopyExecutableURL ());
391 if (bundle_exe_url.get())
392 {
393 if (::CFURLGetFileSystemRepresentation (bundle_exe_url.get(), true, (UInt8*)path, sizeof(path)-1))
394 {
395 FileSpec bundle_exe_file_spec (path, true);
396
397 if (FileAtPathContainsArchAndUUID (bundle_exe_file_spec, arch, uuid))
398 {
399 ++items_found;
400 *out_exec_fspec = bundle_exe_file_spec;
401 }
402 }
403 }
404 }
405 break;
406
407 case FileSpec::eFileTypePipe: // Forget pipes
408 case FileSpec::eFileTypeSocket: // We can't process socket files
409 case FileSpec::eFileTypeInvalid: // File doesn't exist...
410 break;
411
412 case FileSpec::eFileTypeUnknown:
413 case FileSpec::eFileTypeRegular:
414 case FileSpec::eFileTypeSymbolicLink:
415 case FileSpec::eFileTypeOther:
416 if (FileAtPathContainsArchAndUUID (file_spec, arch, uuid))
417 {
418 ++items_found;
419 *out_exec_fspec = file_spec;
420 }
421 break;
422 }
423 }
424 }
425 }
Chris Lattner24943d22010-06-08 16:52:24 +0000426 }
427 }
428 }
429 }
430 }
Greg Clayton3e4238d2011-11-04 03:34:56 +0000431#endif // #if !defined (__arm__)
432
Chris Lattner24943d22010-06-08 16:52:24 +0000433 return items_found;
434}
435
436static bool
Greg Clayton0467c782011-02-04 18:53:10 +0000437LocateDSYMInVincinityOfExecutable (const FileSpec *exec_fspec, const ArchSpec* arch, const lldb_private::UUID *uuid, FileSpec &dsym_fspec)
Chris Lattner24943d22010-06-08 16:52:24 +0000438{
439 if (exec_fspec)
440 {
441 char path[PATH_MAX];
442 if (exec_fspec->GetPath(path, sizeof(path)))
443 {
444 // Make sure the module isn't already just a dSYM file...
445 if (strcasestr(path, ".dSYM/Contents/Resources/DWARF") == NULL)
446 {
447 size_t obj_file_path_length = strlen(path);
448 strncat(path, ".dSYM/Contents/Resources/DWARF/", sizeof(path));
449 strncat(path, exec_fspec->GetFilename().AsCString(), sizeof(path));
450
Greg Clayton537a7a82010-10-20 20:54:39 +0000451 dsym_fspec.SetFile(path, false);
Chris Lattner24943d22010-06-08 16:52:24 +0000452
Greg Claytondb2dc2b2012-01-12 05:25:17 +0000453 if (dsym_fspec.Exists() && FileAtPathContainsArchAndUUID (dsym_fspec, arch, uuid))
Chris Lattner24943d22010-06-08 16:52:24 +0000454 {
455 return true;
456 }
457 else
458 {
459 path[obj_file_path_length] = '\0';
460
461 char *last_dot = strrchr(path, '.');
462 while (last_dot != NULL && last_dot[0])
463 {
464 char *next_slash = strchr(last_dot, '/');
465 if (next_slash != NULL)
466 {
467 *next_slash = '\0';
468 strncat(path, ".dSYM/Contents/Resources/DWARF/", sizeof(path));
469 strncat(path, exec_fspec->GetFilename().AsCString(), sizeof(path));
Greg Clayton537a7a82010-10-20 20:54:39 +0000470 dsym_fspec.SetFile(path, false);
Greg Claytondb2dc2b2012-01-12 05:25:17 +0000471 if (dsym_fspec.Exists() && FileAtPathContainsArchAndUUID (dsym_fspec, arch, uuid))
Chris Lattner24943d22010-06-08 16:52:24 +0000472 return true;
473 else
474 {
475 *last_dot = '\0';
476 char *prev_slash = strrchr(path, '/');
477 if (prev_slash != NULL)
478 *prev_slash = '\0';
479 else
480 break;
481 }
482 }
483 else
484 {
485 break;
486 }
487 }
488 }
489 }
490 }
491 }
492 dsym_fspec.Clear();
493 return false;
494}
495
496FileSpec
Greg Clayton0467c782011-02-04 18:53:10 +0000497Symbols::LocateExecutableObjectFile (const FileSpec *exec_fspec, const ArchSpec* arch, const lldb_private::UUID *uuid)
Chris Lattner24943d22010-06-08 16:52:24 +0000498{
499 Timer scoped_timer (__PRETTY_FUNCTION__,
500 "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)",
501 exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>",
Greg Clayton940b1032011-02-23 00:35:02 +0000502 arch ? arch->GetArchitectureName() : "<NULL>",
Chris Lattner24943d22010-06-08 16:52:24 +0000503 uuid);
504
505 FileSpec objfile_fspec;
506 if (exec_fspec && FileAtPathContainsArchAndUUID (*exec_fspec, arch, uuid))
507 objfile_fspec = *exec_fspec;
508 else
509 LocateMacOSXFilesUsingDebugSymbols (exec_fspec, arch, uuid, &objfile_fspec, NULL);
510 return objfile_fspec;
511}
512
513FileSpec
Greg Clayton0467c782011-02-04 18:53:10 +0000514Symbols::LocateExecutableSymbolFile (const FileSpec *exec_fspec, const ArchSpec* arch, const lldb_private::UUID *uuid)
Chris Lattner24943d22010-06-08 16:52:24 +0000515{
516 Timer scoped_timer (__PRETTY_FUNCTION__,
517 "LocateExecutableSymbolFile (file = %s, arch = %s, uuid = %p)",
518 exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>",
Greg Clayton940b1032011-02-23 00:35:02 +0000519 arch ? arch->GetArchitectureName() : "<NULL>",
Chris Lattner24943d22010-06-08 16:52:24 +0000520 uuid);
521
522 FileSpec symbol_fspec;
523 // First try and find the dSYM in the same directory as the executable or in
524 // an appropriate parent directory
525 if (LocateDSYMInVincinityOfExecutable (exec_fspec, arch, uuid, symbol_fspec) == false)
526 {
527 // We failed to easily find the dSYM above, so use DebugSymbols
528 LocateMacOSXFilesUsingDebugSymbols (exec_fspec, arch, uuid, NULL, &symbol_fspec);
529 }
530 return symbol_fspec;
531}