124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===-- Symbols.cpp ---------------------------------------------*- C++ -*-===//
224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//                     The LLVM Compiler Infrastructure
424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// This file is distributed under the University of Illinois Open Source
624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// License. See LICENSE.TXT for details.
724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===----------------------------------------------------------------------===//
924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Host/Symbols.h"
1124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// C Includes
1324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <dirent.h>
14f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda#include <pwd.h>
151674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton#include "llvm/Support/MachO.h"
1624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// C++ Includes
1824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Other libraries and framework includes
1924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <CoreFoundation/CoreFoundation.h>
2024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
2124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Project includes
2224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/ArchSpec.h"
2324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/DataBuffer.h"
2424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/DataExtractor.h"
25444fe998bf707bd076a70c3a779db8575533695eGreg Clayton#include "lldb/Core/Module.h"
2649ce8969d3154e1560106cfe530444c09410f217Greg Clayton#include "lldb/Core/ModuleSpec.h"
279262cd52e254fb261334254a80a1b316d59b555cJohnny Chen#include "lldb/Core/StreamString.h"
2824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/Timer.h"
2924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/UUID.h"
30cd548034fa23113e995b8463d14f910ba2f7298cGreg Clayton#include "lldb/Host/Endian.h"
31cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen#include "lldb/Host/Host.h"
32ad400274d4e3ed01a4c730e1d6f95e6cb2ac73dcGreg Clayton#include "lldb/Utility/CleanUp.h"
33a1ebbd2410cafb890ab8519ae4e6b24cc618bd6aDaniel Dunbar#include "Host/macosx/cfcpp/CFCBundle.h"
34b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton#include "Host/macosx/cfcpp/CFCData.h"
3554e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton#include "Host/macosx/cfcpp/CFCReleaser.h"
36b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton#include "Host/macosx/cfcpp/CFCString.h"
375bc7b67ccc8bb4a977d129e51313067dcbc7bb94Chris Lattner#include "mach/machine.h"
3854e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton
390fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton
4024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb;
4124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb_private;
421674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Claytonusing namespace llvm::MachO;
4324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
443e4238d47a6d1a3106f357d2e7b495870721c7aeGreg Clayton#if !defined (__arm__) // No DebugSymbols on the iOS devices
4524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerextern "C" {
4654e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton
4724943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerCFURLRef DBGCopyFullDSYMURLForUUID (CFUUIDRef uuid, CFURLRef exec_url);
4824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerCFDictionaryRef DBGCopyDSYMPropertyLists (CFURLRef dsym_url);
4954e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton
5054e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton}
513e4238d47a6d1a3106f357d2e7b495870721c7aeGreg Clayton#endif
5224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
5324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic bool
5424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerSkinnyMachOFileContainsArchAndUUID
5524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner(
5624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const FileSpec &file_spec,
5724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const ArchSpec *arch,
580467c78e9a75eff9ec33d3c1f39fa83e1c5d9241Greg Clayton    const lldb_private::UUID *uuid,   // the UUID we are looking for
5924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    off_t file_offset,
6024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DataExtractor& data,
6136da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton    lldb::offset_t data_offset,
6224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint32_t magic
6324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner)
6424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
651674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton    assert(magic == HeaderMagic32 || magic == HeaderMagic32Swapped || magic == HeaderMagic64 || magic == HeaderMagic64Swapped);
661674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton    if (magic == HeaderMagic32 || magic == HeaderMagic64)
67cd548034fa23113e995b8463d14f910ba2f7298cGreg Clayton        data.SetByteOrder (lldb::endian::InlHostByteOrder());
68cd548034fa23113e995b8463d14f910ba2f7298cGreg Clayton    else if (lldb::endian::InlHostByteOrder() == eByteOrderBig)
6924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        data.SetByteOrder (eByteOrderLittle);
7024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
7124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        data.SetByteOrder (eByteOrderBig);
7224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
7324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    uint32_t i;
7424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint32_t cputype      = data.GetU32(&data_offset);    // cpu specifier
7524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint32_t cpusubtype   = data.GetU32(&data_offset);    // machine specifier
7624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    data_offset+=4; // Skip mach file type
7724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint32_t ncmds        = data.GetU32(&data_offset);    // number of load commands
7824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint32_t sizeofcmds   = data.GetU32(&data_offset);    // the size of all the load commands
7924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    data_offset+=4; // Skip flags
8024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
8124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Check the architecture if we have a valid arch pointer
8224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (arch)
8324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
84cf0150574a0a97049efe2dce2cc0aa433705feb3Greg Clayton        ArchSpec file_arch(eArchTypeMachO, cputype, cpusubtype);
8524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
86878f13c99c0dcbe2a5ac22f233522233d8dc52d4Sean Callanan        if (!file_arch.IsCompatibleMatch(*arch))
8724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return false;
8824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
8924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
9024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // The file exists, and if a valid arch pointer was passed in we know
9124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // if already matches, so we can return if we aren't looking for a specific
9224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // UUID
9324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (uuid == NULL)
9424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return true;
9524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
961674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton    if (magic == HeaderMagic64Swapped || magic == HeaderMagic64)
9724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        data_offset += 4;   // Skip reserved field for in mach_header_64
9824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
9924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Make sure we have enough data for all the load commands
1001674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton    if (magic == HeaderMagic64Swapped || magic == HeaderMagic64)
10124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
10224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (data.GetByteSize() < sizeof(struct mach_header_64) + sizeofcmds)
10324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
10424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header_64) + sizeofcmds));
10524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            data.SetData (data_buffer_sp);
10624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
10724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
10824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
10924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
11024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (data.GetByteSize() < sizeof(struct mach_header) + sizeofcmds)
11124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
11224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header) + sizeofcmds));
11324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            data.SetData (data_buffer_sp);
11424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
11524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
11624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
11724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    for (i=0; i<ncmds; i++)
11824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
11936da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton        const lldb::offset_t cmd_offset = data_offset;    // Save this data_offset in case parsing of the segment goes awry!
12024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        uint32_t cmd        = data.GetU32(&data_offset);
12124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        uint32_t cmd_size   = data.GetU32(&data_offset);
1221674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        if (cmd == LoadCommandUUID)
12324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
1240467c78e9a75eff9ec33d3c1f39fa83e1c5d9241Greg Clayton            lldb_private::UUID file_uuid (data.GetData(&data_offset, 16), 16);
125cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen            if (file_uuid == *uuid)
126cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen                return true;
127cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen            return false;
12824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
12924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        data_offset = cmd_offset + cmd_size;
13024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
13124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return false;
13224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
13324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
13424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
13524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerUniversalMachOFileContainsArchAndUUID
13624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner(
13724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const FileSpec &file_spec,
13824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const ArchSpec *arch,
1390467c78e9a75eff9ec33d3c1f39fa83e1c5d9241Greg Clayton    const lldb_private::UUID *uuid,
14024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    off_t file_offset,
14124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DataExtractor& data,
14236da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton    lldb::offset_t data_offset,
14324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint32_t magic
14424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner)
14524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
1461674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton    assert(magic == UniversalMagic || magic == UniversalMagicSwapped);
14724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
14824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Universal mach-o files always have their headers encoded as BIG endian
14924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    data.SetByteOrder(eByteOrderBig);
15024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
15124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    uint32_t i;
15224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint32_t nfat_arch = data.GetU32(&data_offset);   // number of structs that follow
15324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint32_t fat_header_and_arch_size = sizeof(struct fat_header) + nfat_arch * sizeof(struct fat_arch);
15424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (data.GetByteSize() < fat_header_and_arch_size)
15524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
15624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, fat_header_and_arch_size));
15724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        data.SetData (data_buffer_sp);
15824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
15924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
16024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    for (i=0; i<nfat_arch; i++)
16124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
16224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        cpu_type_t      arch_cputype        = data.GetU32(&data_offset);    // cpu specifier (int)
16324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        cpu_subtype_t   arch_cpusubtype     = data.GetU32(&data_offset);    // machine specifier (int)
16424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        uint32_t        arch_offset         = data.GetU32(&data_offset);    // file offset to this object file
16524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    //  uint32_t        arch_size           = data.GetU32(&data_offset);    // size of this object file
16624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    //  uint32_t        arch_align          = data.GetU32(&data_offset);    // alignment as a power of 2
16724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        data_offset += 8;   // Skip size and align as we don't need those
16824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Only process this slice if the cpu type/subtype matches
16924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (arch)
17024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
171cf0150574a0a97049efe2dce2cc0aa433705feb3Greg Clayton            ArchSpec fat_arch(eArchTypeMachO, arch_cputype, arch_cpusubtype);
17264246cda58b64208f5c415fc52909c45c3dc3e2bSean Callanan            if (!fat_arch.IsExactMatch(*arch))
17324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                continue;
17424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
17524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
17624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Create a buffer with only the arch slice date in it
17724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        DataExtractor arch_data;
17824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset + arch_offset, 0x1000));
17924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        arch_data.SetData(data_buffer_sp);
18036da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton        lldb::offset_t arch_data_offset = 0;
18124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        uint32_t arch_magic = arch_data.GetU32(&arch_data_offset);
18224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
18324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        switch (arch_magic)
18424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
1851674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic32:
1861674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic32Swapped:
1871674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic64:
1881674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic64Swapped:
18924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (SkinnyMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset + arch_offset, arch_data, arch_data_offset, arch_magic))
19024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                return true;
19124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            break;
19224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
19324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
19424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return false;
19524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
19624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
19724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic bool
19824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileAtPathContainsArchAndUUID
19924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner(
20024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const FileSpec &file_spec,
20124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const ArchSpec *arch,
2020467c78e9a75eff9ec33d3c1f39fa83e1c5d9241Greg Clayton    const lldb_private::UUID *uuid
20324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner)
20424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
20524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DataExtractor data;
20624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    off_t file_offset = 0;
20724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, 0x1000));
20824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
20924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (data_buffer_sp && data_buffer_sp->GetByteSize() > 0)
21024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
21124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        data.SetData(data_buffer_sp);
21224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
21336da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton        lldb::offset_t data_offset = 0;
21424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        uint32_t magic = data.GetU32(&data_offset);
21524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
21624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        switch (magic)
21724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
21824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // 32 bit mach-o file
2191674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic32:
2201674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic32Swapped:
2211674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic64:
2221674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic64Swapped:
22324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return SkinnyMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset, data, data_offset, magic);
22424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
22524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // fat mach-o file
2261674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case UniversalMagic:
2271674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case UniversalMagicSwapped:
22824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return UniversalMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset, data, data_offset, magic);
22924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
23024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        default:
23124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            break;
23224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
23324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
23424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return false;
23524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
23624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
23795b765e8000b44644d021e95bc58eac95028573bGreg ClaytonFileSpec
23895b765e8000b44644d021e95bc58eac95028573bGreg ClaytonSymbols::FindSymbolFileInBundle (const FileSpec& dsym_bundle_fspec,
23995b765e8000b44644d021e95bc58eac95028573bGreg Clayton                                 const lldb_private::UUID *uuid,
24095b765e8000b44644d021e95bc58eac95028573bGreg Clayton                                 const ArchSpec *arch)
24124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
24224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char path[PATH_MAX];
24324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
24424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    FileSpec dsym_fspec;
24524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
24624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (dsym_bundle_fspec.GetPath(path, sizeof(path)))
24724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
24824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        ::strncat (path, "/Contents/Resources/DWARF", sizeof(path) - strlen(path) - 1);
24924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
25052fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton        lldb_utility::CleanUp <DIR *, int> dirp (opendir(path), NULL, closedir);
251ad400274d4e3ed01a4c730e1d6f95e6cb2ac73dcGreg Clayton        if (dirp.is_valid())
25224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
253537a7a86687683fd403ce652d178fbc89e06ef9fGreg Clayton            dsym_fspec.GetDirectory().SetCString(path);
25424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            struct dirent* dp;
255ad400274d4e3ed01a4c730e1d6f95e6cb2ac73dcGreg Clayton            while ((dp = readdir(dirp.get())) != NULL)
25624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
25724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // Only search directories
25824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN)
25924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
26024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (dp->d_namlen == 1 && dp->d_name[0] == '.')
26124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        continue;
26224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
26324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (dp->d_namlen == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.')
26424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        continue;
26524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
26624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
26724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (dp->d_type == DT_REG || dp->d_type == DT_UNKNOWN)
26824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
269537a7a86687683fd403ce652d178fbc89e06ef9fGreg Clayton                    dsym_fspec.GetFilename().SetCString(dp->d_name);
27024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (FileAtPathContainsArchAndUUID (dsym_fspec, arch, uuid))
27124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        return dsym_fspec;
27224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
27324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
27424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
27524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
27624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    dsym_fspec.Clear();
27724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return dsym_fspec;
27824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
27924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
28024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic int
28124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerLocateMacOSXFilesUsingDebugSymbols
28224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner(
283444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const ModuleSpec &module_spec,
28424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    FileSpec *out_exec_fspec,   // If non-NULL, try and find the executable
28524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    FileSpec *out_dsym_fspec    // If non-NULL try and find the debug symbol file
28624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner)
28724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
28824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    int items_found = 0;
28924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
29024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (out_exec_fspec)
29124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        out_exec_fspec->Clear();
29224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
29324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (out_dsym_fspec)
29424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        out_dsym_fspec->Clear();
29524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
2963e4238d47a6d1a3106f357d2e7b495870721c7aeGreg Clayton#if !defined (__arm__) // No DebugSymbols on the iOS devices
2973e4238d47a6d1a3106f357d2e7b495870721c7aeGreg Clayton
298444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const UUID *uuid = module_spec.GetUUIDPtr();
299444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const ArchSpec *arch = module_spec.GetArchitecturePtr();
300444fe998bf707bd076a70c3a779db8575533695eGreg Clayton
30124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (uuid && uuid->IsValid())
30224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
30324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Try and locate the dSYM file using DebugSymbols first
30424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        const UInt8 *module_uuid = (const UInt8 *)uuid->GetBytes();
30524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (module_uuid != NULL)
30624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
3070fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton            CFCReleaser<CFUUIDRef> module_uuid_ref(::CFUUIDCreateWithBytes (NULL,
30824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[0],
30924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[1],
31024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[2],
31124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[3],
31224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[4],
31324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[5],
31424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[6],
31524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[7],
31624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[8],
31724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[9],
31824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[10],
31924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[11],
32024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[12],
32124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[13],
32224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[14],
32324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[15]));
32424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
32524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (module_uuid_ref.get())
32624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
32724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                CFCReleaser<CFURLRef> exec_url;
328444fe998bf707bd076a70c3a779db8575533695eGreg Clayton                const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
32924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (exec_fspec)
33024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
33124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    char exec_cf_path[PATH_MAX];
33224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (exec_fspec->GetPath(exec_cf_path, sizeof(exec_cf_path)))
33324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        exec_url.reset(::CFURLCreateFromFileSystemRepresentation (NULL,
33424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                                  (const UInt8 *)exec_cf_path,
33524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                                  strlen(exec_cf_path),
33624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                                  FALSE));
33724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
33824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
33924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                CFCReleaser<CFURLRef> dsym_url (::DBGCopyFullDSYMURLForUUID(module_uuid_ref.get(), exec_url.get()));
34024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                char path[PATH_MAX];
34124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
34224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (dsym_url.get())
34324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
34424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (out_dsym_fspec)
34524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
34624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1))
34724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
3481b09dfef975addaa4aa330edb1dc7e28b8436028Jason Molenda                            out_dsym_fspec->SetFile(path, path[0] == '~');
34924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
35024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            if (out_dsym_fspec->GetFileType () == FileSpec::eFileTypeDirectory)
35124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            {
35295b765e8000b44644d021e95bc58eac95028573bGreg Clayton                                *out_dsym_fspec = Symbols::FindSymbolFileInBundle (*out_dsym_fspec, uuid, arch);
35324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                if (*out_dsym_fspec)
35424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                    ++items_found;
35524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            }
35624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            else
35724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            {
35824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                ++items_found;
35924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            }
36024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
36124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
36224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
363964deba8853eb794e59263322b59b09b43669618Greg Clayton                    CFCReleaser<CFDictionaryRef> dict(::DBGCopyDSYMPropertyLists (dsym_url.get()));
364964deba8853eb794e59263322b59b09b43669618Greg Clayton                    CFDictionaryRef uuid_dict = NULL;
365964deba8853eb794e59263322b59b09b43669618Greg Clayton                    if (dict.get())
36624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
36742b336cd509cad89be08f78775d3b1c8c7656a1bJason Molenda                        CFCString uuid_cfstr (uuid->GetAsString().c_str());
36863e5cf65c43615da20b272fde2a21ffd4fa6eb29Jason Molenda                        uuid_dict = static_cast<CFDictionaryRef>(::CFDictionaryGetValue (dict.get(), uuid_cfstr.get()));
369964deba8853eb794e59263322b59b09b43669618Greg Clayton                        if (uuid_dict)
37024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
371964deba8853eb794e59263322b59b09b43669618Greg Clayton
372964deba8853eb794e59263322b59b09b43669618Greg Clayton                            CFStringRef actual_src_cfpath = static_cast<CFStringRef>(::CFDictionaryGetValue (uuid_dict, CFSTR("DBGSourcePath")));
373964deba8853eb794e59263322b59b09b43669618Greg Clayton                            if (actual_src_cfpath)
37424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            {
375964deba8853eb794e59263322b59b09b43669618Greg Clayton                                CFStringRef build_src_cfpath = static_cast<CFStringRef>(::CFDictionaryGetValue (uuid_dict, CFSTR("DBGBuildSourcePath")));
376964deba8853eb794e59263322b59b09b43669618Greg Clayton                                if (build_src_cfpath)
377b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton                                {
378964deba8853eb794e59263322b59b09b43669618Greg Clayton                                    char actual_src_path[PATH_MAX];
379964deba8853eb794e59263322b59b09b43669618Greg Clayton                                    char build_src_path[PATH_MAX];
380964deba8853eb794e59263322b59b09b43669618Greg Clayton                                    ::CFStringGetFileSystemRepresentation (actual_src_cfpath, actual_src_path, sizeof(actual_src_path));
381964deba8853eb794e59263322b59b09b43669618Greg Clayton                                    ::CFStringGetFileSystemRepresentation (build_src_cfpath, build_src_path, sizeof(build_src_path));
3824d8c5434779393d5502b45f42a9371477604aab7Greg Clayton                                    if (actual_src_path[0] == '~')
3834d8c5434779393d5502b45f42a9371477604aab7Greg Clayton                                    {
3844d8c5434779393d5502b45f42a9371477604aab7Greg Clayton                                        FileSpec resolved_source_path(actual_src_path, true);
3854d8c5434779393d5502b45f42a9371477604aab7Greg Clayton                                        resolved_source_path.GetPath(actual_src_path, sizeof(actual_src_path));
3864d8c5434779393d5502b45f42a9371477604aab7Greg Clayton                                    }
387964deba8853eb794e59263322b59b09b43669618Greg Clayton                                    module_spec.GetSourceMappingList().Append (ConstString(build_src_path), ConstString(actual_src_path), true);
388b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton                                }
3890fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                            }
3900fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                        }
391964deba8853eb794e59263322b59b09b43669618Greg Clayton                    }
392964deba8853eb794e59263322b59b09b43669618Greg Clayton
393964deba8853eb794e59263322b59b09b43669618Greg Clayton                    if (out_exec_fspec)
394964deba8853eb794e59263322b59b09b43669618Greg Clayton                    {
395964deba8853eb794e59263322b59b09b43669618Greg Clayton                        bool success = false;
396964deba8853eb794e59263322b59b09b43669618Greg Clayton                        if (uuid_dict)
397964deba8853eb794e59263322b59b09b43669618Greg Clayton                        {
398964deba8853eb794e59263322b59b09b43669618Greg Clayton                            CFStringRef exec_cf_path = static_cast<CFStringRef>(::CFDictionaryGetValue (uuid_dict, CFSTR("DBGSymbolRichExecutable")));
399964deba8853eb794e59263322b59b09b43669618Greg Clayton                            if (exec_cf_path && ::CFStringGetFileSystemRepresentation (exec_cf_path, path, sizeof(path)))
400964deba8853eb794e59263322b59b09b43669618Greg Clayton                            {
401964deba8853eb794e59263322b59b09b43669618Greg Clayton                                ++items_found;
402964deba8853eb794e59263322b59b09b43669618Greg Clayton                                out_exec_fspec->SetFile(path, path[0] == '~');
403964deba8853eb794e59263322b59b09b43669618Greg Clayton                                if (out_exec_fspec->Exists())
404964deba8853eb794e59263322b59b09b43669618Greg Clayton                                    success = true;
405964deba8853eb794e59263322b59b09b43669618Greg Clayton                            }
406964deba8853eb794e59263322b59b09b43669618Greg Clayton                        }
4079ce953807eb814a93b449dc243de4f7bf32c3115Greg Clayton
4089ce953807eb814a93b449dc243de4f7bf32c3115Greg Clayton                        if (!success)
4090fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                        {
4100fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                            // No dictionary, check near the dSYM bundle for an executable that matches...
4110fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                            if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1))
4120fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                            {
4130fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                char *dsym_extension_pos = ::strstr (path, ".dSYM");
4140fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                if (dsym_extension_pos)
4150fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                {
4160fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                    *dsym_extension_pos = '\0';
4170fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                    FileSpec file_spec (path, true);
4180fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                    switch (file_spec.GetFileType())
4190fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                    {
4200fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeDirectory:  // Bundle directory?
4210fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            {
4220fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                CFCBundle bundle (path);
4230fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                CFCReleaser<CFURLRef> bundle_exe_url (bundle.CopyExecutableURL ());
4240fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                if (bundle_exe_url.get())
4250fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                {
4260fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                    if (::CFURLGetFileSystemRepresentation (bundle_exe_url.get(), true, (UInt8*)path, sizeof(path)-1))
4270fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                    {
4280fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                        FileSpec bundle_exe_file_spec (path, true);
4290fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton
4300fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                        if (FileAtPathContainsArchAndUUID (bundle_exe_file_spec, arch, uuid))
4310fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                        {
4320fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                            ++items_found;
4330fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                            *out_exec_fspec = bundle_exe_file_spec;
4340fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                        }
4350fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                    }
4360fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                }
4370fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            }
4380fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            break;
4390fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton
4400fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypePipe:       // Forget pipes
4410fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeSocket:     // We can't process socket files
4420fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeInvalid:    // File doesn't exist...
4430fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            break;
4440fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton
4450fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeUnknown:
4460fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeRegular:
4470fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeSymbolicLink:
4480fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeOther:
4490fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            if (FileAtPathContainsArchAndUUID (file_spec, arch, uuid))
4500fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            {
4510fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                ++items_found;
4520fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                *out_exec_fspec = file_spec;
4530fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            }
4540fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            break;
4550fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                    }
4560fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                }
45724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            }
45824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
45924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
46024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
46124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
46224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
46324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
4643e4238d47a6d1a3106f357d2e7b495870721c7aeGreg Clayton#endif // #if !defined (__arm__)
4653e4238d47a6d1a3106f357d2e7b495870721c7aeGreg Clayton
46624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return items_found;
46724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
46824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
46924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic bool
470444fe998bf707bd076a70c3a779db8575533695eGreg ClaytonLocateDSYMInVincinityOfExecutable (const ModuleSpec &module_spec, FileSpec &dsym_fspec)
47124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
472444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
47324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (exec_fspec)
47424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
47524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        char path[PATH_MAX];
47624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (exec_fspec->GetPath(path, sizeof(path)))
47724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
47824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            // Make sure the module isn't already just a dSYM file...
47924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (strcasestr(path, ".dSYM/Contents/Resources/DWARF") == NULL)
48024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
48124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                size_t obj_file_path_length = strlen(path);
48278c180ab423d3a802566d49a41363b132f20c907Filipe Cabecinhas                strlcat(path, ".dSYM/Contents/Resources/DWARF/", sizeof(path));
48378c180ab423d3a802566d49a41363b132f20c907Filipe Cabecinhas                strlcat(path, exec_fspec->GetFilename().AsCString(), sizeof(path));
48424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
485537a7a86687683fd403ce652d178fbc89e06ef9fGreg Clayton                dsym_fspec.SetFile(path, false);
48624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
487444fe998bf707bd076a70c3a779db8575533695eGreg Clayton                if (dsym_fspec.Exists() && FileAtPathContainsArchAndUUID (dsym_fspec, module_spec.GetArchitecturePtr(), module_spec.GetUUIDPtr()))
48824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
48924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    return true;
49024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
49124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                else
49224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
49324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    path[obj_file_path_length] = '\0';
49424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
49524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    char *last_dot = strrchr(path, '.');
49624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    while (last_dot != NULL && last_dot[0])
49724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
49824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        char *next_slash = strchr(last_dot, '/');
49924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        if (next_slash != NULL)
50024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
50124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            *next_slash = '\0';
50278c180ab423d3a802566d49a41363b132f20c907Filipe Cabecinhas                            strlcat(path, ".dSYM/Contents/Resources/DWARF/", sizeof(path));
50378c180ab423d3a802566d49a41363b132f20c907Filipe Cabecinhas                            strlcat(path, exec_fspec->GetFilename().AsCString(), sizeof(path));
504537a7a86687683fd403ce652d178fbc89e06ef9fGreg Clayton                            dsym_fspec.SetFile(path, false);
505444fe998bf707bd076a70c3a779db8575533695eGreg Clayton                            if (dsym_fspec.Exists() && FileAtPathContainsArchAndUUID (dsym_fspec, module_spec.GetArchitecturePtr(), module_spec.GetUUIDPtr()))
50624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                return true;
50724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            else
50824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            {
50924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                *last_dot = '\0';
51024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                char *prev_slash = strrchr(path, '/');
51124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                if (prev_slash != NULL)
51224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                    *prev_slash = '\0';
51324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                else
51424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                    break;
51524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            }
51624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
51724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        else
51824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
51924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            break;
52024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
52124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
52224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
52324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
52424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
52524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
52624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    dsym_fspec.Clear();
52724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return false;
52824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
52924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
53024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec
531444fe998bf707bd076a70c3a779db8575533695eGreg ClaytonSymbols::LocateExecutableObjectFile (const ModuleSpec &module_spec)
53224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
533444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
534444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const ArchSpec *arch = module_spec.GetArchitecturePtr();
535444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const UUID *uuid = module_spec.GetUUIDPtr();
53624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    Timer scoped_timer (__PRETTY_FUNCTION__,
53724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)",
53824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>",
539940b103224f3062578c7a7e6e76d8bf4a7956f2aGreg Clayton                        arch ? arch->GetArchitectureName() : "<NULL>",
54024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        uuid);
54124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
54224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    FileSpec objfile_fspec;
543444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    if (exec_fspec && FileAtPathContainsArchAndUUID (exec_fspec, arch, uuid))
544444fe998bf707bd076a70c3a779db8575533695eGreg Clayton        objfile_fspec = exec_fspec;
54524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
546444fe998bf707bd076a70c3a779db8575533695eGreg Clayton        LocateMacOSXFilesUsingDebugSymbols (module_spec, &objfile_fspec, NULL);
54724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return objfile_fspec;
54824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
54924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
55024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec
551444fe998bf707bd076a70c3a779db8575533695eGreg ClaytonSymbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec)
55224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
553444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
554444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const ArchSpec *arch = module_spec.GetArchitecturePtr();
555444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const UUID *uuid = module_spec.GetUUIDPtr();
556444fe998bf707bd076a70c3a779db8575533695eGreg Clayton
55724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    Timer scoped_timer (__PRETTY_FUNCTION__,
55824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        "LocateExecutableSymbolFile (file = %s, arch = %s, uuid = %p)",
55924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>",
560940b103224f3062578c7a7e6e76d8bf4a7956f2aGreg Clayton                        arch ? arch->GetArchitectureName() : "<NULL>",
56124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        uuid);
56224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
56324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    FileSpec symbol_fspec;
56424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // First try and find the dSYM in the same directory as the executable or in
56524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // an appropriate parent directory
566444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    if (LocateDSYMInVincinityOfExecutable (module_spec, symbol_fspec) == false)
56724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
56824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // We failed to easily find the dSYM above, so use DebugSymbols
569444fe998bf707bd076a70c3a779db8575533695eGreg Clayton        LocateMacOSXFilesUsingDebugSymbols (module_spec, NULL, &symbol_fspec);
57024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
57124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return symbol_fspec;
57224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
573b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton
574b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton
575437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Claytonstatic bool
576437b5bccea45a5981edbbbeb4e23424aec4ce774Greg ClaytonGetModuleSpecInfoFromUUIDDictionary (CFDictionaryRef uuid_dict, ModuleSpec &module_spec)
577437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton{
578437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton    bool success = false;
579437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton    if (uuid_dict != NULL && CFGetTypeID (uuid_dict) == CFDictionaryGetTypeID ())
580437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton    {
581437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        std::string str;
582437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        CFStringRef cf_str;
583437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
584437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGSymbolRichExecutable"));
585437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
586437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        {
587437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            if (CFCString::FileSystemRepresentation(cf_str, str))
588437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                module_spec.GetFileSpec().SetFile (str.c_str(), true);
589437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        }
590437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
591437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGDSYMPath"));
592437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
593437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        {
594437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            if (CFCString::FileSystemRepresentation(cf_str, str))
595437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            {
596437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                module_spec.GetSymbolFileSpec().SetFile (str.c_str(), true);
597437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                success = true;
598437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            }
599437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        }
600437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
601437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGArchitecture"));
602437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
603437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        {
604437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            if (CFCString::FileSystemRepresentation(cf_str, str))
605437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                module_spec.GetArchitecture().SetTriple(str.c_str());
606437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        }
607437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
608437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        std::string DBGBuildSourcePath;
609437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        std::string DBGSourcePath;
610437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
611437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGBuildSourcePath"));
612437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
613437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        {
614437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            CFCString::FileSystemRepresentation(cf_str, DBGBuildSourcePath);
615437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        }
616437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
617437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGSourcePath"));
618437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
619437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        {
620437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            CFCString::FileSystemRepresentation(cf_str, DBGSourcePath);
621437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        }
622437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
623437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        if (!DBGBuildSourcePath.empty() && !DBGSourcePath.empty())
624437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        {
625437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            module_spec.GetSourceMappingList().Append (ConstString(DBGBuildSourcePath.c_str()), ConstString(DBGSourcePath.c_str()), true);
626437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        }
627437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton    }
628437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton    return success;
629437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton}
630b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton
631b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton
632b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Claytonbool
633d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason MolendaSymbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec, bool force_lookup)
634b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton{
635b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton    bool success = false;
636b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton    const UUID *uuid_ptr = module_spec.GetUUIDPtr();
637437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton    const FileSpec *file_spec_ptr = module_spec.GetFileSpecPtr();
638d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda
639d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    // It's expensive to check for the DBGShellCommands defaults setting, only do it once per
640d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    // lldb run and cache the result.
641d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    static bool g_have_checked_for_dbgshell_command = false;
642d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    static const char *g_dbgshell_command = NULL;
643d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    if (g_have_checked_for_dbgshell_command == false)
644d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    {
645d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda        g_have_checked_for_dbgshell_command = true;
646d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda        CFTypeRef defaults_setting = CFPreferencesCopyAppValue (CFSTR ("DBGShellCommands"), CFSTR ("com.apple.DebugSymbols"));
647d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda        if (defaults_setting && CFGetTypeID (defaults_setting) == CFStringGetTypeID())
648d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda        {
649d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda            char cstr_buf[PATH_MAX];
650d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda            if (CFStringGetCString ((CFStringRef) defaults_setting, cstr_buf, sizeof (cstr_buf), kCFStringEncodingUTF8))
651d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda            {
652d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda                g_dbgshell_command = strdup (cstr_buf);  // this malloc'ed memory will never be freed
653d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda            }
654d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda        }
655d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda        if (defaults_setting)
656d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda        {
657d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda            CFRelease (defaults_setting);
658d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda        }
659d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    }
660d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda
661d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    // When g_dbgshell_command is NULL, the user has not enabled the use of an external program
662d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    // to find the symbols, don't run it for them.
663d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    if (force_lookup == false && g_dbgshell_command == NULL)
664d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    {
665d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda        return false;
666d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    }
667d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda
668437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton    if (uuid_ptr || (file_spec_ptr && file_spec_ptr->Exists()))
669b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton    {
670b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton        static bool g_located_dsym_for_uuid_exe = false;
671b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton        static bool g_dsym_for_uuid_exe_exists = false;
672b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton        static char g_dsym_for_uuid_exe_path[PATH_MAX];
673b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton        if (!g_located_dsym_for_uuid_exe)
674b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton        {
675b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            g_located_dsym_for_uuid_exe = true;
676b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            const char *dsym_for_uuid_exe_path_cstr = getenv("LLDB_APPLE_DSYMFORUUID_EXECUTABLE");
677b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            FileSpec dsym_for_uuid_exe_spec;
678b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            if (dsym_for_uuid_exe_path_cstr)
679b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            {
680b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                dsym_for_uuid_exe_spec.SetFile(dsym_for_uuid_exe_path_cstr, true);
681b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
682b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            }
683b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton
684b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            if (!g_dsym_for_uuid_exe_exists)
685b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            {
686f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                dsym_for_uuid_exe_spec.SetFile("/usr/local/bin/dsymForUUID", false);
687b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
688b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                if (!g_dsym_for_uuid_exe_exists)
689b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                {
69036da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton                    long bufsize;
691f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                    if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) != -1)
692f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                    {
693f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                        char buffer[bufsize];
694f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                        struct passwd pwd;
695f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                        struct passwd *tilde_rc = NULL;
696f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                        // we are a library so we need to use the reentrant version of getpwnam()
697f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                        if (getpwnam_r ("rc", &pwd, buffer, bufsize, &tilde_rc) == 0
698f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                            && tilde_rc
699f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                            && tilde_rc->pw_dir)
700f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                        {
701f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                            std::string dsymforuuid_path(tilde_rc->pw_dir);
702f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                            dsymforuuid_path += "/bin/dsymForUUID";
703f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                            dsym_for_uuid_exe_spec.SetFile(dsymforuuid_path.c_str(), false);
704f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                            g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
705f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                        }
706f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                    }
707b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                }
708b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            }
709d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda            if (!g_dsym_for_uuid_exe_exists && g_dbgshell_command != NULL)
710d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda            {
711d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda                dsym_for_uuid_exe_spec.SetFile(g_dbgshell_command, true);
712d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda                g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
713d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda            }
714d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda
715b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            if (g_dsym_for_uuid_exe_exists)
716b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                dsym_for_uuid_exe_spec.GetPath (g_dsym_for_uuid_exe_path, sizeof(g_dsym_for_uuid_exe_path));
717b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton        }
718b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton        if (g_dsym_for_uuid_exe_exists)
719b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton        {
72042b336cd509cad89be08f78775d3b1c8c7656a1bJason Molenda            std::string uuid_str;
721437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            char file_path[PATH_MAX];
722437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            file_path[0] = '\0';
723437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
724437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            if (uuid_ptr)
72542b336cd509cad89be08f78775d3b1c8c7656a1bJason Molenda                uuid_str = uuid_ptr->GetAsString();
726437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
727437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            if (file_spec_ptr)
728437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                file_spec_ptr->GetPath(file_path, sizeof(file_path));
729437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
730437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            StreamString command;
73142b336cd509cad89be08f78775d3b1c8c7656a1bJason Molenda            if (!uuid_str.empty())
73242b336cd509cad89be08f78775d3b1c8c7656a1bJason Molenda                command.Printf("%s --ignoreNegativeCache --copyExecutable %s", g_dsym_for_uuid_exe_path, uuid_str.c_str());
733437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            else if (file_path && file_path[0])
73463e5cf65c43615da20b272fde2a21ffd4fa6eb29Jason Molenda                command.Printf("%s --ignoreNegativeCache --copyExecutable %s", g_dsym_for_uuid_exe_path, file_path);
735437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
736437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            if (!command.GetString().empty())
737b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            {
738437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                int exit_status = -1;
739437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                int signo = -1;
740437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                std::string command_output;
741437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                Error error = Host::RunShellCommand (command.GetData(),
742437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                     NULL,              // current working directory
743437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                     &exit_status,      // Exit status
744437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                     &signo,            // Signal int *
745437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                     &command_output,   // Command output
746437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                     30,                // Large timeout to allow for long dsym download times
747437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                     NULL);             // Don't run in a shell (we don't need shell expansion)
748437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                if (error.Success() && exit_status == 0 && !command_output.empty())
749b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                {
750437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                    CFCData data (CFDataCreateWithBytesNoCopy (NULL,
751437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                               (const UInt8 *)command_output.data(),
752437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                               command_output.size(),
753437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                               kCFAllocatorNull));
754437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
755437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                    CFCReleaser<CFDictionaryRef> plist((CFDictionaryRef)::CFPropertyListCreateFromXMLData (NULL, data.get(), kCFPropertyListImmutable, NULL));
756437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
75750972aead4df9c8524d5f8b522e9d92895c72e48Sean Callanan                    if (plist.get() && CFGetTypeID (plist.get()) == CFDictionaryGetTypeID ())
758b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                    {
75942b336cd509cad89be08f78775d3b1c8c7656a1bJason Molenda                        if (!uuid_str.empty())
760b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                        {
76142b336cd509cad89be08f78775d3b1c8c7656a1bJason Molenda                            CFCString uuid_cfstr(uuid_str.c_str());
762437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                            CFDictionaryRef uuid_dict = (CFDictionaryRef)CFDictionaryGetValue (plist.get(), uuid_cfstr.get());
763437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                            success = GetModuleSpecInfoFromUUIDDictionary (uuid_dict, module_spec);
764b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                        }
765437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                        else
766b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                        {
767437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                            const CFIndex num_values = ::CFDictionaryGetCount(plist.get());
768437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                            if (num_values > 0)
769b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                            {
770437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                std::vector<CFStringRef> keys (num_values, NULL);
771437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                std::vector<CFDictionaryRef> values (num_values, NULL);
772437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                ::CFDictionaryGetKeysAndValues(plist.get(), NULL, (const void **)&values[0]);
773437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                if (num_values == 1)
774437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                {
775437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                    return GetModuleSpecInfoFromUUIDDictionary (values[0], module_spec);
776437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                }
777437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                else
778437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                {
779437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                    for (CFIndex i=0; i<num_values; ++i)
780437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                    {
781437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                        ModuleSpec curr_module_spec;
782437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                        if (GetModuleSpecInfoFromUUIDDictionary (values[i], curr_module_spec))
783437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                        {
78440e278caddf5442776f9408f20d757cc85fe630aSean Callanan                                            if (module_spec.GetArchitecture().IsCompatibleMatch(curr_module_spec.GetArchitecture()))
785437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                            {
786437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                module_spec = curr_module_spec;
787437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                return true;
788437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                            }
789437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                        }
790437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                    }
791437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                }
792b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                            }
793b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                        }
794b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                    }
795b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                }
796b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            }
797b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton        }
798b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton    }
799b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton    return success;
800b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton}
801b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton
802